Make more examples cross-platform

This commit is contained in:
Jonathan Kelley committed 2024-01-20 00:11:55 -08:00
1 parent 552ce92c64
commit 3ded0f5329
23 files changed
+99 -105

No files matched your search

+1 -1
View File
@@ -49,7 +49,7 @@ members = [
"playwright-tests/web", "playwright-tests/web",
"playwright-tests/fullstack", "playwright-tests/fullstack",
] ]
exclude = ["examples/mobile_demo", "packages/fermi", "examples/openid_connect_demo",] exclude = ["examples/mobile_demo", "examples/openid_connect_demo",]
[workspace.package] [workspace.package]
version = "0.4.3" version = "0.4.3"
+5 -5
View File
@@ -3,20 +3,20 @@ This example is a simple iOS-style calculator. This particular example can run a
This calculator version uses React-style state management. All state is held as individual use_states. This calculator version uses React-style state management. All state is held as individual use_states.
*/ */
use dioxus::desktop::{Config, LogicalSize, WindowBuilder};
use dioxus::events::*; use dioxus::events::*;
use dioxus::html::input_data::keyboard_types::Key; use dioxus::html::input_data::keyboard_types::Key;
use dioxus::prelude::*; use dioxus::prelude::*;
fn main() { fn main() {
LaunchBuilder::desktop() LaunchBuilder::new()
.with_cfg( .with_cfg(desktop!({
use dioxus::desktop::{Config, LogicalSize, WindowBuilder};
Config::new().with_window( Config::new().with_window(
WindowBuilder::default() WindowBuilder::default()
.with_title("Calculator") .with_title("Calculator")
.with_inner_size(LogicalSize::new(300.0, 525.0)), .with_inner_size(LogicalSize::new(300.0, 525.0)),
), )
) }))
.launch(app); .launch(app);
} }
-1
View File
@@ -11,7 +11,6 @@ fn app() -> Element {
loop { loop {
tokio::time::sleep(std::time::Duration::from_millis(10)).await; tokio::time::sleep(std::time::Duration::from_millis(10)).await;
count += 1; count += 1;
println!("current: {count}");
} }
}); });
+1 -1
View File
@@ -7,7 +7,7 @@ static ASSET_PATH: &str = "examples/assets/logo.png";
static ASSET_PATH: &str = manganis::mg!(image("examples/assets/logo.png").format(ImageType::Avif)); static ASSET_PATH: &str = manganis::mg!(image("examples/assets/logo.png").format(ImageType::Avif));
fn main() { fn main() {
launch_desktop(app); launch(app);
} }
fn app() -> Element { fn app() -> Element {
+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 std::collections::HashMap; use std::collections::HashMap;
fn main() { fn main() {
launch_desktop(app); launch(app);
} }
fn app() -> Element { fn app() -> Element {
+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
@@ -4,7 +4,7 @@ use dioxus::prelude::*;
use tokio::time::sleep; use tokio::time::sleep;
fn main() { fn main() {
launch_desktop(App); launch(App);
} }
fn App() -> Element { fn App() -> Element {
+27 -30
View File
@@ -3,15 +3,11 @@ use dioxus::prelude::*;
use dioxus::router::prelude::*; use dioxus::router::prelude::*;
fn main() { fn main() {
LaunchBuilder::desktop() launch(|| {
.with_cfg( rsx! {
Config::new().with_window( Router::<Route> {}
WindowBuilder::new() }
.with_inner_size(LogicalSize::new(600, 1000)) })
.with_resizable(false),
),
)
.launch(|| rsx! { Router::<Route> {} })
} }
#[derive(Routable, Clone)] #[derive(Routable, Clone)]
@@ -20,10 +16,13 @@ enum Route {
#[layout(Footer)] #[layout(Footer)]
#[route("/")] #[route("/")]
Home {}, Home {},
#[route("/games")] #[route("/games")]
Games {}, Games {},
#[route("/play")] #[route("/play")]
Play {}, Play {},
#[route("/settings")] #[route("/settings")]
Settings {}, Settings {},
} }
@@ -31,27 +30,14 @@ enum Route {
#[component] #[component]
fn Footer() -> Element { fn Footer() -> Element {
rsx! { rsx! {
div { Outlet::<Route> {}
Outlet::<Route> {} p { "----" }
nav {
p { "----" } style { {STYLE} }
Link { to: Route::Home {}, class: "nav-btn", "Home" }
nav { Link { to: Route::Games {}, class: "nav-btn", "Games" }
ul { Link { to: Route::Play {}, class: "nav-btn", "Play" }
li { Link { to: Route::Settings {}, class: "nav-btn", "Settings" }
Link { to: Route::Home {}, "Home" }
}
li {
Link { to: Route::Games {}, "Games" }
}
li {
Link { to: Route::Play {}, "Play" }
}
li {
Link { to: Route::Settings {}, "Settings" }
}
}
}
} }
} }
} }
@@ -75,3 +61,14 @@ fn Play() -> Element {
fn Settings() -> Element { fn Settings() -> Element {
rsx!("Settings") rsx!("Settings")
} }
const STYLE: &str = r#"
nav {
display: flex;
justify-content: space-around;
}
.nav-btn {
text-decoration: none;
color: black;
}
"#;
+1 -1
View File
@@ -8,7 +8,7 @@ static COUNT: GlobalSignal<i32> = Signal::global(|| 0);
static DOUBLED_COUNT: GlobalSelector<i32> = Signal::global_selector(|| COUNT() * 2); static DOUBLED_COUNT: GlobalSelector<i32> = Signal::global_selector(|| COUNT() * 2);
fn main() { fn main() {
launch_desktop(app); launch(app);
} }
fn app() -> Element { fn app() -> Element {
+1 -3
View File
@@ -42,9 +42,7 @@ fn app() -> Element {
// handling inputs on divs will catch all input events below // handling inputs on divs will catch all input events below
// so the value of our input event will be either huey, dewey, louie, or true/false (because of the checkboxe) // so the value of our input event will be either huey, dewey, louie, or true/false (because of the checkboxe)
// be mindful in grouping inputs together, as they will all be handled by the same event handler // be mindful in grouping inputs together, as they will all be handled by the same event handler
oninput: move |evt| { oninput: move |evt| println!("{evt:?}"),
println!("{evt:?}");
},
div { div {
input { input {
id: "huey", id: "huey",
+7 -10
View File
@@ -5,21 +5,18 @@ fn main() {
} }
fn app() -> Element { fn app() -> Element {
let onclick = move |_| {
let dom = VirtualDom::new(popup);
dioxus::desktop::window().new_window(dom, Default::default());
};
rsx! { rsx! {
div { button { onclick, "New Window" }
button {
onclick: move |_| {
let dom = VirtualDom::new(popup);
dioxus::desktop::window().new_window(dom, Default::default());
},
"New Window"
}
}
} }
} }
fn popup() -> Element { fn popup() -> Element {
rsx! { rsx! {
div { "This is a popup!" } div { "This is a popup window!" }
} }
} }
+1 -1
View File
@@ -7,7 +7,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
@@ -7,7 +7,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
@@ -8,7 +8,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
@@ -5,7 +5,7 @@
use dioxus::prelude::*; use dioxus::prelude::*;
fn main() { fn main() {
launch_desktop(app); launch(app);
} }
fn app() -> Element { fn app() -> Element {
+7 -6
View File
@@ -19,17 +19,18 @@ fn app() -> Element {
} }
} }
fn spreadable_component(props: Props) -> Element {
rsx! {
audio { ..props.attributes, "1: {props.extra_data}\n2: {props.extra_data2}" }
}
}
#[derive(Props, PartialEq, Clone)] #[derive(Props, PartialEq, Clone)]
struct Props { struct Props {
#[props(extends = GlobalAttributes)] #[props(extends = GlobalAttributes)]
attributes: Vec<Attribute>, attributes: Vec<Attribute>,
extra_data: String, extra_data: String,
extra_data2: String, extra_data2: String,
} }
fn spreadable_component(props: Props) -> Element {
rsx! {
audio { ..props.attributes, "1: {props.extra_data}\n2: {props.extra_data2}" }
}
}
+7 -9
View File
@@ -4,16 +4,14 @@ use dioxus::prelude::*;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
fn main() { fn main() {
launch_desktop(app); launch(|| {
} rsx! {
div { user_select: "none", webkit_user_select: "none", margin_left: "10%", margin_right: "10%",
fn app() -> Element { h1 { "Click die to generate a new value" }
rsx! { div { cursor: "pointer", height: "100%", width: "100%", Dice {} }
div { user_select: "none", webkit_user_select: "none", margin_left: "10%", margin_right: "10%", }
h1 { "Click die to generate a new value" }
div { cursor: "pointer", height: "100%", width: "100%", Dice {} }
} }
} });
} }
#[component] #[component]
+6 -6
View File
@@ -1,5 +1,9 @@
use dioxus::prelude::*; use dioxus::prelude::*;
fn main() {
launch(app);
}
fn app() -> Element { fn app() -> Element {
rsx! { rsx! {
svg { svg {
@@ -71,13 +75,9 @@ fn app() -> Element {
path { path {
d: "M9.00001 9C9 62 103.5 124 103.5 178", d: "M9.00001 9C9 62 103.5 124 103.5 178",
stroke: "#3CC4DC", stroke: "#3CC4DC",
"stroke-linecap": "square", stroke_linecap: "square",
"stroke-width": "square", stroke_width: "5",
} }
} }
} }
} }
fn main() {
launch_desktop(app);
}
+24 -20
View File
@@ -4,24 +4,26 @@ use dioxus_elements::input_data::keyboard_types::Key;
use std::collections::HashMap; use std::collections::HashMap;
fn main() { fn main() {
launch_desktop(app); launch(app);
} }
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
pub enum FilterState { enum FilterState {
All, All,
Active, Active,
Completed, Completed,
} }
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq)]
pub struct TodoItem { struct TodoItem {
pub id: u32, id: u32,
pub checked: bool, checked: bool,
pub contents: String, contents: String,
} }
pub fn app() -> Element { const STYLE: &str = include_str!("./assets/todomvc.css");
fn app() -> Element {
let mut todos = use_signal(|| HashMap::<u32, TodoItem>::new()); let mut todos = use_signal(|| HashMap::<u32, TodoItem>::new());
let mut filter = use_signal(|| FilterState::All); let mut filter = use_signal(|| FilterState::All);
@@ -45,9 +47,16 @@ pub fn app() -> Element {
filtered_todos filtered_todos
}); });
let mut toggle_all = move |_| {
let check = active_todo_count() != 0;
for (_, item) in todos.write().iter_mut() {
item.checked = check;
}
};
rsx! { rsx! {
section { class: "todoapp", section { class: "todoapp",
style { {include_str!("./assets/todomvc.css")} } style { {STYLE} }
TodoHeader { todos } TodoHeader { todos }
section { class: "main", section { class: "main",
if !todos.read().is_empty() { if !todos.read().is_empty() {
@@ -55,18 +64,13 @@ pub fn app() -> Element {
id: "toggle-all", id: "toggle-all",
class: "toggle-all", class: "toggle-all",
r#type: "checkbox", r#type: "checkbox",
onchange: move |_| { onchange: toggle_all,
let check = active_todo_count() != 0;
for (_, item) in todos.write().iter_mut() {
item.checked = check;
}
},
checked: active_todo_count() == 0, checked: active_todo_count() == 0,
} }
label { r#for: "toggle-all" } label { r#for: "toggle-all" }
} }
ul { class: "todo-list", ul { class: "todo-list",
for id in filtered_todos.read().iter().copied() { for id in filtered_todos() {
TodoEntry { key: "{id}", id, todos } TodoEntry { key: "{id}", id, todos }
} }
} }
@@ -80,7 +84,7 @@ pub fn app() -> Element {
} }
#[component] #[component]
pub fn TodoHeader(mut todos: Signal<HashMap<u32, TodoItem>>) -> Element { fn TodoHeader(mut todos: Signal<HashMap<u32, TodoItem>>) -> Element {
let mut draft = use_signal(|| "".to_string()); let mut draft = use_signal(|| "".to_string());
let mut todo_id = use_signal(|| 0); let mut todo_id = use_signal(|| 0);
@@ -114,7 +118,7 @@ pub fn TodoHeader(mut todos: Signal<HashMap<u32, TodoItem>>) -> Element {
} }
#[component] #[component]
pub fn TodoEntry(mut todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element { fn TodoEntry(mut todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element {
let mut is_editing = use_signal(|| false); let mut is_editing = use_signal(|| false);
let checked = use_selector(move || todos.read().get(&id).unwrap().checked); let checked = use_selector(move || todos.read().get(&id).unwrap().checked);
let contents = use_selector(move || todos.read().get(&id).unwrap().contents.clone()); let contents = use_selector(move || todos.read().get(&id).unwrap().contents.clone());
@@ -161,7 +165,7 @@ pub fn TodoEntry(mut todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element
} }
#[component] #[component]
pub fn ListFooter( fn ListFooter(
mut todos: Signal<HashMap<u32, TodoItem>>, mut todos: Signal<HashMap<u32, TodoItem>>,
active_todo_count: ReadOnlySignal<usize>, active_todo_count: ReadOnlySignal<usize>,
mut filter: Signal<FilterState>, mut filter: Signal<FilterState>,
@@ -208,7 +212,7 @@ pub fn ListFooter(
} }
} }
pub fn PageFooter() -> Element { fn PageFooter() -> Element {
rsx! { rsx! {
footer { class: "info", footer { class: "info",
p { "Double-click to edit a todo" } p { "Double-click to edit a todo" }
+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
@@ -11,7 +11,7 @@ fn main() {
} }
fn app() -> Element { fn app() -> Element {
let mut focused = use_signal(|| false); let mut focused = use_signal(|| true);
use_wry_event_handler(move |event, _| match event { use_wry_event_handler(move |event, _| match event {
WryEvent::WindowEvent { WryEvent::WindowEvent {
+2 -2
View File
@@ -726,7 +726,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> PartialEq for ReadOnlySignal<T, S> {
} }
} }
impl<T: Copy, S: Storage<SignalData<T>> + 'static> Deref for ReadOnlySignal<T, S> { impl<T: Clone, S: Storage<SignalData<T>> + 'static> Deref for ReadOnlySignal<T, S> {
type Target = dyn Fn() -> T; type Target = dyn Fn() -> T;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@@ -735,7 +735,7 @@ impl<T: Copy, S: Storage<SignalData<T>> + 'static> Deref for ReadOnlySignal<T, S
// First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>). // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>).
let uninit_callable = MaybeUninit::<Self>::uninit(); let uninit_callable = MaybeUninit::<Self>::uninit();
// Then move that value into the closure. We assume that the closure now has a in memory layout of Self. // Then move that value into the closure. We assume that the closure now has a in memory layout of Self.
let uninit_closure = move || *Self::read(unsafe { &*uninit_callable.as_ptr() }); let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() }).clone();
// Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure. // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure.
let size_of_closure = std::mem::size_of_val(&uninit_closure); let size_of_closure = std::mem::size_of_val(&uninit_closure);