From 8657b474015b28984c999b54f1af338d076fbf60 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 9 Mar 2023 11:05:41 -0600 Subject: [PATCH 1/5] Add function to remove all global shortcuts. --- packages/desktop/src/desktop_context.rs | 5 +++++ packages/desktop/src/shortcut.rs | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index 7db554517..2ed4bbee9 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -271,6 +271,11 @@ impl DesktopContext { self.shortcut_manager.remove_shortcut(id) } + /// Remove all global shortcuts + pub fn remove_all_shortcuts(&self) { + self.shortcut_manager.remove_all() + } + /// Push an objc view to the window #[cfg(target_os = "ios")] pub fn push_view(&self, view: objc_id::ShareId) { diff --git a/packages/desktop/src/shortcut.rs b/packages/desktop/src/shortcut.rs index cf70d307a..5232bdb8b 100644 --- a/packages/desktop/src/shortcut.rs +++ b/packages/desktop/src/shortcut.rs @@ -113,6 +113,18 @@ impl ShortcutRegistry { } } } + + pub(crate) fn remove_all(&self) { + let mut shortcuts = self.shortcuts.borrow_mut(); + shortcuts.clear(); + let _ = self.manager.borrow_mut().unregister_all(); + // prevent CTRL+R from reloading the page which breaks apps + let _ = self.add_shortcut( + Some(ModifiersState::CONTROL), + KeyCode::KeyR, + Box::new(|| {}), + ); + } } #[non_exhaustive] From 9ae5f47d19dc1c9882e42e1f33a81487da927700 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 9 Mar 2023 17:01:41 -0800 Subject: [PATCH 2/5] Allow liveview to spawn pre-injected virtualdoms --- packages/liveview/src/pool.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/liveview/src/pool.rs b/packages/liveview/src/pool.rs index 022641d5c..e02c8195b 100644 --- a/packages/liveview/src/pool.rs +++ b/packages/liveview/src/pool.rs @@ -37,7 +37,16 @@ impl LiveViewPool { app: fn(Scope) -> Element, props: T, ) -> Result<(), LiveViewError> { - match self.pool.spawn_pinned(move || run(app, props, ws)).await { + self.launch_virtualdom(ws, move || VirtualDom::new_with_props(app, props)) + .await + } + + pub async fn launch_virtualdom VirtualDom + Send + 'static>( + &self, + ws: impl LiveViewSocket, + make_app: F, + ) -> Result<(), LiveViewError> { + match self.pool.spawn_pinned(move || run(make_app(), ws)).await { Ok(Ok(_)) => Ok(()), Ok(Err(e)) => Err(e), Err(_) => Err(LiveViewError::SendingFailed), @@ -95,14 +104,7 @@ impl LiveViewSocket for S where /// As long as your framework can provide a Sink and Stream of Strings, you can use this function. /// /// You might need to transform the error types of the web backend into the LiveView error type. -pub async fn run( - app: Component, - props: T, - ws: impl LiveViewSocket, -) -> Result<(), LiveViewError> -where - T: Send + 'static, -{ +pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), LiveViewError> { #[cfg(all(feature = "hot-reload", debug_assertions))] let mut hot_reload_rx = { let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); @@ -112,8 +114,6 @@ where rx }; - let mut vdom = VirtualDom::new_with_props(app, props); - // todo: use an efficient binary packed format for this let edits = serde_json::to_string(&vdom.rebuild()).unwrap(); From 4847789a839d1486fcba18ca849cbac8565c310f Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 12 Mar 2023 14:47:30 -0500 Subject: [PATCH 3/5] fix event bubbling within a single template --- packages/core/src/arena.rs | 6 +++--- packages/core/src/virtual_dom.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/arena.rs b/packages/core/src/arena.rs index 7fbaf0e12..caa863adf 100644 --- a/packages/core/src/arena.rs +++ b/packages/core/src/arena.rs @@ -175,10 +175,10 @@ impl VirtualDom { } impl ElementPath { - pub(crate) fn is_ascendant(&self, big: &&[u8]) -> bool { + pub(crate) fn is_decendant(&self, small: &&[u8]) -> bool { match *self { - ElementPath::Deep(small) => small.len() <= big.len() && small == &big[..small.len()], - ElementPath::Root(r) => big.len() == 1 && big[0] == r as u8, + ElementPath::Deep(big) => small.len() <= big.len() && *small == &big[..small.len()], + ElementPath::Root(r) => small.len() == 1 && small[0] == r as u8, } } } diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index a29671f5d..2269815aa 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -396,7 +396,7 @@ impl VirtualDom { // Remove the "on" prefix if it exists, TODO, we should remove this and settle on one if attr.name.trim_start_matches("on") == name - && target_path.is_ascendant(&this_path) + && target_path.is_decendant(&this_path) { listeners.push(&attr.value); From 2a648226156fcd53038389b6d4842763e39c5cf3 Mon Sep 17 00:00:00 2001 From: marcerhans <121002093+marcerhans@users.noreply.github.com> Date: Mon, 13 Mar 2023 14:12:41 +0100 Subject: [PATCH 4/5] Updated link in docs for use_hook. (#880) --- docs/guide/src/en/interactivity/custom_hooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/src/en/interactivity/custom_hooks.md b/docs/guide/src/en/interactivity/custom_hooks.md index 2f0155cb5..ebf4f94db 100644 --- a/docs/guide/src/en/interactivity/custom_hooks.md +++ b/docs/guide/src/en/interactivity/custom_hooks.md @@ -14,7 +14,7 @@ For example, if many components need to access an `AppSettings` struct, you can ## Custom Hook Logic -You can use [`cx.use_hook`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.Scope.html#method.use_hook) to build your own hooks. In fact, this is what all the standard hooks are built on! +You can use [`cx.use_hook`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.ScopeState.html#method.use_hook) to build your own hooks. In fact, this is what all the standard hooks are built on! `use_hook` accepts a single closure for initializing the hook. It will be only run the first time the component is rendered. The return value of that closure will be used as the value of the hook – Dioxus will take it, and store it for as long as the component is alive. On every render (not just the first one!), you will get a reference to this value. From 226bd3a6e186a225932add48d71609d666024de5 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Mon, 13 Mar 2023 15:50:05 -0500 Subject: [PATCH 5/5] fix panic when waking future on shutdown --- packages/core/src/scheduler/task.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/scheduler/task.rs b/packages/core/src/scheduler/task.rs index 997953f8e..fc668b364 100644 --- a/packages/core/src/scheduler/task.rs +++ b/packages/core/src/scheduler/task.rs @@ -72,9 +72,9 @@ pub struct LocalTaskHandle { impl ArcWake for LocalTaskHandle { fn wake_by_ref(arc_self: &Arc) { - arc_self + // This can fail if the scheduler has been dropped while the application is shutting down + let _ = arc_self .tx - .unbounded_send(SchedulerMsg::TaskNotified(arc_self.id)) - .unwrap(); + .unbounded_send(SchedulerMsg::TaskNotified(arc_self.id)); } }