// SPDX-License-Identifier: GPL-3.0-or-later use gstore::{self, Actionable, Keybinding}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct State { current_page: String, page_history: Vec, selection: (u32, u32), } impl Default for State { fn default() -> Self { Self { current_page: "home".to_string(), page_history: vec![], selection: Default::default(), } } } #[derive(Debug, Clone, PartialEq, Eq)] pub enum Action { A, B, C, } impl Actionable for Action { fn list() -> Vec { vec![Action::A, Action::B, Action::C] } fn try_from_name(name: &str) -> Option { match name { "a" => Some(Action::A), "b" => Some(Action::B), "c" => Some(Action::C), _ => None, } } fn keybinding(&self) -> Option { None } fn name(&self) -> &'static str { match self { Action::A => "a", Action::B => "b", Action::C => "c", } } } mod dispatch_during_reduce_works_but_is_not_smart { use std::sync::mpsc::sync_channel; use super::*; gstore::store!(Action, State); #[test] fn test() { env_logger::try_init().ok(); let (s, r) = sync_channel(100); let reduce = store().init( |a, _| { println!("Reduce: {:?}", a); if a == &Action::A { store().dispatch(Action::C); store().dispatch(Action::B); store().dispatch(Action::B); store().dispatch(Action::C); store().dispatch(Action::C); } }, move |a| { s.send(a).expect("Failed to send"); }, ); std::thread::spawn(|| { for _ in 0..5 { store().dispatch(Action::A); std::thread::sleep(std::time::Duration::from_millis(10)); store().dispatch(Action::B); std::thread::sleep(std::time::Duration::from_millis(10)); } }); println!("waiting for actions"); const EXPECTED: u32 = 35; let mut actions = Vec::new(); for _ in 0..EXPECTED { if let Ok(a) = r.recv_timeout(std::time::Duration::from_secs(1)) { actions.push(a.name()); reduce(a); } else { assert!(false, "Test ran into timeout"); } } assert_eq!( actions.join(""), "a cbbcc ba cbbcc ba cbbcc ba cbbcc ba cbbcc b".replace(" ", "") ) } }