Split macOS player mode into window toggle + floating control

Replace the three-way macOS Player Mode picker (Separate Window /
Floating Window / Inline) with a single 'Play in a separate window'
toggle in Playback settings, and move the always-on-top choice to a
pin button in the player's top bar (window mode only).

Floating was really a transient window property (NSWindow.level), not
a peer of the window/inline structural choice — so it belongs on a live
control, not in Settings. The pin state persists across sessions.

- Replace MacPlayerMode enum with macPlayerSeparateWindow /
  macPlayerFloating bool settings
- Branch runtime presentation and window level off the two bools
- Add pin.fill/pin toggle to MacOSPlayerControlsView top bar
- Update localization; drop obsolete playerMode strings and enum tests
This commit is contained in:
Arkadiusz Fal
2026-05-30 12:42:18 +02:00
parent 64ca1c10d9
commit 2f2e436fe2
10 changed files with 85 additions and 129 deletions

View File

@@ -70,8 +70,8 @@ final class ExpandedPlayerWindowManager: NSObject {
// Mark expanding state for mini player coordination
appEnvironment.navigationCoordinator.isPlayerExpanding = true
// Get the current player mode for window configuration
let mode = appEnvironment.settingsManager.macPlayerMode
// Whether the window should float above other windows (always on top).
let floating = appEnvironment.settingsManager.macPlayerFloating
// Host a lightweight two-phase root instead of ExpandedPlayerSheet directly.
// AppKit won't composite the window to screen until the hosted SwiftUI view
@@ -133,8 +133,8 @@ final class ExpandedPlayerWindowManager: NSObject {
// Make ExpandedPlayerWindowManager itself the delegate to avoid lifecycle issues
window.delegate = self
// Configure window level based on mode
configureWindowLevel(window, floating: mode.isFloating)
// Configure window level based on the floating preference
configureWindowLevel(window, floating: floating)
// Center window on screen
window.center()

View File

@@ -113,6 +113,24 @@ struct MacOSPlayerControlsView: View {
Spacer(minLength: 12)
// Floating (always-on-top) toggle only meaningful for the separate
// window presentation, so hidden in the inline sheet and in fullscreen.
if let settings = appEnvironment?.settingsManager,
settings.macPlayerSeparateWindow, !isFullscreen {
Button {
settings.macPlayerFloating.toggle()
} label: {
Image(systemName: settings.macPlayerFloating ? "pin.fill" : "pin")
.font(.system(size: 15, weight: .semibold))
.foregroundStyle(.white)
.frame(width: 30, height: 30)
.background(.ultraThinMaterial, in: Circle())
}
.buttonStyle(.plain)
.help(Text("player.controls.keepOnTop"))
.accessibilityLabel(Text("player.controls.keepOnTop"))
}
if onClose != nil {
Button {
onClose?()

View File

@@ -250,14 +250,10 @@ private struct BehaviorSection: View {
SettingsFormSection("settings.playback.behavior.header", footer: footer) {
#if os(macOS)
PlatformMenuPicker(
String(localized: "settings.playback.macOS.playerMode"),
selection: $settings.macPlayerMode
) {
ForEach(MacPlayerMode.allCases, id: \.self) { mode in
Text(mode.displayName).tag(mode)
}
}
Toggle(
String(localized: "settings.playback.macOS.separateWindow"),
isOn: $settings.macPlayerSeparateWindow
)
Toggle(
String(localized: "settings.playback.macOS.autoResizePlayer"),