- Replace manual timeout/pending-value debounce logic with `@tanstack/react-pacer` `Debouncer` - Keep `removeItem`/`flush` behavior while simplifying and standardizing persistence timing
Unified · Split
| @@ -14,6 +14,7 @@ import { · 13 unmodified lines | ||
| 14 | 14 | DEFAULT_RUNTIME_MODE, |
| 15 | 15 | type ChatImageAttachment, |
| 16 | 16 | } from "./types"; |
| 17 | +import { Debouncer } from "@tanstack/react-pacer"; | |
| 17 | 18 | import { create } from "zustand"; |
| 18 | 19 | import { createJSONStorage, persist, type StateStorage } from "zustand/middleware"; |
| 19 | 20 | |
| @@ -27,41 +28,24 @@ interface DebouncedStorage extends StateStorage { · 7 unmodified lines | ||
| 27 | 28 | } |
| 28 | 29 | |
| 29 | 30 | export function createDebouncedStorage(baseStorage: StateStorage): DebouncedStorage { |
| 30 | − let timer: ReturnType<typeof setTimeout> | null = null; | |
| 31 | − let pendingName: string | null = null; | |
| 32 | − let pendingValue: string | null = null; | |
| 31 | + const debouncedSetItem = new Debouncer( | |
| 32 | + (name: string, value: string) => { | |
| 33 | + baseStorage.setItem(name, value); | |
| 34 | + }, | |
| 35 | + { wait: COMPOSER_PERSIST_DEBOUNCE_MS }, | |
| 36 | + ); | |
| 37 | + | |
| 33 | 38 | return { |
| 34 | 39 | getItem: (name) => baseStorage.getItem(name), |
| 35 | 40 | setItem: (name, value) => { |
| 36 | − pendingName = name; | |
| 37 | − pendingValue = value; | |
| 38 | − if (timer !== null) { | |
| 39 | − clearTimeout(timer); | |
| 40 | − } | |
| 41 | − timer = setTimeout(() => { | |
| 42 | − timer = null; | |
| 43 | − pendingName = null; | |
| 44 | − pendingValue = null; | |
| 45 | − baseStorage.setItem(name, value); | |
| 46 | − }, COMPOSER_PERSIST_DEBOUNCE_MS); | |
| 41 | + debouncedSetItem.maybeExecute(name, value); | |
| 47 | 42 | }, |
| 48 | 43 | removeItem: (name) => { |
| 49 | − if (timer !== null) { | |
| 50 | − clearTimeout(timer); | |
| 51 | − timer = null; | |
| 52 | − pendingName = null; | |
| 53 | − pendingValue = null; | |
| 54 | − } | |
| 44 | + debouncedSetItem.cancel(); | |
| 55 | 45 | baseStorage.removeItem(name); |
| 56 | 46 | }, |
| 57 | 47 | flush: () => { |
| 58 | − if (timer !== null && pendingName !== null && pendingValue !== null) { | |
| 59 | − clearTimeout(timer); | |
| 60 | − timer = null; | |
| 61 | − baseStorage.setItem(pendingName, pendingValue); | |
| 62 | − pendingName = null; | |
| 63 | − pendingValue = null; | |
| 64 | − } | |
| 48 | + debouncedSetItem.flush(); | |
| 65 | 49 | }, |
| 66 | 50 | }; |
| 67 | 51 | } |