diff --git a/client/src/components/chat.rs b/client/src/components/chat.rs index fdab86f..7a303e4 100644 --- a/client/src/components/chat.rs +++ b/client/src/components/chat.rs @@ -7,6 +7,7 @@ use lib::models::*; #[component] pub fn Chat() -> impl IntoView { let websocket = expect_context::(); + let chat_context = expect_context::>>(); // Chat stuff let (chat_history, set_chat_history) = create_signal::>(vec![]); @@ -38,34 +39,23 @@ pub fn Chat() -> impl IntoView { }) }); - // let chat = move || { - // if let Some(ye) = chat_input_ref.get() { - // &websocket.send(&ye.value()); - // }; - // }; - - // This should be done elsewhere + // Handle incoming chat messages create_effect(move |_| { - websocket.message.with(move |message_raw| { - // Send all messages as strings into chat box - if let Some(message) = message_raw { - if let Ok(_game) = serde_json::from_str::(message) { - logging::log!("Game object received at chat component"); - } else if let Ok(_state_summary) = - serde_json::from_str::(message) - { - logging::log!("State Summary received at chat component"); - } else { - update_chat_history(&set_chat_history, format!("{}\n", message)); - } + chat_context.with(move |chat_message| { + if let Some(message) = chat_message { + update_chat_history(&set_chat_history, format!("{}\n", message.text)); } }) }); + // Handle sending messages let send_message = move |_| { - websocket.send(&serde_json::to_string(&ChatMessage { - text: chat_input_ref.get().unwrap().value(), - }).unwrap()); + websocket.send( + &serde_json::to_string(&ChatMessage { + text: chat_input_ref.get().unwrap().value(), + }) + .unwrap(), + ); chat_input_ref.get().unwrap().set_value(""); logging::log!("Send Message"); }; diff --git a/client/src/components/websocket.rs b/client/src/components/websocket.rs index 487cefa..96479b3 100644 --- a/client/src/components/websocket.rs +++ b/client/src/components/websocket.rs @@ -8,19 +8,19 @@ use serde_json::to_string; #[derive(Clone)] pub struct WebSocketContext { pub ready_state: Signal, - pub message: Signal>, + // pub message: Signal>, send: Rc, } impl WebSocketContext { pub fn new( ready_state: Signal, - message: Signal>, + // message: Signal>, send: Rc, ) -> Self { Self { ready_state, - message, + // message, send, } } @@ -44,7 +44,7 @@ pub fn Websocket() -> impl IntoView { provide_context(WebSocketContext::new( ready_state, - message, + // message, Rc::new(send.clone()), )); @@ -58,6 +58,7 @@ pub fn Websocket() -> impl IntoView { let open_connection = move |_| { open(); }; + let fake_new_game_request = NewGameRequest { name: String::from("Ligma"), host: Player { @@ -80,34 +81,47 @@ pub fn Websocket() -> impl IntoView { send(&to_string(&fake_new_game_request).unwrap()); }; - // handle incoming messages + // Contexts for message handler + let (state_summary, set_state_summary) = + create_signal::>(Option::None); + let (game_object, set_game_object) = create_signal::>(Option::None); + let (chat_message, set_chat_message) = create_signal::>(Option::None); - // make this a proper message handler + provide_context::>>(game_object); + provide_context::>>(chat_message); + provide_context::>>(state_summary); + + // Message handler create_effect(move |_| { message.with(move |message_raw| { // Send all messages as strings into chat box if let Some(message) = message_raw { - if let Ok(_game) = serde_json::from_str::(message) { - logging::log!("Game object received."); + if let Ok(game) = serde_json::from_str::(message) { + set_game_object(Some(game)); } else if let Ok(state_summary) = serde_json::from_str::(message) { - logging::log!( - "Users: {}\nGames: {}", - state_summary.online_users, - state_summary.active_games - ); - set_online_users(state_summary.online_users); - set_active_games(state_summary.active_games); + set_state_summary(Some(state_summary)); + } else if let Ok(chat_message) = serde_json::from_str::(message) { + set_chat_message(Some(chat_message)); } else { - logging::log!("Send {} to Chat component", message); - // update_chat_history(&set_chat_history, format!("{}\n", message)); + logging::log!("Unhandled message: {}", message); } } }) }); + // Update server info -> move this to a new component + create_effect(move |_| { + state_summary.with(move |state_summary| { + if let Some(state_summary) = state_summary { + set_online_users(state_summary.online_users); + set_active_games(state_summary.active_games); + } + }) + }); + view! {

diff --git a/lib/src/models.rs b/lib/src/models.rs index 748b546..20f4afb 100644 --- a/lib/src/models.rs +++ b/lib/src/models.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use std::net::SocketAddr; /// Chat message -#[derive(Serialize, Deserialize, Debug)] +#[derive(Clone, Serialize, Deserialize, Debug)] pub struct ChatMessage { pub text: String, } diff --git a/server/src/api.rs b/server/src/api.rs index 304568e..143ba03 100644 --- a/server/src/api.rs +++ b/server/src/api.rs @@ -8,15 +8,16 @@ use axum::{ }; use futures::{SinkExt, StreamExt}; use lib::models::*; +use serde_json::to_string; use std::{net::SocketAddr, sync::Arc}; pub mod message_handler; use crate::message_handler::*; -fn motd() -> String { - format!( - "Greetings from the game server!" - ) +fn motd() -> ChatMessage { + ChatMessage { + text: "Greetings from the game server!".to_string(), + } } fn server_sum_update(state: &Arc) -> ServerStateSummary { @@ -36,18 +37,26 @@ pub async fn on_websocket_connection(stream: WebSocket, state: Arc, wh let (mut sender, mut receiver) = stream.split(); // hydrate user - let _ = &sender.send(Message::Text(motd())).await; - let _ = &sender.send(Message::Text(serde_json::to_string(&server_sum_update(&state)).unwrap())).await; + let _ = &sender + .send(Message::Text(to_string::(&motd()).unwrap())) + .await; + let _ = &sender + .send(Message::Text( + to_string(&server_sum_update(&state)).unwrap(), + )) + .await; // ANNOUNCE THY PRESENCE - let msg = format!("{} joined.", who.name); - tracing::debug!("{msg}"); - let _ = &state.tx.send(msg); + let msg = ChatMessage { + text: format!("{} joined.", who.name), + }; + tracing::debug!("{}", msg.text); + let _ = &state.tx.send(to_string::(&msg).unwrap()); // Broadcast server state summary update let _ = &state .tx - .send(serde_json::to_string(&server_sum_update(&state)).unwrap()); + .send(to_string(&server_sum_update(&state)).unwrap()); // subscribe to broadcast channel let mut rx = state.tx.subscribe(); diff --git a/server/src/api/message_handler.rs b/server/src/api/message_handler.rs index fd7f015..1ef3123 100644 --- a/server/src/api/message_handler.rs +++ b/server/src/api/message_handler.rs @@ -1,3 +1,5 @@ +use serde_json::to_string; + use crate::api::*; use crate::AppState; use crate::Arc; @@ -11,7 +13,7 @@ pub async fn message_handler(message: Message, state: &Arc, who: &User tracing::debug!("New game request received."); // create game if let Ok(new_game_object) = Game::new(new_game) { - if let Ok(game_json) = serde_json::to_string(&new_game_object) { + if let Ok(game_json) = to_string(&new_game_object) { tracing::debug!("Sent new game JSON."); // this is a broadcast let _ = tx.send(game_json); @@ -19,7 +21,7 @@ pub async fn message_handler(message: Message, state: &Arc, who: &User tracing::error!("Failed to convert Game object to JSON.") } state.games.lock().unwrap().push(new_game_object); - let _ = tx.send(serde_json::to_string(&server_sum_update(state)).unwrap()); + let _ = tx.send(to_string(&server_sum_update(state)).unwrap()); // let _update = tx.send(motd()); } else { let _res = tx.send(String::from("error creating game")); @@ -27,7 +29,7 @@ pub async fn message_handler(message: Message, state: &Arc, who: &User } else if let Ok(chat_message) = serde_json::from_str::(&text) { let msg = format! {"{0}: {1}", who.name, chat_message.text}; tracing::debug!("{msg}"); - let _res = tx.send(msg); + let _res = tx.send(to_string::(&ChatMessage { text: msg }).unwrap()); } else { tracing::debug!("Unhandled message: {}", &text); } @@ -48,11 +50,13 @@ pub async fn message_handler(message: Message, state: &Arc, who: &User } else { tracing::debug!("close received without close frame") } - let msg = format!("{0} left.", who.name); - tracing::debug!("{msg}"); - let _ = tx.send(msg); + let msg = ChatMessage { + text: format!("{0} left.", who.name), + }; + tracing::debug!("{}", msg.text); + let _ = tx.send(to_string::(&msg).unwrap()); let _ = state.users.lock().unwrap().remove(who); - let _ = tx.send(serde_json::to_string(&server_sum_update(state)).unwrap()); + let _ = tx.send(to_string(&server_sum_update(state)).unwrap()); } Message::Pong(ping) => {