diff --git a/crates/feature_flags/src/feature_flags.rs b/crates/feature_flags/src/feature_flags.rs index ae2980c699fd190543ec53b1950652b42bd66259..dadcab383f091e4de81fac8e9d6e67940c60d2f5 100644 --- a/crates/feature_flags/src/feature_flags.rs +++ b/crates/feature_flags/src/feature_flags.rs @@ -259,12 +259,14 @@ impl FeatureFlagAppExt for App { { self.observe_global::(move |cx| { let store = cx.global::(); - callback( - OnFlagsReady { - is_staff: store.is_staff(), - }, - cx, - ); + if store.server_flags_received() { + callback( + OnFlagsReady { + is_staff: store.is_staff(), + }, + cx, + ); + } }) } diff --git a/crates/feature_flags/src/store.rs b/crates/feature_flags/src/store.rs index 54d261fc7261a06e49051b783ea423db727a3a64..a8376de7e3a878e971d8aa243e0d48c8de69f137 100644 --- a/crates/feature_flags/src/store.rs +++ b/crates/feature_flags/src/store.rs @@ -70,6 +70,7 @@ macro_rules! register_feature_flag { pub struct FeatureFlagStore { staff: bool, server_flags: HashMap, + server_flags_received: bool, _settings_subscription: Option, } @@ -95,12 +96,17 @@ impl FeatureFlagStore { self.staff } + pub fn server_flags_received(&self) -> bool { + self.server_flags_received + } + pub fn set_staff(&mut self, staff: bool) { self.staff = staff; } pub fn update_server_flags(&mut self, staff: bool, flags: Vec) { self.staff = staff; + self.server_flags_received = true; self.server_flags.clear(); for flag in flags { self.server_flags.insert(flag.clone(), flag); @@ -371,4 +377,32 @@ mod tests { assert_eq!(store.try_flag_value::(cx), None); assert_eq!(PresenceFlag::default(), PresenceFlag::Off); } + + #[gpui::test] + fn on_flags_ready_waits_for_server_flags(cx: &mut gpui::TestAppContext) { + use crate::FeatureFlagAppExt; + use std::cell::Cell; + use std::rc::Rc; + + cx.update(|cx| { + init_settings_store(cx); + FeatureFlagStore::init(cx); + }); + + let fired = Rc::new(Cell::new(false)); + cx.update({ + let fired = fired.clone(); + |cx| cx.on_flags_ready(move |_, _| fired.set(true)).detach() + }); + + // Settings-triggered no-op touch must not fire on_flags_ready. + cx.update(|cx| cx.update_default_global::(|_, _| {})); + cx.run_until_parked(); + assert!(!fired.get()); + + // Server flags arrive — now it should fire. + cx.update(|cx| cx.update_flags(true, vec![])); + cx.run_until_parked(); + assert!(fired.get()); + } }