From 1e99e35572f6cf4f3ae09e1d0290b6e43838518d Mon Sep 17 00:00:00 2001 From: David Craven Date: Tue, 22 Nov 2022 21:35:40 +0100 Subject: [PATCH] Implement push view for ios. (#612) --- packages/desktop/Cargo.toml | 4 ++ packages/desktop/src/controller.rs | 6 +++ packages/desktop/src/desktop_context.rs | 55 +++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index 857568b3d2..ee087e7b10 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -34,6 +34,10 @@ dunce = "1.0.2" interprocess = { version = "1.1.1" } +[target.'cfg(target_os = "ios")'.dependencies] +objc = "0.2.7" +objc_id = "0.1.1" + [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.9.3" diff --git a/packages/desktop/src/controller.rs b/packages/desktop/src/controller.rs index f98ba51842..f59874f852 100644 --- a/packages/desktop/src/controller.rs +++ b/packages/desktop/src/controller.rs @@ -1,6 +1,8 @@ use crate::desktop_context::{DesktopContext, UserWindowEvent}; use dioxus_core::*; +#[cfg(target_os = "ios")] +use objc::runtime::Object; use std::{ collections::HashMap, sync::Arc, @@ -18,6 +20,8 @@ pub(super) struct DesktopController { pub(super) pending_edits: Arc>>, pub(super) quit_app_on_close: bool, pub(super) is_ready: Arc, + #[cfg(target_os = "ios")] + pub(super) views: Vec<*mut Object>, } impl DesktopController { @@ -87,6 +91,8 @@ impl DesktopController { webviews: HashMap::new(), is_ready: Arc::new(AtomicBool::new(false)), quit_app_on_close: true, + #[cfg(target_os = "ios")] + views: vec![], } } diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index bf3a253c58..f4d19bb689 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -2,6 +2,8 @@ use crate::controller::DesktopController; use dioxus_core::ScopeState; use wry::application::event_loop::ControlFlow; use wry::application::event_loop::EventLoopProxy; +#[cfg(target_os = "ios")] +use wry::application::platform::ios::WindowExtIOS; use wry::application::window::Fullscreen as WryFullscreen; use UserWindowEvent::*; @@ -134,6 +136,18 @@ impl DesktopContext { pub fn eval(&self, script: impl std::string::ToString) { let _ = self.proxy.send_event(Eval(script.to_string())); } + + /// Push view + #[cfg(target_os = "ios")] + pub fn push_view(&self, view: objc_id::ShareId) { + let _ = self.proxy.send_event(PushView(view)); + } + + /// Push view + #[cfg(target_os = "ios")] + pub fn pop_view(&self) { + let _ = self.proxy.send_event(PopView); + } } #[derive(Debug)] @@ -164,6 +178,11 @@ pub enum UserWindowEvent { DevTool, Eval(String), + + #[cfg(target_os = "ios")] + PushView(objc_id::ShareId), + #[cfg(target_os = "ios")] + PopView, } pub(super) fn handler( @@ -231,6 +250,32 @@ pub(super) fn handler( log::warn!("Eval script error: {e}"); } } + + #[cfg(target_os = "ios")] + PushView(view) => unsafe { + use objc::runtime::Object; + use objc::*; + assert!(is_main_thread()); + let ui_view = window.ui_view() as *mut Object; + let ui_view_frame: *mut Object = msg_send![ui_view, frame]; + let _: () = msg_send![view, setFrame: ui_view_frame]; + let _: () = msg_send![view, setAutoresizingMask: 31]; + + let ui_view_controller = window.ui_view_controller() as *mut Object; + let _: () = msg_send![ui_view_controller, setView: view]; + desktop.views.push(ui_view); + }, + + #[cfg(target_os = "ios")] + PopView => unsafe { + use objc::runtime::Object; + use objc::*; + assert!(is_main_thread()); + if let Some(view) = desktop.views.pop() { + let ui_view_controller = window.ui_view_controller() as *mut Object; + let _: () = msg_send![ui_view_controller, setView: view]; + } + }, } } @@ -240,3 +285,13 @@ pub fn use_eval(cx: &ScopeState) -> &dyn Fn(S) { cx.use_hook(|| move |script| desktop.eval(script)) } + +#[cfg(target_os = "ios")] +fn is_main_thread() -> bool { + use objc::runtime::{Class, BOOL, NO}; + use objc::*; + + let cls = Class::get("NSThread").unwrap(); + let result: BOOL = unsafe { msg_send![cls, isMainThread] }; + result != NO +}