Skip to content

Commit 8ec2934

Browse files
committed
add systray menu network selection
1 parent cda2cb4 commit 8ec2934

File tree

5 files changed

+271
-15
lines changed

5 files changed

+271
-15
lines changed

cmd/massastation/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ func main() {
8181

8282
pluginManager := plugin.NewManager(configDir)
8383

84-
stationGUI, systrayMenu := systray.MakeGUI()
8584
// Create shared config manager once and inject into server
8685
configManager, err := config.GetConfigManager()
8786
if err != nil {
8887
logger.Fatalf("Failed to initialize config manager: %s", err.Error())
8988
}
89+
stationGUI, systrayMenu := systray.New()
9090
server := api.NewServer(serverFlags, configManager)
9191

9292
update.StartUpdateCheck(&stationGUI, systrayMenu)

int/config/manager.go

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,16 @@ const (
2626
// ErrNetworkAlreadyExists is returned when trying to add a network with a name that already exists
2727
var ErrNetworkAlreadyExists = errors.New("network already exists")
2828

29+
// NetworkChangeCallback is a function type called when the network changes.
30+
type NetworkChangeCallback func()
31+
2932
// MSConfigManager represents a manager for network configurations.
3033
type MSConfigManager struct {
31-
Network NetworkConfig
32-
configMutex sync.RWMutex
33-
stopRefresh func()
34+
Network NetworkConfig
35+
configMutex sync.RWMutex
36+
stopRefresh func()
37+
onNetworkChange NetworkChangeCallback
38+
networkChangeMutex sync.RWMutex
3439
}
3540

3641
// NetworkManager is an alias for backward compatibility
@@ -130,7 +135,14 @@ func newMSConfigManager() (*MSConfigManager, error) {
130135
}
131136

132137
func (n *MSConfigManager) CurrentNetwork() *RPCInfos {
133-
return n.Network.currentNetwork
138+
n.configMutex.RLock()
139+
defer n.configMutex.RUnlock()
140+
if n.Network.currentNetwork == nil {
141+
return nil
142+
}
143+
// Return a copy to avoid data races when caller accesses fields after lock release
144+
networkCopy := *n.Network.currentNetwork
145+
return &networkCopy
134146
}
135147

136148
// Networks returns a slice of available network names (for backward compatibility)
@@ -145,12 +157,28 @@ func (n *MSConfigManager) Networks() *[]string {
145157
return &options
146158
}
147159

160+
// GetNetworkInfos returns a thread-safe copy of all network configurations.
161+
func (n *MSConfigManager) GetNetworkInfos() []RPCInfos {
162+
n.configMutex.RLock()
163+
defer n.configMutex.RUnlock()
164+
165+
networks := make([]RPCInfos, len(n.Network.Networks))
166+
copy(networks, n.Network.Networks)
167+
return networks
168+
}
169+
170+
// SetNetworkChangeCallback sets a callback function that will be called whenever the network changes.
171+
func (n *MSConfigManager) SetNetworkChangeCallback(callback NetworkChangeCallback) {
172+
n.networkChangeMutex.Lock()
173+
defer n.networkChangeMutex.Unlock()
174+
n.onNetworkChange = callback
175+
}
176+
148177
// SwitchNetwork switches the current network configuration to the specified network.
149178
// rpcName: The name of the network configuration to switch to.
150179
// Returns any error encountered during the switch operation.
151180
func (n *MSConfigManager) SwitchNetwork(rpcName string) error {
152181
n.configMutex.Lock()
153-
defer n.configMutex.Unlock()
154182

155183
// Find the network with the specified name
156184
var targetNetwork *RPCInfos
@@ -162,6 +190,7 @@ func (n *MSConfigManager) SwitchNetwork(rpcName string) error {
162190
}
163191

164192
if targetNetwork == nil {
193+
n.configMutex.Unlock()
165194
return fmt.Errorf("unknown network: %s", rpcName)
166195
}
167196

@@ -170,6 +199,16 @@ func (n *MSConfigManager) SwitchNetwork(rpcName string) error {
170199

171200
logger.Debugf("Switched to network: %s", rpcName)
172201

202+
n.configMutex.Unlock()
203+
204+
// Call the network change callback if set
205+
n.networkChangeMutex.RLock()
206+
callback := n.onNetworkChange
207+
n.networkChangeMutex.RUnlock()
208+
if callback != nil {
209+
callback()
210+
}
211+
173212
return nil
174213
}
175214

@@ -277,15 +316,16 @@ func (n *MSConfigManager) SaveConfig(cfg *ConfigFile) error {
277316
// AddNetwork adds a new network to both memory and persistent configuration
278317
func (n *MSConfigManager) AddNetwork(name, url string, makeDefault bool) error {
279318
n.configMutex.Lock()
280-
defer n.configMutex.Unlock()
281319

282320
if name == "" || url == "" {
321+
n.configMutex.Unlock()
283322
return fmt.Errorf("name and url are required")
284323
}
285324

286325
// Load current persisted configuration
287326
cfg, err := LoadConfig()
288327
if err != nil {
328+
n.configMutex.Unlock()
289329
return fmt.Errorf("load config: %w", err)
290330
}
291331

@@ -297,6 +337,7 @@ func (n *MSConfigManager) AddNetwork(name, url string, makeDefault bool) error {
297337
nameLower := strings.ToLower(strings.TrimSpace(name))
298338
for existingName := range cfg.Networks {
299339
if strings.ToLower(strings.TrimSpace(existingName)) == nameLower {
340+
n.configMutex.Unlock()
300341
return fmt.Errorf("%w: %s", ErrNetworkAlreadyExists, name)
301342
}
302343
}
@@ -315,6 +356,7 @@ func (n *MSConfigManager) AddNetwork(name, url string, makeDefault bool) error {
315356
}
316357

317358
if err := saveConfigUnsafe(cfg); err != nil {
359+
n.configMutex.Unlock()
318360
return err
319361
}
320362

@@ -334,8 +376,22 @@ func (n *MSConfigManager) AddNetwork(name, url string, makeDefault bool) error {
334376
}
335377
n.Network.Networks = append(n.Network.Networks, newNet)
336378

379+
networkChanged := false
337380
if makeDefault {
338381
n.Network.currentNetwork = &n.Network.Networks[len(n.Network.Networks)-1]
382+
networkChanged = true
383+
}
384+
385+
n.configMutex.Unlock()
386+
387+
// Call the network change callback if set
388+
if networkChanged {
389+
n.networkChangeMutex.RLock()
390+
callback := n.onNetworkChange
391+
n.networkChangeMutex.RUnlock()
392+
if callback != nil {
393+
callback()
394+
}
339395
}
340396

341397
return nil
@@ -346,22 +402,25 @@ func (n *MSConfigManager) AddNetwork(name, url string, makeDefault bool) error {
346402
// and the current network is switched in memory as well.
347403
func (n *MSConfigManager) EditNetwork(currentName string, newURL *string, makeDefault *bool, newName *string) error {
348404
n.configMutex.Lock()
349-
defer n.configMutex.Unlock()
350405

351406
if currentName == "" {
407+
n.configMutex.Unlock()
352408
return fmt.Errorf("currentName is required")
353409
}
354410

355411
cfg, err := LoadConfig()
356412
if err != nil {
413+
n.configMutex.Unlock()
357414
return fmt.Errorf("load config: %w", err)
358415
}
359416
if cfg.Networks == nil {
417+
n.configMutex.Unlock()
360418
return fmt.Errorf("no networks configured")
361419
}
362420

363421
item, exists := cfg.Networks[currentName]
364422
if !exists {
423+
n.configMutex.Unlock()
365424
return fmt.Errorf("unknown network: %s", currentName)
366425
}
367426

@@ -371,6 +430,7 @@ func (n *MSConfigManager) EditNetwork(currentName string, newURL *string, makeDe
371430
newNameLower := strings.ToLower(strings.TrimSpace(*newName))
372431
for existingName := range cfg.Networks {
373432
if strings.ToLower(strings.TrimSpace(existingName)) == newNameLower {
433+
n.configMutex.Unlock()
374434
return fmt.Errorf("%w: %s", ErrNetworkAlreadyExists, *newName)
375435
}
376436
}
@@ -405,6 +465,7 @@ func (n *MSConfigManager) EditNetwork(currentName string, newURL *string, makeDe
405465
}
406466

407467
if err := saveConfigUnsafe(cfg); err != nil {
468+
n.configMutex.Unlock()
408469
return err
409470
}
410471

@@ -450,10 +511,25 @@ func (n *MSConfigManager) EditNetwork(currentName string, newURL *string, makeDe
450511
}
451512

452513
// Switch current network if default requested or if current was renamed
514+
networkChanged := false
453515
if makeDefault != nil && *makeDefault {
454516
n.Network.currentNetwork = &n.Network.Networks[targetIdx]
517+
networkChanged = true
455518
} else if n.Network.currentNetwork != nil && n.Network.currentNetwork.Name == currentName && targetName != currentName {
456519
n.Network.currentNetwork = &n.Network.Networks[targetIdx]
520+
networkChanged = true
521+
}
522+
523+
n.configMutex.Unlock()
524+
525+
// Call the network change callback if set
526+
if networkChanged {
527+
n.networkChangeMutex.RLock()
528+
callback := n.onNetworkChange
529+
n.networkChangeMutex.RUnlock()
530+
if callback != nil {
531+
callback()
532+
}
457533
}
458534

459535
return nil

0 commit comments

Comments
 (0)