Release 3.8.2.12: export/import full server list as JSON.
ci / test (macos-latest) (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run

Save and replace profiles via system file dialog; buttons after Best; prefs unchanged on import.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
M4
2026-08-01 17:51:38 +03:00
co-authored by Cursor
parent 57d719f02f
commit 8b564110d5
22 changed files with 604 additions and 22 deletions
+44
View File
@@ -6,6 +6,7 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"net"
@@ -20,6 +21,7 @@ import (
"vpnclient/internal/core"
"vpnclient/internal/corebin"
"vpnclient/internal/dockicon"
"vpnclient/internal/filedialog"
"vpnclient/internal/logbuf"
"vpnclient/internal/netcheck"
"vpnclient/internal/protocols/awg"
@@ -508,6 +510,44 @@ func (a *App) ImportSubscription(rawURL string) (int, error) {
return n, err
}
// ExportServers opens a Save dialog and writes the full profile list.
func (a *App) ExportServers() (int, error) {
path, err := filedialog.SaveJSON("Сохранить список серверов", "navis-servers.json")
if err != nil {
if errors.Is(err, filedialog.ErrCanceled) {
return 0, nil
}
return 0, err
}
n, err := a.Mgr.ExportServers(path)
if err != nil {
return 0, err
}
a.NotifyState("profile")
return n, nil
}
// ImportServers opens an Open dialog and replaces the profile list.
func (a *App) ImportServers() (int, error) {
path, err := filedialog.OpenJSON("Загрузить список серверов")
if err != nil {
if errors.Is(err, filedialog.ErrCanceled) {
return 0, nil
}
return 0, err
}
n, err := a.Mgr.ImportServersReplace(path)
if err != nil {
return 0, err
}
a.mu.Lock()
a.Pings = nil
a.mu.Unlock()
a.NotifyState("profile")
go a.warmActiveCore()
return n, nil
}
func (a *App) PingServers() ([]netcheck.Result, error) {
return a.runPings()
}
@@ -760,6 +800,10 @@ 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 "exportServers":
return a.ExportServers()
case "importServers":
return a.ImportServers()
case "getLogs":
return a.GetLogs(), nil
case "probeTunnel":