use dioxus::{ fullstack::{CborEncoding, WebSocketOptions, Websocket, extract::State, use_websocket}, html::input_data::MouseButton, logger::tracing, prelude::*, }; use serde::{Deserialize, Serialize}; use crate::components::{KeyboardArea, MouseArea}; #[component] pub fn Controls() -> Element { #[css_module("/assets/styling/controls.module.css")] struct Styles; let mut socket = use_websocket(move || mouse_move(WebSocketOptions::new())); use_future(move || async move { loop { // Wait for the socket to connect _ = socket.connect().await; // Loop poll with recv. Throws an error when the connection closes, making it possible // to run code before the socket re-connects when the name input changes while let Ok(message) = socket.recv().await { tracing::info!("Received message: {:?}", message); } } }); let event_handler = use_callback(move |evt| { spawn(async move { _ = socket.send(evt).await; }); }); rsx! { div { class: Styles::controls, MouseArea { onevent: event_handler } KeyboardArea { onevent: event_handler } } } } #[derive(Serialize, Deserialize, Debug)] pub enum ClientEvent { MouseMove { dx: f64, dy: f64 }, MouseScroll { dx: f64, dy: f64 }, Click { button: MouseButton }, KeyPressEvent { key: String }, TextInputStartEvent, TextInputEvent { text: String }, TextInputDoneEvent { text: String }, } #[derive(Serialize, Deserialize, Debug)] enum ServerEvent { Ping, } #[expect(clippy::unused_async)] #[get("/api/mouse_move_ws", mouse_service: State)] async fn mouse_move( options: WebSocketOptions ) -> Result> { Ok(options.on_upgrade(move |mut socket| async move { _ = socket.send(ServerEvent::Ping).await; while let Ok(event) = socket.recv().await { match event { ClientEvent::MouseMove { dx, dy } => { mouse_service.move_mouse(dx, dy).await; }, ClientEvent::MouseScroll { dx, dy } => { mouse_service.mouse_scroll(dx, dy).await; }, ClientEvent::Click { button } => { mouse_service.click(button).await; }, ClientEvent::KeyPressEvent { key } => { mouse_service.key_press_event(key).await; }, ClientEvent::TextInputEvent { text } => { mouse_service.text_input(text).await; }, ClientEvent::TextInputStartEvent => { mouse_service.text_input_start().await; }, ClientEvent::TextInputDoneEvent { text } => { mouse_service.text_input_end(text).await; }, } } })) }