mirror of
https://github.com/yattee/yattee.git
synced 2026-11-06 03:47:17 +00:00
Rework corner layout with portrait-style info panel below the video
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
This commit is contained in:
@@ -43,6 +43,8 @@ struct PlayerControlsView: View {
|
||||
var isPanelVisible: Bool = true
|
||||
var panelSide: FloatingPanelSide = .right
|
||||
var isPanelPinned: Bool = false
|
||||
/// Corner layout: fullscreen button toggles the panels
|
||||
var isCornerLayout: Bool = false
|
||||
/// Safe area padding from layout (when panel is pinned)
|
||||
var layoutLeadingSafeArea: CGFloat = 0
|
||||
var layoutTrailingSafeArea: CGFloat = 0
|
||||
@@ -230,6 +232,14 @@ struct PlayerControlsView: View {
|
||||
cancelHideTimer()
|
||||
}
|
||||
}
|
||||
.onChange(of: isPanelVisible) { oldValue, newValue in
|
||||
// Corner layout: any panel toggle resizes the controls area —
|
||||
// keep the controls hidden while that transition plays
|
||||
if isCornerLayout, oldValue != newValue {
|
||||
showControls = false
|
||||
cancelHideTimer()
|
||||
}
|
||||
}
|
||||
.onChange(of: playerState.retryState.exhausted) { _, exhausted in
|
||||
// Hide controls when retries are exhausted (retry exhausted overlay takes over)
|
||||
if exhausted {
|
||||
@@ -389,6 +399,7 @@ struct PlayerControlsView: View {
|
||||
isOrientationLocked: isOrientationLocked,
|
||||
isPanelVisible: isPanelVisible,
|
||||
isPanelPinned: isPanelPinned,
|
||||
isCornerLayout: isCornerLayout,
|
||||
panelSide: panelSide,
|
||||
isIPad: isIPad,
|
||||
showVolumeControls: showVolumeControls,
|
||||
@@ -415,6 +426,10 @@ struct PlayerControlsView: View {
|
||||
onTogglePiP: onTogglePiP,
|
||||
onToggleFullscreen: onToggleFullscreen,
|
||||
onToggleDetailsVisibility: onToggleDetailsVisibility,
|
||||
onHideControls: { [self] in
|
||||
showControls = false
|
||||
cancelHideTimer()
|
||||
},
|
||||
onToggleOrientationLock: onToggleOrientationLock,
|
||||
onTogglePanel: onTogglePanel,
|
||||
onTogglePanscan: onTogglePanscan,
|
||||
@@ -484,7 +499,11 @@ struct PlayerControlsView: View {
|
||||
// bottomExtraPadding handles positioning, so no safe area needed
|
||||
// In landscape (widescreen), cap the safe area since home indicator needs less clearance
|
||||
let floatingPanelActive = isPanelVisible && !isPanelPinned
|
||||
let needsBottomSafeArea = (isWideScreenLayout || isFullscreen) && !floatingPanelActive
|
||||
// Corner layout with panels visible: the controls frame ends at the
|
||||
// video area mid-screen, so the window's bottom safe area (incl. the
|
||||
// PiP inset) must not push the bottom bar up from the video edge
|
||||
let cornerPanelsActive = isCornerLayout && isPanelVisible
|
||||
let needsBottomSafeArea = (isWideScreenLayout || isFullscreen) && !floatingPanelActive && !cornerPanelsActive
|
||||
let bottomSafeArea = isWideScreenLayout ? min(safeArea.bottom, 12) : safeArea.bottom
|
||||
let bottomPadding: CGFloat = 2 + (needsBottomSafeArea ? bottomSafeArea : 0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user