web: plumb websocket messages through to UI

This commit is contained in:
Bill Thiede 2025-04-15 10:41:51 -07:00
parent f2042f284e
commit 30f3f14040
3 changed files with 35 additions and 28 deletions

View File

@ -2,6 +2,8 @@
// - it's useful when you want to check your code with `cargo make verify`
// but some rules are too "annoying" or are not applicable for your case.)
#![allow(clippy::wildcard_imports)]
// Until https://github.com/rust-lang/rust/issues/138762 is addressed in dependencies
#![allow(wasm_c_abi)]
use log::Level;
use seed::App;

View File

@ -1,6 +1,7 @@
use std::collections::HashSet;
use graphql_client::GraphQLQuery;
use letterbox_shared::WebsocketMessage;
use log::{debug, error, info, warn};
use seed::{prelude::*, *};
use thiserror::Error;
@ -61,7 +62,7 @@ pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
},
catchup: None,
last_url: Url::current(),
websocket: websocket::init(url, &mut orders.proxy(Msg::WebSocket)),
websocket: websocket::init(&mut orders.proxy(Msg::WebSocket)),
}
}
@ -663,7 +664,15 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
}
Msg::WebSocket(ws) => {
websocket::update(ws, &mut model.websocket, &mut orders.proxy(Msg::WebSocket))
websocket::update(ws, &mut model.websocket, &mut orders.proxy(Msg::WebSocket));
while let Some(msg) = model.websocket.updates.pop_front() {
orders.send_msg(Msg::WebsocketMessage(msg));
}
}
Msg::WebsocketMessage(msg) => {
match msg {
WebsocketMessage::RefreshMessages => orders.send_msg(Msg::Refresh),
};
}
}
}
@ -831,4 +840,5 @@ pub enum Msg {
CatchupExit,
WebSocket(websocket::Msg),
WebsocketMessage(WebsocketMessage),
}

View File

@ -1,8 +1,8 @@
use std::rc::Rc;
use std::{collections::VecDeque, rc::Rc};
use letterbox_shared::WebsocketMessage;
use log::{error, info};
use seed::{prelude::*, *};
use seed::prelude::*;
use serde::{Deserialize, Serialize};
use wasm_sockets::{self, ConnectionStatus, EventClient, Message, WebSocketError};
use web_sys::CloseEvent;
@ -31,16 +31,18 @@ const WS_URL: &str = "wss://6758.z.xinu.tv/api/ws";
pub struct Model {
web_socket: EventClient,
web_socket_reconnector: Option<StreamHandle>,
pub updates: VecDeque<WebsocketMessage>,
}
// ------ ------
// Init
// ------ ------
pub fn init(_: Url, orders: &mut impl Orders<Msg>) -> Model {
pub fn init(orders: &mut impl Orders<Msg>) -> Model {
Model {
web_socket: create_websocket(orders).unwrap(),
web_socket_reconnector: None,
updates: VecDeque::new(),
}
}
@ -50,39 +52,35 @@ pub fn init(_: Url, orders: &mut impl Orders<Msg>) -> Model {
pub enum Msg {
WebSocketOpened,
TextMessageReceived(String),
BinaryMessageReceived(ServerMessage),
CloseWebSocket,
TextMessageReceived(WebsocketMessage),
WebSocketClosed(CloseEvent),
WebSocketFailed,
ReconnectWebSocket(usize),
#[allow(dead_code)]
SendMessage(ClientMessage),
SendBinaryMessage(ClientMessage),
}
pub fn update(msg: Msg, mut model: &mut Model, orders: &mut impl Orders<Msg>) {
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
match msg {
Msg::WebSocketOpened => {
model.web_socket_reconnector = None;
info!("WebSocket connection is open now");
}
Msg::TextMessageReceived(msg) => {
info!("recieved text {}", msg);
}
Msg::BinaryMessageReceived(message) => {
error!("Client received binary message");
}
Msg::CloseWebSocket => {
model.web_socket_reconnector = None;
model.web_socket.close().unwrap();
model.updates.push_back(msg);
}
Msg::WebSocketClosed(close_event) => {
info!("==================");
info!("WebSocket connection was closed:");
info!("Clean: {}", close_event.was_clean());
info!("Code: {}", close_event.code());
info!("Reason: {}", close_event.reason());
info!("==================");
info!(
r#"==================
WebSocket connection was closed:
Clean: {0}
Code: {1}
Reason: {2}
=================="#,
close_event.was_clean(),
close_event.code(),
close_event.reason()
);
// Chrome doesn't invoke `on_error` when the connection is lost.
if !close_event.was_clean() && model.web_socket_reconnector.is_none() {
@ -107,9 +105,6 @@ pub fn update(msg: Msg, mut model: &mut Model, orders: &mut impl Orders<Msg>) {
let txt = serde_json::to_string(&msg).unwrap();
model.web_socket.send_string(&txt).unwrap();
}
Msg::SendBinaryMessage(_msg) => {
error!("Attempt to send binary message, unsupported");
}
}
}
@ -160,7 +155,7 @@ fn decode_message(message: Message, msg_sender: Rc<dyn Fn(Option<Msg>)>) {
let msg: WebsocketMessage = serde_json::from_str(&txt).unwrap_or_else(|e| {
panic!("failed to parse json into WebsocketMessage: {e}\n'{txt}'")
});
msg_sender(Some(Msg::TextMessageReceived(txt)));
msg_sender(Some(Msg::TextMessageReceived(msg)));
}
m => error!("unexpected message type received of {m:?}"),
}