Skip to main content

phosphor_app/state/
input.rs

1//! Input state — NumberBuffer for multi-digit clip jump.
2
3use std::time::Instant;
4
5#[derive(Debug)]
6pub struct NumberBuffer {
7    digits: String,
8    last_input: Option<Instant>,
9    timeout_ms: u128,
10}
11
12impl Default for NumberBuffer {
13    fn default() -> Self { Self::new() }
14}
15
16impl NumberBuffer {
17    pub fn new() -> Self { Self { digits: String::new(), last_input: None, timeout_ms: 500 } }
18
19    pub fn push_digit(&mut self, ch: char) -> Option<usize> {
20        if self.is_timed_out() { self.digits.clear(); }
21        self.digits.push(ch);
22        self.last_input = Some(Instant::now());
23        None
24    }
25
26    pub fn check_timeout(&mut self) -> Option<usize> {
27        if self.digits.is_empty() { return None; }
28        if self.is_timed_out() {
29            let num = self.digits.parse::<usize>().ok();
30            self.digits.clear();
31            self.last_input = None;
32            num
33        } else { None }
34    }
35
36    fn is_timed_out(&self) -> bool {
37        self.last_input.map(|t| t.elapsed().as_millis() >= self.timeout_ms).unwrap_or(true)
38    }
39
40    pub fn display(&self) -> &str {
41        if self.is_timed_out() { "" } else { &self.digits }
42    }
43
44    pub fn commit(&mut self) -> Option<usize> {
45        if self.digits.is_empty() { return None; }
46        let num = self.digits.parse::<usize>().ok();
47        self.digits.clear();
48        self.last_input = None;
49        num
50    }
51}