mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 16:54:41 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebea3ec14d | ||
|
|
ed3ca9eae1 | ||
|
|
ed8abcfbcd | ||
|
|
29a56af38c | ||
|
|
f9d6f7fd64 | ||
|
|
251a472cd5 | ||
|
|
3c76cb24d3 |
@@ -21,10 +21,16 @@ pub fn Nav() -> impl IntoView {
|
||||
<A href="/job">
|
||||
<strong>"Jobs"</strong>
|
||||
</A>
|
||||
<a class="github" href="http://github.com/leptos-rs/leptos" target="_blank" rel="noreferrer">
|
||||
<a
|
||||
class="github"
|
||||
href="http://github.com/leptos-rs/leptos"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
"Built with Leptos"
|
||||
</a>
|
||||
</nav>
|
||||
</header>
|
||||
}
|
||||
.into_any()
|
||||
}
|
||||
|
||||
@@ -50,30 +50,42 @@ pub fn Stories() -> impl IntoView {
|
||||
<div class="news-view">
|
||||
<div class="news-list-nav">
|
||||
<span>
|
||||
{move || if page() > 1 {
|
||||
Either::Left(view! {
|
||||
<a class="page-link"
|
||||
href=move || format!("/{}?page={}", story_type(), page() - 1)
|
||||
aria-label="Previous Page"
|
||||
>
|
||||
"< prev"
|
||||
</a>
|
||||
})
|
||||
} else {
|
||||
Either::Right(view! {
|
||||
<span class="page-link disabled" aria-hidden="true">
|
||||
"< prev"
|
||||
</span>
|
||||
})
|
||||
{move || {
|
||||
if page() > 1 {
|
||||
Either::Left(
|
||||
view! {
|
||||
<a
|
||||
class="page-link"
|
||||
href=move || {
|
||||
format!("/{}?page={}", story_type(), page() - 1)
|
||||
}
|
||||
aria-label="Previous Page"
|
||||
>
|
||||
"< prev"
|
||||
</a>
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Either::Right(
|
||||
view! {
|
||||
<span class="page-link disabled" aria-hidden="true">
|
||||
"< prev"
|
||||
</span>
|
||||
},
|
||||
)
|
||||
}
|
||||
}}
|
||||
|
||||
</span>
|
||||
<span>"page " {page}</span>
|
||||
<Suspense>
|
||||
<span class="page-link"
|
||||
<span
|
||||
class="page-link"
|
||||
class:disabled=hide_more_link
|
||||
aria-hidden=hide_more_link
|
||||
>
|
||||
<a href=move || format!("/{}?page={}", story_type(), page() + 1)
|
||||
<a
|
||||
href=move || format!("/{}?page={}", story_type(), page() + 1)
|
||||
aria-label="Next Page"
|
||||
>
|
||||
"more >"
|
||||
@@ -83,14 +95,10 @@ pub fn Stories() -> impl IntoView {
|
||||
</div>
|
||||
<main class="news-list">
|
||||
<div>
|
||||
<Transition
|
||||
fallback=move || view! { <p>"Loading..."</p> }
|
||||
set_pending
|
||||
>
|
||||
<Show when=move || stories.read().as_ref().map(Option::is_none).unwrap_or(false)>
|
||||
>
|
||||
<p>"Error loading stories."</p>
|
||||
</Show>
|
||||
<Transition fallback=move || view! { <p>"Loading..."</p> } set_pending>
|
||||
<Show when=move || {
|
||||
stories.read().as_ref().map(Option::is_none).unwrap_or(false)
|
||||
}>> <p>"Error loading stories."</p></Show>
|
||||
<ul>
|
||||
<For
|
||||
each=move || stories.get().unwrap_or_default().unwrap_or_default()
|
||||
@@ -105,54 +113,78 @@ pub fn Stories() -> impl IntoView {
|
||||
</main>
|
||||
</div>
|
||||
}
|
||||
.into_any()
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Story(story: api::Story) -> impl IntoView {
|
||||
view! {
|
||||
<li class="news-item">
|
||||
<li class="news-item">
|
||||
<span class="score">{story.points}</span>
|
||||
<span class="title">
|
||||
{if !story.url.starts_with("item?id=") {
|
||||
Either::Left(view! {
|
||||
<span>
|
||||
<a href=story.url target="_blank" rel="noreferrer">
|
||||
{story.title.clone()}
|
||||
</a>
|
||||
<span class="host">"("{story.domain}")"</span>
|
||||
</span>
|
||||
})
|
||||
Either::Left(
|
||||
view! {
|
||||
<span>
|
||||
<a href=story.url target="_blank" rel="noreferrer">
|
||||
{story.title.clone()}
|
||||
</a>
|
||||
<span class="host">"(" {story.domain} ")"</span>
|
||||
</span>
|
||||
},
|
||||
)
|
||||
} else {
|
||||
let title = story.title.clone();
|
||||
Either::Right(view! { <A href=format!("/stories/{}", story.id)>{title}</A> })
|
||||
}}
|
||||
|
||||
</span>
|
||||
<br />
|
||||
<br/>
|
||||
<span class="meta">
|
||||
{if story.story_type != "job" {
|
||||
Either::Left(view! {
|
||||
<span>
|
||||
{"by "}
|
||||
{story.user.map(|user| view ! { <A href=format!("/users/{user}")>{user.clone()}</A>})}
|
||||
{format!(" {} | ", story.time_ago)}
|
||||
<A href=format!("/stories/{}", story.id)>
|
||||
{if story.comments_count.unwrap_or_default() > 0 {
|
||||
format!("{} comments", story.comments_count.unwrap_or_default())
|
||||
} else {
|
||||
"discuss".into()
|
||||
}}
|
||||
</A>
|
||||
</span>
|
||||
})
|
||||
Either::Left(
|
||||
view! {
|
||||
<span>
|
||||
{"by "}
|
||||
{story
|
||||
.user
|
||||
.map(|user| {
|
||||
view! {
|
||||
<A href=format!("/users/{user}")>{user.clone()}</A>
|
||||
}
|
||||
})} {format!(" {} | ", story.time_ago)}
|
||||
<A href=format!(
|
||||
"/stories/{}",
|
||||
story.id,
|
||||
)>
|
||||
{if story.comments_count.unwrap_or_default() > 0 {
|
||||
format!(
|
||||
"{} comments",
|
||||
story.comments_count.unwrap_or_default(),
|
||||
)
|
||||
} else {
|
||||
"discuss".into()
|
||||
}}
|
||||
|
||||
</A>
|
||||
</span>
|
||||
},
|
||||
)
|
||||
} else {
|
||||
let title = story.title.clone();
|
||||
Either::Right(view! { <A href=format!("/item/{}", story.id)>{title}</A> })
|
||||
}}
|
||||
|
||||
</span>
|
||||
{(story.story_type != "link").then(|| view! {
|
||||
" "
|
||||
<span class="label">{story.story_type}</span>
|
||||
})}
|
||||
{(story.story_type != "link")
|
||||
.then(|| {
|
||||
view! {
|
||||
" "
|
||||
<span class="label">{story.story_type}</span>
|
||||
}
|
||||
})}
|
||||
|
||||
</li>
|
||||
}
|
||||
.into_any()
|
||||
}
|
||||
|
||||
@@ -28,18 +28,21 @@ pub fn Story() -> impl IntoView {
|
||||
<Meta name="description" content=story.title.clone()/>
|
||||
<div class="item-view">
|
||||
<div class="item-view-header">
|
||||
<a href=story.url target="_blank">
|
||||
<h1>{story.title}</h1>
|
||||
</a>
|
||||
<span class="host">
|
||||
"("{story.domain}")"
|
||||
</span>
|
||||
{story.user.map(|user| view! { <p class="meta">
|
||||
{story.points}
|
||||
" points | by "
|
||||
<A href=format!("/users/{user}")>{user.clone()}</A>
|
||||
{format!(" {}", story.time_ago)}
|
||||
</p>})}
|
||||
<a href=story.url target="_blank">
|
||||
<h1>{story.title}</h1>
|
||||
</a>
|
||||
<span class="host">"(" {story.domain} ")"</span>
|
||||
{story
|
||||
.user
|
||||
.map(|user| {
|
||||
view! {
|
||||
<p class="meta">
|
||||
{story.points} " points | by "
|
||||
<A href=format!("/users/{user}")>{user.clone()}</A>
|
||||
{format!(" {}", story.time_ago)}
|
||||
</p>
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
<div class="item-view-comments">
|
||||
<p class="item-view-comments-header">
|
||||
@@ -48,6 +51,7 @@ pub fn Story() -> impl IntoView {
|
||||
} else {
|
||||
"No comments yet.".into()
|
||||
}}
|
||||
|
||||
</p>
|
||||
<ul class="comment-children">
|
||||
<For
|
||||
@@ -55,7 +59,7 @@ pub fn Story() -> impl IntoView {
|
||||
key=|comment| comment.id
|
||||
let:comment
|
||||
>
|
||||
<Comment comment />
|
||||
<Comment comment/>
|
||||
</For>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -64,6 +68,7 @@ pub fn Story() -> impl IntoView {
|
||||
}
|
||||
}
|
||||
}))).build())
|
||||
.into_any()
|
||||
}
|
||||
|
||||
#[component]
|
||||
@@ -72,43 +77,65 @@ pub fn Comment(comment: api::Comment) -> impl IntoView {
|
||||
|
||||
view! {
|
||||
<li class="comment">
|
||||
<div class="by">
|
||||
<A href=format!("/users/{}", comment.user.clone().unwrap_or_default())>{comment.user.clone()}</A>
|
||||
{format!(" {}", comment.time_ago)}
|
||||
</div>
|
||||
<div class="text" inner_html=comment.content></div>
|
||||
{(!comment.comments.is_empty()).then(|| {
|
||||
view! {
|
||||
<div>
|
||||
<div class="toggle" class:open=open>
|
||||
<a on:click=move |_| set_open.update(|n| *n = !*n)>
|
||||
{
|
||||
let comments_len = comment.comments.len();
|
||||
move || if open.get() {
|
||||
"[-]".into()
|
||||
} else {
|
||||
format!("[+] {}{} collapsed", comments_len, pluralize(comments_len))
|
||||
}
|
||||
}
|
||||
</a>
|
||||
</div>
|
||||
{move || open.get().then({
|
||||
let comments = comment.comments.clone();
|
||||
move || view! {
|
||||
<ul class="comment-children">
|
||||
<For
|
||||
each=move || comments.clone()
|
||||
key=|comment| comment.id
|
||||
let:comment
|
||||
>
|
||||
<Comment comment />
|
||||
</For>
|
||||
</ul>
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
}
|
||||
})}
|
||||
<div class="by">
|
||||
<A href=format!(
|
||||
"/users/{}",
|
||||
comment.user.clone().unwrap_or_default(),
|
||||
)>{comment.user.clone()}</A>
|
||||
{format!(" {}", comment.time_ago)}
|
||||
</div>
|
||||
<div class="text" inner_html=comment.content></div>
|
||||
{(!comment.comments.is_empty())
|
||||
.then(|| {
|
||||
view! {
|
||||
<div>
|
||||
<div class="toggle" class:open=open>
|
||||
<a on:click=move |_| {
|
||||
set_open.update(|n| *n = !*n)
|
||||
}>
|
||||
|
||||
{
|
||||
let comments_len = comment.comments.len();
|
||||
move || {
|
||||
if open.get() {
|
||||
"[-]".into()
|
||||
} else {
|
||||
format!(
|
||||
"[+] {}{} collapsed",
|
||||
comments_len,
|
||||
pluralize(comments_len),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</a>
|
||||
</div>
|
||||
{move || {
|
||||
open
|
||||
.get()
|
||||
.then({
|
||||
let comments = comment.comments.clone();
|
||||
move || {
|
||||
view! {
|
||||
<ul class="comment-children">
|
||||
<For
|
||||
each=move || comments.clone()
|
||||
key=|comment| comment.id
|
||||
let:comment
|
||||
>
|
||||
<Comment comment/>
|
||||
</For>
|
||||
</ul>
|
||||
}
|
||||
}
|
||||
})
|
||||
}}
|
||||
|
||||
</div>
|
||||
}
|
||||
})}
|
||||
|
||||
</li>
|
||||
}.into_any()
|
||||
}
|
||||
|
||||
@@ -18,30 +18,48 @@ pub fn User() -> impl IntoView {
|
||||
);
|
||||
view! {
|
||||
<div class="user-view">
|
||||
<Suspense fallback=|| view! { "Loading..." }>
|
||||
{move || Suspend::new(async move { match user.await.clone() {
|
||||
None => Either::Left(view! { <h1>"User not found."</h1> }),
|
||||
Some(user) => Either::Right(view! {
|
||||
<div>
|
||||
<h1>"User: " {user.id.clone()}</h1>
|
||||
<ul class="meta">
|
||||
<li>
|
||||
<span class="label">"Created: "</span> {user.created}
|
||||
</li>
|
||||
<li>
|
||||
<span class="label">"Karma: "</span> {user.karma}
|
||||
</li>
|
||||
<li inner_html={user.about} class="about"></li>
|
||||
</ul>
|
||||
<p class="links">
|
||||
<a href=format!("https://news.ycombinator.com/submitted?id={}", user.id)>"submissions"</a>
|
||||
" | "
|
||||
<a href=format!("https://news.ycombinator.com/threads?id={}", user.id)>"comments"</a>
|
||||
</p>
|
||||
</div>
|
||||
})
|
||||
}})}
|
||||
<Suspense fallback=|| {
|
||||
view! { "Loading..." }
|
||||
}>
|
||||
{move || Suspend::new(async move {
|
||||
match user.await.clone() {
|
||||
None => Either::Left(view! { <h1>"User not found."</h1> }),
|
||||
Some(user) => {
|
||||
Either::Right(
|
||||
view! {
|
||||
<div>
|
||||
<h1>"User: " {user.id.clone()}</h1>
|
||||
<ul class="meta">
|
||||
<li>
|
||||
<span class="label">"Created: "</span>
|
||||
{user.created}
|
||||
</li>
|
||||
<li>
|
||||
<span class="label">"Karma: "</span>
|
||||
{user.karma}
|
||||
</li>
|
||||
<li inner_html=user.about class="about"></li>
|
||||
</ul>
|
||||
<p class="links">
|
||||
<a href=format!(
|
||||
"https://news.ycombinator.com/submitted?id={}",
|
||||
user.id,
|
||||
)>"submissions"</a>
|
||||
" | "
|
||||
<a href=format!(
|
||||
"https://news.ycombinator.com/threads?id={}",
|
||||
user.id,
|
||||
)>"comments"</a>
|
||||
</p>
|
||||
</div>
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
})}
|
||||
|
||||
</Suspense>
|
||||
</div>
|
||||
}
|
||||
.into_any()
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
RouteList, RouteListing, RouteMatchId,
|
||||
};
|
||||
use any_spawner::Executor;
|
||||
use either_of::{Either, EitherOf3};
|
||||
use either_of::Either;
|
||||
use futures::FutureExt;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, ScopedFuture},
|
||||
@@ -24,8 +24,9 @@ use tachys::{
|
||||
reactive_graph::OwnedView,
|
||||
ssr::StreamBuilder,
|
||||
view::{
|
||||
add_attr::AddAnyAttr, Mountable, Position, PositionState, Render,
|
||||
RenderHtml,
|
||||
add_attr::AddAnyAttr,
|
||||
any_view::{AnyView, AnyViewState, IntoAny},
|
||||
Mountable, Position, PositionState, Render, RenderHtml,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -39,26 +40,18 @@ pub(crate) struct FlatRoutesView<Loc, Defs, FalFn> {
|
||||
pub transition: bool,
|
||||
}
|
||||
|
||||
pub struct FlatRoutesViewState<Defs, Fal>
|
||||
where
|
||||
Defs: MatchNestedRoutes + 'static,
|
||||
Fal: Render + 'static,
|
||||
{
|
||||
pub struct FlatRoutesViewState {
|
||||
#[allow(clippy::type_complexity)]
|
||||
view: <EitherOf3<(), Fal, OwnedView<<Defs::Match as MatchInterface>::View>> as Render>::State,
|
||||
view: AnyViewState,
|
||||
id: Option<RouteMatchId>,
|
||||
owner: Owner,
|
||||
params: ArcRwSignal<ParamsMap>,
|
||||
path: String,
|
||||
url: ArcRwSignal<Url>,
|
||||
matched: ArcRwSignal<String>
|
||||
matched: ArcRwSignal<String>,
|
||||
}
|
||||
|
||||
impl<Defs, Fal> Mountable for FlatRoutesViewState<Defs, Fal>
|
||||
where
|
||||
Defs: MatchNestedRoutes + 'static,
|
||||
Fal: Render + 'static,
|
||||
{
|
||||
impl Mountable for FlatRoutesViewState {
|
||||
fn unmount(&mut self) {
|
||||
self.view.unmount();
|
||||
}
|
||||
@@ -81,9 +74,9 @@ where
|
||||
Loc: LocationProvider,
|
||||
Defs: MatchNestedRoutes + 'static,
|
||||
FalFn: FnOnce() -> Fal + Send,
|
||||
Fal: Render + 'static,
|
||||
Fal: IntoAny,
|
||||
{
|
||||
type State = Rc<RefCell<FlatRoutesViewState<Defs, Fal>>>;
|
||||
type State = Rc<RefCell<FlatRoutesViewState>>;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
let FlatRoutesView {
|
||||
@@ -123,7 +116,7 @@ where
|
||||
|
||||
match new_match {
|
||||
None => Rc::new(RefCell::new(FlatRoutesViewState {
|
||||
view: EitherOf3::B(fallback()).build(),
|
||||
view: fallback().into_any().build(),
|
||||
id,
|
||||
owner,
|
||||
params,
|
||||
@@ -156,7 +149,7 @@ where
|
||||
|
||||
match view.as_mut().now_or_never() {
|
||||
Some(view) => Rc::new(RefCell::new(FlatRoutesViewState {
|
||||
view: EitherOf3::C(view).build(),
|
||||
view: view.into_any().build(),
|
||||
id,
|
||||
owner,
|
||||
params,
|
||||
@@ -167,7 +160,7 @@ where
|
||||
None => {
|
||||
let state =
|
||||
Rc::new(RefCell::new(FlatRoutesViewState {
|
||||
view: EitherOf3::A(()).build(),
|
||||
view: ().into_any().build(),
|
||||
id,
|
||||
owner,
|
||||
params,
|
||||
@@ -180,7 +173,7 @@ where
|
||||
let state = Rc::clone(&state);
|
||||
async move {
|
||||
let view = view.await;
|
||||
EitherOf3::C(view)
|
||||
view.into_any()
|
||||
.rebuild(&mut state.borrow_mut().view);
|
||||
}
|
||||
});
|
||||
@@ -270,8 +263,7 @@ where
|
||||
provide_context(url);
|
||||
provide_context(params_memo);
|
||||
provide_context(Matched(ArcMemo::from(new_matched)));
|
||||
EitherOf3::B(fallback())
|
||||
.rebuild(&mut state.borrow_mut().view)
|
||||
fallback().into_any().rebuild(&mut state.borrow_mut().view)
|
||||
});
|
||||
}
|
||||
Some(new_match) => {
|
||||
@@ -318,7 +310,7 @@ where
|
||||
== spawned_path
|
||||
{
|
||||
let rebuild = move || {
|
||||
EitherOf3::C(view)
|
||||
view.into_any()
|
||||
.rebuild(&mut state.borrow_mut().view);
|
||||
};
|
||||
if transition {
|
||||
@@ -371,9 +363,7 @@ where
|
||||
FalFn: FnOnce() -> Fal + Send,
|
||||
Fal: RenderHtml + 'static,
|
||||
{
|
||||
fn choose_ssr(
|
||||
self,
|
||||
) -> OwnedView<Either<Fal, <Defs::Match as MatchInterface>::View>> {
|
||||
fn choose_ssr(self) -> OwnedView<AnyView> {
|
||||
let current_url = self.current_url.read_untracked();
|
||||
let new_match = self.routes.match_route(current_url.path());
|
||||
let owner = self.outer_owner.child();
|
||||
@@ -396,7 +386,7 @@ where
|
||||
drop(current_url);
|
||||
|
||||
let view = match new_match {
|
||||
None => Either::Left((self.fallback)()),
|
||||
None => (self.fallback)().into_any(),
|
||||
Some(new_match) => {
|
||||
let (view, _) = new_match.into_view_and_child();
|
||||
let view = owner
|
||||
@@ -410,7 +400,7 @@ where
|
||||
})
|
||||
.now_or_never()
|
||||
.expect("async route used in SSR");
|
||||
Either::Right(view)
|
||||
view.into_any()
|
||||
}
|
||||
};
|
||||
|
||||
@@ -427,10 +417,7 @@ where
|
||||
{
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = <Either<
|
||||
Fal,
|
||||
<Defs::Match as MatchInterface>::View,
|
||||
> as RenderHtml>::MIN_LENGTH;
|
||||
const MIN_LENGTH: usize = <Either<Fal, AnyView> as RenderHtml>::MIN_LENGTH;
|
||||
|
||||
fn dry_resolve(&mut self) {}
|
||||
|
||||
@@ -560,7 +547,8 @@ where
|
||||
|
||||
match new_match {
|
||||
None => Rc::new(RefCell::new(FlatRoutesViewState {
|
||||
view: EitherOf3::B(fallback())
|
||||
view: fallback()
|
||||
.into_any()
|
||||
.hydrate::<FROM_SERVER>(cursor, position),
|
||||
id,
|
||||
owner,
|
||||
@@ -594,7 +582,8 @@ where
|
||||
|
||||
match view.as_mut().now_or_never() {
|
||||
Some(view) => Rc::new(RefCell::new(FlatRoutesViewState {
|
||||
view: EitherOf3::C(view)
|
||||
view: view
|
||||
.into_any()
|
||||
.hydrate::<FROM_SERVER>(cursor, position),
|
||||
id,
|
||||
owner,
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
use either_of::*;
|
||||
use std::{future::Future, marker::PhantomData};
|
||||
use tachys::view::{any_view::AnyView, Render};
|
||||
use tachys::view::any_view::{AnyView, IntoAny};
|
||||
|
||||
pub trait ChooseView
|
||||
where
|
||||
Self: Send + Clone + 'static,
|
||||
{
|
||||
type Output;
|
||||
|
||||
fn choose(self) -> impl Future<Output = Self::Output>;
|
||||
fn choose(self) -> impl Future<Output = AnyView>;
|
||||
|
||||
fn preload(&self) -> impl Future<Output = ()>;
|
||||
}
|
||||
@@ -16,12 +14,10 @@ where
|
||||
impl<F, View> ChooseView for F
|
||||
where
|
||||
F: Fn() -> View + Send + Clone + 'static,
|
||||
View: Render + Send,
|
||||
View: IntoAny,
|
||||
{
|
||||
type Output = View;
|
||||
|
||||
async fn choose(self) -> Self::Output {
|
||||
self()
|
||||
async fn choose(self) -> AnyView {
|
||||
self().into_any()
|
||||
}
|
||||
|
||||
async fn preload(&self) {}
|
||||
@@ -31,10 +27,8 @@ impl<T> ChooseView for Lazy<T>
|
||||
where
|
||||
T: LazyRoute,
|
||||
{
|
||||
type Output = AnyView;
|
||||
|
||||
async fn choose(self) -> Self::Output {
|
||||
T::data().view().await
|
||||
async fn choose(self) -> AnyView {
|
||||
T::data().view().await.into_any()
|
||||
}
|
||||
|
||||
async fn preload(&self) {
|
||||
@@ -74,9 +68,9 @@ impl<T> Default for Lazy<T> {
|
||||
}
|
||||
|
||||
impl ChooseView for () {
|
||||
type Output = ();
|
||||
|
||||
async fn choose(self) -> Self::Output {}
|
||||
async fn choose(self) -> AnyView {
|
||||
().into_any()
|
||||
}
|
||||
|
||||
async fn preload(&self) {}
|
||||
}
|
||||
@@ -86,12 +80,10 @@ where
|
||||
A: ChooseView,
|
||||
B: ChooseView,
|
||||
{
|
||||
type Output = Either<A::Output, B::Output>;
|
||||
|
||||
async fn choose(self) -> Self::Output {
|
||||
async fn choose(self) -> AnyView {
|
||||
match self {
|
||||
Either::Left(f) => Either::Left(f.choose().await),
|
||||
Either::Right(f) => Either::Right(f.choose().await),
|
||||
Either::Left(f) => f.choose().await.into_any(),
|
||||
Either::Right(f) => f.choose().await.into_any(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,11 +101,9 @@ macro_rules! tuples {
|
||||
where
|
||||
$($ty: ChooseView,)*
|
||||
{
|
||||
type Output = $either<$($ty::Output,)*>;
|
||||
|
||||
async fn choose(self ) -> Self::Output {
|
||||
async fn choose(self ) -> AnyView {
|
||||
match self {
|
||||
$($either::$ty(f) => $either::$ty(f.choose().await),)*
|
||||
$($either::$ty(f) => f.choose().await.into_any(),)*
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ use crate::{static_routes::RegenerationFn, Method, SsrMode};
|
||||
pub use horizontal::*;
|
||||
pub use nested::*;
|
||||
use std::{borrow::Cow, collections::HashSet};
|
||||
use tachys::view::{Render, RenderHtml};
|
||||
pub use vertical::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -95,15 +94,12 @@ pub struct RouteMatchId(pub(crate) u16);
|
||||
|
||||
pub trait MatchInterface {
|
||||
type Child: MatchInterface + MatchParams + 'static;
|
||||
type View: Render + RenderHtml + Send + 'static;
|
||||
|
||||
fn as_id(&self) -> RouteMatchId;
|
||||
|
||||
fn as_matched(&self) -> &str;
|
||||
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (impl ChooseView<Output = Self::View>, Option<Self::Child>);
|
||||
fn into_view_and_child(self) -> (impl ChooseView, Option<Self::Child>);
|
||||
}
|
||||
|
||||
pub trait MatchParams {
|
||||
@@ -114,7 +110,6 @@ pub trait MatchParams {
|
||||
|
||||
pub trait MatchNestedRoutes {
|
||||
type Data;
|
||||
type View;
|
||||
type Match: MatchInterface + MatchParams;
|
||||
|
||||
fn match_nested<'a>(
|
||||
|
||||
@@ -10,7 +10,6 @@ use std::{
|
||||
collections::HashSet,
|
||||
sync::atomic::{AtomicU16, Ordering},
|
||||
};
|
||||
use tachys::view::{Render, RenderHtml};
|
||||
|
||||
mod tuples;
|
||||
|
||||
@@ -141,10 +140,8 @@ impl<ParamsIter, Child, View> MatchInterface
|
||||
where
|
||||
Child: MatchInterface + MatchParams + 'static,
|
||||
View: ChooseView,
|
||||
View::Output: Render + RenderHtml + Send + 'static,
|
||||
{
|
||||
type Child = Child;
|
||||
type View = View::Output;
|
||||
|
||||
fn as_id(&self) -> RouteMatchId {
|
||||
self.id
|
||||
@@ -154,9 +151,7 @@ where
|
||||
&self.matched
|
||||
}
|
||||
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (impl ChooseView<Output = Self::View>, Option<Self::Child>) {
|
||||
fn into_view_and_child(self) -> (impl ChooseView, Option<Self::Child>) {
|
||||
(self.view_fn, self.child)
|
||||
}
|
||||
}
|
||||
@@ -173,10 +168,8 @@ where
|
||||
Children: 'static,
|
||||
<Children::Match as MatchParams>::Params: Clone,
|
||||
View: ChooseView + Clone,
|
||||
View::Output: Render + RenderHtml + Send + 'static,
|
||||
{
|
||||
type Data = Data;
|
||||
type View = View::Output;
|
||||
type Match = NestedMatch<iter::Chain<
|
||||
<Segments::ParamsIter as IntoIterator>::IntoIter,
|
||||
Either<iter::Empty::<
|
||||
|
||||
@@ -14,7 +14,6 @@ impl MatchParams for () {
|
||||
|
||||
impl MatchInterface for () {
|
||||
type Child = ();
|
||||
type View = ();
|
||||
|
||||
fn as_id(&self) -> RouteMatchId {
|
||||
RouteMatchId(0)
|
||||
@@ -24,16 +23,13 @@ impl MatchInterface for () {
|
||||
""
|
||||
}
|
||||
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (impl ChooseView<Output = Self::View>, Option<Self::Child>) {
|
||||
fn into_view_and_child(self) -> (impl ChooseView, Option<Self::Child>) {
|
||||
((), None)
|
||||
}
|
||||
}
|
||||
|
||||
impl MatchNestedRoutes for () {
|
||||
type Data = ();
|
||||
type View = ();
|
||||
type Match = ();
|
||||
|
||||
fn match_nested<'a>(
|
||||
@@ -69,7 +65,6 @@ where
|
||||
A: MatchInterface + 'static,
|
||||
{
|
||||
type Child = A::Child;
|
||||
type View = A::View;
|
||||
|
||||
fn as_id(&self) -> RouteMatchId {
|
||||
self.0.as_id()
|
||||
@@ -79,9 +74,7 @@ where
|
||||
self.0.as_matched()
|
||||
}
|
||||
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (impl ChooseView<Output = Self::View>, Option<Self::Child>) {
|
||||
fn into_view_and_child(self) -> (impl ChooseView, Option<Self::Child>) {
|
||||
self.0.into_view_and_child()
|
||||
}
|
||||
}
|
||||
@@ -91,7 +84,6 @@ where
|
||||
A: MatchNestedRoutes + 'static,
|
||||
{
|
||||
type Data = A::Data;
|
||||
type View = A::View;
|
||||
type Match = A::Match;
|
||||
|
||||
fn match_nested<'a>(
|
||||
@@ -132,7 +124,6 @@ where
|
||||
B: MatchInterface,
|
||||
{
|
||||
type Child = Either<A::Child, B::Child>;
|
||||
type View = Either<A::View, B::View>;
|
||||
|
||||
fn as_id(&self) -> RouteMatchId {
|
||||
match self {
|
||||
@@ -148,9 +139,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (impl ChooseView<Output = Self::View>, Option<Self::Child>) {
|
||||
fn into_view_and_child(self) -> (impl ChooseView, Option<Self::Child>) {
|
||||
match self {
|
||||
Either::Left(i) => {
|
||||
let (view, child) = i.into_view_and_child();
|
||||
@@ -170,7 +159,6 @@ where
|
||||
B: MatchNestedRoutes,
|
||||
{
|
||||
type Data = (A::Data, B::Data);
|
||||
type View = Either<A::View, B::View>;
|
||||
type Match = Either<A::Match, B::Match>;
|
||||
|
||||
fn match_nested<'a>(
|
||||
@@ -236,7 +224,6 @@ macro_rules! tuples {
|
||||
$($ty: MatchInterface + 'static),*,
|
||||
{
|
||||
type Child = $either<$($ty::Child,)*>;
|
||||
type View = $either<$($ty::View,)*>;
|
||||
|
||||
fn as_id(&self) -> RouteMatchId {
|
||||
match self {
|
||||
@@ -253,7 +240,7 @@ macro_rules! tuples {
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (
|
||||
impl ChooseView<Output = Self::View>,
|
||||
impl ChooseView,
|
||||
Option<Self::Child>,
|
||||
) {
|
||||
match self {
|
||||
@@ -270,7 +257,6 @@ macro_rules! tuples {
|
||||
$($ty: MatchNestedRoutes + 'static),*,
|
||||
{
|
||||
type Data = ($($ty::Data,)*);
|
||||
type View = $either<$($ty::View,)*>;
|
||||
type Match = $either<$($ty::Match,)*>;
|
||||
|
||||
fn match_nested<'a>(&'a self, path: &'a str) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
||||
|
||||
@@ -353,7 +353,7 @@ impl ResolvedStaticPath {
|
||||
eprintln!("{e}");
|
||||
}
|
||||
}
|
||||
drop(owner);
|
||||
owner.unset();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user