make the root component take no arguments
This commit is contained in:
1 parent
8fe2515413
commit
404c864246
26 files changed
+46
-47
No files matched your search
@@ -1,6 +1,5 @@
|
|||||||
use crate::component_body::ComponentBody;
|
use crate::component_body::ComponentBody;
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::{parse_quote, Path};
|
|
||||||
|
|
||||||
/// The output produced by a deserializer.
|
/// The output produced by a deserializer.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ serde = { version = "1", features = ["derive"], optional = true }
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { workspace = true, features = ["full"] }
|
tokio = { workspace = true, features = ["full"] }
|
||||||
dioxus = { workspace = true }
|
dioxus = { workspace = true }
|
||||||
dioxus-core = { workspace = true, features = ["internal-testing"] }
|
dioxus-core = { workspace = true }
|
||||||
dioxus-html = { workspace = true, features = ["serialize"] }
|
dioxus-html = { workspace = true, features = ["serialize"] }
|
||||||
pretty_assertions = "1.3.0"
|
pretty_assertions = "1.3.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
@@ -43,4 +43,3 @@ trybuild = "1.0"
|
|||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
serialize = ["serde"]
|
serialize = ["serde"]
|
||||||
internal-testing = []
|
|
||||||
@@ -38,7 +38,7 @@ First, start with your app:
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
// First, declare a root component
|
// First, declare a root component
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
div { "hello world" }
|
div { "hello world" }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let count: &RefCell<Vec<Element>> = cx.use_hook(|| RefCell::new(Vec::new()));
|
let count: &RefCell<Vec<Element>> = cx.use_hook(|| RefCell::new(Vec::new()));
|
||||||
|
|
||||||
render! {
|
render! {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> compile_tests/props_safety.rs:8:5
|
--> compile_tests/props_safety.rs:8:5
|
||||||
|
|
|
|
||||||
5 | fn app(cx: Scope) -> Element {
|
5 | fn app() -> Element {
|
||||||
| --
|
| --
|
||||||
| |
|
| |
|
||||||
| `cx` is a reference that is only valid in the function body
|
| `cx` is a reference that is only valid in the function body
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let count = vec![1, 2, 3];
|
let count = vec![1, 2, 3];
|
||||||
|
|
||||||
render! {
|
render! {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ impl<const A: bool> FragmentBuilder<A> {
|
|||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// fn App(cx: Scope) -> Element {
|
/// fn App() -> Element {
|
||||||
/// cx.render(rsx!{
|
/// cx.render(rsx!{
|
||||||
/// CustomCard {
|
/// CustomCard {
|
||||||
/// h1 {}
|
/// h1 {}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ impl Runtime {
|
|||||||
/// let virtual_dom = VirtualDom::new(app);
|
/// let virtual_dom = VirtualDom::new(app);
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn app(cx: Scope) -> Element {
|
/// fn app() -> Element {
|
||||||
/// render!{ Component { runtime: Runtime::current().unwrap() } }
|
/// render!{ Component { runtime: Runtime::current().unwrap() } }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ use std::{any::Any, cell::Cell, collections::BTreeSet, future::Future, rc::Rc};
|
|||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use dioxus::prelude::*;
|
/// # use dioxus::prelude::*;
|
||||||
/// # fn App(cx: Scope) -> Element { cx.render(rsx! { div {} }) }
|
/// # fn App() -> Element { cx.render(rsx! { div {} }) }
|
||||||
///
|
///
|
||||||
/// let mut vdom = VirtualDom::new(App);
|
/// let mut vdom = VirtualDom::new(App);
|
||||||
/// let edits = vdom.rebuild();
|
/// let edits = vdom.rebuild();
|
||||||
@@ -127,7 +127,7 @@ use std::{any::Any, cell::Cell, collections::BTreeSet, future::Future, rc::Rc};
|
|||||||
/// Putting everything together, you can build an event loop around Dioxus by using the methods outlined above.
|
/// Putting everything together, you can build an event loop around Dioxus by using the methods outlined above.
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// #[component]
|
/// #[component]
|
||||||
/// fn App(cx: Scope) -> Element {
|
/// fn App() -> Element {
|
||||||
/// cx.render(rsx! {
|
/// cx.render(rsx! {
|
||||||
/// div { "Hello World" }
|
/// div { "Hello World" }
|
||||||
/// })
|
/// })
|
||||||
@@ -226,8 +226,8 @@ 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, ())
|
Self::new_with_props(|app| app(), app)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new VirtualDom with the given properties for the root component.
|
/// Create a new VirtualDom with the given properties for the root component.
|
||||||
@@ -563,7 +563,6 @@ impl VirtualDom {
|
|||||||
to.append_children(ElementId(0), m);
|
to.append_children(ElementId(0), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(features = "internal-testing")]
|
|
||||||
/// [`VirtualDom::rebuild`] to a vector of mutations for testing purposes
|
/// [`VirtualDom::rebuild`] to a vector of mutations for testing purposes
|
||||||
pub fn rebuild_to_vec(&mut self) -> MutationsVec {
|
pub fn rebuild_to_vec(&mut self) -> MutationsVec {
|
||||||
let mut mutations = MutationsVec::default();
|
let mut mutations = MutationsVec::default();
|
||||||
@@ -590,7 +589,6 @@ impl VirtualDom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(features = "internal-testing")]
|
|
||||||
/// [`Self::render_immediate`] to a vector of mutations for testing purposes
|
/// [`Self::render_immediate`] to a vector of mutations for testing purposes
|
||||||
pub fn render_immediate_to_vec(&mut self) -> MutationsVec {
|
pub fn render_immediate_to_vec(&mut self) -> MutationsVec {
|
||||||
let mut mutations = MutationsVec::default();
|
let mut mutations = MutationsVec::default();
|
||||||
@@ -662,7 +660,6 @@ impl VirtualDom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(features = "internal-testing")]
|
|
||||||
/// [`Self::render_with_deadline`] to a vector of mutations for testing purposes
|
/// [`Self::render_with_deadline`] to a vector of mutations for testing purposes
|
||||||
pub async fn render_with_deadline_to_vec(
|
pub async fn render_with_deadline_to_vec(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let raw = match generation() % 2 {
|
let raw = match generation() % 2 {
|
||||||
0 => "123.123",
|
0 => "123.123",
|
||||||
1 => "123.123.123",
|
1 => "123.123.123",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use dioxus::prelude::*;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn state_shares() {
|
fn state_shares() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
cx.provide_context(generation() as i32);
|
cx.provide_context(generation() as i32);
|
||||||
|
|
||||||
render!(child_1 {})
|
render!(child_1 {})
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use dioxus_core::ElementId;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_fragment_creates_nothing() {
|
fn empty_fragment_creates_nothing() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
render!(())
|
render!(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ fn fragments_nested() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fragments_across_components() {
|
fn fragments_across_components() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
render! {
|
render! {
|
||||||
demo_child {}
|
demo_child {}
|
||||||
demo_child {}
|
demo_child {}
|
||||||
@@ -88,7 +88,7 @@ fn fragments_across_components() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn list_fragments() {
|
fn list_fragments() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
render!(
|
render!(
|
||||||
h1 { "hello" }
|
h1 { "hello" }
|
||||||
(0..6).map(|f| render!( span { "{f}" }))
|
(0..6).map(|f| render!( span { "{f}" }))
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use dioxus_core::ElementId;
|
|||||||
// In Dioxus, we memoize the render! body and simplify it down to a few template loads
|
// In Dioxus, we memoize the render! body and simplify it down to a few template loads
|
||||||
//
|
//
|
||||||
// Also note that the IDs increase linearly. This lets us drive a vec on the renderer for O(1) re-indexing
|
// Also note that the IDs increase linearly. This lets us drive a vec on the renderer for O(1) re-indexing
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
render! {
|
render! {
|
||||||
div {
|
div {
|
||||||
(0..3).map(|i| render! {
|
(0..3).map(|i| render! {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use dioxus_core::ElementId;
|
|||||||
#[test]
|
#[test]
|
||||||
fn nested_passthru_creates() {
|
fn nested_passthru_creates() {
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
render! {
|
render! {
|
||||||
PassThru {
|
PassThru {
|
||||||
PassThru {
|
PassThru {
|
||||||
@@ -39,7 +39,7 @@ fn nested_passthru_creates() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn nested_passthru_creates_add() {
|
fn nested_passthru_creates_add() {
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
render! {
|
render! {
|
||||||
ChildComp {
|
ChildComp {
|
||||||
"1"
|
"1"
|
||||||
@@ -81,7 +81,7 @@ fn nested_passthru_creates_add() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn dynamic_node_as_root() {
|
fn dynamic_node_as_root() {
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
let a = 123;
|
let a = 123;
|
||||||
let b = 456;
|
let b = 456;
|
||||||
render! { "{a}", "{b}" }
|
render! { "{a}", "{b}" }
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use dioxus::prelude::*;
|
|||||||
/// different pointers
|
/// different pointers
|
||||||
#[test]
|
#[test]
|
||||||
fn component_swap() {
|
fn component_swap() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let render_phase = cx.use_hook(|| 0);
|
let render_phase = cx.use_hook(|| 0);
|
||||||
|
|
||||||
*render_phase += 1;
|
*render_phase += 1;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use dioxus_core::ElementId;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn text_diff() {
|
fn text_diff() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let gen = generation();
|
let gen = generation();
|
||||||
render!( h1 { "hello {gen}" } )
|
render!( h1 { "hello {gen}" } )
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ fn text_diff() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn element_swap() {
|
fn element_swap() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let gen = generation();
|
let gen = generation();
|
||||||
|
|
||||||
match gen % 2 {
|
match gen % 2 {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ fn catches_panic() {
|
|||||||
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
|
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
render! {
|
render! {
|
||||||
div {
|
div {
|
||||||
h1 { "Title" }
|
h1 { "Title" }
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ fn events_propagate() {
|
|||||||
assert_eq!(*CLICKS.lock().unwrap(), 3);
|
assert_eq!(*CLICKS.lock().unwrap(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
render! {
|
render! {
|
||||||
div { onclick: move |_| {
|
div { onclick: move |_| {
|
||||||
println!("top clicked");
|
println!("top clicked");
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ fn manual_diffing() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn events_generate() {
|
fn events_generate() {
|
||||||
set_event_converter(Box::new(SerializedHtmlEventConverter));
|
set_event_converter(Box::new(SerializedHtmlEventConverter));
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let count = cx.use_hook(|| 0);
|
let count = cx.use_hook(|| 0);
|
||||||
|
|
||||||
match *count {
|
match *count {
|
||||||
@@ -79,7 +79,7 @@ fn events_generate() {
|
|||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn components_generate() {
|
// fn components_generate() {
|
||||||
// fn app(cx: Scope) -> Element {
|
// fn app() -> Element {
|
||||||
// let render_phase = cx.use_hook(|| 0);
|
// let render_phase = cx.use_hook(|| 0);
|
||||||
// *render_phase += 1;
|
// *render_phase += 1;
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ fn miri_rollover() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
let mut idx = use_state(cx, || 0);
|
let mut idx = use_state(cx, || 0);
|
||||||
let onhover = |_| println!("go!");
|
let onhover = |_| println!("go!");
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use dioxus::prelude::*;
|
|||||||
#[test]
|
#[test]
|
||||||
fn app_drops() {
|
fn app_drops() {
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
render! { div {} }
|
render! { div {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ fn app_drops() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn hooks_drop() {
|
fn hooks_drop() {
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
cx.use_hook(|| String::from("asd"));
|
cx.use_hook(|| String::from("asd"));
|
||||||
cx.use_hook(|| String::from("asd"));
|
cx.use_hook(|| String::from("asd"));
|
||||||
cx.use_hook(|| String::from("asd"));
|
cx.use_hook(|| String::from("asd"));
|
||||||
@@ -36,7 +36,7 @@ fn hooks_drop() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn contexts_drop() {
|
fn contexts_drop() {
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
cx.provide_context(String::from("asd"));
|
cx.provide_context(String::from("asd"));
|
||||||
|
|
||||||
render! {
|
render! {
|
||||||
@@ -61,7 +61,7 @@ fn contexts_drop() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn tasks_drop() {
|
fn tasks_drop() {
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
cx.spawn(async {
|
cx.spawn(async {
|
||||||
// tokio::time::sleep(std::time::Duration::from_millis(100000)).await;
|
// tokio::time::sleep(std::time::Duration::from_millis(100000)).await;
|
||||||
});
|
});
|
||||||
@@ -93,7 +93,7 @@ fn root_props_drop() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn diffing_drops_old() {
|
fn diffing_drops_old() {
|
||||||
#[component]
|
#[component]
|
||||||
fn App(cx: Scope) -> Element {
|
fn App() -> Element {
|
||||||
render! {
|
render! {
|
||||||
div {
|
div {
|
||||||
match generation() % 2 {
|
match generation() % 2 {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use dioxus::prelude::*;
|
|||||||
/// When miri runs, it'll let us know if we leaked or aliased.
|
/// When miri runs, it'll let us know if we leaked or aliased.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_memory_leak() {
|
fn test_memory_leak() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let val = generation();
|
let val = generation();
|
||||||
|
|
||||||
cx.spawn(async {});
|
cx.spawn(async {});
|
||||||
@@ -69,7 +69,7 @@ fn test_memory_leak() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn memo_works_properly() {
|
fn memo_works_properly() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let val = generation();
|
let val = generation();
|
||||||
|
|
||||||
if val == 2 || val == 4 {
|
if val == 2 || val == 4 {
|
||||||
@@ -142,7 +142,7 @@ fn supports_async() {
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
let colors = use_state(cx, || vec!["green", "blue", "red"]);
|
let colors = use_state(cx, || vec!["green", "blue", "red"]);
|
||||||
let padding = use_state(cx, || 10);
|
let padding = use_state(cx, || 10);
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fn it_works() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
render!(
|
render!(
|
||||||
div {
|
div {
|
||||||
"Waiting for... "
|
"Waiting for... "
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ async fn it_works() {
|
|||||||
|
|
||||||
static POLL_COUNT: AtomicUsize = AtomicUsize::new(0);
|
static POLL_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app() -> Element {
|
||||||
cx.use_hook(|| {
|
cx.use_hook(|| {
|
||||||
cx.spawn(async {
|
cx.spawn(async {
|
||||||
for x in 0..10 {
|
for x in 0..10 {
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ use wry::{application::window::WindowId, webview::WebContext};
|
|||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn launch(root: Component) {
|
pub fn launch(root: fn() -> Element) {
|
||||||
launch_with_props(root, (), Config::default())
|
launch_with_props(|root| root(), root, Config::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop, with configuration.
|
/// Launch the WebView and run the event loop, with configuration.
|
||||||
|
|||||||
@@ -105,8 +105,12 @@ mod rehydrate;
|
|||||||
/// render!(div {"hello world"})
|
/// render!(div {"hello world"})
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn launch(root_component: fn(()) -> Element) {
|
pub fn launch(root_component: fn() -> Element) {
|
||||||
launch_with_props(root_component, (), Config::default());
|
launch_with_props(
|
||||||
|
|root_component| root_component(),
|
||||||
|
root_component,
|
||||||
|
Config::default(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Launch your app and run the event loop, with configuration.
|
/// Launch your app and run the event loop, with configuration.
|
||||||
|
|||||||
Reference in new issue
Block a user