use ratatui::crossterm::event::KeyEvent;
use crate::app::App;
use crate::command;
pub const CHORD_CHAIN_TIMEOUT_MS: u64 = 1000;
pub fn dispatch_chord_chain(app: &mut App, key: KeyEvent) -> bool {
use crate::input::keymap::{Chord, SeqResolution};
let new_chord = Chord::of(&key);
app.pending_chord_seq.push(new_chord);
match app.keymap.resolve_seq(&app.pending_chord_seq) {
SeqResolution::Run(id) => {
let id = id.to_owned();
app.pending_chord_seq.clear();
app.pending_chord_deadline = None;
app.pending_chord_fallback = None;
command::run(&id, app);
true
}
SeqResolution::PendingWithFallback(fallback) => {
let fb = fallback.to_owned();
app.pending_chord_fallback = Some(fb);
app.pending_chord_deadline = Some(
std::time::Instant::now()
+ std::time::Duration::from_millis(CHORD_CHAIN_TIMEOUT_MS),
);
true
}
SeqResolution::Pending => {
app.pending_chord_fallback = None;
app.pending_chord_deadline = Some(
std::time::Instant::now()
+ std::time::Duration::from_millis(CHORD_CHAIN_TIMEOUT_MS),
);
true
}
SeqResolution::None => {
let fallback = app.pending_chord_fallback.take();
let was_first_key = app.pending_chord_seq.len() == 1;
app.pending_chord_seq.clear();
app.pending_chord_deadline = None;
if let Some(id) = fallback {
command::run(&id, app);
}
if was_first_key {
return false;
}
if !matches!(new_chord.code, ratatui::crossterm::event::KeyCode::Char(_)) {
return false;
}
app.pending_chord_seq.push(new_chord);
match app.keymap.resolve_seq(&app.pending_chord_seq) {
SeqResolution::Run(id) => {
let id = id.to_owned();
app.pending_chord_seq.clear();
command::run(&id, app);
true
}
SeqResolution::PendingWithFallback(fb) => {
let fb = fb.to_owned();
app.pending_chord_fallback = Some(fb);
app.pending_chord_deadline = Some(
std::time::Instant::now()
+ std::time::Duration::from_millis(CHORD_CHAIN_TIMEOUT_MS),
);
true
}
SeqResolution::Pending => {
app.pending_chord_deadline = Some(
std::time::Instant::now()
+ std::time::Duration::from_millis(CHORD_CHAIN_TIMEOUT_MS),
);
true
}
SeqResolution::None => {
app.pending_chord_seq.clear();
false
}
}
}
}
}
pub fn tick_chord_chain(app: &mut App) {
let Some(deadline) = app.pending_chord_deadline else {
return;
};
if std::time::Instant::now() < deadline {
return;
}
let fallback = app.pending_chord_fallback.take();
app.pending_chord_seq.clear();
app.pending_chord_deadline = None;
if let Some(id) = fallback {
command::run(&id, app);
}
}