Skip to content

Commit

Permalink
Rearranges mobile layout to have more screenspace
Browse files Browse the repository at this point in the history
  • Loading branch information
IongIer committed May 18, 2024
1 parent d34fa90 commit a3f161c
Show file tree
Hide file tree
Showing 18 changed files with 258 additions and 85 deletions.
1 change: 1 addition & 0 deletions apis/src/components/atoms/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ pub mod status_indicator;
pub mod svgs;
pub mod target;
pub mod title;
pub mod toggle_controls;
pub mod undo_button;
47 changes: 47 additions & 0 deletions apis/src/components/atoms/toggle_controls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use crate::components::layouts::base_layout::ControlsSignal;
use leptos::*;
use leptos_icons::*;

#[component]
pub fn ToggleControls() -> impl IntoView {
let controls_signal = expect_context::<ControlsSignal>();
let toggle_controls = move |_| controls_signal.hidden.update(|b| *b = !*b);
let icon = move || {
if controls_signal.hidden.get() {
view! { <Icon icon=icondata::BiDownArrowSolid class="w-4 h-4"/> }
} else {
view! { <Icon icon=icondata::BiUpArrowSolid class="w-4 h-4"/> }
}
};
let title = move || {
if controls_signal.hidden.get() {
"Show controls"
} else {
"Hide Controls"
}
};

let button_color = move || {
if controls_signal.notify.get() && controls_signal.hidden.get() {
"bg-ladybug-red"
} else {
"bg-button-dawn dark:bg-button-twilight"
}
};

view! {
<button
title=title
on:click=toggle_controls
class=move || {
format!(
"{} px-4 py-1 m-1 font-bold text-white rounded transition-transform duration-300 transform hover:bg-pillbug-teal active:scale-95",
button_color(),
)
}
>

{icon}
</button>
}
}
88 changes: 78 additions & 10 deletions apis/src/components/layouts/base_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@ use crate::components::atoms::og::OG;
use crate::components::atoms::title::Title;
use crate::components::molecules::alert::Alert;
use crate::components::organisms::header::Header;
use crate::providers::game_state::GameStateSignal;
use crate::providers::{ApiRequests, AuthContext, ColorScheme};

use crate::providers::navigation_controller::NavigationControllerSignal;
use crate::providers::refocus::RefocusSignal;
use crate::providers::websocket::WebsocketContext;
use crate::providers::PingSignal;
use chrono::Utc;
use hive_lib::GameControl;
use lazy_static::lazy_static;
use leptos::*;
use leptos_meta::*;
use leptos_router::use_location;
use leptos_use::core::ConnectionReadyState;
use leptos_use::utils::Pausable;
use leptos_use::{use_interval_fn, use_window_focus};
use leptos_use::{use_interval_fn, use_media_query, use_window_focus};
use regex::Regex;

lazy_static! {
Expand All @@ -25,18 +27,77 @@ lazy_static! {
pub const COMMON_LINK_STYLE: &str = "bg-button-dawn dark:bg-button-twilight hover:bg-pillbug-teal transform transition-transform duration-300 active:scale-95 text-white font-bold py-2 px-4 m-1 rounded";
pub const DROPDOWN_BUTTON_STYLE: &str= "h-full p-2 hover:bg-pillbug-teal transform transition-transform duration-300 active:scale-95 whitespace-nowrap block";

#[derive(Clone)]
pub struct ControlsSignal {
pub hidden: RwSignal<bool>,
pub notify: Signal<bool>,
}

#[derive(Clone)]
pub struct OrientationSignal {
pub is_tall: Signal<bool>,
pub chat_dropdown_open: RwSignal<bool>,
pub orientation_vertical: Signal<bool>,
}

#[component]
pub fn BaseLayout(children: Children) -> impl IntoView {
pub fn BaseLayout(children: ChildrenFn) -> impl IntoView {
let color_scheme = expect_context::<ColorScheme>();
let ping = expect_context::<PingSignal>();
let ws = expect_context::<WebsocketContext>();
let ws_ready = ws.ready_state;
let auth_context = expect_context::<AuthContext>();
let gamestate = expect_context::<GameStateSignal>();
let stored_children = store_value(children);
let is_tall = use_media_query("(min-height: 100vw)");
let chat_dropdown_open = RwSignal::new(false);
let orientation_vertical = Signal::derive(move || is_tall() || chat_dropdown_open());
provide_context(OrientationSignal {
is_tall,
chat_dropdown_open,
orientation_vertical,
});

let color_scheme_meta = move || {
if (color_scheme.prefers_dark)() {
"dark".to_string()
} else {
"light".to_string()
}
};
let auth_context = expect_context::<AuthContext>();
let ws = expect_context::<WebsocketContext>();

let user = move || match untrack(auth_context.user) {
Some(Ok(Some(user))) => Some(user),
_ => None,
};

let color = move || {
if let Some(user) = user() {
gamestate.user_color(user.id)
} else {
None
}
};
let has_gamecontrol = create_read_slice(gamestate.signal, move |gs| {
if let Some(color) = color() {
let opp_color = color.opposite_color();
matches!(
gs.game_control_pending,
Some(GameControl::TakebackRequest(color) | GameControl::DrawOffer(color)) if color == opp_color
)
} else {
false
}
});
let hide_controls = ControlsSignal {
hidden: RwSignal::new(true),
notify: has_gamecontrol,
};

provide_context(hide_controls);

let is_hidden = RwSignal::new("hidden");
create_effect(move |_| is_hidden.set(""));

create_effect(move |_| {
let location = use_location();
Expand All @@ -47,14 +108,12 @@ pub fn BaseLayout(children: Children) -> impl IntoView {
} else {
None
};
if (auth_context.user)().is_some() && (ws.ready_state)() == ConnectionReadyState::Open {
if ws_ready() == ConnectionReadyState::Open {
navi.update_nanoid(nanoid);
};
});

let api = ApiRequests::new();
let ping = expect_context::<PingSignal>();
let ws = expect_context::<WebsocketContext>();

let focused = use_window_focus();
let _ = watch(
Expand All @@ -77,7 +136,7 @@ pub fn BaseLayout(children: Children) -> impl IntoView {
move || {
api.ping();
counter.update(|c| *c += 1);
match ws.ready_state.get() {
match ws_ready() {
ConnectionReadyState::Closed => {
if retry_at.get() == counter.get() {
//log!("Reconnecting due to ReadyState");
Expand Down Expand Up @@ -122,10 +181,19 @@ pub fn BaseLayout(children: Children) -> impl IntoView {
}/>

<Body/>
<main class="w-full min-h-screen text-xs bg-light dark:bg-gray-950 sm:text-sm md:text-md touch-manipulations">
<main class=move || {
format!(
"w-full min-h-screen text-xs bg-light dark:bg-gray-950 sm:text-sm touch-manipulations {}",
is_hidden(),
)
}>
<Header/>
<Alert/>
{children()}
<Show when=move || ws_ready() != ConnectionReadyState::Open>
<div class="absolute top-1/2 left-1/2 w-10 h-10 rounded-full border-t-2 border-b-2 border-blue-500 animate-spin"></div>
</Show>
{stored_children()()}

</main>
}
}
9 changes: 4 additions & 5 deletions apis/src/components/molecules/analysis_and_download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@ use leptos_icons::*;
#[component]
pub fn AnalysisAndDownload() -> impl IntoView {
let game_state = expect_context::<GameStateSignal>();
let is_finished = move || (game_state.signal)().is_finished();
let analysis_setup = move |_| {
let mut game_state = expect_context::<GameStateSignal>();
game_state.do_analysis();
};

view! {
<Show when=is_finished>
<div class="flex items-center justify-center mt-1">
<Show when=game_state.is_finished()>
<div class="flex justify-center items-center mt-1">
<a
href="/analysis"
class="bg-button-dawn dark:bg-button-twilight hover:bg-pillbug-teal duration-300 text-white rounded m-1 place-self-center justify-self-end"
class="justify-self-end place-self-center m-1 text-white rounded duration-300 bg-button-dawn dark:bg-button-twilight hover:bg-pillbug-teal"
on:click=analysis_setup
>
<Icon icon=icondata::TbMicroscope class="h-7 w-7 py-1"/>
<Icon icon=icondata::TbMicroscope class="py-1 w-7 h-7"/>
</a>
<DownloadPgn/>
</div>
Expand Down
27 changes: 27 additions & 0 deletions apis/src/components/molecules/chat_and_controls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::{
components::{
atoms::toggle_controls::ToggleControls, layouts::base_layout::OrientationSignal,
organisms::dropdowns::ChatDropdown,
},
providers::{game_state::GameStateSignal, navigation_controller::NavigationControllerSignal},
};
use leptos::*;
use shared_types::SimpleDestination;

#[component]
pub fn ChatAndControls() -> impl IntoView {
let gamestate = expect_context::<GameStateSignal>();
let navi = expect_context::<NavigationControllerSignal>();
let orientation_signal = expect_context::<OrientationSignal>();
let is_finished = gamestate.is_finished();
let in_mobile_game =
move || orientation_signal.orientation_vertical.get() && navi.signal.get().nanoid.is_some();
view! {
<Show when=in_mobile_game>
<Show when=move || !is_finished()>
<ToggleControls/>
</Show>
<ChatDropdown destination=SimpleDestination::Game/>
</Show>
}
}
3 changes: 1 addition & 2 deletions apis/src/components/molecules/control_buttons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use shared_types::{ChallengeDetails, ChallengeVisibility};
#[component]
pub fn ControlButtons() -> impl IntoView {
let game_state = expect_context::<GameStateSignal>();
let is_finished = move || (game_state.signal)().is_finished();
let auth_context = expect_context::<AuthContext>();
let user = move || match untrack(auth_context.user) {
Some(Ok(Some(user))) => Some(user),
Expand Down Expand Up @@ -171,7 +170,7 @@ pub fn ControlButtons() -> impl IntoView {
view! {
<div class="flex justify-around items-center mt-1 w-full grow shrink">
<Show
when=is_finished
when=game_state.is_finished()
fallback=move || {
view! {
<div class="flex justify-around items-center grow shrink">
Expand Down
21 changes: 14 additions & 7 deletions apis/src/components/molecules/hamburger.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use leptos::html::Div;
use leptos::*;
use leptos_use::on_click_outside;
use leptos_use::{on_click_outside_with_options, OnClickOutsideOptions};

#[component]
pub fn Hamburger<T: IntoView>(
Expand All @@ -11,28 +11,35 @@ pub fn Hamburger<T: IntoView>(
dropdown_style: &'static str,
content: T,
) -> impl IntoView {
let target = create_node_ref::<Div>();
let children_ref = create_node_ref::<Div>();
create_effect(move |_| {
if hamburger_show() {
let _ = on_click_outside(target, move |_| {
hamburger_show.update(|b| *b = false);
});
let _ = on_click_outside_with_options(
children_ref,
move |_| {
hamburger_show.update(|b| *b = false);
},
OnClickOutsideOptions::default().ignore(["input", "#ignoreChat", "#ignoreButton"]),
);
}
});

let children = store_value(children);

view! {
<div node_ref=target class=format!("inline-block {extend_tw_classes}")>
<div class=format!("inline-block {extend_tw_classes}")>
<button
id="ignoreButton"
on:click=move |_| hamburger_show.update(|b| *b = !*b)

class=button_style
>
{content}
</button>
<Show when=hamburger_show>
<div class=dropdown_style>{children()}</div>
<div ref=children_ref class=dropdown_style>
{children()}
</div>
</Show>
</div>
}
Expand Down
1 change: 1 addition & 0 deletions apis/src/components/molecules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod analysis_and_download;
pub mod banner;
pub mod board_pieces;
pub mod challenge_row;
pub mod chat_and_controls;
pub mod control_buttons;
pub mod game_info;
pub mod game_row;
Expand Down
3 changes: 1 addition & 2 deletions apis/src/components/molecules/user_with_rating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ pub fn UserWithRating(
.game_response
.map(|g| g.black_player),
};
let is_finished = move || (game_state.signal)().is_finished();
let speed = move || {
game_state
.signal
Expand Down Expand Up @@ -69,7 +68,7 @@ pub fn UserWithRating(
}
}}
<Show
when=is_finished
when=game_state.is_finished()
fallback=move || {
view! { <div class=format!("{text_color}")>{rating}</div> }
}
Expand Down
8 changes: 4 additions & 4 deletions apis/src/components/organisms/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ pub fn Message(message: ChatMessage) -> impl IntoView {

view! {
<div class="flex flex-col items-start mb-1 w-full">
<div class="flex px-2 gap-1">
<div class="flex gap-1 px-2">
<div class="font-bold">{message.username}</div>
{user_local_time}
{turn}
</div>
<div class="px-2 max-w-fit break-words">{message.message}</div>
<div class="px-2 break-words max-w-fit">{message.message}</div>
</div>
}
}
Expand Down Expand Up @@ -159,8 +159,8 @@ pub fn ChatWindow(
.unwrap_or_default(),
};
view! {
<div class="flex flex-col h-full">
<div ref=div class="overflow-y-auto h-full">
<div id="ignoreChat" class="flex flex-col max-w-full h-full min-h-full">
<div ref=div class="overflow-y-auto overflow-x-hidden w-full h-full">
<For each=messages key=|message| message.timestamp let:message>
<Message message=message/>
</For>
Expand Down
8 changes: 5 additions & 3 deletions apis/src/components/organisms/darkmode_toggle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ use leptos::*;
use leptos_router::ActionForm;

#[component]
pub fn DarkModeToggle() -> impl IntoView {
pub fn DarkModeToggle(#[prop(optional)] extend_tw_classes: &'static str) -> impl IntoView {
let color_scheme = expect_context::<ColorScheme>();

view! {
<ActionForm
action=color_scheme.action
class="inline-flex justify-center items-center max-h-6 text-base font-medium rounded-md border border-transparent shadow md:max-h-7 dark:bg-orange-twilight bg-gray-950"
class=format!(
"inline-flex justify-center items-center m-1 rounded dark:bg-orange-twilight bg-gray-950 {extend_tw_classes}",
)
>

<input
type="hidden"
name="prefers_dark"
Expand Down
Loading

0 comments on commit a3f161c

Please sign in to comment.