mirror of
				https://github.com/yattee/yattee.git
				synced 2025-10-30 04:01:56 +00:00 
			
		
		
		
	UI improvements, player state refactor
This commit is contained in:
		| @@ -3,7 +3,7 @@ import SwiftUI | ||||
|  | ||||
| struct PlaylistFormView: View { | ||||
|     @State private var name = "" | ||||
|     @State private var visibility = PlaylistVisibility.public | ||||
|     @State private var visibility = Playlist.Visibility.public | ||||
|  | ||||
|     @State private var valid = false | ||||
|     @State private var showingDeleteConfirmation = false | ||||
| @@ -89,7 +89,7 @@ struct PlaylistFormView: View { | ||||
|             self.visibility = self.visibility.next() | ||||
|         } | ||||
|         .contextMenu { | ||||
|             ForEach(PlaylistVisibility.allCases) { visibility in | ||||
|             ForEach(Playlist.Visibility.allCases) { visibility in | ||||
|                 Button(visibility.name) { | ||||
|                     self.visibility = visibility | ||||
|                 } | ||||
|   | ||||
| @@ -19,7 +19,7 @@ struct SearchOptionsView: View { | ||||
|             self.searchSortOrder = self.searchSortOrder.next() | ||||
|         } | ||||
|         .contextMenu { | ||||
|             ForEach(SearchSortOrder.allCases) { sortOrder in | ||||
|             ForEach(SearchQuery.SortOrder.allCases) { sortOrder in | ||||
|                 Button(sortOrder.name) { | ||||
|                     self.searchSortOrder = sortOrder | ||||
|                 } | ||||
| @@ -29,11 +29,11 @@ struct SearchOptionsView: View { | ||||
|  | ||||
|     var searchDateButton: some View { | ||||
|         Button(self.searchDate?.name ?? "All") { | ||||
|             self.searchDate = self.searchDate == nil ? SearchDate.allCases.first : self.searchDate!.next(nilAtEnd: true) | ||||
|             self.searchDate = self.searchDate == nil ? SearchQuery.Date.allCases.first : self.searchDate!.next(nilAtEnd: true) | ||||
|         } | ||||
|  | ||||
|         .contextMenu { | ||||
|             ForEach(SearchDate.allCases) { searchDate in | ||||
|             ForEach(SearchQuery.Date.allCases) { searchDate in | ||||
|                 Button(searchDate.name) { | ||||
|                     self.searchDate = searchDate | ||||
|                 } | ||||
| @@ -47,10 +47,10 @@ struct SearchOptionsView: View { | ||||
|  | ||||
|     var searchDurationButton: some View { | ||||
|         Button(self.searchDuration?.name ?? "All") { | ||||
|             self.searchDuration = self.searchDuration == nil ? SearchDuration.allCases.first : self.searchDuration!.next(nilAtEnd: true) | ||||
|             self.searchDuration = self.searchDuration == nil ? SearchQuery.Duration.allCases.first : self.searchDuration!.next(nilAtEnd: true) | ||||
|         } | ||||
|         .contextMenu { | ||||
|             ForEach(SearchDuration.allCases) { searchDuration in | ||||
|             ForEach(SearchQuery.Duration.allCases) { searchDuration in | ||||
|                 Button(searchDuration.name) { | ||||
|                     self.searchDuration = searchDuration | ||||
|                 } | ||||
|   | ||||
| @@ -1,11 +0,0 @@ | ||||
| import AVKit | ||||
|  | ||||
| final class StreamAVPlayerViewController: AVPlayerViewController { | ||||
|     var state: PlayerState? | ||||
|  | ||||
|     override func viewWillDisappear(_ animated: Bool) { | ||||
|         super.viewWillDisappear(animated) | ||||
|  | ||||
|         state?.destroyPlayer() | ||||
|     } | ||||
| } | ||||
| @@ -11,7 +11,7 @@ struct VideoCellView: View { | ||||
|     var body: some View { | ||||
|         Button(action: { navigationState.playVideo(video) }) { | ||||
|             VStack(alignment: .leading) { | ||||
|                 ZStack(alignment: .trailing) { | ||||
|                 ZStack { | ||||
|                     if let thumbnail = video.thumbnailURL(quality: .high) { | ||||
|                         // to replace with AsyncImage when it is fixed with lazy views | ||||
|                         URLImage(thumbnail) { image in | ||||
| @@ -26,24 +26,30 @@ struct VideoCellView: View { | ||||
|                             .frame(width: 550, height: 310) | ||||
|                     } | ||||
|  | ||||
|                     VStack(alignment: .trailing) { | ||||
|                         Text(video.author) | ||||
|                             .padding(8) | ||||
|                             .background(.thickMaterial) | ||||
|                             .mask(RoundedRectangle(cornerRadius: 12)) | ||||
|                             .offset(x: -5, y: 5) | ||||
|                             .truncationMode(.middle) | ||||
|                     VStack { | ||||
|                         HStack(alignment: .top) { | ||||
|                             if video.live { | ||||
|                                 DetailBadge(text: "Live", style: .outstanding) | ||||
|                             } else if video.upcoming { | ||||
|                                 DetailBadge(text: "Upcoming", style: .informational) | ||||
|                             } | ||||
|  | ||||
|                             Spacer() | ||||
|  | ||||
|                             DetailBadge(text: video.author, style: .prominent) | ||||
|                         } | ||||
|                         .padding(10) | ||||
|  | ||||
|                         Spacer() | ||||
|  | ||||
|                         if let time = video.playTime { | ||||
|                             Text(time) | ||||
|                                 .fontWeight(.bold) | ||||
|                                 .padding(8) | ||||
|                                 .background(.thickMaterial) | ||||
|                                 .mask(RoundedRectangle(cornerRadius: 12)) | ||||
|                                 .offset(x: -5, y: -5) | ||||
|                         HStack(alignment: .top) { | ||||
|                             Spacer() | ||||
|  | ||||
|                             if let time = video.playTime { | ||||
|                                 DetailBadge(text: time, style: .prominent) | ||||
|                             } | ||||
|                         } | ||||
|                         .padding(10) | ||||
|                     } | ||||
|                 } | ||||
|                 .frame(width: 550, height: 310) | ||||
| @@ -58,21 +64,32 @@ struct VideoCellView: View { | ||||
|                         .frame(minHeight: 80, alignment: .top) | ||||
|                         .truncationMode(.middle) | ||||
|  | ||||
|                     if !video.published.isEmpty || video.views != 0 { | ||||
|                         HStack(spacing: 8) { | ||||
|                             if !video.published.isEmpty { | ||||
|                     HStack(spacing: 8) { | ||||
|                         if video.publishedDate != nil || video.views != 0 { | ||||
|                             if let date = video.publishedDate { | ||||
|                                 Image(systemName: "calendar") | ||||
|                                 Text(video.published) | ||||
|                                 Text(date) | ||||
|                             } | ||||
|  | ||||
|                             if video.views != 0 { | ||||
|                                 Image(systemName: "eye") | ||||
|                                 Text(video.viewsCount) | ||||
|                             } | ||||
|                         } else { | ||||
|                             Section { | ||||
|                                 if video.live { | ||||
|                                     Image(systemName: "camera.fill") | ||||
|                                     Text("Premiering now") | ||||
|                                 } else { | ||||
|                                     Image(systemName: "questionmark.app.fill") | ||||
|                                     Text("date and views unavailable") | ||||
|                                 } | ||||
|                             } | ||||
|                             .opacity(0.6) | ||||
|                         } | ||||
|                         .padding([.horizontal, .bottom]) | ||||
|                         .foregroundColor(.secondary) | ||||
|                     } | ||||
|                     .padding([.horizontal, .bottom]) | ||||
|                     .foregroundColor(.secondary) | ||||
|                 } | ||||
|             } | ||||
|             .frame(width: 550, alignment: .leading) | ||||
| @@ -81,3 +98,13 @@ struct VideoCellView: View { | ||||
|         .padding(.vertical) | ||||
|     } | ||||
| } | ||||
|  | ||||
| struct VideoCellView_Preview: PreviewProvider { | ||||
|     static var previews: some View { | ||||
|         HStack { | ||||
|             VideoCellView(video: Video.fixture) | ||||
|             VideoCellView(video: Video.fixtureUpcomingWithoutPublishedOrViews) | ||||
|             VideoCellView(video: Video.fixtureLiveWithoutPublishedOrViews) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -158,7 +158,7 @@ struct VideoListRowView: View { | ||||
|     } | ||||
|  | ||||
|     func thumbnail( | ||||
|         _ quality: ThumbnailQuality, | ||||
|         _ quality: Thumbnail.Quality, | ||||
|         minWidth: Double = 320, | ||||
|         maxWidth: Double = .infinity, | ||||
|         minHeight: Double = 180, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Arkadiusz Fal
					Arkadiusz Fal