Skip to content

Revamp now playing on Android and desktop - #63

Merged
ingoau merged 74 commits into
mainfrom
claude/funny-brahmagupta-9ggj7k
Oct 12, 2026
Merged

ingoau merged 74 commits into
mainfrom
claude/funny-brahmagupta-9ggj7k

Conversation

@ingoau

@ingoau ingoau commented Oct 12, 2026

Copy link
Copy Markdown
Owner

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)

  • Full player layout:
    • Title block: an artist-only subtitle (the track's artist tag, e.g. "A feat. B"), and an add-to-playlist button centred on the title and artist.
    • Seek bar: a wavy seek bar with remaining time. "Playing on X" shows only when another device is playing.
    • Transport: an M3 Expressive button group.
    • Bottom row: a split button for the queue (queue icon and name open the queue; the chevron opens the queue selector), a device button (the playing device's icon, accented when remote), a lyrics toggle, and More (the song menu).
    • Spacing: equal gaps around the seek bar. On taller screens the controls are packed at the bottom and the extra height goes to the artwork or the lyrics/queue area.
  • Taps and sheets:
    • Tapping the title opens an info sheet, which replaces the old About mode.
    • Tapping the artist opens an "Artists and album" sheet listing every artist on the song, then the album.
  • Ratings:
    • The stars accept a swipe to rate, and only show in artwork mode.
    • The new display.playerRating setting (Appearance, synced) hides them.
  • Lyrics and queue modes:
    • Both sit directly on the blurred backdrop, with soft edge fades.
    • The thumbnail is 48 dp, with the title and artist centred on it.
    • Shuffle/repeat/autoplay sit at the bottom of the queue, with the list fading out behind them.
    • Lyrics timing has moved to More while lyrics are open.
  • Swiping between songs: a carousel with the previous and next covers peeking, in the full player and the mini player. Each page renders in its own style (immersive or card) during the swipe, and the colours follow the finger. The controls never move between immersive and card covers.
  • Immersive artwork:
    • Dismiss drag: the cover and its continuation move as one unit, sliding at full size before shrinking, with rounded sheet corners.
    • Top strip: a generated strip above the art keeps the status bar off the cover: a crisp extension for flat tops, a soft blur otherwise. The status bar icons follow its colour.
  • Removed: the "[device] was playing… Resume here" notice.

Desktop (#47)

  • Player bar:
    • Left: art, title, artist (opens an artists-and-album menu), rating, add to playlist and More.
    • Centre: the transport and the seek bar.
    • Right: volume, side panel, lyrics, queue, Connect, mini player and fullscreen.
    • Connect pill: shows the device name only when another device is playing.
    • Lyrics options open by right-clicking a lyrics toggle (or the context-menu key / Shift+F10).
  • Side panel:
    • Overview: one scrollable column with the art, title row, and Lyrics / Up next / About cards, each opening a full view.
    • Queue view: a queue selector dropdown that replaces the Recent tab, plus Autoplay.
    • Immersive covers: the art runs edge to edge.
      • Extend covers fill the whole panel with their colour.
      • Mirror covers fade, behind the first card, into a colour taken from the cover.
      • Cards pick one light or dark style.
    • The scrollbar is hidden.
  • Fullscreen:
    • Layouts: the prototype layout for card covers. Wide immersive covers are centred with generated sides on both edges, falling back to left-anchored when only the right edge qualifies, and use a glass controls card. Tall windows get a stacked layout.
    • Views: opening a view slides the art aside, and the generated part dissolves into the blur. Lyrics, queue and about are one width (clamp(400px, 36vw, 640px)) in every layout.
    • Idle: in art-only playback, the controls fade when the mouse is idle. A setting turns this off.
    • Mode memory: opens on the queue the first time, then the last used view.
    • "Playing from" and the resume notice are removed.

Core

  • display.playerRating: a synced bool, default true.
  • ArtworkLayout: gains left and top edge decisions, both backward compatible through serde(default).
  • artists: Track and TrackSummary gain artists, taken from OpenSubsonic artists with a fallback to artistId + artist. artist stays the tag string.
  • Migration 0005: adds an artists column, and forces a full resync so existing libraries pick it up.

Testing

  • Rust: cargo fmt --check, cargo clippy --workspace --all-features -D warnings, cargo test --workspace --all-features.
  • Desktop: typecheck, lint (no new warnings), unit tests, build, and the full Playwright e2e suite under xvfb.
    • New e2e coverage: side panel views, the queue selector, the Connect pill, the rating setting, fullscreen mode memory, idle hide, centred and fallback immersive layouts, fade smoothness (sampled numerically), equal view widths, the artist menu, and right-click lyrics options.
  • Android: testDebugUnitTest assembleDebug :app:lintDebug, with no new lint issues.
    • New Robolectric tests: layout and gaps, the controls not moving across modes and cover styles, the carousel, the dismiss geometry, the title marquee, both sheets, the star drag, and the status bar strip.
  • Screenshots were reviewed against the prototypes throughout. Not yet verified on a physical device: haptics, spring feel and swipe smoothness.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UxvtESw1sWcYhBn6EUH2hz


Generated by Claude Code

claude added 30 commits October 10, 2026 07:40
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
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
claude added 26 commits October 12, 2026 02:32
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
…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
…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
@ingoau
ingoau merged commit 7f47573 into main Oct 12, 2026
4 checks passed
@ingoau
ingoau deleted the claude/funny-brahmagupta-9ggj7k branch October 12, 2026 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants