Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always run toast eval inside the runtime #3313

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions packages/web/src/devtools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
//! We also set up a little recursive timer that will attempt to reconnect if the connection is lost.

use std::fmt::Display;
use std::rc::Rc;
use std::time::Duration;

use dioxus_core::ScopeId;
use dioxus_core::prelude::RuntimeGuard;
use dioxus_core::{Runtime, ScopeId};
use dioxus_devtools::{DevserverMsg, HotReloadMsg};
use dioxus_document::eval;
use futures_channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
Expand All @@ -22,17 +24,22 @@ const POLL_INTERVAL_SCALE_FACTOR: i32 = 2;
/// Amount of time that toats should be displayed.
const TOAST_TIMEOUT: Duration = Duration::from_secs(5);

pub(crate) fn init() -> UnboundedReceiver<HotReloadMsg> {
pub(crate) fn init(runtime: Rc<Runtime>) -> UnboundedReceiver<HotReloadMsg> {
// Create the tx/rx pair that we'll use for the top-level future in the dioxus loop
let (tx, rx) = unbounded();

// Wire up the websocket to the devserver
make_ws(tx, POLL_INTERVAL_MIN, false);
make_ws(runtime, tx, POLL_INTERVAL_MIN, false);

rx
}

fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool) {
fn make_ws(
runtime: Rc<Runtime>,
tx: UnboundedSender<HotReloadMsg>,
poll_interval: i32,
reload: bool,
) {
// Get the location of the devserver, using the current location plus the /_dioxus path
// The idea here being that the devserver is always located on the /_dioxus behind a proxy
let location = web_sys::window().unwrap().location();
Expand All @@ -49,6 +56,7 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)

// Set the onmessage handler to bounce messages off to the main dioxus loop
let tx_ = tx.clone();
let runtime_ = runtime.clone();
ws.set_onmessage(Some(
Closure::<dyn FnMut(MessageEvent)>::new(move |e: MessageEvent| {
let Ok(text) = e.data().dyn_into::<JsString>() else {
Expand All @@ -72,6 +80,7 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)

// The devserver is telling us that it started a full rebuild. This does not mean that it is ready.
Ok(DevserverMsg::FullReloadStart) => show_toast(
runtime_.clone(),
"Your app is being rebuilt.",
"A non-hot-reloadable change occurred and we must rebuild.",
ToastLevel::Info,
Expand All @@ -80,6 +89,7 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)
),
// The devserver is telling us that the full rebuild failed.
Ok(DevserverMsg::FullReloadFailed) => show_toast(
runtime_.clone(),
"Oops! The build failed.",
"We tried to rebuild your app, but something went wrong.",
ToastLevel::Error,
Expand All @@ -90,6 +100,7 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)
// The devserver is telling us to reload the whole page
Ok(DevserverMsg::FullReloadCommand) => {
show_toast(
runtime_.clone(),
"Successfully rebuilt.",
"Your app was rebuilt successfully and without error.",
ToastLevel::Success,
Expand Down Expand Up @@ -121,11 +132,13 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)

// set timeout to reload the page in timeout_ms
let tx = tx.clone();
let runtime = runtime.clone();
web_sys::window()
.unwrap()
.set_timeout_with_callback_and_timeout_and_arguments_0(
Closure::<dyn FnMut()>::new(move || {
make_ws(
runtime.clone(),
tx.clone(),
POLL_INTERVAL_MAX.min(poll_interval * POLL_INTERVAL_SCALE_FACTOR),
true,
Expand Down Expand Up @@ -189,6 +202,7 @@ impl Display for ToastLevel {

/// Displays a toast to the developer.
fn show_toast(
runtime: Rc<Runtime>,
header_text: &str,
message: &str,
level: ToastLevel,
Expand All @@ -202,6 +216,8 @@ fn show_toast(
false => "showDXToast",
};

// Create the guard before running eval which uses the global runtime context
let _guard = RuntimeGuard::new(runtime);
ScopeId::ROOT.in_runtime(|| {
eval(&format!(
r#"
Expand Down
6 changes: 3 additions & 3 deletions packages/web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ pub async fn run(mut virtual_dom: VirtualDom, web_config: Config) -> ! {
#[cfg(feature = "document")]
virtual_dom.in_runtime(document::init_document);

#[cfg(all(feature = "devtools", debug_assertions))]
let mut hotreload_rx = devtools::init();

let runtime = virtual_dom.runtime();

#[cfg(all(feature = "devtools", debug_assertions))]
let mut hotreload_rx = devtools::init(runtime.clone());

let should_hydrate = web_config.hydrate;

let mut websys_dom = WebsysDom::new(web_config, runtime);
Expand Down
Loading