migrate to leptos 0.7
This commit is contained in:
parent
f22f1a00a9
commit
0de020ac39
19 changed files with 695 additions and 396 deletions
731
Cargo.lock
generated
731
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -7,18 +7,19 @@ authors = ["Adam Doyle <adam@doordesk.net>"]
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
leptos = { version = "0.6", features = ["csr", "nightly"] }
|
leptos = { version = "0.7.0-beta", features = ["csr", "nightly"] }
|
||||||
leptos_meta = { version = "0.6", features = ["csr", "nightly"] }
|
leptos_meta = { version = "0.7.0-beta" }
|
||||||
leptos_router = { version = "0.6", features = ["csr", "nightly"] }
|
leptos_router = { version = "0.7.0-beta", features = ["nightly"] }
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
console_log = "1"
|
console_log = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
leptos-use = "0.13"
|
leptos-use = "0.14.0-beta"
|
||||||
codee = "0.2"
|
codee = "0.2"
|
||||||
|
|
||||||
lib = { workspace = true }
|
lib = { workspace = true }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
thaw = { version = "0.4.0-beta2", features = ["csr", "nightly"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- Add a plain CSS file: see https://trunkrs.dev/assets/#css -->
|
<meta charset="utf-8" />
|
||||||
<!-- If using Tailwind with Leptos CSR, see https://trunkrs.dev/assets/#tailwind instead-->
|
|
||||||
<link data-trunk rel="tailwind-css" href="public/styles.css" />
|
|
||||||
|
|
||||||
<!-- Include favicon in dist output: see https://trunkrs.dev/assets/#icon -->
|
|
||||||
<link data-trunk rel="icon" href="public/favicon.ico" />
|
|
||||||
|
|
||||||
<!-- include support for `wasm-bindgen --weak-refs` - see: https://rustwasm.github.io/docs/wasm-bindgen/reference/weak-references.html -->
|
|
||||||
<link data-trunk rel="rust" data-target-path="client" data-wasm-opt="z" data-weak-refs />
|
<link data-trunk rel="rust" data-target-path="client" data-wasm-opt="z" data-weak-refs />
|
||||||
|
<link data-trunk rel="icon" href="public/favicon.ico" />
|
||||||
|
<link data-trunk rel="tailwind-css" href="public/styles.css" />
|
||||||
|
<title>Cards for Humanity</title>
|
||||||
</head>
|
</head>
|
||||||
<body></body>
|
<body></body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
@apply text-neutral-200;
|
@apply text-neutral-200 bg-neutral-900;
|
||||||
font-family: "Inter", sans-serif;
|
font-family: "Inter", sans-serif;
|
||||||
font-optical-sizing: auto;
|
font-optical-sizing: auto;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use html::Input;
|
use leptos::{html::Input, prelude::*};
|
||||||
use leptos::*;
|
|
||||||
use leptos_use::core::ConnectionReadyState;
|
use leptos_use::core::ConnectionReadyState;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
@ -8,11 +7,11 @@ use serde_json::to_string;
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Auth() -> impl IntoView {
|
pub fn Auth() -> impl IntoView {
|
||||||
let websocket = expect_context::<WebSocketContext>();
|
let websocket = expect_context::<WebSocketContext>();
|
||||||
let (username, set_username) = create_signal("".to_string());
|
let (username, set_username) = signal("".to_string());
|
||||||
let user_context = expect_context::<ReadSignal<Option<UserUpdate>>>();
|
let user_context = expect_context::<ReadSignal<Option<UserUpdate>>>();
|
||||||
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
||||||
|
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
user_context.with(|new_user| {
|
user_context.with(|new_user| {
|
||||||
if let Some(user) = new_user {
|
if let Some(user) = new_user {
|
||||||
set_username(user.username.to_string());
|
set_username(user.username.to_string());
|
||||||
|
@ -20,7 +19,7 @@ pub fn Auth() -> impl IntoView {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let username_input_ref = create_node_ref::<Input>();
|
let username_input_ref = NodeRef::<Input>::new();
|
||||||
let send_login = move |_| {
|
let send_login = move |_| {
|
||||||
if let Some(input) = username_input_ref.get() {
|
if let Some(input) = username_input_ref.get() {
|
||||||
if input.value() != String::from("") {
|
if input.value() != String::from("") {
|
||||||
|
@ -37,7 +36,7 @@ pub fn Auth() -> impl IntoView {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clear user name on disconnect
|
// Clear user name on disconnect
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
if !connected() {
|
if !connected() {
|
||||||
set_username(String::from(""));
|
set_username(String::from(""));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use leptos_use::core::ConnectionReadyState;
|
use leptos_use::core::ConnectionReadyState;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
@ -11,9 +11,9 @@ pub fn Browser() -> impl IntoView {
|
||||||
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
||||||
|
|
||||||
let tx = websocket.clone();
|
let tx = websocket.clone();
|
||||||
let (websocket_send, set_websocket_send) = create_signal("".to_string());
|
let (websocket_send, set_websocket_send) = signal("".to_string());
|
||||||
|
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
if websocket_send() != "".to_string() {
|
if websocket_send() != "".to_string() {
|
||||||
tx.send(&websocket_send());
|
tx.send(&websocket_send());
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,14 @@ pub fn Browser() -> impl IntoView {
|
||||||
|
|
||||||
// Browser stuff
|
// Browser stuff
|
||||||
let game_browser_context = expect_context::<ReadSignal<Vec<GameBrowserMeta>>>();
|
let game_browser_context = expect_context::<ReadSignal<Vec<GameBrowserMeta>>>();
|
||||||
let (join_id, set_join_id) = create_signal("".to_string());
|
let (join_id, set_join_id) = signal("".to_string());
|
||||||
let (delete_id, set_delete_id) = create_signal("".to_string());
|
let (delete_id, set_delete_id) = signal("".to_string());
|
||||||
|
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
set_websocket_send(to_string(&GameJoinRequest { id: join_id() }).unwrap());
|
set_websocket_send(to_string(&GameJoinRequest { id: join_id() }).unwrap());
|
||||||
});
|
});
|
||||||
|
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
set_websocket_send(
|
set_websocket_send(
|
||||||
to_string(&GameDeleteRequest {
|
to_string(&GameDeleteRequest {
|
||||||
delete_game_id: delete_id(),
|
delete_game_id: delete_id(),
|
||||||
|
@ -74,7 +74,7 @@ pub fn Browser() -> impl IntoView {
|
||||||
<td class="text-center border-b">
|
<td class="text-center border-b">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
value=&game.uuid
|
value=game.uuid.clone()
|
||||||
on:click=move |e| {
|
on:click=move |e| {
|
||||||
set_join_id(event_target_value(&e));
|
set_join_id(event_target_value(&e));
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ pub fn Browser() -> impl IntoView {
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
value=&game.uuid
|
value=game.uuid.clone()
|
||||||
on:click=move |e| {
|
on:click=move |e| {
|
||||||
set_delete_id(event_target_value(&e));
|
set_delete_id(event_target_value(&e));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use html::{Input, Textarea};
|
use leptos::{
|
||||||
use leptos::*;
|
html::{Input, Textarea},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
use leptos_use::core::ConnectionReadyState;
|
use leptos_use::core::ConnectionReadyState;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
@ -13,18 +15,18 @@ pub fn Chat() -> impl IntoView {
|
||||||
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
||||||
|
|
||||||
// Chat stuff
|
// Chat stuff
|
||||||
let (chat_history, set_chat_history) = create_signal::<Vec<String>>(vec![]);
|
let (chat_history, set_chat_history) = signal::<Vec<String>>(vec![]);
|
||||||
let (users, set_users) = create_signal::<Vec<String>>(vec![]);
|
let (users, set_users) = signal::<Vec<String>>(vec![]);
|
||||||
let (chat_name, set_chat_name) = create_signal::<String>("".to_string());
|
let (chat_name, set_chat_name) = signal::<String>("".to_string());
|
||||||
let chat_history_ref = create_node_ref::<Textarea>();
|
let chat_history_ref = NodeRef::<Textarea>::new();
|
||||||
let chat_input_ref = create_node_ref::<Input>();
|
let chat_input_ref = NodeRef::<Input>::new();
|
||||||
|
|
||||||
fn update_chat_history(&history: &WriteSignal<Vec<String>>, message: String) {
|
fn update_chat_history(&history: &WriteSignal<Vec<String>>, message: String) {
|
||||||
let _ = &history.update(|history: &mut Vec<_>| history.push(message));
|
let _ = &history.update(|history: &mut Vec<_>| history.push(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection status updates in chat window
|
// Connection status updates in chat window
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
websocket.ready_state.with(move |state| match *state {
|
websocket.ready_state.with(move |state| match *state {
|
||||||
ConnectionReadyState::Connecting => {
|
ConnectionReadyState::Connecting => {
|
||||||
update_chat_history(
|
update_chat_history(
|
||||||
|
@ -45,7 +47,7 @@ pub fn Chat() -> impl IntoView {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle incoming chat messages
|
// Handle incoming chat messages
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
chat_context.with(move |chat_message| {
|
chat_context.with(move |chat_message| {
|
||||||
if let Some(message) = chat_message {
|
if let Some(message) = chat_message {
|
||||||
update_chat_history(&set_chat_history, format!("{}\n", message.text));
|
update_chat_history(&set_chat_history, format!("{}\n", message.text));
|
||||||
|
@ -54,7 +56,7 @@ pub fn Chat() -> impl IntoView {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle users
|
// Handle users
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
chat_update_context.with(move |chat_update| {
|
chat_update_context.with(move |chat_update| {
|
||||||
if let Some(update) = chat_update {
|
if let Some(update) = chat_update {
|
||||||
set_users(update.users.clone());
|
set_users(update.users.clone());
|
||||||
|
@ -64,7 +66,7 @@ pub fn Chat() -> impl IntoView {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clear user list on disconnect
|
// Clear user list on disconnect
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
websocket.ready_state.with(move |status| {
|
websocket.ready_state.with(move |status| {
|
||||||
if *status == ConnectionReadyState::Closed {
|
if *status == ConnectionReadyState::Closed {
|
||||||
set_users(vec![]);
|
set_users(vec![]);
|
||||||
|
@ -88,7 +90,7 @@ pub fn Chat() -> impl IntoView {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Keep chat scrolled to the bottom
|
// Keep chat scrolled to the bottom
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
chat_history.with(move |_| {
|
chat_history.with(move |_| {
|
||||||
// Scroll chat textarea to bottom
|
// Scroll chat textarea to bottom
|
||||||
if let Some(hist) = chat_history_ref.get() {
|
if let Some(hist) = chat_history_ref.get() {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use leptos::html::Input;
|
use leptos::{html::Input, prelude::*};
|
||||||
use leptos::*;
|
|
||||||
use leptos_use::core::ConnectionReadyState;
|
use leptos_use::core::ConnectionReadyState;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
@ -10,12 +9,12 @@ use std::collections::BTreeSet;
|
||||||
pub fn CreateGame() -> impl IntoView {
|
pub fn CreateGame() -> impl IntoView {
|
||||||
// Websocket stuff
|
// Websocket stuff
|
||||||
let websocket = expect_context::<WebSocketContext>();
|
let websocket = expect_context::<WebSocketContext>();
|
||||||
let (websocket_send, set_websocket_send) = create_signal("".to_string());
|
let (websocket_send, set_websocket_send) = signal("".to_string());
|
||||||
|
|
||||||
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
||||||
|
|
||||||
let tx = websocket.clone();
|
let tx = websocket.clone();
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
if websocket_send() != "".to_string() {
|
if websocket_send() != "".to_string() {
|
||||||
tx.send(&websocket_send());
|
tx.send(&websocket_send());
|
||||||
}
|
}
|
||||||
|
@ -24,29 +23,29 @@ pub fn CreateGame() -> impl IntoView {
|
||||||
// New game stuff
|
// New game stuff
|
||||||
let card_packs = expect_context::<ReadSignal<CardPacksMeta>>();
|
let card_packs = expect_context::<ReadSignal<CardPacksMeta>>();
|
||||||
|
|
||||||
let (show_packs, set_show_packs) = create_signal(false);
|
let (show_packs, set_show_packs) = signal(false);
|
||||||
let (selected_packs, set_selected_packs) = create_signal::<BTreeSet<u8>>(BTreeSet::new());
|
let (selected_packs, set_selected_packs) = signal::<BTreeSet<u8>>(BTreeSet::new());
|
||||||
|
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
set_selected_packs
|
set_selected_packs
|
||||||
.update(|set| set.extend(card_packs().official_meta.iter().map(|pack| pack.pack)));
|
.update(|set| set.extend(card_packs().official_meta.iter().map(|pack| pack.pack)));
|
||||||
});
|
});
|
||||||
|
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
set_selected_packs
|
set_selected_packs
|
||||||
.update(|set| set.extend(card_packs().unofficial_meta.iter().map(|pack| pack.pack)));
|
.update(|set| set.extend(card_packs().unofficial_meta.iter().map(|pack| pack.pack)));
|
||||||
});
|
});
|
||||||
|
|
||||||
let new_game_name_ref = create_node_ref::<Input>();
|
let new_game_name_ref = NodeRef::<Input>::new();
|
||||||
|
|
||||||
let toggle_show_packs = move |_| set_show_packs(!show_packs());
|
let toggle_show_packs = move |_| set_show_packs(!show_packs());
|
||||||
|
|
||||||
let request_new_game = move |_| {
|
let request_new_game = move |_| {
|
||||||
if let Some(input) = new_game_name_ref.get() {
|
if let Some(input) = new_game_name_ref.get() {
|
||||||
if input.value() == *"" {
|
if input.value() == *"" {
|
||||||
logging::error!("New game name is empty!");
|
println!("New game name is empty!");
|
||||||
} else if selected_packs().is_empty() {
|
} else if selected_packs().is_empty() {
|
||||||
logging::error!("New game selected packs is empty!");
|
println!("New game selected packs is empty!");
|
||||||
} else {
|
} else {
|
||||||
set_websocket_send(
|
set_websocket_send(
|
||||||
to_string(&NewGameRequest {
|
to_string(&NewGameRequest {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use leptos_use::core::ConnectionReadyState;
|
use leptos_use::core::ConnectionReadyState;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ pub fn Debug() -> impl IntoView {
|
||||||
let state_summary = expect_context::<ReadSignal<Option<ServerStateSummary>>>();
|
let state_summary = expect_context::<ReadSignal<Option<ServerStateSummary>>>();
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
let (online_users, set_online_users) = create_signal(0);
|
let (online_users, set_online_users) = signal(0);
|
||||||
let (active_games, set_active_games) = create_signal(0);
|
let (active_games, set_active_games) = signal(0);
|
||||||
|
|
||||||
// Websocket stuff
|
// Websocket stuff
|
||||||
let status = move || websocket.ready_state.get().to_string();
|
let status = move || websocket.ready_state.get().to_string();
|
||||||
|
@ -26,7 +26,7 @@ pub fn Debug() -> impl IntoView {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update server info -> move this to a new component
|
// Update server info -> move this to a new component
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
state_summary.with(move |state_summary| {
|
state_summary.with(move |state_summary| {
|
||||||
if let Some(state_summary) = state_summary {
|
if let Some(state_summary) = state_summary {
|
||||||
set_online_users(state_summary.online_users);
|
set_online_users(state_summary.online_users);
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::components::game::header::*;
|
||||||
use crate::components::game::views::judging::*;
|
use crate::components::game::views::judging::*;
|
||||||
use crate::components::game::views::playing::*;
|
use crate::components::game::views::playing::*;
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use leptos_use::core::ConnectionReadyState;
|
use leptos_use::core::ConnectionReadyState;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
pub mod cards;
|
pub mod cards;
|
||||||
|
@ -20,10 +20,10 @@ pub fn Game() -> impl IntoView {
|
||||||
let user_update = expect_context::<ReadSignal<Option<UserUpdate>>>();
|
let user_update = expect_context::<ReadSignal<Option<UserUpdate>>>();
|
||||||
|
|
||||||
// Signals //
|
// Signals //
|
||||||
let (judging, set_judging) = create_signal(false);
|
let (judging, set_judging) = signal(false);
|
||||||
|
|
||||||
// Determine judging
|
// Determine judging
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
user_update.with(move |user_meta| {
|
user_update.with(move |user_meta| {
|
||||||
if let Some(user_meta) = user_meta {
|
if let Some(user_meta) = user_meta {
|
||||||
if let Some(game_meta) = game_meta() {
|
if let Some(game_meta) = game_meta() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::components::game::cards::*;
|
use crate::components::game::cards::*;
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
|
||||||
|
@ -13,14 +13,14 @@ pub fn JudgingView() -> impl IntoView {
|
||||||
let set_judge_round = expect_context::<WriteSignal<Option<JudgeRound>>>();
|
let set_judge_round = expect_context::<WriteSignal<Option<JudgeRound>>>();
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
let (selected_cards, set_selected_cards) = create_signal::<Vec<WhiteCardMeta>>(vec![]);
|
let (selected_cards, set_selected_cards) = signal::<Vec<WhiteCardMeta>>(vec![]);
|
||||||
let (card_clicked, set_card_clicked) = create_signal::<String>(String::new());
|
let (card_clicked, set_card_clicked) = signal::<String>(String::new());
|
||||||
|
|
||||||
// Outoging
|
// Outoging
|
||||||
provide_context::<WriteSignal<String>>(set_card_clicked);
|
provide_context::<WriteSignal<String>>(set_card_clicked);
|
||||||
|
|
||||||
// On Incoming Judge
|
// On Incoming Judge
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
// Clear selected cards
|
// Clear selected cards
|
||||||
if judge_round().is_some() {
|
if judge_round().is_some() {
|
||||||
set_selected_cards.update(|list| {
|
set_selected_cards.update(|list| {
|
||||||
|
@ -31,7 +31,7 @@ pub fn JudgingView() -> impl IntoView {
|
||||||
|
|
||||||
// Card selection //
|
// Card selection //
|
||||||
// Toggle selected status of cards
|
// Toggle selected status of cards
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
if card_clicked() != "".to_string() {
|
if card_clicked() != "".to_string() {
|
||||||
let identical_cards = selected_cards
|
let identical_cards = selected_cards
|
||||||
.get_untracked()
|
.get_untracked()
|
||||||
|
@ -86,15 +86,15 @@ pub fn JudgingView() -> impl IntoView {
|
||||||
view! {
|
view! {
|
||||||
<div class="w-full ms-16 inline-flex flex-wrap">
|
<div class="w-full ms-16 inline-flex flex-wrap">
|
||||||
<BlackCard />
|
<BlackCard />
|
||||||
|
|
||||||
// Selected cards
|
// Selected cards
|
||||||
<For
|
{move || {
|
||||||
each=move || selected_cards()
|
selected_cards()
|
||||||
key=move |card| card.uuid.clone()
|
.into_iter()
|
||||||
children=move |card| {
|
.map(|card| {
|
||||||
view! { <WhiteCard card_data=card /> }
|
view! { <WhiteCard card_data=card /> }
|
||||||
}
|
})
|
||||||
/>
|
.collect_view()
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
// Submit button
|
// Submit button
|
||||||
|
@ -114,18 +114,17 @@ pub fn JudgingView() -> impl IntoView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<For
|
{judge_round()
|
||||||
each=move || judge_round().unwrap().cards_to_judge
|
.unwrap()
|
||||||
key=move |_| 69
|
.cards_to_judge
|
||||||
children=move |group| {
|
.into_iter()
|
||||||
|
.map(|group| {
|
||||||
view! {
|
view! {
|
||||||
<div class="m-2 inline-flex flex-wrap justify-center">
|
<div class="m-2 inline-flex flex-wrap justify-center">
|
||||||
<For
|
{group
|
||||||
each=move || group.clone()
|
.into_iter()
|
||||||
key=move |card| card.uuid.clone()
|
.map(|card| {
|
||||||
children=move |card| {
|
|
||||||
view! {
|
view! {
|
||||||
// Hide cards from hand view when they exist as selected
|
|
||||||
<Show when={
|
<Show when={
|
||||||
let waste_of_memory = card.clone();
|
let waste_of_memory = card.clone();
|
||||||
move || { !selected_cards().contains(&waste_of_memory) }
|
move || { !selected_cards().contains(&waste_of_memory) }
|
||||||
|
@ -133,12 +132,12 @@ pub fn JudgingView() -> impl IntoView {
|
||||||
<WhiteCard card_data=card.clone() />
|
<WhiteCard card_data=card.clone() />
|
||||||
</Show>
|
</Show>
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
/>
|
.collect_view()}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
/>
|
.collect_view()}
|
||||||
</Show>
|
</Show>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::components::game::cards::*;
|
use crate::components::game::cards::*;
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
@ -13,13 +13,11 @@ pub fn PlayingView() -> impl IntoView {
|
||||||
let game_state = expect_context::<ReadSignal<Option<GameStateMeta>>>();
|
let game_state = expect_context::<ReadSignal<Option<GameStateMeta>>>();
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
let (selected_cards, set_selected_cards) = create_signal::<Vec<WhiteCardMeta>>(vec![]);
|
let (selected_cards, set_selected_cards) = signal::<Vec<WhiteCardMeta>>(vec![]);
|
||||||
let (submitted_cards, set_submitted_cards) =
|
let (submitted_cards, set_submitted_cards) = signal::<HashSet<WhiteCardMeta>>(HashSet::new());
|
||||||
create_signal::<HashSet<WhiteCardMeta>>(HashSet::new());
|
let (card_clicked, set_card_clicked) = signal::<String>(String::new());
|
||||||
let (card_clicked, set_card_clicked) = create_signal::<String>(String::new());
|
let (submitted, set_submitted) = signal(false);
|
||||||
let (submitted, set_submitted) = create_signal(false);
|
let (player_hand, set_player_hand) = signal::<HashMap<String, WhiteCardMeta>>(HashMap::new());
|
||||||
let (player_hand, set_player_hand) =
|
|
||||||
create_signal::<HashMap<String, WhiteCardMeta>>(HashMap::new());
|
|
||||||
|
|
||||||
// Outoging
|
// Outoging
|
||||||
provide_context::<WriteSignal<String>>(set_card_clicked);
|
provide_context::<WriteSignal<String>>(set_card_clicked);
|
||||||
|
@ -27,7 +25,7 @@ pub fn PlayingView() -> impl IntoView {
|
||||||
// On Incoming Meta //
|
// On Incoming Meta //
|
||||||
// Put cards in a map for easier lookup
|
// Put cards in a map for easier lookup
|
||||||
// The server sends a vec to preserve ordering
|
// The server sends a vec to preserve ordering
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
if game_state().is_some() {
|
if game_state().is_some() {
|
||||||
for card in game_state().unwrap().white {
|
for card in game_state().unwrap().white {
|
||||||
set_player_hand.update(|map| {
|
set_player_hand.update(|map| {
|
||||||
|
@ -46,7 +44,7 @@ pub fn PlayingView() -> impl IntoView {
|
||||||
|
|
||||||
// Card selection
|
// Card selection
|
||||||
// Toggle selected status of cards
|
// Toggle selected status of cards
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
if card_clicked() != "".to_string()
|
if card_clicked() != "".to_string()
|
||||||
&& !submitted()
|
&& !submitted()
|
||||||
&& submitted_cards().len() < game_state().unwrap().black.1.into()
|
&& submitted_cards().len() < game_state().unwrap().black.1.into()
|
||||||
|
@ -102,15 +100,12 @@ pub fn PlayingView() -> impl IntoView {
|
||||||
<div class="w-full inline-flex flex-wrap">
|
<div class="w-full inline-flex flex-wrap">
|
||||||
<BlackCard />
|
<BlackCard />
|
||||||
|
|
||||||
// Selected cards
|
{move || selected_cards()
|
||||||
<For
|
.into_iter()
|
||||||
each=move || selected_cards()
|
.map(|card| {
|
||||||
key=move |card| card.uuid.clone()
|
|
||||||
children=move |card| {
|
|
||||||
view! { <WhiteCard card_data=card /> }
|
view! { <WhiteCard card_data=card /> }
|
||||||
}
|
})
|
||||||
/>
|
.collect_view()}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
// Submit button
|
// Submit button
|
||||||
|
@ -130,13 +125,15 @@ pub fn PlayingView() -> impl IntoView {
|
||||||
|
|
||||||
// Player hand
|
// Player hand
|
||||||
<div class="inline-flex flex-wrap justify-center">
|
<div class="inline-flex flex-wrap justify-center">
|
||||||
<Show when=move || game_state().is_some()>
|
<Show when=move || {
|
||||||
<For
|
game_state().is_some()
|
||||||
each=move || game_state().unwrap().white
|
}>
|
||||||
key=move |card| card.uuid.clone()
|
{game_state()
|
||||||
children=move |card| {
|
.unwrap()
|
||||||
|
.white
|
||||||
|
.into_iter()
|
||||||
|
.map(|card| {
|
||||||
view! {
|
view! {
|
||||||
// Hide cards from hand view when they exist as selected or submitted
|
|
||||||
<Show when={
|
<Show when={
|
||||||
let id = card.uuid.clone();
|
let id = card.uuid.clone();
|
||||||
move || {
|
move || {
|
||||||
|
@ -151,10 +148,9 @@ pub fn PlayingView() -> impl IntoView {
|
||||||
<WhiteCard card_data=card.clone() />
|
<WhiteCard card_data=card.clone() />
|
||||||
</Show>
|
</Show>
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
/>
|
.collect_view()}
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
use codee::string::FromToStringCodec;
|
use codee::string::FromToStringCodec;
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use leptos_use::{core::ConnectionReadyState, use_websocket, UseWebSocketReturn};
|
use leptos_use::{core::ConnectionReadyState, use_websocket, UseWebSocketReturn};
|
||||||
use lib::*;
|
use lib::*;
|
||||||
use serde_json::from_str;
|
use serde_json::from_str;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct WebSocketContext {
|
pub struct WebSocketContext {
|
||||||
pub ready_state: Signal<ConnectionReadyState>,
|
pub ready_state: Signal<ConnectionReadyState>,
|
||||||
// pub message: Signal<Option<String>>,
|
// pub message: Signal<Option<String>>,
|
||||||
send: Rc<dyn Fn(&String)>,
|
send: Arc<dyn Fn(&String) + Send + Sync + 'static>,
|
||||||
pub open: Rc<dyn Fn()>,
|
pub open: Arc<dyn Fn() + Send + Sync + 'static>,
|
||||||
pub close: Rc<dyn Fn()>,
|
pub close: Arc<dyn Fn() + Send + Sync + 'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketContext {
|
impl WebSocketContext {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
ready_state: Signal<ConnectionReadyState>,
|
ready_state: Signal<ConnectionReadyState>,
|
||||||
// message: Signal<Option<String>>,
|
// message: Signal<Option<String>>,
|
||||||
send: Rc<dyn Fn(&String)>,
|
send: Arc<dyn Fn(&String) + Send + Sync + 'static>,
|
||||||
open: Rc<dyn Fn()>,
|
open: Arc<dyn Fn() + Send + Sync + 'static>,
|
||||||
close: Rc<dyn Fn()>,
|
close: Arc<dyn Fn() + Send + Sync + 'static>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ready_state,
|
ready_state,
|
||||||
|
@ -59,38 +59,37 @@ pub fn Websocket() -> impl IntoView {
|
||||||
provide_context(WebSocketContext::new(
|
provide_context(WebSocketContext::new(
|
||||||
ready_state,
|
ready_state,
|
||||||
// message,
|
// message,
|
||||||
Rc::new(send.clone()),
|
Arc::new(send.clone()),
|
||||||
Rc::new(open.clone()),
|
Arc::new(open.clone()),
|
||||||
Rc::new(close.clone()),
|
Arc::new(close.clone()),
|
||||||
));
|
));
|
||||||
|
|
||||||
let connected = move || ready_state.get() == ConnectionReadyState::Open;
|
let connected = move || ready_state.get() == ConnectionReadyState::Open;
|
||||||
|
|
||||||
// Contexts for message handler
|
// Contexts for message handler
|
||||||
// TODO: This context stuff can probably be done better
|
// TODO: This context stuff can probably be done better
|
||||||
let (state_summary, set_state_summary) =
|
let (state_summary, set_state_summary) = signal::<Option<ServerStateSummary>>(Option::None);
|
||||||
create_signal::<Option<ServerStateSummary>>(Option::None);
|
let (active_games, set_active_games) = signal::<Vec<GameBrowserMeta>>(vec![]);
|
||||||
let (active_games, set_active_games) = create_signal::<Vec<GameBrowserMeta>>(vec![]);
|
let (user_update, set_user_update) = signal::<Option<UserUpdate>>(Option::None);
|
||||||
let (user_update, set_user_update) = create_signal::<Option<UserUpdate>>(Option::None);
|
let (chat_update, set_chat_update) = signal::<Option<ChatUpdate>>(Option::None);
|
||||||
let (chat_update, set_chat_update) = create_signal::<Option<ChatUpdate>>(Option::None);
|
let (judge_round, set_judge_round) = signal::<Option<JudgeRound>>(Option::None);
|
||||||
let (judge_round, set_judge_round) = create_signal::<Option<JudgeRound>>(Option::None);
|
let (chat_message, set_chat_message) = signal::<Option<ChatMessage>>(Option::None);
|
||||||
let (chat_message, set_chat_message) = create_signal::<Option<ChatMessage>>(Option::None);
|
let (game_meta, set_game_meta) = signal::<Option<GameMeta>>(Option::None);
|
||||||
let (game_meta, set_game_meta) = create_signal::<Option<GameMeta>>(Option::None);
|
let (game_state, set_game_state) = signal::<Option<GameStateMeta>>(Option::None);
|
||||||
let (game_state, set_game_state) = create_signal::<Option<GameStateMeta>>(Option::None);
|
let (card_packs_meta, set_card_packs_meta) = signal::<CardPacksMeta>(CardPacksMeta {
|
||||||
let (card_packs_meta, set_card_packs_meta) = create_signal::<CardPacksMeta>(CardPacksMeta {
|
|
||||||
official_meta: vec![],
|
official_meta: vec![],
|
||||||
unofficial_meta: vec![],
|
unofficial_meta: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
if !connected() {
|
if !connected() {
|
||||||
set_active_games.set_untracked(vec![]);
|
set_active_games(vec![]);
|
||||||
set_user_update.set_untracked(None);
|
set_user_update(None);
|
||||||
set_chat_update.set_untracked(None);
|
set_chat_update(None);
|
||||||
set_judge_round.set_untracked(None);
|
set_judge_round(None);
|
||||||
set_chat_message.set_untracked(None);
|
set_chat_message(None);
|
||||||
set_game_meta.set_untracked(None);
|
set_game_meta(None);
|
||||||
set_game_state.set_untracked(None);
|
set_game_state(None);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -106,7 +105,7 @@ pub fn Websocket() -> impl IntoView {
|
||||||
provide_context::<ReadSignal<Option<ServerStateSummary>>>(state_summary);
|
provide_context::<ReadSignal<Option<ServerStateSummary>>>(state_summary);
|
||||||
|
|
||||||
// Message handler
|
// Message handler
|
||||||
create_effect(move |_| {
|
Effect::new(move |_| {
|
||||||
message.with(move |message_raw| {
|
message.with(move |message_raw| {
|
||||||
if let Some(message) = message_raw {
|
if let Some(message) = message_raw {
|
||||||
if let Ok(state_summary) = from_str::<ServerStateSummary>(message) {
|
if let Ok(state_summary) = from_str::<ServerStateSummary>(message) {
|
||||||
|
@ -128,7 +127,7 @@ pub fn Websocket() -> impl IntoView {
|
||||||
} else if let Ok(judge_update) = from_str::<JudgeRound>(message) {
|
} else if let Ok(judge_update) = from_str::<JudgeRound>(message) {
|
||||||
set_judge_round(Some(judge_update));
|
set_judge_round(Some(judge_update));
|
||||||
} else {
|
} else {
|
||||||
logging::error!("Unhandled message: {:#?}", message);
|
println!("Unhandled message: {:#?}", message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
use leptos_meta::*;
|
use leptos_router::{
|
||||||
use leptos_router::*;
|
components::{Route, Router, Routes},
|
||||||
|
StaticSegment,
|
||||||
|
};
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
mod components;
|
mod components;
|
||||||
|
@ -8,28 +10,14 @@ mod pages;
|
||||||
|
|
||||||
// Top-Level pages
|
// Top-Level pages
|
||||||
use crate::pages::home::Home;
|
use crate::pages::home::Home;
|
||||||
use crate::pages::not_found::NotFound;
|
|
||||||
|
|
||||||
/// An app router which renders the homepage and handles 404's
|
/// An app router which renders the homepage and handles 404's
|
||||||
#[component]
|
#[component]
|
||||||
pub fn App() -> impl IntoView {
|
pub fn App() -> impl IntoView {
|
||||||
// Provides context that manages stylesheets, titles, meta tags, etc.
|
|
||||||
provide_meta_context();
|
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Html class="bg-neutral-900" lang="en" dir="ltr" attr:data-theme="dark" />
|
|
||||||
|
|
||||||
// sets the document title
|
|
||||||
<Title text="Cards for Humanity" />
|
|
||||||
|
|
||||||
// injects metadata in the <head> of the page
|
|
||||||
<Meta charset="UTF-8" />
|
|
||||||
<Meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
|
|
||||||
<Router>
|
<Router>
|
||||||
<Routes>
|
<Routes fallback=|| "Not found.".into_view()>
|
||||||
<Route path="/" view=Home />
|
<Route path=StaticSegment("") view=Home />
|
||||||
<Route path="/*" view=NotFound />
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
use leptos::*;
|
|
||||||
use client::App;
|
use client::App;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// set up logging
|
|
||||||
_ = console_log::init_with_level(log::Level::Debug);
|
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
|
leptos::mount::mount_to_body(App)
|
||||||
mount_to_body(|| {
|
|
||||||
view! { <App /> }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,15 @@ use crate::components::create_game::*;
|
||||||
use crate::components::debug::*;
|
use crate::components::debug::*;
|
||||||
use crate::components::game::*;
|
use crate::components::game::*;
|
||||||
use crate::components::websocket::*;
|
use crate::components::websocket::*;
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
|
use thaw::*;
|
||||||
|
|
||||||
/// Default Home Page
|
/// Default Home Page
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Home() -> impl IntoView {
|
pub fn Home() -> impl IntoView {
|
||||||
|
let open = RwSignal::new(true);
|
||||||
|
let theme = RwSignal::new(Theme::dark());
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<ErrorBoundary fallback=|errors| {
|
<ErrorBoundary fallback=|errors| {
|
||||||
view! {
|
view! {
|
||||||
|
@ -33,8 +37,13 @@ pub fn Home() -> impl IntoView {
|
||||||
<div class="container m-auto">
|
<div class="container m-auto">
|
||||||
<h1 class="mx-4 text-6xl inter-med text-neutral-200">"Cards For Humanity"</h1>
|
<h1 class="mx-4 text-6xl inter-med text-neutral-200">"Cards For Humanity"</h1>
|
||||||
<div class="p-5 bg-neutral-950 rounded-3xl shadow-black shadow-xl">
|
<div class="p-5 bg-neutral-950 rounded-3xl shadow-black shadow-xl">
|
||||||
<h1 class="text-4xl">Hey!</h1>
|
|
||||||
<br />
|
<ConfigProvider theme>
|
||||||
|
<Dialog open>
|
||||||
|
<DialogSurface>
|
||||||
|
<DialogBody>
|
||||||
|
<DialogTitle>"Hey!"</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
<p>
|
<p>
|
||||||
{"Welcome! Thank you for helping me test this. Please let me know about any issues you may come across. Chances are you already know how to contact me but in case you don't you can email me at "}
|
{"Welcome! Thank you for helping me test this. Please let me know about any issues you may come across. Chances are you already know how to contact me but in case you don't you can email me at "}
|
||||||
<a href="mailto:adam@doordesk.net">adam@doordesk.net</a>
|
<a href="mailto:adam@doordesk.net">adam@doordesk.net</a>
|
||||||
|
@ -42,9 +51,21 @@ pub fn Home() -> impl IntoView {
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<p>Have fun!</p>
|
<p>Have fun!</p>
|
||||||
<br />
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
on_click=move |_| open.set(!open())
|
||||||
|
appearance=ButtonAppearance::Primary
|
||||||
|
>
|
||||||
|
"Got it"
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</DialogBody>
|
||||||
|
</DialogSurface>
|
||||||
|
</Dialog>
|
||||||
|
</ConfigProvider>
|
||||||
|
|
||||||
<Websocket />
|
<Websocket />
|
||||||
<hr />
|
|
||||||
<Auth />
|
<Auth />
|
||||||
<hr />
|
<hr />
|
||||||
<Browser />
|
<Browser />
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use leptos::*;
|
use leptos::prelude::*;
|
||||||
|
|
||||||
/// 404 Not Found Page
|
/// 404 Not Found Page
|
||||||
#[component]
|
#[component]
|
||||||
|
|
Loading…
Add table
Reference in a new issue