mirror of
https://github.com/yattee/yattee.git
synced 2024-12-21 21:13:42 +00:00
Playback state improvements
This commit is contained in:
parent
f80b61f9c7
commit
151121aa31
@ -1,2 +1 @@
|
||||
5
|
||||
|
||||
5
|
@ -3,6 +3,7 @@ parent_config: https://raw.githubusercontent.com/sindresorhus/swiftlint-config/m
|
||||
disabled_rules:
|
||||
- identifier_name
|
||||
- opening_brace
|
||||
- number_separator
|
||||
- multiline_arguments
|
||||
|
||||
excluded:
|
||||
|
@ -22,4 +22,9 @@ final class PlaybackState: ObservableObject {
|
||||
|
||||
return size.width / size.height
|
||||
}
|
||||
|
||||
func reset() {
|
||||
stream = nil
|
||||
time = nil
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,14 @@ final class PlayerState: ObservableObject {
|
||||
private(set) var currentRate: Float = 0.0
|
||||
static let availableRates: [Double] = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]
|
||||
|
||||
var playbackState: PlaybackState?
|
||||
var playbackState: PlaybackState
|
||||
var timeObserver: Any?
|
||||
|
||||
let maxResolution: Stream.Resolution?
|
||||
|
||||
var playingOutsideViewController = false
|
||||
|
||||
init(_ video: Video? = nil, playbackState: PlaybackState? = nil, maxResolution: Stream.Resolution? = nil) {
|
||||
init(_ video: Video? = nil, playbackState: PlaybackState, maxResolution: Stream.Resolution? = nil) {
|
||||
self.video = video
|
||||
self.playbackState = playbackState
|
||||
self.maxResolution = maxResolution
|
||||
@ -41,6 +41,8 @@ final class PlayerState: ObservableObject {
|
||||
return
|
||||
}
|
||||
|
||||
playbackState.reset()
|
||||
|
||||
loadExtendedVideoDetails(video) { video in
|
||||
self.video = video
|
||||
self.playVideo(video)
|
||||
@ -98,12 +100,16 @@ final class PlayerState: ObservableObject {
|
||||
}
|
||||
|
||||
fileprivate func playStream(_ stream: Stream) {
|
||||
guard player != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
logger.warning("loading \(stream.description) to player")
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.saveTime()
|
||||
self.player?.replaceCurrentItem(with: self.playerItemWithMetadata(for: stream))
|
||||
self.playbackState?.stream = stream
|
||||
self.playbackState.stream = stream
|
||||
if self.timeObserver == nil {
|
||||
self.addTimeObserver()
|
||||
}
|
||||
@ -259,7 +265,7 @@ final class PlayerState: ObservableObject {
|
||||
self.player.rate = self.currentRate
|
||||
}
|
||||
|
||||
self.playbackState?.time = self.player.currentTime()
|
||||
self.playbackState.time = self.player.currentTime()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@StateObject private var navigationState = NavigationState()
|
||||
@StateObject private var playbackState = PlaybackState()
|
||||
@StateObject private var searchState = SearchState()
|
||||
|
||||
#if os(iOS)
|
||||
@ -37,6 +38,7 @@ struct ContentView: View {
|
||||
}
|
||||
#endif
|
||||
.environmentObject(navigationState)
|
||||
.environmentObject(playbackState)
|
||||
.environmentObject(searchState)
|
||||
}
|
||||
}
|
||||
|
@ -2,25 +2,32 @@ import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct PlaybackBar: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@ObservedObject var playbackState: PlaybackState
|
||||
let video: Video
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@EnvironmentObject private var playbackState: PlaybackState
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
closeButton
|
||||
.frame(minWidth: 0, maxWidth: 60, alignment: .leading)
|
||||
.frame(width: 60, alignment: .leading)
|
||||
|
||||
Text(playbackFinishAtString)
|
||||
.foregroundColor(.gray)
|
||||
.font(.caption2)
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
.frame(minWidth: 60, maxWidth: .infinity)
|
||||
|
||||
Text(currentStreamString)
|
||||
.foregroundColor(.gray)
|
||||
.font(.caption2)
|
||||
.frame(minWidth: 0, maxWidth: 60, alignment: .trailing)
|
||||
VStack {
|
||||
if playbackState.stream != nil {
|
||||
Text(currentStreamString)
|
||||
} else {
|
||||
Image(systemName: "bolt.horizontal.fill")
|
||||
}
|
||||
}
|
||||
.foregroundColor(.gray)
|
||||
.font(.caption2)
|
||||
.frame(width: 60, alignment: .trailing)
|
||||
.fixedSize(horizontal: true, vertical: true)
|
||||
}
|
||||
.padding(4)
|
||||
.background(.black)
|
||||
@ -37,6 +44,10 @@ struct PlaybackBar: View {
|
||||
|
||||
let remainingSeconds = video.length - playbackState.time!.seconds
|
||||
|
||||
if remainingSeconds < 60 {
|
||||
return "less than a minute"
|
||||
}
|
||||
|
||||
let timeFinishAt = Date.now.addingTimeInterval(remainingSeconds)
|
||||
let timeFinishAtString = timeFinishAt.formatted(date: .omitted, time: .shortened)
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
import SwiftUI
|
||||
|
||||
struct Player: UIViewControllerRepresentable {
|
||||
@ObservedObject var playbackState: PlaybackState
|
||||
@EnvironmentObject<PlaybackState> private var playbackState
|
||||
|
||||
var video: Video?
|
||||
|
||||
func makeUIViewController(context _: Context) -> PlayerViewController {
|
||||
let controller = PlayerViewController()
|
||||
|
||||
controller.playbackState = playbackState
|
||||
controller.video = video
|
||||
controller.playbackState = playbackState
|
||||
|
||||
return controller
|
||||
}
|
||||
|
@ -34,8 +34,7 @@ final class PlayerViewController: UIViewController {
|
||||
}
|
||||
|
||||
func loadPlayer() {
|
||||
playerState = PlayerState()
|
||||
playerState.playbackState = playbackState
|
||||
playerState = PlayerState(playbackState: playbackState)
|
||||
|
||||
guard !playerLoaded else {
|
||||
return
|
||||
|
@ -13,11 +13,10 @@ struct VideoPlayerView: View {
|
||||
}
|
||||
|
||||
@EnvironmentObject<NavigationState> private var navigationState
|
||||
@EnvironmentObject<PlaybackState> private var playbackState
|
||||
|
||||
@ObservedObject private var store = Store<Video>()
|
||||
|
||||
@ObservedObject private var playbackState = PlaybackState()
|
||||
|
||||
#if os(iOS)
|
||||
@Environment(\.verticalSizeClass) private var verticalSizeClass
|
||||
#endif
|
||||
@ -36,19 +35,21 @@ struct VideoPlayerView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
#if os(tvOS)
|
||||
Player(playbackState: playbackState, video: video)
|
||||
Player(video: video)
|
||||
.environmentObject(playbackState)
|
||||
#else
|
||||
GeometryReader { geometry in
|
||||
VStack(spacing: 0) {
|
||||
#if os(iOS)
|
||||
if verticalSizeClass == .regular {
|
||||
PlaybackBar(playbackState: playbackState, video: video)
|
||||
PlaybackBar(video: video)
|
||||
}
|
||||
#elseif os(macOS)
|
||||
PlaybackBar(playbackState: playbackState, video: video)
|
||||
PlaybackBar(video: video)
|
||||
#endif
|
||||
|
||||
Player(playbackState: playbackState, video: video)
|
||||
Player(video: video)
|
||||
.environmentObject(playbackState)
|
||||
.modifier(VideoPlayerSizeModifier(geometry: geometry, aspectRatio: playbackState.aspectRatio))
|
||||
}
|
||||
.background(.black)
|
||||
|
@ -1,14 +1,15 @@
|
||||
import SwiftUI
|
||||
|
||||
struct Player: NSViewControllerRepresentable {
|
||||
@ObservedObject var playbackState: PlaybackState
|
||||
@EnvironmentObject<PlaybackState> private var playbackState
|
||||
|
||||
var video: Video!
|
||||
|
||||
func makeNSViewController(context _: Context) -> PlayerViewController {
|
||||
let controller = PlayerViewController()
|
||||
|
||||
controller.playbackState = playbackState
|
||||
controller.video = video
|
||||
controller.playbackState = playbackState
|
||||
|
||||
return controller
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import SwiftUI
|
||||
|
||||
struct TVNavigationView: View {
|
||||
@EnvironmentObject<NavigationState> private var navigationState
|
||||
@EnvironmentObject<PlaybackState> private var playbackState
|
||||
|
||||
@State private var showingOptions = false
|
||||
|
||||
@ -47,6 +48,7 @@ struct TVNavigationView: View {
|
||||
.fullScreenCover(isPresented: $navigationState.showingVideo) {
|
||||
if let video = navigationState.video {
|
||||
VideoPlayerView(video)
|
||||
.environmentObject(playbackState)
|
||||
}
|
||||
}
|
||||
.onPlayPauseCommand { showingOptions.toggle() }
|
||||
|
Loading…
Reference in New Issue
Block a user