Make the tokio runtime optional

This commit is contained in:
Jonathan Kelley committed 2024-01-04 19:09:59 -08:00
1 parent 73d5069a20
commit 38216fa272
8 files changed
+60 -28

No files matched your search

+3 -2
View File
@@ -1,7 +1,8 @@
use dioxus::prelude::*;
use dioxus_signals::use_signal;
fn main() {
#[tokio::main]
async fn main() {
dioxus_desktop::launch(app);
}
@@ -10,7 +11,7 @@ fn app(cx: Scope) -> Element {
use_future!(cx, || async move {
loop {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
count += 1;
println!("current: {count}");
}
+11 -13
View File
@@ -3,30 +3,28 @@ use crate::{
desktop_context::{EventData, UserWindowEvent, WindowEventHandlers},
edits::WebviewQueue,
element::DesktopElement,
events::IpcMessage,
file_upload::FileDialogRequest,
ipc::IpcMessage,
query::QueryResult,
shortcut::{GlobalHotKeyEvent, ShortcutRegistry},
webview::WebviewHandler,
};
use dioxus_core::{Component, ElementId, VirtualDom};
use dioxus_html::MountedData;
use dioxus_html::{native_bind::NativeFileEngine, FormData, HtmlEvent};
use dioxus_html::{native_bind::NativeFileEngine, FormData, HtmlEvent, MountedData};
use futures_util::{pin_mut, FutureExt};
use std::cell::Cell;
use std::rc::Rc;
use std::{collections::HashMap, sync::Arc};
use tao::event_loop::EventLoopBuilder;
use tao::event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget};
use tao::window::WindowId;
use tao::{event::Event, event_loop::ControlFlow};
use wry::WebView;
use std::{cell::Cell, collections::HashMap, rc::Rc, sync::Arc};
use tao::{
event::Event,
event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget},
window::WindowId,
};
pub struct App<P> {
pub(crate) struct App<P> {
// 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
pub(crate) props: Rc<Cell<Option<P>>>,
pub(crate) cfg: Rc<Cell<Option<Config>>>,
pub(crate) root: Component<P>,
pub(crate) webviews: HashMap<WindowId, WebviewHandler>,
pub(crate) event_handlers: WindowEventHandlers,
@@ -310,7 +308,7 @@ impl<P: 'static> App<P> {
/// Different hide implementations per platform
#[allow(unused)]
pub fn hide_app_window(webview: &WebView) {
pub fn hide_app_window(webview: &wry::WebView) {
#[cfg(target_os = "windows")]
{
use wry::application::platform::windows::WindowExtWindows;
+15
View File
@@ -1,6 +1,7 @@
use std::borrow::Cow;
use std::path::PathBuf;
use dioxus_core::prelude::Component;
use tao::window::{Icon, WindowBuilder, WindowId};
use wry::{
http::{Request as HttpRequest, Response as HttpResponse},
@@ -68,6 +69,20 @@ 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, root: Component<()>) {
crate::launch::launch_cfg(root, self)
}
/// 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>(self, root: Component<P>, props: P) {
crate::launch::launch_with_props(root, props, self)
}
/// Set whether the default menu bar should be enabled.
///
/// > Note: `enable` is `true` by default. To disable the default menu bar pass `false`.
+1 -1
View File
@@ -1,4 +1,4 @@
use crate::events::IpcMessage;
use crate::ipc::IpcMessage;
use crate::query::QueryEngine;
use crate::shortcut::{HotKey, ShortcutId, ShortcutRegistry, ShortcutRegistryError};
use crate::AssetHandler;
File renamed without changes.
+19 -7
View File
@@ -1,12 +1,11 @@
use crate::{
app::App,
desktop_context::{EventData, UserWindowEvent},
events::IpcMethod,
ipc::IpcMethod,
Config,
};
use dioxus_core::*;
use tao::event::{Event, StartCause, WindowEvent};
use tokio::runtime::Builder;
/// Launch the WebView and run the event loop.
///
@@ -55,6 +54,7 @@ pub fn launch_cfg(root: Component, config_builder: Config) {
/// 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
@@ -78,12 +78,24 @@ pub fn launch_cfg(root: Component, config_builder: Config) {
/// }
/// ```
pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config) {
// We start the tokio runtime *on this thread*
// Any future we poll later will use this runtime to spawn tasks and for IO
// I would love to just allow dioxus to work with any runtime... but tokio is weird
let rt = Builder::new_multi_thread().enable_all().build().unwrap();
let _guard = rt.enter();
#[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.
///
/// 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.
pub fn launch_with_props_blocking<P: 'static>(root: Component<P>, props: P, cfg: Config) {
let (event_loop, mut app) = App::new(cfg, props, root);
event_loop.run(move |window_event, event_loop, control_flow| {
+4 -3
View File
@@ -11,18 +11,19 @@ mod edits;
mod element;
mod escape;
mod eval;
mod events;
mod file_upload;
mod hooks;
mod ipc;
mod menubar;
#[cfg(any(target_os = "ios", target_os = "android"))]
mod mobile_shortcut;
mod protocol;
mod query;
mod shortcut;
mod waker;
mod webview;
#[cfg(any(target_os = "ios", target_os = "android"))]
mod mobile_shortcut;
// The main entrypoint for this crate
pub use launch::*;
mod launch;
+7 -2
View File
@@ -57,7 +57,8 @@ pub(super) async fn desktop_handler(
.body(Cow::from(body))
{
Ok(response) => {
return responder.respond(response);
responder.respond(response);
return;
}
Err(err) => tracing::error!("error building response: {}", err),
}
@@ -103,7 +104,10 @@ pub(super) async fn desktop_handler(
.header("Content-Type", content_type)
.body(Cow::from(asset))
{
Ok(response) => return responder.respond(response),
Ok(response) => {
responder.respond(response);
return;
}
Err(err) => tracing::error!("error building response: {}", err),
}
}
@@ -114,6 +118,7 @@ pub(super) async fn desktop_handler(
{
Ok(response) => {
responder.respond(response);
return;
}
Err(err) => tracing::error!("error building response: {}", err),
}