add profile switched event

This commit is contained in:
Eduard Gert
2026-05-18 10:38:13 +02:00
parent 5bdccfe8f4
commit 32f62f3ed8
3 changed files with 20 additions and 0 deletions

View File

@@ -59,6 +59,7 @@ func (s *stringList) Set(v string) error {
func init() {
application.RegisterEvent[services.Status](services.EventStatus)
application.RegisterEvent[services.SystemEvent](services.EventSystem)
application.RegisterEvent[services.ProfileRef](services.EventProfileChanged)
application.RegisterEvent[updater.State](updater.EventStateChanged)
application.RegisterEvent[preferences.UIPreferences](preferences.EventPreferencesChanged)
}

View File

@@ -27,6 +27,13 @@ const (
// forwarded here to updater.Holder.OnSystemEvent so the typed update
// state can be maintained without a second daemon subscription.
EventSystem = "netbird:event"
// EventProfileChanged fires after ProfileSwitcher.SwitchActive completes
// a daemon-side switch. The payload is the new ProfileRef. Both tray
// and React subscribers refresh their profile views off this so a flip
// driven from one surface (tray menu, settings page) paints in the
// others without polling. The daemon itself does not emit a profile
// event, so this is the only signal that closes the gap.
EventProfileChanged = "netbird:profile:changed"
// StatusDaemonUnavailable is the synthetic Status the UI emits when the
// daemon's gRPC socket is unreachable (daemon not running, socket

View File

@@ -57,6 +57,9 @@ type ProfileSwitcher struct {
}
// NewProfileSwitcher creates a ProfileSwitcher backed by the given services.
// EventProfileChanged is emitted via peers.emitter (same package), so React
// refreshes after a tray-driven switch and vice versa — the daemon does
// not emit a dedicated profile event.
func NewProfileSwitcher(profiles *Profiles, connection *Connection, peers *Peers) *ProfileSwitcher {
return &ProfileSwitcher{profiles: profiles, connection: connection, peers: peers}
}
@@ -124,5 +127,14 @@ func (s *ProfileSwitcher) SwitchActive(ctx context.Context, p ProfileRef) error
}
}
// Fan out the switch to every UI surface. The daemon does not emit a
// profile event, so without this the React ProfileContext stays on the
// old profile after a tray-initiated switch (and the tray's profile
// submenu would lag a React-initiated one, except the tray rebuilds on
// every status transition).
if s.peers != nil && s.peers.emitter != nil {
s.peers.emitter.Emit(EventProfileChanged, p)
}
return nil
}