import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:async'; class ThemeProvider with ChangeNotifier { ThemeMode _themeMode = ThemeMode.system; bool _isAutoThemeEnabled = false; // New: state for auto theme Timer? _autoThemeTimer; // New: Timer for automatic updates ThemeMode get themeMode => _themeMode; bool get isAutoThemeEnabled => _isAutoThemeEnabled; ThemeProvider() { _loadThemeSettings(); } // Load theme preference and auto-theme setting from SharedPreferences Future _loadThemeSettings() async { final prefs = await SharedPreferences.getInstance(); final themeString = prefs.getString('themeMode') ?? 'system'; _themeMode = _stringToThemeMode(themeString); _isAutoThemeEnabled = prefs.getBool('isAutoThemeEnabled') ?? false; // Start auto-theme timer if enabled and not system mode if (_isAutoThemeEnabled && _themeMode != ThemeMode.system) { _startAutoThemeTimer(); } notifyListeners(); } // Set theme mode and save to SharedPreferences void setThemeMode(ThemeMode mode) async { if (_themeMode == mode) return; _themeMode = mode; final prefs = await SharedPreferences.getInstance(); await prefs.setString('themeMode', _themeModeToString(mode)); // Stop auto-theme timer if a manual mode is selected or if system mode is chosen if (mode != ThemeMode.system) { _stopAutoThemeTimer(); } else { // If system mode is chosen, auto-theme logic isn't strictly necessary as system handles it. // However, if we want to toggle auto-theme off when system is selected for clarity: setIsAutoThemeEnabled(false); // Disable auto-theme if user goes back to system } notifyListeners(); } // Toggle automatic theme switching void setIsAutoThemeEnabled(bool enable) async { if (_isAutoThemeEnabled == enable) return; _isAutoThemeEnabled = enable; final prefs = await SharedPreferences.getInstance(); await prefs.setBool('isAutoThemeEnabled', enable); if (enable) { _startAutoThemeTimer(); } else { _stopAutoThemeTimer(); } notifyListeners(); } // Logic to determine theme based on time ThemeMode _getThemeModeBasedOnTime() { final now = DateTime.now(); final hour = now.hour; // 6 AM to 7 PM (19:00) is light theme if (hour >= 6 && hour < 19) { return ThemeMode.light; } else { // 7 PM (19:00) to 5:59 AM is dark theme return ThemeMode.dark; } } // Start the timer for automatic theme changes void _startAutoThemeTimer() { _stopAutoThemeTimer(); // Stop any existing timer first _autoThemeTimer = Timer.periodic(const Duration(minutes: 1), (timer) { if (_isAutoThemeEnabled) { final newThemeMode = _getThemeModeBasedOnTime(); if (_themeMode != newThemeMode) { _themeMode = newThemeMode; // Update _themeMode directly notifyListeners(); // Notify listeners for the change // No need to save to SharedPreferences here, as the auto-theme is driven by time // and not a user's explicit selection of light/dark. } } else { _stopAutoThemeTimer(); // Stop if auto-theme was disabled externally } }); // Immediately apply the theme when the timer starts if (_isAutoThemeEnabled) { final initialTheme = _getThemeModeBasedOnTime(); if (_themeMode != initialTheme) { _themeMode = initialTheme; notifyListeners(); } } } // Stop the automatic theme timer void _stopAutoThemeTimer() { _autoThemeTimer?.cancel(); _autoThemeTimer = null; } // Helper to convert ThemeMode to String for SharedPreferences String _themeModeToString(ThemeMode mode) { switch (mode) { case ThemeMode.light: return 'light'; case ThemeMode.dark: return 'dark'; case ThemeMode.system: return 'system'; } } // Helper to convert String to ThemeMode from SharedPreferences ThemeMode _stringToThemeMode(String themeString) { switch (themeString) { case 'light': return ThemeMode.light; case 'dark': return ThemeMode.dark; case 'system': return ThemeMode.system; default: return ThemeMode.system; } } @override void dispose() { _stopAutoThemeTimer(); // Important: cancel timer when provider is disposed super.dispose(); } }