enabled the liveview history by default if the liveview feature is enabled in the router
This commit is contained in:
1 parent
cd019db9ef
commit
3feee729bc
3 files changed
+65
-38
No files matched your search
@@ -54,10 +54,7 @@ fn main() {
|
|||||||
#[cfg(feature = "liveview")]
|
#[cfg(feature = "liveview")]
|
||||||
#[component]
|
#[component]
|
||||||
fn Root(cx: Scope) -> Element {
|
fn Root(cx: Scope) -> Element {
|
||||||
let history = LiveviewHistory::new(cx);
|
render! { Router::<Route> {} }
|
||||||
render! { Router::<Route> {
|
|
||||||
config: || RouterConfig::default().history(history),
|
|
||||||
} }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "liveview"))]
|
#[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}}"
|
"Route1{{\n\tuser_id:{user_id},\n\tdynamic:{dynamic},\n\tquery:{query},\n\textra:{extra}\n}}"
|
||||||
}
|
}
|
||||||
Link {
|
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+\".\""
|
"Route1 with extra+\".\""
|
||||||
}
|
}
|
||||||
p { "Footer" }
|
p { "Footer" }
|
||||||
Link {
|
Link {
|
||||||
to: Route::Route3 { dynamic: String::new() },
|
to: Route::Route3 {
|
||||||
|
dynamic: String::new(),
|
||||||
|
},
|
||||||
"Home"
|
"Home"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,13 +102,13 @@ fn Route1(cx: Scope, user_id: usize, dynamic: usize, query: String, extra: Strin
|
|||||||
#[component]
|
#[component]
|
||||||
fn Route2(cx: Scope, user_id: usize) -> Element {
|
fn Route2(cx: Scope, user_id: usize) -> Element {
|
||||||
render! {
|
render! {
|
||||||
pre {
|
pre { "Route2{{\n\tuser_id:{user_id}\n}}" }
|
||||||
"Route2{{\n\tuser_id:{user_id}\n}}"
|
|
||||||
}
|
|
||||||
(0..*user_id).map(|i| rsx!{ p { "{i}" } }),
|
(0..*user_id).map(|i| rsx!{ p { "{i}" } }),
|
||||||
p { "Footer" }
|
p { "Footer" }
|
||||||
Link {
|
Link {
|
||||||
to: Route::Route3 { dynamic: String::new() },
|
to: Route::Route3 {
|
||||||
|
dynamic: String::new(),
|
||||||
|
},
|
||||||
"Home"
|
"Home"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,22 +134,25 @@ fn Route3(cx: Scope, dynamic: String) -> Element {
|
|||||||
value: "{current_route_str.read()}"
|
value: "{current_route_str.read()}"
|
||||||
}
|
}
|
||||||
"dynamic: {dynamic}"
|
"dynamic: {dynamic}"
|
||||||
Link {
|
Link { to: Route::Route2 { user_id: 8888 }, "hello world link" }
|
||||||
to: Route::Route2 { user_id: 8888 },
|
|
||||||
"hello world link"
|
|
||||||
}
|
|
||||||
button {
|
button {
|
||||||
disabled: !navigator.can_go_back(),
|
disabled: !navigator.can_go_back(),
|
||||||
onclick: move |_| { navigator.go_back(); },
|
onclick: move |_| {
|
||||||
|
navigator.go_back();
|
||||||
|
},
|
||||||
"go back"
|
"go back"
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
disabled: !navigator.can_go_forward(),
|
disabled: !navigator.can_go_forward(),
|
||||||
onclick: move |_| { navigator.go_forward(); },
|
onclick: move |_| {
|
||||||
|
navigator.go_forward();
|
||||||
|
},
|
||||||
"go forward"
|
"go forward"
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
onclick: move |_| { navigator.push("https://www.google.com"); },
|
onclick: move |_| {
|
||||||
|
navigator.push("https://www.google.com");
|
||||||
|
},
|
||||||
"google link"
|
"google link"
|
||||||
}
|
}
|
||||||
p { "Site Map" }
|
p { "Site Map" }
|
||||||
|
|||||||
@@ -132,6 +132,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<R: Routable> Default for LiveviewHistory<R>
|
||||||
|
where
|
||||||
|
<R as FromStr>::Err: std::fmt::Display,
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<R: Routable> LiveviewHistory<R>
|
impl<R: Routable> LiveviewHistory<R>
|
||||||
where
|
where
|
||||||
<R as FromStr>::Err: std::fmt::Display,
|
<R as FromStr>::Err: std::fmt::Display,
|
||||||
@@ -141,10 +150,9 @@ where
|
|||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if not in a Liveview context.
|
/// Panics if the function is not called in a dioxus runtime with a Liveview context.
|
||||||
pub fn new(cx: &ScopeState) -> Self {
|
pub fn new() -> Self {
|
||||||
Self::new_with_initial_path(
|
Self::new_with_initial_path(
|
||||||
cx,
|
|
||||||
"/".parse().unwrap_or_else(|err| {
|
"/".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)
|
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
|
||||||
///
|
///
|
||||||
/// Panics if not in a Liveview context.
|
/// Panics if the function is not called in a dioxus runtime with a Liveview context.
|
||||||
pub fn new_with_initial_path(cx: &ScopeState, initial_path: R) -> Self {
|
pub fn new_with_initial_path(initial_path: R) -> Self {
|
||||||
let (action_tx, action_rx) = tokio::sync::mpsc::unbounded_channel::<Action<R>>();
|
let (action_tx, action_rx) = tokio::sync::mpsc::unbounded_channel::<Action<R>>();
|
||||||
let action_rx = Arc::new(Mutex::new(action_rx));
|
let action_rx = Arc::new(Mutex::new(action_rx));
|
||||||
let timeline = Arc::new(Mutex::new(Timeline::new(initial_path)));
|
let timeline = Arc::new(Mutex::new(Timeline::new(initial_path)));
|
||||||
let updater_callback: Arc<RwLock<Arc<dyn Fn() + Send + Sync>>> =
|
let updater_callback: Arc<RwLock<Arc<dyn Fn() + Send + Sync>>> =
|
||||||
Arc::new(RwLock::new(Arc::new(|| {})));
|
Arc::new(RwLock::new(Arc::new(|| {})));
|
||||||
|
|
||||||
let eval_provider = cx
|
let eval_provider =
|
||||||
.consume_context::<Rc<dyn EvalProvider>>()
|
consume_context::<Rc<dyn EvalProvider>>().expect("evaluator not provided");
|
||||||
.expect("evaluator not provided");
|
|
||||||
|
|
||||||
let create_eval = Rc::new(move |script: &str| {
|
let create_eval = Rc::new(move |script: &str| {
|
||||||
eval_provider
|
eval_provider
|
||||||
@@ -175,7 +182,7 @@ where
|
|||||||
}) as Rc<dyn Fn(&str) -> Result<UseEval, EvalError>>;
|
}) as Rc<dyn Fn(&str) -> Result<UseEval, EvalError>>;
|
||||||
|
|
||||||
// Listen to server actions
|
// Listen to server actions
|
||||||
cx.push_future({
|
push_future({
|
||||||
let timeline = timeline.clone();
|
let timeline = timeline.clone();
|
||||||
let action_rx = action_rx.clone();
|
let action_rx = action_rx.clone();
|
||||||
let create_eval = create_eval.clone();
|
let create_eval = create_eval.clone();
|
||||||
@@ -235,7 +242,7 @@ where
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Listen to browser actions
|
// Listen to browser actions
|
||||||
cx.push_future({
|
push_future({
|
||||||
let updater = updater_callback.clone();
|
let updater = updater_callback.clone();
|
||||||
let timeline = timeline.clone();
|
let timeline = timeline.clone();
|
||||||
let create_eval = create_eval.clone();
|
let create_eval = create_eval.clone();
|
||||||
@@ -256,15 +263,16 @@ where
|
|||||||
Option<State>,
|
Option<State>,
|
||||||
Option<Session<R>>,
|
Option<Session<R>>,
|
||||||
usize,
|
usize,
|
||||||
)>(init_eval).expect("serializable state");
|
)>(init_eval)
|
||||||
|
.expect("serializable state");
|
||||||
let Ok(route) = R::from_str(&route.to_string()) else {
|
let Ok(route) = R::from_str(&route.to_string()) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let mut timeline = timeline.lock().expect("unpoisoned mutex");
|
let mut timeline = timeline.lock().expect("unpoisoned mutex");
|
||||||
let state = timeline.init(route.clone(), state, session, depth);
|
let state = timeline.init(route.clone(), state, session, depth);
|
||||||
let state = serde_json::to_string(&state).expect("serializable state");
|
let state = serde_json::to_string(&state).expect("serializable state");
|
||||||
let session = serde_json::to_string(&timeline.session())
|
let session =
|
||||||
.expect("serializable session");
|
serde_json::to_string(&timeline.session()).expect("serializable session");
|
||||||
|
|
||||||
// Call the updater callback
|
// Call the updater callback
|
||||||
(updater.read().unwrap())();
|
(updater.read().unwrap())();
|
||||||
@@ -288,22 +296,24 @@ where
|
|||||||
Ok(event) => event,
|
Ok(event) => event,
|
||||||
Err(_) => continue,
|
Err(_) => continue,
|
||||||
};
|
};
|
||||||
let (route, state) = serde_json::from_value::<(String, Option<State>)>(event).expect("serializable state");
|
let (route, state) = serde_json::from_value::<(String, Option<State>)>(event)
|
||||||
|
.expect("serializable state");
|
||||||
let Ok(route) = R::from_str(&route.to_string()) else {
|
let Ok(route) = R::from_str(&route.to_string()) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let mut timeline = timeline.lock().expect("unpoisoned mutex");
|
let mut timeline = timeline.lock().expect("unpoisoned mutex");
|
||||||
let state = timeline.update(route.clone(), state);
|
let state = timeline.update(route.clone(), state);
|
||||||
let state = serde_json::to_string(&state).expect("serializable state");
|
let state = serde_json::to_string(&state).expect("serializable state");
|
||||||
let session = serde_json::to_string(&timeline.session())
|
let session =
|
||||||
.expect("serializable session");
|
serde_json::to_string(&timeline.session()).expect("serializable session");
|
||||||
|
|
||||||
let _ = create_eval(&format!(
|
let _ = create_eval(&format!(
|
||||||
r#"
|
r#"
|
||||||
// this does not trigger a PopState event
|
// this does not trigger a PopState event
|
||||||
history.replaceState({state}, "", "{route}");
|
history.replaceState({state}, "", "{route}");
|
||||||
sessionStorage.setItem("liveview", '{session}');
|
sessionStorage.setItem("liveview", '{session}');
|
||||||
"#));
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
// Call the updater callback
|
// Call the updater callback
|
||||||
(updater.read().unwrap())();
|
(updater.read().unwrap())();
|
||||||
|
|||||||
@@ -53,10 +53,15 @@ where
|
|||||||
{
|
{
|
||||||
pub(crate) fn get_history(self) -> Box<dyn HistoryProvider<R>> {
|
pub(crate) fn get_history(self) -> Box<dyn HistoryProvider<R>> {
|
||||||
self.history.unwrap_or_else(|| {
|
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::<WebHistory<R>>::default();
|
let history = Box::<WebHistory<R>>::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::<MemoryHistory<R>>::default();
|
let history = Box::<MemoryHistory<R>>::default();
|
||||||
|
#[cfg(feature = "liveview")]
|
||||||
|
let history = Box::<LiveviewHistory<R>>::default();
|
||||||
history
|
history
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -83,10 +88,15 @@ where
|
|||||||
{
|
{
|
||||||
pub(crate) fn take_history(&mut self) -> Box<dyn AnyHistoryProvider> {
|
pub(crate) fn take_history(&mut self) -> Box<dyn AnyHistoryProvider> {
|
||||||
self.history.take().unwrap_or_else(|| {
|
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::<AnyHistoryProviderImplWrapper<R, WebHistory<R>>>::default();
|
let history = Box::<AnyHistoryProviderImplWrapper<R, WebHistory<R>>>::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::<AnyHistoryProviderImplWrapper<R, MemoryHistory<R>>>::default();
|
let history = Box::<AnyHistoryProviderImplWrapper<R, MemoryHistory<R>>>::default();
|
||||||
|
#[cfg(feature = "liveview")]
|
||||||
|
let history = Box::<AnyHistoryProviderImplWrapper<R, LiveviewHistory<R>>>::default();
|
||||||
history
|
history
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user