Refactor VPN proxy components and update related behavior
Build and Deploy Gateway / build-and-push (push) Successful in 20s
Build and Deploy Gateway / deploy (push) Successful in 13s

This commit is contained in:
2026-08-11 01:27:46 +03:00
parent c89e56942a
commit aa9c959368
58 changed files with 4234 additions and 2755 deletions
+21 -13
View File
@@ -53,9 +53,9 @@ function write(key: string, value: string | string[]) {
}
}
function readAuto() {
function readAuto(key: string) {
try {
return localStorage.getItem(AUTO_KEY) === 'true';
return localStorage.getItem(key) === 'true';
} catch {
return false;
}
@@ -153,7 +153,8 @@ function ServerRow({
}
interface ServerPickerProps {
pingServers: (ids: string[]) => Promise<unknown>;
profileId: string;
pingServers: (profileId: string, ids: string[]) => Promise<unknown>;
servers: PickerServer[];
selectedServerId: string;
disabled: boolean;
@@ -164,6 +165,7 @@ interface ServerPickerProps {
}
export function ServerPicker({
profileId,
pingServers,
servers,
selectedServerId,
@@ -173,13 +175,16 @@ export function ServerPicker({
revealVersion,
onSelect,
}: ServerPickerProps) {
const favoritesKey = `${FAVORITES_KEY}:${profileId}`;
const recentKey = `${RECENT_KEY}:${profileId}`;
const autoKey = `${AUTO_KEY}:${profileId}`;
const [query, setQuery] = useState('');
const [advanced, setAdvanced] = useState(false);
const [view, setView] = useState<'all' | 'favorites' | 'recent'>('all');
const [page, setPage] = useState(0);
const [favorites, setFavorites] = useState(() => readList(FAVORITES_KEY));
const [recent, setRecent] = useState(() => readList(RECENT_KEY));
const [autoActive, setAutoActive] = useState(readAuto);
const [favorites, setFavorites] = useState(() => readList(favoritesKey));
const [recent, setRecent] = useState(() => readList(recentKey));
const [autoActive, setAutoActive] = useState(() => readAuto(autoKey));
const [collapsed, setCollapsed] = useState<string[]>([]);
const [pings, setPings] = useState<PingState>({});
const [checking, setChecking] = useState(false);
@@ -208,18 +213,18 @@ export function ServerPicker({
function toggleFavorite(id: string) {
setFavorites((current) => {
const next = current.includes(id) ? current.filter((item) => item !== id) : [id, ...current];
write(FAVORITES_KEY, next);
write(favoritesKey, next);
return next;
});
}
function select(id: string, automatic = false) {
setAutoActive(automatic);
write(AUTO_KEY, String(automatic));
write(autoKey, String(automatic));
if (!automatic) {
setRecent((current) => {
const next = [id, ...current.filter((item) => item !== id)].slice(0, 5);
write(RECENT_KEY, next);
write(recentKey, next);
return next;
});
}
@@ -236,7 +241,7 @@ export function ServerPicker({
...Object.fromEntries(ids.map((id) => [id, { ...current[id], checking: true }])),
}));
try {
const results = parseServerPingResults(await pingServers(ids)) as PingResult[];
const results = parseServerPingResults(await pingServers(profileId, ids)) as PingResult[];
setPings((current) => ({
...current,
...Object.fromEntries(results.map((result) => [result.id, { ...result, checking: true }])),
@@ -251,7 +256,10 @@ export function ServerPicker({
}])),
}));
} finally {
await new Promise((resolve) => setTimeout(resolve, Math.max(0, 900 - (performance.now() - startedAt))));
const elapsed = performance.now() - startedAt;
const reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
const completeAt = reduced ? elapsed : Math.max(900, Math.ceil(elapsed / 900) * 900);
await new Promise((resolve) => setTimeout(resolve, Math.max(0, completeAt - elapsed)));
setPings((current) => ({
...current,
...Object.fromEntries(ids.map((id) => [id, { ...current[id], checking: false }])),
@@ -324,7 +332,7 @@ export function ServerPicker({
inert={advanced ? true : undefined}
>
<div className="client-server-mode-panel-inner">
<div className={`client-server-scroll${leaving ? ' is-leaving' : ''}`} key={`simple:${serverKey}:${revealVersion}`}>
<div className={`client-server-scroll${leaving ? ' is-leaving' : ''}`} key={`simple:${revealVersion}`}>
<div className="client-server-grid">
{simpleServers.map((server, index) => <ServerRow
key={server.id}
@@ -401,7 +409,7 @@ export function ServerPicker({
/>}
</div>
<div className={`client-server-scroll${leaving ? ' is-leaving' : ''}`} key={`advanced:${serverKey}:${revealVersion}`}>
<div className={`client-server-scroll${leaving ? ' is-leaving' : ''}`} key={`advanced:${revealVersion}`}>
{!visible.length && <p className="client-server-empty">Серверы не найдены</p>}
{grouped ? groupServers(visible).map(([group, items]) => {
const isCollapsed = collapsed.includes(group);