From 151121aa31db2e4739ce8ffab63b1c7f2658dfa3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Mon, 23 Aug 2021 23:31:51 +0200 Subject: [PATCH] Playback state improvements --- .swift-version | 3 +-- .swiftlint.yml | 1 + Model/PlaybackState.swift | 5 ++++ Model/PlayerState.swift | 14 ++++++++---- Shared/Navigation/ContentView.swift | 2 ++ Shared/Player/PlaybackBar.swift | 29 ++++++++++++++++-------- Shared/Player/Player.swift | 5 ++-- Shared/Player/PlayerViewController.swift | 3 +-- Shared/Player/VideoPlayerView.swift | 13 ++++++----- macOS/Player.swift | 5 ++-- tvOS/TVNavigationView.swift | 2 ++ 11 files changed, 55 insertions(+), 27 deletions(-) diff --git a/.swift-version b/.swift-version index 51d7b8d1..7813681f 100644 --- a/.swift-version +++ b/.swift-version @@ -1,2 +1 @@ -5 - +5 \ No newline at end of file diff --git a/.swiftlint.yml b/.swiftlint.yml index 791127c4..9facc479 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -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: diff --git a/Model/PlaybackState.swift b/Model/PlaybackState.swift index df017b9d..0aae38aa 100644 --- a/Model/PlaybackState.swift +++ b/Model/PlaybackState.swift @@ -22,4 +22,9 @@ final class PlaybackState: ObservableObject { return size.width / size.height } + + func reset() { + stream = nil + time = nil + } } diff --git a/Model/PlayerState.swift b/Model/PlayerState.swift index bbcb6f30..b5cbc6c3 100644 --- a/Model/PlayerState.swift +++ b/Model/PlayerState.swift @@ -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() } } diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index e3f4b7df..2c3cfcee 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -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) } } diff --git a/Shared/Player/PlaybackBar.swift b/Shared/Player/PlaybackBar.swift index 489e4b3a..164a116e 100644 --- a/Shared/Player/PlaybackBar.swift +++ b/Shared/Player/PlaybackBar.swift @@ -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) diff --git a/Shared/Player/Player.swift b/Shared/Player/Player.swift index 417c0a4f..888164da 100644 --- a/Shared/Player/Player.swift +++ b/Shared/Player/Player.swift @@ -1,14 +1,15 @@ import SwiftUI struct Player: UIViewControllerRepresentable { - @ObservedObject var playbackState: PlaybackState + @EnvironmentObject 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 } diff --git a/Shared/Player/PlayerViewController.swift b/Shared/Player/PlayerViewController.swift index 95645d90..c8c35583 100644 --- a/Shared/Player/PlayerViewController.swift +++ b/Shared/Player/PlayerViewController.swift @@ -34,8 +34,7 @@ final class PlayerViewController: UIViewController { } func loadPlayer() { - playerState = PlayerState() - playerState.playbackState = playbackState + playerState = PlayerState(playbackState: playbackState) guard !playerLoaded else { return diff --git a/Shared/Player/VideoPlayerView.swift b/Shared/Player/VideoPlayerView.swift index 41b1b4b8..15105fcb 100644 --- a/Shared/Player/VideoPlayerView.swift +++ b/Shared/Player/VideoPlayerView.swift @@ -13,11 +13,10 @@ struct VideoPlayerView: View { } @EnvironmentObject private var navigationState + @EnvironmentObject private var playbackState @ObservedObject private var store = Store