From 37a8fb539161ceeb6dc4da33976067a995460e69 Mon Sep 17 00:00:00 2001 From: Kaid Date: Mon, 5 Jun 2023 16:47:04 +0800 Subject: [PATCH 01/25] Add directory support for file input. --- examples/file_upload.rs | 13 ++++++---- packages/desktop/src/file_upload.rs | 25 +++++++++++++++---- packages/desktop/src/protocol.rs | 2 +- packages/html/src/elements.rs | 1 + .../interpreter/src/sledgehammer_bindings.rs | 1 + 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/examples/file_upload.rs b/examples/file_upload.rs index b23648b50..502d32bd8 100644 --- a/examples/file_upload.rs +++ b/examples/file_upload.rs @@ -1,5 +1,6 @@ #![allow(non_snake_case)] use dioxus::prelude::*; +use tokio::time::sleep; fn main() { dioxus_desktop::launch(App); @@ -13,20 +14,22 @@ fn App(cx: Scope) -> Element { r#type: "file", accept: ".txt, .rs", multiple: true, + directory: true, onchange: |evt| { to_owned![files_uploaded]; async move { if let Some(file_engine) = &evt.files { let files = file_engine.files(); - for file_name in &files { - if let Some(file) = file_engine.read_file_to_string(file_name).await{ - files_uploaded.write().push(file); - } + for file_name in files { + sleep(std::time::Duration::from_secs(1)).await; + files_uploaded.write().push(file_name); } } } }, - } + }, + + div { "progress: {files_uploaded.read().len()}" }, ul { for file in files_uploaded.read().iter() { diff --git a/packages/desktop/src/file_upload.rs b/packages/desktop/src/file_upload.rs index 1b24ffc55..b815064ec 100644 --- a/packages/desktop/src/file_upload.rs +++ b/packages/desktop/src/file_upload.rs @@ -7,14 +7,21 @@ pub(crate) struct FileDiologRequest { #[serde(default)] accept: Option, multiple: bool, + directory: bool, pub event: String, pub target: usize, pub bubbles: bool, } -pub(crate) fn get_file_event(request: &FileDiologRequest) -> Vec { - let mut dialog = rfd::FileDialog::new(); +fn get_file_event_for_folder(request: &FileDiologRequest, dialog: rfd::FileDialog) -> Vec { + if request.multiple { + dialog.pick_folders().into_iter().flatten().collect() + } else { + dialog.pick_folder().into_iter().collect() + } +} +fn get_file_event_for_file(request: &FileDiologRequest, mut dialog: rfd::FileDialog) -> Vec { let filters: Vec<_> = request .accept .as_deref() @@ -30,13 +37,21 @@ pub(crate) fn get_file_event(request: &FileDiologRequest) -> Vec { dialog = dialog.add_filter("name", file_extensions.as_slice()); - let files: Vec<_> = if request.multiple { + if request.multiple { dialog.pick_files().into_iter().flatten().collect() } else { dialog.pick_file().into_iter().collect() - }; + } +} - files +pub(crate) fn get_file_event(request: &FileDiologRequest) -> Vec { + let dialog = rfd::FileDialog::new(); + + if request.directory { + get_file_event_for_folder(request, dialog) + } else { + get_file_event_for_file(request, dialog) + } } enum Filters { diff --git a/packages/desktop/src/protocol.rs b/packages/desktop/src/protocol.rs index 6be5d08b4..25e276003 100644 --- a/packages/desktop/src/protocol.rs +++ b/packages/desktop/src/protocol.rs @@ -24,7 +24,7 @@ fn module_loader(root_name: &str) -> String { let target_id = find_real_id(target); if (target_id !== null) { const send = (event_name) => { - const message = serializeIpcMessage("file_diolog", { accept: target.getAttribute("accept"), multiple: target.hasAttribute("multiple"), target: parseInt(target_id), bubbles: event_bubbles(event_name), event: event_name }); + const message = serializeIpcMessage("file_diolog", { accept: target.getAttribute("accept"), directory: target.hasAttribute("directory"), multiple: target.hasAttribute("multiple"), target: parseInt(target_id), bubbles: event_bubbles(event_name), event: event_name }); window.ipc.postMessage(message); }; send("change&input"); diff --git a/packages/html/src/elements.rs b/packages/html/src/elements.rs index e1e80057e..ed001a843 100644 --- a/packages/html/src/elements.rs +++ b/packages/html/src/elements.rs @@ -1098,6 +1098,7 @@ builder_constructors! { autofocus: Bool DEFAULT, capture: String DEFAULT, checked: Bool DEFAULT, + directory: Bool DEFAULT, disabled: Bool DEFAULT, form: Id DEFAULT, formaction: Uri DEFAULT, diff --git a/packages/interpreter/src/sledgehammer_bindings.rs b/packages/interpreter/src/sledgehammer_bindings.rs index 6c2804b59..02c2cc8dd 100644 --- a/packages/interpreter/src/sledgehammer_bindings.rs +++ b/packages/interpreter/src/sledgehammer_bindings.rs @@ -143,6 +143,7 @@ mod js { autofocus: true, autoplay: true, checked: true, + directory: true, controls: true, default: true, defer: true, From 277436f673c806f37fab4c90621e868632183f00 Mon Sep 17 00:00:00 2001 From: Kaid Date: Tue, 6 Jun 2023 08:06:27 +0800 Subject: [PATCH 02/25] Changed underlying directory attribute to `webkitdirectory`, fixed attribute parsing to properly toggle it. --- examples/file_upload.rs | 14 +++++++++++++- packages/desktop/src/file_upload.rs | 5 ++++- packages/desktop/src/protocol.rs | 2 +- packages/html/src/elements.rs | 2 +- packages/interpreter/src/sledgehammer_bindings.rs | 2 +- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/examples/file_upload.rs b/examples/file_upload.rs index 502d32bd8..888459574 100644 --- a/examples/file_upload.rs +++ b/examples/file_upload.rs @@ -7,14 +7,26 @@ fn main() { } fn App(cx: Scope) -> Element { + let enable_directory_upload = use_state(cx, || false); let files_uploaded: &UseRef> = use_ref(cx, Vec::new); cx.render(rsx! { + label { + input { + r#type: "checkbox", + checked: "{enable_directory_upload}", + oninput: move |evt| { + enable_directory_upload.set(evt.value.parse().unwrap()); + }, + }, + "Enable directory upload" + } + input { r#type: "file", accept: ".txt, .rs", multiple: true, - directory: true, + directory: **enable_directory_upload, onchange: |evt| { to_owned![files_uploaded]; async move { diff --git a/packages/desktop/src/file_upload.rs b/packages/desktop/src/file_upload.rs index b815064ec..307577168 100644 --- a/packages/desktop/src/file_upload.rs +++ b/packages/desktop/src/file_upload.rs @@ -21,7 +21,10 @@ fn get_file_event_for_folder(request: &FileDiologRequest, dialog: rfd::FileDialo } } -fn get_file_event_for_file(request: &FileDiologRequest, mut dialog: rfd::FileDialog) -> Vec { +fn get_file_event_for_file( + request: &FileDiologRequest, + mut dialog: rfd::FileDialog, +) -> Vec { let filters: Vec<_> = request .accept .as_deref() diff --git a/packages/desktop/src/protocol.rs b/packages/desktop/src/protocol.rs index 25e276003..89ce50a48 100644 --- a/packages/desktop/src/protocol.rs +++ b/packages/desktop/src/protocol.rs @@ -24,7 +24,7 @@ fn module_loader(root_name: &str) -> String { let target_id = find_real_id(target); if (target_id !== null) { const send = (event_name) => { - const message = serializeIpcMessage("file_diolog", { accept: target.getAttribute("accept"), directory: target.hasAttribute("directory"), multiple: target.hasAttribute("multiple"), target: parseInt(target_id), bubbles: event_bubbles(event_name), event: event_name }); + const message = serializeIpcMessage("file_diolog", { accept: target.getAttribute("accept"), directory: target.getAttribute("webkitdirectory") === "true", multiple: target.hasAttribute("multiple"), target: parseInt(target_id), bubbles: event_bubbles(event_name), event: event_name }); window.ipc.postMessage(message); }; send("change&input"); diff --git a/packages/html/src/elements.rs b/packages/html/src/elements.rs index ed001a843..514aea2d1 100644 --- a/packages/html/src/elements.rs +++ b/packages/html/src/elements.rs @@ -1098,7 +1098,7 @@ builder_constructors! { autofocus: Bool DEFAULT, capture: String DEFAULT, checked: Bool DEFAULT, - directory: Bool DEFAULT, + directory: Bool "webkitdirectory", disabled: Bool DEFAULT, form: Id DEFAULT, formaction: Uri DEFAULT, diff --git a/packages/interpreter/src/sledgehammer_bindings.rs b/packages/interpreter/src/sledgehammer_bindings.rs index 02c2cc8dd..508c78a7a 100644 --- a/packages/interpreter/src/sledgehammer_bindings.rs +++ b/packages/interpreter/src/sledgehammer_bindings.rs @@ -143,10 +143,10 @@ mod js { autofocus: true, autoplay: true, checked: true, - directory: true, controls: true, default: true, defer: true, + directory: true, disabled: true, formnovalidate: true, hidden: true, From d27af03e3f4fb697bb3f9ce2d03f78c270dad368 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 14 Jul 2023 13:52:54 -0700 Subject: [PATCH 03/25] Remove the dioxus bin from the cli --- packages/cli/Cargo.toml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index c947baa63..3aa741615 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -86,13 +86,6 @@ dioxus-core = { workspace = true, features = ["serialize"] } default = [] plugin = ["mlua"] -# install path dx and dioxus as the same command -# so, they're not really aliases -# eventually dx will defer to the right version of dioxus -[[bin]] -path = "src/main.rs" -name = "dioxus" - [[bin]] path = "src/main.rs" name = "dx" From 16763c065bf1d0a0d6a3c4a9e72f91d3e1c81de9 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 14 Jul 2023 13:53:06 -0700 Subject: [PATCH 04/25] Rename dioxus to dx in examples and fullstack --- docs/guide/src/en/fullstack/getting_started.md | 4 ++-- docs/guide/src/en/fullstack/server_functions.md | 2 +- examples/PWA-example/README.md | 6 +++--- notes/FAQ.md | 2 +- packages/cli/Dioxus.toml | 4 ++-- packages/cli/README.md | 4 ++-- packages/cli/docs/src/cmd/README.md | 6 +++--- packages/cli/docs/src/cmd/build.md | 16 ++++++++-------- packages/cli/docs/src/cmd/clean.md | 4 ++-- packages/cli/docs/src/cmd/serve.md | 6 +++--- packages/cli/docs/src/cmd/translate.md | 6 +++--- packages/cli/docs/src/configure.md | 4 ++-- packages/cli/docs/src/creating.md | 2 +- packages/cli/docs/src/plugin/README.md | 4 ++-- packages/cli/src/assets/dioxus.toml | 2 +- packages/cli/src/builder.rs | 4 ++-- packages/cli/src/cli/plugin/mod.rs | 2 +- .../examples/axum-hello-world/src/main.rs | 4 ++-- .../fullstack/examples/axum-router/src/main.rs | 4 ++-- .../examples/salvo-hello-world/src/main.rs | 4 ++-- .../examples/warp-hello-world/src/main.rs | 4 ++-- playwrite-tests/fullstack/src/main.rs | 2 +- 22 files changed, 48 insertions(+), 48 deletions(-) diff --git a/docs/guide/src/en/fullstack/getting_started.md b/docs/guide/src/en/fullstack/getting_started.md index 9511b8a6c..401af1d43 100644 --- a/docs/guide/src/en/fullstack/getting_started.md +++ b/docs/guide/src/en/fullstack/getting_started.md @@ -76,7 +76,7 @@ Next, we need to modify our `main.rs` to use either hydrate on the client or ren {{#include ../../../examples/hydration.rs}} ``` -Now, build your client-side bundle with `dioxus build --features web` and run your server with `cargo run --features ssr`. You should see the same page as before, but now you can interact with the buttons! +Now, build your client-side bundle with `dx build --features web` and run your server with `cargo run --features ssr`. You should see the same page as before, but now you can interact with the buttons! ## Sycronizing props between the server and client @@ -99,4 +99,4 @@ The only thing we need to change on the client is the props. `dioxus-fullstack` {{#include ../../../examples/hydration_props.rs}} ``` -Now, build your client-side bundle with `dioxus build --features web` and run your server with `cargo run --features ssr`. Navigate to `http://localhost:8080/1` and you should see the counter start at 1. Navigate to `http://localhost:8080/2` and you should see the counter start at 2. +Now, build your client-side bundle with `dx build --features web` and run your server with `cargo run --features ssr`. Navigate to `http://localhost:8080/1` and you should see the counter start at 1. Navigate to `http://localhost:8080/2` and you should see the counter start at 2. diff --git a/docs/guide/src/en/fullstack/server_functions.md b/docs/guide/src/en/fullstack/server_functions.md index 57883885a..581aa382a 100644 --- a/docs/guide/src/en/fullstack/server_functions.md +++ b/docs/guide/src/en/fullstack/server_functions.md @@ -24,7 +24,7 @@ Next, add the server function to your `main.rs`: {{#include ../../../examples/server_function.rs}} ``` -Now, build your client-side bundle with `dioxus build --features web` and run your server with `cargo run --features ssr`. You should see a new button that multiplies the count by 2. +Now, build your client-side bundle with `dx build --features web` and run your server with `cargo run --features ssr`. You should see a new button that multiplies the count by 2. ## Conclusion diff --git a/examples/PWA-example/README.md b/examples/PWA-example/README.md index dfd986302..d42a61311 100644 --- a/examples/PWA-example/README.md +++ b/examples/PWA-example/README.md @@ -9,8 +9,8 @@ It is also very much usable as a template for your projects, if you're aiming to Make sure you have Dioxus CLI installed (if you're unsure, run `cargo install dioxus-cli`). -You can run `dioxus serve` in this directory to start the web server locally, or run -`dioxus build --release` to build the project so you can deploy it on a separate web-server. +You can run `dx serve` in this directory to start the web server locally, or run +`dx build --release` to build the project so you can deploy it on a separate web-server. ## Project Structure ``` @@ -41,4 +41,4 @@ For service worker scripting (in JavaScript): * [Service worker guide from PWABuilder](https://docs.pwabuilder.com/#/home/sw-intro) * [Service worker examples, also from PWABuilder](https://github.com/pwa-builder/pwabuilder-serviceworkers) -If you want to stay as close to 100% Rust as possible, you can try using [wasi-worker](https://github.com/dunnock/wasi-worker) to replace the JS service worker file. The JSON manifest will still be required though. \ No newline at end of file +If you want to stay as close to 100% Rust as possible, you can try using [wasi-worker](https://github.com/dunnock/wasi-worker) to replace the JS service worker file. The JSON manifest will still be required though. diff --git a/notes/FAQ.md b/notes/FAQ.md index 4e9ea00e4..a94071130 100644 --- a/notes/FAQ.md +++ b/notes/FAQ.md @@ -18,7 +18,7 @@ There are plenty Rust Elm-like frameworks in the world - we were not interested The `RSX` DSL is _barely_ a DSL. Rustaceans will find the DSL very similar to simply assembling nested structs, but without the syntactical overhead of "Default" everywhere or having to jump through hoops with the builder pattern. Between RSX, HTML, the Raw Factory API, and the NodeBuilder syntax, there's plenty of options to choose from. ### What are the build times like? Why on earth would I choose Rust instead of JS/TS/Elm? -Dioxus builds as roughly as fast as a complex WebPack-TypeScript site. Compile times will be slower than an equivalent TypeScript site, but not unbearably slow. The Wasm compiler backend for Rust is very fast. Iterating on small components is basically instant and larger apps takes a few seconds. In practice, the compiler guarantees of Rust balance out the rebuild times. +dx builds as roughly as fast as a complex WebPack-TypeScript site. Compile times will be slower than an equivalent TypeScript site, but not unbearably slow. The Wasm compiler backend for Rust is very fast. Iterating on small components is basically instant and larger apps takes a few seconds. In practice, the compiler guarantees of Rust balance out the rebuild times. ### What about Yew/Seed/Sycamore/Dominator/Dodrio/Percy? - Yew and Seed use an Elm-like pattern and don't support SSR or any alternate rendering platforms diff --git a/packages/cli/Dioxus.toml b/packages/cli/Dioxus.toml index c3e0dd8a0..792a15165 100644 --- a/packages/cli/Dioxus.toml +++ b/packages/cli/Dioxus.toml @@ -4,7 +4,7 @@ name = "dioxus-cli" # default platfrom -# you can also use `dioxus serve/build --platform XXX` to use other platform +# you can also use `dx serve/build --platform XXX` to use other platform # value: web | desktop default_platform = "desktop" @@ -42,4 +42,4 @@ script = [] # use binaryen.wasm-opt for output Wasm file # binaryen just will trigger in `web` platform -binaryen = { wasm_opt = true } \ No newline at end of file +binaryen = { wasm_opt = true } diff --git a/packages/cli/README.md b/packages/cli/README.md index 6f0826e10..3167a6746 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -24,7 +24,7 @@ cargo install --path . --debug ## Get Started -Use `dioxus create project-name` to initialize a new Dioxus project.
+Use `dx create project-name` to initialize a new Dioxus project.
It will be cloned from the [dioxus-template](https://github.com/DioxusLabs/dioxus-template) repository. @@ -33,7 +33,7 @@ It will be cloned from the [dioxus-template](https://github.com/DioxusLabs/dioxu Alternatively, you can specify the template path: ``` -dioxus create hello --template gh:dioxuslabs/dioxus-template +dx create hello --template gh:dioxuslabs/dioxus-template ``` ## Dioxus Config File diff --git a/packages/cli/docs/src/cmd/README.md b/packages/cli/docs/src/cmd/README.md index dae226577..30586d73a 100644 --- a/packages/cli/docs/src/cmd/README.md +++ b/packages/cli/docs/src/cmd/README.md @@ -2,10 +2,10 @@ In this chapter we will introduce all `dioxus-cli` commands. -> You can also use `dioxus --help` to get cli help info. +> You can also use `dx --help` to get cli help info. ``` -dioxus +dioxus Build, bundle, & ship your Dioxus app USAGE: @@ -23,4 +23,4 @@ SUBCOMMANDS: help Print this message or the help of the given subcommand(s) serve Build, watch & serve the Rust WASM app and all of its assets translate Translate some html file into a Dioxus component -``` \ No newline at end of file +``` diff --git a/packages/cli/docs/src/cmd/build.md b/packages/cli/docs/src/cmd/build.md index 1fb892475..d0444721e 100644 --- a/packages/cli/docs/src/cmd/build.md +++ b/packages/cli/docs/src/cmd/build.md @@ -1,13 +1,13 @@ # Build -The `dioxus build` command can help you `pack & build` a dioxus project. +The `dx build` command can help you `pack & build` a dioxus project. ``` -dioxus-build +dioxus-build Build the Rust WASM app and all of its assets USAGE: - dioxus build [OPTIONS] + dx build [OPTIONS] OPTIONS: --example [default: ""] @@ -18,7 +18,7 @@ OPTIONS: You can use this command to build a project: ``` -dioxus build --release +dx build --release ``` ## Target platform @@ -27,14 +27,14 @@ Use the `platform` option to choose your target platform: ``` # for desktop project -dioxus build --platform desktop +dx build --platform desktop ``` `platform` currently only supports `desktop` & `web`. ``` # for web project -dioxus build --platform web +dx build --platform web ``` ## Build Example @@ -43,5 +43,5 @@ You can use the `example` option to select a example to build: ``` # build the `test` example -dioxus build --exmaple test -``` \ No newline at end of file +dx build --exmaple test +``` diff --git a/packages/cli/docs/src/cmd/clean.md b/packages/cli/docs/src/cmd/clean.md index bbb3a132e..eef83a2a9 100644 --- a/packages/cli/docs/src/cmd/clean.md +++ b/packages/cli/docs/src/cmd/clean.md @@ -1,9 +1,9 @@ # Clean -`dioxus clean` will clear the build artifacts (the out_dir and the cargo cache) +`dx clean` will clear the build artifacts (the out_dir and the cargo cache) ``` -dioxus-clean +dioxus-clean Clean build artifacts USAGE: diff --git a/packages/cli/docs/src/cmd/serve.md b/packages/cli/docs/src/cmd/serve.md index 41abf5350..5b1f411dd 100644 --- a/packages/cli/docs/src/cmd/serve.md +++ b/packages/cli/docs/src/cmd/serve.md @@ -1,9 +1,9 @@ # Serve -The `dioxus serve` can start a dev server with hot-reloading +The `dx serve` can start a dev server with hot-reloading ``` -dioxus-serve +dioxus-serve Build, watch & serve the Rust WASM app and all of its assets USAGE: @@ -58,4 +58,4 @@ You can add the `cross-origin-policy` option to change cross-origin header to: ``` dioxus serve --corss-origin-policy -``` \ No newline at end of file +``` diff --git a/packages/cli/docs/src/cmd/translate.md b/packages/cli/docs/src/cmd/translate.md index 7237e1dcf..0fb3ed8c9 100644 --- a/packages/cli/docs/src/cmd/translate.md +++ b/packages/cli/docs/src/cmd/translate.md @@ -1,9 +1,9 @@ # Translate -`dioxus translate` can translate some `html` file into a Dioxus compoent +`dx translate` can translate some `html` file into a Dioxus compoent ``` -dioxus-translate +dioxus-translate Translate some source file into a Dioxus component USAGE: @@ -65,4 +65,4 @@ fn component(cx: Scope) -> Element { } }) } -``` \ No newline at end of file +``` diff --git a/packages/cli/docs/src/configure.md b/packages/cli/docs/src/configure.md index 35904caae..8da66d9ec 100644 --- a/packages/cli/docs/src/configure.md +++ b/packages/cli/docs/src/configure.md @@ -29,8 +29,8 @@ General application confiration: # default: web default_platform = "web" ``` - if you change this to `desktop`, the `dioxus build` will default building a desktop app -3. ***out_dir*** - The directory to place the build artifacts from `dioxus build` or `dioxus service` into. This is also where the `assets` directory will be copied to + if you change this to `desktop`, the `dx build` will default building a desktop app +3. ***out_dir*** - The directory to place the build artifacts from `dx build` or `dx service` into. This is also where the `assets` directory will be copied to ``` out_dir = "dist" ``` diff --git a/packages/cli/docs/src/creating.md b/packages/cli/docs/src/creating.md index 5bb98fd10..c5d791013 100644 --- a/packages/cli/docs/src/creating.md +++ b/packages/cli/docs/src/creating.md @@ -4,7 +4,7 @@ Once you have the Dioxus CLI tool installed, you can use it to create dioxus pro ## Initializing a default project -First, run the `dioxus create` command to create a new project ready to be used with Dioxus and the Dioxus CLI: +First, run the `dx create` command to create a new project ready to be used with Dioxus and the Dioxus CLI: ``` dioxus create hello-dioxus diff --git a/packages/cli/docs/src/plugin/README.md b/packages/cli/docs/src/plugin/README.md index 9983f024b..0a1a7b606 100644 --- a/packages/cli/docs/src/plugin/README.md +++ b/packages/cli/docs/src/plugin/README.md @@ -2,7 +2,7 @@ > For Cli 0.2.0 we will add `plugin-develop` support. -Before the 0.2.0 we use `dioxus tool` to use & install some plugin, but we think that is not good for extend cli program, some people want tailwind support, some people want sass support, we can't add all this thing in to the cli source code and we don't have time to maintain a lot of tools that user request, so maybe user make plugin by themself is a good choice. +Before the 0.2.0 we use `dx tool` to use & install some plugin, but we think that is not good for extend cli program, some people want tailwind support, some people want sass support, we can't add all this thing in to the cli source code and we don't have time to maintain a lot of tools that user request, so maybe user make plugin by themself is a good choice. ### Why Lua ? @@ -76,4 +76,4 @@ end manager.serve.interval = 1000 return manager -``` \ No newline at end of file +``` diff --git a/packages/cli/src/assets/dioxus.toml b/packages/cli/src/assets/dioxus.toml index 3827d0f8f..dfdeb9f92 100644 --- a/packages/cli/src/assets/dioxus.toml +++ b/packages/cli/src/assets/dioxus.toml @@ -4,7 +4,7 @@ name = "{{project-name}}" # default platfrom -# you can also use `dioxus serve/build --platform XXX` to use other platform +# you can also use `dx serve/build --platform XXX` to use other platform # value: web | desktop default_platform = "{{default-platform}}" diff --git a/packages/cli/src/builder.rs b/packages/cli/src/builder.rs index 6f50fc49d..cf7ccd7b3 100644 --- a/packages/cli/src/builder.rs +++ b/packages/cli/src/builder.rs @@ -161,7 +161,7 @@ pub fn build(config: &CrateConfig, quiet: bool) -> Result { } } else { log::warn!( - "Binaryen tool not found, you can use `dioxus tool add binaryen` to install it." + "Binaryen tool not found, you can use `dx tool add binaryen` to install it." ); } } @@ -200,7 +200,7 @@ pub fn build(config: &CrateConfig, quiet: bool) -> Result { } } else { log::warn!( - "Tailwind tool not found, you can use `dioxus tool add tailwindcss` to install it." + "Tailwind tool not found, you can use `dx tool add tailwindcss` to install it." ); } } diff --git a/packages/cli/src/cli/plugin/mod.rs b/packages/cli/src/cli/plugin/mod.rs index 812c3ae1c..9f514edec 100644 --- a/packages/cli/src/cli/plugin/mod.rs +++ b/packages/cli/src/cli/plugin/mod.rs @@ -31,7 +31,7 @@ impl Plugin { } } Plugin::Add { name: _ } => { - log::info!("You can use `dioxus plugin app-path` to get Installation position"); + log::info!("You can use `dx plugin app-path` to get Installation position"); } } Ok(()) diff --git a/packages/fullstack/examples/axum-hello-world/src/main.rs b/packages/fullstack/examples/axum-hello-world/src/main.rs index 5ded85070..6b919aa42 100644 --- a/packages/fullstack/examples/axum-hello-world/src/main.rs +++ b/packages/fullstack/examples/axum-hello-world/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr --no-default-features //! ``` @@ -21,7 +21,7 @@ fn main() { { // Start hot reloading hot_reload_init!(dioxus_hot_reload::Config::new().with_rebuild_callback(|| { - execute::shell("dioxus build --features web") + execute::shell("dx build --features web") .spawn() .unwrap() .wait() diff --git a/packages/fullstack/examples/axum-router/src/main.rs b/packages/fullstack/examples/axum-router/src/main.rs index 2b98ad842..dd95e2f8a 100644 --- a/packages/fullstack/examples/axum-router/src/main.rs +++ b/packages/fullstack/examples/axum-router/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr --no-default-features //! ``` @@ -22,7 +22,7 @@ fn main() { { // Start hot reloading hot_reload_init!(dioxus_hot_reload::Config::new().with_rebuild_callback(|| { - execute::shell("dioxus build --features web") + execute::shell("dx build --features web") .spawn() .unwrap() .wait() diff --git a/packages/fullstack/examples/salvo-hello-world/src/main.rs b/packages/fullstack/examples/salvo-hello-world/src/main.rs index 01b67ff99..c1d128103 100644 --- a/packages/fullstack/examples/salvo-hello-world/src/main.rs +++ b/packages/fullstack/examples/salvo-hello-world/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr --no-default-features //! ``` @@ -21,7 +21,7 @@ fn main() { { // Start hot reloading hot_reload_init!(dioxus_hot_reload::Config::new().with_rebuild_callback(|| { - execute::shell("dioxus build --features web") + execute::shell("dx build --features web") .spawn() .unwrap() .wait() diff --git a/packages/fullstack/examples/warp-hello-world/src/main.rs b/packages/fullstack/examples/warp-hello-world/src/main.rs index 34fc24c77..cd0170363 100644 --- a/packages/fullstack/examples/warp-hello-world/src/main.rs +++ b/packages/fullstack/examples/warp-hello-world/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr --no-default-features //! ``` @@ -21,7 +21,7 @@ fn main() { { // Start hot reloading hot_reload_init!(dioxus_hot_reload::Config::new().with_rebuild_callback(|| { - execute::shell("dioxus build --features web") + execute::shell("dx build --features web") .spawn() .unwrap() .wait() diff --git a/playwrite-tests/fullstack/src/main.rs b/playwrite-tests/fullstack/src/main.rs index 98caadbb6..3152458f2 100644 --- a/playwrite-tests/fullstack/src/main.rs +++ b/playwrite-tests/fullstack/src/main.rs @@ -20,7 +20,7 @@ fn main() { { // Start hot reloading hot_reload_init!(dioxus_hot_reload::Config::new().with_rebuild_callback(|| { - execute::shell("dioxus build --features web") + execute::shell("dx build --features web") .spawn() .unwrap() .wait() From df23c3c6518351cea872065e4100f543bc89e9a0 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 14 Jul 2023 13:58:49 -0700 Subject: [PATCH 05/25] Update more docs --- .../guide/src/en/__unused/advanced-guides/testing.md | 2 +- docs/guide/src/en/getting_started/hot_reload.md | 2 +- docs/guide/src/en/getting_started/web.md | 2 +- docs/guide/src/pt-br/getting_started/hot_reload.md | 2 +- docs/reference/src/guide/hot_reloading_pt-br.md | 2 +- docs/reference/src/platforms/desktop.md | 6 +++--- docs/router/src/guide/getting-started.md | 2 +- examples/tailwind/README.md | 2 +- packages/cli/docs/src/cmd/README.md | 4 ++-- packages/cli/docs/src/cmd/clean.md | 4 ++-- packages/cli/docs/src/cmd/serve.md | 12 ++++++------ packages/cli/docs/src/cmd/translate.md | 8 ++++---- packages/cli/docs/src/creating.md | 4 ++-- 13 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/guide/src/en/__unused/advanced-guides/testing.md b/docs/guide/src/en/__unused/advanced-guides/testing.md index 87e72309c..405c929a9 100644 --- a/docs/guide/src/en/__unused/advanced-guides/testing.md +++ b/docs/guide/src/en/__unused/advanced-guides/testing.md @@ -21,7 +21,7 @@ fn runs_in_browser() { Then, when you run ```console -dioxus test --chrome +dx test --chrome ``` Dioxus will build and test your code using the Chrome browser as a harness. diff --git a/docs/guide/src/en/getting_started/hot_reload.md b/docs/guide/src/en/getting_started/hot_reload.md index b14de30a4..d207f361a 100644 --- a/docs/guide/src/en/getting_started/hot_reload.md +++ b/docs/guide/src/en/getting_started/hot_reload.md @@ -18,7 +18,7 @@ Hot reloading is automatically enabled when using the web renderer on debug buil 1. Run: ```bash -dioxus serve --hot-reload +dx serve --hot-reload ``` 2. Change some code within a rsx or render macro diff --git a/docs/guide/src/en/getting_started/web.md b/docs/guide/src/en/getting_started/web.md index 7f3d04848..48818bf8f 100644 --- a/docs/guide/src/en/getting_started/web.md +++ b/docs/guide/src/en/getting_started/web.md @@ -59,5 +59,5 @@ Edit your `main.rs`: And to serve our app: ```bash -dioxus serve +dx serve ``` diff --git a/docs/guide/src/pt-br/getting_started/hot_reload.md b/docs/guide/src/pt-br/getting_started/hot_reload.md index 2dabde536..447169055 100644 --- a/docs/guide/src/pt-br/getting_started/hot_reload.md +++ b/docs/guide/src/pt-br/getting_started/hot_reload.md @@ -18,7 +18,7 @@ dioxus = { version = "*", features = ["hot-reload"] } 1. Execute: ``` -dioxus serve --hot-reload +dx serve --hot-reload ``` 2. alterar algum código dentro de uma macro `rsx` diff --git a/docs/reference/src/guide/hot_reloading_pt-br.md b/docs/reference/src/guide/hot_reloading_pt-br.md index 475cc38e9..6878c1522 100644 --- a/docs/reference/src/guide/hot_reloading_pt-br.md +++ b/docs/reference/src/guide/hot_reloading_pt-br.md @@ -18,7 +18,7 @@ dioxus = { version = "*", features = ["web", "hot_reload"] } 1. run: ``` -dioxus serve --hot-reload +dx serve --hot-reload ``` 2. alterar algum código dentro de uma macro rsx diff --git a/docs/reference/src/platforms/desktop.md b/docs/reference/src/platforms/desktop.md index 30fe698ff..98aafaf21 100644 --- a/docs/reference/src/platforms/desktop.md +++ b/docs/reference/src/platforms/desktop.md @@ -13,10 +13,10 @@ $ cargo new --bin demo $ cd demo ``` -Add Dioxus with the `desktop` feature: +Add Dioxus-desktop: ```shell -$ cargo add dioxus --features desktop +$ cargo add dioxus_desktop ``` Edit your `main.rs`: @@ -26,7 +26,7 @@ Edit your `main.rs`: use dioxus::prelude::*; fn main() { - dioxus::desktop::launch(app); + dioxus_desktop::launch(app); } fn app(cx: Scope) -> Element { diff --git a/docs/router/src/guide/getting-started.md b/docs/router/src/guide/getting-started.md index 7bce3c30a..793511535 100644 --- a/docs/router/src/guide/getting-started.md +++ b/docs/router/src/guide/getting-started.md @@ -60,7 +60,7 @@ fn app(cx: Scope) -> Element { Our project is now setup! To make sure everything is running correctly, in the root of your project run: ``` -dioxus serve --platform web +dx serve --platform web ``` Then head to [http://localhost:8080](http://localhost:8080) in your browser, and you should see ``Hello, wasm!`` on your screen. diff --git a/examples/tailwind/README.md b/examples/tailwind/README.md index 0498ecbd3..f2a08eba9 100644 --- a/examples/tailwind/README.md +++ b/examples/tailwind/README.md @@ -122,7 +122,7 @@ npx tailwindcss -i ./input.css -o ./public/tailwind.css --watch - Run the following command in the root of the project to start the dioxus dev server: ```bash -dioxus serve --hot-reload +dx serve --hot-reload ``` - Open the browser to http://localhost:8080 diff --git a/packages/cli/docs/src/cmd/README.md b/packages/cli/docs/src/cmd/README.md index 30586d73a..2de7cc138 100644 --- a/packages/cli/docs/src/cmd/README.md +++ b/packages/cli/docs/src/cmd/README.md @@ -5,11 +5,11 @@ In this chapter we will introduce all `dioxus-cli` commands. > You can also use `dx --help` to get cli help info. ``` -dioxus +dx Build, bundle, & ship your Dioxus app USAGE: - dioxus [OPTIONS] + dx [OPTIONS] OPTIONS: -h, --help Print help information diff --git a/packages/cli/docs/src/cmd/clean.md b/packages/cli/docs/src/cmd/clean.md index eef83a2a9..effb166ba 100644 --- a/packages/cli/docs/src/cmd/clean.md +++ b/packages/cli/docs/src/cmd/clean.md @@ -7,12 +7,12 @@ dioxus-clean Clean build artifacts USAGE: - dioxus clean + dx clean ``` # Example ``` -dioxus clean +dx clean ``` diff --git a/packages/cli/docs/src/cmd/serve.md b/packages/cli/docs/src/cmd/serve.md index 5b1f411dd..175168485 100644 --- a/packages/cli/docs/src/cmd/serve.md +++ b/packages/cli/docs/src/cmd/serve.md @@ -7,7 +7,7 @@ dioxus-serve Build, watch & serve the Rust WASM app and all of its assets USAGE: - dioxus serve [OPTIONS] + dx serve [OPTIONS] OPTIONS: --example [default: ""] @@ -19,7 +19,7 @@ OPTIONS: You can use this command to build project and start a dev server: ``` -dioxus serve +dx serve ``` ## Serve Example @@ -28,7 +28,7 @@ You can use the `example` option to serve a example: ``` # serve the `test` example -dioxus serve --exmaple test +dx serve --exmaple test ``` ## Open Browser @@ -36,7 +36,7 @@ dioxus serve --exmaple test You can add the `--open` option to open system default browser when server startup: ``` -dioxus serve --open +dx serve --open ``` ## RSX Hot Reloading @@ -44,7 +44,7 @@ dioxus serve --open You can add the `--hot-reload` flag to enable [rsx hot reloading](https://dioxuslabs.com/docs/0.3/guide/en/getting_started/hot_reload.html). This will allow you to reload some rsx changes without a full recompile: ``` -dioxus serve --open +dx serve --open ``` ## Cross Origin Policy @@ -57,5 +57,5 @@ You can add the `cross-origin-policy` option to change cross-origin header to: ``` ``` -dioxus serve --corss-origin-policy +dx serve --corss-origin-policy ``` diff --git a/packages/cli/docs/src/cmd/translate.md b/packages/cli/docs/src/cmd/translate.md index 0fb3ed8c9..b03b4422c 100644 --- a/packages/cli/docs/src/cmd/translate.md +++ b/packages/cli/docs/src/cmd/translate.md @@ -7,7 +7,7 @@ dioxus-translate Translate some source file into a Dioxus component USAGE: - dioxus translate [OPTIONS] [OUTPUT] + dx translate [OPTIONS] [OUTPUT] ARGS: Output file, defaults to stdout if not present @@ -22,7 +22,7 @@ OPTIONS: You can use the `file` option to set path to the `html` file to translate: ``` -dioxus transtale --file ./index.html +dx transtale --file ./index.html ``` ## Output rsx to a file @@ -30,7 +30,7 @@ dioxus transtale --file ./index.html You can pass a file to the traslate command to set the path to write the output of the command to: ``` -dioxus translate --file ./index.html component.rsx +dx translate --file ./index.html component.rsx ``` ## Output rsx to a file @@ -38,7 +38,7 @@ dioxus translate --file ./index.html component.rsx Setting the `component` option will create a compoent from the HTML: ``` -dioxus translate --file ./index.html --component +dx translate --file ./index.html --component ``` ## Example diff --git a/packages/cli/docs/src/creating.md b/packages/cli/docs/src/creating.md index c5d791013..95470827f 100644 --- a/packages/cli/docs/src/creating.md +++ b/packages/cli/docs/src/creating.md @@ -15,7 +15,7 @@ dioxus create hello-dioxus > > You can choose to create your project from a different template by passing the `template` argument: > ``` -> dioxus init hello-dioxus --template=gh:dioxuslabs/dioxus-template +> dx init hello-dioxus --template=gh:dioxuslabs/dioxus-template > ``` Next, move the current directory into your new project: @@ -33,7 +33,7 @@ cd hello-dioxus Finally, create serve your project with the Dioxus CLI: ``` -dioxus serve +dx serve ``` By default, the CLI serve your site at: [`http://127.0.0.1:8080/`](http://127.0.0.1:8080/) From 7453486448e1335510509eb7de439de87edb7822 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Mon, 17 Jul 2023 15:12:57 -0700 Subject: [PATCH 06/25] fix formatting --- packages/cli/src/cli/autoformat/mod.rs | 8 ++++++-- packages/cli/src/config.rs | 4 +++- packages/html/src/events/form.rs | 7 +++---- packages/rink/src/widgets/button.rs | 16 ++++++++++++---- packages/rink/src/widgets/checkbox.rs | 20 +++++++++++++++----- packages/rink/src/widgets/input.rs | 4 +++- packages/rink/src/widgets/slider.rs | 20 +++++++++++++++----- packages/rink/src/widgets/text_like.rs | 24 ++++++++++++++++++------ packages/router-macro/src/lib.rs | 14 +++++++------- packages/ssr/src/fs_cache.rs | 7 ++----- packages/ssr/src/incremental.rs | 2 +- 11 files changed, 85 insertions(+), 41 deletions(-) diff --git a/packages/cli/src/cli/autoformat/mod.rs b/packages/cli/src/cli/autoformat/mod.rs index 257e237f2..9a61bb16d 100644 --- a/packages/cli/src/cli/autoformat/mod.rs +++ b/packages/cli/src/cli/autoformat/mod.rs @@ -136,12 +136,16 @@ async fn autoformat_project(check: bool) -> Result<()> { } fn collect_rs_files(folder: &Path, files: &mut Vec) { - let Ok(folder) = folder.read_dir() else { return }; + let Ok(folder) = folder.read_dir() else { + return; + }; // load the gitignore for entry in folder { - let Ok(entry) = entry else { continue; }; + let Ok(entry) = entry else { + continue; + }; let path = entry.path(); diff --git a/packages/cli/src/config.rs b/packages/cli/src/config.rs index 79e6c7321..aeeb0616d 100644 --- a/packages/cli/src/config.rs +++ b/packages/cli/src/config.rs @@ -21,7 +21,9 @@ fn default_plugin() -> toml::Value { impl DioxusConfig { pub fn load() -> crate::error::Result> { - let Ok(crate_dir) = crate::cargo::crate_root() else { return Ok(None); }; + let Ok(crate_dir) = crate::cargo::crate_root() else { + return Ok(None); + }; let crate_dir = crate_dir.as_path(); let Some(dioxus_conf_file) = acquire_dioxus_toml(crate_dir) else { diff --git a/packages/html/src/events/form.rs b/packages/html/src/events/form.rs index 113c765c5..1fe59a640 100644 --- a/packages/html/src/events/form.rs +++ b/packages/html/src/events/form.rs @@ -56,10 +56,9 @@ where { use serde::Deserialize; - let Ok(file_engine) = - SerializedFileEngine::deserialize(deserializer) else{ - return Ok(None); - }; + let Ok(file_engine) = SerializedFileEngine::deserialize(deserializer) else { + return Ok(None); + }; let file_engine = std::sync::Arc::new(file_engine); Ok(Some(file_engine)) diff --git a/packages/rink/src/widgets/button.rs b/packages/rink/src/widgets/button.rs index e4d3754f1..9018a3e9a 100644 --- a/packages/rink/src/widgets/button.rs +++ b/packages/rink/src/widgets/button.rs @@ -82,7 +82,9 @@ impl Button { fn write_value(&self, rdom: &mut RealDom) { if let Some(mut text) = rdom.get_mut(self.text_id) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; *text.text_mut() = self.value.clone(); } } @@ -111,7 +113,9 @@ impl CustomElement for Button { fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self { let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let value = el .attributes @@ -146,7 +150,9 @@ impl CustomElement for Button { AttributeMask::All => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; self.update_value_attr(&el); self.update_size_attr(&mut el); } @@ -155,7 +161,9 @@ impl CustomElement for Button { AttributeMask::Some(attrs) => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; if attrs.contains("width") || attrs.contains("height") { self.update_size_attr(&mut el); } diff --git a/packages/rink/src/widgets/checkbox.rs b/packages/rink/src/widgets/checkbox.rs index 24b3f6244..fab809ed2 100644 --- a/packages/rink/src/widgets/checkbox.rs +++ b/packages/rink/src/widgets/checkbox.rs @@ -94,14 +94,18 @@ impl CheckBox { fn write_value(&self, mut root: NodeMut) { let single_char = { let node_type = root.node_type_mut(); - let NodeTypeMut::Element( el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(el) = node_type else { + panic!("input must be an element") + }; Self::width(&el) == "1px" || Self::height(&el) == "1px" }; let rdom = root.real_dom_mut(); if let Some(mut text) = rdom.get_mut(self.text_id) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; let value = if single_char { if self.checked { "☑" @@ -156,7 +160,9 @@ impl CustomElement for CheckBox { fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self { let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let value = el .attributes @@ -197,7 +203,9 @@ impl CustomElement for CheckBox { AttributeMask::All => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; self.update_value_attr(&el); self.update_size_attr(&mut el); self.update_checked_attr(&el); @@ -207,7 +215,9 @@ impl CustomElement for CheckBox { AttributeMask::Some(attrs) => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; if attrs.contains("width") || attrs.contains("height") { self.update_size_attr(&mut el); } diff --git a/packages/rink/src/widgets/input.rs b/packages/rink/src/widgets/input.rs index c6a3e56b9..c1fb563d7 100644 --- a/packages/rink/src/widgets/input.rs +++ b/packages/rink/src/widgets/input.rs @@ -56,7 +56,9 @@ impl CustomElement for Input { } let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let input_type = el .attributes .get(&OwnedAttributeDiscription { diff --git a/packages/rink/src/widgets/slider.rs b/packages/rink/src/widgets/slider.rs index f97c12bf6..7080b6c12 100644 --- a/packages/rink/src/widgets/slider.rs +++ b/packages/rink/src/widgets/slider.rs @@ -163,7 +163,9 @@ impl Slider { if let Some(mut div) = rdom.get_mut(self.pre_cursor_div) { let node_type = div.node_type_mut(); - let NodeTypeMut::Element(mut element) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut element) = node_type else { + panic!("input must be an element") + }; element.set_attribute( OwnedAttributeDiscription { name: "width".to_string(), @@ -175,7 +177,9 @@ impl Slider { if let Some(mut div) = rdom.get_mut(self.post_cursor_div) { let node_type = div.node_type_mut(); - let NodeTypeMut::Element(mut element) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut element) = node_type else { + panic!("input must be an element") + }; element.set_attribute( OwnedAttributeDiscription { name: "width".to_string(), @@ -259,7 +263,9 @@ impl CustomElement for Slider { fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self { let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let value = el.attributes.get(&OwnedAttributeDiscription { name: "value".to_string(), @@ -390,7 +396,9 @@ impl CustomElement for Slider { AttributeMask::All => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; self.update_value_attr(&el); self.update_size_attr(&mut el); self.update_max_attr(&el); @@ -403,7 +411,9 @@ impl CustomElement for Slider { AttributeMask::Some(attrs) => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; if attrs.contains("width") || attrs.contains("height") { self.update_size_attr(&mut el); } diff --git a/packages/rink/src/widgets/text_like.rs b/packages/rink/src/widgets/text_like.rs index b5874c776..6521073d0 100644 --- a/packages/rink/src/widgets/text_like.rs +++ b/packages/rink/src/widgets/text_like.rs @@ -143,19 +143,25 @@ impl TextLike { if let Some(mut text) = rdom.get_mut(self.pre_cursor_text) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; *text.text_mut() = self.controller.display_text(text_before_first_cursor); } if let Some(mut text) = rdom.get_mut(self.highlighted_text) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; *text.text_mut() = self.controller.display_text(text_highlighted); } if let Some(mut text) = rdom.get_mut(self.post_cursor_text) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; *text.text_mut() = self.controller.display_text(text_after_second_cursor); } @@ -288,7 +294,9 @@ impl CustomElement for fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self { let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let value = el .attributes @@ -370,7 +378,9 @@ impl CustomElement for AttributeMask::All => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; self.update_value_attr(&el); self.update_size_attr(&mut el); self.update_max_width_attr(&el); @@ -381,7 +391,9 @@ impl CustomElement for AttributeMask::Some(attrs) => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; if attrs.contains("width") || attrs.contains("height") { self.update_size_attr(&mut el); } diff --git a/packages/router-macro/src/lib.rs b/packages/router-macro/src/lib.rs index abbbf4355..5dada19cf 100644 --- a/packages/router-macro/src/lib.rs +++ b/packages/router-macro/src/lib.rs @@ -369,13 +369,13 @@ impl RouteEnum { let (exclude, layout): (bool, Layout) = attr.parse_args_with(parser)?; if exclude { - let Some(layout_index) = - layouts.iter().position(|l| l.comp == layout.comp) else { - return Err(syn::Error::new( - Span::call_site(), - "Attempted to exclude a layout that does not exist", - )); - }; + let Some(layout_index) = layouts.iter().position(|l| l.comp == layout.comp) + else { + return Err(syn::Error::new( + Span::call_site(), + "Attempted to exclude a layout that does not exist", + )); + }; excluded.push(LayoutId(layout_index)); } else { let layout_index = layouts.len(); diff --git a/packages/ssr/src/fs_cache.rs b/packages/ssr/src/fs_cache.rs index efaa52b80..0abf9c319 100644 --- a/packages/ssr/src/fs_cache.rs +++ b/packages/ssr/src/fs_cache.rs @@ -1,14 +1,11 @@ #![allow(non_snake_case)] - - use std::{ ops::{Deref, DerefMut}, - path::{PathBuf}, - time::{Duration}, + path::PathBuf, + time::Duration, }; - /// Information about the freshness of a rendered response #[derive(Debug, Clone, Copy)] pub struct RenderFreshness { diff --git a/packages/ssr/src/incremental.rs b/packages/ssr/src/incremental.rs index 00fd3e9e2..0e999b493 100644 --- a/packages/ssr/src/incremental.rs +++ b/packages/ssr/src/incremental.rs @@ -9,7 +9,7 @@ use std::{ hash::BuildHasherDefault, io::Write, ops::{Deref, DerefMut}, - path::{PathBuf}, + path::PathBuf, time::{Duration, SystemTime}, }; use tokio::io::{AsyncWrite, AsyncWriteExt, BufReader}; From ee28c89f5e4d2fab5d691108c3d32fae19379c77 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 18 Jul 2023 12:53:38 -0700 Subject: [PATCH 07/25] Change to a stream of bytes for liveview to make using sledgehammer later non-breaking --- packages/liveview/src/pool.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/liveview/src/pool.rs b/packages/liveview/src/pool.rs index 089d0bad4..5ed340eff 100644 --- a/packages/liveview/src/pool.rs +++ b/packages/liveview/src/pool.rs @@ -87,16 +87,16 @@ impl LiveViewPool { /// } /// ``` pub trait LiveViewSocket: - SinkExt - + StreamExt> + SinkExt, Error = LiveViewError> + + StreamExt, LiveViewError>> + Send + 'static { } impl LiveViewSocket for S where - S: SinkExt - + StreamExt> + S: SinkExt, Error = LiveViewError> + + StreamExt, LiveViewError>> + Send + 'static { From 8188011fe3d78e04204982558ec618c5f973d835 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 18 Jul 2023 13:03:34 -0700 Subject: [PATCH 08/25] fix adapters --- packages/liveview/src/adapters/axum_adapter.rs | 7 ++++--- .../liveview/src/adapters/salvo_adapter.rs | 10 ++++------ packages/liveview/src/adapters/warp_adapter.rs | 9 +++------ packages/liveview/src/pool.rs | 18 +++++++++++------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/liveview/src/adapters/axum_adapter.rs b/packages/liveview/src/adapters/axum_adapter.rs index 646cde38e..dda37acc1 100644 --- a/packages/liveview/src/adapters/axum_adapter.rs +++ b/packages/liveview/src/adapters/axum_adapter.rs @@ -11,13 +11,14 @@ pub fn axum_socket(ws: WebSocket) -> impl LiveViewSocket { .sink_map_err(|_| LiveViewError::SendingFailed) } -fn transform_rx(message: Result) -> Result { +fn transform_rx(message: Result) -> Result, LiveViewError> { message .map_err(|_| LiveViewError::SendingFailed)? .into_text() + .map(|s| s.into_bytes()) .map_err(|_| LiveViewError::SendingFailed) } -async fn transform_tx(message: String) -> Result { - Ok(Message::Text(message)) +async fn transform_tx(message: Vec) -> Result { + Ok(Message::Text(String::from_utf8_lossy(&message).to_string())) } diff --git a/packages/liveview/src/adapters/salvo_adapter.rs b/packages/liveview/src/adapters/salvo_adapter.rs index 2c8912a57..138196da7 100644 --- a/packages/liveview/src/adapters/salvo_adapter.rs +++ b/packages/liveview/src/adapters/salvo_adapter.rs @@ -12,14 +12,12 @@ pub fn salvo_socket(ws: WebSocket) -> impl LiveViewSocket { .sink_map_err(|_| LiveViewError::SendingFailed) } -fn transform_rx(message: Result) -> Result { +fn transform_rx(message: Result) -> Result, LiveViewError> { let as_bytes = message.map_err(|_| LiveViewError::SendingFailed)?; - let msg = String::from_utf8(as_bytes.into_bytes()).map_err(|_| LiveViewError::SendingFailed)?; - - Ok(msg) + Ok(as_bytes.into()) } -async fn transform_tx(message: String) -> Result { - Ok(Message::text(message)) +async fn transform_tx(message: Vec) -> Result { + Ok(Message::text(String::from_utf8_lossy(&message).to_string())) } diff --git a/packages/liveview/src/adapters/warp_adapter.rs b/packages/liveview/src/adapters/warp_adapter.rs index e5c821ce3..9ee8c6fe4 100644 --- a/packages/liveview/src/adapters/warp_adapter.rs +++ b/packages/liveview/src/adapters/warp_adapter.rs @@ -11,18 +11,15 @@ pub fn warp_socket(ws: WebSocket) -> impl LiveViewSocket { .sink_map_err(|_| LiveViewError::SendingFailed) } -fn transform_rx(message: Result) -> Result { +fn transform_rx(message: Result) -> Result, LiveViewError> { // destructure the message into the buffer we got from warp let msg = message .map_err(|_| LiveViewError::SendingFailed)? .into_bytes(); - // transform it back into a string, saving us the allocation - let msg = String::from_utf8(msg).map_err(|_| LiveViewError::SendingFailed)?; - Ok(msg) } -async fn transform_tx(message: String) -> Result { - Ok(Message::text(message)) +async fn transform_tx(message: Vec) -> Result { + Ok(Message::text(String::from_utf8_lossy(&message).to_string())) } diff --git a/packages/liveview/src/pool.rs b/packages/liveview/src/pool.rs index 5ed340eff..9bf62cefa 100644 --- a/packages/liveview/src/pool.rs +++ b/packages/liveview/src/pool.rs @@ -126,7 +126,7 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li pin_mut!(ws); // send the initial render to the client - ws.send(edits).await?; + ws.send(edits.into_bytes()).await?; // Create the a proxy for query engine let (query_tx, mut query_rx) = tokio::sync::mpsc::unbounded_channel(); @@ -156,11 +156,11 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li evt = ws.next() => { match evt.as_ref().map(|o| o.as_deref()) { // respond with a pong every ping to keep the websocket alive - Some(Ok("__ping__")) => { - ws.send("__pong__".to_string()).await?; + Some(Ok(b"__ping__")) => { + ws.send(b"__pong__".to_vec()).await?; } Some(Ok(evt)) => { - if let Ok(message) = serde_json::from_str::(evt) { + if let Ok(message) = serde_json::from_str::(&*String::from_utf8_lossy(evt)) { match message { IpcMessage::Event(evt) => { // Intercept the mounted event and insert a custom element type @@ -196,7 +196,7 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li // handle any new queries Some(query) = query_rx.recv() => { - ws.send(serde_json::to_string(&ClientUpdate::Query(query)).unwrap()).await?; + ws.send(serde_json::to_string(&ClientUpdate::Query(query)).unwrap().into_bytes()).await?; } Some(msg) = hot_reload_wait => { @@ -218,8 +218,12 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li .render_with_deadline(tokio::time::sleep(Duration::from_millis(10))) .await; - ws.send(serde_json::to_string(&ClientUpdate::Edits(edits)).unwrap()) - .await?; + ws.send( + serde_json::to_string(&ClientUpdate::Edits(edits)) + .unwrap() + .into_bytes(), + ) + .await?; } } From a96ccdc6f3ef536b1978d49df53660fa5089fe23 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 18 Jul 2023 13:16:17 -0700 Subject: [PATCH 09/25] fix clippy --- packages/core/src/scopes.rs | 4 ++-- packages/liveview/src/pool.rs | 2 +- packages/signals/src/lib.rs | 8 +------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs index ff94c456d..87e894ef3 100644 --- a/packages/core/src/scopes.rs +++ b/packages/core/src/scopes.rs @@ -688,13 +688,13 @@ impl<'src> ScopeState { raw_ref.downcast_mut::() }) .expect( - r###" + r#" Unable to retrieve the hook that was initialized at this index. Consult the `rules of hooks` to understand how to use hooks properly. You likely used the hook in a conditional. Hooks rely on consistent ordering between renders. Functions prefixed with "use" should never be called conditionally. - "###, + "#, ) } } diff --git a/packages/liveview/src/pool.rs b/packages/liveview/src/pool.rs index 9bf62cefa..dc7e4ea9e 100644 --- a/packages/liveview/src/pool.rs +++ b/packages/liveview/src/pool.rs @@ -160,7 +160,7 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li ws.send(b"__pong__".to_vec()).await?; } Some(Ok(evt)) => { - if let Ok(message) = serde_json::from_str::(&*String::from_utf8_lossy(evt)) { + if let Ok(message) = serde_json::from_str::(&String::from_utf8_lossy(evt)) { match message { IpcMessage::Event(evt) => { // Intercept the mounted event and insert a custom element type diff --git a/packages/signals/src/lib.rs b/packages/signals/src/lib.rs index 4e950e0dc..5b6a740cf 100644 --- a/packages/signals/src/lib.rs +++ b/packages/signals/src/lib.rs @@ -10,8 +10,6 @@ mod rt; use dioxus_core::ScopeState; pub use rt::*; -use crate::rt::claim_rt; - pub fn use_init_signal_rt(cx: &ScopeState) { cx.use_hook(|| { let rt = claim_rt(cx.schedule_update_any()); @@ -96,11 +94,7 @@ impl std::ops::Deref for Signal { impl std::clone::Clone for Signal { fn clone(&self) -> Self { - Self { - t: PhantomData, - id: self.id, - rt: self.rt, - } + *self } } From 01e5e7e47fb137f734cfb37c533cb18cb647ca3e Mon Sep 17 00:00:00 2001 From: Jason Schein Date: Tue, 18 Jul 2023 13:49:20 -0700 Subject: [PATCH 10/25] hooks.md and walkthrough_readme.md updates. (#1094) * Minor improvements to hooks.md, mostly adding more links. * walkthrough_readme.md updated to be more friendly to unfamiliar readers. --------- Co-authored-by: ealmloff --- .../src/en/contributing/walkthrough_readme.md | 64 +++++++++++-------- docs/guide/src/en/interactivity/hooks.md | 35 +++++++--- 2 files changed, 64 insertions(+), 35 deletions(-) diff --git a/docs/guide/src/en/contributing/walkthrough_readme.md b/docs/guide/src/en/contributing/walkthrough_readme.md index 5334630c9..5be9d4b5a 100644 --- a/docs/guide/src/en/contributing/walkthrough_readme.md +++ b/docs/guide/src/en/contributing/walkthrough_readme.md @@ -14,13 +14,13 @@ We start will a hello world program. This program renders a desktop app with the ## The rsx! Macro -Before the Rust compiler runs the program, it will expand all macros. Here is what the hello world example looks like expanded: +Before the Rust compiler runs the program, it will expand all [macros](https://doc.rust-lang.org/reference/procedural-macros.html). Here is what the hello world example looks like expanded: ```rust, no_run {{#include ../../../examples/readme_expanded.rs}} ``` -The rsx macro separates the static parts of the rsx (the template) and the dynamic parts (the dynamic_nodes and dynamic_attributes). +The rsx macro separates the static parts of the rsx (the template) and the dynamic parts (the [dynamic_nodes](https://docs.rs/dioxus-core/0.3.2/dioxus_core/prelude/struct.VNode.html#structfield.dynamic_nodes) and [dynamic_attributes](https://docs.rs/dioxus-core/0.3.2/dioxus_core/prelude/struct.VNode.html#structfield.dynamic_attrs)). The static template only contains the parts of the rsx that cannot change at runtime with holes for the dynamic parts: @@ -32,17 +32,17 @@ The dynamic_nodes and dynamic_attributes are the parts of the rsx that can chang ## Launching the App -The app is launched by calling the `launch` function with the root component. Internally, this function will create a new web view using [wry](https://docs.rs/wry/latest/wry/) and create a virtual dom with the root component. This guide will not explain the renderer in-depth, but you can read more about it in the [custom renderer](/guide/custom-renderer) section. +The app is launched by calling the `launch` function with the root component. Internally, this function will create a new web view using [wry](https://docs.rs/wry/latest/wry/) and create a virtual dom with the root component (`fn app()` in the readme example). This guide will not explain the renderer in-depth, but you can read more about it in the [custom renderer](/guide/custom-renderer) section. ## The Virtual DOM -Before we dive into the initial render in the virtual dom, we need to discuss what the virtual dom is. The virtual dom is a representation of the dom that is used to diff the current dom from the new dom. This diff is then used to create a list of mutations that need to be applied to the dom. +Before we dive into the initial render in the virtual DOM, we need to discuss what the virtual DOM is. The virtual DOM is a representation of the DOM that is used to diff the current DOM from the new DOM. This diff is then used to create a list of mutations that need to be applied to the DOM to bring it into sync with the virtual DOM. -The Virtual Dom roughly looks like this: +The Virtual DOM roughly looks like this: ```rust, no_run pub struct VirtualDom { - // All the templates that have been created or set durring hot reloading + // All the templates that have been created or set during hot reloading pub(crate) templates: FxHashMap>>, // A slab of all the scopes that have been created @@ -63,64 +63,74 @@ pub struct VirtualDom { ``` > What is a [slab](https://docs.rs/slab/latest/slab/)? +> > A slab acts like a hashmap with integer keys if you don't care about the value of the keys. It is internally backed by a dense vector which makes it more efficient than a hashmap. When you insert a value into a slab, it returns an integer key that you can use to retrieve the value later. > How does Dioxus use slabs? -> Dioxus uses "synchronized slabs" to communicate between the renderer and the VDOM. When an node is created in the Virtual Dom, a ElementId is passed along with the mutation to the renderer to identify the node. These ids are used by the Virtual Dom to reference that nodes in future mutations like setting an attribute on a node or removing a node. -> When the renderer sends an event to the Virtual Dom, it sends the ElementId of the node that the event was triggered on. The Virtual Dom uses this id to find the node in the slab and then run the necessary event handlers. +> +> Dioxus uses "synchronized slabs" to communicate between the renderer and the VDOM. When a node is created in the Virtual DOM, an (elementId, mutation) pair is passed to the renderer to identify that node, which the renderer will then render in actual DOM. These ids are also used by the Virtual Dom to reference that node in future mutations, like setting an attribute on a node or removing a node. When the renderer sends an event to the Virtual Dom, it sends the ElementId of the node that the event was triggered on. The Virtual DOM uses this id to find that node in the slab and then run the necessary event handlers. -The virtual dom is a tree of scopes. A new scope is created for every component when it is first rendered and recycled when the component is unmounted. +The virtual DOM is a tree of scopes. A new `Scope` is created for every component when it is first rendered and recycled when the component is unmounted. Scopes serve three main purposes: 1. They store the state of hooks used by the component -2. They store the state for the context API -3. They store the current and previous VNode that was rendered for diffing +2. They store the state for the context API (for example: using + [use_shared_state_provider](https://docs.rs/dioxus/latest/dioxus/prelude/fn.use_shared_state_provider.html)). +3. They store the current and previous versions of the `VNode` that was rendered, so they can be + diffed to generate the set of mutations needed to re-render it. ### The Initial Render The root scope is created and rebuilt: 1. The root component is run -2. The root component returns a VNode -3. Mutations for the VNode are created and added to the mutation list (this may involve creating new child components) -4. The VNode is stored in the root scope +2. The root component returns a `VNode` +3. Mutations for this `VNode` are created and added to the mutation list (this may involve creating new child components) +4. The `VNode` is stored in the root's `Scope`. -After the root scope is built, the mutations are sent to the renderer to be applied to the dom. +After the root's `Scope` is built, all generated mutations are sent to the renderer, which applies them to the DOM. -After the initial render, the root scope looks like this: +After the initial render, the root `Scope` looks like this: [![](https://mermaid.ink/img/pako:eNqtVE1P4zAQ_SuzPrWikRpWXCLtBRDisItWsOxhCaqM7RKricdyJrQV8N93QtvQNCkfEnOynydv3nxkHoVCbUQipjnOVSYDwc_L1AFbWd3dB-kzuEQkuFLoDUwDFkCZAek9nGDh0RlHK__atA1GkUUHf45f0YbppAqB_aOzIAvz-t7-chN_Y-1bw1WSJKsglIu2w9tktWXxIIuHURT5XCqTYa5NmDguw2R8c5MKq2GcgF46WTB_jafi9rZL0yi5q4jQTSrf9altO4okCn1Ratwyz55Qxuku2ITlTMgs6HCQimsPmb3PvqVi-L5gjXP3QcnxWnL8JZLrwGvR31n0KV-Bx6-r-oVkT_-3G1S-NQLbk9i8rj7udP2cixed2QcDCitHJiQw7ub3EVlNecrPjudG2-6soFO5VbMECmR9T5OnlUY4-AFxfw9aTFst3McU9TK1Otm6NEn_DubBYlX2_dglLXOz48FgwJmJ5lZTlhz6xWgNaFnyDgpymcARHO0W2a9J_l5w2wYXvHuGPcqaQ-rESBQmFNJq3nCPNZoK3l4sUSR81DLMUpG6Z_aTFeHV0imRUKjMSFReSzKnVnKGhUimMi8ZNdoShl-rlfmyOUfCS_cPcePz_B_Wl4pc?type=png)](https://mermaid.live/edit#pako:eNqtVE1P4zAQ_SuzPrWikRpWXCLtBRDisItWsOxhCaqM7RKricdyJrQV8N93QtvQNCkfEnOynydv3nxkHoVCbUQipjnOVSYDwc_L1AFbWd3dB-kzuEQkuFLoDUwDFkCZAek9nGDh0RlHK__atA1GkUUHf45f0YbppAqB_aOzIAvz-t7-chN_Y-1bw1WSJKsglIu2w9tktWXxIIuHURT5XCqTYa5NmDguw2R8c5MKq2GcgF46WTB_jafi9rZL0yi5q4jQTSrf9altO4okCn1Ratwyz55Qxuku2ITlTMgs6HCQimsPmb3PvqVi-L5gjXP3QcnxWnL8JZLrwGvR31n0KV-Bx6-r-oVkT_-3G1S-NQLbk9i8rj7udP2cixed2QcDCitHJiQw7ub3EVlNecrPjudG2-6soFO5VbMECmR9T5OnlUY4-AFxfw9aTFst3McU9TK1Otm6NEn_DubBYlX2_dglLXOz48FgwJmJ5lZTlhz6xWgNaFnyDgpymcARHO0W2a9J_l5w2wYXvHuGPcqaQ-rESBQmFNJq3nCPNZoK3l4sUSR81DLMUpG6Z_aTFeHV0imRUKjMSFReSzKnVnKGhUimMi8ZNdoShl-rlfmyOUfCS_cPcePz_B_Wl4pc) ### Waiting for Events -The Virtual Dom will only ever rerender a scope if it is marked as dirty. Each hook is responsible for marking the scope as dirty if the state has changed. Hooks can mark a scope as dirty by sending a message to the Virtual Dom's channel. +The Virtual DOM will only ever re-render a `Scope` if it is marked as dirty. Each hook is responsible for marking the `Scope` as dirty if the state has changed. Hooks can mark a scope as dirty by sending a message to the Virtual Dom's channel. You can see the [implementations](https://github.com/DioxusLabs/dioxus/tree/master/packages/hooks) for the hooks dioxus includes by default on how this is done. Calling `needs_update()` on a hook will also cause it to mark its scope as dirty. There are generally two ways a scope is marked as dirty: -1. The renderer triggers an event: This causes an event listener to be called if needed which may mark a component as dirty -2. The renderer calls wait for work: This polls futures which may mark a component as dirty +1. The renderer triggers an event: An event listener on this event may be called, which may mark a + component as dirty, if processing the event resulted in any generated any mutations. +2. The renderer calls + [`wait_for_work`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.VirtualDom.html#method.wait_for_work): + This polls dioxus internal future queue. One of these futures may mark a component as dirty. -Once at least one scope is marked as dirty, the renderer can call `render_with_deadline` to diff the dirty scopes. +Once at least one `Scope` is marked as dirty, the renderer can call [`render_with_deadline`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.VirtualDom.html#method.render_with_deadline) to diff the dirty scopes. ### Diffing Scopes -If the user clicked the "up high" button, the root scope would be marked as dirty by the use_state hook. Once the desktop renderer calls `render_with_deadline`, the root scope would be diffed. +When a user clicks the "up high" button, the root `Scope` will be marked as dirty by the `use_state` hook. The desktop renderer will then call `render_with_deadline`, which will diff the root `Scope`. -To start the diffing process, the component is run. After the root component is run it will look like this: +To start the diffing process, the component function is run. After the root component is run it, the root `Scope` will look like this: [![](https://mermaid.ink/img/pako:eNrFVlFP2zAQ_iuen0BrpCaIl0i8AEJ72KQJtpcRFBnbJVYTn-U4tBXw33dpG5M2CetoBfdkny_ffb67fPIT5SAkjekkhxnPmHXk-3WiCVpZ3T9YZjJyDeDIDQcjycRCQVwmCTOGXEBhQEvtVvG1CWUldwo0-XX-6vVIF5W1GB9cWVbI1_PNL5v8jW3uPFbpmFOc2HK-GfA2WG1ZeJSFx0EQmJxxmUEupE01liEd394mVAkyjolYaFYgfu1P6N1dF8Yzua-cA51WphtTWzsLc872Zan9CnEGUkktuk6fFm_i5NxFRwn9bUimHrIvCT3-N2EBM70j5XBNOTwI5TrxmvQJkr7ELcHx67Jeggz0v92g8q0RaE-iP1193On6NyxecKUeJeFQaSdtTMLu_Xah5ctT_u94Nty2ZwU0zxWfxqQA5PecPq84kq9nfRw7SK0WDiEFZ4O37d34S_-08lFBVfb92KVb5HIrAp0WpjKYKeGyODLz0dohWIkaZNkiJqfkdLvIH6oRaTSoEmm0n06k0a5K0ZdpL61Io0Yt0nfpxc7UQ0_9cJrhyZ8syX-6brS706Mc489Vjja7fbWj3cxDqIdfJJqOaCFtwZTAV8hT7U0ovjBQRmiMS8HsNKGJfsE4Vjm4WWhOY2crOaKVEczJS8WwgAWNJywv0SuFcmB_rJ41y9fNiBqm_wA0MS9_AUuAiy0?type=png)](https://mermaid.live/edit#pako:eNrFVlFP2zAQ_iuen0BrpCaIl0i8AEJ72KQJtpcRFBnbJVYTn-U4tBXw33dpG5M2CetoBfdkny_ffb67fPIT5SAkjekkhxnPmHXk-3WiCVpZ3T9YZjJyDeDIDQcjycRCQVwmCTOGXEBhQEvtVvG1CWUldwo0-XX-6vVIF5W1GB9cWVbI1_PNL5v8jW3uPFbpmFOc2HK-GfA2WG1ZeJSFx0EQmJxxmUEupE01liEd394mVAkyjolYaFYgfu1P6N1dF8Yzua-cA51WphtTWzsLc872Zan9CnEGUkktuk6fFm_i5NxFRwn9bUimHrIvCT3-N2EBM70j5XBNOTwI5TrxmvQJkr7ELcHx67Jeggz0v92g8q0RaE-iP1193On6NyxecKUeJeFQaSdtTMLu_Xah5ctT_u94Nty2ZwU0zxWfxqQA5PecPq84kq9nfRw7SK0WDiEFZ4O37d34S_-08lFBVfb92KVb5HIrAp0WpjKYKeGyODLz0dohWIkaZNkiJqfkdLvIH6oRaTSoEmm0n06k0a5K0ZdpL61Io0Yt0nfpxc7UQ0_9cJrhyZ8syX-6brS706Mc489Vjja7fbWj3cxDqIdfJJqOaCFtwZTAV8hT7U0ovjBQRmiMS8HsNKGJfsE4Vjm4WWhOY2crOaKVEczJS8WwgAWNJywv0SuFcmB_rJ41y9fNiBqm_wA0MS9_AUuAiy0) -Next, the Virtual Dom will compare the new VNode with the previous VNode and only update the parts of the tree that have changed. - -When a component is re-rendered, the Virtual Dom will compare the new VNode with the previous VNode and only update the parts of the tree that have changed. +Next, the Virtual DOM will compare the new VNode with the previous VNode and only update the parts of the tree that have changed. Because of this approach, when a component is re-rendered only the parts of the tree that have changed will be updated in the DOM by the renderer. The diffing algorithm goes through the list of dynamic attributes and nodes and compares them to the previous VNode. If the attribute or node has changed, a mutation that describes the change is added to the mutation list. -Here is what the diffing algorithm looks like for the root scope (red lines indicate that a mutation was generated, and green lines indicate that no mutation was generated) +Here is what the diffing algorithm looks like for the root `Scope` (red lines indicate that a mutation was generated, and green lines indicate that no mutation was generated) [![](https://mermaid.ink/img/pako:eNrFlFFPwjAQx7_KpT7Kko2Elya8qCE-aGLAJ5khpe1Yw9Zbug4k4He3OJjbGPig0T5t17tf_nf777aEo5CEkijBNY-ZsfAwDjW4kxfzhWFZDGNECxOOmYTIYAo2lsCyDG4xzVBLbcv8_RHKSG4V6orSIN0Wxrh8b2RYKr_uTyubd1W92GiWKg7aac6bOU3G803HbVk82xfP_Ok0JEqAT-FeLWJvpFYSOBbaSkMhCMnra5MgtfhWFrPWqHlhL2urT6atbU-oa0PNE8WXFFJ0-nazXakRroddGk9IwYEUnCd5w7Pddr5UTT8ZuVJY5F0fM7ebRLYyXNDgUnprJWxM-9lb7xAQLHe-M2xDYQCD9pD_2hez_kVn-P_rjLq6n3qjYv2iO5qz9DyvPdyv1ETp5eTTJ_7BGvQq8v1TVtl5jXUcRRcrqFh-dI4VtFlBN6t_ynLNkh5JpUmZEm5rbvfhkLiN6H4BQt2jYGYZklC_uzxWWJxsNCfUmkL2SJEJZuWdYs4cKaERS3IXlUJZNI_lGv7cxj2SMf2CeMx5_wBcbK19?type=png)](https://mermaid.live/edit#pako:eNrFlFFPwjAQx7_KpT7Kko2Elya8qCE-aGLAJ5khpe1Yw9Zbug4k4He3OJjbGPig0T5t17tf_nf777aEo5CEkijBNY-ZsfAwDjW4kxfzhWFZDGNECxOOmYTIYAo2lsCyDG4xzVBLbcv8_RHKSG4V6orSIN0Wxrh8b2RYKr_uTyubd1W92GiWKg7aac6bOU3G803HbVk82xfP_Ok0JEqAT-FeLWJvpFYSOBbaSkMhCMnra5MgtfhWFrPWqHlhL2urT6atbU-oa0PNE8WXFFJ0-nazXakRroddGk9IwYEUnCd5w7Pddr5UTT8ZuVJY5F0fM7ebRLYyXNDgUnprJWxM-9lb7xAQLHe-M2xDYQCD9pD_2hez_kVn-P_rjLq6n3qjYv2iO5qz9DyvPdyv1ETp5eTTJ_7BGvQq8v1TVtl5jXUcRRcrqFh-dI4VtFlBN6t_ynLNkh5JpUmZEm5rbvfhkLiN6H4BQt2jYGYZklC_uzxWWJxsNCfUmkL2SJEJZuWdYs4cKaERS3IXlUJZNI_lGv7cxj2SMf2CeMx5_wBcbK19) ## Conclusion -This is only a brief overview of how the Virtual Dom works. There are several aspects not yet covered in this guide including how the Virtual Dom handles async-components, keyed diffing, and how it uses [bump allocation](https://github.com/fitzgen/bumpalo) to efficiently allocate VNodes. If need more information about the Virtual Dom, you can read the code of the [core](https://github.com/DioxusLabs/dioxus/tree/master/packages/core) crate or reach out to us on [Discord](https://discord.gg/XgGxMSkvUM). +This is only a brief overview of how the Virtual Dom works. There are several aspects not yet covered in this guide including: + + * How the Virtual DOM handles async-components + * Keyed diffing + * Using [bump allocation](https://github.com/fitzgen/bumpalo) to efficiently allocate VNodes. + +If you need more information about the Virtual Dom, you can read the code of the [core](https://github.com/DioxusLabs/dioxus/tree/master/packages/core) crate or reach out to us on [Discord](https://discord.gg/XgGxMSkvUM). \ No newline at end of file diff --git a/docs/guide/src/en/interactivity/hooks.md b/docs/guide/src/en/interactivity/hooks.md index 6851aacbf..8b571dacd 100644 --- a/docs/guide/src/en/interactivity/hooks.md +++ b/docs/guide/src/en/interactivity/hooks.md @@ -2,15 +2,16 @@ So far our components have had no state like a normal rust functions. However, in a UI component, it is often useful to have stateful functionality to build user interactions. For example, you might want to track whether the user has opened a drop-down, and render different things accordingly. -Hooks allow us to create state in our components. Hooks are Rust functions that take a reference to `ScopeState` (in a component, you can pass `cx`), and provide you with functionality and state. +Hooks allow us to create state in our components. Hooks are Rust functions that take a reference to [`ScopeState`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.ScopeState.html) (in a component, you can pass `cx`), and provide you with functionality and state. ## `use_state` Hook [`use_state`](https://docs.rs/dioxus/latest/dioxus/prelude/fn.use_state.html) is one of the simplest hooks. -- You provide a closure that determines the initial value +- You provide a closure that determines the initial value: `let mut count = use_state(cx, || 0);` - `use_state` gives you the current value, and a way to update it by setting it to something else -- When the value updates, `use_state` makes the component re-render, and provides you with the new value +- When the value updates, `use_state` makes the component re-render (along with any other component + that references it), and then provides you with the new value. For example, you might have seen the counter example, in which state (a number) is tracked using the `use_state` hook: @@ -45,10 +46,11 @@ But how can Dioxus differentiate between multiple hooks in the same component? A This is only possible because the two hooks are always called in the same order, so Dioxus knows which is which. Because the order you call hooks matters, you must follow certain rules when using hooks: 1. Hooks may be only used in components or other hooks (we'll get to that later) -2. On every call to the component function +2. On every call to a component function 1. The same hooks must be called (except in the case of early returns, as explained later in the [Error Handling chapter](../best_practices/error_handling.md)) 2. In the same order -3. Hooks name's should start with `use_` so you don't accidentally confuse them with regular functions +3. Hook names should start with `use_` so you don't accidentally confuse them with regular + functions (`use_state()`, `use_ref()`, `use_future()`, etc...) These rules mean that there are certain things you can't do with hooks: @@ -74,9 +76,12 @@ These rules mean that there are certain things you can't do with hooks: `use_state` is great for tracking simple values. However, you may notice in the [`UseState` API](https://docs.rs/dioxus/latest/dioxus/hooks/struct.UseState.html) that the only way to modify its value is to replace it with something else (e.g., by calling `set`, or through one of the `+=`, `-=` operators). This works well when it is cheap to construct a value (such as any primitive). But what if you want to maintain more complex data in the components state? -For example, suppose we want to maintain a `Vec` of values. If we stored it with `use_state`, the only way to add a new value to the list would be to create a new `Vec` with the additional value, and put it in the state. This is expensive! We want to modify the existing `Vec` instead. +For example, suppose we want to maintain a `Vec` of values. If we stored it with `use_state`, the +only way to add a new value to the list would be to copy the existing `Vec`, add our value to it, +and then replace the existing `Vec` in the state with it. This is expensive! We want to modify the +existing `Vec` instead. -Thankfully, there is another hook for that, `use_ref`! It is similar to `use_state`, but it lets you get a mutable reference to the contained data. +Thankfully, there is another hook for that, `use_ref`! It **is** similar to `use_state`, but it lets you get a mutable reference to the contained data. Here's a simple example that keeps a list of events in a `use_ref`. We can acquire write access to the state with `.with_mut()`, and then just `.push` a new value to the state: @@ -84,4 +89,18 @@ Here's a simple example that keeps a list of events in a `use_ref`. We can acqui {{#include ../../../examples/hooks_use_ref.rs:component}} ``` -> The return values of `use_state` and `use_ref` (`UseState` and `UseRef`, respectively) are in some ways similar to [`Cell`](https://doc.rust-lang.org/std/cell/) and [`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) – they provide interior mutability. However, these Dioxus wrappers also ensure that the component gets re-rendered whenever you change the state. +> The return values of `use_state` and `use_ref` ( +> [`UseState`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.UseState.html) and +> [`UseRef`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.UseRef.html), respectively) are in +> some ways similar to [`Cell`](https://doc.rust-lang.org/std/cell/) and +> [`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) – they provide interior +> mutability. However, these Dioxus wrappers also ensure that the component gets re-rendered +> whenever you change the state. + + +## Additional Resources + +- [**dioxus_hooks** ](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/) rustdoc + - Documents all hook types included with dioxus by default Most of these are also covered in + later chapters of this guide. +- [Hooks Package](https://github.com/DioxusLabs/dioxus/tree/master/packages/hooks) From 61e9fd9973a66e0cf6f08b4ec00736cefa8f0296 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 18 Jul 2023 16:34:27 -0700 Subject: [PATCH 11/25] use :.. instead of :... --- docs/router/examples/catch_all.rs | 2 +- docs/router/examples/catch_all_segments.rs | 2 +- docs/router/examples/dynamic_route.rs | 2 +- docs/router/examples/full_example.rs | 2 +- docs/router/examples/links.rs | 2 +- docs/router/examples/navigator.rs | 2 +- docs/router/examples/nested_routes.rs | 2 +- examples/router.rs | 2 +- packages/router-macro/src/lib.rs | 4 ++-- packages/router-macro/src/route.rs | 6 +++--- packages/router-macro/src/segment.rs | 4 ++-- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/router/examples/catch_all.rs b/docs/router/examples/catch_all.rs index d55b8efcb..38dfa11f1 100644 --- a/docs/router/examples/catch_all.rs +++ b/docs/router/examples/catch_all.rs @@ -8,7 +8,7 @@ enum Route { #[route("/")] Home {}, // PageNotFound is a catch all route that will match any route and placing the matched segments in the route field - #[route("/:...route")] + #[route("/:..route")] PageNotFound { route: Vec }, } // ANCHOR_END: router diff --git a/docs/router/examples/catch_all_segments.rs b/docs/router/examples/catch_all_segments.rs index d4fcb5261..ce84a84db 100644 --- a/docs/router/examples/catch_all_segments.rs +++ b/docs/router/examples/catch_all_segments.rs @@ -7,7 +7,7 @@ use dioxus_router::prelude::*; #[rustfmt::skip] enum Route { // segments that start with :... are catch all segments - #[route("/blog/:...segments")] + #[route("/blog/:..segments")] BlogPost { // You must include catch all segment in child variants segments: Vec, diff --git a/docs/router/examples/dynamic_route.rs b/docs/router/examples/dynamic_route.rs index bb02e57b8..4ea5b3b45 100644 --- a/docs/router/examples/dynamic_route.rs +++ b/docs/router/examples/dynamic_route.rs @@ -26,7 +26,7 @@ enum Route { #[end_layout] #[end_nest] #[end_layout] - #[route("/:...route")] + #[route("/:..route")] PageNotFound { route: Vec, }, diff --git a/docs/router/examples/full_example.rs b/docs/router/examples/full_example.rs index 2f6251968..ff8302926 100644 --- a/docs/router/examples/full_example.rs +++ b/docs/router/examples/full_example.rs @@ -30,7 +30,7 @@ enum Route { #[redirect("/", || Route::BlogList {})] #[redirect("/:name", |name: String| Route::BlogPost { name })] #[end_nest] - #[route("/:...route")] + #[route("/:..route")] PageNotFound { route: Vec, }, diff --git a/docs/router/examples/links.rs b/docs/router/examples/links.rs index a84d50158..c74865927 100644 --- a/docs/router/examples/links.rs +++ b/docs/router/examples/links.rs @@ -11,7 +11,7 @@ enum Route { #[route("/")] Home {}, #[end_layout] - #[route("/:...route")] + #[route("/:..route")] PageNotFound { route: Vec }, } // ANCHOR_END: router diff --git a/docs/router/examples/navigator.rs b/docs/router/examples/navigator.rs index 786f832a4..4c6249366 100644 --- a/docs/router/examples/navigator.rs +++ b/docs/router/examples/navigator.rs @@ -7,7 +7,7 @@ use dioxus_router::prelude::*; enum Route { #[route("/")] Home {}, - #[route("/:...route")] + #[route("/:..route")] PageNotFound { route: Vec }, } diff --git a/docs/router/examples/nested_routes.rs b/docs/router/examples/nested_routes.rs index fa8c81494..7462d8e74 100644 --- a/docs/router/examples/nested_routes.rs +++ b/docs/router/examples/nested_routes.rs @@ -11,7 +11,7 @@ enum Route { #[route("/")] Home {}, #[end_layout] - #[route("/:...route")] + #[route("/:..route")] PageNotFound { route: Vec }, } // ANCHOR_END: router diff --git a/examples/router.rs b/examples/router.rs index 2f6251968..ff8302926 100644 --- a/examples/router.rs +++ b/examples/router.rs @@ -30,7 +30,7 @@ enum Route { #[redirect("/", || Route::BlogList {})] #[redirect("/:name", |name: String| Route::BlogPost { name })] #[end_nest] - #[route("/:...route")] + #[route("/:..route")] PageNotFound { route: Vec, }, diff --git a/packages/router-macro/src/lib.rs b/packages/router-macro/src/lib.rs index 5dada19cf..f8c9cff1d 100644 --- a/packages/router-macro/src/lib.rs +++ b/packages/router-macro/src/lib.rs @@ -31,11 +31,11 @@ mod segment; /// Route Segments: /// 1. Static Segments: "/static" /// 2. Dynamic Segments: "/:dynamic" (where dynamic has a type that is FromStr in all child Variants) -/// 3. Catch all Segments: "/:...segments" (where segments has a type that is FromSegments in all child Variants) +/// 3. Catch all Segments: "/:..segments" (where segments has a type that is FromSegments in all child Variants) /// 4. Query Segments: "/?:query" (where query has a type that is FromQuery in all child Variants) /// /// Routes are matched: -/// 1. By there specificity this order: Query Routes ("/?:query"), Static Routes ("/route"), Dynamic Routes ("/:route"), Catch All Routes ("/:...route") +/// 1. By there specificity this order: Query Routes ("/?:query"), Static Routes ("/route"), Dynamic Routes ("/:route"), Catch All Routes ("/:..route") /// 2. By the order they are defined in the enum /// /// All features: diff --git a/packages/router-macro/src/route.rs b/packages/router-macro/src/route.rs index 329a7c132..ad8c74857 100644 --- a/packages/router-macro/src/route.rs +++ b/packages/router-macro/src/route.rs @@ -126,7 +126,7 @@ impl Route { None => { return Err(syn::Error::new_spanned( variant.clone(), - "Routable variants with a #[child(...)] attribute must have a field named \"child\" or a field with a #[child] attribute", + "Routable variants with a #[child(..)] attribute must have a field named \"child\" or a field with a #[child] attribute", )); } } @@ -134,14 +134,14 @@ impl Route { _ => { return Err(syn::Error::new_spanned( variant.clone(), - "Routable variants with a #[child(...)] attribute must have named fields", + "Routable variants with a #[child(..)] attribute must have named fields", )) } } } else { return Err(syn::Error::new_spanned( variant.clone(), - "Routable variants must either have a #[route(...)] attribute or a #[child(...)] attribute", + "Routable variants must either have a #[route(..)] attribute or a #[child(..)] attribute", )); } } diff --git a/packages/router-macro/src/segment.rs b/packages/router-macro/src/segment.rs index 30b9e7e10..2f7455a3f 100644 --- a/packages/router-macro/src/segment.rs +++ b/packages/router-macro/src/segment.rs @@ -150,10 +150,10 @@ pub fn parse_route_segments<'a>( while let Some(segment) = iterator.next() { if let Some(segment) = segment.strip_prefix(':') { - let spread = segment.starts_with("..."); + let spread = segment.starts_with(".."); let ident = if spread { - segment[3..].to_string() + segment[2..].to_string() } else { segment.to_string() }; From 4e278fead514fddf0322dc96178e4b265967f227 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 18 Jul 2023 18:23:55 -0700 Subject: [PATCH 12/25] rustfmt --- packages/desktop/src/file_upload.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/desktop/src/file_upload.rs b/packages/desktop/src/file_upload.rs index eab06c2cb..778c209ac 100644 --- a/packages/desktop/src/file_upload.rs +++ b/packages/desktop/src/file_upload.rs @@ -51,26 +51,26 @@ fn get_file_event_for_file( } #[cfg(not(any( -target_os = "windows", -target_os = "macos", -target_os = "linux", -target_os = "dragonfly", -target_os = "freebsd", -target_os = "netbsd", -target_os = "openbsd" + target_os = "windows", + target_os = "macos", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" )))] pub(crate) fn get_file_event(_request: &FileDialogRequest) -> Vec { vec![] } #[cfg(any( -target_os = "windows", -target_os = "macos", -target_os = "linux", -target_os = "dragonfly", -target_os = "freebsd", -target_os = "netbsd", -target_os = "openbsd" + target_os = "windows", + target_os = "macos", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" ))] pub(crate) fn get_file_event(request: &FileDialogRequest) -> Vec { let dialog = rfd::FileDialog::new(); From 31a68a9743351677dd32ca41998305dc96c68ad0 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 18 Jul 2023 18:33:14 -0700 Subject: [PATCH 13/25] Rename dioxus to dx --- packages/cli/docs/src/cmd/build.md | 2 +- packages/cli/docs/src/cmd/clean.md | 2 +- packages/cli/docs/src/cmd/serve.md | 2 +- packages/cli/docs/src/creating.md | 2 +- packages/fullstack/examples/axum-auth/src/main.rs | 2 +- packages/fullstack/examples/axum-hello-world/src/main.rs | 2 +- packages/fullstack/examples/axum-router/src/main.rs | 2 +- packages/fullstack/examples/salvo-hello-world/src/main.rs | 2 +- packages/fullstack/examples/static-hydrated/src/main.rs | 2 +- packages/fullstack/examples/warp-hello-world/src/main.rs | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/cli/docs/src/cmd/build.md b/packages/cli/docs/src/cmd/build.md index ec067c774..6109d14f1 100644 --- a/packages/cli/docs/src/cmd/build.md +++ b/packages/cli/docs/src/cmd/build.md @@ -43,7 +43,7 @@ dx build --platform web You can add the `--bin` option to select which crate you want Dioxus to build: ``` -dioxus build --bin app +dx build --bin app ``` ## Build Example diff --git a/packages/cli/docs/src/cmd/clean.md b/packages/cli/docs/src/cmd/clean.md index c81f352e5..ef938d245 100644 --- a/packages/cli/docs/src/cmd/clean.md +++ b/packages/cli/docs/src/cmd/clean.md @@ -23,5 +23,5 @@ dx clean You can add the `--bin` option to select which crate you want Dioxus to clean artifacts from: ``` -dioxus clean --bin app +dx clean --bin app ``` diff --git a/packages/cli/docs/src/cmd/serve.md b/packages/cli/docs/src/cmd/serve.md index ccf70d310..d8b4e0d42 100644 --- a/packages/cli/docs/src/cmd/serve.md +++ b/packages/cli/docs/src/cmd/serve.md @@ -37,7 +37,7 @@ dx serve --exmaple test You can add the `--bin` option to select which crate you want Dioxus to build and serve: ``` -dioxus serve --bin app +dx serve --bin app ``` ## Open Browser diff --git a/packages/cli/docs/src/creating.md b/packages/cli/docs/src/creating.md index 95470827f..6c2d5754c 100644 --- a/packages/cli/docs/src/creating.md +++ b/packages/cli/docs/src/creating.md @@ -7,7 +7,7 @@ Once you have the Dioxus CLI tool installed, you can use it to create dioxus pro First, run the `dx create` command to create a new project ready to be used with Dioxus and the Dioxus CLI: ``` -dioxus create hello-dioxus +dx create hello-dioxus ``` > It will clone a default template from github template: [DioxusLabs/dioxus-template](https://github.com/DioxusLabs/dioxus-template) diff --git a/packages/fullstack/examples/axum-auth/src/main.rs b/packages/fullstack/examples/axum-auth/src/main.rs index 00ddb95f9..fe94c9628 100644 --- a/packages/fullstack/examples/axum-auth/src/main.rs +++ b/packages/fullstack/examples/axum-auth/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr //! ``` diff --git a/packages/fullstack/examples/axum-hello-world/src/main.rs b/packages/fullstack/examples/axum-hello-world/src/main.rs index 739a24b1c..e00b9ae05 100644 --- a/packages/fullstack/examples/axum-hello-world/src/main.rs +++ b/packages/fullstack/examples/axum-hello-world/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr //! ``` diff --git a/packages/fullstack/examples/axum-router/src/main.rs b/packages/fullstack/examples/axum-router/src/main.rs index f78904277..54ce11769 100644 --- a/packages/fullstack/examples/axum-router/src/main.rs +++ b/packages/fullstack/examples/axum-router/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr //! ``` diff --git a/packages/fullstack/examples/salvo-hello-world/src/main.rs b/packages/fullstack/examples/salvo-hello-world/src/main.rs index 9e5649efc..bf6c2872a 100644 --- a/packages/fullstack/examples/salvo-hello-world/src/main.rs +++ b/packages/fullstack/examples/salvo-hello-world/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr //! ``` diff --git a/packages/fullstack/examples/static-hydrated/src/main.rs b/packages/fullstack/examples/static-hydrated/src/main.rs index eedc0187e..f89b01cce 100644 --- a/packages/fullstack/examples/static-hydrated/src/main.rs +++ b/packages/fullstack/examples/static-hydrated/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr //! ``` diff --git a/packages/fullstack/examples/warp-hello-world/src/main.rs b/packages/fullstack/examples/warp-hello-world/src/main.rs index 9e5649efc..bf6c2872a 100644 --- a/packages/fullstack/examples/warp-hello-world/src/main.rs +++ b/packages/fullstack/examples/warp-hello-world/src/main.rs @@ -1,7 +1,7 @@ //! Run with: //! //! ```sh -//! dioxus build --features web +//! dx build --features web //! cargo run --features ssr //! ``` From f69b84bf34114c68749e956f26ed61db38079f7c Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 18 Jul 2023 18:39:06 -0700 Subject: [PATCH 14/25] Fix playwrite cli args --- playwright.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/playwright.config.js b/playwright.config.js index 978979b9c..d7f019bbd 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -82,7 +82,7 @@ module.exports = defineConfig({ }, { cwd: path.join(process.cwd(), "playwright-tests", "web"), - command: "dioxus serve", + command: "dx serve", port: 8080, timeout: 10 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -90,7 +90,7 @@ module.exports = defineConfig({ }, { cwd: path.join(process.cwd(), 'playwrite-tests', 'fullstack'), - command: 'dioxus build --features web --release\ncargo run --release --features ssr', + command: 'dx build --features web --release\ncargo run --release --features ssr', port: 3333, timeout: 10 * 60 * 1000, reuseExistingServer: !process.env.CI, From 8527e60e018b071b8d7fc27ab6ebff9952aa932d Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 09:52:51 -0700 Subject: [PATCH 15/25] Move playwright stuff into its own directory --- package-lock.json => playwright-tests/package-lock.json | 0 package.json => playwright-tests/package.json | 0 playwright.config.js => playwright-tests/playwright.config.js | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename package-lock.json => playwright-tests/package-lock.json (100%) rename package.json => playwright-tests/package.json (100%) rename playwright.config.js => playwright-tests/playwright.config.js (98%) diff --git a/package-lock.json b/playwright-tests/package-lock.json similarity index 100% rename from package-lock.json rename to playwright-tests/package-lock.json diff --git a/package.json b/playwright-tests/package.json similarity index 100% rename from package.json rename to playwright-tests/package.json diff --git a/playwright.config.js b/playwright-tests/playwright.config.js similarity index 98% rename from playwright.config.js rename to playwright-tests/playwright.config.js index d7f019bbd..026a574ad 100644 --- a/playwright.config.js +++ b/playwright-tests/playwright.config.js @@ -12,7 +12,7 @@ const path = require("path"); * @see https://playwright.dev/docs/test-configuration */ module.exports = defineConfig({ - testDir: "./playwright-tests", + testDir: ".", /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ From b9794aaad4bcd6898ee93c5bc8a6b529f7efa52d Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 09:54:54 -0700 Subject: [PATCH 16/25] Only run miri for changed files --- .github/workflows/miri.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml index 73b38dec9..0146e98bc 100644 --- a/.github/workflows/miri.yml +++ b/.github/workflows/miri.yml @@ -6,6 +6,13 @@ on: branches: - 'auto' - 'try' + paths: + - packages/** + - examples/** + - src/** + - .github/** + - lib.rs + - Cargo.toml pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: From 5eac6cd1c5d76de3c72bbd1da1543d1ef3c2ebd0 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 09:57:00 -0700 Subject: [PATCH 17/25] Add working dir --- .github/workflows/playwright.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 84891f403..77dda0c11 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -9,17 +9,12 @@ jobs: if: github.event.pull_request.draft == false timeout-minutes: 60 runs-on: ubuntu-20.04 + working-directory: playwright-tests steps: - - uses: actions/checkout@v3 + # Do our best to cache the toolchain and node install steps - uses: actions/setup-node@v3 with: node-version: 16 - - name: Install dependencies - run: npm ci - - name: Install Playwright - run: npm install -D @playwright/test - - name: Install Playwright Browsers - run: npx playwright install --with-deps - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -29,11 +24,18 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Install WASM toolchain run: rustup target add wasm32-unknown-unknown + - uses: actions/checkout@v3 + - name: Install dependencies + run: npm ci + - name: Install Playwright + run: npm install -D @playwright/test + - name: Install Playwright Browsers + run: npx playwright install --with-deps - name: Install Dioxus CLI uses: actions-rs/cargo@v1 with: command: install - args: --path packages/cli + args: --path ../packages/cli - name: Run Playwright tests run: npx playwright test - uses: actions/upload-artifact@v3 From f51b0099dd6b723f9546d7eb5890283fc31b75fe Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 09:59:05 -0700 Subject: [PATCH 18/25] CD as a step --- .github/workflows/playwright.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 77dda0c11..cdd7fb996 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -9,7 +9,6 @@ jobs: if: github.event.pull_request.draft == false timeout-minutes: 60 runs-on: ubuntu-20.04 - working-directory: playwright-tests steps: # Do our best to cache the toolchain and node install steps - uses: actions/setup-node@v3 @@ -25,6 +24,8 @@ jobs: - name: Install WASM toolchain run: rustup target add wasm32-unknown-unknown - uses: actions/checkout@v3 + - name: Enter playwright-tests + run: cd playwright-tests - name: Install dependencies run: npm ci - name: Install Playwright From da21e5f4c1269e2893c955e44616bebc85e34d77 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 10:03:28 -0700 Subject: [PATCH 19/25] Move order around, set default working directory --- .github/workflows/playwright.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index cdd7fb996..974649419 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -4,6 +4,9 @@ on: branches: [ main, master ] pull_request: branches: [ main, master ] +defaults: + run: + working-directory: ./playwright-tests jobs: test: if: github.event.pull_request.draft == false @@ -11,6 +14,7 @@ jobs: runs-on: ubuntu-20.04 steps: # Do our best to cache the toolchain and node install steps + - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 16 @@ -23,9 +27,6 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Install WASM toolchain run: rustup target add wasm32-unknown-unknown - - uses: actions/checkout@v3 - - name: Enter playwright-tests - run: cd playwright-tests - name: Install dependencies run: npm ci - name: Install Playwright From 22ea04e45da8d2354c93305d3d82c86c870b48b3 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 10:08:50 -0700 Subject: [PATCH 20/25] Use different path for cli --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 974649419..bddc767e6 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -37,7 +37,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: install - args: --path ../packages/cli + args: --path packages/cli - name: Run Playwright tests run: npx playwright test - uses: actions/upload-artifact@v3 From 0ceaaa6c964b1c75f2beec47bad321acba4556f1 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 10:11:11 -0700 Subject: [PATCH 21/25] Don't install the CLI --- .github/workflows/playwright.yml | 11 ++++++----- playwright-tests/playwright.config.js | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index bddc767e6..7fe524bb3 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -33,11 +33,12 @@ jobs: run: npm install -D @playwright/test - name: Install Playwright Browsers run: npx playwright install --with-deps - - name: Install Dioxus CLI - uses: actions-rs/cargo@v1 - with: - command: install - args: --path packages/cli + # Cache the CLI by using cargo run internally + # - name: Install Dioxus CLI + # uses: actions-rs/cargo@v1 + # with: + # command: install + # args: --path packages/cli - name: Run Playwright tests run: npx playwright test - uses: actions/upload-artifact@v3 diff --git a/playwright-tests/playwright.config.js b/playwright-tests/playwright.config.js index 026a574ad..5ab81f161 100644 --- a/playwright-tests/playwright.config.js +++ b/playwright-tests/playwright.config.js @@ -82,7 +82,7 @@ module.exports = defineConfig({ }, { cwd: path.join(process.cwd(), "playwright-tests", "web"), - command: "dx serve", + command: "cargo run --package dioxus-cli -- serve", port: 8080, timeout: 10 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -90,7 +90,7 @@ module.exports = defineConfig({ }, { cwd: path.join(process.cwd(), 'playwrite-tests', 'fullstack'), - command: 'dx build --features web --release\ncargo run --release --features ssr', + command: 'cargo run --package dioxus-cli -- build --features web --release\ncargo run --release --features ssr', port: 3333, timeout: 10 * 60 * 1000, reuseExistingServer: !process.env.CI, From eb43429ff6c839929ce2d77c648b928761acc845 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 10:16:27 -0700 Subject: [PATCH 22/25] Bump versions, move paths --- playwright-tests/package-lock.json | 20 +++--- playwright-tests/package.json | 2 +- playwright-tests/playwright-report/index.html | 62 +++++++++++++++++++ playwright-tests/playwright.config.js | 4 +- 4 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 playwright-tests/playwright-report/index.html diff --git a/playwright-tests/package-lock.json b/playwright-tests/package-lock.json index 348b505d4..4f1b932ac 100644 --- a/playwright-tests/package-lock.json +++ b/playwright-tests/package-lock.json @@ -9,23 +9,23 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { - "@playwright/test": "^1.34.3" + "@playwright/test": "^1.36.1" } }, "node_modules/@playwright/test": { - "version": "1.34.3", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.34.3.tgz", - "integrity": "sha512-zPLef6w9P6T/iT6XDYG3mvGOqOyb6eHaV9XtkunYs0+OzxBtrPAAaHotc0X+PJ00WPPnLfFBTl7mf45Mn8DBmw==", + "version": "1.36.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.36.1.tgz", + "integrity": "sha512-YK7yGWK0N3C2QInPU6iaf/L3N95dlGdbsezLya4n0ZCh3IL7VgPGxC6Gnznh9ApWdOmkJeleT2kMTcWPRZvzqg==", "dev": true, "dependencies": { "@types/node": "*", - "playwright-core": "1.34.3" + "playwright-core": "1.36.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=14" + "node": ">=16" }, "optionalDependencies": { "fsevents": "2.3.2" @@ -52,15 +52,15 @@ } }, "node_modules/playwright-core": { - "version": "1.34.3", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.34.3.tgz", - "integrity": "sha512-2pWd6G7OHKemc5x1r1rp8aQcpvDh7goMBZlJv6Co5vCNLVcQJdhxRL09SGaY6HcyHH9aT4tiynZabMofVasBYw==", + "version": "1.36.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.36.1.tgz", + "integrity": "sha512-7+tmPuMcEW4xeCL9cp9KxmYpQYHKkyjwoXRnoeTowaeNat8PoBMk/HwCYhqkH2fRkshfKEOiVus/IhID2Pg8kg==", "dev": true, "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=14" + "node": ">=16" } } } diff --git a/playwright-tests/package.json b/playwright-tests/package.json index ceb38db89..31d444420 100644 --- a/playwright-tests/package.json +++ b/playwright-tests/package.json @@ -12,6 +12,6 @@ "author": "", "license": "ISC", "devDependencies": { - "@playwright/test": "^1.34.3" + "@playwright/test": "^1.36.1" } } diff --git a/playwright-tests/playwright-report/index.html b/playwright-tests/playwright-report/index.html new file mode 100644 index 000000000..71730368d --- /dev/null +++ b/playwright-tests/playwright-report/index.html @@ -0,0 +1,62 @@ + + + + + + + + + Playwright Test Report + + + + +
+ + + + \ No newline at end of file diff --git a/playwright-tests/playwright.config.js b/playwright-tests/playwright.config.js index 5ab81f161..54fe810a7 100644 --- a/playwright-tests/playwright.config.js +++ b/playwright-tests/playwright.config.js @@ -81,7 +81,7 @@ module.exports = defineConfig({ stdout: "pipe", }, { - cwd: path.join(process.cwd(), "playwright-tests", "web"), + cwd: path.join(process.cwd(), "web"), command: "cargo run --package dioxus-cli -- serve", port: 8080, timeout: 10 * 60 * 1000, @@ -89,7 +89,7 @@ module.exports = defineConfig({ stdout: "pipe", }, { - cwd: path.join(process.cwd(), 'playwrite-tests', 'fullstack'), + cwd: path.join(process.cwd(), 'fullstack'), command: 'cargo run --package dioxus-cli -- build --features web --release\ncargo run --release --features ssr', port: 3333, timeout: 10 * 60 * 1000, From 2871c8bb4dbaaa29e58d6348fda734d9d60f4d71 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 12:08:13 -0700 Subject: [PATCH 23/25] Don't use boxed cell slice, use a refcell instead --- packages/core/src/create.rs | 5 +- packages/core/src/diff.rs | 18 ++-- packages/core/src/nodes.rs | 105 +------------------- packages/core/src/scope_arena.rs | 8 +- packages/core/src/virtual_dom.rs | 3 + packages/dioxus-tui/examples/colorpicker.rs | 2 +- packages/web/src/rehydrate.rs | 2 +- 7 files changed, 24 insertions(+), 119 deletions(-) diff --git a/packages/core/src/create.rs b/packages/core/src/create.rs index 8efdf13e4..6159c882b 100644 --- a/packages/core/src/create.rs +++ b/packages/core/src/create.rs @@ -88,8 +88,7 @@ impl<'b> VirtualDom { } // Intialize the root nodes slice - node.root_ids - .intialize(vec![ElementId(0); node.template.get().roots.len()].into_boxed_slice()); + *node.root_ids.borrow_mut() = vec![ElementId(0); node.template.get().roots.len()]; // The best renderers will have templates prehydrated and registered // Just in case, let's create the template using instructions anyways @@ -328,7 +327,7 @@ impl<'b> VirtualDom { fn load_template_root(&mut self, template: &VNode, root_idx: usize) -> ElementId { // Get an ID for this root since it's a real root let this_id = self.next_root(template, root_idx); - template.root_ids.set(root_idx, this_id); + template.root_ids.borrow_mut()[root_idx] = this_id; self.mutations.push(LoadTemplate { name: template.template.get().name, diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index cfda18505..74988210a 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -129,12 +129,14 @@ impl<'b> VirtualDom { }); // Make sure the roots get transferred over while we're here - right_template.root_ids.transfer(&left_template.root_ids); + *right_template.root_ids.borrow_mut() = left_template.root_ids.borrow().clone(); + + let root_ids = right_template.root_ids.borrow(); // Update the node refs - for i in 0..right_template.root_ids.len() { - if let Some(root_id) = right_template.root_ids.get(i) { - self.update_template(root_id, right_template); + for i in 0..root_ids.len() { + if let Some(root_id) = root_ids.get(i) { + self.update_template(*root_id, right_template); } } } @@ -686,7 +688,7 @@ impl<'b> VirtualDom { Some(node) => node, None => { self.mutations.push(Mutation::PushRoot { - id: node.root_ids.get(idx).unwrap(), + id: node.root_ids.borrow()[idx], }); return 1; } @@ -821,7 +823,7 @@ impl<'b> VirtualDom { if let Some(dy) = node.dynamic_root(idx) { self.remove_dynamic_node(dy, gen_muts); } else { - let id = node.root_ids.get(idx).unwrap(); + let id = node.root_ids.borrow()[idx]; if gen_muts { self.mutations.push(Mutation::Remove { id }); } @@ -928,7 +930,7 @@ impl<'b> VirtualDom { fn find_first_element(&self, node: &'b VNode<'b>) -> ElementId { match node.dynamic_root(0) { - None => node.root_ids.get(0).unwrap(), + None => node.root_ids.borrow()[0], Some(Text(t)) => t.id.get().unwrap(), Some(Fragment(t)) => self.find_first_element(&t[0]), Some(Placeholder(t)) => t.id.get().unwrap(), @@ -944,7 +946,7 @@ impl<'b> VirtualDom { fn find_last_element(&self, node: &'b VNode<'b>) -> ElementId { match node.dynamic_root(node.template.get().roots.len() - 1) { - None => node.root_ids.last().unwrap(), + None => *node.root_ids.borrow().last().unwrap(), Some(Text(t)) => t.id.get().unwrap(), Some(Fragment(t)) => self.find_last_element(t.last().unwrap()), Some(Placeholder(t)) => t.id.get().unwrap(), diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 209c37c77..197550a3b 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -5,7 +5,7 @@ use bumpalo::boxed::Box as BumpBox; use bumpalo::Bump; use std::{ any::{Any, TypeId}, - cell::{Cell, RefCell, UnsafeCell}, + cell::{Cell, RefCell}, fmt::{Arguments, Debug}, }; @@ -54,7 +54,7 @@ pub struct VNode<'a> { /// The IDs for the roots of this template - to be used when moving the template around and removing it from /// the actual Dom - pub root_ids: BoxedCellSlice, + pub root_ids: RefCell>, /// The dynamic parts of the template pub dynamic_nodes: &'a [DynamicNode<'a>], @@ -63,112 +63,13 @@ pub struct VNode<'a> { pub dynamic_attrs: &'a [Attribute<'a>], } -// Saftey: There is no way to get references to the internal data of this struct so no refrences will be invalidated by mutating the data with a immutable reference (The same principle behind Cell) -#[derive(Debug, Default)] -pub struct BoxedCellSlice(UnsafeCell>>); - -impl Clone for BoxedCellSlice { - fn clone(&self) -> Self { - Self(UnsafeCell::new(unsafe { (*self.0.get()).clone() })) - } -} - -impl BoxedCellSlice { - pub fn last(&self) -> Option { - unsafe { - (*self.0.get()) - .as_ref() - .and_then(|inner| inner.as_ref().last().copied()) - } - } - - pub fn get(&self, idx: usize) -> Option { - unsafe { - (*self.0.get()) - .as_ref() - .and_then(|inner| inner.as_ref().get(idx).copied()) - } - } - - pub unsafe fn get_unchecked(&self, idx: usize) -> Option { - (*self.0.get()) - .as_ref() - .and_then(|inner| inner.as_ref().get(idx).copied()) - } - - pub fn set(&self, idx: usize, new: ElementId) { - unsafe { - if let Some(inner) = &mut *self.0.get() { - inner[idx] = new; - } - } - } - - pub fn intialize(&self, contents: Box<[ElementId]>) { - unsafe { - *self.0.get() = Some(contents); - } - } - - pub fn transfer(&self, other: &Self) { - unsafe { - *self.0.get() = (*other.0.get()).clone(); - } - } - - pub fn take_from(&self, other: &Self) { - unsafe { - *self.0.get() = (*other.0.get()).take(); - } - } - - pub fn len(&self) -> usize { - unsafe { - (*self.0.get()) - .as_ref() - .map(|inner| inner.len()) - .unwrap_or(0) - } - } -} - -impl<'a> IntoIterator for &'a BoxedCellSlice { - type Item = ElementId; - - type IntoIter = BoxedCellSliceIter<'a>; - - fn into_iter(self) -> Self::IntoIter { - BoxedCellSliceIter { - index: 0, - borrow: self, - } - } -} - -pub struct BoxedCellSliceIter<'a> { - index: usize, - borrow: &'a BoxedCellSlice, -} - -impl Iterator for BoxedCellSliceIter<'_> { - type Item = ElementId; - - fn next(&mut self) -> Option { - let result = self.borrow.get(self.index); - if result.is_some() { - self.index += 1; - } - result - } -} - impl<'a> VNode<'a> { /// Create a template with no nodes that will be skipped over during diffing pub fn empty() -> Element<'a> { Some(VNode { key: None, parent: None, - root_ids: BoxedCellSlice::default(), + root_ids: Default::default(), dynamic_nodes: &[], dynamic_attrs: &[], template: Cell::new(Template { diff --git a/packages/core/src/scope_arena.rs b/packages/core/src/scope_arena.rs index d058e34de..e8134c238 100644 --- a/packages/core/src/scope_arena.rs +++ b/packages/core/src/scope_arena.rs @@ -83,12 +83,12 @@ impl VirtualDom { id: scope.id, }); - if matches!(allocated, RenderReturn::Aborted(_)) { - if scope.suspended.get() { + if scope.suspended.get() { + if matches!(allocated, RenderReturn::Aborted(_)) { self.suspended_scopes.insert(scope.id); - } else if !self.suspended_scopes.is_empty() { - _ = self.suspended_scopes.remove(&scope.id); } + } else if !self.suspended_scopes.is_empty() { + _ = self.suspended_scopes.remove(&scope.id); } // rebind the lifetime now that its stored internally diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 31a1b5912..ee6e9c5d6 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -571,12 +571,15 @@ impl VirtualDom { /// The mutations will be thrown out, so it's best to use this method for things like SSR that have async content pub async fn wait_for_suspense(&mut self) { loop { + // println!("waiting for suspense {:?}", self.suspended_scopes); if self.suspended_scopes.is_empty() { return; } + // println!("waiting for suspense"); self.wait_for_work().await; + // println!("Rendered immediately"); _ = self.render_immediate(); } } diff --git a/packages/dioxus-tui/examples/colorpicker.rs b/packages/dioxus-tui/examples/colorpicker.rs index 1de6b8209..00f8ef7e0 100644 --- a/packages/dioxus-tui/examples/colorpicker.rs +++ b/packages/dioxus-tui/examples/colorpicker.rs @@ -20,7 +20,7 @@ fn app(cx: Scope) -> Element { background_color: "hsl({hue}, 70%, {brightness}%)", onmousemove: move |evt| { if let RenderReturn::Ready(node) = cx.root_node() { - if let Some(id) = node.root_ids.get(0){ + if let Some(id) = node.root_ids.borrow().get(0).cloned() { let node = tui_query.get(mapping.get_node_id(id).unwrap()); let Size{width, height} = node.size().unwrap(); let pos = evt.inner().element_coordinates(); diff --git a/packages/web/src/rehydrate.rs b/packages/web/src/rehydrate.rs index 8af7da16d..5cc9ea57e 100644 --- a/packages/web/src/rehydrate.rs +++ b/packages/web/src/rehydrate.rs @@ -90,7 +90,7 @@ impl WebsysDom { // make sure we set the root node ids even if the node is not dynamic set_node( hydrated, - vnode.root_ids.get(i).ok_or(VNodeNotInitialized)?, + *vnode.root_ids.borrow().get(i).ok_or(VNodeNotInitialized)?, current_child.clone()?, ); From 163fe68f455c93b0a425b3d9fb0bf527e08f2063 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 12:26:32 -0700 Subject: [PATCH 24/25] Remove a bit more unsafe --- packages/core/tests/task.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/core/tests/task.rs b/packages/core/tests/task.rs index 2704c5eb2..316cea6dd 100644 --- a/packages/core/tests/task.rs +++ b/packages/core/tests/task.rs @@ -1,9 +1,9 @@ //! Verify that tasks get polled by the virtualdom properly, and that we escape wait_for_work safely use dioxus::prelude::*; -use std::time::Duration; +use std::{sync::atomic::AtomicUsize, time::Duration}; -static mut POLL_COUNT: usize = 0; +static POLL_COUNT: AtomicUsize = AtomicUsize::new(0); #[tokio::test] async fn it_works() { @@ -18,7 +18,10 @@ async fn it_works() { // By the time the tasks are finished, we should've accumulated ticks from two tasks // Be warned that by setting the delay to too short, tokio might not schedule in the tasks - assert_eq!(unsafe { POLL_COUNT }, 135); + assert_eq!( + POLL_COUNT.fetch_add(0, std::sync::atomic::Ordering::Relaxed), + 135 + ); } fn app(cx: Scope) -> Element { @@ -26,14 +29,14 @@ fn app(cx: Scope) -> Element { cx.spawn(async { for x in 0..10 { tokio::time::sleep(Duration::from_micros(50)).await; - unsafe { POLL_COUNT += x } + POLL_COUNT.fetch_add(x, std::sync::atomic::Ordering::Relaxed); } }); cx.spawn(async { for x in 0..10 { tokio::time::sleep(Duration::from_micros(25)).await; - unsafe { POLL_COUNT += x * 2 } + POLL_COUNT.fetch_add(x * 2, std::sync::atomic::Ordering::Relaxed); } }); }); From d82b2f226f23cbcf8f7b8cb5f817de5e37bdfce3 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 19 Jul 2023 12:50:28 -0700 Subject: [PATCH 25/25] Kill previous CI jobs when new pushed --- .github/workflows/docs stable.yml | 4 ++++ .github/workflows/docs.yml | 4 ++++ .github/workflows/macos.yml | 4 ++++ .github/workflows/main.yml | 4 ++++ .github/workflows/miri.yml | 4 +++- .github/workflows/playwright.yml | 5 +++++ .github/workflows/windows.yml | 4 ++++ 7 files changed, 28 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs stable.yml b/.github/workflows/docs stable.yml index a2d4e2c07..069d4308a 100644 --- a/.github/workflows/docs stable.yml +++ b/.github/workflows/docs stable.yml @@ -3,6 +3,10 @@ name: docs stable on: workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: build-deploy: runs-on: ubuntu-latest diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index dafe0384d..3a452e770 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -8,6 +8,10 @@ on: branches: - master +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: build-deploy: runs-on: ubuntu-latest diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index eef04d521..471bdd715 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -24,6 +24,10 @@ on: - lib.rs - Cargo.toml +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: test: if: github.event.pull_request.draft == false diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b37e63aa4..a95af8574 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,6 +27,10 @@ on: - lib.rs - Cargo.toml +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: check: if: github.event.pull_request.draft == false diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml index 0146e98bc..e8aab0732 100644 --- a/.github/workflows/miri.yml +++ b/.github/workflows/miri.yml @@ -38,7 +38,9 @@ env: # - tokio-stream/Cargo.toml # rust_min: 1.49.0 - +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: test: diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 7fe524bb3..41fa92fa7 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -7,6 +7,11 @@ on: defaults: run: working-directory: ./playwright-tests + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: test: if: github.event.pull_request.draft == false diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 368df1630..f5792cf1e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -24,6 +24,10 @@ on: - lib.rs - Cargo.toml +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: test: if: github.event.pull_request.draft == false