From 3c89b4ddbb711767726392a21373272edfa7e4f6 Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Fri, 31 Oct 2025 10:54:56 +0530 Subject: [PATCH] feat: Implement color theme persistence and toggle functionality in ThemeCustomizer and ThemeEditorWidget --- lib/helpers/theme/theme_customizer.dart | 46 ++++++++++++++++++++-- lib/helpers/theme/theme_editor_widget.dart | 16 +++++++- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/lib/helpers/theme/theme_customizer.dart b/lib/helpers/theme/theme_customizer.dart index cf6f16a..7c2eeaf 100644 --- a/lib/helpers/theme/theme_customizer.dart +++ b/lib/helpers/theme/theme_customizer.dart @@ -1,5 +1,5 @@ import 'dart:convert'; - +import 'package:flutter/material.dart'; import 'package:marco/helpers/services/json_decoder.dart'; import 'package:marco/helpers/services/localizations/language.dart'; import 'package:marco/helpers/services/localizations/translator.dart'; @@ -7,8 +7,8 @@ import 'package:marco/helpers/services/navigation_services.dart'; import 'package:marco/helpers/theme/admin_theme.dart'; import 'package:marco/helpers/theme/app_notifier.dart'; import 'package:marco/helpers/theme/app_theme.dart'; -import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; typedef ThemeChangeCallback = void Function( ThemeCustomizer oldVal, ThemeCustomizer newVal); @@ -33,6 +33,8 @@ class ThemeCustomizer { static Future init() async { await initLanguage(); + await _loadColorTheme(); + _notify(); } static initLanguage() async { @@ -40,7 +42,7 @@ class ThemeCustomizer { } String toJSON() { - return jsonEncode({'theme': theme.name}); + return jsonEncode({'theme': theme.name, 'colorTheme': colorTheme.name}); } static ThemeCustomizer fromJSON(String? json) { @@ -49,6 +51,8 @@ class ThemeCustomizer { JSONDecoder decoder = JSONDecoder(json); instance.theme = decoder.getEnum('theme', ThemeMode.values, ThemeMode.light); + instance.colorTheme = decoder.getEnum( + 'colorTheme', ColorThemeType.values, ColorThemeType.red); } return instance; } @@ -117,12 +121,46 @@ class ThemeCustomizer { tc.topBarTheme = topBarTheme; tc.rightBarOpen = rightBarOpen; tc.leftBarCondensed = leftBarCondensed; + tc.colorTheme = colorTheme; tc.currentLanguage = currentLanguage.clone(); return tc; } @override String toString() { - return 'ThemeCustomizer{theme: $theme}'; + return 'ThemeCustomizer{theme: $theme, colorTheme: $colorTheme}'; + } + + // --------------------------------------------------------------------------- + // 🟢 Color Theme Persistence + // --------------------------------------------------------------------------- + + static const _colorThemeKey = 'color_theme_type'; + + /// Save selected color theme + static Future saveColorTheme(ColorThemeType type) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString(_colorThemeKey, type.name); + instance.colorTheme = type; + _notify(); + } + + /// Load saved color theme (called at startup) + static Future _loadColorTheme() async { + final prefs = await SharedPreferences.getInstance(); + final savedType = prefs.getString(_colorThemeKey); + if (savedType != null) { + instance.colorTheme = ColorThemeType.values.firstWhere( + (e) => e.name == savedType, + orElse: () => ColorThemeType.red, + ); + } + } + + /// Change color theme & persist + static Future changeColorTheme(ColorThemeType type) async { + oldInstance = instance.clone(); + instance.colorTheme = type; + await saveColorTheme(type); } } diff --git a/lib/helpers/theme/theme_editor_widget.dart b/lib/helpers/theme/theme_editor_widget.dart index 8e6b2b3..31466da 100644 --- a/lib/helpers/theme/theme_editor_widget.dart +++ b/lib/helpers/theme/theme_editor_widget.dart @@ -4,6 +4,7 @@ import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/helpers/widgets/wave_background.dart'; import 'package:marco/helpers/theme/admin_theme.dart'; import 'package:marco/helpers/theme/theme_customizer.dart'; +import 'package:flutter_lucide/flutter_lucide.dart'; class ThemeOption { final String label; @@ -105,7 +106,20 @@ class _ThemeEditorWidgetState extends State { ], ), const SizedBox(height: 12), - + InkWell( + onTap: () { + ThemeCustomizer.setTheme( + ThemeCustomizer.instance.theme == ThemeMode.dark + ? ThemeMode.light + : ThemeMode.dark); + }, + child: Icon( + ThemeCustomizer.instance.theme == ThemeMode.dark + ? LucideIcons.sun + : LucideIcons.moon, + size: 18, + ), + ), // Theme cards wrapped in reactive Obx widget Center( child: Obx(