@@ -69,6 +69,7 @@ const defaultChatRenderOptions: ChatRenderOptions = {
6969 timeZone : CHAT_RENDER_TIME_ZONE ,
7070 useRelativeDayLabels : false ,
7171} ;
72+ const CHAT_DRAFT_WRITE_DELAY_MS = 150 ;
7273
7374function getChatDraftStorageKey ( {
7475 threadId,
@@ -174,6 +175,13 @@ const ChatWindow = memo(function ChatWindow({
174175 const realListing = isDemo ? null : ( listing as ChatListing ) ;
175176 const sendMutation = useInlineMutation < ChatSendResult > ( ) ;
176177 const lastReadSignatureRef = useRef < string | null > ( null ) ;
178+ const draftWriteTimeoutRef = useRef < ReturnType < typeof setTimeout > | null > (
179+ null
180+ ) ;
181+ const pendingDraftWriteRef = useRef < {
182+ key : string ;
183+ message : string ;
184+ } | null > ( null ) ;
177185
178186 const [ message , setMessage ] = useState ( "" ) ;
179187 const [ threadId , setThreadId ] = useState < string | null > (
@@ -239,11 +247,51 @@ const ChatWindow = memo(function ChatWindow({
239247 return errorMessage ;
240248 }
241249
250+ function clearPendingDraftWrite ( ) {
251+ if ( draftWriteTimeoutRef . current ) {
252+ clearTimeout ( draftWriteTimeoutRef . current ) ;
253+ draftWriteTimeoutRef . current = null ;
254+ }
255+ }
256+
257+ function flushPendingDraftWrite ( ) {
258+ clearPendingDraftWrite ( ) ;
259+
260+ if ( ! pendingDraftWriteRef . current ) {
261+ return ;
262+ }
263+
264+ const { key, message } = pendingDraftWriteRef . current ;
265+ pendingDraftWriteRef . current = null ;
266+ sessionStorage . setItem ( key , message ) ;
267+ }
268+
269+ function scheduleDraftWrite ( key : string , nextMessage : string ) {
270+ clearPendingDraftWrite ( ) ;
271+ pendingDraftWriteRef . current = {
272+ key,
273+ message : nextMessage ,
274+ } ;
275+ draftWriteTimeoutRef . current = setTimeout ( ( ) => {
276+ flushPendingDraftWrite ( ) ;
277+ } , CHAT_DRAFT_WRITE_DELAY_MS ) ;
278+ }
279+
280+ function removeDraftWrite ( key : string ) {
281+ if ( pendingDraftWriteRef . current ?. key === key ) {
282+ clearPendingDraftWrite ( ) ;
283+ pendingDraftWriteRef . current = null ;
284+ }
285+
286+ sessionStorage . removeItem ( key ) ;
287+ }
288+
242289 useEffect ( ( ) => {
243290 setClientTimeZone ( getClientTimeZone ( ) ) ;
244291 } , [ ] ) ;
245292
246293 useEffect ( ( ) => {
294+ flushPendingDraftWrite ( ) ;
247295 setThreadId ( existingThread ?. id ?? null ) ;
248296 setMessages ( getThreadMessages ( existingThread ) ) ;
249297 setMessage (
@@ -252,6 +300,13 @@ const ChatWindow = memo(function ChatWindow({
252300 lastReadSignatureRef . current = null ;
253301 } , [ draftStorageKey , existingThread ] ) ;
254302
303+ useEffect (
304+ ( ) => ( ) => {
305+ flushPendingDraftWrite ( ) ;
306+ } ,
307+ [ ]
308+ ) ;
309+
255310 useEffect ( ( ) => {
256311 if ( isDemo || ! supabase || ! threadId || ! user ?. id ) {
257312 return ;
@@ -386,7 +441,7 @@ const ChatWindow = memo(function ChatWindow({
386441 setThreadId ( sentThreadId ) ;
387442 setMessages ( ( previousMessages ) => [ ...previousMessages , sentMessage ] ) ;
388443 if ( draftStorageKey ) {
389- sessionStorage . removeItem ( draftStorageKey ) ;
444+ removeDraftWrite ( draftStorageKey ) ;
390445 }
391446 setMessage ( "" ) ;
392447 }
@@ -408,9 +463,9 @@ const ChatWindow = memo(function ChatWindow({
408463 }
409464
410465 if ( nextMessage . trim ( ) . length > 0 ) {
411- sessionStorage . setItem ( draftStorageKey , nextMessage ) ;
466+ scheduleDraftWrite ( draftStorageKey , nextMessage ) ;
412467 } else {
413- sessionStorage . removeItem ( draftStorageKey ) ;
468+ removeDraftWrite ( draftStorageKey ) ;
414469 }
415470 } ;
416471
0 commit comments