#13: pin a message

Any participant can pin/unpin a message from its ⋮ menu. Adds pinned_at/pinned_by
columns, /api/messages/pin (toggle, broadcasts chat-pinned) and
/api/messages/pinned (list, newest first, excludes deleted + delete-for-me).
The conversation shows a pinned strip under the header (latest pin + count);
tap it to jump to the message, × to unpin. Live-updates across participants and
devices. Added pin/pinOff Lucide icons.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 23:00:06 +05:30
parent 9017d2ff25
commit d0863351d2
5 changed files with 85 additions and 2 deletions
+4
View File
@@ -222,6 +222,10 @@ try { db.exec('CREATE TABLE IF NOT EXISTS message_hidden (message_id TEXT NOT NU
// A message can be edited by its sender; edited_at marks it (shows an "edited" label).
try { db.exec('ALTER TABLE messages ADD COLUMN edited_at INTEGER'); } catch (e) { /* exists */ }
try { db.exec('ALTER TABLE messages ADD COLUMN fwd_from TEXT'); } catch (e) { /* exists — original sender name when a message was forwarded (#5) */ }
// #13 Pin a message: pinned_at (when it was pinned, NULL = not pinned) + pinned_by (who pinned it). A
// conversation's pinned strip lists its messages with a non-NULL pinned_at.
try { db.exec('ALTER TABLE messages ADD COLUMN pinned_at INTEGER'); } catch (e) { /* exists */ }
try { db.exec('ALTER TABLE messages ADD COLUMN pinned_by TEXT'); } catch (e) { /* exists */ }
// User-set presence status: 'active' | 'away' | 'onleave'. ('incall' is derived live, not stored.)
try { db.exec("ALTER TABLE users ADD COLUMN status TEXT NOT NULL DEFAULT 'active'"); } catch (e) { /* exists */ }
// BizGaze person-id (s.userId): the SAME value whether the person signs in with their email or