use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use crate::app::{App, Screen};
pub(crate) fn editable_aliases(app: &App) -> Vec<String> {
app.hosts_state
.list
.iter()
.filter(|h| h.source_file.is_none())
.map(|h| h.alias.clone())
.collect()
}
pub(crate) fn filtered_hosts(app: &App) -> Vec<(String, String)> {
let query = app.ui.tunnel_host_picker_query.to_lowercase();
app.hosts_state
.list
.iter()
.filter(|h| h.source_file.is_none())
.filter(|h| {
if query.is_empty() {
return true;
}
h.alias.to_lowercase().contains(&query) || h.hostname.to_lowercase().contains(&query)
})
.map(|h| (h.alias.clone(), h.hostname.clone()))
.collect()
}
pub(super) fn handle_keys(app: &mut App, key: KeyEvent) {
let total = filtered_hosts(app).len();
match key.code {
KeyCode::Esc => close(app),
KeyCode::Down if total > 0 => {
let cur = app.ui.tunnel_host_picker_state.selected().unwrap_or(0);
let next = (cur + 1).min(total - 1);
app.ui.tunnel_host_picker_state.select(Some(next));
}
KeyCode::Up => {
let cur = app.ui.tunnel_host_picker_state.selected().unwrap_or(0);
app.ui
.tunnel_host_picker_state
.select(Some(cur.saturating_sub(1)));
}
KeyCode::Enter => {
let Some(idx) = app.ui.tunnel_host_picker_state.selected() else {
return;
};
let Some((alias, _)) = filtered_hosts(app).into_iter().nth(idx) else {
return;
};
app.tunnels.form = crate::app::TunnelForm::new();
app.ui.tunnel_host_picker_state.select(None);
app.ui.tunnel_host_picker_query.clear();
app.set_screen(Screen::TunnelForm {
alias,
editing: None,
});
app.capture_form_mtime();
app.capture_tunnel_form_baseline();
}
KeyCode::Backspace => {
if app.ui.tunnel_host_picker_query.is_empty() {
close(app);
} else {
app.ui.tunnel_host_picker_query.pop();
reset_cursor_after_query_change(app);
}
}
KeyCode::Char(c)
if !key.modifiers.contains(KeyModifiers::CONTROL)
&& app.ui.tunnel_host_picker_query.len() < 64 =>
{
app.ui.tunnel_host_picker_query.push(c);
reset_cursor_after_query_change(app);
}
_ => {}
}
}
fn close(app: &mut App) {
app.ui.tunnel_host_picker_state.select(None);
app.ui.tunnel_host_picker_query.clear();
app.set_screen(Screen::HostList);
}
fn reset_cursor_after_query_change(app: &mut App) {
let total = filtered_hosts(app).len();
if total == 0 {
app.ui.tunnel_host_picker_state.select(None);
} else {
app.ui.tunnel_host_picker_state.select(Some(0));
}
}