diff --git a/Model/Player/PlayerControlsModel.swift b/Model/Player/PlayerControlsModel.swift index 3d71c939..e8a55eb9 100644 --- a/Model/Player/PlayerControlsModel.swift +++ b/Model/Player/PlayerControlsModel.swift @@ -88,26 +88,6 @@ final class PlayerControlsModel: ObservableObject { } } - func toggleFullscreen(_ value: Bool) { - withAnimation(Animation.easeOut) { - resetTimer() - withAnimation(PlayerControls.animation) { - playingFullscreen = !value - } - - #if os(iOS) - if playingFullscreen { - guard !(UIApplication.shared.windows.first?.windowScene?.interfaceOrientation.isLandscape ?? true) else { - return - } - Orientation.lockOrientation(.landscape, andRotateTo: .landscapeRight) - } else { - Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait) - } - #endif - } - } - func reset() { currentTime = .zero duration = .zero diff --git a/Model/Player/PlayerModel.swift b/Model/Player/PlayerModel.swift index 050aa187..e7f504ea 100644 --- a/Model/Player/PlayerModel.swift +++ b/Model/Player/PlayerModel.swift @@ -382,8 +382,8 @@ final class PlayerModel: ObservableObject { return "\(formatter.string(from: NSNumber(value: rate))!)×" } - func closeCurrentItem() { - prepareCurrentItemForHistory() + func closeCurrentItem(finished: Bool = false) { + prepareCurrentItemForHistory(finished: finished) currentItem = nil backend.closeItem() @@ -498,4 +498,25 @@ final class PlayerModel: ObservableObject { currentArtwork = MPMediaItemArtwork(boundsSize: image!.size) { _ in image! } } + + func toggleFullscreen(_ isFullScreen: Bool) { + controls.resetTimer() + + #if os(macOS) + Windows.player.toggleFullScreen() + #endif + + controls.playingFullscreen = !isFullScreen + + #if os(iOS) + if controls.playingFullscreen { + guard !(UIApplication.shared.windows.first?.windowScene?.interfaceOrientation.isLandscape ?? true) else { + return + } + Orientation.lockOrientation(.landscape, andRotateTo: .landscapeRight) + } else { + Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait) + } + #endif + } } diff --git a/Shared/Player/Controls/PlayerControls.swift b/Shared/Player/Controls/PlayerControls.swift index e4186d3d..189b8cc3 100644 --- a/Shared/Player/Controls/PlayerControls.swift +++ b/Shared/Player/Controls/PlayerControls.swift @@ -187,7 +187,7 @@ struct PlayerControls: View { "Fullscreen", systemImage: fullScreenLayout ? "arrow.down.right.and.arrow.up.left" : "arrow.up.left.and.arrow.down.right" ) { - model.toggleFullscreen(fullScreenLayout) + player.toggleFullscreen(fullScreenLayout) } #if !os(tvOS) .keyboardShortcut(fullScreenLayout ? .cancelAction : .defaultAction) diff --git a/Shared/Player/VideoPlayerView.swift b/Shared/Player/VideoPlayerView.swift index 15ffc0a8..64913846 100644 --- a/Shared/Player/VideoPlayerView.swift +++ b/Shared/Player/VideoPlayerView.swift @@ -49,38 +49,36 @@ struct VideoPlayerView: View { .onOpenURL { OpenURLHandler(accounts: accounts, player: player).handle($0) } .frame(minWidth: 950, minHeight: 700) #else - GeometryReader { geometry in - HStack(spacing: 0) { - content - .onAppear { - #if os(iOS) - configureOrientationUpdatesBasedOnAccelerometer() - #endif - } - } - .onChange(of: fullScreenDetails) { value in - player.backend.setNeedsDrawing(!value) - } - #if os(iOS) - .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in - handleOrientationDidChangeNotification() - } - .onDisappear { - guard !playerControls.playingFullscreen else { - return // swiftlint:disable:this implicit_return + HStack(spacing: 0) { + content + .onAppear { + #if os(iOS) + configureOrientationUpdatesBasedOnAccelerometer() + #endif } - - if Defaults[.lockPortraitWhenBrowsing] { - Orientation.lockOrientation(.portrait, andRotateTo: .portrait) - } else { - Orientation.lockOrientation(.allButUpsideDown) - } - - motionManager?.stopAccelerometerUpdates() - motionManager = nil - } - #endif } + .onChange(of: fullScreenDetails) { value in + player.backend.setNeedsDrawing(!value) + } + #if os(iOS) + .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in + handleOrientationDidChangeNotification() + } + .onDisappear { + guard !playerControls.playingFullscreen else { + return // swiftlint:disable:this implicit_return + } + + if Defaults[.lockPortraitWhenBrowsing] { + Orientation.lockOrientation(.portrait, andRotateTo: .portrait) + } else { + Orientation.lockOrientation(.allButUpsideDown) + } + + motionManager?.stopAccelerometerUpdates() + motionManager = nil + } + #endif #endif } diff --git a/Shared/YatteeApp.swift b/Shared/YatteeApp.swift index 57a42564..2ec75b47 100644 --- a/Shared/YatteeApp.swift +++ b/Shared/YatteeApp.swift @@ -92,6 +92,16 @@ struct YatteeApp: App { .background( HostingWindowFinder { window in Windows.playerWindow = window + + NotificationCenter.default.addObserver( + forName: NSWindow.willExitFullScreenNotification, + object: window, + queue: OperationQueue.main + ) { _ in + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.player.controls.playingFullscreen = false + } + } } ) .onAppear { player.presentingPlayer = true } diff --git a/macOS/Windows.swift b/macOS/Windows.swift index 06eb4ec9..c6181750 100644 --- a/macOS/Windows.swift +++ b/macOS/Windows.swift @@ -42,6 +42,10 @@ enum Windows: String, CaseIterable { Self.main.focus() } } + + func toggleFullScreen() { + window?.toggleFullScreen(nil) + } } struct HostingWindowFinder: NSViewRepresentable {