Display protocol and TLS status on the panel (#231)

* Display protocol and TLS status on the panel

* Improve proxy translation

* Upgrade ui package

* Update screenshots
This commit is contained in:
Gerhard Tan
2025-04-15 23:00:48 +08:00
committed by GitHub
parent 54f94e829f
commit c27ea5ef86
15 changed files with 680 additions and 585 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 72 KiB

2
go.mod
View File

@ -64,4 +64,4 @@ require (
sigs.k8s.io/yaml v1.3.0 // indirect
)
replace github.com/lxn/walk => github.com/koho/frpmgr v0.0.0-20250413103505-f0a017b962b3
replace github.com/lxn/walk => github.com/koho/frpmgr v0.0.0-20250415081305-b17721ccd57c

4
go.sum
View File

@ -66,8 +66,8 @@ github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/4
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/reedsolomon v1.12.0 h1:I5FEp3xSwVCcEh3F5A7dofEfhXdF/bWhQWPH+XwBFno=
github.com/klauspost/reedsolomon v1.12.0/go.mod h1:EPLZJeh4l27pUGC3aXOjheaoh1I9yut7xTURiW3LQ9Y=
github.com/koho/frpmgr v0.0.0-20250413103505-f0a017b962b3 h1:UTMmkSnq0+SWSGoIyrklIJvCYcm7zYfX2r6SVDxcLy0=
github.com/koho/frpmgr v0.0.0-20250413103505-f0a017b962b3/go.mod h1:BEvTAgZsEET00wLNsOhKg8fX//k6l4b5INTzX2APBb8=
github.com/koho/frpmgr v0.0.0-20250415081305-b17721ccd57c h1:bodaJ1ug+0e1nr2Ks8HR/0MEMO5tECiIY17tmwGSyCw=
github.com/koho/frpmgr v0.0.0-20250415081305-b17721ccd57c/go.mod h1:BEvTAgZsEET00wLNsOhKg8fX//k6l4b5INTzX2APBb8=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=

File diff suppressed because it is too large Load Diff

View File

@ -251,6 +251,20 @@
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "Move Up",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "Move Down",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Configuration",
"message": "Configuration",
@ -1030,9 +1044,9 @@
"fuzzy": true
},
{
"id": "HTTP Proxy",
"message": "HTTP Proxy",
"translation": "HTTP Proxy",
"id": "Proxy URL",
"message": "Proxy URL",
"translation": "Proxy URL",
"translatorComment": "Copied from source.",
"fuzzy": true
},
@ -1713,6 +1727,13 @@
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Your connection to the server is encrypted",
"message": "Your connection to the server is encrypted",
"translation": "Your connection to the server is encrypted",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Start",
"message": "Start",
@ -1953,6 +1974,13 @@
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Proxy Server",
"message": "Proxy Server",
"translation": "Proxy Server",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Disable",
"message": "Disable",
@ -1960,20 +1988,6 @@
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "Move Up",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "Move Down",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Domains",
"message": "Domains",

View File

@ -191,6 +191,16 @@
"message": "Clear All",
"translation": "Limpiar todo"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "Mover hacia arriba"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "Mover hacia abajo"
},
{
"id": "Configuration",
"message": "Configuration",
@ -778,9 +788,9 @@
"translation": "Metadatos"
},
{
"id": "HTTP Proxy",
"message": "HTTP Proxy",
"translation": "Proxy HTTP"
"id": "Proxy URL",
"message": "Proxy URL",
"translation": "URL de proxy"
},
{
"id": "UDP Packet Size",
@ -1277,6 +1287,11 @@
"message": "Remote Address",
"translation": "Dirección remota"
},
{
"id": "Your connection to the server is encrypted",
"message": "Your connection to the server is encrypted",
"translation": "Su conexión al servidor está encriptada"
},
{
"id": "Start",
"message": "Start",
@ -1457,21 +1472,16 @@
"message": "HTTP File Server",
"translation": "Servidor de archivos HTTP"
},
{
"id": "Proxy Server",
"message": "Proxy Server",
"translation": "Servidor proxy"
},
{
"id": "Disable",
"message": "Disable",
"translation": "Deshabilitar"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "Mover hacia arriba"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "Mover hacia abajo"
},
{
"id": "Domains",
"message": "Domains",

View File

@ -191,6 +191,16 @@
"message": "Clear All",
"translation": "すべてクリア"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "上へ移動"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "下へ移動"
},
{
"id": "Configuration",
"message": "Configuration",
@ -788,9 +798,9 @@
"translation": "メタデータ"
},
{
"id": "HTTP Proxy",
"message": "HTTP Proxy",
"translation": "HTTP プロキシ"
"id": "Proxy URL",
"message": "Proxy URL",
"translation": "プロキシURL"
},
{
"id": "UDP Packet Size",
@ -1287,6 +1297,11 @@
"message": "Remote Address",
"translation": "リモートアドレス"
},
{
"id": "Your connection to the server is encrypted",
"message": "Your connection to the server is encrypted",
"translation": "サーバーへの接続は暗号化されています"
},
{
"id": "Start",
"message": "Start",
@ -1467,21 +1482,16 @@
"message": "HTTP File Server",
"translation": "HTTP ファイルサーバー"
},
{
"id": "Proxy Server",
"message": "Proxy Server",
"translation": "プロキシサーバー"
},
{
"id": "Disable",
"message": "Disable",
"translation": "無効"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "上へ移動"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "下へ移動"
},
{
"id": "Domains",
"message": "Domains",

View File

@ -191,6 +191,16 @@
"message": "Clear All",
"translation": "모두 지우기"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "위로 이동"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "아래로 이동"
},
{
"id": "Configuration",
"message": "Configuration",
@ -778,9 +788,9 @@
"translation": "메타데이터"
},
{
"id": "HTTP Proxy",
"message": "HTTP Proxy",
"translation": "HTTP 프록시"
"id": "Proxy URL",
"message": "Proxy URL",
"translation": "프록시 URL"
},
{
"id": "UDP Packet Size",
@ -1277,6 +1287,11 @@
"message": "Remote Address",
"translation": "원격 주소"
},
{
"id": "Your connection to the server is encrypted",
"message": "Your connection to the server is encrypted",
"translation": "서버에 대한 연결이 암호화되었습니다"
},
{
"id": "Start",
"message": "Start",
@ -1457,21 +1472,16 @@
"message": "HTTP File Server",
"translation": "HTTP 파일 서버"
},
{
"id": "Proxy Server",
"message": "Proxy Server",
"translation": "프록시 서버"
},
{
"id": "Disable",
"message": "Disable",
"translation": "폐쇄"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "위로 이동"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "아래로 이동"
},
{
"id": "Domains",
"message": "Domains",

View File

@ -191,6 +191,16 @@
"message": "Clear All",
"translation": "全部清除"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "上移"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "下移"
},
{
"id": "Configuration",
"message": "Configuration",
@ -778,9 +788,9 @@
"translation": "元数据"
},
{
"id": "HTTP Proxy",
"message": "HTTP Proxy",
"translation": "HTTP 代理"
"id": "Proxy URL",
"message": "Proxy URL",
"translation": "代理 URL"
},
{
"id": "UDP Packet Size",
@ -1277,6 +1287,11 @@
"message": "Remote Address",
"translation": "远程地址"
},
{
"id": "Your connection to the server is encrypted",
"message": "Your connection to the server is encrypted",
"translation": "与服务器的连接已加密"
},
{
"id": "Start",
"message": "Start",
@ -1457,21 +1472,16 @@
"message": "HTTP File Server",
"translation": "HTTP 文件服务"
},
{
"id": "Proxy Server",
"message": "Proxy Server",
"translation": "代理服务器"
},
{
"id": "Disable",
"message": "Disable",
"translation": "禁用"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "上移"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "下移"
},
{
"id": "Domains",
"message": "Domains",

View File

@ -191,6 +191,16 @@
"message": "Clear All",
"translation": "全部清除"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "上移"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "下移"
},
{
"id": "Configuration",
"message": "Configuration",
@ -778,9 +788,9 @@
"translation": "元資料"
},
{
"id": "HTTP Proxy",
"message": "HTTP Proxy",
"translation": "HTTP 代理"
"id": "Proxy URL",
"message": "Proxy URL",
"translation": "代理 URL"
},
{
"id": "UDP Packet Size",
@ -1277,6 +1287,11 @@
"message": "Remote Address",
"translation": "遠端位址"
},
{
"id": "Your connection to the server is encrypted",
"message": "Your connection to the server is encrypted",
"translation": "與伺服器的連線已加密"
},
{
"id": "Start",
"message": "Start",
@ -1457,21 +1472,16 @@
"message": "HTTP File Server",
"translation": "HTTP 檔案服務"
},
{
"id": "Proxy Server",
"message": "Proxy Server",
"translation": "代理伺服器"
},
{
"id": "Disable",
"message": "Disable",
"translation": "停用"
},
{
"id": "Move Up",
"message": "Move Up",
"translation": "上移"
},
{
"id": "Move Down",
"message": "Move Down",
"translation": "下移"
},
{
"id": "Domains",
"message": "Domains",

View File

@ -54,6 +54,7 @@ var (
IconHttpProxy = Icon{"imageres", -120}
IconOpenPort = Icon{"shell32", -244}
IconLock = Icon{"shell32", -48}
IconFlatLock = Icon{"imageres", -1304}
IconNewVersion1 = Icon{"imageres", -1028}
IconNewVersion2 = Icon{"imageres", 1}
IconUpdate = Icon{"shell32", -47}
@ -91,26 +92,17 @@ var (
)
func init() {
var defaultFontFamily string
var defaultFontFamily = "Microsoft YaHei UI"
versionInfo := windows.RtlGetVersion()
if versionInfo.MajorVersion > 6 || (versionInfo.MajorVersion == 6 && versionInfo.MinorVersion > 1) {
// > Windows 7
defaultFontFamily = "Microsoft YaHei UI"
} else {
// <= Windows 7
// Microsoft YaHei UI is not included in Windows 7
// Fallback to Microsoft YaHei instead
defaultFontFamily = "Microsoft YaHei"
// Fallback icons
IconKey.Index = -82
IconSSH.Index = -100
IconEnable.Index = -253
}
if versionInfo.MajorVersion == 10 && versionInfo.MinorVersion == 0 {
if versionInfo.BuildNumber < 14393 {
// Windows 10 / Windows 10 1511
IconProxyRunning.Index = IconStateRunning.Index
IconProxyError.Index = -98
// Windows 10
if versionInfo.BuildNumber == 10240 {
IconFlatLock = IconLock
}
} else if versionInfo.BuildNumber == 14393 {
// Windows Server 2016 / Windows 10 1607
IconProxyRunning.Index = -1400

View File

@ -451,8 +451,8 @@ func (cd *EditClientDialog) advancedConnDialog() Dialog {
dlg := NewBasicDialog(nil, i18n.Sprintf("Advanced Options"),
loadIcon(res.IconEditDialog, 32),
DataBinder{DataSource: cd.binder}, nil,
Label{Text: i18n.SprintfColon("HTTP Proxy")},
LineEdit{Text: Bind("HTTPProxy")},
Label{Text: i18n.SprintfColon("Proxy URL")},
LineEdit{Text: Bind("HTTPProxy"), CueBanner: "(http|socks5|ntlm)://..."},
Label{Text: i18n.SprintfColon("UDP Packet Size")},
NewNumberInput(NIOption{Value: Bind("UDPPacketSize"), Max: math.MaxFloat64, Width: 90}),
VSpacer{Size: 4},

View File

@ -1,8 +1,10 @@
package ui
import (
"net/url"
"os"
"path/filepath"
"strings"
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
@ -29,6 +31,8 @@ type PanelView struct {
stateText *walk.Label
stateImage *walk.ImageView
addressText *walk.Label
protoText *walk.Label
protoImage *walk.ImageView
toggleBtn *walk.PushButton
}
@ -52,6 +56,7 @@ func (pv *PanelView) View() Widget {
Children: []Widget{
Label{Text: i18n.SprintfColon("Status"), Row: 0, Column: 0, Alignment: AlignHFarVCenter},
Label{Text: i18n.SprintfColon("Remote Address"), Row: 1, Column: 0, Alignment: AlignHFarVCenter},
Label{Text: i18n.SprintfColon("Protocol"), Row: 2, Column: 0, Alignment: AlignHFarVCenter},
Composite{
Layout: HBox{SpacingZero: true, MarginsZero: true},
Row: 0, Column: 1,
@ -94,9 +99,22 @@ func (pv *PanelView) View() Widget {
},
},
Composite{
Layout: HBox{MarginsZero: true},
Layout: HBox{Spacing: 2, MarginsZero: true},
Row: 2, Column: 1,
Alignment: AlignHNearVCenter,
Children: []Widget{
ImageView{
AssignTo: &pv.protoImage,
Image: loadIcon(res.IconFlatLock, 14),
ToolTipText: i18n.Sprintf("Your connection to the server is encrypted"),
},
Label{AssignTo: &pv.protoText},
},
},
Composite{
Layout: HBox{MarginsZero: true},
Row: 3, Column: 1,
Alignment: AlignHNearVCenter,
Children: []Widget{
PushButton{
AssignTo: &pv.toggleBtn,
@ -205,6 +223,8 @@ func (pv *PanelView) Invalidate(state bool) {
pv.SetTitle("")
pv.setState(consts.ConfigStateUnknown)
pv.addressText.SetText("")
pv.protoText.SetText("")
pv.protoImage.SetVisible(false)
return
}
data := conf.Data.(*config.ClientConfig)
@ -218,6 +238,22 @@ func (pv *PanelView) Invalidate(state bool) {
if pv.addressText.Text() != addr {
pv.addressText.SetText(addr)
}
pv.protoImage.SetVisible(data.TLSEnable || data.Protocol == consts.ProtoWSS || data.Protocol == consts.ProtoQUIC)
proto := data.Protocol
if proto == "" {
proto = consts.ProtoTCP
} else if proto == consts.ProtoWebsocket {
proto = "ws"
}
proto = strings.ToUpper(proto)
if data.HTTPProxy != "" {
if u, err := url.Parse(data.HTTPProxy); err == nil {
proto += " + " + strings.ToUpper(u.Scheme)
}
}
if pv.protoText.Text() != proto {
pv.protoText.SetText(proto)
}
if state {
pv.setState(conf.State)
}

View File

@ -34,20 +34,20 @@ type ProxyView struct {
tracker *ProxyTracker
// Actions
newAction *walk.Action
portAction *walk.Action
rdAction *walk.Action
sshAction *walk.Action
webAction *walk.Action
vncAction *walk.Action
dnsAction *walk.Action
ftpAction *walk.Action
httpFileAction *walk.Action
httpProxyAction *walk.Action
vpnAction *walk.Action
editAction *walk.Action
deleteAction *walk.Action
toggleAction *walk.Action
newAction *walk.Action
portAction *walk.Action
rdAction *walk.Action
sshAction *walk.Action
webAction *walk.Action
vncAction *walk.Action
dnsAction *walk.Action
ftpAction *walk.Action
httpFileAction *walk.Action
proxyServerAction *walk.Action
vpnAction *walk.Action
editAction *walk.Action
deleteAction *walk.Action
toggleAction *walk.Action
}
func NewProxyView() *ProxyView {
@ -243,11 +243,11 @@ func (pv *ProxyView) createToolbar() ToolBar {
},
},
Action{
AssignTo: &pv.httpProxyAction,
Text: i18n.Sprintf("HTTP Proxy"),
AssignTo: &pv.proxyServerAction,
Text: i18n.Sprintf("Proxy Server"),
Image: loadIcon(res.IconHttpProxy, 16),
OnTriggered: func() {
pv.onQuickAdd(NewPluginProxyDialog(i18n.Sprintf("HTTP Proxy"), loadIcon(res.IconHttpProxy, 32),
pv.onQuickAdd(NewPluginProxyDialog(i18n.Sprintf("Proxy Server"), loadIcon(res.IconHttpProxy, 32),
consts.PluginHttpProxy))
},
},
@ -366,7 +366,7 @@ func (pv *ProxyView) createProxyTable() TableView {
ActionRef{Action: &pv.vpnAction},
ActionRef{Action: &pv.ftpAction},
ActionRef{Action: &pv.httpFileAction},
ActionRef{Action: &pv.httpProxyAction},
ActionRef{Action: &pv.proxyServerAction},
},
},
Action{