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.
This commit is contained in:
Arkadiusz Fal
2026-08-03 19:36:49 +02:00
parent 01cf9c953d
commit b0f573be82
3 changed files with 24 additions and 24 deletions

View File

@@ -125,7 +125,7 @@ struct ControlsSectionRenderer: View {
case .fullscreen: case .fullscreen:
if actions.shouldShowFullscreenButton { if actions.shouldShowFullscreenButton {
controlButton(systemImage: actions.fullscreenIcon) { controlButton(systemImage: actions.fullscreenIcon) {
handleFullscreenTap() actions.performFullscreenTap()
} }
.disabled(isLocked) .disabled(isLocked)
.opacity(isLocked ? 0.5 : 1.0) .opacity(isLocked ? 0.5 : 1.0)
@@ -818,26 +818,6 @@ struct ControlsSectionRenderer: View {
.animation(.easeInOut(duration: 0.2), value: isBrightnessExpanded) .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 // MARK: - Transport State
private var isTransportDisabled: Bool { private var isTransportDisabled: Bool {

View File

@@ -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. /// Whether tapping fullscreen will cause device rotation.
/// Mirrors the logic in ControlsSectionRenderer.handleFullscreenTap() /// Mirrors the logic in `performFullscreenTap()`
var willRotateOnFullscreenToggle: Bool { var willRotateOnFullscreenToggle: Bool {
// iPad never rotates via fullscreen button // iPad never rotates via fullscreen button
guard !isIPad else { return false } guard !isIPad else { return false }

View File

@@ -1220,8 +1220,8 @@ struct PlayerControlsView: View {
} }
case .toggleFullscreen: case .toggleFullscreen:
// Execute immediately // Execute immediately, using the same decision logic as the fullscreen button
onToggleFullscreen?() controlsActions.performFullscreenTap()
case .togglePiP: case .togglePiP:
// Execute immediately // Execute immediately