implement launch builder for the desktop and web platforms
This commit is contained in:
1 parent
ef553a2cb2
commit
7e4d2debe0
70 files changed
+448
-431
No files matched your search
+1
-1
@@ -125,7 +125,7 @@ rust-version = "1.60.0"
|
|||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dioxus = { workspace = true }
|
dioxus = { workspace = true, features = ["desktop"] }
|
||||||
dioxus-desktop = { workspace = true, features = ["transparent"] }
|
dioxus-desktop = { workspace = true, features = ["transparent"] }
|
||||||
dioxus-ssr = { workspace = true }
|
dioxus-ssr = { workspace = true }
|
||||||
dioxus-router = { workspace = true }
|
dioxus-router = { workspace = true }
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::{events::*, html::MouseEvent, prelude::*};
|
use dioxus::{events::*, html::MouseEvent, prelude::*};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
+34
-14
@@ -15,7 +15,7 @@ fn main() {
|
|||||||
.with_inner_size(LogicalSize::new(300.0, 500.0)),
|
.with_inner_size(LogicalSize::new(300.0, 500.0)),
|
||||||
);
|
);
|
||||||
|
|
||||||
dioxus_desktop::launch_cfg(app, config);
|
LaunchBuilder::new(app).cfg(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
@@ -61,9 +61,7 @@ fn app() -> Element {
|
|||||||
style { {include_str!("./assets/calculator.css")} }
|
style { {include_str!("./assets/calculator.css")} }
|
||||||
div { id: "wrapper",
|
div { id: "wrapper",
|
||||||
div { class: "app",
|
div { class: "app",
|
||||||
div { class: "calculator",
|
div { class: "calculator", tabindex: "0", onkeydown: handle_key_down_event,
|
||||||
tabindex: "0",
|
|
||||||
onkeydown: handle_key_down_event,
|
|
||||||
div { class: "calculator-display", "{val}" }
|
div { class: "calculator-display", "{val}" }
|
||||||
div { class: "calculator-keypad",
|
div { class: "calculator-keypad",
|
||||||
div { class: "input-keys",
|
div { class: "input-keys",
|
||||||
@@ -72,7 +70,7 @@ fn app() -> Element {
|
|||||||
class: "calculator-key key-clear",
|
class: "calculator-key key-clear",
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
val.set(String::new());
|
val.set(String::new());
|
||||||
if !val.cloned().is_empty(){
|
if !val.cloned().is_empty() {
|
||||||
val.set("0".into());
|
val.set("0".into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -93,16 +91,22 @@ fn app() -> Element {
|
|||||||
button {
|
button {
|
||||||
class: "calculator-key key-percent",
|
class: "calculator-key key-percent",
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
val.set(
|
val.set(format!("{}", calc_val(val.cloned().as_str()) / 100.0));
|
||||||
format!("{}", calc_val(val.cloned().as_str()) / 100.0)
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
"%"
|
"%"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div { class: "digit-keys",
|
div { class: "digit-keys",
|
||||||
button { class: "calculator-key key-0", onclick: move |_| input_digit(0), "0" }
|
button {
|
||||||
button { class: "calculator-key key-dot", onclick: move |_| val.write().push('.'), "●" }
|
class: "calculator-key key-0",
|
||||||
|
onclick: move |_| input_digit(0),
|
||||||
|
"0"
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
class: "calculator-key key-dot",
|
||||||
|
onclick: move |_| val.write().push('.'),
|
||||||
|
"●"
|
||||||
|
}
|
||||||
for k in 1..10 {
|
for k in 1..10 {
|
||||||
button {
|
button {
|
||||||
class: "calculator-key {k}",
|
class: "calculator-key {k}",
|
||||||
@@ -114,10 +118,26 @@ fn app() -> Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
div { class: "operator-keys",
|
div { class: "operator-keys",
|
||||||
button { class: "calculator-key key-divide", onclick: move |_| input_operator("/"), "÷" }
|
button {
|
||||||
button { class: "calculator-key key-multiply", onclick: move |_| input_operator("*"), "×" }
|
class: "calculator-key key-divide",
|
||||||
button { class: "calculator-key key-subtract", onclick: move |_| input_operator("-"), "−" }
|
onclick: move |_| input_operator("/"),
|
||||||
button { class: "calculator-key key-add", onclick: move |_| input_operator("+"), "+" }
|
"÷"
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
class: "calculator-key key-multiply",
|
||||||
|
onclick: move |_| input_operator("*"),
|
||||||
|
"×"
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
class: "calculator-key key-subtract",
|
||||||
|
onclick: move |_| input_operator("-"),
|
||||||
|
"−"
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
class: "calculator-key key-add",
|
||||||
|
onclick: move |_| input_operator("+"),
|
||||||
|
"+"
|
||||||
|
}
|
||||||
button {
|
button {
|
||||||
class: "calculator-key key-equals",
|
class: "calculator-key key-equals",
|
||||||
onclick: move |_| val.set(format!("{}", calc_val(val.cloned().as_str()))),
|
onclick: move |_| val.set(format!("{}", calc_val(val.cloned().as_str()))),
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_signals::use_signal;
|
use dioxus_signals::use_signal;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ use dioxus::prelude::*;
|
|||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::rc::Rc;
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_router::prelude::*;
|
use dioxus_router::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type alias that reprsents a shared context between components
|
/// A type alias that reprsents a shared context between components
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -5,13 +5,11 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_desktop::Config;
|
use dioxus_desktop::Config;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch_cfg(
|
LaunchBuilder::new(app).cfg(
|
||||||
app,
|
|
||||||
Config::new().with_custom_head("<style>body { background-color: red; }</style>".into()),
|
Config::new().with_custom_head("<style>body { background-color: red; }</style>".into()),
|
||||||
);
|
);
|
||||||
|
|
||||||
dioxus_desktop::launch_cfg(
|
LaunchBuilder::new(app).cfg(
|
||||||
app,
|
|
||||||
Config::new().with_custom_index(
|
Config::new().with_custom_index(
|
||||||
r#"
|
r#"
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -33,8 +31,6 @@ fn main() {
|
|||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
div { h1 { "hello world!" } }
|
||||||
h1 {"hello world!"}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_desktop::{use_asset_handler, wry::http::Response};
|
use dioxus_desktop::{use_asset_handler, wry::http::Response};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::{dioxus_core::CapturedError, prelude::*};
|
use dioxus::{dioxus_core::CapturedError, prelude::*};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_desktop::{Config, WindowBuilder};
|
use dioxus_desktop::{Config, WindowBuilder};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Config::new()
|
LaunchBuilder::new(app)
|
||||||
.with_window(WindowBuilder::new().with_resizable(true))
|
.cfg(Config::new().with_window(WindowBuilder::new().with_resizable(true)))
|
||||||
.launch(app)
|
.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
const _STYLE: &str = manganis::mg!(file("./examples/assets/fileexplorer.css"));
|
const _STYLE: &str = manganis::mg!(file("./examples/assets/fileexplorer.css"));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use dioxus::prelude::*;
|
|||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(App);
|
launch(App);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn App() -> Element {
|
fn App() -> Element {
|
||||||
|
|||||||
@@ -2,18 +2,16 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_desktop::Config;
|
use dioxus_desktop::Config;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Config::new()
|
LaunchBuilder::new(app)
|
||||||
.with_file_drop_handler(|_w, e| {
|
.cfg(Config::new().with_file_drop_handler(|_w, e| {
|
||||||
println!("{e:?}");
|
println!("{e:?}");
|
||||||
true
|
true
|
||||||
})
|
}))
|
||||||
.launch(app)
|
.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
rsx!(
|
rsx!(
|
||||||
div {
|
div { h1 { "drag a file here and check your console" } }
|
||||||
h1 { "drag a file here and check your console" }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+22
-16
@@ -5,17 +5,17 @@ use dioxus_router::prelude::*;
|
|||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
Config::new()
|
LaunchBuilder::new(|| {
|
||||||
.with_window(
|
render! { Router::<Route> {} }
|
||||||
|
})
|
||||||
|
.cfg(
|
||||||
|
Config::new().with_window(
|
||||||
WindowBuilder::new()
|
WindowBuilder::new()
|
||||||
.with_inner_size(LogicalSize::new(600, 1000))
|
.with_inner_size(LogicalSize::new(600, 1000))
|
||||||
.with_resizable(false),
|
.with_resizable(false),
|
||||||
)
|
),
|
||||||
.launch(|| {
|
)
|
||||||
render! {
|
.launch()
|
||||||
Router::<Route> {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Routable, Clone)]
|
#[derive(Routable, Clone)]
|
||||||
@@ -36,18 +36,24 @@ enum Route {
|
|||||||
fn Footer() -> Element {
|
fn Footer() -> Element {
|
||||||
render! {
|
render! {
|
||||||
div {
|
div {
|
||||||
Outlet::<Route> { }
|
Outlet::<Route> {}
|
||||||
|
|
||||||
p {
|
p { "----" }
|
||||||
"----"
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
ul {
|
ul {
|
||||||
li { Link { to: Route::Home {}, "Home" } }
|
li {
|
||||||
li { Link { to: Route::Games {}, "Games" } }
|
Link { to: Route::Home {}, "Home" }
|
||||||
li { Link { to: Route::Play {}, "Play" } }
|
}
|
||||||
li { Link { to: Route::Settings {}, "Settings" } }
|
li {
|
||||||
|
Link { to: Route::Games {}, "Games" }
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
Link { to: Route::Play {}, "Play" }
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
Link { to: Route::Settings {}, "Settings" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::fmt::Display;
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -13,15 +13,15 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_desktop::Config;
|
use dioxus_desktop::Config;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Config::new()
|
LaunchBuilder::new(app)
|
||||||
.with_prerendered({
|
.cfg(Config::new().with_prerendered({
|
||||||
// We build the dom a first time, then pre-render it to HTML
|
// We build the dom a first time, then pre-render it to HTML
|
||||||
let pre_rendered_dom = VirtualDom::prebuilt(app);
|
let pre_rendered_dom = VirtualDom::prebuilt(app);
|
||||||
|
|
||||||
// We then launch the app with the pre-rendered HTML
|
// We then launch the app with the pre-rendered HTML
|
||||||
dioxus_ssr::pre_render(&pre_rendered_dom)
|
dioxus_ssr::pre_render(&pre_rendered_dom)
|
||||||
})
|
}))
|
||||||
.launch(app);
|
.launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FIELDS: &[(&str, &str)] = &[
|
const FIELDS: &[(&str, &str)] = &[
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_router::prelude::*;
|
use dioxus_router::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(App);
|
launch(App);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -49,8 +49,7 @@ pub fn main() -> Result<()> {
|
|||||||
|
|
||||||
// Right now we're going through dioxus-desktop but we'd like to go through dioxus-mobile
|
// Right now we're going through dioxus-desktop but we'd like to go through dioxus-mobile
|
||||||
// That will seed the index.html with some fixes that prevent the page from scrolling/zooming etc
|
// That will seed the index.html with some fixes that prevent the page from scrolling/zooming etc
|
||||||
dioxus_desktop::launch_cfg(
|
LaunchBuilder::new(app).cfg(
|
||||||
app,
|
|
||||||
// Note that we have to disable the viewport goofiness of the browser.
|
// Note that we have to disable the viewport goofiness of the browser.
|
||||||
// Dioxus_mobile should do this for us
|
// Dioxus_mobile should do this for us
|
||||||
Config::default().with_custom_index(include_str!("index.html").to_string()),
|
Config::default().with_custom_index(include_str!("index.html").to_string()),
|
||||||
@@ -66,10 +65,15 @@ fn app() -> Element {
|
|||||||
|
|
||||||
render! {
|
render! {
|
||||||
div {
|
div {
|
||||||
h1 { "Hello, Mobile"}
|
h1 { "Hello, Mobile" }
|
||||||
div { margin_left: "auto", margin_right: "auto", width: "200px", padding: "10px", border: "1px solid black",
|
div {
|
||||||
|
margin_left: "auto",
|
||||||
|
margin_right: "auto",
|
||||||
|
width: "200px",
|
||||||
|
padding: "10px",
|
||||||
|
border: "1px solid black",
|
||||||
button {
|
button {
|
||||||
onclick: move|_| {
|
onclick: move |_| {
|
||||||
println!("Clicked!");
|
println!("Clicked!");
|
||||||
items.push(items.len());
|
items.push(items.len());
|
||||||
cx.needs_update_any(ScopeId::ROOT);
|
cx.needs_update_any(ScopeId::ROOT);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -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() {
|
||||||
dioxus_desktop::launch_cfg(app, make_config());
|
LaunchBuilder::new(app).cfg(make_config());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ fn main() {
|
|||||||
.with_inner_size(LogicalSize::new(320.0, 530.0)),
|
.with_inner_size(LogicalSize::new(320.0, 530.0)),
|
||||||
);
|
);
|
||||||
|
|
||||||
dioxus_desktop::launch_cfg(app, cfg);
|
LaunchBuilder::new(app).cfg(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const STYLE: &str = include_str!("./assets/calculator.css");
|
const STYLE: &str = include_str!("./assets/calculator.css");
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ use std::rc::Rc;
|
|||||||
use dioxus::{html::geometry::euclid::Rect, prelude::*};
|
use dioxus::{html::geometry::euclid::Rect, prelude::*};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch_cfg(
|
LaunchBuilder::new(app).cfg(
|
||||||
app,
|
|
||||||
dioxus_desktop::Config::default().with_custom_head(
|
dioxus_desktop::Config::default().with_custom_head(
|
||||||
r#"
|
r#"
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@@ -48,9 +47,6 @@ fn app() -> Element {
|
|||||||
"This element is {dimensions():?}"
|
"This element is {dimensions():?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button { onclick: read_dims, "Read dimensions" }
|
||||||
onclick: read_dims,
|
|
||||||
"Read dimensions"
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ fn main() {
|
|||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
dioxus_web::launch(App);
|
dioxus_web::launch(App);
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
dioxus_desktop::launch(App);
|
launch(App);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANCHOR: router
|
// ANCHOR: router
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
todo!()
|
todo!()
|
||||||
// dioxus_desktop::launch(App);
|
// launch(App);
|
||||||
}
|
}
|
||||||
|
|
||||||
// use core::{fmt, str::FromStr};
|
// use core::{fmt, str::FromStr};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_desktop::use_global_shortcut;
|
use dioxus_desktop::use_global_shortcut;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ fn main() {
|
|||||||
.with_module_level("dioxus", log::LevelFilter::Trace)
|
.with_module_level("dioxus", log::LevelFilter::Trace)
|
||||||
.init()
|
.init()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
dioxus_desktop::launch(App);
|
launch(App);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -38,5 +38,5 @@ fn Nav() -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(|| render!(Router::<Route> {}));
|
launch(|| render!(Router::<Route> {}));
|
||||||
}
|
}
|
||||||
+1
-1
@@ -4,7 +4,7 @@ use futures_util::{future, stream, Stream, StreamExt};
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+12
-19
@@ -17,19 +17,21 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_desktop::{Config, LogicalSize, WindowBuilder};
|
use dioxus_desktop::{Config, LogicalSize, WindowBuilder};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Config::new()
|
LaunchBuilder::new(app)
|
||||||
.with_window(
|
.cfg(
|
||||||
WindowBuilder::new()
|
Config::new().with_window(
|
||||||
.with_title("Doggo Fetcher")
|
WindowBuilder::new()
|
||||||
.with_inner_size(LogicalSize::new(600.0, 800.0)),
|
.with_title("Doggo Fetcher")
|
||||||
|
.with_inner_size(LogicalSize::new(600.0, 800.0)),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.launch(app)
|
.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
div {
|
||||||
h1 {"Dogs are very important"}
|
h1 { "Dogs are very important" }
|
||||||
p {
|
p {
|
||||||
"The dog or domestic dog (Canis familiaris[4][5] or Canis lupus familiaris[5])"
|
"The dog or domestic dog (Canis familiaris[4][5] or Canis lupus familiaris[5])"
|
||||||
"is a domesticated descendant of the wolf which is characterized by an upturning tail."
|
"is a domesticated descendant of the wolf which is characterized by an upturning tail."
|
||||||
@@ -39,7 +41,7 @@ fn app() -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h3 { "Illustrious Dog Photo" }
|
h3 { "Illustrious Dog Photo" }
|
||||||
Doggo { }
|
Doggo {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,17 +65,8 @@ fn Doggo() -> Element {
|
|||||||
|
|
||||||
match fut.value().read().as_ref() {
|
match fut.value().read().as_ref() {
|
||||||
Some(Ok(resp)) => rsx! {
|
Some(Ok(resp)) => rsx! {
|
||||||
button {
|
button { onclick: move |_| fut.restart(), "Click to fetch another doggo" }
|
||||||
onclick: move |_| fut.restart(),
|
div { img { max_width: "500px", max_height: "500px", src: "{resp.message}" } }
|
||||||
"Click to fetch another doggo"
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
img {
|
|
||||||
max_width: "500px",
|
|
||||||
max_height: "500px",
|
|
||||||
src: "{resp.message}",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Some(Err(_)) => rsx! { div { "loading dogs failed" } },
|
Some(Err(_)) => rsx! { div { "loading dogs failed" } },
|
||||||
None => rsx! { div { "loading dogs..." } },
|
None => rsx! { div { "loading dogs..." } },
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ use dioxus::prelude::*;
|
|||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -79,5 +79,5 @@ fn app() -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ const _STYLE: &str = manganis::mg!(file("./public/tailwind.css"));
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
dioxus_web::launch(app);
|
dioxus_web::launch(app);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ use dioxus::prelude::*;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ use dioxus_elements::input_data::keyboard_types::Key;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
+18
-13
@@ -2,13 +2,15 @@ use dioxus::prelude::*;
|
|||||||
use dioxus_desktop::{window, Config, WindowBuilder};
|
use dioxus_desktop::{window, Config, WindowBuilder};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Config::new()
|
LaunchBuilder::new(app)
|
||||||
.with_window(
|
.cfg(
|
||||||
WindowBuilder::new()
|
Config::new().with_window(
|
||||||
.with_title("Borderless Window")
|
WindowBuilder::new()
|
||||||
.with_decorations(false),
|
.with_title("Borderless Window")
|
||||||
|
.with_decorations(false),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.launch(app)
|
.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
@@ -17,11 +19,16 @@ fn app() -> Element {
|
|||||||
let mut decorations = use_signal(|| false);
|
let mut decorations = use_signal(|| false);
|
||||||
|
|
||||||
rsx!(
|
rsx!(
|
||||||
link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css", rel:"stylesheet" }
|
link {
|
||||||
header { class: "text-gray-400 bg-gray-900 body-font", onmousedown: move |_| window().drag(),
|
href: "https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css",
|
||||||
|
rel: "stylesheet"
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
class: "text-gray-400 bg-gray-900 body-font",
|
||||||
|
onmousedown: move |_| window().drag(),
|
||||||
div { class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
|
div { class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
|
||||||
a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0",
|
a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0",
|
||||||
span { class: "ml-3 text-xl", "Dioxus"}
|
span { class: "ml-3 text-xl", "Dioxus" }
|
||||||
}
|
}
|
||||||
nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center" }
|
nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center" }
|
||||||
button {
|
button {
|
||||||
@@ -49,10 +56,8 @@ fn app() -> Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
br {}
|
br {}
|
||||||
div {
|
div { class: "container mx-auto",
|
||||||
class: "container mx-auto",
|
div { class: "grid grid-cols-5",
|
||||||
div {
|
|
||||||
class: "grid grid-cols-5",
|
|
||||||
div {
|
div {
|
||||||
button {
|
button {
|
||||||
class: "inline-flex items-center text-white bg-green-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
|
class: "inline-flex items-center text-white bg-green-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ use dioxus_desktop::use_wry_event_handler;
|
|||||||
use dioxus_desktop::{Config, WindowCloseBehaviour};
|
use dioxus_desktop::{Config, WindowCloseBehaviour};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Config::new()
|
LaunchBuilder::new(app)
|
||||||
.with_close_behaviour(WindowCloseBehaviour::CloseWindow)
|
.cfg(Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow))
|
||||||
.launch(app)
|
.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
@@ -22,12 +22,7 @@ fn app() -> Element {
|
|||||||
});
|
});
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
div { width: "100%", height: "100%", display: "flex", flex_direction: "column", align_items: "center",
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
display: "flex",
|
|
||||||
flex_direction: "column",
|
|
||||||
align_items: "center",
|
|
||||||
if focused() {
|
if focused() {
|
||||||
"This window is focused!"
|
"This window is focused!"
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(app);
|
launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ mod fragment;
|
|||||||
mod global_context;
|
mod global_context;
|
||||||
mod mutations;
|
mod mutations;
|
||||||
mod nodes;
|
mod nodes;
|
||||||
|
mod platform;
|
||||||
mod properties;
|
mod properties;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
mod scheduler;
|
mod scheduler;
|
||||||
@@ -30,6 +31,7 @@ pub(crate) mod innerlude {
|
|||||||
pub use crate::global_context::*;
|
pub use crate::global_context::*;
|
||||||
pub use crate::mutations::*;
|
pub use crate::mutations::*;
|
||||||
pub use crate::nodes::*;
|
pub use crate::nodes::*;
|
||||||
|
pub use crate::platform::*;
|
||||||
pub use crate::properties::*;
|
pub use crate::properties::*;
|
||||||
pub use crate::runtime::{Runtime, RuntimeGuard};
|
pub use crate::runtime::{Runtime, RuntimeGuard};
|
||||||
pub use crate::scheduler::*;
|
pub use crate::scheduler::*;
|
||||||
@@ -73,11 +75,11 @@ pub(crate) mod innerlude {
|
|||||||
|
|
||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
fc_to_builder, generation, schedule_update, schedule_update_any, use_hook, vdom_is_rendering,
|
fc_to_builder, generation, schedule_update, schedule_update_any, use_hook, vdom_is_rendering,
|
||||||
AnyValue, Attribute, AttributeValue, CapturedError, Component, ComponentFunction, DynamicNode,
|
AnyValue, Attribute, AttributeValue, BoxedContext, CapturedError, Component, ComponentFunction,
|
||||||
Element, ElementId, Event, Fragment, HasAttributes, IntoDynNode, Mutation, Mutations,
|
CrossPlatformConfig, DynamicNode, Element, ElementId, Event, Fragment, HasAttributes,
|
||||||
NoOpMutations, Properties, RenderReturn, ScopeId, ScopeState, Task, Template,
|
IntoDynNode, Mutation, Mutations, NoOpMutations, PlatformBuilder, Properties, RenderReturn,
|
||||||
TemplateAttribute, TemplateNode, VComponent, VNode, VNodeInner, VPlaceholder, VText,
|
ScopeId, ScopeState, Task, Template, TemplateAttribute, TemplateNode, VComponent, VNode,
|
||||||
VirtualDom, WriteMutations,
|
VNodeInner, VPlaceholder, VText, VirtualDom, WriteMutations,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The purpose of this module is to alleviate imports of many common types
|
/// The purpose of this module is to alleviate imports of many common types
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
use std::{any::Any, marker::PhantomData};
|
||||||
|
|
||||||
|
use crate::{ComponentFunction, VirtualDom};
|
||||||
|
|
||||||
|
/// A boxed object that can be injected into a component's context.
|
||||||
|
pub struct BoxedContext(Box<dyn ClonableAny>);
|
||||||
|
|
||||||
|
impl BoxedContext {
|
||||||
|
/// Create a new boxed context.
|
||||||
|
pub fn new(value: impl Any + Clone + 'static) -> Self {
|
||||||
|
Self(Box::new(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unwrap the boxed context into its inner value.
|
||||||
|
pub fn into_inner(self) -> Box<dyn Any> {
|
||||||
|
self.0.into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for BoxedContext {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(self.0.clone_box())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ClonableAny: Any {
|
||||||
|
fn clone_box(&self) -> Box<dyn ClonableAny>;
|
||||||
|
|
||||||
|
fn into_inner(self: Box<Self>) -> Box<dyn Any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Any + Clone> ClonableAny for T {
|
||||||
|
fn clone_box(&self) -> Box<dyn ClonableAny> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self: Box<Self>) -> Box<dyn Any> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The platform-independent part of the config needed to launch an application.
|
||||||
|
pub struct CrossPlatformConfig<
|
||||||
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
|
Props: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
> {
|
||||||
|
/// The root component function.
|
||||||
|
pub component: Component,
|
||||||
|
/// The props for the root component.
|
||||||
|
pub props: Props,
|
||||||
|
/// The contexts to provide to the root component.
|
||||||
|
pub root_contexts: Vec<BoxedContext>,
|
||||||
|
_phantom: PhantomData<Phantom>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
|
Props: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
> CrossPlatformConfig<Component, Props, Phantom>
|
||||||
|
{
|
||||||
|
/// Create a new cross-platform config.
|
||||||
|
pub fn new(component: Component, props: Props, root_contexts: Vec<BoxedContext>) -> Self {
|
||||||
|
Self {
|
||||||
|
component,
|
||||||
|
props,
|
||||||
|
root_contexts,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build a virtual dom from the config.
|
||||||
|
pub fn build_vdom(self) -> VirtualDom {
|
||||||
|
let mut vdom = VirtualDom::new_with_props(self.component, self.props);
|
||||||
|
|
||||||
|
for context in self.root_contexts {
|
||||||
|
vdom.insert_boxed_root_context(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
vdom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A builder to launch a specific platform.
|
||||||
|
pub trait PlatformBuilder<Props: Clone + 'static> {
|
||||||
|
/// The platform-specific config needed to launch an application.
|
||||||
|
type Config: Default;
|
||||||
|
|
||||||
|
/// Launch the app.
|
||||||
|
fn launch<Component: ComponentFunction<Phantom, Props = Props>, Phantom: 'static>(
|
||||||
|
config: CrossPlatformConfig<Component, Props, Phantom>,
|
||||||
|
platform_config: Self::Config,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Props: Clone + 'static> PlatformBuilder<Props> for () {
|
||||||
|
type Config = ();
|
||||||
|
|
||||||
|
fn launch<Component: ComponentFunction<Phantom, Props = Props>, Phantom: 'static>(
|
||||||
|
_: CrossPlatformConfig<Component, Props, Phantom>,
|
||||||
|
_: Self::Config,
|
||||||
|
) {
|
||||||
|
panic!("No platform is currently enabled. Please enable a platform feature for the dioxus crate.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -309,12 +309,11 @@ impl ScopeContext {
|
|||||||
impl Drop for ScopeContext {
|
impl Drop for ScopeContext {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Drop all spawned tasks
|
// Drop all spawned tasks
|
||||||
with_runtime(|rt| {
|
_ = with_runtime(|rt| {
|
||||||
for id in self.spawned_tasks.borrow().iter() {
|
for id in self.spawned_tasks.borrow().iter() {
|
||||||
rt.remove_task(*id);
|
rt.remove_task(*id);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.expect("Runtime to exist")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ impl VirtualDom {
|
|||||||
///
|
///
|
||||||
/// Note: the VirtualDom is not progressed, you must either "run_with_deadline" or use "rebuild" to progress it.
|
/// Note: the VirtualDom is not progressed, you must either "run_with_deadline" or use "rebuild" to progress it.
|
||||||
pub fn new(app: fn() -> Element) -> Self {
|
pub fn new(app: fn() -> Element) -> Self {
|
||||||
Self::new_with_props(|app| app(), app)
|
Self::new_with_props(app, ())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new virtualdom and build it immediately
|
/// Create a new virtualdom and build it immediately
|
||||||
@@ -267,7 +267,14 @@ impl VirtualDom {
|
|||||||
/// let mut dom = VirtualDom::new_with_props(Example, SomeProps { name: "jane" });
|
/// let mut dom = VirtualDom::new_with_props(Example, SomeProps { name: "jane" });
|
||||||
/// let mutations = dom.rebuild();
|
/// let mutations = dom.rebuild();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new_with_props<P: Clone + 'static>(root: fn(P) -> Element, root_props: P) -> Self {
|
pub fn new_with_props<
|
||||||
|
F: crate::ComponentFunction<Phantom, Props = P>,
|
||||||
|
P: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
>(
|
||||||
|
root: F,
|
||||||
|
root_props: P,
|
||||||
|
) -> Self {
|
||||||
let (tx, rx) = futures_channel::mpsc::unbounded();
|
let (tx, rx) = futures_channel::mpsc::unbounded();
|
||||||
|
|
||||||
let mut dom = Self {
|
let mut dom = Self {
|
||||||
@@ -328,11 +335,10 @@ impl VirtualDom {
|
|||||||
/// Build the virtualdom with a global context inserted into the base scope
|
/// Build the virtualdom with a global context inserted into the base scope
|
||||||
///
|
///
|
||||||
/// This method is useful for when you want to provide a context in your app without knowing its type
|
/// This method is useful for when you want to provide a context in your app without knowing its type
|
||||||
pub fn with_boxed_root_context(self, context: BoxedContext) -> Self {
|
pub fn insert_boxed_root_context(&mut self, context: BoxedContext) {
|
||||||
self.base_scope()
|
self.base_scope()
|
||||||
.context()
|
.context()
|
||||||
.provide_any_context(context.into_inner());
|
.provide_any_context(context.into_inner());
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Manually mark a scope as requiring a re-render
|
/// Manually mark a scope as requiring a re-render
|
||||||
|
|||||||
+24
-14
@@ -10,7 +10,7 @@ use crate::{
|
|||||||
webview::WebviewInstance,
|
webview::WebviewInstance,
|
||||||
};
|
};
|
||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
use dioxus_core::{Component, ElementId, VirtualDom};
|
use dioxus_core::{ComponentFunction, CrossPlatformConfig, ElementId};
|
||||||
use dioxus_html::{
|
use dioxus_html::{
|
||||||
native_bind::NativeFileEngine, FileEngine, HasFileData, HasFormData, HtmlEvent,
|
native_bind::NativeFileEngine, FileEngine, HasFileData, HasFormData, HtmlEvent,
|
||||||
PlatformEventData,
|
PlatformEventData,
|
||||||
@@ -18,6 +18,7 @@ use dioxus_html::{
|
|||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
marker::PhantomData,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
@@ -28,14 +29,17 @@ use tao::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// The single top-level object that manages all the running windows, assets, shortcuts, etc
|
/// The single top-level object that manages all the running windows, assets, shortcuts, etc
|
||||||
pub(crate) struct App<P> {
|
pub(crate) struct App<
|
||||||
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
|
Props: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
> {
|
||||||
// move the props into a cell so we can pop it out later to create the first window
|
// move the props into a cell so we can pop it out later to create the first window
|
||||||
// iOS panics if we create a window before the event loop is started, so we toss them into a cell
|
// iOS panics if we create a window before the event loop is started, so we toss them into a cell
|
||||||
pub(crate) props: Cell<Option<P>>,
|
pub(crate) dioxus_config: Cell<Option<CrossPlatformConfig<Component, Props, Phantom>>>,
|
||||||
pub(crate) cfg: Cell<Option<Config>>,
|
pub(crate) cfg: Cell<Option<Config>>,
|
||||||
|
|
||||||
// Stuff we need mutable access to
|
// Stuff we need mutable access to
|
||||||
pub(crate) root: Component<P>,
|
|
||||||
pub(crate) control_flow: ControlFlow,
|
pub(crate) control_flow: ControlFlow,
|
||||||
pub(crate) is_visible_before_start: bool,
|
pub(crate) is_visible_before_start: bool,
|
||||||
pub(crate) window_behavior: WindowCloseBehaviour,
|
pub(crate) window_behavior: WindowCloseBehaviour,
|
||||||
@@ -45,6 +49,8 @@ pub(crate) struct App<P> {
|
|||||||
///
|
///
|
||||||
/// This includes stuff like the event handlers, shortcuts, etc as well as ways to modify *other* windows
|
/// This includes stuff like the event handlers, shortcuts, etc as well as ways to modify *other* windows
|
||||||
pub(crate) shared: Rc<SharedContext>,
|
pub(crate) shared: Rc<SharedContext>,
|
||||||
|
|
||||||
|
phantom: PhantomData<Phantom>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A bundle of state shared between all the windows, providing a way for us to communicate with running webview.
|
/// A bundle of state shared between all the windows, providing a way for us to communicate with running webview.
|
||||||
@@ -59,17 +65,24 @@ pub struct SharedContext {
|
|||||||
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
|
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: 'static + Clone> App<P> {
|
impl<
|
||||||
pub fn new(cfg: Config, props: P, root: Component<P>) -> (EventLoop<UserWindowEvent>, Self) {
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
|
Props: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
> App<Component, Props, Phantom>
|
||||||
|
{
|
||||||
|
pub fn new(
|
||||||
|
cfg: Config,
|
||||||
|
dioxus_config: CrossPlatformConfig<Component, Props, Phantom>,
|
||||||
|
) -> (EventLoop<UserWindowEvent>, Self) {
|
||||||
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
||||||
|
|
||||||
let app = Self {
|
let app = Self {
|
||||||
root,
|
|
||||||
window_behavior: cfg.last_window_close_behaviour,
|
window_behavior: cfg.last_window_close_behaviour,
|
||||||
is_visible_before_start: true,
|
is_visible_before_start: true,
|
||||||
webviews: HashMap::new(),
|
webviews: HashMap::new(),
|
||||||
control_flow: ControlFlow::Wait,
|
control_flow: ControlFlow::Wait,
|
||||||
props: Cell::new(Some(props)),
|
dioxus_config: Cell::new(Some(dioxus_config)),
|
||||||
cfg: Cell::new(Some(cfg)),
|
cfg: Cell::new(Some(cfg)),
|
||||||
shared: Rc::new(SharedContext {
|
shared: Rc::new(SharedContext {
|
||||||
event_handlers: WindowEventHandlers::default(),
|
event_handlers: WindowEventHandlers::default(),
|
||||||
@@ -79,6 +92,7 @@ impl<P: 'static + Clone> App<P> {
|
|||||||
proxy: event_loop.create_proxy(),
|
proxy: event_loop.create_proxy(),
|
||||||
target: event_loop.clone(),
|
target: event_loop.clone(),
|
||||||
}),
|
}),
|
||||||
|
phantom: PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the event converter
|
// Set the event converter
|
||||||
@@ -164,16 +178,12 @@ impl<P: 'static + Clone> App<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_start_cause_init(&mut self) {
|
pub fn handle_start_cause_init(&mut self) {
|
||||||
let props = self.props.take().unwrap();
|
let dioxus_config = self.dioxus_config.take().unwrap();
|
||||||
let cfg = self.cfg.take().unwrap();
|
let cfg = self.cfg.take().unwrap();
|
||||||
|
|
||||||
self.is_visible_before_start = cfg.window.window.visible;
|
self.is_visible_before_start = cfg.window.window.visible;
|
||||||
|
|
||||||
let webview = WebviewInstance::new(
|
let webview = WebviewInstance::new(cfg, dioxus_config.build_vdom(), self.shared.clone());
|
||||||
cfg,
|
|
||||||
VirtualDom::new_with_props(self.root, props),
|
|
||||||
self.shared.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let id = webview.desktop_context.window.id();
|
let id = webview.desktop_context.window.id();
|
||||||
self.webviews.insert(id, webview);
|
self.webviews.insert(id, webview);
|
||||||
|
|||||||
@@ -71,20 +71,6 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Launch a Dioxus app using the given component and config
|
|
||||||
///
|
|
||||||
/// See the [`crate::launch::launch`] function for more details.
|
|
||||||
pub fn launch(self, app: fn() -> Element) {
|
|
||||||
self.launch_with_props(|props| props(), app)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Launch a Dioxus app using the given component, config, and props
|
|
||||||
///
|
|
||||||
/// See the [`crate::launch::launch_with_props`] function for more details.
|
|
||||||
pub fn launch_with_props<P: 'static + Clone>(self, root: Component<P>, props: P) {
|
|
||||||
crate::launch::launch_with_props(root, props, self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether the default menu bar should be enabled.
|
/// Set whether the default menu bar should be enabled.
|
||||||
///
|
///
|
||||||
/// > Note: `enable` is `true` by default. To disable the default menu bar pass `false`.
|
/// > Note: `enable` is `true` by default. To disable the default menu bar pass `false`.
|
||||||
|
|||||||
@@ -6,96 +6,19 @@ use crate::{
|
|||||||
use dioxus_core::*;
|
use dioxus_core::*;
|
||||||
use tao::event::{Event, StartCause, WindowEvent};
|
use tao::event::{Event, StartCause, WindowEvent};
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop.
|
|
||||||
///
|
|
||||||
/// This function will start a multithreaded Tokio runtime as well the WebView event loop.
|
|
||||||
///
|
|
||||||
/// ```rust, no_run
|
|
||||||
/// use dioxus::prelude::*;
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// dioxus_desktop::launch(app);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn app() -> Element {
|
|
||||||
/// rsx!{
|
|
||||||
/// h1 {"hello world!"}
|
|
||||||
/// })
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn launch(app: fn() -> Element) {
|
|
||||||
launch_with_props(|root| root(), app, Config::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop, with configuration.
|
|
||||||
///
|
|
||||||
/// This function will start a multithreaded Tokio runtime as well the WebView event loop.
|
|
||||||
///
|
|
||||||
/// You can configure the WebView window with a configuration closure
|
|
||||||
///
|
|
||||||
/// ```rust, no_run
|
|
||||||
/// use dioxus::prelude::*;
|
|
||||||
/// use dioxus_desktop::*;
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// dioxus_desktop::launch_cfg(app, Config::default().with_window(WindowBuilder::new().with_title("My App")));
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn app() -> Element {
|
|
||||||
/// rsx!{
|
|
||||||
/// h1 {"hello world!"}
|
|
||||||
/// })
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn launch_cfg(app: fn() -> Element, config_builder: Config) {
|
|
||||||
launch_with_props(|props| props(), app, config_builder)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop, with configuration and root props.
|
|
||||||
///
|
|
||||||
/// If the [`tokio`] feature is enabled, this will also startup and block a tokio runtime using the unconstrained task.
|
|
||||||
/// This function will start a multithreaded Tokio runtime as well the WebView event loop. This will block the current thread.
|
|
||||||
///
|
|
||||||
/// You can configure the WebView window with a configuration closure
|
|
||||||
///
|
|
||||||
/// ```rust, no_run
|
|
||||||
/// use dioxus::prelude::*;
|
|
||||||
/// use dioxus_desktop::Config;
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// dioxus_desktop::launch_with_props(app, AppProps { name: "asd" }, Config::default());
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// struct AppProps {
|
|
||||||
/// name: &'static str
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn app(cx: Scope<AppProps>) -> Element {
|
|
||||||
/// rsx!{
|
|
||||||
/// h1 {"hello {cx.props.name}!"}
|
|
||||||
/// })
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn launch_with_props<P: 'static + Clone>(root: Component<P>, props: P, cfg: Config) {
|
|
||||||
#[cfg(feature = "tokio")]
|
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
.block_on(tokio::task::unconstrained(async move {
|
|
||||||
launch_with_props_blocking(root, props, cfg);
|
|
||||||
}));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "tokio"))]
|
|
||||||
launch_with_props_blocking(root, props, cfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop, with configuration and root props.
|
/// Launch the WebView and run the event loop, with configuration and root props.
|
||||||
///
|
///
|
||||||
/// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
|
/// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
|
||||||
/// and is equivalent to calling launch_with_props with the tokio feature disabled.
|
/// and is equivalent to calling launch_with_props with the tokio feature disabled.
|
||||||
pub fn launch_with_props_blocking<P: 'static + Clone>(root: Component<P>, props: P, cfg: Config) {
|
pub fn launch_with_props_blocking<
|
||||||
let (event_loop, mut app) = App::new(cfg, props, root);
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
|
Props: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
>(
|
||||||
|
dioxus_cfg: CrossPlatformConfig<Component, Props, Phantom>,
|
||||||
|
desktop_config: Config,
|
||||||
|
) {
|
||||||
|
let (event_loop, mut app) = App::new(desktop_config, dioxus_cfg);
|
||||||
|
|
||||||
event_loop.run(move |window_event, _, control_flow| {
|
event_loop.run(move |window_event, _, control_flow| {
|
||||||
app.tick(&window_event);
|
app.tick(&window_event);
|
||||||
@@ -130,3 +53,27 @@ pub fn launch_with_props_blocking<P: 'static + Clone>(root: Component<P>, props:
|
|||||||
*control_flow = app.control_flow;
|
*control_flow = app.control_flow;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The desktop renderer platform
|
||||||
|
pub struct DesktopPlatform;
|
||||||
|
|
||||||
|
impl<Props: Clone + 'static> PlatformBuilder<Props> for DesktopPlatform {
|
||||||
|
type Config = Config;
|
||||||
|
|
||||||
|
fn launch<Component: ComponentFunction<Phantom, Props = Props>, Phantom: 'static>(
|
||||||
|
config: dioxus_core::CrossPlatformConfig<Component, Props, Phantom>,
|
||||||
|
platform_config: Self::Config,
|
||||||
|
) {
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.block_on(tokio::task::unconstrained(async move {
|
||||||
|
launch_with_props_blocking(config, platform_config)
|
||||||
|
}));
|
||||||
|
|
||||||
|
#[cfg(not(feature = "tokio"))]
|
||||||
|
launch_with_props_blocking(config, platform_config)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,98 +5,104 @@ use std::any::Any;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
use dioxus_core::ComponentFunction;
|
use dioxus_core::ComponentFunction;
|
||||||
|
use dioxus_core::{BoxedContext, CrossPlatformConfig, PlatformBuilder};
|
||||||
pub trait ClonableAny: Any {
|
|
||||||
fn clone_box(&self) -> Box<dyn ClonableAny>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Any + Clone> ClonableAny for T {
|
|
||||||
fn clone_box(&self) -> Box<dyn ClonableAny> {
|
|
||||||
Box::new(self.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The platform-independent part of the config needed to launch an application.
|
|
||||||
pub struct CrossPlatformConfig<F: ComponentFunction<P>, P> {
|
|
||||||
/// The root component function.
|
|
||||||
pub component: F,
|
|
||||||
/// The props for the root component.
|
|
||||||
pub props: P,
|
|
||||||
/// The contexts to provide to the root component.
|
|
||||||
pub root_contexts: Vec<Box<dyn ClonableAny>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait PlatformBuilder<P> {
|
|
||||||
type Config;
|
|
||||||
|
|
||||||
/// Launch the app.
|
|
||||||
fn launch<F: ComponentFunction<P>>(config: CrossPlatformConfig<F, P>, config: Self::Config);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> PlatformBuilder<P> for () {
|
|
||||||
type Config = ();
|
|
||||||
|
|
||||||
fn launch<F: ComponentFunction<P>>(config: CrossPlatformConfig<F, P>, _: ()) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A builder for a fullstack app.
|
/// A builder for a fullstack app.
|
||||||
pub struct LaunchBuilder<F: ComponentFunction<P>, P> {
|
pub struct LaunchBuilder<
|
||||||
cross_platform_config: CrossPlatformConfig<F, P>,
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
|
Props: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
> {
|
||||||
|
cross_platform_config: CrossPlatformConfig<Component, Props, Phantom>,
|
||||||
|
platform_config: Option<<CurrentPlatform as PlatformBuilder<Props>>::Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ComponentFunction<P>, P> LaunchBuilder<F, P> {
|
impl<
|
||||||
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
|
Props: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
> LaunchBuilder<Component, Props, Phantom>
|
||||||
|
{
|
||||||
/// Create a new builder for your application.
|
/// Create a new builder for your application.
|
||||||
pub fn new(component: F) -> Self
|
pub fn new(component: Component) -> Self
|
||||||
where
|
where
|
||||||
P: Default,
|
Props: Default,
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
cross_platform_config: CrossPlatformConfig {
|
cross_platform_config: CrossPlatformConfig::new(
|
||||||
component,
|
component,
|
||||||
props: Default::default(),
|
Default::default(),
|
||||||
root_contexts: vec![],
|
Default::default(),
|
||||||
},
|
),
|
||||||
|
platform_config: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pass some props to your application.
|
/// Pass some props to your application.
|
||||||
pub fn props(mut self, props: P) -> Self {
|
pub fn props(mut self, props: Props) -> Self {
|
||||||
self.cross_platform_config.props = props;
|
self.cross_platform_config.props = props;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inject state into the root component's context.
|
/// Inject state into the root component's context.
|
||||||
pub fn context(mut self, state: impl ClonableAny + 'static) -> Self {
|
pub fn context(mut self, state: impl Any + Clone + 'static) -> Self {
|
||||||
self.cross_platform_config
|
self.cross_platform_config
|
||||||
.root_contexts
|
.root_contexts
|
||||||
.push(Box::new(state));
|
.push(BoxedContext::new(state));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provide a platform-specific config to the builder.
|
/// Provide a platform-specific config to the builder.
|
||||||
pub fn platform_config(
|
pub fn cfg(
|
||||||
self,
|
mut self,
|
||||||
config: Option<<CurrentPlatform as PlatformBuilder<P>>::Config>,
|
config: impl Into<Option<<CurrentPlatform as PlatformBuilder<Props>>::Config>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
if let Some(config) = config.into() {
|
||||||
|
self.platform_config = Some(config);
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unit_arg)]
|
||||||
/// Launch the app.
|
/// Launch the app.
|
||||||
pub fn launch(self) {}
|
pub fn launch(self) {
|
||||||
}
|
CurrentPlatform::launch(
|
||||||
|
self.cross_platform_config,
|
||||||
#[cfg(feature = "router")]
|
self.platform_config.unwrap_or_default(),
|
||||||
impl<R: Routable> LaunchBuilder<crate::router::FullstackRouterConfig<R>>
|
);
|
||||||
where
|
|
||||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
|
||||||
R: Clone + serde::Serialize + serde::de::DeserializeOwned + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
/// Create a new launch builder for the given router.
|
|
||||||
pub fn router() -> Self {
|
|
||||||
let component = crate::router::RouteWithCfg::<R>;
|
|
||||||
let props = crate::router::FullstackRouterConfig::default();
|
|
||||||
Self::new_with_props(component, props)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[cfg(feature = "router")]
|
||||||
|
// impl<R: Routable> LaunchBuilder<crate::router::FullstackRouterConfig<R>>
|
||||||
|
// where
|
||||||
|
// <R as std::str::FromStr>::Err: std::fmt::Display,
|
||||||
|
// R: Clone + serde::Serialize + serde::de::DeserializeOwned + Send + Sync + 'static,
|
||||||
|
// {
|
||||||
|
// /// Create a new launch builder for the given router.
|
||||||
|
// pub fn router() -> Self {
|
||||||
|
// let component = crate::router::RouteWithCfg::<R>;
|
||||||
|
// let props = crate::router::FullstackRouterConfig::default();
|
||||||
|
// Self::new_with_props(component, props)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[cfg(feature = "desktop")]
|
||||||
|
type CurrentPlatform = dioxus_desktop::DesktopPlatform;
|
||||||
|
#[cfg(feature = "web")]
|
||||||
|
type CurrentPlatform = dioxus_web::WebPlatform;
|
||||||
|
#[cfg(not(any(feature = "desktop", feature = "web")))]
|
||||||
type CurrentPlatform = ();
|
type CurrentPlatform = ();
|
||||||
|
|
||||||
|
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||||
|
pub fn launch<
|
||||||
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
|
Props: Clone + 'static,
|
||||||
|
Phantom: 'static,
|
||||||
|
>(
|
||||||
|
component: Component,
|
||||||
|
) where
|
||||||
|
Props: Default,
|
||||||
|
{
|
||||||
|
LaunchBuilder::new(component).launch()
|
||||||
|
}
|
||||||
@@ -6,8 +6,6 @@ pub use dioxus_core;
|
|||||||
|
|
||||||
#[cfg(feature = "launch")]
|
#[cfg(feature = "launch")]
|
||||||
mod launch;
|
mod launch;
|
||||||
#[cfg(feature = "launch")]
|
|
||||||
pub use launch::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "hooks")]
|
#[cfg(feature = "hooks")]
|
||||||
pub use dioxus_hooks as hooks;
|
pub use dioxus_hooks as hooks;
|
||||||
@@ -30,6 +28,9 @@ pub use dioxus_rsx as rsx;
|
|||||||
pub use dioxus_core_macro as core_macro;
|
pub use dioxus_core_macro as core_macro;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
#[cfg(feature = "launch")]
|
||||||
|
pub use crate::launch::*;
|
||||||
|
|
||||||
#[cfg(feature = "hooks")]
|
#[cfg(feature = "hooks")]
|
||||||
pub use crate::hooks::*;
|
pub use crate::hooks::*;
|
||||||
|
|
||||||
|
|||||||
+13
-91
@@ -60,7 +60,7 @@ use std::rc::Rc;
|
|||||||
pub use crate::cfg::Config;
|
pub use crate::cfg::Config;
|
||||||
#[cfg(feature = "file_engine")]
|
#[cfg(feature = "file_engine")]
|
||||||
pub use crate::file_engine::WebFileEngineExt;
|
pub use crate::file_engine::WebFileEngineExt;
|
||||||
use dioxus_core::{Element, VirtualDom};
|
use dioxus_core::{ComponentFunction, CrossPlatformConfig, VirtualDom};
|
||||||
use futures_util::{
|
use futures_util::{
|
||||||
future::{select, Either},
|
future::{select, Either},
|
||||||
pin_mut, FutureExt, StreamExt,
|
pin_mut, FutureExt, StreamExt,
|
||||||
@@ -72,7 +72,9 @@ mod dom;
|
|||||||
mod eval;
|
mod eval;
|
||||||
mod event;
|
mod event;
|
||||||
mod mutations;
|
mod mutations;
|
||||||
|
mod platform;
|
||||||
pub use event::*;
|
pub use event::*;
|
||||||
|
pub use platform::*;
|
||||||
#[cfg(feature = "file_engine")]
|
#[cfg(feature = "file_engine")]
|
||||||
mod file_engine;
|
mod file_engine;
|
||||||
#[cfg(all(feature = "hot_reload", debug_assertions))]
|
#[cfg(all(feature = "hot_reload", debug_assertions))]
|
||||||
@@ -85,89 +87,6 @@ mod rehydrate;
|
|||||||
// mod ric_raf;
|
// mod ric_raf;
|
||||||
// mod rehydrate;
|
// mod rehydrate;
|
||||||
|
|
||||||
/// Launch the VirtualDOM given a root component and a configuration.
|
|
||||||
///
|
|
||||||
/// This function expects the root component to not have root props. To launch the root component with root props, use
|
|
||||||
/// `launch_with_props` instead.
|
|
||||||
///
|
|
||||||
/// This method will block the thread with `spawn_local` from wasm_bindgen_futures.
|
|
||||||
///
|
|
||||||
/// If you need to run the VirtualDOM in its own thread, use `run_with_props` instead and await the future.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```rust, ignore
|
|
||||||
/// fn main() {
|
|
||||||
/// dioxus_web::launch(App);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// static App: Component = |cx| {
|
|
||||||
/// render!(div {"hello world"})
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn launch(root_component: fn() -> Element) {
|
|
||||||
launch_with_props(
|
|
||||||
|root_component| root_component(),
|
|
||||||
root_component,
|
|
||||||
Config::default(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Launch your app and run the event loop, with configuration.
|
|
||||||
///
|
|
||||||
/// This function will start your web app on the main web thread.
|
|
||||||
///
|
|
||||||
/// You can configure the WebView window with a configuration closure
|
|
||||||
///
|
|
||||||
/// ```rust, ignore
|
|
||||||
/// use dioxus::prelude::*;
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// dioxus_web::launch_with_props(App, Config::new().pre_render(true));
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn app() -> Element {
|
|
||||||
/// rsx!{
|
|
||||||
/// h1 {"hello world!"}
|
|
||||||
/// })
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn launch_cfg(root: fn(()) -> Element, config: Config) {
|
|
||||||
launch_with_props(root, (), config)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Launches the VirtualDOM from the specified component function and props.
|
|
||||||
///
|
|
||||||
/// This method will block the thread with `spawn_local`
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```rust, ignore
|
|
||||||
/// fn main() {
|
|
||||||
/// dioxus_web::launch_with_props(
|
|
||||||
/// App,
|
|
||||||
/// RootProps { name: String::from("joe") },
|
|
||||||
/// Config::new()
|
|
||||||
/// );
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[derive(ParitalEq, Props)]
|
|
||||||
/// struct RootProps {
|
|
||||||
/// name: String
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// static App: Component<RootProps> = |cx| {
|
|
||||||
/// render!(div {"hello {cx.props.name}"})
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn launch_with_props<T: Clone + 'static>(
|
|
||||||
root_component: fn(T) -> Element,
|
|
||||||
root_properties: T,
|
|
||||||
config: Config,
|
|
||||||
) {
|
|
||||||
wasm_bindgen_futures::spawn_local(run_with_props(root_component, root_properties, config));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runs the app as a future that can be scheduled around the main thread.
|
/// Runs the app as a future that can be scheduled around the main thread.
|
||||||
///
|
///
|
||||||
/// Polls futures internal to the VirtualDOM, hence the async nature of this function.
|
/// Polls futures internal to the VirtualDOM, hence the async nature of this function.
|
||||||
@@ -180,14 +99,17 @@ pub fn launch_with_props<T: Clone + 'static>(
|
|||||||
/// wasm_bindgen_futures::spawn_local(app_fut);
|
/// wasm_bindgen_futures::spawn_local(app_fut);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn run_with_props<T: Clone + 'static>(
|
pub async fn run_with_props<
|
||||||
root: fn(T) -> Element,
|
Component: ComponentFunction<Phantom, Props = Props>,
|
||||||
root_props: T,
|
Props: Clone + 'static,
|
||||||
cfg: Config,
|
Phantom: 'static,
|
||||||
|
>(
|
||||||
|
dioxus_config: CrossPlatformConfig<Component, Props, Phantom>,
|
||||||
|
web_config: Config,
|
||||||
) {
|
) {
|
||||||
tracing::info!("Starting up");
|
tracing::info!("Starting up");
|
||||||
|
|
||||||
let mut dom = VirtualDom::new_with_props(root, root_props);
|
let mut dom = dioxus_config.build_vdom();
|
||||||
|
|
||||||
#[cfg(feature = "eval")]
|
#[cfg(feature = "eval")]
|
||||||
{
|
{
|
||||||
@@ -198,7 +120,7 @@ pub async fn run_with_props<T: Clone + 'static>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "panic_hook")]
|
#[cfg(feature = "panic_hook")]
|
||||||
if cfg.default_panic_hook {
|
if web_config.default_panic_hook {
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +134,7 @@ pub async fn run_with_props<T: Clone + 'static>(
|
|||||||
#[cfg(not(feature = "hydrate"))]
|
#[cfg(not(feature = "hydrate"))]
|
||||||
let should_hydrate = false;
|
let should_hydrate = false;
|
||||||
|
|
||||||
let mut websys_dom = dom::WebsysDom::new(cfg, tx);
|
let mut websys_dom = dom::WebsysDom::new(web_config, tx);
|
||||||
|
|
||||||
tracing::info!("rebuilding app");
|
tracing::info!("rebuilding app");
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
use dioxus_core::*;
|
||||||
|
|
||||||
|
use crate::Config;
|
||||||
|
|
||||||
|
/// The web renderer platform
|
||||||
|
pub struct WebPlatform;
|
||||||
|
|
||||||
|
impl<Props: Clone + 'static> PlatformBuilder<Props> for WebPlatform {
|
||||||
|
type Config = Config;
|
||||||
|
|
||||||
|
fn launch<Component: ComponentFunction<Phantom, Props = Props>, Phantom: 'static>(
|
||||||
|
config: CrossPlatformConfig<Component, Props, Phantom>,
|
||||||
|
platform_config: Self::Config,
|
||||||
|
) {
|
||||||
|
wasm_bindgen_futures::spawn_local(async move {
|
||||||
|
crate::run_with_props(config, platform_config).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user