@ermis-network/ermis-chat-react 2.0.0 → 2.0.1

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.
Files changed (72) hide show
  1. package/README.md +144 -0
  2. package/dist/index.cjs +5087 -11279
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +632 -152
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.mts +273 -9
  7. package/dist/index.d.ts +273 -9
  8. package/dist/index.mjs +5085 -11295
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +2 -2
  11. package/src/components/Channel.tsx +0 -3
  12. package/src/components/ChannelActions.tsx +6 -1
  13. package/src/components/ChannelHeader.tsx +8 -32
  14. package/src/components/ChannelInfo/AddMemberModal.tsx +7 -1
  15. package/src/components/ChannelInfo/ChannelInfo.tsx +82 -2
  16. package/src/components/ChannelInfo/EditChannelModal.tsx +2 -2
  17. package/src/components/ChannelInfo/MediaGridItem.tsx +215 -78
  18. package/src/components/ChannelInfo/useChannelInfoTabs.tsx +170 -129
  19. package/src/components/ChannelList.tsx +72 -13
  20. package/src/components/CreateChannelModal.tsx +131 -12
  21. package/src/components/FilesPreview.tsx +8 -12
  22. package/src/components/FlatTopicGroupItem.tsx +27 -16
  23. package/src/components/ForwardMessageModal.tsx +11 -3
  24. package/src/components/MediaLightbox.tsx +444 -304
  25. package/src/components/MessageActionsBox.tsx +2 -0
  26. package/src/components/MessageInput.tsx +41 -12
  27. package/src/components/MessageItem.tsx +70 -25
  28. package/src/components/MessageQuickReactions.tsx +131 -128
  29. package/src/components/MessageReactions.tsx +47 -2
  30. package/src/components/MessageRenderers.tsx +1030 -433
  31. package/src/components/PinnedMessages.tsx +40 -12
  32. package/src/components/QuotedMessagePreview.tsx +99 -8
  33. package/src/components/RecoveryPin/RecoveryPin.tsx +279 -0
  34. package/src/components/RecoveryPin/index.ts +19 -0
  35. package/src/components/TopicList.tsx +20 -5
  36. package/src/components/TypingIndicator.tsx +3 -3
  37. package/src/components/UserPicker.tsx +26 -25
  38. package/src/components/VirtualMessageList.tsx +345 -125
  39. package/src/context/ChatProvider.tsx +27 -1
  40. package/src/hooks/useChannelListUpdates.ts +22 -1
  41. package/src/hooks/useChannelMessages.ts +338 -51
  42. package/src/hooks/useChannelRowUpdates.ts +18 -6
  43. package/src/hooks/useChatUser.ts +9 -1
  44. package/src/hooks/useE2eeAttachmentRenderer.ts +204 -0
  45. package/src/hooks/useE2eeFileUpload.ts +38 -0
  46. package/src/hooks/useFileUpload.ts +25 -5
  47. package/src/hooks/useForwardMessage.ts +210 -13
  48. package/src/hooks/useLoadMessages.ts +16 -4
  49. package/src/hooks/useMentions.ts +60 -6
  50. package/src/hooks/useMessageActions.ts +14 -8
  51. package/src/hooks/useMessageSend.ts +64 -12
  52. package/src/hooks/usePendingE2eeSends.ts +29 -0
  53. package/src/hooks/useRecoveryPin.ts +287 -0
  54. package/src/hooks/useScrollToMessage.ts +29 -4
  55. package/src/hooks/useTopicGroupUpdates.ts +49 -11
  56. package/src/index.ts +23 -0
  57. package/src/messageTypeUtils.ts +14 -0
  58. package/src/styles/_channel-info.css +9 -0
  59. package/src/styles/_channel-list.css +37 -14
  60. package/src/styles/_media-lightbox.css +36 -3
  61. package/src/styles/_message-bubble.css +381 -41
  62. package/src/styles/_message-input.css +8 -0
  63. package/src/styles/_message-list.css +67 -10
  64. package/src/styles/_message-quick-reactions.css +101 -59
  65. package/src/styles/_message-reactions.css +18 -32
  66. package/src/styles/_recovery-pin.css +97 -0
  67. package/src/styles/_tokens.css +5 -5
  68. package/src/styles/_typing-indicator.css +23 -13
  69. package/src/styles/index.css +1 -0
  70. package/src/types.ts +115 -1
  71. package/src/utils/avatarColors.ts +1 -1
  72. package/src/utils.ts +38 -18
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default from 'react';
3
3
  import * as _ermis_network_ermis_chat_sdk from '@ermis-network/ermis-chat-sdk';
4
- import { Channel as Channel$1, Attachment, FormatMessageResponse, ChannelFilters, ChannelSort, ChannelQueryOptions, SystemMessageTranslations, SignalMessageTranslations, ErmisChat, UserCallInfo, MessageLabel, ExtendableGenerics, DefaultGenerics, UserResponse, ErmisCallNode, CallStatus } from '@ermis-network/ermis-chat-sdk';
4
+ import { Channel as Channel$1, E2eeAttachmentManifest, Attachment, FormatMessageResponse, ChannelFilters, ChannelSort, ChannelQueryOptions, SystemMessageTranslations, SignalMessageTranslations, ErmisChat, UserCallInfo, E2eeRecoveryPolicy, MessageLabel, ExtendableGenerics, DefaultGenerics, UserResponse, E2eeAttachmentTransferProgress, PendingE2eeSendRecord, RestoreProgressRecord, RepairMode, RepairResult, EncryptedChannelRepairMode, EncryptedChannelRepairResult, ErmisCallNode, CallStatus } from '@ermis-network/ermis-chat-sdk';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import { VListHandle } from 'virtua';
7
7
 
@@ -55,6 +55,18 @@ type ChatContextValue = {
55
55
  setJumpToMessageId: (id: string | null) => void;
56
56
  /** Indicates whether the direct call feature is enabled */
57
57
  enableCall?: boolean;
58
+ /** Save a draft message (innerHTML and files) for a specific channel */
59
+ setDraft: (cid: string, draft: {
60
+ html: string;
61
+ files: any[];
62
+ }) => void;
63
+ /** Retrieve the saved draft for a specific channel */
64
+ getDraft: (cid: string) => {
65
+ html: string;
66
+ files: any[];
67
+ } | undefined;
68
+ /** Clear all saved drafts (e.g. on logout) */
69
+ clearAllDrafts: () => void;
58
70
  };
59
71
 
60
72
  type ChatProviderProps = {
@@ -432,6 +444,8 @@ type TopicListProps = {
432
444
  videoMessageLabel?: React.ReactNode;
433
445
  voiceRecordingMessageLabel?: React.ReactNode;
434
446
  fileMessageLabel?: React.ReactNode;
447
+ encryptedMessageLabel?: React.ReactNode;
448
+ encryptedMessageUnavailableLabel?: React.ReactNode;
435
449
  systemMessageTranslations?: SystemMessageTranslations;
436
450
  signalMessageTranslations?: SignalMessageTranslations;
437
451
  };
@@ -486,6 +500,10 @@ type ChannelListProps = {
486
500
  voiceRecordingMessageLabel?: React.ReactNode;
487
501
  /** Label for file messages in the preview strip (default: '📎 File') */
488
502
  fileMessageLabel?: React.ReactNode;
503
+ /** Label for encrypted messages in the preview strip (default: 'Encrypted message') */
504
+ encryptedMessageLabel?: React.ReactNode;
505
+ /** Label for encrypted messages that failed in the preview strip (default: 'Encrypted message unavailable') */
506
+ encryptedMessageUnavailableLabel?: React.ReactNode;
489
507
  /** Custom translation templates for system messages in the preview strip */
490
508
  systemMessageTranslations?: SystemMessageTranslations;
491
509
  /** Custom translation templates for signal (call) messages in the preview strip */
@@ -526,6 +544,8 @@ type ChannelListProps = {
526
544
  FlatTopicGroupItemComponent?: React.ComponentType<any>;
527
545
  /** Auto-scroll the channel list to the top when the current user sends a message (default: true) */
528
546
  scrollToTopOnOwnMessage?: boolean;
547
+ /** Whether to show topic pills on team channels (default: false) */
548
+ showTopicPills?: boolean;
529
549
  };
530
550
  type AttachmentProps = {
531
551
  attachment: Attachment;
@@ -538,6 +558,12 @@ type MessageRendererProps = {
538
558
  systemMessageTranslations?: SystemMessageTranslations;
539
559
  signalMessageTranslations?: SignalMessageTranslations;
540
560
  onMentionClick?: (userId: string) => void;
561
+ /** I18n Label for encrypted messages (default: 'Encrypted message') */
562
+ encryptedMessageLabel?: string;
563
+ /** I18n Label for encrypted messages that failed to decrypt (default: 'Encrypted message could not be decrypted') */
564
+ encryptedMessageFailedLabel?: string;
565
+ /** I18n Label for encrypted messages being decrypted (default: 'Decrypting encrypted message...') */
566
+ encryptedMessageDecryptingLabel?: string;
541
567
  };
542
568
  type MessageBubbleProps = {
543
569
  message: FormatMessageResponse;
@@ -552,9 +578,16 @@ type JumpToLatestProps = {
552
578
  };
553
579
  type MediaLightboxItem = {
554
580
  type: 'image' | 'video';
555
- src: string;
581
+ src?: string;
556
582
  alt?: string;
557
583
  posterSrc?: string;
584
+ loading?: boolean;
585
+ progressLabel?: string;
586
+ download?: () => Promise<void> | void;
587
+ onPlaybackError?: (context?: {
588
+ currentTime?: number;
589
+ }) => Promise<void> | void;
590
+ onDispose?: () => Promise<void> | void;
558
591
  };
559
592
  type MediaLightboxProps = {
560
593
  items: MediaLightboxItem[];
@@ -663,6 +696,18 @@ type MessageListProps = {
663
696
  }>) => string;
664
697
  /** I18n Label for deleted display messages (display_type === 'deleted') */
665
698
  deletedMessageLabel?: string;
699
+ /** I18n Label for attachment-only previews */
700
+ attachmentLabel?: string;
701
+ /** I18n Label for messages whose contents are unavailable */
702
+ unavailableMessageLabel?: string;
703
+ /** I18n Label for encrypted messages (default: 'Encrypted message') */
704
+ encryptedMessageLabel?: string;
705
+ /** I18n Label for encrypted messages that failed to decrypt (default: 'Encrypted message could not be decrypted') */
706
+ encryptedMessageFailedLabel?: string;
707
+ /** I18n Label for encrypted messages being decrypted (default: 'Decrypting encrypted message...') */
708
+ encryptedMessageDecryptingLabel?: string;
709
+ /** I18n Label for encrypted messages unavailable in sidebar preview (default: 'Encrypted message unavailable') */
710
+ encryptedMessageUnavailableLabel?: string;
666
711
  /** Custom translation templates for system messages */
667
712
  systemMessageTranslations?: SystemMessageTranslations;
668
713
  /** Custom translation templates for signal (call) messages */
@@ -753,6 +798,18 @@ type MessageItemProps = {
753
798
  editedLabel?: string;
754
799
  /** I18n Label for deleted display messages (display_type === 'deleted') */
755
800
  deletedMessageLabel?: React.ReactNode;
801
+ /** I18n Label for attachment-only previews */
802
+ attachmentLabel?: string;
803
+ /** I18n Label for messages whose contents are unavailable */
804
+ unavailableMessageLabel?: string;
805
+ /** I18n Label for sticker message previews */
806
+ stickerLabel?: string;
807
+ /** I18n Label for encrypted messages (default: 'Encrypted message') */
808
+ encryptedMessageLabel?: string;
809
+ /** I18n Label for encrypted messages that failed to decrypt (default: 'Encrypted message could not be decrypted') */
810
+ encryptedMessageFailedLabel?: string;
811
+ /** I18n Label for encrypted messages being decrypted (default: 'Decrypting encrypted message...') */
812
+ encryptedMessageDecryptingLabel?: string;
756
813
  /** Custom translation templates for system messages */
757
814
  systemMessageTranslations?: SystemMessageTranslations;
758
815
  /** Custom translation templates for signal (call) messages */
@@ -763,6 +820,8 @@ type MessageItemProps = {
763
820
  onUserNameClick?: (userId: string) => void;
764
821
  /** Handler when clicking to add a custom reaction */
765
822
  onAddReactionClick?: (e: React.MouseEvent, messageId: string) => void;
823
+ /** When true, the avatar column is not rendered (handled by group wrapper) */
824
+ hideAvatar?: boolean;
766
825
  };
767
826
  type SystemMessageItemProps = {
768
827
  message: FormatMessageResponse;
@@ -939,6 +998,8 @@ type PinnedMessageItemProps = {
939
998
  AvatarComponent: React.ComponentType<AvatarProps>;
940
999
  unpinLabel?: string;
941
1000
  stickerLabel?: string;
1001
+ attachmentLabel?: string;
1002
+ unavailableMessageLabel?: string;
942
1003
  };
943
1004
  type PinnedMessagesProps = {
944
1005
  /** Additional CSS class name */
@@ -957,6 +1018,8 @@ type PinnedMessagesProps = {
957
1018
  collapseLabel?: string;
958
1019
  unpinLabel?: string;
959
1020
  stickerLabel?: string;
1021
+ attachmentLabel?: string;
1022
+ unavailableMessageLabel?: string;
960
1023
  };
961
1024
  type QuotedMessagePreviewProps = {
962
1025
  /** The quoted (replied-to) message object */
@@ -967,11 +1030,28 @@ type QuotedMessagePreviewProps = {
967
1030
  id?: string;
968
1031
  name?: string;
969
1032
  };
1033
+ attachments?: Attachment[];
1034
+ content_type?: string;
1035
+ mls_ciphertext?: unknown;
1036
+ e2ee_status?: string;
1037
+ sticker_url?: string;
1038
+ type?: string;
1039
+ display_type?: string;
1040
+ mentioned_users?: string[];
1041
+ mentioned_all?: boolean;
970
1042
  };
971
1043
  /** Whether the parent message is from the current user */
972
1044
  isOwnMessage: boolean;
973
1045
  /** Callback when the quote box is clicked */
974
1046
  onClick: (messageId: string) => void;
1047
+ /** I18n Label for attachment-only quoted messages */
1048
+ attachmentLabel?: string;
1049
+ /** I18n Label for quoted messages whose contents are unavailable */
1050
+ unavailableMessageLabel?: string;
1051
+ /** I18n Label for sticker quoted messages */
1052
+ stickerLabel?: string;
1053
+ /** I18n Label for deleted messages */
1054
+ deletedMessageLabel?: string;
975
1055
  };
976
1056
  type MentionSuggestionsProps = {
977
1057
  members: MentionMember[];
@@ -1022,6 +1102,10 @@ type FilePreviewItem = {
1022
1102
  previewUrl?: string;
1023
1103
  /** Upload status */
1024
1104
  status: 'pending' | 'uploading' | 'done' | 'error';
1105
+ /** E2EE upload phase when the file is handled by MLS attachment flow */
1106
+ e2eePhase?: 'generating_preview' | 'encrypting' | 'uploading' | 'completing' | 'sending' | 'retrying' | 'failed';
1107
+ /** Upload progress percentage (0-100) */
1108
+ progress?: number;
1025
1109
  /** Error message if upload failed */
1026
1110
  error?: string;
1027
1111
  /** URL returned after successful upload */
@@ -1097,6 +1181,8 @@ type AttachmentItem = {
1097
1181
  og_scrape_url?: string;
1098
1182
  image_url?: string;
1099
1183
  text?: string;
1184
+ e2ee_manifest?: E2eeAttachmentManifest;
1185
+ e2ee_manifest_missing?: boolean;
1100
1186
  };
1101
1187
  type MediaTab = 'members' | 'media' | 'links' | 'files';
1102
1188
  type ChannelInfoTabHeaderProps = {
@@ -1156,8 +1242,13 @@ type ChannelInfoCoverProps = {
1156
1242
  isTopic?: boolean;
1157
1243
  /** Whether the channel is a team channel */
1158
1244
  isTeamChannel?: boolean;
1245
+ /** Whether this channel or inherited parent topic is E2EE enabled */
1246
+ isE2ee?: boolean;
1247
+ /** Current encryption epoch, if available */
1248
+ encryptionEpoch?: number;
1159
1249
  };
1160
1250
  type ChannelInfoActionsProps = {
1251
+ channel?: Channel$1;
1161
1252
  onSearchClick?: () => void;
1162
1253
  onSettingsClick?: () => void;
1163
1254
  onLeaveChannel?: () => void;
@@ -1191,6 +1282,15 @@ type ChannelInfoActionsProps = {
1191
1282
  onCreateTopic?: () => void;
1192
1283
  createTopicLabel?: string;
1193
1284
  topicsEnabled?: boolean;
1285
+ isE2ee?: boolean;
1286
+ encryptionInitialized?: boolean;
1287
+ encryptionEpoch?: number;
1288
+ onRotateKey?: () => void;
1289
+ rotateKeyLabel?: string;
1290
+ rotateKeyDisabled?: boolean;
1291
+ onEnableE2ee?: () => void;
1292
+ enableE2eeLabel?: string;
1293
+ enableE2eeDisabled?: boolean;
1194
1294
  };
1195
1295
  type ChannelInfoMember = {
1196
1296
  id: string;
@@ -1564,6 +1664,7 @@ type CreateChannelFooterProps = {
1564
1664
  messageButtonLabel?: string;
1565
1665
  nextButtonLabel?: string;
1566
1666
  backButtonLabel?: string;
1667
+ e2eeEnabled?: boolean;
1567
1668
  };
1568
1669
  type CreateChannelGroupFieldsProps = {
1569
1670
  name: string;
@@ -1578,11 +1679,25 @@ type CreateChannelGroupFieldsProps = {
1578
1679
  groupDescriptionLabel?: string;
1579
1680
  groupDescriptionPlaceholder?: string;
1580
1681
  groupPublicLabel?: string;
1682
+ e2eeEnabled?: boolean;
1683
+ onE2eeChange?: (enabled: boolean) => void;
1684
+ e2eeLabel?: string;
1685
+ e2eeDescription?: string;
1686
+ e2eeDisabled?: boolean;
1687
+ };
1688
+ type CreateChannelE2eeToggleProps = {
1689
+ enabled: boolean;
1690
+ onChange: (enabled: boolean) => void;
1691
+ disabled?: boolean;
1692
+ label?: string;
1693
+ description?: string;
1581
1694
  };
1582
1695
  type CreateChannelModalProps = {
1583
1696
  isOpen: boolean;
1584
1697
  onClose: () => void;
1585
1698
  onSuccess?: (channel: any) => void;
1699
+ /** Recovery coverage policy for newly created E2EE channels. Defaults to member_assisted. */
1700
+ e2eeRecoveryPolicy?: E2eeRecoveryPolicy;
1586
1701
  /** Override visual components */
1587
1702
  AvatarComponent?: React.ComponentType<AvatarProps>;
1588
1703
  UserItemComponent?: React.ComponentType<UserPickerItemProps>;
@@ -1595,6 +1710,7 @@ type CreateChannelModalProps = {
1595
1710
  placeholder: string;
1596
1711
  }>;
1597
1712
  SelectedBoxComponent?: React.ComponentType<UserPickerSelectedBoxProps>;
1713
+ E2eeToggleComponent?: React.ComponentType<CreateChannelE2eeToggleProps>;
1598
1714
  /** i18n labels */
1599
1715
  title?: string;
1600
1716
  directTabLabel?: string;
@@ -1613,6 +1729,9 @@ type CreateChannelModalProps = {
1613
1729
  nextButtonLabel?: string;
1614
1730
  backButtonLabel?: string;
1615
1731
  emptyStateLabel?: string;
1732
+ e2eeLabel?: string;
1733
+ e2eeDescription?: string;
1734
+ e2eeUnavailableLabel?: string;
1616
1735
  /** File upload configuration for group channel images */
1617
1736
  imageAccept?: string;
1618
1737
  maxImageSize?: number;
@@ -1797,6 +1916,8 @@ type TopicGroupUpdatesOptions = {
1797
1916
  videoMessageLabel?: React__default.ReactNode;
1798
1917
  voiceRecordingMessageLabel?: React__default.ReactNode;
1799
1918
  fileMessageLabel?: React__default.ReactNode;
1919
+ encryptedMessageLabel?: React__default.ReactNode;
1920
+ encryptedMessageUnavailableLabel?: React__default.ReactNode;
1800
1921
  systemMessageTranslations?: SystemMessageTranslations;
1801
1922
  signalMessageTranslations?: SignalMessageTranslations;
1802
1923
  };
@@ -1868,6 +1989,45 @@ declare function useFileUpload({ activeChannel, editableRef, setHasContent }: Us
1868
1989
  cleanupFiles: () => void;
1869
1990
  };
1870
1991
 
1992
+ type E2eeFileUploadProgress = {
1993
+ fileIndex: number;
1994
+ phase: 'generating_preview' | 'encrypting' | 'uploading' | 'completing';
1995
+ loaded: number;
1996
+ total: number;
1997
+ percentage: number;
1998
+ };
1999
+ declare function useE2eeFileUpload(channel: Channel$1 | null): {
2000
+ upload: (files: Blob[]) => Promise<{
2001
+ attachments: E2eeAttachmentManifest[];
2002
+ e2ee_attachment_ids: string[];
2003
+ }>;
2004
+ progress: E2eeFileUploadProgress | null;
2005
+ uploading: boolean;
2006
+ error: string | undefined;
2007
+ };
2008
+
2009
+ type E2eeAttachmentRenderState = {
2010
+ url?: string;
2011
+ blob?: Blob;
2012
+ loading: boolean;
2013
+ error?: string;
2014
+ progress?: E2eeAttachmentTransferProgress;
2015
+ load: () => Promise<string | undefined>;
2016
+ download: (filename?: string) => Promise<void>;
2017
+ streamUrl?: string;
2018
+ streamLoading: boolean;
2019
+ loadStream: () => Promise<string | undefined>;
2020
+ disposeStream: () => Promise<void>;
2021
+ revoke: () => void;
2022
+ };
2023
+ declare function useE2eeAttachmentRenderer(channel: Channel$1 | null, manifest?: E2eeAttachmentManifest, kind?: 'original' | 'preview'): E2eeAttachmentRenderState;
2024
+
2025
+ declare function usePendingE2eeSends(statuses?: string[]): {
2026
+ records: PendingE2eeSendRecord[];
2027
+ loading: boolean;
2028
+ refresh: () => Promise<void>;
2029
+ };
2030
+
1871
2031
  type UseEmojiPickerOptions = {
1872
2032
  editableRef: React.RefObject<HTMLDivElement | null>;
1873
2033
  setHasContent: (value: boolean) => void;
@@ -1958,6 +2118,8 @@ type ChannelRowProps = {
1958
2118
  videoMessageLabel?: React__default.ReactNode;
1959
2119
  voiceRecordingMessageLabel?: React__default.ReactNode;
1960
2120
  fileMessageLabel?: React__default.ReactNode;
2121
+ encryptedMessageLabel?: React__default.ReactNode;
2122
+ encryptedMessageUnavailableLabel?: React__default.ReactNode;
1961
2123
  systemMessageTranslations?: SystemMessageTranslations;
1962
2124
  signalMessageTranslations?: SignalMessageTranslations;
1963
2125
  };
@@ -1989,6 +2151,7 @@ type FlatTopicGroupItemProps = {
1989
2151
  fileMessageLabel?: React__default.ReactNode;
1990
2152
  systemMessageTranslations?: SystemMessageTranslations;
1991
2153
  signalMessageTranslations?: SignalMessageTranslations;
2154
+ showTopicPills?: boolean;
1992
2155
  };
1993
2156
  declare const FlatTopicGroupItem: React__default.FC<FlatTopicGroupItemProps>;
1994
2157
 
@@ -2040,7 +2203,6 @@ declare const MessageQuickReactions: React__default.FC<{
2040
2203
  message: FormatMessageResponse;
2041
2204
  isOwnMessage: boolean;
2042
2205
  disabled?: boolean;
2043
- onAddReactionClick?: (e: React__default.MouseEvent, messageId: string) => void;
2044
2206
  }>;
2045
2207
 
2046
2208
  type MessageActionList = {
@@ -2059,6 +2221,7 @@ type MessageActionList = {
2059
2221
  hasCapPin: boolean;
2060
2222
  hasCapReply: boolean;
2061
2223
  hasCapQuote: boolean;
2224
+ hasCapReact: boolean;
2062
2225
  };
2063
2226
  declare const useMessageActions: (message: FormatMessageResponse, isOwnMessage: boolean) => MessageActionList;
2064
2227
 
@@ -2067,7 +2230,8 @@ declare const useMessageActions: (message: FormatMessageResponse, isOwnMessage:
2067
2230
  */
2068
2231
  declare function removeAccents(str: string): string;
2069
2232
  /**
2070
- * Format a Date or date-string to a short time string (HH:MM).
2233
+ * Format a Date or date-string to a short time string (HH:MM, 24-hour).
2234
+ * Matches Telegram's compact time display.
2071
2235
  */
2072
2236
  declare function formatTime(date: Date | string | undefined): string;
2073
2237
  /**
@@ -2089,7 +2253,7 @@ declare function getMessageUserId(message: FormatMessageResponse): string;
2089
2253
  * Returns the formatted string.
2090
2254
  */
2091
2255
  declare function replaceMentionsForPreview(text: string, message: FormatMessageResponse | {
2092
- mentioned_users?: string[];
2256
+ mentioned_users?: any[];
2093
2257
  mentioned_all?: boolean;
2094
2258
  }, userMap: Record<string, string>, renderWrapper?: (userId: string, name: string) => string): string;
2095
2259
  /**
@@ -2113,6 +2277,8 @@ declare function getLastMessagePreview(channel: Channel$1, myUserId?: string, op
2113
2277
  videoMessageLabel?: React__default.ReactNode;
2114
2278
  voiceRecordingMessageLabel?: React__default.ReactNode;
2115
2279
  fileMessageLabel?: React__default.ReactNode;
2280
+ encryptedMessageLabel?: React__default.ReactNode;
2281
+ encryptedMessageUnavailableLabel?: React__default.ReactNode;
2116
2282
  systemMessageTranslations?: SystemMessageTranslations;
2117
2283
  signalMessageTranslations?: SignalMessageTranslations;
2118
2284
  }): {
@@ -2222,7 +2388,8 @@ declare function isDeletedDisplayMessage(message: any): boolean;
2222
2388
 
2223
2389
  declare const MessageAttachment: React__default.FC<AttachmentProps>;
2224
2390
  declare const AttachmentList: React__default.FC<{
2225
- attachments?: Attachment[];
2391
+ attachments?: Array<Attachment | E2eeAttachmentManifest>;
2392
+ e2eeGrantReady?: boolean;
2226
2393
  }>;
2227
2394
  /** Regular message: text with @mentions + attachments */
2228
2395
  declare const RegularMessage: React__default.FC<MessageRendererProps>;
@@ -2298,6 +2465,8 @@ type UseLoadMessagesOptions = {
2298
2465
  messagesRef: React.MutableRefObject<FormatMessageResponse[]>;
2299
2466
  /** Shared guard ref — skip scroll-triggered loads during jump transitions */
2300
2467
  jumpingRef: React.MutableRefObject<boolean>;
2468
+ /** Blocks scroll-triggered pagination while auto-following appended messages. */
2469
+ scrollLoadLockRef?: React.MutableRefObject<boolean>;
2301
2470
  loadMoreLimit?: number;
2302
2471
  };
2303
2472
  type UseLoadMessagesReturn = {
@@ -2316,10 +2485,14 @@ type UseLoadMessagesReturn = {
2316
2485
  handleScroll: (offset: number) => void;
2317
2486
  isAtBottomRef: React.MutableRefObject<boolean>;
2318
2487
  };
2319
- declare function useLoadMessages({ vlistRef, messagesRef, jumpingRef, loadMoreLimit, }: UseLoadMessagesOptions): UseLoadMessagesReturn;
2488
+ declare function useLoadMessages({ vlistRef, messagesRef, jumpingRef, scrollLoadLockRef, loadMoreLimit, }: UseLoadMessagesOptions): UseLoadMessagesReturn;
2320
2489
 
2321
2490
  type UseChannelMessagesOptions = {
2322
2491
  scrollToBottom: (smooth: boolean) => void;
2492
+ /** Reads the live virtual-list metrics to decide whether the viewport is near the bottom. */
2493
+ isNearBottom?: () => boolean;
2494
+ /** Temporarily blocks scroll-triggered pagination while auto-following new messages. */
2495
+ holdScrollLoadLock?: (duration?: number) => void;
2323
2496
  /** Shared guard ref — blocks scroll-triggered loads during channel switch */
2324
2497
  jumpingRef: React.MutableRefObject<boolean>;
2325
2498
  isAtBottomRef: React.MutableRefObject<boolean>;
@@ -2337,7 +2510,7 @@ declare const markChannelAsFullyQueried: (cid: string) => Set<string>;
2337
2510
  * - message.updated / message.deleted → sync only
2338
2511
  * - Channel switch → reset state + scroll to bottom
2339
2512
  */
2340
- declare function useChannelMessages({ scrollToBottom, jumpingRef, isAtBottomRef, onChannelSwitch, includeHiddenMessages, containerRef, }: UseChannelMessagesOptions): void;
2513
+ declare function useChannelMessages({ scrollToBottom, isNearBottom, holdScrollLoadLock, jumpingRef, isAtBottomRef, onChannelSwitch, includeHiddenMessages, containerRef, }: UseChannelMessagesOptions): void;
2341
2514
 
2342
2515
  declare function useForwardMessage(message: FormatMessageResponse, onDismiss: () => void): {
2343
2516
  search: string;
@@ -2357,6 +2530,55 @@ declare function useForwardMessage(message: FormatMessageResponse, onDismiss: ()
2357
2530
  handleSend: () => Promise<void>;
2358
2531
  };
2359
2532
 
2533
+ type RecoveryPinStatus = 'idle' | 'working' | 'ready' | 'locked' | 'error';
2534
+ type RecoveryStatusInfo = {
2535
+ hasVault: boolean;
2536
+ unlocked: boolean;
2537
+ hasIncompleteRestore: boolean;
2538
+ incompleteChannels: string[];
2539
+ channelsWithPermanentGaps: string[];
2540
+ restoreProgressWithIssues: RestoreProgressRecord[];
2541
+ e2eeBootstrapRunning?: boolean;
2542
+ e2eeBootstrapCompleted?: number;
2543
+ e2eeBootstrapTotal?: number;
2544
+ };
2545
+ type RecoveryRestoredMessage = {
2546
+ epoch: number;
2547
+ messageId?: string;
2548
+ plaintext?: unknown;
2549
+ source?: 'archive';
2550
+ createdAt?: string;
2551
+ gap?: boolean;
2552
+ reason?: string;
2553
+ };
2554
+ type UseRecoveryPinReturn = {
2555
+ status: RecoveryPinStatus;
2556
+ error: Error | null;
2557
+ hasRecoveryKey: boolean;
2558
+ recoveryStatus: RecoveryStatusInfo | null;
2559
+ setupRecoveryPin: (pin: string) => Promise<void>;
2560
+ unlockRecoveryVault: (pin: string) => Promise<void>;
2561
+ changeRecoveryPin: (oldPin: string, newPin: string) => Promise<void>;
2562
+ changeUnlockedRecoveryPin: (newPin: string) => Promise<void>;
2563
+ repairRecoveryChannel: (channelType: string, channelId: string, options?: {
2564
+ mode?: RepairMode;
2565
+ }) => Promise<RepairResult>;
2566
+ repairEncryptedChannel: (channelType: string, channelId: string, options?: {
2567
+ mode?: EncryptedChannelRepairMode;
2568
+ }) => Promise<EncryptedChannelRepairResult>;
2569
+ enqueueRestore: (channelType: string, channelId: string, priority?: 'active' | 'background', options?: {
2570
+ fromEpoch?: number;
2571
+ toEpoch?: number;
2572
+ }) => void;
2573
+ loadRestoreProgress: (channelType: string, channelId: string) => Promise<RestoreProgressRecord | null>;
2574
+ restoreHistoricalMessages: (channelType: string, channelId: string, options?: {
2575
+ fromEpoch?: number;
2576
+ toEpoch?: number;
2577
+ }) => Promise<RecoveryRestoredMessage[]>;
2578
+ refresh: () => void;
2579
+ };
2580
+ declare const useRecoveryPin: () => UseRecoveryPinReturn;
2581
+
2360
2582
  declare const QuotedMessagePreview: React__default.FC<QuotedMessagePreviewProps>;
2361
2583
 
2362
2584
  declare const ReplyPreview: React__default.FC<ReplyPreviewProps>;
@@ -2466,6 +2688,48 @@ declare const UserPicker: React__default.FC<UserPickerProps>;
2466
2688
 
2467
2689
  declare const CreateChannelModal: React__default.FC<CreateChannelModalProps>;
2468
2690
 
2691
+ type RecoveryPinSetupProps = {
2692
+ onComplete?: () => void;
2693
+ minDigits?: number;
2694
+ };
2695
+ type RecoveryPinRestoreProps = {
2696
+ onComplete?: () => void;
2697
+ };
2698
+ type RecoveryPinChangeProps = {
2699
+ onComplete?: () => void;
2700
+ minDigits?: number;
2701
+ };
2702
+ type RecoveryStatusProps = {
2703
+ status?: RecoveryPinStatus;
2704
+ hasRecoveryKey?: boolean;
2705
+ className?: string;
2706
+ };
2707
+ type RecoveryGapProps = {
2708
+ epoch?: number;
2709
+ reason: string;
2710
+ className?: string;
2711
+ };
2712
+ type RecoveryGateProps = {
2713
+ onSkip?: () => void;
2714
+ className?: string;
2715
+ };
2716
+ type RecoveryRestoreProgressProps = {
2717
+ restoredEpochs: number;
2718
+ totalEpochs: number;
2719
+ gaps?: Array<{
2720
+ epoch?: number;
2721
+ reason: string;
2722
+ }>;
2723
+ className?: string;
2724
+ };
2725
+ declare const RecoveryPinSetup: React__default.FC<RecoveryPinSetupProps>;
2726
+ declare const RecoveryPinRestore: React__default.FC<RecoveryPinRestoreProps>;
2727
+ declare const RecoveryPinChange: React__default.FC<RecoveryPinChangeProps>;
2728
+ declare const RecoveryStatus: React__default.FC<RecoveryStatusProps>;
2729
+ declare const RecoveryGap: React__default.FC<RecoveryGapProps>;
2730
+ declare const RecoveryGate: React__default.FC<RecoveryGateProps>;
2731
+ declare const RecoveryRestoreProgress: React__default.FC<RecoveryRestoreProgressProps>;
2732
+
2469
2733
  type CallContextValue = {
2470
2734
  callNode: ErmisCallNode | null;
2471
2735
  callStatus: CallStatus | '';
@@ -2510,4 +2774,4 @@ declare const ErmisCallProvider: React__default.FC<ErmisCallProviderProps>;
2510
2774
 
2511
2775
  declare const ErmisCallUI: React__default.FC<ErmisCallUIProps>;
2512
2776
 
2513
- export { ATTACHMENT_TYPES, type AddMemberButtonProps, type AddMemberModalProps, type AddMemberUserItemProps, type AttachButtonProps, type AttachmentItem, AttachmentList, type AttachmentProps, type AttachmentType, Avatar, type AvatarProps, CHANNEL_ROLES, type CallContextValue, Channel, type ChannelAction, type ChannelActionsProps, ChannelHeader, type ChannelHeaderData, type ChannelHeaderProps, ChannelInfo, type ChannelInfoActionsProps, type ChannelInfoCoverProps, type ChannelInfoEmptyStateProps, type ChannelInfoFileItemProps, type ChannelInfoHeaderProps, type ChannelInfoLinkItemProps, type ChannelInfoMediaItemProps, type ChannelInfoMemberItemProps, type ChannelInfoProps, type ChannelInfoTabHeaderProps, type ChannelInfoTabsProps, ChannelItem, type ChannelItemProps, ChannelList, type ChannelListProps, type ChannelProps, type ChannelRole, ChannelRow, ChannelSettingsPanel, type ChannelSettingsPanelProps, type ChatContextValue, ChatProvider, type ChatProviderProps, CreateChannelModal, type CreateChannelModalProps, type DateSeparatorProps, DefaultChannelActions, DefaultChannelInfoActions, DefaultChannelInfoCover, DefaultChannelInfoHeader, DefaultChannelInfoTabs, DefaultPinnedIcon, Dropdown, type DropdownProps, type EditChannelData, type EditChannelModalProps, EditPreview, type EmojiButtonProps, type EmojiPickerProps, type ErmisCallConnectedAudioProps, type ErmisCallConnectedVideoProps, ErmisCallContext, type ErmisCallControlsBarProps, type ErmisCallErrorProps, ErmisCallProvider, type ErmisCallProviderProps, type ErmisCallRingingProps, ErmisCallUI, type ErmisCallUIProps, ErrorMessage, type FilePreviewItem, FilesPreview, type FilesPreviewProps, FlatTopicGroupItem, type ForwardChannelItemProps, ForwardMessageModal, type ForwardMessageModalProps, HighlightedText, type JumpToLatestProps, type LatestReaction, MESSAGE_DISPLAY_TYPES, MESSAGE_TYPES, MediaLightbox, type MediaLightboxItem, type MediaLightboxProps, type MediaTab, type MentionMember, type MentionPayload, MentionSuggestions, type MentionSuggestionsProps, MessageActionsBox, type MessageActionsBoxProps, MessageAttachment, type MessageBubbleProps, type MessageDisplayType, MessageInput, type MessageInputProps, MessageItem, type MessageItemProps, type MessageListProps, MessageQuickReactions, MessageReactions, type MessageReactionsProps, type MessageRendererProps, MessageSearchPanel, type MessageSearchPanelProps, type MessageType, Modal, type ModalProps, type OnlineStatus, Panel, type PinnedMessageItemProps, PinnedMessages, type PinnedMessagesProps, PollMessage, PreviewOverlay, QuotedMessagePreview, type QuotedMessagePreviewProps, type ReactionUser, RegularMessage, ReplyPreview, type ReplyPreviewProps, type SendButtonProps, SignalMessage, StickerMessage, SystemMessage, SystemMessageItem, type SystemMessageItemProps, type Theme, TopicList, type TopicListProps, TopicModal, type TopicModalProps, type TopicPillProps, TypingIndicator, type TypingIndicatorProps, type TypingUser, type UseChannelMessagesOptions, type UseChannelReturn, type UseLoadMessagesOptions, type UseLoadMessagesReturn, type UseMentionsOptions, type UseMentionsReturn, type UseScrollToMessageOptions, type UseScrollToMessageReturn, type UseStickerPickerOptions, UserPicker, type UserPickerItemProps, type UserPickerProps, type UserPickerSelectedBoxProps, type UserPickerUser, VirtualMessageList, buildUserMap, canBanTargetMember, canDemoteTargetMember, canManageChannel, canPromoteTargetMember, canRemoveTargetMember, closeAllDropdowns, computeDefaultActions, countWords, dedupMessages, defaultMessageRenderers, formatDateLabel, formatRelativeDate, formatTime, getAvatarGradient, getDateKey, getLastMessagePreview, getMentionHtml, getMessageUserId, hasTopicsEnabled, isDeletedDisplayMessage, isDirectChannel, isFriendChannel, isGeneralProxy, isGroupChannel, isImage, isImageAttachment, isLinkPreviewAttachment, isOwnerMember, isPendingMember, isPublicGroupChannel, isRegularMessage, isSignalMessage, isSkippedMember, isStickerMessage, isSystemMessage, isTopicChannel, isVideo, isVideoAttachment, isVoiceRecordingAttachment, markChannelAsFullyQueried, removeAccents, replaceMentionsForPreview, supportsBlocking, useBannedState, useBlockedState, useCallContext, useChannel, useChannelCapabilities, useChannelListUpdates, useChannelMembers, useChannelMessages, useChannelProfile, useChannelRowUpdates, useChannelSettings, useChatClient, useChatUser, useContactChannels, useContactCount, useDragAndDrop, useEmojiPicker, useFileUpload, useForwardMessage, useInviteChannels, useInviteCount, useLoadMessages, useMentions, useMessageActions, useMessageSearch, useMessageSend, useOnlineStatus, useOnlineUsers, usePendingState, usePreviewState, useScrollToMessage, useStickerPicker, useTopicGroupUpdates, useTypingIndicator };
2777
+ export { ATTACHMENT_TYPES, type AddMemberButtonProps, type AddMemberModalProps, type AddMemberUserItemProps, type AttachButtonProps, type AttachmentItem, AttachmentList, type AttachmentProps, type AttachmentType, Avatar, type AvatarProps, CHANNEL_ROLES, type CallContextValue, Channel, type ChannelAction, type ChannelActionsProps, ChannelHeader, type ChannelHeaderData, type ChannelHeaderProps, ChannelInfo, type ChannelInfoActionsProps, type ChannelInfoCoverProps, type ChannelInfoEmptyStateProps, type ChannelInfoFileItemProps, type ChannelInfoHeaderProps, type ChannelInfoLinkItemProps, type ChannelInfoMediaItemProps, type ChannelInfoMemberItemProps, type ChannelInfoProps, type ChannelInfoTabHeaderProps, type ChannelInfoTabsProps, ChannelItem, type ChannelItemProps, ChannelList, type ChannelListProps, type ChannelProps, type ChannelRole, ChannelRow, ChannelSettingsPanel, type ChannelSettingsPanelProps, type ChatContextValue, ChatProvider, type ChatProviderProps, CreateChannelModal, type CreateChannelModalProps, type DateSeparatorProps, DefaultChannelActions, DefaultChannelInfoActions, DefaultChannelInfoCover, DefaultChannelInfoHeader, DefaultChannelInfoTabs, DefaultPinnedIcon, Dropdown, type DropdownProps, type EditChannelData, type EditChannelModalProps, EditPreview, type EmojiButtonProps, type EmojiPickerProps, type ErmisCallConnectedAudioProps, type ErmisCallConnectedVideoProps, ErmisCallContext, type ErmisCallControlsBarProps, type ErmisCallErrorProps, ErmisCallProvider, type ErmisCallProviderProps, type ErmisCallRingingProps, ErmisCallUI, type ErmisCallUIProps, ErrorMessage, type FilePreviewItem, FilesPreview, type FilesPreviewProps, FlatTopicGroupItem, type ForwardChannelItemProps, ForwardMessageModal, type ForwardMessageModalProps, HighlightedText, type JumpToLatestProps, type LatestReaction, MESSAGE_DISPLAY_TYPES, MESSAGE_TYPES, MediaLightbox, type MediaLightboxItem, type MediaLightboxProps, type MediaTab, type MentionMember, type MentionPayload, MentionSuggestions, type MentionSuggestionsProps, MessageActionsBox, type MessageActionsBoxProps, MessageAttachment, type MessageBubbleProps, type MessageDisplayType, MessageInput, type MessageInputProps, MessageItem, type MessageItemProps, type MessageListProps, MessageQuickReactions, MessageReactions, type MessageReactionsProps, type MessageRendererProps, MessageSearchPanel, type MessageSearchPanelProps, type MessageType, Modal, type ModalProps, type OnlineStatus, Panel, type PinnedMessageItemProps, PinnedMessages, type PinnedMessagesProps, PollMessage, PreviewOverlay, QuotedMessagePreview, type QuotedMessagePreviewProps, type ReactionUser, RecoveryGap, type RecoveryGapProps, RecoveryGate, type RecoveryGateProps, RecoveryPinChange, type RecoveryPinChangeProps, RecoveryPinRestore, type RecoveryPinRestoreProps, RecoveryPinSetup, type RecoveryPinSetupProps, type RecoveryPinStatus, RecoveryRestoreProgress, type RecoveryRestoreProgressProps, type RecoveryRestoredMessage, RecoveryStatus, type RecoveryStatusInfo, type RecoveryStatusProps, RegularMessage, ReplyPreview, type ReplyPreviewProps, type SendButtonProps, SignalMessage, StickerMessage, SystemMessage, SystemMessageItem, type SystemMessageItemProps, type Theme, TopicList, type TopicListProps, TopicModal, type TopicModalProps, type TopicPillProps, TypingIndicator, type TypingIndicatorProps, type TypingUser, type UseChannelMessagesOptions, type UseChannelReturn, type UseLoadMessagesOptions, type UseLoadMessagesReturn, type UseMentionsOptions, type UseMentionsReturn, type UseRecoveryPinReturn, type UseScrollToMessageOptions, type UseScrollToMessageReturn, type UseStickerPickerOptions, UserPicker, type UserPickerItemProps, type UserPickerProps, type UserPickerSelectedBoxProps, type UserPickerUser, VirtualMessageList, buildUserMap, canBanTargetMember, canDemoteTargetMember, canManageChannel, canPromoteTargetMember, canRemoveTargetMember, closeAllDropdowns, computeDefaultActions, countWords, dedupMessages, defaultMessageRenderers, formatDateLabel, formatRelativeDate, formatTime, getAvatarGradient, getDateKey, getLastMessagePreview, getMentionHtml, getMessageUserId, hasTopicsEnabled, isDeletedDisplayMessage, isDirectChannel, isFriendChannel, isGeneralProxy, isGroupChannel, isImage, isImageAttachment, isLinkPreviewAttachment, isOwnerMember, isPendingMember, isPublicGroupChannel, isRegularMessage, isSignalMessage, isSkippedMember, isStickerMessage, isSystemMessage, isTopicChannel, isVideo, isVideoAttachment, isVoiceRecordingAttachment, markChannelAsFullyQueried, removeAccents, replaceMentionsForPreview, supportsBlocking, useBannedState, useBlockedState, useCallContext, useChannel, useChannelCapabilities, useChannelListUpdates, useChannelMembers, useChannelMessages, useChannelProfile, useChannelRowUpdates, useChannelSettings, useChatClient, useChatUser, useContactChannels, useContactCount, useDragAndDrop, useE2eeAttachmentRenderer, useE2eeFileUpload, useEmojiPicker, useFileUpload, useForwardMessage, useInviteChannels, useInviteCount, useLoadMessages, useMentions, useMessageActions, useMessageSearch, useMessageSend, useOnlineStatus, useOnlineUsers, usePendingE2eeSends, usePendingState, usePreviewState, useRecoveryPin, useScrollToMessage, useStickerPicker, useTopicGroupUpdates, useTypingIndicator };