fix(web): only load tl after refresh

also improved tl.more()
This commit is contained in:
əlemi 2024-05-27 16:50:42 +02:00
parent eb3c647691
commit 6397647511
Signed by: alemi
GPG key ID: A4895B84D311642C
6 changed files with 50 additions and 96 deletions

View file

@ -12,29 +12,6 @@ pub fn App() -> impl IntoView {
let (userid, set_userid) = use_cookie::<String, FromToStringCodec>("user_id");
let (config, set_config, _) = use_local_storage::<crate::Config, JsonCodec>("config");
if let Some(tok) = token.get_untracked() {
spawn_local(async move {
match reqwest::Client::new()
.request(Method::PATCH, format!("{URL_BASE}/auth"))
.json(&serde_json::json!({"token": tok}))
.send()
.await
{
Err(e) => tracing::error!("could not refresh token: {e}"),
Ok(res) => match res.error_for_status() {
Err(e) => tracing::error!("server rejected refresh: {e}"),
Ok(doc) => match doc.json::<AuthResponse>().await {
Err(e) => tracing::error!("failed parsing auth response: {e}"),
Ok(auth) => {
set_token.set(Some(auth.token));
set_userid.set(Some(auth.user));
},
}
}
}
})
};
let auth = Auth { token, userid };
provide_context(auth);
provide_context(config);
@ -55,26 +32,39 @@ pub fn App() -> impl IntoView {
let (menu, set_menu) = create_signal(screen_width <= 786);
let (advanced, set_advanced) = create_signal(false);
spawn_local(async move {
if let Err(e) = server_tl.more(auth).await {
tracing::error!("error populating timeline: {e}");
}
});
let auth_present = auth.token.get_untracked().is_some(); // skip helper to use get_untracked
if auth_present {
spawn_local(async move {
if let Err(e) = home_tl.more(auth).await {
tracing::error!("error populating timeline: {e}");
}
});
}
let title_target = move || if auth_present { "/web/home" } else { "/web/server" };
let title_target = if auth_present { "/web/home" } else { "/web/server" };
if let Some(tok) = token.get_untracked() {
spawn_local(async move {
// refresh token first, or verify that we're still authed
match reqwest::Client::new()
.request(Method::PATCH, format!("{URL_BASE}/auth"))
.json(&serde_json::json!({"token": tok}))
.send()
.await
{
Err(e) => tracing::error!("could not refresh token: {e}"),
Ok(res) => match res.error_for_status() {
Err(e) => tracing::error!("server rejected refresh: {e}"),
Ok(doc) => match doc.json::<AuthResponse>().await {
Err(e) => tracing::error!("failed parsing auth response: {e}"),
Ok(auth) => {
set_token.set(Some(auth.token));
set_userid.set(Some(auth.user));
},
}
}
}
server_tl.more(auth);
if auth_present { home_tl.more(auth) };
})
};
view! {
<nav class="w-100 mt-1 mb-1 pb-s">
<code class="color ml-3" ><a class="upub-title" href={title_target} >μpub</a></code>
<code class="color ml-3" ><a class="upub-title" href=title_target >μpub</a></code>
<small class="ml-1 mr-1 hidden-on-tiny" ><a class="clean" href="/web/server" >micro social network, federated</a></small>
/* TODO kinda jank with the float but whatever, will do for now */
<input type="submit" class="mr-2 rev" on:click=move |_| set_menu.set(!menu.get()) value="menu" style="float: right" />

View file

@ -19,11 +19,7 @@ pub fn LoginBox(
token_tx.set(None);
home_tl.reset(format!("{URL_BASE}/outbox/page"));
server_tl.reset(format!("{URL_BASE}/inbox/page"));
spawn_local(async move {
if let Err(e) = server_tl.more(auth).await {
logging::error!("failed refreshing server timeline: {e}");
}
});
server_tl.more(auth);
} />
</div>
<div class:hidden=move || auth.present() >
@ -50,18 +46,10 @@ pub fn LoginBox(
token_tx.set(Some(auth_response.token));
// reset home feed and point it to our user's inbox
home_tl.reset(format!("{URL_BASE}/users/{}/inbox/page", username));
spawn_local(async move {
if let Err(e) = home_tl.more(auth).await {
tracing::error!("failed refreshing home timeline: {e}");
}
});
home_tl.more(auth);
// reset server feed: there may be more content now that we're authed
server_tl.reset(format!("{URL_BASE}/inbox/page"));
spawn_local(async move {
if let Err(e) = server_tl.more(auth).await {
tracing::error!("failed refreshing server timeline: {e}");
}
});
server_tl.more(auth);
});
} >
<table class="w-100 align">

View file

@ -36,14 +36,20 @@ impl Timeline {
self.over.set(false);
}
pub async fn more(&self, auth: Auth) -> reqwest::Result<()> {
self.loading.set(true);
let res = self.more_inner(auth).await;
self.loading.set(false);
res
pub fn more(&self, auth: Auth) {
if self.loading.get() { return }
let _self = *self;
spawn_local(async move {
_self.loading.set(true);
let res = _self.load_more(auth).await;
_self.loading.set(false);
if let Err(e) = res {
tracing::error!("failed loading posts for timeline: {e}");
}
});
}
async fn more_inner(&self, auth: Auth) -> reqwest::Result<()> {
pub async fn load_more(&self, auth: Auth) -> reqwest::Result<()> {
use apb::{Collection, CollectionPage};
let feed_url = self.next.get_untracked();
@ -119,13 +125,7 @@ pub fn TimelineReplies(tl: Timeline, root: String) -> impl IntoView {
<div class="center mt-1 mb-1" class:hidden=tl.over >
<button type="button"
prop:disabled=tl.loading
on:click=move |_| {
spawn_local(async move {
if let Err(e) = tl.more(auth).await {
tracing::error!("error fetching more items for timeline: {e}");
}
})
}
on:click=move |_| tl.more(auth)
>
{move || if tl.loading.get() {
view! { "loading"<span class="dots"></span> }.into_view()
@ -152,9 +152,7 @@ pub fn TimelineFeed(tl: Timeline) -> impl IntoView {
move |(s, h)| async move {
if !config.get().infinite_scroll { return }
if s > 0.0 && h - s < view_height && !tl.loading.get() {
if let Err(e) = tl.more(auth).await {
tracing::error!("auto load failed: {e}");
}
tl.more(auth);
}
},
);
@ -179,7 +177,7 @@ pub fn TimelineFeed(tl: Timeline) -> impl IntoView {
<div class="center mt-1 mb-1" class:hidden=tl.over >
<button type="button"
prop:disabled=tl.loading
on:click=move |_| load_more(tl, auth)
on:click=move |_| tl.more(auth)
>
{move || if tl.loading.get() {
view! { "loading"<span class="dots"></span> }.into_view()
@ -189,16 +187,6 @@ pub fn TimelineFeed(tl: Timeline) -> impl IntoView {
}
}
fn load_more(tl: Timeline, auth: Auth) {
if !tl.loading.get() {
spawn_local(async move {
if let Err(e) = tl.more(auth).await {
tracing::error!("error fetching more items for timeline: {e}");
}
})
}
}
async fn process_activities(activities: Vec<serde_json::Value>, auth: Auth) -> Vec<String> {
let mut sub_tasks : Vec<Pin<Box<dyn futures::Future<Output = ()>>>> = Vec::new();
let mut gonna_fetch = BTreeSet::new();

View file

@ -41,11 +41,7 @@ pub fn ObjectPage(tl: Timeline) -> impl IntoView {
class:hidden=move || tl.is_empty()
on:click=move |_| {
tl.reset(tl.next.get().split('?').next().unwrap_or_default().to_string());
spawn_local(async move {
if let Err(e) = tl.more(auth).await {
tracing::error!("error fetching more items for timeline: {e}");
}
})
tl.more(auth);
}><span class="emoji">
"\u{1f5d8}"
</span></a>

View file

@ -10,11 +10,7 @@ pub fn TimelinePage(name: &'static str, tl: Timeline) -> impl IntoView {
{name}
<a class="clean ml-1" href="#" on:click=move |_| {
tl.reset(tl.next.get().split('?').next().unwrap_or_default().to_string());
spawn_local(async move {
if let Err(e) = tl.more(auth).await {
tracing::error!("error fetching more items for timeline: {e}");
}
})
tl.more(auth);
}><span class="emoji">
"\u{1f5d8}"
</span></a>

View file

@ -50,12 +50,8 @@ pub fn UserPage(tl: Timeline) -> impl IntoView {
class="clean ml-1" href="#"
class:hidden=move || tl.is_empty()
on:click=move |_| {
tl.reset(tl.next.get().split('?').next().unwrap_or_default().to_string());
spawn_local(async move {
if let Err(e) = tl.more(auth).await {
tracing::error!("error fetching more items for timeline: {e}");
}
})
tl.reset(tl.next.get().split('?').next().unwrap_or_default().to_string());
tl.more(auth);
}><span class="emoji">
"\u{1f5d8}"
</span></a>