@ethora/chat-component 26.9.4 → 26.9.6
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 +2 -0
- package/dist/{ChatProfileModal-Pr4--RdW.js → ChatProfileModal-DKuxJsdM.js} +526 -519
- package/dist/{FilePreviewModal-CYHlKzRc.js → FilePreviewModal-BcaSoO3-.js} +89 -89
- package/dist/{ManageDataModal-BE1eGlYh.js → ManageDataModal-Dw4dCQll.js} +2 -2
- package/dist/{MarkdownBody-G0_J0NL6.js → MarkdownBody-xtKDMR0h.js} +1 -1
- package/dist/MessageSearchModal-BVKU6H3v.js +389 -0
- package/dist/PublicChatsModal-CscOnVaQ.js +202 -0
- package/dist/{SideDrawer-BG2m7Bcm.js → SideDrawer-WneDrrWG.js} +27 -27
- package/dist/{UserProfileModal-B2Hp5bAF.js → UserProfileModal-CMHFq1I9.js} +3 -3
- package/dist/{UserSettingsModal-D871FDAT.js → UserSettingsModal-BoZXZ0oR.js} +2 -2
- package/dist/{VideoCallOverlay-Br0ji0nZ.js → VideoCallOverlay-CQNi7wp5.js} +1 -1
- package/dist/{VisibilityModal-DdFBV1_g.js → VisibilityModal-BPsNiMzJ.js} +2 -2
- package/dist/assets/icons.d.ts +9 -0
- package/dist/components/InputComponents/Search.d.ts +4 -0
- package/dist/components/MainComponents/ArchivedMessageCard.d.ts +11 -0
- package/dist/components/MainComponents/computeAnchoredScrollTop.d.ts +9 -0
- package/dist/components/MainComponents/useJumpToMessage.d.ts +63 -0
- package/dist/components/MainComponents/useStickToBottom.d.ts +27 -0
- package/dist/components/Modals/MessageSearchModal/MessageHitResults.d.ts +22 -0
- package/dist/components/Modals/MessageSearchModal/MessageSearchModal.d.ts +6 -0
- package/dist/components/Modals/MessageSearchModal/resolveSender.d.ts +33 -0
- package/dist/components/Modals/MessageSearchModal/searchFilters.d.ts +34 -0
- package/dist/components/Modals/MessageSearchModal/snippet.d.ts +14 -0
- package/dist/components/Modals/MessageSearchModal/useMessageSearch.d.ts +22 -0
- package/dist/components/Modals/PublicChatsModal/PublicChatsModal.d.ts +13 -0
- package/dist/components/styled/RoomListComponents/index.d.ts +3 -0
- package/dist/context/ToastContext.d.ts +7 -0
- package/dist/firebase-messaging-sw.js +21 -3
- package/dist/{handleCopyClick-DPjxMoJn.js → handleCopyClick-B70vLjJD.js} +1 -1
- package/dist/helpers/constants/MODAL_TYPES.d.ts +2 -0
- package/dist/helpers/nanoToMs.d.ts +1 -1
- package/dist/helpers/openRoomAtMessage.d.ts +17 -0
- package/dist/hooks/useMessageSearchShortcut.d.ts +14 -0
- package/dist/hooks/useRoomState.d.ts +1 -0
- package/dist/{main-BRIZ98KV.js → main-rJpE4hh-.js} +12318 -11108
- package/dist/main.css +1 -1
- package/dist/main.js +6 -6
- package/dist/networking/api-requests/messageSearch.api.d.ts +56 -0
- package/dist/networking/api-requests/publicChats.api.d.ts +23 -0
- package/dist/networking/api-requests/xmppToken.api.d.ts +1 -0
- package/dist/networking/xmppClient.d.ts +2 -0
- package/dist/roomStore/chatSettingsSlice.d.ts +1 -1
- package/dist/roomStore/roomsSlice.d.ts +38 -1
- package/dist/styles/classNames.d.ts +2 -0
- package/dist/types/models/config.model.d.ts +11 -0
- package/dist/utils/notificationUtils.d.ts +12 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/public/firebase-messaging-sw.js +21 -3
package/dist/main.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.ethora-chat-root{font-family:var( --ethora-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif );-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ethora-chat-root code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.ethora-chat-root,.ethora-chat-root *{scrollbar-width:thin;scrollbar-color:rgba(20,20,20,.22) transparent;scrollbar-color:var( --ethora-scrollbar-thumb, color-mix(in srgb, var(--ethora-icon-color, #0052cd) 35%, transparent) ) var(--ethora-scrollbar-track, transparent)}.ethora-chat-root::-webkit-scrollbar,.ethora-chat-root ::-webkit-scrollbar{width:8px;height:8px}.ethora-chat-root::-webkit-scrollbar-thumb,.ethora-chat-root ::-webkit-scrollbar-thumb{background-color:#14141438;background-color:var( --ethora-scrollbar-thumb, color-mix(in srgb, var(--ethora-icon-color, #0052cd) 35%, transparent) );border-radius:var(--ethora-radius-full, 999px);border:2px solid transparent;background-clip:content-box}.ethora-chat-root::-webkit-scrollbar-thumb:hover,.ethora-chat-root ::-webkit-scrollbar-thumb:hover{background-color:#14141466;background-color:var( --ethora-scrollbar-thumb-hover, color-mix(in srgb, var(--ethora-icon-color, #0052cd) 60%, transparent) );background-clip:content-box}.ethora-chat-root::-webkit-scrollbar-track,.ethora-chat-root ::-webkit-scrollbar-track{background-color:var(--ethora-scrollbar-track, transparent)}.ethora-apple-emoji{font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif}.ethora-chat-root .emoji-mart{max-width:320px;max-height:360px;overflow-y:auto;border-radius:12px;box-shadow:0 4px 12px #0000001a}.ethora-message-highlight{animation:ethoraMessageHighlight
|
|
1
|
+
.ethora-chat-root{font-family:var( --ethora-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif );-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ethora-chat-root code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.ethora-chat-root,.ethora-chat-root *{scrollbar-width:thin;scrollbar-color:rgba(20,20,20,.22) transparent;scrollbar-color:var( --ethora-scrollbar-thumb, color-mix(in srgb, var(--ethora-icon-color, #0052cd) 35%, transparent) ) var(--ethora-scrollbar-track, transparent)}.ethora-chat-root::-webkit-scrollbar,.ethora-chat-root ::-webkit-scrollbar{width:8px;height:8px}.ethora-chat-root::-webkit-scrollbar-thumb,.ethora-chat-root ::-webkit-scrollbar-thumb{background-color:#14141438;background-color:var( --ethora-scrollbar-thumb, color-mix(in srgb, var(--ethora-icon-color, #0052cd) 35%, transparent) );border-radius:var(--ethora-radius-full, 999px);border:2px solid transparent;background-clip:content-box}.ethora-chat-root::-webkit-scrollbar-thumb:hover,.ethora-chat-root ::-webkit-scrollbar-thumb:hover{background-color:#14141466;background-color:var( --ethora-scrollbar-thumb-hover, color-mix(in srgb, var(--ethora-icon-color, #0052cd) 60%, transparent) );background-clip:content-box}.ethora-chat-root::-webkit-scrollbar-track,.ethora-chat-root ::-webkit-scrollbar-track{background-color:var(--ethora-scrollbar-track, transparent)}.ethora-apple-emoji{font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif}.ethora-chat-root .emoji-mart{max-width:320px;max-height:360px;overflow-y:auto;border-radius:12px;box-shadow:0 4px 12px #0000001a}[data-message-id].ethora-message-highlight{animation:ethoraMessageFlash 1s ease-out;border-radius:var(--ethora-radius-md, 12px)}@keyframes ethoraMessageFlash{0%{background-color:color-mix(in srgb,var(--ethora-color-primary, #0052cd) 35%,transparent)}to{background-color:transparent}}.ethora-message-highlight{animation:ethoraMessageHighlight 1s ease-out;transition:background-color .3s ease}@keyframes ethoraMessageHighlight{0%{background-color:#2196f366;transform:scale(1.02);box-shadow:0 0 0 2px #2196f333}30%{background-color:#2196f34d;box-shadow:0 0 0 2px #2196f326}60%{background-color:#2196f333;box-shadow:0 0 0 1px #2196f31a}to{background-color:transparent;transform:scale(1);box-shadow:none}}@media(max-width:768px){.ethora-message-notification-container{left:50%!important;right:auto!important;transform:translate(-50%)!important;align-items:center!important}.ethora-message-notification-container[data-position-horizontal=left],.ethora-message-notification-container[data-position-horizontal=right]{left:50%!important;right:auto!important;transform:translate(-50%)!important}}
|
package/dist/main.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ba as a, bb as r, bc as b, bd as o, be as t, bf as u, bg as i, bh as p, bi as h, bj as n, bk as l, bl as d, bm as f, L as m, bn as T, bo as g, bp as y, bq as I, br as R, bs as c, bt as k, bu as C, bv as A, ak as E, al as Q, bw as v, bx as F } from "./main-rJpE4hh-.js";
|
|
2
2
|
export {
|
|
3
3
|
a as AuthTestIds,
|
|
4
4
|
r as Chat,
|
|
5
5
|
b as ChatInputTestIds,
|
|
6
6
|
o as MessageBubbleTestIds,
|
|
7
7
|
t as RefreshFatalError,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
u as RoomListTestIds,
|
|
9
|
+
i as XmppProvider,
|
|
10
|
+
p as applyTypography,
|
|
11
11
|
h as clearTypography,
|
|
12
12
|
n as formatFingerprint,
|
|
13
13
|
l as handleQRChatId,
|
|
@@ -25,6 +25,6 @@ export {
|
|
|
25
25
|
A as useQRCodeChat,
|
|
26
26
|
E as useRoomMute,
|
|
27
27
|
Q as useRoomPresence,
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
v as useTypography,
|
|
29
|
+
F as useUnread
|
|
30
30
|
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /v2/apps/{appId}/messages/search: full-text / substring search over
|
|
3
|
+
* the chat archive. For a user token the server restricts it to chats the
|
|
4
|
+
* caller can see, so no client-side filtering is needed for privacy.
|
|
5
|
+
*/
|
|
6
|
+
export interface MessageSearchHit {
|
|
7
|
+
/** The archive row's own id: the only identifier every hit is guaranteed to have. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Room name, the local part of the room JID. */
|
|
10
|
+
chatId: string;
|
|
11
|
+
chatType: string;
|
|
12
|
+
/** Full room JID. */
|
|
13
|
+
room: string;
|
|
14
|
+
/** Sender's full JID, WITH the xmpp host: `appId_userId@xmpp.host`. */
|
|
15
|
+
from: string;
|
|
16
|
+
fromUserId: string;
|
|
17
|
+
body: string;
|
|
18
|
+
messageId: string;
|
|
19
|
+
stanzaId: string;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface MessageSearchPage {
|
|
23
|
+
items: MessageSearchHit[];
|
|
24
|
+
/** Total matches on the server, not the size of this page. */
|
|
25
|
+
total: number;
|
|
26
|
+
offset: number;
|
|
27
|
+
limit: number;
|
|
28
|
+
/**
|
|
29
|
+
* Where the next page starts. Counted in SERVER rows, not in `items`:
|
|
30
|
+
* deleted messages are dropped from `items`, and paging by the filtered
|
|
31
|
+
* count would re-request rows already seen.
|
|
32
|
+
*/
|
|
33
|
+
nextOffset: number;
|
|
34
|
+
}
|
|
35
|
+
export interface SearchMessagesParams {
|
|
36
|
+
q: string;
|
|
37
|
+
/** Room name (local part of the JID). Omit to search every visible chat. */
|
|
38
|
+
chatId?: string;
|
|
39
|
+
/** Only messages from this user (a room member's `_id`). */
|
|
40
|
+
fromUserId?: string;
|
|
41
|
+
/** ISO 8601 bounds; the server rejects anything else. */
|
|
42
|
+
since?: string;
|
|
43
|
+
until?: string;
|
|
44
|
+
limit?: number;
|
|
45
|
+
offset?: number;
|
|
46
|
+
signal?: AbortSignal;
|
|
47
|
+
}
|
|
48
|
+
export declare const MESSAGE_SEARCH_PAGE_SIZE = 20;
|
|
49
|
+
export declare function searchMessages({ q, chatId, fromUserId, since, until, limit, offset, signal, }: SearchMessagesParams): Promise<MessageSearchPage>;
|
|
50
|
+
/**
|
|
51
|
+
* A key that is unique per hit. stanzaId and messageId are NOT: on QA whole
|
|
52
|
+
* pages of older hits come back with both empty, which made every React key
|
|
53
|
+
* `chatId:` (rows were left behind when the list changed) and made a
|
|
54
|
+
* duplicate check by those ids throw real hits away.
|
|
55
|
+
*/
|
|
56
|
+
export declare const hitKey: (hit: MessageSearchHit) => string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** One entry of GET /v1/chats/public: a chat anyone in the app may join. */
|
|
2
|
+
export interface PublicChat {
|
|
3
|
+
/** Room name: the local part of its JID. */
|
|
4
|
+
name: string;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
picture: string;
|
|
8
|
+
e2ee: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface PublicChatsPage {
|
|
11
|
+
items: PublicChat[];
|
|
12
|
+
total: number;
|
|
13
|
+
offset: number;
|
|
14
|
+
limit: number;
|
|
15
|
+
/** Server rows consumed so far, not counting hidden ones. */
|
|
16
|
+
nextOffset: number;
|
|
17
|
+
}
|
|
18
|
+
export declare const PUBLIC_CHATS_PAGE_SIZE = 50;
|
|
19
|
+
export declare function getPublicChats({ offset, limit, signal, }?: {
|
|
20
|
+
offset?: number;
|
|
21
|
+
limit?: number;
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
}): Promise<PublicChatsPage>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function fetchFreshXmppPassword(): Promise<string | null>;
|
|
@@ -38,7 +38,7 @@ export declare const setUser: import('@reduxjs/toolkit').ActionCreatorWithOption
|
|
|
38
38
|
refreshToken: string;
|
|
39
39
|
fileToken?: string;
|
|
40
40
|
xmppPassword?: string;
|
|
41
|
-
}, "chatSettingStore/refreshTokens">, logout: import('@reduxjs/toolkit').ActionCreatorWithoutPayload<"chatSettingStore/logout">, setActiveModal: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string, "chatSettingStore/setActiveModal">, setDeleteModal: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<DeleteModal, "chatSettingStore/setDeleteModal">, setSelectedUser: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<IUser, "chatSettingStore/setSelectedUser">, updateUser: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<{
|
|
41
|
+
}, "chatSettingStore/refreshTokens">, setXmppPassword: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string, "chatSettingStore/setXmppPassword">, logout: import('@reduxjs/toolkit').ActionCreatorWithoutPayload<"chatSettingStore/logout">, setActiveModal: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string, "chatSettingStore/setActiveModal">, setDeleteModal: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<DeleteModal, "chatSettingStore/setDeleteModal">, setSelectedUser: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<IUser, "chatSettingStore/setSelectedUser">, updateUser: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<{
|
|
42
42
|
updates: Partial<User>;
|
|
43
43
|
}, "chatSettingStore/updateUser">, setActiveFile: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<ModalFile, "chatSettingStore/setActiveFile">, setLangSource: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<Iso639_1Codes, "chatSettingStore/setLangSource">, setTranslateSendEnabled: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<boolean, "chatSettingStore/setTranslateSendEnabled">, setTranslateMode: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<"auto" | "manual", "chatSettingStore/setTranslateMode">;
|
|
44
44
|
declare const _default: import('redux').Reducer<ChatState>;
|
|
@@ -16,6 +16,34 @@ import { default as XmppClient } from '../networking/xmppClient';
|
|
|
16
16
|
*/
|
|
17
17
|
export declare const MAX_DRAFT_LENGTH = 2000;
|
|
18
18
|
export declare const MAX_PERSISTED_DRAFTS = 30;
|
|
19
|
+
/** A message found in the archive that the chat cannot show in place. */
|
|
20
|
+
export interface ArchivedMessage {
|
|
21
|
+
roomJID: string;
|
|
22
|
+
sender: string;
|
|
23
|
+
body: string;
|
|
24
|
+
/** ISO timestamp from the archive. */
|
|
25
|
+
createdAt: string;
|
|
26
|
+
}
|
|
27
|
+
/** A request to scroll a room's transcript to one message. */
|
|
28
|
+
export interface PendingJump {
|
|
29
|
+
roomJID: string;
|
|
30
|
+
/** Any id the message may be known by: message id, stanza id, xmpp id. */
|
|
31
|
+
ids: string[];
|
|
32
|
+
/**
|
|
33
|
+
* For a message that has no usable id (search archive rows often carry
|
|
34
|
+
* none): its timestamp and text, matched against the loaded transcript.
|
|
35
|
+
*/
|
|
36
|
+
createdAt?: string;
|
|
37
|
+
body?: string;
|
|
38
|
+
/**
|
|
39
|
+
* What to show if the message cannot be reached in the transcript: the hit
|
|
40
|
+
* itself, so a tap on a search result always ends with the message on
|
|
41
|
+
* screen rather than an error.
|
|
42
|
+
*/
|
|
43
|
+
preview?: ArchivedMessage;
|
|
44
|
+
/** Epoch ms the request was made, to drop one nobody ever fulfilled. */
|
|
45
|
+
at: number;
|
|
46
|
+
}
|
|
19
47
|
interface RoomMessagesState {
|
|
20
48
|
rooms: {
|
|
21
49
|
[jid: string]: IRoom;
|
|
@@ -34,6 +62,9 @@ interface RoomMessagesState {
|
|
|
34
62
|
loadingText?: string;
|
|
35
63
|
roomsLoadedOnce: boolean;
|
|
36
64
|
roomsLoadError: boolean;
|
|
65
|
+
pendingJump: PendingJump | null;
|
|
66
|
+
archivedMessage: ArchivedMessage | null;
|
|
67
|
+
joiningRoomJID: string | null;
|
|
37
68
|
drafts: Record<string, string>;
|
|
38
69
|
}
|
|
39
70
|
interface PreloadRoomUpdate {
|
|
@@ -102,7 +133,13 @@ export declare const addRoom: import('@reduxjs/toolkit').ActionCreatorWithOption
|
|
|
102
133
|
chatJID?: string;
|
|
103
134
|
}, "roomMessages/setRoomNoMessages">, setRoomsLoadResolved: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<{
|
|
104
135
|
success: boolean;
|
|
105
|
-
}, "roomMessages/setRoomsLoadResolved">,
|
|
136
|
+
}, "roomMessages/setRoomsLoadResolved">, requestJumpToMessage: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<{
|
|
137
|
+
roomJID: string;
|
|
138
|
+
ids: string[];
|
|
139
|
+
createdAt?: string;
|
|
140
|
+
body?: string;
|
|
141
|
+
preview?: ArchivedMessage;
|
|
142
|
+
}, "roomMessages/requestJumpToMessage">, clearPendingJump: import('@reduxjs/toolkit').ActionCreatorWithoutPayload<"roomMessages/clearPendingJump">, showArchivedMessage: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<ArchivedMessage, "roomMessages/showArchivedMessage">, clearArchivedMessage: import('@reduxjs/toolkit').ActionCreatorWithoutPayload<"roomMessages/clearArchivedMessage">, setJoiningRoom: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string, "roomMessages/setJoiningRoom">, clearJoiningRoom: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string, "roomMessages/clearJoiningRoom">, setCurrentRoom: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<{
|
|
106
143
|
roomJID: string | null;
|
|
107
144
|
}, "roomMessages/setCurrentRoom">, setMemberOnline: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<{
|
|
108
145
|
roomJID: string;
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
export declare const CHAT_ROOT_CLASS = "ethora-chat-root";
|
|
30
30
|
/** Transient highlight flashed on a message when a notification is opened. */
|
|
31
31
|
export declare const MESSAGE_HIGHLIGHT_CLASS = "ethora-message-highlight";
|
|
32
|
+
/** How long the highlight stays on a message; keep equal to the CSS animation. */
|
|
33
|
+
export declare const HIGHLIGHT_MS = 1000;
|
|
32
34
|
/** Fixed-position container holding the in-app notification toasts. */
|
|
33
35
|
export declare const NOTIFICATION_CONTAINER_CLASS = "ethora-message-notification-container";
|
|
34
36
|
/** Forces the colour-emoji font on nodes that render a bare emoji glyph. */
|
|
@@ -494,6 +494,17 @@ export interface IConfig {
|
|
|
494
494
|
* a presence state, not a count, so it is unaffected.
|
|
495
495
|
*/
|
|
496
496
|
disableUserCount?: boolean;
|
|
497
|
+
/**
|
|
498
|
+
* Hide the "Search messages" button in the chat header (and so the search
|
|
499
|
+
* panel). Search is also hidden when `appId` is not set, since the archive
|
|
500
|
+
* it queries is scoped by app.
|
|
501
|
+
*/
|
|
502
|
+
disableMessageSearch?: boolean;
|
|
503
|
+
/**
|
|
504
|
+
* Hide the "Discover chats" entry of the room list menu, the directory of
|
|
505
|
+
* the app's public chats (GET /v1/chats/public).
|
|
506
|
+
*/
|
|
507
|
+
disablePublicChatsDirectory?: boolean;
|
|
497
508
|
disableSentLogic?: boolean;
|
|
498
509
|
initBeforeLoad?: boolean;
|
|
499
510
|
initBeforeLoadAuth?: {
|
|
@@ -9,6 +9,18 @@ import { PushPayloadLike } from './notificationPolicy';
|
|
|
9
9
|
export declare function showBrowserNotification(title: string, options: NotificationOptions & {
|
|
10
10
|
data?: any;
|
|
11
11
|
}, serviceWorkerScope?: string, onClick?: (event: Event) => void): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Only http(s) URLs and same-origin paths are usable as a notification icon;
|
|
14
|
+
* anything else is dropped rather than handed to the browser.
|
|
15
|
+
*/
|
|
16
|
+
export declare function sanitizeIconUrl(value: unknown): string;
|
|
17
|
+
/**
|
|
18
|
+
* The icon a push asks for: its own icon first (data.icon, notification.icon),
|
|
19
|
+
* then the picture it carries (notification.image, what this used to return
|
|
20
|
+
* unconditionally), then the favicon. The service worker applies the same
|
|
21
|
+
* preference for a backgrounded tab.
|
|
22
|
+
*/
|
|
23
|
+
export declare function pickPushIcon(payload: PushPayloadLike): string;
|
|
12
24
|
/**
|
|
13
25
|
* Helper to extract common data from a message/payload for browser notifications.
|
|
14
26
|
*/
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const ETHORA_CHAT_COMPONENT_VERSION = "26.9.
|
|
1
|
+
export declare const ETHORA_CHAT_COMPONENT_VERSION = "26.9.6";
|
package/package.json
CHANGED
|
@@ -172,8 +172,26 @@ function pickUrl(raw = {}, data = {}, notification = {}) {
|
|
|
172
172
|
);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
// An icon the push itself carries (data.icon, notification.icon or icon on
|
|
176
|
+
// the payload) wins over the one configured for the whole app: a push about a
|
|
177
|
+
// specific chat or sender knows better than the app-wide default. Only http(s)
|
|
178
|
+
// and same-origin paths are accepted; anything else (data:, javascript:, a
|
|
179
|
+
// bare word) is ignored and the configured/default icon is used instead.
|
|
180
|
+
function sanitizeIconUrl(value) {
|
|
181
|
+
const url = typeof value === 'string' ? value.trim() : '';
|
|
182
|
+
if (!url) return '';
|
|
183
|
+
if (url.charAt(0) === '/' && url.charAt(1) !== '/') return url;
|
|
184
|
+
return /^https?:\/\/[^\s]+$/i.test(url) ? url : '';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function pickIcon(raw = {}, data = {}, notification = {}) {
|
|
188
|
+
return (
|
|
189
|
+
sanitizeIconUrl(data.icon) ||
|
|
190
|
+
sanitizeIconUrl(notification.icon) ||
|
|
191
|
+
sanitizeIconUrl(raw.icon) ||
|
|
192
|
+
CUSTOM_ICON ||
|
|
193
|
+
DEFAULT_ICON
|
|
194
|
+
);
|
|
177
195
|
}
|
|
178
196
|
|
|
179
197
|
function pickBadge() {
|
|
@@ -332,7 +350,7 @@ async function handlePush(raw = {}, source = 'push') {
|
|
|
332
350
|
const title = pickTitle(raw, data, notification);
|
|
333
351
|
const body = pickBody(raw, data, notification);
|
|
334
352
|
const url = pickUrl(raw, data, notification);
|
|
335
|
-
const icon = pickIcon();
|
|
353
|
+
const icon = pickIcon(raw, data, notification);
|
|
336
354
|
const badge = pickBadge();
|
|
337
355
|
const image = pickImage(raw, data, notification);
|
|
338
356
|
|