From 7444796a85646605e56a063bc4c1116d82fe490f Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 4 Jan 2024 18:01:13 -0800 Subject: [PATCH] Simplify asset code a bit --- packages/desktop/src/app.rs | 8 +-- packages/desktop/src/assets.rs | 6 +- packages/desktop/src/desktop_context.rs | 27 +++----- packages/desktop/src/edits.rs | 22 +++--- packages/desktop/src/hooks.rs | 20 +++++- packages/desktop/src/lib.rs | 6 +- packages/desktop/src/shortcut.rs | 89 ++++++++++--------------- packages/desktop/src/webview.rs | 2 +- 8 files changed, 84 insertions(+), 96 deletions(-) diff --git a/packages/desktop/src/app.rs b/packages/desktop/src/app.rs index 931d239cb..4e954d496 100644 --- a/packages/desktop/src/app.rs +++ b/packages/desktop/src/app.rs @@ -11,7 +11,7 @@ use crate::hooks::*; use crate::query::QueryResult; use crate::shortcut::GlobalHotKeyEvent; use crate::shortcut::ShortcutRegistry; -pub use crate::shortcut::{use_global_shortcut, ShortcutHandle, ShortcutId, ShortcutRegistryError}; +pub use crate::shortcut::{ShortcutHandle, ShortcutId, ShortcutRegistryError}; use crate::{ desktop_context::{EventData, UserWindowEvent, WindowEventHandlers}, webview::WebviewHandler, @@ -171,9 +171,9 @@ impl App

{ let handler = crate::webview::create_new_window( cfg, + dom, target, &self.proxy, - dom, &self.queue, &self.event_handlers, self.shortcut_manager.clone(), @@ -212,10 +212,6 @@ impl App

{ } } - pub fn handle_poll_msg(&mut self, id: WindowId) { - self.poll_vdom(id); - } - pub fn handle_query_msg(&mut self, msg: IpcMessage, id: WindowId) { let Ok(result) = serde_json::from_value::(msg.params()) else { return; diff --git a/packages/desktop/src/assets.rs b/packages/desktop/src/assets.rs index f27dcb504..f80c7542a 100644 --- a/packages/desktop/src/assets.rs +++ b/packages/desktop/src/assets.rs @@ -75,8 +75,10 @@ impl F + Send + Sync + 'static> AssetHan } } -type AssetHandlerRegistryInner = - Slab Pin> + Send + Sync + 'static>>; +type UserAssetHandler = + Box Pin> + Send + Sync + 'static>; + +type AssetHandlerRegistryInner = Slab; #[derive(Clone)] pub struct AssetHandlerRegistry(Arc>); diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index 0a2a768e4..240f8ec24 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -1,26 +1,22 @@ +use crate::events::IpcMessage; use crate::query::QueryEngine; use crate::shortcut::{HotKey, ShortcutId, ShortcutRegistry, ShortcutRegistryError}; use crate::AssetHandler; use crate::Config; use crate::{assets::AssetFuture, edits::WebviewQueue}; use crate::{assets::AssetHandlerRegistry, edits::EditQueue}; -use crate::{events::IpcMessage, webview::WebviewHandler}; +use dioxus_core::Mutations; use dioxus_core::VirtualDom; -use dioxus_core::{Mutations, ScopeState}; use dioxus_interpreter_js::binary_protocol::Channel; use rustc_hash::FxHashMap; use slab::Slab; -use std::{ - cell::RefCell, fmt::Debug, fmt::Formatter, rc::Rc, rc::Weak, sync::atomic::AtomicU16, - sync::Arc, sync::Mutex, -}; +use std::{cell::RefCell, fmt::Debug, rc::Rc, rc::Weak, sync::atomic::AtomicU16}; use tao::{ event::Event, event_loop::{EventLoopProxy, EventLoopWindowTarget}, window::{Fullscreen as WryFullscreen, Window, WindowId}, }; - -use wry::{RequestAsyncResponder, WebView}; +use wry::WebView; #[cfg(target_os = "ios")] use tao::platform::ios::WindowExtIOS; @@ -123,16 +119,13 @@ impl DesktopService { /// Send a list of mutations to the webview pub(crate) fn send_edits(&self, edits: Mutations) { - let mut channel = self.channel.borrow_mut(); - let mut templates = self.templates.borrow_mut(); - if let Some(bytes) = crate::edits::apply_edits( + crate::edits::apply_edits( edits, - &mut channel, - &mut templates, + &mut self.channel.borrow_mut(), + &mut self.templates.borrow_mut(), &self.max_template_count, - ) { - self.edit_queue.add_edits(bytes) - } + ) + .map(|bytes| self.edit_queue.add_edits(bytes)); } /// Create a new window using the props and window builder @@ -145,9 +138,9 @@ impl DesktopService { pub fn new_window(&self, dom: VirtualDom, cfg: Config) -> Weak { let window = crate::webview::create_new_window( cfg, + dom, &self.event_loop, &self.proxy, - dom, &self.pending_windows, &self.event_handlers, self.shortcut_manager.clone(), diff --git a/packages/desktop/src/edits.rs b/packages/desktop/src/edits.rs index fa9306156..4eeb48a9b 100644 --- a/packages/desktop/src/edits.rs +++ b/packages/desktop/src/edits.rs @@ -1,12 +1,6 @@ -use crate::query::QueryEngine; -use crate::shortcut::{HotKey, ShortcutId, ShortcutRegistry, ShortcutRegistryError}; -use crate::AssetHandler; -use crate::Config; -use crate::{assets::AssetFuture, DesktopContext}; -use crate::{assets::AssetHandlerRegistry, DesktopService}; -use crate::{events::IpcMessage, webview::WebviewHandler}; -use dioxus_core::{BorrowedAttributeValue, Template, TemplateAttribute, TemplateNode, VirtualDom}; -use dioxus_core::{Mutations, ScopeState}; +use crate::webview::WebviewHandler; +use dioxus_core::Mutations; +use dioxus_core::{BorrowedAttributeValue, Template, TemplateAttribute, TemplateNode}; use dioxus_html::event_bubbles; use dioxus_interpreter_js::binary_protocol::Channel; use rustc_hash::FxHashMap; @@ -18,12 +12,16 @@ use std::{ sync::{atomic::Ordering, Mutex}, }; -use wry::{RequestAsyncResponder, WebView}; +use wry::RequestAsyncResponder; pub(crate) type WebviewQueue = Rc>>; -/// This handles communication between the requests that the webview makes and the interpreter. The interpreter constantly makes long running requests to the webview to get any edits that should be made to the DOM almost like server side events. -/// It will hold onto the requests until the interpreter is ready to handle them and hold onto any pending edits until a new request is made. +/// This handles communication between the requests that the webview makes and the interpreter. The interpreter +/// constantly makes long running requests to the webview to get any edits that should be made to the DOM almost like +/// server side events. +/// +/// It will hold onto the requests until the interpreter is ready to handle them and hold onto any pending edits until +/// a new request is made. #[derive(Default, Clone)] pub(crate) struct EditQueue { queue: Arc>>>, diff --git a/packages/desktop/src/hooks.rs b/packages/desktop/src/hooks.rs index 7ebdf4963..54d114abb 100644 --- a/packages/desktop/src/hooks.rs +++ b/packages/desktop/src/hooks.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use crate::assets::*; +use crate::{assets::*, shortcut::IntoAccelerator, ShortcutHandle, ShortcutRegistryError}; use crate::{desktop_context::UserWindowEvent, window, DesktopContext, WryEventHandler}; use dioxus_core::ScopeState; use tao::{event::Event, event_loop::EventLoopWindowTarget}; @@ -52,3 +52,21 @@ pub fn use_asset_handler( } }) } + +/// Get a closure that executes any JavaScript in the WebView context. +pub fn use_global_shortcut( + cx: &ScopeState, + accelerator: impl IntoAccelerator, + handler: impl FnMut() + 'static, +) -> &Result { + cx.use_hook(move || { + let desktop = window(); + + let id = desktop.create_shortcut(accelerator.accelerator(), handler); + + Ok(ShortcutHandle { + desktop, + shortcut_id: id?, + }) + }) +} diff --git a/packages/desktop/src/lib.rs b/packages/desktop/src/lib.rs index 3e8608200..ca1e851fb 100644 --- a/packages/desktop/src/lib.rs +++ b/packages/desktop/src/lib.rs @@ -37,9 +37,9 @@ pub use cfg::{Config, WindowCloseBehaviour}; pub use desktop_context::{ window, DesktopContext, DesktopService, WryEventHandler, WryEventHandlerId, }; -pub use hooks::{use_asset_handler, use_window, use_wry_event_handler}; +pub use hooks::{use_asset_handler, use_global_shortcut, use_window, use_wry_event_handler}; pub use menubar::build_default_menu_bar; -pub use shortcut::{use_global_shortcut, ShortcutHandle, ShortcutId, ShortcutRegistryError}; +pub use shortcut::{ShortcutHandle, ShortcutId, ShortcutRegistryError}; #[allow(deprecated)] use desktop_context::{EventData, UserWindowEvent}; @@ -139,7 +139,7 @@ pub fn launch_with_props(root: Component

, props: P, cfg: Config) _ => {} }, Event::UserEvent(UserWindowEvent(event, id)) => match event { - EventData::Poll => app.handle_poll_msg(id), + EventData::Poll => app.poll_vdom(id), EventData::NewWindow => app.handle_new_window(), EventData::CloseWindow => app.handle_close_msg(id), EventData::HotReloadEvent(msg) => app.handle_hot_reload_msg(msg), diff --git a/packages/desktop/src/shortcut.rs b/packages/desktop/src/shortcut.rs index 55d49b405..f67d21a4d 100644 --- a/packages/desktop/src/shortcut.rs +++ b/packages/desktop/src/shortcut.rs @@ -1,11 +1,10 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc, str::FromStr}; -use dioxus_core::ScopeState; use dioxus_html::input_data::keyboard_types::Modifiers; use slab::Slab; use tao::keyboard::ModifiersState; -use crate::{desktop_context::DesktopContext, window}; +use crate::desktop_context::DesktopContext; #[cfg(any( target_os = "windows", @@ -26,7 +25,7 @@ pub use crate::mobile_shortcut::*; #[derive(Clone)] pub(crate) struct ShortcutRegistry { - manager: Rc>, + manager: Rc, shortcuts: ShortcutMap, } @@ -55,7 +54,7 @@ impl Shortcut { impl ShortcutRegistry { pub fn new() -> Self { Self { - manager: Rc::new(RefCell::new(GlobalHotKeyManager::new().unwrap())), + manager: Rc::new(GlobalHotKeyManager::new().unwrap()), shortcuts: Rc::new(RefCell::new(HashMap::new())), } } @@ -74,36 +73,36 @@ impl ShortcutRegistry { callback: Box, ) -> Result { let accelerator_id = hotkey.clone().id(); + let mut shortcuts = self.shortcuts.borrow_mut(); - Ok( - if let Some(callbacks) = shortcuts.get_mut(&accelerator_id) { - let id = callbacks.insert(callback); - ShortcutId { - id: accelerator_id, - number: id, - } - } else { - match self.manager.borrow_mut().register(hotkey) { - Ok(_) => { - let mut slab = Slab::new(); - let id = slab.insert(callback); - let shortcut = Shortcut { - shortcut: hotkey, - callbacks: slab, - }; - shortcuts.insert(accelerator_id, shortcut); - ShortcutId { - id: accelerator_id, - number: id, - } - } - Err(HotkeyError::HotKeyParseError(shortcut)) => { - return Err(ShortcutRegistryError::InvalidShortcut(shortcut)) - } - Err(err) => return Err(ShortcutRegistryError::Other(Box::new(err))), - } - }, - ) + + if let Some(callbacks) = shortcuts.get_mut(&accelerator_id) { + return Ok(ShortcutId { + id: accelerator_id, + number: callbacks.insert(callback), + }); + }; + + self.manager.register(hotkey).map_err(|e| match e { + HotkeyError::HotKeyParseError(shortcut) => { + ShortcutRegistryError::InvalidShortcut(shortcut) + } + err => ShortcutRegistryError::Other(Box::new(err)), + })?; + + let mut shortcut = Shortcut { + shortcut: hotkey, + callbacks: Slab::new(), + }; + + let id = shortcut.callbacks.insert(callback); + + shortcuts.insert(accelerator_id, shortcut); + + Ok(ShortcutId { + id: accelerator_id, + number: id, + }) } pub(crate) fn remove_shortcut(&self, id: ShortcutId) { @@ -112,7 +111,7 @@ impl ShortcutRegistry { callbacks.remove(id.number); if callbacks.is_empty() { if let Some(_shortcut) = shortcuts.remove(&id.id) { - let _ = self.manager.borrow_mut().unregister(_shortcut.shortcut); + let _ = self.manager.unregister(_shortcut.shortcut); } } } @@ -121,7 +120,7 @@ impl ShortcutRegistry { pub(crate) fn remove_all(&self) { let mut shortcuts = self.shortcuts.borrow_mut(); let hotkeys: Vec<_> = shortcuts.drain().map(|(_, v)| v.shortcut).collect(); - let _ = self.manager.borrow_mut().unregister_all(&hotkeys); + let _ = self.manager.unregister_all(&hotkeys); } } @@ -144,7 +143,7 @@ pub struct ShortcutId { /// A global shortcut. This will be automatically removed when it is dropped. pub struct ShortcutHandle { - desktop: DesktopContext, + pub(crate) desktop: DesktopContext, /// The id of the shortcut pub shortcut_id: ShortcutId, } @@ -177,24 +176,6 @@ impl IntoAccelerator for &str { } } -/// Get a closure that executes any JavaScript in the WebView context. -pub fn use_global_shortcut( - cx: &ScopeState, - accelerator: impl IntoAccelerator, - handler: impl FnMut() + 'static, -) -> &Result { - cx.use_hook(move || { - let desktop = window(); - - let id = desktop.create_shortcut(accelerator.accelerator(), handler); - - Ok(ShortcutHandle { - desktop, - shortcut_id: id?, - }) - }) -} - impl ShortcutHandle { /// Remove the shortcut. pub fn remove(&self) { diff --git a/packages/desktop/src/webview.rs b/packages/desktop/src/webview.rs index 537b3e241..cd83362b5 100644 --- a/packages/desktop/src/webview.rs +++ b/packages/desktop/src/webview.rs @@ -30,9 +30,9 @@ pub struct WebviewHandler { pub fn create_new_window( mut cfg: Config, + dom: VirtualDom, event_loop: &EventLoopWindowTarget, proxy: &EventLoopProxy, - dom: VirtualDom, queue: &WebviewQueue, event_handlers: &WindowEventHandlers, shortcut_manager: ShortcutRegistry,