1use std::sync::atomic::Ordering;
2use std::sync::mpsc;
3
4use anyhow::Result;
5use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
6
7use crate::app::{App, Screen};
8use crate::event::AppEvent;
9
10mod bulk_tag_editor;
11mod confirm;
12mod container_exec_prompt;
13pub(crate) mod container_host_picker;
14pub(crate) mod container_logs;
15mod containers;
16pub(crate) mod containers_overview;
17mod ctx;
18pub(crate) mod event_loop;
19mod file_browser;
20mod help;
21mod host_detail;
22mod host_form;
23mod host_list;
24mod jump;
25pub(crate) mod key_push_picker;
26mod keys_overview;
27pub(crate) mod password_prompt;
28mod picker;
29mod ping;
30mod provider;
31mod snippet;
32pub(crate) mod snippet_host_picker;
33mod snippets_overview;
34mod sync;
35mod tag_picker;
36mod theme_picker;
37mod tunnel;
38pub(crate) mod tunnel_host_picker;
39mod tunnels_overview;
40mod welcome;
41mod whats_new;
42
43pub use confirm::{ConfirmAction, route_confirm_key};
44pub(crate) use provider::zone_data_for;
45pub use sync::spawn_provider_sync;
46
47pub fn handle_key_event(
49 app: &mut App,
50 key: KeyEvent,
51 events_tx: &mpsc::Sender<AppEvent>,
52) -> Result<()> {
53 if key.modifiers.contains(KeyModifiers::CONTROL) && key.code == KeyCode::Char('c') {
55 if matches!(app.screen, Screen::SnippetOutput) {
56 if let Some(state) = app.snippets.output()
57 && !state.all_done
58 {
59 if state.cancel.load(Ordering::Relaxed) {
60 } else {
62 state.cancel.store(true, Ordering::Relaxed);
64 return Ok(());
65 }
66 }
67 app.snippets.set_output(None);
68 app.set_screen(Screen::HostList);
69 return Ok(());
70 }
71 if let Some(cancel) = app.vault.signing_cancel() {
72 cancel.store(true, std::sync::atomic::Ordering::Relaxed);
73 }
74 app.running = false;
75 return Ok(());
76 }
77
78 if app.jump.is_some() {
80 jump::handle_key(app, key, events_tx);
81 return Ok(());
82 }
83
84 match &app.screen {
85 Screen::HostList => host_list::handle_key(app, key, events_tx),
86 Screen::AddHost | Screen::EditHost { .. } => host_form::handle_key(app, key),
87 Screen::ConfirmDelete { .. } => confirm::handle_delete_key(app, key),
88 Screen::Help { .. } => help::handle_key(app, key),
89 Screen::KeyList => help::handle_key_list_key(app, key),
90 Screen::KeyDetail { .. } => help::handle_key_detail_key(app, key),
91 Screen::KeyPushPicker { .. } => key_push_picker::handle_key(app, key),
92 Screen::ConfirmKeyPush { .. } => confirm::handle_key_push_key(app, key, events_tx),
93 Screen::HostDetail { .. } => host_detail::handle_key(app, key),
94 Screen::TagPicker => tag_picker::handle_key(app, key),
95 Screen::BulkTagEditor => bulk_tag_editor::handle_key(app, key),
96 Screen::ThemePicker => theme_picker::handle_key(app, key),
97 Screen::Providers => provider::handle_provider_list_key(app, key, events_tx),
98 Screen::ProviderForm { .. } => provider::handle_provider_form_key(app, key, events_tx),
99 Screen::ProviderLabelMigration { .. } => {
100 provider::handle_label_migration_key(app, key, events_tx)
101 }
102 Screen::TunnelList { .. } => tunnel::handle_tunnel_list_key(app, key),
103 Screen::TunnelForm { .. } => tunnel::handle_tunnel_form_key(app, key),
104 Screen::TunnelHostPicker => tunnel_host_picker::handle_key(app, key),
105 Screen::ContainerHostPicker => container_host_picker::handle_key(app, key, events_tx),
106 Screen::SnippetPicker => snippet::handle_picker_key(app, key, events_tx),
107 Screen::SnippetForm => snippet::handle_form_key(app, key),
108 Screen::SnippetOutput => snippet::handle_output_key(app, key),
109 Screen::SnippetParamForm => snippet::handle_param_form_key(app, key, events_tx),
110 Screen::SnippetHostPicker => snippet_host_picker::handle_key(app, key),
111 Screen::ConfirmRunSnippet => confirm::handle_run_snippet_confirm_key(app, key, events_tx),
112 Screen::ConfirmHostKeyReset { .. } => confirm::handle_host_key_reset_key(app, key),
113 Screen::ConfirmHostKeyTrust { .. } => {
114 confirm::handle_host_key_trust_key(app, key, events_tx)
115 }
116 Screen::PasswordPrompt => password_prompt::handle_key(app, key, events_tx),
117 Screen::ConfirmVaultSign => confirm::handle_vault_sign_key(app, key, events_tx),
118 Screen::ConfirmImport { .. } => confirm::handle_import_key(app, key),
119 Screen::ConfirmPurgeStale => confirm::handle_purge_stale_key(app, key),
120 Screen::FileBrowser { .. } => file_browser::handle_key(app, key, events_tx),
121 Screen::Containers { .. } => containers::handle_key(app, key, events_tx)?,
122 Screen::ContainerLogs => container_logs::handle_key(app, key, events_tx),
123 Screen::ConfirmContainerRestart { .. } => confirm::handle_container_restart_key(app, key),
124 Screen::ConfirmContainerStop { .. } => confirm::handle_container_stop_key(app, key),
125 Screen::ContainerExecPrompt { .. } => container_exec_prompt::handle_key(app, key),
126 Screen::ConfirmStackRestart => confirm::handle_stack_restart_key(app, key),
127 Screen::ConfirmHostRestartAll => confirm::handle_host_restart_all_key(app, key),
128 Screen::ConfirmHostStopAll => confirm::handle_host_stop_all_key(app, key),
129 Screen::Welcome { .. } => welcome::handle_key(app, key),
130 Screen::WhatsNew(_) => whats_new::handle_key(app, key),
131 }
132 Ok(())
133}
134
135#[cfg(test)]
136mod tests;