From b27ed5e0cffc3847b0cd60f6e08d515d98fba09f Mon Sep 17 00:00:00 2001 From: Hakan Sariman Date: Sun, 22 Jun 2025 10:44:06 +0300 Subject: [PATCH] feat: implement default profile and enhance profile management UI --- .../internal/profilemanager/profilemanager.go | 2 + client/ui/client_ui.go | 17 +++-- client/ui/event_handler.go | 10 --- client/ui/profile.go | 62 +++++++++++++++++-- 4 files changed, 66 insertions(+), 25 deletions(-) diff --git a/client/internal/profilemanager/profilemanager.go b/client/internal/profilemanager/profilemanager.go index 35d7b997a..ca62f48a9 100644 --- a/client/internal/profilemanager/profilemanager.go +++ b/client/internal/profilemanager/profilemanager.go @@ -114,6 +114,8 @@ func (pm *ProfileManager) ListProfiles() ([]Profile, error) { } var profiles []Profile + // add default profile always + profiles = append(profiles, Profile{Name: "default", IsActive: activeProfName == "default"}) for _, file := range files { profileName := strings.TrimSuffix(filepath.Base(file), ".json") var isActive bool diff --git a/client/ui/client_ui.go b/client/ui/client_ui.go index ed6d5ad66..055a38995 100644 --- a/client/ui/client_ui.go +++ b/client/ui/client_ui.go @@ -221,11 +221,10 @@ type serviceClient struct { // systray menu items mStatus *systray.MenuItem - mProfileName *systray.MenuItem mUp *systray.MenuItem mDown *systray.MenuItem mSettings *systray.MenuItem - mProfiles *systray.MenuItem + mProfile *profileMenu mAbout *systray.MenuItem mGitHub *systray.MenuItem mVersionUI *systray.MenuItem @@ -722,14 +721,12 @@ func (s *serviceClient) onTrayReady() { s.mStatus = systray.AddMenuItem("Disconnected", "Disconnected") s.mStatus.SetIcon(s.icDisconnectedDot) s.mStatus.Disable() - s.mProfileName = systray.AddMenuItem("hakan_work", "Selected Profile: Home") - systray.AddMenuItem("(hakan.@gmail.com)", "").Disable() - s.mProfiles = s.mProfileName - s.mProfileName.AddSubMenuItem("hakan_work", "Selected Profile: Personal").Check() - s.mProfileName.AddSubMenuItem("hakan_personal", "Selected Profile: Personal") - s.mProfileName.AddSubMenuItem("common", "Selected Profile: Common") - s.mProfileName.AddSeparator() - s.mProfileName.AddSubMenuItem("Manage Profiles", "Selected Profile: Work") + + s.profileManager = profilemanager.NewProfileManager() + profileMenuItem := systray.AddMenuItem("", "") + emailMenuItem := systray.AddMenuItem("", "") + s.mProfile = newProfileMenu(s.profileManager, profileMenuItem, emailMenuItem) + systray.AddSeparator() s.mUp = systray.AddMenuItem("Connect", "Connect") s.mDown = systray.AddMenuItem("Disconnect", "Disconnect") diff --git a/client/ui/event_handler.go b/client/ui/event_handler.go index c04b91f60..5441f3481 100644 --- a/client/ui/event_handler.go +++ b/client/ui/event_handler.go @@ -49,8 +49,6 @@ func (h *eventHandler) listen(ctx context.Context) { h.handleAdvancedSettingsClick() case <-h.client.mCreateDebugBundle.ClickedCh: h.handleCreateDebugBundleClick() - case <-h.client.mProfiles.ClickedCh: - h.handleProfilesClick() case <-h.client.mQuit.ClickedCh: h.handleQuitClick() return @@ -136,14 +134,6 @@ func (h *eventHandler) handleCreateDebugBundleClick() { }() } -func (h *eventHandler) handleProfilesClick() { - h.client.mProfiles.Disable() - go func() { - defer h.client.mProfiles.Enable() - h.runSelfCommand("profiles", "true") - }() -} - func (h *eventHandler) handleQuitClick() { systray.Quit() } diff --git a/client/ui/profile.go b/client/ui/profile.go index 5b7b743d4..179cc8f77 100644 --- a/client/ui/profile.go +++ b/client/ui/profile.go @@ -9,11 +9,17 @@ import ( "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/widget" + "fyne.io/systray" log "github.com/sirupsen/logrus" "github.com/netbirdio/netbird/client/internal/profilemanager" ) +type profile struct { + name string + selected bool +} + // showProfilesUI creates and displays the Profiles window with a list of existing profiles, // a button to add new profiles, allows removal, and lets the user switch the active profile. func (s *serviceClient) showProfilesUI() { @@ -185,11 +191,6 @@ func (s *serviceClient) showProfilesUI() { s.wProfiles.Show() } -type profile struct { - name string - selected bool -} - // func (p *profileMenu) updateProfiles(ctx context.Context, conn proto.DaemonServiceClient) { // profiles, err := p.getProfiles(ctx, conn) // if err != nil { @@ -243,3 +244,54 @@ func (s *serviceClient) getProfiles() ([]profilemanager.Profile, error) { } return prof, nil } + +type profileMenu struct { + profileManager *profilemanager.ProfileManager + profileMenuItem *systray.MenuItem + emailMenuItem *systray.MenuItem + profileItems []*systray.MenuItem + manageProfilesItem *systray.MenuItem +} + +func newProfileMenu(profileManager *profilemanager.ProfileManager, profileMenuItem, emailMenuItem *systray.MenuItem) *profileMenu { + p := profileMenu{ + profileManager: profileManager, + profileMenuItem: profileMenuItem, + emailMenuItem: emailMenuItem, + } + + p.refresh() + + return &p +} + +func (p *profileMenu) refresh() { + profiles, err := p.profileManager.ListProfiles() + if err != nil { + log.Errorf("failed to list profiles: %v", err) + return + } + + // Clear existing profile items + for _, item := range p.profileItems { + item.Remove() + } + + if p.manageProfilesItem != nil { + // Remove the manage profiles item if it exists + p.manageProfilesItem.Remove() + } + + for _, profile := range profiles { + item := p.profileMenuItem.AddSubMenuItem(profile.Name, "") + if profile.IsActive { + item.Check() + } + + p.profileItems = append(p.profileItems, item) + // TODO(hakan): handle switch profile + } + p.profileMenuItem.AddSeparator() + p.manageProfilesItem = p.profileMenuItem.AddSubMenuItem("Manage Profiles", "") + +}