From 3f41ca857acd790b4d040c93e56941347545f846 Mon Sep 17 00:00:00 2001 From: sravan Date: Mon, 17 Aug 2026 14:08:31 +0530 Subject: [PATCH] chat list: clear the stale "message deleted" label when a newer message arrives The sidebar shows "This message was deleted" whenever a row's last_deleted flag is set, but the new-message handlers (incoming, my-sent, edit) updated the preview text and never cleared last_deleted. So once a conversation's last message had been deleted (server-computed last_deleted=true at load), a NEWER message left the flag stale and the list kept showing "deleted"/"you deleted this" even though the actual last message was a normal one. Remote deletes already self-corrected via onChatDeleted->loadSidebar; this was the in-session new-message path. Now last_deleted is cleared wherever a fresh non-deleted message becomes the row's last message. Web-only; live on next app launch. Co-Authored-By: Claude Opus 4.8 --- server/public/home.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/public/home.html b/server/public/home.html index dbcc35f..5a96348 100644 --- a/server/public/home.html +++ b/server/public/home.html @@ -2437,7 +2437,7 @@ async function saveEdit(text){ const t=THREAD.find(x=>x.id===m.id); if(t){ t.body=text; t.edited_at=Date.now(); updateBubble(t); } THREAD_CACHE.forEach(arr=>arr.forEach(x=>{ if(x.id===m.id){ x.body=text; x.edited_at=Date.now(); } })); // keep the chat-list preview in sync if this was the last message - const it=rowFor(selected.kind, selected.id); if(it && it.last_from_me){ const last=THREAD[THREAD.length-1]; if(last && last.id===m.id){ it.last_body=text; renderChats(searchVal()); } } + const it=rowFor(selected.kind, selected.id); if(it && it.last_from_me){ const last=THREAD[THREAD.length-1]; if(last && last.id===m.id){ it.last_body=text; it.last_deleted=false; renderChats(searchVal()); } } }catch(e){ toast(e.message||'Could not edit'); } } // A message I can see was edited by its sender → update it in place (thread + cache + list preview). @@ -3892,7 +3892,7 @@ async function sendMessage(){ if(!THREAD.some(x=>x.id===m.id)){ THREAD.push(m); appendBubble(m); } { const ck=selected.kind+':'+selected.id; if(THREAD_CACHE.has(ck)){ const a=THREAD_CACHE.get(ck); if(!a.some(x=>x.id===m.id)) a.push(m); } } const it=rowFor(selected.kind,selected.id); - if(it){ it.last_body=m.body||(m.attachment?'📎 '+(m.attachment.name||'Attachment'):''); it.last_at=m.created_at; it.last_from_me=true; it.last_status='sent'; it.last_msg_id=m.id; it.unread=0; } + if(it){ it.last_body=m.body||(m.attachment?'📎 '+(m.attachment.name||'Attachment'):''); it.last_at=m.created_at; it.last_from_me=true; it.last_status='sent'; it.last_msg_id=m.id; it.unread=0; it.last_deleted=false; } // clear any stale "deleted" list label — this fresh message is the new last one }catch(e){ toast(e.message||'Could not send'); if(j.body && !inp.value){ inp.value=j.body; try{ autoGrow(inp); }catch(_){} } } } composeMentions=new Map(); @@ -4558,7 +4558,7 @@ function onChatMessage(m){ else if(kind==='dm' && wasNew) addNotif({icon:'chat', text:'New chat from '+pEsc(m.fromName||'someone'), link:{kind:'dm', id:rid}}); } if(it){ - it.last_body=isSys?m.body:(m.body||(m.attachment?'📎 '+(m.attachment.name||'Attachment'):'')); it.last_at=m.created_at; it.last_from_me=(m.from===ME.id); + it.last_body=isSys?m.body:(m.body||(m.attachment?'📎 '+(m.attachment.name||'Attachment'):'')); it.last_at=m.created_at; it.last_from_me=(m.from===ME.id); it.last_deleted=false; // a fresh message means the last message is no longer a deleted one — clear the stale "deleted" list label // #6: the server echoes my own sent message back — don't let that echo DOWNGRADE a delivered/read // tick that already arrived for this same message (it would flip the list back to a single tick). if(m.from===ME.id){ if(!(it.last_msg_id===m.id && (it.last_status==='delivered'||it.last_status==='read'))) it.last_status='sent'; it.last_msg_id=m.id; }