From 775e9e29b8cde45a13bdae22a6f54b25518e7192 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 13 Jul 2021 16:48:11 -0400 Subject: [PATCH] wip: cut down on errors --- Cargo.toml | 38 ++++---- packages/core/examples/async.rs | 12 +++ packages/core/src/context.rs | 108 ++++++++++++++++++---- packages/core/src/diff.rs | 25 +++--- packages/core/src/nodes.rs | 2 +- packages/webview/src/lib.rs | 155 ++------------------------------ 6 files changed, 142 insertions(+), 198 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4cd6e311c..dcd62426f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,14 +20,14 @@ dioxus-ssr = { path = "./packages/ssr", optional = true } [features] default = [ "core", - "atoms", "macro", - "ssr", "hooks", - "router", "html", - "web", - "desktop", + # "atoms", + # "ssr", + # "router", + # "web", + # "desktop", ] atoms = [] macro = ["dioxus-core-macro"] @@ -43,17 +43,17 @@ core = [] [dev-dependencies] -futures = "0.3.15" -log = "0.4.14" -num-format = "0.4.0" -separator = "0.4.1" -serde = { version = "1.0.126", features = ["derive"] } -surf = "2.2.0" -env_logger = "*" -async-std = { version = "1.9.0", features = ["attributes"] } -im-rc = "15.0.0" -rand = { version = "0.8.4", features = ["small_rng"] } -fxhash = "0.2.1" +# futures = "0.3.15" +# log = "0.4.14" +# num-format = "0.4.0" +# separator = "0.4.1" +# serde = { version = "1.0.126", features = ["derive"] } +# surf = "2.2.0" +# env_logger = "*" +# async-std = { version = "1.9.0", features = ["attributes"] } +# im-rc = "15.0.0" +# rand = { version = "0.8.4", features = ["small_rng"] } +# fxhash = "0.2.1" [workspace] @@ -62,9 +62,9 @@ members = [ "packages/core-macro", "packages/html", "packages/hooks", - "packages/web", - "packages/webview", - "packages/ssr", + # "packages/web", + # "packages/webview", + # "packages/ssr", # "packages/atoms", # "packages/docsite", ] diff --git a/packages/core/examples/async.rs b/packages/core/examples/async.rs index a6a0749a7..ad67be67a 100644 --- a/packages/core/examples/async.rs +++ b/packages/core/examples/async.rs @@ -22,3 +22,15 @@ const App: FC<()> = |cx| { todo!() }; + +const Task: FC<()> = |cx| { + // + + let s = cx.use_task(|| async { "hello world".to_string() }); + + todo!() +}; + +fn use_mut(cx: Context

, f: impl FnOnce() -> T) -> &mut T { + todo!() +} diff --git a/packages/core/src/context.rs b/packages/core/src/context.rs index 01b9aaef7..b38b83b8e 100644 --- a/packages/core/src/context.rs +++ b/packages/core/src/context.rs @@ -2,9 +2,12 @@ use crate::hooklist::HookList; use crate::{arena::SharedArena, innerlude::*}; use appendlist::AppendList; use bumpalo::Bump; +use futures_util::{pin_mut, FutureExt}; use slotmap::DefaultKey; use slotmap::SlotMap; +use std::borrow::BorrowMut; use std::marker::PhantomData; +use std::sync::{Arc, RwLock}; use std::{ any::{Any, TypeId}, cell::{Cell, RefCell}, @@ -39,9 +42,9 @@ use std::{ pub struct Context<'src, T> { pub props: &'src T, pub scope: &'src Scope, - pub tasks: &'src RefCell>, + pub tasks: &'src RefCell>>, } -pub type PinnedTask = Pin>>; +// pub type PinnedTask = Pin>>; impl<'src, T> Copy for Context<'src, T> {} impl<'src, T> Clone for Context<'src, T> { @@ -263,18 +266,6 @@ Any function prefixed with "use" should not be called conditionally. ) } - pub fn suspend VNode<'src> + 'src>( - &'src self, - fut: &'src mut Pin + 'static>>, - callback: Fut, - ) -> VNode<'src> { - use futures_util::FutureExt; - match fut.now_or_never() { - Some(out) => callback(SuspendedContext {}, out), - None => NodeFactory::suspended(), - } - } - /// `submit_task` will submit the future to be polled. /// /// This is useful when you have some async task that needs to be progressed. @@ -289,11 +280,96 @@ Any function prefixed with "use" should not be called conditionally. /// /// /// - pub fn submit_task(&self, task: &'src mut PinnedTask) -> TaskHandle { - self.tasks.borrow_mut().push(task); + pub fn submit_task(&self, task: Pin>>) -> TaskHandle { + // let r = task.then(|f| async { + // // + // }); + // self.use_hook(|| Box::new(r), |_| {}, |_| {}); + // *task = task.then(|f| async { + // // + // t + // // () + // }); + todo!(); + // let new_fut = task.then(|f| async { + // // + // () + // }); + // self.tasks.borrow_mut().push(new_fut); TaskHandle { _p: PhantomData {} } } + + /// Awaits the given task, forcing the component to re-render when the value is ready. + /// + /// + pub fn use_task( + &self, + task_initializer: impl FnOnce() -> Fut + 'src, + ) -> &mut Option + where + Out: 'static, + Fut: Future, + { + struct TaskHook { + task_dump: Rc>>, + value: Option, + } + + // whenever the task is complete, save it into th + self.use_hook( + move || { + let task_fut = task_initializer(); + + let task_dump = Rc::new(RefCell::new(None)); + + let slot = task_dump.clone(); + + self.submit_task(Box::pin(task_fut.then(move |output| async move { + *slot.as_ref().borrow_mut() = Some(output); + }))); + + TaskHook { + task_dump, + value: None, + } + }, + |hook| { + if let Some(val) = hook.task_dump.as_ref().borrow_mut().take() { + hook.value = Some(val); + } + &mut hook.value + }, + |_| {}, + ) + } + + /// Asynchronously render new nodes once the given future has completed. + /// + /// + /// + /// + /// # Easda + /// + /// + /// # Example + /// + pub fn suspend( + &'src self, + task_initializer: impl FnOnce() -> Fut + 'src, + callback: impl FnOnce(SuspendedContext, Out) -> VNode<'src> + 'src, + ) -> VNode<'src> + where + Out: 'src, + Fut: Future, + { + todo!() + // use futures_util::FutureExt; + // match fut.now_or_never() { + // Some(out) => callback(SuspendedContext {}, out), + // None => NodeFactory::suspended(), + // } + } } pub struct TaskHandle<'src> { diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 2f51bfe2b..72cd3a2cb 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -343,9 +343,8 @@ where match &node.kind { VNodeKind::Text(text) => { let real_id = self.dom.create_text_node(text.text); - todo!() - // text.dom_id.set(real_id); - // CreateMeta::new(text.is_static, 1) + node.dom_id.set(real_id); + CreateMeta::new(text.is_static, 1) } VNodeKind::Element(el) => { // we have the potential to completely eliminate working on this node in the future(!) @@ -371,7 +370,7 @@ where } else { self.dom.create_element(tag_name, None) }; - // dom_id.set(real_id); + node.dom_id.set(real_id); listeners.iter().enumerate().for_each(|(idx, listener)| { listener.mounted_node.set(real_id); @@ -397,12 +396,12 @@ where // Notice: this is a web-specific optimization and may be changed in the future // // TODO move over - // if children.len() == 1 { - // if let VNodeKind::Text(text) = &children[0] { - // self.dom.set_text(text.text); - // return; - // } - // } + if children.len() == 1 { + if let VNodeKind::Text(text) = &children[0].kind { + self.dom.set_text(text.text); + return CreateMeta::new(is_static, 1); + } + } for child in *children { let child_meta = self.create(child); @@ -499,9 +498,8 @@ where } VNodeKind::Suspended => { - todo!(); - // let id = self.dom.create_placeholder(); - // real.set(id); + let id = self.dom.create_placeholder(); + node.dom_id.set(id); CreateMeta::new(false, 1) } } @@ -603,7 +601,6 @@ impl<'a, 'bump, Dom: RealDom<'bump>> DiffMachine<'a, 'bump, Dom> { old: &'bump [Attribute<'bump>], new: &'bump [Attribute<'bump>], namespace: Option<&'bump str>, - // is_namespaced: bool, ) { // Do O(n^2) passes to add/update and remove attributes, since // there are almost always very few attributes. diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 007c3ec0f..f63e85633 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -296,7 +296,7 @@ impl<'a> NodeFactory<'a> { // submit any async tasks to the scope for task in tasks.borrow_mut().drain(..) { - scp.submit_task(task); + // scp.submit_task(task); } let g2 = unsafe { std::mem::transmute(res) }; diff --git a/packages/webview/src/lib.rs b/packages/webview/src/lib.rs index 2e34b8806..0a2548ca0 100644 --- a/packages/webview/src/lib.rs +++ b/packages/webview/src/lib.rs @@ -5,6 +5,10 @@ use std::sync::{Arc, RwLock}; use dioxus_core::*; +use wry::application::event::{Event, WindowEvent}; +use wry::application::event_loop::{ControlFlow, EventLoop}; +use wry::application::window::Fullscreen; +use wry::webview::WebViewBuilder; use wry::{ application::window::{Window, WindowBuilder}, webview::{RpcRequest, RpcResponse}, @@ -57,15 +61,6 @@ impl WebviewRenderer { user_builder: impl FnOnce(WindowBuilder) -> WindowBuilder, redits: Option>>, ) -> anyhow::Result<()> { - use wry::{ - application::{ - event::{Event, StartCause, WindowEvent}, - event_loop::{ControlFlow, EventLoop}, - window::WindowBuilder, - }, - webview::WebViewBuilder, - }; - let event_loop = EventLoop::new(); let window = user_builder(WindowBuilder::new()).build(&event_loop)?; @@ -78,7 +73,7 @@ impl WebviewRenderer { let webview = WebViewBuilder::new(window)? .with_url(&format!("data:text/html,{}", HTML_CONTENT))? - .with_rpc_handler(move |window: &Window, mut req: RpcRequest| { + .with_rpc_handler(move |_window: &Window, mut req: RpcRequest| { match req.method.as_str() { "initiate" => { let edits = if let Some(edits) = &redits { @@ -144,45 +139,6 @@ impl WebviewRenderer { } } }); - - // let mut view = web_view::builder() - // .invoke_handler(|view, arg| { - // let handle = view.handle(); - // sender - // .send(InnerEvent::Initiate(handle)) - // .expect("should not fail"); - - // Ok(()) - // }) - // .content(web_view::Content::Html(HTML_CONTENT)) - // .user_data(()) - // .title(title) - // .size(width, height) - // .resizable(resizable) - // .debug(debug) - // .frameless(frameless) - // .visible(visible) - // .min_size(min_width, min_height) - // .build() - // .unwrap(); - // loop { - // view.step() - // .expect("should not fail") - // .expect("should not fail"); - // std::thread::sleep(std::time::Duration::from_millis(15)); - - // if let Ok(event) = receiver.try_recv() { - // if let InnerEvent::Initiate(handle) = event { - // let editlist = ref_edits.clone(); - // handle - // .dispatch(move |view| { - // let escaped = escape(&editlist); - // view.eval(&format!("EditListReceived({});", escaped)) - // }) - // .expect("Dispatch failed"); - // } - // } - // } } /// Create a new text-renderer instance from a functional component root. @@ -200,12 +156,12 @@ impl WebviewRenderer { } /// Pass new args to the root function - pub fn update(&mut self, new_val: T) { + pub fn update(&mut self, _new_val: T) { todo!() } /// Modify the root function in place, forcing a re-render regardless if the props changed - pub fn update_mut(&mut self, modifier: impl Fn(&mut T)) { + pub fn update_mut(&mut self, _modifier: impl Fn(&mut T)) { todo!() } } @@ -221,15 +177,6 @@ struct MessageParameters { } fn HANDLER(window: &Window, mut req: RpcRequest) -> Option { - use wry::{ - application::{ - event::{Event, WindowEvent}, - event_loop::{ControlFlow, EventLoop}, - window::{Fullscreen, Window, WindowBuilder}, - }, - webview::{RpcRequest, RpcResponse, WebViewBuilder}, - }; - let mut response = None; if &req.method == "fullscreen" { if let Some(params) = req.params.take() { @@ -262,91 +209,3 @@ fn HANDLER(window: &Window, mut req: RpcRequest) -> Option { response } - -pub struct DioxusWebviewBuilder<'a> { - pub(crate) title: &'a str, - pub(crate) width: i32, - pub(crate) height: i32, - pub(crate) resizable: bool, - pub(crate) debug: bool, - pub(crate) frameless: bool, - pub(crate) visible: bool, - pub(crate) min_width: i32, - pub(crate) min_height: i32, -} -impl<'a> DioxusWebviewBuilder<'a> { - fn new() -> Self { - #[cfg(debug_assertions)] - let debug = true; - #[cfg(not(debug_assertions))] - let debug = false; - - DioxusWebviewBuilder { - title: "Application", - width: 800, - height: 600, - resizable: true, - debug, - frameless: false, - visible: true, - min_width: 300, - min_height: 300, - } - } - /// Sets the title of the WebView window. - /// - /// Defaults to `"Application"`. - pub fn title(mut self, title: &'a str) -> Self { - self.title = title; - self - } - - /// Sets the size of the WebView window. - /// - /// Defaults to 800 x 600. - pub fn size(mut self, width: i32, height: i32) -> Self { - self.width = width; - self.height = height; - self - } - - /// Sets the resizability of the WebView window. If set to false, the window cannot be resized. - /// - /// Defaults to `true`. - pub fn resizable(mut self, resizable: bool) -> Self { - self.resizable = resizable; - self - } - - /// Enables or disables debug mode. - /// - /// Defaults to `true` for debug builds, `false` for release builds. - pub fn debug(mut self, debug: bool) -> Self { - self.debug = debug; - self - } - /// The window crated will be frameless - /// - /// defaults to `false` - pub fn frameless(mut self, frameless: bool) -> Self { - self.frameless = frameless; - self - } - - /// Set the visibility of the WebView window. - /// - /// defaults to `true` - pub fn visible(mut self, visible: bool) -> Self { - self.visible = visible; - self - } - - /// Sets the minimum size of the WebView window. - /// - /// Defaults to 300 x 300. - pub fn min_size(mut self, width: i32, height: i32) -> Self { - self.min_width = width; - self.min_height = height; - self - } -}