feat(flutter/cache): migrate artistProvider to drift-first (#357 plan C)
artistProvider becomes a StreamProvider backed by drift's cached_artists watch(). Empty + online triggers REST fallback; populates drift; watch re-emits. Empty + offline yields a sentinel ArtistRef(id: '', name: ''); surfaces should already check state.value?.id.isNotEmpty. AsyncValue<ArtistRef> shape unchanged so .when callsites keep working. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,15 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:drift/drift.dart' as drift;
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import '../api/client.dart';
|
import '../api/client.dart';
|
||||||
import '../api/endpoints/library.dart';
|
import '../api/endpoints/library.dart';
|
||||||
import '../auth/auth_provider.dart';
|
import '../auth/auth_provider.dart';
|
||||||
|
import '../cache/adapters.dart';
|
||||||
|
import '../cache/audio_cache_manager.dart' show appDbProvider;
|
||||||
|
import '../cache/cache_first.dart';
|
||||||
|
import '../cache/connectivity_provider.dart';
|
||||||
|
import '../cache/db.dart';
|
||||||
import '../models/album.dart';
|
import '../models/album.dart';
|
||||||
import '../models/artist.dart';
|
import '../models/artist.dart';
|
||||||
import '../models/home_data.dart';
|
import '../models/home_data.dart';
|
||||||
@@ -37,9 +43,26 @@ final homeProvider = FutureProvider<HomeData>((ref) async {
|
|||||||
return (await ref.watch(libraryApiProvider.future)).getHome();
|
return (await ref.watch(libraryApiProvider.future)).getHome();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Drift-first per #357 plan C. Watches cached_artists for the row;
|
||||||
|
/// when empty + online, fetches via REST + populates drift, which
|
||||||
|
/// re-emits via watch().
|
||||||
final artistProvider =
|
final artistProvider =
|
||||||
FutureProvider.family<ArtistRef, String>((ref, id) async {
|
StreamProvider.family<ArtistRef, String>((ref, id) {
|
||||||
return (await ref.watch(libraryApiProvider.future)).getArtist(id);
|
final db = ref.watch(appDbProvider);
|
||||||
|
return cacheFirst<CachedArtist, ArtistRef>(
|
||||||
|
driftStream: (db.select(db.cachedArtists)..where((t) => t.id.equals(id)))
|
||||||
|
.watch(),
|
||||||
|
fetchAndPopulate: () async {
|
||||||
|
final api = await ref.read(libraryApiProvider.future);
|
||||||
|
final fresh = await api.getArtist(id);
|
||||||
|
await db.into(db.cachedArtists).insertOnConflictUpdate(fresh.toDrift());
|
||||||
|
},
|
||||||
|
toResult: (rows) => rows.isEmpty
|
||||||
|
? const ArtistRef(id: '', name: '')
|
||||||
|
: rows.first.toRef(),
|
||||||
|
isOnline: () async =>
|
||||||
|
(await ref.read(connectivityProvider.future)),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
final artistAlbumsProvider =
|
final artistAlbumsProvider =
|
||||||
|
|||||||
Reference in New Issue
Block a user