chat: group chat UI — room tabs, creation flow, member mgmt

Generalises the flyout from peer-only to a thread abstraction
({kind: 'peer'|'room', key, label}). Conversations list and peer
strip render rooms with a group icon alongside 1:1 peers; clicking
either opens the same thread view.

New UI surface:
  - Pick view gets a 1:1 / group mode switch. Group mode reveals a
    name field + multi-select member list and a Create button.
  - Room threads show an info icon in the flyout header that opens a
    member list; owners can add/remove members, rename-later, or
    delete the room; non-owners can leave.
  - 1:1 threads show a disposable toggle (ph-fire) in the header;
    flipping it tells the relay to drop future sends after delivery
    instead of persisting.
  - Group bubbles show the author's username above each message when
    it changes, matching common chat UX.

Thread open triggers a backfill fetch so cold caches / second
devices catch up on older history from the relay.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
thandClaude Opus 4.6 committed 2026-04-15 20:15:50 +02:00
1 parent 52da9abd44
commit 9267c7c6a1
3 files changed
+592 -108

No files matched your search

+138
View File
@@ -329,6 +329,144 @@
color: var(--t-accent);
}
.chat-pick-row.selected {
background: var(--t-raised);
color: var(--t-accent);
}
.chat-pick-row .chat-pick-check {
margin-left: auto;
color: var(--t-accent);
font-size: 12px;
}
.chat-pick-row:not(.selected) .chat-pick-check { visibility: hidden; }
/* Picker mode switch (1:1 vs. group). */
.chat-pick-mode {
display: flex;
gap: 4px;
padding: 6px 10px;
border-bottom: 1px solid var(--t-border);
background: var(--t-bg);
flex-shrink: 0;
}
.chat-pick-mode-btn {
flex: 1;
padding: 3px 8px;
border: 1px solid var(--t-border);
background: transparent;
color: var(--t-muted);
font-family: var(--t-font-pixel);
font-size: 10px;
cursor: pointer;
transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.chat-pick-mode-btn:hover { color: var(--t-accent); border-color: var(--t-accent); }
.chat-pick-mode-btn.active {
border-color: var(--t-accent);
background: var(--t-accent);
color: var(--t-bg);
}
.chat-group-name {
margin: 8px 10px 4px;
padding: 5px 8px;
background: var(--t-surface);
border: 1px solid var(--t-border);
color: var(--t-bright);
font-size: 11px;
font-family: var(--t-font-mono, monospace);
outline: none;
}
.chat-group-name:focus { border-color: var(--t-accent); }
.chat-group-name.hidden { display: none; }
.chat-group-actions {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border-top: 1px solid var(--t-border);
background: var(--t-bg);
flex-shrink: 0;
}
.chat-group-actions.hidden { display: none; }
/* Room-info view: member list + owner actions. */
#chat-room-info-header {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-bottom: 1px solid var(--t-border);
background: var(--t-bg);
flex-shrink: 0;
}
.chat-room-info-body {
flex: 1;
overflow-y: auto;
padding: 10px 12px;
display: flex;
flex-direction: column;
gap: 10px;
}
.chat-room-info-body .section-label {
font-family: var(--t-font-pixel);
font-size: 9px;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--t-dim);
margin-top: 4px;
}
.chat-room-member-row {
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
color: var(--t-bright);
padding: 3px 0;
}
.chat-room-member-row .owner-badge {
font-family: var(--t-font-pixel);
font-size: 8px;
color: var(--t-accent);
background: var(--t-raised);
padding: 1px 5px;
border: 1px solid var(--t-accent);
margin-left: 4px;
}
.chat-room-info-body .btn {
padding: 4px 10px;
font-size: 10px;
font-family: var(--t-font-pixel);
border: 1px solid var(--t-border);
background: transparent;
color: var(--t-muted);
cursor: pointer;
transition: all 0.12s;
}
.chat-room-info-body .btn:hover { border-color: var(--t-accent); color: var(--t-accent); }
.chat-room-info-body .btn.danger:hover { border-color: var(--t-danger); color: var(--t-danger); }
/* Author name above group-thread bubbles. */
.chat-bubble-author {
font-family: var(--t-font-pixel);
font-size: 8px;
color: var(--t-dim);
margin-top: 4px;
padding-left: 2px;
}
/* Peer-tab variant for rooms — group icon instead of initial. */
.chat-peer-tab .chat-peer-tab-icon {
font-size: 10px;
flex-shrink: 0;
}
/* Disposable / info icons in flyout header. */
#chat-thread-disposable.active {
color: var(--t-accent);
}
/* ── Footer button ── */
#chat-footer-btn {