diff --git a/packages/neon/neon/lib/neon.dart b/packages/neon/neon/lib/neon.dart index d8f8001a..22d99305 100644 --- a/packages/neon/neon/lib/neon.dart +++ b/packages/neon/neon/lib/neon.dart @@ -10,6 +10,7 @@ import 'package:neon/src/blocs/push_notifications.dart'; import 'package:neon/src/models/account.dart'; import 'package:neon/src/models/app_implementation.dart'; import 'package:neon/src/platform/platform.dart'; +import 'package:neon/src/settings/models/storage.dart'; import 'package:neon/src/theme/neon.dart'; import 'package:neon/src/utils/global_options.dart'; import 'package:neon/src/utils/request_manager.dart'; @@ -33,6 +34,8 @@ Future runNeon({ await NeonPlatform.setup(); await RequestManager.instance.initCache(); + await AppStorage.init(); + final allAppImplementations = getAppImplementations(sharedPreferences); final packageInfo = await PackageInfo.fromPlatform(); diff --git a/packages/neon/neon/lib/src/blocs/accounts.dart b/packages/neon/neon/lib/src/blocs/accounts.dart index 8068d10a..e3f77c46 100644 --- a/packages/neon/neon/lib/src/blocs/accounts.dart +++ b/packages/neon/neon/lib/src/blocs/accounts.dart @@ -96,7 +96,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState } } - late final AppStorage _storage = AppStorage('accounts', _sharedPreferences); + late final AppStorage _storage = AppStorage('accounts'); final SharedPreferences _sharedPreferences; final GlobalOptions _globalOptions; final Iterable _allAppImplementations; @@ -213,7 +213,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState /// Use [activeOptions] to get them for the [activeAccount]. AccountSpecificOptions getOptionsFor(final Account account) => _accountsOptions[account.id] ??= AccountSpecificOptions( - AppStorage('accounts-${account.id}', _sharedPreferences), + AppStorage('accounts-${account.id}'), getAppsBlocFor(account), ); diff --git a/packages/neon/neon/lib/src/blocs/push_notifications.dart b/packages/neon/neon/lib/src/blocs/push_notifications.dart index d280b379..ae61b769 100644 --- a/packages/neon/neon/lib/src/blocs/push_notifications.dart +++ b/packages/neon/neon/lib/src/blocs/push_notifications.dart @@ -40,7 +40,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents, final AccountsBloc _accountsBloc; final SharedPreferences _sharedPreferences; - late final _storage = AppStorage(AppIDs.notifications, _sharedPreferences); + late final _storage = AppStorage(AppIDs.notifications); final GlobalOptions _globalOptions; final _notificationsController = StreamController(); diff --git a/packages/neon/neon/lib/src/models/app_implementation.dart b/packages/neon/neon/lib/src/models/app_implementation.dart index 83aa5c47..0e0ee87e 100644 --- a/packages/neon/neon/lib/src/models/app_implementation.dart +++ b/packages/neon/neon/lib/src/models/app_implementation.dart @@ -17,7 +17,7 @@ abstract class AppImplementation AppImplementation( final SharedPreferences sharedPreferences, ) { - final storage = AppStorage('app-$id', sharedPreferences); + final storage = AppStorage('app-$id'); options = buildOptions(storage); } diff --git a/packages/neon/neon/lib/src/settings/models/storage.dart b/packages/neon/neon/lib/src/settings/models/storage.dart index 7ae22cf2..d033964d 100644 --- a/packages/neon/neon/lib/src/settings/models/storage.dart +++ b/packages/neon/neon/lib/src/settings/models/storage.dart @@ -1,3 +1,4 @@ +import 'package:meta/meta.dart'; import 'package:shared_preferences/shared_preferences.dart'; abstract interface class SettingsStorage { @@ -14,35 +15,55 @@ abstract interface class SettingsStorage { } class AppStorage implements SettingsStorage { - AppStorage( - this._id, - this._sharedPreferences, - ); + AppStorage(this._id); final String _id; - final SharedPreferences _sharedPreferences; + + /// Shared preferences instance. + /// + /// Use [reqireDatabase] to access it. + /// Make sure it has been initialized wiht [init] before. + static SharedPreferences? _sharedPreferences; + + /// Sets up the [SharedPreferences] instance. + /// + /// Required to be called before accessing [reqireDatabase]. + static Future init() async { + _sharedPreferences = await SharedPreferences.getInstance(); + } + + @visibleForTesting + static SharedPreferences get reqireDatabase { + if (_sharedPreferences == null) { + throw StateError( + 'AppStorage has not been initialized yet. Please make sure AppStorage.init() has been called before and completed.', + ); + } + + return _sharedPreferences!; + } String _formatKey(final String key) => '$_id-$key'; - bool containsKey(final String key) => _sharedPreferences.containsKey(_formatKey(key)); + bool containsKey(final String key) => reqireDatabase.containsKey(_formatKey(key)); @override - Future remove(final String key) => _sharedPreferences.remove(_formatKey(key)); + Future remove(final String key) => reqireDatabase.remove(_formatKey(key)); @override - String? getString(final String key) => _sharedPreferences.getString(_formatKey(key)); + String? getString(final String key) => reqireDatabase.getString(_formatKey(key)); @override - Future setString(final String key, final String value) => _sharedPreferences.setString(_formatKey(key), value); + Future setString(final String key, final String value) => reqireDatabase.setString(_formatKey(key), value); @override - bool? getBool(final String key) => _sharedPreferences.getBool(_formatKey(key)); + bool? getBool(final String key) => reqireDatabase.getBool(_formatKey(key)); @override - Future setBool(final String key, final bool value) => _sharedPreferences.setBool(_formatKey(key), value); + Future setBool(final String key, final bool value) => reqireDatabase.setBool(_formatKey(key), value); - List? getStringList(final String key) => _sharedPreferences.getStringList(_formatKey(key)); + List? getStringList(final String key) => reqireDatabase.getStringList(_formatKey(key)); Future setStringList(final String key, final List value) => - _sharedPreferences.setStringList(_formatKey(key), value); + reqireDatabase.setStringList(_formatKey(key), value); } diff --git a/packages/neon/neon/lib/src/utils/global_options.dart b/packages/neon/neon/lib/src/utils/global_options.dart index 15657168..70aa436a 100644 --- a/packages/neon/neon/lib/src/utils/global_options.dart +++ b/packages/neon/neon/lib/src/utils/global_options.dart @@ -52,7 +52,7 @@ class GlobalOptions { } final SharedPreferences _sharedPreferences; - late final AppStorage _storage = AppStorage('global', _sharedPreferences); + late final AppStorage _storage = AppStorage('global'); final PackageInfo _packageInfo; late final _distributorsMap = { diff --git a/packages/neon/neon/lib/src/utils/push_utils.dart b/packages/neon/neon/lib/src/utils/push_utils.dart index 353bfc01..302a75be 100644 --- a/packages/neon/neon/lib/src/utils/push_utils.dart +++ b/packages/neon/neon/lib/src/utils/push_utils.dart @@ -71,9 +71,9 @@ class PushUtils { } }, ); - final sharedPreferences = await SharedPreferences.getInstance(); + await AppStorage.init(); - final keypair = await loadRSAKeypair(AppStorage(AppIDs.notifications, sharedPreferences)); + final keypair = await loadRSAKeypair(AppStorage(AppIDs.notifications)); for (final message in Uri(query: utf8.decode(messages)).queryParameters.values) { final data = json.decode(message) as Map; @@ -99,7 +99,7 @@ class PushUtils { NotificationsNotification? notification; AndroidBitmap? largeIconBitmap; try { - accounts = loadAccounts(AppStorage('accounts', sharedPreferences)); + accounts = loadAccounts(AppStorage('accounts')); account = accounts.tryFind(instance); if (account != null) { notification =