@@ -35,7 +35,9 @@ import (
35
35
"github.com/netbirdio/netbird/client/proto"
36
36
"github.com/netbirdio/netbird/client/ui/desktop"
37
37
"github.com/netbirdio/netbird/client/ui/event"
38
+ "github.com/netbirdio/netbird/client/ui/process"
38
39
"github.com/netbirdio/netbird/util"
40
+
39
41
"github.com/netbirdio/netbird/version"
40
42
)
41
43
@@ -44,94 +46,125 @@ const (
44
46
failFastTimeout = time .Second
45
47
)
46
48
49
+ const (
50
+ censoredPreSharedKey = "**********"
51
+ )
52
+
47
53
func main () {
48
- var daemonAddr string
54
+ daemonAddr , showSettings , showNetworks , errorMsg , saveLogsInFile := parseFlags ()
55
+
56
+ // Initialize file logging if needed.
57
+ if saveLogsInFile {
58
+ if err := initLogFile (); err != nil {
59
+ log .Errorf ("error while initializing log: %v" , err )
60
+ return
61
+ }
62
+ }
63
+
64
+ // Create the Fyne application.
65
+ a := app .NewWithID ("NetBird" )
66
+ a .SetIcon (fyne .NewStaticResource ("netbird" , iconDisconnected ))
67
+
68
+ // Show error message window if needed.
69
+ if errorMsg != "" {
70
+ showErrorMessage (errorMsg )
71
+ return
72
+ }
73
+
74
+ // Create the service client (this also builds the settings or networks UI if requested).
75
+ client := newServiceClient (daemonAddr , a , showSettings , showNetworks )
49
76
77
+ // Watch for theme/settings changes to update the icon.
78
+ go watchSettingsChanges (a , client )
79
+
80
+ // Run in window mode if any UI flag was set.
81
+ if showSettings || showNetworks {
82
+ a .Run ()
83
+ return
84
+ }
85
+
86
+ // Check for another running process.
87
+ running , err := process .IsAnotherProcessRunning ()
88
+ if err != nil {
89
+ log .Errorf ("error while checking process: %v" , err )
90
+ return
91
+ }
92
+ if running {
93
+ log .Warn ("another process is running" )
94
+ return
95
+ }
96
+
97
+ client .setDefaultFonts ()
98
+ systray .Run (client .onTrayReady , client .onTrayExit )
99
+ }
100
+
101
+ // parseFlags reads and returns all needed command-line flags.
102
+ func parseFlags () (daemonAddr string , showSettings , showNetworks bool , errorMsg string , saveLogsInFile bool ) {
50
103
defaultDaemonAddr := "unix:///var/run/netbird.sock"
51
104
if runtime .GOOS == "windows" {
52
105
defaultDaemonAddr = "tcp://127.0.0.1:41731"
53
106
}
54
-
55
- flag .StringVar (
56
- & daemonAddr , "daemon-addr" ,
57
- defaultDaemonAddr ,
58
- "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]" )
59
-
60
- var showSettings bool
61
- flag .BoolVar (& showSettings , "settings" , false , "run settings windows" )
62
- var showRoutes bool
63
- flag .BoolVar (& showRoutes , "networks" , false , "run networks windows" )
64
- var errorMSG string
65
- flag .StringVar (& errorMSG , "error-msg" , "" , "displays a error message window" )
107
+ flag .StringVar (& daemonAddr , "daemon-addr" , defaultDaemonAddr , "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]" )
108
+ flag .BoolVar (& showSettings , "settings" , false , "run settings window" )
109
+ flag .BoolVar (& showNetworks , "networks" , false , "run networks window" )
110
+ flag .StringVar (& errorMsg , "error-msg" , "" , "displays an error message window" )
66
111
67
112
tmpDir := "/tmp"
68
113
if runtime .GOOS == "windows" {
69
114
tmpDir = os .TempDir ()
70
115
}
71
-
72
- var saveLogsInFile bool
73
116
flag .BoolVar (& saveLogsInFile , "use-log-file" , false , fmt .Sprintf ("save logs in a file: %s/netbird-ui-PID.log" , tmpDir ))
74
-
75
117
flag .Parse ()
118
+ return
119
+ }
76
120
77
- if saveLogsInFile {
78
- logFile := path .Join (tmpDir , fmt .Sprintf ("netbird-ui-%d.log" , os .Getpid ()))
79
- err := util .InitLog ("trace" , logFile )
80
- if err != nil {
81
- log .Errorf ("error while initializing log: %v" , err )
82
- return
83
- }
84
- }
85
-
86
- a := app .NewWithID ("NetBird" )
87
- a .SetIcon (fyne .NewStaticResource ("netbird" , iconDisconnected ))
88
-
89
- if errorMSG != "" {
90
- showErrorMSG (errorMSG )
91
- return
121
+ // initLogFile initializes logging into a file.
122
+ func initLogFile () error {
123
+ tmpDir := "/tmp"
124
+ if runtime .GOOS == "windows" {
125
+ tmpDir = os .TempDir ()
92
126
}
127
+ logFile := path .Join (tmpDir , fmt .Sprintf ("netbird-ui-%d.log" , os .Getpid ()))
128
+ return util .InitLog ("trace" , logFile )
129
+ }
93
130
94
- client := newServiceClient (daemonAddr , a , showSettings , showRoutes )
131
+ // watchSettingsChanges listens for Fyne theme/settings changes and updates the client icon.
132
+ func watchSettingsChanges (a fyne.App , client * serviceClient ) {
95
133
settingsChangeChan := make (chan fyne.Settings )
96
134
a .Settings ().AddChangeListener (settingsChangeChan )
97
- go func () {
98
- for range settingsChangeChan {
99
- client .updateIcon ()
100
- }
101
- }()
102
-
103
- if showSettings || showRoutes {
104
- a .Run ()
105
- } else {
106
- running , err := isAnotherProcessRunning ()
107
- if err != nil {
108
- log .Errorf ("error while checking process: %v" , err )
109
- }
110
- if running {
111
- log .Warn ("another process is running" )
112
- return
113
- }
114
- client .setDefaultFonts ()
115
- systray .Run (client .onTrayReady , client .onTrayExit )
135
+ for range settingsChangeChan {
136
+ client .updateIcon ()
116
137
}
117
138
}
118
139
119
- //go:embed netbird-systemtray-connected-macos.png
140
+ // showErrorMessage displays an error message in a simple window.
141
+ func showErrorMessage (msg string ) {
142
+ a := app .New ()
143
+ w := a .NewWindow ("NetBird Error" )
144
+ label := widget .NewLabel (msg )
145
+ label .Wrapping = fyne .TextWrapWord
146
+ w .SetContent (label )
147
+ w .Resize (fyne .NewSize (400 , 100 ))
148
+ w .Show ()
149
+ a .Run ()
150
+ }
151
+
152
+ //go:embed assets/netbird-systemtray-connected-macos.png
120
153
var iconConnectedMacOS []byte
121
154
122
- //go:embed netbird-systemtray-disconnected-macos.png
155
+ //go:embed assets/ netbird-systemtray-disconnected-macos.png
123
156
var iconDisconnectedMacOS []byte
124
157
125
- //go:embed netbird-systemtray-update-disconnected-macos.png
158
+ //go:embed assets/ netbird-systemtray-update-disconnected-macos.png
126
159
var iconUpdateDisconnectedMacOS []byte
127
160
128
- //go:embed netbird-systemtray-update-connected-macos.png
161
+ //go:embed assets/ netbird-systemtray-update-connected-macos.png
129
162
var iconUpdateConnectedMacOS []byte
130
163
131
- //go:embed netbird-systemtray-connecting-macos.png
164
+ //go:embed assets/ netbird-systemtray-connecting-macos.png
132
165
var iconConnectingMacOS []byte
133
166
134
- //go:embed netbird-systemtray-error-macos.png
167
+ //go:embed assets/ netbird-systemtray-error-macos.png
135
168
var iconErrorMacOS []byte
136
169
137
170
type serviceClient struct {
@@ -301,18 +334,6 @@ func (s *serviceClient) showSettingsUI() {
301
334
s .wSettings .Show ()
302
335
}
303
336
304
- // showErrorMSG opens a fyne app window to display the supplied message
305
- func showErrorMSG (msg string ) {
306
- app := app .New ()
307
- w := app .NewWindow ("NetBird Error" )
308
- content := widget .NewLabel (msg )
309
- content .Wrapping = fyne .TextWrapWord
310
- w .SetContent (content )
311
- w .Resize (fyne .NewSize (400 , 100 ))
312
- w .Show ()
313
- app .Run ()
314
- }
315
-
316
337
// getSettingsForm to embed it into settings window.
317
338
func (s * serviceClient ) getSettingsForm () * widget.Form {
318
339
return & widget.Form {
@@ -328,7 +349,7 @@ func (s *serviceClient) getSettingsForm() *widget.Form {
328
349
},
329
350
SubmitText : "Save" ,
330
351
OnSubmit : func () {
331
- if s .iPreSharedKey .Text != "" && s .iPreSharedKey .Text != "**********" {
352
+ if s .iPreSharedKey .Text != "" && s .iPreSharedKey .Text != censoredPreSharedKey {
332
353
// validate preSharedKey if it added
333
354
if _ , err := wgtypes .ParseKey (s .iPreSharedKey .Text ); err != nil {
334
355
dialog .ShowError (fmt .Errorf ("Invalid Pre-shared Key Value" ), s .wSettings )
@@ -366,7 +387,7 @@ func (s *serviceClient) getSettingsForm() *widget.Form {
366
387
WireguardPort : & port ,
367
388
}
368
389
369
- if s .iPreSharedKey .Text != "**********" {
390
+ if s .iPreSharedKey .Text != censoredPreSharedKey {
370
391
loginRequest .OptionalPreSharedKey = & s .iPreSharedKey .Text
371
392
}
372
393
@@ -588,21 +609,21 @@ func (s *serviceClient) onTrayReady() {
588
609
s .mAdminPanel = systray .AddMenuItem ("Admin Panel" , "Netbird Admin Panel" )
589
610
systray .AddSeparator ()
590
611
591
- s .mSettings = systray .AddMenuItem ("Settings" , "Settings of the application" )
592
- s .mAllowSSH = s .mSettings .AddSubMenuItemCheckbox ("Allow SSH" , "Allow SSH connections" , false )
593
- s .mAutoConnect = s .mSettings .AddSubMenuItemCheckbox ("Connect on Startup" , "Connect automatically when the service starts" , false )
594
- s .mEnableRosenpass = s .mSettings .AddSubMenuItemCheckbox ("Enable Quantum-Resistance" , "Enable post-quantum security via Rosenpass" , false )
595
- s .mNotifications = s .mSettings .AddSubMenuItemCheckbox ("Notifications" , "Enable notifications" , false )
596
- s .mAdvancedSettings = s .mSettings .AddSubMenuItem ("Advanced Settings" , "Advanced settings of the application" )
597
- s .mCreateDebugBundle = s .mSettings .AddSubMenuItem ("Create Debug Bundle" , "Create and open debug information bundle" )
612
+ s .mSettings = systray .AddMenuItem ("Settings" , settingsMenuDescr )
613
+ s .mAllowSSH = s .mSettings .AddSubMenuItemCheckbox ("Allow SSH" , allowSSHMenuDescr , false )
614
+ s .mAutoConnect = s .mSettings .AddSubMenuItemCheckbox ("Connect on Startup" , autoConnectMenuDescr , false )
615
+ s .mEnableRosenpass = s .mSettings .AddSubMenuItemCheckbox ("Enable Quantum-Resistance" , quantumResistanceMenuDescr , false )
616
+ s .mNotifications = s .mSettings .AddSubMenuItemCheckbox ("Notifications" , notificationsMenuDescr , false )
617
+ s .mAdvancedSettings = s .mSettings .AddSubMenuItem ("Advanced Settings" , advancedSettingsMenuDescr )
618
+ s .mCreateDebugBundle = s .mSettings .AddSubMenuItem ("Create Debug Bundle" , debugBundleMenuDescr )
598
619
s .loadSettings ()
599
620
600
621
s .exitNodeMu .Lock ()
601
- s .mExitNode = systray .AddMenuItem ("Exit Node" , "Select exit node for routing traffic" )
622
+ s .mExitNode = systray .AddMenuItem ("Exit Node" , exitNodeMenuDescr )
602
623
s .mExitNode .Disable ()
603
624
s .exitNodeMu .Unlock ()
604
625
605
- s .mNetworks = systray .AddMenuItem ("Networks" , "Open the networks management window" )
626
+ s .mNetworks = systray .AddMenuItem ("Networks" , networksMenuDescr )
606
627
s .mNetworks .Disable ()
607
628
systray .AddSeparator ()
608
629
@@ -619,11 +640,11 @@ func (s *serviceClient) onTrayReady() {
619
640
s .mVersionDaemon .Disable ()
620
641
s .mVersionDaemon .Hide ()
621
642
622
- s .mUpdate = s .mAbout .AddSubMenuItem ("Download latest version" , "Download latest version" )
643
+ s .mUpdate = s .mAbout .AddSubMenuItem ("Download latest version" , latestVersionMenuDescr )
623
644
s .mUpdate .Hide ()
624
645
625
646
systray .AddSeparator ()
626
- s .mQuit = systray .AddMenuItem ("Quit" , "Quit the client app" )
647
+ s .mQuit = systray .AddMenuItem ("Quit" , quitMenuDescr )
627
648
628
649
// update exit node menu in case service is already connected
629
650
go s .updateExitNodes ()
0 commit comments