@@ -17,6 +17,7 @@ pub struct App {
1717 pub focused_field : TaskField ,
1818 pub disable_saving : bool , // For testing
1919 pub theme : Theme ,
20+ pub selected_theme_index : usize , // for theme selector view
2021}
2122
2223// which field is focused in task detail view
@@ -42,6 +43,7 @@ pub enum InputMode {
4243 AddingColumn ,
4344 RenamingColumn ,
4445 ConfirmingDelete ,
46+ SelectingTheme ,
4547}
4648
4749impl App {
@@ -74,6 +76,7 @@ impl App {
7476 focused_field : TaskField :: Title ,
7577 disable_saving : false ,
7678 theme,
79+ selected_theme_index : 0 ,
7780 }
7881 }
7982
@@ -115,6 +118,7 @@ impl App {
115118 focused_field : TaskField :: Title ,
116119 disable_saving : true ,
117120 theme : Theme :: default ( ) ,
121+ selected_theme_index : 0 ,
118122 }
119123 }
120124
@@ -467,7 +471,8 @@ impl App {
467471 | InputMode :: ViewingTask
468472 | InputMode :: ViewingHelp
469473 | InputMode :: ProjectList
470- | InputMode :: ConfirmingDelete => { }
474+ | InputMode :: ConfirmingDelete
475+ | InputMode :: SelectingTheme => { }
471476 }
472477 self . cancel_input ( ) ;
473478 }
@@ -588,6 +593,54 @@ impl App {
588593 let _ = storage:: save_config ( & config) ;
589594 }
590595
596+ // theme management
597+ pub fn open_theme_selector ( & mut self ) {
598+ self . input_mode = InputMode :: SelectingTheme ;
599+ // Find current theme index
600+ let config = storage:: load_config ( ) ;
601+ let current_theme_name = config. theme . as_deref ( ) . unwrap_or ( "high-contrast" ) ;
602+ let theme_names = Theme :: all_theme_names ( ) ;
603+ self . selected_theme_index = theme_names
604+ . iter ( )
605+ . position ( |& name| name == current_theme_name)
606+ . unwrap_or ( 0 ) ;
607+ }
608+
609+ pub fn move_theme_up ( & mut self ) {
610+ let theme_count = Theme :: all_theme_names ( ) . len ( ) ;
611+ if self . selected_theme_index == 0 {
612+ self . selected_theme_index = theme_count - 1 ;
613+ } else {
614+ self . selected_theme_index -= 1 ;
615+ }
616+ }
617+
618+ pub fn move_theme_down ( & mut self ) {
619+ let theme_count = Theme :: all_theme_names ( ) . len ( ) ;
620+ if self . selected_theme_index >= theme_count - 1 {
621+ self . selected_theme_index = 0 ;
622+ } else {
623+ self . selected_theme_index += 1 ;
624+ }
625+ }
626+
627+ pub fn apply_theme ( & mut self ) {
628+ let theme_names = Theme :: all_theme_names ( ) ;
629+ let theme_name = theme_names[ self . selected_theme_index ] ;
630+
631+ // Update app theme
632+ self . theme = Theme :: from_name ( theme_name) . unwrap_or_default ( ) ;
633+
634+ // Save to config
635+ let mut config = storage:: load_config ( ) ;
636+ config. theme = Some ( theme_name. to_string ( ) ) ;
637+ let _ = storage:: save_config ( & config) ;
638+ }
639+
640+ pub fn close_theme_selector ( & mut self ) {
641+ self . input_mode = InputMode :: Normal ;
642+ }
643+
591644 // show help view
592645 pub fn show_help ( & mut self ) {
593646 self . input_mode = InputMode :: ViewingHelp ;
0 commit comments