From 23c215da0218281db7e342e053e1709b4ae3495d Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 17 Sep 2023 14:11:13 -0500 Subject: [PATCH 01/11] make RuntimeGuard public --- packages/core/src/runtime.rs | 81 +++++++++++++++--------------------- 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/packages/core/src/runtime.rs b/packages/core/src/runtime.rs index 4b9dcdab0..566e9ba7c 100644 --- a/packages/core/src/runtime.rs +++ b/packages/core/src/runtime.rs @@ -7,51 +7,6 @@ thread_local! { static RUNTIMES: RefCell>> = RefCell::new(vec![]); } -/// Run some code within a runtime -pub fn in_runtime(runtime: Rc, f: impl FnOnce() -> R) -> R { - let _guard = RuntimeGuard::new(runtime); - f() -} - -/// Override the current runtime. This must be used to override the current runtime when importing components from a dynamic library that has it's own runtime. -/// -/// ```rust -/// use dioxus::prelude::*; -/// -/// fn main() { -/// let virtual_dom = VirtualDom::new(app); -/// } -/// -/// fn app(cx: Scope) -> Element { -/// render!{ Component { runtime: Runtime::current().unwrap() } } -/// } -/// -/// // In a dynamic library -/// #[derive(Props)] -/// struct ComponentProps { -/// runtime: std::rc::Rc, -/// } -/// -/// impl PartialEq for ComponentProps { -/// fn eq(&self, _other: &Self) -> bool { -/// true -/// } -/// } -/// -/// fn Component(cx: Scope) -> Element { -/// cx.use_hook(|| override_runtime(cx.props.runtime.clone())); -/// -/// render! { div {} } -/// } -/// ``` -pub fn override_runtime(runtime: Rc) { - RUNTIMES.with(|stack| { - let mut stack = stack.borrow_mut(); - stack.pop(); - stack.push(runtime); - }); -} - /// Pushes a new scope onto the stack pub(crate) fn push_runtime(runtime: Rc) { RUNTIMES.with(|stack| stack.borrow_mut().push(runtime)); @@ -143,10 +98,42 @@ impl Runtime { } } -pub(crate) struct RuntimeGuard(Rc); +/// A gaurd for a new runtime. This must be used to override the current runtime when importing components from a dynamic library that has it's own runtime. +/// +/// ```rust +/// use dioxus::prelude::*; +/// +/// fn main() { +/// let virtual_dom = VirtualDom::new(app); +/// } +/// +/// fn app(cx: Scope) -> Element { +/// render!{ Component { runtime: Runtime::current().unwrap() } } +/// } +/// +/// // In a dynamic library +/// #[derive(Props)] +/// struct ComponentProps { +/// runtime: std::rc::Rc, +/// } +/// +/// impl PartialEq for ComponentProps { +/// fn eq(&self, _other: &Self) -> bool { +/// true +/// } +/// } +/// +/// fn Component(cx: Scope) -> Element { +/// cx.use_hook(|| RuntimeGuard::new(cx.props.runtime.clone())); +/// +/// render! { div {} } +/// } +/// ``` +pub struct RuntimeGuard(Rc); impl RuntimeGuard { - pub(crate) fn new(runtime: Rc) -> Self { + /// Create a new runtime guard that sets the current Dioxus runtime. The runtime will be reset when the guard is dropped + pub fn new(runtime: Rc) -> Self { push_runtime(runtime.clone()); Self(runtime) } From b9a92a1bd814101f65d7038e07678152f0bfa848 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 17 Sep 2023 20:03:58 -0500 Subject: [PATCH 02/11] fix core exports --- packages/core/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 5b2f83305..029e884db 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -32,7 +32,7 @@ pub(crate) mod innerlude { pub use crate::nodes::RenderReturn; pub use crate::nodes::*; pub use crate::properties::*; - pub use crate::runtime::{in_runtime, override_runtime, Runtime}; + pub use crate::runtime::{Runtime, RuntimeGuard}; pub use crate::scheduler::*; pub use crate::scope_context::*; pub use crate::scopes::*; @@ -87,11 +87,11 @@ pub use crate::innerlude::{ pub mod prelude { pub use crate::innerlude::{ consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, has_context, - in_runtime, override_runtime, provide_context, provide_context_to_scope, - provide_root_context, push_future, remove_future, schedule_update_any, spawn, - spawn_forever, suspend, throw, AnyValue, Component, Element, Event, EventHandler, Fragment, - IntoAttributeValue, LazyNodes, Properties, Runtime, Scope, ScopeId, ScopeState, Scoped, - TaskId, Template, TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom, + provide_context, provide_context_to_scope, provide_root_context, push_future, + remove_future, schedule_update_any, spawn, spawn_forever, suspend, throw, AnyValue, + Component, Element, Event, EventHandler, Fragment, IntoAttributeValue, LazyNodes, + Properties, Runtime, RuntimeGuard, Scope, ScopeId, ScopeState, Scoped, TaskId, Template, + TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom, }; } From ef6e9098fdd57e434b7efe67606fc4e5802c5b87 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 17 Sep 2023 20:06:41 -0500 Subject: [PATCH 03/11] fix formatting --- packages/fullstack/src/adapters/warp_adapter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fullstack/src/adapters/warp_adapter.rs b/packages/fullstack/src/adapters/warp_adapter.rs index 5afcb5077..316d70e56 100644 --- a/packages/fullstack/src/adapters/warp_adapter.rs +++ b/packages/fullstack/src/adapters/warp_adapter.rs @@ -143,7 +143,7 @@ pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl R let req = warp::hyper::Request::from_parts(parts, bytes.into()); service.run(req).await.map_err(|err| { tracing::error!("Server function error: {}", err); - + struct WarpServerFnError(String); impl std::fmt::Debug for WarpServerFnError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -152,7 +152,7 @@ pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl R } impl warp::reject::Reject for WarpServerFnError {} - + warp::reject::custom(WarpServerFnError(err.to_string())) }) } From 07613c806b3240ac3c56052fe8737936386968af Mon Sep 17 00:00:00 2001 From: Leonard Date: Tue, 19 Sep 2023 01:51:04 +0200 Subject: [PATCH 04/11] Fix #1367 (#1471) * Bump cargo_toml to 1.16.0 * Format --- packages/cli/Cargo.toml | 2 +- packages/cli/src/cli/bundle.rs | 8 ++++---- packages/fullstack/src/adapters/warp_adapter.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index f325430aa..98bc8155b 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.79" toml = "0.5.8" fs_extra = "1.2.0" -cargo_toml = "0.11.4" +cargo_toml = "0.16.0" futures = "0.3.21" notify = { version = "5.0.0-pre.16", features = ["serde"] } html_parser = { workspace = true } diff --git a/packages/cli/src/cli/bundle.rs b/packages/cli/src/cli/bundle.rs index 0d4fb23da..80b52cf2f 100644 --- a/packages/cli/src/cli/bundle.rs +++ b/packages/cli/src/cli/bundle.rs @@ -132,10 +132,10 @@ impl Bundle { .project_out_directory(crate_config.out_dir) .package_settings(PackageSettings { product_name: crate_config.dioxus_config.application.name.clone(), - version: package.version, - description: package.description.unwrap_or_default(), - homepage: package.homepage, - authors: Some(package.authors), + version: package.version().to_string(), + description: package.description().unwrap_or_default().to_string(), + homepage: Some(package.homepage().unwrap_or_default().to_string()), + authors: Some(Vec::from(package.authors())), default_run: Some(crate_config.dioxus_config.application.name.clone()), }) .binaries(binaries) diff --git a/packages/fullstack/src/adapters/warp_adapter.rs b/packages/fullstack/src/adapters/warp_adapter.rs index 5afcb5077..316d70e56 100644 --- a/packages/fullstack/src/adapters/warp_adapter.rs +++ b/packages/fullstack/src/adapters/warp_adapter.rs @@ -143,7 +143,7 @@ pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl R let req = warp::hyper::Request::from_parts(parts, bytes.into()); service.run(req).await.map_err(|err| { tracing::error!("Server function error: {}", err); - + struct WarpServerFnError(String); impl std::fmt::Debug for WarpServerFnError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -152,7 +152,7 @@ pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl R } impl warp::reject::Reject for WarpServerFnError {} - + warp::reject::custom(WarpServerFnError(err.to_string())) }) } From 98babe10962be8fa3bcc22b973d460bf87eb4b53 Mon Sep 17 00:00:00 2001 From: Calastrophe Date: Tue, 19 Sep 2023 00:50:57 +0000 Subject: [PATCH 05/11] partial ord impl (#1473) --- packages/hooks/src/usestate.rs | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/packages/hooks/src/usestate.rs b/packages/hooks/src/usestate.rs index 9e3fb5eed..a2da3c885 100644 --- a/packages/hooks/src/usestate.rs +++ b/packages/hooks/src/usestate.rs @@ -336,6 +336,50 @@ impl PartialEq> for UseState { } } +impl PartialOrd for UseState { + fn ge(&self, other: &T) -> bool { + *self.current_val >= *other + } + + fn gt(&self, other: &T) -> bool { + *self.current_val > *other + } + + fn le(&self, other: &T) -> bool { + *self.current_val <= *other + } + + fn lt(&self, other: &T) -> bool { + *self.current_val < *other + } + + fn partial_cmp(&self, other: &T) -> Option { + (*self.current_val).partial_cmp(other) + } +} + +impl PartialOrd> for UseState { + fn ge(&self, other: &UseState) -> bool { + self.current_val >= other.current_val + } + + fn gt(&self, other: &UseState) -> bool { + self.current_val > other.current_val + } + + fn le(&self, other: &UseState) -> bool { + self.current_val <= other.current_val + } + + fn lt(&self, other: &UseState) -> bool { + self.current_val < other.current_val + } + + fn partial_cmp(&self, other: &UseState) -> Option { + self.current_val.partial_cmp(&other.current_val) + } +} + impl Debug for UseState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self.current_val) From 60ee82942c4decf67b6ad263f639553d9b7e28a9 Mon Sep 17 00:00:00 2001 From: ealmloff Date: Tue, 19 Sep 2023 16:48:01 -0500 Subject: [PATCH 06/11] restore the tray feature in the desktop crate (#1475) --- packages/desktop/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index a884928ba..dcb994120 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -56,6 +56,7 @@ tokio_runtime = ["tokio"] fullscreen = ["wry/fullscreen"] transparent = ["wry/transparent"] devtools = ["wry/devtools"] +tray = ["wry/tray"] dox = ["wry/dox"] hot-reload = ["dioxus-hot-reload"] From dc6ea152eebf6910139e0e6218a081a262976ab7 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 20 Sep 2023 14:34:47 -0500 Subject: [PATCH 07/11] fix playwright tests on windows --- playwright-tests/playwright.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-tests/playwright.config.js b/playwright-tests/playwright.config.js index 54fe810a7..b4b0c4041 100644 --- a/playwright-tests/playwright.config.js +++ b/playwright-tests/playwright.config.js @@ -90,7 +90,7 @@ module.exports = defineConfig({ }, { cwd: path.join(process.cwd(), 'fullstack'), - command: 'cargo run --package dioxus-cli -- build --features web --release\ncargo run --release --features ssr', + command: 'cargo run --package dioxus-cli -- build --features web --release && cargo run --release --features ssr', port: 3333, timeout: 10 * 60 * 1000, reuseExistingServer: !process.env.CI, From 517a43d7659680a05c1705426f9d5da55579458e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Esp=C3=ADn?= Date: Mon, 25 Sep 2023 15:31:35 +0200 Subject: [PATCH 08/11] fix: Update server function docs link (#1489) --- packages/server-macro/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server-macro/src/lib.rs b/packages/server-macro/src/lib.rs index d00c009d0..7cdc470d9 100644 --- a/packages/server-macro/src/lib.rs +++ b/packages/server-macro/src/lib.rs @@ -8,7 +8,7 @@ use syn::{ Ident, ItemFn, Token, }; -/// Declares that a function is a [server function](dioxus_fullstack). This means that +/// Declares that a function is a [server function](https://dioxuslabs.com/learn/0.4/reference/fullstack/server_functions). This means that /// its body will only run on the server, i.e., when the `ssr` feature is enabled. /// /// If you call a server function from the client (i.e., when the `csr` or `hydrate` features From 31780b3ede85b2fe198aeec178d6277686b04f2f Mon Sep 17 00:00:00 2001 From: Seungwoo Kang Date: Wed, 27 Sep 2023 06:35:17 +0900 Subject: [PATCH 09/11] liveview: Add `interpreter_glue_relative_uri (#1481) * liveview: Add `interpreter_glue_relative_uri` By utilizing `window.location.host` in the client-side JavaScript, we can easily derive the WebSocket URI from a relative path URI. This approach obviates the need for host address retrieval on the server side, unlike the method of serving glue code in liveview using `interpreter_glue`. * liveview: Merge `.._relative_url` functionality - Merged `.._relative_url` to current API `interpreter_glue`. - Edit axum example to work with new feature. * liveview: Fix clippy warning --- packages/liveview/examples/axum.rs | 61 ++++++++++++++++++------------ packages/liveview/src/lib.rs | 41 ++++++++++++++++++-- 2 files changed, 74 insertions(+), 28 deletions(-) diff --git a/packages/liveview/examples/axum.rs b/packages/liveview/examples/axum.rs index 2e7f10ee7..6584d5e9b 100644 --- a/packages/liveview/examples/axum.rs +++ b/packages/liveview/examples/axum.rs @@ -19,32 +19,43 @@ async fn main() { let addr: std::net::SocketAddr = ([127, 0, 0, 1], 3030).into(); let view = dioxus_liveview::LiveViewPool::new(); + let index_page_with_glue = |glue: &str| { + Html(format!( + r#" + + + Dioxus LiveView with axum +
+ {glue} + + "#, + )) + }; - let app = Router::new() - .route( - "/", - get(move || async move { - Html(format!( - r#" - - - Dioxus LiveView with axum -
- {glue} - - "#, - glue = dioxus_liveview::interpreter_glue(&format!("ws://{addr}/ws")) - )) - }), - ) - .route( - "/ws", - get(move |ws: WebSocketUpgrade| async move { - ws.on_upgrade(move |socket| async move { - _ = view.launch(dioxus_liveview::axum_socket(socket), app).await; - }) - }), - ); + let app = + Router::new() + .route( + "/", + get(move || async move { + index_page_with_glue(&dioxus_liveview::interpreter_glue(&format!( + "ws://{addr}/ws" + ))) + }), + ) + .route( + "/as-path", + get(move || async move { + index_page_with_glue(&dioxus_liveview::interpreter_glue("/ws")) + }), + ) + .route( + "/ws", + get(move |ws: WebSocketUpgrade| async move { + ws.on_upgrade(move |socket| async move { + _ = view.launch(dioxus_liveview::axum_socket(socket), app).await; + }) + }), + ); println!("Listening on http://{addr}"); diff --git a/packages/liveview/src/lib.rs b/packages/liveview/src/lib.rs index 92cce63e6..a7370e91c 100644 --- a/packages/liveview/src/lib.rs +++ b/packages/liveview/src/lib.rs @@ -93,14 +93,49 @@ static MAIN_JS: &str = include_str!("./main.js"); /// This script that gets injected into your app connects this page to the websocket endpoint /// /// Once the endpoint is connected, it will send the initial state of the app, and then start -/// processing user events and returning edits to the liveview instance -pub fn interpreter_glue(url: &str) -> String { +/// processing user events and returning edits to the liveview instance. +/// +/// You can pass a relative path prefixed with "/", or enter a full URL including the protocol +/// (`ws:` or `wss:`) as an argument. +/// +/// If you enter a relative path, the web client automatically prefixes the host address in +/// `window.location` when creating a web socket to LiveView. +/// +/// ``` +/// // Creates websocket connection to same host as current page +/// interpreter_glue("/api/liveview"); +/// +/// // Creates websocket connection to specified url +/// interpreter_glue("ws://localhost:8080/api/liveview"); +/// ``` +pub fn interpreter_glue(url_or_path: &str) -> String { + // If the url starts with a `/`, generate glue which reuses current host + let get_ws_url = if url_or_path.starts_with('/') { + r#" + let loc = window.location; + let new_url = ""; + if (loc.protocol === "https:") {{ + new_url = "wss:"; + }} else {{ + new_url = "ws:"; + }} + new_url += "//" + loc.host + path; + return new_url; + "# + } else { + "return path;" + }; + let js = &*INTERPRETER_JS; let common = &*COMMON_JS; format!( r#"