use cosmic::iced::futures::{channel::mpsc::Sender, executor, SinkExt}; use std::{ fs, io, path::Path, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, }; use tokio::sync::Mutex; use crate::{app::Message, fl}; // Special reader just for operations, handling cancel and progress pub struct OpReader { file: fs::File, metadata: fs::Metadata, current: u64, id: u64, msg_tx: Arc>>, cancelled: Arc, } impl OpReader { pub fn new>( path: P, id: u64, msg_tx: Arc>>, cancelled: Arc, ) -> io::Result { let file = fs::File::open(&path)?; let metadata = file.metadata()?; Ok(Self { file, metadata, current: 0, id, msg_tx, cancelled, }) } } impl io::Read for OpReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { if self.cancelled.load(Ordering::SeqCst) { return Err(io::Error::new(io::ErrorKind::Other, fl!("cancelled"))); } let count = self.file.read(buf)?; self.current += count as u64; let progress = self.current as f32 / self.metadata.len() as f32; executor::block_on(async { let _ = self .msg_tx .lock() .await .send(Message::PendingProgress(self.id, 100.0 * progress)) .await; }); Ok(count) } }