feat: add model download screen and gate app on model presence
Adds a one-time download flow for the on-device Gemma 2B model (~1.1 GB) with a progress bar, partial-download cleanup, and automatic navigation to the app shell once the file is verified. App.dart now gates on modelPresentProvider instead of onboarding state.
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../llm/model_download_service.dart';
|
||||
import 'settings_provider.dart';
|
||||
|
||||
// ── Is the model file present on disk? ───────────────────────────────────────
|
||||
|
||||
final modelPresentProvider = FutureProvider<bool>((ref) {
|
||||
return ModelDownloadService().isModelPresent();
|
||||
});
|
||||
|
||||
// ── Download notifier — streams progress and marks completion ─────────────────
|
||||
|
||||
class ModelDownloadNotifier extends Notifier<AsyncValue<double>> {
|
||||
@override
|
||||
AsyncValue<double> build() => const AsyncData(0.0);
|
||||
|
||||
Future<void> startDownload() async {
|
||||
state = const AsyncData(0.0);
|
||||
try {
|
||||
await for (final progress in ModelDownloadService().download()) {
|
||||
if (!ref.mounted) return;
|
||||
state = AsyncData(progress);
|
||||
}
|
||||
if (!ref.mounted) return;
|
||||
await ref.read(settingsNotifierProvider.notifier).markModelDownloaded();
|
||||
ref.invalidate(modelPresentProvider);
|
||||
} catch (e, st) {
|
||||
if (!ref.mounted) return;
|
||||
state = AsyncError(e, st);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() => state = const AsyncData(0.0);
|
||||
}
|
||||
|
||||
final modelDownloadNotifierProvider =
|
||||
NotifierProvider<ModelDownloadNotifier, AsyncValue<double>>(
|
||||
ModelDownloadNotifier.new);
|
||||
Reference in New Issue
Block a user