Commit Graph
490 Commits
Author SHA1 Message Date
austinried d8ac7fefc7 db: keep playlist owner and sharing in filtered lists
The hand-written playlist projection used by the Downloaded filter and
offline mode did not select the new owner and shared columns, so the
playlist Info dialog lost them there while unfiltered lists had them.
Select both columns and pin the filtered path in LibraryDaoTest.

Also share the artist-name extraction between the subtitle and the
plural label so duplicate or blank refs cannot make them disagree,
accept the XML boolean form "1" for the public flag, and strengthen the
date-adjacency and pluralisation tests.
2026-10-21 14:04:46 +00:00
austinried f46f43b6cd ui: finish the library info dialogs and add playlist info
Sort names and titles are only shown when they differ from the regular
name, so artists without a distinct sort name no longer repeat the name.

Track info uses plural labels for both the artists and their sort name
when the track has more than one artist, and singular labels otherwise.
Added and last played sit together in album info.

Playlists gain an Info dialog with owner, sharing, song count, length,
creation and update dates. Owner and the public flag are synced from
getPlaylists, so a schema migration adds both columns.
2026-10-21 13:54:37 +00:00
austinried 3ffe38d988 ui: float the offline indicator opposite the library FAB
Drop the strip above the tab bar, which kept the bottom of the library
busy, and go back to a floating tonal cloud-off button at the bottom
start, level with the FAB on the other side. Tapping it still leaves
offline mode, and the tab bar goes back to just tabs and the gear.
2026-10-21 10:14:10 +00:00
austinried b76328fc26 ui: hold the offline strip to the 48dp touch target
Keep the strip's own tint and the clickable row, but give it the
standard minimum interactive height now that the Surface is no longer
padding it invisibly.
2026-10-21 10:14:10 +00:00
austinried 9feaf54cd2 ui: stop the offline strip reserving a 48dp touch target
The clickable Surface enforced Material's minimum interactive size, so
trimming its row only moved the text inside a band that stayed 48dp
tall and kept the gap to the tabs. Make the strip itself clickable
instead, so it sizes from its padding, and pin it at 36dp.
2026-10-21 10:14:10 +00:00
austinried be08e50314 ui: keep a gap before the first library tab
Put an 8dp spacer at the start of the scrollable content and let the
reveal leave that gap when scrolling back towards the first tab, so the
selected pill no longer sits flush against the screen edge. The spacer
scrolls away, so a tab that is half off is still cut at the edge.
2026-10-21 10:14:10 +00:00
austinried 47787182d0 ui: scroll the library tab strip and explain offline mode
The tab bar measured the selected tab's full label before the trailing
controls, so a long translation or a large font scale squeezed the
settings gear and eventually removed it, and an indicator in the bar
made that happen sooner. Put the tabs in a weighted, horizontally
scrollable strip and keep the gear outside it, then scroll the selected
tab into view when the pager settles, in either layout direction.

Move the offline indicator out of the bar into a strip above the tabs
that names the mode and offers to go online. Offline mode limits every
list, and Home already swaps to downloaded content without saying why;
an icon in the bar could not explain that and competed for the same
width.
2026-10-21 10:14:10 +00:00
austinried 677596c21b library: rank artist cover fallback like the materialized list
Reuse the materialized ranking CTE chain for the per-artist fallback so
duplicate covers keep the same album, exercise the four-row cap, and
test every credit path plus source isolation. Resolve the art input as a
pure function and key the artist and covers off the same source.
2026-10-21 10:14:01 +00:00
austinried 1dbfb027fe library: resolve artist art from live credits
Artist detail only used the materialized artist cover list, so credited
track artists without an artists row, or with an empty or stale cover
list, always fell back to the letter placeholder even though their
appearances albums had art. Observe the credit-derived cover query and
use it for the detail art, preferring the cached downloaded covers when
offline. The query covers album, album_artists, song and song_artists
credits.
2026-10-21 10:14:01 +00:00
austinried 2da0d61d4c library: bound the detail scroll restore and cover grids
Gate the restore on the caller's content being ready instead of an item
count that can include only the header, clear it after clamping to the
available rows, and include offset-only positions. Apply the same saver
to the artist grid so a process-death restore does not open at the top.
2026-10-21 10:13:52 +00:00
austinried 61774a19ca library: restore detail scroll positions after the rows load
The lazy list restores its saved position before a paging-backed playlist
has replayed its cached pages, so a zero-item first frame clamped it back
to the top. Track the position separately and reapply it once the item
exists, which covers paged playlists as well as the album and artist
lists. The test disposes and restores the scaffold with an empty first
frame to keep this from regressing.
2026-10-21 10:13:52 +00:00
austinried 0602f835dc ui: list the default sort mode first 2026-10-21 06:42:12 +00:00
austinried 45fc169c42 ui: default to regular names when sorting 2026-10-21 06:36:53 +00:00
austinried e487d2e0b1 library: drop the download progress indicator 2026-10-21 06:04:23 +00:00
austinried 6f1e1612e1 ui: open the artist chooser immediately from the menu 2026-10-21 00:30:41 +00:00
austinried fbd4c0c4fe ui: separate info labels from their values 2026-10-20 14:58:52 +00:00
austinried c56a6d4f83 add library info dialogs and sort name preference
Album and artist context menus gain an Info dialog covering the plural
album artists, sort names and the play and download details the screens
do not show. Multiple artist links collapse into one ellipsised entry
that opens the artist chooser instead of listing each artist.

Sort lists can now prefer regular names over sort names, or only use
sort names for names without Latin letters. The new plain-name indexes
keep those orders out of a temp B-tree.

Also carry plural artists through the Media3 queue so Now Playing and
the mini player keep them, drop the album artist tap ripple, and show
the aggregate download progress in the tab bar where offline mode used
to sit.
2026-10-20 14:28:32 +00:00
austinried 77e3fa87f1 library: keep artist art maintenance self-healing and cheap
Move change detection into a desired CTE with UPDATE ... FROM so mass updates do not turn the trailing WHERE into a quadratic correlated scan, and so no-op passes write zero rows. Fold the trigger optimization into the 35->36 migration and re-check/rewrite it from onOpen, so a future migration cannot silently restore the full UPDATE triggers. Re-resolve artist detail art when the active source becomes ready, and cover artist search renames in a Room-level test.
2026-10-20 11:23:02 +00:00
austinried 0a5b3512da library: stop artist art updates from reindexing artist search
The materialized art update rewrote every artist row on every library-changing sync. That fired the FTS5 content-sync triggers for each artist, which was the real cost: the same SQL is ~10ms with the triggers removed and ~4.7s for 100 changed artists with them in place. Only update rows whose cover lists actually changed, and replace the generated artist search triggers with UPDATE OF name, sortName so art-only writes never touch the FTS index. Existing databases get this through migration 36->37; fresh databases get it from the onCreate callback.
2026-10-20 10:13:20 +00:00
austinried 783d7f2ebc library: address artist art review findings
Cap the resolver at four covers, re-rank after deduplication so duplicate covers do not consume the grid budget, carry a thumbnail per fallback step, and advance to the grid when both the full image and its thumbnail fail. Negative-cache failed provider-image fetches per artist URL, clear materialized downloaded covers when all downloads are removed, and drop redundant plumbing.
2026-10-20 09:11:20 +00:00
austinried 18118492c7 library: materialize artist art and provider images
Store the OpenSubsonic artistImageUrl and two materialized cover-id lists on each artist row, backfill them in the 35->36 migration, and refresh downloaded covers only for affected artists when downloads change. Icons and the artist hero now resolve provider art, server artist art, then the same materialized grid synchronously, with a definitive-failure fallback so a dead provider URL does not strand the letter placeholder.

Download artwork also caches the provider image for the track and album artists, falls back to the artist cover when that fetch fails, and keeps both keys across sweeps. Query timing for the materialization pass is down from roughly 3.4s to 1.9s on the 20k-song benchmark.
2026-10-20 08:53:23 +00:00
austinried 0d1118011f ui: use the album grid for artist icons too
Load up to four thumbnail covers per visible artist row on demand and render the same 1-4 layout inside the circular artist icon. Lists stay on the expensive per-row query for now.
2026-10-20 07:27:42 +00:00
austinried 6e60ff6183 test: render the three-cover artist hero grid 2026-10-20 02:50:19 +00:00
austinried d038a33b36 ui: close the list search on back 2026-10-19 14:30:38 +00:00
austinried fb1c2a02ff ui: show plural artists in song subtitles and info dialog 2026-10-19 14:16:31 +00:00
austinried d81efe168e playback: make Auto the default ReplayGain mode
Use Auto for the preference fallback, the settings initial state and the controller's pre-preference default. Existing stored modes are unchanged.
2026-10-19 14:13:22 +00:00
austinried 0bd8f1bda8 playback: call the context-aware ReplayGain mode Auto
Rename the ReplayGainMode value, string resource and user-facing label from Dynamic to Auto. No behaviour change.
2026-10-19 14:13:22 +00:00
austinried 14ed037996 test: cover more up-next drag states
Cover context drags within the runs on either side of the block while the anchor is the playing track, plus moving the playing up-next track.
2026-10-19 14:13:22 +00:00
austinried e32df2fb08 test: cover up-next queue drag permutations
Exercise context and block drags against the queue authority: all context positions across the up-next block, a far move that crosses the window, a context move while an up-next track plays, and moving the playing up-next track.
2026-10-19 14:13:22 +00:00
austinried 43f0721d26 playback: keep the queue and player in sync across up-next
A context drag that crosses the up-next block moves the block's anchor in the repository but the old player.move used the combined drop position, leaving the two in different orders. Rebuild the window for context moves that happen while a block exists, in both the in-window and window-offset paths.

Also drop the redundant rebuildWindow snapshot parameter, the unused media-item context read-back, and add coverage for shuffled album context, ranged album moves and ranged up-next moves.
2026-10-19 14:13:22 +00:00
austinried 3f1d9b0d8d playback: add dynamic ReplayGain mode
Use album gain for items whose queue entry references an album and track gain for playlists, singles and other mixed contexts, including shuffled album queues. Carry the resolved context on each media item so the audio thread does not need to inspect the queue.

Keep a track moved within an album as an album range so it stays in album context; moves out of playlists, artists, genres and other mixed contexts remain pinned song entries.
2026-10-19 14:13:22 +00:00
austinried 8348e048b5 ui: keep the artist gradient anchored to the hero image
Use symmetric page margins for the artist bio, let lines below the action buttons use the full width, and stop the expanding bio from shifting the hero gradient.
2026-10-19 14:01:30 +00:00
austinried 77190a2af1 ui: drop bio justification and normalize cached biographies
Read normalization heals biographies cached before line breaks were preserved, without waiting for a refresh.
2026-10-19 13:55:16 +00:00
austinried 028685d62b ui: show three lines of the collapsed artist bio 2026-10-19 13:47:43 +00:00
austinried cac1f6af24 ui: add a Less control and preserve bio paragraphs
Keep source line breaks, treat the triple-space paragraph separator some servers return as a blank line, justify wrapped bio lines, and append a bold Less control to the expanded bio.
2026-10-19 13:36:06 +00:00
austinried 98398ab2fe library: keep the cached bio on an empty refresh 2026-10-19 13:14:08 +00:00
austinried d4ba9c0faf fix: handle artist bio failure and refresh edge cases
Retry a failed download bio fetch instead of blacklisting the artist for
the rest of the process, and give a failed or offline refresh its own
message so it is not mistaken for a server with no biography.

Wait for the stored row before choosing the bio text, so a cached bio no
longer flashes the loading state on entry, and bound the page refresh so
a stalled response cannot leave the loading state up indefinitely.

Render an oversized first token instead of a blank collapsed line, and
check whether the whole remainder fits in one measurement.
2026-10-19 13:14:08 +00:00
austinried 889bdb452b ui: show and expand the artist biography
Load the biography when the artist page is entered. A stored biography is
rendered immediately while it refreshes in the background; otherwise the
page starts with the loading message and falls back to the empty state.

Collapse a biography to two lines and append a bold More only when the
text does not fit. Tapping that line expands the biography, after which
the first lines keep clear of the star and overflow buttons and the rest
use the full width.
2026-10-19 13:14:08 +00:00
austinried 194787dfcc library: cache on-demand artist biographies
Artist biographies come from getArtistInfo2, which the library sync does
not call. Store them in their own table so a page open can use the last
value immediately and downloads can keep it for offline use, without
pulling a large text column into every artist list query.

A missing row means the artist has never been fetched; a row with a null
biography means the server had none. That lets the page show the loading
state only until the first fetch completes.
2026-10-19 13:14:08 +00:00
austinried 2e54d09acb ui: restore search focus when returning
Keep the query populated and put the cursor back at the end of the search field when the screen is restored.
2026-10-19 13:06:27 +00:00
austinried 4b3a7d1dfa library: keep artist paging off song and album writes
The fallback art reads albums and credits, but a successful sync invalidates through the sources row, so observing those tables only adds refreshes for play, star, and sync writes that do not change artist art.
2026-10-19 12:39:01 +00:00
austinried bb71f4889d ui: finish search focus and artist art review follow-ups
Avoid re-requesting search focus when the screen is restored, keep the cheaper album-credit-first art lookup, and test restoration plus association-table invalidation.
2026-10-19 10:14:01 +00:00
austinried 915225f812 ui: address review feedback on search focus and artist art
Keep the search field from stealing focus again when a result is dismissed, observe album and credit tables in artist paging, and simplify the cover fallback to one ranked union. Cover the association-table and invalidation paths in tests.
2026-10-19 10:03:28 +00:00
austinried 88e83c2a86 ui: polish artist art, chooser navigation, and list search
Fall back to the first album credit cover (then the first track credit) for artist art, keep list searches when opening a result, resume search at the end of the query, and navigate immediately from the artist chooser.
2026-10-19 09:30:18 +00:00
austinried b8b5594d04 ui: move artist actions back onto the meta row
Keep the type and count on the same row as the star and more buttons, and move
that row down to where it sat before the split. Give the Albums and Appears on
headers the album and microphone icons alongside the disc-title styling.
2026-10-19 04:57:33 +00:00
austinried 4f6a292e74 ui: style artist section headers like album disc titles
Use the same uppercase label-large semibold text with letter spacing as the
disc headers on the album screen.
2026-10-19 04:49:33 +00:00
austinried 5dd6e8dab9 ui: lower the artist actions and drop section counts
Move the star and more buttons from the meta line onto the first section
header so they sit below the hanging shuffle button again, and remove the
per-section counts now that the meta line carries the total.
2026-10-19 04:44:26 +00:00
austinried 733a4d2941 ui: pin the downloaded artist album visibility rules
Distinguish the album-credit rule (any downloaded song on the album) from the
track-credit rule (the credited track itself must be downloaded) in the
repository test, so a swap of those clauses fails.
2026-10-19 03:18:16 +00:00
austinried 3198a94df3 ui: cover the artist section split in tests
Assert the combined meta line while loading, cover the downloaded partition
and the plural album/song credit branches, share the album-credit id query
with its plan test, and put the meta line through a translatable string.
2026-10-19 03:14:13 +00:00
austinried 8cdbe64942 ui: split artist album credits from track appearances
Put the artist type and total album count on the single meta row beside the
star and more buttons, then list albums where the artist is an album artist
separately from albums where they only have a track credit. The hero shuffle
button and page-level actions stay where they were.

The split comes from an albumCredit flag on the shared credit rows, so the
online and downloaded album lists are partitioned by the same rule and the
two sections still sum to the stored album count.
2026-10-19 02:57:56 +00:00