ranim/cmd/preview/
hot_reload.rs1use std::sync::{
4 Arc, Once,
5 atomic::{AtomicBool, Ordering},
6};
7
8use eframe::egui;
9
10struct Notification {
11 pending: AtomicBool,
12 ctx: egui::Context,
13}
14
15pub(super) struct HotReload(Arc<Notification>);
18
19impl HotReload {
20 pub(super) fn new(ctx: egui::Context) -> Self {
21 let notification = Arc::new(Notification {
22 pending: AtomicBool::new(false),
23 ctx,
24 });
25 let weak = Arc::downgrade(¬ification);
26 dioxus_devtools::subsecond::register_handler(Arc::new(move || {
27 if let Some(notification) = weak.upgrade() {
28 notification.pending.store(true, Ordering::Release);
29 notification.ctx.request_repaint();
30 }
31 }));
32
33 static CONNECT: Once = Once::new();
35 CONNECT.call_once(dioxus_devtools::connect_subsecond);
36 Self(notification)
37 }
38
39 pub(super) fn take_pending(&self) -> bool {
40 self.0.pending.swap(false, Ordering::AcqRel)
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn notifications_coalesce_and_are_consumed_once() {
50 let reload = HotReload(Arc::new(Notification {
52 pending: AtomicBool::new(false),
53 ctx: egui::Context::default(),
54 }));
55 assert!(!reload.take_pending());
56 reload.0.pending.store(true, Ordering::Release);
57 reload.0.pending.store(true, Ordering::Release);
58 assert!(reload.take_pending());
59 assert!(!reload.take_pending());
60 }
61}