Release 2.0.0: redesign UI, icon and connect-first UX.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -210,6 +210,10 @@ https://evilfox.win/
|
||||
|
||||
Некоторые AV (Bkav, Microsoft Wacapew/Wacatac, Ikarus Trojan.WinGo.Agent, Google, Trapmine) часто помечают **любые** неподписанные Go-бинарники с сетью и сменой системного прокси.
|
||||
|
||||
В 2.0.0:
|
||||
- новый интерфейс (connect-first), обновлённая иконка и типографика;
|
||||
- чище UX: протокол-бейдж, сворачиваемые сервисные действия, статус-карточка.
|
||||
|
||||
В 1.9.0:
|
||||
- VLESS / VMess / Trojan через официальный Xray-core (кнопка «Установить cores»).
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 890 KiB After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 52 KiB |
@@ -107,9 +107,9 @@ func main() {
|
||||
AutoFocus: true,
|
||||
DataPath: dataPath,
|
||||
WindowOptions: webview2.WindowOptions{
|
||||
Title: "Navis",
|
||||
Width: 520,
|
||||
Height: 860,
|
||||
Title: "Navis 2",
|
||||
Width: 500,
|
||||
Height: 820,
|
||||
Center: true,
|
||||
IconId: 1,
|
||||
},
|
||||
@@ -124,7 +124,7 @@ func main() {
|
||||
}()
|
||||
|
||||
applyWindowIcon(w.Window())
|
||||
w.SetSize(520, 860, webview2.HintNone)
|
||||
w.SetSize(500, 820, webview2.HintNone)
|
||||
|
||||
mustBind(w, "getState", a.getState)
|
||||
mustBind(w, "connect", a.connect)
|
||||
|
||||
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+6
-6
@@ -1,28 +1,28 @@
|
||||
{
|
||||
"version": "1.9.0",
|
||||
"notes": "VLESS / VMess / Trojan через Xray-core; нажмите «Установить cores»",
|
||||
"version": "2.0.0",
|
||||
"notes": "Navis 2.0: новый интерфейс, иконка и UX (connect-first)",
|
||||
"platform": "windows-amd64",
|
||||
"os": "windows",
|
||||
"arch": "amd64",
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "bd78ead7711b23a25b1a30278ec381bd762b595e91c4c00f7370c62d785740f7",
|
||||
"sha256": "aec3a8614383c0676137ee580ff3752881feb3405189b4fa3482aa3d8a758012",
|
||||
"mandatory": false,
|
||||
"platforms": {
|
||||
"windows-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "bd78ead7711b23a25b1a30278ec381bd762b595e91c4c00f7370c62d785740f7",
|
||||
"sha256": "aec3a8614383c0676137ee580ff3752881feb3405189b4fa3482aa3d8a758012",
|
||||
"os": "windows",
|
||||
"arch": "amd64"
|
||||
},
|
||||
"darwin-arm64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||
"sha256": "237962c24fb875f3dd2a5ecfad0db5d6837cefb6b691860a3e1d6f0e721f8449",
|
||||
"sha256": "f86c20342b6ffa7cdea900de67a8ce3eb28ffffae2b209b45dbe13078361606c",
|
||||
"os": "darwin",
|
||||
"arch": "arm64"
|
||||
},
|
||||
"darwin-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||
"sha256": "91430bb85df68b3816d9cc643b1bdc3d022410473c4f87f4d8573bb99259ba45",
|
||||
"sha256": "1c9abd8f7d496fa71e86a93b459e95121d0da11298b7c8c7de8671009cf6f716",
|
||||
"os": "darwin",
|
||||
"arch": "amd64"
|
||||
}
|
||||
|
||||
Vendored
+6
-6
@@ -1,28 +1,28 @@
|
||||
{
|
||||
"version": "1.9.0",
|
||||
"notes": "VLESS / VMess / Trojan через Xray-core; нажмите «Установить cores»",
|
||||
"version": "2.0.0",
|
||||
"notes": "Navis 2.0: новый интерфейс, иконка и UX (connect-first)",
|
||||
"platform": "windows-amd64",
|
||||
"os": "windows",
|
||||
"arch": "amd64",
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "bd78ead7711b23a25b1a30278ec381bd762b595e91c4c00f7370c62d785740f7",
|
||||
"sha256": "aec3a8614383c0676137ee580ff3752881feb3405189b4fa3482aa3d8a758012",
|
||||
"mandatory": false,
|
||||
"platforms": {
|
||||
"windows-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "bd78ead7711b23a25b1a30278ec381bd762b595e91c4c00f7370c62d785740f7",
|
||||
"sha256": "aec3a8614383c0676137ee580ff3752881feb3405189b4fa3482aa3d8a758012",
|
||||
"os": "windows",
|
||||
"arch": "amd64"
|
||||
},
|
||||
"darwin-arm64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||
"sha256": "237962c24fb875f3dd2a5ecfad0db5d6837cefb6b691860a3e1d6f0e721f8449",
|
||||
"sha256": "f86c20342b6ffa7cdea900de67a8ce3eb28ffffae2b209b45dbe13078361606c",
|
||||
"os": "darwin",
|
||||
"arch": "arm64"
|
||||
},
|
||||
"darwin-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||
"sha256": "91430bb85df68b3816d9cc643b1bdc3d022410473c4f87f4d8573bb99259ba45",
|
||||
"sha256": "1c9abd8f7d496fa71e86a93b459e95121d0da11298b7c8c7de8671009cf6f716",
|
||||
"os": "darwin",
|
||||
"arch": "amd64"
|
||||
}
|
||||
|
||||
+500
-222
@@ -6,273 +6,456 @@
|
||||
<title>Navis</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@500;600;700;800&family=Figtree:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
:root {
|
||||
--bg0: #dff3ea;
|
||||
--bg1: #f3faf7;
|
||||
--ink: #10241c;
|
||||
--muted: #567064;
|
||||
--line: rgba(16, 36, 28, 0.12);
|
||||
--accent: #0c7a55;
|
||||
--accent-2: #10956a;
|
||||
--danger: #b42318;
|
||||
--surface: rgba(255, 255, 255, 0.78);
|
||||
--shadow: 0 22px 60px rgba(16, 36, 28, 0.10);
|
||||
--ink: #0b1c18;
|
||||
--muted: #5a736b;
|
||||
--line: rgba(11, 28, 24, 0.10);
|
||||
--accent: #0d8a66;
|
||||
--accent-deep: #086b4f;
|
||||
--accent-soft: #d8f3e9;
|
||||
--danger: #c0362c;
|
||||
--ok: #0d8a66;
|
||||
--surface: rgba(255, 255, 255, 0.82);
|
||||
--surface-2: rgba(255, 255, 255, 0.62);
|
||||
--shadow: 0 18px 50px rgba(8, 40, 32, 0.12);
|
||||
--radius: 22px;
|
||||
--ease: cubic-bezier(.22,.8,.24,1);
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html, body {
|
||||
margin: 0; min-height: 100%;
|
||||
font-family: Manrope, sans-serif;
|
||||
margin: 0;
|
||||
min-height: 100%;
|
||||
font-family: Figtree, sans-serif;
|
||||
color: var(--ink);
|
||||
background:
|
||||
radial-gradient(900px 520px at 0% 0%, #bfe8d4 0%, transparent 55%),
|
||||
radial-gradient(700px 420px at 100% 10%, #c9dcf0 0%, transparent 50%),
|
||||
linear-gradient(160deg, var(--bg0), var(--bg1));
|
||||
radial-gradient(780px 420px at 8% -10%, #9fe0c8 0%, transparent 55%),
|
||||
radial-gradient(640px 380px at 100% 0%, #b8d4e8 0%, transparent 48%),
|
||||
radial-gradient(500px 320px at 50% 110%, #cfe8dc 0%, transparent 45%),
|
||||
linear-gradient(165deg, #e7f6f0 0%, #f4faf7 48%, #eef4f8 100%);
|
||||
}
|
||||
body {
|
||||
display: grid;
|
||||
place-items: start center;
|
||||
padding: 16px 12px 20px;
|
||||
}
|
||||
body { display: grid; place-items: center; padding: 22px 14px; }
|
||||
.shell {
|
||||
width: min(460px, 100%);
|
||||
width: min(480px, 100%);
|
||||
background: var(--surface);
|
||||
backdrop-filter: blur(16px);
|
||||
backdrop-filter: blur(18px) saturate(1.15);
|
||||
border: 1px solid var(--line);
|
||||
box-shadow: var(--shadow);
|
||||
border-radius: 28px;
|
||||
padding: 24px 22px 20px;
|
||||
animation: rise .5s cubic-bezier(.2,.8,.2,1) both;
|
||||
padding: 18px 18px 16px;
|
||||
animation: rise .55s var(--ease) both;
|
||||
}
|
||||
@keyframes rise {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
from { opacity: 0; transform: translateY(14px) scale(.985); }
|
||||
to { opacity: 1; transform: none; }
|
||||
}
|
||||
|
||||
.update-banner {
|
||||
display: none;
|
||||
margin-bottom: 12px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(13, 138, 102, 0.28);
|
||||
background: linear-gradient(135deg, rgba(13,138,102,.14), rgba(255,255,255,.75));
|
||||
animation: rise .4s var(--ease) both;
|
||||
}
|
||||
.update-banner.show { display: block; }
|
||||
.update-banner strong {
|
||||
font-family: Sora, sans-serif;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-size: .95rem;
|
||||
}
|
||||
.update-banner p {
|
||||
margin: 0 0 10px;
|
||||
color: var(--muted);
|
||||
font-size: .84rem;
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex; align-items: center; gap: 14px; margin-bottom: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.logo {
|
||||
width: 48px; height: 48px; border-radius: 14px;
|
||||
background: linear-gradient(145deg, #0c7a55, #1aa876);
|
||||
display: grid; place-items: center;
|
||||
box-shadow: 0 10px 24px rgba(12, 122, 85, 0.28);
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
flex: 0 0 auto;
|
||||
box-shadow: 0 10px 24px rgba(13, 138, 102, 0.28);
|
||||
background: linear-gradient(145deg, #0d8a66, #1bb887);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
.logo svg { width: 30px; height: 30px; }
|
||||
.brand-wrap { min-width: 0; flex: 1; }
|
||||
.brand-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.logo svg { width: 26px; height: 26px; }
|
||||
.brand-wrap { min-width: 0; }
|
||||
.brand {
|
||||
font-family: Syne, sans-serif;
|
||||
font-size: 1.85rem; font-weight: 800;
|
||||
letter-spacing: -0.04em; line-height: 1; margin: 0;
|
||||
font-family: Sora, sans-serif;
|
||||
font-size: 1.7rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.045em;
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
}
|
||||
.badge-ver {
|
||||
font-size: .68rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: .04em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent-deep);
|
||||
background: var(--accent-soft);
|
||||
border: 1px solid rgba(13,138,102,.18);
|
||||
border-radius: 999px;
|
||||
padding: 3px 8px;
|
||||
}
|
||||
.tagline {
|
||||
margin: 5px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: .84rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
.tagline { margin: 4px 0 0; color: var(--muted); font-size: .86rem; }
|
||||
|
||||
.hero {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid var(--line);
|
||||
background:
|
||||
linear-gradient(160deg, rgba(255,255,255,.92), rgba(232,247,240,.88));
|
||||
padding: 16px 16px 14px;
|
||||
margin-bottom: 14px;
|
||||
transition: border-color .25s, box-shadow .25s, background .25s;
|
||||
}
|
||||
.hero.on {
|
||||
border-color: rgba(13,138,102,.35);
|
||||
box-shadow: 0 14px 36px rgba(13, 138, 102, 0.14);
|
||||
background:
|
||||
linear-gradient(160deg, rgba(216,243,233,.95), rgba(255,255,255,.9));
|
||||
}
|
||||
.hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 160px; height: 160px;
|
||||
right: -40px; top: -50px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(13,138,102,.18), transparent 70%);
|
||||
pointer-events: none;
|
||||
transition: opacity .3s;
|
||||
opacity: .55;
|
||||
}
|
||||
.hero.on::after { opacity: 1; }
|
||||
.status-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.status {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
margin-bottom: 16px; font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-weight: 700;
|
||||
font-size: .98rem;
|
||||
}
|
||||
.dot {
|
||||
width: 10px; height: 10px; border-radius: 50%; background: #9aa89f;
|
||||
width: 11px; height: 11px; border-radius: 50%;
|
||||
background: #9aaba4;
|
||||
transition: background .2s;
|
||||
}
|
||||
.dot.on {
|
||||
background: var(--accent);
|
||||
background: var(--ok);
|
||||
animation: pulse 1.8s ease-out infinite;
|
||||
}
|
||||
@keyframes pulse {
|
||||
0% { box-shadow: 0 0 0 0 rgba(12,122,85,.35); }
|
||||
70% { box-shadow: 0 0 0 10px rgba(12,122,85,0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(12,122,85,0); }
|
||||
0% { box-shadow: 0 0 0 0 rgba(13,138,102,.4); }
|
||||
70% { box-shadow: 0 0 0 12px rgba(13,138,102,0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(13,138,102,0); }
|
||||
}
|
||||
.proto-chip {
|
||||
font-size: .72rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: .03em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
background: rgba(255,255,255,.75);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 999px;
|
||||
padding: 5px 10px;
|
||||
max-width: 46%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.proto-chip.active {
|
||||
color: var(--accent-deep);
|
||||
background: var(--accent-soft);
|
||||
border-color: rgba(13,138,102,.22);
|
||||
}
|
||||
.hero-actions { position: relative; z-index: 1; display: grid; gap: 8px; }
|
||||
.hero-hint {
|
||||
margin: 8px 0 0;
|
||||
font-size: .8rem;
|
||||
color: var(--muted);
|
||||
min-height: 1.2em;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin: 0 0 8px;
|
||||
font-family: Sora, sans-serif;
|
||||
font-size: .78rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: .04em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
label.field {
|
||||
display: block; font-size: .72rem; font-weight: 700;
|
||||
letter-spacing: .06em; text-transform: uppercase;
|
||||
color: var(--muted); margin: 0 0 8px;
|
||||
display: block;
|
||||
font-size: .72rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: .05em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
margin: 0 0 6px;
|
||||
}
|
||||
.profile-bar {
|
||||
display: grid; grid-template-columns: 1fr auto auto; gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.sub-bar {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 8px;
|
||||
}
|
||||
select, input[type="text"], textarea {
|
||||
width: 100%; border: 1px solid var(--line);
|
||||
background: rgba(255,255,255,.92);
|
||||
border-radius: 14px; padding: 12px 14px;
|
||||
font: inherit; color: var(--ink); outline: none;
|
||||
width: 100%;
|
||||
border: 1px solid var(--line);
|
||||
background: rgba(255,255,255,.94);
|
||||
border-radius: 14px;
|
||||
padding: 11px 13px;
|
||||
font: inherit;
|
||||
color: var(--ink);
|
||||
outline: none;
|
||||
transition: border-color .15s, box-shadow .15s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
textarea {
|
||||
min-height: 88px;
|
||||
min-height: 78px;
|
||||
resize: vertical;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
font-size: .8rem;
|
||||
line-height: 1.35;
|
||||
font-size: .78rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
select:focus, input[type="text"]:focus, textarea:focus {
|
||||
border-color: rgba(12,122,85,.55);
|
||||
box-shadow: 0 0 0 4px rgba(12,122,85,.12);
|
||||
border-color: rgba(13,138,102,.5);
|
||||
box-shadow: 0 0 0 4px rgba(13,138,102,.12);
|
||||
}
|
||||
.icon-btn {
|
||||
width: 46px; padding: 0; display: grid; place-items: center;
|
||||
border-radius: 14px; border: 1px solid var(--line);
|
||||
background: rgba(255,255,255,.7); color: var(--ink);
|
||||
font-size: 1.2rem; font-weight: 700; cursor: pointer;
|
||||
width: 44px;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 14px;
|
||||
border: 1px solid var(--line);
|
||||
background: rgba(255,255,255,.78);
|
||||
color: var(--ink);
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: background .15s, border-color .15s, color .15s;
|
||||
}
|
||||
.icon-btn:hover { background: #fff; }
|
||||
.icon-btn:hover { background: #fff; border-color: rgba(13,138,102,.35); color: var(--accent); }
|
||||
.icon-btn.danger { color: var(--danger); }
|
||||
.icon-btn.wide {
|
||||
width: auto;
|
||||
padding: 0 14px;
|
||||
font-size: .82rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.stack { display: grid; gap: 10px; margin-bottom: 14px; }
|
||||
.stack { display: grid; gap: 10px; }
|
||||
|
||||
details.hy2 {
|
||||
margin-bottom: 14px;
|
||||
details.panel {
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
padding: 10px 12px;
|
||||
background: rgba(255,255,255,.55);
|
||||
padding: 8px 12px 10px;
|
||||
background: var(--surface-2);
|
||||
}
|
||||
details.hy2 summary {
|
||||
details.panel summary {
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
font-size: .84rem;
|
||||
color: var(--accent);
|
||||
font-size: .86rem;
|
||||
color: var(--ink);
|
||||
list-style: none;
|
||||
padding: 6px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
details.hy2 .grid2 {
|
||||
details.panel summary::-webkit-details-marker { display: none; }
|
||||
details.panel summary::after {
|
||||
content: "+";
|
||||
color: var(--muted);
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
transition: transform .2s;
|
||||
}
|
||||
details.panel[open] summary::after { content: "–"; }
|
||||
details.panel .grid2 {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
details.hy2 label.field { margin-top: 6px; }
|
||||
details.panel label.field { margin-top: 4px; }
|
||||
.check {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
font-size: .88rem; margin-top: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: .86rem;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
gap: 12px; padding: 12px 14px;
|
||||
border: 1px solid var(--line); border-radius: 14px;
|
||||
background: rgba(255,255,255,.55); margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 11px 13px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
background: rgba(255,255,255,.6);
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
font-size: .9rem;
|
||||
}
|
||||
.switch { position: relative; width: 44px; height: 26px; flex: 0 0 auto; }
|
||||
.switch input { opacity: 0; width: 0; height: 0; }
|
||||
.slider {
|
||||
position: absolute; inset: 0; background: #c5d2cb;
|
||||
position: absolute; inset: 0; background: #c7d5cf;
|
||||
border-radius: 999px; cursor: pointer; transition: background .15s;
|
||||
}
|
||||
.slider::before {
|
||||
content: ""; position: absolute; width: 20px; height: 20px;
|
||||
left: 3px; top: 3px; background: #fff; border-radius: 50%;
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 20px; height: 20px;
|
||||
left: 3px; top: 3px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
transition: transform .15s;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,.12);
|
||||
}
|
||||
.switch input:checked + .slider { background: var(--accent); }
|
||||
.switch input:checked + .slider::before { transform: translateX(18px); }
|
||||
|
||||
.actions { display: grid; gap: 10px; }
|
||||
button.action {
|
||||
appearance: none; border: 0; border-radius: 16px;
|
||||
padding: 14px 16px; font: inherit; font-weight: 700; cursor: pointer;
|
||||
appearance: none;
|
||||
border: 0;
|
||||
border-radius: 15px;
|
||||
padding: 13px 15px;
|
||||
font: inherit;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: transform .12s, background .15s, opacity .15s, box-shadow .15s, border-color .15s, color .15s;
|
||||
box-shadow: 0 8px 18px rgba(16, 36, 28, 0.08);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
button.action:active { transform: translateY(1px); box-shadow: 0 3px 10px rgba(16, 36, 28, 0.08); }
|
||||
button.action:active { transform: translateY(1px); }
|
||||
button.action:disabled { opacity: .55; cursor: not-allowed; transform: none; box-shadow: none; }
|
||||
.primary {
|
||||
background: linear-gradient(145deg, #0c7a55, #12966a);
|
||||
color: #f4fff9;
|
||||
box-shadow: 0 12px 28px rgba(12, 122, 85, 0.28);
|
||||
background: linear-gradient(145deg, var(--accent-deep), var(--accent));
|
||||
color: #f3fff9;
|
||||
box-shadow: 0 12px 28px rgba(13, 138, 102, 0.28);
|
||||
}
|
||||
.primary:hover:not(:disabled) {
|
||||
background: linear-gradient(145deg, #0e8a60, #14a575);
|
||||
box-shadow: 0 14px 30px rgba(12, 122, 85, 0.34);
|
||||
background: linear-gradient(145deg, #0a7a59, #12a078);
|
||||
box-shadow: 0 14px 30px rgba(13, 138, 102, 0.34);
|
||||
}
|
||||
.primary.danger {
|
||||
background: linear-gradient(145deg, #b42318, #d6453a);
|
||||
box-shadow: 0 12px 28px rgba(180, 35, 24, 0.25);
|
||||
background: linear-gradient(145deg, #a52c24, #d14a3f);
|
||||
box-shadow: 0 12px 28px rgba(192, 54, 44, 0.24);
|
||||
}
|
||||
.primary.danger:hover:not(:disabled) {
|
||||
background: linear-gradient(145deg, #c52c20, #e05548);
|
||||
background: linear-gradient(145deg, #b8342b, #e0574b);
|
||||
}
|
||||
.secondary {
|
||||
background: linear-gradient(180deg, #ffffff, #eef7f2);
|
||||
background: linear-gradient(180deg, #ffffff, #eef6f2);
|
||||
color: var(--ink);
|
||||
border: 1px solid rgba(16, 36, 28, 0.14);
|
||||
border: 1px solid rgba(11, 28, 24, 0.12);
|
||||
box-shadow: 0 6px 14px rgba(11, 28, 24, 0.05);
|
||||
}
|
||||
.secondary:hover:not(:disabled) {
|
||||
background: #fff;
|
||||
border-color: rgba(12, 122, 85, 0.35);
|
||||
border-color: rgba(13,138,102,.35);
|
||||
color: var(--accent);
|
||||
box-shadow: 0 10px 22px rgba(16, 36, 28, 0.12);
|
||||
}
|
||||
.ghost {
|
||||
background: linear-gradient(180deg, #ffffff, #eef7f2);
|
||||
color: var(--ink);
|
||||
border: 1px solid rgba(16, 36, 28, 0.14);
|
||||
}
|
||||
.ghost:hover:not(:disabled) {
|
||||
background: #fff;
|
||||
border-color: rgba(12, 122, 85, 0.35);
|
||||
color: var(--accent);
|
||||
box-shadow: 0 10px 22px rgba(16, 36, 28, 0.12);
|
||||
}
|
||||
|
||||
.meta {
|
||||
margin-top: 14px; font-size: .82rem; color: var(--muted);
|
||||
line-height: 1.45; min-height: 2.6em;
|
||||
}
|
||||
|
||||
.shop {
|
||||
margin-top: 16px;
|
||||
padding: 14px 14px 12px;
|
||||
border-radius: 18px;
|
||||
border: 1px solid rgba(12, 122, 85, 0.18);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(12, 122, 85, 0.10), rgba(255,255,255,0.55));
|
||||
}
|
||||
.shop h3 {
|
||||
font-family: Syne, sans-serif;
|
||||
font-size: 1.05rem;
|
||||
letter-spacing: -0.02em;
|
||||
margin: 0 0 6px;
|
||||
}
|
||||
.shop p {
|
||||
margin: 0 0 12px;
|
||||
color: var(--muted);
|
||||
font-size: .84rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.shop .action {
|
||||
.cta {
|
||||
width: 100%;
|
||||
min-height: 52px;
|
||||
font-size: 1.02rem;
|
||||
font-family: Sora, sans-serif;
|
||||
}
|
||||
.shop-link {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
font: inherit;
|
||||
font-size: .78rem;
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
box-shadow: none;
|
||||
}
|
||||
.shop-link:hover { text-decoration: underline; }
|
||||
|
||||
.actions { display: grid; gap: 8px; }
|
||||
.tools {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
margin-top: 0;
|
||||
gap: 8px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.tools .action {
|
||||
min-height: 48px;
|
||||
font-size: .92rem;
|
||||
.tools .action { min-height: 44px; font-size: .9rem; }
|
||||
|
||||
.meta {
|
||||
margin: 10px 0 0;
|
||||
font-size: .82rem;
|
||||
color: var(--muted);
|
||||
line-height: 1.45;
|
||||
min-height: 2.4em;
|
||||
padding: 8px 10px;
|
||||
border-radius: 12px;
|
||||
background: rgba(255,255,255,.35);
|
||||
border: 1px solid transparent;
|
||||
transition: color .15s, border-color .15s, background .15s;
|
||||
}
|
||||
.meta.ok {
|
||||
color: var(--ok);
|
||||
background: rgba(216,243,233,.65);
|
||||
border-color: rgba(13,138,102,.18);
|
||||
}
|
||||
.meta.err {
|
||||
color: var(--danger);
|
||||
background: rgba(255,236,234,.75);
|
||||
border-color: rgba(192,54,44,.16);
|
||||
}
|
||||
|
||||
.ping-list {
|
||||
margin-top: 10px;
|
||||
margin-top: 8px;
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
@@ -283,55 +466,93 @@
|
||||
padding: 8px 12px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--line);
|
||||
background: rgba(255,255,255,.55);
|
||||
font-size: .84rem;
|
||||
background: rgba(255,255,255,.6);
|
||||
font-size: .82rem;
|
||||
}
|
||||
.ping-item .ms { font-weight: 700; }
|
||||
.ping-item .ms.ok { color: var(--accent); }
|
||||
.ping-item .ms.ok { color: var(--ok); }
|
||||
.ping-item .ms.bad { color: var(--danger); }
|
||||
|
||||
.update-banner {
|
||||
display: none;
|
||||
margin-bottom: 14px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(12,122,85,.25);
|
||||
background: linear-gradient(135deg, rgba(12,122,85,.14), rgba(255,255,255,.7));
|
||||
.shop {
|
||||
margin-top: 12px;
|
||||
padding: 13px 14px 12px;
|
||||
border-radius: 18px;
|
||||
border: 1px solid rgba(13, 138, 102, 0.16);
|
||||
background: linear-gradient(135deg, rgba(13,138,102,.09), rgba(255,255,255,.55));
|
||||
}
|
||||
.update-banner.show { display: block; }
|
||||
.update-banner strong {
|
||||
font-family: Syne, sans-serif;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
.shop h3 {
|
||||
font-family: Sora, sans-serif;
|
||||
font-size: 1rem;
|
||||
letter-spacing: -0.02em;
|
||||
margin: 0 0 5px;
|
||||
}
|
||||
.update-banner p {
|
||||
.shop p {
|
||||
margin: 0 0 10px;
|
||||
color: var(--muted);
|
||||
font-size: .84rem;
|
||||
font-size: .82rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.shop .action { width: 100%; }
|
||||
.shop-link {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
font: inherit;
|
||||
font-size: .76rem;
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
box-shadow: none;
|
||||
}
|
||||
.shop-link:hover { text-decoration: underline; }
|
||||
|
||||
.ver {
|
||||
margin-top: 10px;
|
||||
font-size: .75rem;
|
||||
margin-top: 8px;
|
||||
font-size: .72rem;
|
||||
color: var(--muted);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal-backdrop {
|
||||
position: fixed; inset: 0; background: rgba(16,36,28,.35);
|
||||
display: none; place-items: center; padding: 18px; z-index: 20;
|
||||
position: fixed; inset: 0;
|
||||
background: rgba(8, 28, 24, .42);
|
||||
backdrop-filter: blur(4px);
|
||||
display: none;
|
||||
place-items: center;
|
||||
padding: 18px;
|
||||
z-index: 20;
|
||||
}
|
||||
.modal-backdrop.open { display: grid; }
|
||||
.modal {
|
||||
width: min(400px, 100%); background: #f7fcf9;
|
||||
border-radius: 22px; border: 1px solid var(--line);
|
||||
box-shadow: var(--shadow); padding: 20px;
|
||||
animation: rise .35s ease both;
|
||||
width: min(400px, 100%);
|
||||
background: #f5fbf8;
|
||||
border-radius: 22px;
|
||||
border: 1px solid var(--line);
|
||||
box-shadow: var(--shadow);
|
||||
padding: 18px;
|
||||
animation: rise .35s var(--ease) both;
|
||||
}
|
||||
.modal h2 {
|
||||
font-family: Syne, sans-serif; margin: 0 0 14px;
|
||||
font-size: 1.25rem; letter-spacing: -.02em;
|
||||
font-family: Sora, sans-serif;
|
||||
margin: 0 0 12px;
|
||||
font-size: 1.2rem;
|
||||
letter-spacing: -.02em;
|
||||
}
|
||||
.modal .actions {
|
||||
margin-top: 12px;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
.shell { padding: 14px 12px 12px; border-radius: 22px; }
|
||||
.brand { font-size: 1.45rem; }
|
||||
details.panel .grid2 { grid-template-columns: 1fr; }
|
||||
.tools { grid-template-columns: 1fr; }
|
||||
}
|
||||
.modal .actions { margin-top: 14px; grid-template-columns: 1fr 1fr; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -342,24 +563,38 @@
|
||||
<button class="action primary" id="updateBtn" type="button">Обновить и перезапустить</button>
|
||||
</div>
|
||||
|
||||
<div class="top">
|
||||
<header class="top">
|
||||
<div class="logo" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none">
|
||||
<path d="M12 3l6.5 17H16l-2.2-5.8H10.2L8 20H5.5L12 3z" fill="#f4fff9"/>
|
||||
<circle cx="12" cy="14.2" r="2.2" fill="#0c7a55"/>
|
||||
<svg viewBox="0 0 32 32" fill="none">
|
||||
<path d="M8 26V6h4.2L20 18.4V6H24v20h-4.2L12 13.6V26H8z" fill="#f4fff9"/>
|
||||
<path d="M22.5 8.2l3.2-1.1-1.1 3.2-5.6 5.6 1.6 1.6 5.6-5.6 3.2-1.1-1.1 3.2" fill="#b8f0d8" opacity=".9"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="brand-wrap">
|
||||
<div class="brand-row">
|
||||
<h1 class="brand">Navis</h1>
|
||||
<p class="tagline">NaiveProxy · Hysteria 2 · несколько серверов</p>
|
||||
<span class="badge-ver">2.0</span>
|
||||
</div>
|
||||
<p class="tagline">Быстрый клиент · Naive · Hy2 · AWG · Xray</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="hero" id="hero">
|
||||
<div class="status-row">
|
||||
<div class="status">
|
||||
<span class="dot" id="dot"></span>
|
||||
<span id="statusText">Отключено</span>
|
||||
</div>
|
||||
<span class="proto-chip" id="protoChip">протокол</span>
|
||||
</div>
|
||||
<div class="hero-actions">
|
||||
<button class="action primary cta" id="toggleBtn" type="button">Подключить</button>
|
||||
</div>
|
||||
<p class="hero-hint" id="heroHint">Выберите профиль и нажмите Подключить</p>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="section-title"><span>Сервер</span></div>
|
||||
<label class="field" for="profile">Профиль</label>
|
||||
<div class="profile-bar">
|
||||
<select id="profile"></select>
|
||||
@@ -373,20 +608,33 @@
|
||||
<input id="name" type="text" placeholder="Например: DE-1 / Home" spellcheck="false" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="field" for="proxy">Ссылка / конфиг сервера</label>
|
||||
<textarea id="proxy" rows="4" placeholder="naive+https://… · hysteria2://… · vless:// · vmess:// · trojan:// · AWG .conf" spellcheck="false"></textarea>
|
||||
<label class="field" for="proxy">Ссылка / конфиг</label>
|
||||
<textarea id="proxy" rows="3" placeholder="vless:// · vmess:// · trojan:// · hy2:// · naive+https:// · AWG .conf" spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<label class="field" for="subUrl">URL подписки</label>
|
||||
<div class="profile-bar">
|
||||
<label class="field" for="subUrl">Подписка</label>
|
||||
<div class="sub-bar">
|
||||
<input id="subUrl" type="text" placeholder="https://…/sub" spellcheck="false" />
|
||||
<button class="icon-btn" id="subBtn" type="button" title="Обновить подписку" style="width:auto;padding:0 14px;font-size:.8rem">↻</button>
|
||||
<button class="icon-btn wide" id="subBtn" type="button" title="Обновить подписку">Обновить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="row">
|
||||
<span>Системный прокси</span>
|
||||
<label class="switch">
|
||||
<input id="sysproxy" type="checkbox" checked />
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<details class="hy2" id="hy2Box">
|
||||
<summary>Hysteria 2 · BBR / Salamander / маскировка</summary>
|
||||
<div class="actions">
|
||||
<button class="action secondary" id="saveBtn" type="button">Сохранить профиль</button>
|
||||
</div>
|
||||
|
||||
<details class="panel hy2" id="hy2Box">
|
||||
<summary>Hysteria 2 · BBR / obfuscation</summary>
|
||||
<div class="grid2">
|
||||
<div>
|
||||
<label class="field" for="hy2Congestion">Congestion</label>
|
||||
@@ -421,10 +669,10 @@
|
||||
</div>
|
||||
<div>
|
||||
<label class="field" for="hy2ObfsPass">Obfs password</label>
|
||||
<input id="hy2ObfsPass" type="text" placeholder="пароль salamander/gecko" />
|
||||
<input id="hy2ObfsPass" type="text" placeholder="пароль" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="field" for="hy2Sni">SNI (маскарад HTTPS)</label>
|
||||
<label class="field" for="hy2Sni">SNI</label>
|
||||
<input id="hy2Sni" type="text" placeholder="cdn.example.com" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -441,30 +689,24 @@
|
||||
<label class="check"><input id="hy2Lazy" type="checkbox" /> Lazy connect</label>
|
||||
</details>
|
||||
|
||||
<div class="row">
|
||||
<span>Системный прокси Windows</span>
|
||||
<label class="switch">
|
||||
<input id="sysproxy" type="checkbox" checked />
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button class="action primary" id="toggleBtn" type="button">Подключить</button>
|
||||
<button class="action secondary" id="saveBtn" type="button">Сохранить профиль</button>
|
||||
<details class="panel" id="toolsBox">
|
||||
<summary>Сервис · пинг, cores, обновления</summary>
|
||||
<div class="tools">
|
||||
<button class="action secondary" id="pingBtn" type="button">Пинг серверов</button>
|
||||
<button class="action secondary" id="updCheckBtn" type="button">Проверить обновление</button>
|
||||
</div>
|
||||
<button class="action secondary" id="coreBtn" type="button">Установить cores (naive + hy2 + xray)</button>
|
||||
<div style="margin-top:8px">
|
||||
<button class="action secondary" id="coreBtn" type="button" style="width:100%">Установить cores (naive + hy2 + xray)</button>
|
||||
</div>
|
||||
<div class="ping-list" id="pingList"></div>
|
||||
</details>
|
||||
|
||||
<p class="meta" id="meta">Загрузка…</p>
|
||||
|
||||
<section class="shop" aria-label="Купить подключение">
|
||||
<h3>Безопасное подключение</h3>
|
||||
<p>На любом устройстве — защита данных, стабильность и приватность. Демо-ключ от 30₽.</p>
|
||||
<button class="action primary" id="shopBtn" type="button">Купить на evilfox.win</button>
|
||||
<h3>Нужен доступ?</h3>
|
||||
<p>Ключи и тарифы на evilfox.win — демо от 30₽.</p>
|
||||
<button class="action primary" id="shopBtn" type="button">Открыть магазин</button>
|
||||
<button class="shop-link" id="shopLink" type="button">https://evilfox.win/</button>
|
||||
</section>
|
||||
<p class="ver" id="verLabel">Navis</p>
|
||||
@@ -480,7 +722,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<label class="field" for="newProxy">Ссылка</label>
|
||||
<input id="newProxy" type="text" placeholder="vless://… / vmess://… / trojan://… / hy2 / naive / awg" />
|
||||
<input id="newProxy" type="text" placeholder="vless:// · vmess:// · trojan:// · hy2 · naive · awg" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
@@ -515,6 +757,9 @@
|
||||
const verLabel = $("verLabel");
|
||||
const subUrl = $("subUrl");
|
||||
const subBtn = $("subBtn");
|
||||
const hero = $("hero");
|
||||
const protoChip = $("protoChip");
|
||||
const heroHint = $("heroHint");
|
||||
const SHOP_URL = "https://evilfox.win/";
|
||||
|
||||
function readHy2() {
|
||||
@@ -579,10 +824,25 @@
|
||||
|
||||
function setMeta(text, kind) {
|
||||
meta.textContent = text || "";
|
||||
meta.style.color = kind === "err" ? "var(--danger)" : kind === "ok" ? "var(--accent)" : "var(--muted)";
|
||||
meta.classList.remove("ok", "err");
|
||||
if (kind === "ok") meta.classList.add("ok");
|
||||
if (kind === "err") meta.classList.add("err");
|
||||
if (kind === "ok" || kind === "err") metaHoldUntil = Date.now() + 8000;
|
||||
}
|
||||
|
||||
function detectProtoLabel(state, active) {
|
||||
const p = (state.protocol || active.protocol || "").toLowerCase();
|
||||
const link = (typeof state.proxy === "string" ? state.proxy : (active.proxy || "")).trim().toLowerCase();
|
||||
if (p) return p;
|
||||
if (link.startsWith("vless://")) return "vless";
|
||||
if (link.startsWith("vmess://")) return "vmess";
|
||||
if (link.startsWith("trojan://")) return "trojan";
|
||||
if (link.startsWith("hysteria2://") || link.startsWith("hy2://")) return "hysteria2";
|
||||
if (link.startsWith("awg://") || link.includes("[interface]")) return "awg";
|
||||
if (link.startsWith("naive") || link.startsWith("https://") || link.startsWith("quic://")) return "naive";
|
||||
return "протокол";
|
||||
}
|
||||
|
||||
function fillProfiles(list, active) {
|
||||
profiles = list || [];
|
||||
const cur = profile.value;
|
||||
@@ -590,7 +850,8 @@
|
||||
profiles.forEach((p) => {
|
||||
const opt = document.createElement("option");
|
||||
opt.value = p.name;
|
||||
opt.textContent = (p.protocol ? ("[" + p.protocol + "] ") : "") + (p.host ? (p.name + " · " + p.host) : p.name);
|
||||
const proto = p.protocol ? String(p.protocol).toUpperCase() : "";
|
||||
opt.textContent = (proto ? (proto + " · ") : "") + (p.host ? (p.name + " · " + p.host) : p.name);
|
||||
profile.appendChild(opt);
|
||||
});
|
||||
const want = active || cur || (profiles[0] && profiles[0].name);
|
||||
@@ -611,6 +872,9 @@
|
||||
row.appendChild(right);
|
||||
pingList.appendChild(row);
|
||||
});
|
||||
if ((pings || []).length && $("toolsBox") && !$("toolsBox").open) {
|
||||
$("toolsBox").open = true;
|
||||
}
|
||||
}
|
||||
|
||||
function renderUpdate(u, version) {
|
||||
@@ -632,6 +896,7 @@
|
||||
const syncForm = opts && opts.syncForm;
|
||||
connected = !!state.connected;
|
||||
dot.classList.toggle("on", connected);
|
||||
hero.classList.toggle("on", connected);
|
||||
statusText.textContent = connected
|
||||
? ("Подключено" + (state.profile ? " · " + state.profile : ""))
|
||||
: "Отключено";
|
||||
@@ -671,16 +936,26 @@
|
||||
if (syncForm) dirty = false;
|
||||
}
|
||||
|
||||
const active = (state.profiles || []).find((p) => p.name === profile.value) || {};
|
||||
const label = detectProtoLabel(state, active);
|
||||
protoChip.textContent = label;
|
||||
protoChip.classList.toggle("active", !!state.connected || label !== "протокол");
|
||||
const hy2 = (label === "hysteria2" || label === "hy2");
|
||||
if ($("hy2Box")) $("hy2Box").style.display = hy2 ? "" : "none";
|
||||
|
||||
let detail = "";
|
||||
if (connected) {
|
||||
const parts = [];
|
||||
if (state.http_proxy) parts.push("HTTP " + state.http_proxy);
|
||||
if (state.socks_proxy) parts.push("SOCKS " + state.socks_proxy);
|
||||
detail = parts.join(" · ");
|
||||
detail = parts.join(" · ") || "Туннель активен";
|
||||
heroHint.textContent = detail;
|
||||
} else if (state.core_ready === false) {
|
||||
detail = "Сначала установите cores (naive / hy2 / xray)";
|
||||
detail = "Сначала установите cores в разделе «Сервис»";
|
||||
heroHint.textContent = "Нужны cores для выбранного протокола";
|
||||
} else {
|
||||
detail = "Вставьте ссылку: naive / hy2 / vless / vmess / trojan / awg";
|
||||
detail = "Готово к подключению";
|
||||
heroHint.textContent = "Выберите профиль и нажмите Подключить";
|
||||
}
|
||||
if (!busy && Date.now() > metaHoldUntil) {
|
||||
setMeta(detail, state.core_ready === false ? "err" : "");
|
||||
@@ -751,7 +1026,7 @@
|
||||
try {
|
||||
setMeta("Скачивание official cores…");
|
||||
const path = await installCore();
|
||||
setMeta("Cores: " + path, "ok");
|
||||
setMeta("Cores готовы: " + path, "ok");
|
||||
} catch (e) { setMeta(String(e), "err"); }
|
||||
}));
|
||||
|
||||
@@ -772,6 +1047,9 @@
|
||||
$("newName").focus();
|
||||
});
|
||||
$("cancelNew").addEventListener("click", () => modal.classList.remove("open"));
|
||||
modal.addEventListener("click", (e) => {
|
||||
if (e.target === modal) modal.classList.remove("open");
|
||||
});
|
||||
$("createNew").addEventListener("click", () => withBusy(async () => {
|
||||
try {
|
||||
const n = $("newName").value.trim();
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
// CurrentVersion is the shipped client version.
|
||||
const CurrentVersion = "1.9.0"
|
||||
const CurrentVersion = "2.0.0"
|
||||
|
||||
// DefaultManifestURL is the update feed (hosted in the project git repo).
|
||||
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"
|
||||
|
||||
+6
-6
@@ -1,28 +1,28 @@
|
||||
{
|
||||
"version": "1.9.0",
|
||||
"notes": "VLESS / VMess / Trojan через Xray-core; нажмите «Установить cores»",
|
||||
"version": "2.0.0",
|
||||
"notes": "Navis 2.0: новый интерфейс, иконка и UX (connect-first)",
|
||||
"platform": "windows-amd64",
|
||||
"os": "windows",
|
||||
"arch": "amd64",
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "bd78ead7711b23a25b1a30278ec381bd762b595e91c4c00f7370c62d785740f7",
|
||||
"sha256": "aec3a8614383c0676137ee580ff3752881feb3405189b4fa3482aa3d8a758012",
|
||||
"mandatory": false,
|
||||
"platforms": {
|
||||
"windows-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "bd78ead7711b23a25b1a30278ec381bd762b595e91c4c00f7370c62d785740f7",
|
||||
"sha256": "aec3a8614383c0676137ee580ff3752881feb3405189b4fa3482aa3d8a758012",
|
||||
"os": "windows",
|
||||
"arch": "amd64"
|
||||
},
|
||||
"darwin-arm64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||
"sha256": "237962c24fb875f3dd2a5ecfad0db5d6837cefb6b691860a3e1d6f0e721f8449",
|
||||
"sha256": "f86c20342b6ffa7cdea900de67a8ce3eb28ffffae2b209b45dbe13078361606c",
|
||||
"os": "darwin",
|
||||
"arch": "arm64"
|
||||
},
|
||||
"darwin-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||
"sha256": "91430bb85df68b3816d9cc643b1bdc3d022410473c4f87f4d8573bb99259ba45",
|
||||
"sha256": "1c9abd8f7d496fa71e86a93b459e95121d0da11298b7c8c7de8671009cf6f716",
|
||||
"os": "darwin",
|
||||
"arch": "amd64"
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"FixedFileInfo": {
|
||||
"FileVersion": { "Major": 1, "Minor": 9, "Patch": 0, "Build": 0 },
|
||||
"ProductVersion": { "Major": 1, "Minor": 9, "Patch": 0, "Build": 0 },
|
||||
"FileVersion": { "Major": 2, "Minor": 0, "Patch": 0, "Build": 0 },
|
||||
"ProductVersion": { "Major": 2, "Minor": 0, "Patch": 0, "Build": 0 },
|
||||
"FileFlagsMask": "3f",
|
||||
"FileFlags": "00",
|
||||
"FileOS": "40004",
|
||||
@@ -10,13 +10,13 @@
|
||||
},
|
||||
"StringFileInfo": {
|
||||
"CompanyName": "EvilFox",
|
||||
"FileDescription": "Navis VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)",
|
||||
"FileVersion": "1.9.0.0",
|
||||
"FileDescription": "Navis 2 — VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)",
|
||||
"FileVersion": "2.0.0.0",
|
||||
"InternalName": "Navis",
|
||||
"LegalCopyright": "Copyright (c) EvilFox",
|
||||
"OriginalFilename": "Navis.exe",
|
||||
"ProductName": "Navis",
|
||||
"ProductVersion": "1.9.0.0",
|
||||
"ProductVersion": "2.0.0.0",
|
||||
"Comments": "Open-source VPN/proxy client. https://evilfox.win/"
|
||||
},
|
||||
"VarFileInfo": {
|
||||
|
||||
Reference in New Issue
Block a user