mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 14:44:12 +00:00
restore liveview renderer
This commit is contained in:
parent
41d10075e3
commit
9a38331826
4 changed files with 32 additions and 158 deletions
|
@ -27,6 +27,11 @@ impl MutationState {
|
|||
bytes
|
||||
}
|
||||
|
||||
pub fn write_memory_into(&mut self, buffer: &mut Vec<u8>) {
|
||||
buffer.extend(self.channel.export_memory());
|
||||
self.channel.reset();
|
||||
}
|
||||
|
||||
pub fn channel(&mut self) -> &mut Channel {
|
||||
&mut self.channel
|
||||
}
|
||||
|
@ -167,7 +172,7 @@ impl WriteMutations for MutationState {
|
|||
self.channel
|
||||
.remove_attribute(id.0 as u32, name, ns.unwrap_or_default())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
_ => unreachable!("Any attributes are not supported by the current renderer"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![allow(clippy::await_holding_refcell_ref)]
|
||||
|
||||
use async_trait::async_trait;
|
||||
use dioxus_core::prelude::{consume_context, provide_context};
|
||||
use dioxus_core::ScopeId;
|
||||
use dioxus_html::prelude::{EvalError, EvalProvider, Evaluator};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
|
@ -9,9 +9,9 @@ use crate::query::{Query, QueryEngine};
|
|||
|
||||
/// Provides the DesktopEvalProvider through [`cx.provide_context`].
|
||||
pub fn init_eval() {
|
||||
let query = consume_context::<QueryEngine>().unwrap();
|
||||
let query = ScopeId::ROOT.consume_context::<QueryEngine>().unwrap();
|
||||
let provider: Rc<dyn EvalProvider> = Rc::new(DesktopEvalProvider { query });
|
||||
provide_context(provider);
|
||||
ScopeId::ROOT.provide_context(provider);
|
||||
}
|
||||
|
||||
/// Reprents the desktop-target's provider of evaluators.
|
||||
|
|
|
@ -25,6 +25,7 @@ pub mod adapters {
|
|||
pub use rocket_adapter::*;
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub use adapters::*;
|
||||
|
||||
mod element;
|
||||
|
|
|
@ -5,11 +5,10 @@ use crate::{
|
|||
query::{QueryEngine, QueryResult},
|
||||
LiveViewError,
|
||||
};
|
||||
use dioxus_core::{prelude::*, Attribute, AttributeValue, Mutations};
|
||||
use dioxus_html::{event_bubbles, EventData, HtmlEvent, MountedData, PlatformEventData};
|
||||
use dioxus_interpreter_js::binary_protocol::Channel;
|
||||
use dioxus_core::prelude::*;
|
||||
use dioxus_html::{EventData, HtmlEvent, MountedData, PlatformEventData};
|
||||
use dioxus_interpreter_js::MutationState;
|
||||
use futures_util::{pin_mut, SinkExt, StreamExt};
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Serialize;
|
||||
use std::{rc::Rc, time::Duration};
|
||||
use tokio_util::task::LocalPoolHandle;
|
||||
|
@ -38,12 +37,12 @@ impl LiveViewPool {
|
|||
pub async fn launch(
|
||||
&self,
|
||||
ws: impl LiveViewSocket,
|
||||
app: fn(()) -> Element,
|
||||
app: fn() -> Element,
|
||||
) -> Result<(), LiveViewError> {
|
||||
self.launch_with_props(ws, app, ()).await
|
||||
self.launch_with_props(ws, |app| app(), app).await
|
||||
}
|
||||
|
||||
pub async fn launch_with_props<T: Send + 'static>(
|
||||
pub async fn launch_with_props<T: Clone + Send + 'static>(
|
||||
&self,
|
||||
ws: impl LiveViewSocket,
|
||||
app: fn(T) -> Element,
|
||||
|
@ -126,27 +125,22 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li
|
|||
rx
|
||||
};
|
||||
|
||||
let mut templates: FxHashMap<String, u16> = Default::default();
|
||||
let mut max_template_count = 0;
|
||||
let mut mutations = MutationState::default();
|
||||
|
||||
// Create the a proxy for query engine
|
||||
let (query_tx, mut query_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let query_engine = QueryEngine::new(query_tx);
|
||||
vdom.base_scope().provide_context(query_engine.clone());
|
||||
init_eval();
|
||||
vdom.in_runtime(|| {
|
||||
ScopeId::ROOT.provide_context(query_engine.clone());
|
||||
init_eval();
|
||||
});
|
||||
|
||||
// pin the futures so we can use select!
|
||||
pin_mut!(ws);
|
||||
|
||||
let mut edit_channel = Channel::default();
|
||||
if let Some(edits) = {
|
||||
let mutations = vdom.rebuild();
|
||||
apply_edits(
|
||||
mutations,
|
||||
&mut edit_channel,
|
||||
&mut templates,
|
||||
&mut max_template_count,
|
||||
)
|
||||
vdom.rebuild(&mut mutations);
|
||||
take_edits(&mut mutations)
|
||||
} {
|
||||
// send the initial render to the client
|
||||
ws.send(edits).await?;
|
||||
|
@ -233,18 +227,13 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li
|
|||
}
|
||||
}
|
||||
|
||||
let edits = vdom
|
||||
.render_with_deadline(tokio::time::sleep(Duration::from_millis(10)))
|
||||
.await;
|
||||
vdom.render_with_deadline(
|
||||
tokio::time::sleep(Duration::from_millis(10)),
|
||||
&mut mutations,
|
||||
)
|
||||
.await;
|
||||
|
||||
if let Some(edits) = {
|
||||
apply_edits(
|
||||
edits,
|
||||
&mut edit_channel,
|
||||
&mut templates,
|
||||
&mut max_template_count,
|
||||
)
|
||||
} {
|
||||
if let Some(edits) = take_edits(&mut mutations) {
|
||||
ws.send(edits).await?;
|
||||
}
|
||||
}
|
||||
|
@ -256,132 +245,11 @@ fn text_frame(text: &str) -> Vec<u8> {
|
|||
bytes
|
||||
}
|
||||
|
||||
fn add_template(
|
||||
template: &Template,
|
||||
channel: &mut Channel,
|
||||
templates: &mut FxHashMap<String, u16>,
|
||||
max_template_count: &mut u16,
|
||||
) {
|
||||
for root in template.roots.iter() {
|
||||
create_template_node(channel, root);
|
||||
templates.insert(template.name.to_owned(), *max_template_count);
|
||||
}
|
||||
channel.add_templates(*max_template_count, template.roots.len() as u16);
|
||||
|
||||
*max_template_count += 1
|
||||
}
|
||||
|
||||
fn create_template_node(channel: &mut Channel, v: &'static TemplateNode) {
|
||||
use TemplateNode::*;
|
||||
match v {
|
||||
Element {
|
||||
tag,
|
||||
namespace,
|
||||
attrs,
|
||||
children,
|
||||
..
|
||||
} => {
|
||||
// Push the current node onto the stack
|
||||
match namespace {
|
||||
Some(ns) => channel.create_element_ns(tag, ns),
|
||||
None => channel.create_element(tag),
|
||||
}
|
||||
// Set attributes on the current node
|
||||
for attr in *attrs {
|
||||
if let TemplateAttribute::Static {
|
||||
name,
|
||||
value,
|
||||
namespace,
|
||||
} = attr
|
||||
{
|
||||
channel.set_top_attribute(name, value, namespace.unwrap_or_default())
|
||||
}
|
||||
}
|
||||
// Add each child to the stack
|
||||
for child in *children {
|
||||
create_template_node(channel, child);
|
||||
}
|
||||
// Add all children to the parent
|
||||
channel.append_children_to_top(children.len() as u16);
|
||||
}
|
||||
Text { text } => channel.create_raw_text(text),
|
||||
DynamicText { .. } => channel.create_raw_text("p"),
|
||||
Dynamic { .. } => channel.add_placeholder(),
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_edits(
|
||||
mutations: Mutations,
|
||||
channel: &mut Channel,
|
||||
templates: &mut FxHashMap<String, u16>,
|
||||
max_template_count: &mut u16,
|
||||
) -> Option<Vec<u8>> {
|
||||
use dioxus_core::Mutation::*;
|
||||
if mutations.templates.is_empty() && mutations.edits.is_empty() {
|
||||
return None;
|
||||
}
|
||||
for template in mutations.templates {
|
||||
add_template(&template, channel, templates, max_template_count);
|
||||
}
|
||||
for edit in mutations.edits {
|
||||
match edit {
|
||||
AppendChildren { id, m } => channel.append_children(id.0 as u32, m as u16),
|
||||
AssignId { path, id } => channel.assign_id(path, id.0 as u32),
|
||||
CreatePlaceholder { id } => channel.create_placeholder(id.0 as u32),
|
||||
CreateTextNode { value, id } => channel.create_text_node(value, id.0 as u32),
|
||||
HydrateText { path, value, id } => channel.hydrate_text(path, value, id.0 as u32),
|
||||
LoadTemplate { name, index, id } => {
|
||||
if let Some(tmpl_id) = templates.get(name) {
|
||||
channel.load_template(*tmpl_id, index as u16, id.0 as u32)
|
||||
}
|
||||
}
|
||||
ReplaceWith { id, m } => channel.replace_with(id.0 as u32, m as u16),
|
||||
ReplacePlaceholder { path, m } => channel.replace_placeholder(path, m as u16),
|
||||
InsertAfter { id, m } => channel.insert_after(id.0 as u32, m as u16),
|
||||
InsertBefore { id, m } => channel.insert_before(id.0 as u32, m as u16),
|
||||
SetAttribute {
|
||||
name,
|
||||
value,
|
||||
id,
|
||||
ns,
|
||||
} => match value {
|
||||
BorrowedAttributeValue::Text(txt) => {
|
||||
channel.set_attribute(id.0 as u32, name, txt, ns.unwrap_or_default())
|
||||
}
|
||||
BorrowedAttributeValue::Float(f) => {
|
||||
channel.set_attribute(id.0 as u32, name, &f.to_string(), ns.unwrap_or_default())
|
||||
}
|
||||
BorrowedAttributeValue::Int(n) => {
|
||||
channel.set_attribute(id.0 as u32, name, &n.to_string(), ns.unwrap_or_default())
|
||||
}
|
||||
BorrowedAttributeValue::Bool(b) => channel.set_attribute(
|
||||
id.0 as u32,
|
||||
name,
|
||||
if b { "true" } else { "false" },
|
||||
ns.unwrap_or_default(),
|
||||
),
|
||||
BorrowedAttributeValue::None => {
|
||||
channel.remove_attribute(id.0 as u32, name, ns.unwrap_or_default())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
SetText { value, id } => channel.set_text(id.0 as u32, value),
|
||||
NewEventListener { name, id, .. } => {
|
||||
channel.new_event_listener(name, id.0 as u32, event_bubbles(name) as u8)
|
||||
}
|
||||
RemoveEventListener { name, id } => {
|
||||
channel.remove_event_listener(name, id.0 as u32, event_bubbles(name) as u8)
|
||||
}
|
||||
Remove { id } => channel.remove(id.0 as u32),
|
||||
PushRoot { id } => channel.push_root(id.0 as u32),
|
||||
}
|
||||
}
|
||||
|
||||
fn take_edits(mutations: &mut MutationState) -> Option<Vec<u8>> {
|
||||
// Add an extra one at the beginning to tell the shim this is a binary frame
|
||||
let mut bytes = vec![1];
|
||||
bytes.extend(channel.export_memory());
|
||||
channel.reset();
|
||||
Some(bytes)
|
||||
mutations.write_memory_into(&mut bytes);
|
||||
(bytes.len() > 1).then_some(bytes)
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
|
Loading…
Reference in a new issue