import 'dart:developer' as developer; import 'package:flutter/material.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tatlock_ui/core/auth/auth_provider.dart'; import 'package:tatlock_ui/core/providers/annotations.dart'; part 'theme_provider.g.dart'; /// User's theme preference setting. enum ThemeSetting { /// Follow system preference system, /// Always light mode light, /// Always dark mode dark, } /// Provider for theme setting state. /// /// Syncs with API preferences when user is authenticated. On login, the theme /// from API preferences takes precedence over local storage. @persistentRiverpod class ThemeNotifier extends _$ThemeNotifier { static const _prefsKey = 'theme_setting'; @override ThemeSetting build() { // Load local setting first for immediate UI _loadSavedSetting(); // Listen for auth state changes to sync from API preferences _syncFromAuthPreferences(); return ThemeSetting.system; } Future _loadSavedSetting() async { final prefs = await SharedPreferences.getInstance(); final value = prefs.getString(_prefsKey); if (value != null) { try { state = ThemeSetting.values.byName(value); } catch (_) { // Invalid value, keep default } } } /// Listen to auth state and sync theme from API preferences. void _syncFromAuthPreferences() { ref.listen(authProvider, (_, next) { next.whenData((auth) { final apiTheme = auth.preferences?.theme; if (apiTheme != null && apiTheme.isNotEmpty) { try { final themeSetting = ThemeSetting.values.byName(apiTheme); if (themeSetting != state) { developer.log( 'Syncing theme from API: $apiTheme', name: 'theme', ); state = themeSetting; // Also persist to local storage for offline use _saveToLocalStorage(themeSetting); } } catch (_) { // Invalid theme value from API, keep current } } }); }); } Future _saveToLocalStorage(ThemeSetting setting) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString(_prefsKey, setting.name); } /// Update theme setting and persist to storage. Future setSetting(ThemeSetting setting) async { state = setting; final prefs = await SharedPreferences.getInstance(); await prefs.setString(_prefsKey, setting.name); } /// Get the ThemeMode for MaterialApp. ThemeMode get themeMode => switch (state) { ThemeSetting.system => ThemeMode.system, ThemeSetting.light => ThemeMode.light, ThemeSetting.dark => ThemeMode.dark, }; }