mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 13:12:53 +00:00
Fix clipped top controls and stale top padding in corner fullscreen
The fullscreen video layer extends up into the status bar strip and is shifted with an offset; `.clipped()` came after the offset, so it clipped to the unshifted frame and cut the top strip (title row, avatar) off. Clip before the offset instead. The player controls read the main window's safe area only on geometry changes. With the corner layout keeping its geometry fixed across the status bar hide, the value went stale and the controls kept the status bar height as top padding in fullscreen. Refresh it when the status bar visibility changes, with a few delayed re-reads to cover the fade.
This commit is contained in:
@@ -444,6 +444,11 @@ struct CornerPlayerLayout<PlayerContent: View>: View {
|
||||
)
|
||||
}
|
||||
.frame(width: videoWidth, height: videoHeight + videoTopExtension)
|
||||
// Clip in the frame's own coordinates, BEFORE the offset —
|
||||
// clipping after it uses the unshifted layout frame and cuts
|
||||
// the top strip (status bar height) off the fullscreen video
|
||||
// and its top controls.
|
||||
.clipped()
|
||||
.offset(y: -videoTopExtension)
|
||||
// Keyed to gesture/visibility state, NOT to derived geometry —
|
||||
// appear settling must not animate. The drag-offset springs
|
||||
@@ -456,7 +461,6 @@ struct CornerPlayerLayout<PlayerContent: View>: View {
|
||||
// Aspect ratio changes (new video, stream switch) resize
|
||||
// the video/panel split — animate them
|
||||
.animation(isPanelDragActive ? nil : .spring(response: 0.3, dampingFraction: 1.0), value: playerState?.displayAspectRatio)
|
||||
.clipped()
|
||||
// Swipe up on the video to bring the panel back — the
|
||||
// video's bottom edge follows the finger (like the portrait
|
||||
// reveal) via belowPanelDragOffset counting down from full
|
||||
|
||||
@@ -141,6 +141,7 @@ struct PlayerControlsView: View {
|
||||
@State private var playNextTapCount = 0
|
||||
/// Track safe area to force re-render when it changes
|
||||
@State private var currentSafeArea: UIEdgeInsets = .zero
|
||||
@Environment(\.statusBarVisibilityController) private var statusBarController
|
||||
/// Active player controls layout from preset (passed from parent to avoid flashing during view recreation)
|
||||
var activeLayout: PlayerControlsLayout = .default
|
||||
/// Animation trigger for seek backward button
|
||||
@@ -268,6 +269,18 @@ struct PlayerControlsView: View {
|
||||
// Update safe area when geometry changes (rotation)
|
||||
currentSafeArea = windowSafeArea
|
||||
}
|
||||
.onChange(of: statusBarController?.isHidden) { _, _ in
|
||||
// The window safe area follows the status bar fade with a delay.
|
||||
// Corner layout keeps its geometry fixed across the toggle, so
|
||||
// no geometry change refreshes the value — poll a few times
|
||||
// instead of keeping a stale status bar height as top padding.
|
||||
currentSafeArea = windowSafeArea
|
||||
for delay in [0.15, 0.4, 0.8] {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
|
||||
currentSafeArea = windowSafeArea
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: activeLayout.effectiveGesturesSettings.panscanGesture.snapToEnds, initial: true) { _, newValue in
|
||||
// Sync panscan snap setting to navigation coordinator (initial: true ensures sync on first render)
|
||||
appEnvironment?.navigationCoordinator.shouldSnapPanscan = newValue
|
||||
|
||||
Reference in New Issue
Block a user