Files
dailyou/lib/core/providers/insight_provider.dart
T
stefwill 59597c7a4f feat: wire up app shell, log mood screen, and fix Android build
- Bootstrap ProviderScope in main.dart and move App to app.dart with light/dark theming
- Add initial LogMoodScreen with mood entry flow and shared activity/mood widgets
- Add kIsWeb guard in app_database.dart for drift web support
- Enable Android core library desugaring required by flutter_local_notifications 21.x
- Guard all async notifier state assignments with ref.mounted checks to prevent
  use-after-dispose errors when providers are auto-disposed mid-operation
2026-04-26 12:00:14 +10:00

76 lines
2.4 KiB
Dart

import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:drift/drift.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../database/app_database.dart';
import 'database_provider.dart';
// ── Insight type enum ─────────────────────────────────────────────────────────
enum InsightType { weekly, monthly, query }
// ── Cached insight lookup ─────────────────────────────────────────────────────
final cachedInsightProvider =
FutureProvider.autoDispose.family<LlmInsight?, String>((ref, promptHash) {
return ref.watch(insightDaoProvider).getCached(promptHash);
});
// ── Insight notifier — triggers generation and caches results ─────────────────
class InsightNotifier extends Notifier<AsyncValue<String?>> {
@override
AsyncValue<String?> build() => const AsyncData(null);
String _hashPrompt(String prompt) =>
sha256.convert(utf8.encode(prompt)).toString();
Future<void> generateInsight({
required String prompt,
required InsightType type,
DateTime? rangeStart,
DateTime? rangeEnd,
}) async {
state = const AsyncLoading();
final hash = _hashPrompt(prompt);
final dao = ref.read(insightDaoProvider);
final cached = await dao.getCached(hash);
if (!ref.mounted) return;
if (cached != null) {
state = AsyncData(cached.responseText);
return;
}
// Generation happens in LlmNotifier (see llm_provider.dart)
state = const AsyncData(null);
}
Future<void> saveInsight({
required String promptHash,
required String responseText,
required InsightType type,
DateTime? rangeStart,
DateTime? rangeEnd,
}) async {
await ref.read(insightDaoProvider).upsertInsight(
LlmInsightsCompanion.insert(
type: type.name,
promptHash: promptHash,
responseText: responseText,
rangeStart: Value(rangeStart),
rangeEnd: Value(rangeEnd),
),
);
if (!ref.mounted) return;
state = AsyncData(responseText);
}
void clear() => state = const AsyncData(null);
}
final insightNotifierProvider =
NotifierProvider.autoDispose<InsightNotifier, AsyncValue<String?>>(
InsightNotifier.new);