Three providers all become StreamProviders driven by drift watch():
- artistAlbumsProvider: cacheFirst over the join of cached_albums +
cached_artists for artist_name on each row.
- artistTracksProvider: cacheFirst over the join of cached_tracks +
cached_artists + cached_albums for snapshot fields.
- albumProvider: composite ({album, tracks}) shape, so uses async*
with two queries (album + tracks) for cleaner reactive behavior.
Cold-cache fallback inlined; populates both album and tracks tables
in one batch.
.future call site in artist_detail_screen.dart left as-is —
StreamProvider.future returns the next emission with the same
signature, so no consumer change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ApiClient.buildDio takes on401; the library's dioProvider wires it to
the auth controller's clearSession. The router redirect already handles
navigation away from authed screens once the session goes null.
HomeScreen surfaces the banner on connection_refused with Retry +
Change URL.
LibraryApi wraps GET /api/home, /api/artists/{id}(/tracks),
/api/albums/{id}. dioProvider builds an authenticated dio (token
resolver reads session_token from secure storage on every request).
homeProvider, artistProvider(id), albumProvider(id) sit on top.