ferroui_browser/
browser_system_navigation_manager.rs1use ferroui_base::interactivity::RoutedEventArgs;
2use ferroui_base::platform::ISystemNavigationManagerImpl;
3use ferroui_base::reactive::{Disposable, IDisposable};
4use ferroui_base::utilities::HandlerList;
5use std::rc::Rc;
6
7#[derive(Default)]
11pub struct BrowserSystemNavigationManagerImpl {
12 back_requested: Rc<HandlerList<dyn Fn(&Rc<RoutedEventArgs>)>>,
13}
14
15impl BrowserSystemNavigationManagerImpl {
16 pub fn on_back_requested(&self) -> bool {
18 let routed_event_args = Rc::new(RoutedEventArgs::new());
19
20 for (_, handler) in self.back_requested.snapshot().iter() {
21 handler(&routed_event_args);
22 }
23
24 routed_event_args.handled()
25 }
26}
27
28impl ISystemNavigationManagerImpl for BrowserSystemNavigationManagerImpl {
29 fn back_requested(&self, handler: Rc<dyn Fn(&Rc<RoutedEventArgs>)>) -> Rc<dyn IDisposable> {
30 let token = self.back_requested.add(handler);
31 let handlers = self.back_requested.clone();
32 Disposable::create(move || {
33 handlers.remove(token);
34 })
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41 use std::cell::Cell;
42
43 #[test]
44 fn a_back_request_is_not_handled_without_handlers() {
45 assert!(!BrowserSystemNavigationManagerImpl::default().on_back_requested());
46 }
47
48 #[test]
49 fn a_back_request_is_handled_when_a_handler_marks_it_handled() {
50 let manager = BrowserSystemNavigationManagerImpl::default();
51 let calls = Rc::new(Cell::new(0));
52 let subscription = manager.back_requested({
53 let calls = calls.clone();
54 Rc::new(move |args: &Rc<RoutedEventArgs>| {
55 calls.set(calls.get() + 1);
56 args.set_handled(true);
57 })
58 });
59
60 assert!(manager.on_back_requested());
61 assert_eq!(1, calls.get());
62
63 subscription.dispose();
64 assert!(!manager.on_back_requested());
65 assert_eq!(1, calls.get());
66 }
67
68 #[test]
69 fn every_handler_sees_the_request() {
70 let manager = BrowserSystemNavigationManagerImpl::default();
71 let seen = Rc::new(Cell::new(0));
72 let mut subscriptions = Vec::new();
73 for _ in 0..2 {
74 let seen = seen.clone();
75 subscriptions.push(manager.back_requested(Rc::new(move |_: &Rc<RoutedEventArgs>| seen.set(seen.get() + 1))));
76 }
77
78 assert!(!manager.on_back_requested());
79 assert_eq!(2, seen.get());
80 }
81}