fm/app/
refresher.rs

1use std::sync::mpsc::{self, Sender, TryRecvError};
2use std::sync::Arc;
3use std::thread;
4use std::time::Duration;
5
6use crate::event::FmEvents;
7
8/// Allows refresh if the current path has been modified externally.
9pub struct Refresher {
10    /// Sender of messages, used to terminate the thread properly
11    tx: mpsc::Sender<()>,
12    /// Handle to the `term::Event` sender thread.
13    handle: thread::JoinHandle<()>,
14}
15
16impl Refresher {
17    /// Between 2 refreshed
18    const TEN_SECONDS_IN_CENTISECONDS: u16 = 10 * 100;
19
20    /// Event sent to Fm event poller which is interpreted
21    /// as a request for refresh.
22    ///
23    /// Spawn a thread which sends events to the terminal.
24    /// Those events are interpreted as refresh requests.
25    /// It also listen to a receiver for quit messages.
26    pub fn new(fm_sender: Arc<Sender<FmEvents>>) -> Self {
27        let (tx, rx) = mpsc::channel();
28        // let mut counter: u16 = 0;
29        let mut counter = Counter::default();
30        let handle = thread::spawn(move || loop {
31            match rx.try_recv() {
32                Ok(_) | Err(TryRecvError::Disconnected) => {
33                    return;
34                }
35                Err(TryRecvError::Empty) => {}
36            }
37            counter.incr();
38            thread::sleep(Duration::from_millis(10));
39            let event = counter.pick_according_to_counter();
40            if fm_sender.send(event).is_err() {
41                break;
42            }
43        });
44        Self { tx, handle }
45    }
46
47    /// Send a quit message to the receiver, signaling it to quit.
48    /// Join the refreshing thread which should be terminated.
49    pub fn quit(self) {
50        let _ = self.tx.send(());
51        let _ = self.handle.join();
52    }
53}
54
55#[derive(Default)]
56struct Counter {
57    counter: u16,
58}
59
60impl Counter {
61    fn pick_according_to_counter(&mut self) -> FmEvents {
62        if self.counter >= Refresher::TEN_SECONDS_IN_CENTISECONDS {
63            self.counter = 0;
64            FmEvents::Refresh
65        } else {
66            FmEvents::UpdateTick
67        }
68    }
69
70    fn incr(&mut self) {
71        self.counter += 1;
72    }
73}