Merge branch 'master' into jk/templates-v3

This commit is contained in:
Jonathan Kelley committed 2022-11-22 16:11:12 -08:00
commit 112c954e00
10 files changed
+101 -25

No files matched your search

+1
View File
@@ -69,6 +69,7 @@ impl Buffer {
BodyNode::Component(component) => self.write_component(component), BodyNode::Component(component) => self.write_component(component),
BodyNode::DynamicText(text) => self.write_text(text), BodyNode::DynamicText(text) => self.write_text(text),
BodyNode::RawExpr(exp) => self.write_raw_expr(exp), BodyNode::RawExpr(exp) => self.write_raw_expr(exp),
_ => Ok(()),
} }
} }
+3
View File
@@ -37,6 +37,9 @@ serde = { version = "1", features = ["derive"], optional = true }
[dev-dependencies] [dev-dependencies]
tokio = { version = "*", features = ["full"] } tokio = { version = "*", features = ["full"] }
[dev-dependencies]
dioxus = { path = "../dioxus" }
[features] [features]
default = [] default = []
serialize = ["serde"] serialize = ["serde"]
+4
View File
@@ -36,6 +36,10 @@ dunce = "1.0.2"
interprocess = { version = "1.1.1" } interprocess = { version = "1.1.1" }
futures-util = "0.3.25" futures-util = "0.3.25"
[target.'cfg(target_os = "ios")'.dependencies]
objc = "0.2.7"
objc_id = "0.1.1"
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9.3" core-foundation = "0.9.3"
+6
View File
@@ -3,6 +3,8 @@ use crate::events::{decode_event, EventMessage};
use dioxus_core::*; use dioxus_core::*;
use futures_channel::mpsc::UnboundedReceiver; use futures_channel::mpsc::UnboundedReceiver;
use futures_util::StreamExt; use futures_util::StreamExt;
#[cfg(target_os = "ios")]
use objc::runtime::Object;
use std::{ use std::{
collections::HashMap, collections::HashMap,
sync::Arc, sync::Arc,
@@ -20,6 +22,8 @@ pub(super) struct DesktopController {
pub(super) pending_edits: Arc<Mutex<Vec<String>>>, pub(super) pending_edits: Arc<Mutex<Vec<String>>>,
pub(super) quit_app_on_close: bool, pub(super) quit_app_on_close: bool,
pub(super) is_ready: Arc<AtomicBool>, pub(super) is_ready: Arc<AtomicBool>,
#[cfg(target_os = "ios")]
pub(super) views: Vec<*mut Object>,
} }
impl DesktopController { impl DesktopController {
@@ -88,6 +92,8 @@ impl DesktopController {
webviews: HashMap::new(), webviews: HashMap::new(),
is_ready: Arc::new(AtomicBool::new(false)), is_ready: Arc::new(AtomicBool::new(false)),
quit_app_on_close: true, quit_app_on_close: true,
#[cfg(target_os = "ios")]
views: vec![],
} }
} }
+55
View File
@@ -4,6 +4,8 @@ use crate::controller::DesktopController;
use dioxus_core::ScopeState; use dioxus_core::ScopeState;
use wry::application::event_loop::ControlFlow; use wry::application::event_loop::ControlFlow;
use wry::application::event_loop::EventLoopProxy; use wry::application::event_loop::EventLoopProxy;
#[cfg(target_os = "ios")]
use wry::application::platform::ios::WindowExtIOS;
use wry::application::window::Fullscreen as WryFullscreen; use wry::application::window::Fullscreen as WryFullscreen;
use UserWindowEvent::*; use UserWindowEvent::*;
@@ -143,6 +145,18 @@ impl DesktopContext {
pub fn eval(&self, script: impl std::string::ToString) { pub fn eval(&self, script: impl std::string::ToString) {
let _ = self.proxy.send_event(Eval(script.to_string())); let _ = self.proxy.send_event(Eval(script.to_string()));
} }
/// Push view
#[cfg(target_os = "ios")]
pub fn push_view(&self, view: objc_id::ShareId<objc::runtime::Object>) {
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)] #[derive(Debug)]
@@ -173,6 +187,11 @@ pub enum UserWindowEvent {
DevTool, DevTool,
Eval(String), Eval(String),
#[cfg(target_os = "ios")]
PushView(objc_id::ShareId<objc::runtime::Object>),
#[cfg(target_os = "ios")]
PopView,
} }
pub(super) fn handler( pub(super) fn handler(
@@ -242,5 +261,41 @@ pub(super) fn handler(
log::warn!("Eval script error: {e}"); 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];
}
},
} }
} }
#[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
}
+18 -15
View File
@@ -75,20 +75,21 @@ fn create() {
CreateElement { root: None, tag: "div", children: 2 }, CreateElement { root: None, tag: "div", children: 2 },
CreateTextNode { root: None, text: "Hello, world!" }, CreateTextNode { root: None, text: "Hello, world!" },
CreateElement { root: None, tag: "div", children: 1 }, CreateElement { root: None, tag: "div", children: 1 },
CreateElement { root: None, tag: "div", children: 1 }, CreateElement { root: None, tag: "div", children: 0 },
CreatePlaceholder { root: None },
// clone template // clone template
CloneNodeChildren { id: Some(1), new_ids: vec![2] }, CloneNodeChildren { id: Some(1), new_ids: vec![2] },
CreateTextNode { root: Some(3), text: "hello" },
CreateTextNode { root: Some(4), text: "world" },
// update template
SetLastNode { id: 2 }, SetLastNode { id: 2 },
FirstChild {}, FirstChild {},
StoreWithId { id: 3 },
FirstChild {}, FirstChild {},
NextSibling {}, NextSibling {},
StoreWithId { id: 4 },
FirstChild {}, FirstChild {},
FirstChild {}, StoreWithId { id: 5 },
ReplaceWith { root: None, nodes: vec![3, 4] }, CreateTextNode { root: Some(6), text: "hello" },
CreateTextNode { root: Some(7), text: "world" },
SetLastNode { id: 5 },
AppendChildren { root: None, children: vec![6, 7] },
AppendChildren { root: Some(0), children: vec![2] } AppendChildren { root: Some(0), children: vec![2] }
] ]
); );
@@ -186,30 +187,32 @@ fn create_components() {
// create template // create template
CreateElement { root: Some(1), tag: "template", children: 3 }, CreateElement { root: Some(1), tag: "template", children: 3 },
CreateElement { root: None, tag: "h1", children: 0 }, CreateElement { root: None, tag: "h1", children: 0 },
CreateElement { root: None, tag: "div", children: 1 }, CreateElement { root: None, tag: "div", children: 0 },
CreatePlaceholder { root: None },
CreateElement { root: None, tag: "p", children: 0 }, CreateElement { root: None, tag: "p", children: 0 },
// clone template // clone template
CloneNodeChildren { id: Some(1), new_ids: vec![2, 3, 4] }, CloneNodeChildren { id: Some(1), new_ids: vec![2, 3, 4] },
// update template // update template
SetLastNode { id: 2 },
NextSibling {},
CreateTextNode { root: Some(5), text: "abc1" }, CreateTextNode { root: Some(5), text: "abc1" },
SetLastNode { id: 3 }, SetLastNode { id: 3 },
FirstChild {}, AppendChildren { root: None, children: vec![5] },
ReplaceWith { root: None, nodes: vec![5] },
// clone template // clone template
CloneNodeChildren { id: Some(1), new_ids: vec![6, 7, 8] }, CloneNodeChildren { id: Some(1), new_ids: vec![6, 7, 8] },
SetLastNode { id: 6 },
NextSibling {},
// update template // update template
CreateTextNode { root: Some(9), text: "abc2" }, CreateTextNode { root: Some(9), text: "abc2" },
SetLastNode { id: 7 }, SetLastNode { id: 7 },
FirstChild {}, AppendChildren { root: None, children: vec![9] },
ReplaceWith { root: None, nodes: vec![9] },
// clone template // clone template
CloneNodeChildren { id: Some(1), new_ids: vec![10, 11, 12] }, CloneNodeChildren { id: Some(1), new_ids: vec![10, 11, 12] },
// update template // update template
SetLastNode { id: 10 },
NextSibling {},
CreateTextNode { root: Some(13), text: "abc3" }, CreateTextNode { root: Some(13), text: "abc3" },
SetLastNode { id: 11 }, SetLastNode { id: 11 },
FirstChild {}, AppendChildren { root: None, children: vec![13] },
ReplaceWith { root: None, nodes: vec![13] },
// add to root // add to root
AppendChildren { root: Some(0), children: vec![2, 3, 4, 6, 7, 8, 10, 11, 12] } AppendChildren { root: Some(0), children: vec![2, 3, 4, 6, 7, 8, 10, 11, 12] }
] ]
+1
View File
@@ -20,6 +20,7 @@ fn new_dom<P: 'static + Send>(app: Component<P>, props: P) -> VirtualDom {
/// This test ensures that if a component aborts early, it is replaced with a placeholder. /// This test ensures that if a component aborts early, it is replaced with a placeholder.
/// In debug, this should also toss a warning. /// In debug, this should also toss a warning.
#[test] #[test]
#[ignore]
fn test_memory_leak() { fn test_memory_leak() {
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
let val = cx.use_hook(|| 0); let val = cx.use_hook(|| 0);
+1
View File
@@ -49,6 +49,7 @@ fn lists_work() {
} }
#[test] #[test]
#[ignore]
fn conditional_rendering() { fn conditional_rendering() {
static App: Component = |cx| { static App: Component = |cx| {
cx.render(rsx!( cx.render(rsx!(
+1 -1
View File
@@ -77,7 +77,7 @@ fermi = { git = "https://github.com/dioxuslabs/dioxus" }
## Running examples ## Running examples
The examples here use Dioxus Desktop to showcase their functionality. To run an example, use The examples here use Dioxus Desktop to showcase their functionality. To run an example, use
``` ```sh
$ cargo run --example fermi $ cargo run --example fermi
``` ```
+11 -9
View File
@@ -46,6 +46,8 @@ pub(crate) fn union_ordered_iter<T: Ord + Debug>(
/// Called when the current node's node properties are modified, a child's [ChildDepState] is modified or a child is removed. /// Called when the current node's node properties are modified, a child's [ChildDepState] is modified or a child is removed.
/// Called at most once per update. /// Called at most once per update.
/// ```rust /// ```rust
/// # use dioxus_native_core::node_ref::NodeView;
/// # use dioxus_native_core::state::ChildDepState;
/// #[derive(Clone, Copy, PartialEq, Default)] /// #[derive(Clone, Copy, PartialEq, Default)]
/// struct Layout { /// struct Layout {
/// width: u32, /// width: u32,
@@ -69,8 +71,8 @@ pub(crate) fn union_ordered_iter<T: Ord + Debug>(
/// width: c1.width + c2.width, /// width: c1.width + c2.width,
/// height: c1.height.max(c2.height) /// height: c1.height.max(c2.height)
/// }).unwrap_or_default(); /// }).unwrap_or_default();
/// let changed = new != self.combined; /// let changed = new != *self;
/// self = new; /// *self = new;
/// changed /// changed
/// } /// }
/// } /// }
@@ -120,12 +122,12 @@ pub trait ChildDepState {
/// ) -> bool{ /// ) -> bool{
/// let old = *self; /// let old = *self;
/// // If the font size was set on the parent, it is passed down to the current element /// // If the font size was set on the parent, it is passed down to the current element
/// if let Some(parent) = parent{ /// if let Some(parent) = parent {
/// *self = parent; /// *self = *parent;
/// } /// }
/// // If the current node overrides the font size, use that size insead. /// // If the current node overrides the font size, use that size insead.
/// for attr in node.attributes() { /// for attr in node.attributes().unwrap() {
/// match attr.name { /// match attr.attribute.name.as_str() {
/// "font-size" => { /// "font-size" => {
/// self.0 = attr.value.as_text().unwrap().parse().unwrap(); /// self.0 = attr.value.as_text().unwrap().parse().unwrap();
/// } /// }
@@ -177,9 +179,9 @@ pub trait ParentDepState {
/// siblings: (), /// siblings: (),
/// ctx: &(), /// ctx: &(),
/// ) -> bool { /// ) -> bool {
/// let old = self; /// let old = self.clone();
/// for attr in node.attributes() { /// for attr in node.attributes().unwrap() {
/// match attr.name { /// match attr.attribute.name.as_str() {
/// "tabindex" => { /// "tabindex" => {
/// self.0 = attr.value.as_text().unwrap().parse().unwrap(); /// self.0 = attr.value.as_text().unwrap().parse().unwrap();
/// } /// }