mirror of
				https://github.com/yattee/yattee.git
				synced 2025-11-04 06:32:03 +00:00 
			
		
		
		
	Better UI for autoplay
This commit is contained in:
		@@ -573,20 +573,36 @@ final class PlayerModel: ObservableObject {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func setRelatedAutoplayItem() {
 | 
			
		||||
        guard let video = currentVideo?.related.randomElement() else { return }
 | 
			
		||||
        guard let video = currentVideo else { return }
 | 
			
		||||
        let related = video.related.filter { $0.videoID != autoplayItem?.video?.videoID }
 | 
			
		||||
 | 
			
		||||
        let item = PlayerQueueItem(video)
 | 
			
		||||
        autoplayItem = item
 | 
			
		||||
        autoplayItemSource = video
 | 
			
		||||
        let watchFetchRequest = Watch.fetchRequest()
 | 
			
		||||
        watchFetchRequest.predicate = NSPredicate(format: "videoID IN %@", related.map(\.videoID) as [String])
 | 
			
		||||
 | 
			
		||||
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
 | 
			
		||||
            guard let self = self else { return }
 | 
			
		||||
            self.accounts.api.loadDetails(item, completionHandler: { newItem in
 | 
			
		||||
                guard newItem.videoID == self.autoplayItem?.videoID else { return }
 | 
			
		||||
                self.autoplayItem = newItem
 | 
			
		||||
                self.updateRemoteCommandCenter()
 | 
			
		||||
                self.controls.objectWillChange.send()
 | 
			
		||||
            })
 | 
			
		||||
        let results = try? context.fetch(watchFetchRequest)
 | 
			
		||||
 | 
			
		||||
        context.perform { [weak self] in
 | 
			
		||||
            guard let self = self,
 | 
			
		||||
                  let results = results else { return }
 | 
			
		||||
            let resultsIds = results.map(\.videoID)
 | 
			
		||||
 | 
			
		||||
            guard let autoplayVideo = related.filter({ !resultsIds.contains($0.videoID) }).randomElement() else {
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let item = PlayerQueueItem(autoplayVideo)
 | 
			
		||||
            self.autoplayItem = item
 | 
			
		||||
            self.autoplayItemSource = video
 | 
			
		||||
 | 
			
		||||
            DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
 | 
			
		||||
                guard let self = self else { return }
 | 
			
		||||
                self.accounts.api.loadDetails(item, completionHandler: { newItem in
 | 
			
		||||
                    guard newItem.videoID == self.autoplayItem?.videoID else { return }
 | 
			
		||||
                    self.autoplayItem = newItem
 | 
			
		||||
                    self.updateRemoteCommandCenter()
 | 
			
		||||
                    self.controls.objectWillChange.send()
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import SwiftUI
 | 
			
		||||
struct PlayerQueueRow: View {
 | 
			
		||||
    let item: PlayerQueueItem
 | 
			
		||||
    var history = false
 | 
			
		||||
    var autoplay = false
 | 
			
		||||
    @Binding var fullScreen: Bool
 | 
			
		||||
 | 
			
		||||
    @EnvironmentObject<PlayerModel> private var player
 | 
			
		||||
@@ -14,9 +15,10 @@ struct PlayerQueueRow: View {
 | 
			
		||||
 | 
			
		||||
    @FetchRequest private var watchRequest: FetchedResults<Watch>
 | 
			
		||||
 | 
			
		||||
    init(item: PlayerQueueItem, history: Bool = false, fullScreen: Binding<Bool> = .constant(false)) {
 | 
			
		||||
    init(item: PlayerQueueItem, history: Bool = false, autoplay: Bool = false, fullScreen: Binding<Bool> = .constant(false)) {
 | 
			
		||||
        self.item = item
 | 
			
		||||
        self.history = history
 | 
			
		||||
        self.autoplay = autoplay
 | 
			
		||||
        _fullScreen = fullScreen
 | 
			
		||||
        _watchRequest = FetchRequest<Watch>(
 | 
			
		||||
            entity: Watch.entity(),
 | 
			
		||||
@@ -48,6 +50,10 @@ struct PlayerQueueRow: View {
 | 
			
		||||
            if closePiPOnNavigation, player.playingInPictureInPicture {
 | 
			
		||||
                player.closePiP()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if autoplay {
 | 
			
		||||
                player.resetAutoplay()
 | 
			
		||||
            }
 | 
			
		||||
        } label: {
 | 
			
		||||
            VideoBanner(video: item.video, playbackTime: watchStoppedAt, videoDuration: watch?.videoDuration)
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,9 @@ struct PlayerQueueView: View {
 | 
			
		||||
    var body: some View {
 | 
			
		||||
        List {
 | 
			
		||||
            Group {
 | 
			
		||||
                if player.playbackMode == .related {
 | 
			
		||||
                    autoplaying
 | 
			
		||||
                }
 | 
			
		||||
                playingNext
 | 
			
		||||
                if sidebarQueue {
 | 
			
		||||
                    related
 | 
			
		||||
@@ -46,10 +49,42 @@ struct PlayerQueueView: View {
 | 
			
		||||
        #endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ViewBuilder var autoplaying: some View {
 | 
			
		||||
        Section(header: autoplayingHeader) {
 | 
			
		||||
            if let item = player.autoplayItem {
 | 
			
		||||
                PlayerQueueRow(item: item, autoplay: true)
 | 
			
		||||
            } else {
 | 
			
		||||
                Group {
 | 
			
		||||
                    if player.currentItem.isNil {
 | 
			
		||||
                        Text("Not Playing")
 | 
			
		||||
                    } else {
 | 
			
		||||
                        Text("Finding something to play...")
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                .foregroundColor(.secondary)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var autoplayingHeader: some View {
 | 
			
		||||
        HStack {
 | 
			
		||||
            Text("Autoplaying Next")
 | 
			
		||||
            Spacer()
 | 
			
		||||
            Button {
 | 
			
		||||
                player.setRelatedAutoplayItem()
 | 
			
		||||
            } label: {
 | 
			
		||||
                Label("Find Other", systemImage: "arrow.triangle.2.circlepath.circle")
 | 
			
		||||
                    .labelStyle(.iconOnly)
 | 
			
		||||
            }
 | 
			
		||||
            .disabled(player.currentItem.isNil)
 | 
			
		||||
            .buttonStyle(.plain)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var playingNext: some View {
 | 
			
		||||
        Section(header: Text("Playing Next")) {
 | 
			
		||||
        Section(header: Text("Queue")) {
 | 
			
		||||
            if player.queue.isEmpty {
 | 
			
		||||
                Text("Playback queue is empty")
 | 
			
		||||
                Text("Queue is empty")
 | 
			
		||||
                    .foregroundColor(.secondary)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +108,7 @@ struct PlayerQueueView: View {
 | 
			
		||||
    var playedPreviously: some View {
 | 
			
		||||
        Group {
 | 
			
		||||
            if !visibleWatches.isEmpty {
 | 
			
		||||
                Section(header: Text("Played Previously")) {
 | 
			
		||||
                Section(header: Text("History")) {
 | 
			
		||||
                    ForEach(visibleWatches, id: \.videoID) { watch in
 | 
			
		||||
                        PlayerQueueRow(
 | 
			
		||||
                            item: PlayerQueueItem.from(watch, video: player.historyVideo(watch.videoID)),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user