mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-07 05:35:00 +03:00
66740b7ef4
* fix(frontend): preserve edited server drafts * fix(frontend): retain Xray server projections * fix(frontend): keep draft controls internal * fix(frontend): rehydrate saved redacted settings * fix(frontend): order saved draft hydration * fix(frontend): preserve draft baselines on security saves --------- Co-authored-by: PathGao <gaoyanbo@gaoyanbodeMacBook-Air.local>
38 lines
1.3 KiB
TypeScript
38 lines
1.3 KiB
TypeScript
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
|
export function useServerDraft<T>(server: T | undefined, clone: (value: T) => T, equals: (left: T, right: T) => boolean) {
|
|
const cloneRef = useRef(clone);
|
|
const equalsRef = useRef(equals);
|
|
cloneRef.current = clone;
|
|
equalsRef.current = equals;
|
|
|
|
const [draft, setDraft] = useState<T | undefined>();
|
|
const [baseline, setBaseline] = useState<T | undefined>();
|
|
const draftRef = useRef(draft);
|
|
const baselineRef = useRef(baseline);
|
|
draftRef.current = draft;
|
|
baselineRef.current = baseline;
|
|
|
|
useEffect(() => {
|
|
if (server === undefined) return;
|
|
const currentDraft = draftRef.current;
|
|
const currentBaseline = baselineRef.current;
|
|
const isDirty = currentDraft !== undefined
|
|
&& (currentBaseline === undefined || !equalsRef.current(currentDraft, currentBaseline));
|
|
setBaseline(server);
|
|
if (isDirty && !equalsRef.current(currentDraft, server)) return;
|
|
setDraft(cloneRef.current(server));
|
|
}, [server]);
|
|
|
|
const markSaved = useCallback((value: T) => {
|
|
setBaseline(cloneRef.current(value));
|
|
}, []);
|
|
|
|
const isDirty = useMemo(
|
|
() => draft !== undefined && (baseline === undefined || !equalsRef.current(draft, baseline)),
|
|
[baseline, draft],
|
|
);
|
|
|
|
return { draft, setDraft, isDirty, markSaved };
|
|
}
|