@corva/chat-core 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,105 @@
1
+ import * as zustand_vanilla from 'zustand/vanilla';
2
+
3
+ declare const ALERT_SEVERITY: {
4
+ readonly CRITICAL: "critical";
5
+ readonly WARNING: "warning";
6
+ readonly INFO: "info";
7
+ };
8
+ type AlertSeverity = (typeof ALERT_SEVERITY)[keyof typeof ALERT_SEVERITY];
9
+ interface AlertData {
10
+ alertId: string;
11
+ alertDefinitionId?: string;
12
+ severity: AlertSeverity;
13
+ rig?: {
14
+ id: string;
15
+ name: string;
16
+ };
17
+ title: string;
18
+ description: string;
19
+ isTruncated?: boolean;
20
+ details?: string;
21
+ detailsUrl?: string;
22
+ appName?: string;
23
+ assetId?: string;
24
+ assetName?: string;
25
+ }
26
+
27
+ interface AppCommentAttachment {
28
+ url: string;
29
+ /** Original file name (with extension), used to tell images apart from other file types. */
30
+ name?: string;
31
+ /** File size in bytes, shown next to the name for non-media attachments. */
32
+ size?: number;
33
+ }
34
+ interface AppCommentData {
35
+ body: string;
36
+ appName?: string;
37
+ authorCorvaId?: number;
38
+ forwarderCorvaId?: number;
39
+ activityType?: string;
40
+ activityId?: string;
41
+ attachments?: AppCommentAttachment[];
42
+ /** @deprecated Use `attachments`. Kept so messages sent before multi-attachment still render. */
43
+ attachmentUrl?: string;
44
+ /** @deprecated Use `attachments`. */
45
+ attachmentName?: string;
46
+ /** @deprecated Use `attachments`. */
47
+ attachmentSize?: number;
48
+ appId?: string;
49
+ dashboardId?: string;
50
+ appUrl?: string;
51
+ /** Structured metadata — depth values in ft, formatted at render time in the viewer's preferred unit. */
52
+ metadata?: {
53
+ holeDepth?: number;
54
+ bitDepth?: number;
55
+ commentDepth?: number;
56
+ };
57
+ settingsSnapshotId?: string;
58
+ isTruncated?: boolean;
59
+ /** Transient: app settings at forward time. Saved to snapshot storage, never sent in the message. */
60
+ settings?: Record<string, unknown>;
61
+ }
62
+ /** Single source of truth for reading a comment's files, whichever field the sender populated. */
63
+ declare function getAppCommentAttachments(data: AppCommentData): AppCommentAttachment[];
64
+ /** A single file shared to channels as a new message, rather than forwarded with its comment. */
65
+ interface SharedFile {
66
+ url: string;
67
+ name: string;
68
+ type?: string;
69
+ /** Worked out from the file name upstream; more reliable than a stored MIME type. */
70
+ kind?: 'image' | 'video' | 'file';
71
+ }
72
+
73
+ interface AskCorvaData {
74
+ responseId: string;
75
+ answer: string;
76
+ answerRef?: string;
77
+ companyId?: number;
78
+ isTruncated?: boolean;
79
+ assetId?: number;
80
+ agentName?: string;
81
+ }
82
+
83
+ type ChatAssetType = 'rig' | 'frac_fleet' | 'intervention_unit';
84
+ type SelectableAssetType = ChatAssetType | 'well';
85
+ interface ChatAsset {
86
+ id: string;
87
+ name: string;
88
+ type: SelectableAssetType;
89
+ status?: string;
90
+ }
91
+ interface AssetChatChannel {
92
+ revolt_channel_id: string;
93
+ rig_id: number | null;
94
+ frac_fleet_id: number | null;
95
+ intervention_unit_id: number | null;
96
+ }
97
+
98
+ interface LoginCredentials {
99
+ username: string;
100
+ password: string;
101
+ }
102
+
1
103
  declare const CORVA_SYS_PREFIX = "$$CORVA::";
2
104
  declare const CORVA_MESSAGE_TYPES: {
3
105
  readonly ALERT: "alert";
@@ -97,6 +199,568 @@ interface AppCommentWirePayload {
97
199
  trunc?: boolean;
98
200
  }
99
201
 
202
+ interface FeedItemData {
203
+ feedItemId: string;
204
+ feedType: string;
205
+ title: string;
206
+ description?: string;
207
+ assetId?: string;
208
+ author?: string;
209
+ }
210
+
211
+ interface Message {
212
+ _id: string;
213
+ rid: string;
214
+ msg: string;
215
+ ts: string;
216
+ u: {
217
+ _id: string;
218
+ username: string;
219
+ name?: string;
220
+ };
221
+ _updatedAt: string;
222
+ urls?: Array<{
223
+ url: string;
224
+ meta?: Record<string, unknown>;
225
+ }>;
226
+ attachments?: Attachment[];
227
+ file?: FileAttachment;
228
+ files?: FileAttachment[];
229
+ editedAt?: string;
230
+ editedBy?: {
231
+ _id: string;
232
+ username: string;
233
+ };
234
+ alias?: string;
235
+ avatar?: string;
236
+ groupable?: boolean;
237
+ parseUrls?: boolean;
238
+ t?: string;
239
+ reactions?: {
240
+ [emoji: string]: {
241
+ userIds: string[];
242
+ };
243
+ };
244
+ replies?: string[];
245
+ tcount?: number;
246
+ tlm?: string;
247
+ tmid?: string;
248
+ deleted?: boolean;
249
+ pinned?: boolean;
250
+ pinnedBy?: {
251
+ _id: string;
252
+ username: string;
253
+ };
254
+ pinnedAt?: string;
255
+ pinnedMessageId?: string;
256
+ unpinnedMessageId?: string;
257
+ systemUsers?: {
258
+ userId?: string;
259
+ actorId?: string;
260
+ };
261
+ alert?: AlertData;
262
+ feedItem?: FeedItemData;
263
+ askCorva?: AskCorvaData;
264
+ appComment?: AppCommentData;
265
+ forwardedFrom?: ForwardedFrom;
266
+ nonce?: string;
267
+ isOptimistic?: boolean;
268
+ sendFailed?: boolean;
269
+ retryFormData?: MessageFormData;
270
+ }
271
+ interface Attachment {
272
+ title?: string;
273
+ title_link?: string;
274
+ text?: string;
275
+ color?: string;
276
+ image_url?: string;
277
+ audio_url?: string;
278
+ video_url?: string;
279
+ message_link?: string;
280
+ thumb_url?: string;
281
+ collapsed?: boolean;
282
+ author_name?: string;
283
+ author_link?: string;
284
+ author_icon?: string;
285
+ fields?: Array<{
286
+ short?: boolean;
287
+ title: string;
288
+ value: string;
289
+ }>;
290
+ }
291
+ interface FileAttachment {
292
+ _id: string;
293
+ name: string;
294
+ type: string;
295
+ size: number;
296
+ rid: string;
297
+ userId: string;
298
+ description?: string;
299
+ url?: string;
300
+ }
301
+ /**
302
+ * A file picked for upload. Structural so a browser `File` fits as-is; React Native passes a
303
+ * plain object. The host's upload adapter knows how to read its own shape.
304
+ */
305
+ interface UploadFile {
306
+ name: string;
307
+ size: number;
308
+ type: string;
309
+ }
310
+ interface MessageFormData {
311
+ text: string;
312
+ roomId: string;
313
+ threadId?: string;
314
+ file?: UploadFile;
315
+ files?: UploadFile[];
316
+ uploadedFileIds?: string[];
317
+ uploadedFileUrls?: string[];
318
+ }
319
+ interface ForwardedFrom {
320
+ channelId: string;
321
+ messageId: string;
322
+ channelName: string;
323
+ isPrivate: boolean;
324
+ note?: string;
325
+ ts?: string;
326
+ }
327
+
328
+ interface RevoltSystemMessage {
329
+ type?: string;
330
+ id?: string;
331
+ by?: string;
332
+ }
333
+ interface RevoltIncomingMessagePayload {
334
+ _id: string;
335
+ nonce?: string;
336
+ author?: string;
337
+ channel: string;
338
+ content?: string;
339
+ edited?: string;
340
+ created_at?: string;
341
+ replies?: Array<{
342
+ id: string;
343
+ mention?: boolean;
344
+ }> | string[];
345
+ system?: RevoltSystemMessage;
346
+ attachments?: RevoltMessageAttachment[];
347
+ }
348
+ interface RevoltLoginResponse {
349
+ user_id: string;
350
+ session_id: string;
351
+ token: string;
352
+ }
353
+ interface RevoltUserResponse {
354
+ _id: string;
355
+ username: string;
356
+ discriminator: string;
357
+ display_name?: string;
358
+ avatar?: {
359
+ _id: string;
360
+ tag: string;
361
+ filename: string;
362
+ metadata: {
363
+ type: string;
364
+ width: number;
365
+ height: number;
366
+ };
367
+ content_type: string;
368
+ size: number;
369
+ };
370
+ online: boolean;
371
+ bot?: {
372
+ owner: string;
373
+ };
374
+ relationship?: 'User' | 'Friend' | 'Blocked' | 'Incoming' | 'Outgoing';
375
+ relations?: {
376
+ servers?: string[];
377
+ } | Array<{
378
+ _id: string;
379
+ status?: string;
380
+ }>;
381
+ email?: string;
382
+ }
383
+ interface RevoltChannel {
384
+ _id: string;
385
+ channel_type: 'TextChannel' | 'VoiceChannel' | 'DirectMessage' | 'Group' | 'SavedMessages';
386
+ name?: string;
387
+ description?: string;
388
+ icon?: {
389
+ _id: string;
390
+ tag: string;
391
+ filename: string;
392
+ metadata: {
393
+ type: string;
394
+ width: number;
395
+ height: number;
396
+ };
397
+ content_type: string;
398
+ size: number;
399
+ };
400
+ recipients?: string[];
401
+ owner?: string;
402
+ server?: string;
403
+ default_permissions?: number;
404
+ role_permissions?: Record<string, number>;
405
+ nsfw?: boolean;
406
+ last_message_id?: string;
407
+ members?: RevoltUserResponse[];
408
+ }
409
+ interface RevoltMessageAttachment {
410
+ _id?: string;
411
+ id?: string;
412
+ tag?: string;
413
+ filename?: string;
414
+ metadata?: {
415
+ type: string;
416
+ width?: number;
417
+ height?: number;
418
+ };
419
+ content_type?: string;
420
+ size?: number;
421
+ }
422
+ interface RevoltMessage {
423
+ _id: string;
424
+ nonce?: string;
425
+ channel: string;
426
+ author: string;
427
+ content?: string;
428
+ attachments?: RevoltMessageAttachment[];
429
+ edited?: string;
430
+ embeds?: unknown[];
431
+ mentions?: string[];
432
+ replies?: string[];
433
+ reactions?: Record<string, string[]> | Array<{
434
+ emoji: string;
435
+ user_id: string;
436
+ }>;
437
+ created_at: string;
438
+ updated_at?: string;
439
+ system?: {
440
+ type?: string;
441
+ id?: string;
442
+ by?: string;
443
+ };
444
+ pinned?: boolean;
445
+ }
446
+ interface RevoltMessageResponse {
447
+ _id: string;
448
+ nonce?: string;
449
+ channel: string;
450
+ content?: string;
451
+ author: string;
452
+ user?: {
453
+ username: string;
454
+ };
455
+ }
456
+ interface RevoltUploadResponse {
457
+ url: string;
458
+ id?: string;
459
+ }
460
+
461
+ interface Room {
462
+ _id: string;
463
+ name?: string;
464
+ fname?: string;
465
+ t: RoomType;
466
+ msgs?: number;
467
+ usersCount?: number;
468
+ u?: {
469
+ _id: string;
470
+ username: string;
471
+ };
472
+ ts?: string;
473
+ ro?: boolean;
474
+ sysMes?: boolean;
475
+ default?: boolean;
476
+ description?: string;
477
+ topic?: string;
478
+ announcement?: string;
479
+ lastMessage?: Message;
480
+ last_message_id?: string;
481
+ alert?: boolean;
482
+ open?: boolean;
483
+ hideUnreadStatus?: boolean;
484
+ rid?: string;
485
+ dmUsername?: string;
486
+ dmAvatarUrl?: string;
487
+ dmUserId?: string;
488
+ recipients?: string[];
489
+ }
490
+ type RoomType = 'c' | 'p' | 'd' | 'l';
491
+
492
+ interface TypingEventData {
493
+ userId: string;
494
+ username: string;
495
+ isTyping: boolean;
496
+ roomId: string;
497
+ }
498
+ interface ReadyChannelData {
499
+ _id: string;
500
+ channel_type: string;
501
+ last_message_id?: string;
502
+ name?: string;
503
+ }
504
+ interface ChannelUnread {
505
+ _id: {
506
+ channel: string;
507
+ };
508
+ last_id?: string;
509
+ }
510
+ interface RevoltSocketEventHandlers {
511
+ onConnected?: () => void;
512
+ onAuthenticated?: () => void;
513
+ onDisconnected?: () => void;
514
+ onInvalidSession?: () => void;
515
+ onReady?: (channels: ReadyChannelData[], channelUnreads?: ChannelUnread[]) => void;
516
+ onMessage?: (message: Message) => void;
517
+ onMessageUpdate?: (messageId: string, channelId: string, data: {
518
+ content?: string;
519
+ edited?: string;
520
+ }) => void;
521
+ onMessageDelete?: (messageId: string, channelId: string) => void;
522
+ onUserStatusChange?: (userId: string, status: string) => void;
523
+ onTyping?: (data: TypingEventData) => void;
524
+ onRoomChange?: (roomId: string, change: unknown) => void;
525
+ onChannelAck?: (channelId: string, messageId: string) => void;
526
+ onError?: (error: unknown) => void;
527
+ }
528
+
529
+ interface Subscription {
530
+ _id: string;
531
+ rid: string;
532
+ name: string;
533
+ fname?: string;
534
+ t: RoomType;
535
+ u: {
536
+ _id: string;
537
+ username: string;
538
+ };
539
+ ts: string;
540
+ ls?: string;
541
+ lr?: string;
542
+ open: boolean;
543
+ alert: boolean;
544
+ last_acked_message_id?: string;
545
+ userMentions: number;
546
+ groupMentions: number;
547
+ roles?: string[];
548
+ archived?: boolean;
549
+ audioNotificationValue?: string;
550
+ desktopNotificationDuration?: number;
551
+ desktopNotifications?: string;
552
+ disableNotifications?: boolean;
553
+ emailNotifications?: string;
554
+ hideUnreadStatus?: boolean;
555
+ mobilePushNotifications?: string;
556
+ muteGroupMentions?: boolean;
557
+ blocked?: boolean;
558
+ blocker?: boolean;
559
+ autoTranslate?: boolean;
560
+ autoTranslateLanguage?: string;
561
+ lastMessage?: Message;
562
+ last_message_id?: string;
563
+ dmUsername?: string;
564
+ dmAvatarUrl?: string;
565
+ dmUserId?: string;
566
+ recipients?: string[];
567
+ }
568
+
569
+ interface User {
570
+ _id: string;
571
+ username: string;
572
+ name?: string;
573
+ emails?: Array<{
574
+ address: string;
575
+ verified: boolean;
576
+ }>;
577
+ status?: UserStatus;
578
+ statusConnection?: UserStatus;
579
+ avatarUrl?: string;
580
+ roles?: string[];
581
+ active?: boolean;
582
+ isBot?: boolean;
583
+ displayName?: string;
584
+ displayAvatar?: string;
585
+ email?: string;
586
+ title?: string;
587
+ role?: string;
588
+ company?: string;
589
+ }
590
+ type UserStatus = 'online' | 'away' | 'busy' | 'offline';
591
+
592
+ declare const ASSET_CHAT_PREFIXES: Record<ChatAssetType, string>;
593
+ declare const ASSET_NOUN: Record<SelectableAssetType, string>;
594
+ declare const ASSET_API_FIELDS: Record<ChatAssetType, string[]>;
595
+ declare const MENTION_REPLACE_PATTERN: RegExp;
596
+ declare const MENTION_SPLIT_PATTERN: RegExp;
597
+ declare const REVOLT_SYSTEM_USER_ID = "00000000000000000000000000";
598
+ declare const SYSTEM_MESSAGE_TEXTS: {
599
+ readonly USER_ADDED: (by: string, user: string) => string;
600
+ readonly USER_REMOVED: (by: string, user: string) => string;
601
+ readonly USER_LEFT: (user: string) => string;
602
+ readonly MESSAGE_PINNED: (user: string) => string;
603
+ readonly MESSAGE_UNPINNED: (user: string) => string;
604
+ readonly DEFAULT_USER: "User";
605
+ };
606
+ declare const CHANNEL_TYPES: {
607
+ readonly DIRECT_MESSAGE: "DirectMessage";
608
+ readonly GROUP: "Group";
609
+ readonly TEXT_CHANNEL: "TextChannel";
610
+ readonly SAVED_MESSAGES: "SavedMessages";
611
+ };
612
+ declare const GENERAL_CHAT_NAME = "General";
613
+ declare const CHANNEL_NAME_MAX_LENGTH = 32;
614
+ declare const SIDEBAR_SECTIONS: {
615
+ readonly FAVORITES: "favorites";
616
+ readonly CHANNELS: "channels";
617
+ readonly DIRECT: "direct";
618
+ };
619
+ type SidebarSectionKey = (typeof SIDEBAR_SECTIONS)[keyof typeof SIDEBAR_SECTIONS];
620
+ declare const SIDEBAR_TABS: {
621
+ readonly ALL: "all";
622
+ readonly UNREAD: "unread";
623
+ readonly RECENT: "recent";
624
+ };
625
+ type SidebarTabKey = (typeof SIDEBAR_TABS)[keyof typeof SIDEBAR_TABS];
626
+ declare const ROOM_LIST_ORDER: {
627
+ readonly ALPHABETICAL: "alphabetical";
628
+ readonly RECENT: "recent";
629
+ };
630
+ type RoomListOrder = (typeof ROOM_LIST_ORDER)[keyof typeof ROOM_LIST_ORDER];
631
+ declare const DEFAULT_ROOM_LIST_ORDER: RoomListOrder;
632
+ declare const MAX_ATTACHMENT_SIZE_MB = 500;
633
+ declare const MAX_ATTACHMENT_SIZE_BYTES: number;
634
+
635
+ declare function alertMessageAsText(message: Message): Message;
636
+
637
+ /**
638
+ * Builds a group channel name from an ordered list of display names, fitting
639
+ * within the backend's 32-character limit.
640
+ *
641
+ * Strategy (in order):
642
+ * 1. Full display names joined by ", "
643
+ * 2. First names only joined by ", "
644
+ * 3. As many first names as fit + ", and N others"
645
+ * 4. Single (possibly truncated) first name + ", and N others"
646
+ */
647
+ declare function buildGroupChannelName(displayNames: string[]): string;
648
+
649
+ declare const canDeleteMessage: (message: Message, currentUserId: string) => boolean;
650
+
651
+ declare const canEditMessage: (message: Message, currentUserId: string) => boolean;
652
+
653
+ interface ChannelAsset {
654
+ assetId: number;
655
+ assetType: ChatAssetType;
656
+ }
657
+ declare function channelToAsset(channel: AssetChatChannel): ChannelAsset | null;
658
+
659
+ declare function setAllowedChatAssetTypes(assetTypes: ChatAssetType[]): void;
660
+ declare function isChatAssetTypeAllowed(assetType: ChatAssetType): boolean;
661
+ declare function isDisallowedAssetChatRoom(roomId: string, assetChatChannels: AssetChatChannel[]): boolean;
662
+ declare function resetChatAssetPermissionsSnapshot(): void;
663
+
664
+ /**
665
+ * Comparator factory for subscription lists: unread first, then by last activity
666
+ * (last_message_id descending — ULIDs are lexicographically time-sortable), then
667
+ * alphabetically by the name returned from getName.
668
+ */
669
+ declare const compareByActivity: (getName: (sub: Subscription) => string) => (a: Subscription, b: Subscription) => number;
670
+
671
+ declare const compareByName: (getName: (sub: Subscription) => string) => (a: Subscription, b: Subscription) => number;
672
+
673
+ declare function createLatestWinsQueue<T>(send: (value: T) => Promise<unknown> | void): (value: T) => void;
674
+
675
+ declare const DATE_SEPARATOR_LABELS: {
676
+ readonly TODAY: "Today";
677
+ readonly YESTERDAY: "Yesterday";
678
+ };
679
+
680
+ interface ChatAssetIdentity {
681
+ assetId: string;
682
+ assetType: ChatAssetType;
683
+ }
684
+ declare function deriveAllowedChatAsset(segment: string | null | undefined, rigId: number | null | undefined, fracFleetId: number | null | undefined, interventionUnitId: number | null | undefined, allowedAssetTypes: ChatAssetType[]): ChatAssetIdentity | null;
685
+
686
+ /**
687
+ * Infers asset type from room display name. Asset chat names use
688
+ * "Rig: ..." / "Fleet: ..." / "Unit: ..." prefixes.
689
+ * Returns null if the name does not match.
690
+ */
691
+ declare function getAssetTypeFromDisplayName(displayName: string): ChatAssetType | null;
692
+
693
+ declare const getReactionCount: (message: Message, emoji: string) => number;
694
+
695
+ declare const DIRECT_MESSAGE_PLACEHOLDER = "Direct Message";
696
+ /**
697
+ * Strips the system prefix from asset chat names: "Rig: AssetName" /
698
+ * "Fleet: AssetName" / "Unit: AssetName" display as just "AssetName".
699
+ */
700
+ declare function formatAssetChatName(name: string): string;
701
+ declare const getRoomDisplayName: (room: Room | Subscription) => string;
702
+
703
+ declare const getSystemMessageWithCorvaNames: (message: Message, getUserById: (userId: string) => User | undefined) => string;
704
+
705
+ declare const getUserDisplayName: (user: Partial<User>) => string;
706
+
707
+ /**
708
+ * Returns a secondary text for a user (typically shown below the display name).
709
+ * Format: "email | title/role" or just "title/role" or "@username"
710
+ */
711
+ declare const getUserSecondaryText: (user: Partial<User>) => string | undefined;
712
+
713
+ declare const hasReactions: (message: Message) => boolean;
714
+
715
+ declare const hasUserReacted: (message: Message, emoji: string, _username: string, currentUserId?: string) => boolean;
716
+
717
+ declare function isAlertMessage(message: Message): boolean;
718
+
719
+ declare function isAppCommentMessage(message: Message): boolean;
720
+
721
+ declare function isAskCorvaMessage(message: Message): boolean;
722
+
723
+ declare const isDmGroup: (sub: Subscription) => boolean;
724
+
725
+ declare function isForwardedMessage(message: Message): boolean;
726
+
727
+ /**
728
+ * Identifies the "General" room (backend-created channel). Name is "General" only.
729
+ */
730
+ declare function isGeneralRoom(room: {
731
+ name?: string;
732
+ fname?: string;
733
+ } | null | undefined): boolean;
734
+ /**
735
+ * Find the General room from a list. General is always a channel (t === 'c').
736
+ */
737
+ declare function findGeneralRoom<T extends {
738
+ _id: string;
739
+ name?: string;
740
+ fname?: string;
741
+ t?: string;
742
+ }>(rooms: T[]): T | undefined;
743
+
744
+ declare const SOFT_DELETE_MARKER = "[sysmessage: deleted]";
745
+ declare const isSoftDeletedMessage: (message: Message) => boolean;
746
+ declare const createSoftDeletedMessage: (message: Message) => Message;
747
+
748
+ declare const isSystemMessage: (message: Message) => boolean;
749
+
750
+ declare function isUnread(sub: Pick<Subscription, 'last_message_id' | 'last_acked_message_id'>): boolean;
751
+
752
+ declare function isUserOnline(user: User): boolean;
753
+
754
+ declare function isVisibleUnread(sub: Subscription, isRoomDisallowed: (roomId: string) => boolean): boolean;
755
+
756
+ interface ParsedCorvaMessage {
757
+ messageType: string;
758
+ alert?: AlertData;
759
+ feedItem?: FeedItemData;
760
+ askCorva?: AskCorvaData;
761
+ appComment?: AppCommentData;
762
+ forwardedFrom?: ForwardedFrom;
763
+ }
100
764
  /**
101
765
  * Builds the wire-format content string for an AskCorva response.
102
766
  */
@@ -105,5 +769,926 @@ declare function buildAskCorvaMessageContent(requestId: string, answer: string,
105
769
  * Builds the wire-format content string for a forwarded message.
106
770
  */
107
771
  declare function buildForwardMessageContent(sourceChannelId: string, messageId: string, channelName: string, isPrivate: boolean, note?: string, ts?: string): string;
772
+ /**
773
+ * Builds the wire-format content string for an app comment forwarded to chat.
774
+ * If the body exceeds MAX_COMMENT_BODY_LENGTH and an activityId is provided,
775
+ * the body is truncated and `trunc` flag is set for lazy-fetching.
776
+ */
777
+ declare function buildAppCommentMessageContent(data: AppCommentData): string;
778
+ /**
779
+ * Detects the $$CORVA:: prefix in message content
780
+ * and parses the JSON payload into internal types.
781
+ * Returns null if the content is not a Corva system message.
782
+ */
783
+ declare function parseCorvaSystemMessage(content: string): ParsedCorvaMessage | null;
784
+ /**
785
+ * If the raw message content is a $$CORVA:: message,
786
+ * enriches the Message object with parsed typed data
787
+ * and sets `t` to the appropriate message type.
788
+ * Returns the message unchanged if it's not a Corva
789
+ * system message.
790
+ */
791
+ declare function enrichWithCorvaData(message: Message): Message;
792
+
793
+ declare const searchMessages: (messages: Message[], query: string) => Message[];
794
+
795
+ declare const searchRooms: (rooms: (Room | Subscription)[], query: string) => (Room | Subscription)[];
796
+
797
+ declare const searchUsers: (users: User[], query: string) => User[];
798
+
799
+ declare const compareByRecencyDesc: (a: Subscription, b: Subscription) => number;
800
+
801
+ /**
802
+ * Sorts channels: pinned first (asset chat if set, else General), then by the
803
+ * chosen order — alphabetically by name or most recent activity first.
804
+ */
805
+ declare function sortChannels(channels: Subscription[], assetChatId: string | undefined, order?: RoomListOrder): Subscription[];
806
+
807
+ /**
808
+ * Sorts DMs and group DMs by the chosen order — alphabetically by display name
809
+ * or most recent activity first.
810
+ */
811
+ declare function sortDMs(dms: Subscription[], order?: RoomListOrder): Subscription[];
812
+
813
+ declare const sortMessagesByTime: (messages: Message[]) => Message[];
814
+
815
+ declare const sortUsersByStatus: (users: User[]) => User[];
816
+
817
+ /**
818
+ * Converts platform mention markup (@[user:ID|Display Name]) to plain @Display Name.
819
+ */
820
+ declare function stripPlatformMentions(body: string): string;
821
+
822
+ /**
823
+ * Extract timestamp from Revolt ULID
824
+ * ULIDs contain a timestamp in the first 48 bits
825
+ */
826
+ declare function extractTimestampFromULID(ulid: string): Date;
827
+ /**
828
+ * Get message timestamp from Revolt message
829
+ * Uses _id (ULID) to extract creation time
830
+ */
831
+ declare function getMessageTimestamp(message: {
832
+ _id: string;
833
+ nonce?: string;
834
+ }): string;
835
+
836
+ interface ChannelNameValidation {
837
+ error: string | null;
838
+ isValid: boolean;
839
+ }
840
+ declare function validateChannelName(name: string, existingChannelNames?: string[]): ChannelNameValidation;
841
+
842
+ type Handler<E> = {
843
+ bivarianceHack(event: E): void;
844
+ }['bivarianceHack'];
845
+ interface HttpRequestInit {
846
+ method?: string;
847
+ headers?: Record<string, string>;
848
+ body?: unknown;
849
+ keepalive?: boolean;
850
+ }
851
+ interface HttpResponseLike {
852
+ ok: boolean;
853
+ status: number;
854
+ statusText: string;
855
+ headers: {
856
+ get(name: string): string | null;
857
+ };
858
+ json(): Promise<unknown>;
859
+ text(): Promise<string>;
860
+ }
861
+ interface SocketCloseEventLike {
862
+ code: number;
863
+ reason: string;
864
+ wasClean: boolean;
865
+ }
866
+ declare const WEBSOCKET_CONNECTING = 0;
867
+ declare const WEBSOCKET_OPEN = 1;
868
+ interface WebSocketLike {
869
+ readonly readyState: number;
870
+ onopen: Handler<unknown> | null;
871
+ onmessage: Handler<{
872
+ data: unknown;
873
+ }> | null;
874
+ onclose: Handler<SocketCloseEventLike> | null;
875
+ onerror: Handler<unknown> | null;
876
+ send(data: string): void;
877
+ close(code?: number): void;
878
+ }
879
+ /**
880
+ * Everything core needs from the host platform. Web passes browser APIs; React Native passes its
881
+ * own `fetch`, `WebSocket` and `FormData` handling plus AppState/NetInfo for reconnect hints.
882
+ *
883
+ * Wrap native functions rather than passing them bare (`fetch: (url, init) => fetch(url, init)`):
884
+ * browsers throw "Illegal invocation" when `window.fetch` is called on another object.
885
+ */
886
+ interface ChatPlatform {
887
+ fetch(url: string, init?: HttpRequestInit): Promise<HttpResponseLike>;
888
+ createWebSocket(url: string): WebSocketLike;
889
+ /** Multipart body for an Autumn upload, with the file under the `file` field. */
890
+ createUploadBody(file: UploadFile): unknown;
891
+ /**
892
+ * Calls `retry` whenever a pending reconnect is worth attempting right away (network came back,
893
+ * app returned to the foreground). Returns an unsubscribe function.
894
+ */
895
+ subscribeReconnectHints?(retry: () => void): () => void;
896
+ }
897
+
898
+ interface HttpClientConfig {
899
+ baseUrl: string;
900
+ fetch: ChatPlatform['fetch'];
901
+ getToken: () => string | null;
902
+ onUnauthorized?: (path: string) => void;
903
+ }
904
+ declare class HttpError extends Error {
905
+ status: number;
906
+ statusText: string;
907
+ body: unknown;
908
+ constructor(status: number, statusText: string, body: unknown, method?: string, path?: string);
909
+ }
910
+ declare function createHttpClient(config: HttpClientConfig): {
911
+ request: <T = unknown>(path: string, init?: HttpRequestInit) => Promise<T>;
912
+ };
913
+ type HttpClient = ReturnType<typeof createHttpClient>;
914
+
915
+ declare function createRevoltAPI(baseUrl: string, platform: ChatPlatform): {
916
+ getBaseUrl: () => string;
917
+ seedUserCache: (users: User[]) => void;
918
+ clearUserCache: () => void;
919
+ setUnauthorizedHandler: (handler: ((source: string) => void) | null) => void;
920
+ notifyUnauthorized: (source: string) => void | undefined;
921
+ createGroup: (name: string, recipientIds: string[]) => Promise<{
922
+ _id: string;
923
+ }>;
924
+ addUserToGroup: (groupId: string, userId: string) => Promise<boolean>;
925
+ removeUserFromGroup: (groupId: string, userId: string) => Promise<boolean>;
926
+ getGroupMembers: (groupId: string) => Promise<User[]>;
927
+ getServerMembers: (serverId: string) => Promise<User[]>;
928
+ getOrCreateDMFromUser: (userId: string) => Promise<{
929
+ _id: string;
930
+ }>;
931
+ getDMRecipient: (dmChannelId: string, currentUserId?: string, cachedChannel?: RevoltChannel) => Promise<User | null>;
932
+ uploadAttachment: (file: UploadFile) => Promise<{
933
+ id?: string;
934
+ url?: string;
935
+ }>;
936
+ addReaction: (channelId: string, messageId: string, emoji: string) => Promise<void>;
937
+ removeReaction: (channelId: string, messageId: string, emoji: string) => Promise<void>;
938
+ getChannelMessages: (channelId: string, limit?: number, before?: string, nearby?: string) => Promise<Message[]>;
939
+ sendMessage: (channelId: string, text: string, threadId?: string, attachmentIds?: string[], nonce?: string) => Promise<unknown>;
940
+ editMessage: (channelId: string, messageId: string, content: string) => Promise<void>;
941
+ deleteMessage: (channelId: string, messageId: string) => Promise<void>;
942
+ pinMessage: (channelId: string, messageId: string) => Promise<void>;
943
+ unpinMessage: (channelId: string, messageId: string) => Promise<void>;
944
+ fetchMessage: (channelId: string, messageId: string) => Promise<RevoltMessage>;
945
+ forwardMessage: (targetChannelId: string, sourceChannelId: string, messageId: string, channelName: string, isPrivate: boolean, customMessage?: string, attachmentIds?: string[], sourceTs?: string) => Promise<unknown>;
946
+ getChannel: (channelId: string) => Promise<RevoltChannel>;
947
+ getRooms: (serverId?: string | null) => Promise<Room[]>;
948
+ leaveChannel: (channelId: string, leaveSilently?: boolean | null) => Promise<void>;
949
+ ackMessage: (channelId: string, messageId: string, options?: {
950
+ keepalive?: boolean;
951
+ }) => Promise<boolean>;
952
+ getUnreads: () => Promise<Map<string, string>>;
953
+ updateChannel: (channelId: string, updates: {
954
+ name?: string;
955
+ description?: string;
956
+ }) => Promise<RevoltChannel>;
957
+ getUser: (userId: string) => Promise<User | null>;
958
+ getFriends: () => Promise<User[]>;
959
+ searchUsers: (_query: string) => Promise<User[]>;
960
+ login: (credentials: LoginCredentials) => Promise<{
961
+ token: string;
962
+ me: User;
963
+ }>;
964
+ me: () => Promise<User>;
965
+ setToken: (token: string | null) => void;
966
+ getToken: () => string | null;
967
+ };
968
+ type RevoltAPIInstance = ReturnType<typeof createRevoltAPI>;
969
+
970
+ interface RevoltSocketConfig {
971
+ apiUrl: string;
972
+ wsUrl: string;
973
+ platform: ChatPlatform;
974
+ }
975
+ declare function createRevoltSocket({ apiUrl, wsUrl, platform }: RevoltSocketConfig, handlers?: RevoltSocketEventHandlers, getMemberById?: (userId: string) => User | undefined): {
976
+ connect: (sessionToken: string, userId: string) => Promise<void>;
977
+ disconnect: () => void;
978
+ destroy: () => void;
979
+ isConnected: () => boolean;
980
+ seedUsers: (users: Array<{
981
+ _id: string;
982
+ username: string;
983
+ }>) => void;
984
+ subscribeToRoom: (_roomId: string) => void;
985
+ sendTyping: (roomId: string, isTyping: boolean) => void;
986
+ setEventHandlers: (handlers: RevoltSocketEventHandlers) => void;
987
+ };
988
+ type RevoltSocketInstance = ReturnType<typeof createRevoltSocket>;
989
+
990
+ /**
991
+ * Synchronous key-value storage, shaped like `localStorage`. Core reads session and last-room
992
+ * data synchronously; React Native can back this with MMKV, or an in-memory map hydrated from
993
+ * AsyncStorage before chat starts and written through in the background.
994
+ */
995
+ interface KeyValueStorage {
996
+ getItem(key: string): string | null;
997
+ setItem(key: string, value: string): void;
998
+ removeItem(key: string): void;
999
+ }
1000
+ declare function configureChatStorage(storage: KeyValueStorage | null): void;
1001
+ /** Throws until configured; callers already treat storage errors as "storage unavailable". */
1002
+ declare function getChatStorage(): KeyValueStorage;
1003
+ declare function createMemoryStorage(): KeyValueStorage;
1004
+
1005
+ declare const SESSION_STORAGE_KEY = "revolt_chat_session";
1006
+ interface SessionData {
1007
+ user: User;
1008
+ token: string;
1009
+ serverId?: string;
1010
+ revoltUserId?: string;
1011
+ assetChatChannels?: AssetChatChannel[];
1012
+ chatUsed?: boolean | null;
1013
+ attentionSeriesPlayed?: number;
1014
+ attentionNextSeriesAt?: number | null;
1015
+ }
1016
+ interface AttentionBudget {
1017
+ attentionSeriesPlayed: number;
1018
+ attentionNextSeriesAt: number | null;
1019
+ }
1020
+ interface SaveSessionParams {
1021
+ user: User;
1022
+ token: string;
1023
+ serverId?: string;
1024
+ assetChatChannels?: AssetChatChannel[];
1025
+ chatUsed?: boolean | null;
1026
+ }
1027
+ declare class SessionManager {
1028
+ static clear(): void;
1029
+ static save({ user, token, serverId, assetChatChannels, chatUsed, }: SaveSessionParams): void;
1030
+ static markChatUsed(): void;
1031
+ static saveAttentionBudget(budget: AttentionBudget): void;
1032
+ static loadAttentionBudget(): AttentionBudget;
1033
+ private static patch;
1034
+ static parseChatUsed(serialized: string | null): boolean | null;
1035
+ static load(): SessionData | null;
1036
+ }
1037
+
1038
+ declare function saveLastOpenedRoom(roomId: string, userId: string): void;
1039
+ declare function getLastOpenedRoom(userId: string): string | null;
1040
+ declare function clearLastOpenedRoom(userId: string): void;
1041
+ declare function saveLastChatActivity(userId: string): void;
1042
+ declare function wasRecentlyActive(userId: string, thresholdDays?: number): boolean;
1043
+
1044
+ declare function createMessageCache(): {
1045
+ get: (roomId: string) => Message[] | undefined;
1046
+ set: (roomId: string, messages: Message[]) => void;
1047
+ markDirty: (roomId: string) => void;
1048
+ isDirty: (roomId: string) => boolean;
1049
+ clear: (roomId?: string) => void;
1050
+ };
1051
+ type MessageCache = ReturnType<typeof createMessageCache>;
1052
+
1053
+ interface PageCursor {
1054
+ before?: string;
1055
+ around?: string;
1056
+ }
1057
+ interface LocatorContext {
1058
+ getMessages: () => Message[];
1059
+ applyMessages: (messages: Message[]) => void;
1060
+ fetchPage: (cursor: PageCursor) => Promise<Message[]>;
1061
+ isCancelled: () => boolean;
1062
+ maxPages?: number;
1063
+ }
1064
+ declare function loadUntilFound(targetId: string, ctx: LocatorContext): Promise<boolean>;
1065
+
1066
+ declare function createTypingManager(): {
1067
+ getDisplayName: (userId: string) => string | undefined;
1068
+ setDisplayName: (userId: string, displayName: string) => void;
1069
+ getDisplayById: () => Record<string, string>;
1070
+ clearTimeout: (userId: string) => void;
1071
+ setTimeout: (userId: string, callback: () => void, delay: number) => void;
1072
+ clearAllTimeouts: () => void;
1073
+ clear: () => void;
1074
+ };
1075
+ type TypingManager = ReturnType<typeof createTypingManager>;
1076
+
1077
+ declare function createRoomTaskQueue(): (roomId: string, task: () => Promise<void>) => Promise<void>;
1078
+
1079
+ interface UploadedFile {
1080
+ file: UploadFile;
1081
+ url: string;
1082
+ id?: string;
1083
+ }
1084
+ interface UploadAndSendResult {
1085
+ response: RevoltMessageResponse;
1086
+ uploadedFiles: UploadedFile[];
1087
+ }
1088
+ declare function uploadAndSend(api: RevoltAPIInstance, data: MessageFormData, nonce: string): Promise<UploadAndSendResult>;
1089
+ declare function buildFinalMessage(response: RevoltMessageResponse, data: MessageFormData, currentUser: {
1090
+ _id: string;
1091
+ username: string;
1092
+ } | null, uploadedFiles?: UploadedFile[]): Message;
1093
+ declare function settleOptimisticMessage(messages: Message[], tempId: string, finalMessage: Message): Message[];
1094
+ declare function failOptimisticMessage(messages: Message[], optimistic: Message, threadId?: string): Message[];
1095
+
1096
+ declare const addMessage: (currentMessages: Message[], newMessage: Message) => Message[];
1097
+ declare const updateMessageInList: (messages: Message[], messageId: string, updates: Partial<Message>) => Message[];
1098
+ declare const removeMessageFromList: (messages: Message[], messageId: string) => Message[];
1099
+
1100
+ declare const createGroupSubscription: (groupId: string, name: string, owner: {
1101
+ _id: string;
1102
+ username: string;
1103
+ }, recipientIds: string[]) => Subscription;
1104
+ declare const createDMSubscription: (roomId: string, recipient?: User) => Subscription;
1105
+ declare const addOrUpdateSubscription: (subscriptions: Subscription[], newSubscription: Subscription) => Subscription[];
1106
+ declare const removeSubscription: (subscriptions: Subscription[], roomId: string) => Subscription[];
1107
+
1108
+ /** Requests against corva-api. The host adds the base URL, the Corva JWT and query encoding. */
1109
+ interface CorvaApiAdapter {
1110
+ get<T = unknown>(path: string, params?: Record<string, unknown>): Promise<T>;
1111
+ post<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T>;
1112
+ }
1113
+ interface AppStateAdapter {
1114
+ /** Tab hidden (web) or app in the background (React Native). */
1115
+ isHidden(): boolean;
1116
+ /** Hidden, or visible without focus. Incoming messages alert while inactive. */
1117
+ isInactive(): boolean;
1118
+ /** Fires on hidden <-> visible changes. Returns an unsubscribe function. */
1119
+ subscribe(listener: (hidden: boolean) => void): () => void;
1120
+ /** Fires when the page or app is about to go away (web `pagehide`), to flush pending acks. */
1121
+ onTerminate?(listener: () => void): () => void;
1122
+ }
1123
+ /** Host-side reactions to chat events; each app decides how (browser notification, push, sound). */
1124
+ interface ChatNotifier<TContext = unknown> {
1125
+ showIncomingMessage?(context: TContext): void;
1126
+ onMessageSent?(userId: string): void;
1127
+ onLogout?(): void;
1128
+ }
1129
+ interface ChatDates {
1130
+ /** Epoch ms of tomorrow at `hour`:00 in the user's timezone. */
1131
+ startOfTomorrowAt(hour: number, now: number): number;
1132
+ }
1133
+ interface ChatHost {
1134
+ apiUrl: string;
1135
+ wsUrl: string;
1136
+ platform: ChatPlatform;
1137
+ storage: KeyValueStorage;
1138
+ corvaApi: CorvaApiAdapter;
1139
+ appState: AppStateAdapter;
1140
+ dates: ChatDates;
1141
+ notifier?: ChatNotifier;
1142
+ }
1143
+ /** Call once at app start, before any store is used. */
1144
+ declare function configureChat(host: ChatHost): void;
1145
+ declare function getChatHost(): ChatHost;
1146
+ declare function resetChatHost(): void;
1147
+
1148
+ /** The signed-in Corva user fields chat reads. The host's full user object fits as-is. */
1149
+ interface CorvaUser {
1150
+ id: number;
1151
+ email: string;
1152
+ first_name: string;
1153
+ last_name: string;
1154
+ company_id: number;
1155
+ profile_photo?: string;
1156
+ title?: string | null;
1157
+ role?: string;
1158
+ company?: {
1159
+ name?: string;
1160
+ };
1161
+ }
1162
+ interface CorvaRevoltAuthResponse {
1163
+ revolt_session_token: string;
1164
+ revolt_user_id: string;
1165
+ revolt_company_server_id: string;
1166
+ revolt_channel_id: string;
1167
+ revolt_chat_channels?: AssetChatChannel[];
1168
+ chat_used?: boolean | null;
1169
+ }
1170
+ interface CorvaAPIUserAttributes {
1171
+ email: string;
1172
+ first_name: string;
1173
+ last_name: string;
1174
+ profile_photo?: string;
1175
+ title?: string;
1176
+ role?: string;
1177
+ }
1178
+ interface CorvaAPIUser {
1179
+ id: string;
1180
+ attributes: CorvaAPIUserAttributes;
1181
+ }
1182
+
1183
+ type ViewportMode = 'historical' | 'live';
1184
+ type ViewportIndexCurve = 'measured_depth' | 'tvd' | 'tvdss' | 'timestamp';
1185
+ type ViewportDeepLink = {
1186
+ mode: ViewportMode;
1187
+ indexCurve: ViewportIndexCurve;
1188
+ range?: {
1189
+ from: number;
1190
+ to: number;
1191
+ };
1192
+ };
1193
+
1194
+ /** A well or pad's active period, used to jump the message list to that time window. */
1195
+ interface FilterEntityWindow {
1196
+ id: number;
1197
+ name: string;
1198
+ startMs: number | null;
1199
+ endMs: number | null;
1200
+ dateMs: number | null;
1201
+ }
1202
+
1203
+ /** Structural equality for plain JSON-like data (settings objects), in place of lodash `isEqual`. */
1204
+ declare function isDeepEqual(a: unknown, b: unknown): boolean;
1205
+
1206
+ declare const PAUSE_INDEFINITELY: number;
1207
+ declare const PAUSE_PRESETS: {
1208
+ readonly THIRTY_MIN: "30m";
1209
+ readonly ONE_HOUR: "1h";
1210
+ readonly FOUR_HOURS: "4h";
1211
+ readonly EIGHT_HOURS: "8h";
1212
+ readonly UNTIL_TOMORROW: "tomorrow";
1213
+ readonly INDEFINITELY: "indefinitely";
1214
+ };
1215
+ type PausePreset = (typeof PAUSE_PRESETS)[keyof typeof PAUSE_PRESETS];
1216
+ interface PausePresetOption {
1217
+ value: PausePreset;
1218
+ label: string;
1219
+ }
1220
+ declare const PAUSE_PRESET_OPTIONS: PausePresetOption[];
1221
+ declare const MUTE_PRESET_OPTIONS: PausePresetOption[];
1222
+ declare function getPauseUntil(preset: PausePreset, now?: number): number;
1223
+ declare function isPauseActive(until: number | null | undefined, now?: number): boolean;
1224
+ declare function isValidPausePreset(value: unknown): value is PausePreset;
1225
+
1226
+ declare function waitForNextPaint(): Promise<void>;
1227
+
1228
+ declare function getAssetChatChannel(assetId: string, assetType: ChatAssetType): Promise<string>;
1229
+
1230
+ type StoredCorvaUser = CorvaUser | CorvaAPIUser;
1231
+ /** Extracts common fields from either CorvaUser or CorvaAPIUser */
1232
+ declare function getCorvaUserFields(corvaUser: StoredCorvaUser): {
1233
+ firstName: string;
1234
+ lastName: string;
1235
+ email: string;
1236
+ profilePhoto: string | undefined;
1237
+ title: string | null | undefined;
1238
+ role: string | undefined;
1239
+ id: string | number;
1240
+ };
1241
+ declare function createCorvaUserService(): {
1242
+ setMapping(revoltUserId: string, corvaUser: StoredCorvaUser): void;
1243
+ getCorvaUser(revoltUserId: string): StoredCorvaUser | undefined;
1244
+ clear(): void;
1245
+ enrichUser(user: User): User;
1246
+ };
1247
+ type CorvaUserService = ReturnType<typeof createCorvaUserService>;
1248
+
1249
+ interface AckScheduler {
1250
+ (channelId: string, messageId: string): void;
1251
+ flushAll: () => void;
1252
+ clear: () => void;
1253
+ /** Newest id this page session acked for the channel (TEMP, see applyUnreads). */
1254
+ sessionAcked: (channelId: string) => string | undefined;
1255
+ }
1256
+ declare function createAckScheduler(api: RevoltAPIInstance): AckScheduler;
1257
+
1258
+ interface SharedRefs {
1259
+ api?: RevoltAPIInstance;
1260
+ socket?: RevoltSocketInstance;
1261
+ serverUrl?: string;
1262
+ messageCache: MessageCache;
1263
+ typingManager: TypingManager;
1264
+ corvaUserService: CorvaUserService;
1265
+ forwardedMessageCache: Map<string, Message>;
1266
+ ackChannel?: AckScheduler;
1267
+ }
1268
+ declare const sharedRefs: SharedRefs;
1269
+
1270
+ /**
1271
+ * Bootstrap: creates the Revolt API + WebSocket client, wires socket event
1272
+ * handlers to the new stores, and populates sharedRefs. Idempotent for the
1273
+ * configured apiUrl.
1274
+ */
1275
+ declare const initChat: () => void;
1276
+
1277
+ interface AuthStore {
1278
+ user: User | null;
1279
+ serverId: string | null;
1280
+ isConnected: boolean;
1281
+ hasEverConnected: boolean;
1282
+ connectionGaveUp: boolean;
1283
+ assetChatChannels: AssetChatChannel[];
1284
+ chatUsed: boolean | null;
1285
+ setUser: (user: User | null) => void;
1286
+ setConnected: (connected: boolean) => void;
1287
+ setHasEverConnected: (hasConnected: boolean) => void;
1288
+ addAssetChatChannel: (channel: AssetChatChannel) => void;
1289
+ markChatUsed: () => void;
1290
+ login: (credentials: LoginCredentials) => Promise<{
1291
+ success: boolean;
1292
+ user?: User;
1293
+ error?: string;
1294
+ }>;
1295
+ loginWithCorva: (corvaUser: CorvaUser) => Promise<{
1296
+ success: boolean;
1297
+ user?: User;
1298
+ error?: string;
1299
+ }>;
1300
+ logout: () => void;
1301
+ restoreSession: (expectedRevoltUserId?: string) => Promise<boolean>;
1302
+ isAuthenticated: () => boolean;
1303
+ isSocketConnected: () => boolean;
1304
+ }
1305
+ declare function keepChatUsed(current: boolean | null, incoming: boolean | null | undefined): boolean | null;
1306
+ declare const authStore: zustand_vanilla.StoreApi<AuthStore>;
1307
+ /** @public */
1308
+ declare const resetAuthStore: () => void;
1309
+
1310
+ interface HiddenRoomsSettings {
1311
+ hiddenRooms: string[];
1312
+ }
1313
+ declare const DEFAULT_HIDDEN_ROOMS_SETTINGS: HiddenRoomsSettings;
1314
+ interface RoomStore {
1315
+ rooms: Room[];
1316
+ subscriptions: Subscription[];
1317
+ /** True once the initial loadSubscriptions attempt has finished (even on failure). */
1318
+ subscriptionsLoaded: boolean;
1319
+ /** True once Ready (or /sync/unreads) has replaced the "seeded as read" pointers with server truth. */
1320
+ unreadsHydrated: boolean;
1321
+ currentRoom: Room | null;
1322
+ hiddenRoomsSettings: HiddenRoomsSettings;
1323
+ persistHiddenRoomsCallback?: (hiddenRooms: string[]) => void;
1324
+ roomListOrder: RoomListOrder;
1325
+ setRooms: (rooms: Room[]) => void;
1326
+ setSubscriptions: (subscriptions: Subscription[]) => void;
1327
+ setCurrentRoom: (room: Room | null) => void;
1328
+ addOrUpdateSubscription: (subscription: Subscription) => void;
1329
+ removeSubscriptionById: (roomId: string) => void;
1330
+ setRoomListOrder: (order: RoomListOrder) => void;
1331
+ markAllAsRead: () => void;
1332
+ setHiddenRoomsSettings: (settings: HiddenRoomsSettings) => void;
1333
+ setPersistHiddenRoomsCallback: (callback: ((hiddenRooms: string[]) => void) | undefined) => void;
1334
+ hideRoom: (roomId: string) => void;
1335
+ unhideRoom: (roomId: string) => void;
1336
+ isRoomHidden: (roomId: string) => boolean;
1337
+ loadSubscriptions: () => Promise<void>;
1338
+ selectRoom: (roomId: string) => Promise<void>;
1339
+ navigateToMessage: (roomId: string, messageId: string, options?: {
1340
+ threadId?: string;
1341
+ }) => Promise<boolean>;
1342
+ enrichDmSubscription: (roomId: string, userId: string) => Promise<void>;
1343
+ createDirectMessage: (username: string) => Promise<Room | undefined>;
1344
+ createDirectMessageById: (userId: string) => Promise<Room | undefined>;
1345
+ createGroupChannel: (name: string, userIds: string[]) => Promise<Room | undefined>;
1346
+ addUserToGroup: (groupId: string, userId: string) => Promise<boolean>;
1347
+ removeUserFromGroup: (groupId: string, userId: string) => Promise<boolean>;
1348
+ getGroupMembers: (groupId: string) => Promise<User[]>;
1349
+ leaveCurrentChannel: (leaveSilently?: boolean | null) => Promise<boolean>;
1350
+ updateChannel: (channelId: string, updates: {
1351
+ name?: string;
1352
+ description?: string;
1353
+ }) => Promise<RevoltChannel | null>;
1354
+ }
1355
+ declare const roomStore: zustand_vanilla.StoreApi<RoomStore>;
1356
+ declare const resetRoomStore: () => void;
1357
+
1358
+ interface MessageStore {
1359
+ messages: Message[];
1360
+ hasMoreMessages: boolean;
1361
+ isLoadingMoreMessages: boolean;
1362
+ setMessages: (messages: Message[]) => void;
1363
+ addMessageToList: (message: Message) => void;
1364
+ updateMessage: (messageId: string, updates: Partial<Message>) => void;
1365
+ removeMessage: (messageId: string) => void;
1366
+ setHasMoreMessages: (hasMore: boolean) => void;
1367
+ setLoadingMoreMessages: (loading: boolean) => void;
1368
+ loadMessages: (roomId: string, roomType: RoomType, count?: number) => Promise<void>;
1369
+ loadMoreMessages: () => Promise<void>;
1370
+ sendMessage: (data: MessageFormData) => Promise<unknown>;
1371
+ retrySendMessage: (tempId: string) => Promise<unknown>;
1372
+ dismissFailedMessage: (tempId: string) => void;
1373
+ editMessage: (messageId: string, content: string) => Promise<void>;
1374
+ deleteMessage: (messageId: string) => Promise<void>;
1375
+ pinMessage: (messageId: string) => Promise<void>;
1376
+ unpinMessage: (messageId: string) => Promise<void>;
1377
+ toggleReaction: (messageId: string, emoji: string) => Promise<void>;
1378
+ getAllMessages: (roomId: string, maxMessages?: number) => Promise<Message[]>;
1379
+ preloadRoomMessages: (roomId: string) => Promise<void>;
1380
+ fetchOriginalMessage: (channelId: string, messageId: string) => Promise<Message | null>;
1381
+ }
1382
+ declare const messageStore: zustand_vanilla.StoreApi<MessageStore>;
1383
+ declare const resetMessageStore: () => void;
1384
+
1385
+ interface MemberStore {
1386
+ members: User[];
1387
+ membersRoomId: string | null;
1388
+ membersById: Record<string, User>;
1389
+ typingUsers: string[];
1390
+ serverMembersLoaded: boolean;
1391
+ serverMembersCache: User[] | null;
1392
+ allVisibleUsersCache: User[] | null;
1393
+ corvaUserMappings: Record<string, CorvaUser | CorvaAPIUser>;
1394
+ setMembers: (members: User[], roomId?: string) => void;
1395
+ setCorvaUserMapping: (revoltUserId: string, corvaUser: CorvaUser | CorvaAPIUser) => void;
1396
+ bulkSetCorvaUserMappings: (mappings: Array<{
1397
+ revoltUserId: string;
1398
+ corvaUser: CorvaUser | CorvaAPIUser;
1399
+ }>) => void;
1400
+ getCorvaUserFromState: (revoltUserId: string) => CorvaUser | CorvaAPIUser | undefined;
1401
+ addMemberToCache: (user: User) => void;
1402
+ getMemberById: (userId: string) => User | undefined;
1403
+ removeUserFromMembers: (userId: string) => void;
1404
+ addTypingUser: (userId: string) => void;
1405
+ removeTypingUser: (userId: string) => void;
1406
+ setTypingUsers: (users: string[]) => void;
1407
+ simulateTyping: (userKey: string, isTyping: boolean, displayName?: string) => void;
1408
+ loadRoomMembers: (roomId: string, roomType: RoomType, isAssetChat?: boolean) => Promise<void>;
1409
+ searchUsers: (query: string) => Promise<User[]>;
1410
+ getUserByUsername: (username: string) => Promise<User | null>;
1411
+ getAllVisibleUsers: () => Promise<User[]>;
1412
+ syncCorvaUsers: (companyId?: number) => Promise<boolean>;
1413
+ }
1414
+ declare const memberStore: zustand_vanilla.StoreApi<MemberStore>;
1415
+ declare const resetMemberStore: () => void;
1416
+
1417
+ interface TracesViewportRequest {
1418
+ wellAssetId: number;
1419
+ viewport: ViewportDeepLink;
1420
+ }
1421
+ interface InlineViewState {
1422
+ appId: string;
1423
+ activityId?: string;
1424
+ viewKey: string;
1425
+ appUrl?: string;
1426
+ settingsSnapshotId?: string;
1427
+ tracesViewport?: TracesViewportRequest;
1428
+ }
1429
+ interface UIStore {
1430
+ isLoading: boolean;
1431
+ error: string | null;
1432
+ isChatVisible: boolean;
1433
+ isSidebarOpen: boolean;
1434
+ sidebarTab: SidebarTabKey;
1435
+ sidebarSectionRequest: SidebarSectionKey | null;
1436
+ sidebarSearchFocusTrigger: number;
1437
+ isNewMessageOpen: boolean;
1438
+ inputFocusTrigger: number;
1439
+ pendingThreadId: string | null;
1440
+ pendingThreadRoomId: string | null;
1441
+ pendingHighlightMessageId: string | null;
1442
+ ephemeralMentionUsersByRoom: Record<string, User[]>;
1443
+ messageDraftsByRoom: Record<string, string>;
1444
+ forwardingMessage: Message | null;
1445
+ forwardingComment: AppCommentData | null;
1446
+ sharingFile: SharedFile | null;
1447
+ inlineViewState: InlineViewState | null;
1448
+ isNavigatingToMessage: boolean;
1449
+ isSwitchingRoom: boolean;
1450
+ pendingWellJump: FilterEntityWindow | null;
1451
+ attentionSeriesPlayed: number;
1452
+ attentionNextSeriesAt: number | null;
1453
+ channelSettingsRequestedAt: number | null;
1454
+ setLoading: (loading: boolean) => void;
1455
+ setError: (error: string | null) => void;
1456
+ clearError: () => void;
1457
+ setChatVisible: (visible: boolean) => void;
1458
+ setSidebarOpen: (open: boolean) => void;
1459
+ setSidebarTab: (tab: SidebarTabKey) => void;
1460
+ requestSidebarSection: (section: SidebarSectionKey) => void;
1461
+ clearSidebarSectionRequest: () => void;
1462
+ requestSidebarSearchFocus: () => void;
1463
+ setNewMessageOpen: (open: boolean) => void;
1464
+ triggerInputFocus: () => void;
1465
+ setPendingThreadId: (threadId: string | null) => void;
1466
+ setPendingThreadRoomId: (roomId: string | null) => void;
1467
+ setPendingHighlightMessageId: (messageId: string | null) => void;
1468
+ setEphemeralMentionUsers: (roomId: string, users: User[]) => void;
1469
+ clearEphemeralMentionUsers: (roomId: string) => void;
1470
+ getEphemeralMentionUsers: (roomId: string | undefined) => User[];
1471
+ setMessageDraft: (draftKey: string, text: string) => void;
1472
+ setForwardingMessage: (message: Message | null) => void;
1473
+ setForwardingComment: (data: AppCommentData | null) => void;
1474
+ setSharingFile: (file: SharedFile | null) => void;
1475
+ setInlineViewState: (state: InlineViewState | null) => void;
1476
+ setNavigatingToMessage: (navigating: boolean) => void;
1477
+ setSwitchingRoom: (switching: boolean) => void;
1478
+ setPendingWellJump: (period: FilterEntityWindow | null) => void;
1479
+ recordAttentionSeries: (params: {
1480
+ startedAt: number;
1481
+ cooldownMs: number;
1482
+ }) => void;
1483
+ requestChannelSettings: () => void;
1484
+ clearChannelSettingsRequest: () => void;
1485
+ }
1486
+ declare const uiStore: zustand_vanilla.StoreApi<UIStore>;
1487
+ declare const resetUIStore: () => void;
1488
+
1489
+ type LockedAsset = ChatAsset & {
1490
+ type: ChatAssetType;
1491
+ };
1492
+ interface AssetStore {
1493
+ currentAssetId: string | null;
1494
+ currentAssetType: ChatAssetType | null;
1495
+ currentAssetName: string | null;
1496
+ currentAssetStatus: string | null;
1497
+ assetChatId: string | null;
1498
+ assetChatError: string | null;
1499
+ knownAssetChatIds: Set<string>;
1500
+ panelSyncedAssetId: string | null;
1501
+ isAssetLocked: boolean;
1502
+ lockedAsset: LockedAsset | null;
1503
+ isAssetSwitching: boolean;
1504
+ setAssetContext: (assetId: string, assetType: ChatAssetType, assetName?: string, assetStatus?: string, skipAutoSelect?: boolean) => Promise<void>;
1505
+ clearAssetContext: () => void;
1506
+ ensureAssetChatSubscription: () => Promise<Subscription | null>;
1507
+ toggleAssetLock: () => void;
1508
+ relockToAsset: (assetId: string, assetType: ChatAssetType, assetName: string) => Promise<void>;
1509
+ }
1510
+ declare const assetStore: zustand_vanilla.StoreApi<AssetStore>;
1511
+ declare const resetAssetStore: () => void;
1512
+
1513
+ declare const NOTIFICATION_SETTING_ALL: "all";
1514
+ declare const NOTIFICATION_SETTING_MENTIONS: "mentions";
1515
+ declare const NOTIFICATION_SETTING_NOTHING: "nothing";
1516
+ type ChannelNotificationSetting = typeof NOTIFICATION_SETTING_ALL | typeof NOTIFICATION_SETTING_MENTIONS | typeof NOTIFICATION_SETTING_NOTHING;
1517
+ type EmailNotificationSetting = typeof NOTIFICATION_SETTING_MENTIONS | typeof NOTIFICATION_SETTING_NOTHING;
1518
+ declare const NOTIFICATION_DESTINATIONS: {
1519
+ readonly PLATFORM: "platform";
1520
+ readonly MOBILE: "mobile";
1521
+ readonly EMAIL: "email";
1522
+ };
1523
+ type NotificationDestination = (typeof NOTIFICATION_DESTINATIONS)[keyof typeof NOTIFICATION_DESTINATIONS];
1524
+ interface ChannelDestinationSettings {
1525
+ platform: ChannelNotificationSetting;
1526
+ mobile: ChannelNotificationSetting;
1527
+ email: EmailNotificationSetting;
1528
+ }
1529
+ interface ChannelNotificationPreference {
1530
+ setting: ChannelDestinationSettings;
1531
+ muted: boolean;
1532
+ mutedUntil: number | null;
1533
+ mutePreset: PausePreset | null;
1534
+ notifyThreadReplies: boolean;
1535
+ }
1536
+ interface NotificationSettings {
1537
+ channels: Record<string, ChannelNotificationPreference>;
1538
+ }
1539
+ interface NotificationPreferences {
1540
+ browserNotifications: boolean;
1541
+ sound: boolean;
1542
+ pausedUntil: number | null;
1543
+ pausePreset: PausePreset | null;
1544
+ }
1545
+ interface NotificationStore {
1546
+ notificationSettings: NotificationSettings;
1547
+ preferences: NotificationPreferences;
1548
+ setPreferences: (preferences: NotificationPreferences) => void;
1549
+ setBrowserNotificationsEnabled: (enabled: boolean) => void;
1550
+ setSoundEnabled: (enabled: boolean) => void;
1551
+ pauseNotifications: (preset: PausePreset) => void;
1552
+ resumeNotifications: () => void;
1553
+ setChannelNotificationSetting: (roomId: string, setting: ChannelNotificationSetting) => void;
1554
+ setChannelDestinationSetting: {
1555
+ (roomId: string, destination: typeof NOTIFICATION_DESTINATIONS.EMAIL, setting: EmailNotificationSetting): void;
1556
+ (roomId: string, destination: typeof NOTIFICATION_DESTINATIONS.PLATFORM | typeof NOTIFICATION_DESTINATIONS.MOBILE, setting: ChannelNotificationSetting): void;
1557
+ (roomId: string, destination: NotificationDestination, setting: ChannelNotificationSetting): void;
1558
+ };
1559
+ setChannelMuted: (roomId: string, muted: boolean) => void;
1560
+ muteChannelFor: (roomId: string, preset: PausePreset | null) => void;
1561
+ setChannelThreadReplies: (roomId: string, notify: boolean) => void;
1562
+ resetChannelPreference: (roomId: string) => void;
1563
+ setNotificationSettings: (settings: NotificationSettings) => void;
1564
+ }
1565
+ declare const DEFAULT_NOTIFICATION_SETTINGS: NotificationSettings;
1566
+ declare const DEFAULT_NOTIFICATION_PREFERENCES: NotificationPreferences;
1567
+ declare const DEFAULT_CHANNEL_PREFERENCE: ChannelNotificationPreference;
1568
+ type StoredChannelPreference = Partial<Omit<ChannelNotificationPreference, 'setting'> & {
1569
+ setting: ChannelNotificationSetting | Partial<ChannelDestinationSettings>;
1570
+ }>;
1571
+ declare function withChannelPreferenceDefaults(pref: StoredChannelPreference | undefined): ChannelNotificationPreference;
1572
+ declare function isDefaultChannelPreference(pref: StoredChannelPreference | undefined): boolean;
1573
+ declare function isChannelMuted(pref: Pick<ChannelNotificationPreference, 'muted' | 'mutedUntil'> | undefined, now?: number): boolean;
1574
+ declare function isNotificationsPaused(preferences: Pick<NotificationPreferences, 'pausedUntil'>, now?: number): boolean;
1575
+ declare const notificationStore: zustand_vanilla.StoreApi<NotificationStore>;
1576
+ declare const resetNotificationStore: () => void;
1577
+
1578
+ interface ChannelContentFilter {
1579
+ showFeeds: boolean;
1580
+ selectedFeeds: string[];
1581
+ }
1582
+ interface ChannelContentFilters {
1583
+ channels: Record<string, ChannelContentFilter>;
1584
+ }
1585
+ interface ChannelContentFilterStore {
1586
+ channelContentFilters: ChannelContentFilters;
1587
+ setChannelContentFilters: (filters: ChannelContentFilters) => void;
1588
+ setChannelShowFeeds: (channelId: string, showFeeds: boolean) => void;
1589
+ setChannelSelectedFeeds: (channelId: string, selectedFeeds: string[]) => void;
1590
+ }
1591
+ declare const DEFAULT_CHANNEL_CONTENT_FILTER: ChannelContentFilter;
1592
+ declare const DEFAULT_CHANNEL_CONTENT_FILTERS: ChannelContentFilters;
1593
+ declare const channelContentFilterStore: zustand_vanilla.StoreApi<ChannelContentFilterStore>;
1594
+ declare const resetChannelContentFilterStore: () => void;
1595
+
1596
+ type ChatToastData = {
1597
+ title: string;
1598
+ content?: string;
1599
+ };
1600
+ type ChatToastStore = {
1601
+ toastsById: Record<string, ChatToastData>;
1602
+ setToast: (toastId: string, data: ChatToastData) => void;
1603
+ removeToast: (toastId: string) => void;
1604
+ };
1605
+ declare const chatToastStore: zustand_vanilla.StoreApi<ChatToastStore>;
1606
+
1607
+ interface FavoriteRoomsSettings {
1608
+ favoriteRoomIds: string[];
1609
+ }
1610
+ interface FavoriteRoomsStore {
1611
+ favoriteRoomsSettings: FavoriteRoomsSettings;
1612
+ persistFavoriteRoomsCallback?: (favoriteRoomIds: string[]) => void;
1613
+ setFavoriteRoomsSettings: (settings: FavoriteRoomsSettings) => void;
1614
+ setPersistFavoriteRoomsCallback: (callback: ((favoriteRoomIds: string[]) => void) | undefined) => void;
1615
+ addFavoriteRoom: (roomId: string) => void;
1616
+ removeFavoriteRoom: (roomId: string) => void;
1617
+ isRoomFavorite: (roomId: string) => boolean;
1618
+ }
1619
+ declare const DEFAULT_FAVORITE_ROOMS_SETTINGS: FavoriteRoomsSettings;
1620
+ declare const favoriteRoomsStore: zustand_vanilla.StoreApi<FavoriteRoomsStore>;
1621
+ declare const resetFavoriteRoomsStore: () => void;
1622
+
1623
+ interface NavigationEntry {
1624
+ roomId: string;
1625
+ threadId?: string;
1626
+ }
1627
+ interface NavigationHistoryStore {
1628
+ entries: NavigationEntry[];
1629
+ index: number;
1630
+ requestedEntry: NavigationEntry | null;
1631
+ record: (entry: NavigationEntry) => void;
1632
+ goBack: () => void;
1633
+ goForward: () => void;
1634
+ clearRequestedEntry: () => void;
1635
+ forgetRoom: (roomId: string) => void;
1636
+ }
1637
+ declare const MAX_NAVIGATION_HISTORY = 50;
1638
+ declare const navigationHistoryStore: zustand_vanilla.StoreApi<NavigationHistoryStore>;
1639
+ declare const selectCanGoBack: (s: NavigationHistoryStore) => boolean;
1640
+ declare const selectCanGoForward: (s: NavigationHistoryStore) => boolean;
1641
+ declare const resetNavigationHistoryStore: () => void;
1642
+
1643
+ declare function handleUnauthorized(): Promise<void>;
1644
+ declare function ensureChatSession(corvaUser: CorvaUser): Promise<boolean>;
1645
+
1646
+ type RoomSelectionStateUpdate = Partial<Pick<UIStore, 'isLoading' | 'isSwitchingRoom'>>;
1647
+ interface PrepareRoomSelectionParams {
1648
+ roomId: string;
1649
+ currentRoomId?: string;
1650
+ isCacheDirty: (roomId: string) => boolean;
1651
+ getCachedMessages: (roomId: string) => Message[] | undefined;
1652
+ setState: (state: RoomSelectionStateUpdate) => void;
1653
+ }
1654
+ interface RoomSelectionRequest {
1655
+ id: number;
1656
+ roomId: string;
1657
+ }
1658
+ declare function isCurrentRoomSelection(request: RoomSelectionRequest): boolean;
1659
+ declare function prepareRoomSelection({ roomId, currentRoomId, isCacheDirty, getCachedMessages, setState, }: PrepareRoomSelectionParams): Promise<RoomSelectionRequest | null>;
1660
+
1661
+ interface SocketEventHandlersConfig {
1662
+ api: RevoltAPIInstance;
1663
+ messageCache: MessageCache;
1664
+ typingManager: TypingManager;
1665
+ loadMessages: (roomId: string, roomType: RoomType) => Promise<void>;
1666
+ simulateTyping: (userKey: string, isTyping: boolean, displayName?: string) => void;
1667
+ }
1668
+ declare const createSocketEventHandlers: (config: SocketEventHandlersConfig) => {
1669
+ onConnected: () => void;
1670
+ onAuthenticated: () => void;
1671
+ onDisconnected: () => void;
1672
+ onReady: (channels: ReadyChannelData[], channelUnreads?: ChannelUnread[]) => void;
1673
+ onChannelAck: (channelId: string, messageId: string) => void;
1674
+ onMessage: (message: Message) => void;
1675
+ onRoomChange: (roomId: string, change: unknown) => void;
1676
+ onTyping: (data: {
1677
+ userId?: string;
1678
+ username: string;
1679
+ roomId: string;
1680
+ isTyping: boolean;
1681
+ }) => void;
1682
+ onMessageUpdate: (messageId: string, channelId: string, data: {
1683
+ content?: string;
1684
+ edited?: string;
1685
+ }) => void;
1686
+ onMessageDelete: (messageId: string, channelId: string) => void;
1687
+ onUserStatusChange: (userId: string, status: string) => void;
1688
+ onInvalidSession: () => void | undefined;
1689
+ onError: (error: unknown) => void;
1690
+ };
1691
+
1692
+ declare const installUnreadWatcher: () => void;
108
1693
 
109
- export { type AlertWirePayload, type AppCommentWirePayload, type AskCorvaWirePayload, type AttachmentWirePayload, CORVA_MESSAGE_TYPES, CORVA_SYS_PREFIX, type CorvaSystemMessage, type FeedWirePayload, type ForwardWirePayload, type WireSeverity, buildAskCorvaMessageContent, buildForwardMessageContent };
1694
+ export { ALERT_SEVERITY, ASSET_API_FIELDS, ASSET_CHAT_PREFIXES, ASSET_NOUN, type AckScheduler, type AlertData, type AlertSeverity, type AlertWirePayload, type AppCommentAttachment, type AppCommentData, type AppCommentWirePayload, type AppStateAdapter, type AskCorvaData, type AskCorvaWirePayload, type AssetChatChannel, type AssetStore, type Attachment, type AuthStore, CHANNEL_NAME_MAX_LENGTH, CHANNEL_TYPES, CORVA_MESSAGE_TYPES, CORVA_SYS_PREFIX, type ChannelAsset, type ChannelContentFilter, type ChannelContentFilterStore, type ChannelContentFilters, type ChannelNameValidation, type ChannelNotificationPreference, type ChannelNotificationSetting, type ChannelUnread, type ChatAsset, type ChatAssetIdentity, type ChatAssetType, type ChatDates, type ChatHost, type ChatNotifier, type ChatPlatform, type CorvaAPIUser, type CorvaApiAdapter, type CorvaRevoltAuthResponse, type CorvaSystemMessage, type CorvaUser, type CorvaUserService, DATE_SEPARATOR_LABELS, DEFAULT_CHANNEL_CONTENT_FILTER, DEFAULT_CHANNEL_CONTENT_FILTERS, DEFAULT_CHANNEL_PREFERENCE, DEFAULT_FAVORITE_ROOMS_SETTINGS, DEFAULT_HIDDEN_ROOMS_SETTINGS, DEFAULT_NOTIFICATION_PREFERENCES, DEFAULT_NOTIFICATION_SETTINGS, DEFAULT_ROOM_LIST_ORDER, DIRECT_MESSAGE_PLACEHOLDER, type FavoriteRoomsSettings, type FavoriteRoomsStore, type FeedItemData, type FeedWirePayload, type FileAttachment, type FilterEntityWindow, type ForwardWirePayload, type ForwardedFrom, GENERAL_CHAT_NAME, type HiddenRoomsSettings, type HttpClient, type HttpClientConfig, HttpError, type HttpRequestInit, type HttpResponseLike, type KeyValueStorage, type LocatorContext, type LoginCredentials, MAX_ATTACHMENT_SIZE_BYTES, MAX_ATTACHMENT_SIZE_MB, MAX_NAVIGATION_HISTORY, MENTION_REPLACE_PATTERN, MENTION_SPLIT_PATTERN, MUTE_PRESET_OPTIONS, type MemberStore, type Message, type MessageCache, type MessageFormData, type MessageStore, NOTIFICATION_DESTINATIONS, NOTIFICATION_SETTING_ALL, NOTIFICATION_SETTING_MENTIONS, NOTIFICATION_SETTING_NOTHING, type NavigationEntry, type NavigationHistoryStore, type NotificationDestination, type NotificationPreferences, type NotificationSettings, type NotificationStore, PAUSE_INDEFINITELY, PAUSE_PRESETS, PAUSE_PRESET_OPTIONS, type PausePreset, type PausePresetOption, REVOLT_SYSTEM_USER_ID, ROOM_LIST_ORDER, type ReadyChannelData, type RevoltAPIInstance, type RevoltChannel, type RevoltIncomingMessagePayload, type RevoltLoginResponse, type RevoltMessage, type RevoltMessageResponse, type RevoltSocketConfig, type RevoltSocketEventHandlers, type RevoltSocketInstance, type RevoltUploadResponse, type RevoltUserResponse, type Room, type RoomListOrder, type RoomStore, type RoomType, SESSION_STORAGE_KEY, SIDEBAR_SECTIONS, SIDEBAR_TABS, SOFT_DELETE_MARKER, SYSTEM_MESSAGE_TEXTS, type SaveSessionParams, type SelectableAssetType, type SessionData, SessionManager, type SharedFile, type SharedRefs, type SidebarSectionKey, type SidebarTabKey, type SocketCloseEventLike, type SocketEventHandlersConfig, type StoredChannelPreference, type Subscription, type TracesViewportRequest, type TypingManager, type UIStore, type UploadAndSendResult, type UploadFile, type UploadedFile, type User, type UserStatus, type ViewportDeepLink, type ViewportIndexCurve, type ViewportMode, WEBSOCKET_CONNECTING, WEBSOCKET_OPEN, type WebSocketLike, type WireSeverity, addMessage, addOrUpdateSubscription, alertMessageAsText, assetStore, authStore, buildAppCommentMessageContent, buildAskCorvaMessageContent, buildFinalMessage, buildForwardMessageContent, buildGroupChannelName, canDeleteMessage, canEditMessage, channelContentFilterStore, channelToAsset, chatToastStore, clearLastOpenedRoom, compareByActivity, compareByName, compareByRecencyDesc, configureChat, configureChatStorage, createAckScheduler, createCorvaUserService, createDMSubscription, createGroupSubscription, createHttpClient, createLatestWinsQueue, createMemoryStorage, createMessageCache, createRevoltAPI, createRevoltSocket, createRoomTaskQueue, createSocketEventHandlers, createSoftDeletedMessage, createTypingManager, deriveAllowedChatAsset, enrichWithCorvaData, ensureChatSession, extractTimestampFromULID, failOptimisticMessage, favoriteRoomsStore, findGeneralRoom, formatAssetChatName, getAppCommentAttachments, getAssetChatChannel, getAssetTypeFromDisplayName, getChatHost, getChatStorage, getCorvaUserFields, getLastOpenedRoom, getMessageTimestamp, getPauseUntil, getReactionCount, getRoomDisplayName, getSystemMessageWithCorvaNames, getUserDisplayName, getUserSecondaryText, handleUnauthorized, hasReactions, hasUserReacted, initChat, installUnreadWatcher, isAlertMessage, isAppCommentMessage, isAskCorvaMessage, isChannelMuted, isChatAssetTypeAllowed, isCurrentRoomSelection, isDeepEqual, isDefaultChannelPreference, isDisallowedAssetChatRoom, isDmGroup, isForwardedMessage, isGeneralRoom, isNotificationsPaused, isPauseActive, isSoftDeletedMessage, isSystemMessage, isUnread, isUserOnline, isValidPausePreset, isVisibleUnread, keepChatUsed, loadUntilFound, memberStore, messageStore, navigationHistoryStore, notificationStore, parseCorvaSystemMessage, prepareRoomSelection, removeMessageFromList, removeSubscription, resetAssetStore, resetAuthStore, resetChannelContentFilterStore, resetChatAssetPermissionsSnapshot, resetChatHost, resetFavoriteRoomsStore, resetMemberStore, resetMessageStore, resetNavigationHistoryStore, resetNotificationStore, resetRoomStore, resetUIStore, roomStore, saveLastChatActivity, saveLastOpenedRoom, searchMessages, searchRooms, searchUsers, selectCanGoBack, selectCanGoForward, setAllowedChatAssetTypes, settleOptimisticMessage, sharedRefs, sortChannels, sortDMs, sortMessagesByTime, sortUsersByStatus, stripPlatformMentions, uiStore, updateMessageInList, uploadAndSend, validateChannelName, waitForNextPaint, wasRecentlyActive, withChannelPreferenceDefaults };