Skip to content

feat(frontend): implement dynamic light/dark/system theme switching, accent colors, and reactive settings - #204

Draft
Joyy-dev wants to merge 3 commits into
mainfrom
feat/color-mode
Draft

Joyy-dev wants to merge 3 commits into
mainfrom
feat/color-mode

Conversation

@Joyy-dev

Copy link
Copy Markdown
Collaborator

Summary

This PR introduces comprehensive support for dynamic theme modes (Dark, Light, and System) and customizable accent colors across the UI. It establishes a modernized theme architecture under lib/core/theme/, fixes mutual exclusivity issues in the Settings appearance panel, and resolves state reactivity bottlenecks that previously prevented theme changes from reflecting in real-time without a hot reload or restart.


Key Changes

1. Theme System Architecture (lib/core/theme/)

  • HudColors (hud_colors.dart): Defines semantic dark and light color tokens (lightBgBase, darkBgBase, lightBgPanel, darkBgPanel, borders, text hierarchies) and dynamic accent color resolvers (cyan, green, amber, red, purple, blue).
  • HudTextTheme (hud_text_theme.dart): Added typography styling tailored for both light and dark modes.
  • HudTheme (hud_theme.dart): Generates dynamic lightTheme(accentColor) and darkTheme(accentColor) ThemeData configurations, with helper resolveThemeMode() to map cyber_light, cyber_dark, and system to Flutter's ThemeMode.
  • Refactored Legacy Imports: Relocated static HUD palette definitions to hudd_theme.dart and migrated imports across all screens and widgets.

2. Settings Screen & Appearance Toggles (settings_screen.dart)

  • Mutual Exclusivity: Ensured Dark Mode, Light Mode, and System Mode toggles operate mutually exclusively—activating one turns off the other two.
  • Deselection Guard: Prevented turning off an already active mode to avoid an invalid state with no active theme.
  • Direct Binding: Bound toggles to app.theme ('cyber_dark', 'cyber_light', 'system') and removed the obsolete appTheme boolean field from AppearanceSettings.
  • Theme-Aware Background: Updated SettingsScreen's Scaffold to use Theme.of(context).scaffoldBackgroundColor instead of hardcoding dark backgrounds.

3. Immediate Theme Reactivity (main.dart & settings_provider.dart)

  • Primitive Riverpod Selectors in main.dart: Switched from selecting the mutable appearance object reference to observing primitive value strings (appearance.theme and appearance.accentColor) directly. This resolves Riverpod caching identical object instances and enables immediate, real-time UI re-renders without hot reload or app restart.
  • Immutable State Clones: Updated updateUI() and saveChanges() in SettingsNotifier (settings_provider.dart) to emit cloned currentSettings instances, ensuring proper state propagation across Riverpod listeners.

Testing & Verification

  • test/widgets/settings_appearance_test.dart:
    • Verifies default theme is Dark Mode ON, Light Mode OFF, System Mode OFF.
    • Verifies toggling Light Mode switches Light ON and Dark/System OFF.
    • Verifies toggling System Mode switches System ON and Dark/Light OFF.
    • Verifies tapping an active mode retains its active state.
  • test/widgets/theme_mode_rebuild_test.dart:
    • Verifies that MaterialApp immediately rebuilds with updated themeMode upon state change.
  • test/models/app_settings_test.dart:
    • Verified JSON serialization and deserialization for settings.

All unit and widget tests pass:

flutter test test/widgets/settings_appearance_test.dart test/widgets/theme_mode_rebuild_test.dart test/models/app_settings_test.dart

@G00dS0ul
G00dS0ul self-requested a review September 20, 2026 10:31
@G00dS0ul
G00dS0ul marked this pull request as ready for review September 20, 2026 10:31
@G00dS0ul
G00dS0ul marked this pull request as draft September 20, 2026 10:33
@G00dS0ul

Copy link
Copy Markdown
Collaborator

Required Action Items

Please address the following items to align this PR with the project architecture and specifications:

  1. Implement ThemeExtension<HudTheme> as mandated by Technical Specification which i will share with you shortly:

    • Create class HudTheme extends ThemeExtension<HudTheme> in lib/theme/hud_theme.dart (or lib/utils/hud_theme.dart).
    • Define all Cyber-HUD tokens (bgBase, bgPanel, primaryBorder, accentCyan, accentGreen, headerCyan, labelMuted, statGreen, valueStyle, etc.) as instance fields.
    • Implement copyWith and lerp.
    • Ensure tokens can be accessed cleanly via Theme.of(context).extension<HudTheme>() or a helper extension like context.hudTheme.
  2. Remove hudd_theme.dart and restore lib/theme/hud_theme.dart:

    • Delete the temporary lib/core/theme/hudd_theme.dart file.
    • Repoint existing imports to the restored lib/theme/hud_theme.dart.
  3. Fix HudTextTheme.light:

    • Change the bodySmall text color from HudColors.lightAccentGreen to HudColors.lightTextDim.
  4. Refactor Settings UX:

    • Replace the three separate toggle switches (DARK MODE, LIGHT MODE, SYSTEM MODE) with a single SegmentedButton or DropdownButton for Theme Mode selection.
  5. Clean up deprecated imports:

    • Remove package:flutter_riverpod/legacy.dart from the newly added tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants