1646b02ca2
The home screen renders solely from the per-item cached_home_index path (proven on devices for many releases); the legacy snapshot stack was dead weight. - library_providers: remove homeProvider + _encodeHomeData + _albumToJson/_artistToJson/_trackToJson; drop now-unused dart:convert and models/home_data.dart imports - metadata_prefetcher: re-point off homeIndexProvider/HomeIndex — pre-warm artistProvider from the rediscover/last-played artist sections (album/track tiles hydrate their own artist on render) - live_events_dispatcher: homeProvider -> homeIndexProvider so live events still refresh the home screen - db.dart: drop CachedHomeSnapshot (table class + @DriftDatabase entry); schemaVersion 10->11; from<3 createTable -> raw customStatement so the historical step compiles without the generated symbol; from<11 DROP TABLE cached_home_snapshot No test references the removed symbols. db.g.dart regenerated by CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
68 lines
2.4 KiB
Dart
68 lines
2.4 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../library/library_providers.dart';
|
|
import '../models/home_index.dart';
|
|
|
|
/// Pre-warms the drift cache for likely-tap targets. Conservative on
|
|
/// purpose: only warms artistProvider rows (single row, single round
|
|
/// trip per id) and only ever fires once per id per session. Album
|
|
/// detail is NOT prewarmed — the albumProvider auto-fetches its track
|
|
/// list when missing, and pre-warming N albums fans out N parallel
|
|
/// "fetch tracks" round trips that compete with the user's actual
|
|
/// playback request for bandwidth.
|
|
///
|
|
/// Driven off the per-item home path (homeIndexProvider). Only the
|
|
/// artist-typed sections (rediscover / last-played artists) carry
|
|
/// artist ids directly; album/track tiles hydrate their own artist on
|
|
/// render via the per-item path, so warming those here is unnecessary.
|
|
class MetadataPrefetcher {
|
|
MetadataPrefetcher(this._ref) {
|
|
_ref.listen<AsyncValue<HomeIndex>>(homeIndexProvider, (_, next) {
|
|
next.whenData(_warmIndex);
|
|
});
|
|
}
|
|
|
|
final Ref _ref;
|
|
|
|
/// Per-session dedupe so re-rendering a screen (every UI rebuild
|
|
/// fires the data: callback) doesn't trigger N more fetches for
|
|
/// ids we've already warmed.
|
|
final Set<String> _warmedArtists = {};
|
|
|
|
/// Cap warmed per emission. Covers what fits on screen without
|
|
/// scrolling.
|
|
static const _topN = 8;
|
|
|
|
/// Pre-warm artists. Albums are intentionally not pre-warmed —
|
|
/// see class comment.
|
|
void warmArtists(Iterable<String> ids) {
|
|
var n = 0;
|
|
for (final id in ids) {
|
|
if (id.isEmpty) continue;
|
|
if (!_warmedArtists.add(id)) continue; // already warmed
|
|
if (n++ >= _topN) break;
|
|
_swallow(_ref.read(artistProvider(id).future));
|
|
}
|
|
}
|
|
|
|
void _warmIndex(HomeIndex h) {
|
|
warmArtists(<String>{
|
|
...h.rediscoverArtists.take(_topN),
|
|
...h.lastPlayedArtists.take(_topN),
|
|
});
|
|
}
|
|
|
|
/// Discards the return value and any error from a fire-and-forget
|
|
/// provider read. We don't care about the value here — we only want
|
|
/// the side effect of writing drift.
|
|
void _swallow(Future<Object?> f) {
|
|
f.then<void>((_) {}).onError((_, __) {});
|
|
}
|
|
}
|
|
|
|
/// Read once at app start to activate the prefetcher (e.g. wire it
|
|
/// from a top-level Consumer or main.dart container override).
|
|
final metadataPrefetcherProvider = Provider<MetadataPrefetcher>((ref) {
|
|
return MetadataPrefetcher(ref);
|
|
});
|