From fa47bab2cda85eb7e14c34859ade1ca399b0666e Mon Sep 17 00:00:00 2001 From: Maccesch Date: Sat, 29 Jul 2023 15:12:09 +0100 Subject: [PATCH] fixed use_event_listener removing of listener with non default options --- Cargo.toml | 4 + src/use_event_listener.rs | 7 +- src/use_websocket.rs | 309 +++++++++++++++++++------------------- 3 files changed, 162 insertions(+), 158 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4de7412..f06f7d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ wasm-bindgen-futures = "0.4" [dependencies.web-sys] version = "0.3" features = [ + "AddEventListenerOptions", "BinaryType", "CssStyleDeclaration", "CloseEvent", @@ -38,6 +39,9 @@ features = [ "DataTransfer", "DragEvent", "Element", + "EventListener", + "EventListenerOptions", + "EventTarget", "File", "FileList", "HtmlElement", diff --git a/src/use_event_listener.rs b/src/use_event_listener.rs index f80a645..51f9d5c 100644 --- a/src/use_event_listener.rs +++ b/src/use_event_listener.rs @@ -112,11 +112,13 @@ where let cleanup_fn = { let closure_js = closure_js.clone(); + let options = options.clone(); move |element: &web_sys::EventTarget| { - let _ = element.remove_event_listener_with_callback( + let _ = element.remove_event_listener_with_callback_and_event_listener_options( &event_name, closure_js.as_ref().unchecked_ref(), + options.unchecked_ref(), ); } }; @@ -125,8 +127,7 @@ where let signal = (target).into(); - let prev_element: Rc>> = - Rc::new(RefCell::new(signal.get_untracked().map(|e| e.into()))); + let prev_element = Rc::new(RefCell::new(None::)); let cleanup_prev_element = { let prev_element = prev_element.clone(); diff --git a/src/use_websocket.rs b/src/use_websocket.rs index c75add0..0fbfa3e 100644 --- a/src/use_websocket.rs +++ b/src/use_websocket.rs @@ -24,7 +24,8 @@ use crate::utils::CloneableFnWithArg; /// /// ``` /// # use leptos::*; -/// # use leptos_use::{use_websocket, UseWebsocketReturn}; +/// # use leptos_use::{use_websocket, UseWebsocketReturn}; +/// # use leptos_use::core::ConnectionReadyState; /// # /// # #[component] /// # fn Demo() -> impl IntoView { @@ -37,16 +38,14 @@ use crate::utils::CloneableFnWithArg; /// open, /// close, /// .. -/// } = use_websocket("wss://echo.websocket.events/".to_string()); +/// } = use_websocket("wss://echo.websocket.events/"); /// /// let send_message = move |_| { -/// let m = "Hello, world!".to_string(); -/// send(m.clone()); +/// send("Hello, world!".to_string()); /// }; /// /// let send_byte_message = move |_| { -/// let m = b"Hello, world!\r\n".to_vec(); -/// send_bytes(m.clone()); +/// send_bytes(b"Hello, world!\r\n".to_vec()); /// }; /// /// let status = move || ready_state.get().to_string(); @@ -118,167 +117,167 @@ pub fn use_websocket_with_options( let connect_ref: StoredValue>> = store_value(None); - // cfg_if! { if #[cfg(not(feature = "ssr"))] { - let on_open_ref = store_value(options.on_open); - let on_message_ref = store_value(options.on_message); - let on_message_bytes_ref = store_value(options.on_message_bytes); - let on_error_ref = store_value(options.on_error); - let on_close_ref = store_value(options.on_close); + cfg_if! { if #[cfg(not(feature = "ssr"))] { + let on_open_ref = store_value(options.on_open); + let on_message_ref = store_value(options.on_message); + let on_message_bytes_ref = store_value(options.on_message_bytes); + let on_error_ref = store_value(options.on_error); + let on_close_ref = store_value(options.on_close); - let reconnect_interval = options.reconnect_interval; - let protocols = options.protocols; + let reconnect_interval = options.reconnect_interval; + let protocols = options.protocols; - let reconnect_ref: StoredValue>> = store_value(None); - reconnect_ref.set_value({ - let ws = ws_ref.get_value(); - Some(Rc::new(move || { - if reconnect_times_ref.get_value() < reconnect_limit - && ws - .clone() - .map_or(false, |ws: WebSocket| ws.ready_state() != WebSocket::OPEN) - { - reconnect_timer_ref.set_value( - set_timeout_with_handle( - move || { - if let Some(connect) = connect_ref.get_value() { - connect(); - reconnect_times_ref.update_value(|current| *current += 1); - } - }, - Duration::from_millis(reconnect_interval), - ) - .ok(), - ); - } - })) - }); - - connect_ref.set_value({ - let ws = ws_ref.get_value(); - let url = url; - - Some(Rc::new(move || { - reconnect_timer_ref.set_value(None); - - if let Some(web_socket) = &ws { - let _ = web_socket.close(); - } - - let web_socket = { - protocols.as_ref().map_or_else( - || WebSocket::new(&url).unwrap_throw(), - |protocols| { - let array = protocols - .iter() - .map(|p| JsValue::from(p.clone())) - .collect::(); - WebSocket::new_with_str_sequence(&url, &JsValue::from(&array)) - .unwrap_throw() - }, - ) - }; - web_socket.set_binary_type(BinaryType::Arraybuffer); - set_ready_state.set(ConnectionReadyState::Connecting); - - // onopen handler - { - let onopen_closure = Closure::wrap(Box::new(move |e: Event| { - if unmounted_ref.get_value() { - return; - } - - let callback = on_open_ref.get_value(); - callback(e); - - set_ready_state.set(ConnectionReadyState::Open); - }) as Box); - web_socket.set_onopen(Some(onopen_closure.as_ref().unchecked_ref())); - // Forget the closure to keep it alive - onopen_closure.forget(); - } - - // onmessage handler - { - let onmessage_closure = Closure::wrap(Box::new(move |e: MessageEvent| { - if unmounted_ref.get_value() { - return; - } - - e.data().dyn_into::().map_or_else( - |_| { - e.data().dyn_into::().map_or_else( - |_| { - unreachable!("message event, received Unknown: {:?}", e.data()); - }, - |txt| { - let txt = String::from(&txt); - let callback = on_message_ref.get_value(); - callback(txt.clone()); - - set_message.set(Some(txt)); - }, - ); - }, - |array_buffer| { - let array = js_sys::Uint8Array::new(&array_buffer); - let array = array.to_vec(); - let callback = on_message_bytes_ref.get_value(); - callback(array.clone()); - - set_message_bytes.set(Some(array)); - }, + let reconnect_ref: StoredValue>> = store_value(None); + reconnect_ref.set_value({ + let ws = ws_ref.get_value(); + Some(Rc::new(move || { + if reconnect_times_ref.get_value() < reconnect_limit + && ws + .clone() + .map_or(false, |ws: WebSocket| ws.ready_state() != WebSocket::OPEN) + { + reconnect_timer_ref.set_value( + set_timeout_with_handle( + move || { + if let Some(connect) = connect_ref.get_value() { + connect(); + reconnect_times_ref.update_value(|current| *current += 1); + } + }, + Duration::from_millis(reconnect_interval), + ) + .ok(), ); - }) - as Box); - web_socket.set_onmessage(Some(onmessage_closure.as_ref().unchecked_ref())); - onmessage_closure.forget(); - } + } + })) + }); - // onerror handler - { - let onerror_closure = Closure::wrap(Box::new(move |e: Event| { - if unmounted_ref.get_value() { - return; - } + connect_ref.set_value({ + let ws = ws_ref.get_value(); + let url = url; - if let Some(reconnect) = &reconnect_ref.get_value() { - reconnect(); - } + Some(Rc::new(move || { + reconnect_timer_ref.set_value(None); - let callback = on_error_ref.get_value(); - callback(e); + if let Some(web_socket) = &ws { + let _ = web_socket.close(); + } - set_ready_state.set(ConnectionReadyState::Closed); - }) as Box); - web_socket.set_onerror(Some(onerror_closure.as_ref().unchecked_ref())); - onerror_closure.forget(); - } + let web_socket = { + protocols.as_ref().map_or_else( + || WebSocket::new(&url).unwrap_throw(), + |protocols| { + let array = protocols + .iter() + .map(|p| JsValue::from(p.clone())) + .collect::(); + WebSocket::new_with_str_sequence(&url, &JsValue::from(&array)) + .unwrap_throw() + }, + ) + }; + web_socket.set_binary_type(BinaryType::Arraybuffer); + set_ready_state.set(ConnectionReadyState::Connecting); - // onclose handler - { - let onclose_closure = Closure::wrap(Box::new(move |e: CloseEvent| { - if unmounted_ref.get_value() { - return; - } + // onopen handler + { + let onopen_closure = Closure::wrap(Box::new(move |e: Event| { + if unmounted_ref.get_value() { + return; + } - if let Some(reconnect) = &reconnect_ref.get_value() { - reconnect(); - } + let callback = on_open_ref.get_value(); + callback(e); - let callback = on_close_ref.get_value(); - callback(e); + set_ready_state.set(ConnectionReadyState::Open); + }) as Box); + web_socket.set_onopen(Some(onopen_closure.as_ref().unchecked_ref())); + // Forget the closure to keep it alive + onopen_closure.forget(); + } - set_ready_state.set(ConnectionReadyState::Closed); - }) - as Box); - web_socket.set_onclose(Some(onclose_closure.as_ref().unchecked_ref())); - onclose_closure.forget(); - } + // onmessage handler + { + let onmessage_closure = Closure::wrap(Box::new(move |e: MessageEvent| { + if unmounted_ref.get_value() { + return; + } - ws_ref.set_value(Some(web_socket)); - })) - }); - // }} + e.data().dyn_into::().map_or_else( + |_| { + e.data().dyn_into::().map_or_else( + |_| { + unreachable!("message event, received Unknown: {:?}", e.data()); + }, + |txt| { + let txt = String::from(&txt); + let callback = on_message_ref.get_value(); + callback(txt.clone()); + + set_message.set(Some(txt)); + }, + ); + }, + |array_buffer| { + let array = js_sys::Uint8Array::new(&array_buffer); + let array = array.to_vec(); + let callback = on_message_bytes_ref.get_value(); + callback(array.clone()); + + set_message_bytes.set(Some(array)); + }, + ); + }) + as Box); + web_socket.set_onmessage(Some(onmessage_closure.as_ref().unchecked_ref())); + onmessage_closure.forget(); + } + + // onerror handler + { + let onerror_closure = Closure::wrap(Box::new(move |e: Event| { + if unmounted_ref.get_value() { + return; + } + + if let Some(reconnect) = &reconnect_ref.get_value() { + reconnect(); + } + + let callback = on_error_ref.get_value(); + callback(e); + + set_ready_state.set(ConnectionReadyState::Closed); + }) as Box); + web_socket.set_onerror(Some(onerror_closure.as_ref().unchecked_ref())); + onerror_closure.forget(); + } + + // onclose handler + { + let onclose_closure = Closure::wrap(Box::new(move |e: CloseEvent| { + if unmounted_ref.get_value() { + return; + } + + if let Some(reconnect) = &reconnect_ref.get_value() { + reconnect(); + } + + let callback = on_close_ref.get_value(); + callback(e); + + set_ready_state.set(ConnectionReadyState::Closed); + }) + as Box); + web_socket.set_onclose(Some(onclose_closure.as_ref().unchecked_ref())); + onclose_closure.forget(); + } + + ws_ref.set_value(Some(web_socket)); + })) + }); + }} // Send text (String) let send = {