handle liveview sockets disconnecting

This commit is contained in:
Evan Almloff 2023-01-11 14:59:00 -06:00
parent e5e1abbdac
commit 1b53d4585e
2 changed files with 49 additions and 8 deletions

View file

@ -5,6 +5,7 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use dioxus_core::Template;
pub use dioxus_hot_reload_macro::hot_reload; pub use dioxus_hot_reload_macro::hot_reload;
use dioxus_html::HtmlCtx; use dioxus_html::HtmlCtx;
use dioxus_rsx::hot_reload::{FileMap, UpdateResult}; use dioxus_rsx::hot_reload::{FileMap, UpdateResult};
@ -15,13 +16,30 @@ pub fn init(path: &'static str) {
if let Ok(crate_dir) = PathBuf::from_str(path) { if let Ok(crate_dir) = PathBuf::from_str(path) {
let temp_file = std::env::temp_dir().join("@dioxusin"); let temp_file = std::env::temp_dir().join("@dioxusin");
let channels = Arc::new(Mutex::new(Vec::new())); let channels = Arc::new(Mutex::new(Vec::new()));
let file_map = Arc::new(Mutex::new(FileMap::<HtmlCtx>::new(crate_dir.clone())));
if let Ok(local_socket_stream) = LocalSocketListener::bind(temp_file.as_path()) { if let Ok(local_socket_stream) = LocalSocketListener::bind(temp_file.as_path()) {
// listen for connections // listen for connections
std::thread::spawn({ std::thread::spawn({
let file_map = file_map.clone();
let channels = channels.clone(); let channels = channels.clone();
move || { move || {
for connection in local_socket_stream.incoming() { for connection in local_socket_stream.incoming() {
if let Ok(connection) = connection { if let Ok(mut connection) = connection {
// send any templates than have changed before the socket connected
let templates: Vec<_> = {
file_map
.lock()
.unwrap()
.map
.values()
.filter_map(|(_, template_slot)| *template_slot)
.collect()
};
for template in templates {
if !send_template(template, &mut connection) {
continue;
}
}
channels.lock().unwrap().push(connection); channels.lock().unwrap().push(connection);
println!("Connected to hot reloading 🚀"); println!("Connected to hot reloading 🚀");
} }
@ -32,7 +50,6 @@ pub fn init(path: &'static str) {
// watch for changes // watch for changes
std::thread::spawn(move || { std::thread::spawn(move || {
let mut last_update_time = chrono::Local::now().timestamp(); let mut last_update_time = chrono::Local::now().timestamp();
let mut file_map = FileMap::<HtmlCtx>::new(crate_dir.clone());
let (tx, rx) = std::sync::mpsc::channel(); let (tx, rx) = std::sync::mpsc::channel();
@ -58,13 +75,21 @@ pub fn init(path: &'static str) {
} }
// find changes to the rsx in the file // find changes to the rsx in the file
match file_map.update_rsx(&path, crate_dir.as_path()) { match file_map
.lock()
.unwrap()
.update_rsx(&path, crate_dir.as_path())
{
UpdateResult::UpdatedRsx(msgs) => { UpdateResult::UpdatedRsx(msgs) => {
for msg in msgs { for msg in msgs {
for channel in channels.iter_mut() { let mut i = 0;
let msg = serde_json::to_string(&msg).unwrap(); while i < channels.len() {
channel.write_all(msg.as_bytes()).unwrap(); let channel = &mut channels[i];
channel.write_all(&[b'\n']).unwrap(); if send_template(msg, channel) {
i += 1;
} else {
channels.remove(i);
}
} }
} }
} }
@ -82,3 +107,17 @@ pub fn init(path: &'static str) {
} }
} }
} }
fn send_template(template: Template<'static>, channel: &mut impl Write) -> bool {
if let Ok(msg) = serde_json::to_string(&template) {
if channel.write_all(msg.as_bytes()).is_err() {
return false;
}
if channel.write_all(&[b'\n']).is_err() {
return false;
}
true
} else {
false
}
}

View file

@ -17,7 +17,9 @@ pub(crate) fn init(proxy: UnboundedSender<Template<'static>>) {
Ok(_) => { Ok(_) => {
let template: Template<'static> = let template: Template<'static> =
serde_json::from_str(Box::leak(buf.into_boxed_str())).unwrap(); serde_json::from_str(Box::leak(buf.into_boxed_str())).unwrap();
proxy.send(template).unwrap(); if proxy.send(template).is_err() {
return;
}
} }
Err(err) => { Err(err) => {
if err.kind() != std::io::ErrorKind::WouldBlock { if err.kind() != std::io::ErrorKind::WouldBlock {