Skip to content

Commit

Permalink
Adds move confirmation per time control
Browse files Browse the repository at this point in the history
  • Loading branch information
IongIer committed Jun 20, 2024
1 parent d5e1c72 commit 07658da
Show file tree
Hide file tree
Showing 16 changed files with 329 additions and 140 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 @@ -13,6 +13,7 @@ pub mod profile_link;
pub mod rating;
pub mod select_options;
pub mod simple_hex;
pub mod simple_piece;
pub mod status_indicator;
pub mod svgs;
pub mod target;
Expand Down
33 changes: 11 additions & 22 deletions apis/src/components/atoms/piece.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::common::{MoveConfirm, TileDesign, TileDots, TileRotation};
use crate::common::{PieceType, SvgPos};
use crate::pages::analysis::InAnalysis;
use crate::pages::{analysis::InAnalysis, play::CurrentConfirm};
use crate::providers::game_state::GameStateSignal;
use crate::providers::Config;
use hive_lib::{Bug, Piece, Position};
Expand Down Expand Up @@ -62,28 +62,23 @@ pub fn Piece(
""
};

let mut game_state_signal = expect_context::<GameStateSignal>();
let mut game_state = expect_context::<GameStateSignal>();
let current_confirm = expect_context::<CurrentConfirm>().0;
let in_analysis = use_context::<InAnalysis>().unwrap_or(InAnalysis(RwSignal::new(false)));

let onclick = move |evt: MouseEvent| {
evt.stop_propagation();
let in_analysis = in_analysis.0.get_untracked();
if in_analysis || game_state_signal.is_move_allowed() {
if in_analysis || game_state.is_move_allowed() {
match piece_type {
PieceType::Board => {
game_state_signal.show_moves(piece, position);
game_state.show_moves(piece, position);
}
PieceType::Reserve => {
game_state_signal.show_spawns(piece, position);
game_state.show_spawns(piece, position);
}
PieceType::Move | PieceType::Spawn => {
if in_analysis
|| matches!(
(config.confirm_mode.preferred_confirm)(),
MoveConfirm::Double
)
{
game_state_signal.move_active();
if current_confirm() == MoveConfirm::Double {
game_state.move_active();
}
}
_ => {}
Expand Down Expand Up @@ -126,29 +121,23 @@ pub fn Piece(
String::new()
};

let top_piece = game_state_signal
let top_piece = game_state
.signal
.get_untracked()
.state
.board
.top_piece(position)
.unwrap_or(piece);

let active_piece = create_read_slice(game_state_signal.signal, |gs| gs.move_info.active);
let active_piece = create_read_slice(game_state.signal, |gs| gs.move_info.active);
let show_ds = move || {
if let Some(active) = active_piece() {
if active == piece {
return "#no_ds";
}
return "#ds";
};
if match game_state_signal
.signal
.get_untracked()
.state
.board
.last_move
{
if match game_state.signal.get_untracked().state.board.last_move {
(Some(_), Some(pos)) => position != pos || piece != top_piece,
(Some(pos), None) => position != pos || piece != top_piece,
(None, Some(pos)) => position != pos || piece != top_piece,
Expand Down
15 changes: 5 additions & 10 deletions apis/src/components/atoms/simple_hex.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
use crate::{
common::{Hex, HexType},
components::atoms::{active::Active, last_move::LastMove, piece::Piece, target::Target},
components::atoms::simple_piece::SimplePiece,
};

use leptos::*;

#[component]
pub fn SimpleHex(hex: Hex) -> impl IntoView {
match hex.kind {
HexType::Active(_) => view! { <Active position=hex.position level=hex.level/> },
HexType::Tile(piece, piece_type) => {
view! { <Piece piece=piece position=hex.position level=hex.level piece_type=piece_type/> }
}
HexType::LastMove(dir) => {
view! { <LastMove position=hex.position level=hex.level direction=dir/> }
}
HexType::Target => view! { <Target position=hex.position level=hex.level/> },
if let HexType::Tile(piece, _) = hex.kind {
view! { <SimplePiece piece=piece position=hex.position level=hex.level/> }
} else {
view! {}.into_view()
}
}
132 changes: 132 additions & 0 deletions apis/src/components/atoms/simple_piece.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use crate::common::SvgPos;
use crate::common::{TileDesign, TileDots, TileRotation};
use crate::providers::game_state::GameStateSignal;
use crate::providers::Config;
use hive_lib::{Bug, Piece, Position};
use leptos::*;

#[component]
pub fn SimplePiece(
// WARN piece and position are untracked and might break reactivity if passed in as signals in the future
#[prop(into)] piece: MaybeSignal<Piece>,
#[prop(into)] position: MaybeSignal<Position>,
#[prop(into)] level: MaybeSignal<usize>,
) -> impl IntoView {
let game_state = expect_context::<GameStateSignal>();
let config = expect_context::<Config>();
let piece = piece.get_untracked();
let position = position.get_untracked();
let center = move || SvgPos::center_for_level(position, level());
let order = piece.order();
let ds_transform = move || format!("translate({},{})", center().0, center().1);
let transform = move || {
if (config.tile_rotation.preferred_tile_rotation)() == TileRotation::Yes {
format!(
"translate({},{}) rotate({})",
center().0,
center().1,
order.saturating_sub(1) * 60
)
} else {
format!("translate({},{})", center().0, center().1)
}
};
let bug = piece.bug();
let color = piece.color();

let dot_color = move || {
if (config.tile_design.preferred_tile_design)() == TileDesign::Official {
match bug {
Bug::Ant => " color: #289ee0",
Bug::Beetle => " color: #9a7fc7",
Bug::Grasshopper => " color: #42b23c",
Bug::Spider => " color: #a4572a",
_ => " color: #FF0000",
}
} else {
match bug {
Bug::Ant => " color: #3574a5",
Bug::Beetle => " color: #7a4fab",
Bug::Grasshopper => " color: #3f9b3a",
Bug::Spider => " color: #993c1e",
_ => " color: #FF0000",
}
}
};

let bug_transform = move || {
if (config.tile_design.preferred_tile_design)() == TileDesign::Official {
"scale(0.56, 0.56) translate(-45, -50)"
} else {
"scale(0.56, 0.56) translate(-50, -45)"
}
};

let bug_svg = move || {
if (config.tile_design.preferred_tile_design)() == TileDesign::Official {
format!("#{}", bug)
} else {
format!("#f{}", bug)
}
};

let tile_svg = move || {
if (config.tile_design.preferred_tile_design)() == TileDesign::Official {
format!("#{}", color)
} else {
format!("#f{}", color)
}
};

let dots = move || {
if (config.tile_dots.preferred_tile_dots)() == TileDots::Yes {
if (config.tile_design.preferred_tile_design)() == TileDesign::Official {
return format!("#{}", order);
} else {
return format!("#f{}", order);
}
}
String::new()
};

let top_piece = game_state
.signal
.get_untracked()
.state
.board
.top_piece(position)
.unwrap_or(piece);

let active_piece = create_read_slice(game_state.signal, |gs| gs.move_info.active);
let show_ds = move || {
if let Some(active) = active_piece() {
if active == piece {
return "#no_ds";
}
return "#ds";
};
if match game_state.signal.get_untracked().state.board.last_move {
(Some(_), Some(pos)) => position != pos || piece != top_piece,
(Some(pos), None) => position != pos || piece != top_piece,
(None, Some(pos)) => position != pos || piece != top_piece,
_ => true,
} {
"#ds"
} else {
"#no_ds"
}
};

view! {
<g style=dot_color>
<g transform=ds_transform>
<use_ href=show_ds transform="scale(0.56, 0.56) translate(-67, -64.5)"></use_>
</g>
<g transform=transform>
<use_ href=tile_svg transform="scale(0.56, 0.56) translate(-45, -50)"></use_>
<use_ href=bug_svg transform=bug_transform></use_>
<use_ href=dots transform="scale(0.56, 0.56) translate(-45, -50)"></use_>
</g>
</g>
}
}
23 changes: 10 additions & 13 deletions apis/src/components/atoms/target.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::common::MoveConfirm;
use crate::common::SvgPos;
use crate::pages::analysis::InAnalysis;
use crate::pages::{analysis::InAnalysis, play::CurrentConfirm};
use crate::providers::game_state::GameStateSignal;
use crate::providers::Config;
use hive_lib::Position;
use leptos::*;

Expand All @@ -14,22 +13,20 @@ pub fn Target(
) -> impl IntoView {
let center = move || SvgPos::center_for_level(position, level());
let transform = move || format!("translate({},{})", center().0, center().1);
let mut game_state_signal = expect_context::<GameStateSignal>();
let config = expect_context::<Config>();
let mut game_state = expect_context::<GameStateSignal>();
let in_analysis = use_context::<InAnalysis>().unwrap_or(InAnalysis(RwSignal::new(false)));
let current_confirm = expect_context::<CurrentConfirm>().0;

// Select the target position and make a move if it's the correct mode
let onclick = move |_| {
let in_analysis = in_analysis.0.get_untracked();
if in_analysis || game_state_signal.is_move_allowed() {
game_state_signal.set_target(position);
if matches!(
(config.confirm_mode.preferred_confirm)(),
MoveConfirm::Single
) && !in_analysis
{
game_state_signal.move_active();
}
if in_analysis || game_state.is_move_allowed() {
batch(move || {
game_state.set_target(position);
if current_confirm() == MoveConfirm::Single || in_analysis {
game_state.move_active();
}
});
}
};

Expand Down
4 changes: 2 additions & 2 deletions apis/src/components/molecules/board_pieces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use leptos::*;

#[component]
pub fn BoardPieces() -> impl IntoView {
let game_state_signal = expect_context::<GameStateSignal>();
let game_state = expect_context::<GameStateSignal>();
// TODO get the BOARD_SIZE from board
let board = move || {
let mut board = Vec::new();
let game_state = (game_state_signal.signal)();
let game_state = (game_state.signal)();
let targets = game_state.move_info.target_positions;
let last_move = game_state.state.board.last_move;
let active_piece = (
Expand Down
9 changes: 6 additions & 3 deletions apis/src/components/molecules/challenge_row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ pub fn ChallengeRow(challenge: StoredValue<ChallengeResponse>, single: bool) ->
</Show>
<button
on:click=move |_| {
ApiRequests::new().challenge_cancel(challenge().challenge_id)
ApiRequests::new()
.challenge_cancel(challenge().challenge_id)
}

class="px-1 py-1 m-1 text-white rounded transition-transform duration-300 transform bg-ladybug-red hover:bg-red-400 active:scale-95 focus:outline-none focus:shadow-outline"
Expand All @@ -200,7 +201,8 @@ pub fn ChallengeRow(challenge: StoredValue<ChallengeResponse>, single: bool) ->
Some(Ok(Some(_))) => {
let mut game_state = expect_context::<GameStateSignal>();
game_state.full_reset();
ApiRequests::new().challenge_accept(challenge().challenge_id);
ApiRequests::new()
.challenge_accept(challenge().challenge_id);
}
_ => {
let navigate = use_navigate();
Expand All @@ -220,7 +222,8 @@ pub fn ChallengeRow(challenge: StoredValue<ChallengeResponse>, single: bool) ->
on:click=move |_| {
match (auth_context.user)() {
Some(Ok(Some(_))) => {
ApiRequests::new().challenge_cancel(challenge().challenge_id);
ApiRequests::new()
.challenge_cancel(challenge().challenge_id);
}
_ => {
let navigate = use_navigate();
Expand Down
29 changes: 19 additions & 10 deletions apis/src/components/organisms/confirm_mode_toggle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,42 @@ use crate::{common::MoveConfirm, providers::Config};
use leptos::*;
use leptos_icons::Icon;
use leptos_router::ActionForm;
use shared_types::GameSpeed;

#[component]
pub fn ConfirmModeToggle() -> impl IntoView {
pub fn ConfirmModeToggle(game_speed: GameSpeed) -> impl IntoView {
let game_speed = store_value(game_speed);
view! {
<p class="m-1 text-black dark:text-white">Move confirmation:</p>
<div class="flex">
<ConfirmModeButton move_confirm=MoveConfirm::Single/>
<ConfirmModeButton move_confirm=MoveConfirm::Double/>
<ConfirmModeButton move_confirm=MoveConfirm::Clock/>
<ConfirmModeButton move_confirm=MoveConfirm::Single game_speed=game_speed()/>
<ConfirmModeButton move_confirm=MoveConfirm::Double game_speed=game_speed()/>
<ConfirmModeButton move_confirm=MoveConfirm::Clock game_speed=game_speed()/>
</div>
}
}

#[component]
pub fn ConfirmModeButton(move_confirm: MoveConfirm) -> impl IntoView {
pub fn ConfirmModeButton(move_confirm: MoveConfirm, game_speed: GameSpeed) -> impl IntoView {
let move_confirm = store_value(move_confirm);
let game_speed = store_value(game_speed);
let config = expect_context::<Config>();
let (title, icon) = match move_confirm() {
MoveConfirm::Clock => ("Click on your clock", icondata::BiStopwatchRegular),
MoveConfirm::Double => ("Double click", icondata::TbHandTwoFingers),
MoveConfirm::Single => ("Single click", icondata::TbHandFinger),
};
let is_active = move || {
if (config.confirm_mode.preferred_confirm)() == move_confirm() {
"bg-pillbug-teal"
} else {
"bg-button-dawn dark:bg-button-twilight hover:bg-pillbug-teal"
}
let inactive_class = "bg-button-dawn dark:bg-button-twilight hover:bg-pillbug-teal";
(config.confirm_mode.preferred_confirms)()
.get(&game_speed())
.map_or(inactive_class, |preferred| {
if *preferred == move_confirm() {
"bg-pillbug-teal"
} else {
inactive_class
}
})
};

view! {
Expand All @@ -38,6 +46,7 @@ pub fn ConfirmModeButton(move_confirm: MoveConfirm) -> impl IntoView {
class="inline-flex justify-center items-center m-1 text-base font-medium rounded-md border border-transparent shadow cursor-pointer"
>
<input type="hidden" name="move_confirm" value=move_confirm().to_string()/>
<input type="hidden" name="game_speed" value=game_speed().to_string()/>
<button
class=move || {
format!(
Expand Down
Loading

0 comments on commit 07658da

Please sign in to comment.