From b0f573be820693e96cbbb695c235d0090c04f29d Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Mon, 3 Aug 2026 19:36:49 +0200 Subject: [PATCH] Fix double-tap fullscreen gesture rotating on portrait videos The fullscreen button routes through a portrait-video check (toggling the details panel instead of rotating), but the double-tap gesture called onToggleFullscreen directly and always rotated to landscape. Extract the shared decision into PlayerControlsActions.performFullscreenTap() and use it from both the button and the tap gesture handler. --- .../Player/ControlsSectionRenderer.swift | 22 +------------------ .../Views/Player/PlayerControlsActions.swift | 22 ++++++++++++++++++- Yattee/Views/Player/PlayerControlsView.swift | 4 ++-- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Yattee/Views/Player/ControlsSectionRenderer.swift b/Yattee/Views/Player/ControlsSectionRenderer.swift index fd56db16..a29b825d 100644 --- a/Yattee/Views/Player/ControlsSectionRenderer.swift +++ b/Yattee/Views/Player/ControlsSectionRenderer.swift @@ -125,7 +125,7 @@ struct ControlsSectionRenderer: View { case .fullscreen: if actions.shouldShowFullscreenButton { controlButton(systemImage: actions.fullscreenIcon) { - handleFullscreenTap() + actions.performFullscreenTap() } .disabled(isLocked) .opacity(isLocked ? 0.5 : 1.0) @@ -818,26 +818,6 @@ struct ControlsSectionRenderer: View { .animation(.easeInOut(duration: 0.2), value: isBrightnessExpanded) } - // MARK: - Fullscreen Handling - - private func handleFullscreenTap() { - let isActualWidescreenLayout = actions.isWideScreenLayout && actions.onTogglePanel != nil - - if actions.isIPad { - // iPad: always toggle details visibility - actions.onToggleDetailsVisibility?() - } else if isActualWidescreenLayout && actions.isFullscreen && !actions.isWidescreenVideo { - // iPhone in landscape with portrait video fullscreen: rotate back to portrait - actions.onToggleFullscreen?() - } else if !actions.isWidescreenVideo { - // iPhone portrait video in portrait layout: toggle details visibility - actions.onToggleDetailsVisibility?() - } else { - // iPhone with widescreen video: rotate orientation - actions.onToggleFullscreen?() - } - } - // MARK: - Transport State private var isTransportDisabled: Bool { diff --git a/Yattee/Views/Player/PlayerControlsActions.swift b/Yattee/Views/Player/PlayerControlsActions.swift index 3e95a69d..781793b5 100644 --- a/Yattee/Views/Player/PlayerControlsActions.swift +++ b/Yattee/Views/Player/PlayerControlsActions.swift @@ -277,8 +277,28 @@ struct PlayerControlsActions { } } + /// Shared fullscreen-tap decision used by the fullscreen button and tap gestures. + /// Keep in sync with `willRotateOnFullscreenToggle` (icon mirror of this logic). + func performFullscreenTap() { + let isActualWidescreenLayout = isWideScreenLayout && onTogglePanel != nil + + if isIPad { + // iPad: always toggle details visibility + onToggleDetailsVisibility?() + } else if isActualWidescreenLayout && isFullscreen && !isWidescreenVideo { + // iPhone in landscape with portrait video fullscreen: rotate back to portrait + onToggleFullscreen?() + } else if !isWidescreenVideo { + // iPhone portrait video in portrait layout: toggle details visibility + onToggleDetailsVisibility?() + } else { + // iPhone with widescreen video: rotate orientation + onToggleFullscreen?() + } + } + /// Whether tapping fullscreen will cause device rotation. - /// Mirrors the logic in ControlsSectionRenderer.handleFullscreenTap() + /// Mirrors the logic in `performFullscreenTap()` var willRotateOnFullscreenToggle: Bool { // iPad never rotates via fullscreen button guard !isIPad else { return false } diff --git a/Yattee/Views/Player/PlayerControlsView.swift b/Yattee/Views/Player/PlayerControlsView.swift index dbf5665f..9337d380 100644 --- a/Yattee/Views/Player/PlayerControlsView.swift +++ b/Yattee/Views/Player/PlayerControlsView.swift @@ -1220,8 +1220,8 @@ struct PlayerControlsView: View { } case .toggleFullscreen: - // Execute immediately - onToggleFullscreen?() + // Execute immediately, using the same decision logic as the fullscreen button + controlsActions.performFullscreenTap() case .togglePiP: // Execute immediately