wip: almost there

This commit is contained in:
Jonathan Kelley committed 2021-09-24 02:10:54 -04:00
1 parent f07e345eb2
commit 047c810507
11 files changed
+155 -385

No files matched your search

-14
View File
@@ -1,14 +0,0 @@
use dioxus::prelude::*;
fn main() {
let g = dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory| {
use dioxus_elements::{GlobalAttributes, SvgAttributes};
__cx.element(
dioxus_elements::button,
[dioxus::events::on::onclick(__cx, move |_| {})],
[],
[],
None,
)
});
}
+15 -21
View File
@@ -12,7 +12,7 @@ fn main() {
const APP: FC<()> = |cx, _| {
let cur_val = use_state(cx, || 0.0_f64);
let operator = use_state(cx, || None);
let operator = use_state(cx, || None as Option<&'static str>);
let display_value = use_state(cx, || String::from(""));
let clear_display = display_value == "0";
@@ -25,11 +25,12 @@ const APP: FC<()> = |cx, _| {
let perform_operation = move || {
if let Some(op) = operator.as_ref() {
let rhs = display_value.parse::<f64>().unwrap();
let new_val = match op {
Operator::Add => *cur_val + rhs,
Operator::Sub => *cur_val - rhs,
Operator::Mul => *cur_val * rhs,
Operator::Div => *cur_val / rhs,
let new_val = match *op {
"+" => *cur_val + rhs,
"-" => *cur_val - rhs,
"*" => *cur_val * rhs,
"/" => *cur_val / rhs,
_ => unreachable!(),
};
cur_val.set(new_val);
display_value.set(new_val.to_string());
@@ -56,10 +57,10 @@ const APP: FC<()> = |cx, _| {
};
let keydownhandler = move |evt: KeyboardEvent| match evt.key_code() {
KeyCode::Add => operator.set(Some(Operator::Add)),
KeyCode::Subtract => operator.set(Some(Operator::Sub)),
KeyCode::Divide => operator.set(Some(Operator::Div)),
KeyCode::Multiply => operator.set(Some(Operator::Mul)),
KeyCode::Add => operator.set(Some("+")),
KeyCode::Subtract => operator.set(Some("-")),
KeyCode::Divide => operator.set(Some("/")),
KeyCode::Multiply => operator.set(Some("*")),
KeyCode::Num0 => input_digit(0),
KeyCode::Num1 => input_digit(1),
KeyCode::Num2 => input_digit(2),
@@ -99,23 +100,16 @@ const APP: FC<()> = |cx, _| {
})}
}
div { class: "operator-keys"
CalculatorKey { name: "key-divide", onclick: move |_| operator.set(Some(Operator::Div)) "÷" }
CalculatorKey { name: "key-multiply", onclick: move |_| operator.set(Some(Operator::Mul)) "×" }
CalculatorKey { name: "key-subtract", onclick: move |_| operator.set(Some(Operator::Sub)) "−" }
CalculatorKey { name: "key-add", onclick: move |_| operator.set(Some(Operator::Add)) "+" }
CalculatorKey { name: "key-divide", onclick: move |_| operator.set(Some("/")) "÷" }
CalculatorKey { name: "key-multiply", onclick: move |_| operator.set(Some("*")) "×" }
CalculatorKey { name: "key-subtract", onclick: move |_| operator.set(Some("-")) "−" }
CalculatorKey { name: "key-add", onclick: move |_| operator.set(Some("+")) "+" }
CalculatorKey { name: "key-equals", onclick: move |_| perform_operation() "=" }
}
}
})
};
enum Operator {
Add,
Sub,
Mul,
Div,
}
#[derive(Props)]
struct CalculatorKeyProps<'a> {
name: &'static str,
+59 -32
View File
@@ -6,7 +6,6 @@ use dioxus::prelude::*;
fn main() {
dioxus::web::launch(App, |c| c);
}
enum Scene {
ClientsList,
NewClientForm,
@@ -28,50 +27,78 @@ static App: FC<()> = |cx, _| {
let lastname = use_state(cx, || String::new());
let description = use_state(cx, || String::new());
match *scene {
let scene = match *scene {
Scene::ClientsList => {
rsx!(cx, div { class: "crm"
h1 { "List of clients" }
div { class: "clients" {clients.read().iter().map(|client| rsx!(
div { class: "client" style: "margin-bottom: 50px"
p { "First Name: {client.first_name}" }
p { "Last Name: {client.last_name}" }
p {"Description: {client.description}"}
}))}
h2 { "List of clients" margin_bottom: "10px" }
div { class: "clients" margin_left: "10px"
{clients.read().iter().map(|client| rsx!(
div { class: "client" style: "margin-bottom: 50px"
p { "First Name: {client.first_name}" }
p { "Last Name: {client.last_name}" }
p {"Description: {client.description}"}
})
)}
}
button { onclick: move |_| scene.set(Scene::NewClientForm), "Add New" }
button { onclick: move |_| scene.set(Scene::Settings), "Settings" }
button { class: "pure-button pure-button-primary" onclick: move |_| scene.set(Scene::NewClientForm), "Add New" }
button { class: "pure-button" onclick: move |_| scene.set(Scene::Settings), "Settings" }
})
}
Scene::NewClientForm => {
rsx!(cx, div { class: "crm"
h1 {"Add new client"}
div { class: "names"
input { class: "new-client firstname" placeholder: "First name"
onchange: move |e| firstname.set(e.value())
}
input { class: "new-client lastname" placeholder: "Last name"
onchange: move |e| lastname.set(e.value())
}
textarea { class: "new-client description" placeholder: "Description"
onchange: move |e| description.set(e.value())
}
}
button { disabled: "false", onclick: move |_| clients.write().push(Client {
let add_new = move |_| {
clients.write().push(Client {
description: (*description).clone(),
first_name: (*firstname).clone(),
last_name: (*lastname).clone(),
}), "Add New" }
button { onclick: move |_| scene.set(Scene::ClientsList), "Go Back" }
});
description.set(String::new());
firstname.set(String::new());
lastname.set(String::new());
};
rsx!(cx, div { class: "crm"
h2 {"Add new client" margin_bottom: "10px" }
form { class: "pure-form"
input { class: "new-client firstname" placeholder: "First name" value: "{firstname}"
oninput: move |e| firstname.set(e.value())
}
input { class: "new-client lastname" placeholder: "Last name" value: "{lastname}"
oninput: move |e| lastname.set(e.value())
}
textarea { class: "new-client description" placeholder: "Description" value: "{description}"
oninput: move |e| description.set(e.value())
}
}
button { class: "pure-button pure-button-primary", onclick: {add_new}, "Add New" }
button { class: "pure-button", onclick: move |_| scene.set(Scene::ClientsList), "Go Back" }
})
}
Scene::Settings => {
rsx!(cx, div {
h1 {"Settings"}
button { onclick: move |_| clients.write().clear() "Remove all clients" }
button { onclick: move |_| scene.set(Scene::ClientsList), "Go Back" }
h2 {"Settings" margin_bottom: "10px" }
button {
background: "rgb(202, 60, 60)"
class: "pure-button pure-button-primary"
onclick: move |_| clients.write().clear(),
"Remove all clients"
}
button {
class: "pure-button pure-button-primary"
onclick: move |_| scene.set(Scene::ClientsList),
"Go Back"
}
})
}
}
};
rsx!(cx, body {
link {
rel: "stylesheet"
href: "https://unpkg.com/purecss@2.0.6/build/pure-min.css"
integrity: "sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5"
crossorigin: "anonymous"
}
margin_left: "35%"
h1 {"Dioxus CRM Example"}
{scene}
})
};
+1 -2
View File
@@ -7,7 +7,6 @@
use dioxus::desktop::wry::application::dpi::LogicalSize;
use dioxus::prelude::*;
use std::fs::{self, DirEntry};
fn main() {
env_logger::init();
@@ -73,7 +72,7 @@ impl Files {
fn reload_path_list(&mut self) {
let cur_path = self.path_stack.last().unwrap();
let paths = match fs::read_dir(cur_path) {
let paths = match std::fs::read_dir(cur_path) {
Ok(e) => e,
Err(err) => {
let err = format!("An error occured: {:?}", err);
-2
View File
@@ -6,7 +6,6 @@ fn main() {
// .. should result in an "invalid node tree"
let edits = vec![
CreateElement { tag: "div", id: 0 },
// CreatePlaceholder { id: 1 },
CreateElement { tag: "h1", id: 2 },
CreateTextNode {
text: "hello world",
@@ -15,7 +14,6 @@ fn main() {
AppendChildren { many: 1 },
AppendChildren { many: 1 },
AppendChildren { many: 1 },
// ReplaceWith { many: 1 },
];
dioxus_desktop::WebviewRenderer::run_with_edits(App, (), |c| c, Some(edits)).expect("failed");
+26 -29
View File
@@ -33,40 +33,38 @@ fn main() {
}
static App: FC<()> = |cx, props| {
let state = use_state(cx, || Calculator::new());
let state = use_ref(cx, || Calculator::new());
let clear_display = state.display_value.eq("0");
let clear_display = state.read().display_value.eq("0");
let clear_text = if clear_display { "C" } else { "AC" };
let formatted = state.formatted_display();
let formatted = state.read().formatted_display();
cx.render(rsx! {
div { id: "wrapper"
div { class: "app", style { "{STYLE}" }
div { class: "calculator", onkeypress: move |evt| state.modify().handle_keydown(evt),
div { class: "calculator-display", "{formatted}"}
div { class: "calculator-keypad"
div { class: "input-keys"
div { class: "function-keys"
CalculatorKey { name: "key-clear", onclick: move |_| state.modify().clear_display(), "{clear_text}" }
CalculatorKey { name: "key-sign", onclick: move |_| state.modify().toggle_sign(), "±"}
CalculatorKey { name: "key-percent", onclick: move |_| state.modify().toggle_percent(), "%"}
}
div { class: "digit-keys"
CalculatorKey { name: "key-0", onclick: move |_| state.modify().input_digit(0), "0" }
CalculatorKey { name: "key-dot", onclick: move |_| state.modify().input_dot(), "●" }
{(1..10).map(move |k| rsx!{
CalculatorKey { key: "{k}", name: "key-{k}", onclick: move |_| state.modify().input_digit(k), "{k}" }
})}
}
rsx!(cx, div { id: "wrapper"
div { class: "app", style { "{STYLE}" }
div { class: "calculator", onkeypress: move |evt| state.write().handle_keydown(evt),
div { class: "calculator-display", "{formatted}"}
div { class: "calculator-keypad"
div { class: "input-keys"
div { class: "function-keys"
CalculatorKey { name: "key-clear", onclick: move |_| state.write().clear_display(), "{clear_text}" }
CalculatorKey { name: "key-sign", onclick: move |_| state.write().toggle_sign(), "±"}
CalculatorKey { name: "key-percent", onclick: move |_| state.write().toggle_percent(), "%"}
}
div { class: "operator-keys"
CalculatorKey { name:"key-divide", onclick: move |_| state.modify().set_operator(Operator::Div), "÷" }
CalculatorKey { name:"key-multiply", onclick: move |_| state.modify().set_operator(Operator::Mul), "×" }
CalculatorKey { name:"key-subtract", onclick: move |_| state.modify().set_operator(Operator::Sub), "−" }
CalculatorKey { name:"key-add", onclick: move |_| state.modify().set_operator(Operator::Add), "+" }
CalculatorKey { name:"key-equals", onclick: move |_| state.modify().perform_operation(), "=" }
div { class: "digit-keys"
CalculatorKey { name: "key-0", onclick: move |_| state.write().input_digit(0), "0" }
CalculatorKey { name: "key-dot", onclick: move |_| state.write().input_dot(), "●" }
{(1..10).map(move |k| rsx!{
CalculatorKey { key: "{k}", name: "key-{k}", onclick: move |_| state.write().input_digit(k), "{k}" }
})}
}
}
div { class: "operator-keys"
CalculatorKey { name:"key-divide", onclick: move |_| state.write().set_operator(Operator::Div), "÷" }
CalculatorKey { name:"key-multiply", onclick: move |_| state.write().set_operator(Operator::Mul), "×" }
CalculatorKey { name:"key-subtract", onclick: move |_| state.write().set_operator(Operator::Sub), "−" }
CalculatorKey { name:"key-add", onclick: move |_| state.write().set_operator(Operator::Add), "+" }
CalculatorKey { name:"key-equals", onclick: move |_| state.write().perform_operation(), "=" }
}
}
}
}
@@ -89,7 +87,6 @@ fn CalculatorKey<'a, 'r>(cx: Context<'a>, props: &'a CalculatorKeyProps) -> DomT
})
}
#[derive(Clone)]
struct Calculator {
display_value: String,
operator: Option<Operator>,
+11 -13
View File
@@ -11,23 +11,21 @@ fn main() {
dioxus::desktop::launch(App, |c| c);
}
pub static App: FC<()> = |cx, props| {
pub static App: FC<()> = |cx, _| {
let state = use_state(cx, PlayerState::new);
let is_playing = state.is_playing();
cx.render(rsx! {
div {
h1 {"Select an option"}
h3 {"The radio is... {is_playing}!"}
button {
"Pause"
onclick: move |_| state.modify().reduce(PlayerAction::Pause)
}
button {
"Play"
onclick: move |_| state.modify().reduce(PlayerAction::Play)
}
rsx!(cx, div {
h1 {"Select an option"}
h3 {"The radio is... {is_playing}!"}
button {
"Pause"
onclick: move |_| state.modify().reduce(PlayerAction::Pause)
}
button {
"Play"
onclick: move |_| state.modify().reduce(PlayerAction::Play)
}
})
};
-112
View File
@@ -1,112 +0,0 @@
//! Example: Webview Renderer
//! -------------------------
//!
//! This example shows how to use the dioxus_desktop crate to build a basic desktop application.
//!
//! Under the hood, the dioxus_desktop crate bridges a native Dioxus VirtualDom with a custom prebuit application running
//! in the webview runtime. Custom handlers are provided for the webview instance to consume patches and emit user events
//! into the native VDom instance.
//!
//! Currently, NodeRefs won't work properly, but all other event functionality will.
use dioxus::prelude::*;
fn main() {
dioxus::desktop::launch(App, |c| c);
}
static App: FC<()> = |cx, props| {
let slides = use_state(cx, SlideController::new);
let slide = match slides.slide_id {
0 => cx.render(rsx!(Title {})),
1 => cx.render(rsx!(Slide1 {})),
2 => cx.render(rsx!(Slide2 {})),
3 => cx.render(rsx!(Slide3 {})),
_ => cx.render(rsx!(End {})),
};
cx.render(rsx! {
div {
style: {
background_color: "red"
}
div {
div { h1 {"my awesome slideshow"} }
div {
button {"<-", onclick: move |_| slides.modify().go_forward()}
h3 { "{slides.slide_id}" }
button {"->" onclick: move |_| slides.modify().go_backward()}
}
}
{slide}
}
})
};
#[derive(Clone)]
struct SlideController {
slide_id: isize,
}
impl SlideController {
fn new() -> Self {
Self { slide_id: 0 }
}
fn can_go_forward(&self) -> bool {
false
}
fn can_go_backward(&self) -> bool {
true
}
fn go_forward(&mut self) {
if self.can_go_forward() {
self.slide_id += 1;
}
}
fn go_backward(&mut self) {
if self.can_go_backward() {
self.slide_id -= 1;
}
}
}
const Title: FC<()> = |cx, props| {
cx.render(rsx! {
div {
h1 { "Title" }
p {}
}
})
};
const Slide1: FC<()> = |cx, props| {
cx.render(rsx! {
div {
h1 { "Slide1" }
p {}
}
})
};
const Slide2: FC<()> = |cx, props| {
cx.render(rsx! {
div {
h1 { "Slide2" }
p {}
}
})
};
const Slide3: FC<()> = |cx, props| {
cx.render(rsx! {
div {
h1 { "Slide3" }
p {}
}
})
};
const End: FC<()> = |cx, props| {
cx.render(rsx! {
div {
h1 { "End" }
p {}
}
})
};
-67
View File
@@ -1,67 +0,0 @@
use std::cell::Cell;
use dioxus::prelude::*;
use dioxus_core::{
nodes::{VElement, VText},
ElementId,
};
fn main() {
env_logger::init();
dioxus::desktop::launch(Example, |c| c);
}
const STYLE: &str = r#"
body {background-color: powderblue;}
h1 {color: blue;}
p {color: red;}
"#;
const Example: FC<()> = |cx, props| {
cx.render(rsx! {
Fragment {
Fragment {
Fragment {
"h1"
div {
}
}
"h2"
}
"h3"
}
"h4"
div { "h5" }
button { }
Child {}
})
};
const Child: FC<()> = |cx, props| {
cx.render(rsx!(
h1 {"1" }
h1 {"2" }
h1 {"3" }
h1 {"4" }
))
};
// this is a bad case that hurts our subtree memoization :(
const AbTest: FC<()> = |cx, props| {
if 1 == 2 {
cx.render(rsx!(
h1 {"1"}
h1 {"2"}
h1 {"3"}
h1 {"4"}
))
} else {
cx.render(rsx!(
h1 {"1"}
h1 {"2"}
h2 {"basd"}
h1 {"4"}
))
}
};
+43 -45
View File
@@ -48,62 +48,60 @@ const App: FC<()> = |cx, props| {
_ => "items",
};
cx.render(rsx! {
div { id: "app"
style {"{STYLE}"}
div {
header { class: "header"
h1 {"todos"}
input {
class: "new-todo"
placeholder: "What needs to be done?"
value: "{draft}"
oninput: move |evt| draft.set(evt.value())
rsx!(cx, div { id: "app"
style {"{STYLE}"}
div {
header { class: "header"
h1 {"todos"}
input {
class: "new-todo"
placeholder: "What needs to be done?"
value: "{draft}"
oninput: move |evt| draft.set(evt.value())
}
}
{todolist}
{(!todos.is_empty()).then(|| rsx!(
footer {
span { strong {"{items_left}"} span {"{item_text} left"} }
ul { class: "filters"
li { class: "All", a { href: "", onclick: move |_| filter.set(FilterState::All), "All" }}
li { class: "Active", a { href: "active", onclick: move |_| filter.set(FilterState::Active), "Active" }}
li { class: "Completed", a { href: "completed", onclick: move |_| filter.set(FilterState::Completed), "Completed" }}
}
}
{todolist}
{(!todos.is_empty()).then(|| rsx!(
footer {
span { strong {"{items_left}"} span {"{item_text} left"} }
ul { class: "filters"
li { class: "All", a { href: "", onclick: move |_| filter.set(FilterState::All), "All" }}
li { class: "Active", a { href: "active", onclick: move |_| filter.set(FilterState::Active), "Active" }}
li { class: "Completed", a { href: "completed", onclick: move |_| filter.set(FilterState::Completed), "Completed" }}
}
}
))}
}
footer { class: "info"
p {"Double-click to edit a todo"}
p { "Created by ", a { "jkelleyrtp", href: "http://github.com/jkelleyrtp/" }}
p { "Part of ", a { "TodoMVC", href: "http://todomvc.com" }}
}
))}
}
footer { class: "info"
p {"Double-click to edit a todo"}
p { "Created by ", a { "jkelleyrtp", href: "http://github.com/jkelleyrtp/" }}
p { "Part of ", a { "TodoMVC", href: "http://todomvc.com" }}
}
})
};
#[derive(PartialEq, Props)]
pub struct TodoEntryProps {
todo: std::rc::Rc<TodoItem>,
todo: Rc<TodoItem>,
}
pub fn TodoEntry<'a>(cx: Context<'a>, TodoEntryProps { todo }: &'a TodoEntryProps) -> DomTree<'a> {
pub fn TodoEntry<'a>(cx: Context<'a>, props: &TodoEntryProps) -> DomTree<'a> {
let is_editing = use_state(cx, || false);
let contents = "";
let contents = use_state(cx, || String::from(""));
let todo = &props.todo;
cx.render(rsx! (
li {
"{todo.id}"
input {
class: "toggle"
r#type: "checkbox"
"{todo.checked}"
}
{is_editing.then(|| rsx!{
input {
value: "{contents}"
}
})}
rsx!(cx, li {
"{todo.id}"
input {
class: "toggle"
r#type: "checkbox"
"{todo.checked}"
}
))
{is_editing.then(|| rsx!{
input {
value: "{contents}"
oninput: move |evt| contents.set(evt.value())
}
})}
})
}
-48
View File
@@ -1,48 +0,0 @@
//! Example: Webview Renderer
//! -------------------------
//!
//! This example shows how to use the dioxus_desktop crate to build a basic desktop application.
//!
//! Under the hood, the dioxus_desktop crate bridges a native Dioxus VirtualDom with a custom prebuit application running
//! in the webview runtime. Custom handlers are provided for the webview instance to consume patches and emit user events
//! into the native VDom instance.
//!
//! Currently, NodeRefs won't work properly, but all other event functionality will.
#![allow(non_upper_case_globals, non_snake_case)]
use dioxus::{events::on::MouseEvent, prelude::*};
fn main() -> anyhow::Result<()> {
env_logger::init();
dioxus::desktop::launch(App, |c| c)
}
static App: FC<()> = |cx, props| {
let state = use_state(cx, || String::from("hello"));
let clear_text = state == "hello";
dbg!("rednering parent");
cx.render(rsx! {
div {
h1 {"{state}"}
CalculatorKey { name: "key-clear", onclick: move |_| state.modify().push_str("hello"), "{clear_text}" }
CalculatorKey { name: "key-sign", onclick: move |_| { state.modify().pop(); }, "±"}
}
})
};
#[derive(Props)]
struct CalculatorKeyProps<'a> {
name: &'static str,
onclick: &'a dyn Fn(MouseEvent),
}
fn CalculatorKey<'a>(cx: Context<'a>, props: &'a CalculatorKeyProps) -> DomTree<'a> {
cx.render(rsx! {
button {
class: "calculator-key {props.name}"
onclick: {props.onclick}
{cx.children()}
}
})
}