Skip to content

Commit

Permalink
wasm example
Browse files Browse the repository at this point in the history
  • Loading branch information
jgraef committed Jun 13, 2024
1 parent 41ef76d commit 69018d0
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ Thumbs.db
# Rust
/Cargo.lock
/target

# wasm-example
/wasm-example/dist
/wasm-example/target
/wasm-example/Cargo.lock
16 changes: 16 additions & 0 deletions wasm-example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "wasm-example"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
reqwest = "0.12"
reqwest-websocket = { path = "../" }
leptos = { version = "0.6", features = ["csr"] }
console_error_panic_hook = "0.1"
futures = "0.3"
tracing = "0.1"
tracing-wasm = "0.2"
wasm-bindgen = "0.2"
gloo-utils = "0.2"
15 changes: 15 additions & 0 deletions wasm-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
<title>reqwest-websocket WASM example</title>
<base href="/"/>
</head>
<body>
<div id="root"></div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</body>
</html>
134 changes: 134 additions & 0 deletions wasm-example/src/app.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use futures::{channel::mpsc, StreamExt, TryStreamExt, SinkExt};
use leptos::{component, create_node_ref, html::Input, spawn_local, view, For, IntoView, RwSignal, SignalUpdate, SignalWith};

#[derive(Clone, Debug)]
enum Message {
User(String),
Server(String),
Error(String),
}

#[component]
pub fn App() -> impl IntoView {
let message_input = create_node_ref::<Input>();
let (send_tx, mut send_rx) = mpsc::unbounded::<String>();

let messages = RwSignal::new(vec![]);

spawn_local(async move {
let websocket = reqwest_websocket::websocket("https://echo.websocket.org/").await.unwrap();
let (mut sender, mut receiver) = websocket.split();

futures::join!(
async move {
loop {
match receiver.try_next().await {
Err(e) => {
messages.update(|messages| messages.push(Message::Error(e.to_string())));
break;
}
Ok(None) => {
break;
}
Ok(Some(reqwest_websocket::Message::Text(text))) => {
messages.update(|messages| messages.push(Message::Server(text)))
},
_ => {}
}
}
},
async move {
while let Some(message) = send_rx.next().await {
sender.send(message.into()).await.unwrap();
}
}
);
});

let send_message = move || {
let input = message_input.get().unwrap();
let message = input.value();
input.set_value("");

messages.update(|messages| messages.push(Message::User(message.clone())));
send_tx.unbounded_send(message).unwrap();
};

view! {
<div class="d-flex flex-column" style="width: 100vw; height: 100vh;">
<main class="main d-flex flex-column w-100 h-100 mw-100 mh-100">
<div class="d-flex flex-column w-100 p-4 overflow-y-scroll">
<For
each=move || messages.with(|messages| messages.iter().map(ToOwned::to_owned).enumerate().collect::<Vec<_>>())
key=|(i, _)| *i
children=|(_, message)| {
match message {
Message::User(message) => {
view! {
<div class="card bg-light bg-gradient mb-3 bx-3 w-75 ms-auto">
<div class="card-header">"User"</div>
<div class="card-body">
<p class="card-text">{message}</p>
</div>
</div>
}
},
Message::Server(message) => {
view! {
<div class="card bg-light bg-gradient mb-3 bx-3 w-75 me-auto">
<div class="card-header">"Server"</div>
<div class="card-body">
<p class="card-text">{message}</p>
</div>
</div>
}
},
Message::Error(message) => {
view! {
<div class="card bg-error bg-gradient mb-3 bx-3 w-75 mx-auto">
<div class="card-header">"Error"</div>
<div class="card-body">
<p class="card-text">{message}</p>
</div>
</div>
}
},
}
}
/>
</div>
<div class="d-flex flex-row w-100 mt-auto">
<div class="input-group">
<form
class="d-flex flex-row w-100"
on:submit={
let send_message = send_message.clone();
move |e| {
e.prevent_default();
send_message();
}
}
>
<input
type="text"
class="form-control"
placeholder="Type your message here"
aria-label="Your message"
aria-describedby="button-send"
node_ref=message_input
/>
<button
class="btn btn-outline-secondary"
type="button"
id="button-send"
on:click=move |_| send_message()
>
<i class="bi bi-send"></i>
</button>
</form>
</div>
</div>
</main>
</div>
}
}
21 changes: 21 additions & 0 deletions wasm-example/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
mod app;

use wasm_bindgen::JsCast;

use crate::app::App;

fn main() {
tracing_wasm::set_as_global_default();
console_error_panic_hook::set_once();

tracing::info!("starting app");

let root = gloo_utils::document()
.get_element_by_id("root")
.expect("no root node found")
.dyn_into()
.unwrap();

leptos::mount_to(root, App);
}

0 comments on commit 69018d0

Please sign in to comment.