mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-10 15:26:38 +08:00
fix: stop pinned-library toggle from saving an empty list (#23)
The pin hook captured the optimistic ID list inside a React setState updater. That updater can run after the following lines, so save ran with optimistic=[] and overwrote server pins — matching the flash then wipe when pinning a mounted Emby library after a local pin. Compute previous/optimistic synchronously from a ref before calling setState. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: truewhile <truewhile@users.noreply.github.com>
This commit is contained in:
@@ -12,6 +12,12 @@ export function usePinnedLibraries() {
|
|||||||
const [syncing, setSyncing] = useState(false)
|
const [syncing, setSyncing] = useState(false)
|
||||||
const [loadError, setLoadError] = useState(false)
|
const [loadError, setLoadError] = useState(false)
|
||||||
const loadedRef = useRef(false)
|
const loadedRef = useRef(false)
|
||||||
|
const pinnedIdsRef = useRef<string[]>([])
|
||||||
|
const syncingRef = useRef(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
pinnedIdsRef.current = pinnedIds
|
||||||
|
}, [pinnedIds])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
@@ -22,6 +28,7 @@ export function usePinnedLibraries() {
|
|||||||
.then((ids) => {
|
.then((ids) => {
|
||||||
if (cancelled) return
|
if (cancelled) return
|
||||||
loadedRef.current = true
|
loadedRef.current = true
|
||||||
|
pinnedIdsRef.current = ids
|
||||||
setPinnedIds(ids)
|
setPinnedIds(ids)
|
||||||
setLoadError(false)
|
setLoadError(false)
|
||||||
})
|
})
|
||||||
@@ -29,7 +36,6 @@ export function usePinnedLibraries() {
|
|||||||
if (cancelled) return
|
if (cancelled) return
|
||||||
loadedRef.current = false
|
loadedRef.current = false
|
||||||
setLoadError(true)
|
setLoadError(true)
|
||||||
// Keep any existing pins in memory; never replace a known server list with [].
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
if (!cancelled) setLoading(false)
|
if (!cancelled) setLoading(false)
|
||||||
@@ -40,25 +46,27 @@ export function usePinnedLibraries() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const togglePin = useCallback(async (libraryId: string) => {
|
const togglePin = useCallback(async (libraryId: string) => {
|
||||||
// Avoid saving from an unloaded/failed state — that would overwrite the
|
if (!loadedRef.current || loading || loadError || syncingRef.current) return
|
||||||
// server list with only the clicked id and can wipe existing local pins
|
|
||||||
// when mounted Emby ids used to be filtered out server-side.
|
|
||||||
if (!loadedRef.current || loading || loadError) return
|
|
||||||
|
|
||||||
let previous: string[] = []
|
// Compute the next list synchronously from a ref. Do NOT capture the next
|
||||||
let optimistic: string[] = []
|
// value inside setState updater callbacks — React may defer those, leaving
|
||||||
setPinnedIds((current) => {
|
// optimistic as [] and wiping the server-side pin list.
|
||||||
previous = current
|
const previous = pinnedIdsRef.current
|
||||||
optimistic = togglePinnedLibraryId(current, libraryId)
|
const optimistic = togglePinnedLibraryId(previous, libraryId)
|
||||||
return optimistic
|
|
||||||
})
|
pinnedIdsRef.current = optimistic
|
||||||
|
setPinnedIds(optimistic)
|
||||||
|
syncingRef.current = true
|
||||||
setSyncing(true)
|
setSyncing(true)
|
||||||
try {
|
try {
|
||||||
const saved = await savePinnedLibraryIds(optimistic)
|
const saved = await savePinnedLibraryIds(optimistic)
|
||||||
|
pinnedIdsRef.current = saved
|
||||||
setPinnedIds(saved)
|
setPinnedIds(saved)
|
||||||
} catch {
|
} catch {
|
||||||
|
pinnedIdsRef.current = previous
|
||||||
setPinnedIds(previous)
|
setPinnedIds(previous)
|
||||||
} finally {
|
} finally {
|
||||||
|
syncingRef.current = false
|
||||||
setSyncing(false)
|
setSyncing(false)
|
||||||
}
|
}
|
||||||
}, [loading, loadError])
|
}, [loading, loadError])
|
||||||
|
|||||||
Reference in New Issue
Block a user