yattee/Model/Player/PlayerControlsModel.swift

139 lines
3.7 KiB
Swift
Raw Permalink Normal View History

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
#if os(tvOS)
2023-06-17 12:09:51 +00:00
private(set) var reporter = PassthroughSubject<String, Never>() // swiftlint:disable:this private_subject
#endif
2022-12-18 12:11:06 +00:00
var player: PlayerModel! { .shared }
2022-09-01 23:05:31 +00:00
private var controlsOverlayModel = ControlOverlaysModel.shared
2022-02-16 20:23:11 +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
) {
self.isLoadingVideo = isLoadingVideo
self.isPlaying = isPlaying
self.presentingControls = presentingControls
2022-07-10 17:51:46 +00:00
self.presentingDetailsOverlay = presentingDetailsOverlay
self.timer = timer
2022-02-16 20:23:11 +00:00
}
func handlePresentationChange() {
2022-09-28 14:27:01 +00:00
guard let player else { return }
2022-08-23 21:14:13 +00:00
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 os(macOS)
NSCursor.setHiddenUntilMouseMoves(player.playingFullScreen)
#endif
2022-08-23 21:14:13 +00:00
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-11-17 21:47:45 +00:00
controlsOverlayModel.hide()
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-09-28 14:27:01 +00:00
guard let player,
2022-06-07 21:27:48 +00:00
!player.musicMode
else {
return
}
2022-03-27 19:24:32 +00:00
2022-11-10 20:47:32 +00:00
player.backend?.stopControlsUpdates()
2022-06-07 21:27:48 +00:00
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() {
2023-06-17 12:09:51 +00:00
if presentingControls {
hide()
} else {
show()
}
2022-02-16 20:23:11 +00:00
}
func resetTimer() {
removeTimer()
2022-06-07 21:27:48 +00:00
2022-09-28 14:27:01 +00:00
guard let 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
}