Merge branch 'DioxusLabs:master' into events-2

This commit is contained in:
ealmloff 2023-10-02 19:48:52 -05:00 committed by GitHub
commit 072ca3529b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 191 additions and 106 deletions

View file

@ -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 }

View file

@ -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)

View file

@ -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,
};
}

View file

@ -7,51 +7,6 @@ thread_local! {
static RUNTIMES: RefCell<Vec<Rc<Runtime>>> = RefCell::new(vec![]);
}
/// Run some code within a runtime
pub fn in_runtime<R>(runtime: Rc<Runtime>, 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<Runtime>,
/// }
///
/// impl PartialEq for ComponentProps {
/// fn eq(&self, _other: &Self) -> bool {
/// true
/// }
/// }
///
/// fn Component(cx: Scope<ComponentProps>) -> Element {
/// cx.use_hook(|| override_runtime(cx.props.runtime.clone()));
///
/// render! { div {} }
/// }
/// ```
pub fn override_runtime(runtime: Rc<Runtime>) {
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<Runtime>) {
RUNTIMES.with(|stack| stack.borrow_mut().push(runtime));
@ -143,10 +98,42 @@ impl Runtime {
}
}
pub(crate) struct RuntimeGuard(Rc<Runtime>);
/// 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<Runtime>,
/// }
///
/// impl PartialEq for ComponentProps {
/// fn eq(&self, _other: &Self) -> bool {
/// true
/// }
/// }
///
/// fn Component(cx: Scope<ComponentProps>) -> Element {
/// cx.use_hook(|| RuntimeGuard::new(cx.props.runtime.clone()));
///
/// render! { div {} }
/// }
/// ```
pub struct RuntimeGuard(Rc<Runtime>);
impl RuntimeGuard {
pub(crate) fn new(runtime: Rc<Runtime>) -> 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<Runtime>) -> Self {
push_runtime(runtime.clone());
Self(runtime)
}

View file

@ -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"]

View file

@ -57,32 +57,32 @@ pub mod computed;
mod use_on_unmount;
pub use use_on_unmount::*;
mod usecontext;
pub use usecontext::*;
mod use_context;
pub use use_context::*;
mod usestate;
pub use usestate::{use_state, UseState};
mod use_state;
pub use use_state::{use_state, UseState};
mod useref;
pub use useref::*;
mod use_ref;
pub use use_ref::*;
mod use_shared_state;
pub use use_shared_state::*;
mod usecoroutine;
pub use usecoroutine::*;
mod use_coroutine;
pub use use_coroutine::*;
mod usefuture;
pub use usefuture::*;
mod use_future;
pub use use_future::*;
mod useeffect;
pub use useeffect::*;
mod use_effect;
pub use use_effect::*;
mod usecallback;
pub use usecallback::*;
mod use_callback;
pub use use_callback::*;
mod usememo;
pub use usememo::*;
mod use_memo;
pub use use_memo::*;
mod userootcontext;
pub use userootcontext::*;
mod use_root_context;
pub use use_root_context::*;

View file

@ -336,6 +336,50 @@ impl<T> PartialEq<UseState<T>> for UseState<T> {
}
}
impl<T: std::cmp::PartialOrd> PartialOrd<T> for UseState<T> {
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<std::cmp::Ordering> {
(*self.current_val).partial_cmp(other)
}
}
impl<T: std::cmp::PartialOrd> PartialOrd<UseState<T>> for UseState<T> {
fn ge(&self, other: &UseState<T>) -> bool {
self.current_val >= other.current_val
}
fn gt(&self, other: &UseState<T>) -> bool {
self.current_val > other.current_val
}
fn le(&self, other: &UseState<T>) -> bool {
self.current_val <= other.current_val
}
fn lt(&self, other: &UseState<T>) -> bool {
self.current_val < other.current_val
}
fn partial_cmp(&self, other: &UseState<T>) -> Option<std::cmp::Ordering> {
self.current_val.partial_cmp(&other.current_val)
}
}
impl<T: Debug> Debug for UseState<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.current_val)

View file

@ -1203,6 +1203,7 @@ builder_constructors! {
value: String DEFAULT,
selected: Bool volatile,
initial_selected: Bool DEFAULT,
};
/// Build a

View file

@ -54,6 +54,9 @@ export function setAttributeInner(node, field, value, ns) {
case "selected":
node.selected = truthy(value);
break;
case "initial_selected":
node.defaultSelected = truthy(value);
break;
case "dangerous_inner_html":
node.innerHTML = value;
break;

View file

@ -83,6 +83,9 @@ mod js {
case "selected":
node.selected = truthy(value);
break;
case "initial_selected":
node.defaultSelected = truthy(value);
break;
case "dangerous_inner_html":
node.innerHTML = value;
break;

View file

@ -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#"
<!DOCTYPE html>
<html>
<head> <title>Dioxus LiveView with axum</title> </head>
<body> <div id="main"></div> </body>
{glue}
</html>
"#,
))
};
let app = Router::new()
.route(
"/",
get(move || async move {
Html(format!(
r#"
<!DOCTYPE html>
<html>
<head> <title>Dioxus LiveView with axum</title> </head>
<body> <div id="main"></div> </body>
{glue}
</html>
"#,
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}");

View file

@ -94,14 +94,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#"
<script>
var WS_ADDR = "{url}";
function __dioxusGetWsUrl(path) {{
{get_ws_url}
}}
var WS_ADDR = __dioxusGetWsUrl("{url_or_path}");
{js}
{common}
{MAIN_JS}

View file

@ -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

View file

@ -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,