mirror of
https://github.com/yattee/yattee.git
synced 2025-08-09 20:24:06 +00:00
Remove Watch Next
This commit is contained in:
@@ -107,7 +107,6 @@ struct OpenVideosModel {
|
||||
prepending: playbackMode == .playNow || playbackMode == .playNext
|
||||
)
|
||||
|
||||
WatchNextViewModel.shared.hide()
|
||||
NavigationModel.shared.presentingChannelSheet = false
|
||||
|
||||
if playbackMode == .playNow || playbackMode == .shuffleAll {
|
||||
|
@@ -105,47 +105,27 @@ extension PlayerBackend {
|
||||
return
|
||||
}
|
||||
|
||||
let action = {
|
||||
switch model.playbackMode {
|
||||
case .queue, .shuffle:
|
||||
model.prepareCurrentItemForHistory(finished: true)
|
||||
switch model.playbackMode {
|
||||
case .queue, .shuffle:
|
||||
model.prepareCurrentItemForHistory(finished: true)
|
||||
|
||||
if model.queue.isEmpty {
|
||||
#if os(tvOS)
|
||||
if model.activeBackend == .appleAVPlayer {
|
||||
model.avPlayerBackend.controller?.dismiss(animated: false)
|
||||
}
|
||||
#endif
|
||||
model.resetQueue()
|
||||
model.hide()
|
||||
} else {
|
||||
model.advanceToNextItem()
|
||||
}
|
||||
case .loopOne:
|
||||
loopAction()
|
||||
case .related:
|
||||
guard let item = model.autoplayItem else { return }
|
||||
model.resetAutoplay()
|
||||
model.advanceToItem(item)
|
||||
}
|
||||
}
|
||||
let actionAndHideWatchNext: (Bool) -> Void = { delay in
|
||||
WatchNextViewModel.shared.hide()
|
||||
if delay {
|
||||
Delay.by(0.3) {
|
||||
action()
|
||||
}
|
||||
if model.queue.isEmpty {
|
||||
#if os(tvOS)
|
||||
if model.activeBackend == .appleAVPlayer {
|
||||
model.avPlayerBackend.controller?.dismiss(animated: false)
|
||||
}
|
||||
#endif
|
||||
model.resetQueue()
|
||||
model.hide()
|
||||
} else {
|
||||
action()
|
||||
model.advanceToNextItem()
|
||||
}
|
||||
}
|
||||
if Defaults[.openWatchNextOnFinishedWatching], model.presentingPlayer {
|
||||
let timer = Delay.by(TimeInterval(Defaults[.openWatchNextOnFinishedWatchingDelay]) ?? 5.0) {
|
||||
actionAndHideWatchNext(true)
|
||||
}
|
||||
WatchNextViewModel.shared.finishedWatching(model.currentItem, timer: timer)
|
||||
} else {
|
||||
actionAndHideWatchNext(false)
|
||||
case .loopOne:
|
||||
loopAction()
|
||||
case .related:
|
||||
guard let item = model.autoplayItem else { return }
|
||||
model.resetAutoplay()
|
||||
model.advanceToItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -334,7 +334,6 @@ final class PlayerModel: ObservableObject {
|
||||
pause()
|
||||
videoBeingOpened = video
|
||||
|
||||
WatchNextViewModel.shared.hide()
|
||||
navigation.presentingChannelSheet = false
|
||||
|
||||
var changeBackendHandler: (() -> Void)?
|
||||
|
@@ -14,7 +14,6 @@ extension PlayerModel {
|
||||
}
|
||||
|
||||
func play(_ videos: [Video], shuffling: Bool = false) {
|
||||
WatchNextViewModel.shared.hide()
|
||||
navigation.presentingChannelSheet = false
|
||||
|
||||
playbackMode = shuffling ? .shuffle : .queue
|
||||
@@ -59,7 +58,6 @@ extension PlayerModel {
|
||||
|
||||
comments.reset()
|
||||
stream = nil
|
||||
WatchNextViewModel.shared.hide()
|
||||
navigation.presentingChannelSheet = false
|
||||
|
||||
withAnimation {
|
||||
@@ -180,7 +178,6 @@ extension PlayerModel {
|
||||
|
||||
remove(newItem)
|
||||
|
||||
WatchNextViewModel.shared.hide()
|
||||
navigation.presentingChannelSheet = false
|
||||
currentItem = newItem
|
||||
currentItem.playbackTime = time
|
||||
@@ -229,7 +226,6 @@ extension PlayerModel {
|
||||
|
||||
withAnimation {
|
||||
aspectRatio = VideoPlayerView.defaultAspectRatio
|
||||
WatchNextViewModel.shared.hide()
|
||||
navigation.presentingChannelSheet = false
|
||||
currentItem = item
|
||||
}
|
||||
|
@@ -1,205 +0,0 @@
|
||||
import Combine
|
||||
import Defaults
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
final class WatchNextViewModel: ObservableObject {
|
||||
enum Page: String, CaseIterable {
|
||||
case queue
|
||||
case related
|
||||
case history
|
||||
|
||||
var title: String {
|
||||
rawValue.capitalized.localized()
|
||||
}
|
||||
|
||||
var systemImageName: String {
|
||||
switch self {
|
||||
case .queue:
|
||||
return "list.and.film"
|
||||
case .related:
|
||||
return "rectangle.stack.fill"
|
||||
case .history:
|
||||
return "clock"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum PresentationReason {
|
||||
case userInteracted
|
||||
case finishedWatching
|
||||
case closed
|
||||
}
|
||||
|
||||
static let animation = Animation.easeIn(duration: 0.25)
|
||||
static let shared = WatchNextViewModel()
|
||||
|
||||
@Published var item: PlayerQueueItem?
|
||||
@Published private(set) var isPresenting = false
|
||||
@Published var reason: PresentationReason?
|
||||
@Published var page = Page.queue
|
||||
|
||||
@Published var countdown = 0.0
|
||||
var countdownTimer: Timer?
|
||||
|
||||
var player = PlayerModel.shared
|
||||
|
||||
var autoplayTimer: Timer?
|
||||
|
||||
var isAutoplaying: Bool {
|
||||
reason == .finishedWatching
|
||||
}
|
||||
|
||||
var isHideable: Bool {
|
||||
reason == .userInteracted
|
||||
}
|
||||
|
||||
var isRestartable: Bool {
|
||||
player.currentItem != nil && reason != .userInteracted
|
||||
}
|
||||
|
||||
var canAutoplay: Bool {
|
||||
switch player.playbackMode {
|
||||
case .shuffle:
|
||||
return !player.queue.isEmpty
|
||||
default:
|
||||
return nextFromTheQueue != nil
|
||||
}
|
||||
}
|
||||
|
||||
func userInteractedOpen(_ item: PlayerQueueItem?) {
|
||||
self.item = item
|
||||
open(reason: .userInteracted)
|
||||
}
|
||||
|
||||
func finishedWatching(_ item: PlayerQueueItem?, timer: Timer? = nil) {
|
||||
if canAutoplay {
|
||||
countdown = TimeInterval(Defaults[.openWatchNextOnFinishedWatchingDelay]) ?? 5.0
|
||||
resetCountdownTimer()
|
||||
autoplayTimer?.invalidate()
|
||||
autoplayTimer = timer
|
||||
} else {
|
||||
timer?.invalidate()
|
||||
}
|
||||
self.item = item
|
||||
open(reason: .finishedWatching)
|
||||
}
|
||||
|
||||
func resetCountdownTimer() {
|
||||
countdownTimer?.invalidate()
|
||||
countdownTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
|
||||
guard self.countdown > 0 else {
|
||||
timer.invalidate()
|
||||
return
|
||||
}
|
||||
self.countdown = max(0, self.countdown - 1)
|
||||
}
|
||||
}
|
||||
|
||||
func closed(_ item: PlayerQueueItem) {
|
||||
self.item = item
|
||||
open(reason: .closed)
|
||||
}
|
||||
|
||||
func keepFromAutoplaying() {
|
||||
userInteractedOpen(item)
|
||||
cancelAutoplay()
|
||||
}
|
||||
|
||||
func cancelAutoplay() {
|
||||
autoplayTimer?.invalidate()
|
||||
countdownTimer?.invalidate()
|
||||
}
|
||||
|
||||
func restart() {
|
||||
cancelAutoplay()
|
||||
|
||||
guard player.currentItem != nil else { return }
|
||||
|
||||
if reason == .closed {
|
||||
hide()
|
||||
return
|
||||
}
|
||||
|
||||
player.backend.seek(to: .zero, seekType: .loopRestart) { _ in
|
||||
self.hide()
|
||||
self.player.play()
|
||||
}
|
||||
}
|
||||
|
||||
private func open(reason: PresentationReason) {
|
||||
self.reason = reason
|
||||
setPageAfterOpening()
|
||||
|
||||
guard !isPresenting else { return }
|
||||
withAnimation(Self.animation) {
|
||||
isPresenting = true
|
||||
}
|
||||
}
|
||||
|
||||
private func setPageAfterOpening() {
|
||||
let firstAvailable = Page.allCases.first { isAvailable($0) } ?? .history
|
||||
|
||||
switch reason {
|
||||
case .finishedWatching:
|
||||
page = player.playbackMode == .related ? .queue : firstAvailable
|
||||
case .closed:
|
||||
page = player.playbackMode == .related ? .queue : firstAvailable
|
||||
default:
|
||||
page = firstAvailable
|
||||
}
|
||||
}
|
||||
|
||||
func close() {
|
||||
let close = {
|
||||
self.player.closeCurrentItem()
|
||||
self.player.hide()
|
||||
Delay.by(0.5) {
|
||||
self.isPresenting = false
|
||||
}
|
||||
}
|
||||
if reason == .closed {
|
||||
close()
|
||||
return
|
||||
}
|
||||
if canAutoplay {
|
||||
cancelAutoplay()
|
||||
hide()
|
||||
} else {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
func hide() {
|
||||
guard isPresenting else { return }
|
||||
withAnimation(Self.animation) {
|
||||
isPresenting = false
|
||||
}
|
||||
}
|
||||
|
||||
func resetItem() {
|
||||
item = nil
|
||||
}
|
||||
|
||||
func isAvailable(_ page: Page) -> Bool {
|
||||
switch page {
|
||||
case .queue:
|
||||
return !player.queue.isEmpty
|
||||
case .related:
|
||||
guard let video = item?.video else { return false }
|
||||
return !video.related.isEmpty
|
||||
case .history:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
var nextFromTheQueue: PlayerQueueItem? {
|
||||
if player.playbackMode == .related {
|
||||
return player.autoplayItem
|
||||
} else if player.playbackMode == .queue {
|
||||
return player.queue.first
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user