feat(chat): delete a chat, disband a group, Seen — and purge what everyone deleted
Delete chat is the caller's alone: the history so far vanishes for them (chat_members.cleared_id) and a direct chat leaves their list (hidden) until a new message arrives; the others keep theirs. What EVERY member has deleted is deleted for real (purge): messages up to the lowest cleared_id and their files on disk, and a direct chat both people deleted, whole. Purge also runs when a member leaves or is removed. A group's creator disbands it for everyone (DELETE /api/chat/rooms/:id). Seen: rooms carry every member's read mark (reads); a mark that moves is told to the members (chat_read, exactAudience) and never passes the newest message. Under your newest message: Seen / Seen by … / Seen by everyone. A room open on a tab you come back to is marked read then.
This commit is contained in:
@@ -577,6 +577,10 @@ export type ChatRoom = {
|
||||
members: number[];
|
||||
lastMessage: ChatMessage | null;
|
||||
lastReadId: number;
|
||||
/** Messages up to this id were deleted by the viewer for themselves. */
|
||||
clearedId?: number;
|
||||
/** Every member's read mark by user id ("Seen"); absent from an older server. */
|
||||
reads?: Record<string, number>;
|
||||
unread: number;
|
||||
};
|
||||
/** One account in Settings → Users (`GET /api/users`). */
|
||||
@@ -1645,6 +1649,11 @@ export const api = {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ upTo }),
|
||||
}),
|
||||
/** Delete the chat for yourself only (a direct chat leaves your list). */
|
||||
clear: (id: number) =>
|
||||
request<{ hidden: boolean }>(`/chat/rooms/${id}/clear`, { method: "POST" }),
|
||||
/** The group's creator deletes it for everyone. */
|
||||
disband: (id: number) => request<{ ok: true }>(`/chat/rooms/${id}`, { method: "DELETE" }),
|
||||
/** Your own message only (403 otherwise). */
|
||||
deleteMessage: (roomId: number, messageId: number) =>
|
||||
request<{ ok: true }>(`/chat/rooms/${roomId}/messages/${messageId}`, { method: "DELETE" }),
|
||||
|
||||
+10
-2
@@ -1919,13 +1919,14 @@ export interface WSMessage {
|
||||
* remote_data.updated → RemoteDataUpdatedPayload;
|
||||
* lane_update → { lane?: Lane; removed?: number };
|
||||
* chat_message → { roomId, message: ChatMessage, to }; chat_room → { roomId, to };
|
||||
* chat_deleted → { roomId, messageId, to }. */
|
||||
* chat_deleted → { roomId, messageId, to }; chat_read → { roomId, userId, lastReadId, to }. */
|
||||
type:
|
||||
| "session_created"
|
||||
| "session_updated"
|
||||
| "chat_message"
|
||||
| "chat_room"
|
||||
| "chat_deleted"
|
||||
| "chat_read"
|
||||
| "agent_created"
|
||||
| "agent_updated"
|
||||
| "new_event"
|
||||
@@ -1974,7 +1975,14 @@ export interface WSMessage {
|
||||
| LaneRuntimePayload
|
||||
| LaneHookResultPayload
|
||||
/** chat_message / chat_room (lib/api.ts ChatMessage). */
|
||||
| { roomId: number; message?: unknown; messageId?: number; to?: number[] };
|
||||
| {
|
||||
roomId: number;
|
||||
message?: unknown;
|
||||
messageId?: number;
|
||||
userId?: number;
|
||||
lastReadId?: number;
|
||||
to?: number[];
|
||||
};
|
||||
/** ISO timestamp the server broadcast this message (not necessarily the
|
||||
* same instant the underlying event occurred). */
|
||||
timestamp: string;
|
||||
|
||||
Reference in New Issue
Block a user