lowfi/src/ui/input.rs
2025-12-06 22:11:49 +01:00

68 lines
2.3 KiB
Rust

//! Responsible for specifically receiving terminal input
//! using [`crossterm`].
use crate::Message;
use crossterm::event::{self, EventStream, KeyCode, KeyEventKind, KeyModifiers};
use futures_util::{FutureExt, StreamExt};
use tokio::sync::mpsc::Sender;
/// Starts the listener to receive input from the terminal for various events.
pub async fn listen(sender: Sender<Message>) -> super::Result<()> {
let mut reader = EventStream::new();
loop {
let Some(Ok(event::Event::Key(event))) = reader.next().fuse().await else {
continue;
};
if event.kind == KeyEventKind::Release {
continue;
}
let messages = match event.code {
// Arrow key volume controls.
KeyCode::Up => Message::ChangeVolume(0.1),
KeyCode::Right => Message::ChangeVolume(0.01),
KeyCode::Down => Message::ChangeVolume(-0.1),
KeyCode::Left => Message::ChangeVolume(-0.01),
KeyCode::Char(character) => match character.to_ascii_lowercase() {
// Ctrl+C
'c' if event.modifiers == KeyModifiers::CONTROL => Message::Quit,
// Quit
'q' => Message::Quit,
// Skip/Next
's' | 'n' | 'l' => Message::Next,
// Pause
'p' | ' ' => Message::PlayPause,
// Volume up & down
'+' | '=' | 'k' => Message::ChangeVolume(0.1),
'-' | '_' | 'j' => Message::ChangeVolume(-0.1),
// Bookmark
'b' => Message::Bookmark,
_ => continue,
},
// Media keys
KeyCode::Media(media) => match media {
event::MediaKeyCode::Pause
| event::MediaKeyCode::Play
| event::MediaKeyCode::PlayPause => Message::PlayPause,
event::MediaKeyCode::Stop => Message::Pause,
event::MediaKeyCode::TrackNext => Message::Next,
event::MediaKeyCode::LowerVolume => Message::ChangeVolume(-0.1),
event::MediaKeyCode::RaiseVolume => Message::ChangeVolume(0.1),
event::MediaKeyCode::MuteVolume => Message::ChangeVolume(-1.0),
_ => continue,
},
_ => continue,
};
sender.send(messages).await?;
}
}