CachedIndicator (lib/library/widgets/cached_indicator.dart) — small
download glyph rendered next to a track row when AudioCacheManager
reports the track as cached. FutureBuilder one-shot.
Wiring:
- track_row.dart: render CachedIndicator before the duration label
- playlist_detail: 'Download' OutlinedButton next to Play; pins all
playable tracks with source: autoPlaylist + SnackBar feedback
- album_detail: 'Download' IconButton in the header; same pin pattern
- app.dart: now ConsumerStatefulWidget — initState fires the initial
sync + activates the prefetcher provider
Together these complete the operator-facing surfaces of the offline
slice: visible cache state, explicit download trigger, automatic
sync + queue-ahead prefetch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds optional actions: bool = true param. When true (default), renders
the 3-dot menu trigger at the end of the row. Album detail / Search /
History / Liked tabs all consume TrackRow so they pick up the menu
transitively.
Pair with c8baaa5 which wired the button into the other 3 surfaces;
this commit completes the wire-up by including TrackRow itself (its
write was missed in the previous commit).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HorizontalScrollRow takes an optional shared ScrollController so
multi-row sections (Most played: 3 rows) couple their scroll like the
web HorizontalScrollRow.svelte. Cards fall back to the synced
album-fallback.svg when coverUrl is empty.