feat(messaging-ui): message timestamps + group/channel settings panel (0.1.5)
- Every message now shows a Slack-style time (clock today, then 'Yesterday', weekday, else a date; full timestamp on hover). - New ConversationSettings panel for groups AND channels (public + private): rename, member list, add people (from the directory), remove, and leave. Opened from a new thread header gear; DMs show no gear. Adapter gains addMember/removeMember/renameConversation (optional, OPA still gates writes). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -163,6 +163,21 @@ export class MockAdapter implements MessagingAdapter {
|
||||
return MOCK_PEOPLE.map((p) => ({ ...p }));
|
||||
}
|
||||
|
||||
async addMember(threadId: string, userId: string): Promise<void> {
|
||||
const t = this.threads.get(threadId);
|
||||
if (t && !t.participants.includes(userId)) t.participants = [...t.participants, userId];
|
||||
}
|
||||
|
||||
async removeMember(threadId: string, userId: string): Promise<void> {
|
||||
const t = this.threads.get(threadId);
|
||||
if (t) t.participants = t.participants.filter((p) => p !== userId);
|
||||
}
|
||||
|
||||
async renameConversation(threadId: string, subject: string): Promise<void> {
|
||||
const t = this.threads.get(threadId);
|
||||
if (t) t.subject = subject;
|
||||
}
|
||||
|
||||
async openThread(p: { participantIds: string[]; membership?: Membership; subject?: string }): Promise<{ threadId: string }> {
|
||||
// A DM to someone you already have reuses the existing 1:1 thread (dedupe, like the live door).
|
||||
if ((p.membership ?? (p.participantIds.length === 1 ? 'dm' : 'group')) === 'dm' && p.participantIds.length === 1) {
|
||||
|
||||
Reference in New Issue
Block a user