diff --git a/README.md b/README.md index e380951..6094e03 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Navis -Клиент [NaiveProxy](https://github.com/klzgrad/naiveproxy) + [Hysteria 2](https://github.com/apernet/hysteria) + [AmneziaWG 2.0](https://docs.amnezia.org/documentation/amnezia-wg/) + [Xray](https://github.com/XTLS/Xray-core) (VLESS / VMess / Trojan) с профилями, пингом, URL-подпиской и автообновлением. +Клиент [NaiveProxy](https://github.com/klzgrad/naiveproxy) + [Hysteria 2](https://github.com/apernet/hysteria) + [AmneziaWG 2.0](https://docs.amnezia.org/documentation/amnezia-wg/) + [Xray](https://github.com/XTLS/Xray-core) (VLESS / VMess / Trojan) с профилями, пингом, URL-подпиской / **Remnawave API** и автообновлением. ## Платформы @@ -210,13 +210,26 @@ Navis — Win32 + WebView2 VPN/прокси-клиент (системный п ```powershell build.bat -.\scripts\pack-msix.ps1 +.\scripts\pack-msix.ps1 -Version 3.9.0.1 ``` Нужен Windows SDK (`MakeAppx.exe`). Перед публикацией подставьте Identity Name / Publisher из Partner Center (см. `packaging/msix/AppxManifest.xml` и [packaging/msix/README.md](packaging/msix/README.md)). Сборка из Store **не** самообновляется через in-app updater (детект MSIX package identity) — только обновления Microsoft Store. +### Remnawave + +Импорт нод из панели [Remnawave](https://remna.st): + +| Способ | Что указать | +|--------|-------------| +| Публичная подписка | `https:///api/sub/` в поле «URL подписки» | +| Панель + short UUID | блок Remnawave API → URL панели + short UUID → «Синхронизировать» | +| С API token | токен из панели → API Tokens (для `/api/subscriptions/…`, `/api/users/…`) | +| Caddy auth | опциональный `X-Api-Key` | + +Токены хранятся только локально в `configs/config.json` (не коммитьте). + ## Сборка macOS (кросс с Windows / Linux) ```bat @@ -270,6 +283,11 @@ https://evilfox.win/ Некоторые AV (Bkav, Microsoft Wacapew/Wacatac, Ikarus Trojan.WinGo.Agent, Google, Trapmine) часто помечают **любые** неподписанные Go-бинарники с сетью и сменой системного прокси. +В 3.9.0: +- выдача конфигов через Remnawave API (`/api/sub/{shortUuid}`, опционально Bearer token); +- UI в стиле Remnawave (тёмная тема по умолчанию, cyan accent), флаги стран у серверов; +- MSIX / Store prep для `3.9.0.1`. + В 2.9.0: - светлая / тёмная тема с переключателем (preference в localStorage, по умолчанию — системная); - подготовка к Microsoft Store: MSIX-манифест, `scripts/pack-msix.ps1`, отключение in-app updater в MSIX-сборке. diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index ed68d96..09a59cc 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -13,8 +13,8 @@ android { minSdk = 26 targetSdk = 35 // versionCode = major*1_000_000 + minor*10_000 + patch*100 + build - versionCode = 3_080_201 - versionName = "3.8.2+1" + versionCode = 3_090_001 + versionName = "3.9.0+1" vectorDrawables.useSupportLibrary = true ndk { abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86_64") diff --git a/assets/app.manifest b/assets/app.manifest index df8b289..46dfb33 100644 --- a/assets/app.manifest +++ b/assets/app.manifest @@ -1,7 +1,7 @@ diff --git a/cmd/vpnapp/main_windows.go b/cmd/vpnapp/main_windows.go index 9940536..62d5f86 100644 --- a/cmd/vpnapp/main_windows.go +++ b/cmd/vpnapp/main_windows.go @@ -25,6 +25,7 @@ import ( "vpnclient/internal/protocols/hysteria2" "vpnclient/internal/protocols/naive" "vpnclient/internal/protocols/xray" + "vpnclient/internal/remnawave" "vpnclient/internal/update" ) @@ -55,6 +56,7 @@ type uiState struct { 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"` } @@ -143,6 +145,8 @@ func main() { mustBind(w, "applyUpdate", a.applyUpdate) mustBind(w, "saveHy2", a.saveHy2) mustBind(w, "importSubscription", a.importSubscription) + mustBind(w, "saveRemnawave", a.saveRemnawave) + mustBind(w, "importRemnawave", a.importRemnawave) go a.autoCheckUpdate() @@ -209,6 +213,7 @@ func (a *app) getState() (uiState, error) { Update: a.updateStatus, Pings: append([]netcheck.Result(nil), a.pings...), Subscription: cfg.SubscriptionURL, + Remnawave: a.mgr.RemnawaveSettings(), Hy2: a.mgr.ActiveHy2Options(), StorePackaged: update.IsStorePackaged(), } @@ -326,6 +331,14 @@ func (a *app) importSubscription(rawURL string) (int, error) { return a.mgr.ImportSubscription(rawURL) } +func (a *app) saveRemnawave(s remnawave.Settings) error { + return a.mgr.SaveRemnawaveSettings(s) +} + +func (a *app) importRemnawave(s remnawave.Settings) (int, error) { + return a.mgr.ImportRemnawave(s) +} + type pingBestResult struct { Pings []netcheck.Result `json:"pings"` BestName string `json:"best_name,omitempty"` diff --git a/configs/config.example.json b/configs/config.example.json index 00ea099..2c45d19 100644 --- a/configs/config.example.json +++ b/configs/config.example.json @@ -3,6 +3,9 @@ "system_proxy": true, "bin_dir": "bin", "subscription_url": "", + "remnawave_base_url": "", + "remnawave_short_uuid": "", + "remnawave_token": "", "profiles": [ { "name": "naive-main", diff --git a/dist/navis-release/update.json b/dist/navis-release/update.json index 2efd3f3..41ec907 100644 --- a/dist/navis-release/update.json +++ b/dist/navis-release/update.json @@ -1,16 +1,16 @@ -{ - "version": "3.8.2", - "notes": "3.8.2: Windows product version 3.8.2.1 (build 1).", +{ + "version": "3.9.0", + "notes": "3.9.0: Remnawave API config delivery, Remnawave-inspired UI + flags, Windows 3.9.0.1.", "platform": "windows-amd64", "os": "windows", "arch": "amd64", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/windows/Navis.exe", - "sha256": "8049f973e8e8712b31fccac42c48be5eb436a5a6bf103eb979729e1cbfdec8ec", + "sha256": "ba2d2860c771dc99081b4fa9cea147a8da4495a93c55aacfb11e6114e3a7a614", "mandatory": false, "platforms": { "windows-amd64": { "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/windows/Navis.exe", - "sha256": "8049f973e8e8712b31fccac42c48be5eb436a5a6bf103eb979729e1cbfdec8ec", + "sha256": "ba2d2860c771dc99081b4fa9cea147a8da4495a93c55aacfb11e6114e3a7a614", "os": "windows", "arch": "amd64" }, diff --git a/dist/navis-release/windows/Navis.exe b/dist/navis-release/windows/Navis.exe index fce1e64..3de5264 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 2726718..fc673cc 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 2efd3f3..41ec907 100644 --- a/dist/update.json +++ b/dist/update.json @@ -1,16 +1,16 @@ -{ - "version": "3.8.2", - "notes": "3.8.2: Windows product version 3.8.2.1 (build 1).", +{ + "version": "3.9.0", + "notes": "3.9.0: Remnawave API config delivery, Remnawave-inspired UI + flags, Windows 3.9.0.1.", "platform": "windows-amd64", "os": "windows", "arch": "amd64", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/windows/Navis.exe", - "sha256": "8049f973e8e8712b31fccac42c48be5eb436a5a6bf103eb979729e1cbfdec8ec", + "sha256": "ba2d2860c771dc99081b4fa9cea147a8da4495a93c55aacfb11e6114e3a7a614", "mandatory": false, "platforms": { "windows-amd64": { "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/windows/Navis.exe", - "sha256": "8049f973e8e8712b31fccac42c48be5eb436a5a6bf103eb979729e1cbfdec8ec", + "sha256": "ba2d2860c771dc99081b4fa9cea147a8da4495a93c55aacfb11e6114e3a7a614", "os": "windows", "arch": "amd64" }, diff --git a/internal/apphost/app.go b/internal/apphost/app.go index a48ed6a..27f5ee8 100644 --- a/internal/apphost/app.go +++ b/internal/apphost/app.go @@ -21,6 +21,7 @@ import ( "vpnclient/internal/protocols/hysteria2" "vpnclient/internal/protocols/naive" "vpnclient/internal/protocols/xray" + "vpnclient/internal/remnawave" "vpnclient/internal/update" ) @@ -53,6 +54,7 @@ type UIState struct { 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"` } @@ -130,6 +132,7 @@ func (a *App) GetState() (UIState, error) { Update: a.UpdateStatus, Pings: append([]netcheck.Result(nil), a.Pings...), Subscription: cfg.SubscriptionURL, + Remnawave: a.Mgr.RemnawaveSettings(), Hy2: a.Mgr.ActiveHy2Options(), StorePackaged: update.IsStorePackaged(), } @@ -240,6 +243,14 @@ func (a *App) ImportSubscription(rawURL string) (int, error) { return a.Mgr.ImportSubscription(rawURL) } +func (a *App) SaveRemnawave(s remnawave.Settings) error { + return a.Mgr.SaveRemnawaveSettings(s) +} + +func (a *App) ImportRemnawave(s remnawave.Settings) (int, error) { + return a.Mgr.ImportRemnawave(s) +} + func (a *App) PingServers() ([]netcheck.Result, error) { return a.runPings() } @@ -486,6 +497,18 @@ func (a *App) dispatch(name string, args []json.RawMessage) (any, error) { return nil, a.SaveHy2(opts) case "importSubscription": return a.ImportSubscription(arg(args, 0, "")) + case "saveRemnawave": + var s remnawave.Settings + if len(args) > 0 { + _ = json.Unmarshal(args[0], &s) + } + return nil, a.SaveRemnawave(s) + case "importRemnawave": + var s remnawave.Settings + if len(args) > 0 { + _ = json.Unmarshal(args[0], &s) + } + return a.ImportRemnawave(s) case "quit": go func() { time.Sleep(200 * time.Millisecond) diff --git a/internal/appui/index.html b/internal/appui/index.html index 0d8839c..a5c9973 100644 --- a/internal/appui/index.html +++ b/internal/appui/index.html @@ -10,125 +10,126 @@ var k = "navis.theme"; var t = localStorage.getItem(k); if (t !== "light" && t !== "dark") { - t = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; + t = "dark"; } document.documentElement.setAttribute("data-theme", t); } catch (_) { - document.documentElement.setAttribute("data-theme", "light"); + document.documentElement.setAttribute("data-theme", "dark"); } })(); - +