diff --git a/apps/web/src/components/stickies/StickyNoteCard.tsx b/apps/web/src/components/stickies/StickyNoteCard.tsx index c8985c72..9cfcd790 100644 --- a/apps/web/src/components/stickies/StickyNoteCard.tsx +++ b/apps/web/src/components/stickies/StickyNoteCard.tsx @@ -196,8 +196,10 @@ export function StickyNoteCard({ const safeSlug = workspaceSlug.trim(); const initialHtml = getInitialStickyHtml(sticky); const debounceRef = useRef | null>(null); + const pendingHtmlRef = useRef(null); const lastSyncedHtmlRef = useRef(initialHtml); const contentRequestIdRef = useRef(0); + const stickyUpdateChainRef = useRef>(Promise.resolve()); const colorRequestIdRef = useRef(0); const colorListboxId = useId(); const [colorOpen, setColorOpen] = useState(false); @@ -209,11 +211,17 @@ export function StickyNoteCard({ if (!safeSlug) return; const plain = htmlToPlainText(html).slice(0, 255); const requestId = ++contentRequestIdRef.current; - stickiesService - .update(safeSlug, sticky.id, { + const save = stickyUpdateChainRef.current.then(() => + stickiesService.update(safeSlug, sticky.id, { description: html, name: plain || 'Untitled', - }) + }), + ); + stickyUpdateChainRef.current = save.then( + () => undefined, + () => undefined, + ); + save .then((data) => { if (requestId !== contentRequestIdRef.current) return; setContentSaveError(false); @@ -228,6 +236,11 @@ export function StickyNoteCard({ }, [safeSlug, sticky.id, onUpdate], ); + const persistStickyRef = useRef(persistSticky); + + useEffect(() => { + persistStickyRef.current = persistSticky; + }, [persistSticky]); const editor = useEditor({ extensions: [ @@ -259,15 +272,25 @@ export function StickyNoteCard({ ], content: initialHtml, onUpdate: ({ editor: ed }) => { - const html = ed.getHTML(); + pendingHtmlRef.current = ed.getHTML(); if (debounceRef.current) clearTimeout(debounceRef.current); - debounceRef.current = setTimeout(() => persistSticky(html), 400); + debounceRef.current = setTimeout(() => { + debounceRef.current = null; + const pendingHtml = pendingHtmlRef.current; + pendingHtmlRef.current = null; + if (pendingHtml !== null) persistStickyRef.current(pendingHtml); + }, 400); }, }); useEffect( () => () => { - if (debounceRef.current) clearTimeout(debounceRef.current); + if (!debounceRef.current) return; + clearTimeout(debounceRef.current); + debounceRef.current = null; + const pendingHtml = pendingHtmlRef.current; + pendingHtmlRef.current = null; + if (pendingHtml !== null) persistStickyRef.current(pendingHtml); }, [], ); @@ -295,8 +318,14 @@ export function StickyNoteCard({ const setStickyColor = (next: string) => { if (!safeSlug) return; const requestId = ++colorRequestIdRef.current; - stickiesService - .update(safeSlug, sticky.id, { color: next }) + const update = stickyUpdateChainRef.current.then(() => + stickiesService.update(safeSlug, sticky.id, { color: next }), + ); + stickyUpdateChainRef.current = update.then( + () => undefined, + () => undefined, + ); + update .then((data) => { if (requestId !== colorRequestIdRef.current) return; onUpdate(data);