From 8bdc98c2ac80ba573d40ad61aa29cf573a3a3469 Mon Sep 17 00:00:00 2001 From: itsscb Date: Wed, 28 Aug 2024 22:36:31 +0200 Subject: [PATCH 1/2] feat: improves frontend --- Cargo.lock | 2 + frontend/Cargo.toml | 2 + frontend/src/pages/game.rs | 24 +++++++ frontend/src/pages/home.rs | 143 +++++++++++++++++++++++++------------ 4 files changed, 127 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0720bfc..931dac4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2763,7 +2763,9 @@ name = "wordl-frontend" version = "0.1.0" dependencies = [ "gloo-net 0.6.0", + "rand", "serde", + "serde_json", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index 304fff5..f318717 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -18,3 +18,5 @@ wasm-bindgen = "0.2.93" yewdux = "0.10.0" gloo-net = "0.6.0" serde = { version = "1.0.209", features = ["derive"] } +serde_json = "1.0.127" +rand = "0.8.5" diff --git a/frontend/src/pages/game.rs b/frontend/src/pages/game.rs index 8239191..bae27b0 100644 --- a/frontend/src/pages/game.rs +++ b/frontend/src/pages/game.rs @@ -1,3 +1,4 @@ +use rand::seq::SliceRandom; use serde::{Deserialize, Serialize}; use crate::CharStatus; @@ -9,6 +10,29 @@ struct Game { result: GameResult, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct WordList { + words: Vec, +} + +impl WordList { + pub const fn new() -> Self { + Self { words: Vec::new() } + } + pub fn from_json(s: &str) -> Self { + serde_json::from_str(s).map_or(Self::new(), |w| w) + } + pub fn to_json(&self) -> String { + serde_json::to_string_pretty(self).map_or(String::new(), |w| w) + } + pub fn get_word(&self) -> String { + let mut rng = rand::thread_rng(); + self.words + .choose(&mut rng) + .map_or_else(String::new, |w| (*w).to_string()) + } +} + impl Game { #[allow(dead_code)] pub fn new(word: String, submitted_words: Vec>>) -> Self { diff --git a/frontend/src/pages/home.rs b/frontend/src/pages/home.rs index 4476035..d5c81f0 100644 --- a/frontend/src/pages/home.rs +++ b/frontend/src/pages/home.rs @@ -1,14 +1,21 @@ +use std::time::Duration; + use gloo_net::http::Request; +use wasm_bindgen_futures::spawn_local; use web_sys::wasm_bindgen::convert::OptionIntoWasmAbi; use web_sys::wasm_bindgen::JsCast; use web_sys::HtmlElement; +use yew::platform::time::sleep; use yew::prelude::*; use yew::{classes, function_component, Callback, Html}; use crate::pages::game::GameResult; use crate::CharStatus; +use super::game::WordList; + static NEW_WORD_URI: &str = "https://wordl.shuttleapp.rs/word"; +static WORDS_URI: &str = "https://wordl.shuttleapp.rs/public/wordlist.json"; static MAX_TRIES: usize = 5; fn set_focus(index: usize) { @@ -36,6 +43,7 @@ fn string_to_html(input: &[CharStatus]) -> Html { "py-4", "font-bold", "text-lg", + "mb-4", ); html! (
    ]) -> Html { #[allow(clippy::too_many_arguments)] fn fetch_new_word( + word_list: &UseStateHandle, word: &UseStateHandle, loading: &UseStateHandle, submitted_words: &UseStateHandle>>>, @@ -105,7 +114,6 @@ fn fetch_new_word( node_refs: &UseStateHandle>, result: &UseStateHandle, ) { - let handle = word.clone(); let loading = loading.clone(); let submitted_words = submitted_words.clone(); let input_values = input_values.clone(); @@ -113,7 +121,8 @@ fn fetch_new_word( let length = length.clone(); let node_refs = node_refs.clone(); let result = result.clone(); - + let word = word.clone(); + // let word_list = word_list.clone(); wasm_bindgen_futures::spawn_local(async move { loading.set(true); let res = Request::get(NEW_WORD_URI).send().await; @@ -122,11 +131,25 @@ fn fetch_new_word( length.set(w.len()); node_refs.set(vec![NodeRef::default(); w.len()]); input_values.set(vec![String::new(); w.len()]); - handle.set(w.to_uppercase()); + word.set(w.to_uppercase()); submitted_words.set(Vec::with_capacity(MAX_TRIES)); game_over.set(false); result.set(GameResult::Lose); loading.set(false); + // sleep(Duration::from_secs(5)).await; + // word.set(word_list.get_word().to_uppercase()); + } + } + }); +} + +fn fetch_words(state: &UseStateHandle) { + let state = state.clone(); + wasm_bindgen_futures::spawn_local(async move { + let res = Request::get(WORDS_URI).send().await; + if let Ok(r) = res { + if let Ok(w) = r.text().await { + state.set(WordList::from_json(&w)); } } }); @@ -134,6 +157,8 @@ fn fetch_new_word( #[function_component] pub fn Home() -> Html { + let word_list: UseStateHandle = use_state(WordList::new); + let word: UseStateHandle = use_state(String::new); let loading: UseStateHandle = use_state(|| true); let curr_index: UseStateHandle = use_state(|| 0usize); @@ -149,6 +174,8 @@ pub fn Home() -> Html { let result = use_state(|| GameResult::Lose); { + let word_list = word_list.clone(); + let wl = word_list.clone(); let handle = word.clone(); let loading = loading.clone(); @@ -159,8 +186,16 @@ pub fn Home() -> Html { let node_refs = node_refs.clone(); let result = result.clone(); + // use_effect_with((), move |()| { + // spawn_local(async move { + // fetch_words(&wl); + // }); + // }); + use_effect_with((), move |()| { + // sleep(Duration::from_millis(200)); fetch_new_word( + &word_list, &handle, &loading, &submitted_words, @@ -208,10 +243,12 @@ pub fn Home() -> Html { let loading = loading.clone(); let result = result.clone(); let curr_index = curr_index.clone(); + let word_list = word_list.clone(); Callback::from(move |_e: MouseEvent| { if *game_over { curr_index.set(0); + let word_list = word_list.clone(); let input_values = input_values.clone(); let submitted_words = submitted_words.clone(); let game_over = game_over.clone(); @@ -221,6 +258,7 @@ pub fn Home() -> Html { let node_refs = node_refs.clone(); let result = result.clone(); fetch_new_word( + &word_list, &word, &loading, &submitted_words, @@ -246,60 +284,65 @@ pub fn Home() -> Html { }) }; let on_enter = { - let on_submit = on_submit.clone(); - let curr_index = curr_index.clone(); - let node_refs = node_refs.clone(); - let input_values = input_values.clone(); + let on_submit = on_submit.clone(); + let curr_index = curr_index.clone(); + let node_refs = node_refs.clone(); + let input_values = input_values.clone(); + let length = length.clone(); - Callback::from(move |e: KeyboardEvent| { - - match e.key().as_ref() { - "Enter" => { - if let Ok(m) = MouseEvent::new("click") { - on_submit.emit(m); - } + Callback::from(move |e: KeyboardEvent| match e.key().as_ref() { + "Enter" => { + if let Ok(m) = MouseEvent::new("click") { + on_submit.emit(m); } - "Backspace" => { - e.prevent_default(); - - - let index = *curr_index; - let mut values = (*input_values).clone(); - if node_refs[index] - .cast::() - .is_some() - && index > 0 - { - values[index] = String::new(); - input_values.set(values); - let index = index - 1; - curr_index.set(index); - set_focus(index); - } - } - _ => {} } + "Backspace" => { + e.prevent_default(); + + let mut index = *curr_index; + let mut values = (*input_values).clone(); + + if index >= *length { + curr_index.set(*length - 1); + index = *length - 1; + } + + if node_refs[index] + .cast::() + .is_some() + && index > 0 + { + values[index] = String::new(); + input_values.set(values); + let index = index - 1; + curr_index.set(index); + set_focus(index); + } + } + _ => {} }) }; - + let on_input = { let curr_index = curr_index.clone(); let length = length.clone(); let input_values = input_values.clone(); - + Callback::from(move |e: InputEvent| { if let Some(value) = e.data() { let index = *curr_index; let mut values = (*input_values).clone(); - if value.len() < values[index].len() && index > 0 { + if index >= *length { + values[index - 1] = value; + input_values.set(values); + } else if value.len() < values[index].len() && index > 0 && index <= *length { values[index] = String::new(); input_values.set(values); let new_index = index - 1; curr_index.set(new_index); set_focus(new_index); - } - else if value.len() == 1 && value.chars().all(char::is_alphabetic) { + } else if value.len() == 1 && value.chars().all(char::is_alphabetic) { values[index] = value.to_uppercase(); input_values.set(values); if index < *length { @@ -310,7 +353,7 @@ pub fn Home() -> Html { } else { values[index] = String::new(); input_values.set(values); - } + } } }) }; @@ -329,11 +372,23 @@ pub fn Home() -> Html { ) } > + //

    {format!("{:?}",*word_list)}

    - -
    + +
    { for submitted_words.iter().map(|e| {string_to_html(e)})}
    Html { "w-full", "flex", "justify-end", - + ) } > @@ -506,7 +561,7 @@ pub fn Home() -> Html { } } } - +
    } From af044b14ce533cdd322831ea4ea27f4cd8ea115f Mon Sep 17 00:00:00 2001 From: itsscb Date: Wed, 28 Aug 2024 22:54:57 +0200 Subject: [PATCH 2/2] fix(workflow): removes on PR --- .github/workflows/prod.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml index b401d5c..c33e75c 100644 --- a/.github/workflows/prod.yml +++ b/.github/workflows/prod.yml @@ -2,9 +2,6 @@ on: push: branches: - master - pull_request: - branches: - - master permissions: contents: write