Goal is UI responsiveness: the History tab was fetch-on-visit and
showed a spinner on every open. Now it paints instantly from a cached
snapshot and refreshes underneath — the native mirror of Flutter's
cacheFirst _historyProvider (alwaysRefresh over the cached_history_
snapshot drift row).
Native implementation (idiomatic, not a drift transliteration):
* CachedHistorySnapshotEntity — single-row table (id=1) holding the
raw /api/me/history wire JSON + updatedAt. AppDatabase v5→6
(fallbackToDestructiveMigration rebuilds; cache refills from server).
* CachedHistorySnapshotDao.observe() Flow + upsert; DatabaseModule
@Provides bridge (the AudioCacheIndexDao lesson — every @Inject dep
needs a provider).
* HistoryRepository.observeHistory(): Flow<HistoryPage?> decodes the
blob; refresh() fetches + overwrites the snapshot. Whole page as one
JSON blob (read-only timestamp-keyed snapshot — no per-row bookkeeping
for no UX gain), matching Flutter's snapshot shape.
* HistoryTabViewModel: uiState = combine(observeHistory, refreshError)
— cache-first, SWR, and Error only when there's no cache to show.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>