From 77c3103748237dcd58bb3b175f546f0dc5b93f7a Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Mon, 12 Oct 2026 22:03:02 +0200 Subject: [PATCH] Keep player buttons off the hinge in book posture On a foldable with the hinge partially open in landscape, the fullscreen player's buttons move to the half right of the hinge. The dimming background and tap handling still cover the whole screen. --- .../Player/ExpandedPlayerSheet+Layouts.swift | 21 ++++++++++++++++++- Yattee/Views/Player/PlayerControlsView.swift | 5 +++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Yattee/Views/Player/ExpandedPlayerSheet+Layouts.swift b/Yattee/Views/Player/ExpandedPlayerSheet+Layouts.swift index dac8f02d..2f806595 100644 --- a/Yattee/Views/Player/ExpandedPlayerSheet+Layouts.swift +++ b/Yattee/Views/Player/ExpandedPlayerSheet+Layouts.swift @@ -30,6 +30,9 @@ extension ExpandedPlayerSheet { /// center controls and side sliders clear of both. static let tabletopTopBarInset: CGFloat = 72 static let tabletopBottomBarInset: CGFloat = 96 + /// Book posture (hinge vertical): clearance between the hinge line and + /// the controls confined to the trailing half. + static let bookFoldHingeGap: CGFloat = 16 #if os(iOS) /// Reflection strength at the hinge line; it fades to nothing at @@ -1419,6 +1422,21 @@ extension ExpandedPlayerSheet { // Calculate offset for controls positioning (used for animation) let controlsOffset = (leadingSafeArea - trailingSafeArea) / 2 + #if os(iOS) + // Foldable in book posture (hinge partially open, landscape, the + // player spanning the fold): the buttons move to the trailing half so + // nothing sits on the hinge; dimming and taps still cover the whole + // screen. The corner layout's hinge split with panels shown already + // gives the player one half only. + let bookFoldButtonsInset: CGFloat = { + guard isTabletopHinge, + fullWidth > fullHeight, + fullWidth >= Self.minWidthForCornerLayout else { return 0 } + // Controls frame starts at the leading safe area + return max(0, fullWidth / 2 + Self.bookFoldHingeGap - leadingSafeArea) + }() + #endif + // Calculate video frame size based on panscan // At panscan 0: aspect-fit (may have black bars) // At panscan 1: aspect-fill (cropped to fill) @@ -1665,7 +1683,8 @@ extension ExpandedPlayerSheet { onTogglePanscan: { [weak navigationCoordinator] in navigationCoordinator?.togglePanscan() }, - activeLayout: playerControlsLayout + activeLayout: playerControlsLayout, + buttonsLeadingInset: bookFoldButtonsInset ) .frame(width: availableWidth, height: availableHeight) .offset(x: controlsOffset) diff --git a/Yattee/Views/Player/PlayerControlsView.swift b/Yattee/Views/Player/PlayerControlsView.swift index a5fbb898..1a99e552 100644 --- a/Yattee/Views/Player/PlayerControlsView.swift +++ b/Yattee/Views/Player/PlayerControlsView.swift @@ -149,6 +149,10 @@ struct PlayerControlsView: View { @Environment(\.statusBarVisibilityController) private var statusBarController /// Active player controls layout from preset (passed from parent to avoid flashing during view recreation) var activeLayout: PlayerControlsLayout = .default + /// Moves the buttons off the leading part of the controls frame while the + /// dimming background and tap handling keep covering all of it (foldable + /// book posture: buttons on the half right of the hinge). + var buttonsLeadingInset: CGFloat = 0 /// Animation trigger for seek backward button @State private var seekBackwardTrigger = false /// Animation trigger for seek forward button @@ -512,6 +516,7 @@ struct PlayerControlsView: View { // Controls layout - explicitly fill parent bounds controlsVStack + .padding(.leading, buttonsLeadingInset) .frame(maxWidth: .infinity, maxHeight: .infinity) } }