diff --git a/apis/src/app.rs b/apis/src/app.rs index e024abcc..8341ffa0 100644 --- a/apis/src/app.rs +++ b/apis/src/app.rs @@ -1,27 +1,12 @@ +use crate::pages::profile_view::ProfileGamesView; use crate::{ components::layouts::base_layout::BaseLayout, pages::{ - account::Account, - admin::Admin, - analysis::Analysis, - challenge_view::ChallengeView, - config::Config, - display_games::DisplayGames, - donate::Donate, - faq::Faq, - home::Home, - login::Login, - play::Play, - profile_view::{ProfileGamesView, ProfileView}, - puzzles::Puzzles, - register::Register, - resources::Resources, - rules::Rules, - strategy::Strategy, - top_players::TopPlayers, - tournament::Tournament, - tournament_create::TournamentCreate, - tournaments::Tournaments, + account::Account, admin::Admin, analysis::Analysis, challenge_view::ChallengeView, + config::Config, display_games::DisplayGames, donate::Donate, faq::Faq, home::Home, + login::Login, play::Play, profile_view::ProfileView, puzzles::Puzzles, register::Register, + resources::Resources, rules::Rules, strategy::Strategy, top_players::TopPlayers, + tournament::Tournament, tournament_create::TournamentCreate, tournaments::Tournaments, tutorial::Tutorial, }, providers::{ diff --git a/apis/src/components/organisms/analysis/tree.rs b/apis/src/components/organisms/analysis/tree.rs index fa4e03cf..2dae737a 100644 --- a/apis/src/components/organisms/analysis/tree.rs +++ b/apis/src/components/organisms/analysis/tree.rs @@ -54,7 +54,7 @@ impl AnalysisTree { hashes, game_type: gs.state.game_type, }; - tree.update_node(gs.history_turn.unwrap_or(0)as i32); + tree.update_node(gs.history_turn.unwrap_or(0) as i32); Some(tree) } diff --git a/apis/src/pages/display_games.rs b/apis/src/pages/display_games.rs index 2dffd082..68da755b 100644 --- a/apis/src/pages/display_games.rs +++ b/apis/src/pages/display_games.rs @@ -1,30 +1,93 @@ +use html::Div; +use leptos::*; use crate::{ + functions::users::get::get_finished_games_in_batches, pages::profile_view::ProfileGamesContext, components::molecules::game_row::GameRow, - pages::profile_view::{AllUserGames, ProfileGamesView}, + components::organisms::display_profile::DisplayProfile, }; -use leptos::*; +use super::profile_view::ProfileGamesView; +use leptos_router::A; +use leptos_use::{use_infinite_scroll_with_options, UseInfiniteScrollOptions}; #[component] pub fn DisplayGames(tab_view: ProfileGamesView) -> impl IntoView { - let all_games = expect_context::(); - let games = match tab_view { - ProfileGamesView::Finished => all_games.finished, - ProfileGamesView::Playing => all_games.playing, - ProfileGamesView::Unstarted => all_games.unstarted, + let ctx = expect_context::(); + let el = create_node_ref::
(); + let active = move |view: ProfileGamesView| { + let button_style = String::from("hover:bg-pillbug-teal transform transition-transform duration-300 active:scale-95 text-white font-bold py-2 px-4 m-1 rounded"); + if tab_view == view { + button_style + " bg-pillbug-teal" + } else { + button_style + " bg-button-dawn dark:bg-button-twilight" + } }; - let is_active = expect_context::>(); - let elem = create_node_ref::(); - elem.on_load(move |_| is_active.update(|v| *v = tab_view)); + let username = store_value(ctx.user.username.clone()); + let _ = use_infinite_scroll_with_options( + el, + move |_| async move { + if tab_view == ProfileGamesView::Finished && ctx.more_finished.get() { + let games = get_finished_games_in_batches( + username(), + ctx.finished_last_timestamp.get(), + ctx.finished_last_id.get(), + 5, + ) + .await; + if let Ok((g, are_more)) = games { + ctx.finished_last_timestamp + .update(|v| *v = g.last().map(|gr| gr.updated_at)); + ctx.finished_last_id + .update(|v| *v = g.last().map(|gr| gr.uuid)); + ctx.more_finished.set(are_more); + ctx.finished.update(|v| v.extend(g.clone())); + } + } + }, + UseInfiniteScrollOptions::default().distance(10.0), + ); view! { -
- + + +
+ ctx.finished.get(), + ProfileGamesView::Playing => ctx.playing.get(), + ProfileGamesView::Unstarted => ctx.unstarted.get(), + } - key=|game| (game.uuid) - let:game - > - - + key=|game| (game.uuid) + let:game + > + + +
} } diff --git a/apis/src/pages/profile_view.rs b/apis/src/pages/profile_view.rs index 9b2d942b..4844f29b 100644 --- a/apis/src/pages/profile_view.rs +++ b/apis/src/pages/profile_view.rs @@ -1,22 +1,21 @@ -use crate::{ - components::organisms::display_profile::DisplayProfile, - functions::users::get::{ - get_finished_games_in_batches, get_ongoing_games, get_user_by_username, - }, - responses::GameResponse, +use crate::functions::users::get::{ + get_finished_games_in_batches, get_ongoing_games, get_user_by_username, }; +use crate::responses::GameResponse; +use crate::responses::UserResponse; +use chrono::{DateTime, Utc}; use hive_lib::GameStatus; -use leptos::{ev::scroll, *}; +use leptos::*; use leptos_router::*; -use leptos_use::{use_document, use_event_listener, use_throttle_fn, use_window}; use shared_types::GameStart; +use uuid::Uuid; #[derive(Params, PartialEq, Eq)] struct UsernameParams { username: String, } -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Copy)] pub enum ProfileGamesView { Unstarted, Playing, @@ -24,17 +23,19 @@ pub enum ProfileGamesView { } #[derive(Debug, Clone)] -pub struct AllUserGames { +pub struct ProfileGamesContext { pub unstarted: RwSignal>, pub playing: RwSignal>, pub finished: RwSignal>, + pub more_finished: RwSignal, + pub finished_last_timestamp: RwSignal>>, + pub finished_last_id: RwSignal>, + pub user: UserResponse, } #[component] pub fn ProfileView(children: ChildrenFn) -> impl IntoView { let params = use_params::(); - //TODO: @ion fix finished.clear() - let finished: RwSignal> = RwSignal::new(Vec::new()); let username = move || { params.with(|params| { params @@ -44,53 +45,23 @@ pub fn ProfileView(children: ChildrenFn) -> impl IntoView { }) }; let user = Resource::new(username, move |_| get_user_by_username(username())); - let get_more = RwSignal::new(0); let last_timestamp = RwSignal::new(None); let last_id = RwSignal::new(None); - let finished_games = Resource::new( - move || (username(), get_more()), - move |_| { - get_finished_games_in_batches( - username(), - last_timestamp.get_untracked(), - last_id.get_untracked(), - 3, - ) - }, - ); - let ongoing_games = Resource::new(username, move |_| get_ongoing_games(username())); - let stored_children = store_value(children); - let tab_view = create_rw_signal(ProfileGamesView::Playing); - let active = move |view: ProfileGamesView| { - let button_style = String::from("hover:bg-pillbug-teal transform transition-transform duration-300 active:scale-95 text-white font-bold py-2 px-4 m-1 rounded"); - if tab_view() == view { - button_style + " bg-pillbug-teal" - } else { - button_style + " bg-button-dawn dark:bg-button-twilight" - } - }; - let still_more_games = RwSignal::from(true); - let throttled_more_games = use_throttle_fn( - move || { - if tab_view.get_untracked() == ProfileGamesView::Finished - && is_end_of_page() - && still_more_games.get_untracked() - { - get_more.update(|v| *v += 1) - } - }, - 500.0, - ); - provide_context(tab_view); - _ = use_event_listener(use_window(), scroll, move |_| { - throttled_more_games(); + let children = store_value(children); + let first_batch_finished = Resource::new(username, move |_| { + get_finished_games_in_batches( + username(), + last_timestamp.get_untracked(), + last_id.get_untracked(), + 5, + ) }); - + let ongoing_games = Resource::new(username, move |_| get_ongoing_games(username())); view! {
- + {move || { - let (current_finished_games, more_games) = finished_games() + let (first_batch, more_finished) = first_batch_finished() .and_then(|games| games.ok()) .unwrap_or((Vec::new(), false)); let mut ongoing_games = ongoing_games() @@ -108,78 +79,32 @@ pub fn ProfileView(children: ChildrenFn) -> impl IntoView { true } }); - finished.update(move |v| v.extend(current_finished_games)); - still_more_games.set(more_games); - let playing = RwSignal::from(ongoing_games); - let unstarted = RwSignal::from(unstarted); - last_id.update(move |v| { *v = finished().last().map(|gr| gr.uuid) }); + let first_batch = store_value(first_batch); + let playing = RwSignal::new(ongoing_games); + let unstarted = RwSignal::new(unstarted); + let finished = RwSignal::new(first_batch()); + last_id.update(move |v| { *v = first_batch().last().map(|gr| gr.uuid) }); last_timestamp - .update(move |v| { *v = finished().last().map(|gr| gr.updated_at) }); - provide_context(AllUserGames { - unstarted, - finished, - playing, - }); + .update(move |v| { *v = first_batch().last().map(|gr| gr.updated_at) }); user() .map(|data| match data { Err(_) => view! {
"Page not found"
}.into_view(), Ok(user) => { - view! { - - - {stored_children()()} - -
-
- } - .into_view() + provide_context(ProfileGamesContext { + unstarted, + finished, + playing, + finished_last_timestamp: last_timestamp, + finished_last_id: last_id, + more_finished: RwSignal::new(more_finished), + user, + }); + children()().into_view() } }) }} -
+
} } - -fn is_end_of_page() -> bool { - let document = use_document(); - const OFFSET_PX: f64 = 200.0; - let inner_height = window() - .inner_height() - .expect("window") - .as_f64() - .expect("Converted to f64"); - let page_y_offset = window().page_y_offset().expect("window again"); - let body_offset_height = document.body().expect("Body").offset_height() as f64; - - inner_height + page_y_offset >= body_offset_height - OFFSET_PX -}