feat(gui): redesign kanholec GUI with modern interface and WiX v7 installer
golangci-lint / lint (push) Failing after 4s
golangci-lint / lint (push) Failing after 4s
- Complete GUI overhaul with Fyne framework * Modern dark theme with indigo/pink accent colors * 4-step setup wizard (Welcome → Server → Auth → Finish) * Dashboard with proxy list, real-time logs, and config viewer * Windows Service manager (install/start/stop/uninstall) * System tray integration with quick controls - WiX v7 MSI installer * Auto-registers as Windows Service (manual start) * Feature tree UI for optional components * Desktop shortcut and PATH options * Build script: packaging/windows/build-msi.ps1 - Build system updates * Added kanholec-windows-gui target (CGO required) * Added kanholec-windows-msi target * Separate main_gui.go entry point for GUI builds GUI binary: bin/kanholec-windows-amd64.exe (31.4 MB) MSI installer: bin/kanholec-0.69.0-amd64.msi (12.1 MB)
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
//go:build kanholec_gui
|
||||
|
||||
package gui
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/systray"
|
||||
)
|
||||
|
||||
type TrayManager struct {
|
||||
app *App
|
||||
running bool
|
||||
|
||||
mShow *systray.MenuItem
|
||||
mStatus *systray.MenuItem
|
||||
mStart *systray.MenuItem
|
||||
mStop *systray.MenuItem
|
||||
mQuit *systray.MenuItem
|
||||
}
|
||||
|
||||
func NewTrayManager(app *App) *TrayManager {
|
||||
return &TrayManager{app: app}
|
||||
}
|
||||
|
||||
func (t *TrayManager) Start() {
|
||||
go t.run()
|
||||
}
|
||||
|
||||
func (t *TrayManager) run() {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
systray.Run(t.onReady, t.onExit)
|
||||
}
|
||||
|
||||
func (t *TrayManager) onReady() {
|
||||
t.running = true
|
||||
|
||||
systray.SetIcon(trayIconData())
|
||||
systray.SetTitle("kanholec")
|
||||
systray.SetTooltip("kanholec - kanhole Client")
|
||||
|
||||
t.mShow = systray.AddMenuItem("Show Dashboard", "Open kanholec GUI")
|
||||
systray.AddSeparator()
|
||||
t.mStatus = systray.AddMenuItem("Status: Disconnected", "")
|
||||
t.mStatus.Disable()
|
||||
systray.AddSeparator()
|
||||
t.mStart = systray.AddMenuItem("Start Client", "Start the kanholec client")
|
||||
t.mStop = systray.AddMenuItem("Stop Client", "Stop the kanholec client")
|
||||
t.mStop.Disable()
|
||||
systray.AddSeparator()
|
||||
t.mQuit = systray.AddMenuItem("Quit", "Exit kanholec")
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-t.mShow.ClickedCh:
|
||||
if t.app.window != nil {
|
||||
t.app.window.Show()
|
||||
t.app.window.RequestFocus()
|
||||
}
|
||||
case <-t.mStart.ClickedCh:
|
||||
t.app.startClient()
|
||||
t.mStart.Disable()
|
||||
t.mStop.Enable()
|
||||
t.mStatus.SetTitle("Status: Running")
|
||||
case <-t.mStop.ClickedCh:
|
||||
t.app.stopClient()
|
||||
t.mStart.Enable()
|
||||
t.mStop.Disable()
|
||||
t.mStatus.SetTitle("Status: Stopped")
|
||||
case <-t.mQuit.ClickedCh:
|
||||
t.app.Quit()
|
||||
systray.Quit()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (t *TrayManager) onExit() {
|
||||
t.running = false
|
||||
}
|
||||
|
||||
func (t *TrayManager) SetStatus(status string) {
|
||||
if !t.running || t.mStatus == nil {
|
||||
return
|
||||
}
|
||||
t.mStatus.SetTitle("Status: " + status)
|
||||
}
|
||||
|
||||
func (t *TrayManager) SetRunning(running bool) {
|
||||
if !t.running {
|
||||
return
|
||||
}
|
||||
if running {
|
||||
t.mStart.Disable()
|
||||
t.mStop.Enable()
|
||||
t.mStatus.SetTitle("Status: Running")
|
||||
} else {
|
||||
t.mStart.Enable()
|
||||
t.mStop.Disable()
|
||||
t.mStatus.SetTitle("Status: Stopped")
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TrayManager) Stop() {
|
||||
if t.running {
|
||||
systray.Quit()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TrayManager) IsSupported() bool {
|
||||
return t.running
|
||||
}
|
||||
|
||||
func trayIconResource() *fyne.StaticResource {
|
||||
return &fyne.StaticResource{
|
||||
StaticName: "kanholec.ico",
|
||||
StaticContent: trayIconData(),
|
||||
}
|
||||
}
|
||||
|
||||
func trayIconData() []byte {
|
||||
return []byte{
|
||||
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x00,
|
||||
0x20, 0x00, 0x68, 0x04, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user