Fix various issues

This commit is contained in:
Arkadiusz Fal 2023-05-21 00:18:10 +02:00
parent 34a05433d5
commit 1cc66fdc10
9 changed files with 154 additions and 106 deletions

View File

@ -427,16 +427,18 @@ enum FullScreenRotationSetting: String, CaseIterable, Defaults.Serializable {
case landscapeLeft
case landscapeRight
var interaceOrientation: UIInterfaceOrientation {
switch self {
case .landscapeLeft:
return .landscapeLeft
case .landscapeRight:
return .landscapeRight
default:
return .portrait
#if os(iOS)
var interaceOrientation: UIInterfaceOrientation {
switch self {
case .landscapeLeft:
return .landscapeLeft
case .landscapeRight:
return .landscapeRight
default:
return .portrait
}
}
}
#endif
var isRotating: Bool {
self != .disabled

View File

@ -18,9 +18,9 @@ struct ContentView: View {
@Default(.avPlayerUsesSystemControls) private var avPlayerUsesSystemControls
var body: some View {
Group {
#if os(iOS)
GeometryReader { proxy in
GeometryReader { proxy in
Group {
#if os(iOS)
Group {
if Constants.isIPhone {
AppTabNavigation()
@ -32,17 +32,19 @@ struct ContentView: View {
}
}
}
.onAppear {
SafeAreaModel.shared.safeArea = proxy.safeAreaInsets
}
.onChange(of: proxy.safeAreaInsets) { newValue in
SafeAreaModel.shared.safeArea = newValue
}
}
#elseif os(macOS)
AppSidebarNavigation()
#elseif os(tvOS)
TVNavigationView()
#elseif os(macOS)
AppSidebarNavigation()
#elseif os(tvOS)
TVNavigationView()
#endif
}
#if !os(macOS)
.onAppear {
SafeAreaModel.shared.safeArea = proxy.safeAreaInsets
}
.onChange(of: proxy.safeAreaInsets) { newValue in
SafeAreaModel.shared.safeArea = newValue
}
#endif
}
#if os(iOS)
@ -135,7 +137,9 @@ struct ContentView: View {
)
#endif
.alert(isPresented: $navigation.presentingAlert) { navigation.alert }
.statusBarHidden(player.playingFullScreen)
#if os(iOS)
.statusBarHidden(player.playingFullScreen)
#endif
}
var navigationStyle: NavigationStyle {

View File

@ -4,6 +4,7 @@ import SwiftUI
struct TVControls: UIViewRepresentable {
var model: PlayerControlsModel!
var player: PlayerModel { .shared }
var safeArea: SafeAreaModel { .shared }
var thumbnails: ThumbnailsModel { .shared }
@State private var direction = ""
@ -32,10 +33,10 @@ struct TVControls: UIViewRepresentable {
let controls = UIHostingController(rootView: PlayerControls())
controls.view.frame = .init(
origin: .init(x: SafeArea.insets.left, y: SafeArea.insets.top),
origin: .init(x: safeArea.safeArea.leading, y: safeArea.safeArea.top),
size: .init(
width: UIScreen.main.bounds.width - SafeArea.horizontalInsets,
height: UIScreen.main.bounds.height - SafeArea.verticalInset
width: UIScreen.main.bounds.width - safeArea.horizontalInsets,
height: UIScreen.main.bounds.height - safeArea.verticalInsets
)
)

View File

@ -4,9 +4,9 @@ import SwiftUI
struct PlayerBackendView: View {
#if os(iOS)
@Environment(\.verticalSizeClass) private var verticalSizeClass
@ObservedObject private var safeAreaModel = SafeAreaModel.shared
#endif
@ObservedObject private var player = PlayerModel.shared
@ObservedObject private var safeAreaModel = SafeAreaModel.shared
@Default(.avPlayerUsesSystemControls) private var avPlayerUsesSystemControls
@ -36,9 +36,6 @@ struct PlayerBackendView: View {
}
}
.zIndex(0)
ControlsGradientView()
.zIndex(1)
}
}
.overlay(GeometryReader { proxy in

View File

@ -104,65 +104,67 @@ struct VideoPlayerView: View {
}
}
.ignoresSafeArea(.all, edges: .bottom)
.frame(height: playerHeight.isNil ? nil : Double(playerHeight!))
.onChange(of: geometry.size) { _ in
self.playerSize = geometry.size
}
.onChange(of: fullScreenDetails) { value in
player.backend.setNeedsDrawing(!value)
}
#if os(iOS)
.onChange(of: player.presentingPlayer) { newValue in
if newValue {
viewDragOffset = 0
.frame(height: playerHeight.isNil ? nil : Double(playerHeight!))
#endif
.onChange(of: geometry.size) { _ in
self.playerSize = geometry.size
}
}
.onAppear {
#if os(macOS)
if player.videoForDisplay.isNil {
player.hide()
.onChange(of: fullScreenDetails) { value in
player.backend.setNeedsDrawing(!value)
}
#if os(iOS)
.onChange(of: player.presentingPlayer) { newValue in
if newValue {
viewDragOffset = 0
}
#endif
viewDragOffset = 0
}
.onAppear {
#if os(macOS)
if player.videoForDisplay.isNil {
player.hide()
}
#endif
viewDragOffset = 0
Delay.by(0.2) {
orientationModel.configureOrientationUpdatesBasedOnAccelerometer()
Delay.by(0.2) {
orientationModel.configureOrientationUpdatesBasedOnAccelerometer()
if let orientationMask = player.lockedOrientation {
Orientation.lockOrientation(
orientationMask,
andRotateTo: orientationMask == .landscapeLeft ? .landscapeLeft : orientationMask == .landscapeRight ? .landscapeRight : .portrait
)
if let orientationMask = player.lockedOrientation {
Orientation.lockOrientation(
orientationMask,
andRotateTo: orientationMask == .landscapeLeft ? .landscapeLeft : orientationMask == .landscapeRight ? .landscapeRight : .portrait
)
} else {
Orientation.lockOrientation(.allButUpsideDown)
}
}
}
.onDisappear {
if Defaults[.lockPortraitWhenBrowsing] {
Orientation.lockOrientation(.portrait, andRotateTo: .portrait)
} else {
Orientation.lockOrientation(.allButUpsideDown)
}
orientationModel.stopOrientationUpdates()
player.controls.hideOverlays()
}
}
.onDisappear {
if Defaults[.lockPortraitWhenBrowsing] {
Orientation.lockOrientation(.portrait, andRotateTo: .portrait)
} else {
Orientation.lockOrientation(.allButUpsideDown)
}
orientationModel.stopOrientationUpdates()
player.controls.hideOverlays()
}
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
guard player.lockedOrientation.isNil else {
return
}
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
guard player.lockedOrientation.isNil else {
return
}
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: OrientationTracker.shared.currentInterfaceOrientation)
}
.onAnimationCompleted(for: viewDragOffset) {
guard !dragGestureState else { return }
if viewDragOffset == 0 {
player.onPresentPlayer.forEach { $0() }
player.onPresentPlayer = []
} else if viewDragOffset == Self.hiddenOffset {
player.hide(animate: false)
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: OrientationTracker.shared.currentInterfaceOrientation)
}
.onAnimationCompleted(for: viewDragOffset) {
guard !dragGestureState else { return }
if viewDragOffset == 0 {
player.onPresentPlayer.forEach { $0() }
player.onPresentPlayer = []
} else if viewDragOffset == Self.hiddenOffset {
player.hide(animate: false)
}
}
}
#endif
}
#if os(iOS)
@ -326,7 +328,9 @@ struct VideoPlayerView: View {
}
#endif
}
#if os(iOS)
.background(BackgroundBlackView().edgesIgnoringSafeArea(.all))
#endif
.background(((colorScheme == .dark || fullScreenPlayer) ? Color.black : Color.white).edgesIgnoringSafeArea(.all))
#if os(macOS)
.frame(minWidth: 650)
@ -426,7 +430,11 @@ struct VideoPlayerView: View {
return true
}
return !avPlayerUsesSystemControls || verticalSizeClass == .compact
#if os(iOS)
return !avPlayerUsesSystemControls || verticalSizeClass == .compact
#else
return !avPlayerUsesSystemControls
#endif
}
var fullScreenPlayer: Bool {
@ -495,15 +503,17 @@ struct VideoPlayerView_Previews: PreviewProvider {
}
}
struct BackgroundBlackView: UIViewRepresentable {
func makeUIView(context _: Context) -> UIView {
let view = UIView()
DispatchQueue.main.async {
view.superview?.superview?.backgroundColor = .black
view.superview?.superview?.layer.removeAllAnimations()
#if os(iOS)
struct BackgroundBlackView: UIViewRepresentable {
func makeUIView(context _: Context) -> UIView {
let view = UIView()
DispatchQueue.main.async {
view.superview?.superview?.backgroundColor = .black
view.superview?.superview?.layer.removeAllAnimations()
}
return view
}
return view
}
func updateUIView(_: UIView, context _: Context) {}
}
func updateUIView(_: UIView, context _: Context) {}
}
#endif

View File

@ -725,6 +725,9 @@
37B795912771DAE0001CF27B /* OpenURLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B7958F2771DAE0001CF27B /* OpenURLHandler.swift */; };
37B7CFE92A19603B001B0564 /* ToolbarBackground+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B7CFE82A19603B001B0564 /* ToolbarBackground+Backport.swift */; };
37B7CFEB2A1960EC001B0564 /* ToolbarColorScheme+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B7CFEA2A1960EC001B0564 /* ToolbarColorScheme+Backport.swift */; };
37B7CFEC2A197844001B0564 /* AppleAVPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */; };
37B7CFEE2A19789F001B0564 /* MacOSPiPDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B7CFED2A19789F001B0564 /* MacOSPiPDelegate.swift */; };
37B7CFEF2A197A08001B0564 /* SafeAreaModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCD3142A18F7630059A470 /* SafeAreaModel.swift */; };
37B81AF926D2C9A700675966 /* VideoPlayerSizeModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B81AF826D2C9A700675966 /* VideoPlayerSizeModifier.swift */; };
37B81AFA26D2C9A700675966 /* VideoPlayerSizeModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B81AF826D2C9A700675966 /* VideoPlayerSizeModifier.swift */; };
37B81AFC26D2C9C900675966 /* VideoDetailsPaddingModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B81AFB26D2C9C900675966 /* VideoDetailsPaddingModifier.swift */; };
@ -781,7 +784,6 @@
37BE0BD326A1D4780092E2DB /* AppleAVPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */; };
37BE0BD426A1D47D0092E2DB /* AppleAVPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */; };
37BE0BD726A1D4A90092E2DB /* AppleAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */; };
37BE0BDC26A2367F0092E2DB /* AppleAVPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */; };
37C069782725962F00F7F6CB /* ScreenSaverManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C069772725962F00F7F6CB /* ScreenSaverManager.swift */; };
37C0697A2725C09E00F7F6CB /* PlayerQueueItemBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C069792725C09E00F7F6CB /* PlayerQueueItemBridge.swift */; };
37C0697B2725C09E00F7F6CB /* PlayerQueueItemBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C069792725C09E00F7F6CB /* PlayerQueueItemBridge.swift */; };
@ -888,7 +890,6 @@
37DCD3112A18E8150059A470 /* OrientationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCD3102A18E8150059A470 /* OrientationModel.swift */; };
37DCD3152A18F7630059A470 /* SafeAreaModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCD3142A18F7630059A470 /* SafeAreaModel.swift */; };
37DCD3172A191A180059A470 /* AVPlayerViewController+FullScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCD3162A191A180059A470 /* AVPlayerViewController+FullScreen.swift */; };
37DCD3182A191A180059A470 /* AVPlayerViewController+FullScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCD3162A191A180059A470 /* AVPlayerViewController+FullScreen.swift */; };
37DCD3192A191A180059A470 /* AVPlayerViewController+FullScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCD3162A191A180059A470 /* AVPlayerViewController+FullScreen.swift */; };
37DCD31A2A191A180059A470 /* AVPlayerViewController+FullScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCD3162A191A180059A470 /* AVPlayerViewController+FullScreen.swift */; };
37DD87C7271C9CFE0027CBF9 /* PlayerStreams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DD87C6271C9CFE0027CBF9 /* PlayerStreams.swift */; };
@ -1387,6 +1388,7 @@
37B7958F2771DAE0001CF27B /* OpenURLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenURLHandler.swift; sourceTree = "<group>"; };
37B7CFE82A19603B001B0564 /* ToolbarBackground+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ToolbarBackground+Backport.swift"; sourceTree = "<group>"; };
37B7CFEA2A1960EC001B0564 /* ToolbarColorScheme+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ToolbarColorScheme+Backport.swift"; sourceTree = "<group>"; };
37B7CFED2A19789F001B0564 /* MacOSPiPDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacOSPiPDelegate.swift; sourceTree = "<group>"; };
37B81AF826D2C9A700675966 /* VideoPlayerSizeModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerSizeModifier.swift; sourceTree = "<group>"; };
37B81AFB26D2C9C900675966 /* VideoDetailsPaddingModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDetailsPaddingModifier.swift; sourceTree = "<group>"; };
37B81AFE26D2CA3700675966 /* VideoDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDetails.swift; sourceTree = "<group>"; };
@ -1409,7 +1411,6 @@
37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = "<group>"; };
37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerViewController.swift; sourceTree = "<group>"; };
37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = "<group>"; };
37C069772725962F00F7F6CB /* ScreenSaverManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenSaverManager.swift; sourceTree = "<group>"; };
37C069792725C09E00F7F6CB /* PlayerQueueItemBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerQueueItemBridge.swift; sourceTree = "<group>"; };
37C0697D2725C8D400F7F6CB /* CMTime+DefaultTimescale.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CMTime+DefaultTimescale.swift"; sourceTree = "<group>"; };
@ -2222,8 +2223,8 @@
isa = PBXGroup;
children = (
374C0542272496E4009BDDBE /* AppDelegate.swift */,
37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */,
37FD43DB270470B70073EE42 /* InstancesSettings.swift */,
37B7CFED2A19789F001B0564 /* MacOSPiPDelegate.swift */,
3751BA7D27E63F1D007B1A60 /* MPVOGLView.swift */,
37F7AB5428A951B200FB46B5 /* Power.swift */,
37E04C0E275940FB00172673 /* VerticalScrollingFix.swift */,
@ -3349,11 +3350,11 @@
37D836BD294927E700005E5E /* ChannelsCacheModel.swift in Sources */,
3727B74B27872B880021C15E /* VisualEffectBlur-macOS.swift in Sources */,
374710062755291C00CE0F87 /* SearchTextField.swift in Sources */,
37B7CFEC2A197844001B0564 /* AppleAVPlayerView.swift in Sources */,
37F0F4EB286F397E00C06C2E /* SettingsModel.swift in Sources */,
378AE93F274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */,
37C194C826F6A9C8005D3B96 /* RecentsModel.swift in Sources */,
37737786276F9858000521C1 /* Windows.swift in Sources */,
37BE0BDC26A2367F0092E2DB /* AppleAVPlayerView.swift in Sources */,
3786D05F294C737300D23E82 /* RequestErrorButton.swift in Sources */,
3743CA53270F284F00E4D32B /* View+Borders.swift in Sources */,
37599F39272B4D740087F250 /* FavoriteButton.swift in Sources */,
@ -3418,6 +3419,7 @@
37B81B0026D2CA3700675966 /* VideoDetails.swift in Sources */,
3752069A285E8DD300CA655F /* Chapter.swift in Sources */,
373EBD69291F252D002ADB9C /* EditFavorites.swift in Sources */,
37B7CFEE2A19789F001B0564 /* MacOSPiPDelegate.swift in Sources */,
37484C1A26FC837400287258 /* PlayerSettings.swift in Sources */,
3776925329463C310055EC18 /* PlaylistsCacheModel.swift in Sources */,
37BD07C32698AD4F003EBB87 /* ContentView.swift in Sources */,
@ -3573,7 +3575,6 @@
3711404026B206A6005B3555 /* SearchModel.swift in Sources */,
37484C2A26FC83FF00287258 /* AccountForm.swift in Sources */,
37BE0BD026A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
37DCD3182A191A180059A470 /* AVPlayerViewController+FullScreen.swift in Sources */,
373CFAEC26975CBF003CB2C6 /* PlaylistFormView.swift in Sources */,
37D2E0D528B67EFC00F64D52 /* Delay.swift in Sources */,
37977584268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
@ -3752,6 +3753,7 @@
3786D060294C737300D23E82 /* RequestErrorButton.swift in Sources */,
37A362C429537FED00BDF328 /* PlaybackSettingsPresentationDetents+Backport.swift in Sources */,
37BDFF1929487B99000C6404 /* PlaylistVideosView.swift in Sources */,
37B7CFEF2A197A08001B0564 /* SafeAreaModel.swift in Sources */,
37C0698427260B2100F7F6CB /* ThumbnailsModel.swift in Sources */,
374924DC2921050B0017D862 /* LocationsSettings.swift in Sources */,
37D6025B28C17375009E8D98 /* PlaybackStatsView.swift in Sources */,

View File

@ -4,4 +4,12 @@ import SwiftUI
final class SafeAreaModel: ObservableObject {
static var shared = SafeAreaModel()
@Published var safeArea = EdgeInsets()
var horizontalInsets: Double {
safeArea.leading + safeArea.trailing
}
var verticalInsets: Double {
safeArea.top + safeArea.bottom
}
}

View File

@ -1,10 +0,0 @@
import Defaults
import SwiftUI
struct AppleAVPlayerView: NSViewRepresentable {
func makeNSView(context _: Context) -> some NSView {
PlayerLayerView(frame: .zero)
}
func updateNSView(_: NSViewType, context _: Context) {}
}

View File

@ -0,0 +1,34 @@
import AVKit
import Foundation
final class MacOSPiPDelegate: NSObject, AVPlayerViewPictureInPictureDelegate {
var playerModel: PlayerModel { .shared }
func playerViewShouldAutomaticallyDismissAtPicture(inPictureStart _: AVPlayerView) -> Bool {
false
}
func playerViewWillStartPicture(inPicture _: AVPlayerView) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
self?.playerModel.playingInPictureInPicture = true
self?.playerModel.hide()
}
}
func playerViewWillStopPicture(inPicture _: AVPlayerView) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
self?.playerModel.playingInPictureInPicture = false
self?.playerModel.show()
}
}
func playerView(
_: AVPlayerView,
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: (Bool) -> Void
) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
self?.playerModel.show()
}
completionHandler(true)
}
}