Lock macOS inline player sheet resize to the video aspect ratio

In floating/window mode, interactive resize is aspect-locked via the
window's contentAspectRatio, so no black bars appear. The inline sheet
had no such lock, allowing free resize with pan bars on the sides.

Make applyAspectRatioConstraint static so the sheet path can reuse the
exact same lock the standalone window uses, and apply it to the sheet's
backing NSWindow from SheetWindowResizer whenever the video ratio is
known. Like the standalone window, the resize lock always follows the
real video ratio (independent of the playerSheetAutoResize size setting).
This commit is contained in:
Arkadiusz Fal
2026-05-27 23:21:07 +02:00
parent 6bc58f10b2
commit ef213307dc
2 changed files with 37 additions and 9 deletions

View File

@@ -94,6 +94,7 @@ struct ContentView: View {
set: { appEnvironment.navigationCoordinator.isPlayerExpanded = $0 }
)) {
let size = expandedSheetSize(appEnvironment: appEnvironment)
let lockAspect = sheetLockAspectRatio(appEnvironment: appEnvironment)
ExpandedPlayerSheet()
// Floor keeps the content flexible so it tracks the window's
// animated resize with no gap do NOT pin an exact (max) size:
@@ -109,8 +110,9 @@ struct ContentView: View {
.presentationSizing(.fitted)
// `.presentationSizing(.fitted)` only fits the sheet once, at
// presentation. Resize the backing window directly when the
// aspect-ratio-derived size changes so the sheet tracks the video.
.sheetWindowSize(size)
// aspect-ratio-derived size changes so the sheet tracks the video,
// and lock interactive resize to the video ratio (no black bars).
.sheetWindowSize(size, aspectRatio: lockAspect)
}
#elseif os(tvOS)
.fullScreenCover(isPresented: Binding(
@@ -142,6 +144,16 @@ struct ContentView: View {
}
return ExpandedPlayerWindowManager.fittedSheetSize(for: aspect)
}
/// Real video aspect ratio to lock the sheet's interactive resize to, or `0`
/// when unknown. Unlike the sheet *size* (which honors `playerSheetAutoResize`),
/// the resize lock always follows the actual video ratio mirroring the
/// standalone window, which locks unconditionally. Reading `videoAspectRatio`
/// here registers the @Observable dependency that keeps the lock in sync.
private func sheetLockAspectRatio(appEnvironment: AppEnvironment) -> Double {
let ratio = appEnvironment.playerService.state.videoAspectRatio ?? 0
return ratio > 0 ? ratio : 0
}
#endif
#if os(macOS)