diff --git a/crates/tui/src/tui/ui.rs b/crates/tui/src/tui/ui.rs index 4713d39b..05c2a72d 100644 --- a/crates/tui/src/tui/ui.rs +++ b/crates/tui/src/tui/ui.rs @@ -1586,24 +1586,6 @@ async fn run_event_loop( // Handle onboarding flow if app.onboarding != OnboardingState::None { - // After Welcome (and the new Language step) we route to either - // the API-key step, the trust prompt, or the tips screen - // depending on what the user still needs to set up. - let advance_after_language = |app: &mut App| { - app.status_message = None; - if app.onboarding_needs_api_key { - app.onboarding = OnboardingState::ApiKey; - } else if !app.trust_mode && onboarding::needs_trust(&app.workspace) { - app.onboarding = OnboardingState::TrustDirectory; - } else { - app.onboarding = OnboardingState::Tips; - } - }; - let advance_onboarding = |app: &mut App| { - app.status_message = None; - app.onboarding = OnboardingState::Language; - }; - match key.code { KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { let _ = engine_handle.send(Op::Shutdown).await; @@ -1639,7 +1621,7 @@ async fn run_event_loop( StatusToastLevel::Info, Some(2_500), ); - advance_after_language(app); + advance_onboarding_after_language(app); } Err(err) => { app.status_message = @@ -1650,12 +1632,12 @@ async fn run_event_loop( } KeyCode::Enter => match app.onboarding { OnboardingState::Welcome => { - advance_onboarding(app); + advance_onboarding_from_welcome(app); } OnboardingState::Language => { // Enter without a digit pick keeps the existing // setting (which defaults to "auto"). - advance_after_language(app); + advance_onboarding_after_language(app); } OnboardingState::ApiKey => { let key = app.api_key_input.trim().to_string(); @@ -1708,7 +1690,7 @@ async fn run_event_loop( .await; } - advance_onboarding(app); + advance_onboarding_after_language(app); } Err(e) => { app.status_message = Some(e.to_string()); @@ -3192,6 +3174,22 @@ fn validate_api_key_for_onboarding(api_key: &str) -> ApiKeyValidation { ApiKeyValidation::Accept { warning: None } } +fn advance_onboarding_from_welcome(app: &mut App) { + app.status_message = None; + app.onboarding = OnboardingState::Language; +} + +fn advance_onboarding_after_language(app: &mut App) { + app.status_message = None; + if app.onboarding_needs_api_key { + app.onboarding = OnboardingState::ApiKey; + } else if !app.trust_mode && onboarding::needs_trust(&app.workspace) { + app.onboarding = OnboardingState::TrustDirectory; + } else { + app.onboarding = OnboardingState::Tips; + } +} + fn sync_api_key_validation_status(app: &mut App, show_empty_error: bool) { if app.api_key_input.trim().is_empty() && !show_empty_error { app.status_message = None; diff --git a/crates/tui/src/tui/ui/tests.rs b/crates/tui/src/tui/ui/tests.rs index e78b3f6e..bab65f89 100644 --- a/crates/tui/src/tui/ui/tests.rs +++ b/crates/tui/src/tui/ui/tests.rs @@ -1588,6 +1588,34 @@ fn api_key_validation_warns_without_blocking_unusual_formats() { )); } +#[test] +fn onboarding_after_api_key_save_does_not_repeat_language_step() { + let mut app = create_test_app(); + app.onboarding = OnboardingState::ApiKey; + app.onboarding_needs_api_key = false; + app.trust_mode = true; + app.status_message = Some("saved".to_string()); + + advance_onboarding_after_language(&mut app); + + assert_eq!(app.onboarding, OnboardingState::Tips); + assert_eq!(app.status_message, None); +} + +#[test] +fn onboarding_after_api_key_save_routes_to_trust_when_needed() { + let tmpdir = TempDir::new().expect("tempdir"); + let mut app = create_test_app(); + app.workspace = tmpdir.path().to_path_buf(); + app.onboarding = OnboardingState::ApiKey; + app.onboarding_needs_api_key = false; + app.trust_mode = false; + + advance_onboarding_after_language(&mut app); + + assert_eq!(app.onboarding, OnboardingState::TrustDirectory); +} + #[test] fn api_key_paste_shortcut_is_not_plain_text_input() { let ctrl_v = KeyEvent::new(KeyCode::Char('v'), KeyModifiers::CONTROL);