Merge branch 'master' into jk/templates-v3
This commit is contained in:
commit
112c954e00
10 files changed
+101
-25
No files matched your search
@@ -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(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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] }
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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!(
|
||||||
|
|||||||
@@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
/// }
|
/// }
|
||||||
|
|||||||
Reference in new issue
Block a user