Skip to content

Commit

Permalink
Migrate to SharedPreferencesAsync
Browse files Browse the repository at this point in the history
  • Loading branch information
proninyaroslav committed Sep 8, 2024
1 parent bb39c01 commit e136d75
Show file tree
Hide file tree
Showing 33 changed files with 1,785 additions and 612 deletions.
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"request": "launch",
"type": "dart",
"flutterMode": "debug",
"args": ["--flavor", "base"],
// TODO: https://github.com/flutter/flutter/issues/146890#issuecomment-2212409188
"args": ["--flavor", "base" /*"--enable-software-rendering"*/],
"program": "lib/main.dart"
},
{
Expand Down
84 changes: 58 additions & 26 deletions lib/core/settings/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -330,56 +330,59 @@ abstract class _AppSettingsKey {
abstract class SharedPreferencesModule {
@Singleton(env: [Env.prod, Env.dev])
@preResolve
Future<SharedPreferences> get oldPref async =>
Future<SharedPreferences> get prefOld async =>
SharedPreferences.getInstance();

@Singleton(env: [Env.prod, Env.dev])
@preResolve
Future<SharedPreferencesAsync> get pref async => SharedPreferencesAsync();
Future<SharedPreferencesAsync> pref(SharedPreferences prefOld) async {
final pref = SharedPreferencesAsync();
final migrator = SharedPreferencesMigrator(
oldPrefs: prefOld,
newPrefs: pref,
);
await migrator.migrate();

return pref;
}

@Singleton(env: [Env.test])
@preResolve
Future<SharedPreferences> get testPref async => TestSharedPreferences();
}
Future<SharedPreferencesAsync> get testPref async =>
TestSharedPreferencesAsync();

class TestSharedPreferences implements SharedPreferences {
final Map<String, dynamic> _map = {};

@override
Future<bool> clear() async {
_map.clear();
return true;
@Singleton(env: [Env.test])
@preResolve
Future<SharedPreferences> get testOldPref async {
// ignore: invalid_use_of_visible_for_testing_member
SharedPreferences.setMockInitialValues({});
return SharedPreferences.getInstance();
}
}

@override
Future<bool> commit() async => true;

@override
bool containsKey(String key) => _map.containsKey(key);
class TestSharedPreferencesAsync implements SharedPreferencesAsync {
final Map<String, dynamic> _map = {};

@override
dynamic get(String key) => _map[key];

@override
bool? getBool(String key) => get(key) as bool?;

@override
double? getDouble(String key) => get(key) as double?;
Future<bool> containsKey(String key) async => _map.containsKey(key);

@override
int? getInt(String key) => get(key) as int?;
Future<bool?> getBool(String key) async => get(key) as bool?;

@override
Set<String> getKeys() => _map.keys.toSet();
Future<double?> getDouble(String key) async => get(key) as double?;

@override
String? getString(String key) => get(key) as String?;
Future<int?> getInt(String key) async => get(key) as int?;

@override
List<String>? getStringList(String key) => get(key) as List<String>?;
Future<String?> getString(String key) async => get(key) as String?;

@override
Future<void> reload() async {}
Future<List<String>?> getStringList(String key) async =>
get(key) as List<String>?;

@override
Future<bool> remove(String key) async => _map.remove(key) != null;
Expand All @@ -404,4 +407,33 @@ class TestSharedPreferences implements SharedPreferences {
@override
Future<bool> setStringList(String key, List<String> value) async =>
_set(key, value);

@override
Future<void> clear({Set<String>? allowList}) async {
if (allowList == null) {
_map.clear();
} else {
_map.removeWhere((k, v) => !allowList.contains(k));
}
}

@override
Future<Map<String, Object?>> getAll({Set<String>? allowList}) async {
if (allowList == null) {
return _map;
} else {
return Map.fromEntries(
_map.entries.where((e) => allowList.contains(e.key)),
);
}
}

@override
Future<Set<String>> getKeys({Set<String>? allowList}) async {
if (allowList == null) {
return Set.from(_map.keys);
} else {
return Set.from(_map.keys.where((k) => allowList.contains(k)));
}
}
}
12 changes: 10 additions & 2 deletions lib/core/settings/shared_pref_migrator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'dart:async';

import 'package:shared_preferences/shared_preferences.dart';

import '../../logger.dart';

class SharedPreferencesMigrator {
final SharedPreferences oldPrefs;
final SharedPreferencesAsync newPrefs;
Expand All @@ -15,8 +17,11 @@ class SharedPreferencesMigrator {

/// Reads all the values from [oldPrefs] and saves them to [newPrefs].
Future<void> migrate() async {
if (didMigrate ?? false) return;
for (final key in oldPrefs.getKeys()) {
if (didMigrate ?? false) {
return;
}
final keys = oldPrefs.getKeys();
for (final key in keys) {
final value = oldPrefs.get(key);
if (value is String) {
await newPrefs.setString(key, value);
Expand All @@ -30,6 +35,9 @@ class SharedPreferencesMigrator {
await newPrefs.setStringList(key, value);
}
}
if (keys.isNotEmpty) {
log().i('[SharedPreferences] Migration completed');
}
oldPrefs.setBool("shared_preferences_package_did_migrate", true);
}
}
59 changes: 37 additions & 22 deletions lib/injector.config.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 12 additions & 4 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2021 Yaroslav Pronin <[email protected]>
// Copyright (C) 2021-2024 Yaroslav Pronin <[email protected]>
// Copyright (C) 2021 Insurgo Inc. <[email protected]>
//
// This file is part of LibreTrack.
Expand All @@ -19,11 +19,14 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:libretrack/core/app_database_isolate_binder.dart';
import 'package:libretrack/core/crash_catcher/crash_catcher.dart';
import 'package:libretrack/core/crash_catcher/hook/flutter_crash_hook.dart';
import 'package:libretrack/core/notification_manager.dart';
import 'package:libretrack/core/settings/settings.dart';
import 'package:libretrack/platform/system_tray.dart';
import 'package:libretrack/ui/app_cubit.dart';

import 'core/tracking_scheduler.dart';
import 'core/work_manager/work_manager.dart';
Expand All @@ -46,9 +49,14 @@ Future<void> _main() async {
await getIt<TrackingScheduler>().init();

runApp(
App(
enableDevicePreview: false,
navigatorKey: navigatorKey,
BlocProvider(
create: (context) => AppCubit(
getIt<AppSettings>(),
),
child: App(
enableDevicePreview: false,
navigatorKey: navigatorKey,
),
),
);
}
Expand Down
Loading

0 comments on commit e136d75

Please sign in to comment.