diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index e2ee6ff3b..d5bc040a7 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -37,9 +37,11 @@ dunce = "1.0.2" slab = { workspace = true } futures-util = { workspace = true } -rfd = "0.11.3" urlencoding = "2.1.2" +[target.'cfg(not(target_os = "ios"))'.dependencies] +rfd = "0.11.3" + [target.'cfg(target_os = "ios")'.dependencies] objc = "0.2.7" objc_id = "0.1.1" diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index 1caa0da64..92d49fd4e 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -52,7 +52,7 @@ pub(crate) type WebviewQueue = Rc>>; /// ``` pub struct DesktopService { /// The wry/tao proxy to the current window - pub webview: WebView, + pub webview: Rc, /// The proxy to the event loop pub proxy: ProxyType, @@ -94,7 +94,7 @@ impl DesktopService { shortcut_manager: ShortcutRegistry, ) -> Self { Self { - webview, + webview: Rc::new(webview), proxy, event_loop, query: Default::default(), diff --git a/packages/desktop/src/file_upload.rs b/packages/desktop/src/file_upload.rs index 1b24ffc55..c7bb113c8 100644 --- a/packages/desktop/src/file_upload.rs +++ b/packages/desktop/src/file_upload.rs @@ -1,9 +1,10 @@ -use std::{path::PathBuf, str::FromStr}; +#![allow(unused)] use serde::Deserialize; +use std::{path::PathBuf, str::FromStr}; #[derive(Debug, Deserialize)] -pub(crate) struct FileDiologRequest { +pub(crate) struct FileDialogRequest { #[serde(default)] accept: Option, multiple: bool, @@ -12,7 +13,13 @@ pub(crate) struct FileDiologRequest { pub bubbles: bool, } -pub(crate) fn get_file_event(request: &FileDiologRequest) -> Vec { +#[cfg(target_os = "ios")] +pub(crate) fn get_file_event(_request: &FileDialogRequest) -> Vec { + vec![] +} + +#[cfg(not(target_os = "ios"))] +pub(crate) fn get_file_event(request: &FileDialogRequest) -> Vec { let mut dialog = rfd::FileDialog::new(); let filters: Vec<_> = request diff --git a/packages/desktop/src/lib.rs b/packages/desktop/src/lib.rs index 779122b9c..fe5c862ed 100644 --- a/packages/desktop/src/lib.rs +++ b/packages/desktop/src/lib.rs @@ -16,6 +16,9 @@ mod shortcut; mod waker; mod webview; +#[cfg(any(target_os = "ios", target_os = "android"))] +mod mobile_shortcut; + use crate::query::QueryResult; pub use cfg::Config; pub use desktop_context::DesktopContext; @@ -120,15 +123,15 @@ pub fn launch_with_props(root: Component

, props: P, cfg: Config) // Intialize hot reloading if it is enabled #[cfg(all(feature = "hot-reload", debug_assertions))] - { + dioxus_hot_reload::connect({ let proxy = proxy.clone(); - dioxus_hot_reload::connect(move |template| { + move |template| { let _ = proxy.send_event(UserWindowEvent( EventData::HotReloadEvent(template), unsafe { WindowId::dummy() }, )); - }); - } + } + }); // We start the tokio runtime *on this thread* // Any future we poll later will use this runtime to spawn tasks and for IO @@ -304,7 +307,7 @@ pub fn launch_with_props(root: Component

, props: P, cfg: Config) EventData::Ipc(msg) if msg.method() == "file_diolog" => { if let Ok(file_diolog) = - serde_json::from_value::(msg.params()) + serde_json::from_value::(msg.params()) { let id = ElementId(file_diolog.target); let event_name = &file_diolog.event; @@ -359,15 +362,12 @@ fn create_new_window( dom.base_scope().provide_context(desktop_context.clone()); - let id = desktop_context.webview.window().id(); - - // We want to poll the virtualdom and the event loop at the same time, so the waker will be connected to both - WebviewHandler { + // We want to poll the virtualdom and the event loop at the same time, so the waker will be connected to both + waker: waker::tao_waker(proxy, desktop_context.webview.window().id()), desktop_context, dom, - waker: waker::tao_waker(proxy, id), - web_context, + _web_context: web_context, } } @@ -375,9 +375,10 @@ struct WebviewHandler { dom: VirtualDom, desktop_context: DesktopContext, waker: Waker, - // This is nessisary because of a bug in wry. Wry assumes the webcontext is alive for the lifetime of the webview. We need to keep the webcontext alive, otherwise the webview will crash - #[allow(dead_code)] - web_context: WebContext, + + // Wry assumes the webcontext is alive for the lifetime of the webview. + // We need to keep the webcontext alive, otherwise the webview will crash + _web_context: WebContext, } /// Poll the virtualdom until it's pending diff --git a/packages/desktop/src/mobile_shortcut.rs b/packages/desktop/src/mobile_shortcut.rs new file mode 100644 index 000000000..29149b55b --- /dev/null +++ b/packages/desktop/src/mobile_shortcut.rs @@ -0,0 +1,55 @@ +#![allow(unused)] + +use super::*; +use wry::application::accelerator::Accelerator; +use wry::application::event_loop::EventLoopWindowTarget; + +pub struct GlobalShortcut(); +pub struct ShortcutManager(); + +impl ShortcutManager { + pub fn new(target: &EventLoopWindowTarget) -> Self { + Self() + } + + pub fn register( + &mut self, + accelerator: Accelerator, + ) -> Result { + Ok(GlobalShortcut()) + } + + pub fn unregister(&mut self, id: ShortcutId) -> Result<(), ShortcutManagerError> { + Ok(()) + } + + pub fn unregister_all(&mut self) -> Result<(), ShortcutManagerError> { + Ok(()) + } +} + +use std::{error, fmt}; + +/// An error whose cause the `ShortcutManager` to fail. +#[non_exhaustive] +#[derive(Debug)] +pub enum ShortcutManagerError { + AcceleratorAlreadyRegistered(Accelerator), + AcceleratorNotRegistered(Accelerator), + InvalidAccelerator(String), +} + +impl error::Error for ShortcutManagerError {} +impl fmt::Display for ShortcutManagerError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match self { + ShortcutManagerError::AcceleratorAlreadyRegistered(e) => { + f.pad(&format!("hotkey already registered: {:?}", e)) + } + ShortcutManagerError::AcceleratorNotRegistered(e) => { + f.pad(&format!("hotkey not registered: {:?}", e)) + } + ShortcutManagerError::InvalidAccelerator(e) => e.fmt(f), + } + } +} diff --git a/packages/desktop/src/shortcut.rs b/packages/desktop/src/shortcut.rs index e3ef9fbad..5f46682e8 100644 --- a/packages/desktop/src/shortcut.rs +++ b/packages/desktop/src/shortcut.rs @@ -6,12 +6,25 @@ use slab::Slab; use wry::application::{ accelerator::{Accelerator, AcceleratorId}, event_loop::EventLoopWindowTarget, - global_shortcut::{GlobalShortcut, ShortcutManager, ShortcutManagerError}, keyboard::{KeyCode, ModifiersState}, }; use crate::{desktop_context::DesktopContext, use_window}; +#[cfg(any( + target_os = "windows", + target_os = "macos", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" +))] +use wry::application::global_shortcut::{GlobalShortcut, ShortcutManager, ShortcutManagerError}; + +#[cfg(any(target_os = "ios", target_os = "android"))] +pub use crate::mobile_shortcut::*; + #[derive(Clone)] pub(crate) struct ShortcutRegistry { manager: Rc>, @@ -21,6 +34,7 @@ pub(crate) struct ShortcutRegistry { type ShortcutMap = Rc>>; struct Shortcut { + #[allow(unused)] shortcut: GlobalShortcut, callbacks: Slab>, } @@ -98,8 +112,9 @@ impl ShortcutRegistry { if let Some(callbacks) = shortcuts.get_mut(&id.id) { callbacks.remove(id.number); if callbacks.is_empty() { - if let Some(shortcut) = shortcuts.remove(&id.id) { - let _ = self.manager.borrow_mut().unregister(shortcut.shortcut); + if let Some(_shortcut) = shortcuts.remove(&id.id) { + #[cfg(not(target_os = "ios"))] + let _ = self.manager.borrow_mut().unregister(_shortcut.shortcut); } } } diff --git a/packages/html/Cargo.toml b/packages/html/Cargo.toml index 5a9a51aa8..95c2252e0 100644 --- a/packages/html/Cargo.toml +++ b/packages/html/Cargo.toml @@ -22,7 +22,6 @@ keyboard-types = "0.6.2" async-trait = "0.1.58" serde-value = "0.7.0" tokio = { workspace = true, features = ["fs", "io-util"], optional = true } -rfd = { version = "0.11.3", optional = true } [dependencies.web-sys] optional = true @@ -53,7 +52,13 @@ serde_json = "1" [features] default = ["serialize"] -serialize = ["serde", "serde_repr", "euclid/serde", "keyboard-types/serde", "dioxus-core/serialize"] +serialize = [ + "serde", + "serde_repr", + "euclid/serde", + "keyboard-types/serde", + "dioxus-core/serialize", +] wasm-bind = ["web-sys", "wasm-bindgen"] -native-bind = ["tokio", "rfd"] +native-bind = ["tokio"] hot-reload-context = ["dioxus-rsx"]