suspense works in desktop
This commit is contained in:
1 parent
66319cf6e2
commit
642b21f125
12 files changed
+180
-109
No files matched your search
+31
-28
@@ -6,7 +6,11 @@ use dioxus::prelude::*;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
dioxus_desktop::launch(|cx| {
|
||||||
|
cx.render(rsx! {
|
||||||
|
app_root {}
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
|
#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
|
||||||
@@ -14,8 +18,8 @@ struct ListBreeds {
|
|||||||
message: HashMap<String, Vec<String>>,
|
message: HashMap<String, Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
async fn app_root(cx: Scope<'_>) -> Element {
|
||||||
let breed = use_state(&cx, || None);
|
let breed = use_state(&cx, || "deerhound".to_string());
|
||||||
|
|
||||||
let breeds = use_future(&cx, (), |_| async move {
|
let breeds = use_future(&cx, (), |_| async move {
|
||||||
reqwest::get("https://dog.ceo/api/breeds/list/all")
|
reqwest::get("https://dog.ceo/api/breeds/list/all")
|
||||||
@@ -25,32 +29,26 @@ fn app(cx: Scope) -> Element {
|
|||||||
.await
|
.await
|
||||||
});
|
});
|
||||||
|
|
||||||
match breeds.value() {
|
match breeds.await {
|
||||||
Some(Ok(breeds)) => cx.render(rsx! {
|
Ok(breeds) => cx.render(rsx! {
|
||||||
div {
|
div { height: "500px",
|
||||||
h1 { "Select a dog breed!" }
|
h1 { "Select a dog breed!" }
|
||||||
div { display: "flex",
|
div { display: "flex",
|
||||||
ul { flex: "50%",
|
ul { flex: "50%",
|
||||||
breeds.message.keys().map(|cur_breed| rsx!(
|
breeds.message.keys().take(5).map(|cur_breed| rsx!(
|
||||||
li {
|
li {
|
||||||
button {
|
button {
|
||||||
onclick: move |_| breed.set(Some(cur_breed.clone())),
|
onclick: move |_| breed.set(cur_breed.clone()),
|
||||||
"{cur_breed}"
|
"{cur_breed}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
div { flex: "50%",
|
div { flex: "50%", Breed { breed: breed.to_string() } }
|
||||||
match breed.get() {
|
|
||||||
Some(breed) => rsx!( Breed { breed: breed.clone() } ),
|
|
||||||
None => rsx!("No Breed selected"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Some(Err(_e)) => cx.render(rsx! { div { "Error fetching breeds" } }),
|
Err(_e) => cx.render(rsx! { div { "Error fetching breeds" } }),
|
||||||
None => cx.render(rsx! { div { "Loading dogs..." } }),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +58,9 @@ struct DogApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline_props]
|
#[inline_props]
|
||||||
fn Breed(cx: Scope, breed: String) -> Element {
|
async fn Breed(cx: Scope, breed: String) -> Element {
|
||||||
|
println!("Rendering Breed: {}", breed);
|
||||||
|
|
||||||
let fut = use_future(&cx, (breed,), |(breed,)| async move {
|
let fut = use_future(&cx, (breed,), |(breed,)| async move {
|
||||||
reqwest::get(format!("https://dog.ceo/api/breed/{}/images/random", breed))
|
reqwest::get(format!("https://dog.ceo/api/breed/{}/images/random", breed))
|
||||||
.await
|
.await
|
||||||
@@ -69,21 +69,24 @@ fn Breed(cx: Scope, breed: String) -> Element {
|
|||||||
.await
|
.await
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.render(match fut.value() {
|
let resp = fut.await;
|
||||||
Some(Ok(resp)) => rsx! {
|
|
||||||
button {
|
println!("achieved results!");
|
||||||
onclick: move |_| fut.restart(),
|
|
||||||
"Click to fetch another doggo"
|
match resp {
|
||||||
}
|
Ok(resp) => cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
button {
|
||||||
|
onclick: move |_| fut.restart(),
|
||||||
|
"Click to fetch another doggo"
|
||||||
|
}
|
||||||
img {
|
img {
|
||||||
|
src: "{resp.message}",
|
||||||
max_width: "500px",
|
max_width: "500px",
|
||||||
max_height: "500px",
|
max_height: "500px",
|
||||||
src: "{resp.message}",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
Some(Err(_)) => rsx! { div { "loading dogs failed" } },
|
Err(e) => cx.render(rsx! { div { "loading dogs failed" } }),
|
||||||
None => rsx! { div { "loading dogs..." } },
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
use dioxus::prelude::*;
|
||||||
|
use dioxus_desktop::{Config, LogicalSize, WindowBuilder};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
dioxus_desktop::launch(|cx| cx.render(rsx! { async_app {} }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn async_app(cx: Scope<'_>) -> Element {
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
||||||
|
|
||||||
|
cx.render(rsx! {
|
||||||
|
div {
|
||||||
|
"hi!"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ use syn::{
|
|||||||
pub struct InlinePropsBody {
|
pub struct InlinePropsBody {
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
pub vis: syn::Visibility,
|
pub vis: syn::Visibility,
|
||||||
|
pub maybe_async: Option<Token![async]>,
|
||||||
pub fn_token: Token![fn],
|
pub fn_token: Token![fn],
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
pub cx_token: Box<Pat>,
|
pub cx_token: Box<Pat>,
|
||||||
@@ -25,6 +26,7 @@ pub struct InlinePropsBody {
|
|||||||
impl Parse for InlinePropsBody {
|
impl Parse for InlinePropsBody {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
let attrs: Vec<Attribute> = input.call(Attribute::parse_outer)?;
|
let attrs: Vec<Attribute> = input.call(Attribute::parse_outer)?;
|
||||||
|
let maybe_async: Option<Token![async]> = input.parse().ok();
|
||||||
let vis: Visibility = input.parse()?;
|
let vis: Visibility = input.parse()?;
|
||||||
|
|
||||||
let fn_token = input.parse()?;
|
let fn_token = input.parse()?;
|
||||||
@@ -57,6 +59,7 @@ impl Parse for InlinePropsBody {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
vis,
|
vis,
|
||||||
|
maybe_async,
|
||||||
fn_token,
|
fn_token,
|
||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
@@ -84,6 +87,7 @@ impl ToTokens for InlinePropsBody {
|
|||||||
block,
|
block,
|
||||||
cx_token,
|
cx_token,
|
||||||
attrs,
|
attrs,
|
||||||
|
maybe_async,
|
||||||
..
|
..
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
@@ -151,7 +155,7 @@ impl ToTokens for InlinePropsBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#vis fn #ident #fn_generics (#cx_token: Scope<#scope_lifetime #struct_name #generics>) #output
|
#maybe_async #vis fn #ident #fn_generics (#cx_token: Scope<#scope_lifetime #struct_name #generics>) #output
|
||||||
#where_clause
|
#where_clause
|
||||||
{
|
{
|
||||||
let #struct_name { #(#field_names),* } = &cx.props;
|
let #struct_name { #(#field_names),* } = &cx.props;
|
||||||
|
|||||||
+70
-45
@@ -1,11 +1,13 @@
|
|||||||
|
use std::ops::Bound;
|
||||||
|
|
||||||
use crate::factory::RenderReturn;
|
use crate::factory::RenderReturn;
|
||||||
use crate::innerlude::{Mutations, SuspenseContext};
|
use crate::innerlude::{Mutations, SuspenseContext, SuspenseId};
|
||||||
use crate::mutations::Mutation;
|
use crate::mutations::Mutation;
|
||||||
use crate::mutations::Mutation::*;
|
use crate::mutations::Mutation::*;
|
||||||
use crate::nodes::VNode;
|
use crate::nodes::VNode;
|
||||||
use crate::nodes::{DynamicNode, TemplateNode};
|
use crate::nodes::{DynamicNode, TemplateNode};
|
||||||
use crate::virtual_dom::VirtualDom;
|
use crate::virtual_dom::VirtualDom;
|
||||||
use crate::{AttributeValue, ElementId, ScopeId, TemplateAttribute};
|
use crate::{AttributeValue, ScopeId, TemplateAttribute};
|
||||||
|
|
||||||
impl VirtualDom {
|
impl VirtualDom {
|
||||||
pub(crate) fn create_scope<'a>(
|
pub(crate) fn create_scope<'a>(
|
||||||
@@ -50,8 +52,6 @@ impl VirtualDom {
|
|||||||
|
|
||||||
let cur_scope = self.scope_stack.last().copied().unwrap();
|
let cur_scope = self.scope_stack.last().copied().unwrap();
|
||||||
|
|
||||||
println!("creating template: {:#?}", template);
|
|
||||||
|
|
||||||
let mut on_stack = 0;
|
let mut on_stack = 0;
|
||||||
for (root_idx, root) in template.template.roots.iter().enumerate() {
|
for (root_idx, root) in template.template.roots.iter().enumerate() {
|
||||||
on_stack += match root {
|
on_stack += match root {
|
||||||
@@ -64,9 +64,7 @@ impl VirtualDom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TemplateNode::DynamicText(id) | TemplateNode::Dynamic(id) => {
|
TemplateNode::DynamicText(id) | TemplateNode::Dynamic(id) => {
|
||||||
let dynamic_node = &template.dynamic_nodes[*id];
|
match &template.dynamic_nodes[*id] {
|
||||||
|
|
||||||
match dynamic_node {
|
|
||||||
DynamicNode::Fragment { .. } | DynamicNode::Component { .. } => self
|
DynamicNode::Fragment { .. } | DynamicNode::Component { .. } => self
|
||||||
.create_dynamic_node(
|
.create_dynamic_node(
|
||||||
mutations,
|
mutations,
|
||||||
@@ -79,19 +77,16 @@ impl VirtualDom {
|
|||||||
} => {
|
} => {
|
||||||
let id = self.next_element(template);
|
let id = self.next_element(template);
|
||||||
slot.set(id);
|
slot.set(id);
|
||||||
mutations.push(CreateTextNode {
|
mutations.push(CreateTextNode { value, id });
|
||||||
value: value.clone(),
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
DynamicNode::Placeholder(id) => {
|
DynamicNode::Placeholder(slot) => {
|
||||||
let id = self.next_element(template);
|
let id = self.next_element(template);
|
||||||
|
slot.set(id);
|
||||||
mutations.push(CreatePlaceholder { id });
|
mutations.push(CreatePlaceholder { id });
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// self.create_dynamic_node(mutations, template, &template.dynamic_nodes[*id], *id)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -141,31 +136,34 @@ impl VirtualDom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo:
|
|
||||||
//
|
|
||||||
// we walk the roots front to back when creating nodes, bur want to fill in the dynamic nodes
|
|
||||||
// back to front. This is because the indices would shift around because the paths become invalid
|
|
||||||
//
|
|
||||||
// We could easily implement this without the vec by walking the indicies forward
|
|
||||||
let mut queued_changes = vec![];
|
|
||||||
|
|
||||||
// We're on top of a node that has a dynamic child for a descendant
|
// We're on top of a node that has a dynamic child for a descendant
|
||||||
// Skip any node that's a root
|
// Skip any node that's a root
|
||||||
while let Some((idx, path)) =
|
let mut start = None;
|
||||||
dynamic_nodes.next_if(|(_, p)| p.len() > 1 && p[0] == root_idx as u8)
|
let mut end = None;
|
||||||
{
|
|
||||||
let node = &template.dynamic_nodes[idx];
|
while let Some((idx, p)) = dynamic_nodes.next_if(|(_, p)| p[0] == root_idx as u8) {
|
||||||
let m = self.create_dynamic_node(mutations, template, node, idx);
|
if p.len() == 1 {
|
||||||
if m > 0 {
|
continue;
|
||||||
queued_changes.push(ReplacePlaceholder {
|
|
||||||
m,
|
|
||||||
path: &path[1..],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if start.is_none() {
|
||||||
|
start = Some(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
end = Some(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for change in queued_changes.into_iter().rev() {
|
if let (Some(start), Some(end)) = (start, end) {
|
||||||
mutations.push(change);
|
for idx in start..=end {
|
||||||
|
let node = &template.dynamic_nodes[idx];
|
||||||
|
let m = self.create_dynamic_node(mutations, template, node, idx);
|
||||||
|
if m > 0 {
|
||||||
|
mutations.push(ReplacePlaceholder {
|
||||||
|
m,
|
||||||
|
path: &template.template.node_paths[idx][1..],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +238,7 @@ impl VirtualDom {
|
|||||||
idx: usize,
|
idx: usize,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match &node {
|
match &node {
|
||||||
DynamicNode::Text { id, value, inner } => {
|
DynamicNode::Text { id, value, .. } => {
|
||||||
let new_id = self.next_element(template);
|
let new_id = self.next_element(template);
|
||||||
id.set(new_id);
|
id.set(new_id);
|
||||||
mutations.push(HydrateText {
|
mutations.push(HydrateText {
|
||||||
@@ -266,14 +264,32 @@ impl VirtualDom {
|
|||||||
let return_nodes = unsafe { self.run_scope(scope).extend_lifetime_ref() };
|
let return_nodes = unsafe { self.run_scope(scope).extend_lifetime_ref() };
|
||||||
|
|
||||||
match return_nodes {
|
match return_nodes {
|
||||||
RenderReturn::Sync(None) | RenderReturn::Async(_) => {
|
RenderReturn::Sync(None) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderReturn::Async(_) => {
|
||||||
let new_id = self.next_element(template);
|
let new_id = self.next_element(template);
|
||||||
placeholder.set(Some(new_id));
|
placeholder.set(Some(new_id));
|
||||||
self.scopes[scope.0].placeholder.set(Some(new_id));
|
self.scopes[scope.0].placeholder.set(Some(new_id));
|
||||||
|
|
||||||
mutations.push(AssignId {
|
mutations.push(AssignId {
|
||||||
id: new_id,
|
id: new_id,
|
||||||
path: &template.template.node_paths[idx][1..],
|
path: &template.template.node_paths[idx][1..],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let boudary = self.scopes[scope.0]
|
||||||
|
.consume_context::<SuspenseContext>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if boudary.placeholder.get().is_none() {
|
||||||
|
boudary.placeholder.set(Some(new_id));
|
||||||
|
}
|
||||||
|
boudary
|
||||||
|
.waiting_on
|
||||||
|
.borrow_mut()
|
||||||
|
.extend(self.collected_leaves.drain(..));
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,16 +304,6 @@ impl VirtualDom {
|
|||||||
if let Some(boundary) =
|
if let Some(boundary) =
|
||||||
self.scopes[scope.0].has_context::<SuspenseContext>()
|
self.scopes[scope.0].has_context::<SuspenseContext>()
|
||||||
{
|
{
|
||||||
let mut boundary_mut = boundary.borrow_mut();
|
|
||||||
let split_off = mutations.split_off(mutations_to_this_point);
|
|
||||||
|
|
||||||
let split_off = unsafe { std::mem::transmute(split_off) };
|
|
||||||
|
|
||||||
boundary_mut.mutations.edits = split_off;
|
|
||||||
boundary_mut
|
|
||||||
.waiting_on
|
|
||||||
.extend(self.collected_leaves.drain(..));
|
|
||||||
|
|
||||||
// Since this is a boundary, use it as a placeholder
|
// Since this is a boundary, use it as a placeholder
|
||||||
let new_id = self.next_element(template);
|
let new_id = self.next_element(template);
|
||||||
placeholder.set(Some(new_id));
|
placeholder.set(Some(new_id));
|
||||||
@@ -306,6 +312,25 @@ impl VirtualDom {
|
|||||||
id: new_id,
|
id: new_id,
|
||||||
path: &template.template.node_paths[idx][1..],
|
path: &template.template.node_paths[idx][1..],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Now connect everything to the boundary
|
||||||
|
let boundary_mut = boundary;
|
||||||
|
let split_off = mutations.split_off(mutations_to_this_point);
|
||||||
|
let split_off: Vec<Mutation> =
|
||||||
|
unsafe { std::mem::transmute(split_off) };
|
||||||
|
|
||||||
|
if boundary_mut.placeholder.get().is_none() {
|
||||||
|
boundary_mut.placeholder.set(Some(new_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the generated edits, we want to pick off from where we left off.
|
||||||
|
boundary_mut.mutations.borrow_mut().edits.extend(split_off);
|
||||||
|
|
||||||
|
boundary_mut
|
||||||
|
.waiting_on
|
||||||
|
.borrow_mut()
|
||||||
|
.extend(self.collected_leaves.drain(..));
|
||||||
|
|
||||||
created = 0;
|
created = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use super::{waker::RcWake, SchedulerMsg};
|
use super::{waker::RcWake, SchedulerMsg};
|
||||||
|
use crate::ElementId;
|
||||||
use crate::{innerlude::Mutations, Element, ScopeId};
|
use crate::{innerlude::Mutations, Element, ScopeId};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::{
|
use std::{
|
||||||
@@ -10,22 +11,24 @@ use std::{
|
|||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct SuspenseId(pub usize);
|
pub struct SuspenseId(pub usize);
|
||||||
|
|
||||||
pub type SuspenseContext = Rc<RefCell<SuspenseBoundary>>;
|
pub type SuspenseContext = Rc<SuspenseBoundary>;
|
||||||
|
|
||||||
/// Essentially a fiber in React
|
/// Essentially a fiber in React
|
||||||
pub struct SuspenseBoundary {
|
pub struct SuspenseBoundary {
|
||||||
pub id: ScopeId,
|
pub id: ScopeId,
|
||||||
pub waiting_on: HashSet<SuspenseId>,
|
pub waiting_on: RefCell<HashSet<SuspenseId>>,
|
||||||
pub mutations: Mutations<'static>,
|
pub mutations: RefCell<Mutations<'static>>,
|
||||||
|
pub placeholder: Cell<Option<ElementId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SuspenseBoundary {
|
impl SuspenseBoundary {
|
||||||
pub fn new(id: ScopeId) -> Rc<RefCell<Self>> {
|
pub fn new(id: ScopeId) -> Rc<Self> {
|
||||||
Rc::new(RefCell::new(Self {
|
Rc::new(Self {
|
||||||
id,
|
id,
|
||||||
waiting_on: Default::default(),
|
waiting_on: Default::default(),
|
||||||
mutations: Mutations::new(0),
|
mutations: RefCell::new(Mutations::new(0)),
|
||||||
}))
|
placeholder: Cell::new(None),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,14 +53,12 @@ impl VirtualDom {
|
|||||||
// we should attach them to that component and then render its children
|
// we should attach them to that component and then render its children
|
||||||
// continue rendering the tree until we hit yet another suspended component
|
// continue rendering the tree until we hit yet another suspended component
|
||||||
if let Poll::Ready(new_nodes) = as_pinned_mut.poll_unpin(&mut cx) {
|
if let Poll::Ready(new_nodes) = as_pinned_mut.poll_unpin(&mut cx) {
|
||||||
let boundary = &self.scopes[leaf.scope_id.0]
|
let fiber = &self.scopes[leaf.scope_id.0]
|
||||||
.consume_context::<SuspenseContext>()
|
.consume_context::<SuspenseContext>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
println!("ready pool");
|
println!("ready pool");
|
||||||
|
|
||||||
let mut fiber = boundary.borrow_mut();
|
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Existing mutations {:?}, scope {:?}",
|
"Existing mutations {:?}, scope {:?}",
|
||||||
fiber.mutations, fiber.id
|
fiber.mutations, fiber.id
|
||||||
@@ -72,16 +70,33 @@ impl VirtualDom {
|
|||||||
let ret = arena.bump.alloc(RenderReturn::Sync(new_nodes));
|
let ret = arena.bump.alloc(RenderReturn::Sync(new_nodes));
|
||||||
arena.node.set(ret);
|
arena.node.set(ret);
|
||||||
|
|
||||||
|
fiber.waiting_on.borrow_mut().remove(&id);
|
||||||
|
|
||||||
if let RenderReturn::Sync(Some(template)) = ret {
|
if let RenderReturn::Sync(Some(template)) = ret {
|
||||||
let mutations = &mut fiber.mutations;
|
let mutations_ref = &mut fiber.mutations.borrow_mut();
|
||||||
|
let mutations = &mut **mutations_ref;
|
||||||
let template: &VNode = unsafe { std::mem::transmute(template) };
|
let template: &VNode = unsafe { std::mem::transmute(template) };
|
||||||
let mutations: &mut Mutations = unsafe { std::mem::transmute(mutations) };
|
let mutations: &mut Mutations = unsafe { std::mem::transmute(mutations) };
|
||||||
|
|
||||||
|
let place_holder_id = scope.placeholder.get().unwrap();
|
||||||
self.scope_stack.push(scope_id);
|
self.scope_stack.push(scope_id);
|
||||||
self.create(mutations, template);
|
let created = self.create(mutations, template);
|
||||||
self.scope_stack.pop();
|
self.scope_stack.pop();
|
||||||
|
mutations.push(Mutation::ReplaceWith {
|
||||||
|
id: place_holder_id,
|
||||||
|
m: created,
|
||||||
|
});
|
||||||
|
|
||||||
println!("{:#?}", mutations);
|
// for leaf in self.collected_leaves.drain(..) {
|
||||||
|
// fiber.waiting_on.borrow_mut().insert(leaf);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if fiber.waiting_on.borrow().is_empty() {
|
||||||
|
println!("fiber is finished!");
|
||||||
|
self.finished_fibers.push(fiber.id);
|
||||||
|
} else {
|
||||||
|
println!("fiber is not finished {:?}", fiber.waiting_on);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("nodes arent right");
|
println!("nodes arent right");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,8 +268,8 @@ impl VirtualDom {
|
|||||||
!self.scopes[id.0]
|
!self.scopes[id.0]
|
||||||
.consume_context::<SuspenseContext>()
|
.consume_context::<SuspenseContext>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow()
|
|
||||||
.waiting_on
|
.waiting_on
|
||||||
|
.borrow()
|
||||||
.is_empty()
|
.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,8 +469,15 @@ impl VirtualDom {
|
|||||||
for finished_fiber in self.finished_fibers.drain(..) {
|
for finished_fiber in self.finished_fibers.drain(..) {
|
||||||
let scope = &mut self.scopes[finished_fiber.0];
|
let scope = &mut self.scopes[finished_fiber.0];
|
||||||
let context = scope.has_context::<SuspenseContext>().unwrap();
|
let context = scope.has_context::<SuspenseContext>().unwrap();
|
||||||
let mut context = context.borrow_mut();
|
println!("unloading suspense tree {:?}", context.mutations);
|
||||||
mutations.extend(context.mutations.drain(..));
|
|
||||||
|
mutations.extend(context.mutations.borrow_mut().template_mutations.drain(..));
|
||||||
|
mutations.extend(context.mutations.borrow_mut().drain(..));
|
||||||
|
|
||||||
|
mutations.push(Mutation::ReplaceWith {
|
||||||
|
id: context.placeholder.get().unwrap(),
|
||||||
|
m: 1,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next, diff any dirty scopes
|
// Next, diff any dirty scopes
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ impl DesktopController {
|
|||||||
|
|
||||||
let edits = dom.rebuild();
|
let edits = dom.rebuild();
|
||||||
|
|
||||||
println!("got muts: {:#?}", edits);
|
// println!("got muts: {:#?}", edits);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut queue = edit_queue.lock().unwrap();
|
let mut queue = edit_queue.lock().unwrap();
|
||||||
@@ -68,20 +68,15 @@ impl DesktopController {
|
|||||||
|
|
||||||
let muts = dom
|
let muts = dom
|
||||||
.render_with_deadline(tokio::time::sleep(
|
.render_with_deadline(tokio::time::sleep(
|
||||||
tokio::time::Duration::from_millis(100),
|
tokio::time::Duration::from_millis(16),
|
||||||
))
|
))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut queue = edit_queue.lock().unwrap();
|
let mut queue = edit_queue.lock().unwrap();
|
||||||
|
|
||||||
for edit in muts.template_mutations {
|
queue.push(serde_json::to_string(&muts.template_mutations).unwrap());
|
||||||
queue.push(serde_json::to_string(&edit).unwrap());
|
queue.push(serde_json::to_string(&muts.edits).unwrap());
|
||||||
}
|
|
||||||
|
|
||||||
for edit in muts.edits {
|
|
||||||
queue.push(serde_json::to_string(&edit).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
drop(queue);
|
drop(queue);
|
||||||
}
|
}
|
||||||
@@ -118,6 +113,8 @@ impl DesktopController {
|
|||||||
|
|
||||||
let (_id, view) = self.webviews.iter_mut().next().unwrap();
|
let (_id, view) = self.webviews.iter_mut().next().unwrap();
|
||||||
|
|
||||||
|
println!("sending edits {:#?}", new_queue);
|
||||||
|
|
||||||
for edit in new_queue.drain(..) {
|
for edit in new_queue.drain(..) {
|
||||||
view.evaluate_script(&format!("window.interpreter.handleEdits({})", edit))
|
view.evaluate_script(&format!("window.interpreter.handleEdits({})", edit))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -181,12 +181,6 @@ pub fn launch_with_props<P: 'static + Send>(root: Component<P>, props: P, mut cf
|
|||||||
index_file.clone(),
|
index_file.clone(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
// passing edits via the custom protocol is faster than using eval, maybe?
|
|
||||||
.with_custom_protocol(String::from("edits"), move |r| {
|
|
||||||
//
|
|
||||||
// Ok(Response::body())
|
|
||||||
todo!()
|
|
||||||
})
|
|
||||||
.with_file_drop_handler(move |window, evet| {
|
.with_file_drop_handler(move |window, evet| {
|
||||||
file_handler
|
file_handler
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ pub(super) fn desktop_handler(
|
|||||||
custom_head: Option<String>,
|
custom_head: Option<String>,
|
||||||
custom_index: Option<String>,
|
custom_index: Option<String>,
|
||||||
) -> Result<Response<Vec<u8>>> {
|
) -> Result<Response<Vec<u8>>> {
|
||||||
|
println!("loading request: {:?}", request.uri());
|
||||||
|
|
||||||
// Any content that uses the `dioxus://` scheme will be shuttled through this handler as a "special case".
|
// Any content that uses the `dioxus://` scheme will be shuttled through this handler as a "special case".
|
||||||
// For now, we only serve two pieces of content which get included as bytes into the final binary.
|
// For now, we only serve two pieces of content which get included as bytes into the final binary.
|
||||||
let path = request.uri().to_string().replace("dioxus://", "");
|
let path = request.uri().to_string().replace("dioxus://", "");
|
||||||
|
|||||||
@@ -134,8 +134,11 @@ impl<T> UseFuture<T> {
|
|||||||
///
|
///
|
||||||
/// If the future has never completed, the returned value will be `None`.
|
/// If the future has never completed, the returned value will be `None`.
|
||||||
pub fn value(&self) -> Option<&T> {
|
pub fn value(&self) -> Option<&T> {
|
||||||
// self.value.as_ref()
|
self.values
|
||||||
todo!()
|
.borrow_mut()
|
||||||
|
.last()
|
||||||
|
.cloned()
|
||||||
|
.map(|x| unsafe { &*x })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the ID of the future in Dioxus' internal scheduler
|
/// Get the ID of the future in Dioxus' internal scheduler
|
||||||
@@ -181,7 +184,6 @@ impl<'a, T> Future for UseFutureAwait<'a, T> {
|
|||||||
self: std::pin::Pin<&mut Self>,
|
self: std::pin::Pin<&mut Self>,
|
||||||
cx: &mut std::task::Context<'_>,
|
cx: &mut std::task::Context<'_>,
|
||||||
) -> std::task::Poll<Self::Output> {
|
) -> std::task::Poll<Self::Output> {
|
||||||
println!("polling future");
|
|
||||||
match self.hook.values.borrow_mut().last().cloned() {
|
match self.hook.values.borrow_mut().last().cloned() {
|
||||||
Some(value) => std::task::Poll::Ready(unsafe { &*value }),
|
Some(value) => std::task::Poll::Ready(unsafe { &*value }),
|
||||||
None => {
|
None => {
|
||||||
|
|||||||
@@ -167,7 +167,10 @@ export class Interpreter {
|
|||||||
const name = field;
|
const name = field;
|
||||||
const node = this.nodes[root];
|
const node = this.nodes[root];
|
||||||
if (ns === "style") {
|
if (ns === "style") {
|
||||||
// @ts-ignore
|
// ????? why do we need to do this
|
||||||
|
if (node.style === undefined) {
|
||||||
|
node.style = {};
|
||||||
|
}
|
||||||
node.style[name] = value;
|
node.style[name] = value;
|
||||||
} else if (ns != null || ns != undefined) {
|
} else if (ns != null || ns != undefined) {
|
||||||
node.setAttributeNS(ns, name, value);
|
node.setAttributeNS(ns, name, value);
|
||||||
|
|||||||
Reference in new issue
Block a user