Browse Source

Merge pull request #1572 from DioxusLabs/jk/global-window-fun

Feat: add global context functions
Jonathan Kelley 1 year ago
parent
commit
ea0c39b14c

+ 0 - 18
examples/button.rs

@@ -1,18 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(app);
-}
-
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
-        button {
-            onclick: |_| async move {
-                println!("hello, desktop!");
-                tokio::time::sleep(std::time::Duration::from_secs(1)).await;
-                println!("goodbye, desktop!");
-            },
-            "hello, desktop!"
-        }
-    })
-}

+ 2 - 7
examples/compose.rs

@@ -1,7 +1,6 @@
 //! This example shows how to create a popup window and send data back to the parent window.
 
 use dioxus::prelude::*;
-use dioxus_desktop::use_window;
 use futures_util::StreamExt;
 
 fn main() {
@@ -9,7 +8,6 @@ fn main() {
 }
 
 fn app(cx: Scope) -> Element {
-    let window = use_window(cx);
     let emails_sent = use_ref(cx, Vec::new);
 
     let tx = use_coroutine(cx, |mut rx: UnboundedReceiver<String>| {
@@ -51,7 +49,6 @@ struct ComposeProps {
 
 fn compose(cx: Scope<ComposeProps>) -> Element {
     let user_input = use_state(cx, String::new);
-    let window = use_window(cx);
 
     cx.render(rsx! {
         div {
@@ -60,15 +57,13 @@ fn compose(cx: Scope<ComposeProps>) -> Element {
             button {
                 onclick: move |_| {
                     cx.props.app_tx.send(user_input.get().clone());
-                    window.close();
+                    dioxus_desktop::window().close();
                 },
                 "Click to send"
             }
 
             input {
-                oninput: move |e| {
-                    user_input.set(e.value.clone());
-                },
+                oninput: move |e| user_input.set(e.value.clone()),
                 value: "{user_input}"
             }
         }

+ 1 - 3
examples/crm.rs

@@ -87,8 +87,6 @@ fn ClientAdd(cx: Scope) -> Element {
     let last_name = use_state(cx, String::new);
     let description = use_state(cx, String::new);
 
-    let navigator = use_navigator(cx);
-
     cx.render(rsx! {
         h2 { "Add new Client" }
 
@@ -103,7 +101,7 @@ fn ClientAdd(cx: Scope) -> Element {
                     description: description.to_string(),
                 });
 
-                navigator.push(Route::ClientList {});
+                dioxus_router::router().push(Route::ClientList {});
             },
 
             fieldset {

+ 9 - 14
examples/eval.rs

@@ -5,26 +5,21 @@ fn main() {
 }
 
 fn app(cx: Scope) -> Element {
-    let eval_provider = use_eval(cx);
-
-    let future = use_future(cx, (), |_| {
-        to_owned![eval_provider];
-        async move {
-            let eval = eval_provider(
-                r#"
+    let future = use_future(cx, (), |_| async move {
+        let eval = eval(
+            r#"
                 dioxus.send("Hi from JS!");
                 let msg = await dioxus.recv();
                 console.log(msg);
                 return "hello world";
             "#,
-            )
-            .unwrap();
+        )
+        .unwrap();
 
-            eval.send("Hi from Rust!".into()).unwrap();
-            let res = eval.recv().await.unwrap();
-            println!("{:?}", eval.await);
-            res
-        }
+        eval.send("Hi from Rust!".into()).unwrap();
+        let res = eval.recv().await.unwrap();
+        println!("{:?}", eval.await);
+        res
     });
 
     match future.value() {

+ 16 - 18
examples/login_form.rs

@@ -8,27 +8,25 @@ fn main() {
 }
 
 fn app(cx: Scope) -> Element {
-    let onsubmit = move |evt: FormEvent| {
-        cx.spawn(async move {
-            let resp = reqwest::Client::new()
-                .post("http://localhost:8080/login")
-                .form(&[
-                    ("username", &evt.values["username"]),
-                    ("password", &evt.values["password"]),
-                ])
-                .send()
-                .await;
+    let onsubmit = move |evt: FormEvent| async move {
+        let resp = reqwest::Client::new()
+            .post("http://localhost:8080/login")
+            .form(&[
+                ("username", &evt.values["username"]),
+                ("password", &evt.values["password"]),
+            ])
+            .send()
+            .await;
 
-            match resp {
-                // Parse data from here, such as storing a response token
-                Ok(_data) => println!("Login successful!"),
+        match resp {
+            // Parse data from here, such as storing a response token
+            Ok(_data) => println!("Login successful!"),
 
-                //Handle any errors from the fetch here
-                Err(_err) => {
-                    println!("Login failed - you need a login server running on localhost:8080.")
-                }
+            //Handle any errors from the fetch here
+            Err(_err) => {
+                println!("Login failed - you need a login server running on localhost:8080.")
             }
-        });
+        }
     };
 
     cx.render(rsx! {

+ 1 - 3
examples/multiwindow.rs

@@ -5,14 +5,12 @@ fn main() {
 }
 
 fn app(cx: Scope) -> Element {
-    let window = dioxus_desktop::use_window(cx);
-
     cx.render(rsx! {
         div {
             button {
                 onclick: move |_| {
                     let dom = VirtualDom::new(popup);
-                    window.new_window(dom, Default::default());
+                    dioxus_desktop::window().new_window(dom, Default::default());
                 },
                 "New Window"
             }

+ 2 - 4
examples/overlay.rs

@@ -1,13 +1,11 @@
 use dioxus::prelude::*;
-use dioxus_desktop::{tao::dpi::PhysicalPosition, use_window, LogicalSize, WindowBuilder};
+use dioxus_desktop::{tao::dpi::PhysicalPosition, LogicalSize, WindowBuilder};
 
 fn main() {
     dioxus_desktop::launch_cfg(app, make_config());
 }
 
 fn app(cx: Scope) -> Element {
-    let window = use_window(cx);
-
     cx.render(rsx! {
         div {
             width: "100%",
@@ -19,7 +17,7 @@ fn app(cx: Scope) -> Element {
                 width: "100%",
                 height: "10px",
                 background_color: "black",
-                onmousedown: move |_| window.drag(),
+                onmousedown: move |_| dioxus_desktop::window().drag(),
             }
 
             "This is an overlay!"

+ 1 - 3
examples/window_zoom.rs

@@ -1,12 +1,10 @@
 use dioxus::prelude::*;
-use dioxus_desktop::use_window;
 
 fn main() {
     dioxus_desktop::launch(app);
 }
 
 fn app(cx: Scope) -> Element {
-    let window = use_window(cx);
     let level = use_state(cx, || 1.0);
 
     cx.render(rsx! {
@@ -16,7 +14,7 @@ fn app(cx: Scope) -> Element {
             oninput: |e| {
                 if let Ok(new_zoom) = e.value.parse::<f64>() {
                     level.set(new_zoom);
-                    window.webview.zoom(new_zoom);
+                    dioxus_desktop::window().webview.zoom(new_zoom);
                 }
             }
         }

+ 10 - 0
packages/desktop/src/desktop_context.rs

@@ -34,7 +34,17 @@ use wry::webview::WebView;
 
 pub type ProxyType = EventLoopProxy<UserWindowEvent>;
 
+/// Get an imperative handle to the current window without using a hook
+///
+/// ## Panics
+///
+/// This function will panic if it is called outside of the context of a Dioxus App.
+pub fn window() -> DesktopContext {
+    dioxus_core::prelude::consume_context().unwrap()
+}
+
 /// Get an imperative handle to the current window
+#[deprecated = "Prefer the using the `window` function directly for cleaner code"]
 pub fn use_window(cx: &ScopeState) -> &DesktopContext {
     cx.use_hook(|| cx.consume_context::<DesktopContext>())
         .as_ref()

+ 1 - 1
packages/desktop/src/lib.rs

@@ -23,7 +23,7 @@ use crate::shortcut::GlobalHotKeyEvent;
 pub use cfg::{Config, WindowCloseBehaviour};
 pub use desktop_context::DesktopContext;
 pub use desktop_context::{
-    use_window, use_wry_event_handler, DesktopService, WryEventHandler, WryEventHandlerId,
+    use_window, use_wry_event_handler, window, DesktopService, WryEventHandler, WryEventHandlerId,
 };
 use desktop_context::{EventData, UserWindowEvent, WebviewQueue, WindowEventHandlers};
 use dioxus_core::*;

+ 9 - 0
packages/html/src/eval.rs

@@ -48,6 +48,15 @@ pub fn use_eval(cx: &ScopeState) -> &EvalCreator {
     })
 }
 
+pub fn eval(script: &str) -> Result<UseEval, EvalError> {
+    let eval_provider = dioxus_core::prelude::consume_context::<Rc<dyn EvalProvider>>()
+        .expect("evaluator not provided");
+
+    eval_provider
+        .new_evaluator(script.to_string())
+        .map(UseEval::new)
+}
+
 /// A wrapper around the target platform's evaluator.
 #[derive(Clone)]
 pub struct UseEval {

+ 3 - 4
packages/router/examples/simple_routes.rs

@@ -112,7 +112,6 @@ fn Route2(cx: Scope, user_id: usize) -> Element {
 
 #[component]
 fn Route3(cx: Scope, dynamic: String) -> Element {
-    let navigator = use_navigator(cx);
     let current_route = use_route(cx)?;
     let current_route_str = use_ref(cx, String::new);
     let parsed = Route::from_str(&current_route_str.read());
@@ -122,11 +121,11 @@ fn Route3(cx: Scope, dynamic: String) -> Element {
         .flat_map(|seg| seg.flatten().into_iter())
         .collect::<Vec<_>>();
 
+    let navigator = use_navigator(cx);
+  
     render! {
         input {
-            oninput: move |evt| {
-                *current_route_str.write() = evt.value.clone();
-            },
+            oninput: move |evt| *current_route_str.write() = evt.value.clone(),
             value: "{current_route_str.read()}"
         }
         "dynamic: {dynamic}"

+ 14 - 0
packages/router/src/contexts/navigator.rs

@@ -1,5 +1,19 @@
 use crate::prelude::{ExternalNavigationFailure, IntoRoutable, RouterContext};
 
+/// Acquire the navigator without subscribing to updates.
+///
+/// Can be called anywhere in the application provided a Router has been initialized.
+///
+/// ## Panics
+///
+/// Panics if there is no router present.
+pub fn navigator() -> Navigator {
+    Navigator(
+        dioxus::core::prelude::consume_context::<RouterContext>()
+            .expect("A router must be present to use navigator"),
+    )
+}
+
 /// A view into the navigation state of a router.
 #[derive(Clone)]
 pub struct Navigator(pub(crate) RouterContext);

+ 1 - 0
packages/router/src/hooks/use_navigator.rs

@@ -49,6 +49,7 @@ use crate::prelude::{Navigator, RouterContext};
 /// # let _ = vdom.rebuild();
 /// ```
 #[must_use]
+#[deprecated = "Prefer acquiring the router directly with `dioxus_router::router()`"]
 pub fn use_navigator(cx: &ScopeState) -> &Navigator {
     &*cx.use_hook(|| {
         let router = cx

+ 6 - 1
packages/router/src/hooks/use_router.rs

@@ -2,7 +2,7 @@ use dioxus::prelude::ScopeState;
 
 use crate::{prelude::RouterContext, utils::use_router_internal::use_router_internal};
 
-#[deprecated = "prefer the use_navigator or use_route functions"]
+#[deprecated = "prefer the `router()` function or `use_route` functions"]
 #[must_use]
 /// A hook that provides access to information about the router.
 pub fn use_router(cx: &ScopeState) -> &RouterContext {
@@ -10,3 +10,8 @@ pub fn use_router(cx: &ScopeState) -> &RouterContext {
         .as_ref()
         .expect("use_route must have access to a router")
 }
+
+/// Aquire the router without subscribing to updates.
+pub fn router() -> RouterContext {
+    dioxus::core::prelude::consume_context().unwrap()
+}

+ 2 - 0
packages/router/src/lib.rs

@@ -53,6 +53,8 @@ pub mod hooks {
     pub use use_navigator::*;
 }
 
+pub use hooks::router;
+
 /// A collection of useful items most applications might need.
 pub mod prelude {
     pub use crate::components::*;