use std::io;
use std::path;
use std::sync::mpsc;
use std::thread;
use signal_hook::consts::signal;
use signal_hook::iterator::exfiltrator::SignalOnly;
use signal_hook::iterator::SignalsInfo;
use termion::event::Event;
use termion::input::TermRead;
use uuid::Uuid;
use crate::error::AppResult;
use crate::fs::JoshutoDirList;
use crate::io::FileOperationProgress;
use crate::preview::preview_file::FilePreview;
#[derive(Debug)]
pub enum AppEvent {
Termion(Event),
IoWorkerCreate,
FileOperationProgress(FileOperationProgress),
IoWorkerResult(AppResult<FileOperationProgress>),
ChildProcessComplete(u32),
PreviewDir {
id: Uuid,
path: path::PathBuf,
res: Box<io::Result<JoshutoDirList>>,
},
PreviewFile {
path: path::PathBuf,
res: Box<io::Result<FilePreview>>,
},
Signal(i32),
Filesystem(notify::Event),
}
#[derive(Default, Debug, Clone, Copy)]
pub struct Config {}
pub struct Events {
pub event_tx: mpsc::Sender<AppEvent>,
event_rx: mpsc::Receiver<AppEvent>,
pub input_tx: mpsc::Sender<()>,
}
impl Events {
pub fn new() -> Self {
Self::default()
}
pub fn next(&self) -> Result<AppEvent, mpsc::RecvError> {
let event = self.event_rx.recv()?;
Ok(event)
}
pub fn flush(&self) {
loop {
if self.input_tx.send(()).is_ok() {
break;
}
}
}
}
impl std::default::Default for Events {
fn default() -> Self {
let (input_tx, input_rx) = mpsc::channel();
let (event_tx, event_rx) = mpsc::channel();
let _ = input_tx.send(());
let event_tx2 = event_tx.clone();
let _ = thread::spawn(move || {
let sigs = vec![signal::SIGWINCH];
let mut signals = SignalsInfo::<SignalOnly>::new(sigs).unwrap();
for signal in &mut signals {
if let Err(e) = event_tx2.send(AppEvent::Signal(signal)) {
eprintln!("Signal thread send err: {:#?}", e);
return;
}
}
});
let event_tx2 = event_tx.clone();
let _ = thread::spawn(move || {
let stdin = io::stdin();
let mut events = stdin.events();
loop {
let _ = input_rx.recv();
if let Some(Ok(event)) = events.next() {
let _ = event_tx2.send(AppEvent::Termion(event));
}
}
});
Events {
event_tx,
event_rx,
input_tx,
}
}
}