Merge branch 'master' into update-crossterm-rink
This commit is contained in:
351 files changed
+26767
-1752
No files matched your search
@@ -13,21 +13,21 @@ license = "MIT/Apache-2.0"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus = { path = "../dioxus", version = "^0.3.0" }
|
||||
dioxus-core = { path = "../core", version = "^0.3.0", features = ["serialize"] }
|
||||
dioxus-html = { path = "../html", version = "^0.3.0" }
|
||||
dioxus-native-core = { path = "../native-core", version = "^0.2.0", features = ["dioxus"] }
|
||||
dioxus-native-core-macro = { path = "../native-core-macro", version = "^0.3.0" }
|
||||
dioxus-hot-reload = { path = "../hot-reload", optional = true }
|
||||
rink = { path = "../rink" }
|
||||
dioxus = { workspace = true }
|
||||
dioxus-core = { workspace = true, features = ["serialize"] }
|
||||
dioxus-html = { workspace = true }
|
||||
dioxus-native-core = { workspace = true, features = ["dioxus"] }
|
||||
dioxus-native-core-macro = { workspace = true }
|
||||
dioxus-hot-reload = { workspace = true, optional = true }
|
||||
rink = { workspace = true }
|
||||
|
||||
crossterm = "0.26.0"
|
||||
tokio = { version = "1.15.0", features = ["full"] }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
futures = "0.3.19"
|
||||
taffy = "0.2.1"
|
||||
taffy = "0.3.12"
|
||||
|
||||
[dev-dependencies]
|
||||
dioxus = { path = "../dioxus" }
|
||||
dioxus = { workspace = true }
|
||||
tokio = { version = "1" }
|
||||
criterion = "0.3.5"
|
||||
|
||||
|
||||
File renamed without changes.
@@ -1,67 +0,0 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_tui::Config;
|
||||
|
||||
fn main() {
|
||||
dioxus_tui::launch_cfg(app, Config::default());
|
||||
}
|
||||
|
||||
#[derive(Props, PartialEq)]
|
||||
struct QuadrentProps {
|
||||
color: String,
|
||||
text: String,
|
||||
}
|
||||
|
||||
fn Quadrant(cx: Scope<QuadrentProps>) -> Element {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
border_width: "1px",
|
||||
width: "50%",
|
||||
height: "100%",
|
||||
background_color: "{cx.props.color}",
|
||||
justify_content: "center",
|
||||
align_items: "center",
|
||||
|
||||
"{cx.props.text}"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
flex_direction: "column",
|
||||
|
||||
div {
|
||||
width: "100%",
|
||||
height: "50%",
|
||||
flex_direction: "row",
|
||||
Quadrant{
|
||||
color: "red".to_string(),
|
||||
text: "[A]".to_string()
|
||||
},
|
||||
Quadrant{
|
||||
color: "black".to_string(),
|
||||
text: "[B]".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
width: "100%",
|
||||
height: "50%",
|
||||
flex_direction: "row",
|
||||
Quadrant{
|
||||
color: "green".to_string(),
|
||||
text: "[C]".to_string()
|
||||
},
|
||||
Quadrant{
|
||||
color: "blue".to_string(),
|
||||
text: "[D]".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
File renamed without changes.
@@ -1,7 +1,31 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_tui::Config;
|
||||
|
||||
fn main() {
|
||||
dioxus_tui::launch(app);
|
||||
dioxus_tui::launch_cfg(app, Config::default());
|
||||
}
|
||||
|
||||
#[derive(Props, PartialEq)]
|
||||
struct QuadrentProps {
|
||||
color: String,
|
||||
text: String,
|
||||
}
|
||||
|
||||
fn Quadrant(cx: Scope<QuadrentProps>) -> Element {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
border_width: "1px",
|
||||
width: "50%",
|
||||
height: "100%",
|
||||
background_color: "{cx.props.color}",
|
||||
justify_content: "center",
|
||||
align_items: "center",
|
||||
|
||||
"{cx.props.text}"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
@@ -15,22 +39,13 @@ fn app(cx: Scope) -> Element {
|
||||
width: "100%",
|
||||
height: "50%",
|
||||
flex_direction: "row",
|
||||
div {
|
||||
border_width: "1px",
|
||||
width: "50%",
|
||||
height: "100%",
|
||||
background_color: "red",
|
||||
justify_content: "center",
|
||||
align_items: "center",
|
||||
"[A]"
|
||||
}
|
||||
div {
|
||||
width: "50%",
|
||||
height: "100%",
|
||||
background_color: "black",
|
||||
justify_content: "center",
|
||||
align_items: "center",
|
||||
"[B]"
|
||||
Quadrant{
|
||||
color: "red".to_string(),
|
||||
text: "[A]".to_string()
|
||||
},
|
||||
Quadrant{
|
||||
color: "black".to_string(),
|
||||
text: "[B]".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,21 +53,13 @@ fn app(cx: Scope) -> Element {
|
||||
width: "100%",
|
||||
height: "50%",
|
||||
flex_direction: "row",
|
||||
div {
|
||||
width: "50%",
|
||||
height: "100%",
|
||||
background_color: "green",
|
||||
justify_content: "center",
|
||||
align_items: "center",
|
||||
"[C]"
|
||||
}
|
||||
div {
|
||||
width: "50%",
|
||||
height: "100%",
|
||||
background_color: "blue",
|
||||
justify_content: "center",
|
||||
align_items: "center",
|
||||
"[D]"
|
||||
Quadrant{
|
||||
color: "green".to_string(),
|
||||
text: "[C]".to_string()
|
||||
},
|
||||
Quadrant{
|
||||
color: "blue".to_string(),
|
||||
text: "[D]".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,99 @@
|
||||
use std::{
|
||||
any::Any,
|
||||
fmt::{Display, Formatter},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use dioxus_core::{ElementId, Mutations, VirtualDom};
|
||||
use dioxus_html::{
|
||||
geometry::euclid::{Point2D, Rect, Size2D},
|
||||
MountedData, MountedError, RenderedElementBacking,
|
||||
};
|
||||
|
||||
use dioxus_native_core::NodeId;
|
||||
use rink::query::{ElementRef, Query};
|
||||
|
||||
pub(crate) fn find_mount_events(mutations: &Mutations) -> Vec<ElementId> {
|
||||
let mut mount_events = Vec::new();
|
||||
for mutation in &mutations.edits {
|
||||
if let dioxus_core::Mutation::NewEventListener {
|
||||
name: "mounted",
|
||||
id,
|
||||
} = mutation
|
||||
{
|
||||
mount_events.push(*id);
|
||||
}
|
||||
}
|
||||
mount_events
|
||||
}
|
||||
|
||||
// We need to queue the mounted events to give rink time to rendere and resolve the layout of elements after they are created
|
||||
pub(crate) fn create_mounted_events(
|
||||
vdom: &VirtualDom,
|
||||
events: &mut Vec<(ElementId, &'static str, Rc<dyn Any>, bool)>,
|
||||
mount_events: impl Iterator<Item = (ElementId, NodeId)>,
|
||||
) {
|
||||
let query: Query = vdom
|
||||
.base_scope()
|
||||
.consume_context()
|
||||
.expect("Query should be in context");
|
||||
for (id, node_id) in mount_events {
|
||||
let element = TuiElement {
|
||||
query: query.clone(),
|
||||
id: node_id,
|
||||
};
|
||||
events.push((id, "mounted", Rc::new(MountedData::new(element)), false));
|
||||
}
|
||||
}
|
||||
|
||||
struct TuiElement {
|
||||
query: Query,
|
||||
id: NodeId,
|
||||
}
|
||||
|
||||
impl TuiElement {
|
||||
pub(crate) fn element(&self) -> ElementRef {
|
||||
self.query.get(self.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderedElementBacking for TuiElement {
|
||||
fn get_client_rect(
|
||||
&self,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn futures::Future<
|
||||
Output = dioxus_html::MountedResult<dioxus_html::geometry::euclid::Rect<f64, f64>>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
let layout = self.element().layout();
|
||||
Box::pin(async move {
|
||||
match layout {
|
||||
Some(layout) => {
|
||||
let x = layout.location.x as f64;
|
||||
let y = layout.location.y as f64;
|
||||
let width = layout.size.width as f64;
|
||||
let height = layout.size.height as f64;
|
||||
Ok(Rect::new(Point2D::new(x, y), Size2D::new(width, height)))
|
||||
}
|
||||
None => Err(MountedError::OperationFailed(Box::new(TuiElementNotFound))),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn get_raw_element(&self) -> dioxus_html::MountedResult<&dyn std::any::Any> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TuiElementNotFound;
|
||||
|
||||
impl Display for TuiElementNotFound {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "TUI element not found")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for TuiElementNotFound {}
|
||||
@@ -1,7 +1,9 @@
|
||||
mod element;
|
||||
pub mod prelude;
|
||||
pub mod widgets;
|
||||
|
||||
use std::{
|
||||
any::Any,
|
||||
ops::Deref,
|
||||
rc::Rc,
|
||||
sync::{Arc, RwLock},
|
||||
@@ -12,6 +14,7 @@ use dioxus_html::EventData;
|
||||
use dioxus_native_core::dioxus::{DioxusState, NodeImmutableDioxusExt};
|
||||
use dioxus_native_core::prelude::*;
|
||||
|
||||
use element::{create_mounted_events, find_mount_events};
|
||||
pub use rink::{query::Query, Config, RenderingMode, Size, TuiContext};
|
||||
use rink::{render, Driver};
|
||||
|
||||
@@ -37,14 +40,32 @@ pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props
|
||||
mapping: dioxus_state.clone(),
|
||||
});
|
||||
let muts = vdom.rebuild();
|
||||
let mut rdom = rdom.write().unwrap();
|
||||
dioxus_state
|
||||
.write()
|
||||
.unwrap()
|
||||
.apply_mutations(&mut rdom, muts);
|
||||
|
||||
let mut queued_events = Vec::new();
|
||||
|
||||
{
|
||||
let mut rdom = rdom.write().unwrap();
|
||||
let mut dioxus_state = dioxus_state.write().unwrap();
|
||||
|
||||
// Find any mount events
|
||||
let mounted = dbg!(find_mount_events(&muts));
|
||||
|
||||
dioxus_state.apply_mutations(&mut rdom, muts);
|
||||
|
||||
// Send the mount events
|
||||
create_mounted_events(
|
||||
&vdom,
|
||||
&mut queued_events,
|
||||
mounted
|
||||
.iter()
|
||||
.map(|id| (*dbg!(id), dioxus_state.element_to_node_id(*id))),
|
||||
);
|
||||
}
|
||||
|
||||
DioxusRenderer {
|
||||
vdom,
|
||||
dioxus_state,
|
||||
queued_events,
|
||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||
hot_reload_rx: {
|
||||
let (hot_reload_tx, hot_reload_rx) =
|
||||
@@ -62,6 +83,8 @@ pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props
|
||||
struct DioxusRenderer {
|
||||
vdom: VirtualDom,
|
||||
dioxus_state: Rc<RwLock<DioxusState>>,
|
||||
// Events that are queued up to be sent to the vdom next time the vdom is polled
|
||||
queued_events: Vec<(ElementId, &'static str, Rc<dyn Any>, bool)>,
|
||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||
hot_reload_rx: tokio::sync::mpsc::UnboundedReceiver<dioxus_hot_reload::HotReloadMsg>,
|
||||
}
|
||||
@@ -71,10 +94,23 @@ impl Driver for DioxusRenderer {
|
||||
let muts = self.vdom.render_immediate();
|
||||
{
|
||||
let mut rdom = rdom.write().unwrap();
|
||||
self.dioxus_state
|
||||
.write()
|
||||
.unwrap()
|
||||
.apply_mutations(&mut rdom, muts);
|
||||
|
||||
{
|
||||
// Find any mount events
|
||||
let mounted = find_mount_events(&muts);
|
||||
|
||||
let mut dioxus_state = self.dioxus_state.write().unwrap();
|
||||
dioxus_state.apply_mutations(&mut rdom, muts);
|
||||
|
||||
// Send the mount events
|
||||
create_mounted_events(
|
||||
&self.vdom,
|
||||
&mut self.queued_events,
|
||||
mounted
|
||||
.iter()
|
||||
.map(|id| (*id, dioxus_state.element_to_node_id(*id))),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +130,11 @@ impl Driver for DioxusRenderer {
|
||||
}
|
||||
|
||||
fn poll_async(&mut self) -> std::pin::Pin<Box<dyn futures::Future<Output = ()> + '_>> {
|
||||
// Add any queued events
|
||||
for (id, event, value, bubbles) in self.queued_events.drain(..) {
|
||||
self.vdom.handle_event(event, value, id, bubbles);
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||
return Box::pin(async {
|
||||
let hot_reload_wait = self.hot_reload_rx.recv();
|
||||
|
||||
Reference in new issue
Block a user