Skip to content

Commit

Permalink
feat: Use SharedPreferenceAsync instead of SharedPreference to store …
Browse files Browse the repository at this point in the history
…theme and remove GetX dependency - CU-86c0287m8
  • Loading branch information
basemosama committed Aug 22, 2024
1 parent bcfc9d3 commit ef4213f
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 41 deletions.
12 changes: 6 additions & 6 deletions .flutter-plugins
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ path_provider_android=E:\\flutter\\cache\\hosted\\pub.dev\\path_provider_android
path_provider_foundation=E:\\flutter\\cache\\hosted\\pub.dev\\path_provider_foundation-2.2.4\\
path_provider_linux=E:\\flutter\\cache\\hosted\\pub.dev\\path_provider_linux-2.1.10\\
path_provider_windows=E:\\flutter\\cache\\hosted\\pub.dev\\path_provider_windows-2.1.7\\
shared_preferences=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences-2.2.3\\
shared_preferences_android=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_android-2.1.4\\
shared_preferences_foundation=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_foundation-2.4.0\\
shared_preferences_linux=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_linux-2.2.0\\
shared_preferences_web=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_web-2.1.0\\
shared_preferences_windows=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_windows-2.2.0\\
shared_preferences=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences-2.3.2\\
shared_preferences_android=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_android-2.3.1\\
shared_preferences_foundation=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_foundation-2.5.2\\
shared_preferences_linux=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_linux-2.4.1\\
shared_preferences_web=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_web-2.4.2\\
shared_preferences_windows=E:\\flutter\\cache\\hosted\\pub.dev\\shared_preferences_windows-2.4.1\\
2 changes: 1 addition & 1 deletion .flutter-plugins-dependencies
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage-9.2.2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.4.0\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage-9.2.2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]},{"name":"shared_preferences_android","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.1.4\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"flutter_secure_storage_macos","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_macos-3.1.2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.4.0\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"flutter_secure_storage_linux","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_linux-1.2.1\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_linux","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.1.10\\\\","native_build":false,"dependencies":[]},{"name":"shared_preferences_linux","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_linux-2.2.0\\\\","native_build":false,"dependencies":["path_provider_linux"]}],"windows":[{"name":"flutter_secure_storage_windows","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_windows-3.1.2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]},{"name":"shared_preferences_windows","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_windows-2.2.0\\\\","native_build":false,"dependencies":["path_provider_windows"]}],"web":[{"name":"flutter_secure_storage_web","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_web-1.2.1\\\\","dependencies":[]},{"name":"shared_preferences_web","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.1.0\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2024-07-08 23:24:35.058762","version":"3.22.0"}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage-9.2.2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.2\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage-9.2.2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]},{"name":"shared_preferences_android","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.3.1\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"flutter_secure_storage_macos","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_macos-3.1.2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.2\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"flutter_secure_storage_linux","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_linux-1.2.1\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_linux","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.1.10\\\\","native_build":false,"dependencies":[]},{"name":"shared_preferences_linux","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_linux-2.4.1\\\\","native_build":false,"dependencies":["path_provider_linux"]}],"windows":[{"name":"flutter_secure_storage_windows","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_windows-3.1.2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]},{"name":"shared_preferences_windows","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_windows-2.4.1\\\\","native_build":false,"dependencies":["path_provider_windows"]}],"web":[{"name":"flutter_secure_storage_web","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_web-1.2.1\\\\","dependencies":[]},{"name":"shared_preferences_web","path":"E:\\\\flutter\\\\cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.4.2\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2024-08-22 11:36:45.080844","version":"3.24.0","swift_package_manager_enabled":false}
3 changes: 3 additions & 0 deletions lib/src/config/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ class PlayxThemeConfig {
/// List of themes to use in the app.
List<XTheme> themes;

final bool migratePrefsToAsyncPrefs;

PlayxThemeConfig({
this.initialThemeIndex = 0,
this.saveTheme = true,
this.themes = const [],
this.migratePrefsToAsyncPrefs = false,
}) : assert(initialThemeIndex >= 0 && initialThemeIndex < themes.length),
assert(themes.isNotEmpty);
}
Expand Down
43 changes: 37 additions & 6 deletions lib/src/controller/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import 'package:playx_theme/src/utils/animation_utils.dart';
class XThemeController extends ValueNotifier<XTheme> {
static const lastKnownIndexKey = 'playx.theme.last_known_index';

static XThemeController? _instance;

/// Get the instance of the [XThemeController].
static XThemeController get instance {
if (_instance == null) {
throw Exception(
'PlayxTheme is not initialized. Please call `boot` before accessing the instance.');
}
return _instance!;
}

/// Theme configuration.
final PlayxThemeConfig config;

Expand Down Expand Up @@ -54,16 +65,35 @@ class XThemeController extends ValueNotifier<XTheme> {

/// set up the base controller
Future<void> boot() async {
final lastKnownIndex = config.saveTheme
? PlayxPrefs.getInt(lastKnownIndexKey, fallback: initialIndex)
: initialIndex;
final lastSavedIndex = await getLastSavedIndexFromPrefs(
migratePrefsToAsync: config.migratePrefsToAsyncPrefs);
final lastKnownIndex =
config.saveTheme ? lastSavedIndex ?? initialIndex : initialIndex;

currentIndex = lastKnownIndex;

value = config.themes.atOrNull(
lastKnownIndex,
) ??
config.themes.first;
_instance = this;
}

Future<int?> getLastSavedIndexFromPrefs({
bool migratePrefsToAsync = false,
}) async {
await PlayxAsyncPrefs.create();
int? lastSavedIndex = await PlayxAsyncPrefs.maybeGetInt(
lastKnownIndexKey,
);
if (migratePrefsToAsync && lastSavedIndex == null) {
await PlayxPrefs.create();
final lastKnownIndexInPrefs =
PlayxPrefs.getInt(lastKnownIndexKey, fallback: initialIndex);
await PlayxAsyncPrefs.setInt(lastKnownIndexKey, lastKnownIndexInPrefs);
lastSavedIndex = lastKnownIndexInPrefs;
}
return lastSavedIndex;
}

/// Update the theme to one of the theme list.
Expand Down Expand Up @@ -102,7 +132,7 @@ class XThemeController extends ValueNotifier<XTheme> {
}
}
if (config.saveTheme) {
await PlayxPrefs.setInt(lastKnownIndexKey, currentIndex);
await PlayxAsyncPrefs.setInt(lastKnownIndexKey, currentIndex);
}
}

Expand Down Expand Up @@ -131,7 +161,7 @@ class XThemeController extends ValueNotifier<XTheme> {
bool forceUpdateNonAnimatedTheme = false,
}) async {
if (!availableThemes.contains(theme)) {
throw Exception('The provided theme is not in the available themes list');
throw Exception('The provided theme is not in the available theme list');
}
return _updateTheme(
theme: theme,
Expand Down Expand Up @@ -353,7 +383,7 @@ class XThemeController extends ValueNotifier<XTheme> {

/// Clear the last saved theme index.
static Future<void> clearLastSavedTheme() {
return PlayxPrefs.remove(lastKnownIndexKey);
return PlayxAsyncPrefs.remove(lastKnownIndexKey);
}

/// Animate the theme change.
Expand Down Expand Up @@ -403,6 +433,7 @@ class XThemeController extends ValueNotifier<XTheme> {
@override
void dispose() {
timer?.cancel();
_instance = null;
super.dispose();
}
}
20 changes: 13 additions & 7 deletions lib/src/playx_theme.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:animated_theme_switcher/animated_theme_switcher.dart';
import 'package:flutter/material.dart';
import 'package:playx_core/playx_core.dart';
import 'package:playx_theme/src/config/config.dart';
import 'package:playx_theme/src/controller/controller.dart';
import 'package:playx_theme/src/model/playx_colors.dart';
Expand All @@ -9,17 +8,23 @@ import 'package:playx_theme/src/model/x_theme.dart';
/// PlayxTheme :
/// It controls current app theme and how to change current theme.
abstract class PlayxTheme {
/// shortcut for the rest of the functions
static XThemeController get _controller => Get.find<XThemeController>();
static XThemeController? _themeControllerInstance;

static XThemeController get _controller {
if (_themeControllerInstance == null) {
throw Exception(
"PlayxTheme is not initialized. Please call boot() before accessing PlayxTheme.");
}
return _themeControllerInstance!;
}

/// Used to setup AppTheme.
/// Must be called to initialize dependencies.
static Future<void> boot({
required PlayxThemeConfig config,
}) async {
//TODO(1): Try to not depend on GetX package for DI.
final controller = XThemeController(config: config);
Get.put<XThemeController>(controller);
_themeControllerInstance = controller;
return controller.boot();
}

Expand Down Expand Up @@ -301,8 +306,9 @@ abstract class PlayxTheme {

/// Dispose playx theme dependencies.
static Future<bool> dispose() async {
if (Get.isRegistered<XThemeController>()) {
return Get.delete<XThemeController>();
if (_themeControllerInstance != null) {
_themeControllerInstance!.dispose();
_themeControllerInstance = null;
}
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/widgets/animation/playx_theme_switching_area.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class PlayxThemeSwitchingArea extends StatelessWidget {

@override
Widget build(BuildContext context) {
final controller = Get.find<XThemeController>();
final controller = XThemeController.instance;
Widget child;
if (controller.oldTheme == null ||
controller.oldTheme == controller.theme ||
Expand Down
4 changes: 2 additions & 2 deletions lib/src/widgets/playx_theme_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class _ThemeProviderState extends State<PlayxThemeBuilder>
with TickerProviderStateMixin {
late AnimationController _controller;

final themeController = Get.find<XThemeController>();
final themeController = XThemeController.instance;

@override
void initState() {
Expand All @@ -40,7 +40,7 @@ class _ThemeProviderState extends State<PlayxThemeBuilder>

@override
Widget build(BuildContext context) {
final controller = Get.find<XThemeController>();
final controller = XThemeController.instance;
return ValueListenableBuilder(
valueListenable: controller,
builder: (context, xTheme, _) {
Expand Down
7 changes: 4 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: playx_theme
description: Simplify app theming in Flutter with Playx Theme. Effortlessly switch themes, enjoy smooth animations, and customize color schemes with ease.
version: 0.6.0
version: 0.7.0
homepage: https://github.com/playx-flutter/playx_theme
repository: https://github.com/playx-flutter/playx_theme
issue_tracker: https://github.com/playx-flutter/playx_theme/issues
Expand All @@ -18,14 +18,15 @@ environment:
dependencies:
flutter:
sdk: flutter
playx_core: ^0.4.2
flex_seed_scheme: ^3.0.0
playx_core: ^0.5.2
flex_seed_scheme: ^3.1.2
animated_theme_switcher: ^2.0.10


dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^4.0.0
shared_preferences_platform_interface: ^2.4.1

flutter:
10 changes: 6 additions & 4 deletions test/controller/controller_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:playx_theme/playx_theme.dart';
import 'package:playx_theme/src/controller/controller.dart';
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';

import '../config/config.dart';

Expand All @@ -16,14 +18,14 @@ void main() {

setUp(() async {
PlayxPrefs.setMockInitialValues({});
await PlayxCore.bootCore();
SharedPreferencesAsyncPlatform.instance =
InMemorySharedPreferencesAsync.empty();
controller = XThemeController(config: getTestConfig());
await controller.boot();
});
tearDown(() async {
await PlayxPrefs.clear();
await PlayxCore.dispose();
// await PlayxTheme.dispose();
await PlayxAsyncPrefs.clear();
await PlayxTheme.dispose();
});

group('XThemeController Test', () {
Expand Down
Loading

0 comments on commit ef4213f

Please sign in to comment.