Make cargo check --all --examples work!

This commit is contained in:
Jonathan Kelley committed 2024-01-19 14:19:49 -08:00
1 parent 08475af221
commit 83bce6ce97
40 files changed
+295 -399

No files matched your search

Generated
+1 -3
View File
@@ -2690,6 +2690,7 @@ version = "0.4.3"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum 0.6.20", "axum 0.6.20",
"dioxus",
"dioxus-core", "dioxus-core",
"dioxus-hot-reload", "dioxus-hot-reload",
"dioxus-html", "dioxus-html",
@@ -2806,14 +2807,12 @@ dependencies = [
"criterion 0.5.1", "criterion 0.5.1",
"dioxus", "dioxus",
"dioxus-cli-config", "dioxus-cli-config",
"dioxus-desktop",
"dioxus-fullstack", "dioxus-fullstack",
"dioxus-lib", "dioxus-lib",
"dioxus-liveview", "dioxus-liveview",
"dioxus-router", "dioxus-router",
"dioxus-router-macro", "dioxus-router-macro",
"dioxus-ssr", "dioxus-ssr",
"dioxus-web",
"gloo", "gloo",
"gloo-utils", "gloo-utils",
"js-sys", "js-sys",
@@ -2858,7 +2857,6 @@ version = "0.4.3"
dependencies = [ dependencies = [
"dioxus", "dioxus",
"dioxus-core", "dioxus-core",
"dioxus-desktop",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"generational-box", "generational-box",
+2 -2
View File
@@ -5,13 +5,13 @@ use dioxus::prelude::*;
use dioxus_desktop::Config; use dioxus_desktop::Config;
fn main() { fn main() {
LaunchBuilder::new() LaunchBuilder::desktop()
.with_cfg( .with_cfg(
Config::new().with_custom_head("<style>body { background-color: red; }</style>".into()), Config::new().with_custom_head("<style>body { background-color: red; }</style>".into()),
) )
.launch(app); .launch(app);
LaunchBuilder::new() LaunchBuilder::desktop()
.with_cfg( .with_cfg(
Config::new().with_custom_index( Config::new().with_custom_index(
r#" r#"
+1 -1
View File
@@ -12,7 +12,7 @@ use dioxus::prelude::*;
use dioxus_desktop::{Config, WindowBuilder}; use dioxus_desktop::{Config, WindowBuilder};
fn main() { fn main() {
LaunchBuilder::new() LaunchBuilder::desktop()
.with_cfg(Config::new().with_window(WindowBuilder::new().with_resizable(true))) .with_cfg(Config::new().with_window(WindowBuilder::new().with_resizable(true)))
.launch(app) .launch(app)
} }
+1 -1
View File
@@ -1,7 +1,7 @@
use dioxus::prelude::*; use dioxus::prelude::*;
fn main() { fn main() {
launch_desktop(app); launch(app);
} }
fn app() -> Element { fn app() -> Element {
+1 -1
View File
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
use dioxus_desktop::{tao::dpi::PhysicalPosition, LogicalSize, WindowBuilder}; use dioxus_desktop::{tao::dpi::PhysicalPosition, LogicalSize, WindowBuilder};
fn main() { fn main() {
LaunchBuilder::new().with_cfg(make_config()); LaunchBuilder::desktop().with_cfg(make_config());
} }
fn app() -> Element { fn app() -> Element {
+1 -1
View File
@@ -32,7 +32,7 @@ fn main() {
.with_inner_size(LogicalSize::new(320.0, 530.0)), .with_inner_size(LogicalSize::new(320.0, 530.0)),
); );
LaunchBuilder::new().with_cfg(cfg).launch(app); LaunchBuilder::desktop().with_cfg(cfg).launch(app);
} }
const STYLE: &str = include_str!("./assets/calculator.css"); const STYLE: &str = include_str!("./assets/calculator.css");
+2 -2
View File
@@ -4,8 +4,8 @@ use std::rc::Rc;
use dioxus::{html::geometry::euclid::Rect, prelude::*}; use dioxus::{html::geometry::euclid::Rect, prelude::*};
fn main() { fn main() {
LaunchBuilder::new().with_cfg( LaunchBuilder::desktop().with_cfg(
dioxus_desktop::Config::default().with_custom_head( dioxus::desktop::Config::default().with_custom_head(
r#" r#"
<style type="text/css"> <style type="text/css">
html, body { html, body {
+1 -1
View File
@@ -5,7 +5,7 @@ use dioxus_desktop::use_wry_event_handler;
use dioxus_desktop::{Config, WindowCloseBehaviour}; use dioxus_desktop::{Config, WindowCloseBehaviour};
fn main() { fn main() {
LaunchBuilder::new() LaunchBuilder::desktop()
.with_cfg(Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow)) .with_cfg(Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow))
.launch(app) .launch(app)
} }
+1 -1
View File
@@ -79,7 +79,7 @@ default-features = false
features = ["tokio_runtime", "hot-reload"] features = ["tokio_runtime", "hot-reload"]
[dev-dependencies] [dev-dependencies]
dioxus = { workspace = true, features = ["launch", "desktop"]} dioxus = { workspace = true }
exitcode = "1.1.2" exitcode = "1.1.2"
[build-dependencies] [build-dependencies]
+2 -4
View File
@@ -12,9 +12,7 @@ fn app() -> Element {
rsx! { rsx! {
button { button {
onclick: move |_| { onclick: move |_| state.set(0),
state.set(0);
},
"reset" "reset"
} }
for _ in 0..10000 { for _ in 0..10000 {
@@ -26,5 +24,5 @@ fn app() -> Element {
} }
fn main() { fn main() {
launch(app); dioxus_desktop::launch::launch(app, Default::default(), Default::default());
} }
@@ -27,10 +27,11 @@ enum Event {
const MAX_EVENTS: usize = 8; const MAX_EVENTS: usize = 8;
fn app() -> Element { fn app() -> Element {
let events = use_signal(Vec::new); let mut events = use_signal(Vec::new);
let events_lock = events.read(); let events_lock = events.read();
let first_index = events_lock.len().saturating_sub(MAX_EVENTS); let first_index = events_lock.len().saturating_sub(MAX_EVENTS);
let events_rendered = events_lock[first_index..].iter().map(|event| { let events_rendered = events_lock[first_index..].iter().map(|event| {
// TUI panics if text overflows (https://github.com/DioxusLabs/dioxus/issues/371) // TUI panics if text overflows (https://github.com/DioxusLabs/dioxus/issues/371)
// temporary hack: just trim the strings (and make sure viewport is big enough) // temporary hack: just trim the strings (and make sure viewport is big enough)
@@ -40,9 +41,7 @@ fn app() -> Element {
rsx!( p { "{trimmed}" } ) rsx!( p { "{trimmed}" } )
}); });
let log_event = move |event: Event| { let mut log_event = move |event: Event| events.write().push(event);
events.write().push(event);
};
rsx! { rsx! {
div { width: "100%", height: "100%", flex_direction: "column", div { width: "100%", height: "100%", flex_direction: "column",
+2 -2
View File
@@ -5,7 +5,7 @@ fn main() {
} }
fn app() -> Element { fn app() -> Element {
let radius = use_signal(|| 0); let mut radius = use_signal(|| 0);
rsx! { rsx! {
div { div {
@@ -14,7 +14,7 @@ fn app() -> Element {
justify_content: "center", justify_content: "center",
align_items: "center", align_items: "center",
background_color: "hsl(248, 53%, 58%)", background_color: "hsl(248, 53%, 58%)",
onwheel: move |w| radius.modify(|r| (r + w.delta().strip_units().y as i8).abs()), onwheel: move |w| radius.with_mut(|r| *r = (*r + w.delta().strip_units().y as i8).abs()),
border_style: "solid none solid double", border_style: "solid none solid double",
border_width: "thick", border_width: "thick",
+12 -24
View File
@@ -5,19 +5,13 @@ fn main() {
dioxus_tui::launch(app); dioxus_tui::launch(app);
} }
#[derive(PartialEq, Props)] #[component]
struct ButtonProps { fn Button(color_offset: u32, layer: u16) -> Element {
color_offset: u32, let mut toggle = use_signal(|| false);
layer: u16, let mut hovered = use_signal(|| false);
}
#[allow(non_snake_case)] let hue = color_offset % 255;
fn Button(cx: Scope<ButtonProps>) -> Element { let saturation = if toggle() { 50 } else { 25 } + if hovered() { 50 } else { 25 };
let toggle = use_signal(|| false);
let hovered = use_signal(|| false);
let hue = cx.props.color_offset % 255;
let saturation = if *toggle.get() { 50 } else { 25 } + if *hovered.get() { 50 } else { 25 };
let brightness = saturation / 2; let brightness = saturation / 2;
let color = format!("hsl({hue}, {saturation}, {brightness})"); let color = format!("hsl({hue}, {saturation}, {brightness})");
@@ -26,26 +20,20 @@ fn Button(cx: Scope<ButtonProps>) -> Element {
width: "100%", width: "100%",
height: "100%", height: "100%",
background_color: "{color}", background_color: "{color}",
tabindex: "{cx.props.layer}", tabindex: "{layer}",
onkeydown: move |e| { onkeydown: move |e| {
if let Code::Space = e.inner().code() { if let Code::Space = e.inner().code() {
toggle.modify(|f| !f); toggle.toggle();
} }
}, },
onclick: move |_| { onclick: move |_| toggle.toggle(),
toggle.modify(|f| !f); onmouseenter: move |_| hovered.set(true),
}, onmouseleave: move |_| hovered.set(false),
onmouseenter: move |_| {
hovered.set(true);
},
onmouseleave: move |_|{
hovered.set(false);
},
justify_content: "center", justify_content: "center",
align_items: "center", align_items: "center",
display: "flex", display: "flex",
flex_direction: "column", flex_direction: "column",
p{ "tabindex: {cx.props.layer}" } p { "tabindex: {layer}" }
} }
} }
} }
+15 -13
View File
@@ -9,25 +9,27 @@ fn main() {
} }
fn app() -> Element { fn app() -> Element {
let hue = use_signal(|| 0.0); let mut hue = use_signal(|| 0.0);
let brightness = use_signal(|| 0.0); let mut brightness = use_signal(|| 0.0);
let tui_query: Query = cx.consume_context().unwrap(); let tui_query: Query = consume_context();
let mapping: DioxusElementToNodeId = cx.consume_context().unwrap(); let mapping: DioxusElementToNodeId = consume_context();
// disable templates so that every node has an id and can be queried // disable templates so that every node has an id and can be queried
rsx! { rsx! {
div { div {
width: "100%", width: "100%",
background_color: "hsl({hue}, 70%, {brightness}%)", background_color: "hsl({hue}, 70%, {brightness}%)",
onmousemove: move |evt| { onmousemove: move |evt| {
if let RenderReturn::Ready(node) = cx.root_node() { todo!()
if let Some(id) = node.root_ids.borrow().first().cloned() { // if let RenderReturn::Ready(node) = root_node() {
let node = tui_query.get(mapping.get_node_id(id).unwrap()); // if let Some(id) = node.root_ids.borrow().first().cloned() {
let Size { width, height } = node.size().unwrap(); // let node = tui_query.get(mapping.get_node_id(id).unwrap());
let pos = evt.inner().element_coordinates(); // let Size { width, height } = node.size().unwrap();
hue.set((pos.x as f32 / width as f32) * 255.0); // let pos = evt.inner().element_coordinates();
brightness.set((pos.y as f32 / height as f32) * 100.0); // hue.set((pos.x as f32 / width as f32) * 255.0);
} // brightness.set((pos.y as f32 / height as f32) * 100.0);
} // }
// }
}, },
"hsl({hue}, 70%, {brightness}%)" "hsl({hue}, 70%, {brightness}%)"
} }
+21 -29
View File
@@ -23,32 +23,24 @@ fn app() -> Element {
127 * b 127 * b
} }
let q1_color = use_signal(|| [200; 3]); let mut q1_color = use_signal(|| [200; 3]);
let q2_color = use_signal(|| [200; 3]); let mut q2_color = use_signal(|| [200; 3]);
let q3_color = use_signal(|| [200; 3]); let mut q3_color = use_signal(|| [200; 3]);
let q4_color = use_signal(|| [200; 3]); let mut q4_color = use_signal(|| [200; 3]);
let q1_color_str = to_str(q1_color); let mut page_coordinates = use_signal(|| "".to_string());
let q2_color_str = to_str(q2_color); let mut element_coordinates = use_signal(|| "".to_string());
let q3_color_str = to_str(q3_color); let mut buttons = use_signal(|| "".to_string());
let q4_color_str = to_str(q4_color); let mut modifiers = use_signal(|| "".to_string());
let page_coordinates = use_signal(|| "".to_string()); let mut update_data = move |event: Event<MouseData>| {
let element_coordinates = use_signal(|| "".to_string()); page_coordinates.set(format!("{:?}", event.page_coordinates()));
let buttons = use_signal(|| "".to_string()); element_coordinates.set(format!("{:?}", event.element_coordinates()));
let modifiers = use_signal(|| "".to_string());
let update_data = move |event: Event<MouseData>| {
let mouse_data = event.inner();
page_coordinates.set(format!("{:?}", mouse_data.page_coordinates()));
element_coordinates.set(format!("{:?}", mouse_data.element_coordinates()));
// Note: client coordinates are also available, but they would be the same as the page coordinates in this example, because there is no scrolling. // Note: client coordinates are also available, but they would be the same as the page coordinates in this example, because there is no scrolling.
// There are also screen coordinates, but they are currently the same as client coordinates due to technical limitations // There are also screen coordinates, but they are currently the same as client coordinates due to technical limitations
buttons.set(format!("{:?}", event.held_buttons()));
buttons.set(format!("{:?}", mouse_data.held_buttons())); modifiers.set(format!("{:?}", event.modifiers()));
modifiers.set(format!("{:?}", mouse_data.modifiers()));
}; };
rsx! { rsx! {
@@ -66,11 +58,11 @@ fn app() -> Element {
height: "100%", height: "100%",
justify_content: "center", justify_content: "center",
align_items: "center", align_items: "center",
background_color: "{q1_color_str}", background_color: to_str(&q1_color()),
onmouseenter: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]), onmouseenter: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
onmousedown: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]), onmousedown: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
onmouseup: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]), onmouseup: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
onwheel: move |w| q1_color.set([q1_color[0] + (10.0 * w.delta().strip_units().y) as i32, 0, 0]), onwheel: move |w| q1_color.set([q1_color()[0] + (10.0 * w.delta().strip_units().y) as i32, 0, 0]),
onmouseleave: move |_| q1_color.set([200; 3]), onmouseleave: move |_| q1_color.set([200; 3]),
onmousemove: update_data, onmousemove: update_data,
"click me" "click me"
@@ -80,11 +72,11 @@ fn app() -> Element {
height: "100%", height: "100%",
justify_content: "center", justify_content: "center",
align_items: "center", align_items: "center",
background_color: "{q2_color_str}", background_color: to_str(&q2_color()),
onmouseenter: move |m| q2_color.set([get_brightness(m.inner()); 3]), onmouseenter: move |m| q2_color.set([get_brightness(m.inner()); 3]),
onmousedown: move |m| q2_color.set([get_brightness(m.inner()); 3]), onmousedown: move |m| q2_color.set([get_brightness(m.inner()); 3]),
onmouseup: move |m| q2_color.set([get_brightness(m.inner()); 3]), onmouseup: move |m| q2_color.set([get_brightness(m.inner()); 3]),
onwheel: move |w| q2_color.set([q2_color[0] + (10.0 * w.delta().strip_units().y) as i32; 3]), onwheel: move |w| q2_color.set([q2_color()[0] + (10.0 * w.delta().strip_units().y) as i32; 3]),
onmouseleave: move |_| q2_color.set([200; 3]), onmouseleave: move |_| q2_color.set([200; 3]),
onmousemove: update_data, onmousemove: update_data,
"click me" "click me"
@@ -100,11 +92,11 @@ fn app() -> Element {
height: "100%", height: "100%",
justify_content: "center", justify_content: "center",
align_items: "center", align_items: "center",
background_color: "{q3_color_str}", background_color: to_str(&q3_color()),
onmouseenter: move |m| q3_color.set([0, get_brightness(m.inner()), 0]), onmouseenter: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
onmousedown: move |m| q3_color.set([0, get_brightness(m.inner()), 0]), onmousedown: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
onmouseup: move |m| q3_color.set([0, get_brightness(m.inner()), 0]), onmouseup: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
onwheel: move |w| q3_color.set([0, q3_color[1] + (10.0 * w.delta().strip_units().y) as i32, 0]), onwheel: move |w| q3_color.set([0, q3_color()[1] + (10.0 * w.delta().strip_units().y) as i32, 0]),
onmouseleave: move |_| q3_color.set([200; 3]), onmouseleave: move |_| q3_color.set([200; 3]),
onmousemove: update_data, onmousemove: update_data,
"click me" "click me"
@@ -114,11 +106,11 @@ fn app() -> Element {
height: "100%", height: "100%",
justify_content: "center", justify_content: "center",
align_items: "center", align_items: "center",
background_color: "{q4_color_str}", background_color: to_str(&q4_color()),
onmouseenter: move |m| q4_color.set([0, 0, get_brightness(m.inner())]), onmouseenter: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
onmousedown: move |m| q4_color.set([0, 0, get_brightness(m.inner())]), onmousedown: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
onmouseup: move |m| q4_color.set([0, 0, get_brightness(m.inner())]), onmouseup: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
onwheel: move |w| q4_color.set([0, 0, q4_color[2] + (10.0 * w.delta().strip_units().y) as i32]), onwheel: move |w| q4_color.set([0, 0, q4_color()[2] + (10.0 * w.delta().strip_units().y) as i32]),
onmouseleave: move |_| q4_color.set([200; 3]), onmouseleave: move |_| q4_color.set([200; 3]),
onmousemove: update_data, onmousemove: update_data,
"click me" "click me"
@@ -5,28 +5,22 @@ use dioxus_tui::{Config, TuiContext};
fn main() { fn main() {
for size in 1..=20usize { for size in 1..=20usize {
for _ in 0..10 { for _ in 0..10 {
dioxus_tui::launch_cfg_with_props(app, size, Config::default().with_headless()) todo!()
// dioxus_tui::launch_cfg(app, vec![size], Config::default().with_headless())
} }
} }
} }
#[derive(Props, PartialEq)] #[component]
struct BoxProps { fn Box(x: usize, y: usize, hue: f32, alpha: f32) -> Element {
x: usize,
y: usize,
hue: f32,
alpha: f32,
}
#[allow(non_snake_case)]
fn Box(cx: Scope<BoxProps>) -> Element {
let count = use_signal(|| 0); let count = use_signal(|| 0);
let x = cx.props.x * 2; let x = x * 2;
let y = cx.props.y * 2; let y = y * 2;
let hue = cx.props.hue; let hue = hue;
let display_hue = cx.props.hue as u32 / 10; let display_hue = hue as u32 / 10;
let count = count.get();
let alpha = cx.props.alpha + (count % 100) as f32; let alpha = alpha + (count() % 100) as f32;
rsx! { rsx! {
div { div {
@@ -41,22 +35,19 @@ fn Box(cx: Scope<BoxProps>) -> Element {
} }
} }
#[derive(Props, PartialEq)] #[component]
struct GridProps { fn Grid(size: usize) -> Element {
size: usize, let size = size;
} let mut count = use_signal(|| 0);
#[allow(non_snake_case)] let mut counts = use_signal(|| vec![0; size * size]);
fn Grid(cx: Scope<GridProps>) -> Element {
let size = cx.props.size;
let count = use_signal(|| 0);
let counts = use_signal(|| vec![0; size * size]);
let ctx: TuiContext = cx.consume_context().unwrap(); let ctx: TuiContext = consume_context();
if *count.get() + 1 >= (size * size) {
if count() + 1 >= (size * size) {
ctx.quit(); ctx.quit();
} else { } else {
counts.with_mut(|c| { counts.with_mut(|c| {
let i = *count.current(); let i = count();
c[i] += 1; c[i] += 1;
c[i] %= 360; c[i] %= 360;
}); });
@@ -97,14 +88,12 @@ fn Grid(cx: Scope<GridProps>) -> Element {
} }
} }
fn app(cx: Scope<usize>) -> Element { fn app(props: usize) -> Element {
rsx! { rsx! {
div{ div{
width: "100%", width: "100%",
height: "100%", height: "100%",
Grid{ Grid{ size: props }
size: *cx.props,
}
} }
} }
} }
+9 -18
View File
@@ -1,29 +1,22 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_tui::Config;
fn main() { fn main() {
dioxus_tui::launch_cfg(app, Config::default()); dioxus_tui::launch_cfg(app, Default::default());
} }
#[derive(Props, PartialEq)] #[component]
struct QuadrentProps { fn Quadrant(color: String, text: String) -> Element {
color: String,
text: String,
}
fn Quadrant(cx: Scope<QuadrentProps>) -> Element {
rsx! { rsx! {
div { div {
border_width: "1px", border_width: "1px",
width: "50%", width: "50%",
height: "100%", height: "100%",
background_color: "{cx.props.color}",
justify_content: "center", justify_content: "center",
align_items: "center", align_items: "center",
background_color: "{color}",
"{cx.props.text}" "{text}"
} }
} }
} }
@@ -34,30 +27,28 @@ fn app() -> Element {
width: "100%", width: "100%",
height: "100%", height: "100%",
flex_direction: "column", flex_direction: "column",
div { div {
width: "100%", width: "100%",
height: "50%", height: "50%",
flex_direction: "row", flex_direction: "row",
Quadrant{ Quadrant {
color: "red".to_string(), color: "red".to_string(),
text: "[A]".to_string() text: "[A]".to_string()
}, },
Quadrant{ Quadrant {
color: "black".to_string(), color: "black".to_string(),
text: "[B]".to_string() text: "[B]".to_string()
} }
} }
div { div {
width: "100%", width: "100%",
height: "50%", height: "50%",
flex_direction: "row", flex_direction: "row",
Quadrant{ Quadrant {
color: "green".to_string(), color: "green".to_string(),
text: "[C]".to_string() text: "[C]".to_string()
}, },
Quadrant{ Quadrant {
color: "blue".to_string(), color: "blue".to_string(),
text: "[D]".to_string() text: "[D]".to_string()
} }
+6 -10
View File
@@ -5,17 +5,13 @@ fn main() {
} }
fn app() -> Element { fn app() -> Element {
let count = use_signal(|| 0); let mut count = use_signal(|| 0);
use_future(move |_| { use_future(move || async move {
let count = count.to_owned(); loop {
let update = cx.schedule_update(); count += 1;
async move { tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
loop { schedule_update();
count.with_mut(|f| *f += 1);
tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
update();
}
} }
}); });
+2 -2
View File
@@ -5,14 +5,14 @@ fn main() {
} }
fn app() -> Element { fn app() -> Element {
let alpha = use_signal(|| 100); let mut alpha = use_signal(|| 100);
rsx! { rsx! {
div { div {
width: "100%", width: "100%",
height: "100%", height: "100%",
flex_direction: "column", flex_direction: "column",
onwheel: move |evt| alpha.set((**alpha + evt.inner().delta().strip_units().y as i64).clamp(0, 100)), onwheel: move |evt| alpha.set((alpha() + evt.inner().delta().strip_units().y as i64).clamp(0, 100)),
p { p {
background_color: "black", background_color: "black",
+13 -16
View File
@@ -6,19 +6,18 @@ fn main() {
} }
fn app() -> Element { fn app() -> Element {
let bg_green = use_signal(|| false); let mut bg_green = use_signal(|| false);
let color = if bg_green() { "green" } else { "red" };
let color = if *bg_green.get() { "green" } else { "red" };
rsx! { rsx! {
div{ div {
width: "100%", width: "100%",
background_color: "{color}", background_color: "{color}",
flex_direction: "column", flex_direction: "column",
align_items: "center", align_items: "center",
justify_content: "center", justify_content: "center",
input { input {
oninput: |data| if &data.value()== "good"{ oninput: move |data| if data.value() == "good" {
bg_green.set(true); bg_green.set(true);
} else{ } else{
bg_green.set(false); bg_green.set(false);
@@ -30,9 +29,9 @@ fn app() -> Element {
checked: "true", checked: "true",
} }
input { input {
oninput: |data| if &data.value()== "hello world"{ oninput: move |data| if &data.value() == "hello world"{
bg_green.set(true); bg_green.set(true);
} else{ } else {
bg_green.set(false); bg_green.set(false);
}, },
width: "50%", width: "50%",
@@ -40,7 +39,7 @@ fn app() -> Element {
maxlength: "11", maxlength: "11",
} }
input { input {
oninput: |data| { oninput: move |data| {
if (data.value().parse::<f32>().unwrap() - 40.0).abs() < 5.0 { if (data.value().parse::<f32>().unwrap() - 40.0).abs() < 5.0 {
bg_green.set(true); bg_green.set(true);
} else{ } else{
@@ -54,10 +53,10 @@ fn app() -> Element {
max: "80", max: "80",
} }
input { input {
oninput: |data| { oninput: move |data| {
if data.value()== "10"{ if data.value() == "10"{
bg_green.set(true); bg_green.set(true);
} else{ } else {
bg_green.set(false); bg_green.set(false);
} }
}, },
@@ -67,8 +66,8 @@ fn app() -> Element {
maxlength: "4", maxlength: "4",
} }
input { input {
oninput: |data| { oninput: move |data| {
if data.value()== "hello world"{ if data.value() == "hello world"{
bg_green.set(true); bg_green.set(true);
} else{ } else{
bg_green.set(false); bg_green.set(false);
@@ -80,9 +79,7 @@ fn app() -> Element {
maxlength: "11", maxlength: "11",
} }
input { input {
oninput: |_| { oninput: move |_| { bg_green.set(true) },
bg_green.set(true)
},
r#type: "button", r#type: "button",
value: "green", value: "green",
width: "50%", width: "50%",
+29 -20
View File
@@ -68,7 +68,7 @@ impl LaunchBuilder {
/// Launch your fullstack application. /// Launch your fullstack application.
#[cfg(feature = "mobile")] #[cfg(feature = "mobile")]
pub fn mobile() -> LaunchBuilder<dioxus_mobile::Config> { pub fn mobile() -> LaunchBuilder<dioxus_mobile::Config, UnsendContext> {
LaunchBuilder { LaunchBuilder {
launch_fn: dioxus_mobile::launch::launch, launch_fn: dioxus_mobile::launch::launch,
contexts: Vec::new(), contexts: Vec::new(),
@@ -89,30 +89,40 @@ impl LaunchBuilder {
} }
// Fullstack platform builder // Fullstack platform builder
impl<Cfg: Default> LaunchBuilder<Cfg, ValidContext> { impl<Cfg> LaunchBuilder<Cfg, UnsendContext> {
/// Inject state into the root component's context that is created on the thread that the app is launched on. /// Inject state into the root component's context that is created on the thread that the app is launched on.
pub fn with_context_provider( pub fn with_context_provider(mut self, state: impl Fn() -> Box<dyn Any> + 'static) -> Self {
mut self, self.contexts.push(Box::new(state) as Box<UnsendContext>);
#[cfg(feature = "fullstack")] state: impl Fn() -> Box<dyn Any> + Send + Sync + 'static,
#[cfg(not(feature = "fullstack"))] state: impl Fn() -> Box<dyn Any> + 'static,
) -> Self {
self.contexts.push(Box::new(state) as Box<ValidContext>);
self self
} }
#[cfg(feature = "fullstack")]
/// Inject state into the root component's context. /// Inject state into the root component's context.
pub fn with_context( pub fn with_context(mut self, state: impl Any + Clone + 'static) -> Self {
mut self,
#[cfg(feature = "fullstack")] state: impl Any + Clone + Send + Sync + 'static,
#[cfg(not(feature = "fullstack"))] state: impl Any + Clone + 'static,
) -> Self {
self.contexts self.contexts
.push(Box::new(move || Box::new(state.clone()))); .push(Box::new(move || Box::new(state.clone())));
self self
} }
}
impl<Cfg> LaunchBuilder<Cfg, SendContext> {
/// Inject state into the root component's context that is created on the thread that the app is launched on.
pub fn with_context_provider(
mut self,
state: impl Fn() -> Box<dyn Any> + Send + Sync + 'static,
) -> Self {
self.contexts.push(Box::new(state) as Box<SendContext>);
self
}
/// Inject state into the root component's context.
pub fn with_context(mut self, state: impl Any + Clone + Send + Sync + 'static) -> Self {
self.contexts
.push(Box::new(move || Box::new(state.clone())));
self
}
}
impl<Cfg: Default, ContextFn: ?Sized> LaunchBuilder<Cfg, ContextFn> {
/// Provide a platform-specific config to the builder. /// Provide a platform-specific config to the builder.
pub fn with_cfg(mut self, config: impl Into<Option<Cfg>>) -> Self { pub fn with_cfg(mut self, config: impl Into<Option<Cfg>>) -> Self {
if let Some(config) = config.into() { if let Some(config) = config.into() {
@@ -121,10 +131,9 @@ impl<Cfg: Default> LaunchBuilder<Cfg, ValidContext> {
self self
} }
#[allow(clippy::unit_arg)] /// Launch your application.
/// Launch the app.
pub fn launch(self, app: fn() -> Element) { pub fn launch(self, app: fn() -> Element) {
(self.launch_fn)(app, self.contexts, self.platform_config.unwrap_or_default()); (self.launch_fn)(app, self.contexts, self.platform_config.unwrap_or_default())
} }
} }
@@ -151,13 +160,13 @@ pub fn launch(app: fn() -> Element) {
LaunchBuilder::new().launch(app) LaunchBuilder::new().launch(app)
} }
#[cfg(all(feature = "web", not(feature = "fullstack")))] #[cfg(all(feature = "web"))]
/// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options. /// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options.
pub fn launch_web(app: fn() -> Element) { pub fn launch_web(app: fn() -> Element) {
LaunchBuilder::web().launch(app) LaunchBuilder::web().launch(app)
} }
#[cfg(all(feature = "desktop", not(feature = "fullstack")))] #[cfg(all(feature = "desktop"))]
/// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options. /// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options.
pub fn launch_desktop(app: fn() -> Element) { pub fn launch_desktop(app: fn() -> Element) {
LaunchBuilder::desktop().launch(app) LaunchBuilder::desktop().launch(app)
+2 -1
View File
@@ -57,8 +57,9 @@ salvo = { version = "0.63.0", features = ["affix", "websocket"] }
rocket = "0.5.0" rocket = "0.5.0"
rocket_ws = "0.1.0" rocket_ws = "0.1.0"
tower = "0.4.13" tower = "0.4.13"
dioxus = { workspace = true }
# [build-dependencies] [build-dependencies]
# dioxus-interpreter-js = { workspace = true, features = ["binary-protocol"] } # dioxus-interpreter-js = { workspace = true, features = ["binary-protocol"] }
# minify-js = "0.5.6" # minify-js = "0.5.6"
+3 -3
View File
@@ -12,10 +12,10 @@ fn main() {
async function read_files() { async function read_files() {
const files = target.files; const files = target.files;
const file_contents = {}; const file_contents = {};
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
const file = files[i]; const file = files[i];
file_contents[file.name] = Array.from( file_contents[file.name] = Array.from(
new Uint8Array(await file.arrayBuffer()) new Uint8Array(await file.arrayBuffer())
); );
@@ -24,7 +24,7 @@ fn main() {
files: file_contents, files: file_contents,
}; };
contents.files = file_engine; contents.files = file_engine;
if (realId === null) { if (realId === null) {
return; return;
} }
+5 -8
View File
@@ -2,14 +2,11 @@ use axum::{extract::ws::WebSocketUpgrade, response::Html, routing::get, Router};
use dioxus::prelude::*; use dioxus::prelude::*;
fn app() -> Element { fn app() -> Element {
let state = use_signal(|| 0); let mut state = use_signal(|| 0);
use_future(|| { use_future(move || async move {
to_owned![state]; loop {
async move { state += 1;
loop { tokio::time::sleep(std::time::Duration::from_millis(1)).await;
state += 1;
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
}
} }
}); });
+1 -1
View File
@@ -227,5 +227,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// wait 1 second // wait 1 second
tokio::time::sleep(std::time::Duration::from_secs(1)).await; tokio::time::sleep(std::time::Duration::from_secs(1)).await;
} }
} })
} }
+1 -1
View File
@@ -171,5 +171,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// wait 1 second // wait 1 second
tokio::time::sleep(std::time::Duration::from_secs(1)).await; tokio::time::sleep(std::time::Duration::from_secs(1)).await;
} }
} })
} }
+1 -1
View File
@@ -218,5 +218,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// wait 1 second // wait 1 second
tokio::time::sleep(std::time::Duration::from_secs(1)).await; tokio::time::sleep(std::time::Duration::from_secs(1)).await;
} }
} })
} }
+13 -17
View File
@@ -167,31 +167,27 @@ impl State for Border {
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
fn app() -> Element { fn app() -> Element {
let count = use_signal(|| 0); let mut count = use_signal(|| 0);
use_future((count,), |(count,)| async move { use_future(|| async move {
loop { loop {
tokio::time::sleep(std::time::Duration::from_secs(1)).await; tokio::time::sleep(std::time::Duration::from_secs(1)).await;
count.set(*count + 1); count += 1;
} }
}); });
rsx! { rsx! {
div{ div { color: "red",
color: "red",
"{count}", "{count}",
Comp {} Comp {}
} }
}) }
} }
fn Comp() -> Element { fn Comp() -> Element {
rsx! { rsx! {
div{ div { border: "", "hello world" }
border: "", }
"hello world"
}
})
} }
// create the vdom, the real_dom, and the binding layer between them // create the vdom, the real_dom, and the binding layer between them
@@ -203,9 +199,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
]); ]);
let mut dioxus_intigration_state = DioxusState::create(&mut rdom); let mut dioxus_intigration_state = DioxusState::create(&mut rdom);
let mutations = vdom.rebuild();
// update the structure of the real_dom tree // update the structure of the real_dom tree
dioxus_intigration_state.apply_mutations(&mut rdom, mutations); let mut writer = dioxus_intigration_state.create_mutation_writer(&mut rdom);
vdom.rebuild(&mut writer);
let mut ctx = SendAnyMap::new(); let mut ctx = SendAnyMap::new();
// set the font size to 3.3 // set the font size to 3.3
ctx.insert(FontSize(3.3)); ctx.insert(FontSize(3.3));
@@ -222,10 +219,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
vdom.wait_for_work().await; vdom.wait_for_work().await;
// get the mutations from the vdom // get the mutations from the vdom
let mutations = vdom.render_immediate();
// update the structure of the real_dom tree // update the structure of the real_dom tree
dioxus_intigration_state.apply_mutations(&mut rdom, mutations); let mut writer = dioxus_intigration_state.create_mutation_writer(&mut rdom);
vdom.rebuild(&mut writer);
// update the state of the real_dom tree // update the state of the real_dom tree
let mut ctx = SendAnyMap::new(); let mut ctx = SendAnyMap::new();
@@ -245,5 +241,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("{indent}{id:?} {color:?} {size:?} {border:?} {node_type:?}"); println!("{indent}{id:?} {color:?} {size:?} {border:?} {node_type:?}");
}); });
} }
} })
} }
+5 -5
View File
@@ -41,8 +41,8 @@ fullstack = ["dioxus-fullstack"]
[dev-dependencies] [dev-dependencies]
axum = { version = "0.6.1", features = ["ws"] } axum = { version = "0.6.1", features = ["ws"] }
dioxus = { path = "../dioxus" } dioxus = { workspace = true }
dioxus-liveview = { workspace = true, features = ["axum"] } # dioxus-liveview = { workspace = true, features = ["axum"] }
dioxus-ssr = { path = "../ssr" } dioxus-ssr = { path = "../ssr" }
criterion = { version = "0.5", features = ["async_tokio", "html_reports"] } criterion = { version = "0.5", features = ["async_tokio", "html_reports"] }
@@ -55,12 +55,12 @@ name = "incremental"
required-features = ["ssr"] required-features = ["ssr"]
harness = false harness = false
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies] # [target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
dioxus-desktop = { path = "../desktop" } # dioxus-desktop = { path = "../desktop" }
[target.'cfg(target_family = "wasm")'.dev-dependencies] [target.'cfg(target_family = "wasm")'.dev-dependencies]
console_error_panic_hook = "0.1.7" console_error_panic_hook = "0.1.7"
dioxus-router = { path = ".", features = ["web"] } dioxus-router = { path = ".", features = ["web"] }
dioxus-web = { workspace = true } # dioxus-web = { workspace = true }
gloo = "0.8.0" gloo = "0.8.0"
wasm-bindgen-test = "0.3.33" wasm-bindgen-test = "0.3.33"
+10 -5
View File
@@ -44,7 +44,11 @@ async fn main() {
#[cfg(not(feature = "liveview"))] #[cfg(not(feature = "liveview"))]
fn main() { fn main() {
launch(Route::Home {}) launch(|| {
rsx! {
Router::<Route> {}
}
})
} }
#[component] #[component]
@@ -66,8 +70,8 @@ fn Route1(user_id: usize, dynamic: usize, query: String, extra: String) -> Eleme
} }
Link { Link {
to: Route::Route1 { to: Route::Route1 {
user_id: *user_id, user_id,
dynamic: *dynamic, dynamic,
query: String::new(), query: String::new(),
extra: extra.clone() + ".", extra: extra.clone() + ".",
}, },
@@ -87,7 +91,7 @@ fn Route1(user_id: usize, dynamic: usize, query: String, extra: String) -> Eleme
fn Route2(user_id: usize) -> Element { fn Route2(user_id: usize) -> Element {
rsx! { rsx! {
pre { "Route2{{\n\tuser_id:{user_id}\n}}" } pre { "Route2{{\n\tuser_id:{user_id}\n}}" }
{(0..*user_id).map(|i| rsx!{ p { "{i}" } })}, {(0..user_id).map(|i| rsx!{ p { "{i}" } })},
p { "Footer" } p { "Footer" }
Link { Link {
to: Route::Route3 { to: Route::Route3 {
@@ -100,8 +104,9 @@ fn Route2(user_id: usize) -> Element {
#[component] #[component]
fn Route3(dynamic: String) -> Element { fn Route3(dynamic: String) -> Element {
let mut current_route_str = use_signal(String::new);
let current_route = use_route()?; let current_route = use_route()?;
let current_route_str = use_signal(String::new);
let parsed = Route::from_str(&current_route_str.read()); let parsed = Route::from_str(&current_route_str.read());
let site_map = Route::SITE_MAP let site_map = Route::SITE_MAP
+1 -1
View File
@@ -25,7 +25,7 @@ futures-util = { workspace = true }
[dev-dependencies] [dev-dependencies]
dioxus = { workspace = true } dioxus = { workspace = true }
dioxus-desktop = { workspace = true } # dioxus-desktop = { workspace = true }
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
tracing-subscriber = "0.3.17" tracing-subscriber = "0.3.17"
simple_logger = "4.2.0" simple_logger = "4.2.0"
+7 -11
View File
@@ -4,22 +4,18 @@ use dioxus::prelude::*;
use dioxus_signals::Signal; use dioxus_signals::Signal;
fn main() { fn main() {
dioxus_desktop::launch(app); // dioxus_desktop::launch(app);
} }
// Because signal is never read in this component, this component will not rerun when the signal changes
fn app() -> Element { fn app() -> Element {
// Because signal is never read in this component, this component will not rerun when the signal changes
use_context_provider(|| Signal::new(0)); use_context_provider(|| Signal::new(0));
rsx! { Child {} }
rsx! {
Child {}
}
} }
// This component does read from the signal, so when the signal changes it will rerun
#[component]
fn Child() -> Element { fn Child() -> Element {
let signal: Signal<i32> = *use_context(cx).unwrap(); let signal: Signal<i32> = use_context();
// This component does read from the signal, so when the signal changes it will rerun rsx! { "{signal}" }
rsx! {
"{signal}"
}
} }
+9 -17
View File
@@ -1,37 +1,29 @@
#![allow(non_snake_case)]
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_signals::*;
fn main() { fn main() {
dioxus_desktop::launch(app); // dioxus_desktop::launch(app);
} }
fn app() -> Element { fn app() -> Element {
let signal = use_signal(|| 0); let mut signal = use_signal(|| 0);
use_future(|| async move { use_future(|| async move {
loop { loop {
tokio::time::sleep(std::time::Duration::from_secs(1)).await; tokio::time::sleep(std::time::Duration::from_secs(1)).await;
*signal.write() += 1; signal += 1;
} }
}); });
let local_state = use_signal(|| 0); let mut local_state = use_signal(|| 0);
let computed = use_selector_with_dependencies((local_state.get(),), move |(local_state,)| {
let computed = use_selector_with_dependencies((&local_state(),), move |(local_state,)| {
local_state * 2 + signal.cloned() local_state * 2 + signal.cloned()
}); });
println!("Running app"); println!("Running app");
rsx! { rsx! {
button { button { onclick: move |_| local_state.set(local_state() + 1), "Add one" }
onclick: move |_| { div { "{computed}" }
local_state.set(local_state.get() + 1);
},
"Add one"
}
div {
"{computed}"
}
} }
} }
+48 -63
View File
@@ -1,11 +1,7 @@
#![allow(non_snake_case)]
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_signals::{use_signal, use_signal_sync, Signal};
use generational_box::SyncStorage;
fn main() { fn main() {
dioxus_desktop::launch(app); // dioxus_desktop::launch(app);
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@@ -15,76 +11,65 @@ enum ErrorComponent {
ReadDropped, ReadDropped,
} }
fn app(cx: Scope) -> Element { fn app() -> Element {
let error = use_signal(cx, || None); let mut error = use_signal(|| None as Option<ErrorComponent>);
render! { render! {
match *error() { match error() {
Some(ErrorComponent::Read) => render! { Read {} }, Some(ErrorComponent::Read) => render! { Read {} },
Some(ErrorComponent::ReadMut) => render! { ReadMut {} }, Some(ErrorComponent::ReadMut) => render! { ReadMut {} },
Some(ErrorComponent::ReadDropped) => render! { ReadDropped {} }, Some(ErrorComponent::ReadDropped) => render! { ReadDropped {} },
None => render! { None => render! {
button { button { onclick: move |_| error.set(Some(ErrorComponent::Read)), "Read" }
onclick: move |_| error.set(Some(ErrorComponent::Read)), button { onclick: move |_| error.set(Some(ErrorComponent::ReadMut)), "ReadMut" }
"Read" button { onclick: move |_| error.set(Some(ErrorComponent::ReadDropped)), "ReadDropped"}
}
button {
onclick: move |_| error.set(Some(ErrorComponent::ReadMut)),
"ReadMut"
}
button {
onclick: move |_| error.set(Some(ErrorComponent::ReadDropped)),
"ReadDropped"
}
}
}
}
}
fn Read(cx: Scope) -> Element {
let signal = use_signal_sync(cx, || 0);
let _write = signal.write();
let _read = signal.read();
todo!()
}
fn ReadMut(cx: Scope) -> Element {
let signal = use_signal_sync(cx, || 0);
let _read = signal.read();
let _write = signal.write();
todo!()
}
fn ReadDropped(cx: Scope) -> Element {
let signal = use_signal_sync(cx, || None);
if cx.generation() < 4 {
cx.needs_update();
}
render! {
if let Some(value) = &*signal() {
render!{"{value:?}"}
} else {
render! {
ReadDroppedSignalChild { parent_signal: signal }
} }
} }
} }
} }
#[component] #[component]
fn ReadDroppedSignalChild( fn Read() -> Element {
cx: Scope, let mut signal = use_signal_sync(|| 0);
parent_signal: Signal<Option<Signal<i32, SyncStorage>>, SyncStorage>,
) -> Element { let _write = signal.write();
let signal = use_signal_sync(cx, || 0); let _read = signal.read();
cx.use_hook(move || {
parent_signal.set(Some(signal)); todo!()
}); }
#[component]
fn ReadMut() -> Element {
let mut signal = use_signal_sync(|| 0);
let _read = signal.read();
let _write = signal.write();
todo!()
}
#[component]
fn ReadDropped() -> Element {
let signal = use_signal_sync(|| None as Option<SyncSignal<i32>>);
if generation() < 4 {
needs_update();
}
render! { render! {
"{signal}" if let Some(value) = signal() {
"{value:?}"
} else {
ReadDroppedSignalChild { parent_signal: signal }
}
} }
} }
#[component]
fn ReadDroppedSignalChild(parent_signal: SyncSignal<Option<SyncSignal<i32>>>) -> Element {
let signal = use_signal_sync(|| 0);
use_hook(move || parent_signal.set(Some(signal)));
render! { "{signal}" }
}
+3 -3
View File
@@ -2,17 +2,17 @@ use dioxus::prelude::*;
use dioxus_signals::*; use dioxus_signals::*;
fn main() { fn main() {
dioxus_desktop::launch(App); // dioxus_desktop::launch(App);
} }
#[component] #[component]
fn App() -> Element { fn App() -> Element {
let signal = use_signal(|| 0); let mut signal = use_signal(|| 0);
let doubled = use_selector(move || signal * 2); let doubled = use_selector(move || signal * 2);
rsx! { rsx! {
button { button {
onclick: move |_| *signal.write() += 1, onclick: move |_| signal += 1,
"Increase" "Increase"
} }
Child { signal: doubled } Child { signal: doubled }
+8 -11
View File
@@ -2,25 +2,22 @@ use dioxus::prelude::*;
use dioxus_signals::*; use dioxus_signals::*;
fn main() { fn main() {
tracing_subscriber::fmt::init(); // dioxus_desktop::launch(App);
dioxus_desktop::launch(App);
} }
#[component] #[component]
fn App(cx: Scope) -> Element { fn App() -> Element {
let mut signal = use_signal_sync(cx, || 0); let mut signal = use_signal_sync(|| 0);
cx.use_hook(|| {
use_hook(|| {
std::thread::spawn(move || loop { std::thread::spawn(move || loop {
std::thread::sleep(std::time::Duration::from_secs(1)); std::thread::sleep(std::time::Duration::from_secs(1));
signal += 1; signal += 1;
}) });
}); });
render! { rsx! {
button { button { onclick: move |_| signal += 1, "Increase" }
onclick: move |_| signal += 1,
"Increase"
}
"{signal}" "{signal}"
} }
} }
@@ -4,7 +4,7 @@ use dioxus::prelude::*;
use dioxus_signals::Signal; use dioxus_signals::Signal;
fn main() { fn main() {
dioxus_desktop::launch(app); // dioxus_desktop::launch(app);
} }
#[derive(Clone, Copy, Default)] #[derive(Clone, Copy, Default)]
@@ -14,10 +14,6 @@ struct ApplicationData {
many_signals: Signal<Vec<Signal<i32>>>, many_signals: Signal<Vec<Signal<i32>>>,
} }
fn use_app_data() -> ApplicationData {
*use_context(cx).unwrap()
}
fn app() -> Element { fn app() -> Element {
use_context_provider(ApplicationData::default); use_context_provider(ApplicationData::default);
@@ -28,9 +24,10 @@ fn app() -> Element {
} }
} }
#[component]
fn ReadsFirst() -> Element { fn ReadsFirst() -> Element {
println!("running first"); println!("running first");
let data = use_app_data(cx); let mut data = use_context::<ApplicationData>();
rsx! { rsx! {
button { button {
@@ -55,54 +52,37 @@ fn ReadsFirst() -> Element {
} }
} }
#[component]
fn ReadsSecond() -> Element { fn ReadsSecond() -> Element {
println!("running second"); println!("running second");
let data = use_app_data(cx); let mut data = use_context::<ApplicationData>();
rsx! { rsx! {
button { button { onclick: move |_| data.second_data += 1, "Increase" }
onclick: move |_| { button { onclick: move |_| data.second_data -= 1, "Decrease" }
*data.second_data.write() += 1; button { onclick: move |_| data.second_data.set(0), "Reset" }
},
"Increase"
}
button {
onclick: move |_| {
*data.second_data.write() -= 1;
},
"Decrease"
}
button {
onclick: move |_| {
*data.second_data.write() = 0;
},
"Reset"
}
"{data.second_data}" "{data.second_data}"
} }
} }
#[component]
fn ReadsManySignals() -> Element { fn ReadsManySignals() -> Element {
println!("running many signals"); println!("running many signals");
let data = use_app_data(cx); let mut data = use_context::<ApplicationData>();
rsx! { rsx! {
button { button {
onclick: move |_| { onclick: move |_| data.many_signals.write().push(Signal::new(0)),
data.many_signals.write().push(Signal::new(0));
},
"Create" "Create"
} }
button { button {
onclick: move |_| { onclick: move |_| { data.many_signals.write().pop(); },
data.many_signals.write().pop();
},
"Destroy" "Destroy"
} }
button { button {
onclick: move |_| { onclick: move |_| {
if let Some(first) = data.many_signals.read().first() { if let Some(mut first) = data.many_signals.read().first().cloned() {
*first.write() += 1; first += 1;
} }
}, },
"Increase First Item" "Increase First Item"
@@ -113,30 +93,15 @@ fn ReadsManySignals() -> Element {
} }
} }
#[derive(Props, PartialEq)] #[component]
struct ChildProps { fn Child(mut count: Signal<i32>) -> Element {
count: Signal<i32>,
}
fn Child(cx: Scope<ChildProps>) -> Element {
println!("running child"); println!("running child");
let count = cx.props.count;
rsx! { rsx! {
div { div {
"Child: {count}" "Child: {count}"
button { button { onclick: move |_| count += 1, "Increase" }
onclick: move |_| { button { onclick: move |_| count -= 1, "Decrease" }
*count.write() += 1;
},
"Increase"
}
button {
onclick: move |_| {
*count.write() -= 1;
},
"Decrease"
}
} }
} }
} }
+3
View File
@@ -194,6 +194,9 @@ pub struct Signal<T: 'static, S: Storage<SignalData<T>> = UnsyncStorage> {
pub(crate) inner: CopyValue<SignalData<T>, S>, pub(crate) inner: CopyValue<SignalData<T>, S>,
} }
/// A signal that can safely shared between threads.
pub type SyncSignal<T> = Signal<T, SyncStorage>;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
impl<T: serde::Serialize + 'static> serde::Serialize for Signal<T> { impl<T: serde::Serialize + 'static> serde::Serialize for Signal<T> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+1 -1
View File
@@ -53,5 +53,5 @@ fn main() {
.set_inner_html(&pre); .set_inner_html(&pre);
// now rehydrate // now rehydrate
dioxus_web::launch_with_props(app, (), Config::new().hydrate(true)); dioxus_web::launch::launch(app, vec![], Config::new().hydrate(true));
} }
+10 -10
View File
@@ -2,17 +2,16 @@
use dioxus::prelude::*; use dioxus::prelude::*;
fn main() { fn main() {
dioxus_web::launch(app); dioxus_web::launch::launch(app, vec![], Default::default());
} }
fn app() -> Element { fn app() -> Element {
let count = use_signal(|| 0); let mut count = use_signal(|| 0);
let started = use_signal(|| false); let mut started = use_signal(|| false);
let start = move || { let mut start = move || {
if !*started.get() { if !started() {
let count = count.clone(); // clone reference rather than value let alert = move || gloo_dialogs::alert(&format!("Your score was {count}!",));
let alert = move || gloo_dialogs::alert(&format!("Your score was {}!", count.read()));
gloo_timers::callback::Timeout::new(5_000, alert).forget(); gloo_timers::callback::Timeout::new(5_000, alert).forget();
} }
started.set(true); // this cannot be done inside condition or infinite loop started.set(true); // this cannot be done inside condition or infinite loop
@@ -22,10 +21,11 @@ fn app() -> Element {
button { button {
onclick: move |_event| { onclick: move |_event| {
start(); start();
*count.write() += 1; count += 1;
}, },
if **started {
"Current score: {count.read()}" if started() {
"Current score: {count}"
} else { } else {
"Start" "Start"
} }