ソースを参照

wip: cut down on errors

Jonathan Kelley 4 年 前
コミット
775e9e29b8

+ 19 - 19
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",
 ]

+ 12 - 0
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<P, T>(cx: Context<P>, f: impl FnOnce() -> T) -> &mut T {
+    todo!()
+}

+ 92 - 16
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<Vec<&'src mut PinnedTask>>,
+    pub tasks: &'src RefCell<Vec<&'src mut dyn Future<Output = ()>>>,
 }
-pub type PinnedTask = Pin<Box<dyn Future<Output = ()>>>;
+// pub type PinnedTask = Pin<Box<dyn Future<Output = ()>>>;
 
 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<Output: 'src, Fut: FnOnce(SuspendedContext, Output) -> VNode<'src> + 'src>(
-        &'src self,
-        fut: &'src mut Pin<Box<dyn Future<Output = Output> + '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<Box<dyn Future<Output = ()>>>) -> 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<Out, Fut: 'static>(
+        &self,
+        task_initializer: impl FnOnce() -> Fut + 'src,
+    ) -> &mut Option<Out>
+    where
+        Out: 'static,
+        Fut: Future<Output = Out>,
+    {
+        struct TaskHook<T> {
+            task_dump: Rc<RefCell<Option<T>>>,
+            value: Option<T>,
+        }
+
+        // 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<Out, Fut: 'static>(
+        &'src self,
+        task_initializer: impl FnOnce() -> Fut + 'src,
+        callback: impl FnOnce(SuspendedContext, Out) -> VNode<'src> + 'src,
+    ) -> VNode<'src>
+    where
+        Out: 'src,
+        Fut: Future<Output = Out>,
+    {
+        todo!()
+        // use futures_util::FutureExt;
+        // match fut.now_or_never() {
+        //     Some(out) => callback(SuspendedContext {}, out),
+        //     None => NodeFactory::suspended(),
+        // }
+    }
 }
 
 pub struct TaskHandle<'src> {

+ 11 - 14
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.

+ 1 - 1
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) };

+ 7 - 148
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<T: Properties + 'static> WebviewRenderer<T> {
         user_builder: impl FnOnce(WindowBuilder) -> WindowBuilder,
         redits: Option<Vec<DomEdit<'static>>>,
     ) -> 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<T: Properties + 'static> WebviewRenderer<T> {
 
         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<T: Properties + 'static> WebviewRenderer<T> {
                 }
             }
         });
-
-        // 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<T: Properties + 'static> WebviewRenderer<T> {
     }
 
     /// 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<RpcResponse> {
-    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<RpcResponse> {
 
     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
-    }
-}