Răsfoiți Sursa

app: add is_started flag so we can avoid calling init() twice for nodes added during runtime in the theme

darkfi 13 ore în urmă
părinte
comite
4146de0d42
2 a modificat fișierele cu 15 adăugiri și 4 ștergeri
  1. 5 0
      bin/app/src/app/mod.rs
  2. 10 4
      bin/app/src/theme/mod.rs

+ 5 - 0
bin/app/src/app/mod.rs

@@ -71,6 +71,8 @@ pub struct App {
     /// True on the first run of a new app version, i.e. when no version
     /// or a different one is recorded in the app DB. Loaded in `setup()`.
     pub is_first_time: AtomicBool,
+    /// True once App::start() has finished its init/start tree walks.
+    pub is_started: AtomicBool,
     /// The installed theme's ctx (journal, tracked nodes); `None` when
     /// the minimal baseline is active. The active theme name lives in
     /// `/setting/theme`.
@@ -91,6 +93,7 @@ impl App {
             redraw_trigger,
             redraw_rx,
             is_first_time: AtomicBool::new(false),
+            is_started: AtomicBool::new(false),
             theme_ctx: SyncMutex::new(None),
             kv_db: std::sync::OnceLock::new(),
         })
@@ -243,6 +246,8 @@ impl App {
         self.redraw_trigger.trigger();
 
         self.start_procs(event_pub).await;
+
+        self.is_started.store(true, Ordering::Release);
         i!("App started");
     }
 

+ 10 - 4
bin/app/src/theme/mod.rs

@@ -27,7 +27,7 @@
 //! a complete look (design D1/D6).
 
 use parking_lot::Mutex as SyncMutex;
-use std::sync::Arc;
+use std::sync::{atomic::Ordering, Arc};
 
 use tracing::{error, info};
 
@@ -234,9 +234,15 @@ impl ThemeCtx {
         // run once at App::start and never again, so nodes linked at
         // runtime would sit dead — pimpls that load resources in init()
         // (Video::load_video) or register when_change handlers in
-        // start() would never run them. Null pimpls (data-only token
-        // nodes) have no lifecycle to run.
-        if !matches!(child.pimpl(), Pimpl::Null) {
+        // start() would never run them. Nodes linked before App::start
+        // skip this: the startup tree walk covers them, and running the
+        // lifecycle here as well would init/start them twice. Null
+        // pimpls (data-only token nodes) have no lifecycle to run.
+        let mut is_started = true;
+        if let Some(app) = &self.app {
+            is_started = app.is_started.load(Ordering::Acquire);
+        }
+        if !matches!(child.pimpl(), Pimpl::Null) && is_started {
             let obj = get_ui_object3(&child);
             obj.init();
             if let Some(app) = &self.app {