- #6: the server echoes your own sent message back over the socket; onChatMessage reset last_status='sent', overwriting a delivered/read that arrived first → the chat-list tick flipped back to single. Track last_msg_id and never downgrade the same message's tick. - #3: pin the 'You' note-to-self chat in its own slot — tinted row + 'Note to self' tag + a divider separating it from the conversation list. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-5
@@ -110,6 +110,10 @@
|
||||
.chatcol{width:312px;flex:0 0 312px;background:var(--card);border-right:1px solid var(--line);display:flex;flex-direction:column;min-height:0;}
|
||||
.chatcol.hidden{display:none;}
|
||||
.side-sec{font-size:.68rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:700;padding:.6rem .9rem .25rem;}
|
||||
/* Pinned "You" (note-to-self) set apart from the conversation list (#3): tinted + a divider. */
|
||||
.side-div{height:1px;background:var(--line);margin:.4rem .7rem .3rem;}
|
||||
.chat-row.self{background:var(--blue-soft);}
|
||||
.chat-row.self .chat-name::after{content:"Note to self";font-size:.58rem;font-weight:700;color:var(--blue);background:#fff;border:1px solid var(--line);border-radius:99px;padding:.03rem .35rem;margin-left:.4rem;vertical-align:middle;text-transform:none;}
|
||||
.contact-row,.dir-row{display:flex;align-items:center;gap:.6rem;padding:.5rem .9rem;cursor:pointer;}
|
||||
.contact-row:hover,.dir-row:hover{background:var(--blue-soft);}
|
||||
.contact-row .cr-name,.dir-row .cr-name{font-size:.9rem;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
||||
@@ -753,7 +757,7 @@
|
||||
<body>
|
||||
<script src="/icons.js?v=4"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@twemoji/api@15.1.0/dist/twemoji.min.js" crossorigin="anonymous"></script>
|
||||
<script>window.__BUILD='2026-07-02-batch32';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
<script>window.__BUILD='2026-07-02-batch33';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
// Render modern (Twemoji) emojis in place of the OS's flat ones. No-op if the CDN didn't load
|
||||
// (emojis stay as plain Unicode). (#5)
|
||||
function twemojify(el){ try{ if(el && window.twemoji) window.twemoji.parse(el, { folder:'svg', ext:'.svg' }); }catch(_){} }</script>
|
||||
@@ -1089,7 +1093,7 @@ function avatarHTML(it, big){
|
||||
}
|
||||
function rowHTML(it){
|
||||
const active=selected&&selected.kind===it.kind&&selected.id===it.id;
|
||||
const cls=['chat-row']; if(active)cls.push('active'); if(it.unread>0)cls.push('unread');
|
||||
const cls=['chat-row']; if(active)cls.push('active'); if(it.unread>0)cls.push('unread'); if(it.self)cls.push('self');
|
||||
const isG=it.kind==='group';
|
||||
const draft=getDraft(it.kind,it.id);
|
||||
let inner;
|
||||
@@ -1111,7 +1115,8 @@ function renderChats(filter){
|
||||
if(!q){ // "You" pinned at top, then favourites, then the rest
|
||||
const self=rows.find(r=>r.self), others=rows.filter(r=>!r.self);
|
||||
const favs=others.filter(r=>r.favorite), rest=others.filter(r=>!r.favorite);
|
||||
let h = self ? rowHTML(self) : '';
|
||||
// "You" (note to self) sits in its own pinned slot, set apart from the conversation list.
|
||||
let h = self ? (rowHTML(self)+(others.length?'<div class="side-div"></div>':'')) : '';
|
||||
if(favs.length){ h+='<div class="side-sec">'+ic('star',12)+' Favourites</div>'+favs.map(rowHTML).join(''); if(rest.length) h+='<div class="side-sec">All chats</div>'; }
|
||||
h+=rest.map(rowHTML).join('');
|
||||
html = (self||others.length) ? h : '<div class="no-results">No conversations yet.</div>';
|
||||
@@ -1866,7 +1871,7 @@ async function sendMessage(){
|
||||
clearReply(); pendingAttach=null; hideAttach();
|
||||
{ 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.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; }
|
||||
renderChats(searchVal());
|
||||
}catch(e){ inp.value=text; toast(e.message||'Could not send'); }
|
||||
}
|
||||
@@ -2081,7 +2086,11 @@ 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_status=(m.from===ME.id)?'sent':null;
|
||||
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);
|
||||
// #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; }
|
||||
else it.last_status=null;
|
||||
if(m.from!==ME.id && !isOpen && !isSys) it.unread=(it.unread||0)+1;
|
||||
}
|
||||
if(isOpen){
|
||||
|
||||
Reference in New Issue
Block a user