Task #31: Let people leave, mute, or archive a group chat
Adds per-user mute / archive / leave actions for chats. Schema: - `lib/db/src/schema/conversations.ts`: added `is_muted` and `is_archived` boolean columns on `conversation_participants`. - Columns applied directly via SQL (drizzle push wanted to make unrelated app_opens decisions; force-applied is_muted/is_archived with `ALTER TABLE ... ADD COLUMN IF NOT EXISTS`). API (`artifacts/api-server/src/routes/conversations.ts`): - New endpoint `PATCH /conversations/:id/state` — current user toggles their own `isMuted` / `isArchived`. - New endpoint `POST /conversations/:id/leave` — removes the caller from a group conversation; rejects DMs. - `buildConversationDetails` now returns `isMuted` and `isArchived` for the requesting user. - `sendMessage` auto-clears `isArchived` for all participants so archived chats reappear when a new message arrives. OpenAPI (`lib/api-spec/openapi.yaml`): - Added the two new operations and `UpdateConversationStateBody`. - Added `isMuted` / `isArchived` to `ConversationWithDetails`. - Re-ran codegen for `@workspace/api-zod` and `@workspace/api-client-react`. UI (`artifacts/teaboy-os/src/pages/chat.tsx`): - Header gets a kebab "chat actions" button visible for both DMs and groups when a conversation is open. - Action sheet offers Mute/Unmute, Archive/Unarchive, and (groups only) Leave with a confirmation dialog. - Conversation list now has Active / Archived tabs and a bell-off indicator + dimmed unread badge for muted chats. - Bilingual strings added to en.json and ar.json. Side fixes (unrelated pre-existing schema drift discovered while testing): added missing `users.clock_hour12` and `conversations.avatar_url` columns directly so login and the conversations list work; the schema files already declared them. Verified end-to-end with the testing tool: mute, archive, unarchive, and leave-group flows all pass.
This commit is contained in:
@@ -729,6 +729,50 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ConversationWithDetails"
|
||||
|
||||
/conversations/{id}/state:
|
||||
patch:
|
||||
operationId: updateConversationState
|
||||
tags: [conversations]
|
||||
summary: Update per-user state (mute, archive)
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/UpdateConversationStateBody"
|
||||
responses:
|
||||
"200":
|
||||
description: Updated conversation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ConversationWithDetails"
|
||||
|
||||
/conversations/{id}/leave:
|
||||
post:
|
||||
operationId: leaveConversation
|
||||
tags: [conversations]
|
||||
summary: Leave a group conversation
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
"200":
|
||||
description: Left conversation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SuccessResponse"
|
||||
|
||||
/conversations/{id}/messages:
|
||||
get:
|
||||
operationId: listMessages
|
||||
@@ -1458,6 +1502,10 @@ components:
|
||||
nullable: true
|
||||
unreadCount:
|
||||
type: integer
|
||||
isMuted:
|
||||
type: boolean
|
||||
isArchived:
|
||||
type: boolean
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -1470,6 +1518,8 @@ components:
|
||||
- createdBy
|
||||
- participants
|
||||
- unreadCount
|
||||
- isMuted
|
||||
- isArchived
|
||||
- createdAt
|
||||
- updatedAt
|
||||
|
||||
@@ -1521,6 +1571,14 @@ components:
|
||||
nameEn:
|
||||
type: ["string", "null"]
|
||||
|
||||
UpdateConversationStateBody:
|
||||
type: object
|
||||
properties:
|
||||
isMuted:
|
||||
type: boolean
|
||||
isArchived:
|
||||
type: boolean
|
||||
|
||||
AddParticipantsBody:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in New Issue
Block a user