get compiling
This commit is contained in:
18 files changed
+325
-344
No files matched your search
@@ -568,51 +568,6 @@ pub enum TemplateAttribute {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An attribute with information about its position in the DOM and the element it was mounted to
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct MountedAttribute<'a> {
|
|
||||||
pub(crate) ty: AttributeType<'a>,
|
|
||||||
|
|
||||||
/// The element in the DOM that this attribute belongs to
|
|
||||||
pub(crate) mounted_element: Cell<ElementId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<Attribute<'a>> for MountedAttribute<'a> {
|
|
||||||
fn from(attr: Attribute<'a>) -> Self {
|
|
||||||
Self {
|
|
||||||
ty: AttributeType::Single(attr),
|
|
||||||
mounted_element: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a [Attribute<'a>]> for MountedAttribute<'a> {
|
|
||||||
fn from(attr: &'a [Attribute<'a>]) -> Self {
|
|
||||||
Self {
|
|
||||||
ty: AttributeType::Many(attr),
|
|
||||||
mounted_element: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a Vec<Attribute<'a>>> for MountedAttribute<'a> {
|
|
||||||
fn from(attr: &'a Vec<Attribute<'a>>) -> Self {
|
|
||||||
attr.as_slice().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> MountedAttribute<'a> {
|
|
||||||
/// Get the type of this attribute
|
|
||||||
pub fn attribute_type(&self) -> &AttributeType<'a> {
|
|
||||||
&self.ty
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the element that this attribute is mounted to
|
|
||||||
pub fn mounted_element(&self) -> ElementId {
|
|
||||||
self.mounted_element.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An attribute on a DOM node, such as `id="my-thing"` or `href="https://example.com"`
|
/// An attribute on a DOM node, such as `id="my-thing"` or `href="https://example.com"`
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Attribute {
|
pub struct Attribute {
|
||||||
@@ -928,7 +883,7 @@ pub trait HasAttributes<'a> {
|
|||||||
self,
|
self,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
ns: Option<&'static str>,
|
ns: Option<&'static str>,
|
||||||
attr: impl IntoAttributeValue<'a>,
|
attr: impl IntoAttributeValue,
|
||||||
volatile: bool,
|
volatile: bool,
|
||||||
) -> Self;
|
) -> Self;
|
||||||
}
|
}
|
||||||
@@ -391,13 +391,13 @@ impl ScopeId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn a future on a component given its [`ScopeId`].
|
/// Spawn a future on a component given its [`ScopeId`].
|
||||||
pub fn spawn_at(fut: impl Future<Output = ()> + 'static, scope_id: ScopeId) -> Option<TaskId> {
|
pub fn spawn_at(fut: impl Future<Output = ()> + 'static, scope_id: ScopeId) -> Option<Task> {
|
||||||
with_runtime(|rt| rt.get_context(scope_id).unwrap().push_future(fut))
|
with_runtime(|rt| rt.get_context(scope_id).unwrap().push_future(fut))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
||||||
///
|
///
|
||||||
/// This is good for tasks that need to be run after the component has been dropped.
|
/// This is good for tasks that need to be run after the component has been dropped.
|
||||||
pub fn spawn_forever(fut: impl Future<Output = ()> + 'static) -> Option<TaskId> {
|
pub fn spawn_forever(fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
||||||
spawn_at(fut, ScopeId(0))
|
spawn_at(fut, ScopeId(0))
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,6 @@ pub struct ScopeState {
|
|||||||
|
|
||||||
impl Drop for ScopeState {
|
impl Drop for ScopeState {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.drop_listeners();
|
|
||||||
self.runtime.remove_context(self.context_id);
|
self.runtime.remove_context(self.context_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,6 +338,7 @@ impl VirtualDom {
|
|||||||
/// It is up to the listeners themselves to mark nodes as dirty.
|
/// It is up to the listeners themselves to mark nodes as dirty.
|
||||||
///
|
///
|
||||||
/// If you have multiple events, you can call this method multiple times before calling "render_with_deadline"
|
/// If you have multiple events, you can call this method multiple times before calling "render_with_deadline"
|
||||||
|
|
||||||
pub fn handle_event(
|
pub fn handle_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
@@ -394,14 +395,17 @@ impl VirtualDom {
|
|||||||
let this_path = node_template.attr_paths[idx];
|
let this_path = node_template.attr_paths[idx];
|
||||||
|
|
||||||
// Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
|
// Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
|
||||||
if target_path.is_decendant(&this_path) {
|
if attr.name.trim_start_matches("on") == name
|
||||||
attr.ty.for_each(|attribute| {
|
&& target_path.is_decendant(&this_path)
|
||||||
if attribute.name.trim_start_matches("on") == name {
|
{
|
||||||
if let AttributeValue::Listener(listener) = &attribute.value {
|
listeners.push(&attr.value);
|
||||||
listeners.push(listener);
|
|
||||||
}
|
// Break if this is the exact target element.
|
||||||
}
|
// This means we won't call two listeners with the same name on the same element. This should be
|
||||||
});
|
// documented, or be rejected from the rsx! macro outright
|
||||||
|
if target_path == this_path {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,67 +417,38 @@ impl VirtualDom {
|
|||||||
listener.call(uievent.clone());
|
listener.call(uievent.clone());
|
||||||
self.runtime.rendering.set(true);
|
self.runtime.rendering.set(true);
|
||||||
|
|
||||||
// let origin: ScopeId = path.scope;
|
|
||||||
// self.runtime.scope_stack.borrow_mut().push(origin);
|
|
||||||
// self.runtime.rendering.set(false);
|
|
||||||
// if let Some(cb) = listener.borrow_mut().as_deref_mut() {
|
|
||||||
// cb(uievent.clone());
|
|
||||||
// }
|
|
||||||
// self.runtime.scope_stack.borrow_mut().pop();
|
|
||||||
// self.runtime.rendering.set(true);
|
|
||||||
|
|
||||||
if !uievent.propagates.get() {
|
if !uievent.propagates.get() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mount = el_ref.mount.get().as_usize();
|
let mount = el_ref.mount.get().as_usize();
|
||||||
parent_node = mount.and_then(|id| self.mounts.get(id).and_then(|el| el.parent));
|
parent_node = mount.and_then(|id| self.mounts.get(id).and_then(|el| el.parent));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise, we just call the listener on the target element
|
||||||
|
if let Some(path) = parent_node {
|
||||||
|
let el_ref = &self.mounts[path.mount.0].node;
|
||||||
|
let node_template = el_ref.template.get();
|
||||||
|
let target_path = path.path;
|
||||||
|
|
||||||
|
for (idx, attr) in el_ref.dynamic_attrs.iter().enumerate() {
|
||||||
|
let this_path = node_template.attr_paths[idx];
|
||||||
|
|
||||||
|
// Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
|
||||||
|
// Only call the listener if this is the exact target element.
|
||||||
|
if attr.name.trim_start_matches("on") == name && target_path == this_path {
|
||||||
|
if let AttributeValue::Listener(listener) = &attr.value {
|
||||||
|
self.runtime.rendering.set(false);
|
||||||
|
listener.call(uievent.clone());
|
||||||
|
self.runtime.rendering.set(true);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// else {
|
|
||||||
// // Otherwise, we just call the listener on the target element
|
|
||||||
// if let Some(path) = parent_node {
|
|
||||||
// let el_ref = &self.mounts[path.mount.0].node;
|
|
||||||
// let node_template = el_ref.template.get();
|
|
||||||
// let target_path = path.path;
|
|
||||||
|
|
||||||
// for (idx, attr) in el_ref.dynamic_attrs.iter().enumerate() {
|
|
||||||
// let this_path = node_template.attr_paths[idx];
|
|
||||||
|
|
||||||
// // Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
|
|
||||||
// // Only call the listener if this is the exact target element.
|
|
||||||
// if attr.name.trim_start_matches("on") == name && target_path == this_path {
|
|
||||||
// if let AttributeValue::Listener(listener) = &attr.value {
|
|
||||||
// self.runtime.rendering.set(false);
|
|
||||||
// listener.call(uievent.clone());
|
|
||||||
// self.runtime.rendering.set(true);
|
|
||||||
|
|
||||||
// // if target_path == this_path {
|
|
||||||
// // let mut should_stop = false;
|
|
||||||
// // attr.ty.for_each(|attribute| {
|
|
||||||
// // if attribute.name.trim_start_matches("on") == name {
|
|
||||||
// // if let AttributeValue::Listener(listener) = &attribute.value {
|
|
||||||
// // let origin = path.scope;
|
|
||||||
// // self.runtime.scope_stack.borrow_mut().push(origin);
|
|
||||||
// // self.runtime.rendering.set(false);
|
|
||||||
// // if let Some(cb) = listener.borrow_mut().as_deref_mut() {
|
|
||||||
// // cb(uievent.clone());
|
|
||||||
// // }
|
|
||||||
// // self.runtime.scope_stack.borrow_mut().pop();
|
|
||||||
// // self.runtime.rendering.set(true);
|
|
||||||
|
|
||||||
// should_stop = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // });
|
|
||||||
// if should_stop {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub struct SharedContext {
|
|||||||
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
|
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: 'static> App<P> {
|
impl<P: 'static + Clone> App<P> {
|
||||||
pub fn new(cfg: Config, props: P, root: Component<P>) -> (EventLoop<UserWindowEvent>, Self) {
|
pub fn new(cfg: Config, props: P, root: Component<P>) -> (EventLoop<UserWindowEvent>, Self) {
|
||||||
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
||||||
|
|
||||||
@@ -196,8 +196,16 @@ impl<P: 'static> App<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_initialize_msg(&mut self, id: WindowId) {
|
pub fn handle_initialize_msg(&mut self, id: WindowId) {
|
||||||
|
// view.dom
|
||||||
|
// .rebuild(&mut *view.desktop_context.mutation_state.borrow_mut());
|
||||||
|
// send_edits(&view.desktop_context);
|
||||||
|
|
||||||
|
println!("initialize message received, sending edits to {id:?}");
|
||||||
|
|
||||||
let view = self.webviews.get_mut(&id).unwrap();
|
let view = self.webviews.get_mut(&id).unwrap();
|
||||||
view.desktop_context.send_edits(view.dom.rebuild());
|
view.dom
|
||||||
|
.render_immediate(&mut *view.desktop_context.mutation_state.borrow_mut());
|
||||||
|
view.desktop_context.send_edits();
|
||||||
view.desktop_context
|
view.desktop_context
|
||||||
.window
|
.window
|
||||||
.set_visible(self.is_visible_before_start);
|
.set_visible(self.is_visible_before_start);
|
||||||
@@ -249,7 +257,9 @@ impl<P: 'static> App<P> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
view.dom.handle_event(&name, as_any, element, bubbles);
|
view.dom.handle_event(&name, as_any, element, bubbles);
|
||||||
view.desktop_context.send_edits(view.dom.render_immediate());
|
view.dom
|
||||||
|
.render_immediate(&mut *view.desktop_context.mutation_state.borrow_mut());
|
||||||
|
view.desktop_context.send_edits();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||||
@@ -306,7 +316,9 @@ impl<P: 'static> App<P> {
|
|||||||
view.dom.handle_event(event_name, data, id, event_bubbles);
|
view.dom.handle_event(event_name, data, id, event_bubbles);
|
||||||
}
|
}
|
||||||
|
|
||||||
view.desktop_context.send_edits(view.dom.render_immediate());
|
view.dom
|
||||||
|
.render_immediate(&mut *view.desktop_context.mutation_state.borrow_mut());
|
||||||
|
view.desktop_context.send_edits();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Poll the virtualdom until it's pending
|
/// Poll the virtualdom until it's pending
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ impl Config {
|
|||||||
/// Launch a Dioxus app using the given component, config, and props
|
/// Launch a Dioxus app using the given component, config, and props
|
||||||
///
|
///
|
||||||
/// See the [`crate::launch::launch_with_props`] function for more details.
|
/// See the [`crate::launch::launch_with_props`] function for more details.
|
||||||
pub fn launch_with_props<P: 'static>(self, root: Component<P>, props: P) {
|
pub fn launch_with_props<P: 'static + Clone>(self, root: Component<P>, props: P) {
|
||||||
crate::launch::launch_with_props(root, props, self)
|
crate::launch::launch_with_props(root, props, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ use crate::{
|
|||||||
AssetRequest, Config,
|
AssetRequest, Config,
|
||||||
};
|
};
|
||||||
use dioxus_core::{
|
use dioxus_core::{
|
||||||
|
once,
|
||||||
prelude::{current_scope_id, ScopeId},
|
prelude::{current_scope_id, ScopeId},
|
||||||
Mutations, VirtualDom,
|
VirtualDom,
|
||||||
};
|
};
|
||||||
use dioxus_interpreter_js::binary_protocol::Channel;
|
use dioxus_interpreter_js::binary_protocol::Channel;
|
||||||
use dioxus_interpreter_js::MutationState;
|
use dioxus_interpreter_js::MutationState;
|
||||||
@@ -64,10 +65,6 @@ pub struct DesktopService {
|
|||||||
pub(super) query: QueryEngine,
|
pub(super) query: QueryEngine,
|
||||||
pub(crate) edit_queue: EditQueue,
|
pub(crate) edit_queue: EditQueue,
|
||||||
pub(crate) mutation_state: RefCell<MutationState>,
|
pub(crate) mutation_state: RefCell<MutationState>,
|
||||||
|
|
||||||
pub(crate) templates: RefCell<FxHashMap<String, u16>>,
|
|
||||||
pub(crate) max_template_count: AtomicU16,
|
|
||||||
pub(crate) channel: RefCell<Channel>,
|
|
||||||
pub(crate) asset_handlers: AssetHandlerRegistry,
|
pub(crate) asset_handlers: AssetHandlerRegistry,
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
@@ -99,24 +96,17 @@ impl DesktopService {
|
|||||||
mutation_state: Default::default(),
|
mutation_state: Default::default(),
|
||||||
asset_handlers,
|
asset_handlers,
|
||||||
query: Default::default(),
|
query: Default::default(),
|
||||||
templates: Default::default(),
|
|
||||||
max_template_count: Default::default(),
|
|
||||||
channel: Default::default(),
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
views: Default::default(),
|
views: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a list of mutations to the webview
|
/// Send a list of mutations to the webview
|
||||||
pub(crate) fn send_edits(&self, edits: Mutations) {
|
pub(crate) fn send_edits(&self) {
|
||||||
if let Some(bytes) = crate::edits::apply_edits(
|
let mut mutations = self.mutation_state.borrow_mut();
|
||||||
edits,
|
let serialized_edits = mutations.export_memory();
|
||||||
&mut self.channel.borrow_mut(),
|
dbg!(serialized_edits.len());
|
||||||
&mut self.templates.borrow_mut(),
|
self.edit_queue.add_edits(serialized_edits);
|
||||||
&self.max_template_count,
|
|
||||||
) {
|
|
||||||
self.edit_queue.add_edits(bytes)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new window using the props and window builder
|
/// Create a new window using the props and window builder
|
||||||
@@ -402,7 +392,7 @@ pub fn use_wry_event_handler(
|
|||||||
let id = desktop.create_wry_event_handler(handler);
|
let id = desktop.create_wry_event_handler(handler);
|
||||||
|
|
||||||
WryEventHandler {
|
WryEventHandler {
|
||||||
handlers: desktop.event_handlers.clone(),
|
handlers: desktop.shared.event_handlers.clone(),
|
||||||
id,
|
id,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+139
-131
@@ -1,4 +1,4 @@
|
|||||||
use dioxus_core::{BorrowedAttributeValue, Mutations, Template, TemplateAttribute, TemplateNode};
|
use dioxus_core::{AttributeValue, Template, TemplateAttribute, TemplateNode};
|
||||||
use dioxus_html::event_bubbles;
|
use dioxus_html::event_bubbles;
|
||||||
use dioxus_interpreter_js::binary_protocol::Channel;
|
use dioxus_interpreter_js::binary_protocol::Channel;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
@@ -8,22 +8,30 @@ use std::{
|
|||||||
sync::{atomic::Ordering, Mutex},
|
sync::{atomic::Ordering, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
use wry::RequestAsyncResponder;
|
use wry::RequestAsyncResponder;
|
||||||
|
|
||||||
/// This handles communication between the requests that the webview makes and the interpreter. The interpreter
|
/// This handles communication between the requests that the webview makes and the interpreter. The interpreter constantly makes long running requests to the webview to get any edits that should be made to the DOM almost like server side events.
|
||||||
/// constantly makes long running requests to the webview to get any edits that should be made to the DOM almost like
|
/// It will hold onto the requests until the interpreter is ready to handle them and hold onto any pending edits until a new request is made.
|
||||||
/// server side events.
|
|
||||||
///
|
|
||||||
/// It will hold onto the requests until the interpreter is ready to handle them and hold onto any pending edits until
|
|
||||||
/// a new request is made.
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub(crate) struct EditQueue {
|
pub(crate) struct EditQueue {
|
||||||
queue: Arc<Mutex<Vec<Vec<u8>>>>,
|
queue: Arc<Mutex<Vec<Vec<u8>>>>,
|
||||||
responder: Arc<Mutex<Option<RequestAsyncResponder>>>,
|
responder: Arc<Mutex<Option<wry::RequestAsyncResponder>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for EditQueue {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("EditQueue")
|
||||||
|
.field("queue", &self.queue)
|
||||||
|
.field("responder", {
|
||||||
|
&self.responder.lock().unwrap().as_ref().map(|_| ())
|
||||||
|
})
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditQueue {
|
impl EditQueue {
|
||||||
pub fn handle_request(&self, responder: RequestAsyncResponder) {
|
pub fn handle_request(&self, responder: wry::RequestAsyncResponder) {
|
||||||
let mut queue = self.queue.lock().unwrap();
|
let mut queue = self.queue.lock().unwrap();
|
||||||
if let Some(bytes) = queue.pop() {
|
if let Some(bytes) = queue.pop() {
|
||||||
responder.respond(wry::http::Response::new(bytes));
|
responder.respond(wry::http::Response::new(bytes));
|
||||||
@@ -42,131 +50,131 @@ impl EditQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn apply_edits(
|
// pub(crate) fn apply_edits(
|
||||||
mutations: Mutations,
|
// mutations: Mutations,
|
||||||
channel: &mut Channel,
|
// channel: &mut Channel,
|
||||||
templates: &mut FxHashMap<String, u16>,
|
// templates: &mut FxHashMap<String, u16>,
|
||||||
max_template_count: &AtomicU16,
|
// max_template_count: &AtomicU16,
|
||||||
) -> Option<Vec<u8>> {
|
// ) -> Option<Vec<u8>> {
|
||||||
if mutations.templates.is_empty() && mutations.edits.is_empty() {
|
// if mutations.templates.is_empty() && mutations.edits.is_empty() {
|
||||||
return None;
|
// return None;
|
||||||
}
|
// }
|
||||||
|
|
||||||
for template in mutations.templates {
|
// for template in mutations.templates {
|
||||||
add_template(&template, channel, templates, max_template_count);
|
// add_template(&template, channel, templates, max_template_count);
|
||||||
}
|
// }
|
||||||
|
|
||||||
use dioxus_core::Mutation::*;
|
// use dioxus_core::Mutation::*;
|
||||||
for edit in mutations.edits {
|
// for edit in mutations.edits {
|
||||||
match edit {
|
// match edit {
|
||||||
AppendChildren { id, m } => channel.append_children(id.0 as u32, m as u16),
|
// AppendChildren { id, m } => channel.append_children(id.0 as u32, m as u16),
|
||||||
AssignId { path, id } => channel.assign_id(path, id.0 as u32),
|
// AssignId { path, id } => channel.assign_id(path, id.0 as u32),
|
||||||
CreatePlaceholder { id } => channel.create_placeholder(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),
|
// 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),
|
// HydrateText { path, value, id } => channel.hydrate_text(path, value, id.0 as u32),
|
||||||
LoadTemplate { name, index, id } => {
|
// LoadTemplate { name, index, id } => {
|
||||||
if let Some(tmpl_id) = templates.get(name) {
|
// if let Some(tmpl_id) = templates.get(name) {
|
||||||
channel.load_template(*tmpl_id, index as u16, id.0 as u32)
|
// 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),
|
// ReplaceWith { id, m } => channel.replace_with(id.0 as u32, m as u16),
|
||||||
ReplacePlaceholder { path, m } => channel.replace_placeholder(path, 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),
|
// 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),
|
// InsertBefore { id, m } => channel.insert_before(id.0 as u32, m as u16),
|
||||||
SetAttribute {
|
// SetAttribute {
|
||||||
name,
|
// name,
|
||||||
value,
|
// value,
|
||||||
id,
|
// id,
|
||||||
ns,
|
// ns,
|
||||||
} => match value {
|
// } => match value {
|
||||||
BorrowedAttributeValue::Text(txt) => {
|
// AttributeValue::Text(txt) => {
|
||||||
channel.set_attribute(id.0 as u32, name, txt, ns.unwrap_or_default())
|
// channel.set_attribute(id.0 as u32, name, txt, ns.unwrap_or_default())
|
||||||
}
|
// }
|
||||||
BorrowedAttributeValue::Float(f) => {
|
// AttributeValue::Float(f) => {
|
||||||
channel.set_attribute(id.0 as u32, name, &f.to_string(), ns.unwrap_or_default())
|
// channel.set_attribute(id.0 as u32, name, &f.to_string(), ns.unwrap_or_default())
|
||||||
}
|
// }
|
||||||
BorrowedAttributeValue::Int(n) => {
|
// AttributeValue::Int(n) => {
|
||||||
channel.set_attribute(id.0 as u32, name, &n.to_string(), ns.unwrap_or_default())
|
// channel.set_attribute(id.0 as u32, name, &n.to_string(), ns.unwrap_or_default())
|
||||||
}
|
// }
|
||||||
BorrowedAttributeValue::Bool(b) => channel.set_attribute(
|
// AttributeValue::Bool(b) => channel.set_attribute(
|
||||||
id.0 as u32,
|
// id.0 as u32,
|
||||||
name,
|
// name,
|
||||||
if b { "true" } else { "false" },
|
// if b { "true" } else { "false" },
|
||||||
ns.unwrap_or_default(),
|
// ns.unwrap_or_default(),
|
||||||
),
|
// ),
|
||||||
BorrowedAttributeValue::None => {
|
// AttributeValue::None => {
|
||||||
channel.remove_attribute(id.0 as u32, name, ns.unwrap_or_default())
|
// channel.remove_attribute(id.0 as u32, name, ns.unwrap_or_default())
|
||||||
}
|
// }
|
||||||
_ => unreachable!(),
|
// _ => unreachable!(),
|
||||||
},
|
// },
|
||||||
SetText { value, id } => channel.set_text(id.0 as u32, value),
|
// SetText { value, id } => channel.set_text(id.0 as u32, value),
|
||||||
NewEventListener { name, id, .. } => {
|
// NewEventListener { name, id, .. } => {
|
||||||
channel.new_event_listener(name, id.0 as u32, event_bubbles(name) as u8)
|
// channel.new_event_listener(name, id.0 as u32, event_bubbles(name) as u8)
|
||||||
}
|
// }
|
||||||
RemoveEventListener { name, id } => {
|
// RemoveEventListener { name, id } => {
|
||||||
channel.remove_event_listener(name, id.0 as u32, event_bubbles(name) as u8)
|
// channel.remove_event_listener(name, id.0 as u32, event_bubbles(name) as u8)
|
||||||
}
|
// }
|
||||||
Remove { id } => channel.remove(id.0 as u32),
|
// Remove { id } => channel.remove(id.0 as u32),
|
||||||
PushRoot { id } => channel.push_root(id.0 as u32),
|
// PushRoot { id } => channel.push_root(id.0 as u32),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
let bytes: Vec<_> = channel.export_memory().collect();
|
// let bytes: Vec<_> = channel.export_memory().collect();
|
||||||
channel.reset();
|
// channel.reset();
|
||||||
Some(bytes)
|
// Some(bytes)
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn add_template(
|
// pub fn add_template(
|
||||||
template: &Template<'static>,
|
// template: &Template<'static>,
|
||||||
channel: &mut Channel,
|
// channel: &mut Channel,
|
||||||
templates: &mut FxHashMap<String, u16>,
|
// templates: &mut FxHashMap<String, u16>,
|
||||||
max_template_count: &AtomicU16,
|
// max_template_count: &AtomicU16,
|
||||||
) {
|
// ) {
|
||||||
let current_max_template_count = max_template_count.load(Ordering::Relaxed);
|
// let current_max_template_count = max_template_count.load(Ordering::Relaxed);
|
||||||
for root in template.roots.iter() {
|
// for root in template.roots.iter() {
|
||||||
create_template_node(channel, root);
|
// create_template_node(channel, root);
|
||||||
templates.insert(template.name.to_owned(), current_max_template_count);
|
// templates.insert(template.name.to_owned(), current_max_template_count);
|
||||||
}
|
// }
|
||||||
channel.add_templates(current_max_template_count, template.roots.len() as u16);
|
// channel.add_templates(current_max_template_count, template.roots.len() as u16);
|
||||||
|
|
||||||
max_template_count.fetch_add(1, Ordering::Relaxed);
|
// max_template_count.fetch_add(1, Ordering::Relaxed);
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn create_template_node(channel: &mut Channel, node: &'static TemplateNode<'static>) {
|
// pub fn create_template_node(channel: &mut Channel, node: &'static TemplateNode<'static>) {
|
||||||
use TemplateNode::*;
|
// use TemplateNode::*;
|
||||||
match node {
|
// match node {
|
||||||
Element {
|
// Element {
|
||||||
tag,
|
// tag,
|
||||||
namespace,
|
// namespace,
|
||||||
attrs,
|
// attrs,
|
||||||
children,
|
// children,
|
||||||
..
|
// ..
|
||||||
} => {
|
// } => {
|
||||||
// Push the current node onto the stack
|
// // Push the current node onto the stack
|
||||||
match namespace {
|
// match namespace {
|
||||||
Some(ns) => channel.create_element_ns(tag, ns),
|
// Some(ns) => channel.create_element_ns(tag, ns),
|
||||||
None => channel.create_element(tag),
|
// None => channel.create_element(tag),
|
||||||
}
|
// }
|
||||||
// Set attributes on the current node
|
// // Set attributes on the current node
|
||||||
for attr in *attrs {
|
// for attr in *attrs {
|
||||||
if let TemplateAttribute::Static {
|
// if let TemplateAttribute::Static {
|
||||||
name,
|
// name,
|
||||||
value,
|
// value,
|
||||||
namespace,
|
// namespace,
|
||||||
} = attr
|
// } = attr
|
||||||
{
|
// {
|
||||||
channel.set_top_attribute(name, value, namespace.unwrap_or_default())
|
// channel.set_top_attribute(name, value, namespace.unwrap_or_default())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
// Add each child to the stack
|
// // Add each child to the stack
|
||||||
for child in *children {
|
// for child in *children {
|
||||||
create_template_node(channel, child);
|
// create_template_node(channel, child);
|
||||||
}
|
// }
|
||||||
// Add all children to the parent
|
// // Add all children to the parent
|
||||||
channel.append_children_to_top(children.len() as u16);
|
// channel.append_children_to_top(children.len() as u16);
|
||||||
}
|
// }
|
||||||
Text { text } => channel.create_raw_text(text),
|
// Text { text } => channel.create_raw_text(text),
|
||||||
DynamicText { .. } => channel.create_raw_text("p"),
|
// DynamicText { .. } => channel.create_raw_text("p"),
|
||||||
Dynamic { .. } => channel.add_placeholder(),
|
// Dynamic { .. } => channel.add_placeholder(),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
@@ -2,76 +2,75 @@ use crate::{
|
|||||||
assets::*, ipc::UserWindowEvent, shortcut::IntoAccelerator, window, DesktopContext,
|
assets::*, ipc::UserWindowEvent, shortcut::IntoAccelerator, window, DesktopContext,
|
||||||
ShortcutHandle, ShortcutRegistryError, WryEventHandler,
|
ShortcutHandle, ShortcutRegistryError, WryEventHandler,
|
||||||
};
|
};
|
||||||
use dioxus_core::ScopeState;
|
|
||||||
use tao::{event::Event, event_loop::EventLoopWindowTarget};
|
use tao::{event::Event, event_loop::EventLoopWindowTarget};
|
||||||
use wry::RequestAsyncResponder;
|
use wry::RequestAsyncResponder;
|
||||||
|
|
||||||
/// Get an imperative handle to the current window
|
// /// Get an imperative handle to the current window
|
||||||
pub fn use_window(cx: &ScopeState) -> &DesktopContext {
|
// pub fn use_window(cx: &ScopeState) -> &DesktopContext {
|
||||||
cx.use_hook(|| cx.consume_context::<DesktopContext>())
|
// cx.use_hook(|| cx.consume_context::<DesktopContext>())
|
||||||
.as_ref()
|
// .as_ref()
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Get a closure that executes any JavaScript in the WebView context.
|
// /// Get a closure that executes any JavaScript in the WebView context.
|
||||||
pub fn use_wry_event_handler(
|
// pub fn use_wry_event_handler(
|
||||||
cx: &ScopeState,
|
// cx: &ScopeState,
|
||||||
handler: impl FnMut(&Event<UserWindowEvent>, &EventLoopWindowTarget<UserWindowEvent>) + 'static,
|
// handler: impl FnMut(&Event<UserWindowEvent>, &EventLoopWindowTarget<UserWindowEvent>) + 'static,
|
||||||
) -> &WryEventHandler {
|
// ) -> &WryEventHandler {
|
||||||
cx.use_hook(move || {
|
// cx.use_hook(move || {
|
||||||
let desktop = window();
|
// let desktop = window();
|
||||||
|
|
||||||
let id = desktop.create_wry_event_handler(handler);
|
// let id = desktop.create_wry_event_handler(handler);
|
||||||
|
|
||||||
WryEventHandler {
|
// WryEventHandler {
|
||||||
handlers: desktop.shared.event_handlers.clone(),
|
// handlers: desktop.shared.event_handlers.clone(),
|
||||||
id,
|
// id,
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Provide a callback to handle asset loading yourself.
|
// /// Provide a callback to handle asset loading yourself.
|
||||||
///
|
// ///
|
||||||
/// The callback takes a path as requested by the web view, and it should return `Some(response)`
|
// /// The callback takes a path as requested by the web view, and it should return `Some(response)`
|
||||||
/// if you want to load the asset, and `None` if you want to fallback on the default behavior.
|
// /// if you want to load the asset, and `None` if you want to fallback on the default behavior.
|
||||||
pub fn use_asset_handler(
|
// pub fn use_asset_handler(
|
||||||
cx: &ScopeState,
|
// cx: &ScopeState,
|
||||||
name: &str,
|
// name: &str,
|
||||||
handler: impl Fn(AssetRequest, RequestAsyncResponder) + 'static,
|
// handler: impl Fn(AssetRequest, RequestAsyncResponder) + 'static,
|
||||||
) {
|
// ) {
|
||||||
cx.use_hook(|| {
|
// cx.use_hook(|| {
|
||||||
crate::window().asset_handlers.register_handler(
|
// crate::window().asset_handlers.register_handler(
|
||||||
name.to_string(),
|
// name.to_string(),
|
||||||
Box::new(handler),
|
// Box::new(handler),
|
||||||
cx.scope_id(),
|
// cx.scope_id(),
|
||||||
);
|
// );
|
||||||
|
|
||||||
Handler(name.to_string())
|
// Handler(name.to_string())
|
||||||
});
|
// });
|
||||||
|
|
||||||
// todo: can we just put ondrop in core?
|
// // todo: can we just put ondrop in core?
|
||||||
struct Handler(String);
|
// struct Handler(String);
|
||||||
impl Drop for Handler {
|
// impl Drop for Handler {
|
||||||
fn drop(&mut self) {
|
// fn drop(&mut self) {
|
||||||
_ = crate::window().asset_handlers.remove_handler(&self.0);
|
// _ = crate::window().asset_handlers.remove_handler(&self.0);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Get a closure that executes any JavaScript in the WebView context.
|
// /// Get a closure that executes any JavaScript in the WebView context.
|
||||||
pub fn use_global_shortcut(
|
// pub fn use_global_shortcut(
|
||||||
cx: &ScopeState,
|
// cx: &ScopeState,
|
||||||
accelerator: impl IntoAccelerator,
|
// accelerator: impl IntoAccelerator,
|
||||||
handler: impl FnMut() + 'static,
|
// handler: impl FnMut() + 'static,
|
||||||
) -> &Result<ShortcutHandle, ShortcutRegistryError> {
|
// ) -> &Result<ShortcutHandle, ShortcutRegistryError> {
|
||||||
cx.use_hook(move || {
|
// cx.use_hook(move || {
|
||||||
let desktop = window();
|
// let desktop = window();
|
||||||
|
|
||||||
let id = desktop.create_shortcut(accelerator.accelerator(), handler);
|
// let id = desktop.create_shortcut(accelerator.accelerator(), handler);
|
||||||
|
|
||||||
Ok(ShortcutHandle {
|
// Ok(ShortcutHandle {
|
||||||
desktop,
|
// desktop,
|
||||||
shortcut_id: id?,
|
// shortcut_id: id?,
|
||||||
})
|
// })
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
@@ -76,7 +76,7 @@ pub fn launch_cfg(root: Component, config_builder: Config) {
|
|||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config) {
|
pub fn launch_with_props<P: 'static + Clone>(root: Component<P>, props: P, cfg: Config) {
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
@@ -94,7 +94,7 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
|||||||
///
|
///
|
||||||
/// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
|
/// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
|
||||||
/// and is equivalent to calling launch_with_props with the tokio feature disabled.
|
/// and is equivalent to calling launch_with_props with the tokio feature disabled.
|
||||||
pub fn launch_with_props_blocking<P: 'static>(root: Component<P>, props: P, cfg: Config) {
|
pub fn launch_with_props_blocking<P: 'static + Clone>(root: Component<P>, props: P, cfg: Config) {
|
||||||
let (event_loop, mut app) = App::new(cfg, props, root);
|
let (event_loop, mut app) = App::new(cfg, props, root);
|
||||||
|
|
||||||
event_loop.run(move |window_event, _, control_flow| {
|
event_loop.run(move |window_event, _, control_flow| {
|
||||||
|
|||||||
@@ -43,6 +43,6 @@ pub use config::{Config, WindowCloseBehaviour};
|
|||||||
pub use desktop_context::{
|
pub use desktop_context::{
|
||||||
window, DesktopContext, DesktopService, WryEventHandler, WryEventHandlerId,
|
window, DesktopContext, DesktopService, WryEventHandler, WryEventHandlerId,
|
||||||
};
|
};
|
||||||
pub use hooks::{use_asset_handler, use_global_shortcut, use_window, use_wry_event_handler};
|
// pub use hooks::{use_asset_handler, use_global_shortcut, use_window, use_wry_event_handler};
|
||||||
pub use shortcut::{ShortcutHandle, ShortcutId, ShortcutRegistryError};
|
pub use shortcut::{ShortcutHandle, ShortcutId, ShortcutRegistryError};
|
||||||
pub use wry::RequestAsyncResponder;
|
pub use wry::RequestAsyncResponder;
|
||||||
@@ -53,6 +53,47 @@ pub(super) fn index_request(
|
|||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let assets_head = {
|
||||||
|
// #[cfg(all(
|
||||||
|
// debug_assertions,
|
||||||
|
// any(
|
||||||
|
// target_os = "windows",
|
||||||
|
// target_os = "macos",
|
||||||
|
// target_os = "linux",
|
||||||
|
// target_os = "dragonfly",
|
||||||
|
// target_os = "freebsd",
|
||||||
|
// target_os = "netbsd",
|
||||||
|
// target_os = "openbsd"
|
||||||
|
// )
|
||||||
|
// ))]
|
||||||
|
// {
|
||||||
|
// None
|
||||||
|
// }
|
||||||
|
// #[cfg(not(all(
|
||||||
|
// debug_assertions,
|
||||||
|
// any(
|
||||||
|
// target_os = "windows",
|
||||||
|
// target_os = "macos",
|
||||||
|
// target_os = "linux",
|
||||||
|
// target_os = "dragonfly",
|
||||||
|
// target_os = "freebsd",
|
||||||
|
// target_os = "netbsd",
|
||||||
|
// target_os = "openbsd"
|
||||||
|
// )
|
||||||
|
// )))]
|
||||||
|
// {
|
||||||
|
// let head = crate::protocol::get_asset_root_or_default();
|
||||||
|
// let head = head.join("dist/__assets_head.html");
|
||||||
|
// match std::fs::read_to_string(&head) {
|
||||||
|
// Ok(s) => Some(s),
|
||||||
|
// Err(err) => {
|
||||||
|
// tracing::error!("Failed to read {head:?}: {err}");
|
||||||
|
// None
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
/// Handle a request from the webview
|
/// Handle a request from the webview
|
||||||
///
|
///
|
||||||
/// - Tries to stream edits if they're requested.
|
/// - Tries to stream edits if they're requested.
|
||||||
@@ -66,6 +107,7 @@ pub(super) fn desktop_handler(
|
|||||||
) {
|
) {
|
||||||
// If the request is asking for edits (ie binary protocol streaming, do that)
|
// If the request is asking for edits (ie binary protocol streaming, do that)
|
||||||
if request.uri().path().trim_matches('/') == "edits" {
|
if request.uri().path().trim_matches('/') == "edits" {
|
||||||
|
println!("Handling edits from handler");
|
||||||
return edit_queue.handle_request(responder);
|
return edit_queue.handle_request(responder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::{cell::RefCell, collections::HashMap, str::FromStr};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc, str::FromStr};
|
||||||
|
|
||||||
use dioxus_html::input_data::keyboard_types::Modifiers;
|
use dioxus_html::input_data::keyboard_types::Modifiers;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
@@ -84,7 +84,7 @@ impl ShortcutRegistry {
|
|||||||
HotkeyError::HotKeyParseError(shortcut) => {
|
HotkeyError::HotKeyParseError(shortcut) => {
|
||||||
ShortcutRegistryError::InvalidShortcut(shortcut)
|
ShortcutRegistryError::InvalidShortcut(shortcut)
|
||||||
}
|
}
|
||||||
err => ShortcutRegistryError::Other(Box::new(err)),
|
err => ShortcutRegistryError::Other(Rc::new(err)),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut shortcut = Shortcut {
|
let mut shortcut = Shortcut {
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ impl WebviewInstance {
|
|||||||
));
|
));
|
||||||
|
|
||||||
// Provide the desktop context to the virtualdom
|
// Provide the desktop context to the virtualdom
|
||||||
dom.base_scope().provide_context(desktop_context.clone());
|
// dom.base_scope().provide_context(desktop_context.clone());
|
||||||
|
|
||||||
// let query = dom.in_runtime(|| {
|
// let query = dom.in_runtime(|| {
|
||||||
// let query = ScopeId::ROOT.provide_context(desktop_context.clone());
|
// let query = ScopeId::ROOT.provide_context(desktop_context.clone());
|
||||||
@@ -163,7 +163,7 @@ impl WebviewInstance {
|
|||||||
// a different TypeId.
|
// a different TypeId.
|
||||||
let provider: Rc<dyn EvalProvider> =
|
let provider: Rc<dyn EvalProvider> =
|
||||||
Rc::new(DesktopEvalProvider::new(desktop_context.clone()));
|
Rc::new(DesktopEvalProvider::new(desktop_context.clone()));
|
||||||
dom.base_scope().provide_context(provider);
|
// dom.base_scope().provide_context(provider);
|
||||||
|
|
||||||
WebviewInstance {
|
WebviewInstance {
|
||||||
waker: tao_waker(shared.proxy.clone(), desktop_context.window.id()),
|
waker: tao_waker(shared.proxy.clone(), desktop_context.window.id()),
|
||||||
@@ -190,7 +190,11 @@ impl WebviewInstance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.desktop_context.send_edits(self.dom.render_immediate());
|
// self.desktop_context.send_edits(self.dom.render_immediate());
|
||||||
|
|
||||||
|
self.dom
|
||||||
|
.render_immediate(&mut *self.desktop_context.mutation_state.borrow_mut());
|
||||||
|
self.desktop_context.send_edits();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
use dioxus_core::prelude::IntoAttributeValue;
|
use dioxus_core::prelude::IntoAttributeValue;
|
||||||
use dioxus_core::HasAttributes;
|
|
||||||
use dioxus_html_internal_macro::impl_extension_attributes;
|
use dioxus_html_internal_macro::impl_extension_attributes;
|
||||||
#[cfg(feature = "hot-reload-context")]
|
#[cfg(feature = "hot-reload-context")]
|
||||||
use dioxus_rsx::HotReloadingContext;
|
use dioxus_rsx::HotReloadingContext;
|
||||||
@@ -386,9 +385,9 @@ macro_rules! builder_constructors {
|
|||||||
|
|
||||||
pub(crate) mod extensions {
|
pub(crate) mod extensions {
|
||||||
use super::*;
|
use super::*;
|
||||||
$(
|
// $(
|
||||||
impl_extension_attributes![ELEMENT $name { $($fil,)* }];
|
// impl_extension_attributes![ELEMENT $name { $($fil,)* }];
|
||||||
)*
|
// )*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
use dioxus_core::prelude::IntoAttributeValue;
|
use dioxus_core::prelude::IntoAttributeValue;
|
||||||
use dioxus_core::HasAttributes;
|
|
||||||
use dioxus_html_internal_macro::impl_extension_attributes;
|
use dioxus_html_internal_macro::impl_extension_attributes;
|
||||||
|
|
||||||
use crate::AttributeDiscription;
|
use crate::AttributeDiscription;
|
||||||
@@ -111,7 +110,7 @@ macro_rules! trait_methods {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_extension_attributes![GLOBAL $trait { $($name,)* }];
|
// impl_extension_attributes![GLOBAL $trait { $($name,)* }];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rename the incoming ident and apply a custom namespace
|
// Rename the incoming ident and apply a custom namespace
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ pub mod eval;
|
|||||||
|
|
||||||
pub mod extensions {
|
pub mod extensions {
|
||||||
pub use crate::elements::extensions::*;
|
pub use crate::elements::extensions::*;
|
||||||
pub use crate::global_attributes::{GlobalAttributesExtension, SvgAttributesExtension};
|
// pub use crate::global_attributes::{GlobalAttributesExtension, SvgAttributesExtension};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
@@ -58,7 +58,7 @@ pub mod prelude {
|
|||||||
#[cfg(feature = "eval")]
|
#[cfg(feature = "eval")]
|
||||||
pub use crate::eval::*;
|
pub use crate::eval::*;
|
||||||
pub use crate::events::*;
|
pub use crate::events::*;
|
||||||
pub use crate::global_attributes::{GlobalAttributesExtension, SvgAttributesExtension};
|
// pub use crate::global_attributes::{GlobalAttributesExtension, SvgAttributesExtension};
|
||||||
pub use crate::point_interaction::*;
|
pub use crate::point_interaction::*;
|
||||||
pub use keyboard_types::{self, Code, Key, Location, Modifiers};
|
pub use keyboard_types::{self, Code, Key, Location, Modifiers};
|
||||||
}
|
}
|
||||||
@@ -253,8 +253,7 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
|
|||||||
attr_paths: &[ #(#attr_paths),* ],
|
attr_paths: &[ #(#attr_paths),* ],
|
||||||
};
|
};
|
||||||
|
|
||||||
__cx.vnode(
|
::dioxus::core::VNode::new(
|
||||||
None.into(),
|
|
||||||
#key_tokens,
|
#key_tokens,
|
||||||
TEMPLATE,
|
TEMPLATE,
|
||||||
Box::new([ #( #node_printer ),* ]),
|
Box::new([ #( #node_printer ),* ]),
|
||||||
|
|||||||
Reference in new issue
Block a user