use std::fs;
use std::process;
use super::settings;
use crate::app::RunUblxParams;
use crate::config::{
UblxOpts, UblxOverlay, UblxPaths, prior_indexed_roots_recent, record_prior_root_selected,
remember_indexed_root_path, write_local_enhance_only_toml, write_ublx_overlay_at,
};
use crate::handlers;
use crate::layout::setup::{StartupPromptPhase, StartupPromptState, UblxState};
use crate::ui::UblxAction;
fn local_or_nontrivial_overlay_cache(paths: &UblxPaths) -> bool {
paths.toml_path().is_some()
|| UblxOpts::load_overlay_from_cache(paths).is_some_and(|o| o != UblxOverlay::default())
}
fn discard_project_local_and_overlay_cache(paths: &UblxPaths) {
for p in [paths.hidden_toml(), paths.visible_toml()] {
if p.exists() {
let _ = fs::remove_file(&p);
}
}
if let Some(cache) = paths.last_applied_config_path()
&& cache.exists()
{
let _ = fs::remove_file(&cache);
}
}
fn first_run_reload_and_maybe_snapshot(
state_mut: &mut UblxState,
params_mut: &mut RunUblxParams<'_>,
ublx_opts_mut: &mut UblxOpts,
) {
settings::apply_config_reload(params_mut, ublx_opts_mut, state_mut, Option::<&str>::None);
if params_mut.startup.defer_first_snapshot {
handlers::spawn_snapshot_from_dir_db(
¶ms_mut.dir_to_ublx,
¶ms_mut.db_path,
params_mut.snapshot_done_tx.as_ref(),
params_mut.bumper,
Some(ublx_opts_mut),
);
params_mut.startup.defer_first_snapshot = false;
}
}
fn complete_first_run_with_prior_config(
state_mut: &mut UblxState,
params_mut: &mut RunUblxParams<'_>,
ublx_opts_mut: &mut UblxOpts,
config_written_by_us: bool,
) {
state_mut.startup_prompt = None;
let _ = remember_indexed_root_path(¶ms_mut.dir_to_ublx);
if config_written_by_us {
state_mut.config_written_by_us_at = Some(std::time::Instant::now());
}
first_run_reload_and_maybe_snapshot(state_mut, params_mut, ublx_opts_mut);
}
fn use_previous_project_settings(
state_mut: &mut UblxState,
params_mut: &mut RunUblxParams<'_>,
ublx_opts_mut: &mut UblxOpts,
) {
let paths = UblxPaths::new(¶ms_mut.dir_to_ublx);
let had_local = paths.toml_path().is_some();
let copied_from_cache = if had_local {
false
} else {
match UblxOpts::load_overlay_from_cache(&paths) {
Some(overlay) if overlay != UblxOverlay::default() => {
write_ublx_overlay_at(&paths.hidden_toml(), &overlay);
true
}
_ => false,
}
};
complete_first_run_with_prior_config(state_mut, params_mut, ublx_opts_mut, copied_from_cache);
}
fn start_fresh_then_proceed(
state_mut: &mut UblxState,
params_mut: &mut RunUblxParams<'_>,
ublx_opts_mut: &mut UblxOpts,
) {
let paths = UblxPaths::new(¶ms_mut.dir_to_ublx);
discard_project_local_and_overlay_cache(&paths);
settings::apply_config_reload(params_mut, ublx_opts_mut, state_mut, Option::<&str>::None);
index_this_directory(state_mut, params_mut, ublx_opts_mut);
}
pub fn handle_startup_prompt(
state_mut: &mut UblxState,
params_mut: &mut RunUblxParams<'_>,
ublx_opts_mut: &mut UblxOpts,
action: UblxAction,
) -> bool {
let Some(ref mut sp) = state_mut.startup_prompt else {
return false;
};
match &mut sp.phase {
StartupPromptPhase::RootChoice {
selected_index,
roots,
} => match action {
UblxAction::MoveDown => {
let max = roots.len();
*selected_index = (*selected_index + 1).min(max);
true
}
UblxAction::MoveUp => {
*selected_index = selected_index.saturating_sub(1);
true
}
UblxAction::SearchSubmit => {
if *selected_index == 0 {
let paths = UblxPaths::new(¶ms_mut.dir_to_ublx);
if local_or_nontrivial_overlay_cache(&paths) {
if let Some(sp) = state_mut.startup_prompt.as_mut() {
sp.phase = StartupPromptPhase::PreviousSettings { selected_index: 0 };
}
} else {
index_this_directory(state_mut, params_mut, ublx_opts_mut);
}
} else if let Some(dir) = roots.get(*selected_index - 1).cloned() {
let _ = record_prior_root_selected(&dir);
handlers::relaunch_ublx_indexed_dir(&dir);
}
true
}
UblxAction::Quit | UblxAction::SearchClear => {
handlers::restore_terminal();
process::exit(0);
}
_ => true,
},
StartupPromptPhase::PreviousSettings { selected_index } => match action {
UblxAction::MoveDown => {
*selected_index = (*selected_index + 1).min(1);
true
}
UblxAction::MoveUp => {
*selected_index = selected_index.saturating_sub(1);
true
}
UblxAction::SearchSubmit => {
if *selected_index == 0 {
use_previous_project_settings(state_mut, params_mut, ublx_opts_mut);
} else {
start_fresh_then_proceed(state_mut, params_mut, ublx_opts_mut);
}
true
}
UblxAction::ConfirmYes => {
use_previous_project_settings(state_mut, params_mut, ublx_opts_mut);
true
}
UblxAction::ConfirmNo | UblxAction::Quit | UblxAction::SearchClear => {
start_fresh_then_proceed(state_mut, params_mut, ublx_opts_mut);
true
}
_ => true,
},
StartupPromptPhase::Enhance { selected_index } => match action {
UblxAction::MoveDown => {
*selected_index = (*selected_index + 1).min(1);
true
}
UblxAction::MoveUp => {
*selected_index = selected_index.saturating_sub(1);
true
}
UblxAction::SearchSubmit => {
let enable = *selected_index == 0;
finish_enhance_flow(state_mut, params_mut, ublx_opts_mut, enable);
true
}
UblxAction::ConfirmYes => {
finish_enhance_flow(state_mut, params_mut, ublx_opts_mut, true);
true
}
UblxAction::ConfirmNo | UblxAction::Quit | UblxAction::SearchClear => {
finish_enhance_flow(state_mut, params_mut, ublx_opts_mut, false);
true
}
_ => true,
},
}
}
fn index_this_directory(
state_mut: &mut UblxState,
params_mut: &mut RunUblxParams<'_>,
ublx_opts_mut: &mut UblxOpts,
) {
if ublx_opts_mut.ask_enhance_on_new_root {
if let Some(sp) = state_mut.startup_prompt.as_mut() {
sp.phase = StartupPromptPhase::Enhance { selected_index: 0 };
}
} else {
finish_enhance_flow(
state_mut,
params_mut,
ublx_opts_mut,
ublx_opts_mut.enable_enhance_all,
);
}
}
fn finish_enhance_flow(
state_mut: &mut UblxState,
params_mut: &mut RunUblxParams<'_>,
ublx_opts_mut: &mut UblxOpts,
enable_enhance_all: bool,
) {
state_mut.startup_prompt = None;
let _ = remember_indexed_root_path(¶ms_mut.dir_to_ublx);
let paths = UblxPaths::new(¶ms_mut.dir_to_ublx);
if let Err(e) = write_local_enhance_only_toml(&paths, enable_enhance_all) {
log::warn!("write ublx.toml: {e}");
}
state_mut.config_written_by_us_at = Some(std::time::Instant::now());
first_run_reload_and_maybe_snapshot(state_mut, params_mut, ublx_opts_mut);
}
pub fn init_prompt_state(state_mut: &mut UblxState, current_ref: &std::path::Path) {
let roots = prior_indexed_roots_recent(current_ref, 5);
state_mut.startup_prompt = Some(StartupPromptState {
phase: StartupPromptPhase::RootChoice {
selected_index: 0,
roots,
},
});
}