2022-06-29 21:43:39 +00:00
|
|
|
import Combine
|
2022-02-16 20:23:11 +00:00
|
|
|
import CoreMedia
|
2022-07-11 16:30:12 +00:00
|
|
|
import Defaults
|
2022-02-16 20:23:11 +00:00
|
|
|
import Foundation
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
|
final class PlayerControlsModel: ObservableObject {
|
2022-09-01 18:01:01 +00:00
|
|
|
static var shared = PlayerControlsModel()
|
|
|
|
|
2022-05-21 20:58:11 +00:00
|
|
|
@Published var isLoadingVideo = false
|
2022-02-16 20:23:11 +00:00
|
|
|
@Published var isPlaying = true
|
|
|
|
@Published var presentingControls = false { didSet { handlePresentationChange() } }
|
2022-07-11 16:30:12 +00:00
|
|
|
@Published var presentingDetailsOverlay = false { didSet { handleDetailsOverlayPresentationChange() } }
|
2022-08-14 16:53:03 +00:00
|
|
|
var timer: Timer?
|
2022-02-16 20:23:11 +00:00
|
|
|
|
2022-06-29 21:43:39 +00:00
|
|
|
#if os(tvOS)
|
2022-08-28 17:18:49 +00:00
|
|
|
private(set) var reporter = PassthroughSubject<String, Never>()
|
2022-06-29 21:43:39 +00:00
|
|
|
#endif
|
|
|
|
|
2022-09-01 23:05:31 +00:00
|
|
|
private var player: PlayerModel! { .shared }
|
|
|
|
private var controlsOverlayModel = ControlOverlaysModel.shared
|
2022-02-16 20:23:11 +00:00
|
|
|
|
2022-06-18 12:39:49 +00:00
|
|
|
init(
|
|
|
|
isLoadingVideo: Bool = false,
|
|
|
|
isPlaying: Bool = true,
|
|
|
|
presentingControls: Bool = false,
|
2022-07-10 17:51:46 +00:00
|
|
|
presentingDetailsOverlay: Bool = false,
|
2022-09-01 23:05:31 +00:00
|
|
|
timer: Timer? = nil
|
2022-06-18 12:39:49 +00:00
|
|
|
) {
|
|
|
|
self.isLoadingVideo = isLoadingVideo
|
|
|
|
self.isPlaying = isPlaying
|
|
|
|
self.presentingControls = presentingControls
|
2022-07-10 17:51:46 +00:00
|
|
|
self.presentingDetailsOverlay = presentingDetailsOverlay
|
2022-06-18 12:39:49 +00:00
|
|
|
self.timer = timer
|
2022-02-16 20:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func handlePresentationChange() {
|
2022-08-23 21:14:13 +00:00
|
|
|
guard let player = player else { return }
|
|
|
|
if presentingControls {
|
2022-08-23 21:29:50 +00:00
|
|
|
DispatchQueue.main.async(qos: .userInteractive) { [weak self] in
|
|
|
|
player.backend.startControlsUpdates()
|
|
|
|
self?.resetTimer()
|
|
|
|
}
|
2022-08-23 21:14:13 +00:00
|
|
|
} else {
|
|
|
|
if !player.musicMode {
|
2022-08-23 21:29:50 +00:00
|
|
|
DispatchQueue.main.async(qos: .userInteractive) { [weak self] in
|
|
|
|
player.backend.stopControlsUpdates()
|
|
|
|
self?.removeTimer()
|
|
|
|
}
|
2022-07-10 17:51:46 +00:00
|
|
|
} else {
|
2022-08-23 21:29:50 +00:00
|
|
|
DispatchQueue.main.async(qos: .userInteractive) { [weak self] in
|
|
|
|
self?.presentingControls = true
|
|
|
|
}
|
2022-02-16 20:23:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 16:30:12 +00:00
|
|
|
func handleSettingsOverlayPresentationChange() {
|
2022-09-01 23:05:31 +00:00
|
|
|
player?.backend.setNeedsNetworkStateUpdates(controlsOverlayModel.presenting && Defaults[.showMPVPlaybackStats])
|
2022-06-24 23:39:29 +00:00
|
|
|
}
|
|
|
|
|
2022-08-23 21:14:13 +00:00
|
|
|
func handleDetailsOverlayPresentationChange() {}
|
2022-07-11 16:30:12 +00:00
|
|
|
|
2022-07-10 17:51:46 +00:00
|
|
|
var presentingOverlays: Bool {
|
2022-09-01 23:05:31 +00:00
|
|
|
presentingDetailsOverlay || controlsOverlayModel.presenting
|
2022-07-10 17:51:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func hideOverlays() {
|
|
|
|
presentingDetailsOverlay = false
|
2022-09-01 23:05:31 +00:00
|
|
|
controlsOverlayModel.presenting = false
|
2022-07-10 17:51:46 +00:00
|
|
|
}
|
|
|
|
|
2022-02-16 20:23:11 +00:00
|
|
|
func show() {
|
2022-09-01 23:05:31 +00:00
|
|
|
guard !player.currentItem.isNil, !presentingControls else {
|
2022-03-27 19:24:32 +00:00
|
|
|
return
|
|
|
|
}
|
2022-02-21 20:57:12 +00:00
|
|
|
|
2022-06-16 17:44:39 +00:00
|
|
|
player.backend.updateControls()
|
2022-02-16 20:23:11 +00:00
|
|
|
withAnimation(PlayerControls.animation) {
|
|
|
|
presentingControls = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func hide() {
|
2022-06-07 21:27:48 +00:00
|
|
|
guard let player = player,
|
|
|
|
!player.musicMode
|
|
|
|
else {
|
|
|
|
return
|
|
|
|
}
|
2022-03-27 19:24:32 +00:00
|
|
|
|
2022-06-07 21:27:48 +00:00
|
|
|
player.backend.stopControlsUpdates()
|
|
|
|
|
|
|
|
guard !player.currentItem.isNil else {
|
2022-03-27 19:24:32 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
guard presentingControls else {
|
|
|
|
return
|
|
|
|
}
|
2022-02-16 20:23:11 +00:00
|
|
|
withAnimation(PlayerControls.animation) {
|
|
|
|
presentingControls = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func toggle() {
|
2022-06-07 21:27:48 +00:00
|
|
|
presentingControls ? hide() : show()
|
2022-02-16 20:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func resetTimer() {
|
|
|
|
removeTimer()
|
2022-06-07 21:27:48 +00:00
|
|
|
|
2022-06-07 22:05:02 +00:00
|
|
|
guard let player = player, !player.musicMode else {
|
2022-06-07 21:27:48 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-02-16 20:23:11 +00:00
|
|
|
timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { _ in
|
|
|
|
withAnimation(PlayerControls.animation) { [weak self] in
|
|
|
|
self?.presentingControls = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func removeTimer() {
|
|
|
|
timer?.invalidate()
|
|
|
|
timer = nil
|
|
|
|
}
|
2022-09-01 23:05:31 +00:00
|
|
|
|
|
|
|
func update() {
|
|
|
|
player?.backend.updateControls()
|
|
|
|
}
|
2022-02-16 20:23:11 +00:00
|
|
|
}
|