Merge pull request #1140 from DioxusLabs/jk/stub-out-ios

Stub out File input and RFD on iOS
This commit is contained in:
Jon Kelley authored and GitHub committed 2023-07-03 10:16:30 -07:00
commit a75223cd88
7 files changed
+111 -26

No files matched your search

+3 -1
View File
@@ -37,9 +37,11 @@ dunce = "1.0.2"
slab = { workspace = true } slab = { workspace = true }
futures-util = { workspace = true } futures-util = { workspace = true }
rfd = "0.11.3"
urlencoding = "2.1.2" urlencoding = "2.1.2"
[target.'cfg(not(target_os = "ios"))'.dependencies]
rfd = "0.11.3"
[target.'cfg(target_os = "ios")'.dependencies] [target.'cfg(target_os = "ios")'.dependencies]
objc = "0.2.7" objc = "0.2.7"
objc_id = "0.1.1" objc_id = "0.1.1"
+2 -2
View File
@@ -52,7 +52,7 @@ pub(crate) type WebviewQueue = Rc<RefCell<Vec<WebviewHandler>>>;
/// ``` /// ```
pub struct DesktopService { pub struct DesktopService {
/// The wry/tao proxy to the current window /// The wry/tao proxy to the current window
pub webview: WebView, pub webview: Rc<WebView>,
/// The proxy to the event loop /// The proxy to the event loop
pub proxy: ProxyType, pub proxy: ProxyType,
@@ -94,7 +94,7 @@ impl DesktopService {
shortcut_manager: ShortcutRegistry, shortcut_manager: ShortcutRegistry,
) -> Self { ) -> Self {
Self { Self {
webview, webview: Rc::new(webview),
proxy, proxy,
event_loop, event_loop,
query: Default::default(), query: Default::default(),
+10 -3
View File
@@ -1,9 +1,10 @@
use std::{path::PathBuf, str::FromStr}; #![allow(unused)]
use serde::Deserialize; use serde::Deserialize;
use std::{path::PathBuf, str::FromStr};
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub(crate) struct FileDiologRequest { pub(crate) struct FileDialogRequest {
#[serde(default)] #[serde(default)]
accept: Option<String>, accept: Option<String>,
multiple: bool, multiple: bool,
@@ -12,7 +13,13 @@ pub(crate) struct FileDiologRequest {
pub bubbles: bool, pub bubbles: bool,
} }
pub(crate) fn get_file_event(request: &FileDiologRequest) -> Vec<PathBuf> { #[cfg(target_os = "ios")]
pub(crate) fn get_file_event(_request: &FileDialogRequest) -> Vec<PathBuf> {
vec![]
}
#[cfg(not(target_os = "ios"))]
pub(crate) fn get_file_event(request: &FileDialogRequest) -> Vec<PathBuf> {
let mut dialog = rfd::FileDialog::new(); let mut dialog = rfd::FileDialog::new();
let filters: Vec<_> = request let filters: Vec<_> = request
+15 -14
View File
@@ -16,6 +16,9 @@ mod shortcut;
mod waker; mod waker;
mod webview; mod webview;
#[cfg(any(target_os = "ios", target_os = "android"))]
mod mobile_shortcut;
use crate::query::QueryResult; use crate::query::QueryResult;
pub use cfg::Config; pub use cfg::Config;
pub use desktop_context::DesktopContext; pub use desktop_context::DesktopContext;
@@ -120,15 +123,15 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
// Intialize hot reloading if it is enabled // Intialize hot reloading if it is enabled
#[cfg(all(feature = "hot-reload", debug_assertions))] #[cfg(all(feature = "hot-reload", debug_assertions))]
{ dioxus_hot_reload::connect({
let proxy = proxy.clone(); let proxy = proxy.clone();
dioxus_hot_reload::connect(move |template| { move |template| {
let _ = proxy.send_event(UserWindowEvent( let _ = proxy.send_event(UserWindowEvent(
EventData::HotReloadEvent(template), EventData::HotReloadEvent(template),
unsafe { WindowId::dummy() }, unsafe { WindowId::dummy() },
)); ));
}); }
} });
// We start the tokio runtime *on this thread* // We start the tokio runtime *on this thread*
// Any future we poll later will use this runtime to spawn tasks and for IO // Any future we poll later will use this runtime to spawn tasks and for IO
@@ -304,7 +307,7 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
EventData::Ipc(msg) if msg.method() == "file_diolog" => { EventData::Ipc(msg) if msg.method() == "file_diolog" => {
if let Ok(file_diolog) = if let Ok(file_diolog) =
serde_json::from_value::<file_upload::FileDiologRequest>(msg.params()) serde_json::from_value::<file_upload::FileDialogRequest>(msg.params())
{ {
let id = ElementId(file_diolog.target); let id = ElementId(file_diolog.target);
let event_name = &file_diolog.event; let event_name = &file_diolog.event;
@@ -359,15 +362,12 @@ fn create_new_window(
dom.base_scope().provide_context(desktop_context.clone()); 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 { 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, desktop_context,
dom, dom,
waker: waker::tao_waker(proxy, id), _web_context: web_context,
web_context,
} }
} }
@@ -375,9 +375,10 @@ struct WebviewHandler {
dom: VirtualDom, dom: VirtualDom,
desktop_context: DesktopContext, desktop_context: DesktopContext,
waker: Waker, 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)] // Wry assumes the webcontext is alive for the lifetime of the webview.
web_context: WebContext, // We need to keep the webcontext alive, otherwise the webview will crash
_web_context: WebContext,
} }
/// Poll the virtualdom until it's pending /// Poll the virtualdom until it's pending
+55
View File
@@ -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<T>(target: &EventLoopWindowTarget<T>) -> Self {
Self()
}
pub fn register(
&mut self,
accelerator: Accelerator,
) -> Result<GlobalShortcut, ShortcutManagerError> {
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),
}
}
}
+18 -3
View File
@@ -6,12 +6,25 @@ use slab::Slab;
use wry::application::{ use wry::application::{
accelerator::{Accelerator, AcceleratorId}, accelerator::{Accelerator, AcceleratorId},
event_loop::EventLoopWindowTarget, event_loop::EventLoopWindowTarget,
global_shortcut::{GlobalShortcut, ShortcutManager, ShortcutManagerError},
keyboard::{KeyCode, ModifiersState}, keyboard::{KeyCode, ModifiersState},
}; };
use crate::{desktop_context::DesktopContext, use_window}; 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)] #[derive(Clone)]
pub(crate) struct ShortcutRegistry { pub(crate) struct ShortcutRegistry {
manager: Rc<RefCell<ShortcutManager>>, manager: Rc<RefCell<ShortcutManager>>,
@@ -21,6 +34,7 @@ pub(crate) struct ShortcutRegistry {
type ShortcutMap = Rc<RefCell<HashMap<AcceleratorId, Shortcut>>>; type ShortcutMap = Rc<RefCell<HashMap<AcceleratorId, Shortcut>>>;
struct Shortcut { struct Shortcut {
#[allow(unused)]
shortcut: GlobalShortcut, shortcut: GlobalShortcut,
callbacks: Slab<Box<dyn FnMut()>>, callbacks: Slab<Box<dyn FnMut()>>,
} }
@@ -98,8 +112,9 @@ impl ShortcutRegistry {
if let Some(callbacks) = shortcuts.get_mut(&id.id) { if let Some(callbacks) = shortcuts.get_mut(&id.id) {
callbacks.remove(id.number); callbacks.remove(id.number);
if callbacks.is_empty() { if callbacks.is_empty() {
if let Some(shortcut) = shortcuts.remove(&id.id) { if let Some(_shortcut) = shortcuts.remove(&id.id) {
let _ = self.manager.borrow_mut().unregister(shortcut.shortcut); #[cfg(not(target_os = "ios"))]
let _ = self.manager.borrow_mut().unregister(_shortcut.shortcut);
} }
} }
} }
+8 -3
View File
@@ -22,7 +22,6 @@ keyboard-types = "0.6.2"
async-trait = "0.1.58" async-trait = "0.1.58"
serde-value = "0.7.0" serde-value = "0.7.0"
tokio = { workspace = true, features = ["fs", "io-util"], optional = true } tokio = { workspace = true, features = ["fs", "io-util"], optional = true }
rfd = { version = "0.11.3", optional = true }
[dependencies.web-sys] [dependencies.web-sys]
optional = true optional = true
@@ -53,7 +52,13 @@ serde_json = "1"
[features] [features]
default = ["serialize"] 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"] wasm-bind = ["web-sys", "wasm-bindgen"]
native-bind = ["tokio", "rfd"] native-bind = ["tokio"]
hot-reload-context = ["dioxus-rsx"] hot-reload-context = ["dioxus-rsx"]