mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-08 09:49:54 +00:00
[client/ui-wails] Slim the tray menu, move toggles to Settings page
The Fyne 1:1 tray pulled the entire daemon-config knobset (Allow SSH,
Connect on Startup, Quantum-Resistance, Lazy Connections, Block Inbound,
Notifications) into a Settings submenu — useful in a tray-only UI but
redundant now that the Wails app has a real Settings page. Drop the
submenu and route a single top-level "Settings" entry to /settings;
"Create Debug Bundle" stays at the top level for support workflows.
Side effects:
- flipFlag and ptrBool go away with the checkbox callbacks.
- loadConfig keeps seeding notificationsEnabled (the tray still gates
OS toasts in onSystemEvent on it) but no longer mirrors any other
config field.
- Unused menu/notify constants (Allow SSH, Connect on Startup, ...,
notifyErrorSettingsFmt) are removed from the central const block.
This commit is contained in:
@@ -33,15 +33,11 @@ const (
|
||||
menuNetworks = "Networks"
|
||||
menuQuit = "Quit"
|
||||
|
||||
// Settings submenu.
|
||||
// Settings + diagnostics. The settings page replaces the Fyne tray's
|
||||
// Settings submenu (per-toggle checkboxes for SSH, auto-connect,
|
||||
// Rosenpass, lazy connections, block-inbound, notifications); those
|
||||
// live in the in-window Settings page now.
|
||||
menuSettings = "Settings"
|
||||
menuAllowSSH = "Allow SSH"
|
||||
menuConnectOnStartup = "Connect on Startup"
|
||||
menuQuantumResistance = "Enable Quantum-Resistance"
|
||||
menuLazyConnections = "Enable Lazy Connections"
|
||||
menuBlockInbound = "Block Inbound Connections"
|
||||
menuNotifications = "Notifications"
|
||||
menuAdvancedSettings = "Advanced Settings"
|
||||
menuCreateDebugBundle = "Create Debug Bundle"
|
||||
|
||||
// About submenu and update flow.
|
||||
@@ -60,7 +56,6 @@ const (
|
||||
notifyErrorTitle = "Error"
|
||||
notifyErrorConnect = "Failed to connect"
|
||||
notifyErrorDisconnect = "Failed to disconnect"
|
||||
notifyErrorSettingsFmt = "Failed to update %s settings"
|
||||
|
||||
// Notification IDs (used to coalesce duplicate toasts).
|
||||
notifyIDUpdatePrefix = "netbird-update-"
|
||||
@@ -86,18 +81,12 @@ type Tray struct {
|
||||
notifier *notifications.NotificationService
|
||||
update *services.Update
|
||||
|
||||
statusItem *application.MenuItem
|
||||
upItem *application.MenuItem
|
||||
downItem *application.MenuItem
|
||||
exitNodeItem *application.MenuItem
|
||||
networksItem *application.MenuItem
|
||||
allowSSHItem *application.MenuItem
|
||||
autoConnItem *application.MenuItem
|
||||
rosenpassItem *application.MenuItem
|
||||
lazyConnItem *application.MenuItem
|
||||
blockInItem *application.MenuItem
|
||||
notifyItem *application.MenuItem
|
||||
updateItem *application.MenuItem
|
||||
statusItem *application.MenuItem
|
||||
upItem *application.MenuItem
|
||||
downItem *application.MenuItem
|
||||
exitNodeItem *application.MenuItem
|
||||
networksItem *application.MenuItem
|
||||
updateItem *application.MenuItem
|
||||
|
||||
mu sync.Mutex
|
||||
connected bool
|
||||
@@ -199,35 +188,20 @@ func (t *Tray) buildMenu() *application.Menu {
|
||||
|
||||
menu.AddSeparator()
|
||||
|
||||
settingsSub := menu.AddSubmenu(menuSettings)
|
||||
t.allowSSHItem = settingsSub.AddCheckbox(menuAllowSSH, false).OnClick(func(*application.Context) {
|
||||
t.flipFlag("ssh", t.allowSSHItem.Checked())
|
||||
})
|
||||
t.autoConnItem = settingsSub.AddCheckbox(menuConnectOnStartup, false).OnClick(func(*application.Context) {
|
||||
t.flipFlag("auto", t.autoConnItem.Checked())
|
||||
})
|
||||
t.rosenpassItem = settingsSub.AddCheckbox(menuQuantumResistance, false).OnClick(func(*application.Context) {
|
||||
t.flipFlag("rosenpass", t.rosenpassItem.Checked())
|
||||
})
|
||||
t.lazyConnItem = settingsSub.AddCheckbox(menuLazyConnections, false).OnClick(func(*application.Context) {
|
||||
t.flipFlag("lazy", t.lazyConnItem.Checked())
|
||||
})
|
||||
t.blockInItem = settingsSub.AddCheckbox(menuBlockInbound, false).OnClick(func(*application.Context) {
|
||||
t.flipFlag("blockin", t.blockInItem.Checked())
|
||||
})
|
||||
t.notifyItem = settingsSub.AddCheckbox(menuNotifications, true).OnClick(func(*application.Context) {
|
||||
t.flipFlag("notify", t.notifyItem.Checked())
|
||||
})
|
||||
settingsSub.AddSeparator()
|
||||
settingsSub.Add(menuAdvancedSettings).OnClick(func(*application.Context) { t.openRoute("/settings") })
|
||||
settingsSub.Add(menuCreateDebugBundle).OnClick(func(*application.Context) { t.openRoute("/debug") })
|
||||
|
||||
t.exitNodeItem = menu.Add(menuExitNode).SetEnabled(false)
|
||||
|
||||
t.networksItem = menu.Add(menuNetworks).OnClick(func(*application.Context) { t.openRoute("/networks") })
|
||||
|
||||
menu.AddSeparator()
|
||||
|
||||
// Settings, runtime toggles (SSH, Quantum-Resistance, lazy connection,
|
||||
// block-inbound, auto-connect, notifications) and profile switching
|
||||
// all live in the in-window Settings page now. The tray menu only
|
||||
// surfaces the day-to-day actions.
|
||||
menu.Add(menuSettings).OnClick(func(*application.Context) { t.openRoute("/settings") })
|
||||
menu.Add(menuCreateDebugBundle).OnClick(func(*application.Context) { t.openRoute("/debug") })
|
||||
|
||||
menu.AddSeparator()
|
||||
|
||||
about := menu.AddSubmenu(menuAbout)
|
||||
about.Add(menuGitHub).OnClick(func(*application.Context) {
|
||||
_ = t.app.Browser.OpenURL(urlGitHubRepo)
|
||||
@@ -291,69 +265,6 @@ func (t *Tray) handleDisconnect() {
|
||||
}()
|
||||
}
|
||||
|
||||
// flipFlag pushes a partial SetConfig for one tray-toggled boolean. On
|
||||
// failure the tray checkbox is reverted to keep it in sync with the daemon
|
||||
// and an error notification is fired so the user knows the change didn't
|
||||
// stick. The "notify" flag also updates the in-process gate that decides
|
||||
// whether daemon SystemEvents become OS notifications.
|
||||
func (t *Tray) flipFlag(name string, checked bool) {
|
||||
go func() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
t.mu.Lock()
|
||||
profile, username := t.activeProfile, t.activeUsername
|
||||
t.mu.Unlock()
|
||||
|
||||
req := services.SetConfigParams{ProfileName: profile, Username: username}
|
||||
var (
|
||||
label string
|
||||
item *application.MenuItem
|
||||
)
|
||||
switch name {
|
||||
case "ssh":
|
||||
req.ServerSSHAllowed = ptrBool(checked)
|
||||
label, item = "SSH", t.allowSSHItem
|
||||
case "auto":
|
||||
// "Connect on Startup" is the inverse of disableAutoConnect.
|
||||
req.DisableAutoConnect = ptrBool(!checked)
|
||||
label, item = "auto-connect", t.autoConnItem
|
||||
case "rosenpass":
|
||||
req.RosenpassEnabled = ptrBool(checked)
|
||||
label, item = "Rosenpass", t.rosenpassItem
|
||||
case "lazy":
|
||||
req.LazyConnectionEnabled = ptrBool(checked)
|
||||
label, item = "lazy connection", t.lazyConnItem
|
||||
case "blockin":
|
||||
req.BlockInbound = ptrBool(checked)
|
||||
label, item = "block inbound", t.blockInItem
|
||||
case "notify":
|
||||
req.DisableNotifications = ptrBool(!checked)
|
||||
label, item = "notifications", t.notifyItem
|
||||
default:
|
||||
log.Debugf("tray flipFlag: unknown flag %q", name)
|
||||
return
|
||||
}
|
||||
|
||||
if err := t.settings.SetConfig(ctx, req); err != nil {
|
||||
log.Errorf("set %s: %v", label, err)
|
||||
t.notifyError(fmt.Sprintf(notifyErrorSettingsFmt, label))
|
||||
if item != nil {
|
||||
item.SetChecked(!checked) // revert
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if name == "notify" {
|
||||
t.mu.Lock()
|
||||
t.notificationsEnabled = checked
|
||||
t.mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func ptrBool(b bool) *bool { return &b }
|
||||
|
||||
func (t *Tray) onStatusEvent(ev *application.CustomEvent) {
|
||||
st, ok := ev.Data.(services.Status)
|
||||
if !ok {
|
||||
@@ -604,9 +515,15 @@ func (t *Tray) iconForState() (icon, dark []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// loadConfig syncs the tray-submenu checkboxes with the daemon's stored
|
||||
// config and seeds the notifications gate. Called once at startup from a
|
||||
// goroutine so a slow or unreachable daemon does not block menu construction.
|
||||
// loadConfig seeds the in-process notifications gate from the daemon's
|
||||
// stored config and caches the active-profile identity for any future
|
||||
// SetConfig calls. Called once at startup from a goroutine so a slow or
|
||||
// unreachable daemon does not block menu construction.
|
||||
//
|
||||
// The Settings page in the main window is the source of truth for every
|
||||
// other knob (SSH, auto-connect, Rosenpass, lazy connections, block-inbound,
|
||||
// notifications); we only mirror the notifications flag because the tray
|
||||
// itself uses it to gate OS toasts in onSystemEvent.
|
||||
func (t *Tray) loadConfig() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
@@ -627,25 +544,6 @@ func (t *Tray) loadConfig() {
|
||||
t.activeUsername = active.Username
|
||||
t.notificationsEnabled = !cfg.DisableNotifications
|
||||
t.mu.Unlock()
|
||||
|
||||
if t.allowSSHItem != nil {
|
||||
t.allowSSHItem.SetChecked(cfg.ServerSSHAllowed)
|
||||
}
|
||||
if t.autoConnItem != nil {
|
||||
t.autoConnItem.SetChecked(!cfg.DisableAutoConnect)
|
||||
}
|
||||
if t.rosenpassItem != nil {
|
||||
t.rosenpassItem.SetChecked(cfg.RosenpassEnabled)
|
||||
}
|
||||
if t.lazyConnItem != nil {
|
||||
t.lazyConnItem.SetChecked(cfg.LazyConnectionEnabled)
|
||||
}
|
||||
if t.blockInItem != nil {
|
||||
t.blockInItem.SetChecked(cfg.BlockInbound)
|
||||
}
|
||||
if t.notifyItem != nil {
|
||||
t.notifyItem.SetChecked(!cfg.DisableNotifications)
|
||||
}
|
||||
}
|
||||
|
||||
// notify wraps the Wails notification service with the tray's standard
|
||||
|
||||
Reference in New Issue
Block a user