mirror of
https://github.com/yattee/yattee.git
synced 2026-10-25 22:22:52 +00:00
Replace UIScreen.main with scene-local context
- List row hairlines read displayScale from the SwiftUI environment - MPV render views take contentScaleFactor from traitCollection and re-apply it on UITraitDisplayScale changes - ExpandedPlayerWindow scales against the presenting view's own height - MPVPiPBridge sizes the PiP layer from the container view's window scene screen (UIScreen.main kept only as a nil-window fallback) - WideScreenPlayerLayout falls back to the offered geometry size - Remote control fullscreen state comes from the player sheet's layout pass via NavigationCoordinator.isWideScreenLayoutActive instead of screen bounds aspect - Orientation TODOs for Dynamic Island side detection and prefersInterfaceOrientationLocked
This commit is contained in:
@@ -16,6 +16,8 @@ struct SourceListRow<Content: View>: View {
|
||||
|
||||
@ViewBuilder let content: () -> Content
|
||||
|
||||
@Environment(\.displayScale) private var displayScale
|
||||
|
||||
/// Horizontal padding for row content.
|
||||
#if os(macOS)
|
||||
private let horizontalPadding: CGFloat = 12
|
||||
@@ -64,7 +66,7 @@ struct SourceListRow<Content: View>: View {
|
||||
#if os(iOS)
|
||||
Rectangle()
|
||||
.fill(Color(uiColor: .separator))
|
||||
.frame(height: 1 / UIScreen.main.scale)
|
||||
.frame(height: 1 / displayScale)
|
||||
.padding(.leading, dividerLeadingPadding)
|
||||
#elseif os(macOS)
|
||||
Rectangle()
|
||||
|
||||
@@ -56,6 +56,8 @@ struct VideoListRow<Content: View>: View {
|
||||
|
||||
@ViewBuilder let content: () -> Content
|
||||
|
||||
@Environment(\.displayScale) private var displayScale
|
||||
|
||||
/// Horizontal padding for row content.
|
||||
private let horizontalPadding: CGFloat = 16
|
||||
|
||||
@@ -91,7 +93,7 @@ struct VideoListRow<Content: View>: View {
|
||||
#if os(iOS)
|
||||
Rectangle()
|
||||
.fill(Color(uiColor: .separator))
|
||||
.frame(height: 1 / UIScreen.main.scale)
|
||||
.frame(height: 1 / displayScale)
|
||||
.padding(.leading, dividerLeadingPadding)
|
||||
#elseif os(macOS)
|
||||
Rectangle()
|
||||
|
||||
@@ -367,6 +367,9 @@ struct ExpandedPlayerSheet: View {
|
||||
navigationCoordinator?.isCornerLayoutActive = newValue
|
||||
}
|
||||
#endif
|
||||
.onChange(of: wideScreen, initial: true) { _, newValue in
|
||||
navigationCoordinator?.isWideScreenLayoutActive = newValue
|
||||
}
|
||||
.onChange(of: wideScreen) { _, newValue in
|
||||
isInWideScreenLayout = newValue
|
||||
#if os(iOS)
|
||||
|
||||
@@ -622,11 +622,6 @@ final class ExpandedPlayerWindowManager {
|
||||
mainWindow?.subviews.first
|
||||
}
|
||||
|
||||
/// Current window height for calculating transforms
|
||||
private var windowHeight: CGFloat {
|
||||
mainWindow?.bounds.height ?? UIScreen.main.bounds.height
|
||||
}
|
||||
|
||||
/// Applies scale and corner radius to main window based on progress (0 = normal, 1 = fully scaled)
|
||||
func scaleMainWindow(progress: CGFloat) {
|
||||
// Capture the presenting view reference on first call
|
||||
@@ -648,7 +643,7 @@ final class ExpandedPlayerWindowManager {
|
||||
let scale = 1 - scaleAmount
|
||||
|
||||
// Offset to keep the view centered vertically after scaling
|
||||
let offsetY = (windowHeight * scaleAmount) / 2
|
||||
let offsetY = (presentingView.bounds.height * scaleAmount) / 2
|
||||
|
||||
// Apply corner radius proportional to progress
|
||||
presentingView.layer.cornerRadius = clampedProgress * scaledCornerRadius
|
||||
@@ -667,7 +662,7 @@ final class ExpandedPlayerWindowManager {
|
||||
let clampedProgress = max(0, min(1, progress))
|
||||
let scaleAmount = clampedProgress * maxScaleProgress
|
||||
let scale = 1 - scaleAmount
|
||||
let offsetY = (windowHeight * scaleAmount) / 2
|
||||
let offsetY = (presentingView.bounds.height * scaleAmount) / 2
|
||||
let cornerRadius = clampedProgress * scaledCornerRadius
|
||||
|
||||
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: damping, initialSpringVelocity: 0, options: []) {
|
||||
|
||||
@@ -139,12 +139,11 @@ struct WideScreenPlayerLayout<PlayerContent: View>: View {
|
||||
|
||||
/// Get full screen bounds from window scene (ignores safe area constraints from parent)
|
||||
/// On macOS, this is not used - geometry reader size is used directly
|
||||
private var windowSceneBounds: CGSize {
|
||||
private func windowSceneBounds(fallback: CGSize) -> CGSize {
|
||||
#if os(iOS)
|
||||
guard let window = foregroundWindow else {
|
||||
// Fallback to screen bounds
|
||||
let screen = UIScreen.main.bounds
|
||||
return CGSize(width: max(screen.width, screen.height), height: min(screen.width, screen.height))
|
||||
// Fallback to the space this view was actually offered
|
||||
return fallback
|
||||
}
|
||||
// Window frame gives actual size including orientation
|
||||
return window.frame.size
|
||||
@@ -158,7 +157,7 @@ struct WideScreenPlayerLayout<PlayerContent: View>: View {
|
||||
// On iOS: Use window bounds to get full size (avoids safe area constraint from parent)
|
||||
// On macOS: Use geometry reader size directly (no safe area concerns, window is the source of truth)
|
||||
#if os(iOS)
|
||||
let windowBounds = windowSceneBounds
|
||||
let windowBounds = windowSceneBounds(fallback: geometry.size)
|
||||
let availableWidth = windowBounds.width
|
||||
let availableHeight = windowBounds.height
|
||||
let safeAreaLeft = windowSafeAreaInsets.leading
|
||||
@@ -181,6 +180,13 @@ struct WideScreenPlayerLayout<PlayerContent: View>: View {
|
||||
// Detect which side has Dynamic Island based on interface orientation
|
||||
// Note: Can't use safe area comparison because both sides have similar values (~62px each)
|
||||
#if os(iOS)
|
||||
// TODO: Modernization - This distinguishes landscapeLeft from landscapeRight to locate
|
||||
// the Dynamic Island, which window bounds/size classes cannot express. Read the
|
||||
// orientation from the hosting scene's `effectiveGeometry.interfaceOrientation`
|
||||
// (iOS 26+) instead of the deprecated `UIWindowScene.interfaceOrientation` once the
|
||||
// deployment target allows, and consider `traitCollection.verticalBarEdge` (iOS 27.1)
|
||||
// for the bar-edge question. Global scene lookup should be replaced by the hosting
|
||||
// window (e.g. via a UIViewRepresentable reading `view.window?.windowScene`).
|
||||
let interfaceOrientation = UIApplication.shared.connectedScenes
|
||||
.compactMap { $0 as? UIWindowScene }
|
||||
.first?
|
||||
|
||||
Reference in New Issue
Block a user