fix: keep sidebar header controls visible

This commit is contained in:
2026-10-18 01:27:19 +02:00
parent fc857870de
commit 2690a22d39
2 changed files with 20 additions and 18 deletions
+1 -1
View File
@@ -59,7 +59,7 @@ Use the titlebar's **Queue** icon or **View → Show Queue** to show the editabl
In a normal window, showing the queue expands the window outward while preserving the video's size; hiding it removes that extra width. The window shifts left when necessary near the screen's right edge. Fullscreen keeps its fixed bounds. In a normal window, showing the queue expands the window outward while preserving the video's size; hiding it removes that extra width. The window shifts left when necessary near the screen's right edge. Fullscreen keeps its fixed bounds.
The queue count and window controls share the top bar across the full expanded window; the sidebar starts with queue navigation and Add to Queue. While the sidebar is open, its persistent top header holds the queue count, queue toggle, pin, Cast and settings controls; these do not fade with the video controls. Closing the sidebar returns those controls to the auto-hiding video titlebar.
Playback advances automatically and stops at the end, without wrapping. **Previous Queue Item** and **Next Queue Item** are available in the sidebar and Playback menu and are disabled at their respective ends. Reordering or removing another item does not interrupt playback; removing the current item plays its next neighbor, or stops if there is none. A playback error stays on that item rather than skipping it. Playback advances automatically and stops at the end, without wrapping. **Previous Queue Item** and **Next Queue Item** are available in the sidebar and Playback menu and are disabled at their respective ends. Reordering or removing another item does not interrupt playback; removing the current item plays its next neighbor, or stops if there is none. A playback error stays on that item rather than skipping it.
+19 -17
View File
@@ -2043,17 +2043,10 @@ private struct PlayerContent: View {
.frame(height: 24) .frame(height: 24)
.background(PlayerGlass(cornerRadius: 8).clipShape(RoundedRectangle(cornerRadius: 8)).allowsHitTesting(false)) .background(PlayerGlass(cornerRadius: 8).clipShape(RoundedRectangle(cornerRadius: 8)).allowsHitTesting(false))
Spacer(minLength: 12) Spacer(minLength: 12)
if model.showsQueue { if !model.showsQueue {
HStack(spacing: 4) {
Text("Queue").fontWeight(.semibold)
Text("\(model.queue.items.count)").foregroundStyle(.secondary)
}
.font(.system(size: 13))
.padding(.trailing, 8)
.accessibilityElement(children: .combine)
}
titleControls titleControls
} }
}
.padding(.leading, model.isFullScreen ? 16 : 86) .padding(.leading, model.isFullScreen ? 16 : 86)
.padding(.trailing, 12) .padding(.trailing, 12)
.frame(height: 32) .frame(height: 32)
@@ -2249,6 +2242,18 @@ private struct PlayerContent: View {
private var queueSidebar: some View { private var queueSidebar: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
HStack(spacing: 4) {
HStack(spacing: 4) {
Text("Queue").fontWeight(.semibold)
Text("\(model.queue.items.count)").foregroundStyle(.secondary)
}
.font(.system(size: 13))
.accessibilityElement(children: .combine)
Spacer(minLength: 4)
titleControls
}
.padding(.horizontal, 12)
.frame(height: 32)
HStack { HStack {
iconButton("backward.end.fill", "Previous Queue Item") { model.advanceQueue(-1) } iconButton("backward.end.fill", "Previous Queue Item") { model.advanceQueue(-1) }
.disabled(!model.canPreviousQueueItem) .disabled(!model.canPreviousQueueItem)
@@ -2309,7 +2314,6 @@ private struct PlayerContent: View {
} }
} }
.frame(width: 260) .frame(width: 260)
.padding(.top, 32)
.background(PlayerGlass(cornerRadius: 0)) .background(PlayerGlass(cornerRadius: 0))
.dropDestination(for: URL.self) { urls, _ in .dropDestination(for: URL.self) { urls, _ in
guard model.canOpen, urls.contains(where: \.isFileURL) else { return false } guard model.canOpen, urls.contains(where: \.isFileURL) else { return false }
@@ -2327,12 +2331,6 @@ private struct PlayerContent: View {
queueSidebar queueSidebar
} }
} }
.overlay(alignment: .top) {
titlebar
.opacity(model.isCompact || model.compactWindow.isTransitioning ? 0 : 1)
.allowsHitTesting(!model.isCompact && !model.compactWindow.isTransitioning && model.controlsVisible)
.accessibilityHidden(model.isCompact || model.compactWindow.isTransitioning || !model.controlsVisible)
}
.frame(minWidth: model.isCompact || model.compactWindow.isTransitioning ? 160 : (model.showsQueue ? 660 : 400), .frame(minWidth: model.isCompact || model.compactWindow.isTransitioning ? 160 : (model.showsQueue ? 660 : 400),
minHeight: model.isCompact || model.compactWindow.isTransitioning ? model.compactContentMinimumHeight : 240) minHeight: model.isCompact || model.compactWindow.isTransitioning ? model.compactContentMinimumHeight : 240)
.ignoresSafeArea() .ignoresSafeArea()
@@ -2554,7 +2552,11 @@ private struct PlayerContent: View {
.allowsHitTesting(model.isCompact) .allowsHitTesting(model.isCompact)
.accessibilityHidden(!model.isCompact) .accessibilityHidden(!model.isCompact)
titlebar
.frame(width: geometry.size.width)
.opacity(model.isCompact || model.compactWindow.isTransitioning ? 0 : 1)
.allowsHitTesting(!model.isCompact && !model.compactWindow.isTransitioning && model.controlsVisible)
.accessibilityHidden(model.isCompact || model.compactWindow.isTransitioning || !model.controlsVisible)
if model.canTogglePlayback { if model.canTogglePlayback {
playbackControls playbackControls
.frame(width: 440, height: controlHeight) .frame(width: 440, height: controlHeight)