When "Play in a separate window" is disabled, the expanded player was a
native sheet attached to the main window. AppKit refuses fullscreen with
an attached sheet, so pressing F swapped the sheet for an in-window
overlay before fullscreening — a visible two-step transition.
Present the inline player as the full-window overlay from the start, so
fullscreen is just the window's native toggle. This removes the whole
sheet-swap machinery (toggleSheetFullScreen with its detach timing,
SheetWindowResizer, sheet sizing helpers).
- beginInlineOverlay/endInlineOverlay hide/restore the main window
toolbar and mirror the window's fullscreen state into the renamed
isMacInlinePlayerFullScreen flag via NSWindow notifications, so exits
through Esc/green button/Mission Control stay in sync
- Collapsing exits fullscreen only if it was entered for the video
- Esc in the windowed overlay collapses to the mini bar via a new
onCollapse callback (replacing the sheet's default Esc-dismiss)
- ContentView registers its hosting window (MainContentWindowReader) so
the overlay targets the right window even when the setting is toggled
while the Settings window has focus
The controls overlay was gated on the player backend existing, but the
backend is created only after the video details fetch completes, so the
loading phase showed just the thumbnail and spinner with no controls.
Drop the backend gate (MPV is the only backend type) and resolve the
PiP backend dynamically in the toggle callback. Also make ended/failed
states hide controls directly in shouldShowControls instead of relying
on catching the state transition, and reset the manual visibility
override when a new load starts so controls reappear for the next video.
The fullscreen button did nothing in sheet mode: AppKit ignores
toggleFullScreen on a window attached as a sheet, and the old fallback
targeted the key window — the sheet itself. Two other strategies were
ruled out first: fullscreening the sheet's parent is silently refused
while any sheet is attached, and resizing the sheet's backing window to
screen size NaN-asserts inside AppKit's sheet positioning even without
animation.
Working approach: swap the sheet for a plain overlay in the main window
and native-fullscreen the now sheet-free main window.
- isMacPlayerFullScreenOverlay on NavigationCoordinator dismisses the
sheet (presentation binding excludes it; the setter ignores the
dismissal write-back) and mounts ExpandedPlayerSheet as a black-backed
overlay in ContentView
- ExpandedPlayerWindowManager fullscreens the parent after the sheet
detaches, verifies AppKit accepted it (rolls back if refused), hides
the window toolbar (NSWindow keeps it as a strip above the overlay
otherwise) and restores it on exit
- a didExitFullScreen observer restores the sheet on any exit path
(button, Esc, green button, Window menu); closing the player while
fullscreen exits the main window's fullscreen too
- scheduleSharedViewAdoptionRetry on entry re-homes the shared render
view once the dismissing sheet's window loses visibility — its steal
is declined mid-dismissal and nothing else retried, leaving the
overlay black until the next video load
A pinned window carries .fullScreenAuxiliary, which AppKit refuses to
make a primary fullscreen window, so toggleFullScreen was a silent
no-op. Drop the floating config before entering fullscreen and restore
it in windowDidExitFullScreen, keeping the pin setting intact.
The mini player buttons set NavigationCoordinator flags, but only the
iOS tab views hosted the corresponding sheets. Host QueueManagementSheet
and PlaylistSelectorSheet on the macOS root view, bound directly to the
coordinator flags.
Also wire the add-to-playlist button in the full macOS player controls:
add the missing .addToPlaylist case to MacOSControlsSectionRenderer and
thread onShowPlaylistSelector from the expanded sheet layouts through
MacOSPlayerControlsView to the existing playlist sheet host.
Render the macOS control bar button row and top bar from the active
preset's sections via a new MacOSControlsSectionRenderer, replacing the
hardcoded QuickTime-style rows in MacOSControlBar. Add a keepOnTop
button type and macOS-specific button availability lists, and adapt the
player controls settings editors (preset editor, section editor, button
configuration) for macOS.
Also apply the preset font style to the control bar time labels, and
update the built-in macOS Default preset order (queue before transport,
fullscreen at the end), bumping builtInPresetsVersion to 7.
Show a top row in the macOS player controls (like tvOS) with the channel
avatar, video title, author name, and a close button whenever controls are
visible.
- Offset the top row below the traffic lights in the floating window by
measuring the window buttons against the top bar (no effect in fullscreen,
the inline sheet, or the side panel where there is no overlap).
- Tapping the avatar/title/author toggles the floating details panel, mirroring
the iOS title/author control.
- Hide the controls immediately when the details panel opens instead of waiting
for the auto-hide timer.
Add Queue (list.bullet), More (VideoContextMenuView ellipsis), and Play
Previous buttons to the macOS control bar. Play Previous is shown always and
disabled when the queue has no previous item. Remove the skip-back/forward 10s
buttons and the fullscreen button from the bar (arrow-key seek and F-key
fullscreen shortcuts are retained).
Queue reuses the existing cross-platform queue sheet; More reuses the shared
VideoContextMenuView (already !os(tvOS)), styled borderless to match the flat
bar buttons.
Reset isCommentsExpanded and commentsFrame on the NavigationCoordinator
directly when the portrait panel is dismissed, since PortraitDetailsPanel
owns its own @State that doesn't sync back through .onChange during dismiss.
Also track comments overlay frame via GeometryReader so the dismiss gesture
can allow swipes outside the comments area instead of blanket-blocking.