修复按钮逻辑bug

This commit is contained in:
2026-07-07 13:34:48 +08:00
parent e08480f609
commit 9c16d804d9
4 changed files with 76 additions and 52 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ APP_BUNDLE = $(APP_NAME).app
GO = go GO = go
CGO_ENABLED = 1 CGO_ENABLED = 1
GIT_HASH = $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) GIT_HASH = $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
VERSION = 0.2.6-$(GIT_HASH) VERSION = 0.3.2-$(GIT_HASH)
LDFLAGS = -s -w -X lmvpn/internal/version.Version=$(VERSION) LDFLAGS = -s -w -X lmvpn/internal/version.Version=$(VERSION)
.PHONY: all build app run daemon clean vet tidy fmt icon .PHONY: all build app run daemon clean vet tidy fmt icon
+27 -17
View File
@@ -112,13 +112,26 @@ func Run() {
hideDockIcon() hideDockIcon()
a.window.Hide() a.window.Hide()
} else { } else {
a.fyneApp.Quit() a.quit()
} }
}) })
a.window.ShowAndRun() a.window.ShowAndRun()
} }
// quit disconnects any active VPN session (via the daemon) and then
// quits the application. The daemon process itself remains running.
func (a *App) quit() {
a.mu.Lock()
client := a.ipcClient
a.ipcClient = nil
a.mu.Unlock()
if client != nil {
_ = ipc.SendStop(client)
}
a.fyneApp.Quit()
}
// loadProfiles loads all profiles from the database and populates the // loadProfiles loads all profiles from the database and populates the
// selector. // selector.
func (a *App) loadProfiles() { func (a *App) loadProfiles() {
@@ -218,18 +231,17 @@ func (a *App) onResetDB() {
// Reset UI state. // Reset UI state.
a.currentProfile = nil a.currentProfile = nil
a.loadProfiles() a.loadProfiles()
a.stateLabel.SetText(i18n.T("StateDisconnected")) a.stateLabel.SetText(i18n.T("StateDisconnected"))
a.ipLabel.SetText(i18n.T("IpNone")) a.ipLabel.SetText(i18n.T("IpNone"))
a.ip6Label.SetText(i18n.T("Ip6None")) a.ip6Label.SetText(i18n.T("Ip6None"))
a.uptimeLabel.SetText(i18n.T("UptimeNone")) a.uptimeLabel.SetText(i18n.T("UptimeNone"))
a.rxV4Label.SetText(i18n.T("RxV4Zero")) a.rxV4Label.SetText(i18n.T("RxV4Zero"))
a.txV4Label.SetText(i18n.T("TxV4Zero")) a.txV4Label.SetText(i18n.T("TxV4Zero"))
a.rxV6Label.SetText(i18n.T("RxV6Zero")) a.rxV6Label.SetText(i18n.T("RxV6Zero"))
a.txV6Label.SetText(i18n.T("TxV6Zero")) a.txV6Label.SetText(i18n.T("TxV6Zero"))
a.rxTotalLabel.SetText(i18n.T("RxTotalZero")) a.rxTotalLabel.SetText(i18n.T("RxTotalZero"))
a.txTotalLabel.SetText(i18n.T("TxTotalZero")) a.txTotalLabel.SetText(i18n.T("TxTotalZero"))
a.connectBtn.Enable() a.setConnButtons(true, false)
a.disconnectBtn.Disable()
}, a.window).Show() }, a.window).Show()
} }
@@ -296,12 +308,10 @@ func (a *App) rebuildUI() {
// Restore connection state. // Restore connection state.
if wasConnected { if wasConnected {
a.connectBtn.Disable() a.setConnButtons(false, true)
a.disconnectBtn.Enable()
a.stateLabel.SetText(i18n.T("StateConnected")) a.stateLabel.SetText(i18n.T("StateConnected"))
} else { } else {
a.connectBtn.Enable() a.setConnButtons(true, false)
a.disconnectBtn.Disable()
a.stateLabel.SetText(i18n.T("StateDisconnected")) a.stateLabel.SetText(i18n.T("StateDisconnected"))
} }
+21 -12
View File
@@ -46,24 +46,33 @@ func (a *App) setupTray() {
autoItem, enItem, zhItem, autoItem, enItem, zhItem,
) )
menu := fyne.NewMenu(i18n.T("WindowTitle"), connectItem := fyne.NewMenuItem(i18n.T("TrayConnect"), func() {
fyne.NewMenuItem(i18n.T("TrayShowWindow"), func() {
showDockIcon()
a.window.Show()
a.window.RequestFocus()
}),
fyne.NewMenuItemSeparator(),
fyne.NewMenuItem(i18n.T("TrayConnect"), func() {
a.onConnect() a.onConnect()
}), })
fyne.NewMenuItem(i18n.T("TrayDisconnect"), func() { disconnectItem := fyne.NewMenuItem(i18n.T("TrayDisconnect"), func() {
a.onDisconnect() a.onDisconnect()
}), })
if a.connectBtn != nil {
connectItem.Disabled = a.connectBtn.Disabled()
}
if a.disconnectBtn != nil {
disconnectItem.Disabled = a.disconnectBtn.Disabled()
}
menu := fyne.NewMenu(i18n.T("WindowTitle"),
fyne.NewMenuItem(i18n.T("TrayShowWindow"), func() {
showDockIcon()
a.window.Show()
a.window.RequestFocus()
}),
fyne.NewMenuItemSeparator(),
connectItem,
disconnectItem,
fyne.NewMenuItemSeparator(), fyne.NewMenuItemSeparator(),
langItem, langItem,
fyne.NewMenuItemSeparator(), fyne.NewMenuItemSeparator(),
fyne.NewMenuItem(i18n.T("TrayQuit"), func() { fyne.NewMenuItem(i18n.T("TrayQuit"), func() {
a.fyneApp.Quit() a.quit()
}), }),
) )
deskApp.SetSystemTrayMenu(menu) deskApp.SetSystemTrayMenu(menu)
+27 -22
View File
@@ -19,6 +19,22 @@ func showError(title, message string, parent fyne.Window) {
dialog.NewCustom(title, i18n.T("BtnOK"), widget.NewLabel(message), parent).Show() dialog.NewCustom(title, i18n.T("BtnOK"), widget.NewLabel(message), parent).Show()
} }
// setConnButtons enables/disables the connect and disconnect buttons
// and refreshes the tray menu to match.
func (a *App) setConnButtons(connectEnabled, disconnectEnabled bool) {
if connectEnabled {
a.connectBtn.Enable()
} else {
a.connectBtn.Disable()
}
if disconnectEnabled {
a.disconnectBtn.Enable()
} else {
a.disconnectBtn.Disable()
}
a.setupTray()
}
// buildMainWindow creates the main application window layout. // buildMainWindow creates the main application window layout.
func (a *App) buildMainWindow() fyne.CanvasObject { func (a *App) buildMainWindow() fyne.CanvasObject {
// Profile selector. // Profile selector.
@@ -78,8 +94,7 @@ func (a *App) onConnect() {
return return
} }
a.connectBtn.Disable() a.setConnButtons(false, true)
a.disconnectBtn.Enable()
a.stateLabel.SetText(i18n.T("StateConnecting")) a.stateLabel.SetText(i18n.T("StateConnecting"))
go func() { go func() {
@@ -89,8 +104,7 @@ func (a *App) onConnect() {
fyne.Do(func() { fyne.Do(func() {
showError(i18n.T("DlgDaemonError"), err.Error(), a.window) showError(i18n.T("DlgDaemonError"), err.Error(), a.window)
a.stateLabel.SetText(i18n.T("StateDisconnected")) a.stateLabel.SetText(i18n.T("StateDisconnected"))
a.connectBtn.Enable() a.setConnButtons(true, false)
a.disconnectBtn.Disable()
}) })
return return
} }
@@ -107,8 +121,7 @@ func (a *App) onConnect() {
i18n.T("DlgCredentialErrorMsg"), i18n.T("DlgCredentialErrorMsg"),
a.window) a.window)
a.stateLabel.SetText(i18n.T("StateDisconnected")) a.stateLabel.SetText(i18n.T("StateDisconnected"))
a.connectBtn.Enable() a.setConnButtons(true, false)
a.disconnectBtn.Disable()
}) })
return return
} }
@@ -137,8 +150,7 @@ func (a *App) onConnect() {
fyne.Do(func() { fyne.Do(func() {
showError(i18n.T("DlgIPCError"), err.Error(), a.window) showError(i18n.T("DlgIPCError"), err.Error(), a.window)
a.stateLabel.SetText(i18n.T("StateDisconnected")) a.stateLabel.SetText(i18n.T("StateDisconnected"))
a.connectBtn.Enable() a.setConnButtons(true, false)
a.disconnectBtn.Disable()
}) })
return return
} }
@@ -157,8 +169,7 @@ func (a *App) onDisconnect() {
return return
} }
_ = ipc.SendStop(client) _ = ipc.SendStop(client)
a.disconnectBtn.Disable() a.setConnButtons(true, false)
a.connectBtn.Enable()
a.stateLabel.SetText(i18n.T("StateDisconnected")) a.stateLabel.SetText(i18n.T("StateDisconnected"))
} }
@@ -189,8 +200,7 @@ func (a *App) eventLoop() {
a.txV6Label.SetText(i18n.T("TxV6Zero")) a.txV6Label.SetText(i18n.T("TxV6Zero"))
a.rxTotalLabel.SetText(i18n.T("RxTotalZero")) a.rxTotalLabel.SetText(i18n.T("RxTotalZero"))
a.txTotalLabel.SetText(i18n.T("TxTotalZero")) a.txTotalLabel.SetText(i18n.T("TxTotalZero"))
a.connectBtn.Enable() a.setConnButtons(true, false)
a.disconnectBtn.Disable()
} }
}) })
return return
@@ -222,26 +232,21 @@ func (a *App) applyState(state string) {
switch stats.State(state) { switch stats.State(state) {
case stats.StateConnected: case stats.StateConnected:
a.stateLabel.SetText(i18n.T("StateConnected")) a.stateLabel.SetText(i18n.T("StateConnected"))
a.connectBtn.Disable() a.setConnButtons(false, true)
a.disconnectBtn.Enable()
case stats.StateConnecting: case stats.StateConnecting:
a.stateLabel.SetText(i18n.T("StateConnecting")) a.stateLabel.SetText(i18n.T("StateConnecting"))
a.connectBtn.Disable() a.setConnButtons(false, true)
a.disconnectBtn.Enable()
case stats.StateReconnecting: case stats.StateReconnecting:
a.stateLabel.SetText(i18n.T("StateReconnecting")) a.stateLabel.SetText(i18n.T("StateReconnecting"))
a.connectBtn.Disable() a.setConnButtons(false, true)
a.disconnectBtn.Enable()
case stats.StateDisconnected: case stats.StateDisconnected:
a.stateLabel.SetText(i18n.T("StateDisconnected")) a.stateLabel.SetText(i18n.T("StateDisconnected"))
a.ipLabel.SetText(i18n.T("IpNone")) a.ipLabel.SetText(i18n.T("IpNone"))
a.ip6Label.SetText(i18n.T("Ip6None")) a.ip6Label.SetText(i18n.T("Ip6None"))
a.connectBtn.Enable() a.setConnButtons(true, false)
a.disconnectBtn.Disable()
case stats.StateError: case stats.StateError:
a.stateLabel.SetText(i18n.T("StateError")) a.stateLabel.SetText(i18n.T("StateError"))
a.connectBtn.Enable() a.setConnButtons(true, false)
a.disconnectBtn.Disable()
} }
} }