feat: hyperlinks, group seen-by for all, profile-pic preview, in-call invite fix + desktop update progress (0.1.6)

- #1: URLs in chat are now clickable links (open externally on desktop).
- #2: group 'Seen by X, Y +N more' now shows under the LATEST message to EVERYONE
  (server computes reads for all messages; click shows the names).
- #5: tapping the conversation-header avatar previews the DP/group photo full-size.
- #4: in-call invite lists only people you've messaged, excludes those already in the
  call/invited, and the Invite button is sticky.
- #3 (0.1.6 shell): auto-updater emits checking/available/downloading/ready/error to
  the web UI, which shows a progress banner (+ Restart button) so updates aren't silent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 15:58:09 +05:30
parent 7682e17a53
commit 49718e5d37
4 changed files with 58 additions and 13 deletions
+3 -2
View File
@@ -774,10 +774,11 @@ route('GET', '/api/messages/thread', async (req, res) => {
try { CHAT.pushToUser(u.id, { type: 'notif-clear', kind: 'group', id: group }); } catch (_) {} // #13
}
const rxBy = groupReactions(R.reactions.forConversation(group), u.id, names);
const reads = R.conversations.memberReads(group).filter((r) => r.user_id !== u.id); // others' read times
const reads = R.conversations.memberReads(group); // ALL members' read times (#2: seen-by visible to everyone)
return json(res, 200, rows.map((m) => {
const d = buildMsgDTO(m, names, u.id); d.fromName = names[m.sender_id] || ''; d.reactions = dtoReactions(rxBy, m.id);
if (m.sender_id === u.id) d.seenBy = reads.filter((r) => r.last_read_at >= m.created_at).map((r) => names[r.user_id] || 'Someone');
// Who has read this message (excluding its sender) — shown to every member, not just the sender.
d.seenBy = reads.filter((r) => r.user_id !== m.sender_id && r.last_read_at >= m.created_at).map((r) => names[r.user_id] || 'Someone');
return d;
}));
}