diff --git a/packages/desktop/src/app.rs b/packages/desktop/src/app.rs index 6d0cd5b08..a918118b2 100644 --- a/packages/desktop/src/app.rs +++ b/packages/desktop/src/app.rs @@ -12,7 +12,7 @@ use crate::{ use crossbeam_channel::Receiver; use dioxus_core::{Component, ElementId, VirtualDom}; use dioxus_html::{ - native_bind::NativeFileEngine, FileEngine, FormData, HasFormData, HtmlEvent, MountedData, + native_bind::NativeFileEngine, FileEngine, HasFormData, HtmlEvent, MountedData, PlatformEventData, SerializedHtmlEventConverter, }; use std::{ @@ -35,22 +35,24 @@ pub(crate) struct App

{ pub(crate) cfg: Cell>, // Stuff we need mutable access to + pub(crate) root: Component

, pub(crate) control_flow: ControlFlow, pub(crate) is_visible_before_start: bool, - pub(crate) root: Component

, - pub(crate) webviews: HashMap, pub(crate) window_behavior: WindowCloseBehaviour, + pub(crate) webviews: HashMap, - pub(crate) shared: SharedContext, + /// This single blob of state is shared between all the windows so they have access to the runtime state + /// + /// This includes stuff like the event handlers, shortcuts, etc as well as ways to modify *other* windows + pub(crate) shared: Rc, } /// A bundle of state shared between all the windows, providing a way for us to communicate with running webview. /// /// Todo: everything in this struct is wrapped in Rc<>, but we really only need the one top-level refcell -#[derive(Clone)] pub struct SharedContext { pub(crate) event_handlers: WindowEventHandlers, - pub(crate) pending_webviews: Rc>>, + pub(crate) pending_webviews: RefCell>, pub(crate) shortcut_manager: ShortcutRegistry, pub(crate) global_hotkey_channel: Receiver, pub(crate) proxy: EventLoopProxy, @@ -69,14 +71,14 @@ impl App

{ control_flow: ControlFlow::Wait, props: Cell::new(Some(props)), cfg: Cell::new(Some(cfg)), - shared: SharedContext { + shared: Rc::new(SharedContext { event_handlers: WindowEventHandlers::default(), pending_webviews: Default::default(), shortcut_manager: ShortcutRegistry::new(), global_hotkey_channel: GlobalHotKeyEvent::receiver().clone(), proxy: event_loop.create_proxy(), target: event_loop.clone(), - }, + }), }; // Copy over any assets we find diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index b02eca60e..d0af4cd80 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -54,7 +54,7 @@ pub struct DesktopService { /// The tao window itself pub window: Window, - pub(crate) shared: SharedContext, + pub(crate) shared: Rc, /// The receiver for queries about the current window pub(super) query: QueryEngine, @@ -81,7 +81,7 @@ impl DesktopService { pub(crate) fn new( window: Window, webview: WebView, - shared: SharedContext, + shared: Rc, edit_queue: EditQueue, asset_handlers: AssetHandlerRegistry, ) -> Self { diff --git a/packages/desktop/src/events.rs b/packages/desktop/src/events.rs index 941ab2938..ac5a3df0d 100644 --- a/packages/desktop/src/events.rs +++ b/packages/desktop/src/events.rs @@ -1,9 +1,7 @@ //! Convert a serialized event to an event trigger -use dioxus_html::*; -use serde::{Deserialize, Serialize}; - use crate::element::DesktopElement; +use dioxus_html::*; pub(crate) struct SerializedHtmlEventConverter; diff --git a/packages/desktop/src/protocol.rs b/packages/desktop/src/protocol.rs index a721a3cfc..a62851128 100644 --- a/packages/desktop/src/protocol.rs +++ b/packages/desktop/src/protocol.rs @@ -37,6 +37,7 @@ pub(super) async fn desktop_handler( } // If the user provided a custom asset handler, then call it and return the response if the request was handled. + // todo(jon): I dont want this function to be async - we can probably just use a drop handler on the responder if let Some(response) = asset_handlers.try_handlers(&request).await { return responder.respond(response); } @@ -50,9 +51,7 @@ pub(super) async fn desktop_handler( fn serve_from_fs(request: AssetRequest) -> Result { // If the path is relative, we'll try to serve it from the assets directory. - let mut asset = get_asset_root() - .unwrap_or_else(|| Path::new(".").to_path_buf()) - .join(&request.path); + let mut asset = get_asset_root_or_default().join(&request.path); // If we can't find it, make it absolute and try again if !asset.exists() { @@ -87,7 +86,7 @@ fn build_index_file( custom_head: Option, root_name: &str, headless: bool, -) -> std::result::Result>, wry::http::Error> { +) -> std::result::Result>, wry::http::Error> { // Load a custom index file if provided let mut index = custom_index.unwrap_or_else(|| DEFAULT_INDEX.to_string()); @@ -97,7 +96,9 @@ fn build_index_file( index.insert_str(index.find("").expect("Head element to exist"), &head); } - // Inject our module loader + // Inject our module loader by looking for a body tag + // A failure mode here, obviously, is if the user provided a custom index without a body tag + // Might want to document this index.insert_str( index.find("").expect("Body element to exist"), &module_loader(root_name, headless), @@ -106,7 +107,7 @@ fn build_index_file( Response::builder() .header("Content-Type", "text/html") .header("Access-Control-Allow-Origin", "*") - .body(Cow::from(index.into_bytes())) + .body(index.into_bytes().into()) } /// Construct the inline script that boots up the page and bridges the webview with rust code. @@ -135,6 +136,14 @@ fn module_loader(root_id: &str, headless: bool) -> String { ) } +//// Get the assset directory, following tauri/cargo-bundles directory discovery approach +//// +//// Defaults to the current directory if no asset directory is found, which is useful for development when the app +//// isn't bundled. +fn get_asset_root_or_default() -> PathBuf { + get_asset_root().unwrap_or_else(|| Path::new(".").to_path_buf()) +} + /// Get the asset directory, following tauri/cargo-bundles directory discovery approach /// /// Currently supports: @@ -144,11 +153,6 @@ fn module_loader(root_id: &str, headless: bool) -> String { /// - [ ] Linux (deb) /// - [ ] iOS /// - [ ] Android -#[allow(unreachable_code)] -pub(crate) fn get_asset_root_or_default() -> PathBuf { - get_asset_root().unwrap_or_else(|| Path::new(".").to_path_buf()) -} - #[allow(unreachable_code)] fn get_asset_root() -> Option { // If running under cargo, there's no bundle! diff --git a/packages/desktop/src/shortcut.rs b/packages/desktop/src/shortcut.rs index f67d21a4d..5173483ed 100644 --- a/packages/desktop/src/shortcut.rs +++ b/packages/desktop/src/shortcut.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, collections::HashMap, rc::Rc, str::FromStr}; +use std::{cell::RefCell, collections::HashMap, str::FromStr}; use dioxus_html::input_data::keyboard_types::Modifiers; use slab::Slab; @@ -23,14 +23,11 @@ pub use global_hotkey::{ #[cfg(any(target_os = "ios", target_os = "android"))] pub use crate::mobile_shortcut::*; -#[derive(Clone)] pub(crate) struct ShortcutRegistry { - manager: Rc, - shortcuts: ShortcutMap, + manager: GlobalHotKeyManager, + shortcuts: RefCell>, } -type ShortcutMap = Rc>>; - struct Shortcut { #[allow(unused)] shortcut: HotKey, @@ -54,8 +51,8 @@ impl Shortcut { impl ShortcutRegistry { pub fn new() -> Self { Self { - manager: Rc::new(GlobalHotKeyManager::new().unwrap()), - shortcuts: Rc::new(RefCell::new(HashMap::new())), + manager: GlobalHotKeyManager::new().unwrap(), + shortcuts: RefCell::new(HashMap::new()), } } diff --git a/packages/desktop/src/webview.rs b/packages/desktop/src/webview.rs index 286109e13..1b1e3b041 100644 --- a/packages/desktop/src/webview.rs +++ b/packages/desktop/src/webview.rs @@ -24,7 +24,7 @@ pub struct WebviewInstance { } impl WebviewInstance { - pub fn new(mut cfg: Config, dom: VirtualDom, shared: SharedContext) -> WebviewInstance { + pub fn new(mut cfg: Config, dom: VirtualDom, shared: Rc) -> WebviewInstance { let window = cfg.window.clone().build(&shared.target).unwrap(); // TODO: allow users to specify their own menubars, again :/