Merge pull request #754 from Demonthos/desktop-hot-reload

Implement hot reloading for Desktop, TUI, and Liveview
This commit is contained in:
Jon Kelley authored and GitHub committed 2023-01-23 09:48:54 -10:00
commit 1b597f43d1
16 files changed
+705 -79

No files matched your search

+3
View File
@@ -9,6 +9,7 @@ use crate::Config;
use crate::WebviewHandler;
use dioxus_core::ScopeState;
use dioxus_core::VirtualDom;
use dioxus_hot_reload::HotReloadMsg;
use serde_json::Value;
use slab::Slab;
use wry::application::event::Event;
@@ -285,6 +286,8 @@ pub enum EventData {
Ipc(IpcMessage),
HotReloadEvent(HotReloadMsg),
NewWindow,
CloseWindow,
-54
View File
@@ -1,54 +0,0 @@
#![allow(dead_code)]
use dioxus_core::Template;
use interprocess::local_socket::{LocalSocketListener, LocalSocketStream};
use std::io::{BufRead, BufReader};
use std::time::Duration;
use std::{sync::Arc, sync::Mutex};
fn handle_error(connection: std::io::Result<LocalSocketStream>) -> Option<LocalSocketStream> {
connection
.map_err(|error| eprintln!("Incoming connection failed: {}", error))
.ok()
}
pub(crate) fn init(proxy: futures_channel::mpsc::UnboundedSender<Template<'static>>) {
let latest_in_connection: Arc<Mutex<Option<BufReader<LocalSocketStream>>>> =
Arc::new(Mutex::new(None));
let latest_in_connection_handle = latest_in_connection.clone();
// connect to processes for incoming data
std::thread::spawn(move || {
let temp_file = std::env::temp_dir().join("@dioxusin");
if let Ok(listener) = LocalSocketListener::bind(temp_file) {
for conn in listener.incoming().filter_map(handle_error) {
*latest_in_connection_handle.lock().unwrap() = Some(BufReader::new(conn));
}
}
});
std::thread::spawn(move || {
loop {
if let Some(conn) = &mut *latest_in_connection.lock().unwrap() {
let mut buf = String::new();
match conn.read_line(&mut buf) {
Ok(_) => {
let msg: Template<'static> =
serde_json::from_str(Box::leak(buf.into_boxed_str())).unwrap();
proxy.unbounded_send(msg).unwrap();
}
Err(err) => {
if err.kind() != std::io::ErrorKind::WouldBlock {
break;
}
}
}
}
// give the error handler time to take the mutex
std::thread::sleep(Duration::from_millis(100));
}
});
}
+25 -3
View File
@@ -12,9 +12,6 @@ mod protocol;
mod waker;
mod webview;
#[cfg(all(feature = "hot-reload", debug_assertions))]
mod hot_reload;
pub use cfg::Config;
pub use desktop_context::{
use_window, use_wry_event_handler, DesktopContext, WryEventHandler, WryEventHandlerId,
@@ -111,6 +108,18 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
let proxy = event_loop.create_proxy();
// Intialize hot reloading if it is enabled
#[cfg(all(feature = "hot-reload", debug_assertions))]
{
let proxy = proxy.clone();
dioxus_hot_reload::connect(move |template| {
let _ = proxy.send_event(UserWindowEvent(
EventData::HotReloadEvent(template),
unsafe { WindowId::dummy() },
));
});
}
// We start the tokio runtime *on this thread*
// Any future we poll later will use this runtime to spawn tasks and for IO
let rt = tokio::runtime::Builder::new_multi_thread()
@@ -176,6 +185,19 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
}
Event::UserEvent(event) => match event.0 {
EventData::HotReloadEvent(msg) => match msg {
dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => {
for webview in webviews.values_mut() {
webview.dom.replace_template(template);
poll_vdom(webview);
}
}
dioxus_hot_reload::HotReloadMsg::Shutdown => {
*control_flow = ControlFlow::Exit;
}
},
EventData::CloseWindow => {
webviews.remove(&event.1);