style: clear queue fade and stack row actions

This commit is contained in:
2026-10-18 21:18:22 +02:00
parent 0084609a00
commit c551203af2
3 changed files with 20 additions and 17 deletions
+2 -2
View File
@@ -65,7 +65,7 @@ Use the **Queue** icon immediately left of the compact-mode button in the playba
The fixed bottom row holds the queue label/count and **+** on the left, with previous/next controls on the right. Its text matches the rows' 13-point medium-weight filenames, and its icons match the rows' 12-point icons. The **+** is a 20-point rounded-square button with an accent-tinted background and an 8-point gap after the queue count; navigation buttons retain their 24-point hit areas. The fixed bottom row holds the queue label/count and **+** on the left, with previous/next controls on the right. Its text matches the rows' 13-point medium-weight filenames, and its icons match the rows' 12-point icons. The **+** is a 20-point rounded-square button with an accent-tinted background and an 8-point gap after the queue count; navigation buttons retain their 24-point hit areas.
Queue rows show a medium-weight, two-line filename without its extension, with a smaller format label beneath it. Rows have a 56-point minimum height, 8-point vertical and 4-point horizontal internal padding, and no horizontal outer insets; leading and remove icons are smaller and subdued. The current item has an accent play marker and a subtle rounded highlight. Full filenames and paths remain available in row tooltips. Queue rows show a medium-weight, two-line filename without its extension, with a smaller format label beneath it. Rows have a 56-point minimum height, 8-point vertical and 4-point horizontal internal padding, and no horizontal outer insets. The subdued remove button sits beneath the media icon in the left column, leaving the remaining width for the filename. The current item has an accent play marker and a subtle rounded highlight. Full filenames and paths remain available in row tooltips.
In a normal window, showing the queue expands the window outward while preserving the video's size; hiding it removes that extra width. The sidebar meets the video directly, without a separate divider gap. 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 sidebar meets the video directly, without a separate divider gap. The window shifts left when necessary near the screen's right edge. Fullscreen keeps its fixed bounds.
@@ -73,7 +73,7 @@ Resizing with the queue open preserves the video's aspect ratio while keeping th
While the sidebar is open, its persistent top-right overlay holds the pin, Cast and settings controls above the list without a surrounding glass container, with matching top and right button insets; these and the bottom queue controls do not fade with the video controls. The native layout check verifies that all three header glyphs actually render. Closing the sidebar returns the pin, Cast and settings controls to the auto-hiding video titlebar with its glass container. The queue toggle stays in the playback controls. Space and configured playback shortcuts continue working with queue-list focus; Tab navigation, deliberately focused buttons/sliders and text entry keep their native keyboard behavior. While the sidebar is open, its persistent top-right overlay holds the pin, Cast and settings controls above the list without a surrounding glass container, with matching top and right button insets; these and the bottom queue controls do not fade with the video controls. The native layout check verifies that all three header glyphs actually render. Closing the sidebar returns the pin, Cast and settings controls to the auto-hiding video titlebar with its glass container. The queue toggle stays in the playback controls. Space and configured playback shortcuts continue working with queue-list focus; Tab navigation, deliberately focused buttons/sliders and text entry keep their native keyboard behavior.
The sidebar, top controls and queue footer share an opaque playlist background. The top backing fades downward into the list over 20 points; the footer backing fades upward by the same amount, keeping scrolled filenames from interfering with the controls without hard edges. The sidebar, top controls and queue footer share an opaque playlist background. The top backing fades downward over 20 points; the list starts below the full 32-point control row and its fade so the first entry is unobscured. The footer backing fades upward into the list by the same amount, keeping scrolled filenames from interfering with the controls without hard edges.
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.
+17 -15
View File
@@ -2307,16 +2307,27 @@ private struct PlayerContent: View {
private var queueSidebar: some View { private var queueSidebar: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
Color.clear.frame(height: 32) Color.clear.frame(height: 52)
List { List {
ForEach(model.queue.items) { item in ForEach(model.queue.items) { item in
let isCurrent = item.id == model.queue.currentID let isCurrent = item.id == model.queue.currentID
HStack(spacing: 8) { HStack(spacing: 8) {
Image(systemName: isCurrent ? "play.fill" : "film") VStack(spacing: 4) {
.font(.system(size: 12)) Image(systemName: isCurrent ? "play.fill" : "film")
.foregroundStyle(isCurrent ? Color(SunsetPalette.accent) : Color(SunsetPalette.secondaryText).opacity(0.6)) .font(.system(size: 12))
.frame(width: 20, alignment: .center) .foregroundStyle(isCurrent ? Color(SunsetPalette.accent) : Color(SunsetPalette.secondaryText).opacity(0.6))
.accessibilityLabel(isCurrent ? "Current item" : "Queued item") .frame(width: 20, alignment: .center)
.accessibilityLabel(isCurrent ? "Current item" : "Queued item")
Button { model.removeQueueItem(item.id) } label: {
Image(systemName: "minus.circle")
.font(.system(size: 12))
.foregroundStyle(.secondary)
.frame(width: 20, height: 24)
}
.buttonStyle(.plain)
.help("Remove from Queue")
.accessibilityLabel("Remove \(item.url.lastPathComponent) from Queue")
}
VStack(alignment: .leading, spacing: 3) { VStack(alignment: .leading, spacing: 3) {
Text(item.url.deletingPathExtension().lastPathComponent) Text(item.url.deletingPathExtension().lastPathComponent)
.font(.system(size: 13, weight: .medium)) .font(.system(size: 13, weight: .medium))
@@ -2331,15 +2342,6 @@ private struct PlayerContent: View {
} }
} }
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
Button { model.removeQueueItem(item.id) } label: {
Image(systemName: "minus.circle")
.font(.system(size: 12))
.foregroundStyle(.secondary)
.frame(width: 20, height: 24)
}
.buttonStyle(.plain)
.help("Remove from Queue")
.accessibilityLabel("Remove \(item.url.lastPathComponent) from Queue")
} }
.padding(.vertical, 8) .padding(.vertical, 8)
.padding(.horizontal, 4) .padding(.horizontal, 4)
+1
View File
@@ -8,5 +8,6 @@
- installs to ~/Applications, migrates the old hidden app, registers with Launch Services and requests Spotlight indexing; actual install, CLI, code signature, registration and Spotlight query passed; Spotlight UI remains unverified - installs to ~/Applications, migrates the old hidden app, registers with Launch Services and requests Spotlight indexing; actual install, CLI, code signature, registration and Spotlight query passed; Spotlight UI remains unverified
- [x] takes an awfully long time seek in local videos which i find weird, since seeking in streamed youtube videos is pretty much instant - [x] takes an awfully long time seek in local videos which i find weird, since seeking in streamed youtube videos is pretty much instant
- local seek preroll skips disposable non-reference pictures without sacrificing exact target frames; measured 1080p/10-second-GOP paused seek improved from 541 ms to 400 ms and playing seek from 682 ms to 488 ms; timestamp/pixel checks passed across six decoder formats; long-GOP reference decoding remains necessary, and the originally affected files still need manual verification - local seek preroll skips disposable non-reference pictures without sacrificing exact target frames; measured 1080p/10-second-GOP paused seek improved from 541 ms to 400 ms and playing seek from 682 ms to 488 ms; timestamp/pixel checks passed across six decoder formats; long-GOP reference decoding remains necessary, and the originally affected files still need manual verification
- [ ] make the sidebar expand/collapse with a nice transition
- [ ] in the "choose what to play" screen, we should change the youtube button to general streaming - [ ] in the "choose what to play" screen, we should change the youtube button to general streaming
- we can figure out the stream and how to handle it from the url (i.e. if youtube url, handle as youtube stream; if miruro url, handle accordingly) - we can figure out the stream and how to handle it from the url (i.e. if youtube url, handle as youtube stream; if miruro url, handle accordingly)