// --- Enriched types (server→client) --- export type UserInfo = { id: string; username: string; display_name: string; avatar_url: string; }; export type RoomInfo = { id: string; name: string; }; export type WorkspaceInfo = { id: string; name: string; avatar_url: string; }; // --- Enums --- export type UserPresenceStatus = "online" | "idle" | "dnd" | "offline"; // --- Reactions --- export type ReactionGroup = { emoji: string; count: number; reacted_by_me: boolean; users: UserInfo[]; }; // --- Message Service structs --- export type MessageNewService = { id: string; seq: number; room: RoomInfo; sender_type: string; sender: UserInfo; thread: string | null; in_reply_to: string | null; content: string; content_type: string; pinned?: boolean; system_type: string | null; metadata: Record; thinking_content: string | null; thinking_is_chunked: boolean | null; send_at: string; reactions: ReactionGroup[]; }; export type MessageEditedService = { id: string; seq: number; room: RoomInfo; sender: UserInfo; content: string; edited_at: string; }; export type MessageRevokedService = { id: string; seq: number; room: RoomInfo; revoked_by: UserInfo; revoked_at: string; }; export type MessageStreamStartService = { message_id: string; room: RoomInfo; sse_url: string | null; display_name: string | null; }; export type MessageStreamChunkService = { message_id: string; room: RoomInfo; seq: number; content: string; chunk_type: string; display_name: string | null; }; export type MessageStreamDoneService = { message_id: string; room: RoomInfo; content: string; thinking_content: string | null; display_name: string | null; error: string | null; }; export type MessageListService = { room: RoomInfo; messages: MessageNewService[]; total: number; }; // --- Member Service structs --- export type MemberJoinedService = { room: RoomInfo; user: UserInfo; project_role: string | null; joined_at: string; }; export type MemberRemovedService = { room: RoomInfo; user: UserInfo; removed_by: UserInfo; removed_at: string; }; export type ReadReceiptService = { room: RoomInfo; user: UserInfo; last_read_seq: number; updated_at: string; }; export type TypingStartService = { room: RoomInfo; user: UserInfo; sender_type: string; started_at: string; }; export type TypingStopService = { room: RoomInfo; user: UserInfo; sender_type: string; stopped_at: string; }; // --- Reaction Service structs --- export type ReactionAddedService = { id: string; room: RoomInfo; message: string; user: UserInfo; emoji: string; created_at: string; }; export type ReactionRemovedService = { id: string; room: RoomInfo; message: string; user: UserInfo; emoji: string; removed_at: string; }; export type ReactionBatchUpdatedService = { room: RoomInfo; message: string; reactions: ReactionGroup[]; }; // --- Thread Service structs --- export type ThreadCreatedService = { id: string; room: RoomInfo; parent: number; created_by: UserInfo; participants: unknown; created_at: string; }; export type ThreadUpdatedService = { id: string; room: RoomInfo; last_message_at: string | null; last_message_preview: string | null; updated_at: string; }; export type ThreadResolvedService = { id: string; room: RoomInfo; resolved_by: UserInfo; resolved_at: string; }; export type ThreadArchivedService = { id: string; room: RoomInfo; archived_by: UserInfo; archived_at: string; }; // --- Pin Service structs --- export type PinAddedService = { room: RoomInfo; message: string; pinned_by: UserInfo; pinned_at: string; }; export type PinRemovedService = { room: RoomInfo; message: string; removed_by: UserInfo; removed_at: string; }; // --- Draft Service structs --- export type DraftSavedService = { user: UserInfo; room: RoomInfo; content: string; saved_at: string; }; export type DraftClearedService = { user: UserInfo; room: RoomInfo; cleared_at: string; }; // --- Room Service structs --- export type RoomCreatedService = { room: RoomInfo; workspace: WorkspaceInfo; public: boolean; category: string | null; created_by: UserInfo; created_at: string; }; export type RoomDeletedService = { room: RoomInfo; workspace: WorkspaceInfo; deleted_by: UserInfo; deleted_at: string; }; export type RoomRenamedService = { room: RoomInfo; workspace: WorkspaceInfo; old_name: string; new_name: string; renamed_by: UserInfo; renamed_at: string; }; export type RoomMovedService = { room: RoomInfo; workspace: WorkspaceInfo; old_category: string | null; new_category: string | null; moved_by: UserInfo; moved_at: string; }; export type RoomTopicUpdatedService = { room: RoomInfo; workspace: WorkspaceInfo; old_topic: string | null; new_topic: string | null; updated_by: UserInfo; updated_at: string; }; export type RoomSettingsUpdatedService = { room: RoomInfo; workspace: WorkspaceInfo; slowmode_seconds: number | null; nsfw: boolean; default_auto_archive_duration: number | null; updated_by: UserInfo; updated_at: string; }; // --- Workspace Service structs --- export type WorkspaceRoomCreatedService = { workspace: WorkspaceInfo; room: RoomInfo; public: boolean; category: string | null; created_by: UserInfo; created_at: string; }; export type WorkspaceRoomDeletedService = { workspace: WorkspaceInfo; room: RoomInfo; deleted_by: UserInfo; deleted_at: string; }; // --- Category Service structs --- export type CategoryCreatedService = { id: string; workspace: WorkspaceInfo; name: string; position: number; created_by: UserInfo; created_at: string; }; export type CategoryUpdatedService = { id: string; workspace: WorkspaceInfo; name: string | null; position: number | null; updated_by: UserInfo; updated_at: string; }; export type CategoryDeletedService = { id: string; workspace: WorkspaceInfo; deleted_by: UserInfo; deleted_at: string; }; // --- Notify Service structs --- export type NotifyCreatedService = { id: string; room: RoomInfo | null; workspace: WorkspaceInfo | null; user: UserInfo; notification_type: string; title: string; content: string | null; related_message_id: string | null; related_user: UserInfo | null; metadata: unknown; created_at: string; deep_link_url: string | null; }; export type NotifyReadService = { id: string; user: UserInfo; read_at: string; }; // --- Presence Service structs --- export type PresenceChangedService = { user: UserInfo; workspace: WorkspaceInfo | null; status: UserPresenceStatus; last_seen_at: string | null; }; export type CustomStatusUpdatedService = { user: UserInfo; emoji: string | null; text: string | null; expires_at: string | null; }; // --- Invite Service structs --- export type InviteCreatedService = { id: string; workspace: WorkspaceInfo; room: RoomInfo | null; inviter: UserInfo; invitee: UserInfo | null; code: string; max_uses: number | null; expires_at: string | null; created_at: string; }; export type InviteAcceptedService = { id: string; workspace: WorkspaceInfo; room: RoomInfo | null; user: UserInfo; accepted_at: string; }; // --- Ban Service structs --- export type BannedService = { workspace: WorkspaceInfo; user: UserInfo; banned_by: UserInfo; reason: string | null; expires_at: string | null; banned_at: string; }; export type UnbannedService = { workspace: WorkspaceInfo; user: UserInfo; unbanned_by: UserInfo; unbanned_at: string; }; // --- Voice Service structs --- export type VoiceChannelJoinedService = { room: RoomInfo; workspace: WorkspaceInfo | null; user: UserInfo; muted: boolean; deafened: boolean; video: boolean; joined_at: string; }; export type VoiceChannelLeftService = { room: RoomInfo; workspace: WorkspaceInfo | null; user: UserInfo; left_at: string; }; // --- Search Service structs --- export type SearchMessageHitService = MessageNewService & { highlighted_content: string; }; export type SearchResultService = { q: string; room: RoomInfo | null; messages: SearchMessageHitService[]; total: number; took_ms: number; }; // --- Attachment Service structs --- export type AttachmentUploadedService = { id: string; room: RoomInfo; message: string; filename: string; content_type: string | null; size: number; url: string | null; uploaded_by: UserInfo; uploaded_at: string; }; // --- Conversation state (OpenIM Conversation model) --- export type ConversationPinnedService = { user: UserInfo; room: RoomInfo; pinned_at: string; }; export type ConversationUnpinnedService = { user: UserInfo; room: RoomInfo; unpinned_at: string; }; export type ConversationMutedService = { user: UserInfo; room: RoomInfo; muted_at: string; }; export type ConversationUnmutedService = { user: UserInfo; room: RoomInfo; unmuted_at: string; }; export type ConversationUnreadUpdatedService = { user: UserInfo; room: RoomInfo; last_read_seq: number; unread_count: number; updated_at: string; }; export type ConversationSummary = { room: string; room_name: string; room_type: string; is_pinned: boolean; is_muted: boolean; notify_level: string; last_read_seq: number; max_seq: number; unread_count: number; last_read_at: string | null; }; // --- Per-message read tracking (OpenIM MarkMsgsAsRead) --- export type MessageReadService = { room: RoomInfo; message_id: string; message_seq: number; reader: UserInfo; read_at: string; }; export type MessageReadBatchService = { room: RoomInfo; message_ids: string[]; last_seq: number; reader: UserInfo; read_at: string; }; export type MessageReaderEntry = { user: UserInfo; read_at: string; }; export type MessageReadersService = { message_id: string; readers: MessageReaderEntry[]; }; // --- Message starring (Rocket.Chat starMessage) --- export type MessageStarredService = { room: RoomInfo; message_id: string; message_seq: number; starred_by: UserInfo; starred_at: string; }; export type MessageUnstarredService = { room: RoomInfo; message_id: string; unstarred_by: UserInfo; unstarred_at: string; }; export type StarredMessageEntry = { message_id: string; room: RoomInfo; seq: number; content: string; content_type: string; sender: UserInfo; starred_at: string; sent_at: string; }; // --- Message forwarding (OpenIM forward) --- export type MessageForwardedService = { id: string; seq: number; room: RoomInfo; sender: UserInfo; content: string; content_type: string; source_room: RoomInfo; source_message_id: string; forwarded_at: string; }; // --- WsOutEvent discriminated union --- export type WsError = { type: "error"; code: number; error: string; message: string; }; export type WsOutEvent = | { type: "pong"; protocol_version: number } | WsError | { type: "csrf_token"; token: string } | { type: "room_created"; room: RoomInfo; data: RoomCreatedService } | { type: "room_deleted"; room: RoomInfo; data: RoomDeletedService } | { type: "room_renamed"; room: RoomInfo; data: RoomRenamedService } | { type: "room_topic_updated"; room: RoomInfo; data: RoomTopicUpdatedService } | { type: "room_settings_updated"; room: RoomInfo; data: RoomSettingsUpdatedService } | { type: "room_moved"; room: RoomInfo; data: RoomMovedService } | { type: "message_new"; room: RoomInfo; data: MessageNewService } | { type: "message_edited"; room: RoomInfo; data: MessageEditedService } | { type: "message_revoked"; room: RoomInfo; data: MessageRevokedService } | { type: "message_stream_start"; room: RoomInfo; data: MessageStreamStartService } | { type: "message_stream_chunk"; room: RoomInfo; data: MessageStreamChunkService } | { type: "message_stream_done"; room: RoomInfo; data: MessageStreamDoneService } | { type: "message_list"; room: RoomInfo; data: MessageListService } | { type: "member_joined"; room: RoomInfo; data: MemberJoinedService } | { type: "member_removed"; room: RoomInfo; data: MemberRemovedService } | { type: "read_receipt"; room: RoomInfo; data: ReadReceiptService } | { type: "typing_start"; room: RoomInfo; data: TypingStartService } | { type: "typing_stop"; room: RoomInfo; data: TypingStopService } | { type: "reaction_added"; room: RoomInfo; data: ReactionAddedService } | { type: "reaction_removed"; room: RoomInfo; data: ReactionRemovedService } | { type: "reaction_batch_updated"; room: RoomInfo; data: ReactionBatchUpdatedService } | { type: "thread_created"; room: RoomInfo; data: ThreadCreatedService } | { type: "thread_updated"; room: RoomInfo; data: ThreadUpdatedService } | { type: "thread_resolved"; room: RoomInfo; data: ThreadResolvedService } | { type: "thread_archived"; room: RoomInfo; data: ThreadArchivedService } | { type: "category_created"; workspace: WorkspaceInfo; data: CategoryCreatedService } | { type: "category_updated"; workspace: WorkspaceInfo; data: CategoryUpdatedService } | { type: "category_deleted"; workspace: WorkspaceInfo; data: CategoryDeletedService } | { type: "pin_added"; room: RoomInfo; data: PinAddedService } | { type: "pin_removed"; room: RoomInfo; data: PinRemovedService } | { type: "workspace_room_created"; workspace: WorkspaceInfo; data: WorkspaceRoomCreatedService } | { type: "workspace_room_deleted"; workspace: WorkspaceInfo; data: WorkspaceRoomDeletedService } | { type: "draft_saved"; room: RoomInfo; data: DraftSavedService } | { type: "draft_cleared"; room: RoomInfo; data: DraftClearedService } | { type: "search_result"; data: SearchResultService } | { type: "notify_created"; data: NotifyCreatedService } | { type: "notify_read"; data: NotifyReadService } | { type: "presence_changed"; data: PresenceChangedService } | { type: "custom_status_updated"; data: CustomStatusUpdatedService } | { type: "invite_created"; data: InviteCreatedService } | { type: "invite_accepted"; data: InviteAcceptedService } | { type: "attachment_uploaded"; data: AttachmentUploadedService } | { type: "user_banned"; data: BannedService } | { type: "user_unbanned"; data: UnbannedService } | { type: "voice_channel_left"; data: VoiceChannelLeftService } | { type: "conversation_pinned"; room: RoomInfo; data: ConversationPinnedService } | { type: "conversation_unpinned"; room: RoomInfo; data: ConversationUnpinnedService } | { type: "conversation_muted"; room: RoomInfo; data: ConversationMutedService } | { type: "conversation_unmuted"; room: RoomInfo; data: ConversationUnmutedService } | { type: "conversation_unread_updated"; room: RoomInfo; data: ConversationUnreadUpdatedService } | { type: "conversation_list"; data: ConversationSummary[] } | { type: "message_read"; room: RoomInfo; data: MessageReadService } | { type: "message_read_batch"; room: RoomInfo; data: MessageReadBatchService } | { type: "message_readers"; data: MessageReadersService } | { type: "message_starred"; room: RoomInfo; data: MessageStarredService } | { type: "message_unstarred"; room: RoomInfo; data: MessageUnstarredService } | { type: "starred_list"; data: StarredMessageEntry[] } | { type: "message_forwarded"; room: RoomInfo; data: MessageForwardedService } | { type: "response"; request_id: string; data: unknown };