wip: updates to router

This commit is contained in:
Jonathan Kelley committed 2021-11-22 15:22:42 -05:00
1 parent a5f05d73ac
commit bab21a0aa1
8 files changed
+208 -217

No files matched your search

+72 -22
View File
@@ -6,23 +6,24 @@ use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::{format_args_f, rsx, Props};
use dioxus_html as dioxus_elements;
use wasm_bindgen::JsValue;
use web_sys::Event;
use wasm_bindgen::{JsCast, JsValue};
use web_sys::{window, Event};
use crate::utils::fetch_base_url;
use crate::utils::strip_slash_suffix;
pub trait Routable: 'static + Send + Clone + ToString + PartialEq {}
impl<T> Routable for T where T: 'static + Send + Clone + ToString + PartialEq {}
pub trait Routable: 'static + Send + Clone + PartialEq {}
impl<T> Routable for T where T: 'static + Send + Clone + PartialEq {}
pub struct RouterService<R: Routable> {
historic_routes: RefCell<Vec<R>>,
history_service: web_sys::History,
historic_routes: Vec<R>,
history_service: RefCell<web_sys::History>,
base_ur: RefCell<Option<String>>,
}
impl<R: Routable> RouterService<R> {
fn push_route(&self, r: R) {
self.historic_routes.borrow_mut().push(r);
todo!()
// self.historic_routes.borrow_mut().push(r);
}
fn get_current_route(&self) -> &str {
@@ -65,41 +66,73 @@ impl<R: Routable> RouterService<R> {
/// This hould only be used once per app
///
/// You can manually parse the route if you want, but the derived `parse` method on `Routable` will also work just fine
pub fn use_router<R: Routable>(cx: Context, parse: impl FnMut(&str) -> R) -> &R {
pub fn use_router<R: Routable>(cx: Context, mut parse: impl FnMut(&str) -> R + 'static) -> &R {
// for the web, attach to the history api
cx.use_hook(
|f| {
//
use gloo::events::EventListener;
let base_url = fetch_base_url();
let base = window()
.unwrap()
.document()
.unwrap()
.query_selector("base[href]")
.ok()
.flatten()
.and_then(|base| {
let base = JsCast::unchecked_into::<web_sys::HtmlBaseElement>(base).href();
let url = web_sys::Url::new(&base).unwrap();
if url.pathname() != "/" {
Some(strip_slash_suffix(&base).to_string())
} else {
None
}
});
let location = window().unwrap().location();
let pathname = location.pathname().unwrap();
let initial_route = parse(&pathname);
let service: RouterService<R> = RouterService {
historic_routes: RefCell::new(vec![]),
history_service: web_sys::window().unwrap().history().expect("no history"),
base_ur: RefCell::new(base_url),
historic_routes: vec![initial_route],
history_service: RefCell::new(
web_sys::window().unwrap().history().expect("no history"),
),
base_ur: RefCell::new(base),
};
// let base = base_url();
// let url = route.to_path();
// pending_routes: RefCell::new(vec![]),
// service.history_service.push_state(data, title);
cx.provide_state(service);
// cx.provide_state(service);
let regenerate = cx.schedule_update();
// when "back" is called by the user, we want to to re-render the component
// // when "back" is called by the user, we want to to re-render the component
let listener = EventListener::new(&web_sys::window().unwrap(), "popstate", move |_| {
//
regenerate();
});
service
},
|f| {
|state| {
let base = state.base_ur.borrow();
if let Some(base) = base.as_ref() {
//
let path = format!("{}{}", base, state.get_current_route());
}
let history = state.history_service.borrow();
todo!()
// history.state.historic_routes.last().unwrap()
//
},
);
todo!()
// let router = use_router_service::<R>(cx)?;
// Some(cfg(router.get_current_route()))
)
}
pub fn use_router_service<R: Routable>(cx: Context) -> Option<&Rc<RouterService<R>>> {
@@ -109,6 +142,23 @@ pub fn use_router_service<R: Routable>(cx: Context) -> Option<&Rc<RouterService<
#[derive(Props)]
pub struct LinkProps<R: Routable> {
to: R,
/// The url that gets pushed to the history stack
///
/// You can either put it your own inline method or just autoderive the route using `derive(Routable)`
///
/// ```rust
///
/// Link { to: Route::Home, href: |_| "home".to_string() }
///
/// // or
///
/// Link { to: Route::Home, href: Route::as_url }
///
/// ```
href: fn(&R) -> String,
#[builder(default)]
children: Element,
}
@@ -116,7 +166,7 @@ pub fn Link<R: Routable>(cx: Context, props: &LinkProps<R>) -> Element {
let service = use_router_service::<R>(cx)?;
cx.render(rsx! {
a {
href: format_args!("{}", props.to.to_string()),
href: format_args!("{}", (props.href)(&props.to)),
onclick: move |_| service.push_route(props.to.clone()),
{&props.children},
}
-25
View File
@@ -1,31 +1,6 @@
use wasm_bindgen::JsCast;
use web_sys::window;
pub fn fetch_base_url() -> Option<String> {
match window()
.unwrap()
.document()
.unwrap()
.query_selector("base[href]")
{
Ok(Some(base)) => {
let base = JsCast::unchecked_into::<web_sys::HtmlBaseElement>(base).href();
let url = web_sys::Url::new(&base).unwrap();
let base = url.pathname();
let base = if base != "/" {
strip_slash_suffix(&base)
} else {
return None;
};
Some(base.to_string())
}
_ => None,
}
}
pub(crate) fn strip_slash_suffix(path: &str) -> &str {
path.strip_suffix('/').unwrap_or(path)
}