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:
+18
-5
@@ -22,12 +22,25 @@ function namesFor(teamId){ const o = {}; for (const x of R.users.listByTenant(te
|
||||
// person id, else email, else name) and let a photo-less row borrow its twin's photo.
|
||||
function avatarsFor(teamId) {
|
||||
const users = R.users.listByTenant(teamId);
|
||||
const personKey = (x) => (x.bizgaze_user_id ? 'bz:' + x.bizgaze_user_id
|
||||
: (x.email ? 'em:' + String(x.email).toLowerCase() : 'nm:' + String(x.name || '').trim().toLowerCase()));
|
||||
const byPerson = {};
|
||||
for (const x of users) { if (x.avatar_url) { const k = personKey(x); if (!byPerson[k]) byPerson[k] = x.avatar_url; } }
|
||||
const em = (x) => (x.email ? String(x.email).toLowerCase() : '');
|
||||
const nm = (x) => String(x.name || '').trim().toLowerCase();
|
||||
// Index every KNOWN photo under all three identities, then let a photo-less row match on ANY of them —
|
||||
// a single composite key missed the common case where the twin rows have different emails.
|
||||
const byBz = {}, byEmail = {}, byName = {};
|
||||
for (const x of users) {
|
||||
if (!x.avatar_url) continue;
|
||||
if (x.bizgaze_user_id && !byBz[x.bizgaze_user_id]) byBz[x.bizgaze_user_id] = x.avatar_url;
|
||||
if (em(x) && !byEmail[em(x)]) byEmail[em(x)] = x.avatar_url;
|
||||
if (nm(x) && !byName[nm(x)]) byName[nm(x)] = x.avatar_url;
|
||||
}
|
||||
const out = {};
|
||||
for (const x of users) out[x.id] = x.avatar_url || byPerson[personKey(x)] || null;
|
||||
for (const x of users) {
|
||||
out[x.id] = x.avatar_url
|
||||
|| (x.bizgaze_user_id && byBz[x.bizgaze_user_id])
|
||||
|| (em(x) && byEmail[em(x)])
|
||||
|| (nm(x) && byName[nm(x)])
|
||||
|| null;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
// Next future occurrence (same time-of-day) of a weekly-recurring meeting; searches 14 days ahead.
|
||||
|
||||
Reference in New Issue
Block a user