The fullscreen toggle used to slide both panels off screen while the video
frame grew into the freed space. Panels now stay at their home positions
as layers under the video, and the video frame grows over them to hide and
shrinks back to reveal. Both panels stay in the hierarchy while covered, so
scroll position and loaded content survive toggles; hit testing,
accessibility and the dismiss-pan exclusion frames are switched off while
covered (PanelResizeGrabber gets a publishesFrame flag for this).
Side column gestures (grabber overdrag, trailing edge swipe) drive the
video's trailing edge over the static column. The below panel's handle drag
keeps sliding the panel off the bottom, with the video growing in lockstep
so the edges coincide. The below panel is raised above the video only while
expanding over it, and drops back under it after the collapse spring has
fully settled.
Hiding the status bar in the fullscreen state changed the top safe area and
reflowed the whole layout mid-transition. The layout now ignores the top
safe area and pads by a fixed status bar height (remembered by
StatusBarVisibilityController while the bar is visible); the fullscreen
video grows up into that strip as part of the same animation.
Starting a column resize drag with a diagonal (downward) motion let the
window-level dismiss pan begin, cancelling the resize and dragging the
player down instead. The grabber now publishes its strip frame (with 8pt
slop on each side) to NavigationCoordinator, and the dismiss pan refuses
to begin from touches inside it — same exclusion pattern as the corner
layout's below-video panel frame.
The corner layout now always renders the info page as a portrait-style
panel below the video (collapsible description, drag to hide/expand),
while the side column holds tabs for the remaining pages. Key pieces:
- Below-video panel reuses PortraitDetailsPanel (no comments pill,
square corners, chapters/related stay in the side column tabs)
- Drag down hides the panel with the video recentering in lockstep;
swipe up on the video reveals it following the finger
- Fullscreen button toggles the panels in corner layout (controls hide
first so their resize never plays visibly); status bar and home
indicator hide only while the panels are hidden
- Panel visibility and column width are seeded at init from a warmed
PlayerControlsLayout cache, so the first frame resolves corner mode
without flashing the default layout or animating the panels in
- Dismiss pan is blocked inside the below-video panel frame
(cornerBelowPanelFrame in NavigationCoordinator)
- Resize grabber slimmed to match the panel drag handle look
The preset's When Player Opens setting only drove the landscape/floating
panel state, so on iPhone in portrait the details panel reappeared on
every player expansion regardless of the setting. Mirror the resolved
visibility into the portrait panel state, and seed it into the sheet's
initial state at all creation sites so the first frame already renders
the correct layout - applying it in onAppear animated a visible
top-to-center video jump during expansion. Portrait panel toggles now
also persist the last visibility so Remember Last works there too.
Reset isCommentsExpanded and commentsFrame on the NavigationCoordinator
directly when the portrait panel is dismissed, since PortraitDetailsPanel
owns its own @State that doesn't sync back through .onChange during dismiss.
Also track comments overlay frame via GeometryReader so the dismiss gesture
can allow swipes outside the comments area instead of blanket-blocking.