61 lines
2.3 KiB
Rust
61 lines
2.3 KiB
Rust
use crate::{screens::screens::UiEvent, ui::UI};
|
|
use crossterm::event::{Event, KeyEvent, KeyEventKind, KeyModifiers, poll, read};
|
|
use std::sync::Arc;
|
|
use std::time::Duration;
|
|
use tokio::sync::mpsc;
|
|
use tokio::task::JoinHandle;
|
|
|
|
pub fn setup_input_handler(ui: Arc<UI>) -> JoinHandle<Result<(), String>> {
|
|
tokio::spawn(async move {
|
|
let cancellation = ui.cancellation_token();
|
|
let (tx, mut rx) = mpsc::unbounded_channel();
|
|
let worker_cancellation = cancellation.clone();
|
|
let worker = tokio::task::spawn_blocking(move || -> Result<(), String> {
|
|
while !worker_cancellation.is_cancelled() {
|
|
if poll(Duration::from_millis(100)).map_err(|e| e.to_string())? {
|
|
tx.send(read().map_err(|e| e.to_string())?)
|
|
.map_err(|_| "input session closed".to_string())?;
|
|
}
|
|
}
|
|
Ok(())
|
|
});
|
|
loop {
|
|
if ui.is_shutdown() {
|
|
break;
|
|
}
|
|
|
|
tokio::select! {
|
|
event = rx.recv() => match event {
|
|
Some(Event::Key(key)) if key.kind == KeyEventKind::Press => handle_input(key, ui.clone()).await,
|
|
Some(Event::Mouse(mouse)) => ui.clone().handle_event(UiEvent::Mouse(mouse)).await,
|
|
Some(Event::Resize(width, height)) => ui.clone().handle_event(UiEvent::Resize(width, height)).await,
|
|
Some(Event::Paste(text)) => ui.clone().handle_event(UiEvent::Paste(text)).await,
|
|
Some(_) => {},
|
|
None => break,
|
|
},
|
|
_ = cancellation.cancelled() => break,
|
|
}
|
|
}
|
|
let result = match worker.await {
|
|
Ok(result) => result,
|
|
Err(error) if error.is_cancelled() => Ok(()),
|
|
Err(error) => Err(format!("input worker failed: {error}")),
|
|
};
|
|
if result.is_err() {
|
|
ui.request_shutdown();
|
|
}
|
|
result
|
|
})
|
|
}
|
|
|
|
pub async fn handle_input(key: KeyEvent, ui: Arc<UI>) {
|
|
if matches!(
|
|
key.code,
|
|
crossterm::event::KeyCode::Char('q') | crossterm::event::KeyCode::Char('c')
|
|
) && key.modifiers.contains(KeyModifiers::CONTROL)
|
|
{
|
|
ui.request_shutdown();
|
|
} else {
|
|
ui.handle_event(UiEvent::Key(key)).await;
|
|
}
|
|
}
|