diff --git a/Cargo.toml b/Cargo.toml index 8bde861..b114361 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,7 @@ members = [ ] [workspace.dependencies] -dioxus-std = { path = "./std"} +dioxus-std = { path = "./std" } +dioxus = { version = "0.5" } +dioxus-web = { version = "0.5" } +dioxus-desktop = { version = "0.5" } \ No newline at end of file diff --git a/README.md b/README.md index 1c39168..ad418f0 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ - [x] Notifications - (Desktop) - [x] Color Scheme - (any) - [x] Utility Hooks - - [x] use_rw - (any) - [x] use_channel - (any) - [ ] use_interval (any) - [x] i18n - (any) @@ -49,19 +48,19 @@ use dioxus_std::geolocation::{ init_geolocator, use_geolocation, PowerMode }; -fn app(cx: Scope) -> Element { - let geolocator = init_geolocator(cx, PowerMode::High).unwrap(); - let coords = use_geolocation(cx); +fn app() -> Element { + let geolocator = init_geolocator(PowerMode::High).unwrap(); + let coords = use_geolocation(); match coords { Ok(coords) => { - render! { p { format!("Latitude: {} | Longitude: {}", coords.latitude, coords.longitude) } } + rsx!( p { "Latitude: {coords.latitude} | Longitude: {coords.longitude}" } ) } Err(Error::NotInitialized) => { - render! { p { "Initializing..." }} + rsx!( p { "Initializing..." } ) } Err(e) => { - render! { p { "An error occurred {e}" }} + rsx!( p { "An error occurred {e}" } ) } } } @@ -79,7 +78,7 @@ sudo apt-get install xorg-dev You can add `dioxus-std` to your application by adding it to your dependencies. ```toml [dependencies] -dioxus-std = { version = "0.4.2", features = [] } +dioxus-std = { version = "0.5", features = [] } ``` ## License diff --git a/examples/channel/Cargo.toml b/examples/channel/Cargo.toml index 5f21512..9cb8bd3 100644 --- a/examples/channel/Cargo.toml +++ b/examples/channel/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] dioxus-std = { workspace = true, features = ["utils"]} -dioxus = "0.4" -dioxus-web = "0.4" +dioxus = { workspace = true } +dioxus-web = { workspace = true } log = "0.4.6" diff --git a/examples/channel/src/main.rs b/examples/channel/src/main.rs index cc9f7d0..b9dcc77 100644 --- a/examples/channel/src/main.rs +++ b/examples/channel/src/main.rs @@ -6,27 +6,24 @@ fn main() { wasm_logger::init(wasm_logger::Config::default()); console_error_panic_hook::set_once(); - dioxus_web::launch(app); + launch(app); } -fn app(cx: Scope) -> Element { - let channel = use_channel::(cx, 5); +fn app() -> Element { + let channel = use_channel::(5); - use_listen_channel(cx, &channel, |message| async { + use_listen_channel(&channel, |message| async { match message { Ok(value) => log::info!("Incoming message: {value}"), Err(err) => log::info!("Error: {err:?}"), } }); - let send = |_: MouseEvent| { - to_owned![channel]; - async move { - channel.send("Hello").await.ok(); - } + let send = move |_: MouseEvent| async move { + channel.send("Hello").await.ok(); }; - render!( + rsx!( button { onclick: send, "Send hello" diff --git a/examples/clipboard/Cargo.toml b/examples/clipboard/Cargo.toml index 9f29e7e..465b3c0 100644 --- a/examples/clipboard/Cargo.toml +++ b/examples/clipboard/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" [dependencies] dioxus-std = { workspace = true, features = ["clipboard"] } -dioxus = "0.4" -dioxus-desktop = "0.4" +dioxus = { workspace = true } +dioxus-desktop = { workspace = true } diff --git a/examples/clipboard/src/main.rs b/examples/clipboard/src/main.rs index e3c7d68..bcac658 100644 --- a/examples/clipboard/src/main.rs +++ b/examples/clipboard/src/main.rs @@ -5,20 +5,17 @@ fn main() { dioxus_desktop::launch(app); } -fn app(cx: Scope) -> Element { - let clipboard = use_clipboard(cx); - let text = use_state(cx, String::new); +fn app() -> Element { + let mut clipboard = use_clipboard(); + let mut text = use_signal(String::new); - let oninput = |e: FormEvent| { + let oninput = move |e: FormEvent| { text.set(e.data.value.clone()); }; - let oncopy = { - to_owned![clipboard]; - move |_| match clipboard.set(text.get().clone()) { - Ok(_) => println!("Copied to clipboard: {}", text.get()), - Err(err) => println!("Error on copy: {err:?}"), - } + let oncopy = move |_| match clipboard.set(text.read().clone()) { + Ok(_) => println!("Copied to clipboard: {}", text.read()), + Err(err) => println!("Error on copy: {err:?}"), }; let onpaste = move |_| match clipboard.get() { @@ -29,7 +26,7 @@ fn app(cx: Scope) -> Element { Err(err) => println!("Error on paste: {err:?}"), }; - render!( + rsx!( input { oninput: oninput, value: "{text}" diff --git a/examples/color_scheme/Cargo.toml b/examples/color_scheme/Cargo.toml index d335619..deda12c 100644 --- a/examples/color_scheme/Cargo.toml +++ b/examples/color_scheme/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] dioxus-std = { workspace = true, features = ["color_scheme"] } -dioxus = "0.4" -dioxus-web = "0.4" +dioxus = { workspace = true } +dioxus-web = { workspace = true } log = "0.4.6" diff --git a/examples/color_scheme/src/main.rs b/examples/color_scheme/src/main.rs index 6e9c59d..4f5fed5 100644 --- a/examples/color_scheme/src/main.rs +++ b/examples/color_scheme/src/main.rs @@ -9,10 +9,10 @@ fn main() { dioxus_web::launch(app); } -fn app(cx: Scope) -> Element { - let color_scheme = use_preferred_color_scheme(cx); +fn app() -> Element { + let color_scheme = use_preferred_color_scheme(); - render!( + rsx!( div { style: "text-align: center;", h1 { "πŸŒ— Dioxus πŸš€" } diff --git a/examples/geolocation/Cargo.toml b/examples/geolocation/Cargo.toml index 904d72a..deeb997 100644 --- a/examples/geolocation/Cargo.toml +++ b/examples/geolocation/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] dioxus-std = { workspace = true, features = ["geolocation"] } -dioxus = "0.4" -dioxus-desktop = "0.4" -#dioxus-web = "0.4" +dioxus = { workspace = true } +dioxus-desktop ={ workspace = true } +# dioxus-web ={ workspace = true } diff --git a/examples/geolocation/src/main.rs b/examples/geolocation/src/main.rs index 8969974..3d87e9f 100644 --- a/examples/geolocation/src/main.rs +++ b/examples/geolocation/src/main.rs @@ -6,18 +6,16 @@ fn main() { //dioxus_web::launch(app); } -fn app(cx: Scope) -> Element { - let geolocator = init_geolocator(cx, PowerMode::High).unwrap(); - let initial_coords = use_future(cx, (), |_| async move { - geolocator.get_coordinates().await.unwrap() - }); - let latest_coords = use_geolocation(cx); +fn app() -> Element { + let geolocator = init_geolocator(PowerMode::High).unwrap(); + let initial_coords = use_future(|_| async move { geolocator.get_coordinates().await.unwrap() }); + let latest_coords = use_geolocation(); let latest_coords = match latest_coords { Ok(v) => v, Err(e) => { let e = format!("Initializing: {:?}", e); - return cx.render(rsx!(p { "{e}" })); + return rsx!(p { "{e}" }); } }; @@ -26,7 +24,7 @@ fn app(cx: Scope) -> Element { let initial_coords = initial_coords.value(); - cx.render(rsx! ( + rsx!( div { style: "text-align: center;", h1 { "πŸ—ΊοΈ Dioxus Geolocation Example πŸ›°οΈ" } @@ -34,7 +32,7 @@ fn app(cx: Scope) -> Element { p { if let Some(coords) = initial_coords { - format!("Latitude: {} | Longitude: {}", coords.latitude, coords.longitude) + format!("Latitude: {} | Longitude: {}", coords.latitude, coords.longitude) } else { "Loading...".to_string() } @@ -51,5 +49,5 @@ fn app(cx: Scope) -> Element { // src: "https://www.google.com/maps/embed/v1/view?key={key}¢er={latest_coords.latitude},{latest_coords.longitude}&zoom=16", //} } - )) + ) } diff --git a/examples/i18n/Cargo.toml b/examples/i18n/Cargo.toml index 71ec68c..b023daa 100644 --- a/examples/i18n/Cargo.toml +++ b/examples/i18n/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] dioxus-std = { workspace = true, features = ["i18n"] } -dioxus = "0.4" -dioxus-web = "0.4" +dioxus = { workspace = true } +dioxus-web = { workspace = true } log = "0.4.6" diff --git a/examples/i18n/src/main.rs b/examples/i18n/src/main.rs index 3970ed6..7420d26 100644 --- a/examples/i18n/src/main.rs +++ b/examples/i18n/src/main.rs @@ -15,13 +15,13 @@ static EN_US: &str = include_str!("./en-US.json"); static ES_ES: &str = include_str!("./es-ES.json"); #[allow(non_snake_case)] -fn Body(cx: Scope) -> Element { - let i18 = use_i18(cx); +fn Body() -> Element { + let i18 = use_i18(); let change_to_english = move |_| i18.set_language("en-US".parse().unwrap()); let change_to_spanish = move |_| i18.set_language("es-ES".parse().unwrap()); - render!( + rsx!( button { onclick: change_to_english, label { @@ -39,17 +39,12 @@ fn Body(cx: Scope) -> Element { ) } -fn app(cx: Scope) -> Element { - use_init_i18n( - cx, - "en-US".parse().unwrap(), - "en-US".parse().unwrap(), - || { - let en_us = Language::from_str(EN_US).unwrap(); - let es_es = Language::from_str(ES_ES).unwrap(); - vec![en_us, es_es] - }, - ); - - render!(Body {}) +fn app() -> Element { + use_init_i18n("en-US".parse().unwrap(), "en-US".parse().unwrap(), || { + let en_us = Language::from_str(EN_US).unwrap(); + let es_es = Language::from_str(ES_ES).unwrap(); + vec![en_us, es_es] + }); + + rsx!(Body {}) } diff --git a/std/Cargo.toml b/std/Cargo.toml index ffd8aae..ef792f7 100644 --- a/std/Cargo.toml +++ b/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dioxus-std" -version = "0.4.2" +version = "0.5.0" authors = ["Jonathan Kelley", "Dioxus Labs", "ealmloff", "DogeDark", "marc2332"] edition = "2021" description = "Platform agnostic library for supercharging your productivity with Dioxus" @@ -18,11 +18,10 @@ categories = ["multimedia", "os", "wasm"] [features] utils = ["dep:async-broadcast", "uuid/v4"] -clipboard = ["dep:dioxus", "dep:copypasta"] -notifications = ["dep:dioxus", "dep:notify-rust"] +clipboard = ["dep:copypasta"] +notifications = ["dep:notify-rust"] geolocation = [ # Shared - "dep:dioxus", "dep:futures", "dep:futures-util", @@ -37,9 +36,6 @@ geolocation = [ "dep:wasm-bindgen", ] color_scheme = [ - # Shared - "dep:dioxus", - # Wasm "web-sys/Window", "web-sys/MediaQueryList", @@ -65,8 +61,8 @@ desktop-testing = ["clipboard", "notifications", "geolocation", "utils", "i18n"] # # # # # # # # # # # # # # # [dependencies] +dioxus = { workspace = true } cfg-if = "1.0.0" -dioxus = { version = "0.4", optional = true } # Used by: clipboard copypasta = { version = "0.8.2", optional = true } diff --git a/std/src/clipboard/use_clipboard.rs b/std/src/clipboard/use_clipboard.rs index e90d631..499bd7d 100644 --- a/std/src/clipboard/use_clipboard.rs +++ b/std/src/clipboard/use_clipboard.rs @@ -1,65 +1,69 @@ -//! Provides a clipboard abstraction to access the target system's clipboard. - -use copypasta::{ClipboardContext, ClipboardProvider}; -use dioxus::prelude::{RefCell, ScopeState}; -use std::rc::Rc; - -#[derive(Debug, PartialEq, Clone)] -pub enum ClipboardError { - FailedToRead, - FailedToSet, -} - -/// Handle to access the ClipboardContext. -#[derive(Clone)] -pub struct UseClipboard { - clipboard: Rc>, -} - -impl UseClipboard { - // Read from the clipboard - pub fn get(&self) -> Result { - self.clipboard - .borrow_mut() - .get_contents() - .map_err(|_| ClipboardError::FailedToRead) - } - - // Write to the clipboard - pub fn set(&self, contents: String) -> Result<(), ClipboardError> { - self.clipboard - .borrow_mut() - .set_contents(contents) - .map_err(|_| ClipboardError::FailedToSet) - } -} - -/// Access the clipboard. -/// -/// # Examples -/// -/// ```ignore -/// use dioxus_std::clipboard::use_clipboard; -/// -/// // Get a handle to the clipboard -/// let clipboard = use_clipboard(cx); -/// -/// // Read the clipboard content -/// if let Ok(content) = clipboard.get() { -/// println!("{}", content); -/// } -/// -/// // Write to the clipboard -/// clipboard.set("Hello, Dioxus!".to_string());; -/// -/// ``` -pub fn use_clipboard(cx: &ScopeState) -> UseClipboard { - let clipboard = match cx.consume_context() { - Some(rt) => rt, - None => { - let clipboard = ClipboardContext::new().expect("Cannot create Clipboard."); - cx.provide_root_context(Rc::new(RefCell::new(clipboard))) - } - }; - UseClipboard { clipboard } -} +//! Provides a clipboard abstraction to access the target system's clipboard. + +use copypasta::{ClipboardContext, ClipboardProvider}; +use dioxus::prelude::*; + +#[derive(Debug, PartialEq, Clone)] +pub enum ClipboardError { + FailedToRead, + FailedToSet, + NotAvailable, +} + +/// Handle to access the ClipboardContext. +#[derive(Clone, Copy, PartialEq)] +pub struct UseClipboard { + clipboard: Signal>, +} + +impl UseClipboard { + // Read from the clipboard + pub fn get(&mut self) -> Result { + self.clipboard + .write() + .as_mut() + .ok_or(ClipboardError::NotAvailable)? + .get_contents() + .map_err(|_| ClipboardError::FailedToRead) + } + + // Write to the clipboard + pub fn set(&mut self, contents: String) -> Result<(), ClipboardError> { + self.clipboard + .write() + .as_mut() + .ok_or(ClipboardError::NotAvailable)? + .set_contents(contents) + .map_err(|_| ClipboardError::FailedToSet) + } +} + +/// Access the clipboard. +/// +/// # Examples +/// +/// ```ignore +/// use dioxus_std::clipboard::use_clipboard; +/// +/// // Get a handle to the clipboard +/// let mut clipboard = use_clipboard(); +/// +/// // Read the clipboard content +/// if let Ok(content) = clipboard.get() { +/// println!("{}", content); +/// } +/// +/// // Write to the clipboard +/// clipboard.set("Hello, Dioxus!".to_string());; +/// +/// ``` +pub fn use_clipboard() -> UseClipboard { + let clipboard = match try_consume_context() { + Some(rt) => rt, + None => { + let clipboard = ClipboardContext::new().ok(); + provide_root_context(Signal::new(clipboard)) + } + }; + UseClipboard { clipboard } +} diff --git a/std/src/color_scheme/use_preferred_color_scheme.rs b/std/src/color_scheme/use_preferred_color_scheme.rs index 23317f2..8dce8c9 100644 --- a/std/src/color_scheme/use_preferred_color_scheme.rs +++ b/std/src/color_scheme/use_preferred_color_scheme.rs @@ -1,5 +1,5 @@ //! Provides a hook to access the user's preferred color scheme. -use dioxus::prelude::ScopeState; +use dioxus::prelude::*; use std::{fmt, sync::Once}; use wasm_bindgen::{prelude::Closure, JsCast}; @@ -13,9 +13,7 @@ pub enum PreferredColorScheme { static INIT: Once = Once::new(); /// Retrieves (as well as listens for changes) to the user's preferred color scheme (dark or light) so your application can adapt accordingly. -pub fn use_preferred_color_scheme( - cx: &ScopeState, -) -> Result { +pub fn use_preferred_color_scheme() -> Result { // This code is kinda messy.. let window = match web_sys::window() { Some(w) => w, @@ -44,7 +42,7 @@ pub fn use_preferred_color_scheme( } }; - let update_callback = cx.schedule_update(); + let update_callback = schedule_update(); // Create closure that listens to the event of matchMedia and calls write to scheme INIT.call_once(|| { diff --git a/std/src/geolocation/core.rs b/std/src/geolocation/core.rs index 6206612..c2f0e80 100644 --- a/std/src/geolocation/core.rs +++ b/std/src/geolocation/core.rs @@ -75,10 +75,11 @@ impl Geolocator { /// Subscribe a mpsc channel to the events. pub fn listen(&self, listener: Coroutine) -> Result<(), Error> { + let tx = listener.tx(); platform::listen( &self.device_geolocator, Arc::new(move |event: Event| { - listener.send(event); + tx.unbounded_send(event).ok(); }), ) } diff --git a/std/src/geolocation/use_geolocation.rs b/std/src/geolocation/use_geolocation.rs index 6588690..ab4c9bf 100644 --- a/std/src/geolocation/use_geolocation.rs +++ b/std/src/geolocation/use_geolocation.rs @@ -1,37 +1,38 @@ //! Provides an initialization and use_geolocation hook. use super::core::{Error, Event, Geocoordinates, Geolocator, PowerMode, Status}; -use dioxus::prelude::{use_coroutine, ScopeState, UnboundedReceiver}; +use dioxus::{ + prelude::{ + provide_context, try_consume_context, use_coroutine, use_signal, Signal, UnboundedReceiver, + }, + signals::{Readable, Writable}, +}; use futures_util::stream::StreamExt; use std::{rc::Rc, sync::Once}; -use crate::utils::rw::{use_rw, UseRw}; - static INIT: Once = Once::new(); /// Provides the latest geocoordinates. Good for navigation-type apps. -pub fn use_geolocation(cx: &ScopeState) -> Result { +pub fn use_geolocation() -> Result { // Store the coords - let coords: &mut UseRw> = - use_rw(cx, || Err(Error::NotInitialized)); + let mut coords: Signal> = + use_signal(|| Err(Error::NotInitialized)); // Get geolocator - let geolocator = match cx.consume_context::>() { + let geolocator = match try_consume_context::>() { Some(v) => v, None => return Err(Error::NotInitialized), }; - let coords_cloned = coords.clone(); - // Initialize the handler of events - let listener = use_coroutine(cx, |mut rx: UnboundedReceiver| async move { + let listener = use_coroutine(|mut rx: UnboundedReceiver| async move { while let Some(event) = rx.next().await { match event { Event::NewGeocoordinates(new_coords) => { - let _ = coords_cloned.write(Ok(new_coords)); + *coords.write() = Ok(new_coords); } Event::StatusChanged(Status::Disabled) => { - let _ = coords_cloned.write(Err(Error::AccessDenied)); + *coords.write() = Err(Error::AccessDenied); } _ => {} } @@ -40,17 +41,17 @@ pub fn use_geolocation(cx: &ScopeState) -> Result { // Start listening INIT.call_once(|| { - let _ = geolocator.listen(listener.clone()); + geolocator.listen(listener).ok(); }); // Get the result and return a clone - coords.read().map_err(|_| Error::Poisoned)?.clone() + coords.read_unchecked().clone() } /// Must be called before any use of the geolocation abstraction. -pub fn init_geolocator(cx: &ScopeState, power_mode: PowerMode) -> Result, Error> { +pub fn init_geolocator(power_mode: PowerMode) -> Result, Error> { let geolocator = Geolocator::new(power_mode)?; let shared_locator = Rc::new(geolocator); - cx.provide_context(shared_locator.clone()); + provide_context(shared_locator.clone()); Ok(shared_locator) } diff --git a/std/src/i18n/use_i18n.rs b/std/src/i18n/use_i18n.rs index 141b609..2b791ee 100644 --- a/std/src/i18n/use_i18n.rs +++ b/std/src/i18n/use_i18n.rs @@ -74,13 +74,13 @@ impl Language { } } -#[derive(Clone, Copy)] -pub struct UseI18<'a> { - pub selected_language: &'a UseSharedState, - pub data: &'a UseSharedState, +#[derive(Clone, PartialEq, Copy)] +pub struct UseI18 { + pub selected_language: Signal, + pub data: Signal, } -impl<'a> UseI18<'a> { +impl UseI18 { pub fn translate_with_params(&self, id: &str, params: HashMap<&str, String>) -> String { let i18n_data = self.data.read(); @@ -106,17 +106,19 @@ impl<'a> UseI18<'a> { self.translate_with_params(id, HashMap::default()) } - pub fn set_language(&self, id: LanguageIdentifier) { + pub fn set_language(&mut self, id: LanguageIdentifier) { *self.selected_language.write() = id; } } -pub fn use_i18(cx: &ScopeState) -> UseI18 { - let selected_language = use_shared_state::(cx).unwrap(); - let data = use_shared_state::(cx).unwrap(); +pub fn use_i18() -> UseI18 { + use_hook(|| { + let selected_language = consume_context::>(); + let data = consume_context::>(); - UseI18 { - selected_language, - data, - } + UseI18 { + selected_language, + data, + } + }) } diff --git a/std/src/i18n/use_init_i18n.rs b/std/src/i18n/use_init_i18n.rs index f4054c7..49b320e 100644 --- a/std/src/i18n/use_init_i18n.rs +++ b/std/src/i18n/use_init_i18n.rs @@ -9,14 +9,16 @@ pub struct UseInitI18Data { } pub fn use_init_i18n( - cx: &ScopeState, selected_language: LanguageIdentifier, fallback_language: LanguageIdentifier, languages: impl FnOnce() -> Vec, ) { - use_shared_state_provider(cx, || selected_language); - use_shared_state_provider(cx, || UseInitI18Data { + let selected_language = use_signal(|| selected_language); + let init_i18_data = use_signal(|| UseInitI18Data { languages: languages(), fallback_language, - }) + }); + + provide_context(selected_language); + provide_context(init_i18_data); } diff --git a/std/src/utils/channel/use_channel.rs b/std/src/utils/channel/use_channel.rs index 6130dc4..6b8677b 100644 --- a/std/src/utils/channel/use_channel.rs +++ b/std/src/utils/channel/use_channel.rs @@ -1,13 +1,13 @@ use async_broadcast::{broadcast, InactiveReceiver, Receiver, SendError, Sender, TrySendError}; -use dioxus::prelude::ScopeState; +use dioxus::prelude::*; use uuid::Uuid; /// Send and listen for messages between multiple components. -#[derive(Debug, Clone)] -pub struct UseChannel { +#[derive(Clone, Copy)] +pub struct UseChannel { id: Uuid, - sender: Sender, - inactive_receiver: InactiveReceiver, + sender: Signal>, + inactive_receiver: Signal>, } impl PartialEq for UseChannel { @@ -16,36 +16,33 @@ impl PartialEq for UseChannel { } } -impl UseChannel { +impl UseChannel { /// Tries to send a message to all listeners of the channel. pub fn try_send(&self, msg: impl Into) -> Result<(), TrySendError> { - self.sender.try_broadcast(msg.into()).map(|_| ()) + self.sender.peek().try_broadcast(msg.into()).map(|_| ()) } /// Sends a message to all listeners of the channel. pub async fn send(&self, msg: impl Into) -> Result<(), SendError> { - self.sender.broadcast(msg.into()).await.map(|_| ()) + self.sender.peek().broadcast(msg.into()).await.map(|_| ()) } /// Create a receiver for the channel. /// You probably want to use [`super::use_listen_channel()`]. pub fn receiver(&mut self) -> Receiver { - self.inactive_receiver.clone().activate() + self.inactive_receiver.peek().clone().activate() } } /// Send and listen for messages between multiple components. -pub fn use_channel( - cx: &ScopeState, - size: usize, -) -> &UseChannel { - cx.use_hook(|| { +pub fn use_channel(size: usize) -> UseChannel { + use_hook(|| { let id = Uuid::new_v4(); let (sender, receiver) = broadcast::(size); UseChannel { id, - sender, - inactive_receiver: receiver.deactivate(), + sender: Signal::new(sender), + inactive_receiver: Signal::new(receiver.deactivate()), } }) } diff --git a/std/src/utils/channel/use_listen_channel.rs b/std/src/utils/channel/use_listen_channel.rs index 4e2dec7..77e31f0 100644 --- a/std/src/utils/channel/use_listen_channel.rs +++ b/std/src/utils/channel/use_listen_channel.rs @@ -1,7 +1,7 @@ -use std::future::Future; +use std::{future::Future, rc::Rc}; use async_broadcast::RecvError; -use dioxus::prelude::{use_effect, ScopeState}; +use dioxus::prelude::*; use super::UseChannel; @@ -9,22 +9,24 @@ pub type UseListenChannelError = RecvError; /// Create a messages listener for the given channel. pub fn use_listen_channel( - cx: &ScopeState, channel: &UseChannel, action: impl Fn(Result) -> Handler + 'static, ) where Handler: Future + 'static, { - use_effect(cx, (channel,), move |(mut channel,)| async move { - let mut receiver = channel.receiver(); - - loop { - let message = receiver.recv().await; - let message_err = message.clone().err(); - action(message).await; - if message_err == Some(UseListenChannelError::Closed) { - break; + let action = use_hook(|| Rc::new(action)); + use_memo(use_reactive(channel, move |mut channel| { + to_owned![action]; + spawn(async move { + let mut receiver = channel.receiver(); + loop { + let message = receiver.recv().await; + let message_err = message.clone().err(); + action(message).await; + if message_err == Some(UseListenChannelError::Closed) { + break; + } } - } - }); + }) + })); } diff --git a/std/src/utils/mod.rs b/std/src/utils/mod.rs index 68fb600..ff02972 100644 --- a/std/src/utils/mod.rs +++ b/std/src/utils/mod.rs @@ -1,2 +1 @@ pub mod channel; -pub mod rw; diff --git a/std/src/utils/rw/mod.rs b/std/src/utils/rw/mod.rs deleted file mode 100644 index 2e0b8a6..0000000 --- a/std/src/utils/rw/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod use_rw; - -pub use use_rw::*; diff --git a/std/src/utils/rw/use_rw.rs b/std/src/utils/rw/use_rw.rs deleted file mode 100644 index ec0d8e1..0000000 --- a/std/src/utils/rw/use_rw.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! Essentially the use_ref hook except Send + Sync using Arc and RwLock. -use std::sync::{Arc, RwLock, RwLockReadGuard}; - -use dioxus::prelude::ScopeState; - -pub fn use_rw( - cx: &ScopeState, - init_rw: impl FnOnce() -> T, -) -> &mut UseRw { - let hook = cx.use_hook(|| UseRw { - update: cx.schedule_update(), - value: Arc::new(RwLock::new(init_rw())), - }); - - hook -} - -pub struct UseRw { - update: Arc, - value: Arc>, - //dirty: Arc>, -} - -impl Clone for UseRw { - fn clone(&self) -> Self { - Self { - update: self.update.clone(), - value: self.value.clone(), - } - } -} - -impl UseRw { - pub fn read(&self) -> Result, UseRwError> { - self.value.read().map_err(|_| UseRwError::Poisoned) - } - - pub fn write(&self, new_value: T) -> Result<(), UseRwError> { - let mut lock = self.value.write().map_err(|_| UseRwError::Poisoned)?; - *lock = new_value; - self.needs_update(); - Ok(()) - } - - pub fn needs_update(&self) { - (self.update)() - } -} - -#[derive(Debug)] -pub enum UseRwError { - Poisoned, -}