@ethora/chat-component 26.9.6 → 26.10.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.
- package/README.md +45 -3
- package/dist/{ChatProfileModal-DKuxJsdM.js → ChatProfileModal-Bf5jGPBZ.js} +566 -562
- package/dist/FilePreviewModal-Bwx0RZZw.js +1763 -0
- package/dist/{ManageDataModal-Dw4dCQll.js → ManageDataModal-Dhkp0LWH.js} +20 -20
- package/dist/{MarkdownBody-xtKDMR0h.js → MarkdownBody-_sUhW2O8.js} +1 -1
- package/dist/{MessageSearchModal-BVKU6H3v.js → MessageSearchModal-rwwWrILl.js} +106 -114
- package/dist/{PublicChatsModal-CscOnVaQ.js → PublicChatsModal-Byso6_vt.js} +13 -13
- package/dist/{SideDrawer-WneDrrWG.js → SideDrawer-CQPOf0ek.js} +38 -38
- package/dist/{UserProfileModal-CMHFq1I9.js → UserProfileModal-Vj2kICvc.js} +10 -10
- package/dist/{UserSettingsModal-BoZXZ0oR.js → UserSettingsModal-CioX4ZIV.js} +5 -5
- package/dist/{VideoCallOverlay-CQNi7wp5.js → VideoCallOverlay-DodAkiam.js} +3824 -3708
- package/dist/{VisibilityModal-BPsNiMzJ.js → VisibilityModal-CIl7rkBM.js} +12 -12
- package/dist/assets/icons.d.ts +2 -3
- package/dist/components/Files/fileCategory.d.ts +4 -2
- package/dist/components/InputComponents/MentionDropdown.d.ts +2 -0
- package/dist/components/MainComponents/AlbumGrid.d.ts +22 -0
- package/dist/components/MainComponents/AttachmentList.d.ts +6 -6
- package/dist/components/MainComponents/ImageUnavailable.d.ts +21 -0
- package/dist/components/MainComponents/MediaUploadOverlay.d.ts +31 -0
- package/dist/components/MainComponents/MessageContainer.d.ts +3 -0
- package/dist/components/MainComponents/scrollAnchor.d.ts +19 -0
- package/dist/components/MainComponents/useJumpToMessage.d.ts +42 -11
- package/dist/components/MainComponents/useScrollAnchor.d.ts +29 -0
- package/dist/components/MessageBubble/MediaCaption.d.ts +9 -0
- package/dist/components/MessageBubble/MessageAvatarPhoto.d.ts +17 -0
- package/dist/components/MessageBubble/MessageReaction.d.ts +6 -0
- package/dist/components/MessageBubble/QuickReplies.d.ts +2 -0
- package/dist/components/Modals/FilePreviewModal/FilePreviewModal.d.ts +8 -10
- package/dist/components/Modals/FilePreviewModal/ImageLightbox.d.ts +4 -0
- package/dist/components/Modals/FilePreviewModal/PdfView.d.ts +4 -0
- package/dist/components/Modals/FilePreviewModal/ViewerChrome.d.ts +64 -0
- package/dist/components/Modals/MessageSearchModal/MessageHitResults.d.ts +5 -0
- package/dist/components/Modals/styledModalComponents.d.ts +0 -8
- package/dist/components/RoomComponents/LastMessageItem.d.ts +2 -0
- package/dist/components/RoomComponents/styled/LastMessageMedia.d.ts +19 -0
- package/dist/components/RoomComponents/styled/LastTextMessage.d.ts +2 -2
- package/dist/components/RoomComponents/styled/StyledRoomComponents.d.ts +10 -3
- package/dist/components/VideoCalls/VideoCallSession.d.ts +13 -0
- package/dist/components/styled/FileCard.d.ts +20 -0
- package/dist/components/styled/MediaSurface.d.ts +50 -0
- package/dist/components/styled/MessageImage.d.ts +9 -10
- package/dist/components/styled/SendInput.d.ts +12 -2
- package/dist/components/styled/StyledComponents.d.ts +69 -2
- package/dist/components/styled/StyledInputComponents/MediaComponents.d.ts +36 -24
- package/dist/components/styled/UnsupportedType.d.ts +1 -0
- package/dist/components/styled/VideoMessage.d.ts +11 -6
- package/dist/e2ee/callKey.d.ts +32 -0
- package/dist/e2ee/fileEnvelope.d.ts +16 -5
- package/dist/e2ee/omemo.d.ts +18 -0
- package/dist/firebase-messaging-sw.js +20 -3
- package/dist/{handleCopyClick-B70vLjJD.js → handleCopyClick-DGaZhy_u.js} +1 -1
- package/dist/helpers/albumLayout.d.ts +53 -0
- package/dist/helpers/attachments.d.ts +22 -1
- package/dist/helpers/avatarImageCache.d.ts +9 -0
- package/dist/helpers/caption.d.ts +63 -0
- package/dist/helpers/checkUniqueUsers.d.ts +2 -2
- package/dist/helpers/composerFocus.d.ts +22 -0
- package/dist/helpers/createMainMessageForThread.d.ts +1 -1
- package/dist/helpers/dedupeMembers.d.ts +10 -0
- package/dist/helpers/downloadFile.d.ts +19 -0
- package/dist/helpers/fileKind.d.ts +17 -0
- package/dist/helpers/historyPreloadConfig.d.ts +25 -0
- package/dist/helpers/historyPreloadScheduler.d.ts +3 -0
- package/dist/helpers/insertMessageWithDelimiter.d.ts +1 -0
- package/dist/helpers/isMessageSearchEnabled.d.ts +9 -0
- package/dist/helpers/jumpThread.d.ts +56 -0
- package/dist/helpers/jumpWindow.d.ts +73 -0
- package/dist/helpers/lastMessagePreview.d.ts +55 -0
- package/dist/helpers/mapWithConcurrency.d.ts +8 -0
- package/dist/helpers/mediaBox.d.ts +110 -0
- package/dist/helpers/mediaBubble.d.ts +39 -0
- package/dist/helpers/mediaLabel.d.ts +10 -0
- package/dist/helpers/mediaSendRetry.d.ts +25 -0
- package/dist/helpers/messageRuns.d.ts +10 -0
- package/dist/helpers/openThreadForJump.d.ts +26 -0
- package/dist/helpers/pdf/loadPdfjs.d.ts +8 -1
- package/dist/helpers/repairFilenameEncoding.d.ts +11 -0
- package/dist/helpers/roomImageGallery.d.ts +34 -0
- package/dist/helpers/roomUserCount.d.ts +19 -0
- package/dist/helpers/safeUrl.d.ts +15 -0
- package/dist/helpers/secureFileUrl.d.ts +4 -1
- package/dist/helpers/userResolver.d.ts +57 -0
- package/dist/helpers/viewerSender.d.ts +47 -0
- package/dist/helpers/xmppIdShape.d.ts +1 -1
- package/dist/hooks/useAvatarImage.d.ts +21 -0
- package/dist/hooks/useChatWrapperInit.d.ts +6 -0
- package/dist/hooks/useIsMobileViewport.d.ts +5 -0
- package/dist/hooks/useMediaProbe.d.ts +40 -0
- package/dist/hooks/usePaneWidthVar.d.ts +11 -0
- package/dist/hooks/usePdfThumbnail.d.ts +2 -2
- package/dist/hooks/usePrefersReducedMotion.d.ts +2 -0
- package/dist/hooks/useRoomDirectory.d.ts +11 -0
- package/dist/hooks/useSendMessage.d.ts +4 -1
- package/dist/{main-rJpE4hh-.js → main-CUB_w8AZ.js} +29136 -24217
- package/dist/main.css +1 -1
- package/dist/main.js +16 -16
- package/dist/networking/api-requests/auth.api.d.ts +2 -0
- package/dist/networking/api-requests/roomMembers.api.d.ts +18 -0
- package/dist/networking/callKeyStanza.d.ts +7 -0
- package/dist/networking/ethoraEvents.d.ts +44 -0
- package/dist/networking/stanzaHandlers.d.ts +6 -4
- package/dist/networking/xmpp/allRoomPresences.xmpp.d.ts +18 -1
- package/dist/networking/xmpp/presenceInRoom.xmpp.d.ts +1 -1
- package/dist/networking/xmpp/sendDisplayedMarker.xmpp.d.ts +2 -0
- package/dist/networking/xmpp/sendMediaMessage.xmpp.d.ts +8 -0
- package/dist/networking/xmpp/sendReceivedReceipt.xmpp.d.ts +2 -0
- package/dist/networking/xmppClient.d.ts +61 -2
- package/dist/roomStore/Middleware/jumpThreadMiddleware.d.ts +2 -0
- package/dist/roomStore/callSlice.d.ts +6 -1
- package/dist/roomStore/index.d.ts +22 -0
- package/dist/roomStore/roomsSlice.d.ts +51 -4
- package/dist/roomStore/safeKey.d.ts +12 -0
- package/dist/roomStore/usersSetCap.d.ts +15 -0
- package/dist/styles/motion.d.ts +22 -2
- package/dist/types/models/attachment.model.d.ts +19 -0
- package/dist/types/models/config.model.d.ts +98 -5
- package/dist/types/models/customComponents.model.d.ts +2 -0
- package/dist/types/models/message.model.d.ts +9 -0
- package/dist/types/models/modal.model.d.ts +19 -0
- package/dist/types/models/room.model.d.ts +30 -0
- package/dist/types/models/xmpp.model.d.ts +24 -1
- package/dist/utils/messageNotificationContent.d.ts +34 -0
- package/dist/version.d.ts +1 -1
- package/package.json +2 -1
- package/public/firebase-messaging-sw.js +20 -3
- package/dist/FilePreviewModal-BcaSoO3-.js +0 -743
- package/dist/components/MainComponents/computeAnchoredScrollTop.d.ts +0 -9
- package/dist/components/Modals/NewChatModal/UpdNewChatModal.d.ts +0 -3
- package/dist/components/RoomComponents/styled/LastAudioMessage.d.ts +0 -6
- package/dist/components/RoomComponents/styled/LastMessageFile.d.ts +0 -6
- package/dist/components/RoomComponents/styled/LastMessagePhoto.d.ts +0 -6
- package/dist/components/RoomComponents/styled/LastMessageVideo.d.ts +0 -6
- package/dist/components/SortDropDown/index.d.ts +0 -8
|
@@ -45,6 +45,32 @@ export interface VideoCallsConfig {
|
|
|
45
45
|
showScreenShare?: boolean;
|
|
46
46
|
/** Custom icons for the call control bar / ring screen. See VideoCallIcons. */
|
|
47
47
|
icons?: VideoCallIcons;
|
|
48
|
+
/**
|
|
49
|
+
* End-to-end encrypt the call media (LiveKit insertable streams). The media
|
|
50
|
+
* key is exchanged over OMEMO - the same channel the chat uses - so the SFU
|
|
51
|
+
* and the server never see it, which makes the call private even from the
|
|
52
|
+
* operator. The trust model is OMEMO's (blind-trust-before-verification on
|
|
53
|
+
* device fingerprints).
|
|
54
|
+
*
|
|
55
|
+
* Requires the chat's own encryption to be on (`config.e2ee.enabled`) and a
|
|
56
|
+
* room the backend marked `e2ee`. A call that cannot set E2EE up - an
|
|
57
|
+
* unsupported browser, an insecure (non-HTTPS) context, or a peer with no
|
|
58
|
+
* published OMEMO device - falls back to a normal (transport-encrypted)
|
|
59
|
+
* call rather than failing.
|
|
60
|
+
*/
|
|
61
|
+
e2ee?: {
|
|
62
|
+
enabled: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Supplies the Web Worker LiveKit needs for insertable-stream E2EE. The
|
|
65
|
+
* library stays bundler-agnostic, so the host app creates it, typically:
|
|
66
|
+
* () => new Worker(
|
|
67
|
+
* new URL('livekit-client/e2ee-worker', import.meta.url),
|
|
68
|
+
* { type: 'module' }
|
|
69
|
+
* )
|
|
70
|
+
* Without a factory, call E2EE stays off.
|
|
71
|
+
*/
|
|
72
|
+
workerFactory?: () => Worker;
|
|
73
|
+
};
|
|
48
74
|
}
|
|
49
75
|
export interface FBConfig {
|
|
50
76
|
apiKey: string;
|
|
@@ -155,8 +181,8 @@ export interface IConfig {
|
|
|
155
181
|
/** Composer attachment limits. Applies to the built-in SendInput. */
|
|
156
182
|
attachments?: {
|
|
157
183
|
/**
|
|
158
|
-
* How many files one message may carry. Defaults to
|
|
159
|
-
*
|
|
184
|
+
* How many files one message may carry. Defaults to 10, which is also the
|
|
185
|
+
* hard cap set by the stanza payload (MAX_ATTACHMENTS_PER_MESSAGE).
|
|
160
186
|
*/
|
|
161
187
|
maxFiles?: number;
|
|
162
188
|
/** Per-file ceiling in MB. Omit to skip the client-side size check. */
|
|
@@ -174,6 +200,13 @@ export interface IConfig {
|
|
|
174
200
|
* thumbnails, worth overriding if your users open large documents.
|
|
175
201
|
*/
|
|
176
202
|
workerSrc?: string;
|
|
203
|
+
/**
|
|
204
|
+
* URL of a pdf.js ES module build to load at runtime instead of the copy
|
|
205
|
+
* bundled with the component. Pair it with `workerSrc`. For hosts that
|
|
206
|
+
* ship the component as one self-contained script and do not want 1.7 MB
|
|
207
|
+
* of pdf.js in it.
|
|
208
|
+
*/
|
|
209
|
+
libUrl?: string;
|
|
177
210
|
/** Documents above this are not auto-rendered. Default 25. */
|
|
178
211
|
maxFileSizeMb?: number;
|
|
179
212
|
};
|
|
@@ -495,9 +528,17 @@ export interface IConfig {
|
|
|
495
528
|
*/
|
|
496
529
|
disableUserCount?: boolean;
|
|
497
530
|
/**
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
*
|
|
531
|
+
* Opt in to message search: the "Search messages" button in the chat header
|
|
532
|
+
* and profile panel, the Ctrl/Cmd+F shortcut inside the chat, and message
|
|
533
|
+
* matches under the chat-list search box. Off by default. Needs `appId`
|
|
534
|
+
* (the archive it queries is scoped by app) and a backend that serves
|
|
535
|
+
* `GET /v2/apps/{appId}/messages/search`.
|
|
536
|
+
*/
|
|
537
|
+
enableMessageSearch?: boolean;
|
|
538
|
+
/**
|
|
539
|
+
* @deprecated Search is off unless `enableMessageSearch` is set. Kept so
|
|
540
|
+
* hosts that already pass `disableMessageSearch: true` stay off; it wins
|
|
541
|
+
* over `enableMessageSearch`.
|
|
501
542
|
*/
|
|
502
543
|
disableMessageSearch?: boolean;
|
|
503
544
|
/**
|
|
@@ -614,6 +655,44 @@ export interface IConfig {
|
|
|
614
655
|
hideSearch?: boolean;
|
|
615
656
|
};
|
|
616
657
|
useStoreConsoleEnabled?: boolean;
|
|
658
|
+
/**
|
|
659
|
+
* Route for looking up one unknown sender. `'auto'` (default) tries
|
|
660
|
+
* `GET /v1/apps/users/<xmppUsername>` and, when the backend does not accept
|
|
661
|
+
* the user token there (400/401, or a missing route), remembers that for 10
|
|
662
|
+
* minutes and uses `GET /v2/chats/users?xmppUsername=` instead, probing v1
|
|
663
|
+
* again after that. `'v1'` / `'v2'` pin one route with no fallback.
|
|
664
|
+
*/
|
|
665
|
+
userLookupRoute?: 'auto' | 'v1' | 'v2';
|
|
666
|
+
/**
|
|
667
|
+
* Who may push `ethora-event` headlines (`urn:ethora:events:1`,
|
|
668
|
+
* user-profile-updated / chat-meta-updated). Default (unset or empty): any
|
|
669
|
+
* bare JID without a resource on the account's own XMPP domain, which is
|
|
670
|
+
* how the server sends them (from its admin account); room occupants,
|
|
671
|
+
* other users and other domains are never trusted. Set it to pin the exact
|
|
672
|
+
* sender(s), as full bare JIDs (`admin@xmpp.example.com`) or local parts
|
|
673
|
+
* (`admin`).
|
|
674
|
+
*/
|
|
675
|
+
trustedEventSenders?: string[];
|
|
676
|
+
/**
|
|
677
|
+
* Background history preload after connect. Default `{ mode: 'staged',
|
|
678
|
+
* topRooms: 8, concurrency: 3 }`.
|
|
679
|
+
* - `'staged'`: the `topRooms` most recently active rooms are preloaded
|
|
680
|
+
* (a one-message preview pass for rooms the API gave no `lastMessage`
|
|
681
|
+
* for, then a full page), `concurrency` at a time; every other room
|
|
682
|
+
* loads when the user opens it.
|
|
683
|
+
* - `'all'`: preload every room (the pre-staged behaviour; for accounts
|
|
684
|
+
* with few rooms).
|
|
685
|
+
* - `'off'`: no background preload, rooms load when opened.
|
|
686
|
+
* A room the user opens jumps the queue; a reconnect only re-queues rooms
|
|
687
|
+
* that are not already preloaded.
|
|
688
|
+
* Falls back to the older `historyQoS.preloadTopKRooms` /
|
|
689
|
+
* `stagedPreloadConcurrency` when the matching field is not set.
|
|
690
|
+
*/
|
|
691
|
+
historyPreload?: {
|
|
692
|
+
mode?: 'staged' | 'all' | 'off';
|
|
693
|
+
topRooms?: number;
|
|
694
|
+
concurrency?: number;
|
|
695
|
+
};
|
|
617
696
|
historyQoS?: {
|
|
618
697
|
maxInFlightHistory?: number;
|
|
619
698
|
softPauseAfterSendMs?: number;
|
|
@@ -629,6 +708,20 @@ export interface IConfig {
|
|
|
629
708
|
stagedPreloadFirstPassSize?: number;
|
|
630
709
|
stagedPreloadSecondPassSize?: number;
|
|
631
710
|
stagedPreloadConcurrency?: number;
|
|
711
|
+
/**
|
|
712
|
+
* Messages the MUC service replays on every room join, sent as
|
|
713
|
+
* `<history maxstanzas="N"/>`. Default 0: history comes from MAM only, so
|
|
714
|
+
* joining many rooms no longer pulls up to the server default (20) per
|
|
715
|
+
* room. Raise it only if a host relies on the join replay (a room without
|
|
716
|
+
* MAM archiving).
|
|
717
|
+
*/
|
|
718
|
+
joinHistoryStanzas?: number;
|
|
719
|
+
/**
|
|
720
|
+
* Rooms joined in parallel by the background join sweep that runs after
|
|
721
|
+
* the room list is shown (active room first, then most recent activity).
|
|
722
|
+
* Default 5.
|
|
723
|
+
*/
|
|
724
|
+
joinConcurrency?: number;
|
|
632
725
|
};
|
|
633
726
|
inAppNotifications?: {
|
|
634
727
|
enabled?: boolean;
|
|
@@ -11,6 +11,8 @@ export interface NewMessageLabelProps {
|
|
|
11
11
|
export interface DecoratedMessage {
|
|
12
12
|
message: IMessage;
|
|
13
13
|
showDateLabel: boolean;
|
|
14
|
+
/** False when the next row is the same sender's message (a run continues). */
|
|
15
|
+
isLastInGroup?: boolean;
|
|
14
16
|
}
|
|
15
17
|
export interface ScrollControllerApi {
|
|
16
18
|
scrollToBottom: () => void;
|
|
@@ -55,6 +55,7 @@ export interface IMessage {
|
|
|
55
55
|
mainMessage?: string;
|
|
56
56
|
reply?: IReply[];
|
|
57
57
|
reaction?: Record<string, ReactionMessage>;
|
|
58
|
+
receivedBy?: Record<string, number>;
|
|
58
59
|
fileName?: string;
|
|
59
60
|
translations?: TranslationObject;
|
|
60
61
|
langSource?: Iso639_1Codes;
|
|
@@ -71,6 +72,8 @@ export interface IMessage {
|
|
|
71
72
|
xmppFrom?: string;
|
|
72
73
|
quickReplies?: unknown;
|
|
73
74
|
mentions?: IMentionSpan[];
|
|
75
|
+
caption?: string;
|
|
76
|
+
captionMentions?: IMentionSpan[];
|
|
74
77
|
callLog?: {
|
|
75
78
|
callId: string;
|
|
76
79
|
direction: 'outgoing' | 'incoming';
|
|
@@ -95,6 +98,12 @@ export interface MessageProps {
|
|
|
95
98
|
message: IMessage;
|
|
96
99
|
isUser: boolean;
|
|
97
100
|
isReply: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* False when the next message comes from the same sender (a run). The last
|
|
103
|
+
* message of a run carries the bubble tail and the larger gap below it.
|
|
104
|
+
* Omitted means last.
|
|
105
|
+
*/
|
|
106
|
+
isLastInGroup?: boolean;
|
|
98
107
|
}
|
|
99
108
|
export interface MediaMessageType {
|
|
100
109
|
}
|
|
@@ -4,4 +4,23 @@ export interface ModalFile {
|
|
|
4
4
|
fileName: string;
|
|
5
5
|
fileURL: string;
|
|
6
6
|
mimetype: string;
|
|
7
|
+
/** Optional low-resolution copy, used for viewer thumbnails. */
|
|
8
|
+
previewURL?: string;
|
|
9
|
+
/** Optional message timestamp (ISO) shown in the viewer header. */
|
|
10
|
+
date?: string;
|
|
11
|
+
/** Optional sender shown in the viewer header. */
|
|
12
|
+
sender?: {
|
|
13
|
+
id?: string;
|
|
14
|
+
username?: string;
|
|
15
|
+
name?: string;
|
|
16
|
+
firstName?: string;
|
|
17
|
+
lastName?: string;
|
|
18
|
+
photo?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Optional sibling files (e.g. a whole album) the viewer can page through
|
|
22
|
+
* when the room's loaded messages do not already contain this file.
|
|
23
|
+
* Single-file callers leave it out.
|
|
24
|
+
*/
|
|
25
|
+
siblings?: ModalFile[];
|
|
7
26
|
}
|
|
@@ -62,7 +62,18 @@ export interface IRoom {
|
|
|
62
62
|
composingList?: string[];
|
|
63
63
|
lastViewedTimestamp?: number;
|
|
64
64
|
unreadBaselineTimestamp?: number;
|
|
65
|
+
lastDisplayedByUser?: Record<string, string>;
|
|
65
66
|
unreadMessages?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Unread count the server reported for this room in `GET /v1/chats/my`
|
|
69
|
+
* (`unreadCount`) and when it was read. Only present on backends that send
|
|
70
|
+
* it. The unread middleware uses it as a floor while the local message
|
|
71
|
+
* list is too short to count from (history not loaded yet): it lets the
|
|
72
|
+
* room list show a badge without a MAM round-trip per room. Ignored once
|
|
73
|
+
* the user has read past the API's last message, and cleared on open.
|
|
74
|
+
*/
|
|
75
|
+
apiUnreadCount?: number;
|
|
76
|
+
apiUnreadSeededAt?: number;
|
|
66
77
|
noMessages?: boolean;
|
|
67
78
|
role?: string;
|
|
68
79
|
messageStats?: {
|
|
@@ -70,6 +81,8 @@ export interface IRoom {
|
|
|
70
81
|
firstMessageTimestamp?: number;
|
|
71
82
|
};
|
|
72
83
|
historyComplete?: boolean;
|
|
84
|
+
/** Persisted-cache stamp: the saved transcript includes its reactions. */
|
|
85
|
+
reactionsCached?: boolean;
|
|
73
86
|
historyPreloadState?: 'idle' | 'loading' | 'partial' | 'done' | 'error';
|
|
74
87
|
unreadCapped?: boolean;
|
|
75
88
|
/**
|
|
@@ -99,6 +112,19 @@ export interface ApiRoomLastMessage {
|
|
|
99
112
|
isOwn?: boolean;
|
|
100
113
|
senderFirstName?: string;
|
|
101
114
|
senderLastName?: string;
|
|
115
|
+
/**
|
|
116
|
+
* Media fields, present when the last message is a file. Any subset may be
|
|
117
|
+
* sent: a thin payload can carry just `mimetype` and `fileName`.
|
|
118
|
+
*/
|
|
119
|
+
isMediafile?: string | boolean;
|
|
120
|
+
mimetype?: string;
|
|
121
|
+
fileName?: string;
|
|
122
|
+
originalName?: string;
|
|
123
|
+
location?: string;
|
|
124
|
+
locationPreview?: string;
|
|
125
|
+
duration?: string | number;
|
|
126
|
+
attachments?: unknown;
|
|
127
|
+
clientEncrypted?: string | boolean;
|
|
102
128
|
}
|
|
103
129
|
export interface ApiRoom {
|
|
104
130
|
name: string;
|
|
@@ -109,6 +135,8 @@ export interface ApiRoom {
|
|
|
109
135
|
description?: string;
|
|
110
136
|
picture?: string;
|
|
111
137
|
members?: RoomMember[];
|
|
138
|
+
/** True total; `members` is capped at 30 for big public rooms. */
|
|
139
|
+
usersCnt?: number;
|
|
112
140
|
createdBy?: string;
|
|
113
141
|
appId?: any;
|
|
114
142
|
_id?: string;
|
|
@@ -118,6 +146,8 @@ export interface ApiRoom {
|
|
|
118
146
|
__v?: string;
|
|
119
147
|
/** See IRoom.muted - only present when the backend supports per-chat mute. */
|
|
120
148
|
muted?: boolean;
|
|
149
|
+
/** See IRoom.apiUnreadCount - only present when the backend sends it. */
|
|
150
|
+
unreadCount?: number;
|
|
121
151
|
/** See ApiRoomLastMessage - only present when the backend supports it. */
|
|
122
152
|
lastMessage?: ApiRoomLastMessage;
|
|
123
153
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Client } from '@xmpp/client';
|
|
2
2
|
import { Iso639_1Codes } from './language.model';
|
|
3
|
-
import { default as XmppClient } from '../../networking/xmppClient';
|
|
3
|
+
import { default as XmppClient, HistoryWindowPage } from '../../networking/xmppClient';
|
|
4
4
|
import { IMessage } from './message.model';
|
|
5
5
|
export interface XmppState {
|
|
6
6
|
client: XmppClient | null;
|
|
@@ -27,6 +27,20 @@ export interface xmppSettingsInterface {
|
|
|
27
27
|
stagedPreloadFirstPassSize?: number;
|
|
28
28
|
stagedPreloadSecondPassSize?: number;
|
|
29
29
|
stagedPreloadConcurrency?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Messages the MUC service replays on every room join, sent as
|
|
32
|
+
* `<history maxstanzas="N"/>`. Default 0: history comes from MAM only, so
|
|
33
|
+
* joining many rooms no longer pulls up to the server default (20) per
|
|
34
|
+
* room. Raise it only if a host relies on the join replay (a room without
|
|
35
|
+
* MAM archiving).
|
|
36
|
+
*/
|
|
37
|
+
joinHistoryStanzas?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Rooms joined in parallel by the background join sweep that runs after
|
|
40
|
+
* the room list is shown (active room first, then most recent activity).
|
|
41
|
+
* Default 5.
|
|
42
|
+
*/
|
|
43
|
+
joinConcurrency?: number;
|
|
30
44
|
};
|
|
31
45
|
}
|
|
32
46
|
export interface MediaUploadData {
|
|
@@ -65,6 +79,12 @@ export interface XmppClientInterface {
|
|
|
65
79
|
skipIfPreloaded?: boolean;
|
|
66
80
|
source?: 'active' | 'send_ack' | 'background' | 'default';
|
|
67
81
|
}): Promise<IMessage[] | undefined>;
|
|
82
|
+
getHistoryWindow(chatJID: string, max: number, cursor: {
|
|
83
|
+
before?: number;
|
|
84
|
+
after?: number;
|
|
85
|
+
start?: string;
|
|
86
|
+
end?: string;
|
|
87
|
+
}): Promise<HistoryWindowPage>;
|
|
68
88
|
promoteRoomHistory(roomJID: string): void;
|
|
69
89
|
setActiveRoomJid(roomJID: string | null): void;
|
|
70
90
|
isActiveRoomGateOpen(): boolean;
|
|
@@ -84,6 +104,9 @@ export interface XmppClientInterface {
|
|
|
84
104
|
sendMessage(roomJID: string, firstName: string, lastName: string, photo: string, walletAddress: string, userMessage: string, notDisplayedValue?: string, isReply?: boolean, showInChannel?: boolean, mainMessage?: string, customId?: string): void;
|
|
85
105
|
deleteMessageStanza(room: string, msgId: string): void;
|
|
86
106
|
editMessageStanza(room: string, msgId: string, text: string): void;
|
|
107
|
+
sendReceivedReceiptStanza(messageId: string, roomJid: string): void;
|
|
108
|
+
sendDisplayedMarkerStanza(messageId: string, roomJid: string): void;
|
|
109
|
+
sendHistoryReceivedReceiptStanza(roomJid: string, messageId: string): void;
|
|
87
110
|
sendTypingRequestStanza(chatId: string, fullName: string, start: boolean): void;
|
|
88
111
|
getChatsPrivateStoreRequestStanza(): Promise<any>;
|
|
89
112
|
actionSetTimestampToPrivateStoreStanza(chatId: string, timestamp: number, chats?: string[]): Promise<void>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { IMessage } from '../types/models/message.model';
|
|
2
|
+
import { IRoom, RoomMember } from '../types/models/room.model';
|
|
3
|
+
export declare const MAX_NOTIFICATION_BODY_LENGTH = 120;
|
|
4
|
+
export interface NotificationContent {
|
|
5
|
+
title: string;
|
|
6
|
+
body: string;
|
|
7
|
+
/** One per room, so a burst in the same room collapses into one entry. */
|
|
8
|
+
tag: string;
|
|
9
|
+
roomJID: string;
|
|
10
|
+
messageId: string;
|
|
11
|
+
}
|
|
12
|
+
export interface NotificationContentInput {
|
|
13
|
+
message: IMessage;
|
|
14
|
+
roomJID: string;
|
|
15
|
+
room?: IRoom | null;
|
|
16
|
+
usersSet?: Record<string, RoomMember>;
|
|
17
|
+
currentXmppUsername?: string;
|
|
18
|
+
activeRoomJID?: string | null;
|
|
19
|
+
tabVisible: boolean;
|
|
20
|
+
locale?: string | null;
|
|
21
|
+
strings?: Record<string, string> | null;
|
|
22
|
+
/** Names the caller already has (toast args); never trusted blindly. */
|
|
23
|
+
senderNameHint?: string;
|
|
24
|
+
roomNameHint?: string;
|
|
25
|
+
}
|
|
26
|
+
export declare const resolveNotificationSenderName: (message: IMessage, usersSet?: Record<string, RoomMember>, room?: IRoom | null, hint?: string) => string;
|
|
27
|
+
export declare const resolveNotificationRoomName: (roomJID: string, room?: IRoom | null, hint?: string) => string;
|
|
28
|
+
export declare const getNotificationTag: (roomJID: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Returns what to show, or null when this message must not raise an alert:
|
|
31
|
+
* own messages, system/receipt/typing stanzas (nothing to say), muted rooms,
|
|
32
|
+
* and the open room while the tab is visible.
|
|
33
|
+
*/
|
|
34
|
+
export declare const buildNotificationContent: (input: NotificationContentInput) => NotificationContent | null;
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const ETHORA_CHAT_COMPONENT_VERSION = "26.
|
|
1
|
+
export declare const ETHORA_CHAT_COMPONENT_VERSION = "26.10.1";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethora/chat-component",
|
|
3
|
-
"version": "26.
|
|
3
|
+
"version": "26.10.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"types": "dist/main.d.ts",
|
|
@@ -97,6 +97,7 @@
|
|
|
97
97
|
"eslint-plugin-prettier": "^5.5.0",
|
|
98
98
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
99
99
|
"eslint-plugin-react-refresh": "^0.4.20",
|
|
100
|
+
"globals": "^11.12.0",
|
|
100
101
|
"jsdom": "^24.1.0",
|
|
101
102
|
"prettier": "3.6.0",
|
|
102
103
|
"react": "^18.3.1",
|
|
@@ -151,8 +151,25 @@ async function checkAssetAvailability(url) {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
// `<appId>_<userId>` (24-hex ids, or an appId and a uuid) is a machine id,
|
|
155
|
+
// never something to put in a notification title.
|
|
156
|
+
const OPAQUE_ID_RE =
|
|
157
|
+
/^(?:[0-9a-f]{24}(?:_[0-9a-f]{24})?|[a-z0-9]+_(?:[0-9a-f]{24}|[0-9a-f-]{36})(?:_[0-9a-z-]+)*)$/i;
|
|
158
|
+
|
|
159
|
+
function isOpaqueId(value) {
|
|
160
|
+
const text = String(value || '').trim();
|
|
161
|
+
return !!text && OPAQUE_ID_RE.test(text.split('@')[0]);
|
|
162
|
+
}
|
|
163
|
+
|
|
154
164
|
function pickTitle(raw = {}, data = {}, notification = {}) {
|
|
155
|
-
|
|
165
|
+
const title = notification.title || raw.title || data.title || '';
|
|
166
|
+
return title && !isOpaqueId(title) ? title : 'New Message';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// One notification per chat: a newer message in the same room replaces it.
|
|
170
|
+
function roomTag(data = {}) {
|
|
171
|
+
const jid = String(data.jid || '').split('@')[0];
|
|
172
|
+
return jid ? `ethora-room-${jid}` : '';
|
|
156
173
|
}
|
|
157
174
|
|
|
158
175
|
function pickBody(raw = {}, data = {}, notification = {}) {
|
|
@@ -449,8 +466,8 @@ async function handlePush(raw = {}, source = 'push') {
|
|
|
449
466
|
icon,
|
|
450
467
|
badge,
|
|
451
468
|
image,
|
|
452
|
-
tag: isCall ? `call:${callId || dedupKey}` : dedupKey,
|
|
453
|
-
renotify: isCall,
|
|
469
|
+
tag: isCall ? `call:${callId || dedupKey}` : roomTag(data) || dedupKey,
|
|
470
|
+
renotify: isCall || !!roomTag(data),
|
|
454
471
|
requireInteraction: isCall,
|
|
455
472
|
// Spread the ORIGINAL payload first so the click handler's isCallPush()
|
|
456
473
|
// sees the full call fields (callId/callToken/kind/room); our routing
|