fix: DP missing in 1:1 for un-messaged contacts; make web updates fully silent (batch80)
DP bug — real cause found (client-side, not the DB):
loadSidebar builds a DM row for every contact you haven't messaged yet, but it copied only
{name, online} from the contact and DROPPED `avatar` (and status/email). So an un-messaged
contact always rendered initials in the 1:1, while the SAME person showed their photo in a
group (which reads /api/groups/members). Carry the whole contact through.
Kept a server-side safety net: avatarsFor() now indexes known photos under person-id, email
AND name, so a duplicate row missing a photo can match on any of them (the previous single
composite key missed twins with different emails).
Web updates are now completely silent: no banner, no toast. A web build is an implementation
detail — surfacing it makes users reason about "web build vs app version", which is exactly
the confusion to avoid. New code simply applies itself as soon as it's safe.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1002,7 +1002,7 @@
|
||||
<body>
|
||||
<script src="/icons.js?v=6"></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-14-batch79';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
<script>window.__BUILD='2026-07-14-batch80';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>
|
||||
@@ -1649,7 +1649,10 @@ async function loadSidebar(){
|
||||
CONTACTS=(Array.isArray(contacts)?contacts:[]).filter(c=>c.id!==(ME&&ME.id)); // self isn't a normal contact (#4)
|
||||
const items=Array.isArray(convos)?convos.slice():[];
|
||||
const dmIds=new Set(items.filter(i=>i.kind==='dm').map(i=>i.id));
|
||||
for(const c of CONTACTS){ if(!dmIds.has(c.id)) items.push({ kind:'dm', id:c.id, name:c.name, online:!!c.online, last_body:'', last_at:0, last_from_me:false, unread:0 }); }
|
||||
// A contact you haven't messaged YET still needs their profile photo/status: this row was being built
|
||||
// with only name+online, silently dropping `avatar` — so the same person showed their DP in a group
|
||||
// (which reads /api/groups/members) but fell back to initials in the 1:1. Carry the whole contact.
|
||||
for(const c of CONTACTS){ if(!dmIds.has(c.id)) items.push({ kind:'dm', id:c.id, name:c.name, email:c.email||'', avatar:c.avatar||null, online:!!c.online, status:c.status||'active', last_body:'', last_at:0, last_from_me:false, unread:0 }); }
|
||||
const onlineById={}; CONTACTS.forEach(c=>onlineById[c.id]=!!c.online);
|
||||
items.forEach(it=>{ if(it.kind==='dm') it.online=!!onlineById[it.id]; });
|
||||
// Always-available "You" chat (note to self), pinned to the top (#4).
|
||||
@@ -2814,8 +2817,7 @@ function scheduleAutoRefresh(){
|
||||
if(!_newBuild) return;
|
||||
if(!safeToRefresh()) return; // busy → try again shortly
|
||||
clearInterval(_autoRefreshTimer); _autoRefreshTimer=null;
|
||||
try{ sessionStorage.setItem('bzc_autoref','1'); }catch(_){} // so we can confirm after reload
|
||||
hardReloadApp();
|
||||
hardReloadApp(); // silent: no banner, no toast
|
||||
};
|
||||
_autoRefreshTimer=setInterval(tryNow, 15000);
|
||||
setTimeout(tryNow, 1200); // usually applies right away
|
||||
@@ -2832,7 +2834,8 @@ setInterval(checkWebBuild, 5*60*1000); // every 5 min
|
||||
window.addEventListener('focus', checkWebBuild); // and whenever the user comes back to the app
|
||||
document.addEventListener('visibilitychange', ()=>{ if(!document.hidden) checkWebBuild(); });
|
||||
setTimeout(checkWebBuild, 3000); // shortly after boot
|
||||
try{ if(sessionStorage.getItem('bzc_autoref')){ sessionStorage.removeItem('bzc_autoref'); setTimeout(()=>toast('Updated to the latest version'),1200); } }catch(_){}
|
||||
// Deliberately NO banner and NO toast: a web build is an implementation detail. Surfacing it would make
|
||||
// users think about "web build vs app version". It just updates.
|
||||
// Small 'i' badge on the profile button when an update is pending; clicking opens Settings.
|
||||
function applyUpdateBadge(){
|
||||
document.querySelectorAll('.upd-dot').forEach(x=>x.remove());
|
||||
|
||||
Reference in New Issue
Block a user