Files
minstrel/flutter_client/lib/cache/cache_settings_provider.dart
T
bvandeusen 2bcbb53c49 feat(flutter/cache): connectivityProvider + cacheSettingsProvider
connectivityProvider — StreamProvider<bool>; true when any connectivity
result is non-none. No Wi-Fi gate per operator decision.

cacheSettingsProvider — AsyncNotifier<CacheSettings> persisting
capBytes / prefetchWindow / cacheLikedTracks via flutter_secure_storage.
Defaults: 5 GB cap, 5-track prefetch, cache liked = on.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 23:15:17 -04:00

88 lines
2.8 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import '../auth/auth_provider.dart' show secureStorageProvider;
/// Operator-tunable cache settings (#357 plan B). Persisted via
/// flutter_secure_storage on the same device.
class CacheSettings {
const CacheSettings({
required this.capBytes,
required this.prefetchWindow,
required this.cacheLikedTracks,
});
/// 0 = unlimited.
final int capBytes;
/// 1..10. Number of next-tracks the prefetcher pre-downloads.
final int prefetchWindow;
/// When true, every like_track event triggers a pin with source autoLiked.
final bool cacheLikedTracks;
CacheSettings copyWith({
int? capBytes,
int? prefetchWindow,
bool? cacheLikedTracks,
}) =>
CacheSettings(
capBytes: capBytes ?? this.capBytes,
prefetchWindow: prefetchWindow ?? this.prefetchWindow,
cacheLikedTracks: cacheLikedTracks ?? this.cacheLikedTracks,
);
static const defaults = CacheSettings(
capBytes: 5 * 1024 * 1024 * 1024,
prefetchWindow: 5,
cacheLikedTracks: true,
);
}
class CacheSettingsController extends AsyncNotifier<CacheSettings> {
static const _kCap = 'cache_cap_bytes';
static const _kPrefetch = 'cache_prefetch_window';
static const _kCacheLiked = 'cache_liked_tracks';
late FlutterSecureStorage _storage;
@override
Future<CacheSettings> build() async {
_storage = ref.read(secureStorageProvider);
final cap = await _storage.read(key: _kCap);
final pre = await _storage.read(key: _kPrefetch);
final liked = await _storage.read(key: _kCacheLiked);
return CacheSettings(
capBytes: cap == null
? CacheSettings.defaults.capBytes
: int.tryParse(cap) ?? CacheSettings.defaults.capBytes,
prefetchWindow: pre == null
? CacheSettings.defaults.prefetchWindow
: (int.tryParse(pre) ?? 5).clamp(1, 10),
cacheLikedTracks: liked == null
? CacheSettings.defaults.cacheLikedTracks
: liked == 'true',
);
}
Future<void> setCapBytes(int bytes) async {
await _storage.write(key: _kCap, value: bytes.toString());
state = AsyncData(state.value!.copyWith(capBytes: bytes));
}
Future<void> setPrefetchWindow(int n) async {
final clamped = n.clamp(1, 10);
await _storage.write(key: _kPrefetch, value: clamped.toString());
state = AsyncData(state.value!.copyWith(prefetchWindow: clamped));
}
Future<void> setCacheLikedTracks(bool on) async {
await _storage.write(key: _kCacheLiked, value: on.toString());
state = AsyncData(state.value!.copyWith(cacheLikedTracks: on));
}
}
final cacheSettingsProvider =
AsyncNotifierProvider<CacheSettingsController, CacheSettings>(
CacheSettingsController.new);