Skip to content
This repository was archived by the owner on Jul 19, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/yew_router_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ mod switch;
/// ```
/// use yew_router::Switch;
///
/// #[derive(Switch)]
/// #[derive(Switch, Clone)]
/// enum AppRoute {
/// #[to = "/some/simple/route"]
/// SomeSimpleRoute,
Expand All @@ -68,7 +68,7 @@ mod switch;
/// Inner(InnerRoute),
/// }
///
/// #[derive(Switch)]
/// #[derive(Switch, Clone)]
/// #[to = "/inner/route/{first}/{second}"]
/// struct InnerRoute {
/// first: String,
Expand Down
2 changes: 1 addition & 1 deletion examples/minimal/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum Msg {
ChangeRoute(AppRoute),
}

#[derive(Debug, Switch)]
#[derive(Debug, Switch, Clone)]
pub enum AppRoute {
#[to = "/a/{anything}"]
A(String),
Expand Down
2 changes: 1 addition & 1 deletion examples/router_component/src/b_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub struct Props {
pub sub_path: Option<String>,
}

#[derive(Debug, Switch)]
#[derive(Debug, Switch, Clone)]
pub enum BRoute {
#[to = "/{num}?sup_path={sub_path}"]
Both(usize, String),
Expand Down
4 changes: 2 additions & 2 deletions examples/router_component/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl Component for Model {
}
}

#[derive(Debug, Switch)]
#[derive(Debug, Switch, Clone)]
pub enum AppRoute {
#[to = "/a{*:inner}"]
A(AllowMissing<ARoute>),
Expand All @@ -90,6 +90,6 @@ pub enum AppRoute {
PageNotFound(Option<String>),
}

#[derive(Debug, Switch, PartialEq, Clone)]
#[derive(Debug, Switch, PartialEq, Clone, Copy)]
#[to = "/c"]
pub struct ARoute;
8 changes: 4 additions & 4 deletions examples/switch/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn main() {
println!("{}", buf);
}

#[derive(Debug, Switch)]
#[derive(Debug, Switch, Clone)]
pub enum AppRoute {
#[to = "/some/route"]
SomeRoute,
Expand All @@ -77,21 +77,21 @@ pub enum AppRoute {
MissingCapture(Option<String>),
}

#[derive(Switch, Debug)]
#[derive(Switch, Debug, Clone)]
pub enum InnerRoute {
#[to = "/left"]
Left,
#[to = "/right"]
Right,
}

#[derive(Switch, Debug)]
#[derive(Switch, Debug, Clone)]
#[to = "/single/{number}"]
pub struct Single {
number: u32,
}

#[derive(Switch, Debug)]
#[derive(Switch, Debug, Clone)]
#[to = "/othersingle/{number}"]
pub struct OtherSingle(u32);

Expand Down
54 changes: 31 additions & 23 deletions src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,32 +55,33 @@ impl<'de, T> RouterState<'de> for T where T: AgentState<'de> + PartialEq {}
/// }
/// }
///
/// #[derive(Switch)]
/// #[derive(Switch, Clone)]
/// enum S {
/// #[to = "/v"]
/// Variant,
/// }
/// ```
#[derive(Debug)]
pub struct Router<T: for<'de> RouterState<'de>, SW: Switch + 'static, M: 'static> {
route: Route<T>,
pub struct Router<T: for<'de> RouterState<'de>, SW: Switch + Clone + 'static, M: 'static> {
switch: Option<SW>,
props: Props<T, SW, M>,
router_agent: RouteAgentBridge<T>,
}

impl<T, SW, M> Router<T, SW, M>
where
T: for<'de> RouterState<'de>,
SW: Switch + 'static,
SW: Switch + Clone + 'static,
M: 'static,
{
// TODO render fn name is overloaded now with that of the trait: Renderable<_> this should be changed. Maybe: display, show, switch, inner...
/// Wrap a render closure so that it can be used by the Router.
/// # Example
/// ```
/// # use yew_router::Switch;
/// # use yew_router::router::Router;
/// # use yew::{html, Html};
/// # #[derive(Switch)]
/// # #[derive(Switch, Clone)]
/// # enum S {
/// # #[to = "/route"]
/// # Variant
Expand Down Expand Up @@ -124,16 +125,16 @@ impl<T, M> From<M> for Msg<T, M> {
pub trait RenderFn<CTX: Component, SW>: Fn(SW) -> Html<CTX> {}
impl<T, CTX: Component, SW> RenderFn<CTX, SW> for T where T: Fn(SW) -> Html<CTX> {}
/// Owned Render function.
pub struct Render<T: for<'de> RouterState<'de>, SW: Switch + 'static, M: 'static>(
pub struct Render<T: for<'de> RouterState<'de>, SW: Switch + Clone+ 'static, M: 'static>(
pub(crate) Rc<dyn RenderFn<Router<T, SW, M>, SW>>,
);
impl<T: for<'de> RouterState<'de>, SW: Switch, M> Render<T, SW, M> {
impl<T: for<'de> RouterState<'de>, SW: Switch + Clone, M> Render<T, SW, M> {
/// New render function
fn new<F: RenderFn<Router<T, SW, M>, SW> + 'static>(f: F) -> Self {
Render(Rc::new(f))
}
}
impl<T: for<'de> RouterState<'de>, SW: Switch, M> Debug for Render<T, SW, M> {
impl<T: for<'de> RouterState<'de>, SW: Switch + Clone, M> Debug for Render<T, SW, M> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Render").finish()
}
Expand Down Expand Up @@ -162,7 +163,7 @@ impl<STATE: for<'de> RouterState<'de>, SW: Switch, M> Debug for Redirect<SW, STA

/// Properties for Router.
#[derive(Properties)]
pub struct Props<T: for<'de> RouterState<'de>, SW: Switch + 'static, M: 'static> {
pub struct Props<T: for<'de> RouterState<'de>, SW: Switch + Clone + 'static, M: 'static> {
/// Render function that
#[props(required)]
pub render: Render<T, SW, M>,
Expand All @@ -174,7 +175,7 @@ pub struct Props<T: for<'de> RouterState<'de>, SW: Switch + 'static, M: 'static>
pub callback: Option<Callback<M>>,
}

impl<T: for<'de> RouterState<'de>, SW: Switch, M> Debug for Props<T, SW, M> {
impl<T: for<'de> RouterState<'de>, SW: Switch + Clone, M> Debug for Props<T, SW, M> {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
f.debug_struct("Props").finish()
}
Expand All @@ -183,7 +184,7 @@ impl<T: for<'de> RouterState<'de>, SW: Switch, M> Debug for Props<T, SW, M> {
impl<T, SW, M> Component for Router<T, SW, M>
where
T: for<'de> RouterState<'de>,
SW: Switch + 'static,
SW: Switch + Clone + 'static,
M: 'static,
{
type Message = Msg<T, M>;
Expand All @@ -194,7 +195,7 @@ where
let router_agent = RouteAgentBridge::new(callback);

Router {
route: Default::default(), /* This must be updated by immediately requesting a route
switch: Default::default(), /* This must be updated by immediately requesting a route
* update from the service bridge. */
props,
router_agent,
Expand All @@ -209,9 +210,21 @@ where
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::UpdateRoute(route) => {
let did_change = self.route != route;
self.route = route;
did_change
let mut switch = SW::switch(route.clone());

if switch.is_none() {
if let Some(redirect) = &self.props.redirect {
let redirected: SW = (&redirect.0)(route);

log::trace!("Route failed to match, but redirecting route to a known switch.");
// Replace the route in the browser with the redirected.
self.router_agent.send(RouteRequest::ReplaceRouteNoBroadcast(redirected.clone().into()));
switch = Some(redirected)
}
}

self.switch = switch;
true
}
Msg::InnerMessage(m) => {
if let Some(cb) = &self.props.callback {
Expand All @@ -228,16 +241,11 @@ where
}

fn view(&self) -> VNode<Self> {
let switch: Option<SW> = SW::switch(self.route.clone());
match switch {
match self.switch.clone() {
Some(switch) => (&self.props.render.0)(switch),
None => {
if let Some(redirect_fn) = &self.props.redirect {
let switch: SW = (redirect_fn.0)(self.route.clone()); // TODO This should be used to set the route in the browser https://github.com/yewstack/yew_router/issues/171
(&self.props.render.0)(switch)
} else {
html! {format!{"No route for {}", self.route.route}}
}
log::warn!("No route matched, provide a redirect prop to the router to handle cases where no route can be matched");
html! {"No route matched"}
}
}
}
Expand Down
Loading