web: add spinner when loading next page in catchup mode

This commit is contained in:
Bill Thiede 2025-11-26 13:46:19 -08:00
parent 01fd53e467
commit 3c48076996
2 changed files with 35 additions and 8 deletions

View File

@ -291,6 +291,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
first, first,
last, last,
} => { } => {
model.refreshing_state = RefreshingState::Loading;
let (after, before, first, last) = match (after.as_ref(), before.as_ref(), first, last) let (after, before, first, last) = match (after.as_ref(), before.as_ref(), first, last)
{ {
// If no pagination set, set reasonable defaults // If no pagination set, set reasonable defaults
@ -316,25 +317,32 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
}); });
} }
Msg::FrontPageResult(Err(e)) => { Msg::FrontPageResult(Err(e)) => {
error!("error FrontPageResult: {e:?}"); let msg = format!("error FrontPageResult: {e:?}");
error!("{msg}");
model.refreshing_state = RefreshingState::Error(msg);
} }
Msg::FrontPageResult(Ok(graphql_client::Response { Msg::FrontPageResult(Ok(graphql_client::Response {
data: None, data: None,
errors: None, errors: None,
.. ..
})) => { })) => {
error!("FrontPageResult no data or errors, should not happen"); let msg = format!("FrontPageResult no data or errors, should not happen");
error!("{msg}");
model.refreshing_state = RefreshingState::Error(msg);
} }
Msg::FrontPageResult(Ok(graphql_client::Response { Msg::FrontPageResult(Ok(graphql_client::Response {
data: None, data: None,
errors: Some(e), errors: Some(e),
.. ..
})) => { })) => {
error!("FrontPageResult error: {e:?}"); let msg = format!("FrontPageResult error: {e:?}");
error!("{msg}");
model.refreshing_state = RefreshingState::Error(msg);
} }
Msg::FrontPageResult(Ok(graphql_client::Response { Msg::FrontPageResult(Ok(graphql_client::Response {
data: Some(data), .. data: Some(data), ..
})) => { })) => {
model.refreshing_state = RefreshingState::None;
model.tags = Some( model.tags = Some(
data.tags data.tags
.into_iter() .into_iter()
@ -374,6 +382,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
} }
Msg::ShowThreadRequest { thread_id } => { Msg::ShowThreadRequest { thread_id } => {
model.refreshing_state = RefreshingState::Loading;
orders.skip().perform_cmd(async move { orders.skip().perform_cmd(async move {
Msg::ShowThreadResult( Msg::ShowThreadResult(
send_graphql(graphql::ShowThreadQuery::build_query( send_graphql(graphql::ShowThreadQuery::build_query(
@ -386,6 +395,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
Msg::ShowThreadResult(Ok(graphql_client::Response { Msg::ShowThreadResult(Ok(graphql_client::Response {
data: Some(data), .. data: Some(data), ..
})) => { })) => {
model.refreshing_state = RefreshingState::None;
model.tags = Some( model.tags = Some(
data.tags data.tags
.into_iter() .into_iter()
@ -425,9 +435,12 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
orders.send_msg(Msg::WindowScrolled); orders.send_msg(Msg::WindowScrolled);
} }
Msg::ShowThreadResult(bad) => { Msg::ShowThreadResult(bad) => {
error!("show_thread_query error: {bad:#?}"); let msg = format!("show_thread_query error: {bad:#?}");
error!("{msg}");
model.refreshing_state = RefreshingState::Error(msg);
} }
Msg::CatchupRequest { query } => { Msg::CatchupRequest { query } => {
model.refreshing_state = RefreshingState::Loading;
orders.perform_cmd(async move { orders.perform_cmd(async move {
Msg::CatchupResult( Msg::CatchupResult(
send_graphql::<_, graphql::catchup_query::ResponseData>( send_graphql::<_, graphql::catchup_query::ResponseData>(
@ -442,6 +455,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
Msg::CatchupResult(Ok(graphql_client::Response { Msg::CatchupResult(Ok(graphql_client::Response {
data: Some(data), .. data: Some(data), ..
})) => { })) => {
model.refreshing_state = RefreshingState::None;
let items = data.catchup; let items = data.catchup;
if items.is_empty() { if items.is_empty() {
orders.send_msg(Msg::GoToSearchResults); orders.send_msg(Msg::GoToSearchResults);
@ -457,7 +471,9 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
} }
} }
Msg::CatchupResult(bad) => { Msg::CatchupResult(bad) => {
error!("catchup_query error: {bad:#?}"); let msg = format!("catchup_query error: {bad:#?}");
error!("{msg}");
model.refreshing_state = RefreshingState::Error(msg);
} }
Msg::SelectionSetNone => { Msg::SelectionSetNone => {
if let Context::SearchResult { if let Context::SearchResult {

View File

@ -78,6 +78,10 @@ mod tw_classes {
} }
pub fn view(model: &Model) -> Node<Msg> { pub fn view(model: &Model) -> Node<Msg> {
let is_loading = match model.refreshing_state {
RefreshingState::Loading => true,
_ => false,
};
match &model.context { match &model.context {
Context::None => normal_view( Context::None => normal_view(
div![h1!["Loading"]], div![h1!["Loading"]],
@ -96,6 +100,7 @@ pub fn view(model: &Model) -> Node<Msg> {
thread(thread_data, open_messages, &model.content_el, true), thread(thread_data, open_messages, &model.content_el, true),
&catchup.items, &catchup.items,
model.read_completion_ratio, model.read_completion_ratio,
is_loading,
) )
} else { } else {
normal_view( normal_view(
@ -117,6 +122,7 @@ pub fn view(model: &Model) -> Node<Msg> {
news_post(post, &model.content_el, true), news_post(post, &model.content_el, true),
&catchup.items, &catchup.items,
model.read_completion_ratio, model.read_completion_ratio,
is_loading,
) )
} else { } else {
normal_view( normal_view(
@ -186,6 +192,7 @@ fn catchup_view(
content: Node<Msg>, content: Node<Msg>,
items: &[CatchupItem], items: &[CatchupItem],
read_completion_ratio: f64, read_completion_ratio: f64,
is_loading: bool,
) -> Node<Msg> { ) -> Node<Msg> {
div![ div![
C!["w-full", "relative", "text-white"], C!["w-full", "relative", "text-white"],
@ -201,13 +208,17 @@ fn catchup_view(
"bg-black/50", "bg-black/50",
], ],
div![ div![
C!["absolute", "top-0", "right-4", "text-gray-500", "p-4"], C!["absolute", "top-0", "left-4", "text-green-200", "p-4"],
span![i![C!["fas", "fa-x"]]], IF!(is_loading=>span![i![C!["animate-spin", "fas", "fa-spinner"]]])
ev(Ev::Click, move |_| Msg::CatchupExit)
], ],
h1![ h1![
C!["text-center"], C!["text-center"],
format!("{} left ", items.iter().filter(|i| !i.seen).count(),) format!("{} left ", items.iter().filter(|i| !i.seen).count(),)
],
div![
C!["absolute", "top-0", "right-4", "text-gray-500", "p-4"],
span![i![C!["fas", "fa-x"]]],
ev(Ev::Click, move |_| Msg::CatchupExit)
] ]
], ],
div![C!["mt-12", "mb-20"], content], div![C!["mt-12", "mb-20"], content],