Fix global signal owner

This commit is contained in:
Jonathan Kelley committed 2024-01-19 15:48:21 -08:00
1 parent 673caec79f
commit 60f5697e8e
6 files changed
+91 -98

No files matched your search

+30 -48
View File
@@ -1,78 +1,60 @@
use std::{collections::VecDeque, fmt::Debug, rc::Rc};
use dioxus::{events::*, html::MouseEvent, prelude::*};
fn main() {
launch(app);
}
#[derive(Debug)]
enum Event {
MouseMove(MouseEvent),
MouseClick(MouseEvent),
MouseDoubleClick(MouseEvent),
MouseDown(MouseEvent),
MouseUp(MouseEvent),
Wheel(WheelEvent),
KeyDown(KeyboardEvent),
KeyUp(KeyboardEvent),
KeyPress(KeyboardEvent),
FocusIn(FocusEvent),
FocusOut(FocusEvent),
}
const MAX_EVENTS: usize = 8;
const CONTAINER_STYLE: &str = r#"
display: flex;
flex-direction: column;
align-items: center;
"#;
display: flex;
flex-direction: column;
align-items: center;
"#;
const RECT_STYLE: &str = r#"
background: deepskyblue;
height: 50vh;
width: 50vw;
color: white;
padding: 20px;
margin: 20px;
text-aligh: center;
"#;
background: deepskyblue;
height: 50vh;
width: 50vw;
color: white;
padding: 20px;
margin: 20px;
text-aligh: center;
"#;
fn app() -> Element {
let mut events = use_signal(std::collections::VecDeque::new);
let mut events = use_signal(|| std::collections::VecDeque::new() as VecDeque<Rc<dyn Debug>>);
let mut log_event = move |event: Event| {
let mut log_event = move |event: Rc<dyn Debug>| {
let mut events = events.write();
if events.len() >= MAX_EVENTS {
events.pop_front();
}
events.push_back(event);
};
rsx! {
div { style: "{CONTAINER_STYLE}",
div {
style: "{RECT_STYLE}",
// focusing is necessary to catch keyboard events
tabindex: "0",
// focusing is necessary to catch keyboard events
div { style: "{RECT_STYLE}", tabindex: "0",
onmousemove: move |event| log_event(event.inner().clone()),
onclick: move |event| log_event(event.inner().clone()),
ondoubleclick: move |event| log_event(event.inner().clone()),
onmousedown: move |event| log_event(event.inner().clone()),
onmouseup: move |event| log_event(event.inner().clone()),
onmousemove: move |event| log_event(Event::MouseMove(event)),
onclick: move |event| log_event(Event::MouseClick(event)),
ondoubleclick: move |event| log_event(Event::MouseDoubleClick(event)),
onmousedown: move |event| log_event(Event::MouseDown(event)),
onmouseup: move |event| log_event(Event::MouseUp(event)),
onwheel: move |event| log_event(event.inner().clone()),
onwheel: move |event| log_event(Event::Wheel(event)),
onkeydown: move |event| log_event(event.inner().clone()),
onkeyup: move |event| log_event(event.inner().clone()),
onkeypress: move |event| log_event(event.inner().clone()),
onkeydown: move |event| log_event(Event::KeyDown(event)),
onkeyup: move |event| log_event(Event::KeyUp(event)),
onkeypress: move |event| log_event(Event::KeyPress(event)),
onfocusin: move |event| log_event(Event::FocusIn(event)),
onfocusout: move |event| log_event(Event::FocusOut(event)),
onfocusin: move |event| log_event(event.inner().clone()),
onfocusout: move |event| log_event(event.inner().clone()),
"Hover, click, type or scroll to see the info down below"
}
+15 -22
View File
@@ -9,24 +9,26 @@ use dioxus::prelude::*;
use dioxus_desktop::{Config, LogicalSize, WindowBuilder};
fn main() {
let config = Config::new().with_window(
WindowBuilder::default()
.with_title("Calculator")
.with_inner_size(LogicalSize::new(300.0, 525.0)),
);
LaunchBuilder::desktop().with_cfg(config).launch(app);
LaunchBuilder::desktop()
.with_cfg(
Config::new().with_window(
WindowBuilder::default()
.with_title("Calculator")
.with_inner_size(LogicalSize::new(300.0, 525.0)),
),
)
.launch(app);
}
fn app() -> Element {
let mut val = use_signal(|| String::from("0"));
let mut input_digit = move |num: u8| {
if val.cloned() == "0" {
let mut input_digit = move |num: String| {
if val() == "0" {
val.set(String::new());
}
val.write().push_str(num.to_string().as_str());
val.write().push_str(num.as_str());
};
let mut input_operator = move |key: &str| val.write().push_str(key);
@@ -42,16 +44,7 @@ fn app() -> Element {
"-" => input_operator("-"),
"/" => input_operator("/"),
"*" => input_operator("*"),
"0" => input_digit(0),
"1" => input_digit(1),
"2" => input_digit(2),
"3" => input_digit(3),
"4" => input_digit(4),
"5" => input_digit(5),
"6" => input_digit(6),
"7" => input_digit(7),
"8" => input_digit(8),
"9" => input_digit(9),
"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" => input_digit(character),
_ => {}
},
_ => {}
@@ -99,7 +92,7 @@ fn app() -> Element {
div { class: "digit-keys",
button {
class: "calculator-key key-0",
onclick: move |_| input_digit(0),
onclick: move |_| input_digit(0.to_string()),
"0"
}
button {
@@ -111,7 +104,7 @@ fn app() -> Element {
button {
class: "calculator-key {k}",
name: "key-{k}",
onclick: move |_| input_digit(k),
onclick: move |_| input_digit(k.to_string()),
"{k}"
}
}
+1 -1
View File
@@ -19,7 +19,7 @@ fn app() -> Element {
}
});
let open_compose_window = move |evt: MouseEvent| {
let open_compose_window = move |_evt: MouseEvent| {
let tx = handle.tx();
dioxus_desktop::window().new_window(
VirtualDom::new_with_props(compose, Rc::new(move |s| tx.unbounded_send(s).unwrap())),
+20 -18
View File
@@ -3,17 +3,13 @@ use dioxus::prelude::*;
use dioxus_router::prelude::*;
fn main() {
launch_desktop(app);
launch(app);
}
/// A type alias that reprsents a shared context between components
///
/// Normally we'd wrap the Context in a newtype, but we only have one Signal<Vec<Client>> in this app
type Clients = Signal<Vec<Client>>;
/// We only have one list of clients for the whole app, so we can use a global signal.
static CLIENTS: GlobalSignal<Vec<Client>> = Signal::global(|| Vec::new());
fn app() -> Element {
use_context_provider::<Clients>(|| Signal::new(vec![]));
rsx! {
link {
rel: "stylesheet",
@@ -37,7 +33,6 @@ fn app() -> Element {
}
#[derive(Routable, Clone)]
#[rustfmt::skip]
enum Route {
#[route("/")]
ClientList {},
@@ -58,7 +53,9 @@ pub struct Client {
#[component]
fn ClientList() -> Element {
let mut clients = use_context::<Clients>();
let clients = use_hook(|| CLIENTS.signal());
println!("Clients: {:?}", clients.read());
rsx! {
h2 { "List of Clients" }
@@ -80,21 +77,25 @@ fn ClientAdd() -> Element {
let mut description = use_signal(String::new);
let submit_client = move |_: FormEvent| {
consume_context::<Clients>().write().push(Client {
first_name: first_name.to_string(),
last_name: last_name.to_string(),
description: description.to_string(),
// Write the client
CLIENTS.write().push(Client {
first_name: first_name(),
last_name: last_name(),
description: description(),
});
println!("Added client: {:?}", CLIENTS.read());
// And then navigate back to the client list
dioxus_router::router().push(Route::ClientList {});
};
rsx! {
h2 { "Add new Client" }
form { class: "pure-form pure-form-aligned", onsubmit: submit_client,
fieldset {
div { class: "pure-control-group",
label { "for": "first_name", "First Name" }
label { r#for: "first_name", "First Name" }
input {
id: "first_name",
r#type: "text",
@@ -140,13 +141,14 @@ fn ClientAdd() -> Element {
fn Settings() -> Element {
rsx! {
h2 { "Settings" }
button {
class: "pure-button pure-button-primary red",
onclick: move |_| consume_context::<Clients>().write().clear(),
onclick: move |_| {
CLIENTS.write().clear();
dioxus_router::router().push(Route::ClientList {});
},
"Remove all Clients"
}
Link { to: Route::ClientList {}, class: "pure-button", "Go back" }
}
}