use iced::{ futures::{ channel::mpsc::{unbounded, UnboundedReceiver}, StreamExt, }, subscription, Rectangle, }; use std::{fmt::Debug, hash::Hash, collections::HashMap}; use super::RectangleTracker; pub fn rectangle_tracker_subscription< I: 'static + Hash + Copy + Send + Sync + Debug, R: 'static + Hash + Copy + Send + Sync + Debug + Eq, >( id: I, ) -> iced::Subscription<(I, RectangleUpdate)> { subscription::unfold(id, State::Ready, move |state| start_listening(id, state)) } pub enum State { Ready, Waiting(UnboundedReceiver<(I, Rectangle)>, HashMap), Finished, } async fn start_listening( id: I, state: State, ) -> (Option<(I, RectangleUpdate)>, State) { match state { State::Ready => { let (tx, rx) = unbounded(); return ( Some((id, RectangleUpdate::Init(RectangleTracker { tx }))), State::Waiting(rx, HashMap::new()), ); } State::Waiting(mut rx, mut map) => match rx.next().await { Some(u) => { if let Some(prev) = map.get(&u.0) { let new = u.1; if prev.width != new.width || prev.height != new.height || prev.x != new.x || prev.y != new.y { map.insert(u.0, new); return ( Some((id, RectangleUpdate::Rectangle(u))), State::Waiting(rx, map), ); } } else { map.insert(u.0, u.1); return ( Some((id, RectangleUpdate::Rectangle(u))), State::Waiting(rx, map), ); } return (None, State::Waiting(rx, map)) }, None => (None, State::Finished), }, State::Finished => iced::futures::future::pending().await, } } #[derive(Clone, Debug)] pub enum RectangleUpdate where I: 'static + Hash + Copy + Send + Sync + Debug, { Rectangle((I, Rectangle)), Init(RectangleTracker), }