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,4 @@
|
||||
# Legacy Sync Storage Exports
|
||||
|
||||
These files are compatibility exports. The canonical sync storage code now lives
|
||||
under `lib/features/sync/data/storage/`, so prefer editing that folder instead.
|
||||
@@ -1,18 +1,2 @@
|
||||
/// Raw persisted payload for sync queue state.
|
||||
class SyncStateRecord {
|
||||
const SyncStateRecord({required this.rawState});
|
||||
|
||||
final String rawState;
|
||||
}
|
||||
|
||||
/// Persistence boundary for sync queue metadata and pending changes.
|
||||
abstract interface class SyncStateStore {
|
||||
/// Reads stored sync state payload.
|
||||
Future<SyncStateRecord?> read();
|
||||
|
||||
/// Writes sync state payload.
|
||||
Future<void> write({required String rawState});
|
||||
|
||||
/// Clears stored sync state payload.
|
||||
Future<void> clear();
|
||||
}
|
||||
// Legacy compatibility export for the sync state store contract.
|
||||
export 'package:relationship_saver/features/sync/data/storage/sync_state_store.dart';
|
||||
|
||||
@@ -1,46 +1,2 @@
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:relationship_saver/features/sync/storage/sync_state_store.dart';
|
||||
|
||||
/// Hive-backed sync state store.
|
||||
class HiveSyncStateStore implements SyncStateStore {
|
||||
static const String _boxName = 'relationship_saver_sync';
|
||||
static const String _stateKey = 'sync_state_json';
|
||||
|
||||
static bool _initialized = false;
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
final Box<dynamic> box = await _openBox();
|
||||
await box.delete(_stateKey);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SyncStateRecord?> read() async {
|
||||
final Box<dynamic> box = await _openBox();
|
||||
final String? rawState = box.get(_stateKey) as String?;
|
||||
if (rawState == null || rawState.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return SyncStateRecord(rawState: rawState);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> write({required String rawState}) async {
|
||||
final Box<dynamic> box = await _openBox();
|
||||
await box.put(_stateKey, rawState);
|
||||
}
|
||||
|
||||
Future<Box<dynamic>> _openBox() async {
|
||||
if (!_initialized) {
|
||||
await Hive.initFlutter();
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
if (!Hive.isBoxOpen(_boxName)) {
|
||||
return Hive.openBox<dynamic>(_boxName);
|
||||
}
|
||||
|
||||
return Hive.box<dynamic>(_boxName);
|
||||
}
|
||||
}
|
||||
// Legacy compatibility export for the Hive sync state store.
|
||||
export 'package:relationship_saver/features/sync/data/storage/sync_state_store_hive.dart';
|
||||
|
||||
@@ -1,19 +1,2 @@
|
||||
import 'package:relationship_saver/features/sync/storage/sync_state_store.dart';
|
||||
|
||||
/// In-memory sync state store for tests.
|
||||
class InMemorySyncStateStore implements SyncStateStore {
|
||||
SyncStateRecord? _record;
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
_record = null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SyncStateRecord?> read() async => _record;
|
||||
|
||||
@override
|
||||
Future<void> write({required String rawState}) async {
|
||||
_record = SyncStateRecord(rawState: rawState);
|
||||
}
|
||||
}
|
||||
// Legacy compatibility export for the in-memory sync state store.
|
||||
export 'package:relationship_saver/features/sync/data/storage/sync_state_store_in_memory.dart';
|
||||
|
||||
@@ -1,14 +1,2 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:relationship_saver/core/config/app_config.dart';
|
||||
import 'package:relationship_saver/features/sync/storage/sync_state_store.dart';
|
||||
import 'package:relationship_saver/features/sync/storage/sync_state_store_hive.dart';
|
||||
import 'package:relationship_saver/features/sync/storage/sync_state_store_shared_prefs.dart';
|
||||
|
||||
/// Chooses sync queue persistence backend.
|
||||
final Provider<SyncStateStore> syncStateStoreProvider =
|
||||
Provider<SyncStateStore>((Ref ref) {
|
||||
if (AppConfig.useHiveLocalDb) {
|
||||
return HiveSyncStateStore();
|
||||
}
|
||||
return SharedPrefsSyncStateStore();
|
||||
});
|
||||
// Legacy compatibility export for the sync state store provider.
|
||||
export 'package:relationship_saver/features/sync/data/storage/sync_state_store_provider.dart';
|
||||
|
||||
@@ -1,32 +1,2 @@
|
||||
import 'package:relationship_saver/features/sync/storage/sync_state_store.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
/// shared_preferences-backed sync state store.
|
||||
class SharedPrefsSyncStateStore implements SyncStateStore {
|
||||
SharedPrefsSyncStateStore({this.stateKey = 'sync_queue_state_v1'});
|
||||
|
||||
final String stateKey;
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(stateKey);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SyncStateRecord?> read() async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
final String? rawState = prefs.getString(stateKey);
|
||||
if (rawState == null || rawState.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return SyncStateRecord(rawState: rawState);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> write({required String rawState}) async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(stateKey, rawState);
|
||||
}
|
||||
}
|
||||
// Legacy compatibility export for the shared preferences sync state store.
|
||||
export 'package:relationship_saver/features/sync/data/storage/sync_state_store_shared_prefs.dart';
|
||||
|
||||
Reference in New Issue
Block a user