@@ -24,6 +24,8 @@ use tokio::time;
2424pub struct App {
2525 /// Current application state
2626 state : AppState ,
27+ /// Previous application state for ESC restoration
28+ previous_state : AppState ,
2729 /// Current theme
2830 theme : Theme ,
2931 /// Layout manager using Taffy
@@ -40,7 +42,8 @@ impl App {
4042 /// Create a new application instance with the given theme
4143 pub fn new ( theme : Theme ) -> Self {
4244 Self {
43- state : AppState :: Running ,
45+ state : AppState :: Main ,
46+ previous_state : AppState :: Main ,
4447 theme,
4548 layout : AppLayout :: new ( ) . expect ( "Failed to create layout" ) ,
4649 event_handler : EventHandler :: default ( ) ,
@@ -59,6 +62,20 @@ impl App {
5962 matches ! ( self . state, AppState :: Quitting )
6063 }
6164
65+ /// Enter settings modal
66+ pub fn enter_settings ( & mut self ) {
67+ // Only set previous_state if we're not already in Settings
68+ if !matches ! ( self . state, AppState :: Settings ) {
69+ self . previous_state = self . state . clone ( ) ;
70+ }
71+ self . state = AppState :: Settings ;
72+ }
73+
74+ /// Exit settings modal and return to previous state
75+ pub fn exit_settings ( & mut self ) {
76+ self . state = self . previous_state . clone ( ) ;
77+ }
78+
6279 /// Main application run loop with proper async event handling
6380 pub async fn run < B : Backend > (
6481 & mut self ,
@@ -106,6 +123,24 @@ impl App {
106123 AppEvent :: Quit | AppEvent :: ForceQuit => {
107124 self . state = AppState :: Quitting ;
108125 }
126+ AppEvent :: OpenSettings => {
127+ self . enter_settings ( ) ;
128+ }
129+ AppEvent :: CloseSettings => {
130+ // Only close settings if we're in settings mode
131+ if matches ! ( self . state, AppState :: Settings ) {
132+ self . exit_settings ( ) ;
133+ } else {
134+ // If not in settings, ESC means quit
135+ self . state = AppState :: Quitting ;
136+ }
137+ }
138+ AppEvent :: SettingsAction ( action) => {
139+ // Handle settings actions and apply theme changes immediately
140+ if let Err ( e) = self . handle_settings_action ( action) {
141+ self . state = AppState :: Error ( format ! ( "Settings error: {}" , e) ) ;
142+ }
143+ }
109144 AppEvent :: ToggleTheme => {
110145 // Toggle theme through settings system
111146 self . settings . get_mut ( ) . toggle_theme ( ) ;
@@ -166,8 +201,7 @@ impl App {
166201 /// Render the main content area
167202 fn render_main_content ( & self , frame : & mut Frame , area : ratatui:: layout:: Rect ) {
168203 let content = match & self . state {
169- AppState :: Running => {
170- // ASCII Art Logo for Agentic
204+ AppState :: Main => {
171205 format ! ( r#"
172206
173207 ╔═══════════════════════════════════════════════════════════════╗
@@ -202,11 +236,57 @@ impl App {
202236 self . last_size
203237 )
204238 }
239+ AppState :: Settings => {
240+ format ! ( r#"
241+ Settings Panel
242+ ==============================================================
243+
244+ APPEARANCE
245+ --------------------------------------------------------------
246+
247+ Theme Variant: {}
248+
249+ KEYBINDINGS
250+ --------------------------------------------------------------
251+
252+ T - Toggle Theme Variant
253+ ESC - Close Settings & Return to Main
254+
255+ CURRENT CONFIGURATION
256+ --------------------------------------------------------------
257+
258+ Theme: {} Mode
259+ Theme Variant: {}
260+ Settings Foundation: Active
261+ State Machine: Extended
262+
263+ SETTINGS MANAGEMENT
264+ --------------------------------------------------------------
265+
266+ All changes apply immediately
267+ Settings are managed through the SettingsManager
268+ Use ESC to return to the main interface
269+
270+ "# ,
271+ match self . theme. variant( ) {
272+ crate :: theme:: ThemeVariant :: EverforestDark => "Everforest Dark" ,
273+ crate :: theme:: ThemeVariant :: EverforestLight => "Everforest Light" ,
274+ } ,
275+ match self . theme. variant( ) {
276+ crate :: theme:: ThemeVariant :: EverforestDark => "Dark" ,
277+ crate :: theme:: ThemeVariant :: EverforestLight => "Light" ,
278+ } ,
279+ match self . settings( ) . theme_variant {
280+ crate :: theme:: ThemeVariant :: EverforestDark => "Everforest Dark" ,
281+ crate :: theme:: ThemeVariant :: EverforestLight => "Everforest Light" ,
282+ }
283+ )
284+ }
205285 AppState :: Quitting => {
206- "🔄 Shutting down gracefully...\n \n Thank you for using Agentic!\n \n The application will exit momentarily." . to_string ( )
286+ "Shutting down gracefully...\n \n Thank you for using Agentic!\n \n The application will exit momentarily." . to_string ( )
207287 }
208288 AppState :: Error ( error) => {
209- format ! ( "⚠️ Application Error\n \n An error occurred:\n {}\n \n Press ESC or q to quit." , error)
289+ format ! ( "Application Error\n \n An error occurred:\n {}\n \n Press ESC or q to quit." , error)
210290 }
211291 } ;
212292
@@ -239,8 +319,12 @@ impl App {
239319 . title_style ( self . theme . ratatui_style ( Element :: Title ) ) ;
240320
241321 let footer_text = match self . state {
242- AppState :: Running => format ! (
243- "ESC/q: Quit | T: Toggle Theme | Current: [{}] | Production v0.1.0" ,
322+ AppState :: Main => format ! (
323+ "ESC/q: Quit | T: Toggle Theme | ,: Settings | Current: [{}] | Production v0.1.0" ,
324+ current_theme
325+ ) ,
326+ AppState :: Settings => format ! (
327+ "ESC: Back to Main | T: Toggle Theme | Current: [{}] | Settings Mode" ,
244328 current_theme
245329 ) ,
246330 AppState :: Quitting => "Application shutting down gracefully..." . to_string ( ) ,
0 commit comments