freya_components/
native_router.rs

1use dioxus::prelude::*;
2use dioxus_router::prelude::use_navigator;
3use freya_elements::{
4    self as dioxus_elements,
5    events::{
6        MouseButton,
7        PointerEvent,
8        PointerType,
9    },
10};
11
12/// Provides native functionalities for a dioxus-router.
13///
14/// Features:
15/// - Navigate using back and forward buttons of the mouse.
16#[allow(non_snake_case)]
17#[component]
18pub fn NativeRouter(children: Element) -> Element {
19    let router = use_navigator();
20
21    let onpointerup = move |e: PointerEvent| {
22        if let PointerType::Mouse { trigger_button } = e.data().get_pointer_type() {
23            match trigger_button {
24                Some(MouseButton::Back) => router.go_back(),
25                Some(MouseButton::Forward) => router.go_forward(),
26                _ => {}
27            }
28        }
29    };
30
31    rsx!(
32        rect {
33            onpointerup,
34            {children}
35        }
36    )
37}
38
39#[cfg(test)]
40mod test {
41    use dioxus_router::prelude::{
42        Outlet,
43        Routable,
44        Router,
45    };
46    use freya::prelude::*;
47    use freya_core::events::EventName;
48    use freya_testing::prelude::*;
49
50    #[tokio::test]
51    pub async fn native_router() {
52        #[derive(Routable, Clone, PartialEq)]
53        #[rustfmt::skip]
54        pub enum Route {
55            #[layout(App)]
56                #[route("/")]
57                A,
58                #[route("/B")]
59                B,
60            #[end_layout]
61            #[route("/..route")]
62            NotFound { },
63        }
64
65        #[allow(non_snake_case)]
66        #[component]
67        fn NotFound() -> Element {
68            rsx!(
69                label {
70                    "NotFound"
71                }
72            )
73        }
74
75        #[allow(non_snake_case)]
76        #[component]
77        fn A() -> Element {
78            rsx!(
79                label {
80                    "A"
81                }
82            )
83        }
84
85        #[allow(non_snake_case)]
86        #[component]
87        fn B() -> Element {
88            rsx!(
89                label {
90                    "B"
91                }
92            )
93        }
94
95        #[allow(non_snake_case)]
96        fn App() -> Element {
97            rsx!(
98                NativeRouter {
99                    Link {
100                        to: Route::B,
101                        label {
102                            "Got to B"
103                        }
104                    }
105                    Outlet::<Route> {  }
106                }
107            )
108        }
109
110        let mut utils = launch_test(|| -> Element { rsx!(Router::<Route> {}) });
111
112        assert_eq!(utils.root().get(0).get(1).get(0).text(), Some("A"));
113
114        utils.click_cursor((5., 5.)).await;
115
116        assert_eq!(utils.root().get(0).get(1).get(0).text(), Some("B"));
117
118        utils.push_event(TestEvent::Mouse {
119            name: EventName::MouseUp,
120            cursor: (5.0, 5.0).into(),
121            button: Some(MouseButton::Back),
122        });
123        utils.wait_for_update().await;
124
125        assert_eq!(utils.root().get(0).get(1).get(0).text(), Some("A"));
126
127        utils.push_event(TestEvent::Mouse {
128            name: EventName::MouseUp,
129            cursor: (5.0, 5.0).into(),
130            button: Some(MouseButton::Forward),
131        });
132        utils.wait_for_update().await;
133
134        assert_eq!(utils.root().get(0).get(1).get(0).text(), Some("B"));
135    }
136}