diff --git a/cmd/vpnapp/main_windows.go b/cmd/vpnapp/main_windows.go index 62d5f86..e943539 100644 --- a/cmd/vpnapp/main_windows.go +++ b/cmd/vpnapp/main_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows package main @@ -40,25 +40,26 @@ type app struct { } type uiState struct { - Connected bool `json:"connected"` - Profile string `json:"profile,omitempty"` - ActiveProfile string `json:"active_profile,omitempty"` - Protocol string `json:"protocol,omitempty"` - HTTPProxy string `json:"http_proxy,omitempty"` - SOCKSProxy string `json:"socks_proxy,omitempty"` - SystemProxy bool `json:"system_proxy"` - Proxy string `json:"proxy"` - CoreReady bool `json:"core_ready"` - CorePath string `json:"core_path,omitempty"` - ConfigPath string `json:"config_path"` - Profiles []config.ProfileInfo `json:"profiles"` - Version string `json:"version"` - Update update.Status `json:"update"` - Pings []netcheck.Result `json:"pings"` - Subscription string `json:"subscription_url"` - Remnawave remnawave.Settings `json:"remnawave"` - Hy2 core.Hy2Options `json:"hy2"` - StorePackaged bool `json:"store_packaged,omitempty"` + Connected bool `json:"connected"` + Profile string `json:"profile,omitempty"` + ActiveProfile string `json:"active_profile,omitempty"` + Protocol string `json:"protocol,omitempty"` + HTTPProxy string `json:"http_proxy,omitempty"` + SOCKSProxy string `json:"socks_proxy,omitempty"` + SystemProxy bool `json:"system_proxy"` + Proxy string `json:"proxy"` + CoreReady bool `json:"core_ready"` + CorePath string `json:"core_path,omitempty"` + ConfigPath string `json:"config_path"` + Profiles []config.ProfileInfo `json:"profiles"` + Version string `json:"version"` + Update update.Status `json:"update"` + Pings []netcheck.Result `json:"pings"` + Subscription string `json:"subscription_url"` + SubInfo *config.SubscriptionInfo `json:"sub_info,omitempty"` + Remnawave remnawave.Settings `json:"remnawave"` + Hy2 core.Hy2Options `json:"hy2"` + StorePackaged bool `json:"store_packaged,omitempty"` } func main() { @@ -213,6 +214,7 @@ func (a *app) getState() (uiState, error) { Update: a.updateStatus, Pings: append([]netcheck.Result(nil), a.pings...), Subscription: cfg.SubscriptionURL, + SubInfo: a.mgr.SubscriptionInfo(), Remnawave: a.mgr.RemnawaveSettings(), Hy2: a.mgr.ActiveHy2Options(), StorePackaged: update.IsStorePackaged(), @@ -327,7 +329,7 @@ func (a *app) saveHy2(opts core.Hy2Options) error { return a.mgr.SaveHy2Options(opts) } -func (a *app) importSubscription(rawURL string) (int, error) { +func (a *app) importSubscription(rawURL string) (core.ImportResult, error) { return a.mgr.ImportSubscription(rawURL) } @@ -335,7 +337,7 @@ func (a *app) saveRemnawave(s remnawave.Settings) error { return a.mgr.SaveRemnawaveSettings(s) } -func (a *app) importRemnawave(s remnawave.Settings) (int, error) { +func (a *app) importRemnawave(s remnawave.Settings) (core.ImportResult, error) { return a.mgr.ImportRemnawave(s) } diff --git a/dist/navis-release/update.json b/dist/navis-release/update.json index 41ec907..f25830d 100644 --- a/dist/navis-release/update.json +++ b/dist/navis-release/update.json @@ -1,16 +1,16 @@ -{ +{ "version": "3.9.0", - "notes": "3.9.0: Remnawave API config delivery, Remnawave-inspired UI + flags, Windows 3.9.0.1.", + "notes": "3.9.0+2: tolerant subscription import (skips broken entries), full server list from Remnawave subs, subscription info card (expiry / traffic / devices). Windows 3.9.0.2.", "platform": "windows-amd64", "os": "windows", "arch": "amd64", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/windows/Navis.exe", - "sha256": "ba2d2860c771dc99081b4fa9cea147a8da4495a93c55aacfb11e6114e3a7a614", + "sha256": "cba03d356be00b4bae9a2ffb013f035ecc2cd9c167c02aa1b2afee08576920f7", "mandatory": false, "platforms": { "windows-amd64": { "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/windows/Navis.exe", - "sha256": "ba2d2860c771dc99081b4fa9cea147a8da4495a93c55aacfb11e6114e3a7a614", + "sha256": "cba03d356be00b4bae9a2ffb013f035ecc2cd9c167c02aa1b2afee08576920f7", "os": "windows", "arch": "amd64" }, diff --git a/dist/navis-release/windows/Navis.exe b/dist/navis-release/windows/Navis.exe index 3de5264..ad37bc4 100644 Binary files a/dist/navis-release/windows/Navis.exe and b/dist/navis-release/windows/Navis.exe differ diff --git a/dist/navis-release/windows/vpnclient.exe b/dist/navis-release/windows/vpnclient.exe index fc673cc..8de84c4 100644 Binary files a/dist/navis-release/windows/vpnclient.exe and b/dist/navis-release/windows/vpnclient.exe differ diff --git a/dist/update.json b/dist/update.json index 41ec907..f25830d 100644 --- a/dist/update.json +++ b/dist/update.json @@ -1,16 +1,16 @@ -{ +{ "version": "3.9.0", - "notes": "3.9.0: Remnawave API config delivery, Remnawave-inspired UI + flags, Windows 3.9.0.1.", + "notes": "3.9.0+2: tolerant subscription import (skips broken entries), full server list from Remnawave subs, subscription info card (expiry / traffic / devices). Windows 3.9.0.2.", "platform": "windows-amd64", "os": "windows", "arch": "amd64", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/windows/Navis.exe", - "sha256": "ba2d2860c771dc99081b4fa9cea147a8da4495a93c55aacfb11e6114e3a7a614", + "sha256": "cba03d356be00b4bae9a2ffb013f035ecc2cd9c167c02aa1b2afee08576920f7", "mandatory": false, "platforms": { "windows-amd64": { "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/windows/Navis.exe", - "sha256": "ba2d2860c771dc99081b4fa9cea147a8da4495a93c55aacfb11e6114e3a7a614", + "sha256": "cba03d356be00b4bae9a2ffb013f035ecc2cd9c167c02aa1b2afee08576920f7", "os": "windows", "arch": "amd64" }, diff --git a/internal/apphost/app.go b/internal/apphost/app.go index 27f5ee8..5ac0c87 100644 --- a/internal/apphost/app.go +++ b/internal/apphost/app.go @@ -27,36 +27,37 @@ import ( // App is the GUI controller shared by Windows WebView and macOS HTTP UI. type App struct { - mu sync.Mutex - Mgr *core.Manager - CfgPath string - LogBuf *bytes.Buffer - UpdateStatus update.Status - Pings []netcheck.Result - OpenURL func(string) error + mu sync.Mutex + Mgr *core.Manager + CfgPath string + LogBuf *bytes.Buffer + UpdateStatus update.Status + Pings []netcheck.Result + OpenURL func(string) error OnAfterUpdate func() } type UIState struct { - Connected bool `json:"connected"` - Profile string `json:"profile,omitempty"` - ActiveProfile string `json:"active_profile,omitempty"` - Protocol string `json:"protocol,omitempty"` - HTTPProxy string `json:"http_proxy,omitempty"` - SOCKSProxy string `json:"socks_proxy,omitempty"` - SystemProxy bool `json:"system_proxy"` - Proxy string `json:"proxy"` - CoreReady bool `json:"core_ready"` - CorePath string `json:"core_path,omitempty"` - ConfigPath string `json:"config_path"` - Profiles []config.ProfileInfo `json:"profiles"` - Version string `json:"version"` - Update update.Status `json:"update"` - Pings []netcheck.Result `json:"pings"` - Subscription string `json:"subscription_url"` - Remnawave remnawave.Settings `json:"remnawave"` - Hy2 core.Hy2Options `json:"hy2"` - StorePackaged bool `json:"store_packaged,omitempty"` + Connected bool `json:"connected"` + Profile string `json:"profile,omitempty"` + ActiveProfile string `json:"active_profile,omitempty"` + Protocol string `json:"protocol,omitempty"` + HTTPProxy string `json:"http_proxy,omitempty"` + SOCKSProxy string `json:"socks_proxy,omitempty"` + SystemProxy bool `json:"system_proxy"` + Proxy string `json:"proxy"` + CoreReady bool `json:"core_ready"` + CorePath string `json:"core_path,omitempty"` + ConfigPath string `json:"config_path"` + Profiles []config.ProfileInfo `json:"profiles"` + Version string `json:"version"` + Update update.Status `json:"update"` + Pings []netcheck.Result `json:"pings"` + Subscription string `json:"subscription_url"` + SubInfo *config.SubscriptionInfo `json:"sub_info,omitempty"` + Remnawave remnawave.Settings `json:"remnawave"` + Hy2 core.Hy2Options `json:"hy2"` + StorePackaged bool `json:"store_packaged,omitempty"` } type PingBestResult struct { @@ -132,6 +133,7 @@ func (a *App) GetState() (UIState, error) { Update: a.UpdateStatus, Pings: append([]netcheck.Result(nil), a.Pings...), Subscription: cfg.SubscriptionURL, + SubInfo: a.Mgr.SubscriptionInfo(), Remnawave: a.Mgr.RemnawaveSettings(), Hy2: a.Mgr.ActiveHy2Options(), StorePackaged: update.IsStorePackaged(), @@ -239,7 +241,7 @@ func (a *App) SaveHy2(opts core.Hy2Options) error { return a.Mgr.SaveHy2Options(opts) } -func (a *App) ImportSubscription(rawURL string) (int, error) { +func (a *App) ImportSubscription(rawURL string) (core.ImportResult, error) { return a.Mgr.ImportSubscription(rawURL) } @@ -247,7 +249,7 @@ func (a *App) SaveRemnawave(s remnawave.Settings) error { return a.Mgr.SaveRemnawaveSettings(s) } -func (a *App) ImportRemnawave(s remnawave.Settings) (int, error) { +func (a *App) ImportRemnawave(s remnawave.Settings) (core.ImportResult, error) { return a.Mgr.ImportRemnawave(s) } diff --git a/internal/appui/index.html b/internal/appui/index.html index a5c9973..1e1b621 100644 --- a/internal/appui/index.html +++ b/internal/appui/index.html @@ -507,6 +507,35 @@ font-weight: 600; font-size: .9rem; } + .subinfo { + border: 1px solid var(--line); + border-radius: 14px; + background: var(--row-bg); + padding: 11px 13px; + margin-bottom: 12px; + display: grid; + gap: 7px; + } + .subinfo-title { + font-family: Outfit, sans-serif; + font-size: .72rem; + font-weight: 700; + letter-spacing: .05em; + text-transform: uppercase; + color: var(--muted); + } + .subinfo-row { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 12px; + font-size: .84rem; + } + .subinfo-row .k { color: var(--muted); flex: 0 0 auto; } + .subinfo-row .v { font-weight: 700; text-align: right; min-width: 0; } + .subinfo-row .v.warn { color: #dc2626; } + [data-theme="dark"] .subinfo-row .v.warn { color: #f87171; } + .switch { position: relative; width: 44px; height: 26px; flex: 0 0 auto; } .switch input { opacity: 0; width: 0; height: 0; } .slider { @@ -1002,6 +1031,22 @@ + +
Системный прокси