From e0abbf4ee4def58140115be9485d2c9f2846cd60 Mon Sep 17 00:00:00 2001 From: Gabor Feher Date: Tue, 5 Aug 2025 17:24:21 +0200 Subject: [PATCH 1/2] refactor: input handler --- src/handler.rs | 1249 +++++++++++++++++++++--------------------------- 1 file changed, 536 insertions(+), 713 deletions(-) diff --git a/src/handler.rs b/src/handler.rs index 873e000..cebc0c0 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -11,6 +11,36 @@ use iwdrs::modes::Mode; use tokio::sync::mpsc::UnboundedSender; use tui_input::backend::crossterm::EventHandler; +async fn handle_reset_mode_key_event( + key_event: KeyEvent, + app: &mut App, + sender: UnboundedSender, +) -> AppResult<()> { + match key_event.code { + KeyCode::Char('q') => app.quit(), + KeyCode::Char('c' | 'C') => { + if key_event.modifiers == KeyModifiers::CONTROL { + app.quit(); + } + } + KeyCode::Char('j') => { + if app.selected_mode == Mode::Station { + app.selected_mode = Mode::Ap; + } + } + KeyCode::Char('k') => { + if app.selected_mode == Mode::Ap { + app.selected_mode = Mode::Station; + } + } + KeyCode::Enter => { + sender.send(Event::Reset(app.selected_mode.clone()))?; + } + _ => {} + } + Ok(()) +} + pub async fn handle_key_events( key_event: KeyEvent, app: &mut App, @@ -18,751 +48,544 @@ pub async fn handle_key_events( config: Arc, ) -> AppResult<()> { if app.reset_mode { - match key_event.code { - KeyCode::Char('q') => { - app.quit(); + return handle_reset_mode_key_event(key_event, app, sender).await; + } + match ( + app.adapter.device.mode.clone(), + key_event.code, + app.focused_block, + ) { + (_, KeyCode::Enter, FocusedBlock::AuthKey) => { + app.send_passkey().await?; + app.focused_block = FocusedBlock::Device; + } + (_, KeyCode::Esc, FocusedBlock::AuthKey) => { + app.cancel_auth().await?; + app.focused_block = FocusedBlock::Device; + } + (_, KeyCode::Tab, FocusedBlock::AuthKey) => { + app.show_password = !app.show_password; + } + (_, _, FocusedBlock::AuthKey) => { + app.passkey_input + .handle_event(&crossterm::event::Event::Key(key_event)); + } + (_, KeyCode::Enter, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + ap.start(sender.clone()).await?; + sender.send(Event::Reset(app.current_mode.clone()))?; + app.focused_block = FocusedBlock::Device; } - KeyCode::Char('c' | 'C') => { - if key_event.modifiers == KeyModifiers::CONTROL { - app.quit(); - } + } + (_, KeyCode::Esc, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &app.adapter.device.access_point { + // Start AP + ap.ap_start + .store(false, std::sync::atomic::Ordering::Relaxed); } - - KeyCode::Char('j') => { - if app.selected_mode == Mode::Station { - app.selected_mode = Mode::Ap; + app.focused_block = FocusedBlock::AccessPoint; + } + (_, KeyCode::Tab, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + match ap.focused_section { + APFocusedSection::SSID => ap.focused_section = APFocusedSection::PSK, + APFocusedSection::PSK => ap.focused_section = APFocusedSection::SSID, } } - - KeyCode::Char('k') => { - if app.selected_mode == Mode::Ap { - app.selected_mode = Mode::Station; - } + } + (_, _, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + match ap.focused_section { + APFocusedSection::SSID => ap + .ssid + .handle_event(&crossterm::event::Event::Key(key_event)), + APFocusedSection::PSK => ap + .psk + .handle_event(&crossterm::event::Event::Key(key_event)), + }; } - - KeyCode::Enter => { - sender.send(Event::Reset(app.selected_mode.clone()))?; + } + (_, KeyCode::Char('q'), _) => app.quit(), + (_, KeyCode::Char('c' | 'C'), _) => { + if key_event.modifiers == KeyModifiers::CONTROL { + app.quit() } - - _ => {} } - return Ok(()); - } - - match app.focused_block { - FocusedBlock::AuthKey => match key_event.code { - KeyCode::Enter => { - app.send_passkey().await?; + (_, KeyCode::Char('?'), _) => app.focused_block = FocusedBlock::Help, + (_, KeyCode::Char(c), _) + if c == config.switch && key_event.modifiers == KeyModifiers::CONTROL => + { + app.reset_mode = true; + } + (_, KeyCode::Esc, _) => { + if app.focused_block == FocusedBlock::Help + || app.focused_block == FocusedBlock::AdapterInfos + { app.focused_block = FocusedBlock::Device; } - - KeyCode::Esc => { - app.cancel_auth().await?; - app.focused_block = FocusedBlock::Device; + } + (Mode::Station, KeyCode::Char(c), _) if c == config.station.start_scanning => { + app.adapter + .device + .station + .as_mut() + .unwrap() + .scan(sender) + .await?; + } + (Mode::Ap, KeyCode::Char(c), _) if c == config.station.start_scanning => { + app.adapter + .device + .access_point + .as_mut() + .unwrap() + .scan(sender) + .await?; + } + (_, KeyCode::Char(c), _) if c == config.station.start_scanning => {} + (Mode::Station, KeyCode::Tab, _) => match app.focused_block { + FocusedBlock::Device => { + app.focused_block = FocusedBlock::Station; } - - KeyCode::Tab => { - app.show_password = !app.show_password; + FocusedBlock::Station => { + app.focused_block = FocusedBlock::KnownNetworks; } - - _ => { - app.passkey_input - .handle_event(&crossterm::event::Event::Key(key_event)); + FocusedBlock::KnownNetworks => { + app.focused_block = FocusedBlock::NewNetworks; + } + FocusedBlock::NewNetworks => { + app.focused_block = FocusedBlock::Device; } + _ => {} }, - FocusedBlock::AccessPointInput => match key_event.code { - KeyCode::Enter => { - if let Some(ap) = &mut app.adapter.device.access_point { - ap.start(sender.clone()).await?; - sender.send(Event::Reset(app.current_mode.clone()))?; + (Mode::Ap, KeyCode::Tab, FocusedBlock::Device) => { + app.focused_block = FocusedBlock::AccessPoint + } + (Mode::Ap, KeyCode::Tab, FocusedBlock::AccessPoint) => { + if let Some(ap) = app.adapter.device.access_point.as_ref() { + if ap.connected_devices.is_empty() { app.focused_block = FocusedBlock::Device; + } else { + app.focused_block = FocusedBlock::AccessPointConnectedDevices; } } - - KeyCode::Esc => { - if let Some(ap) = &app.adapter.device.access_point { - // Start AP - ap.ap_start - .store(false, std::sync::atomic::Ordering::Relaxed); - } - app.focused_block = FocusedBlock::AccessPoint; + } + (Mode::Ap, KeyCode::Tab, FocusedBlock::AccessPointConnectedDevices) => { + app.focused_block = FocusedBlock::Device; + } + (_, KeyCode::Tab, _) => {} + (Mode::Station, KeyCode::BackTab, _) => match app.focused_block { + FocusedBlock::Device => { + app.focused_block = FocusedBlock::NewNetworks; } - KeyCode::Tab => { - if let Some(ap) = &mut app.adapter.device.access_point { - match ap.focused_section { - APFocusedSection::SSID => ap.focused_section = APFocusedSection::PSK, - APFocusedSection::PSK => ap.focused_section = APFocusedSection::SSID, - } - } + FocusedBlock::Station => { + app.focused_block = FocusedBlock::Device; } - _ => { - if let Some(ap) = &mut app.adapter.device.access_point { - match ap.focused_section { - APFocusedSection::SSID => ap - .ssid - .handle_event(&crossterm::event::Event::Key(key_event)), - APFocusedSection::PSK => ap - .psk - .handle_event(&crossterm::event::Event::Key(key_event)), - }; - } + FocusedBlock::KnownNetworks => { + app.focused_block = FocusedBlock::Station; + } + FocusedBlock::NewNetworks => { + app.focused_block = FocusedBlock::KnownNetworks; } + _ => {} }, - _ => { - match key_event.code { - KeyCode::Char('q') => { - app.quit(); + (Mode::Ap, KeyCode::BackTab, FocusedBlock::Device) => { + if let Some(ap) = app.adapter.device.access_point.as_ref() { + if ap.connected_devices.is_empty() { + app.focused_block = FocusedBlock::AccessPoint; + } else { + app.focused_block = FocusedBlock::AccessPointConnectedDevices; } - KeyCode::Char('c' | 'C') => { - if key_event.modifiers == KeyModifiers::CONTROL { - app.quit(); + } + } + (Mode::Ap, KeyCode::BackTab, FocusedBlock::AccessPoint) => { + app.focused_block = FocusedBlock::Device; + } + (Mode::Ap, KeyCode::BackTab, FocusedBlock::AccessPointConnectedDevices) => { + app.focused_block = FocusedBlock::AccessPoint; + } + (_, KeyCode::BackTab, _) => {} + (_, KeyCode::Char(c), FocusedBlock::Device) if c == config.device.infos => { + app.focused_block = FocusedBlock::AdapterInfos; + } + (_, KeyCode::Char(c), FocusedBlock::Device) if c == config.device.toggle_power => { + if app.adapter.device.is_powered { + match app.adapter.device.power_off().await { + Ok(()) => { + sender.send(Event::Reset(app.current_mode.clone()))?; + Notification::send( + "Device Powered Off".to_string(), + crate::notification::NotificationLevel::Info, + &sender.clone(), + )?; + } + Err(e) => { + Notification::send( + e.to_string(), + crate::notification::NotificationLevel::Error, + &sender.clone(), + )?; } } - - // Show help - KeyCode::Char('?') => { - app.focused_block = FocusedBlock::Help; - } - - // Switch mode - KeyCode::Char(c) - if c == config.switch && key_event.modifiers == KeyModifiers::CONTROL => - { - app.reset_mode = true; - } - - // Discard help popup - KeyCode::Esc => { - if app.focused_block == FocusedBlock::Help - || app.focused_block == FocusedBlock::AdapterInfos - { - app.focused_block = FocusedBlock::Device; + } else { + match app.adapter.device.power_on().await { + Ok(()) => { + sender.send(Event::Reset(app.current_mode.clone()))?; + Notification::send( + "Device Powered On".to_string(), + crate::notification::NotificationLevel::Info, + &sender.clone(), + )?; + } + Err(e) => { + Notification::send( + e.to_string(), + crate::notification::NotificationLevel::Error, + &sender.clone(), + )?; } } - - // Start Scan - KeyCode::Char(c) if c == config.station.start_scanning => { - match app.adapter.device.mode { - Mode::Station => { - app.adapter - .device - .station - .as_mut() - .unwrap() - .scan(sender) - .await?; - } - Mode::Ap => { - app.adapter - .device - .access_point - .as_mut() - .unwrap() - .scan(sender) - .await?; - } - _ => {} + } + } + (_, _, FocusedBlock::Device) => {} + (Mode::Station, KeyCode::Char(c), _) + if c == config.station.known_network.remove + && app.focused_block == FocusedBlock::KnownNetworks => + { + if let Some(net_index) = app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks_state + .selected() + { + let (net, _signal) = + &app.adapter.device.station.as_ref().unwrap().known_networks[net_index]; + let known_net = net.known_network.as_ref().unwrap(); + known_net.forget(sender.clone()).await?; + } + } + // Toggle autoconnect + (Mode::Station, KeyCode::Char(c), _) + if c == config.station.known_network.toggle_autoconnect + && app.focused_block == FocusedBlock::KnownNetworks => + { + if let Some(net_index) = app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks_state + .selected() + { + let (net, _signal) = + &app.adapter.device.station.as_ref().unwrap().known_networks[net_index]; + let known_net = net.known_network.as_ref().unwrap(); + known_net.toggle_autoconnect(sender.clone()).await?; + } + } + // Connect/Disconnect + (Mode::Station, KeyCode::Char(c), FocusedBlock::NewNetworks) + if c == config.station.toggle_connect => + { + if let Some(net_index) = app + .adapter + .device + .station + .as_ref() + .unwrap() + .new_networks_state + .selected() + { + let (net, _) = + app.adapter.device.station.as_ref().unwrap().new_networks[net_index].clone(); + let mode = app.current_mode.clone(); + tokio::spawn(async move { + net.connect(sender.clone()).await.unwrap(); + sender.clone().send(Event::Reset(mode)).unwrap(); + }); + } + } + (Mode::Station, KeyCode::Char(c), FocusedBlock::KnownNetworks) + if c == config.station.toggle_connect => + { + if let Some(connected_net) = &app + .adapter + .device + .station + .as_ref() + .unwrap() + .connected_network + { + let Some(selected_net_index) = app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks_state + .selected() + else { + return Ok(()); + }; + let (selected_net, _signal) = + &app.adapter.device.station.as_ref().unwrap().known_networks + [selected_net_index]; + if selected_net.name == connected_net.name { + app.adapter + .device + .station + .as_ref() + .unwrap() + .disconnect(sender.clone()) + .await?; + } else { + let net_index = app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks + .iter() + .position(|(n, _s)| n.name == selected_net.name); + if let Some(index) = net_index { + let (net, _) = app.adapter.device.station.as_ref().unwrap().known_networks + [index] + .clone(); + app.adapter + .device + .station + .as_ref() + .unwrap() + .disconnect(sender.clone()) + .await?; + tokio::spawn(async move { + net.connect(sender.clone()).await.unwrap(); + }); } } - - KeyCode::Tab => match app.adapter.device.mode { - Mode::Station => match app.focused_block { - FocusedBlock::Device => { - app.focused_block = FocusedBlock::Station; - } - FocusedBlock::Station => { - app.focused_block = FocusedBlock::KnownNetworks; - } - FocusedBlock::KnownNetworks => { - app.focused_block = FocusedBlock::NewNetworks; - } - FocusedBlock::NewNetworks => { - app.focused_block = FocusedBlock::Device; - } - _ => {} - }, - Mode::Ap => match app.focused_block { - FocusedBlock::Device => { - app.focused_block = FocusedBlock::AccessPoint; - } - FocusedBlock::AccessPoint => { - if let Some(ap) = app.adapter.device.access_point.as_ref() { - if ap.connected_devices.is_empty() { - app.focused_block = FocusedBlock::Device; - } else { - app.focused_block = FocusedBlock::AccessPointConnectedDevices; - } - } - } - FocusedBlock::AccessPointConnectedDevices => { - app.focused_block = FocusedBlock::Device; - } - FocusedBlock::AccessPointInput => { - if let Some(ap) = &mut app.adapter.device.access_point { - match ap.focused_section { - APFocusedSection::SSID => { - ap.focused_section = APFocusedSection::PSK; - } - APFocusedSection::PSK => { - ap.focused_section = APFocusedSection::SSID; - } - } - } - } - _ => {} - }, - _ => {} - }, - - KeyCode::BackTab => match app.adapter.device.mode { - Mode::Station => match app.focused_block { - FocusedBlock::Device => { - app.focused_block = FocusedBlock::NewNetworks; - } - FocusedBlock::Station => { - app.focused_block = FocusedBlock::Device; - } - FocusedBlock::KnownNetworks => { - app.focused_block = FocusedBlock::Station; - } - FocusedBlock::NewNetworks => { - app.focused_block = FocusedBlock::KnownNetworks; - } - _ => {} - }, - Mode::Ap => match app.focused_block { - FocusedBlock::Device => { - if let Some(ap) = app.adapter.device.access_point.as_ref() { - if ap.connected_devices.is_empty() { - app.focused_block = FocusedBlock::AccessPoint; - } else { - app.focused_block = FocusedBlock::AccessPointConnectedDevices; - } - } - } - FocusedBlock::AccessPoint => { - app.focused_block = FocusedBlock::Device; - } - FocusedBlock::AccessPointConnectedDevices => { - app.focused_block = FocusedBlock::AccessPoint; - } - FocusedBlock::AccessPointInput => { - if let Some(ap) = &mut app.adapter.device.access_point { - match ap.focused_section { - APFocusedSection::SSID => { - ap.focused_section = APFocusedSection::PSK; - } - APFocusedSection::PSK => { - ap.focused_section = APFocusedSection::SSID; - } - } - } + } else { + let Some(selected_net_index) = app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks_state + .selected() + else { + return Ok(()); + }; + let (selected_net, _signal) = + &app.adapter.device.station.as_ref().unwrap().known_networks + [selected_net_index]; + let net_index = app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks + .iter() + .position(|(n, _s)| n.name == selected_net.name); + if let Some(index) = net_index { + let (net, _) = + app.adapter.device.station.as_ref().unwrap().known_networks[index].clone(); + tokio::spawn(async move { + net.connect(sender.clone()).await.unwrap(); + }); + } + } + } + // scroll down + (Mode::Station, KeyCode::Char('j') | KeyCode::Down, FocusedBlock::KnownNetworks) => { + if !app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks + .is_empty() + { + let i = match app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks_state + .selected() + { + Some(i) => { + if i < app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks + .len() + - 1 + { + i + 1 + } else { + i } - _ => {} - }, - _ => {} - }, - - _ => { - match app.focused_block { - FocusedBlock::Device => match key_event.code { - KeyCode::Char(c) if c == config.device.infos => { - app.focused_block = FocusedBlock::AdapterInfos; - } - - KeyCode::Char(c) if c == config.device.toggle_power => { - if app.adapter.device.is_powered { - match app.adapter.device.power_off().await { - Ok(()) => { - sender.send(Event::Reset(app.current_mode.clone()))?; - Notification::send( - "Device Powered Off".to_string(), - crate::notification::NotificationLevel::Info, - &sender.clone(), - )?; - } - Err(e) => { - Notification::send( - e.to_string(), - crate::notification::NotificationLevel::Error, - &sender.clone(), - )?; - } - } - } else { - match app.adapter.device.power_on().await { - Ok(()) => { - sender.send(Event::Reset(app.current_mode.clone()))?; - Notification::send( - "Device Powered On".to_string(), - crate::notification::NotificationLevel::Info, - &sender.clone(), - )?; - } - Err(e) => { - Notification::send( - e.to_string(), - crate::notification::NotificationLevel::Error, - &sender.clone(), - )?; - } - } - } - } - - _ => {} - }, - - _ => { - match app.adapter.device.mode { - Mode::Station => { - match key_event.code { - // Remove a known network - KeyCode::Char(c) - if c == config.station.known_network.remove - && app.focused_block - == FocusedBlock::KnownNetworks => - { - if let Some(net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - let (net, _signal) = &app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks[net_index]; - - let known_net = net.known_network.as_ref().unwrap(); - known_net.forget(sender.clone()).await?; - } - } - - // Toggle autoconnect - KeyCode::Char(c) - if c == config - .station - .known_network - .toggle_autoconnect - && app.focused_block - == FocusedBlock::KnownNetworks => - { - if let Some(net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - let (net, _signal) = &app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks[net_index]; - - let known_net = net.known_network.as_ref().unwrap(); - known_net - .toggle_autoconnect(sender.clone()) - .await?; - } - } - - // Connect/Disconnect - KeyCode::Char(c) if c == config.station.toggle_connect => { - match app.focused_block { - FocusedBlock::NewNetworks => { - if let Some(net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks_state - .selected() - { - let (net, _) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks[net_index] - .clone(); - - let mode = app.current_mode.clone(); - tokio::spawn(async move { - net.connect(sender.clone()) - .await - .unwrap(); - - sender - .clone() - .send(Event::Reset(mode)) - .unwrap(); - }); - } - } - FocusedBlock::KnownNetworks => { - match &app - .adapter - .device - .station - .as_ref() - .unwrap() - .connected_network - { - Some(connected_net) => { - if let Some(selected_net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - let (selected_net, _signal) = &app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - [selected_net_index]; - - if selected_net.name - == connected_net.name - { - app.adapter - .device - .station - .as_ref() - .unwrap() - .disconnect(sender.clone()) - .await?; - } else { - let net_index = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .iter() - .position(|(n, _s)| { - n.name - == selected_net.name - }); - - if let Some(index) = net_index { - let (net, _) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks[index] - .clone(); - app.adapter - .device - .station - .as_ref() - .unwrap() - .disconnect( - sender.clone(), - ) - .await?; - tokio::spawn(async move { - net.connect( - sender.clone(), - ) - .await - .unwrap(); - }); - } - } - } - } - None => { - if let Some(selected_net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - let (selected_net, _signal) = &app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - [selected_net_index]; - let net_index = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .iter() - .position(|(n, _s)| { - n.name == selected_net.name - }); - - if let Some(index) = net_index { - let (net, _) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks[index] - .clone(); - tokio::spawn(async move { - net.connect(sender.clone()) - .await - .unwrap(); - }); - } - } - } - } - } - _ => {} - } - } - - // Scroll down - KeyCode::Char('j') | KeyCode::Down => { - match app.focused_block { - FocusedBlock::KnownNetworks => { - if !app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .is_empty() - { - let i = match app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - Some(i) => { - if i < app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .len() - - 1 - { - i + 1 - } else { - i - } - } - None => 0, - }; - - app.adapter - .device - .station - .as_mut() - .unwrap() - .known_networks_state - .select(Some(i)); - } - } - FocusedBlock::NewNetworks => { - if !app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks - .is_empty() - { - let i = match app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks_state - .selected() - { - Some(i) => { - if i < app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks - .len() - - 1 - { - i + 1 - } else { - i - } - } - None => 0, - }; - - app.adapter - .device - .station - .as_mut() - .unwrap() - .new_networks_state - .select(Some(i)); - } - } - - FocusedBlock::Help => { - app.help.scroll_down(); - } - _ => {} - } - } - - KeyCode::Char('k') | KeyCode::Up => match app.focused_block - { - FocusedBlock::KnownNetworks => { - if !app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .is_empty() - { - let i = match app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - Some(i) => i.saturating_sub(1), - None => 0, - }; - - app.adapter - .device - .station - .as_mut() - .unwrap() - .known_networks_state - .select(Some(i)); - } - } - FocusedBlock::NewNetworks => { - if !app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks - .is_empty() - { - let i = match app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks_state - .selected() - { - Some(i) => i.saturating_sub(1), - None => 0, - }; - - app.adapter - .device - .station - .as_mut() - .unwrap() - .new_networks_state - .select(Some(i)); - } - } - FocusedBlock::Help => { - app.help.scroll_up(); - } - _ => {} - }, - _ => {} - } - } - Mode::Ap => match key_event.code { - KeyCode::Char(c) if c == config.ap.start => { - if let Some(ap) = &app.adapter.device.access_point { - // Start AP - ap.ap_start - .store(true, std::sync::atomic::Ordering::Relaxed); - } - } - KeyCode::Char(c) if c == config.ap.stop => { - if let Some(ap) = &mut app.adapter.device.access_point { - ap.stop(sender).await?; - ap.connected_devices = Vec::new(); - } - } - - // Scroll down - KeyCode::Char('j') | KeyCode::Down => { - if app.focused_block == FocusedBlock::Help { - app.help.scroll_down(); - } - } - - KeyCode::Char('k') | KeyCode::Up => { - if app.focused_block == FocusedBlock::Help { - app.help.scroll_up(); - } - } - - _ => {} - }, - _ => {} - } + } + None => 0, + }; + app.adapter + .device + .station + .as_mut() + .unwrap() + .known_networks_state + .select(Some(i)); + } + } + (Mode::Station, KeyCode::Char('j') | KeyCode::Down, FocusedBlock::NewNetworks) => { + if !app + .adapter + .device + .station + .as_ref() + .unwrap() + .new_networks + .is_empty() + { + let i = match app + .adapter + .device + .station + .as_ref() + .unwrap() + .new_networks_state + .selected() + { + Some(i) => { + if i < app + .adapter + .device + .station + .as_ref() + .unwrap() + .new_networks + .len() + - 1 + { + i + 1 + } else { + i } } - } + None => 0, + }; + app.adapter + .device + .station + .as_mut() + .unwrap() + .new_networks_state + .select(Some(i)); + } + } + (Mode::Station, KeyCode::Char('k') | KeyCode::Up, FocusedBlock::KnownNetworks) => { + if !app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks + .is_empty() + { + let i = match app + .adapter + .device + .station + .as_ref() + .unwrap() + .known_networks_state + .selected() + { + Some(i) => i.saturating_sub(1), + None => 0, + }; + app.adapter + .device + .station + .as_mut() + .unwrap() + .known_networks_state + .select(Some(i)); + } + } + (Mode::Station, KeyCode::Char('k') | KeyCode::Up, FocusedBlock::NewNetworks) => { + if !app + .adapter + .device + .station + .as_ref() + .unwrap() + .new_networks + .is_empty() + { + let i = match app + .adapter + .device + .station + .as_ref() + .unwrap() + .new_networks_state + .selected() + { + Some(i) => i.saturating_sub(1), + None => 0, + }; + app.adapter + .device + .station + .as_mut() + .unwrap() + .new_networks_state + .select(Some(i)); + } + } + // Scroll down + (Mode::Station, KeyCode::Char('j') | KeyCode::Down, FocusedBlock::Help) => { + app.help.scroll_down(); + } + // Scroll up + (Mode::Station, KeyCode::Char('k') | KeyCode::Up, FocusedBlock::Help) => { + app.help.scroll_up(); + } + (Mode::Ap, KeyCode::Char(c), _) if c == config.ap.start => { + if let Some(ap) = &app.adapter.device.access_point { + // Start AP + ap.ap_start + .store(true, std::sync::atomic::Ordering::Relaxed); } } + (Mode::Ap, KeyCode::Char(c), _) if c == config.ap.stop => { + if let Some(ap) = &mut app.adapter.device.access_point { + ap.stop(sender).await?; + ap.connected_devices = Vec::new(); + } + } + // Scroll down + (Mode::Ap, KeyCode::Char('j') | KeyCode::Down, FocusedBlock::Help) => { + app.help.scroll_down(); + } + // Scroll up + (Mode::Ap, KeyCode::Char('k') | KeyCode::Up, FocusedBlock::Help) => { + app.help.scroll_up(); + } + _ => {} } Ok(()) } From 25d1c2925df5616f9196d8fcc2c8a5599d1bf129 Mon Sep 17 00:00:00 2001 From: Gabor Feher Date: Tue, 5 Aug 2025 23:22:22 +0200 Subject: [PATCH 2/2] chore: input handling based on mode --- src/handler.rs | 550 +---------------------------------------- src/handler/ap.rs | 185 ++++++++++++++ src/handler/station.rs | 310 +++++++++++++++++++++++ 3 files changed, 504 insertions(+), 541 deletions(-) create mode 100644 src/handler/ap.rs create mode 100644 src/handler/station.rs diff --git a/src/handler.rs b/src/handler.rs index cebc0c0..56eb8d9 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,15 +1,15 @@ +mod ap; +mod station; + use std::sync::Arc; -use crate::access_point::APFocusedSection; -use crate::app::{App, AppResult, FocusedBlock}; +use crate::app::{App, AppResult}; use crate::config::Config; use crate::event::Event; -use crate::notification::Notification; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; use iwdrs::modes::Mode; use tokio::sync::mpsc::UnboundedSender; -use tui_input::backend::crossterm::EventHandler; async fn handle_reset_mode_key_event( key_event: KeyEvent, @@ -50,542 +50,10 @@ pub async fn handle_key_events( if app.reset_mode { return handle_reset_mode_key_event(key_event, app, sender).await; } - match ( - app.adapter.device.mode.clone(), - key_event.code, - app.focused_block, - ) { - (_, KeyCode::Enter, FocusedBlock::AuthKey) => { - app.send_passkey().await?; - app.focused_block = FocusedBlock::Device; - } - (_, KeyCode::Esc, FocusedBlock::AuthKey) => { - app.cancel_auth().await?; - app.focused_block = FocusedBlock::Device; - } - (_, KeyCode::Tab, FocusedBlock::AuthKey) => { - app.show_password = !app.show_password; - } - (_, _, FocusedBlock::AuthKey) => { - app.passkey_input - .handle_event(&crossterm::event::Event::Key(key_event)); - } - (_, KeyCode::Enter, FocusedBlock::AccessPointInput) => { - if let Some(ap) = &mut app.adapter.device.access_point { - ap.start(sender.clone()).await?; - sender.send(Event::Reset(app.current_mode.clone()))?; - app.focused_block = FocusedBlock::Device; - } - } - (_, KeyCode::Esc, FocusedBlock::AccessPointInput) => { - if let Some(ap) = &app.adapter.device.access_point { - // Start AP - ap.ap_start - .store(false, std::sync::atomic::Ordering::Relaxed); - } - app.focused_block = FocusedBlock::AccessPoint; - } - (_, KeyCode::Tab, FocusedBlock::AccessPointInput) => { - if let Some(ap) = &mut app.adapter.device.access_point { - match ap.focused_section { - APFocusedSection::SSID => ap.focused_section = APFocusedSection::PSK, - APFocusedSection::PSK => ap.focused_section = APFocusedSection::SSID, - } - } - } - (_, _, FocusedBlock::AccessPointInput) => { - if let Some(ap) = &mut app.adapter.device.access_point { - match ap.focused_section { - APFocusedSection::SSID => ap - .ssid - .handle_event(&crossterm::event::Event::Key(key_event)), - APFocusedSection::PSK => ap - .psk - .handle_event(&crossterm::event::Event::Key(key_event)), - }; - } - } - (_, KeyCode::Char('q'), _) => app.quit(), - (_, KeyCode::Char('c' | 'C'), _) => { - if key_event.modifiers == KeyModifiers::CONTROL { - app.quit() - } - } - (_, KeyCode::Char('?'), _) => app.focused_block = FocusedBlock::Help, - (_, KeyCode::Char(c), _) - if c == config.switch && key_event.modifiers == KeyModifiers::CONTROL => - { - app.reset_mode = true; - } - (_, KeyCode::Esc, _) => { - if app.focused_block == FocusedBlock::Help - || app.focused_block == FocusedBlock::AdapterInfos - { - app.focused_block = FocusedBlock::Device; - } - } - (Mode::Station, KeyCode::Char(c), _) if c == config.station.start_scanning => { - app.adapter - .device - .station - .as_mut() - .unwrap() - .scan(sender) - .await?; - } - (Mode::Ap, KeyCode::Char(c), _) if c == config.station.start_scanning => { - app.adapter - .device - .access_point - .as_mut() - .unwrap() - .scan(sender) - .await?; - } - (_, KeyCode::Char(c), _) if c == config.station.start_scanning => {} - (Mode::Station, KeyCode::Tab, _) => match app.focused_block { - FocusedBlock::Device => { - app.focused_block = FocusedBlock::Station; - } - FocusedBlock::Station => { - app.focused_block = FocusedBlock::KnownNetworks; - } - FocusedBlock::KnownNetworks => { - app.focused_block = FocusedBlock::NewNetworks; - } - FocusedBlock::NewNetworks => { - app.focused_block = FocusedBlock::Device; - } - _ => {} - }, - (Mode::Ap, KeyCode::Tab, FocusedBlock::Device) => { - app.focused_block = FocusedBlock::AccessPoint - } - (Mode::Ap, KeyCode::Tab, FocusedBlock::AccessPoint) => { - if let Some(ap) = app.adapter.device.access_point.as_ref() { - if ap.connected_devices.is_empty() { - app.focused_block = FocusedBlock::Device; - } else { - app.focused_block = FocusedBlock::AccessPointConnectedDevices; - } - } - } - (Mode::Ap, KeyCode::Tab, FocusedBlock::AccessPointConnectedDevices) => { - app.focused_block = FocusedBlock::Device; - } - (_, KeyCode::Tab, _) => {} - (Mode::Station, KeyCode::BackTab, _) => match app.focused_block { - FocusedBlock::Device => { - app.focused_block = FocusedBlock::NewNetworks; - } - FocusedBlock::Station => { - app.focused_block = FocusedBlock::Device; - } - FocusedBlock::KnownNetworks => { - app.focused_block = FocusedBlock::Station; - } - FocusedBlock::NewNetworks => { - app.focused_block = FocusedBlock::KnownNetworks; - } - _ => {} - }, - (Mode::Ap, KeyCode::BackTab, FocusedBlock::Device) => { - if let Some(ap) = app.adapter.device.access_point.as_ref() { - if ap.connected_devices.is_empty() { - app.focused_block = FocusedBlock::AccessPoint; - } else { - app.focused_block = FocusedBlock::AccessPointConnectedDevices; - } - } - } - (Mode::Ap, KeyCode::BackTab, FocusedBlock::AccessPoint) => { - app.focused_block = FocusedBlock::Device; - } - (Mode::Ap, KeyCode::BackTab, FocusedBlock::AccessPointConnectedDevices) => { - app.focused_block = FocusedBlock::AccessPoint; - } - (_, KeyCode::BackTab, _) => {} - (_, KeyCode::Char(c), FocusedBlock::Device) if c == config.device.infos => { - app.focused_block = FocusedBlock::AdapterInfos; - } - (_, KeyCode::Char(c), FocusedBlock::Device) if c == config.device.toggle_power => { - if app.adapter.device.is_powered { - match app.adapter.device.power_off().await { - Ok(()) => { - sender.send(Event::Reset(app.current_mode.clone()))?; - Notification::send( - "Device Powered Off".to_string(), - crate::notification::NotificationLevel::Info, - &sender.clone(), - )?; - } - Err(e) => { - Notification::send( - e.to_string(), - crate::notification::NotificationLevel::Error, - &sender.clone(), - )?; - } - } - } else { - match app.adapter.device.power_on().await { - Ok(()) => { - sender.send(Event::Reset(app.current_mode.clone()))?; - Notification::send( - "Device Powered On".to_string(), - crate::notification::NotificationLevel::Info, - &sender.clone(), - )?; - } - Err(e) => { - Notification::send( - e.to_string(), - crate::notification::NotificationLevel::Error, - &sender.clone(), - )?; - } - } - } - } - (_, _, FocusedBlock::Device) => {} - (Mode::Station, KeyCode::Char(c), _) - if c == config.station.known_network.remove - && app.focused_block == FocusedBlock::KnownNetworks => - { - if let Some(net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - let (net, _signal) = - &app.adapter.device.station.as_ref().unwrap().known_networks[net_index]; - let known_net = net.known_network.as_ref().unwrap(); - known_net.forget(sender.clone()).await?; - } - } - // Toggle autoconnect - (Mode::Station, KeyCode::Char(c), _) - if c == config.station.known_network.toggle_autoconnect - && app.focused_block == FocusedBlock::KnownNetworks => - { - if let Some(net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - let (net, _signal) = - &app.adapter.device.station.as_ref().unwrap().known_networks[net_index]; - let known_net = net.known_network.as_ref().unwrap(); - known_net.toggle_autoconnect(sender.clone()).await?; - } - } - // Connect/Disconnect - (Mode::Station, KeyCode::Char(c), FocusedBlock::NewNetworks) - if c == config.station.toggle_connect => - { - if let Some(net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks_state - .selected() - { - let (net, _) = - app.adapter.device.station.as_ref().unwrap().new_networks[net_index].clone(); - let mode = app.current_mode.clone(); - tokio::spawn(async move { - net.connect(sender.clone()).await.unwrap(); - sender.clone().send(Event::Reset(mode)).unwrap(); - }); - } - } - (Mode::Station, KeyCode::Char(c), FocusedBlock::KnownNetworks) - if c == config.station.toggle_connect => - { - if let Some(connected_net) = &app - .adapter - .device - .station - .as_ref() - .unwrap() - .connected_network - { - let Some(selected_net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - else { - return Ok(()); - }; - let (selected_net, _signal) = - &app.adapter.device.station.as_ref().unwrap().known_networks - [selected_net_index]; - if selected_net.name == connected_net.name { - app.adapter - .device - .station - .as_ref() - .unwrap() - .disconnect(sender.clone()) - .await?; - } else { - let net_index = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .iter() - .position(|(n, _s)| n.name == selected_net.name); - if let Some(index) = net_index { - let (net, _) = app.adapter.device.station.as_ref().unwrap().known_networks - [index] - .clone(); - app.adapter - .device - .station - .as_ref() - .unwrap() - .disconnect(sender.clone()) - .await?; - tokio::spawn(async move { - net.connect(sender.clone()).await.unwrap(); - }); - } - } - } else { - let Some(selected_net_index) = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - else { - return Ok(()); - }; - let (selected_net, _signal) = - &app.adapter.device.station.as_ref().unwrap().known_networks - [selected_net_index]; - let net_index = app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .iter() - .position(|(n, _s)| n.name == selected_net.name); - if let Some(index) = net_index { - let (net, _) = - app.adapter.device.station.as_ref().unwrap().known_networks[index].clone(); - tokio::spawn(async move { - net.connect(sender.clone()).await.unwrap(); - }); - } - } - } - // scroll down - (Mode::Station, KeyCode::Char('j') | KeyCode::Down, FocusedBlock::KnownNetworks) => { - if !app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .is_empty() - { - let i = match app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - Some(i) => { - if i < app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .len() - - 1 - { - i + 1 - } else { - i - } - } - None => 0, - }; - app.adapter - .device - .station - .as_mut() - .unwrap() - .known_networks_state - .select(Some(i)); - } - } - (Mode::Station, KeyCode::Char('j') | KeyCode::Down, FocusedBlock::NewNetworks) => { - if !app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks - .is_empty() - { - let i = match app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks_state - .selected() - { - Some(i) => { - if i < app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks - .len() - - 1 - { - i + 1 - } else { - i - } - } - None => 0, - }; - app.adapter - .device - .station - .as_mut() - .unwrap() - .new_networks_state - .select(Some(i)); - } - } - (Mode::Station, KeyCode::Char('k') | KeyCode::Up, FocusedBlock::KnownNetworks) => { - if !app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks - .is_empty() - { - let i = match app - .adapter - .device - .station - .as_ref() - .unwrap() - .known_networks_state - .selected() - { - Some(i) => i.saturating_sub(1), - None => 0, - }; - app.adapter - .device - .station - .as_mut() - .unwrap() - .known_networks_state - .select(Some(i)); - } - } - (Mode::Station, KeyCode::Char('k') | KeyCode::Up, FocusedBlock::NewNetworks) => { - if !app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks - .is_empty() - { - let i = match app - .adapter - .device - .station - .as_ref() - .unwrap() - .new_networks_state - .selected() - { - Some(i) => i.saturating_sub(1), - None => 0, - }; - app.adapter - .device - .station - .as_mut() - .unwrap() - .new_networks_state - .select(Some(i)); - } - } - // Scroll down - (Mode::Station, KeyCode::Char('j') | KeyCode::Down, FocusedBlock::Help) => { - app.help.scroll_down(); - } - // Scroll up - (Mode::Station, KeyCode::Char('k') | KeyCode::Up, FocusedBlock::Help) => { - app.help.scroll_up(); - } - (Mode::Ap, KeyCode::Char(c), _) if c == config.ap.start => { - if let Some(ap) = &app.adapter.device.access_point { - // Start AP - ap.ap_start - .store(true, std::sync::atomic::Ordering::Relaxed); - } - } - (Mode::Ap, KeyCode::Char(c), _) if c == config.ap.stop => { - if let Some(ap) = &mut app.adapter.device.access_point { - ap.stop(sender).await?; - ap.connected_devices = Vec::new(); - } - } - // Scroll down - (Mode::Ap, KeyCode::Char('j') | KeyCode::Down, FocusedBlock::Help) => { - app.help.scroll_down(); - } - // Scroll up - (Mode::Ap, KeyCode::Char('k') | KeyCode::Up, FocusedBlock::Help) => { - app.help.scroll_up(); - } - _ => {} + + if let Mode::Station = app.adapter.device.mode { + station::handle_station_key_events(key_event, app, sender.clone(), config.clone()).await + } else { + ap::handle_ap_key_events(key_event, app, sender.clone(), config.clone()).await } - Ok(()) } diff --git a/src/handler/ap.rs b/src/handler/ap.rs new file mode 100644 index 0000000..3a52942 --- /dev/null +++ b/src/handler/ap.rs @@ -0,0 +1,185 @@ +use std::sync::Arc; + +use crate::access_point::APFocusedSection; +use crate::app::{App, AppResult, FocusedBlock}; +use crate::config::Config; +use crate::event::Event; +use crate::notification::Notification; + +use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use tokio::sync::mpsc::UnboundedSender; +use tui_input::backend::crossterm::EventHandler; + +pub async fn handle_ap_key_events( + key_event: KeyEvent, + app: &mut App, + sender: UnboundedSender, + config: Arc, +) -> AppResult<()> { + let access_point = &mut app.adapter.device.access_point; + match (key_event.code, app.focused_block) { + (KeyCode::Enter, FocusedBlock::AuthKey) => { + app.send_passkey().await?; + app.focused_block = FocusedBlock::Device; + } + (KeyCode::Esc, FocusedBlock::AuthKey) => { + app.cancel_auth().await?; + app.focused_block = FocusedBlock::Device; + } + (KeyCode::Tab, FocusedBlock::AuthKey) => { + app.show_password = !app.show_password; + } + (_, FocusedBlock::AuthKey) => { + app.passkey_input + .handle_event(&crossterm::event::Event::Key(key_event)); + } + (KeyCode::Enter, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + ap.start(sender.clone()).await?; + sender.send(Event::Reset(app.current_mode.clone()))?; + app.focused_block = FocusedBlock::Device; + } + } + (KeyCode::Esc, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &app.adapter.device.access_point { + // Start AP + ap.ap_start + .store(false, std::sync::atomic::Ordering::Relaxed); + } + app.focused_block = FocusedBlock::AccessPoint; + } + (KeyCode::Tab, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + match ap.focused_section { + APFocusedSection::SSID => ap.focused_section = APFocusedSection::PSK, + APFocusedSection::PSK => ap.focused_section = APFocusedSection::SSID, + } + } + } + (_, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + match ap.focused_section { + APFocusedSection::SSID => ap + .ssid + .handle_event(&crossterm::event::Event::Key(key_event)), + APFocusedSection::PSK => ap + .psk + .handle_event(&crossterm::event::Event::Key(key_event)), + }; + } + } + (KeyCode::Char('q'), _) => app.quit(), + (KeyCode::Char('c' | 'C'), _) => { + if key_event.modifiers == KeyModifiers::CONTROL { + app.quit() + } + } + (KeyCode::Char('?'), _) => app.focused_block = FocusedBlock::Help, + (KeyCode::Char(c), _) + if c == config.switch && key_event.modifiers == KeyModifiers::CONTROL => + { + app.reset_mode = true; + } + (KeyCode::Esc, _) => { + if app.focused_block == FocusedBlock::Help + || app.focused_block == FocusedBlock::AdapterInfos + { + app.focused_block = FocusedBlock::Device; + } + } + (KeyCode::Char(c), FocusedBlock::Device) if c == config.device.infos => { + app.focused_block = FocusedBlock::AdapterInfos; + } + (KeyCode::Char(c), FocusedBlock::Device) if c == config.device.toggle_power => { + if app.adapter.device.is_powered { + match app.adapter.device.power_off().await { + Ok(()) => { + sender.send(Event::Reset(app.current_mode.clone()))?; + Notification::send( + "Device Powered Off".to_string(), + crate::notification::NotificationLevel::Info, + &sender.clone(), + )?; + } + Err(e) => { + Notification::send( + e.to_string(), + crate::notification::NotificationLevel::Error, + &sender.clone(), + )?; + } + } + } else { + match app.adapter.device.power_on().await { + Ok(()) => { + sender.send(Event::Reset(app.current_mode.clone()))?; + Notification::send( + "Device Powered On".to_string(), + crate::notification::NotificationLevel::Info, + &sender.clone(), + )?; + } + Err(e) => { + Notification::send( + e.to_string(), + crate::notification::NotificationLevel::Error, + &sender.clone(), + )?; + } + } + } + } + (KeyCode::Char(c), _) if c == config.station.start_scanning => { + access_point.as_mut().unwrap().scan(sender).await?; + } + (KeyCode::Tab, FocusedBlock::Device) => app.focused_block = FocusedBlock::AccessPoint, + (KeyCode::Tab, FocusedBlock::AccessPoint) => { + if let Some(ap) = access_point.as_ref() { + if ap.connected_devices.is_empty() { + app.focused_block = FocusedBlock::Device; + } else { + app.focused_block = FocusedBlock::AccessPointConnectedDevices; + } + } + } + (KeyCode::Tab, FocusedBlock::AccessPointConnectedDevices) => { + app.focused_block = FocusedBlock::Device; + } + (KeyCode::BackTab, FocusedBlock::Device) => { + if let Some(ap) = access_point.as_ref() { + if ap.connected_devices.is_empty() { + app.focused_block = FocusedBlock::AccessPoint; + } else { + app.focused_block = FocusedBlock::AccessPointConnectedDevices; + } + } + } + (KeyCode::BackTab, FocusedBlock::AccessPoint) => { + app.focused_block = FocusedBlock::Device; + } + (KeyCode::BackTab, FocusedBlock::AccessPointConnectedDevices) => { + app.focused_block = FocusedBlock::AccessPoint; + } + (KeyCode::Char(c), _) if c == config.ap.start => { + if let Some(ap) = &access_point { + // Start AP + ap.ap_start + .store(true, std::sync::atomic::Ordering::Relaxed); + } + } + (KeyCode::Char(c), _) if c == config.ap.stop => { + if let Some(ap) = access_point { + ap.stop(sender).await?; + ap.connected_devices = Vec::new(); + } + } + (KeyCode::Char('j') | KeyCode::Down, FocusedBlock::Help) => { + app.help.scroll_down(); + } + (KeyCode::Char('k') | KeyCode::Up, FocusedBlock::Help) => { + app.help.scroll_up(); + } + _ => {} + } + Ok(()) +} diff --git a/src/handler/station.rs b/src/handler/station.rs new file mode 100644 index 0000000..5d7c185 --- /dev/null +++ b/src/handler/station.rs @@ -0,0 +1,310 @@ +use std::sync::Arc; + +use crate::access_point::APFocusedSection; +use crate::app::{App, AppResult, FocusedBlock}; +use crate::config::Config; +use crate::event::Event; +use crate::notification::Notification; + +use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use tokio::sync::mpsc::UnboundedSender; +use tui_input::backend::crossterm::EventHandler; + +pub async fn handle_station_key_events( + key_event: KeyEvent, + app: &mut App, + sender: UnboundedSender, + config: Arc, +) -> AppResult<()> { + let station = &mut app.adapter.device.station; + match (key_event.code, app.focused_block) { + (KeyCode::Enter, FocusedBlock::AuthKey) => { + app.send_passkey().await?; + app.focused_block = FocusedBlock::Device; + } + (KeyCode::Esc, FocusedBlock::AuthKey) => { + app.cancel_auth().await?; + app.focused_block = FocusedBlock::Device; + } + (KeyCode::Tab, FocusedBlock::AuthKey) => { + app.show_password = !app.show_password; + } + (_, FocusedBlock::AuthKey) => { + app.passkey_input + .handle_event(&crossterm::event::Event::Key(key_event)); + } + (KeyCode::Enter, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + ap.start(sender.clone()).await?; + sender.send(Event::Reset(app.current_mode.clone()))?; + app.focused_block = FocusedBlock::Device; + } + } + (KeyCode::Esc, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &app.adapter.device.access_point { + // Start AP + ap.ap_start + .store(false, std::sync::atomic::Ordering::Relaxed); + } + app.focused_block = FocusedBlock::AccessPoint; + } + (KeyCode::Tab, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + match ap.focused_section { + APFocusedSection::SSID => ap.focused_section = APFocusedSection::PSK, + APFocusedSection::PSK => ap.focused_section = APFocusedSection::SSID, + } + } + } + (_, FocusedBlock::AccessPointInput) => { + if let Some(ap) = &mut app.adapter.device.access_point { + match ap.focused_section { + APFocusedSection::SSID => ap + .ssid + .handle_event(&crossterm::event::Event::Key(key_event)), + APFocusedSection::PSK => ap + .psk + .handle_event(&crossterm::event::Event::Key(key_event)), + }; + } + } + (KeyCode::Char('q'), _) => app.quit(), + (KeyCode::Char('c' | 'C'), _) => { + if key_event.modifiers == KeyModifiers::CONTROL { + app.quit() + } + } + (KeyCode::Char('?'), _) => app.focused_block = FocusedBlock::Help, + (KeyCode::Char(c), _) + if c == config.switch && key_event.modifiers == KeyModifiers::CONTROL => + { + app.reset_mode = true; + } + (KeyCode::Esc, _) => { + if app.focused_block == FocusedBlock::Help + || app.focused_block == FocusedBlock::AdapterInfos + { + app.focused_block = FocusedBlock::Device; + } + } + (KeyCode::Char(c), FocusedBlock::Device) if c == config.device.infos => { + app.focused_block = FocusedBlock::AdapterInfos; + } + (KeyCode::Char(c), FocusedBlock::Device) if c == config.device.toggle_power => { + if app.adapter.device.is_powered { + match app.adapter.device.power_off().await { + Ok(()) => { + sender.send(Event::Reset(app.current_mode.clone()))?; + Notification::send( + "Device Powered Off".to_string(), + crate::notification::NotificationLevel::Info, + &sender.clone(), + )?; + } + Err(e) => { + Notification::send( + e.to_string(), + crate::notification::NotificationLevel::Error, + &sender.clone(), + )?; + } + } + } else { + match app.adapter.device.power_on().await { + Ok(()) => { + sender.send(Event::Reset(app.current_mode.clone()))?; + Notification::send( + "Device Powered On".to_string(), + crate::notification::NotificationLevel::Info, + &sender.clone(), + )?; + } + Err(e) => { + Notification::send( + e.to_string(), + crate::notification::NotificationLevel::Error, + &sender.clone(), + )?; + } + } + } + } + (KeyCode::Char(c), _) if c == config.station.start_scanning => { + station.as_mut().unwrap().scan(sender).await?; + } + (KeyCode::Tab, _) => match app.focused_block { + FocusedBlock::Device => { + app.focused_block = FocusedBlock::Station; + } + FocusedBlock::Station => { + app.focused_block = FocusedBlock::KnownNetworks; + } + FocusedBlock::KnownNetworks => { + app.focused_block = FocusedBlock::NewNetworks; + } + FocusedBlock::NewNetworks => { + app.focused_block = FocusedBlock::Device; + } + _ => {} + }, + (KeyCode::BackTab, _) => match app.focused_block { + FocusedBlock::Device => { + app.focused_block = FocusedBlock::NewNetworks; + } + FocusedBlock::Station => { + app.focused_block = FocusedBlock::Device; + } + FocusedBlock::KnownNetworks => { + app.focused_block = FocusedBlock::Station; + } + FocusedBlock::NewNetworks => { + app.focused_block = FocusedBlock::KnownNetworks; + } + _ => {} + }, + (KeyCode::Char(c), _) + if c == config.station.known_network.remove + && app.focused_block == FocusedBlock::KnownNetworks => + { + if let Some(net_index) = station.as_ref().unwrap().known_networks_state.selected() { + let (net, _signal) = &station.as_ref().unwrap().known_networks[net_index]; + let known_net = net.known_network.as_ref().unwrap(); + known_net.forget(sender.clone()).await?; + } + } + // Toggle autoconnect + (KeyCode::Char(c), _) + if c == config.station.known_network.toggle_autoconnect + && app.focused_block == FocusedBlock::KnownNetworks => + { + if let Some(net_index) = station.as_ref().unwrap().known_networks_state.selected() { + let (net, _signal) = &station.as_ref().unwrap().known_networks[net_index]; + let known_net = net.known_network.as_ref().unwrap(); + known_net.toggle_autoconnect(sender.clone()).await?; + } + } + // Connect/Disconnect + (KeyCode::Char(c), FocusedBlock::NewNetworks) if c == config.station.toggle_connect => { + if let Some(net_index) = station.as_ref().unwrap().new_networks_state.selected() { + let (net, _) = station.as_ref().unwrap().new_networks[net_index].clone(); + let mode = app.current_mode.clone(); + tokio::spawn(async move { + net.connect(sender.clone()).await.unwrap(); + sender.clone().send(Event::Reset(mode)).unwrap(); + }); + } + } + (KeyCode::Char(c), FocusedBlock::KnownNetworks) if c == config.station.toggle_connect => { + if let Some(connected_net) = &station.as_ref().unwrap().connected_network { + let Some(selected_net_index) = + station.as_ref().unwrap().known_networks_state.selected() + else { + return Ok(()); + }; + let (selected_net, _signal) = + &station.as_ref().unwrap().known_networks[selected_net_index]; + if selected_net.name == connected_net.name { + station.as_ref().unwrap().disconnect(sender.clone()).await?; + } else { + let net_index = station + .as_ref() + .unwrap() + .known_networks + .iter() + .position(|(n, _s)| n.name == selected_net.name); + if let Some(index) = net_index { + let (net, _) = station.as_ref().unwrap().known_networks[index].clone(); + station.as_ref().unwrap().disconnect(sender.clone()).await?; + tokio::spawn(async move { + net.connect(sender.clone()).await.unwrap(); + }); + } + } + } else { + let Some(selected_net_index) = + station.as_ref().unwrap().known_networks_state.selected() + else { + return Ok(()); + }; + let (selected_net, _signal) = + &station.as_ref().unwrap().known_networks[selected_net_index]; + let net_index = station + .as_ref() + .unwrap() + .known_networks + .iter() + .position(|(n, _s)| n.name == selected_net.name); + if let Some(index) = net_index { + let (net, _) = station.as_ref().unwrap().known_networks[index].clone(); + tokio::spawn(async move { + net.connect(sender.clone()).await.unwrap(); + }); + } + } + } + (KeyCode::Char('j') | KeyCode::Down, FocusedBlock::KnownNetworks) => { + if !station.as_ref().unwrap().known_networks.is_empty() { + let i = match station.as_ref().unwrap().known_networks_state.selected() { + Some(i) => { + if i < station.as_ref().unwrap().known_networks.len() - 1 { + i + 1 + } else { + i + } + } + None => 0, + }; + station + .as_mut() + .unwrap() + .known_networks_state + .select(Some(i)); + } + } + (KeyCode::Char('j') | KeyCode::Down, FocusedBlock::NewNetworks) => { + if !station.as_ref().unwrap().new_networks.is_empty() { + let i = match station.as_ref().unwrap().new_networks_state.selected() { + Some(i) => { + if i < station.as_ref().unwrap().new_networks.len() - 1 { + i + 1 + } else { + i + } + } + None => 0, + }; + station.as_mut().unwrap().new_networks_state.select(Some(i)); + } + } + (KeyCode::Char('k') | KeyCode::Up, FocusedBlock::KnownNetworks) => { + if !station.as_ref().unwrap().known_networks.is_empty() { + let i = match station.as_ref().unwrap().known_networks_state.selected() { + Some(i) => i.saturating_sub(1), + None => 0, + }; + station + .as_mut() + .unwrap() + .known_networks_state + .select(Some(i)); + } + } + (KeyCode::Char('k') | KeyCode::Up, FocusedBlock::NewNetworks) => { + if !station.as_ref().unwrap().new_networks.is_empty() { + let i = match station.as_ref().unwrap().new_networks_state.selected() { + Some(i) => i.saturating_sub(1), + None => 0, + }; + station.as_mut().unwrap().new_networks_state.select(Some(i)); + } + } + (KeyCode::Char('j') | KeyCode::Down, FocusedBlock::Help) => { + app.help.scroll_down(); + } + (KeyCode::Char('k') | KeyCode::Up, FocusedBlock::Help) => { + app.help.scroll_up(); + } + _ => {} + } + Ok(()) +}