use crate::app::{self, App, InputMode};
use crate::input::Action;
use travelagent_core::forge::PrState;
use super::{handle_command_action, open_browser};
pub fn handle_comment_template_picker_action(app: &mut App, action: Action) {
use crate::ui::comment_template_picker::filter_templates;
match action {
Action::InsertChar(c) => app.ui_layout.push_template_filter_char(c),
Action::DeleteChar => app.ui_layout.pop_template_filter_char(),
Action::DeleteWord => app.ui_layout.word_delete_template_filter(),
Action::ClearLine => app.ui_layout.clear_template_filter(),
Action::CursorDown(_) => {
let filtered =
filter_templates(&app.comment_templates, app.ui_layout.template_filter());
app.ui_layout.advance_template_cursor(filtered.len());
}
Action::CursorUp(_) => app.ui_layout.retreat_template_cursor(),
Action::CommentTemplatePickerSelect => app.select_comment_template(),
Action::CommentTemplatePickerCancel => app.exit_comment_template_picker(),
_ => {}
}
}
pub fn handle_command_palette_action(app: &mut App, action: Action) {
use crate::ui::command_palette::{PALETTE_ENTRIES, filter_entries};
match action {
Action::InsertChar(c) => app.palette.push_char(c),
Action::DeleteChar => {
app.palette.pop_char();
if app.palette.is_empty() {
app.nav.input_mode = InputMode::Normal;
}
}
Action::DeleteWord => app.palette.word_delete(),
Action::ClearLine => app.palette.clear(),
Action::CursorDown(_) => {
let filtered = filter_entries(app.palette.buffer());
app.palette.advance_cursor(filtered.len());
}
Action::CursorUp(_) => app.palette.retreat_cursor(),
Action::SubmitInput => {
let filtered = filter_entries(app.palette.buffer());
if let Some(&entry_idx) = filtered.get(app.palette.cursor()) {
let key = PALETTE_ENTRIES[entry_idx].key;
app.nav.input_mode = InputMode::Normal;
app.palette.clear();
execute_palette_entry(app, key);
} else {
let cmd = app.palette.take_buffer();
app.nav.input_mode = InputMode::Command;
app.palette.set_buffer(cmd);
handle_command_action(app, Action::SubmitInput);
}
}
Action::ExitMode => {
app.nav.input_mode = InputMode::Normal;
app.palette.clear();
}
_ => {}
}
}
fn execute_palette_entry(app: &mut App, key: &str) {
match key {
"r" => app.toggle_reviewed(),
"c" => {
let line = app.get_line_at_cursor();
if line.is_some() {
app.enter_comment_mode(false, line);
} else {
app.set_message("Move cursor to a diff line to add a line comment");
}
}
"C" => app.enter_review_comment_mode(),
"?" => app.toggle_help(),
"R" => {
if app.has_forge() {
app.nav.input_mode = InputMode::ReviewSubmit;
if let Some(r) = app.remote_mut() {
r.review_verdict_cursor = 0;
r.review_body.clear();
r.review_body_editing = false;
}
} else {
app.set_message("Not in remote PR mode");
}
}
"M" => {
if app.has_forge() {
let meta_snapshot = app
.remote()
.and_then(|r| r.pr_metadata.as_ref().map(|m| (m.state, m.is_draft)));
if let Some((state, is_draft)) = meta_snapshot {
if state != PrState::Open {
app.set_warning(format!("PR is already {}", state.display()));
} else if is_draft {
app.set_warning("Cannot merge a draft PR".to_string());
} else {
app.enter_confirm_mode(app::ConfirmAction::Merge);
}
} else {
app.set_warning("No PR metadata available".to_string());
}
} else {
app.set_message("Not in remote PR mode");
}
}
"o" => {
if let Some(url) = app.get_browser_url()
&& let Err(e) = open_browser(&url)
{
app.set_error(format!("Failed to open browser: {e}"));
}
}
"/" => app.enter_search_mode(),
"v" => {
if let Some((line, side)) = app.get_line_at_cursor() {
app.enter_visual_mode(line, side);
} else {
app.set_message("Move cursor to a diff line to start visual selection");
}
}
_ => {
app.nav.input_mode = InputMode::Command;
app.palette.set_buffer(key.to_string());
handle_command_action(app, Action::SubmitInput);
}
}
}