import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/themes/utils/theme_list.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'material_base_theme.dart'; part 'theme_store.g.dart'; /// MobX store for managing theme state class ThemeStore = ThemeStoreBase with _$ThemeStore; abstract class ThemeStoreBase with Store { @observable MaterialThemeBase _currentTheme = ThemeList.lightTheme; @observable ThemeMode _themeMode = ThemeMode.system; @computed MaterialThemeBase get currentTheme => _currentTheme; @computed ThemeMode get themeMode => _themeMode; @computed bool get isDarkMode => _currentTheme.isDark; late SharedPreferences sharedPreferences; @action Future setTheme(MaterialThemeBase theme) async { if (_currentTheme == theme) return; _currentTheme = theme; await sharedPreferences.setInt(PreferencesKey.currentTheme, theme.raw); } @action Future setThemeMode(ThemeMode mode) async { if (_themeMode == mode) return; _themeMode = mode; await _saveThemeModeToPrefs(mode); if (mode == ThemeMode.system) { setTheme(getThemeFromSystem()); } } Future _saveThemeModeToPrefs(ThemeMode mode) async { await sharedPreferences.setString(PreferencesKey.themeMode, mode.toString()); } /// Loads the saved theme preferences Future loadThemePreferences() async { sharedPreferences = await SharedPreferences.getInstance(); await _loadThemeMode(); await _loadAndSetTheme(); _setupThemeReaction(); } /// Loads the saved theme mode from SharedPreferences Future _loadThemeMode() async { final savedThemeMode = sharedPreferences.getString(PreferencesKey.themeMode); if (savedThemeMode != null) { _themeMode = ThemeMode.values.firstWhere( (mode) => mode.toString() == savedThemeMode, orElse: () => ThemeMode.system, ); } } /// Loads and sets the appropriate theme based on platform and installation status Future _loadAndSetTheme() async { final bool isNewInstall = sharedPreferences.getBool(PreferencesKey.isNewInstall) ?? true; bool shouldUseMobileTheme = responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile; if (shouldUseMobileTheme) { await _handleMobileTheme(isNewInstall); } else { await _handleNonMobileTheme(); } } /// Handles theme loading for non-mobile platforms Future _handleNonMobileTheme() async { await setTheme(ThemeList.darkTheme); await setThemeMode(ThemeMode.dark); } /// Handles theme loading for mobile platforms Future _handleMobileTheme(bool isNewInstall) async { if (isNewInstall) { await _setSystemTheme(isNewInstall: isNewInstall); } else { await loadSavedTheme(); } } /// Loads the saved theme from SharedPreferences Future loadSavedTheme({bool isFromBackup = false}) async { try { final savedTheme = sharedPreferences.getInt(PreferencesKey.currentTheme); if (savedTheme == null) { await _setSystemTheme(); return; } final theme = ThemeList.deserialize(raw: savedTheme); final newThemeMode = _getThemeModeOnStartUp(theme, isFromBackup); if (newThemeMode == ThemeMode.system) { await _setSystemTheme(); return; } if (_themeMode != newThemeMode) { await setThemeMode(newThemeMode); } if (_currentTheme != theme) { await setTheme(theme); } } catch (e) { await _setSystemTheme(); } } Future _setSystemTheme({bool isNewInstall = false}) async { final systemTheme = getThemeFromSystem(); if (_currentTheme != systemTheme) { await setTheme(systemTheme); } if (isNewInstall) { await _saveThemeModeToPrefs(ThemeMode.system); } if (_themeMode != ThemeMode.system) { await setThemeMode(ThemeMode.system); } } ThemeMode _getThemeModeOnStartUp(MaterialThemeBase theme, bool isFromBackup) { if (isFromBackup || _themeMode != ThemeMode.system) { return theme.isDark ? ThemeMode.dark : ThemeMode.light; } return ThemeMode.system; } void _setupThemeReaction() { reaction( (_) => currentTheme, (MaterialThemeBase theme) => sharedPreferences.setInt(PreferencesKey.currentTheme, theme.raw), ); } MaterialThemeBase getThemeFromSystem() { final systemBrightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; return systemBrightness == Brightness.dark ? ThemeList.darkTheme : ThemeList.lightTheme; } }