Files
dailyou/lib/core/providers/insight_provider.dart
T

74 lines
2.4 KiB
Dart
Raw Normal View History

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 (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),
),
);
state = AsyncData(responseText);
}
void clear() => state = const AsyncData(null);
}
final insightNotifierProvider =
NotifierProvider.autoDispose<InsightNotifier, AsyncValue<String?>>(
InsightNotifier.new);