Add decoy SNI plumbing, bundle wintun.dll, fix flag icons, add docs
- Прокидываем sni (decoy-хост) по обновлённому UDL через весь стек: guest-js -> Tauri-команда -> desktop/mobile -> Kotlin spawnSession. Список серверов пока статичный (backend еще не отдает sni), но логика похода в реальный /api/v1/nodes оставлена под флагом на будущее. - Бандлим wintun.dll в Windows-инсталлятор через bundle.resources в tauri.windows.conf.json - раньше он копировался только для локального cargo run/tauri dev, но не попадал в NSIS/MSI. - Чиним падение мобильной сборки: гитигнорённые UniFFI Kotlin-биндинги отстали от обновленного UDL (не хватало параметра sni). - Флаги стран - локальные SVG вместо react-country-flag в CDN-режиме: тот бился об CSP и не грузился офлайн. - Добавляем дерево README.md по структуре проекта и точечные комментарии в неочевидных местах кода. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,17 @@ import ReactCountryFlag from "react-country-flag";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useNodesStore } from "@/store/useNodesStore";
|
||||
import { useVpnStore } from "@/store/useVpnStore";
|
||||
import flagNl from "@/assets/flags/nl.svg";
|
||||
import flagSg from "@/assets/flags/sg.svg";
|
||||
|
||||
// react-country-flag в режиме svg тянет иконки с внешнего CDN — это бьётся об
|
||||
// CSP (img-src) и вообще не грузится без сети. Для известных статических
|
||||
// узлов используем забандленные локальные SVG, а для остальных кодов —
|
||||
// эмодзи-режим той же либы (без сети, просто текстовый глиф).
|
||||
const LOCAL_FLAGS: Record<string, string> = {
|
||||
nl: flagNl,
|
||||
sg: flagSg,
|
||||
};
|
||||
|
||||
export function CountrySelect() {
|
||||
const { t } = useTranslation();
|
||||
@@ -57,11 +68,18 @@ export function CountrySelect() {
|
||||
className="cursor-pointer hover:bg-white/10 focus:bg-white/20 transition-colors"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<ReactCountryFlag
|
||||
countryCode={node.countryCode.toUpperCase()}
|
||||
svg
|
||||
className="size-5 rounded-sm"
|
||||
/>
|
||||
{LOCAL_FLAGS[node.countryCode.toLowerCase()] ? (
|
||||
<img
|
||||
src={LOCAL_FLAGS[node.countryCode.toLowerCase()]}
|
||||
alt=""
|
||||
className="size-5 rounded-sm object-cover"
|
||||
/>
|
||||
) : (
|
||||
<ReactCountryFlag
|
||||
countryCode={node.countryCode.toUpperCase()}
|
||||
className="size-5 rounded-sm"
|
||||
/>
|
||||
)}
|
||||
<span className="font-medium text-foreground">{node.name}</span>
|
||||
<span className="ml-auto text-xs text-muted-foreground">
|
||||
{node.currentLoad}%
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# `src/features/`
|
||||
|
||||
Крупные самостоятельные UI-блоки (в отличие от `components/ui` — не
|
||||
переиспользуемые примитивы, а конкретные фичи приложения).
|
||||
|
||||
| Файл | Назначение |
|
||||
|---|---|
|
||||
| `VpnControl.tsx` | Главная кнопка подключения. Берёт выбранный узел из `useNodesStore`, собирает `TunnelConfig` из `useSettingsStore` и вызывает `startVpn(config, ip, port, sni)` из `vpn-plugin`. Слушает Tauri-event `status-change`. |
|
||||
| `CountrySelect.tsx` | Выпадающий список серверов (`useNodesStore`). Флаги — локальные SVG (`assets/flags`) для известных статических узлов, иначе эмодзи-фолбэк через `react-country-flag` (**намеренно без** `svg`-режима этой либы — он тянет иконки с внешнего CDN, что бьётся об CSP и не грузится офлайн). Заблокирован во время подключения. |
|
||||
| `VpnStats.tsx` | RX/TX счётчики трафика из `useTrafficStore`, форматирование байт в человекочитаемый вид. |
|
||||
| `Header.tsx` | Шапка: бургер-кнопка, лого, переключатели темы/языка. |
|
||||
| `BurgerMenu.tsx` | Выезжающее боковое меню с навигацией (Home/Settings/Telegram/About). |
|
||||
| `ThemeToggle.tsx` / `ToggleLanguge.tsx` | Точечные переключатели темы и языка (RU/EN), делегируют в `ThemeProvider`/`i18n`. |
|
||||
| `SplashScreen.tsx` | Интро-заставка при старте (~5 сек), скрывается по таймеру. |
|
||||
| `AppExclusions.tsx` | Диалог выбора приложений для исключения из VPN-туннеля. На Android дёргает `getInstalledApps()` из `vpn-plugin`, на остальных платформах — заглушка. Результат пишется в `useSettingsStore.excludedApps`. |
|
||||
@@ -38,7 +38,7 @@ export function VpnControl() {
|
||||
excludedApps: excludedApps,
|
||||
excludedDomains: excludedDomains,
|
||||
};
|
||||
await startVpn(config, node.ipAddress, node.port);
|
||||
await startVpn(config, node.ipAddress, node.port, node.sni);
|
||||
} else {
|
||||
await stopVpn();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user