Keep the player pill off the hinge in book posture

On a foldable with the hinge partially open, the corner layout's player
pill moves to the center of the trailing half while the side column is
hidden. It slides with the column as it is dragged away or revealed,
keeping its width.
This commit is contained in:
Arkadiusz Fal
2026-10-13 19:01:43 +02:00
parent 3bcf1a52d3
commit a2ee7d5363
2 changed files with 20 additions and 2 deletions

View File

@@ -265,6 +265,13 @@ struct CornerPlayerLayout<PlayerContent: View>: View {
let sideColumnSlide = hasSideColumnLayout ? min(sideColumnHideTravel, max(0, sideColumnDragOffset)) : 0
let columnVideoWidth = hasSideColumnLayout ? min(width, shownVideoWidth + sideColumnSlide) : width
let videoWidth = isPanelVisible ? columnVideoWidth : width
// Hinge split: as the column hides, the below panel widens over
// the fold, so its pills slide from the leading half's center to
// the trailing half's in lockstep with the column (and back on
// reveal). The pills' width (panel width minus inset) stays half
// the screen throughout.
let sideColumnHiddenProgress: CGFloat = hasSideColumnLayout ? sideColumnSlide / max(1, sideColumnHideTravel) : 1
let hingePillsLeadingInset: CGFloat = isHingeSplit ? width / 2 * sideColumnHiddenProgress : 0
let shownVideoHeight: CGFloat = {
let rawAspectRatio = playerState?.displayAspectRatio ?? (16.0 / 9.0)
let aspectRatio = rawAspectRatio > 0 ? rawAspectRatio : (16.0 / 9.0)
@@ -414,7 +421,12 @@ struct CornerPlayerLayout<PlayerContent: View>: View {
Spacer(minLength: 0)
.frame(height: panelSpacerHeight)
belowVideoInfoPanel(video: video, hideTravel: panelHideTravel, publishesFrame: showsBelowVideo)
belowVideoInfoPanel(
video: video,
hideTravel: panelHideTravel,
publishesFrame: showsBelowVideo,
pillsLeadingInset: hingePillsLeadingInset
)
.frame(width: columnVideoWidth)
.frame(height: panelHeight)
.offset(y: belowPanelSlide)
@@ -642,7 +654,7 @@ struct CornerPlayerLayout<PlayerContent: View>: View {
/// pill hidden and no inline chapters/related — those live in the side
/// column tabs.
@ViewBuilder
private func belowVideoInfoPanel(video: Video, hideTravel: CGFloat, publishesFrame: Bool) -> some View {
private func belowVideoInfoPanel(video: Video, hideTravel: CGFloat, publishesFrame: Bool, pillsLeadingInset: CGFloat) -> some View {
Group {
#if os(iOS)
PortraitDetailsPanel(
@@ -653,6 +665,7 @@ struct CornerPlayerLayout<PlayerContent: View>: View {
hidesCommentsPill: !hasBelowVideoComments,
inlineInfoSections: false,
panelCornerRadius: 0,
pillsLeadingInset: pillsLeadingInset,
onDragChanged: { offset in
if appEnvironment?.navigationCoordinator.isPanelDragging != true {
appEnvironment?.navigationCoordinator.isPanelDragging = true

View File

@@ -30,6 +30,10 @@ struct PortraitDetailsPanel: View {
/// Panel clip rounding — the corner layout's below-video host uses 0
/// for a plain rectangle.
var panelCornerRadius: CGFloat = 16
/// Moves the pills off the leading part of the panel (foldable book
/// posture with the side column hidden: pills centered on the half right
/// of the hinge).
var pillsLeadingInset: CGFloat = 0
// Drag gesture callbacks
var onDragChanged: ((CGFloat) -> Void)?
@@ -240,6 +244,7 @@ struct PortraitDetailsPanel: View {
.overlay {
if !isCommentsExpanded {
pillsOverlay
.padding(.leading, pillsLeadingInset)
.opacity(pillsOverlayOpacity)
.allowsHitTesting(pillsOverlayOpacity > 0.01)
}