Address review suggestion, update doc + book

This commit is contained in:
Jens Krause 2023-07-11 19:23:43 +02:00
parent 325db84870
commit 12eb953c70
5 changed files with 173 additions and 103 deletions

View file

@ -57,7 +57,7 @@ cargo test --all-features
First you need to install First you need to install
```shell ```shell
cargo install mdbook-cmdrun trunk cargo install mdbook mdbook-cmdrun trunk
``` ```
To build the book go in your terminal into the docs/book folder To build the book go in your terminal into the docs/book folder

View file

@ -11,6 +11,10 @@
- [use_session_storage](storage/use_session_storage.md) - [use_session_storage](storage/use_session_storage.md)
- [use_storage](storage/use_storage.md) - [use_storage](storage/use_storage.md)
# @WebSocket
- [use_websocket](websocket/use_websocket.md)
# Elements # Elements
- [use_active_element](elements/use_active_element.md) - [use_active_element](elements/use_active_element.md)

View file

@ -0,0 +1,3 @@
# use_websocket
<!-- cmdrun python3 ../extract_doc_comment.py websocket/use_websocket websocket -->

View file

@ -77,34 +77,32 @@ fn Demo(cx: Scope) -> impl IntoView {
} = use_websocket_with_options( } = use_websocket_with_options(
cx, cx,
"wss://echo.websocket.events/".to_string(), "wss://echo.websocket.events/".to_string(),
UseWebSocketOptions { UseWebSocketOptions::default()
manual: true, .manual(true)
onopen: Some(Box::new(move |e| { .onopen(Some(Box::new(move |e| {
set_history2.update(|history: &mut Vec<_>| { set_history2.update(|history: &mut Vec<_>| {
history.push(format! {"[onopen]: event {:?}", e.type_()}) history.push(format! {"[onopen]: event {:?}", e.type_()})
}); });
})), })))
onclose: Some(Box::new(move |e| { .onclose(Some(Box::new(move |e| {
set_history2.update(|history: &mut Vec<_>| { set_history2.update(|history: &mut Vec<_>| {
history.push(format! {"[onclose]: event {:?}", e.type_()}) history.push(format! {"[onclose]: event {:?}", e.type_()})
}); });
})), })))
onerror: Some(Box::new(move |e| { .onerror(Some(Box::new(move |e| {
set_history2.update(|history: &mut Vec<_>| { set_history2.update(|history: &mut Vec<_>| {
history.push(format! {"[onerror]: event {:?}", e.type_()}) history.push(format! {"[onerror]: event {:?}", e.type_()})
}); });
})), })))
onmessage: Some(Box::new(move |m| { .onmessage(Some(Box::new(move |m| {
set_history2 set_history2
.update(|history: &mut Vec<_>| history.push(format! {"[onmessage]: {:?}", m})); .update(|history: &mut Vec<_>| history.push(format! {"[onmessage]: {:?}", m}));
})), })))
onmessage_bytes: Some(Box::new(move |m| { .onmessage_bytes(Some(Box::new(move |m| {
set_history2.update(|history: &mut Vec<_>| { set_history2.update(|history: &mut Vec<_>| {
history.push(format! {"[onmessage_bytes]: {:?}", m}) history.push(format! {"[onmessage_bytes]: {:?}", m})
}); });
})), }))),
..Default::default()
},
); );
let open_connection2 = move |_| { let open_connection2 = move |_| {

View file

@ -4,6 +4,7 @@ use core::fmt;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
use default_struct_builder::DefaultBuilder;
use js_sys::Array; use js_sys::Array;
use wasm_bindgen::{prelude::*, JsCast, JsValue}; use wasm_bindgen::{prelude::*, JsCast, JsValue};
use web_sys::{BinaryType, Event, MessageEvent, WebSocket}; use web_sys::{BinaryType, Event, MessageEvent, WebSocket};
@ -12,91 +13,67 @@ pub use web_sys::CloseEvent;
use crate::utils::CloneableFnMutWithArg; use crate::utils::CloneableFnMutWithArg;
/// The current state of the `WebSocket` connection. /// Creating and managing a [Websocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) connection.
#[derive(Debug, PartialEq, Eq, Clone)] ///
pub enum UseWebSocketReadyState { /// ## Demo
Connecting, ///
Open, /// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_websocket)
Closing, ///
Closed, /// ## Usage
} ///
/// ```
impl fmt::Display for UseWebSocketReadyState { /// # use leptos::*;
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// # use leptos_use::websocket::*;
match *self { /// #
UseWebSocketReadyState::Connecting => write!(f, "Connecting"), /// # #[component]
UseWebSocketReadyState::Open => write!(f, "Open"), /// # fn Demo(cx: Scope) -> impl IntoView {
UseWebSocketReadyState::Closing => write!(f, "Closing"), /// let UseWebsocketReturn {
UseWebSocketReadyState::Closed => write!(f, "Closed"), /// ready_state,
} /// message,
} /// message_bytes,
} /// send,
/// send_bytes,
/// Options for `WebSocket`. /// open,
// #[derive(DefaultBuilder)] /// close,
#[derive(Clone)] /// ..
pub struct UseWebSocketOptions { /// } = use_websocket(cx, "wss://echo.websocket.events/".to_string());
/// `WebSocket` connect callback. ///
pub onopen: Option<Box<dyn CloneableFnMutWithArg<Event>>>, /// let send_message = move |_| {
/// `WebSocket` message callback for text. /// let m = "Hello, world!".to_string();
pub onmessage: Option<Box<dyn CloneableFnMutWithArg<String>>>, /// send(m.clone());
/// `WebSocket` message callback for binary. /// };
pub onmessage_bytes: Option<Box<dyn CloneableFnMutWithArg<Vec<u8>>>>, ///
/// `WebSocket` error callback. /// let send_byte_message = move |_| {
pub onerror: Option<Box<dyn CloneableFnMutWithArg<Event>>>, /// let m = b"Hello, world!\r\n".to_vec();
/// `WebSocket` close callback. /// send_bytes(m.clone());
pub onclose: Option<Box<dyn CloneableFnMutWithArg<CloseEvent>>>, /// };
///
/// Retry times. /// let status = move || ready_state().to_string();
pub reconnect_limit: Option<u64>, ///
/// Retry interval(ms). /// let connected = move || ready_state.get() == UseWebSocketReadyState::Open;
pub reconnect_interval: Option<u64>, ///
/// Manually starts connection /// let open_connection = move |_| {
pub manual: bool, /// open();
/// Sub protocols /// };
pub protocols: Option<Vec<String>>, ///
} /// let close_connection = move |_| {
/// close();
impl Default for UseWebSocketOptions { /// };
fn default() -> Self { ///
Self { /// view! { cx,
onopen: None, /// <div>
onmessage: None, /// <p>"status: " {status}</p>
onmessage_bytes: None, /// button on:click=send_message disabled=move || !connected()>"Send"</button>
onerror: None, /// <button on:click=send_byte_message disabled=move || !connected()>"Send bytes"</button>
onclose: None, /// <button on:click=open_connection disabled=connected>"Open"</button>
reconnect_limit: Some(3), /// <button on:click=close_connection disabled=move || !connected()>"Close"</button>
reconnect_interval: Some(3 * 1000), /// <p>"Receive message: " {format! {"{:?}", message}}</p>
manual: false, /// <p>"Receive byte message: " {format! {"{:?}", message_bytes}}</p>
protocols: Default::default(), /// </div>
} /// }
} /// # }
} /// ```
// #[doc(cfg(feature = "websocket"))]
/// Return type of [`use_websocket`].
#[derive(Clone)]
pub struct UseWebsocketReturn<OpenFn, CloseFn, SendFn, SendBytesFn>
where
OpenFn: Fn() + Clone + 'static,
CloseFn: Fn() + Clone + 'static,
SendFn: Fn(String) + Clone + 'static,
SendBytesFn: Fn(Vec<u8>) + Clone + 'static,
{
/// The current state of the `WebSocket` connection.
pub ready_state: ReadSignal<UseWebSocketReadyState>,
/// Latest text message received from `WebSocket`.
pub message: ReadSignal<Option<String>>,
/// Latest binary message received from `WebSocket`.
pub message_bytes: ReadSignal<Option<Vec<u8>>>,
/// The `WebSocket` instance.
pub ws: Option<WebSocket>,
pub open: OpenFn,
pub close: CloseFn,
pub send: SendFn,
pub send_bytes: SendBytesFn,
}
pub fn use_websocket( pub fn use_websocket(
cx: Scope, cx: Scope,
url: String, url: String,
@ -110,7 +87,7 @@ pub fn use_websocket(
} }
/// Version of [`use_websocket`] that takes `UseWebSocketOptions`. See [`use_websocket`] for how to use. /// Version of [`use_websocket`] that takes `UseWebSocketOptions`. See [`use_websocket`] for how to use.
// #[doc(cfg(feature = "websocket"))]
pub fn use_websocket_with_options( pub fn use_websocket_with_options(
cx: Scope, cx: Scope,
url: String, url: String,
@ -254,7 +231,6 @@ pub fn use_websocket_with_options(
} }
// onerror handler // onerror handler
{ {
// let reconnect = reconnect.clone();
let onerror_closure = Closure::wrap(Box::new(move |e: Event| { let onerror_closure = Closure::wrap(Box::new(move |e: Event| {
if unmounted_ref.get_value() { if unmounted_ref.get_value() {
return; return;
@ -372,3 +348,92 @@ pub fn use_websocket_with_options(
send_bytes, send_bytes,
} }
} }
/// The current state of the `WebSocket` connection.
// #[doc(cfg(feature = "websocket"))]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum UseWebSocketReadyState {
Connecting,
Open,
Closing,
Closed,
}
impl fmt::Display for UseWebSocketReadyState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
UseWebSocketReadyState::Connecting => write!(f, "Connecting"),
UseWebSocketReadyState::Open => write!(f, "Open"),
UseWebSocketReadyState::Closing => write!(f, "Closing"),
UseWebSocketReadyState::Closed => write!(f, "Closed"),
}
}
}
/// Options for [`use_websocket_with_options`].
// #[doc(cfg(feature = "websocket"))]
#[derive(DefaultBuilder, Clone)]
pub struct UseWebSocketOptions {
/// `WebSocket` connect callback.
onopen: Option<Box<dyn CloneableFnMutWithArg<Event>>>,
/// `WebSocket` message callback for text.
onmessage: Option<Box<dyn CloneableFnMutWithArg<String>>>,
/// `WebSocket` message callback for binary.
onmessage_bytes: Option<Box<dyn CloneableFnMutWithArg<Vec<u8>>>>,
/// `WebSocket` error callback.
onerror: Option<Box<dyn CloneableFnMutWithArg<Event>>>,
/// `WebSocket` close callback.
onclose: Option<Box<dyn CloneableFnMutWithArg<CloseEvent>>>,
/// Retry times.
reconnect_limit: Option<u64>,
/// Retry interval(ms).
reconnect_interval: Option<u64>,
/// Manually starts connection
manual: bool,
/// Sub protocols
protocols: Option<Vec<String>>,
}
impl Default for UseWebSocketOptions {
fn default() -> Self {
Self {
onopen: None,
onmessage: None,
onmessage_bytes: None,
onerror: None,
onclose: None,
reconnect_limit: Some(3),
reconnect_interval: Some(3 * 1000),
manual: false,
protocols: Default::default(),
}
}
}
/// Return type of [`use_websocket`].
// #[doc(cfg(feature = "websocket"))]
#[derive(Clone)]
pub struct UseWebsocketReturn<OpenFn, CloseFn, SendFn, SendBytesFn>
where
OpenFn: Fn() + Clone + 'static,
CloseFn: Fn() + Clone + 'static,
SendFn: Fn(String) + Clone + 'static,
SendBytesFn: Fn(Vec<u8>) + Clone + 'static,
{
/// The current state of the `WebSocket` connection.
pub ready_state: ReadSignal<UseWebSocketReadyState>,
/// Latest text message received from `WebSocket`.
pub message: ReadSignal<Option<String>>,
/// Latest binary message received from `WebSocket`.
pub message_bytes: ReadSignal<Option<Vec<u8>>>,
/// The `WebSocket` instance.
pub ws: Option<WebSocket>,
/// Opens the `WebSocket` connection
pub open: OpenFn,
/// Closes the `WebSocket` connection
pub close: CloseFn,
/// Sends `text` (string) based data
pub send: SendFn,
/// Sends binary data
pub send_bytes: SendBytesFn,
}