Move the Websocket connect_to_game operation into the Client
All checks were successful
Monorepo build / build-flake (push) Successful in 3s
All checks were successful
Monorepo build / build-flake (push) Successful in 3s
This commit is contained in:
parent
4ed246f062
commit
b656b24d00
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3998,6 +3998,7 @@ dependencies = [
|
||||
"serde-wasm-bindgen 0.6.5",
|
||||
"serde_json",
|
||||
"stylist",
|
||||
"thiserror 2.0.12",
|
||||
"visions-types",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
|
||||
@ -12,11 +12,12 @@ markdown = "1.0.0"
|
||||
serde = { workspace = true }
|
||||
serde-wasm-bindgen = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
stylist = { version = "0.13.0", features = ["yew", "yew_integration", "yew_use_style"] }
|
||||
stylist = { version = "0.13.0", features = ["yew", "yew_integration", "yew_use_style"] }
|
||||
thiserror = { workspace = true }
|
||||
visions-types = { path = "../types" }
|
||||
wasm-bindgen = { workspace = true }
|
||||
wasm-bindgen-futures = { workspace = true }
|
||||
wasm-sockets = "1.0.0"
|
||||
wasm-sockets = "1.0.0"
|
||||
web-sys = { workspace = true, features = ["Window", "Location"] }
|
||||
yew = { workspace = true }
|
||||
yew-router = { workspace = true }
|
||||
|
||||
@ -1,21 +1,32 @@
|
||||
use std::future::Future;
|
||||
|
||||
use gloo_console::log;
|
||||
use gloo_console::{error, log};
|
||||
use gloo_net::{
|
||||
http::{Request, Response},
|
||||
Error,
|
||||
};
|
||||
use http::StatusCode;
|
||||
use serde::de::DeserializeOwned;
|
||||
use thiserror::Error;
|
||||
use visions_types::*;
|
||||
use wasm_sockets::{EventClient, Message};
|
||||
use web_sys::CloseEvent;
|
||||
use yew::Callback;
|
||||
|
||||
use crate::clone;
|
||||
|
||||
const HOST: &'static str = env!("VISIONS_HOST");
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ClientError {
|
||||
#[allow(dead_code)]
|
||||
#[error("Client is not authorized")]
|
||||
Unauthorized,
|
||||
|
||||
#[error("Client failure: {0}")]
|
||||
Err(u16),
|
||||
|
||||
#[error("Request builder failed: {0}")]
|
||||
RequestError(Error),
|
||||
}
|
||||
|
||||
@ -55,6 +66,13 @@ pub trait Client: Clone + PartialEq {
|
||||
fn new_card(&self, card: Card) -> impl Future<Output = Result<CardId, ClientError>>;
|
||||
|
||||
fn update_card(&self, card: Card) -> impl Future<Output = Result<(), ClientError>>;
|
||||
|
||||
fn connect_to_game(
|
||||
&self,
|
||||
game: GameId,
|
||||
on_message: Callback<GameMessage>,
|
||||
on_socket_closed: Box<dyn Fn(CloseEvent)>,
|
||||
) -> Result<EventClient, ClientError>;
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
@ -260,4 +278,52 @@ impl Client for Connection {
|
||||
|
||||
handle_response(response).await
|
||||
}
|
||||
|
||||
fn connect_to_game(
|
||||
&self,
|
||||
game_id: GameId,
|
||||
on_message: Callback<GameMessage>,
|
||||
on_socket_closed: Box<dyn Fn(CloseEvent)>,
|
||||
) -> Result<EventClient, ClientError> {
|
||||
let mut ws_client = EventClient::new("/api/ws").unwrap();
|
||||
|
||||
ws_client.set_on_error(Some(Box::new(|error| {
|
||||
error!("{:#?}", error);
|
||||
})));
|
||||
|
||||
ws_client.set_on_close(Some(on_socket_closed));
|
||||
|
||||
let session_id = self.session_id.clone();
|
||||
clone!(
|
||||
(session_id, game_id),
|
||||
ws_client.set_on_connection(Some(Box::new({
|
||||
move |ws_client: &wasm_sockets::EventClient| {
|
||||
if let Err(e) = ws_client.send_string(
|
||||
&serde_json::to_string(&GameRequest::JoinGame(
|
||||
session_id.clone(),
|
||||
game_id.clone(),
|
||||
))
|
||||
.unwrap(),
|
||||
) {
|
||||
log!("An error occurred while sending: {:#?}", e);
|
||||
}
|
||||
}
|
||||
})))
|
||||
);
|
||||
|
||||
ws_client.set_on_message(Some(Box::new({
|
||||
let on_message = on_message.clone();
|
||||
|
||||
move |_client: &wasm_sockets::EventClient, message: wasm_sockets::Message| match message
|
||||
{
|
||||
Message::Text(text) => {
|
||||
let message: GameMessage = serde_json::from_str(&text).unwrap();
|
||||
on_message.emit(message);
|
||||
}
|
||||
Message::Binary(_) => unimplemented!(),
|
||||
}
|
||||
})));
|
||||
|
||||
Ok(ws_client)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use gloo_console::{error, info, log};
|
||||
use gloo_console::error;
|
||||
use visions_types::*;
|
||||
use wasm_sockets::{EventClient, Message};
|
||||
use wasm_sockets::EventClient;
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::{client::Client, clone};
|
||||
@ -19,7 +19,7 @@ impl SocketState {
|
||||
.send_string(&serde_json::to_string(&message).unwrap())
|
||||
.unwrap(),
|
||||
None => {
|
||||
log!("no socket available");
|
||||
error!("no socket available");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,57 +60,18 @@ pub fn WebsocketProvider<C: Client + Clone + 'static>(
|
||||
on_message.clone(),
|
||||
),
|
||||
move |(socket_state, client, game_id, on_message)| {
|
||||
let mut ws_client: wasm_sockets::EventClient =
|
||||
wasm_sockets::EventClient::new("ws://localhost:8080/api/ws").unwrap();
|
||||
|
||||
ws_client.set_on_error(Some(Box::new(|error| {
|
||||
error!("{:#?}", error);
|
||||
})));
|
||||
|
||||
clone!(
|
||||
socket_state,
|
||||
ws_client.set_on_close({
|
||||
Some(Box::new(move |_evt| {
|
||||
info!("connection closed");
|
||||
socket_state.set(SocketState { socket: None })
|
||||
}))
|
||||
})
|
||||
let ws_client = client.connect_to_game(
|
||||
game_id.clone(),
|
||||
on_message.clone(),
|
||||
Box::new(clone!(socket_state, move |_evt| socket_state
|
||||
.set(SocketState { socket: None }))),
|
||||
);
|
||||
|
||||
clone!(
|
||||
(client, game_id),
|
||||
ws_client.set_on_connection(Some(Box::new({
|
||||
move |ws_client: &wasm_sockets::EventClient| {
|
||||
if let Err(e) = ws_client.send_string(
|
||||
&serde_json::to_string(&GameRequest::JoinGame(
|
||||
client.session_id().clone(),
|
||||
game_id.clone(),
|
||||
))
|
||||
.unwrap(),
|
||||
) {
|
||||
log!("An error occurred while sending: {:#?}", e);
|
||||
}
|
||||
}
|
||||
})))
|
||||
);
|
||||
|
||||
ws_client.set_on_message(Some(Box::new({
|
||||
let on_message = on_message.clone();
|
||||
|
||||
move |_client: &wasm_sockets::EventClient, message: wasm_sockets::Message| {
|
||||
match message {
|
||||
Message::Text(text) => {
|
||||
let message: GameMessage = serde_json::from_str(&text).unwrap();
|
||||
on_message.emit(message);
|
||||
}
|
||||
Message::Binary(_) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
})));
|
||||
|
||||
socket_state.set(SocketState {
|
||||
socket: Some(Rc::new(ws_client)),
|
||||
});
|
||||
match ws_client {
|
||||
Ok(ws_client) => socket_state.set(SocketState {
|
||||
socket: Some(Rc::new(ws_client)),
|
||||
}),
|
||||
Err(err) => error!("failed to connect to websocket: ", err.to_string()),
|
||||
}
|
||||
|
||||
{
|
||||
let socket_state = socket_state.clone();
|
||||
|
||||
@ -4,7 +4,7 @@ use crate::{
|
||||
client::{Client, ClientError, Connection},
|
||||
clone,
|
||||
};
|
||||
use gloo_console::error;
|
||||
use gloo_console::{error, log};
|
||||
use visions_types::{SessionId, UserOverview};
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::{Storage, Window};
|
||||
@ -139,10 +139,13 @@ pub struct StateProviderProps {
|
||||
pub fn StateProvider(StateProviderProps { children }: &StateProviderProps) -> Html {
|
||||
let app_state: UseReducerHandle<AppState> = use_reducer(init_state);
|
||||
|
||||
use_effect(clone!(app_state, || {
|
||||
wasm_bindgen_futures::spawn_local(hydrate_client(app_state));
|
||||
|| ()
|
||||
}));
|
||||
use_effect_with(
|
||||
app_state.client().cloned(),
|
||||
clone!(app_state, |_| {
|
||||
wasm_bindgen_futures::spawn_local(hydrate_client(app_state));
|
||||
|| ()
|
||||
}),
|
||||
);
|
||||
|
||||
html! {
|
||||
<ContextProvider<UseReducerHandle<AppState>> context={app_state}>
|
||||
@ -172,6 +175,7 @@ async fn hydrate_client_(
|
||||
if let Ok(Some(session_id)) = storage.get_item("session_id") {
|
||||
let session_id: SessionId = session_id.into();
|
||||
let client = Connection::new(session_id.clone());
|
||||
log!("hydrate_cilent_");
|
||||
match client.get_self().await {
|
||||
Ok(user) => set_session(&app_state, client, user),
|
||||
Err(ClientError::Unauthorized) => {
|
||||
@ -231,7 +235,6 @@ pub mod tests {
|
||||
set_session_(
|
||||
clone!(state, move |app_action| reduce_app_state(state, app_action)),
|
||||
Some(&mut storage),
|
||||
session_id.clone(),
|
||||
overview.clone(),
|
||||
);
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use gloo_console::error;
|
||||
use gloo_console::{error, log};
|
||||
use visions_types::*;
|
||||
use yew::prelude::*;
|
||||
|
||||
@ -118,6 +118,7 @@ fn GameList<C: Client + Clone + 'static>(GameListProps { client }: &GameListProp
|
||||
clone!(
|
||||
client,
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
log!("re-running game listing");
|
||||
match client.list_games().await {
|
||||
Ok(games) => game_list.set(games),
|
||||
Err(ClientError::Unauthorized) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user