diff --git a/.vscode/spellright.dict b/.vscode/spellright.dict index c157c79ac..dc23c861e 100644 --- a/.vscode/spellright.dict +++ b/.vscode/spellright.dict @@ -4,3 +4,5 @@ tide_ssr Liveview Dioxus VDoms +Tauri +webview diff --git a/examples/Cargo.toml b/examples/Cargo.toml index e97502bfc..aef0d2331 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -12,6 +12,7 @@ log = "0.4.1" dioxus = { path = "../packages/dioxus" } dioxus-ssr = { path = "../packages/ssr" } rand = "0.8.2" +anyhow = "*" [dev-dependencies] @@ -22,9 +23,7 @@ tide = { version = "0.15.0" } # For the doc generator pulldown-cmark = { version = "0.8.0", default-features = false } - -anyhow = "*" - +dioxus-webview = { path = "../packages/webview", version = "0.0.0" } [lib] path = "common.rs" @@ -48,3 +47,7 @@ name = "router" [[example]] path = "fc_macro.rs" name = "fc_macro" + +[[example]] +path = "webview.rs" +name = "webview" diff --git a/examples/webview.rs b/examples/webview.rs new file mode 100644 index 000000000..eaba4ddab --- /dev/null +++ b/examples/webview.rs @@ -0,0 +1,23 @@ +use dioxus::prelude::*; + +fn main() { + let app = dioxus_webview::new::<()>(|ctx| { + let (count, set_count) = use_state(ctx, || 0); + html! { +
+

"Dioxus Desktop Demo"

+

"Count is {count}"

+ +
+ } + }); + + app.launch(()); +} + +fn use_state(ctx: &mut Context, init: impl Fn() -> T) -> (T, impl Fn(T)) { + let g = init(); + (g, |_| {}) +} diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 87f52b92c..371ba1ca3 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -154,6 +154,11 @@ pub mod virtual_dom { } impl<'a, T> Context<'a, T> { + /// Access the children elements passed into the component + pub fn children(&self) -> Vec { + todo!("Children API not yet implemented for component Context") + } + /// Access a parent context pub fn parent_context(&self) -> C { todo!("Context API is not ready yet") diff --git a/packages/webview/Cargo.toml b/packages/webview/Cargo.toml index b5dae6d27..389221caf 100644 --- a/packages/webview/Cargo.toml +++ b/packages/webview/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -webview = "0.1.1" +web-view = "0.7.2" +dioxus-core = { path = "../core" } diff --git a/packages/webview/README.md b/packages/webview/README.md index d406f5246..2cc617541 100644 --- a/packages/webview/README.md +++ b/packages/webview/README.md @@ -6,7 +6,8 @@ Dioxus-webview is an attempt at making a simpler "Tauri" where creating desktop ```rust // main.rs -fn main() { +#[async_std::main] +async fn main() { dioxus_webview::new(|ctx| { let (count, set_count) = use_state(ctx, || 0); html! { @@ -22,7 +23,8 @@ fn main() { .configure_webview(|view| { // custom webview config options }) - .launch(); + .launch() + .await; } ``` @@ -37,3 +39,10 @@ dioxus bundle --platform macOS Because the host VirtualDOM is running in its own native process, native applications can unlock their full potential. Dioxus-webview is designed to be a 100% rust alternative to ElectronJS without the memory overhead or bloat of ElectronJS apps. By bridging the native process, desktop apps can access full multithreading power, peripheral support, hardware access, and native filesystem controls without the hassle of web technologies. Our goal with Dioxus-webview is to make it easy to ship both a web and native application, and quickly see large performance boosts without having to re-write the whole stack. As the dioxus ecosystem grows, we hope to see 3rd parties providing wrappers for storage, offline mode, etc that supports both web and native technologies. + + +## Tech + +Dioxus-desktop is a pure liveview application where all of the state and event handlers are proxied through the liveview and into the native process. For pure server-based liveview, this would normally be too slow (in both render performance and latency), but because the VDom is local, desktop apps are just as fast as Electron. + +Dioxus-desktop leverages dioxus-liveview under the hood, but with convenience wrappers around setting up the VDom bridge, proxying events, and serving the initial WebSys-Renderer. The backend is served by Tide, so an async runtime is needed to diff --git a/packages/webview/src/lib.rs b/packages/webview/src/lib.rs index 31e1bb209..c0ad17736 100644 --- a/packages/webview/src/lib.rs +++ b/packages/webview/src/lib.rs @@ -1,7 +1,75 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); +use dioxus_core::prelude::*; +use web_view::WebViewBuilder; + +pub fn new(root: FC) -> WebviewRenderer { + WebviewRenderer::new(root) +} + +/// The `WebviewRenderer` provides a way of rendering a Dioxus Virtual DOM through a bridge to a Webview instance. +/// Components used in WebviewRenderer instances can directly use system libraries, access the filesystem, and multithread with ease. +pub struct WebviewRenderer { + /// The root component used to render the Webview + root: FC, +} + +impl WebviewRenderer { + /// Create a new text-renderer instance from a functional component root. + /// Automatically progresses the creation of the VNode tree to completion. + /// + /// A VDom is automatically created. If you want more granular control of the VDom, use `from_vdom` + pub fn new(root: FC) -> Self { + Self { root } + } + + /// Create a new text renderer from an existing Virtual DOM. + /// This will progress the existing VDom's events to completion. + pub fn from_vdom() -> Self { + todo!() + } + + /// Pass new args to the root function + 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)) { + todo!() + } + + pub async fn launch(self, props: T) { + let mut ctx = Context { props: &props }; + let WebviewRenderer { root } = self; + let content = root(&mut ctx); + let html_content = content.to_string(); + /* + TODO: @Jon + Launch the webview with a premade VDom app + */ + + web_view::builder() + .title("My Project") + .content(web_view::Content::Html(html_content)) + .size(320, 480) + .resizable(true) + .debug(true) + .user_data(()) + .invoke_handler(|_webview, _arg| Ok(())) + .run() + .unwrap(); } } + +mod receiver { + use dioxus_core::prelude::*; + + /// The receiver app is a container that builds a connection to the host process that shuttles events and patches. + pub(crate) static ReceiverApp: FC<()> = |ctx| { + // + html! { +
+ {} +
+ } + }; +}