Commit Graph
64 Commits
Author SHA1 Message Date
austinried 7a0dd9aa5b show download status on the library tabs and offer it in their menus
Album tiles, artist rows and playlist rows now carry the badge (lower right on
tiles, trailing end on rows) and their long-press menus take the same bulk
Download / Cancel / Delete entries the hero uses, driven by the shared actions
rule so a partly downloaded item offers both rows and an in-flight one offers
Cancel. The artist page's album cells get the badge and album menu too.

The three list callbacks the artist menu used (and its artist-specific
view-model calls) collapse into one bulkDownload action over a MenuTarget, since
the same menu code now serves album, playlist and artist.
2026-10-04 00:30:03 +00:00
austinried cf6ee00b6f move the artist header row down and the albums up
Drop the row's bottom padding and add to its top so the count and buttons sit closer to the album grid.
2026-10-04 00:30:03 +00:00
austinried 553752bf0a bump the artist album count text size
Use bodyLarge for the album count so it reads a little larger under the artist name.
2026-10-04 00:30:03 +00:00
austinried ea952e5a73 even out the artist album grid gutters
The columns were 16dp from the screen edges but 12dp apart, so the middle looked tighter than the sides. Use the same gap horizontally as vertically.
2026-10-04 00:30:03 +00:00
austinried 9f061e2a31 drop the artist biography placeholder and centre the header row
The 'Artist biography coming soon.' line is temporary and the bio work is shelved, so remove it. With only the album count left, centre it against the star and more buttons under the image (the buttons no longer need to sit below the hanging shuffle).
2026-10-04 00:30:03 +00:00
austinried 37ccfd0b17 confirm the artist delete too
Only a single song deletes without asking; the artist's delete now opens the same
dialog as the album and playlist, naming the artist and the space it frees. The
artist's download action stays in its more-menu rather than getting a visible
control, deliberately, so bulk downloading a whole artist is a considered
action.
2026-10-04 00:30:03 +00:00
austinried bf561075a2 address the bulk download review
- Cancelling a list while its download loop was still enqueueing missed every
  song queued after the cancel looked. The loop now holds the lock for the whole
  queue, so a cancel waits for it to finish and then removes all of it. That
  needed the enqueue helper split into a locked entry point and a body the loop
  can call while already holding the lock — calling the locked one from inside
  the lock deadlocked, which is what hung the tests.
- An empty resolved list now says so instead of doing nothing.
- One song failing to enqueue no longer aborts the rest of the batch.
- The artist actions resolve through the albums the artist page lists, matching
  what is on screen, rather than through songs.artistId, which for a guest on a
  compilation enqueued nothing.
- Bulk actions are one `applyAction` on the repository, so the three view models
  and both screens stop repeating the same dispatch.
- Tests: the playlist and artist resolve paths, a Running row counted as
  downloading, the action dispatch, and the action rule moved to a plain unit
  test.
2026-10-04 00:30:02 +00:00
austinried b2b92a388e download a whole album, playlist or artist at once
Third block of #65: bulk downloads and the list-level actions.

- The hero's download button on albums and playlists is real now. It starts the
  songs the list is missing, cancels what is in flight, or deletes what is
  already downloaded, chosen from the list's own status. The artist has no hero
  button, so its bulk actions live in the context menu, which now carries the
  same status.
- No new storage: a bulk job is the download rows for the list, and the status is
  counted from song_downloads joined to the list's songs, so cancel and delete
  stay well defined without anything to keep in sync.
- downloadAll fetches artwork for the whole list under one shared budget, once
  per unique cover, and skips songs that are already downloaded so re-tapping
  Download resumes rather than restarting.
2026-10-04 00:30:02 +00:00
austinried 8a279dcec2 put the artist star and more back at 14dp 2026-10-04 00:30:02 +00:00
austinried 57b15b1765 nudge the artist star and more further down 2026-10-04 00:30:02 +00:00
austinried f08d34e822 drop the artist star and more to the bio line 2026-10-04 00:30:02 +00:00
austinried 1fdbc8c28b centre the artist shuffle over the star and more buttons
Shift the pill 6dp left to align with the controls' centre and widen the
title's right reserve to keep the same gap.
2026-10-04 00:30:02 +00:00
austinried 284ccaa77b adjust artist details margins 2026-10-04 00:30:02 +00:00
austinried e0345302b6 drop the artist album controls below the shuffle
Move the bio up under the album count and drop the star and more buttons
20dp so they clear the floating shuffle with room to spare.
2026-10-04 00:30:02 +00:00
austinried f6f9648cce tuck the artist album row and its controls tight to the image
Keep the star and more pinned to the right of the row, top-align the row
so the album count sits close under the image, and let the centred
shuffle button's lower half pass just above the controls.
2026-10-04 00:30:02 +00:00
austinried 56379d4433 tighten the artist album row against the image
Bring the album count row up to a 16dp top margin and inset its controls
past the floating shuffle button's column so the two cannot overlap.
2026-10-04 00:30:02 +00:00
austinried 6f4a55b23c float the artist shuffle button on the image edge
Move the shuffle out of the title block so the wrapped name keeps an even
bottom margin, and anchor the button centred on the image's bottom edge.
The title's last line still reserves room on the right, and the album
count row starts below the button's hanging half.
2026-10-04 00:30:02 +00:00
austinried 5c3daed968 keep the artist title's top line clear of the shuffle button
Render the wrapped artist name as two rows: the first line spans the full
width on its own row above, and the last line shares a row with the
shuffle button, so the text can never run under it.
2026-10-04 00:30:02 +00:00
austinried af9b4e304c size up the artist shuffle and keep the title clear of it
- make the shuffle a filled pill matching the album/playlist controls
- wrap the artist name with a hanging indent: the first line may run the
  full width over the button, while the last line stops short of it
2026-10-04 00:30:02 +00:00
austinried 581c5e20a3 rework the artist detail header
- drop the passive star badge from the artists list
- add an album count, star, more and placeholder bio under the artist image
- move the more action down from the top bar into that row
- put a shuffle button beside the artist name, which can now wrap to two lines
- remove the now-unused StarredBadge component
2026-10-04 00:30:02 +00:00
austinried 060cbd2a91 rework song rows and now playing, add star to the notification
- star/unstar from the context menu fills the icon, then dismisses
- drop the star badge from album art and song rows
- song rows keep a track-number column (natural order fallback), shrink
  four-digit numbers, and gain right-hand download and duration columns
- the play indicator always sits in the left column, overlaid on cover art
  with an inset primary outline when art is shown
- now playing is left aligned with a star toggle
- the media notification gets a star button backed by a session command
2026-10-04 00:30:02 +00:00
austinried b55e5cc5e8 make the now playing art and artist names tap targets
Tapping the cover art on now playing opens its album and tapping the artist name opens
the artist, matching the context menu actions; the album detail subtitle does the same
for its artist. Both are inert when the queue item has no album/artist id.

Artist detail's album cells also stop drawing the letter placeholder underneath: with a
thumbnail underlay and the full image on top, the letter only showed because the default
`showPlaceholder = true` was left on, so a cold cell flashed a letter before the art.
They now match the hero's `showPlaceholder = art == null`.
2026-10-04 00:30:00 +00:00
austinried e23f78aa47 add play next / add to queue to the artist detail album menu 2026-10-04 00:30:00 +00:00
austinried 73db0681b5 give the starred badge a shadow when it sits over artwork
Over a cover the primary star was hard to read, so the album grid and artist album cells now
draw it with a small circular shadow.
2026-10-04 00:29:59 +00:00
austinried 7af87d63d9 extract the artist grid scroll estimate and test it
The index to pixel arithmetic was inline and fiddly (it was missing the row gap), so pull it
out as estimateScrollPx and pin the 2-column cases. ROW_GAP is shared with the grid spacing.
2026-10-04 00:29:59 +00:00
austinried 8d8c8be2a8 address review: share one scroll origin for the artist bar and gradient
heroBarColor was given the raw content scroll while HeroGradient used the image-bottom
anchor, so an opaque bar did not match the background it covered. Both now use
scrollPx - imageHeightPx. Also add the first row gap the scroll estimate was missing.
2026-10-04 00:29:59 +00:00
austinried 63279dec50 scroll the artist detail background and match its bar to the hero
The artist background used a static gradient and a scroll-0 bar colour. It now scrolls with
the grid (fading to a dark single colour) and the bar colour comes from heroBarColor at the
real scroll, like the album/playlist hero. The gradient's scroll origin is the hero image
bottom, since the image is full-width and covers the top.
2026-10-04 00:29:59 +00:00
austinried dcdcf553e2 show the starred indicator on artist album cells too 2026-10-04 00:29:59 +00:00
austinried ccdeca563f address review: cancellation-safe star, one star handler, focus logic tested
- setStar no longer treats cancellation as a rejection: rethrow CancellationException
  instead of toasting/rolling back, and roll back under NonCancellable on a real failure
- serialise setStar so overlapping toggles cannot clobber each other's rollback
- the menu star item reverts its label when the request fails (setStar now returns the
  result), so the open menu cannot drift from the row
- ContextMenuHost.dismiss clears the actions so a popped screen's ViewModel is released
- one shared setStar from the app shell instead of five per-ViewModel copies
- extract the nav-focus decision into focusPops and unit-test it
2026-10-04 00:29:59 +00:00
austinried 5aea1d6b4e address feedback: immediate navigation, now-playing fade, stack focus, sheet polish
- menu actions run before the sheet collapses, so tapping an album/artist navigates
  immediately instead of waiting for the dismiss; the sheet still animates closed
- host the sheet in the app shell so it survives the navigation it triggers
- now playing fades out (rather than sliding) when its menu navigates to an album/artist,
  and navigates first
- navigating to a detail screen already on top of the stack focuses it instead of pushing
  a duplicate
- drop the drag handle from both sheets, even the menu header's left/top margins, and add
  a bottom margin
2026-10-04 00:29:59 +00:00
austinried c28271590e address feedback: optimistic star and menu polish
- star/unstar updates the local row immediately and rolls back with a toast if the server
  rejects it, instead of waiting on the response
- the menu collapses with an animation on dismiss
- star/unstar keeps the menu open and toggles its item in place
- the album/artist rows show the target's name instead of "View album"/"View artist"
- the menu header shows the cover art thumbnail
2026-10-04 00:29:59 +00:00
austinried d9e9a6b865 add item menus to the detail screens and now playing
Album, artist and playlist detail screens get a more button plus long-press on their song
and album rows; now playing gets a more button for the current song. Song menus can reach
the album and artist and star; the now-playing song is read from Room so its star state is
current.
2026-10-04 00:29:59 +00:00
austinried da71bccb58 fix queue overlay, focus and artwork loading glitches
- scope QueueViewModel to the queue overlay so its rows are released on close
  and a reopened queue cannot show two overlapping lists; key open() on the
  overlay visibility so a fast reopen still rescans and refocuses
- reuse row ids by song identity when a window (re)loads so Compose does not
  cross-fade the old rows out while the new ones fade in
- fade the artist name scrim in and key its busy check on the thumbnail, the
  same ref the theme already uses, so a cached seed shows it immediately
- start detail gradients from the neutral base artwork until the seed resolves
  instead of inheriting the now playing theme and snapping to the artist colours
- fade the now playing and detail status bar scrims by putting the graphicsLayer
  before statusBarScrim(), which otherwise drew the background outside the layer
- decode full-size and hero covers with FilterQuality.High to stop the moire
  during overscroll stretch
2026-10-04 00:29:59 +00:00
austinried a356226e48 address the review: keep the stored seed on a failed decode, one cache, static bar colour
- resolve() no longer discards a stored seed when the bitmap cannot be decoded (it used to
  return null, dropping the theme for pre-v12 rows); it falls back to the stored pair
- fold the busy flag into the seed cache value so eviction is atomic (a busy entry could be
  evicted from the separate flag LRU while its seed stayed, silently disabling the scrim)
- the artist top bar samples heroBarColor at scroll 0 to match the static HeroGradient, and
  drops the wrong scroll estimate and per-pixel recomposition
- rememberOverlaidNameBusy keys its state so the cached flag is read on key change, not only
  the first composition; bottomBandBusy bails out on an empty bitmap
2026-10-04 00:29:58 +00:00
austinried f4ca0fd6d4 compute and persist the artist name busy flag with the artwork seed
- ArtworkSeedStore now carries the flag; artwork_seeds gains a nullable nameBusy column
  (DB v12, migration 11->12) so it survives cold starts with no decode
- resolve() computes the flag from the same bitmap it extracts the colour seed from, so
  there is no second decode, and persists it alongside the seed
- overlaidNameBusy reuses the seed job and reads the cached flag synchronously, so the
  scrim is known before the art shows; drop the fade
- bottomBandBusy now uses perceptual (gamma-space) luma, edge density and a bright
  fraction, which catches busy art on dark backgrounds (issue #40) that mean/variance missed
2026-10-04 00:29:58 +00:00
austinried 658b7f9452 fade the artist name scrim in instead of popping it in
The busy check can only resolve after the art's first decode, so the scrim appeared in a
single frame. Animate it over 180ms so it eases in behind the name.
2026-10-04 00:29:58 +00:00
austinried 2ba87114da align the artist top bar with the themed screens and scrim a busy name
- the artist top bar now uses the default app-bar title style and the art-derived
  heroBarColor instead of a hardcoded headline/black/white, so it follows the artist theme
- add a bottom scrim behind the overlaid artist name only when the art under it is bright
  or noisy, measured from the seed bitmap (so no extra decode)
2026-10-04 00:29:58 +00:00
austinried 1d97636ec1 match the now playing title, layer artist album art, dim the mini player 2026-10-04 00:29:54 +00:00
austinried d26936c251 theme the artist header from cover art and tune the mini player 2026-10-04 00:29:54 +00:00
austinried 39e2c5d09e polish the themed screens: comment line, brighter mini player, art preloading 2026-10-04 00:29:54 +00:00
austinried f70d1ba27e theme the artist, now playing and mini player from their art 2026-10-04 00:29:54 +00:00
austinried 4c8f3e1740 fade the hero back button and brighten secondary text 2026-10-04 00:29:53 +00:00
austinried 2808568a7a keep the hero back button visible and drop dead code 2026-10-04 00:29:53 +00:00
austinried d8d68d5d8d show the artist hero thumbnail under the full image too 2026-10-04 00:29:53 +00:00
austinried f8da91e0cc prefetch artwork seeds from the grid so an album opens with its theme 2026-10-04 00:29:53 +00:00
austinried f9bb38af74 drop the custom overscroll, keep lists a hair scrollable, restore colours 2026-10-04 00:29:53 +00:00
austinried 651d548c41 fix overscroll stretch, pad the album hero, push the gradient fade down 2026-10-04 00:29:52 +00:00
austinried 461eadb630 stretch overscroll everywhere, overlay the album bar, richer gradient 2026-10-04 00:29:52 +00:00
austinried 444705eabd keep the artist bar transparent when it does not scroll 2026-10-04 00:29:52 +00:00
austinried a78d093042 address artist detail review findings 2026-10-04 00:29:52 +00:00