Repository navigation
Revamp now playing on Android and desktop - #63
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The prototypes from #40 and #47 with the shapes, sizes and spacing read off them, so the build keeps their proportions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
A synced switch under Appearance on both platforms: off, the player leaves the rating to the song menu and the song's details (#40). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
A spec that shoots the player bar, the side panel and the fullscreen player (card and immersive covers via HOCKET_FAKE_COVERS) into HOCKET_SCREENSHOT_DIR, for comparing the layout with the #47 prototypes. This first version captures the UI as it stands, before the revamp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The prototypes' structure in Material 3 Expressive components. The artwork sits right under a drag handle (Cast and collapse go: the handle collapses, as does dragging and back). Under it the title and artist · album open an info sheet (the old About mode), the stars drag along (shown per the display.playerRating setting) and add to playlist is a tonal round button. The seek bar shows elapsed and remaining time with "Playing on <device>" between them only while another device plays, or the current notice. The transport is a ButtonGroup: leaf-cornered skip buttons and a wide play/pause whose corners morph with state and press. The bottom row is the queue's name as a split button (name opens the queue, chevron the switcher), the device switcher (the playing device's icon, accent while another device plays), a lyrics toggle and the song menu (which keeps the sleep timer). Lyrics and the queue take the artwork's place on a tonal panel, so nothing below moves between modes; the queue's shuffle / repeat / autoplay pills sit at the bottom of the panel on a gradient the list fades out under. Swiping the artwork is now a carousel: the neighbours' covers (from the queue, preloaded, immersive ones with their own continuation) follow the finger, past half way or a fling it settles and skips, otherwise it springs back; the mini player does the same in miniature. Previous peeks at the current cover when it would restart it (the core's 3 s rule, now in the fake core too). Dragging an immersive player away keeps the artwork and its continuation one unit: the scene slides down at full size for the first 40% of the drag, the continuation fades out before the artwork shrinks (drawn with the artwork's transform), the seam keeps the landed fade until then, and the handle fades first. Tests follow the redesign and cover the title's info sheet, the star drag, the setting, Playing on and the accent device button, the queue name and chevron, the carousel and the dismiss geometry. The screenshot test hides the fake-core banner through a CompositionLocal and draws the sheets' windows, which Robolectric's capture leaves blank. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
On short screens and at large font sizes the artwork is narrower than the page allows, so a neighbour one slot plus a margin away showed at rest. Neighbours now sit at least far enough to wait off screen. The queue list ends clear of the faded strip under its toggles, the carousel reads its neighbours without touching StateFlow.value in composition, and the strings of the old header and About tab go. ImmersiveMotionScreenshotTest (opt-in, like ImmersiveScreenshotTest) renders real covers through the real classifier: artwork mode, the queue panel, a half swipe with the next scene peeking, and the dismiss drag held at 0.9, 0.7, 0.5 and 0.3. AppScreenshotTest adds a narrow, large-font pass, and steps its semantics clicks through the snapshot so a manual clock still sees them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Material Symbols Rounded for the now playing revamp (#47): a phone and a laptop for the Connect pill's device, view_sidebar for the side panel toggle, arrow_drop_down for the fullscreen Connect drop-down, and open_in_full / close_fullscreen for opening and collapsing the player. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The player bar takes the prototype's layout in the app's Material 3 Expressive language: artwork, title, artist, the rating (hidden with display.playerRating) and add to playlist / More on the left (love moves into More); shuffle, previous, a wide filled play/pause that morphs from a pill to a rounded square, next and repeat over the wavy seek bar in the centre; volume, then the side panel, lyrics and queue toggles, the Connect pill (the device's name on the accent only while another device plays), the mini player and the fullscreen player on the right. Toggles that are on fill tonally and square off. Autoplay moves to the queue view. The side panel replaces the queue/lyrics split with one scrolling pane: an overview (artwork crossfading on track change, the title with add and More, then Lyrics, Up next and About cards) whose links drill into the lyrics, the queue, About this song and Recent queues, with a back arrow and a shared-axis slide. The queue view's header is a queue selector (the saved queues that were the Recent tab, each with its own menu) and the Autoplay toggle. The bar's lyrics and queue buttons (and L / Q) open the panel on that view or close it; the panel button opens the overview. Open, view and width persist in hocket.panels; the divider and the display.queuePanelSplit mirror are gone. The fullscreen player only changes its import here; its revamp follows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…47) The player now has three layouts. Columns, for card covers: the rounded artwork with a glass controls card under it, centred; Lyrics, Queue or About move the column to the left (FLIP, a spring) and take the right. Immersive, for 3:2 or wider windows and a cover the classifier carries on: the artwork full height on the left, flush to the edges, with the card floating over its bottom like Cider's (as dark as the cover's brightest colour needs for 4.5:1, or light over a light continuation). With a view open the carried-on part shortens and dissolves into the moving blur (a registered-property mask, the scene crossfade untouched) and the view sits on that while the card stays put. Stacked, for narrow and tall windows: the phone's layout, with the tall immersive cover on top. Collapse and the window fullscreen toggle sit top right; a pill bottom right carries the Connect device (named only when another device plays, with a drop-down caret), the Lyrics / Queue / About toggles (the one that is on returns to the artwork alone), the sleep timer and volume (now a popover). Over the immersive artwork alone, during playback, the card, the pill and the header fade after three seconds without the mouse and come back on movement or a key; never while paused, while the keyboard is in them, or with a menu open. A device-local setting in Appearance turns it off. The player opens on the view it was left on, the queue the first time; Q, L and Escape work as before. About is the side panel's shared component; the old in-file About and Related are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
A new now-playing spec covers the side panel's overview and drill-ins (with the view remembered), the bar's lyrics/queue/panel buttons and L/Q, the queue selector restoring a saved queue (focus, Escape, a row's menu, All recent queues), the Connect pill naming the device only while another plays, display.playerRating hiding the bar's and the fullscreen player's stars but not About's, the fullscreen player opening on the queue and then on the last view, and the idle fade over immersive artwork (with generated plain covers and the borrowed classifier: fades while playing, returns on movement or a key, never while paused or with a view open, and the setting turns it off). The existing specs follow the redesign rather than the split panel: playFirstAlbum shows the queue view, lyrics tests open the lyrics view, the divider and Recent tab give way to the panel's width and the queue selector, the fullscreen player opens on the queue, volume lives in the pill's popover, the contrast check hides the header and pill too, and keyboard checks focus the content pane instead of clicking its centre (which now lands on the album's rating). exit-motion adds the selector's drop-down. The screenshot spec shoots the new layouts in both themes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…e title With a view open beside a light continuation, the view and the header now sit on the moving blur in white (the carried-on part dissolves sooner and a scrim comes in beside the artwork, so the text holds 4.5:1), while the controls card and the pill keep their light glass and dark controls, so nothing on them changes when the view does. The player bar's add and More sit right after the title, as in the prototype. The screenshot spec also shoots the narrow bar and drawer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
design.md's Desktop layout describes the revamped player bar, the side panel's overview and drill-ins, the queue view's selector, and the fullscreen player's columns, immersive (glass card, idle fade, views on the dissolving blur) and stacked layouts; the keyboard table gains L. The desktop README follows: the side panel replaces the queue/lyrics split, display.queuePanelSplit is unused, and the new specs are listed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
A flat extension has no seam: the artwork stays crisp and its colour carries on below. Dragging the player away faded that continuation out under an opaque artwork, leaving a hard line along the artwork's bottom. In flight the edge now fades as the continuation does, then squares off as the artwork shrinks, like the other styles. The immersive motion screenshots log what the classifier made of each cover, so the shots can be named for the style they show. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
About is a sheet from the title now, so the area never shows it; a state saved before the change restores to the artwork rather than an area nothing in the player can turn off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
- Queue: the list is gone from just above the shuffle / repeat / autoplay toggles to the panel's bottom (the panel's own fill backs them) and fades out over 36 dp above, so no row reads through or between them; the strip's gradient stays. - Lyrics: the lines fade in and out over 72 dp at the panel's top and above the offset controls, eased so a line at the edge dissolves instead of being sliced. Panel fades are eased the same way. - The sheet's top corners round to Material's extra-large 28 dp as soon as it leaves the open rest (within 5% of the travel) and morph to the mini card's on the way down; square only while resting fully open. - The immersive motion screenshots wait for the artwork's part of the frame to hold still before capturing: the light white cover's shot had caught the artwork before its image was drawn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
AMLL dims the lines around the current one with a word mask tuned for white text on a dark blur, so on the side panel's light surface every line read as faint grey and the current one barely stood out. In the panel the lines are now unmasked muted text (the muted token eased toward the surface, still 4.5:1) and the current line is the on-surface colour, whole; background and translation lines stay readable; the current line sits near the middle of the view. The fullscreen player keeps AMLL's own look and its word sweep over the blur. now-playing.spec checks, in both themes, that the current and other lines reach 4.5:1 on the pane, differ, are unmasked, and that the current line is in the middle of the view. The screenshot spec shoots the lyrics view on a sung line rather than in a gap between two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
With a view open, a mirror's carried-on part faded softly into the blur, but a crisp flat extension kept the artwork's hard edge and its colour then stopped short against the view. Beside a view the flat artwork's own last 30% now fades into the moving blur (a smoothstep, eased in as the view opens) and its carried-on colour is gone by that edge, so the soft edge is as wide as a mirror's. With the artwork alone the seam stays crisp, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
From the owner's review:
- Lyrics and the queue sit straight on the player's blurred backdrop in
the artwork's slot (its full width; nothing below moves on a mode
change), fading at the slot's edges. The queue's toggles keep their
place at the bottom on a band of the backdrop's colour that fades in
and out; the list is gone behind them and fades out above.
- The lyrics' tier, source and timing row leaves the player. While the
lyrics show, the song menu offers "Lyrics timing", a sheet with the
same row and offset buttons (the standalone lyrics page keeps its row).
- The "<device> was playing …" resume offer is no longer shown, in the
full player or the mini player; play resumes here as it always did.
Its strings go.
Syllable-synced lines now wrap between words only: at the new width the
renderer's per-syllable flow broke words in two ("sta- tic").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…offer From the owner's review of the screenshots: - Lyrics options (the sync type and source, the per-track offset with earlier / later / reset, the lyrics size) leave the row laid over the lyrics for a small popover behind a tune icon button: in the side panel's lyrics view header (dropping below) and in the fullscreen pill while the lyrics show (rising above, like volume). Focus moves in on open, Escape closes it and returns focus, and it animates out like the other popovers. LyricsView no longer draws tools of its own. - The fullscreen player drops its "Playing from" header in every layout; the queue's name is the queue view's selector. Collapse and the window fullscreen toggle stay top right. - The player bar no longer shows another device's dormant resume offer; the core still tracks it. Its strings and styles go. - The side panel's lyrics lines stay fully opaque (AMLL also fades lines by distance and once a song ends, which axe caught under the options). Specs follow: the lyrics options are opened to read the sync type and set the size; playback asserts the queue name via the selector and that there is no Playing from; now-playing covers the options popover (keys, offset, reset, size, fullscreen placement) and that the resume offer is not shown; a11y audits the popover in both places; the contrast check measures the queue view's text instead of the removed header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
In lyrics and queue modes the thumbnail beside the title now spans the text block as one unit: its top on the title's cap height (worked out from the system font, not the line box), its bottom on the star glyphs' bottom, or with the rating hidden on the artist line's baseline. Its side comes from the measured block (about 82 dp at the default font size), capped at 96 dp or 22% of the row on narrow screens at large font sizes (centred on the block then), with 16 dp corners. The slot it reports to HeroGeometry follows it, so the mode change lands on it. The screenshot test adds the queue with the rating hidden. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The muted lyric lines used color-mix(), whose color(srgb …) computed value axe misreads (it reported 1.37:1 for a colour that reaches 5:1), so the a11y audit failed once the lyrics options opened over them in the dark theme. The colour is now a theme token, --lyrics-muted, the same value written out, and contrast.test checks it reaches 4.5:1 on the pane while staying lighter than muted text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Writes only the shots whose names contain one of the given fragments, so a round of fixes re-shoots just the screens it touched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
… backdrop - The stars sit right under the artist line (its line box trimmed under the text): about 4.6 dp between the descender line and the star glyphs, in every mode. They keep their 48 dp touch row, top-aligned, which hangs 8 dp below the room it takes (never reaching the seek bar) and starts just under the title block, so taps on the artist still open the details. The thumbnail still spans title to star glyphs. - The band behind the shuffle / repeat / autoplay toggles is gone: they sit straight on the backdrop and the list fades out to nothing before them, eased like the lyrics' edges. - AppScreenshotTest takes HOCKET_SCREENSHOT_ONLY to write only some shots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The artist line tucks up under the title (about 2 dp between the title's descenders and the artist's ascenders) and the stars keep their distance below (about 8 dp from the artist's descenders), in every mode. The lines move by layout offsets rather than trimmed line boxes, which clipped the text at large font scales; the moved row is measured at its full height so a neighbour's lines (crossfading in on a swipe) are never squeezed. The stars' 48 dp touch row still starts below the title block and stops short of the seek bar, and the thumbnail still spans the block (its least size goes to 32 dp so it can, with the rating hidden). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The player's rating shows in artwork mode only. In lyrics and queue modes the title block is the thumbnail, the title and the artist: the thumbnail keeps 48 dp with the pair (the title's cap height to the artist's baseline) centred on it, or spans them where they need more. The stars fade and fold away with the artwork's flight to the thumbnail; the mode area takes the room they leave (HeroGeometry.titleFold), so the seek bar, transport and action row never move. The rating stays in the song's details and its menu, and display.playerRating still hides it over the artwork. The three-line span (to the star glyphs) goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…the bottom on tall screens The artist line sits at its natural place under the title again (no pull). Past the reference phone's height (411 x 891 dp) the controls keep the gaps they have there, anchored to the bottom; the rest goes to the mode area, the artwork centred in it (an immersive artwork stays at the top, its continuation filling the gap). Tests for both sizes; tall screenshots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Lyrics, queue and about now take clamp(400px, 36vw, 640px) beside the artwork whether the cover is a card (columns, now centred as a pair) or immersive (centred or left), so immersive views are wider than before and card views narrower. E2E measures the view in each layout at 1456x912 and 1280x800 and checks it clears the controls card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
They were scaffolding for the now playing revamp; the issues hold the prototypes and docs/design.md records what was built. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…that can lose the lease The next peek at the queue's end wraps only with Repeat All, to the context's first item (none with shuffle, whose first the queue view does not tell: the swipe rubber-bands and still skips), and nothing for Repeat One. Previous peeks at the same track again only when it restarts in the core: far enough into a track loaded here, or with nothing before it. The fake core now releases the lease on Stop, can start without it, takes it on Play, and goes back on Previous while another device plays, so tests can see those cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
track_from_summary dropped the artists list, so an autoplay pick cached before its album synced read back as one artist. Also note in migration 0005 that a full sync already under way finishes rather than restarting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The immersive layout tests size the window to 1456x912; xvfb-run's default 1280x1024 screen could clamp it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…renderer Resizing through app.evaluate occasionally failed with "Resulting promise was garbage collected" (Playwright loses the main-process result to a collection, whether or not the resize ran). resizeWindow() resizes through the window's handle, retries that error, and waits until the renderer sees the new size; every spec that resizes the window uses it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The status line's "Playing on" and the device button's accent (and its take over) showed whenever this device did not own the transport, so also on a cold start with a restored queue and after Stop, when nobody holds the lease. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The drag read the rating callback at its end, so a drag spanning a track change rated the new song; it now keeps the callback (and rating) from its start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…ontrols up Idle-hide ignored the player's popovers (portalled into the player, outside its chrome), so the controls faded under an open artist menu or lyrics options. Idle now waits while any of them (or volume) is open; the idle e2e test opens both and checks the controls stay, then fade once they close. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The player's queue list was drawn under the toggle strip and only masked away there, so rows hidden behind the toggles still took taps and accessibility focus. The list now ends where the mask began (a little above the toggles), fading out over its last stretch as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Only an immersive artwork's top strip set the status bar's icons, so on a light system theme the open player (dark behind card covers, lyrics and the queue) kept dark icons. They are now light over it, following an immersive strip's colour in artwork mode, and go back when the player closes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The colour scheme's animate flag read the carousel's busy state (its offset) in composition, recomposing the whole sheet each frame of a swipe; it is derived state now, changing twice a swipe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
A drag started while a skip settled stopped its animation, so the skip was never sent and the carousel stayed committing (the colours snapping from then on). Drags now wait for the settle, and the commit always ends (try/finally). The song is taken at release: if another took its place while the swipe settled (it ended, or another device skipped), no second skip is sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
The swipe has already shown the new song in its own style; the scene hold (for covers whose layout is not known yet) could put the previous cover back at the centre for up to 400 ms under the new title. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…s KDoc The README gains a Screenshots section (HOCKET_SCREENSHOT_DIR/ONLY and their -Dhocket.* properties, HOCKET_COVERS, HOCKET_HOST_LIB, HOCKET_SCREENSHOT_THEME; the desktop's HOCKET_FAKE_COVERS). QueueSwitcherSheet opens from the queue split button's chevron now, not "Playing from". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…nsport Between the two-row layout and about 1330 px (sooner with another device's name showing) the left column shrank to nothing and its art, title and buttons overlapped the transport. The song's block now keeps a 180 px minimum, the centre is a flexible track capped at 520 px, and container queries give way in order: the stars, then add/More (still in the context menu and side panel), then a shorter volume slider and device name. E2E checks the three blocks never overlap at 960 and 1100 px, local and remote; the screenshot spec shoots the bar at 960/1024/1100/1280. The resize helper waits for the size the window actually took (its minimum applies). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Dragging the panel's edge redrew the continuation (several large blurred working canvases and a readback) on every frame. It now draws at once the first time and then only after the width has held for 160 ms, the last drawing stretching to fit meanwhile; its bitmap is released on unmount. E2E checks a run of resize steps draws once, at the final width. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
A drag started while a skip settled was ignored (b50721b), so two quick swipes skipped one song. Now the settling skip is finished at once: its Next/Previous sent once (nothing if the song already changed), the strip snapped to its page, and the new drag carries on from there once that song is current. N swipes, N skips; committing always ends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…o battery saver The bar's wave ran its frame loop whenever the window was visible. It now moves only in the full performance mode with the battery saver off, and holds still otherwise (like with reduced motion); the fullscreen one is unchanged. The fake core sends a snapshot when the battery saver changes so the e2e test can toggle it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…nges SyncedPeek re-rendered every frame through usePosition, paused or behind the fullscreen player. usePositionValue() follows the shared ticker only while the song plays (and here, while the player is not covering it) and sets state only when the derived value, the current line, changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…, the split key) display.queuePanelSplit stays in the core's registry (and the fake core's copy of it) for older clients; nothing in the desktop reads it any more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
… claim on toggles Up next rows are buttons: Enter or Space plays the song (a double-click still does; a single click does nothing). The About card's link is named "More about this song" (not a second "More"). The lyrics toggles drop aria-haspopup (they are pressed toggles; the description gives the shortcut). The file path in About this song is labelled by visually hidden text instead of an aria-label on a span. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…mount The left continuation kept a full-window bitmap while a view had slid it off the edge; it now lets it go once the slide is over and draws again as the artwork comes back. Every continuation canvas releases its bitmap on unmount. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
…v vars design.md: the artwork layout has four edges (top added for the phone), and which reader uses which; recent queues live in the queue selector and the Recent queues drill-in, not a tab. README: HOCKET_SCREENSHOT_DIR, HOCKET_FAKE_COVERS and HOCKET_SCREENSHOT_ONLY. Tests: no contrast logging in CI runs; the playback comment says what np-thumb is in each layout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
This was referenced Oct 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Revamps the now playing experience on Android (#40) and desktop (#47). It follows the prototypes' structure, with Material 3 Expressive standards taking priority over the prototypes, and keeps the immersive artwork from #59 working on both platforms.
Closes #40
Closes #47
Closes #25
Closes #19
Closes #32
Also refs #34 (lyrics timing has moved out of the player into the song menu, but the standalone lyrics page still shows it), #17 (single-line scrolling titles), #38 and #49.
Android (#40)
artisttag, e.g. "A feat. B"), and an add-to-playlist button centred on the title and artist.display.playerRatingsetting (Appearance, synced) hides them.Desktop (#47)
clamp(400px, 36vw, 640px)) in every layout.Core
display.playerRating: a synced bool, default true.ArtworkLayout: gainsleftandtopedge decisions, both backward compatible throughserde(default).artists:TrackandTrackSummarygainartists, taken from OpenSubsonicartistswith a fallback toartistId+artist.artiststays the tag string.artistscolumn, and forces a full resync so existing libraries pick it up.Testing
cargo fmt --check,cargo clippy --workspace --all-features -D warnings,cargo test --workspace --all-features.testDebugUnitTest assembleDebug :app:lintDebug, with no new lint issues.🤖 Generated with Claude Code
https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz
Generated by Claude Code