fix(ui): подтверждать переключение интерфейсов WireGuard

This commit is contained in:
Denozordec committed 2026-09-29 08:33:10 +07:00
1 parent 8fff3d7fff
commit d3ae2598fb
6 files changed
+74 -8

No files matched your search

+17 -2
View File
@@ -186,6 +186,9 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
const [loading, setLoading] = useState(true)
const [loadError, setLoadError] = useState(false)
const [busy, setBusy] = useState(false)
const toggleLock = useRef(false)
const [togglePending, setTogglePending] = useState<string | null>(null)
const [toggleError, setToggleError] = useState<string | null>(null)
const [workspaceTab, setWorkspaceTab] = useState<WgWorkspaceTab>("interfaces")
const [statusFilter, setStatusFilter] = useState<WgStatusFilter>("all")
@@ -492,19 +495,28 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
}
async function handleToggle(iface: WgIfaceWithServer) {
if (toggleLock.current) return
if (sourceUnavailable(iface.serverId)) return
if (!isLive || !iface.rosId) {
toast.info("Доступно только в live-режиме")
return
}
toggleLock.current = true
const context = `${iface.name} · ${iface.serverName}`
setTogglePending(context)
setToggleError(null)
try {
await patchWireGuardInterface(backendUrl, iface.serverId, iface.rosId, {
const result = await patchWireGuardInterface(backendUrl, iface.serverId, iface.rosId, {
disabled: iface.enabled,
})
if (result?.ok !== true) throw new Error("Сервер не подтвердил изменение интерфейса")
toast.success(iface.enabled ? "Отключено" : "Включено")
await loadLive()
} catch (e) {
toast.error(e instanceof Error ? e.message : "Ошибка")
setToggleError(`${context}: ${e instanceof Error ? e.message : "Ошибка переключения"}`)
} finally {
toggleLock.current = false
setTogglePending(null)
}
}
@@ -690,6 +702,8 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
</AlertDescription>
</Alert>
)}
{togglePending && <p role="status" className="text-sm text-muted-foreground">Изменение интерфейса {togglePending}…</p>}
{toggleError && <p role="alert" className="text-sm text-destructive">{toggleError}</p>}
<KpiStatGrid
aria-label="Сводка WireGuard"
items={[
@@ -788,6 +802,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
onExport={(iface) => openExport(iface, "rsc")}
onAddPeer={selectedSourceError ? undefined : iface => { setPeerError(null); setPeerIface(iface) }}
onToggle={selectedSourceError ? undefined : handleToggle}
toggleBusy={togglePending !== null}
onDelete={selectedSourceError ? undefined : (iface) => setPendingDelete({ kind: "iface", iface })}
onDeletePeer={selectedSourceError ? undefined : (iface, peerId) => setPendingDelete({ kind: "peer", iface, peerId })}
onExportPeer={(iface, peerId) => openExport(iface, "peer", peerId)}