diff --git a/minesweeper-lib/src/game.rs b/minesweeper-lib/src/game.rs index d802e5a..a8694f0 100644 --- a/minesweeper-lib/src/game.rs +++ b/minesweeper-lib/src/game.rs @@ -178,7 +178,7 @@ impl Minesweeper { bail!("Tried to play flagged cell") } let mut update_revealed = None::>; - if !(self.players[player].played) && self.has_no_revealed_neighbors(cell_point) { + if !(self.players[player].played) && self.has_no_revealed_nearby(cell_point) { // on first click of empty board space, prevent mine self.players[player].played = true; update_revealed = Some(self.unplant(cell_point, self.superclick)); @@ -346,11 +346,13 @@ impl Minesweeper { }) } - fn has_no_revealed_neighbors(&self, cell_point: BoardPoint) -> bool { + fn has_no_revealed_nearby(&self, cell_point: BoardPoint) -> bool { let neighbors = self.board.neighbors(cell_point); neighbors .iter() .copied() + .map(|n| self.board.neighbors(n)) + .flatten() .filter(|i| self.board[*i].1.revealed) .count() == 0 @@ -786,25 +788,20 @@ mod test { } } - fn set_up_game(plant_3_0: bool) -> Minesweeper { + fn set_up_game() -> Minesweeper { let mut game = empty_game(2); game.plant(POINT_0_0); game.plant(POINT_1_1); game.plant(POINT_1_2); - if plant_3_0 { - game.plant(POINT_2_1); - } + game.plant(POINT_2_1); game } - fn set_up_game_with_replant() -> Minesweeper { - let mut game = empty_game(1); + fn set_up_game_no_superclick() -> Minesweeper { + let mut game = set_up_game(); + game.superclick = false; - game.plant(POINT_0_0); - game.plant(POINT_1_1); - game.plant(POINT_1_2); - game.plant(POINT_2_1); game } @@ -817,7 +814,7 @@ mod test { assert_eq!(num_mines, number); } - fn point_cell(game: &Minesweeper, point: BoardPoint, _cell: Cell) { + fn assert_point_cell(game: &Minesweeper, point: BoardPoint, _cell: Cell) { let board_cell = game.board[point].0; assert!(matches!(board_cell, _cell)); } @@ -853,61 +850,61 @@ mod test { num_mines(&game, 1); assert_eq!(game.available.len(), 9 * 9 - 1); - point_cell(&game, POINT_0_0, Cell::Mine); - point_cell(&game, POINT_0_1, Cell::Empty(1)); - point_cell(&game, POINT_1_0, Cell::Empty(1)); - point_cell(&game, POINT_1_1, Cell::Empty(1)); - point_cell(&game, POINT_0_2, Cell::Empty(0)); + assert_point_cell(&game, POINT_0_0, Cell::Mine); + assert_point_cell(&game, POINT_0_1, Cell::Empty(1)); + assert_point_cell(&game, POINT_1_0, Cell::Empty(1)); + assert_point_cell(&game, POINT_1_1, Cell::Empty(1)); + assert_point_cell(&game, POINT_0_2, Cell::Empty(0)); game.plant(POINT_1_1); num_mines(&game, 2); assert_eq!(game.available.len(), 9 * 9 - 2); - point_cell(&game, POINT_0_0, Cell::Mine); - point_cell(&game, POINT_0_1, Cell::Empty(2)); - point_cell(&game, POINT_1_0, Cell::Empty(2)); - point_cell(&game, POINT_1_1, Cell::Mine); - point_cell(&game, POINT_0_2, Cell::Empty(1)); + assert_point_cell(&game, POINT_0_0, Cell::Mine); + assert_point_cell(&game, POINT_0_1, Cell::Empty(2)); + assert_point_cell(&game, POINT_1_0, Cell::Empty(2)); + assert_point_cell(&game, POINT_1_1, Cell::Mine); + assert_point_cell(&game, POINT_0_2, Cell::Empty(1)); game.plant(POINT_1_2); num_mines(&game, 3); assert_eq!(game.available.len(), 9 * 9 - 3); - point_cell(&game, POINT_0_0, Cell::Mine); - point_cell(&game, POINT_0_1, Cell::Empty(3)); - point_cell(&game, POINT_1_0, Cell::Empty(2)); - point_cell(&game, POINT_1_1, Cell::Mine); - point_cell(&game, POINT_0_2, Cell::Empty(2)); + assert_point_cell(&game, POINT_0_0, Cell::Mine); + assert_point_cell(&game, POINT_0_1, Cell::Empty(3)); + assert_point_cell(&game, POINT_1_0, Cell::Empty(2)); + assert_point_cell(&game, POINT_1_1, Cell::Mine); + assert_point_cell(&game, POINT_0_2, Cell::Empty(2)); } #[test] fn unplant_mine_works() { - let mut game = set_up_game(false); + let mut game = set_up_game(); game.unplant(POINT_0_0, true); - num_mines(&game, 1); - assert_eq!(game.available.len(), 9 * 9 - 3); - point_cell(&game, POINT_0_0, Cell::Empty(0)); - point_cell(&game, POINT_1_1, Cell::Empty(1)); + num_mines(&game, 4); + assert_eq!(game.available.len(), 9 * 9 - 6); + assert_point_cell(&game, POINT_0_0, Cell::Empty(0)); + assert_point_cell(&game, POINT_1_1, Cell::Empty(1)); } #[test] fn unplant_cell_works() { - let mut game = set_up_game(false); + let mut game = set_up_game(); game.unplant(POINT_0_2, true); - num_mines(&game, 1); - assert_eq!(game.available.len(), 9 * 9 - 3); - point_cell(&game, POINT_0_2, Cell::Empty(0)); - point_cell(&game, POINT_0_0, Cell::Mine); - point_cell(&game, POINT_1_1, Cell::Empty(1)); + num_mines(&game, 4); + assert_eq!(game.available.len(), 9 * 9 - 6); + assert_point_cell(&game, POINT_0_2, Cell::Empty(0)); + assert_point_cell(&game, POINT_0_0, Cell::Mine); + assert_point_cell(&game, POINT_1_1, Cell::Empty(1)); } #[test] fn first_play_mine_works() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let res = game .play(Play { @@ -918,19 +915,19 @@ mod test { .unwrap(); assert_eq!(res.len(), 4); - num_mines(&game, 2); - assert_eq!(game.available.len(), 9 * 9 - 6); - point_cell(&game, POINT_0_0, Cell::Empty(0)); + num_mines(&game, 4); + assert_eq!(game.available.len(), 9 * 9 - 8); + assert_point_cell(&game, POINT_0_0, Cell::Empty(0)); point_cell_state(&game, POINT_0_0, true, Some(0)); - point_cell(&game, POINT_1_1, Cell::Empty(2)); + assert_point_cell(&game, POINT_1_1, Cell::Empty(2)); point_cell_state(&game, POINT_1_1, true, Some(0)); - point_cell(&game, POINT_1_2, Cell::Mine); + assert_point_cell(&game, POINT_1_2, Cell::Mine); point_cell_state(&game, POINT_1_2, false, None); } #[test] fn first_play_cell_works() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let res = game.play(Play { player: 0, @@ -941,17 +938,17 @@ mod test { num_mines(&game, 4); assert_eq!(game.available.len(), 4); // not mine and not revealed - point_cell(&game, BoardPoint { row: 8, col: 8 }, Cell::Empty(0)); + assert_point_cell(&game, BoardPoint { row: 8, col: 8 }, Cell::Empty(0)); point_cell_state(&game, BoardPoint { row: 8, col: 8 }, true, Some(0)); - point_cell(&game, POINT_1_1, Cell::Mine); + assert_point_cell(&game, POINT_1_1, Cell::Mine); point_cell_state(&game, POINT_1_1, false, None); - point_cell(&game, POINT_1_2, Cell::Mine); + assert_point_cell(&game, POINT_1_2, Cell::Mine); point_cell_state(&game, POINT_1_2, false, None); } #[test] fn second_click_mine_failure() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let _ = game .play(Play { @@ -972,7 +969,7 @@ mod test { #[test] fn second_click_cell_success() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let _ = game .play(Play { @@ -983,6 +980,7 @@ mod test { .unwrap(); let cell_point = BoardPoint { row: 0, col: 2 }; + game.unplant(cell_point, false); // guarantee not mine let res = game .play(Play { player: 0, @@ -990,13 +988,13 @@ mod test { point: cell_point, }) .unwrap(); - assert!(matches!(res.clone(), PlayOutcome::Success(_))); + assert!(matches!(&res, PlayOutcome::Success(_))); assert_eq!(res.len(), 1); } #[test] fn flag_works() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let _ = game .play(Play { @@ -1026,7 +1024,7 @@ mod test { #[test] fn unplant_updated_works() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let _ = game.play(Play { player: 0, @@ -1034,13 +1032,13 @@ mod test { point: BoardPoint { col: 7, row: 7 }, }); - point_cell(&game, POINT_2_2, Cell::Empty(3)); - point_cell(&game, POINT_0_3, Cell::Empty(1)); + assert_point_cell(&game, POINT_2_2, Cell::Empty(3)); + assert_point_cell(&game, POINT_0_3, Cell::Empty(1)); let updated = game.unplant(POINT_1_1, true); - point_cell(&game, POINT_2_2, Cell::Empty(0)); - point_cell(&game, POINT_0_3, Cell::Empty(0)); + assert_point_cell(&game, POINT_2_2, Cell::Empty(0)); + assert_point_cell(&game, POINT_0_3, Cell::Empty(0)); assert!(updated.contains(&POINT_2_2)); assert!(updated.contains(&POINT_0_3)); @@ -1049,7 +1047,7 @@ mod test { #[test] fn unflag_works() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let _ = game .play(Play { @@ -1088,41 +1086,39 @@ mod test { #[test] fn double_click_works() { - let mut game = set_up_game(true); + let mut game = set_up_game_no_superclick(); let res = game .play(Play { player: 0, action: Action::Reveal, - point: BoardPoint { row: 0, col: 0 }, + point: BoardPoint { row: 2, col: 2 }, }) .unwrap(); - assert_eq!(res.len(), 4); - - num_mines(&game, 2); + assert_eq!(res.len(), 1); + assert_point_cell(&game, BoardPoint { row: 2, col: 2 }, Cell::Empty(3)); let _ = game .play(Play { player: 0, action: Action::Flag, - point: POINT_1_2, + point: POINT_1_1, }) .unwrap(); let _ = game .play(Play { player: 0, action: Action::Flag, - point: POINT_2_1, + point: POINT_1_2, }) .unwrap(); let _ = game .play(Play { player: 0, - action: Action::Reveal, - point: BoardPoint { row: 2, col: 2 }, + action: Action::Flag, + point: POINT_2_1, }) .unwrap(); - point_cell(&game, BoardPoint { row: 2, col: 2 }, Cell::Empty(2)); let res = game .play(Play { @@ -1131,39 +1127,37 @@ mod test { point: BoardPoint { row: 2, col: 2 }, }) .expect("double-click should work"); - assert_eq!(res.len(), 9 * 9 - 9); + assert!(res.len() == 9 * 9 - 9); // 5 is worst case scenario for replant } #[test] fn bad_double_click_fails() { - let mut game = set_up_game(true); + let mut game = set_up_game_no_superclick(); let res = game .play(Play { player: 0, action: Action::Reveal, - point: BoardPoint { row: 0, col: 0 }, + point: BoardPoint { row: 2, col: 2 }, }) .unwrap(); - assert_eq!(res.len(), 4); - - num_mines(&game, 2); + assert_eq!(res.len(), 1); + assert_point_cell(&game, BoardPoint { row: 2, col: 2 }, Cell::Empty(3)); let _ = game .play(Play { player: 0, action: Action::Flag, - point: POINT_1_2, + point: POINT_1_1, }) .unwrap(); let _ = game .play(Play { player: 0, - action: Action::Reveal, - point: BoardPoint { row: 2, col: 2 }, + action: Action::Flag, + point: POINT_1_2, }) .unwrap(); - point_cell(&game, BoardPoint { row: 2, col: 2 }, Cell::Empty(2)); let res = game.play(Play { player: 0, @@ -1175,7 +1169,7 @@ mod test { #[test] fn score_works() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let _ = game .play(Play { @@ -1185,7 +1179,7 @@ mod test { }) .unwrap(); - num_mines(&game, 2); + num_mines(&game, 4); let cell_point = BoardPoint { row: 0, col: 2 }; let res = game.play(Play { @@ -1199,7 +1193,7 @@ mod test { #[test] fn dead_errors() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let _ = game .play(Play { @@ -1226,7 +1220,7 @@ mod test { #[test] fn revealed_errors() { - let mut game = set_up_game(true); + let mut game = set_up_game(); let _ = game .play(Play { @@ -1265,13 +1259,20 @@ mod test { #[test] fn victory_works() { - let mut game = set_up_game(true); + let mut game = set_up_game_no_superclick(); let _ = game .play(Play { player: 0, action: Action::Reveal, - point: POINT_0_0, + point: POINT_0_1, + }) + .unwrap(); + let _ = game + .play(Play { + player: 0, + action: Action::Reveal, + point: POINT_1_0, }) .unwrap(); let _ = game @@ -1297,12 +1298,12 @@ mod test { }) .unwrap(); assert!(matches!(res, PlayOutcome::Victory(..))); - assert_eq!(game.players[0].score, 79); + assert_eq!(game.players[0].score, 77); } #[test] fn replant_works() { - let mut game = set_up_game_with_replant(); + let mut game = set_up_game(); let _ = game .play(Play { player: 0, @@ -1317,7 +1318,7 @@ mod test { assert_eq!(game.board[POINT_1_2].0, Cell::Mine); assert_eq!(game.board[POINT_2_1].0, Cell::Mine); - let mut game = set_up_game_with_replant(); + let mut game = set_up_game(); let _ = game .play(Play { player: 0, diff --git a/minesweeper-lib/src/replay.rs b/minesweeper-lib/src/replay.rs index f73dbe0..d5ad9b2 100644 --- a/minesweeper-lib/src/replay.rs +++ b/minesweeper-lib/src/replay.rs @@ -39,8 +39,8 @@ impl MinesweeperReplay { self.current_play } - pub fn current_board(&self) -> Board { - self.current_board.clone() + pub fn current_board(&self) -> &Board { + &self.current_board } pub fn advance(&mut self) -> Result<()> { @@ -287,37 +287,37 @@ mod test { // test advance assert_eq!(replay.len(), 5); assert!(matches!(replay.advance(), Ok(()))); - assert_eq!(replay.current_board(), expected_board_1); + assert_eq!(replay.current_board(), &expected_board_1); assert!(matches!(replay.advance(), Ok(()))); - assert_eq!(replay.current_board(), expected_board_2); + assert_eq!(replay.current_board(), &expected_board_2); assert!(matches!(replay.advance(), Ok(()))); - assert_eq!(replay.current_board(), expected_board_3); + assert_eq!(replay.current_board(), &expected_board_3); assert!(matches!(replay.advance(), Ok(()))); - assert_eq!(replay.current_board(), expected_final_board); + assert_eq!(replay.current_board(), &expected_final_board); // should error on advance at end assert!(replay.advance().is_err()); // test rewind assert!(matches!(replay.rewind(), Ok(()))); - assert_eq!(replay.current_board(), expected_board_3); + assert_eq!(replay.current_board(), &expected_board_3); assert!(matches!(replay.rewind(), Ok(()))); - assert_eq!(replay.current_board(), expected_board_2); + assert_eq!(replay.current_board(), &expected_board_2); assert!(matches!(replay.rewind(), Ok(()))); - assert_eq!(replay.current_board(), expected_board_1); + assert_eq!(replay.current_board(), &expected_board_1); assert!(matches!(replay.rewind(), Ok(()))); - assert_eq!(replay.current_board(), expected_starting_board); + assert_eq!(replay.current_board(), &expected_starting_board); // should error on rewind at beginning assert!(replay.rewind().is_err()); // try to_pos (auto advance/rewind) assert!(matches!(replay.to_pos(2), Ok(()))); - assert_eq!(replay.current_board(), expected_board_2); + assert_eq!(replay.current_board(), &expected_board_2); assert!(matches!(replay.to_pos(4), Ok(()))); - assert_eq!(replay.current_board(), expected_final_board); + assert_eq!(replay.current_board(), &expected_final_board); assert!(matches!(replay.to_pos(1), Ok(()))); - assert_eq!(replay.current_board(), expected_board_1); + assert_eq!(replay.current_board(), &expected_board_1); assert!(replay.to_pos(5).is_err()); } diff --git a/web/src/app/auth.rs b/web/src/app/auth.rs index f9adeba..046eb43 100644 --- a/web/src/app/auth.rs +++ b/web/src/app/auth.rs @@ -18,7 +18,7 @@ pub struct FrontendUser { } impl FrontendUser { - pub fn display_name_or_anon(display_name: &Option, is_user: bool) -> String { + pub fn display_name_or_anon(display_name: Option<&String>, is_user: bool) -> String { if let Some(name) = display_name { name.to_owned() } else if is_user { diff --git a/web/src/app/header.rs b/web/src/app/header.rs index d7913a8..091efcd 100644 --- a/web/src/app/header.rs +++ b/web/src/app/header.rs @@ -14,18 +14,18 @@ fn logo() -> impl IntoView { let cell_class_flag = cell_class("", "bg-neutral-500 hover:bg-neutral-600/90"); view! { - M - i - n + M + i + n e s - w + w e - e + e - e + e r } @@ -42,18 +42,18 @@ where None => view! { "Guest (" - Log in + "Log in" ")" } .into_view(), Some(user) => { - let name = FrontendUser::display_name_or_anon(&user.display_name, true); + let name = FrontendUser::display_name_or_anon(user.display_name.as_ref(), true); view! { {name} " (" - Profile + "Profile" ")" } diff --git a/web/src/app/minesweeper.rs b/web/src/app/minesweeper.rs index f01d8e9..4fe866c 100644 --- a/web/src/app/minesweeper.rs +++ b/web/src/app/minesweeper.rs @@ -40,7 +40,10 @@ impl From<&PlayerUser> for ClientPlayer { fn from(value: &PlayerUser) -> Self { ClientPlayer { player_id: value.player as usize, - username: FrontendUser::display_name_or_anon(&value.display_name, value.user.is_some()), + username: FrontendUser::display_name_or_anon( + value.display_name.as_ref(), + value.user.is_some(), + ), dead: value.dead, victory_click: value.victory_click, top_score: value.top_score, diff --git a/web/src/app/minesweeper/client.rs b/web/src/app/minesweeper/client.rs index 6db5c25..815d696 100644 --- a/web/src/app/minesweeper/client.rs +++ b/web/src/app/minesweeper/client.rs @@ -28,7 +28,7 @@ pub struct PlayersContext { impl PlayersContext { pub fn from(frontend_game: &FrontendGame) -> Self { PlayersContext { - game_id: frontend_game.game_id.clone(), + game_id: Rc::clone(&frontend_game.game_id), is_owner: frontend_game.is_owner, has_owner: frontend_game.has_owner, player_id: frontend_game.player_id, @@ -103,7 +103,7 @@ impl FrontendGame { let rows = game_info.rows; let cols = game_info.cols; FrontendGame { - game_id: Rc::new(game_info.game_id.clone()), + game_id: Rc::new(game_info.game_id.to_owned()), is_owner: game_info.is_owner, has_owner: game_info.has_owner, cells: read_signals, diff --git a/web/src/app/minesweeper/game.rs b/web/src/app/minesweeper/game.rs index 0a98f89..fc67499 100644 --- a/web/src/app/minesweeper/game.rs +++ b/web/src/app/minesweeper/game.rs @@ -59,17 +59,7 @@ pub async fn get_game(game_id: String) -> Result { } else { None }; - let players_simple = players - .into_iter() - .map(ClientPlayer::from) - .collect::>(); - let players_frontend = - players_simple - .iter() - .fold(vec![None; game.max_players as usize], |mut acc, p| { - acc[p.player_id] = Some(p.clone()); - acc - }); + let players_simple = players.iter().map(ClientPlayer::from).collect::>(); let final_board = match (game.final_board, game_log) { (Some(board), Some(game_log)) => { let completed_minesweeper = CompletedMinesweeper::from_log( @@ -90,6 +80,14 @@ pub async fn get_game(game_id: String) -> Result { game.rows as usize ]), }; + let players_frontend = + players + .into_iter() + .fold(vec![None; game.max_players as usize], |mut acc, p| { + let index = p.player as usize; + acc[index] = Some(ClientPlayer::from(p)); + acc + }); Ok(GameInfo { game_id: game.game_id, has_owner: game.owner.is_some(), @@ -132,7 +130,8 @@ pub fn Game() -> impl IntoView { view! { "Game not found" } - }>{move || { game_info.clone().map(game_view) }} + }>{game_info.map(game_view) + } } }) }} @@ -168,19 +167,22 @@ where { let (error, set_error) = create_signal::>(None); - let game_id = game_info.game_id.clone(); let UseWebSocketReturn { ready_state, message, send, .. - } = use_websocket::(&format!("/api/websocket/game/{}", &game_id)); + } = use_websocket::(&format!( + "/api/websocket/game/{}", + &game_info.game_id + )); let game = FrontendGame::new(&game_info, set_error, Rc::new(send.clone())); let (game_signal, _) = create_signal(game.clone()); - provide_context::(PlayersContext::from(&game)); + let players_context = PlayersContext::from(&game); + let game_id = game_info.game_id.clone(); create_effect(move |_| { log::debug!("before ready_state"); let state = ready_state(); @@ -276,9 +278,9 @@ where view! {

- Game: {{ game_info.game_id.clone() }} + "Game: "{ &game_info.game_id }

- + @@ -322,7 +324,6 @@ where #[component] pub fn InactiveGame(game_info: GameInfo) -> impl IntoView { - let players = game_info.players.clone(); let game_settings = GameSettings::from(&game_info); let game_time = match (game_info.start_time, game_info.end_time) { (Some(st), Some(et)) => et.signed_duration_since(st).num_seconds(), @@ -338,9 +339,9 @@ pub fn InactiveGame(game_info: GameInfo) -> impl IntoView { view! {

- Game: {{ game_info.game_id.clone() }} + "Game: "{ &game_info.game_id }

- + diff --git a/web/src/app/minesweeper/players.rs b/web/src/app/minesweeper/players.rs index 001d2ba..1d26068 100644 --- a/web/src/app/minesweeper/players.rs +++ b/web/src/app/minesweeper/players.rs @@ -1,6 +1,7 @@ use anyhow::Result; use leptos::*; use leptos_router::*; +use std::rc::Rc; use minesweeper_lib::client::ClientPlayer; @@ -25,13 +26,13 @@ where - Player + "Player" - Username + "Username" - Score + "Score" @@ -42,27 +43,28 @@ where } #[component] -pub fn ActivePlayers() -> impl IntoView { - let players_ctx = expect_context::(); +pub fn ActivePlayers(players_context: PlayersContext) -> impl IntoView { let start_game = create_server_action::(); - let (player_id, players, loaded, started, join_trigger) = { - ( - players_ctx.player_id, - players_ctx.players.clone(), - players_ctx.players_loaded, - players_ctx.started, - players_ctx.join_trigger, - ) - }; + let PlayersContext { + game_id, + is_owner, + has_owner, + player_id, + players, + players_loaded, + started, + join_trigger, + } = players_context; log::debug!("players: {players:?}"); let num_players = players.len(); let last_slot = *players.last().unwrap(); - let show_play = - move || loaded() && last_slot().is_none() && player_id().is_none() && num_players > 1; + let show_play = move || { + players_loaded() && last_slot().is_none() && player_id().is_none() && num_players > 1 + }; let show_start = move || { - loaded() - && (players_ctx.is_owner || (!players_ctx.has_owner && player_id().is_some())) + players_loaded() + && (is_owner || (!has_owner && player_id().is_some())) && !started() && num_players > 1 }; @@ -70,7 +72,7 @@ pub fn ActivePlayers() -> impl IntoView { if num_players == 1 { log::debug!("num players 1"); create_effect(move |_| { - if loaded() { + if players_loaded() { log::debug!("join_trigger"); join_trigger.notify(); } @@ -78,10 +80,10 @@ pub fn ActivePlayers() -> impl IntoView { } let buttons = move || { - let game_id = players_ctx.game_id.clone(); + let game_id = Rc::clone(&game_id); view! { - + @@ -94,9 +96,9 @@ pub fn ActivePlayers() -> impl IntoView {

Players

{players - .iter() + .into_iter() .enumerate() - .map(move |(n, &player)| { + .map(move |(n, player)| { view! { } }) .collect_view()} @@ -119,10 +121,10 @@ pub fn InactivePlayers(players: Vec>) -> impl IntoView { {players - .iter() + .into_iter() .enumerate() .map(|(i, player)| { - view! { } + view! { } }) .collect_view()} @@ -143,10 +145,10 @@ fn ActivePlayer(player_num: usize, player: ReadSignal>) -> #[component] fn PlayerRow(player_num: usize, player: Option) -> impl IntoView { let (mut player_class, username, is_dead, victory_click, top_score, score) = - if let Some(player) = &player { + if let Some(player) = player { ( player_class(player.player_id), - player.username.clone(), + player.username, player.dead, player.victory_click, player.top_score, @@ -214,13 +216,11 @@ fn PlayerRow(player_num: usize, player: Option) -> impl IntoView { } #[component] -fn PlayForm() -> impl IntoView { - let players_ctx = expect_context::(); - let (trigger_join, _) = create_signal(players_ctx.join_trigger); +fn PlayForm(join_trigger: Trigger) -> impl IntoView { let (show, set_show) = create_signal(true); let join_game = move || { - trigger_join().notify(); + join_trigger.notify(); set_show(false); }; @@ -243,7 +243,7 @@ fn PlayForm() -> impl IntoView { } .into_view() } else { - view! {
Joining...
}.into_view() + view! {
"Joining..."
}.into_view() } }} } diff --git a/web/src/app/minesweeper/widgets.rs b/web/src/app/minesweeper/widgets.rs index a996fd6..6ae6967 100644 --- a/web/src/app/minesweeper/widgets.rs +++ b/web/src/app/minesweeper/widgets.rs @@ -72,7 +72,7 @@ pub fn ActiveTimer(
- {{ display_time }} + { display_time }
} @@ -83,7 +83,7 @@ pub fn InactiveMines(num_mines: usize) -> impl IntoView { view! {
- {{ num_mines }} + { num_mines }
@@ -114,7 +114,7 @@ pub fn InactiveTimer(game_time: usize) -> impl IntoView {
- {{ game_time }} + { game_time }
} @@ -139,12 +139,13 @@ pub fn CopyGameLink(game_id: String) -> impl IntoView { String::new() } }; + let url = format!("{}/game/{}", origin, game_id); view! {