import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; import '../theme/adaptive_theme.dart'; /// 테마 관리 Provider class ThemeProvider extends ChangeNotifier { static const String _themeBoxName = 'theme_settings'; static const String _themeKey = 'theme_settings'; late Box _themeBox; ThemeSettings _themeSettings = const ThemeSettings(); ThemeSettings get themeSettings => _themeSettings; AppThemeMode get themeMode => _themeSettings.mode; bool get useSystemColors => _themeSettings.useSystemColors; bool get largeText => _themeSettings.largeText; bool get reduceMotion => _themeSettings.reduceMotion; bool get highContrast => _themeSettings.highContrast; /// Provider 초기화 Future initialize() async { _themeBox = await Hive.openBox(_themeBoxName); await _loadThemeSettings(); } /// 저장된 테마 설정 로드 Future _loadThemeSettings() async { final savedSettings = _themeBox.get(_themeKey); if (savedSettings != null) { _themeSettings = ThemeSettings.fromJson( Map.from(savedSettings), ); notifyListeners(); } } /// 테마 설정 저장 Future _saveThemeSettings() async { await _themeBox.put(_themeKey, _themeSettings.toJson()); } /// 테마 모드 변경 Future setThemeMode(AppThemeMode mode) async { _themeSettings = _themeSettings.copyWith(mode: mode); await _saveThemeSettings(); notifyListeners(); } /// 시스템 색상 사용 설정 Future setUseSystemColors(bool value) async { _themeSettings = _themeSettings.copyWith(useSystemColors: value); await _saveThemeSettings(); notifyListeners(); } /// 큰 텍스트 설정 Future setLargeText(bool value) async { _themeSettings = _themeSettings.copyWith(largeText: value); await _saveThemeSettings(); notifyListeners(); } /// 모션 감소 설정 Future setReduceMotion(bool value) async { _themeSettings = _themeSettings.copyWith(reduceMotion: value); await _saveThemeSettings(); notifyListeners(); } /// 고대비 설정 Future setHighContrast(bool value) async { _themeSettings = _themeSettings.copyWith(highContrast: value); await _saveThemeSettings(); notifyListeners(); } /// 현재 설정에 따른 테마 가져오기 ThemeData getTheme(BuildContext context) { final platformBrightness = MediaQuery.of(context).platformBrightness; ThemeData baseTheme; switch (_themeSettings.mode) { case AppThemeMode.light: baseTheme = AdaptiveTheme.lightTheme; break; case AppThemeMode.dark: baseTheme = AdaptiveTheme.darkTheme; break; case AppThemeMode.oled: baseTheme = AdaptiveTheme.oledTheme; break; case AppThemeMode.system: baseTheme = platformBrightness == Brightness.dark ? AdaptiveTheme.darkTheme : AdaptiveTheme.lightTheme; break; } // 접근성 설정 적용 return AdaptiveTheme.getAccessibleTheme( baseTheme, largeText: _themeSettings.largeText, reduceMotion: _themeSettings.reduceMotion, highContrast: _themeSettings.highContrast, ); } /// 현재 테마가 다크 모드인지 확인 bool isDarkMode(BuildContext context) { final platformBrightness = MediaQuery.of(context).platformBrightness; switch (_themeSettings.mode) { case AppThemeMode.light: return false; case AppThemeMode.dark: case AppThemeMode.oled: return true; case AppThemeMode.system: return platformBrightness == Brightness.dark; } } /// 테마 토글 (라이트/다크) Future toggleTheme() async { if (_themeSettings.mode == AppThemeMode.light) { await setThemeMode(AppThemeMode.dark); } else { await setThemeMode(AppThemeMode.light); } } } /// 테마 전환 애니메이션 위젯 class AnimatedThemeBuilder extends StatelessWidget { final Widget Function(BuildContext, ThemeData) builder; final Duration duration; const AnimatedThemeBuilder({ super.key, required this.builder, this.duration = const Duration(milliseconds: 300), }); @override Widget build(BuildContext context) { final themeProvider = context.watch(); final theme = themeProvider.getTheme(context); return AnimatedTheme( data: theme, duration: duration, child: Builder( builder: (context) => builder(context, theme), ), ); } } /// 테마별 색상 위젯 class ThemedColor extends StatelessWidget { final Color lightColor; final Color darkColor; final Widget child; const ThemedColor({ super.key, required this.lightColor, required this.darkColor, required this.child, }); @override Widget build(BuildContext context) { final isDark = context.read().isDarkMode(context); return Theme( data: Theme.of(context).copyWith( primaryColor: isDark ? darkColor : lightColor, ), child: child, ); } }