Compare commits
No commits in common. "cd67863a47d60d059a1ed97c9d0a61a85cdf8b53" and "c2f4f245860e27302132a66d64e25d2637f30320" have entirely different histories.
cd67863a47
...
c2f4f24586
5 changed files with 28 additions and 75 deletions
|
@ -14,8 +14,7 @@ repository = "https://git.alemi.dev/upub.git"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = "0.3"
|
console_log = "1.0"
|
||||||
tracing-subscriber-wasm = "0.1"
|
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
|
@ -2,7 +2,6 @@ use std::{collections::BTreeSet, pin::Pin, sync::Arc};
|
||||||
|
|
||||||
use apb::{Activity, ActivityMut, Base, Object};
|
use apb::{Activity, ActivityMut, Base, Object};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_use::{signal_debounced, signal_throttled, use_display_media, use_document_visibility, use_element_size, use_infinite_scroll_with_options, use_scroll, use_scroll_with_options, use_window, use_window_scroll, UseDisplayMediaReturn, UseElementSizeReturn, UseInfiniteScrollOptions, UseScrollOptions, UseScrollReturn};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
@ -138,67 +137,41 @@ pub fn TimelineReplies(tl: Timeline, root: String) -> impl IntoView {
|
||||||
#[component]
|
#[component]
|
||||||
pub fn TimelineFeed(tl: Timeline) -> impl IntoView {
|
pub fn TimelineFeed(tl: Timeline) -> impl IntoView {
|
||||||
let auth = use_context::<Auth>().expect("missing auth context");
|
let auth = use_context::<Auth>().expect("missing auth context");
|
||||||
let config = use_context::<Signal<crate::Config>>().expect("missing config context");
|
view! {
|
||||||
// double view height: preload when 1 screen away
|
<For
|
||||||
let view_height = 2.0 * window()
|
each=move || tl.feed.get()
|
||||||
.inner_height()
|
key=|k| k.to_string()
|
||||||
.map_or(500.0, |v| v.as_f64().unwrap_or_default());
|
children=move |id: String| {
|
||||||
let scroll_ref = create_node_ref();
|
match CACHE.get(&id) {
|
||||||
let UseElementSizeReturn { width: _w, height } = use_element_size(scroll_ref);
|
Some(i) => view! {
|
||||||
let (_x, scroll) = use_window_scroll();
|
<Item item=i sep=true />
|
||||||
let scroll_debounced = signal_throttled(scroll, 500.0);
|
}.into_view(),
|
||||||
let _auto_loader = create_local_resource(
|
None => view! {
|
||||||
move || (scroll_debounced.get(), height.get()),
|
<p><code>{id}</code>" "[<a href={uri}>go</a>]</p>
|
||||||
move |(s, h)| async move {
|
<hr />
|
||||||
if !config.get().infinite_scroll { return }
|
}.into_view(),
|
||||||
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}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
/ >
|
||||||
);
|
|
||||||
view! {
|
|
||||||
<div ref=scroll_ref>
|
|
||||||
<For
|
|
||||||
each=move || tl.feed.get()
|
|
||||||
key=|k| k.to_string()
|
|
||||||
children=move |id: String| {
|
|
||||||
match CACHE.get(&id) {
|
|
||||||
Some(i) => view! {
|
|
||||||
<Item item=i sep=true />
|
|
||||||
}.into_view(),
|
|
||||||
None => view! {
|
|
||||||
<p><code>{id}</code>" "[<a href={uri}>go</a>]</p>
|
|
||||||
<hr />
|
|
||||||
}.into_view(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/ >
|
|
||||||
</div>
|
|
||||||
<div class="center mt-1 mb-1" class:hidden=tl.over >
|
<div class="center mt-1 mb-1" class:hidden=tl.over >
|
||||||
<button type="button"
|
<button type="button"
|
||||||
prop:disabled=tl.loading
|
prop:disabled=tl.loading
|
||||||
on:click=move |_| load_more(tl, auth)
|
on:click=move |_| {
|
||||||
>
|
spawn_local(async move {
|
||||||
{move || if tl.loading.get() {
|
if let Err(e) = tl.more(auth).await {
|
||||||
view! { "loading"<span class="dots"></span> }.into_view()
|
tracing::error!("error fetching more items for timeline: {e}");
|
||||||
} else { "more".into_view() }}
|
}
|
||||||
</button>
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{move || if tl.loading.get() {
|
||||||
|
view! { "loading"<span class="dots"></span> }.into_view()
|
||||||
|
} else { "more".into_view() }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
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 sub_tasks : Vec<Pin<Box<dyn futures::Future<Output = ()>>>> = Vec::new();
|
||||||
let mut gonna_fetch = BTreeSet::new();
|
let mut gonna_fetch = BTreeSet::new();
|
||||||
|
|
|
@ -11,9 +11,6 @@ pub struct Config {
|
||||||
#[serde_inline_default(true)]
|
#[serde_inline_default(true)]
|
||||||
pub loop_videos: bool,
|
pub loop_videos: bool,
|
||||||
|
|
||||||
#[serde_inline_default(true)]
|
|
||||||
pub infinite_scroll: bool,
|
|
||||||
|
|
||||||
#[serde_inline_default("#BF616A".to_string())]
|
#[serde_inline_default("#BF616A".to_string())]
|
||||||
pub accent_color: String,
|
pub accent_color: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
|
_ = console_log::init_with_level(log::Level::Info);
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
tracing_subscriber::fmt()
|
|
||||||
.with_writer(
|
|
||||||
tracing_subscriber_wasm::MakeConsoleWriter::default()
|
|
||||||
.map_trace_level_to(tracing::Level::DEBUG)
|
|
||||||
)
|
|
||||||
.with_ansi(false)
|
|
||||||
.without_time()
|
|
||||||
.init();
|
|
||||||
|
|
||||||
leptos::mount_to_body(upub_web::App);
|
leptos::mount_to_body(upub_web::App);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,14 +57,6 @@ pub fn ConfigPage(setter: WriteSignal<crate::Config>) -> impl IntoView {
|
||||||
/> collapse content warnings
|
/> collapse content warnings
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
|
||||||
<span title="new posts will be fetched automatically when scrolling down enough">
|
|
||||||
<input type="checkbox" class="mr-1"
|
|
||||||
prop:checked=get_cfg!(infinite_scroll)
|
|
||||||
on:input=set_cfg!(infinite_scroll)
|
|
||||||
/> infinite scroll
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
<p>
|
||||||
accent color
|
accent color
|
||||||
<input type="text" class="ma-1"
|
<input type="text" class="ma-1"
|
||||||
|
|
Loading…
Reference in a new issue