From 45275be11b956f5cd34593a65a26a338c3b842f9 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 18 Nov 2024 23:32:54 -0500 Subject: [PATCH] Serve up the background image via the websocket --- visions/server/src/core.rs | 14 +++++++++++++- visions/server/src/handlers.rs | 5 +++-- visions/server/src/main.rs | 9 ++++----- visions/server/src/types.rs | 4 ++-- visions/ui/src/App.tsx | 2 +- .../components/PlayingField/PlayingField.tsx | 19 +++++++++++++++---- 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/visions/server/src/core.rs b/visions/server/src/core.rs index b86ecaa..bf6780a 100644 --- a/visions/server/src/core.rs +++ b/visions/server/src/core.rs @@ -8,7 +8,7 @@ use std::{ use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}; use uuid::Uuid; -use crate::types::Message; +use crate::types::{AppError, Message, PlayArea}; #[derive(Debug)] struct WebsocketClient { @@ -19,6 +19,8 @@ struct WebsocketClient { pub struct AppState { pub image_base: PathBuf, + pub playfield_background: String, + pub clients: HashMap, } @@ -29,6 +31,7 @@ impl Core { pub fn new() -> Self { Self(Arc::new(RwLock::new(AppState { image_base: PathBuf::from("/home/savanni/Pictures"), + playfield_background: "moon.jpg".to_owned(), clients: HashMap::new(), }))) } @@ -95,6 +98,15 @@ impl Core { .collect() } + pub fn set_playfield_background(&self, path: String) -> Result<(), AppError> { + { + let mut state = self.0.write().unwrap(); + state.playfield_background = path.clone(); + } + self.publish(Message::PlayArea(PlayArea{ background_image: path })); + Ok(()) + } + pub fn publish(&self, message: Message) { let state = self.0.read().unwrap(); diff --git a/visions/server/src/handlers.rs b/visions/server/src/handlers.rs index 8003fa3..c8861ca 100644 --- a/visions/server/src/handlers.rs +++ b/visions/server/src/handlers.rs @@ -98,13 +98,14 @@ pub async fn handle_connect_websocket( ws.on_upgrade(move |socket| { let core = core.clone(); async move { - let (mut ws_sender, mut ws_recv) = socket.split(); + let (mut ws_sender, _) = socket.split(); let mut receiver = core.connect_client(client_id); tokio::task::spawn(async move { + let background_image = core.0.read().unwrap().playfield_background.clone(); let _ = ws_sender .send(Message::text( - serde_json::to_string(&crate::types::Message::Count(0)).unwrap(), + serde_json::to_string(&crate::types::Message::PlayArea(PlayArea{ background_image })).unwrap(), )) .await; while let Some(msg) = receiver.recv().await { diff --git a/visions/server/src/main.rs b/visions/server/src/main.rs index 2a5b079..ff680af 100644 --- a/visions/server/src/main.rs +++ b/visions/server/src/main.rs @@ -134,14 +134,13 @@ pub async fn main() { move |ws, client_id| handle_connect_websocket(core.clone(), ws, client_id) }); - let route_publish = warp::path!("api" / "v1" / "message") - .and(warp::post()) + let route_set_playfield_bg = warp::path!("api" / "v1" / "playfield" / "bg") + .and(warp::put()) .and(warp::body::json()) .map({ let core = core.clone(); move |body| { - println!("route_publish: {:?}", body); - core.publish(body); + core.set_playfield_background(body); warp::reply() } }); @@ -152,7 +151,7 @@ pub async fn main() { .or(route_playing_field) .or(route_image) .or(route_available_images) - .or(route_publish) + .or(route_set_playfield_bg) .recover(handle_rejection); let server = warp::serve(filter); diff --git a/visions/server/src/types.rs b/visions/server/src/types.rs index 5990a8f..4a998fe 100644 --- a/visions/server/src/types.rs +++ b/visions/server/src/types.rs @@ -12,9 +12,9 @@ pub enum AppError { } #[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(tag = "type")] pub enum Message { - Count(u32), - // PlayArea(PlayArea), + PlayArea(PlayArea), } diff --git a/visions/ui/src/App.tsx b/visions/ui/src/App.tsx index b2a38b5..1497180 100644 --- a/visions/ui/src/App.tsx +++ b/visions/ui/src/App.tsx @@ -26,7 +26,7 @@ const App = ({ client }: AppProps) => { }, { path: "/", - element: websocketUrl ? :
+ element: websocketUrl ? :
} ]); return ( diff --git a/visions/ui/src/components/PlayingField/PlayingField.tsx b/visions/ui/src/components/PlayingField/PlayingField.tsx index 8ebf299..ec44de9 100644 --- a/visions/ui/src/components/PlayingField/PlayingField.tsx +++ b/visions/ui/src/components/PlayingField/PlayingField.tsx @@ -26,15 +26,26 @@ export const PlayingFieldComponent = ({ client }: PlayingFieldProps) => { */ interface WebsocketPlayingFieldProps { + client: Client; websocketUrl: string; } -export const WebsocketPlayingFieldComponent = ({ websocketUrl }: WebsocketPlayingFieldProps) => { +type Message = | +{ + type: "PlayArea"; + background_image: string; +} + +export const WebsocketPlayingFieldComponent = ({ client, websocketUrl }: WebsocketPlayingFieldProps) => { const { lastMessage, readyState } = useWebSocket(websocketUrl); + const [backgroundUrl, setBackgroundUrl] = useState(undefined); useEffect(() => { if (lastMessage !== null) { - console.log("last message: ", lastMessage); + const message: Message = JSON.parse(lastMessage.data); + console.log("playing area: ", message); + console.log("playing area: ", message.background_image); + setBackgroundUrl(client.imageUrl(message.background_image)); } }, [lastMessage]); @@ -46,11 +57,11 @@ export const WebsocketPlayingFieldComponent = ({ websocketUrl }: WebsocketPlayin [ReadyState.UNINSTANTIATED]: 'Uninstantiated', }[readyState]; - return ; + return ; } interface PlayingFieldProps { - backgroundUrl: string | undefined; + backgroundUrl: URL | undefined; connectionStatus: string; }