Merge branch 'master' into make-widgets-cross-framework
This commit is contained in:
commit
d99a5f3338
207 files changed
+9886
-1194
No files matched your search
@@ -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,4 +1,7 @@
|
||||
mod element;
|
||||
|
||||
use std::{
|
||||
any::Any,
|
||||
ops::Deref,
|
||||
rc::Rc,
|
||||
sync::{Arc, RwLock},
|
||||
@@ -8,6 +11,7 @@ use dioxus_core::{Component, ElementId, VirtualDom};
|
||||
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};
|
||||
|
||||
@@ -33,14 +37,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) =
|
||||
@@ -58,6 +80,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>,
|
||||
}
|
||||
@@ -67,10 +91,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))),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +128,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