From 3feee729bcfc344cb7f4e1eaa64d2f16d6107cb8 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 20 Dec 2023 09:53:41 -0600 Subject: [PATCH 1/2] enabled the liveview history by default if the liveview feature is enabled in the router --- packages/router/examples/simple_routes.rs | 41 ++++++++++++--------- packages/router/src/history/liveview.rs | 44 ++++++++++++++--------- packages/router/src/router_cfg.rs | 18 +++++++--- 3 files changed, 65 insertions(+), 38 deletions(-) diff --git a/packages/router/examples/simple_routes.rs b/packages/router/examples/simple_routes.rs index aac1e8658..b30e0f3d7 100644 --- a/packages/router/examples/simple_routes.rs +++ b/packages/router/examples/simple_routes.rs @@ -54,10 +54,7 @@ fn main() { #[cfg(feature = "liveview")] #[component] fn Root(cx: Scope) -> Element { - let history = LiveviewHistory::new(cx); - render! { Router:: { - config: || RouterConfig::default().history(history), - } } + render! { Router:: {} } } #[cfg(not(feature = "liveview"))] @@ -84,12 +81,19 @@ fn Route1(cx: Scope, user_id: usize, dynamic: usize, query: String, extra: Strin "Route1{{\n\tuser_id:{user_id},\n\tdynamic:{dynamic},\n\tquery:{query},\n\textra:{extra}\n}}" } Link { - to: Route::Route1 { user_id: *user_id, dynamic: *dynamic, query: String::new(), extra: extra.clone() + "." }, + to: Route::Route1 { + user_id: *user_id, + dynamic: *dynamic, + query: String::new(), + extra: extra.clone() + ".", + }, "Route1 with extra+\".\"" } p { "Footer" } Link { - to: Route::Route3 { dynamic: String::new() }, + to: Route::Route3 { + dynamic: String::new(), + }, "Home" } } @@ -98,13 +102,13 @@ fn Route1(cx: Scope, user_id: usize, dynamic: usize, query: String, extra: Strin #[component] fn Route2(cx: Scope, user_id: usize) -> Element { render! { - pre { - "Route2{{\n\tuser_id:{user_id}\n}}" - } + pre { "Route2{{\n\tuser_id:{user_id}\n}}" } (0..*user_id).map(|i| rsx!{ p { "{i}" } }), p { "Footer" } Link { - to: Route::Route3 { dynamic: String::new() }, + to: Route::Route3 { + dynamic: String::new(), + }, "Home" } } @@ -130,22 +134,25 @@ fn Route3(cx: Scope, dynamic: String) -> Element { value: "{current_route_str.read()}" } "dynamic: {dynamic}" - Link { - to: Route::Route2 { user_id: 8888 }, - "hello world link" - } + Link { to: Route::Route2 { user_id: 8888 }, "hello world link" } button { disabled: !navigator.can_go_back(), - onclick: move |_| { navigator.go_back(); }, + onclick: move |_| { + navigator.go_back(); + }, "go back" } button { disabled: !navigator.can_go_forward(), - onclick: move |_| { navigator.go_forward(); }, + onclick: move |_| { + navigator.go_forward(); + }, "go forward" } button { - onclick: move |_| { navigator.push("https://www.google.com"); }, + onclick: move |_| { + navigator.push("https://www.google.com"); + }, "google link" } p { "Site Map" } diff --git a/packages/router/src/history/liveview.rs b/packages/router/src/history/liveview.rs index 9ffb09c34..354d259b1 100644 --- a/packages/router/src/history/liveview.rs +++ b/packages/router/src/history/liveview.rs @@ -132,6 +132,15 @@ where } } +impl Default for LiveviewHistory +where + ::Err: std::fmt::Display, +{ + fn default() -> Self { + Self::new() + } +} + impl LiveviewHistory where ::Err: std::fmt::Display, @@ -141,10 +150,9 @@ where /// /// # Panics /// - /// Panics if not in a Liveview context. - pub fn new(cx: &ScopeState) -> Self { + /// Panics if the function is not called in a dioxus runtime with a Liveview context. + pub fn new() -> Self { Self::new_with_initial_path( - cx, "/".parse().unwrap_or_else(|err| { panic!("index route does not exist:\n{}\n use LiveviewHistory::new_with_initial_path to set a custom path", err) }), @@ -156,17 +164,16 @@ where /// /// # Panics /// - /// Panics if not in a Liveview context. - pub fn new_with_initial_path(cx: &ScopeState, initial_path: R) -> Self { + /// Panics if the function is not called in a dioxus runtime with a Liveview context. + pub fn new_with_initial_path(initial_path: R) -> Self { let (action_tx, action_rx) = tokio::sync::mpsc::unbounded_channel::>(); let action_rx = Arc::new(Mutex::new(action_rx)); let timeline = Arc::new(Mutex::new(Timeline::new(initial_path))); let updater_callback: Arc>> = Arc::new(RwLock::new(Arc::new(|| {}))); - let eval_provider = cx - .consume_context::>() - .expect("evaluator not provided"); + let eval_provider = + consume_context::>().expect("evaluator not provided"); let create_eval = Rc::new(move |script: &str| { eval_provider @@ -175,7 +182,7 @@ where }) as Rc Result>; // Listen to server actions - cx.push_future({ + push_future({ let timeline = timeline.clone(); let action_rx = action_rx.clone(); let create_eval = create_eval.clone(); @@ -235,7 +242,7 @@ where }); // Listen to browser actions - cx.push_future({ + push_future({ let updater = updater_callback.clone(); let timeline = timeline.clone(); let create_eval = create_eval.clone(); @@ -256,15 +263,16 @@ where Option, Option>, usize, - )>(init_eval).expect("serializable state"); + )>(init_eval) + .expect("serializable state"); let Ok(route) = R::from_str(&route.to_string()) else { return; }; let mut timeline = timeline.lock().expect("unpoisoned mutex"); let state = timeline.init(route.clone(), state, session, depth); let state = serde_json::to_string(&state).expect("serializable state"); - let session = serde_json::to_string(&timeline.session()) - .expect("serializable session"); + let session = + serde_json::to_string(&timeline.session()).expect("serializable session"); // Call the updater callback (updater.read().unwrap())(); @@ -288,22 +296,24 @@ where Ok(event) => event, Err(_) => continue, }; - let (route, state) = serde_json::from_value::<(String, Option)>(event).expect("serializable state"); + let (route, state) = serde_json::from_value::<(String, Option)>(event) + .expect("serializable state"); let Ok(route) = R::from_str(&route.to_string()) else { return; }; let mut timeline = timeline.lock().expect("unpoisoned mutex"); let state = timeline.update(route.clone(), state); let state = serde_json::to_string(&state).expect("serializable state"); - let session = serde_json::to_string(&timeline.session()) - .expect("serializable session"); + let session = + serde_json::to_string(&timeline.session()).expect("serializable session"); let _ = create_eval(&format!( r#" // this does not trigger a PopState event history.replaceState({state}, "", "{route}"); sessionStorage.setItem("liveview", '{session}'); - "#)); + "# + )); // Call the updater callback (updater.read().unwrap())(); diff --git a/packages/router/src/router_cfg.rs b/packages/router/src/router_cfg.rs index dd379e493..d243209f6 100644 --- a/packages/router/src/router_cfg.rs +++ b/packages/router/src/router_cfg.rs @@ -53,10 +53,15 @@ where { pub(crate) fn get_history(self) -> Box> { self.history.unwrap_or_else(|| { - #[cfg(all(target_arch = "wasm32", feature = "web"))] + #[cfg(all(not(feature = "liveview"), target_arch = "wasm32", feature = "web"))] let history = Box::>::default(); - #[cfg(not(all(target_arch = "wasm32", feature = "web")))] + #[cfg(all( + not(feature = "liveview"), + any(not(target_arch = "wasm32"), not(feature = "web")) + ))] let history = Box::>::default(); + #[cfg(feature = "liveview")] + let history = Box::>::default(); history }) } @@ -83,10 +88,15 @@ where { pub(crate) fn take_history(&mut self) -> Box { self.history.take().unwrap_or_else(|| { - #[cfg(all(target_arch = "wasm32", feature = "web"))] + #[cfg(all(not(feature = "liveview"), target_arch = "wasm32", feature = "web"))] let history = Box::>>::default(); - #[cfg(not(all(target_arch = "wasm32", feature = "web")))] + #[cfg(all( + not(feature = "liveview"), + any(not(target_arch = "wasm32"), not(feature = "web")) + ))] let history = Box::>>::default(); + #[cfg(feature = "liveview")] + let history = Box::>>::default(); history }) } From cfbec8240e3864fd808b8a0c1185b39e895aed8f Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Mon, 8 Jan 2024 13:50:01 -0600 Subject: [PATCH 2/2] make the web history a higher priority than the liveview history when compiling to wasm --- packages/router/src/router_cfg.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/router/src/router_cfg.rs b/packages/router/src/router_cfg.rs index d243209f6..e0d2ce358 100644 --- a/packages/router/src/router_cfg.rs +++ b/packages/router/src/router_cfg.rs @@ -88,15 +88,18 @@ where { pub(crate) fn take_history(&mut self) -> Box { self.history.take().unwrap_or_else(|| { - #[cfg(all(not(feature = "liveview"), target_arch = "wasm32", feature = "web"))] + // If we are on wasm32 and the web feature is enabled, use the web history. + #[cfg(all(target_arch = "wasm32", feature = "web"))] let history = Box::>>::default(); + // If we are not on wasm32 and the liveview feature is enabled, use the liveview history. + #[cfg(all(feature = "liveview", not(target_arch = "wasm32")))] + let history = Box::>>::default(); + // If neither of the above are true, use the memory history. #[cfg(all( - not(feature = "liveview"), - any(not(target_arch = "wasm32"), not(feature = "web")) + not(all(target_arch = "wasm32", feature = "web")), + not(all(feature = "liveview", not(target_arch = "wasm32"))), ))] let history = Box::>>::default(); - #[cfg(feature = "liveview")] - let history = Box::>>::default(); history }) }