fix(ui): читать актуальную цель копирования Filters

This commit is contained in:
Denozordec committed 2026-09-30 12:10:20 +07:00
1 parent 365ab2173c
commit 860e88ed3e
5 files changed
+99 -10

No files matched your search

+20 -8
View File
@@ -1527,7 +1527,7 @@ function FiltersPage() {
const applyRules = useCallback(async (
serverId: string,
nextRules: FilterRule[],
nextRules: FilterRule[] | (() => Promise<FilterRule[]>),
source: "apply" | "copy" = "apply",
) => {
if (!mounted.current) return { ok: false, error: "Источник данных изменён" }
@@ -1538,7 +1538,8 @@ function FiltersPage() {
return { ok: false, error }
}
if (!isLive) {
setRulesets(p => p.map(rs => rs.serverId === serverId ? { ...rs, rules: nextRules } : rs))
const rules = typeof nextRules === "function" ? await nextRules() : nextRules
setRulesets(p => p.map(rs => rs.serverId === serverId ? { ...rs, rules } : rs))
return { ok: true }
}
applyLock.current = true
@@ -1546,15 +1547,17 @@ function FiltersPage() {
setRulesReading(false)
setApplyBusy(true)
try {
const rules = typeof nextRules === "function" ? await nextRules() : nextRules
if (!mounted.current) return { ok: false, error: "Источник данных изменён" }
const payload = await apiFetch<unknown>("/api/filters/rules", {
method: "PUT",
body: JSON.stringify({ serverId, rules: nextRules, source }),
body: JSON.stringify({ serverId, rules, source }),
})
if (!mounted.current) return { ok: false, error: "Источник данных изменён" }
const parsed = filtersMutationSchema.safeParse(payload)
if (!parsed.success) throw new Error("Сервер не подтвердил применение правил")
const res = parsed.data
setRulesets(p => p.map(rs => rs.serverId === serverId ? { ...rs, rules: res.rules ?? nextRules } : rs))
setRulesets(p => p.map(rs => rs.serverId === serverId ? { ...rs, rules: res.rules ?? rules } : rs))
toast.success("Правила применены на роутер")
return { ok: true }
} catch (err) {
@@ -1718,11 +1721,20 @@ function FiltersPage() {
}
const handleCopyRules = useCallback(async (targetServerId: string, rules: FilterRule[], mode: CopyMode) => {
const existing = rulesets.find((rs) => rs.serverId === targetServerId)?.rules ?? []
const next = mode === "replace" ? rules : [...existing, ...rules]
const result = await applyRules(targetServerId, next, "copy")
const prepare = async () => {
const payload = await apiFetch<unknown>(`/api/filters/rules?serverId=${encodeURIComponent(targetServerId)}`)
if (!mounted.current) throw new Error("Источник данных изменён")
const parsed = filtersResponseSchema.safeParse(payload)
const target = parsed.success ? parsed.data.rulesets.find(rs => rs.serverId === targetServerId) : undefined
if (!parsed.success || !target || parsed.data.stale || parsed.data.live !== true) throw new Error("Не удалось получить актуальные правила целевого устройства")
setRulesets(prev => prev.map(rs => rs.serverId === targetServerId ? { ...rs, rules: target.rules } : rs))
return mode === "replace" ? rules : [...target.rules, ...rules]
}
const existing = rulesets.find(rs => rs.serverId === targetServerId)?.rules ?? []
const localRules = mode === "replace" ? rules : [...existing, ...rules]
const result = await applyRules(targetServerId, isLive ? prepare : localRules, "copy")
return result.ok ? null : result.error ?? "Не удалось скопировать правила"
}, [rulesets, applyRules])
}, [rulesets, applyRules, apiFetch, isLive])
const handleMove = async (id: string, direction: -1 | 1) => {
if (mutationsLocked || applyLock.current || moveLock.current) return
const index = currentRules.findIndex(r => r.id === id)