@ethora/chat-component 26.9.5 → 26.9.8
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 -1
- package/dist/{ChatProfileModal-Pr4--RdW.js → ChatProfileModal-3UH0H5Ec.js} +725 -714
- package/dist/{FilePreviewModal-CYHlKzRc.js → FilePreviewModal-Cgj1iHry.js} +161 -161
- package/dist/{ManageDataModal-BE1eGlYh.js → ManageDataModal-BblTuE9g.js} +14 -14
- package/dist/{MarkdownBody-G0_J0NL6.js → MarkdownBody-RMEx8yW2.js} +1 -1
- package/dist/MessageSearchModal-CrYR2EH8.js +381 -0
- package/dist/PublicChatsModal-Bi5r4mrV.js +202 -0
- package/dist/{SideDrawer-BG2m7Bcm.js → SideDrawer-CDAoobvX.js} +34 -34
- package/dist/{UserProfileModal-B2Hp5bAF.js → UserProfileModal-4Frgvam-.js} +3 -3
- package/dist/{UserSettingsModal-D871FDAT.js → UserSettingsModal-C-mb-9cb.js} +2 -2
- package/dist/{VideoCallOverlay-Br0ji0nZ.js → VideoCallOverlay-92dFLb9U.js} +1 -1
- package/dist/{VisibilityModal-DdFBV1_g.js → VisibilityModal-zIAV6dAP.js} +9 -9
- package/dist/assets/icons.d.ts +9 -0
- package/dist/components/InputComponents/MentionDropdown.d.ts +2 -0
- package/dist/components/InputComponents/Search.d.ts +4 -0
- package/dist/components/MainComponents/ArchivedMessageCard.d.ts +11 -0
- package/dist/components/MainComponents/scrollAnchor.d.ts +19 -0
- package/dist/components/MainComponents/useJumpToMessage.d.ts +94 -0
- package/dist/components/MainComponents/useScrollAnchor.d.ts +29 -0
- package/dist/components/MainComponents/useStickToBottom.d.ts +27 -0
- package/dist/components/Modals/MessageSearchModal/MessageHitResults.d.ts +27 -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/Modals/styledModalComponents.d.ts +0 -8
- 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-BtXos0AJ.js} +1 -1
- package/dist/helpers/checkUniqueUsers.d.ts +2 -2
- package/dist/helpers/constants/MODAL_TYPES.d.ts +2 -0
- package/dist/helpers/dedupeMembers.d.ts +10 -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/nanoToMs.d.ts +1 -1
- package/dist/helpers/openRoomAtMessage.d.ts +17 -0
- package/dist/helpers/openThreadForJump.d.ts +26 -0
- package/dist/helpers/pdf/loadPdfjs.d.ts +8 -1
- package/dist/helpers/roomUserCount.d.ts +19 -0
- package/dist/helpers/userResolver.d.ts +57 -0
- package/dist/helpers/xmppIdShape.d.ts +1 -1
- package/dist/hooks/useChatWrapperInit.d.ts +6 -0
- package/dist/hooks/useMessageSearchShortcut.d.ts +14 -0
- package/dist/hooks/usePdfThumbnail.d.ts +2 -1
- package/dist/hooks/useRoomDirectory.d.ts +11 -0
- package/dist/hooks/useRoomState.d.ts +1 -0
- package/dist/{main-BRIZ98KV.js → main-BnLtessp.js} +24764 -21859
- package/dist/main.css +1 -1
- package/dist/main.js +16 -16
- 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/roomMembers.api.d.ts +18 -0
- package/dist/networking/api-requests/xmppToken.api.d.ts +1 -0
- package/dist/networking/ethoraEvents.d.ts +44 -0
- package/dist/networking/stanzaHandlers.d.ts +2 -2
- package/dist/networking/xmpp/allRoomPresences.xmpp.d.ts +18 -1
- package/dist/networking/xmpp/presenceInRoom.xmpp.d.ts +1 -1
- package/dist/networking/xmppClient.d.ts +58 -2
- package/dist/roomStore/Middleware/jumpThreadMiddleware.d.ts +2 -0
- package/dist/roomStore/chatSettingsSlice.d.ts +1 -1
- package/dist/roomStore/index.d.ts +12 -0
- package/dist/roomStore/roomsSlice.d.ts +70 -1
- package/dist/roomStore/safeKey.d.ts +12 -0
- package/dist/roomStore/usersSetCap.d.ts +15 -0
- package/dist/styles/classNames.d.ts +2 -0
- package/dist/types/models/config.model.d.ts +78 -0
- package/dist/types/models/room.model.d.ts +14 -0
- package/dist/types/models/xmpp.model.d.ts +21 -1
- package/dist/utils/notificationUtils.d.ts +12 -0
- package/dist/version.d.ts +1 -1
- package/package.json +2 -1
- package/public/firebase-messaging-sw.js +21 -3
- package/dist/components/Modals/NewChatModal/UpdNewChatModal.d.ts +0 -3
- package/dist/components/SortDropDown/index.d.ts +0 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as i, jsx as o } from "react/jsx-runtime";
|
|
2
2
|
import { useId as f, useRef as v } from "react";
|
|
3
|
-
import { p as u, y as g,
|
|
3
|
+
import { p as u, y as g, aO as m, aV as w, B as b, aW as y, x as e, aX as D, aY as k } from "./main-BnLtessp.js";
|
|
4
4
|
const c = 767, R = `${c}px`, z = e.div`
|
|
5
5
|
position: relative;
|
|
6
6
|
pointer-events: auto;
|
|
@@ -58,11 +58,11 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
58
58
|
padding-left: var(--ethora-space-4, 16px);
|
|
59
59
|
padding-right: var(--ethora-space-4, 16px);
|
|
60
60
|
}
|
|
61
|
-
`,
|
|
61
|
+
`, O = e.section`
|
|
62
62
|
display: flex;
|
|
63
63
|
flex-direction: column;
|
|
64
64
|
gap: var(--ethora-space-2, 8px);
|
|
65
|
-
`,
|
|
65
|
+
`, W = e.h3`
|
|
66
66
|
margin: 0;
|
|
67
67
|
padding: 0 var(--ethora-space-1, 4px);
|
|
68
68
|
font-size: var(--ethora-font-size-xs, 12px);
|
|
@@ -70,7 +70,7 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
70
70
|
letter-spacing: 0.06em;
|
|
71
71
|
text-transform: uppercase;
|
|
72
72
|
color: var(--ethora-color-text-muted, #8c8c8c);
|
|
73
|
-
`,
|
|
73
|
+
`, $ = e.div`
|
|
74
74
|
display: flex;
|
|
75
75
|
flex-direction: column;
|
|
76
76
|
box-sizing: border-box;
|
|
@@ -79,17 +79,17 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
79
79
|
border-radius: var(--ethora-radius-md, 12px);
|
|
80
80
|
background-color: var(--ethora-color-bg, #fff);
|
|
81
81
|
overflow: hidden;
|
|
82
|
-
`,
|
|
82
|
+
`, _ = e.div`
|
|
83
83
|
display: flex;
|
|
84
84
|
flex-direction: column;
|
|
85
85
|
gap: var(--ethora-space-1, 4px);
|
|
86
86
|
padding: var(--ethora-space-3, 12px) var(--ethora-space-4, 16px);
|
|
87
|
-
`,
|
|
87
|
+
`, K = e.div`
|
|
88
88
|
display: flex;
|
|
89
89
|
align-items: baseline;
|
|
90
90
|
justify-content: space-between;
|
|
91
91
|
gap: var(--ethora-space-2, 8px);
|
|
92
|
-
`,
|
|
92
|
+
`, V = e.button`
|
|
93
93
|
border: none;
|
|
94
94
|
background: transparent;
|
|
95
95
|
padding: var(--ethora-space-2, 8px) 0;
|
|
@@ -109,11 +109,11 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
109
109
|
outline-offset: 2px;
|
|
110
110
|
border-radius: var(--ethora-radius-sm, 8px);
|
|
111
111
|
}
|
|
112
|
-
`,
|
|
112
|
+
`, X = e.div`
|
|
113
113
|
height: 1px;
|
|
114
114
|
margin: 0 var(--ethora-space-4, 16px);
|
|
115
115
|
background-color: var(--ethora-color-border, #e6e8ec);
|
|
116
|
-
`,
|
|
116
|
+
`, F = e.div`
|
|
117
117
|
display: flex;
|
|
118
118
|
align-items: center;
|
|
119
119
|
gap: var(--ethora-space-2, 8px);
|
|
@@ -135,7 +135,7 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
135
135
|
& > svg {
|
|
136
136
|
flex: 0 0 auto;
|
|
137
137
|
}
|
|
138
|
-
`,
|
|
138
|
+
`, Y = e.input`
|
|
139
139
|
flex: 1 1 auto;
|
|
140
140
|
min-width: 0;
|
|
141
141
|
border: none;
|
|
@@ -152,18 +152,18 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
152
152
|
display: flex;
|
|
153
153
|
flex-direction: column;
|
|
154
154
|
width: 100%;
|
|
155
|
-
`,
|
|
155
|
+
`, T = e.div`
|
|
156
156
|
font-size: var(--ethora-font-size-sm, 14px);
|
|
157
157
|
font-weight: var(--ethora-font-weight-medium, 500);
|
|
158
158
|
color: var(--ethora-color-text, #141414);
|
|
159
159
|
text-align: start;
|
|
160
|
-
`,
|
|
160
|
+
`, C = e.div`
|
|
161
161
|
font-size: var(--ethora-font-size-xs, 12px);
|
|
162
162
|
font-weight: var(--ethora-font-weight-regular, 400);
|
|
163
163
|
color: var(--ethora-color-text-muted, #8c8c8c);
|
|
164
164
|
text-align: start;
|
|
165
165
|
line-height: 1.4;
|
|
166
|
-
`,
|
|
166
|
+
`, E = e.button`
|
|
167
167
|
display: flex;
|
|
168
168
|
align-items: center;
|
|
169
169
|
gap: var(--ethora-space-3, 12px);
|
|
@@ -186,17 +186,17 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
186
186
|
outline: 2px solid var(--ethora-color-primary, #0052cd);
|
|
187
187
|
outline-offset: -2px;
|
|
188
188
|
}
|
|
189
|
-
`,
|
|
189
|
+
`, L = e.span`
|
|
190
190
|
display: flex;
|
|
191
191
|
flex-direction: column;
|
|
192
192
|
gap: var(--ethora-space-1, 4px);
|
|
193
193
|
flex: 1 1 auto;
|
|
194
194
|
min-width: 0;
|
|
195
|
-
`,
|
|
195
|
+
`, j = e.span`
|
|
196
196
|
flex: 0 0 auto;
|
|
197
197
|
display: inline-flex;
|
|
198
198
|
color: var(--ethora-color-text-muted, #8c8c8c);
|
|
199
|
-
`,
|
|
199
|
+
`, M = () => /* @__PURE__ */ o("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ o(
|
|
200
200
|
"path",
|
|
201
201
|
{
|
|
202
202
|
d: "M6 3.5L10.5 8L6 12.5",
|
|
@@ -209,13 +209,13 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
209
209
|
label: r,
|
|
210
210
|
hint: a,
|
|
211
211
|
onClick: t
|
|
212
|
-
}) => /* @__PURE__ */ i(
|
|
213
|
-
/* @__PURE__ */ i(
|
|
214
|
-
/* @__PURE__ */ o(
|
|
215
|
-
a && /* @__PURE__ */ o(
|
|
212
|
+
}) => /* @__PURE__ */ i(E, { type: "button", onClick: t, children: [
|
|
213
|
+
/* @__PURE__ */ i(L, { children: [
|
|
214
|
+
/* @__PURE__ */ o(T, { children: r }),
|
|
215
|
+
a && /* @__PURE__ */ o(C, { children: a })
|
|
216
216
|
] }),
|
|
217
|
-
/* @__PURE__ */ o(
|
|
218
|
-
] }),
|
|
217
|
+
/* @__PURE__ */ o(j, { "aria-hidden": "true", children: /* @__PURE__ */ o(M, {}) })
|
|
218
|
+
] }), J = ({
|
|
219
219
|
title: r,
|
|
220
220
|
onClose: a,
|
|
221
221
|
headerActions: t,
|
|
@@ -253,18 +253,18 @@ const c = 767, R = `${c}px`, z = e.div`
|
|
|
253
253
|
);
|
|
254
254
|
};
|
|
255
255
|
export {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
256
|
+
O as D,
|
|
257
|
+
J as S,
|
|
258
|
+
W as a,
|
|
259
|
+
$ as b,
|
|
260
|
+
X as c,
|
|
261
261
|
G as d,
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
262
|
+
_ as e,
|
|
263
|
+
C as f,
|
|
264
|
+
T as g,
|
|
265
|
+
K as h,
|
|
266
|
+
F as i,
|
|
267
|
+
Y as j,
|
|
268
268
|
q as k,
|
|
269
|
-
|
|
269
|
+
V as l
|
|
270
270
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsxs as u, Fragment as $, jsx as o } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as ge, useState as I, useCallback as y, useImperativeHandle as ve, useRef as ae, useMemo as M } from "react";
|
|
3
|
-
import { a as be, p as J, t as ye, v as xe, w as we, P as re, I as H, x as D, y as Ce, z as Se, C as Ie, D as te, E as De, F as Ne, G as ke, J as Ue, u as Q, K as Fe, L as Pe, N as Ae, O as Re, Q as Y, q as Z, R as ze, S as je, T as Be, s as $e, B as X, U as Ee, W as Oe, X as Te, Y as ee, Z as R, _ as Le, $ as Me, V as He, A as Xe, a0 as We, a1 as Je, a2 as Ke, a3 as Ve } from "./main-
|
|
4
|
-
import { D as E, a as W, b as Ge, e as qe, f as _e, S as Qe } from "./SideDrawer-
|
|
5
|
-
import { P as ne, a as Ye, D as Ze, b as eo, h as oo } from "./handleCopyClick-
|
|
3
|
+
import { a as be, p as J, t as ye, v as xe, w as we, P as re, I as H, x as D, y as Ce, z as Se, C as Ie, D as te, E as De, F as Ne, G as ke, J as Ue, u as Q, K as Fe, L as Pe, N as Ae, O as Re, Q as Y, q as Z, R as ze, S as je, T as Be, s as $e, B as X, U as Ee, W as Oe, X as Te, Y as ee, Z as R, _ as Le, $ as Me, V as He, A as Xe, a0 as We, a1 as Je, a2 as Ke, a3 as Ve } from "./main-BnLtessp.js";
|
|
4
|
+
import { D as E, a as W, b as Ge, e as qe, f as _e, S as Qe } from "./SideDrawer-CDAoobvX.js";
|
|
5
|
+
import { P as ne, a as Ye, D as Ze, b as eo, h as oo } from "./handleCopyClick-BtXos0AJ.js";
|
|
6
6
|
const ao = (c, i) => {
|
|
7
7
|
const l = atob(c.split(",")[1]), g = new ArrayBuffer(l.length), e = new Uint8Array(g);
|
|
8
8
|
for (let r = 0; r < l.length; r++)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as i, jsxs as r } from "react/jsx-runtime";
|
|
2
2
|
import m, { useCallback as D, useMemo as h } from "react";
|
|
3
|
-
import { p, a as g, q as w, M as l } from "./main-
|
|
4
|
-
import { S as b, D as u, a as k, b as y, c as S, d as f } from "./SideDrawer-
|
|
3
|
+
import { p, a as g, q as w, M as l } from "./main-BnLtessp.js";
|
|
4
|
+
import { S as b, D as u, a as k, b as y, c as S, d as f } from "./SideDrawer-CDAoobvX.js";
|
|
5
5
|
const T = ({
|
|
6
6
|
handleCloseModal: n
|
|
7
7
|
}) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs as K, jsx as x, Fragment as Hr } from "react/jsx-runtime";
|
|
2
2
|
import * as F from "react";
|
|
3
3
|
import { useState as Yt, useRef as ke, useEffect as be, useMemo as Wt, useCallback as mi } from "react";
|
|
4
|
-
import { u as Xi, P as Kn, H as xi, a as Hd, b as zd, c as Kd, d as Gd, s as po, e as Jd, f as Yd, g as fo, h as $d, i as Xd, j as mo, k as Qd, l as Zd, r as go, m as eu, n as tu, A as vo, V as bo, B as nu } from "./main-
|
|
4
|
+
import { u as Xi, P as Kn, H as xi, a as Hd, b as zd, c as Kd, d as Gd, s as po, e as Jd, f as Yd, g as fo, h as $d, i as Xd, j as mo, k as Qd, l as Zd, r as go, m as eu, n as tu, A as vo, V as bo, B as nu } from "./main-BnLtessp.js";
|
|
5
5
|
function iu(n, e) {
|
|
6
6
|
return e.forEach(function(t) {
|
|
7
7
|
t && typeof t != "string" && !Array.isArray(t) && Object.keys(t).forEach(function(i) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs as r, jsx as s } from "react/jsx-runtime";
|
|
2
2
|
import { useState as b, useEffect as x } from "react";
|
|
3
|
-
import { x as o, a as L, p as
|
|
4
|
-
import { S as
|
|
3
|
+
import { x as o, a as L, p as N, u as P, aM as D, aN as z } from "./main-BnLtessp.js";
|
|
4
|
+
import { S as I, D as C, a as $, b as k, e as w, f as p } from "./SideDrawer-CDAoobvX.js";
|
|
5
5
|
o.div``;
|
|
6
6
|
o.div`
|
|
7
7
|
font-size: 16px;
|
|
@@ -25,7 +25,7 @@ const O = o.div`
|
|
|
25
25
|
`, u = o.input`
|
|
26
26
|
accent-color: ${({ $radioColor: i }) => i || "var(--ethora-color-primary, #0052CD)"};
|
|
27
27
|
margin: 0px;
|
|
28
|
-
`,
|
|
28
|
+
`, M = o.div`
|
|
29
29
|
padding: 10px 15px;
|
|
30
30
|
margin-top: 16px;
|
|
31
31
|
color: ${({ type: i }) => i === "success" ? "#10b981" : "#ef4444"};
|
|
@@ -39,12 +39,12 @@ const O = o.div`
|
|
|
39
39
|
background: ${({ type: i }) => i === "success" ? "rgba(16, 185, 129, 0.15)" : "rgba(242, 118, 107, 0.15)"};
|
|
40
40
|
border-color: ${({ type: i }) => i === "success" ? "var(--ethora-color-success, #10b981)" : "var(--ethora-color-danger, #ef4444)"};
|
|
41
41
|
}
|
|
42
|
-
`,
|
|
42
|
+
`, B = ({
|
|
43
43
|
handleCloseModal: i
|
|
44
44
|
}) => {
|
|
45
|
-
const S = L(), e =
|
|
45
|
+
const S = L(), e = N(), { user: n, config: l } = P(
|
|
46
46
|
(t) => t.chatSettingStore
|
|
47
|
-
), g = (t) => S(
|
|
47
|
+
), g = (t) => S(z(t)), [a, m] = b(n?.isProfileOpen), [c, v] = b(n?.isAssetsOpen), [f, y] = b(null), d = (t, A) => {
|
|
48
48
|
y({ message: t, type: A }), setTimeout(() => y(null), 3e3);
|
|
49
49
|
};
|
|
50
50
|
return x(() => {
|
|
@@ -56,7 +56,7 @@ const O = o.div`
|
|
|
56
56
|
g(t.user), d(e("notification.saved"), "success");
|
|
57
57
|
}).catch(() => d(e("toast.error"), "error"));
|
|
58
58
|
}, [c]), /* @__PURE__ */ r(
|
|
59
|
-
|
|
59
|
+
I,
|
|
60
60
|
{
|
|
61
61
|
title: e("settings.visibility.title"),
|
|
62
62
|
onClose: i,
|
|
@@ -128,11 +128,11 @@ const O = o.div`
|
|
|
128
128
|
/* @__PURE__ */ s(p, { children: e("settings.visibility.individualDescription") })
|
|
129
129
|
] }) }) })
|
|
130
130
|
] }),
|
|
131
|
-
f && /* @__PURE__ */ s(
|
|
131
|
+
f && /* @__PURE__ */ s(M, { type: f.type, children: f.message })
|
|
132
132
|
]
|
|
133
133
|
}
|
|
134
134
|
);
|
|
135
135
|
};
|
|
136
136
|
export {
|
|
137
|
-
|
|
137
|
+
B as default
|
|
138
138
|
};
|
package/dist/assets/icons.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A compass: "discover". Deliberately not the globe, which is the language
|
|
3
|
+
* selector's icon in the chat header, so the two buttons read as different
|
|
4
|
+
* things when they sit next to each other.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DiscoverIcon: ({ color, ...props }: {
|
|
7
|
+
[x: string]: any;
|
|
8
|
+
color?: string;
|
|
9
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
1
10
|
export declare const GlobeIcon: ({ color, ...props }: {
|
|
2
11
|
[x: string]: any;
|
|
3
12
|
color?: string;
|
|
@@ -8,6 +8,8 @@ interface MentionDropdownProps {
|
|
|
8
8
|
onSelect: (candidate: MentionCandidate) => void;
|
|
9
9
|
onShowAll: () => void;
|
|
10
10
|
onHoverIndex: (index: number) => void;
|
|
11
|
+
/** More people are still being loaded in the background. */
|
|
12
|
+
loading?: boolean;
|
|
11
13
|
}
|
|
12
14
|
export declare const MentionDropdown: React.FC<MentionDropdownProps>;
|
|
13
15
|
export default MentionDropdown;
|
|
@@ -4,6 +4,10 @@ interface SearchInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
|
4
4
|
animated?: boolean;
|
|
5
5
|
direction?: 'left' | 'right';
|
|
6
6
|
colorBg?: string;
|
|
7
|
+
/** When set, a clear button shows while the input has text. */
|
|
8
|
+
onClear?: () => void;
|
|
9
|
+
/** Accessible label for the clear button (pass a translated string). */
|
|
10
|
+
clearLabel?: string;
|
|
7
11
|
}
|
|
8
12
|
declare const SearchInput: React.FC<SearchInputProps>;
|
|
9
13
|
export { SearchInput };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The message a search hit points at, shown when the transcript cannot reach
|
|
4
|
+
* it (the search archive is deeper than the chat's own history). It sits over
|
|
5
|
+
* the conversation of the room it came from, so it needs no navigation and
|
|
6
|
+
* says what the message is instead of reporting that it was not found.
|
|
7
|
+
*/
|
|
8
|
+
declare const ArchivedMessageCard: React.FC<{
|
|
9
|
+
roomJID: string;
|
|
10
|
+
}>;
|
|
11
|
+
export default ArchivedMessageCard;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface AnchorRowRect {
|
|
2
|
+
id: string;
|
|
3
|
+
top: number;
|
|
4
|
+
bottom: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ScrollAnchor {
|
|
7
|
+
id: string;
|
|
8
|
+
/** Row top relative to the scroller's top edge. */
|
|
9
|
+
offset: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The row to hold still while content changes around it: the first row that
|
|
13
|
+
* is fully inside the viewport, or, when none is (a row taller than the
|
|
14
|
+
* viewport, or the viewport cuts every row), the first one that intersects it.
|
|
15
|
+
* `rows` must be in document order.
|
|
16
|
+
*/
|
|
17
|
+
export declare function pickAnchorRow(viewTop: number, viewBottom: number, rows: AnchorRowRect[]): ScrollAnchor | null;
|
|
18
|
+
/** How far scrollTop must move for the anchor row to sit at its old offset. */
|
|
19
|
+
export declare function anchorScrollDelta(anchor: ScrollAnchor, rowTop: number, viewTop: number): number;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { MutableRefObject, RefObject } from 'react';
|
|
2
|
+
import { PendingJump } from '../../roomStore/roomsSlice';
|
|
3
|
+
import { IMessage } from '../../types/types';
|
|
4
|
+
import { findMessageIndex } from '../../helpers/jumpThread';
|
|
5
|
+
export { findMessageIndex };
|
|
6
|
+
export declare const NEAR_LIVE_MESSAGES = 300;
|
|
7
|
+
/**
|
|
8
|
+
* How the attempt to open a window around the target went:
|
|
9
|
+
* - found: the window is in the store; the list now renders it;
|
|
10
|
+
* - missing: the server answered and the target is not in its archive;
|
|
11
|
+
* - unavailable: could not ask (no archive id, request failed): page instead.
|
|
12
|
+
*/
|
|
13
|
+
export type WindowFetchResult = 'found' | 'missing' | 'unavailable';
|
|
14
|
+
/** What the server said about one page of older history. */
|
|
15
|
+
export interface OlderPage {
|
|
16
|
+
/** False when the request failed or timed out. */
|
|
17
|
+
ok: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The RSM `<first>` of the page: the id (microseconds) of the oldest ROW the
|
|
20
|
+
* server returned. The next page continues from here. It is NOT the oldest
|
|
21
|
+
* message that got displayed: a page can be made entirely of reactions,
|
|
22
|
+
* system rows or deleted messages, display nothing, and still be followed
|
|
23
|
+
* by plenty of history.
|
|
24
|
+
*/
|
|
25
|
+
cursor?: number | null;
|
|
26
|
+
/** The server's `<fin complete>`: there is nothing older. */
|
|
27
|
+
complete?: boolean;
|
|
28
|
+
}
|
|
29
|
+
interface Options {
|
|
30
|
+
roomJID: string;
|
|
31
|
+
/** The room's messages, in display order. */
|
|
32
|
+
messages: IMessage[];
|
|
33
|
+
/** How many of them are currently mounted (the newest N). */
|
|
34
|
+
visibleCount: number;
|
|
35
|
+
setRenderWindow: (size: number) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Fetches the next page of older history by MAM and resolves once that page
|
|
38
|
+
* is in the store, with the server's own cursor for what it returned.
|
|
39
|
+
*/
|
|
40
|
+
fetchOlderPage: (roomJID: string, before: number, max: number) => Promise<OlderPage>;
|
|
41
|
+
containerRef: RefObject<HTMLElement>;
|
|
42
|
+
historyComplete?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* MessageList's "reader is away from the bottom" flag. Set for the length of
|
|
45
|
+
* a jump: paging older history grows the message count, and with the flag
|
|
46
|
+
* false the list reads that as new messages arriving and scrolls to the
|
|
47
|
+
* bottom, undoing the jump the moment the target loads.
|
|
48
|
+
*/
|
|
49
|
+
isUserScrolledUpRef: MutableRefObject<boolean>;
|
|
50
|
+
/** `messages` is a jump window around an earlier target, not the live list. */
|
|
51
|
+
jumpWindowActive?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Opens a window around a far target (and puts it in the store). Omitted
|
|
54
|
+
* where windows do not apply (threads); the paging path is used then.
|
|
55
|
+
*/
|
|
56
|
+
fetchWindow?: (jump: PendingJump) => Promise<WindowFetchResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Which list this instance is. A jump is fulfilled by exactly one list: the
|
|
59
|
+
* main list, or the thread its target is a reply in. The other instances
|
|
60
|
+
* stay inert for it, so one of them cannot give up (and show the archived
|
|
61
|
+
* card) while the owner is still working.
|
|
62
|
+
*/
|
|
63
|
+
scope?: 'main' | {
|
|
64
|
+
threadId: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* The room's messages BEFORE the main list's filter (which hides thread
|
|
68
|
+
* replies). Lets the main list recognise a target that is a thread reply.
|
|
69
|
+
*/
|
|
70
|
+
allMessages?: IMessage[];
|
|
71
|
+
/**
|
|
72
|
+
* Opens the thread a reply target belongs to (main list only). Resolves true
|
|
73
|
+
* when the thread is open and owns the jump from now on.
|
|
74
|
+
*/
|
|
75
|
+
resolveReply?: (jump: PendingJump, reply: IMessage) => Promise<boolean>;
|
|
76
|
+
/**
|
|
77
|
+
* The room is still opening (joining, loading its first history). While it
|
|
78
|
+
* is, a request that cannot be answered yet is waited out, not counted as a
|
|
79
|
+
* failure: the card is for "the server answered and the message is absent".
|
|
80
|
+
*/
|
|
81
|
+
roomOpening?: boolean;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Fulfils a pending "scroll to this message" request for this room.
|
|
85
|
+
*
|
|
86
|
+
* The target can be in one of three places, tried in this order:
|
|
87
|
+
* 1. mounted: scroll to it and flash it;
|
|
88
|
+
* 2. in the store but older than the render window: widen the window to
|
|
89
|
+
* include it, then scroll;
|
|
90
|
+
* 3. not loaded at all: page older history from the server until it shows
|
|
91
|
+
* up, bounded by MAX_HISTORY_PAGES and by the end of the archive.
|
|
92
|
+
* If it cannot be reached, say so rather than leaving the tap looking dead.
|
|
93
|
+
*/
|
|
94
|
+
export declare function useJumpToMessage({ roomJID, messages, visibleCount, setRenderWindow, fetchOlderPage, containerRef, historyComplete, isUserScrolledUpRef, jumpWindowActive, fetchWindow, scope, allMessages, resolveReply, roomOpening, }: Options): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
/** The reader counts as still after this long without scrolling. */
|
|
3
|
+
export declare const ANCHOR_IDLE_MS = 100;
|
|
4
|
+
interface Options {
|
|
5
|
+
containerRef: RefObject<HTMLElement>;
|
|
6
|
+
/** The element whose height changes as rows grow. */
|
|
7
|
+
flowRef: RefObject<HTMLElement>;
|
|
8
|
+
/** Identity changes whenever the mounted rows can change. */
|
|
9
|
+
rows: unknown;
|
|
10
|
+
/** True when the reader follows the bottom: nothing is anchored then. */
|
|
11
|
+
isStuckToBottom: () => boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Keeps the rows the reader is looking at perfectly still while content is
|
|
15
|
+
* added or resized above or below them (older history prepended, a jump
|
|
16
|
+
* window paged either way, the render window widened, rows trimmed).
|
|
17
|
+
*
|
|
18
|
+
* - Just before a commit that can change the rows, the anchor is captured from
|
|
19
|
+
* the live DOM (the render phase still sees the previous layout).
|
|
20
|
+
* - The layout effect puts it back before paint, by the anchor ROW's own
|
|
21
|
+
* movement, so a row that gained a date divider or header is absorbed too.
|
|
22
|
+
* - Rows keep changing height after a commit (images, embeds, waveforms).
|
|
23
|
+
* Whenever the content resizes and the reader has been still for
|
|
24
|
+
* ANCHOR_IDLE_MS, the anchor is re-applied by a ResizeObserver. The anchor
|
|
25
|
+
* is re-taken ANCHOR_IDLE_MS after any scroll this hook did not make (the
|
|
26
|
+
* reader, a jump) and dropped while that scroll is going on.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useScrollAnchor({ containerRef, flowRef, rows, isStuckToBottom, }: Options): void;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MutableRefObject, RefObject } from 'react';
|
|
2
|
+
interface Options {
|
|
3
|
+
/** The scrolling element. */
|
|
4
|
+
containerRef: RefObject<HTMLElement>;
|
|
5
|
+
/** The element that grows as messages, images and history arrive. */
|
|
6
|
+
contentRef: RefObject<HTMLElement>;
|
|
7
|
+
/** MessageList's "the reader is away from the bottom" flag. */
|
|
8
|
+
isUserScrolledUpRef: MutableRefObject<boolean>;
|
|
9
|
+
/** An unread delimiter means the list opens ON it, not at the bottom. */
|
|
10
|
+
hasUnreadDelimiter: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Keeps a transcript pinned to the bottom while it is still filling in.
|
|
14
|
+
*
|
|
15
|
+
* Opening a room scrolls to the bottom once, and then the room keeps
|
|
16
|
+
* growing: history pages arrive (prepended above), images and embeds finish
|
|
17
|
+
* sizing. The scrollTop stays where it was, so the reader is left hundreds of
|
|
18
|
+
* pixels above the newest message (measured 1477px, and it stayed there),
|
|
19
|
+
* looking at the middle of the conversation for no visible reason.
|
|
20
|
+
*
|
|
21
|
+
* So: whenever the content's height changes and the reader has not scrolled
|
|
22
|
+
* away, go back to the bottom. A reader who has scrolled up (which also
|
|
23
|
+
* covers a jump to a message, and paging older history by scrolling up) is
|
|
24
|
+
* left exactly where they are.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useStickToBottom({ containerRef, contentRef, isUserScrolledUpRef, hasUnreadDelimiter, }: Options): void;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { MessageSearchHit } from '../../../networking/api-requests/messageSearch.api';
|
|
3
|
+
/**
|
|
4
|
+
* Secondary pill button used for "Show more" and "Retry" under search
|
|
5
|
+
* results, in the search panel and in the room list.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SecondaryPillButton: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
8
|
+
/**
|
|
9
|
+
* What a tap on a search hit does, shared by the search panel and the room
|
|
10
|
+
* list's search box: switch to the hit's room and ask it to scroll to, load
|
|
11
|
+
* and flash the message.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useMessageHitActions(): {
|
|
14
|
+
rooms: any;
|
|
15
|
+
senderName: (hit: MessageSearchHit) => string;
|
|
16
|
+
open: (hit: MessageSearchHit) => boolean;
|
|
17
|
+
isReachable: (hit: MessageSearchHit) => boolean;
|
|
18
|
+
};
|
|
19
|
+
interface MessageHitListProps {
|
|
20
|
+
hits: MessageSearchHit[];
|
|
21
|
+
query: string;
|
|
22
|
+
/** Prefix each row with its chat's title (search across chats). */
|
|
23
|
+
showRoom: boolean;
|
|
24
|
+
onOpen: (hit: MessageSearchHit) => void;
|
|
25
|
+
}
|
|
26
|
+
export declare const MessageHitList: React.FC<MessageHitListProps>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
interface PersonLike {
|
|
2
|
+
_id?: string;
|
|
3
|
+
id?: string;
|
|
4
|
+
firstName?: string;
|
|
5
|
+
lastName?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
xmppUsername?: string;
|
|
8
|
+
}
|
|
9
|
+
/** `appId_userId@xmpp.host` (or without the host) -> `appId_userId`. */
|
|
10
|
+
export declare const localPart: (jid?: string) => string;
|
|
11
|
+
interface Sources {
|
|
12
|
+
/** rooms.usersSet: keyed by `appId_userId`. */
|
|
13
|
+
usersSet?: Record<string, PersonLike>;
|
|
14
|
+
/** The hit's room members, which carry the user id search reports. */
|
|
15
|
+
members?: PersonLike[];
|
|
16
|
+
myXmppUsername?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Who sent a search hit.
|
|
20
|
+
*
|
|
21
|
+
* `from` arrives as a full JID with the XMPP host on it, while usersSet is
|
|
22
|
+
* keyed by the local part, so looking it up as-is found nobody and every hit
|
|
23
|
+
* was attributed to "Someone". The user id (`fromUserId`) is the other way
|
|
24
|
+
* in: room members carry it as `_id`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveSender(hit: {
|
|
27
|
+
from: string;
|
|
28
|
+
fromUserId: string;
|
|
29
|
+
}, { usersSet, members, myXmppUsername }: Sources): {
|
|
30
|
+
name: string;
|
|
31
|
+
isSelf: boolean;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface SearchFilters {
|
|
2
|
+
/** Sender's user id (a room member's `_id`). */
|
|
3
|
+
fromUserId?: string;
|
|
4
|
+
/** ISO 8601 instant: start of the chosen day, in the reader's time zone. */
|
|
5
|
+
since?: string;
|
|
6
|
+
/** ISO 8601 instant: end of the chosen day, in the reader's time zone. */
|
|
7
|
+
until?: string;
|
|
8
|
+
}
|
|
9
|
+
/** `2026-07-14` -> that day's first instant in the reader's time zone. */
|
|
10
|
+
export declare function dayStartISO(day: string): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The day's LAST instant, not just the date. The server reads a bare date in
|
|
13
|
+
* `until` as midnight at the START of that day, so passing "2026-07-14"
|
|
14
|
+
* silently excluded the whole day the reader picked (measured on QA: 329
|
|
15
|
+
* hits with the bare date against 340 with the end of the day).
|
|
16
|
+
*/
|
|
17
|
+
export declare function dayEndISO(day: string): string | undefined;
|
|
18
|
+
/** True when both days are set and the range runs backwards. */
|
|
19
|
+
export declare const isBackwardsRange: (from: string, to: string) => boolean;
|
|
20
|
+
export interface Person {
|
|
21
|
+
_id?: string;
|
|
22
|
+
firstName?: string;
|
|
23
|
+
lastName?: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Up to `limit` people whose name contains `needle`, best matches first
|
|
28
|
+
* (a name that STARTS with it ranks above one that merely contains it).
|
|
29
|
+
* Rooms here have thousands of members, so this never renders them all.
|
|
30
|
+
*/
|
|
31
|
+
export declare function matchPeople(people: Iterable<Person>, needle: string, limit?: number): {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
}[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SnippetPart {
|
|
2
|
+
text: string;
|
|
3
|
+
match: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The part of a message worth showing for a hit: a window around the first
|
|
7
|
+
* match, cut on word boundaries with ellipses, split into matching and
|
|
8
|
+
* non-matching runs so the caller can emphasise the match.
|
|
9
|
+
*
|
|
10
|
+
* Plain substring, case-insensitive, like the server's default mode. The
|
|
11
|
+
* query is never used as a regular expression, so `.` or `(` in it are just
|
|
12
|
+
* characters.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildSnippet(body: string, query: string): SnippetPart[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SearchFilters } from './searchFilters';
|
|
2
|
+
import { MessageSearchHit } from '../../../networking/api-requests/messageSearch.api';
|
|
3
|
+
export declare const MIN_QUERY_LENGTH = 2;
|
|
4
|
+
export type SearchScope = 'chat' | 'all';
|
|
5
|
+
/**
|
|
6
|
+
* Debounced, cancellable message search with paging.
|
|
7
|
+
*
|
|
8
|
+
* A newer query (or scope) aborts the request in flight, and a response that
|
|
9
|
+
* arrives after it was superseded is dropped, so a slow answer to "he" can
|
|
10
|
+
* never overwrite the results for "hello".
|
|
11
|
+
*/
|
|
12
|
+
export declare function useMessageSearch(query: string, scope: SearchScope, roomName?: string, filters?: SearchFilters): {
|
|
13
|
+
searchable: boolean;
|
|
14
|
+
hasMore: boolean;
|
|
15
|
+
loadMore: () => void;
|
|
16
|
+
retry: () => any;
|
|
17
|
+
status: "idle" | "loading" | "loadingMore" | "done" | "error";
|
|
18
|
+
items: MessageSearchHit[];
|
|
19
|
+
total: number;
|
|
20
|
+
/** Server rows consumed so far: the offset of the next page. */
|
|
21
|
+
nextOffset: number;
|
|
22
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
interface PublicChatsModalProps {
|
|
3
|
+
handleCloseModal: () => void;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* A directory of the app's public chats (GET /v1/chats/public), so finding a
|
|
7
|
+
* chat to join no longer needs someone to hand over a link or a QR code.
|
|
8
|
+
*
|
|
9
|
+
* Joining reuses what a shared link already does: selecting a room you are
|
|
10
|
+
* not in makes the room initialiser join it and refresh the room list.
|
|
11
|
+
*/
|
|
12
|
+
declare const PublicChatsModal: React.FC<PublicChatsModalProps>;
|
|
13
|
+
export default PublicChatsModal;
|