Add a fourth Playlists chip/page to the Library filter pager, rendered
as an album-style grid of playlist cells (search filters by name, page
provider short-circuits since playlists come from libraryCollections).
Add a defaultLibraryView setting (last used / all / albums / singles /
playlists) in Library settings, applied on startup and whenever the
shell switches back to the Library tab.
Share one count header row: count text keeps its intrinsic width and the
Filters/Create playlist buttons scale down on narrow widths instead of
truncating the count to an ellipsis.
Crossfade+scale the artwork and fade+slide title/artist on track change.
Make the player page non-scrollable and route vertical gestures instead:
swipe up on the content or bottom tab strip opens the queue sheet, swipe
down still forwards to the route's drag-to-dismiss.
Use SliverFillRemaining(hasScrollBody: false) so the page scrolls as one
unit when the keyboard opens, pad for the nav bar so the form is centered
in the visible area, and set scrollPadding so focusing the URL field also
reveals the Add Repository button.
Scale vertical gaps and icon by viewport height so pages fit with little
or no scrolling, add ScrollEdgeFade as a scroll cue when they still
overflow, and use onSurfaceVariant for inactive page dots (the previous
surfaceContainerHighest was invisible on AMOLED black).
Add ScrollEdgeFade (bottom gradient while more content remains) plus an
always-visible scrollbar on the language list, and bias step centering
upward by the header height so content sits at the optical screen center.
The Go MusicBrainz genre and album-artist ISRC lookups only ran
automatically at download time. The tag editor's auto-fill section
gains a Fetch from MusicBrainz button that bridges both exports in one
channel call (sparing the 1 req/s budget) and fills the fields as
editable suggestions; nothing is written until Save.
The internal player handles setRepeatMode: repeat-one replays the
current track, repeat-all wraps the queue (and keeps a single-track
shuffle queue alive). The mode is broadcast in playback state,
persisted with the playback session, and toggleable from the Now
Playing transport row and the up-next sheet; a small shuffle toggle
joins the transport row for symmetry.
The connectivity listener now stays alive while network-failed items
remain and, on reconnect, shows a debounced snackbar counting them
with a Retry action wired to retryAllFailed scoped to network
failures. Also regenerates localizations for the recent feature
strings.
Every single-track enqueue now shows the shared added-to-queue
snackbar with a View action into Library (six call sites through one
helper). URL fetch failures in Home and via share intent gain a Retry
action; unrecognized-URL errors deliberately keep none since retrying
is deterministic.
The download-time ISRC index now also parses mp3, m4a, ogg, and opus
tags through the existing native readers instead of skipping everything
but .flac. Library settings gain a Review duplicates sheet that groups
history and local-library rows sharing an ISRC via SQL over the
attached databases (no filesystem walk, SAF-safe), shows quality
badges, and offers keep-best and per-copy delete with confirmation.
Track options gain an Open on... entry listing every streaming platform
song.link resolves for the track, served by a new generic
GetTrackPlatformLinks with its own memory cache beside the availability
cache (same request budget). The sheet is data-driven from the platform
map so the app core stays service-agnostic. Completes the bridge
wrappers already landed in 901fa34d; also carries the en strings for
the duplicate review sheet landing next.
Merge origin/l10n_main (PR #428) with a per-key three-way resolution:
Crowdin values win only where main did not change the key since the
last sync, so the unused-key removal, store->repo wording sweep, and
ICU plural fixes survive. Korean is restored at 98% completion and
mapped again in crowdin.yml and both language pickers; ar/hi/nl/zh-CN/
zh-TW stay dropped (37% and below).
Follow-up to the arb removal: unmap ar/hi/ko/nl/zh-CN/zh-TW in
crowdin.yml so crowdin pull does not recreate them, trim the dead
entries from both language pickers, and add the missing uk entry to
the setup-screen picker.
The playlist import picker now also accepts .m3u/.m3u8; EXTINF entries
feed the same Deezer enrichment pipeline as CSV. Collection screens
(wishlist, loved, playlists) gain an export action that resolves each
track to its local file, writes SAF entries relative to the download
tree root so external players and DAP copies resolve them, skips
tracks without a file, and shares the .m3u8 via the system sheet.
Queue, current index, position, and shuffle flag are snapshotted to a
new app_state playback_session table on pause, track change, and queue
mutation (never on position ticks). On launch the session is restored
paused into the mini player; the first play seeks to the saved
position. Plain file paths that no longer exist are dropped, an
explicit stop or mini-player dismiss clears the snapshot, and the
installation-restore guard wipes it alongside the download queue.
Queued rows get a skip-next button that reinserts the item ahead of all
other queued items, so the next free slot picks it up. During an active
native worker run the current batch keeps its order; the new order
applies from the next run.