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_key(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_mut().select(Some(next));
}
KeyCode::Up => {
let cur = app.ui.tunnel_host_picker_state().selected().unwrap_or(0);
app.ui
.tunnel_host_picker_state_mut()
.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.ui.tunnel_host_picker_state_mut().select(None);
app.ui.tunnel_host_picker_query_mut().clear();
app.open_tunnel_add_form(alias);
}
KeyCode::Backspace => {
if app.ui.tunnel_host_picker_query().is_empty() {
close(app);
} else {
app.ui.tunnel_host_picker_query_mut().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_mut().push(c);
reset_cursor_after_query_change(app);
}
_ => {}
}
}
fn close(app: &mut App) {
app.ui.tunnel_host_picker_state_mut().select(None);
app.ui.tunnel_host_picker_query_mut().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_mut().select(None);
} else {
app.ui.tunnel_host_picker_state_mut().select(Some(0));
}
}