This repository has been archived by the owner on Mar 2, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 48
/
router.rs
executable file
·68 lines (63 loc) · 2.48 KB
/
router.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! A simple `#`-fragment router.
use crate::todos::Todos;
use crate::utils;
use crate::visibility::Visibility;
use dodrio::VdomWeak;
use std::str::FromStr;
use wasm_bindgen::{prelude::*, JsCast};
/// Start the router.
pub fn start(vdom: VdomWeak) {
// Callback fired whenever the URL's hash fragment changes. Keeps the root
// todos collection's visibility in sync with the `#` fragment.
let on_hash_change = move || {
let new_vis = utils::hash()
.and_then(|hash| {
if hash.starts_with("#/") {
Visibility::from_str(&hash[2..]).ok()
} else {
None
}
})
.unwrap_or_else(|| {
// If we couldn't parse a visibility, make sure we canonicalize
// it back to our default hash.
let v = Visibility::default();
utils::set_hash(&format!("#/{}", v));
v
});
wasm_bindgen_futures::spawn_local({
let vdom = vdom.clone();
async move {
let _ = vdom
.with_component({
let vdom = vdom.clone();
move |root| {
let todos = root.unwrap_mut::<Todos>();
// If the todos' visibility already matches the event's
// visibility, then there is nothing to do (ha). If they
// don't match, then we need to update the todos' visibility
// and re-render.
if todos.visibility() != new_vis {
todos.set_visibility(new_vis);
vdom.schedule_render();
}
}
})
.await;
}
});
};
// Call it once to handle the initial `#` fragment.
on_hash_change();
// Now listen for hash changes forever.
//
// Note that if we ever intended to unmount our todos app, we would want to
// provide a method for removing this router's event listener and cleaning
// up after ourselves.
let on_hash_change = Closure::wrap(Box::new(on_hash_change) as Box<dyn FnMut()>);
let window = utils::window();
window
.add_event_listener_with_callback("hashchange", on_hash_change.as_ref().unchecked_ref())
.unwrap_throw();
on_hash_change.forget();
}