import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-config/entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:shared_preferences/shared_preferences.dart'; abstract class KeyValueStorage { Future set(String key, String value); Future> get(String key); Future> getWithFormat( String key, T Function(String value) formatter, ); Future remove(String key); Future clear(); } class DartKeyValue implements KeyValueStorage { SharedPreferences? _sharedPreferences; SharedPreferences get sharedPreferences => _sharedPreferences!; @override Future> get(String key) async { await _initSharedPreferencesIfNeeded(); final value = sharedPreferences.getString(key); if (value != null) { return Right(value); } return Left(FlowyError()); } @override Future> getWithFormat( String key, T Function(String value) formatter, ) async { final value = await get(key); return value.fold( (l) => left(l), (r) => right(formatter(r)), ); } @override Future remove(String key) async { await _initSharedPreferencesIfNeeded(); await sharedPreferences.remove(key); } @override Future set(String key, String value) async { await _initSharedPreferencesIfNeeded(); await sharedPreferences.setString(key, value); } @override Future clear() async { await _initSharedPreferencesIfNeeded(); await sharedPreferences.clear(); } Future _initSharedPreferencesIfNeeded() async { _sharedPreferences ??= await SharedPreferences.getInstance(); } } /// Key-value store /// The data is stored in the local storage of the device. class RustKeyValue implements KeyValueStorage { @override Future set(String key, String value) async { await ConfigEventSetKeyValue( KeyValuePB.create() ..key = key ..value = value, ).send(); } @override Future> get(String key) async { final payload = KeyPB.create()..key = key; final response = await ConfigEventGetKeyValue(payload).send(); return response.swap().map((r) => r.value); } @override Future> getWithFormat( String key, T Function(String value) formatter, ) async { final value = await get(key); return value.fold( (l) => left(l), (r) => right(formatter(r)), ); } @override Future remove(String key) async { await ConfigEventRemoveKeyValue( KeyPB.create()..key = key, ).send(); } @override Future clear() async { // TODO(Lucas): implement clear } }