use fenrix_core::{create_signal, provide_service, inject};
use std::collections::HashMap;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{window, HashChangeEvent, Node};
pub type Routable = fn() -> Node;
#[derive(Clone)]
pub struct Router {
routes: Rc<HashMap<String, Routable>>,
pub current_path: Rc<dyn Fn() -> String>,
set_current_path: Rc<dyn Fn(String)>,
}
impl Router {
pub fn new(routes: HashMap<String, Routable>) -> Self {
let (current_path, set_current_path) = create_signal(get_current_hash());
let router = Self {
routes: Rc::new(routes),
current_path: Rc::new(current_path),
set_current_path: Rc::new(set_current_path),
};
let router_clone = router.clone();
let on_hash_change = Closure::wrap(Box::new(move |_: HashChangeEvent| {
(router_clone.set_current_path)(get_current_hash());
}) as Box<dyn FnMut(_)>);
window()
.unwrap()
.add_event_listener_with_callback("hashchange", on_hash_change.as_ref().unchecked_ref())
.unwrap();
on_hash_change.forget();
router
}
pub fn get_component(&self, path: &str) -> Option<Routable> {
self.routes.get(path).cloned()
}
}
fn get_current_hash() -> String {
let hash = window().unwrap().location().hash().unwrap_or_else(|_| "".to_string());
if hash.is_empty() {
"/".to_string()
} else {
hash[1..].to_string()
}
}
pub fn provide_router(routes: HashMap<String, Routable>) {
provide_service(Router::new(routes));
}
pub fn use_router() -> Rc<Router> {
inject::<Router>()
}