History

Use Debouncer for composer draft persistence writes

- Replace manual timeout/pending-value debounce logic with `@tanstack/react-pacer` `Debouncer` - Keep `removeItem`/`flush` behavior while simplifying and standardizing persistence timing

Julius Marminge committed 8 months ago

Commit 82c0a451 parent e7650511 file · +11 −27Browse files

Unified · Split

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