Expand Gio GUI feature coverage

This commit is contained in:
2026-04-06 08:49:20 +07:00
parent 27d3511bbe
commit d591d61c0b
2 changed files with 303 additions and 6 deletions

View File

@@ -24,6 +24,7 @@ import (
"vpn-client/internal/subscription"
"vpn-client/internal/vless"
"vpn-client/internal/vpn"
"vpn-client/internal/wireguard"
)
type tabID string
@@ -31,6 +32,7 @@ type tabID string
const (
tabDashboard tabID = "dashboard"
tabVLESS tabID = "vless"
tabWireGuard tabID = "wireguard"
tabSubscriptions tabID = "subscriptions"
)
@@ -66,22 +68,29 @@ type ui struct {
tabButtons map[tabID]*widget.Clickable
refreshBtn widget.Clickable
disconnectBtn widget.Clickable
openLogsBtn widget.Clickable
addConfigBtn widget.Clickable
addSubBtn widget.Clickable
testURLBtn widget.Clickable
refreshBtn widget.Clickable
disconnectBtn widget.Clickable
openLogsBtn widget.Clickable
addConfigBtn widget.Clickable
addSubBtn widget.Clickable
testURLBtn widget.Clickable
addWGManualBtn widget.Clickable
addWGFileBtn widget.Clickable
vlessConnectBtns []widget.Clickable
vlessDeleteBtns []widget.Clickable
vlessPingBtns []widget.Clickable
wgConnectBtns []widget.Clickable
wgDeleteBtns []widget.Clickable
subUpdateBtns []widget.Clickable
subDeleteBtns []widget.Clickable
subTestBtns []widget.Clickable
contentList layout.List
vlessList layout.List
wgList layout.List
subList layout.List
configNameEditor widget.Editor
@@ -89,6 +98,10 @@ type ui struct {
subNameEditor widget.Editor
subURLEditor widget.Editor
testURLEditor widget.Editor
wgNameEditor widget.Editor
wgConfigEditor widget.Editor
wgFileNameEditor widget.Editor
wgFilePathEditor widget.Editor
}
func Run(window *app.Window) error {
@@ -126,10 +139,12 @@ func newUI(window *app.Window) *ui {
tabButtons: map[tabID]*widget.Clickable{
tabDashboard: new(widget.Clickable),
tabVLESS: new(widget.Clickable),
tabWireGuard: new(widget.Clickable),
tabSubscriptions: new(widget.Clickable),
},
contentList: layout.List{Axis: layout.Vertical},
vlessList: layout.List{Axis: layout.Vertical},
wgList: layout.List{Axis: layout.Vertical},
subList: layout.List{Axis: layout.Vertical},
}
@@ -138,12 +153,19 @@ func newUI(window *app.Window) *ui {
model.subNameEditor.SingleLine = true
model.subURLEditor.SingleLine = true
model.testURLEditor.SingleLine = true
model.wgNameEditor.SingleLine = true
model.wgFileNameEditor.SingleLine = true
model.wgFilePathEditor.SingleLine = true
model.configNameEditor.Submit = true
model.configURLEditor.Submit = true
model.subNameEditor.Submit = true
model.subURLEditor.Submit = true
model.testURLEditor.Submit = true
model.wgNameEditor.Submit = true
model.wgConfigEditor.Submit = true
model.wgFileNameEditor.Submit = true
model.wgFilePathEditor.Submit = true
model.configURLEditor.SetText("vless://")
model.testURLEditor.SetText("vless://")
@@ -190,6 +212,12 @@ func (u *ui) handleClicks(gtx layout.Context) {
for u.testURLBtn.Clicked(gtx) {
u.testURL()
}
for u.addWGManualBtn.Clicked(gtx) {
u.addWireGuardManual()
}
for u.addWGFileBtn.Clicked(gtx) {
u.addWireGuardFromFile()
}
for i := range u.vlessConnectBtns {
for u.vlessConnectBtns[i].Clicked(gtx) {
@@ -223,6 +251,23 @@ func (u *ui) handleClicks(gtx layout.Context) {
}
}
for i := range u.wgConnectBtns {
for u.wgConnectBtns[i].Clicked(gtx) {
if i < len(u.configs.WireGuard) {
name := u.configs.WireGuard[i].Name
u.runAction("Connecting WireGuard "+name+"...", func() error {
return wireguard.Connect(name, config.LogsDir)
})
}
}
for u.wgDeleteBtns[i].Clicked(gtx) {
if i < len(u.configs.WireGuard) {
name := u.configs.WireGuard[i].Name
u.deleteWireGuardConfig(name)
}
}
}
for i := range u.subUpdateBtns {
for u.subUpdateBtns[i].Clicked(gtx) {
if i < len(u.subs.Subscriptions) {
@@ -238,6 +283,14 @@ func (u *ui) handleClicks(gtx layout.Context) {
u.deleteSubscription(name)
}
}
for u.subTestBtns[i].Clicked(gtx) {
if i < len(u.subs.Subscriptions) {
name := u.subs.Subscriptions[i].Name
u.runAction("Testing configs from "+name+"...", func() error {
return u.testSubscriptionConfigs(name)
})
}
}
}
}
@@ -294,8 +347,11 @@ func (u *ui) ensureButtons() {
u.vlessConnectBtns = ensureClickables(u.vlessConnectBtns, len(u.configs.VLESS))
u.vlessDeleteBtns = ensureClickables(u.vlessDeleteBtns, len(u.configs.VLESS))
u.vlessPingBtns = ensureClickables(u.vlessPingBtns, len(u.configs.VLESS))
u.wgConnectBtns = ensureClickables(u.wgConnectBtns, len(u.configs.WireGuard))
u.wgDeleteBtns = ensureClickables(u.wgDeleteBtns, len(u.configs.WireGuard))
u.subUpdateBtns = ensureClickables(u.subUpdateBtns, len(u.subs.Subscriptions))
u.subDeleteBtns = ensureClickables(u.subDeleteBtns, len(u.subs.Subscriptions))
u.subTestBtns = ensureClickables(u.subTestBtns, len(u.subs.Subscriptions))
}
func ensureClickables(list []widget.Clickable, count int) []widget.Clickable {
@@ -629,6 +685,8 @@ func (u *ui) layoutBody(gtx layout.Context) layout.Dimensions {
switch u.tab {
case tabVLESS:
return u.layoutVLESS(gtx)
case tabWireGuard:
return u.layoutWireGuard(gtx)
case tabSubscriptions:
return u.layoutSubscriptions(gtx)
default:
@@ -649,6 +707,10 @@ func (u *ui) layoutTabs(gtx layout.Context) layout.Dimensions {
return u.layoutTab(gtx, tabVLESS, "VLESS")
}),
layout.Rigid(spacerW(10)),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return u.layoutTab(gtx, tabWireGuard, "WireGuard")
}),
layout.Rigid(spacerW(10)),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return u.layoutTab(gtx, tabSubscriptions, "Subscriptions")
}),