Skip to content

Commit

Permalink
Adds optional sounds for turn/move/new_game, refactors frontend timer
Browse files Browse the repository at this point in the history
  • Loading branch information
IongIer committed Jul 23, 2024
1 parent 42d95e5 commit 7269ba6
Show file tree
Hide file tree
Showing 25 changed files with 514 additions and 121 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ thiserror = "1"
anyhow = "1"
tokio = { version = "1.35.1", features = ["full"] }
wasm-bindgen = "0.2.92"
web-sys = {version = "0.3.67", features = ["AbortController", "AbortSignal", "Blob", "Clipboard", "HtmlDocument", "SvgPoint", "SvgsvgElement", "SvgGraphicsElement", "SvgRect", "SvgMatrix", "Url", "Window"] }
wasm-bindgen-futures = "0.4"
web-sys = {version = "0.3.67", features = ["AbortController", "AbortSignal", "AudioContext", "AudioBuffer", "AudioBufferSourceNode", "AudioDestinationNode", "Blob", "Clipboard", "HtmlDocument", "SvgPoint", "SvgsvgElement", "SvgGraphicsElement", "SvgRect", "SvgMatrix", "Url", "Window"] }
bb8 = { version = "0.8" }
diesel = { version = "2.1", features = ["postgres", "chrono", "uuid", "serde_json"] }
diesel-async = { version = "0.4", features = ["postgres", "bb8"] }
Expand Down
1 change: 1 addition & 0 deletions apis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ anyhow = { workspace = true }
tokio = { workspace = true, optional = true }
uuid = { workspace = true }
wasm-bindgen = { workspace = true}
wasm-bindgen-futures = { workspace = true}
web-sys = { workspace = true }
leptix_primitives = {workspace = true}
tree-ds = {workspace = true}
Expand Down
Binary file added apis/assets/low.mp3
Binary file not shown.
Binary file added apis/assets/moves.mp3
Binary file not shown.
Binary file added apis/assets/new.mp3
Binary file not shown.
5 changes: 3 additions & 2 deletions apis/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use crate::{
challenges::provide_challenges, chat::provide_chat, game_state::provide_game_state,
games::provide_games, navigation_controller::provide_navigation_controller,
online_users::provide_users, provide_alerts, provide_auth, provide_color_scheme,
provide_config, provide_notifications, provide_ping, refocus::provide_refocus,
timer::provide_timer, tournament_ready::provide_tournament_ready,
provide_config, provide_notifications, provide_ping, provide_sounds,
refocus::provide_refocus, timer::provide_timer, tournament_ready::provide_tournament_ready,
tournaments::provide_tournaments, user_search::provide_user_search,
websocket::provide_websocket,
},
Expand Down Expand Up @@ -61,6 +61,7 @@ pub fn App() -> impl IntoView {
provide_tournaments();
provide_notifications();
provide_tournament_ready();
provide_sounds();

view! {
<Stylesheet id="leptos" href="/pkg/HiveGame.css"/>
Expand Down
2 changes: 1 addition & 1 deletion apis/src/components/atoms/input_slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn InputSlider(
let min = Signal::derive(move || min() as f64);
let max = Signal::derive(move || max() as f64);
let step: f64 = step as f64;
let default_value = vec![signal_to_update.get() as f64];
let default_value = vec![signal_to_update.get_untracked() as f64];
let on_value_change = Callback::from(move |val: Vec<f64>| {
signal_to_update.set(val[0] as i32);
});
Expand Down
92 changes: 78 additions & 14 deletions apis/src/components/layouts/base_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ 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 crate::providers::{load_audio_buffer, ApiRequests, AuthContext, ColorScheme, SoundsSignal};
use cfg_if::cfg_if;
use chrono::Utc;
use hive_lib::GameControl;
Expand All @@ -21,6 +20,10 @@ use leptos_use::utils::Pausable;
use leptos_use::{use_interval_fn, use_media_query, use_window_focus};
use regex::Regex;
use shared_types::{GameId, TournamentId};
use std::cell::RefCell;
use std::rc::Rc;
use web_sys::AudioContext;

cfg_if! { if #[cfg(not(feature = "ssr"))] {
use leptos_use::utils::IS_IOS;
use std::sync::RwLock;
Expand Down Expand Up @@ -57,6 +60,7 @@ pub struct OrientationSignal {
#[component]
pub fn BaseLayout(children: ChildrenFn) -> impl IntoView {
let color_scheme = expect_context::<ColorScheme>();
let sounds_signal = expect_context::<SoundsSignal>();
let ping = expect_context::<PingSignal>();
let ws = expect_context::<WebsocketContext>();
let ws_ready = ws.ready_state;
Expand Down Expand Up @@ -101,20 +105,14 @@ pub fn BaseLayout(children: ChildrenFn) -> impl IntoView {
}
};

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

let color = move || {
if let Some(user) = user() {
gamestate.user_color(user.id)
} else {
None
}
};
let user_color = gamestate.user_color_as_signal(user_id.into());
let has_gamecontrol = create_read_slice(gamestate.signal, move |gs| {
if let Some(color) = color() {
if let Some(color) = user_color() {
let opp_color = color.opposite_color();
matches!(
gs.game_control_pending,
Expand Down Expand Up @@ -161,7 +159,6 @@ pub fn BaseLayout(children: ChildrenFn) -> impl IntoView {
focused,
move |focused, _, _| {
let mut refocus = expect_context::<RefocusSignal>();
//log!("Focus changed");
if *focused {
refocus.refocus();
} else {
Expand Down Expand Up @@ -214,6 +211,73 @@ pub fn BaseLayout(children: ChildrenFn) -> impl IntoView {
1000,
);

let listener_triggered = RwSignal::new(false);
let sounds_loaded = RwSignal::new(false);
let update_sounds_effect = create_effect(move |_| {
if let Some(context) = sounds_signal.context.get() {
if !sounds_loaded() {
spawn_local(async move {
if let Ok(turn_sound) = load_audio_buffer(&context, "/assets/moves.mp3").await {
sounds_signal
.turn
.try_update_untracked(|v| *v = Some(turn_sound));
}
if let Ok(low_sound) = load_audio_buffer(&context, "/assets/low.mp3").await {
sounds_signal
.low
.try_update_untracked(|v| *v = Some(low_sound));
}
if let Ok(new_sound) = load_audio_buffer(&context, "/assets/new.mp3").await {
sounds_signal
.new
.try_update_untracked(|v| *v = Some(new_sound));
}
});
sounds_loaded.set(true);
}
} else {
sounds_signal
.context
.try_update(|v| *v = AudioContext::new().ok());
}
});

let events = [
"touchend",
"pointerup",
"pointerdown",
"mousedown",
"keydown",
];
let listeners = Rc::new(RefCell::new(vec![]));
for event in events {
let ev = window_event_listener_untyped(event, move |_| {
if let Some(context) = sounds_signal.context.get() {
if !listener_triggered.get_untracked() && context.resume().is_ok() {
listener_triggered.set(true);
} else {
sounds_signal
.context
.try_update(|v| *v = AudioContext::new().ok());
listener_triggered.set(true);
};
}
});
listeners.borrow_mut().push(Box::new(ev));
}

create_effect(move |_| {
if sounds_loaded() {
update_sounds_effect.dispose();
}
});
create_effect(move |_| {
if listener_triggered() && sounds_loaded() {
for event in listeners.borrow_mut().drain(..) {
event.remove();
}
}
});
view! {
<Title/>
<OG/>
Expand Down
44 changes: 17 additions & 27 deletions apis/src/components/molecules/control_buttons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
challenges::ChallengeStateSignal, game_state::GameStateSignal, ApiRequests, AuthContext,
},
};
use hive_lib::{ColorChoice, GameControl};
use hive_lib::{ColorChoice, GameControl, GameStatus};
use leptos::*;
use leptos_router::use_navigate;
use shared_types::{ChallengeDetails, ChallengeVisibility};
Expand All @@ -14,21 +14,19 @@ use shared_types::{ChallengeDetails, ChallengeVisibility};
pub fn ControlButtons() -> impl IntoView {
let game_state = expect_context::<GameStateSignal>();
let auth_context = expect_context::<AuthContext>();
let user = move || match untrack(auth_context.user) {
Some(Ok(Some(user))) => Some(user),
_ => None,
let user_id = move || {
untrack(auth_context.user)
.and_then(|result| result.ok())
.and_then(|account| account.map(|user| user.id))
.expect("Control buttons show only for logged in players")
};

let user_id = move || user().expect("User to be present in control buttons").id;

let color = move || {
if let Some(user) = user() {
game_state
.user_color(user.id)
.expect("User is either white or black")
} else {
unreachable!()
}
game_state
.signal
.get_untracked()
.user_color(user_id())
.expect("Control buttons show only for logged in players")
};
let pending = create_read_slice(game_state.signal, |gs| gs.game_control_pending.clone());
let not_tournament = create_read_slice(game_state.signal, |gs| {
Expand Down Expand Up @@ -120,34 +118,26 @@ pub fn ControlButtons() -> impl IntoView {

let sent_challenge = move || {
if let Some(challenge) = rematch_present() {
if let Some(user) = user() {
return challenge.challenger.uid == user.id;
}
return challenge.challenger.uid == user_id();
}
false
};

let rematch_button_color = move || {
if let Some(challenge) = rematch_present() {
if let Some(user) = user() {
if challenge.challenger.uid != user.id {
return "bg-grasshopper-green hover:bg-green-500";
}
if challenge.challenger.uid != user_id() {
return "bg-grasshopper-green hover:bg-green-500";
}
}
"bg-button-dawn dark:bg-button-twilight hover:bg-pillbug-teal"
};

let rematch_text = move || {
if let Some(challenge) = rematch_present() {
if let Some(user) = user() {
if challenge.challenger.uid == user.id {
"Sent"
} else {
"Accept"
}
if challenge.challenger.uid == user_id() {
"Sent"
} else {
"Not logged in"
"Accept"
}
} else {
"Rematch"
Expand Down
Loading

0 comments on commit 7269ba6

Please sign in to comment.