feat: remove ModePicker overlay and related commands; update mode handling and documentation

This commit is contained in:
asepharyana
2026-07-12 02:14:40 +07:00
parent 662e269f2c
commit 32155f8ea8
9 changed files with 3 additions and 110 deletions
-8
View File
@@ -30,7 +30,6 @@ pub enum Action {
OpenOverlay(Overlay),
CloseOverlay,
ToggleYoloArm,
CycleAgentMode,
SystemNote {
kind: String,
message: String,
@@ -242,13 +241,6 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) {
state.misc.yolo_armed = !state.misc.yolo_armed;
state.dirty = true;
}
Action::CycleAgentMode => {
let next = state.mode.cycle();
state.set_mode(next);
let toast = Toast::new(ToastKind::Info, format!("Mode: {}", state.mode.name()));
state.push_toast(toast);
state.dirty = true;
}
Action::SystemNote { kind: _kind, message } => {
let toast = crate::app::state::types::Toast::new(
crate::app::state::types::ToastKind::Info,
-8
View File
@@ -75,14 +75,6 @@ const COMMANDS: &[&str] = &[
"/lesson import",
"/lesson accept",
"/lesson reject",
"/mode chat",
"/mode bash",
"/mode help",
"/mode settings",
"/mode effort",
"/mode mcp",
"/mode rewind",
"/mode editor",
"/login",
"/login zen",
"/login openai",
+1 -1
View File
@@ -68,7 +68,7 @@ impl AppStateRest {
.map(|n| n.to_string_lossy().to_string())
.unwrap_or_default();
AppStateRest {
mode: AgentMode::Normal,
mode: AgentMode::Auto,
settings,
app_config,
workspace_roots,
-1
View File
@@ -87,7 +87,6 @@ pub enum Overlay {
Loading,
ModelSelector,
ClearConfirm,
ModePicker,
LoginPicker,
}
+1 -1
View File
@@ -44,7 +44,7 @@ pub fn parse_command(text: &str) -> Command {
"/quit" => Command::Quit,
"/clear" if arg1.is_empty() => Command::ClearConfirm,
"/clear" => Command::Clear,
"/mode" if arg1.is_empty() => Command::Help, // open help to show available modes
"/mode" if arg1.is_empty() => Command::Unknown("/mode requires a subcommand: chat, bash, help, settings".to_string()),
"/mode" => {
let mode = match arg1 {
"chat" | "c" => ModeKind::Chat,
-52
View File
@@ -124,10 +124,6 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
state.misc.selected_index = if state.misc.selected_index == 0 { n.saturating_sub(1) } else { state.misc.selected_index - 1 };
state.dirty = true;
Vec::new()
} else if state.misc.overlay == Overlay::ModePicker {
state.misc.selected_index = if state.misc.selected_index == 0 { 3 } else { state.misc.selected_index - 1 };
state.dirty = true;
Vec::new()
} else if state.misc.overlay == Overlay::LoginPicker {
let n = crate::app::mode::onboard_provider::PROVIDERS.len();
state.misc.selected_index = if state.misc.selected_index == 0 { n.saturating_sub(1) } else { state.misc.selected_index - 1 };
@@ -162,10 +158,6 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
state.misc.selected_index = if n == 0 { 0 } else { (state.misc.selected_index + 1) % n };
state.dirty = true;
Vec::new()
} else if state.misc.overlay == Overlay::ModePicker {
state.misc.selected_index = (state.misc.selected_index + 1) % 4;
state.dirty = true;
Vec::new()
} else if state.misc.overlay == Overlay::LoginPicker {
let n = crate::app::mode::onboard_provider::PROVIDERS.len();
state.misc.selected_index = (state.misc.selected_index + 1) % n;
@@ -181,33 +173,6 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
KeyCode::PageDown => {
vec![Action::ScrollDown]
}
KeyCode::Char('h') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::Help)]
}
KeyCode::Char('p') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::Settings)]
}
KeyCode::Char('a') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::ToggleYoloArm]
}
KeyCode::Char('m') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::CycleAgentMode]
}
KeyCode::Char('b') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::Bash)]
}
KeyCode::Char('S') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::Security)]
}
KeyCode::Char('t') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::Todo)]
}
KeyCode::Char('w') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::Workflow)]
}
KeyCode::Char('k') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::KeyInput)]
}
KeyCode::Esc => {
if state.input.autocomplete_visible {
state.input.close_autocomplete();
@@ -230,12 +195,6 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
}
Vec::new()
}
KeyCode::Char('l') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::Learning)]
}
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
vec![Action::OpenOverlay(Overlay::Usage)]
}
KeyCode::Char(c) => {
if state.input.autocomplete_visible {
state.input.close_autocomplete();
@@ -341,17 +300,6 @@ fn handle_overlay_enter(state: &mut AppStateRest) -> Vec<Action> {
state.dirty = true;
Vec::new()
}
Overlay::ModePicker => {
let mode = state.mode.cycle();
state.mode = mode;
state.push_toast(crate::app::state::types::Toast::new(
crate::app::state::types::ToastKind::Info,
format!("Mode: {}", mode.name()),
));
state.misc.overlay = Overlay::None;
state.dirty = true;
Vec::new()
}
Overlay::LoginPicker => {
state.misc.overlay = Overlay::OnboardProvider;
state.dirty = true;
-1
View File
@@ -232,7 +232,6 @@ fn apply_client_update(
Some("Loading") => Overlay::Loading,
Some("ModelSelector") => Overlay::ModelSelector,
Some("ClearConfirm") => Overlay::ClearConfirm,
Some("ModePicker") => Overlay::ModePicker,
Some("LoginPicker") => Overlay::LoginPicker,
_ => Overlay::None,
};
+1 -1
View File
@@ -27,7 +27,7 @@ Modes:
Input:
/help Show help
/clear Clear screen
/mode Show current mode
/model Select AI model provider
/exit Exit application
/settings Open settings
/session Session management
-37
View File
@@ -608,43 +608,6 @@ fn render_overlay(frame: &mut Frame, area: Rect, overlay: crate::app::state::typ
let paragraph = Paragraph::new(lines).block(block);
frame.render_widget(paragraph, overlay_area);
}
crate::app::state::types::Overlay::ModePicker => {
let block = block.title(" Mode ");
let modes = [
("Auto", "auto-approve tools"),
("Normal", "ask before risky tools"),
("Plan", "plan-only mode"),
("Yolo", "full auto"),
];
let current = state.mode.name();
let mut lines: Vec<Line> = vec![
Line::from(Span::styled(
format!("Current: {}", current),
Style::default().fg(Theme::INFO).add_modifier(Modifier::BOLD),
)),
Line::from(Span::styled("", Style::default())),
];
for (i, (name, desc)) in modes.iter().enumerate() {
let is_selected = i == state.misc.selected_index;
let prefix = if is_selected { "" } else { " " };
let label = format!("{}{} ({})", prefix, name, desc);
let style = if *name == current {
Style::default().fg(Theme::HIGHLIGHT).add_modifier(Modifier::BOLD).add_modifier(Modifier::ITALIC)
} else if is_selected {
Style::default().fg(Theme::BG).bg(Theme::HIGHLIGHT)
} else {
Style::default().fg(Theme::TEXT)
};
lines.push(Line::from(Span::styled(label, style)));
}
lines.push(Line::from(Span::styled("", Style::default())));
lines.push(Line::from(Span::styled(
"↑↓ navigate · Enter select · Esc close",
Style::default().fg(Theme::DIM),
)));
let paragraph = Paragraph::new(lines).block(block);
frame.render_widget(paragraph, overlay_area);
}
crate::app::state::types::Overlay::LoginPicker => {
let block = block.title(" Login ");
let providers = crate::app::mode::onboard_provider::PROVIDERS;