mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
feat: add missing server fn redirect hook to router (#2815)
This commit is contained in:
parent
27dbadb7d2
commit
893d47f1c5
3 changed files with 60 additions and 6 deletions
|
@ -69,25 +69,33 @@ where
|
|||
Chil: IntoView,
|
||||
{
|
||||
#[cfg(feature = "ssr")]
|
||||
let current_url = {
|
||||
let (current_url, redirect_hook) = {
|
||||
let req = use_context::<RequestUrl>().expect("no RequestUrl provided");
|
||||
let parsed = req.parse().expect("could not parse RequestUrl");
|
||||
ArcRwSignal::new(parsed)
|
||||
let current_url = ArcRwSignal::new(parsed);
|
||||
|
||||
(current_url, Box::new(move |_: &str| {}))
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
let current_url = {
|
||||
let (current_url, redirect_hook) = {
|
||||
let location =
|
||||
BrowserUrl::new().expect("could not access browser navigation"); // TODO options here
|
||||
location.init(base.clone());
|
||||
provide_context(location.clone());
|
||||
location.as_url().clone()
|
||||
let current_url = location.as_url().clone();
|
||||
|
||||
let redirect_hook = Box::new(|loc: &str| BrowserUrl::redirect(loc));
|
||||
|
||||
(current_url, redirect_hook)
|
||||
};
|
||||
// provide router context
|
||||
let state = ArcRwSignal::new(State::new(None));
|
||||
let location = Location::new(current_url.read_only(), state.read_only());
|
||||
|
||||
// TODO server function redirect hook
|
||||
// set server function redirect hook
|
||||
_ = server_fn::redirect::set_redirect_hook(redirect_hook);
|
||||
|
||||
provide_context(RouterContext {
|
||||
base,
|
||||
current_url,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use super::{handle_anchor_click, LocationChange, LocationProvider, Url};
|
||||
use crate::params::ParamsMap;
|
||||
use crate::{hooks::use_navigate, params::ParamsMap};
|
||||
use core::fmt;
|
||||
use futures::channel::oneshot;
|
||||
use js_sys::{try_iter, Array, JsString};
|
||||
use leptos::prelude::*;
|
||||
use or_poisoned::OrPoisoned;
|
||||
use reactive_graph::{
|
||||
signal::ArcRwSignal,
|
||||
|
@ -206,6 +207,24 @@ impl LocationProvider for BrowserUrl {
|
|||
// scroll to el
|
||||
Self::scroll_to_el(loc.scroll);
|
||||
}
|
||||
|
||||
fn redirect(loc: &str) {
|
||||
let navigate = use_navigate();
|
||||
let Some(url) = resolve_redirect_url(loc) else {
|
||||
return; // resolve_redirect_url() already logs an error
|
||||
};
|
||||
let current_origin = helpers::location().origin().unwrap();
|
||||
if url.origin() == current_origin {
|
||||
let navigate = navigate.clone();
|
||||
// delay by a tick here, so that the Action updates *before* the redirect
|
||||
request_animation_frame(move || {
|
||||
navigate(&url.href(), Default::default());
|
||||
});
|
||||
// Use set_href() if the conditions for client-side navigation were not satisfied
|
||||
} else if let Err(e) = helpers::location().set_href(&url.href()) {
|
||||
leptos::logging::error!("Failed to redirect: {e:#?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn search_params_from_web_url(
|
||||
|
@ -225,3 +244,28 @@ fn search_params_from_web_url(
|
|||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Resolves a redirect location to an (absolute) URL.
|
||||
pub(crate) fn resolve_redirect_url(loc: &str) -> Option<web_sys::Url> {
|
||||
let origin = match window().location().origin() {
|
||||
Ok(origin) => origin,
|
||||
Err(e) => {
|
||||
leptos::logging::error!("Failed to get origin: {:#?}", e);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Use server function's URL as base instead.
|
||||
let base = origin;
|
||||
|
||||
match web_sys::Url::new_with_base(loc, &base) {
|
||||
Ok(url) => Some(url),
|
||||
Err(e) => {
|
||||
leptos::logging::error!(
|
||||
"Invalid redirect location: {}",
|
||||
e.as_string().unwrap_or_default(),
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,6 +165,8 @@ pub trait LocationProvider: Clone + 'static {
|
|||
}
|
||||
|
||||
fn parse_with_base(url: &str, base: &str) -> Result<Url, Self::Error>;
|
||||
|
||||
fn redirect(loc: &str);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
|
Loading…
Reference in a new issue