feat: add local-first private AI digest workflow
Migrate app code into canonical feature slices, add phone-only AI digest scheduling and review, wire local notification/background task support, and cover the flow with tests.
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:relationship_saver/features/ai_digest/domain/ai_digest_models.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
const String _enabledKey = 'llm_digest_enabled';
|
||||
const String _preferredWeekdayKey = 'llm_digest_preferred_weekday';
|
||||
const String _preferredHourKey = 'llm_digest_preferred_hour';
|
||||
const String _requireWifiKey = 'llm_digest_require_wifi';
|
||||
const String _requireChargingKey = 'llm_digest_require_charging';
|
||||
|
||||
class LlmDigestConfigNotifier extends Notifier<LlmDigestConfigState> {
|
||||
Future<void>? _initializeFuture;
|
||||
|
||||
@override
|
||||
LlmDigestConfigState build() {
|
||||
return const LlmDigestConfigState();
|
||||
}
|
||||
|
||||
Future<void> initialize() {
|
||||
_initializeFuture ??= _initializeFromStorage();
|
||||
return _initializeFuture!;
|
||||
}
|
||||
|
||||
Future<void> _initializeFromStorage() async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
state = LlmDigestConfigState(
|
||||
enabled: prefs.getBool(_enabledKey) ?? false,
|
||||
preferredWeekday: prefs.getInt(_preferredWeekdayKey) ?? DateTime.sunday,
|
||||
preferredHour: prefs.getInt(_preferredHourKey) ?? 21,
|
||||
requireWifi: prefs.getBool(_requireWifiKey) ?? true,
|
||||
requireCharging: prefs.getBool(_requireChargingKey) ?? true,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> setEnabled(bool enabled) async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_enabledKey, enabled);
|
||||
state = state.copyWith(enabled: enabled);
|
||||
}
|
||||
|
||||
Future<void> setPreferredRunWindow({
|
||||
required int weekday,
|
||||
required int hour,
|
||||
}) async {
|
||||
final int normalizedWeekday = weekday.clamp(
|
||||
DateTime.monday,
|
||||
DateTime.sunday,
|
||||
);
|
||||
final int normalizedHour = hour.clamp(0, 23);
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setInt(_preferredWeekdayKey, normalizedWeekday);
|
||||
await prefs.setInt(_preferredHourKey, normalizedHour);
|
||||
state = state.copyWith(
|
||||
preferredWeekday: normalizedWeekday,
|
||||
preferredHour: normalizedHour,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> setNetworkPolicy({
|
||||
required bool requireWifi,
|
||||
required bool requireCharging,
|
||||
}) async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_requireWifiKey, requireWifi);
|
||||
await prefs.setBool(_requireChargingKey, requireCharging);
|
||||
state = state.copyWith(
|
||||
requireWifi: requireWifi,
|
||||
requireCharging: requireCharging,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final NotifierProvider<LlmDigestConfigNotifier, LlmDigestConfigState>
|
||||
llmDigestConfigProvider =
|
||||
NotifierProvider<LlmDigestConfigNotifier, LlmDigestConfigState>(
|
||||
LlmDigestConfigNotifier.new,
|
||||
);
|
||||
Reference in New Issue
Block a user