Add local data store adapter layer and Hive scaffold
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
/// Raw local state payload and associated schema version.
|
||||
class LocalDataRecord {
|
||||
const LocalDataRecord({required this.rawState, required this.schemaVersion});
|
||||
|
||||
final String rawState;
|
||||
final int schemaVersion;
|
||||
}
|
||||
|
||||
/// Persistence boundary for local app state.
|
||||
abstract interface class LocalDataStore {
|
||||
/// Reads latest persisted state payload.
|
||||
Future<LocalDataRecord?> read();
|
||||
|
||||
/// Writes state payload and schema version.
|
||||
Future<void> write({required String rawState, required int schemaVersion});
|
||||
|
||||
/// Clears persisted state payload.
|
||||
Future<void> clear();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:relationship_saver/features/local/storage/local_data_store.dart';
|
||||
|
||||
/// Hive-backed local store for future DB migration path.
|
||||
class HiveLocalDataStore implements LocalDataStore {
|
||||
static const String _boxName = 'relationship_saver_local';
|
||||
static const String _stateKey = 'state_json';
|
||||
static const String _schemaVersionKey = 'schema_version';
|
||||
|
||||
static bool _initialized = false;
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
final Box<dynamic> box = await _openBox();
|
||||
await box.delete(_stateKey);
|
||||
await box.delete(_schemaVersionKey);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LocalDataRecord?> read() async {
|
||||
final Box<dynamic> box = await _openBox();
|
||||
final String? rawState = box.get(_stateKey) as String?;
|
||||
if (rawState == null || rawState.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int schemaVersion =
|
||||
(box.get(_schemaVersionKey) as num?)?.toInt() ?? 0;
|
||||
return LocalDataRecord(rawState: rawState, schemaVersion: schemaVersion);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> write({
|
||||
required String rawState,
|
||||
required int schemaVersion,
|
||||
}) async {
|
||||
final Box<dynamic> box = await _openBox();
|
||||
await box.put(_stateKey, rawState);
|
||||
await box.put(_schemaVersionKey, schemaVersion);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import 'package:relationship_saver/features/local/storage/local_data_store.dart';
|
||||
|
||||
/// In-memory local store for deterministic tests.
|
||||
class InMemoryLocalDataStore implements LocalDataStore {
|
||||
LocalDataRecord? _record;
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
_record = null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LocalDataRecord?> read() async => _record;
|
||||
|
||||
@override
|
||||
Future<void> write({
|
||||
required String rawState,
|
||||
required int schemaVersion,
|
||||
}) async {
|
||||
_record = LocalDataRecord(rawState: rawState, schemaVersion: schemaVersion);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:relationship_saver/core/config/app_config.dart';
|
||||
import 'package:relationship_saver/features/local/storage/local_data_store.dart';
|
||||
import 'package:relationship_saver/features/local/storage/local_data_store_hive.dart';
|
||||
import 'package:relationship_saver/features/local/storage/local_data_store_shared_prefs.dart';
|
||||
|
||||
/// Chooses local persistence backend for app state.
|
||||
final Provider<LocalDataStore> localDataStoreProvider =
|
||||
Provider<LocalDataStore>((Ref ref) {
|
||||
if (AppConfig.useHiveLocalDb) {
|
||||
return HiveLocalDataStore();
|
||||
}
|
||||
return SharedPrefsLocalDataStore();
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import 'package:relationship_saver/features/local/storage/local_data_store.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
/// shared_preferences-backed local store used as stable default.
|
||||
class SharedPrefsLocalDataStore implements LocalDataStore {
|
||||
SharedPrefsLocalDataStore({
|
||||
this.stateKey = 'local_data_state_v1',
|
||||
this.schemaVersionKey = 'local_data_schema_version',
|
||||
});
|
||||
|
||||
final String stateKey;
|
||||
final String schemaVersionKey;
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(stateKey);
|
||||
await prefs.remove(schemaVersionKey);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LocalDataRecord?> read() async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
final String? rawState = prefs.getString(stateKey);
|
||||
if (rawState == null || rawState.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return LocalDataRecord(
|
||||
rawState: rawState,
|
||||
schemaVersion: prefs.getInt(schemaVersionKey) ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> write({
|
||||
required String rawState,
|
||||
required int schemaVersion,
|
||||
}) async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(stateKey, rawState);
|
||||
await prefs.setInt(schemaVersionKey, schemaVersion);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user