1
0
mirror of https://github.com/yattee/yattee.git synced 2024-12-13 13:50:32 +05:30
yattee/Model/Player/PlayerControlsModel.swift

155 lines
4.0 KiB
Swift
Raw Normal View History

2022-02-17 01:53:11 +05:30
import CoreMedia
import Foundation
import SwiftUI
final class PlayerControlsModel: ObservableObject {
2022-05-22 02:28:11 +05:30
@Published var isLoadingVideo = false
2022-02-17 01:53:11 +05:30
@Published var isPlaying = true
@Published var currentTime = CMTime.zero
@Published var duration = CMTime.zero
@Published var presentingControls = false { didSet { handlePresentationChange() } }
@Published var timer: Timer?
@Published var playingFullscreen = false
2022-03-28 00:54:32 +05:30
private var throttle = Throttle(interval: 1)
2022-02-17 01:53:11 +05:30
var player: PlayerModel!
var playbackTime: String {
guard let current = currentTime.seconds.formattedAsPlaybackTime(),
let duration = duration.seconds.formattedAsPlaybackTime()
else {
return "--:-- / --:--"
}
var withoutSegments = ""
if let withoutSegmentsDuration = playerItemDurationWithoutSponsorSegments,
self.duration.seconds != withoutSegmentsDuration
{
withoutSegments = " (\(withoutSegmentsDuration.formattedAsPlaybackTime() ?? "--:--"))"
}
return "\(current) / \(duration)\(withoutSegments)"
}
var playerItemDurationWithoutSponsorSegments: Double? {
guard let duration = player.playerItemDurationWithoutSponsorSegments else {
return nil
}
return duration.seconds
}
func handlePresentationChange() {
if presentingControls {
DispatchQueue.main.async { [weak self] in
2022-05-28 04:53:50 +05:30
self?.player?.backend.startControlsUpdates()
2022-02-17 01:53:11 +05:30
self?.resetTimer()
}
} else {
player.backend.stopControlsUpdates()
timer?.invalidate()
timer = nil
}
}
func show() {
2022-03-28 00:54:32 +05:30
guard !(player?.currentItem.isNil ?? true) else {
return
}
guard !presentingControls else {
return
}
2022-02-22 02:27:12 +05:30
2022-02-17 01:53:11 +05:30
withAnimation(PlayerControls.animation) {
presentingControls = true
}
}
func hide() {
2022-06-08 02:57:48 +05:30
guard let player = player,
!player.musicMode
else {
return
}
2022-03-28 00:54:32 +05:30
2022-06-08 02:57:48 +05:30
player.backend.stopControlsUpdates()
guard !player.currentItem.isNil else {
2022-03-28 00:54:32 +05:30
return
}
guard presentingControls else {
return
}
2022-02-17 01:53:11 +05:30
withAnimation(PlayerControls.animation) {
presentingControls = false
}
}
func toggle() {
2022-06-08 02:57:48 +05:30
presentingControls ? hide() : show()
2022-02-17 01:53:11 +05:30
}
func reset() {
currentTime = .zero
duration = .zero
}
func resetTimer() {
2022-05-29 19:05:16 +05:30
#if os(tvOS)
if !presentingControls {
show()
}
#endif
2022-03-27 17:12:20 +05:30
2022-02-17 01:53:11 +05:30
removeTimer()
2022-06-08 02:57:48 +05:30
2022-06-08 03:35:02 +05:30
guard let player = player, !player.musicMode else {
2022-06-08 02:57:48 +05:30
return
}
2022-02-17 01:53:11 +05:30
timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { _ in
withAnimation(PlayerControls.animation) { [weak self] in
self?.presentingControls = false
self?.player.backend.stopControlsUpdates()
}
}
}
2022-05-29 20:08:37 +05:30
func startPiP(startImmediately: Bool = true) {
if player.activeBackend == .mpv {
player.avPlayerBackend.switchToMPVOnPipClose = true
}
#if !os(macOS)
player.exitFullScreen()
#endif
if player.activeBackend != PlayerBackendType.appleAVPlayer {
player.saveTime { [weak player] in
player?.changeActiveBackend(from: .mpv, to: .appleAVPlayer)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak player] in
player?.avPlayerBackend.startPictureInPictureOnPlay = true
if startImmediately {
player?.pipController?.startPictureInPicture()
}
}
}
2022-02-17 01:53:11 +05:30
func removeTimer() {
timer?.invalidate()
timer = nil
}
2022-03-28 00:54:32 +05:30
func update() {
throttle.execute { [weak self] in
self?.player?.backend.updateControls()
}
}
2022-02-17 01:53:11 +05:30
}