diff --git a/front_end/src/html_helper.rs b/front_end/src/html_helper.rs index a727393..18683dc 100644 --- a/front_end/src/html_helper.rs +++ b/front_end/src/html_helper.rs @@ -72,7 +72,7 @@ pub fn element_append_class(document: &Document, id: &str, class: &str) -> Resul .get_element_by_id(id) .ok_or_else(|| format!("Failed to get element with id \"{}\"", id))?; let new_class = format!("{} {}", element.class_name(), class); - element.set_class_name(&new_class); + element.set_class_name(&string_remove_extra_whitespace(&new_class)); Ok(()) } @@ -87,11 +87,29 @@ pub fn element_remove_class(document: &Document, id: &str, class: &str) -> Resul let mut remaining = element_class.split_off(idx); element_class += &remaining.split_off(class.len()); } - element.set_class_name(&element_class); + element.set_class_name(&string_remove_extra_whitespace(&element_class)); Ok(()) } +fn string_remove_extra_whitespace(s: &str) -> String { + let mut replacement_string = String::with_capacity(s.len()); + let mut is_space = false; + for c in s.chars() { + if c != ' ' { + replacement_string.push(c); + is_space = false; + } else if is_space { + continue; + } else { + replacement_string.push(c); + is_space = true; + } + } + + replacement_string +} + pub fn element_has_class(document: &Document, id: &str, class: &str) -> Result { let element = document .get_element_by_id(id) diff --git a/front_end/src/yew_components.rs b/front_end/src/yew_components.rs index d587b1e..08d7c20 100644 --- a/front_end/src/yew_components.rs +++ b/front_end/src/yew_components.rs @@ -177,6 +177,25 @@ impl Component for MainMenu { .clone() .downcast::() .send_message(WrapperMsg::BackendTick); + // set reset when page "unload" + ctx.link() + .get_parent() + .expect("Wrapper should be a parent of MainMenu") + .clone() + .downcast::() + .send_future(async { + let promise = + Promise::new(&mut |resolve: js_sys::Function, _reject| { + let window = + web_sys::window().expect("Should be able to get window"); + window + .add_event_listener_with_callback("pagehide", &resolve) + .expect("Should be able to set \"pagehide\" callback"); + }); + let js_fut = JsFuture::from(promise); + js_fut.await.ok(); + WrapperMsg::Reset + }); } _ => { append_to_info_text( @@ -340,19 +359,6 @@ impl Wrapper { )); } - // set up onbeforeunload to disconnect with the received id - let function = Function::new_no_args(&format!( - " - window.addEventListener(\"beforeunload\", function(event) {{ - let xhr = new XMLHttpRequest(); - xhr.open('POST', '{}'); - xhr.send('{{\"type\": \"disconnect\", \"id\": {}}}'); - }}); - ", - BACKEND_URL, request.id - )); - function.call0(&function).ok(); - if let Some(color) = request.color { WrapperMsg::BackendResponse(BREnum::GotID( request.id, @@ -591,6 +597,7 @@ pub enum WrapperMsg { BackendTick, BackendRequest { place: u8 }, BackendResponse(BREnum), + Reset, } impl WrapperMsg { @@ -1538,6 +1545,33 @@ impl Component for Wrapper { } } } + WrapperMsg::Reset => { + shared.game_state.set(GameState::default()); + shared.turn.set(Turn::CyanPlayer); + for idx in 0..((ROWS * COLS) as usize) { + shared.placed[idx].set(false); + shared.board[idx].set(BoardState::Empty); + element_remove_class(&document, &format!("slot{}", idx), "open").ok(); + element_remove_class(&document, &format!("slot{}", idx), "placed").ok(); + element_remove_class(&document, &format!("slot{}", idx), "win").ok(); + element_remove_class(&document, &format!("slot{}", idx), "cyan").ok(); + element_remove_class(&document, &format!("slot{}", idx), "magenta").ok(); + element_append_class(&document, &format!("slot{}", idx), "open").ok(); + } + if let Some(id) = self.player_id.take() { + let function = Function::new_no_args(&format!( + " + let xhr = new XMLHttpRequest(); + xhr.open('POST', '{}'); + xhr.send('{{\"type\": \"disconnect\", \"id\": {}}}'); + ", + BACKEND_URL, id + )); + function.call0(&function).ok(); + } + self.place_request = None; + self.do_backend_tick = false; + } } // match (msg) true