@linktr.ee/messaging-react 1.26.0 → 1.26.1-rc-1776055454
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Preview-DqAv16NS.js +87 -0
- package/dist/Preview-DqAv16NS.js.map +1 -0
- package/dist/dash.all.min-Duv4lvGS.js +18858 -0
- package/dist/dash.all.min-Duv4lvGS.js.map +1 -0
- package/dist/hls-Bogc7CBn.js +21710 -0
- package/dist/hls-Bogc7CBn.js.map +1 -0
- package/dist/index-Da-xN4Yq.js +16142 -0
- package/dist/index-Da-xN4Yq.js.map +1 -0
- package/dist/index-Dj9rqWcU.js +69 -0
- package/dist/index-Dj9rqWcU.js.map +1 -0
- package/dist/index.d.ts +60 -9
- package/dist/index.js +1766 -1181
- package/dist/index.js.map +1 -1
- package/dist/mixin-B6jYfIcp.js +808 -0
- package/dist/mixin-B6jYfIcp.js.map +1 -0
- package/dist/react-BxlQMOfz.js +419 -0
- package/dist/react-BxlQMOfz.js.map +1 -0
- package/dist/react-COAP-MIW.js +377 -0
- package/dist/react-COAP-MIW.js.map +1 -0
- package/dist/react-Cn4WlMcl.js +3108 -0
- package/dist/react-Cn4WlMcl.js.map +1 -0
- package/dist/react-CwTJArKY.js +459 -0
- package/dist/react-CwTJArKY.js.map +1 -0
- package/dist/react-DkfS_atT.js +373 -0
- package/dist/react-DkfS_atT.js.map +1 -0
- package/dist/react-Pea5fum1.js +286 -0
- package/dist/react-Pea5fum1.js.map +1 -0
- package/dist/react-RiBbsUDd.js +534 -0
- package/dist/react-RiBbsUDd.js.map +1 -0
- package/dist/react-dS1WBxxz.js +238 -0
- package/dist/react-dS1WBxxz.js.map +1 -0
- package/package.json +2 -1
- package/src/components/ChannelView.test.tsx +50 -1
- package/src/components/ChannelView.tsx +13 -3
- package/src/components/CustomMessage/CustomMessage.stories.tsx +61 -2
- package/src/components/CustomMessage/MessageTag.tsx +5 -0
- package/src/components/CustomMessage/index.tsx +46 -4
- package/src/components/LockedAttachmentCard/LockedAttachmentCard.stories.tsx +351 -0
- package/src/components/LockedAttachmentCard/index.tsx +378 -0
- package/src/components/LockedAttachmentCard/mimeType.test.ts +97 -0
- package/src/components/LockedAttachmentCard/mimeType.ts +35 -0
- package/src/index.ts +4 -0
- package/src/stream-custom-data.ts +10 -3
- package/src/types.ts +15 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
var D = Object.defineProperty;
|
|
2
|
+
var P = (t) => {
|
|
3
|
+
throw TypeError(t);
|
|
4
|
+
};
|
|
5
|
+
var F = (t, i, e) => i in t ? D(t, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[i] = e;
|
|
6
|
+
var L = (t, i, e) => F(t, typeof i != "symbol" ? i + "" : i, e), N = (t, i, e) => i.has(t) || P("Cannot " + e);
|
|
7
|
+
var $ = (t, i, e) => (N(t, i, "read from private field"), e ? e.call(t) : i.get(t)), A = (t, i, e) => i.has(t) ? P("Cannot add the same private member more than once") : i instanceof WeakSet ? i.add(t) : i.set(t, e), C = (t, i, e, s) => (N(t, i, "write to private field"), s ? s.call(t, e) : i.set(t, e), e);
|
|
8
|
+
import W from "react";
|
|
9
|
+
import { M as U, C as I } from "./mixin-B6jYfIcp.js";
|
|
10
|
+
var M;
|
|
11
|
+
class k extends U(I) {
|
|
12
|
+
constructor() {
|
|
13
|
+
super(...arguments);
|
|
14
|
+
A(this, M);
|
|
15
|
+
}
|
|
16
|
+
attributeChangedCallback(e, s, n) {
|
|
17
|
+
e !== "src" && super.attributeChangedCallback(e, s, n), e === "src" && s != n && this.load();
|
|
18
|
+
}
|
|
19
|
+
async _initThumbnails(e) {
|
|
20
|
+
const s = async (d, v) => {
|
|
21
|
+
const g = [], h = e.timescale || 1, E = e.startNumber || 1, S = e.presentationTimeOffset ? e.presentationTimeOffset / h : 0, m = e.segmentDuration;
|
|
22
|
+
for (let b = 0; b < d; b++) {
|
|
23
|
+
const y = K({
|
|
24
|
+
thIndex: b,
|
|
25
|
+
thduration: v,
|
|
26
|
+
ttiles: d,
|
|
27
|
+
tduration: m,
|
|
28
|
+
startNumber: E,
|
|
29
|
+
pto: S
|
|
30
|
+
}), _ = y + v, f = new Promise((w, a) => {
|
|
31
|
+
this.api.provideThumbnail(y, ({ url: r, width: l, height: p, x: T, y: O }) => {
|
|
32
|
+
try {
|
|
33
|
+
const R = new VTTCue(
|
|
34
|
+
y,
|
|
35
|
+
_,
|
|
36
|
+
`${r}#xywh=${T},${O},${l},${p}`
|
|
37
|
+
);
|
|
38
|
+
w(R);
|
|
39
|
+
} catch (R) {
|
|
40
|
+
a(R);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
g.push(f);
|
|
45
|
+
}
|
|
46
|
+
return await Promise.all(g).catch((b) => console.error("Error processing thumbnails", b));
|
|
47
|
+
}, { totalThumbnails: n, thumbnailDuration: o } = j(e), u = await s(n, o);
|
|
48
|
+
let c = this.nativeEl.querySelector('track[label="thumbnails"]');
|
|
49
|
+
if (!c) {
|
|
50
|
+
c = q(), this.nativeEl.appendChild(c);
|
|
51
|
+
const d = z(u);
|
|
52
|
+
c.src = d, c.dispatchEvent(new Event("change"));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async load() {
|
|
56
|
+
if ($(this, M)) {
|
|
57
|
+
this.api.attachSource(this.src);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
C(this, M, !0);
|
|
61
|
+
const e = await import("./dash.all.min-Duv4lvGS.js");
|
|
62
|
+
this.api = e.MediaPlayer().create(), this.api.initialize(this.nativeEl, this.src, this.autoplay), this.api.on(e.MediaPlayer.events.STREAM_INITIALIZED, () => {
|
|
63
|
+
const s = this.api.getRepresentationsByType("video");
|
|
64
|
+
let n = this.videoTracks.getTrackById("main");
|
|
65
|
+
n || (n = this.addVideoTrack("main"), n.id = "main", n.selected = !0), s.forEach((o) => {
|
|
66
|
+
const u = o.bandwidth ?? o.bitrate ?? (Number.isFinite(o.bitrateInKbit) ? o.bitrateInKbit * 1e3 : void 0), c = n.addRendition(o.id, o.width, o.height, o.mimeType ?? o.codec, u);
|
|
67
|
+
c.id = o.id;
|
|
68
|
+
}), this.videoRenditions.addEventListener("change", () => {
|
|
69
|
+
const o = this.videoRenditions[this.videoRenditions.selectedIndex];
|
|
70
|
+
o != null && o.id ? (this.api.updateSettings({ streaming: { abr: { autoSwitchBitrate: { video: !1 } } } }), this.api.setRepresentationForTypeById("video", o.id, !0)) : this.api.updateSettings({ streaming: { abr: { autoSwitchBitrate: { video: !0 } } } });
|
|
71
|
+
}), this.api.isDynamic() || this.api.getRepresentationsByType("image").forEach(async (u, c) => {
|
|
72
|
+
c > 0 || this._initThumbnails(u);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
M = new WeakMap(), L(k, "shadowRootOptions", { ...I.shadowRootOptions }), L(k, "getTemplateHTML", (e) => {
|
|
78
|
+
const { src: s, ...n } = e;
|
|
79
|
+
return I.getTemplateHTML(n);
|
|
80
|
+
});
|
|
81
|
+
function j(t) {
|
|
82
|
+
var i, e;
|
|
83
|
+
const s = t.essentialProperties[0], [n, o] = s.value.split("x").map(Number), u = n * o, c = ((e = (i = t.adaptation) == null ? void 0 : i.period) == null ? void 0 : e.duration) || null, d = t.segmentDuration, v = t.timescale || 1, h = d / v / u;
|
|
84
|
+
return { totalThumbnails: c != null ? Math.ceil(c / h) : Math.ceil(d / h), thumbnailDuration: h };
|
|
85
|
+
}
|
|
86
|
+
function K({ thIndex: t, tduration: i, thduration: e, ttiles: s, startNumber: n, pto: o }) {
|
|
87
|
+
const u = Math.floor(t / s) + n, c = t % s + 1, d = (u - 1) * i - o, v = (c - 1) * e;
|
|
88
|
+
return d + v;
|
|
89
|
+
}
|
|
90
|
+
function q() {
|
|
91
|
+
const t = document.createElement("track");
|
|
92
|
+
return t.kind = "metadata", t.label = "thumbnails", t.srclang = "en", t.mode = "hidden", t.default = !0, t;
|
|
93
|
+
}
|
|
94
|
+
function z(t) {
|
|
95
|
+
let i = `WEBVTT
|
|
96
|
+
|
|
97
|
+
`;
|
|
98
|
+
for (const n of t)
|
|
99
|
+
i += `${s(n.startTime)} --> ${s(n.endTime)}
|
|
100
|
+
`, i += `${n.text}
|
|
101
|
+
|
|
102
|
+
`;
|
|
103
|
+
const e = new Blob([i], { type: "text/vtt" });
|
|
104
|
+
return URL.createObjectURL(e);
|
|
105
|
+
function s(n) {
|
|
106
|
+
const o = String(Math.floor(n / 3600)).padStart(2, "0"), u = String(Math.floor(n % 3600 / 60)).padStart(2, "0"), c = (n % 60).toFixed(3).padStart(6, "0");
|
|
107
|
+
return `${o}:${u}:${c}`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
globalThis.customElements && !globalThis.customElements.get("dash-video") && globalThis.customElements.define("dash-video", k);
|
|
111
|
+
var Z = k, G = /* @__PURE__ */ new Set([
|
|
112
|
+
"style",
|
|
113
|
+
"children",
|
|
114
|
+
"ref",
|
|
115
|
+
"key",
|
|
116
|
+
"suppressContentEditableWarning",
|
|
117
|
+
"suppressHydrationWarning",
|
|
118
|
+
"dangerouslySetInnerHTML"
|
|
119
|
+
]), J = {
|
|
120
|
+
className: "class",
|
|
121
|
+
htmlFor: "for"
|
|
122
|
+
};
|
|
123
|
+
function H(t) {
|
|
124
|
+
return t.toLowerCase();
|
|
125
|
+
}
|
|
126
|
+
function x(t) {
|
|
127
|
+
if (typeof t == "boolean") return t ? "" : void 0;
|
|
128
|
+
if (typeof t != "function" && !(typeof t == "object" && t !== null))
|
|
129
|
+
return t;
|
|
130
|
+
}
|
|
131
|
+
function Q({
|
|
132
|
+
react: t,
|
|
133
|
+
tagName: i,
|
|
134
|
+
elementClass: e,
|
|
135
|
+
events: s,
|
|
136
|
+
displayName: n,
|
|
137
|
+
defaultProps: o,
|
|
138
|
+
toAttributeName: u = H,
|
|
139
|
+
toAttributeValue: c = x
|
|
140
|
+
}) {
|
|
141
|
+
const d = Number.parseInt(t.version) >= 19, v = t.forwardRef((g, h) => {
|
|
142
|
+
var E, S;
|
|
143
|
+
const m = t.useRef(null), b = t.useRef(/* @__PURE__ */ new Map()), y = {}, _ = {}, f = {}, w = {};
|
|
144
|
+
for (const [a, r] of Object.entries(g)) {
|
|
145
|
+
if (G.has(a)) {
|
|
146
|
+
f[a] = r;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const l = u(J[a] ?? a);
|
|
150
|
+
if (e.prototype && a in e.prototype && !(a in (((E = globalThis.HTMLElement) == null ? void 0 : E.prototype) ?? {})) && !((S = e.observedAttributes) != null && S.some((T) => T === l))) {
|
|
151
|
+
w[a] = r;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (a.startsWith("on")) {
|
|
155
|
+
y[a] = r;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const p = c(r);
|
|
159
|
+
if (l && p != null && (_[l] = String(p), d || (f[l] = p)), l && d) {
|
|
160
|
+
const T = x(r);
|
|
161
|
+
p !== T ? f[l] = p : f[l] = r;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (typeof window < "u") {
|
|
165
|
+
for (const a in y) {
|
|
166
|
+
const r = y[a], l = a.endsWith("Capture"), p = ((s == null ? void 0 : s[a]) ?? a.slice(2).toLowerCase()).slice(
|
|
167
|
+
0,
|
|
168
|
+
l ? -7 : void 0
|
|
169
|
+
);
|
|
170
|
+
t.useLayoutEffect(() => {
|
|
171
|
+
const T = m == null ? void 0 : m.current;
|
|
172
|
+
if (!(!T || typeof r != "function"))
|
|
173
|
+
return T.addEventListener(p, r, l), () => {
|
|
174
|
+
T.removeEventListener(p, r, l);
|
|
175
|
+
};
|
|
176
|
+
}, [m == null ? void 0 : m.current, r]);
|
|
177
|
+
}
|
|
178
|
+
t.useLayoutEffect(() => {
|
|
179
|
+
if (m.current === null) return;
|
|
180
|
+
const a = /* @__PURE__ */ new Map();
|
|
181
|
+
for (const r in w)
|
|
182
|
+
B(m.current, r, w[r]), b.current.delete(r), a.set(r, w[r]);
|
|
183
|
+
for (const [r, l] of b.current)
|
|
184
|
+
B(m.current, r, void 0);
|
|
185
|
+
b.current = a;
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
if (typeof window > "u" && (e != null && e.getTemplateHTML) && (e != null && e.shadowRootOptions)) {
|
|
189
|
+
const { mode: a, delegatesFocus: r } = e.shadowRootOptions, l = t.createElement("template", {
|
|
190
|
+
shadowrootmode: a,
|
|
191
|
+
shadowrootdelegatesfocus: r,
|
|
192
|
+
dangerouslySetInnerHTML: {
|
|
193
|
+
__html: e.getTemplateHTML(_, g)
|
|
194
|
+
},
|
|
195
|
+
key: "ce-la-react-ssr-template-shadow-root"
|
|
196
|
+
});
|
|
197
|
+
f.children = [l, f.children];
|
|
198
|
+
}
|
|
199
|
+
return t.createElement(i, {
|
|
200
|
+
...o,
|
|
201
|
+
...f,
|
|
202
|
+
ref: t.useCallback(
|
|
203
|
+
(a) => {
|
|
204
|
+
m.current = a, typeof h == "function" ? h(a) : h !== null && (h.current = a);
|
|
205
|
+
},
|
|
206
|
+
[h]
|
|
207
|
+
)
|
|
208
|
+
}, f.children);
|
|
209
|
+
});
|
|
210
|
+
return v.displayName = n ?? e.name, v;
|
|
211
|
+
}
|
|
212
|
+
function B(t, i, e) {
|
|
213
|
+
var s;
|
|
214
|
+
t[i] = e, e == null && i in (((s = globalThis.HTMLElement) == null ? void 0 : s.prototype) ?? {}) && t.removeAttribute(i);
|
|
215
|
+
}
|
|
216
|
+
var tt = Q({
|
|
217
|
+
react: W,
|
|
218
|
+
tagName: "dash-video",
|
|
219
|
+
elementClass: Z,
|
|
220
|
+
toAttributeName(t) {
|
|
221
|
+
return t === "muted" ? "" : t === "defaultMuted" ? "muted" : H(t);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
/*! Bundled license information:
|
|
225
|
+
|
|
226
|
+
ce-la-react/dist/ce-la-react.js:
|
|
227
|
+
(**
|
|
228
|
+
* @license
|
|
229
|
+
* Copyright 2018 Google LLC
|
|
230
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
231
|
+
*
|
|
232
|
+
* Modified version of `@lit/react` for vanilla custom elements with support for SSR.
|
|
233
|
+
*)
|
|
234
|
+
*/
|
|
235
|
+
export {
|
|
236
|
+
tt as default
|
|
237
|
+
};
|
|
238
|
+
//# sourceMappingURL=react-dS1WBxxz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-dS1WBxxz.js","sources":["../../../node_modules/dash-video-element/dist/dash-video-element.js","../../../node_modules/dash-video-element/dist/react.js"],"sourcesContent":["import { CustomVideoElement } from \"custom-media-element\";\nimport { MediaTracksMixin } from \"media-tracks\";\nclass DashVideoElement extends MediaTracksMixin(CustomVideoElement) {\n static shadowRootOptions = { ...CustomVideoElement.shadowRootOptions };\n static getTemplateHTML = (attrs) => {\n const { src, ...rest } = attrs;\n return CustomVideoElement.getTemplateHTML(rest);\n };\n #apiInit;\n attributeChangedCallback(attrName, oldValue, newValue) {\n if (attrName !== \"src\") {\n super.attributeChangedCallback(attrName, oldValue, newValue);\n }\n if (attrName === \"src\" && oldValue != newValue) {\n this.load();\n }\n }\n async _initThumbnails(representation) {\n const generateAllCues = async (totalThumbnails2, thumbnailDuration2) => {\n const promises = [];\n const timescale = representation.timescale || 1;\n const startNumber = representation.startNumber || 1;\n const pto = representation.presentationTimeOffset ? representation.presentationTimeOffset / timescale : 0;\n const tduration = representation.segmentDuration;\n for (let thIndex = 0; thIndex < totalThumbnails2; thIndex++) {\n const startTime = calculateThumbnailStartTime({\n thIndex,\n thduration: thumbnailDuration2,\n ttiles: totalThumbnails2,\n tduration,\n startNumber,\n pto\n });\n const endTime = startTime + thumbnailDuration2;\n const promise = new Promise((resolve, reject) => {\n this.api.provideThumbnail(startTime, ({ url, width, height, x, y }) => {\n try {\n const cue = new VTTCue(\n startTime,\n endTime,\n `${url}#xywh=${x},${y},${width},${height}`\n );\n resolve(cue);\n } catch (err) {\n reject(err);\n }\n });\n });\n promises.push(promise);\n }\n return await Promise.all(promises).catch((e) => console.error(\"Error processing thumbnails\", e));\n };\n const { totalThumbnails, thumbnailDuration } = calculateThumbnailTimes(representation);\n const cues = await generateAllCues(totalThumbnails, thumbnailDuration);\n let track = this.nativeEl.querySelector('track[label=\"thumbnails\"]');\n if (!track) {\n track = createThumbnailTrack();\n this.nativeEl.appendChild(track);\n const vttUrl = cuesToVttBlobUrl(cues);\n track.src = vttUrl;\n track.dispatchEvent(new Event(\"change\"));\n }\n }\n async load() {\n if (this.#apiInit) {\n this.api.attachSource(this.src);\n return;\n }\n this.#apiInit = true;\n const Dash = await import(\"dashjs\");\n this.api = Dash.MediaPlayer().create();\n this.api.initialize(this.nativeEl, this.src, this.autoplay);\n this.api.on(Dash.MediaPlayer.events.STREAM_INITIALIZED, () => {\n const bitrateList = this.api.getRepresentationsByType(\"video\");\n let videoTrack = this.videoTracks.getTrackById(\"main\");\n if (!videoTrack) {\n videoTrack = this.addVideoTrack(\"main\");\n videoTrack.id = \"main\";\n videoTrack.selected = true;\n }\n bitrateList.forEach((rep) => {\n const bitrate = rep.bandwidth ?? rep.bitrate ?? (Number.isFinite(rep.bitrateInKbit) ? rep.bitrateInKbit * 1e3 : void 0);\n const rendition = videoTrack.addRendition(rep.id, rep.width, rep.height, rep.mimeType ?? rep.codec, bitrate);\n rendition.id = rep.id;\n });\n this.videoRenditions.addEventListener(\"change\", () => {\n const selected = this.videoRenditions[this.videoRenditions.selectedIndex];\n if (selected == null ? void 0 : selected.id) {\n this.api.updateSettings({ streaming: { abr: { autoSwitchBitrate: { video: false } } } });\n this.api.setRepresentationForTypeById(\"video\", selected.id, true);\n } else {\n this.api.updateSettings({ streaming: { abr: { autoSwitchBitrate: { video: true } } } });\n }\n });\n if (!this.api.isDynamic()) {\n const imageReps = this.api.getRepresentationsByType(\"image\");\n imageReps.forEach(async (rep, idx) => {\n if (idx > 0) return;\n this._initThumbnails(rep);\n });\n }\n });\n }\n}\nfunction calculateThumbnailTimes(representation) {\n var _a, _b;\n const essentialProp = representation.essentialProperties[0];\n const [htiles, vtiles] = essentialProp.value.split(\"x\").map(Number);\n const ttiles = htiles * vtiles;\n const periodDuration = ((_b = (_a = representation.adaptation) == null ? void 0 : _a.period) == null ? void 0 : _b.duration) || null;\n const tileDuration = representation.segmentDuration;\n const timescale = representation.timescale || 1;\n const tduration = tileDuration / timescale;\n const thduration = tduration / ttiles;\n const totalThumbnails = periodDuration != null ? Math.ceil(periodDuration / thduration) : Math.ceil(tileDuration / thduration);\n return { totalThumbnails, thumbnailDuration: thduration };\n}\nfunction calculateThumbnailStartTime({ thIndex, tduration, thduration, ttiles, startNumber, pto }) {\n const tnumber = Math.floor(thIndex / ttiles) + startNumber;\n const thnumber = thIndex % ttiles + 1;\n const tileStartTime = (tnumber - 1) * tduration - pto;\n const thumbnailStartTime = (thnumber - 1) * thduration;\n return tileStartTime + thumbnailStartTime;\n}\nfunction createThumbnailTrack() {\n const track = document.createElement(\"track\");\n track.kind = \"metadata\";\n track.label = \"thumbnails\";\n track.srclang = \"en\";\n track.mode = \"hidden\";\n track.default = true;\n return track;\n}\nfunction cuesToVttBlobUrl(cues) {\n let vtt = \"WEBVTT\\n\\n\";\n for (const cue of cues) {\n vtt += `${formatTime(cue.startTime)} --> ${formatTime(cue.endTime)}\n`;\n vtt += `${cue.text}\n\n`;\n }\n const blob = new Blob([vtt], { type: \"text/vtt\" });\n return URL.createObjectURL(blob);\n function formatTime(t) {\n const h = String(Math.floor(t / 3600)).padStart(2, \"0\");\n const m = String(Math.floor(t % 3600 / 60)).padStart(2, \"0\");\n const s = (t % 60).toFixed(3).padStart(6, \"0\");\n return `${h}:${m}:${s}`;\n }\n}\nif (globalThis.customElements && !globalThis.customElements.get(\"dash-video\")) {\n globalThis.customElements.define(\"dash-video\", DashVideoElement);\n}\nvar dash_video_element_default = DashVideoElement;\nexport {\n dash_video_element_default as default\n};\n","\"use client\";\n\n// dist/react.ts\nimport React from \"react\";\nimport CustomMediaElement from \"./dash-video-element.js\";\n\n// ../../node_modules/ce-la-react/dist/ce-la-react.js\nvar reservedReactProps = /* @__PURE__ */ new Set([\n \"style\",\n \"children\",\n \"ref\",\n \"key\",\n \"suppressContentEditableWarning\",\n \"suppressHydrationWarning\",\n \"dangerouslySetInnerHTML\"\n]);\nvar reactPropToAttrNameMap = {\n className: \"class\",\n htmlFor: \"for\"\n};\nfunction defaultToAttributeName(propName) {\n return propName.toLowerCase();\n}\nfunction defaultToAttributeValue(propValue) {\n if (typeof propValue === \"boolean\") return propValue ? \"\" : void 0;\n if (typeof propValue === \"function\") return void 0;\n if (typeof propValue === \"object\" && propValue !== null) return void 0;\n return propValue;\n}\nfunction createComponent({\n react: React2,\n tagName,\n elementClass,\n events,\n displayName,\n defaultProps,\n toAttributeName = defaultToAttributeName,\n toAttributeValue = defaultToAttributeValue\n}) {\n const IS_REACT_19_OR_NEWER = Number.parseInt(React2.version) >= 19;\n const ReactComponent = React2.forwardRef((props, ref) => {\n var _a, _b;\n const elementRef = React2.useRef(null);\n const prevElemPropsRef = React2.useRef(/* @__PURE__ */ new Map());\n const eventProps = {};\n const attrs = {};\n const reactProps = {};\n const elementProps = {};\n for (const [k, v] of Object.entries(props)) {\n if (reservedReactProps.has(k)) {\n reactProps[k] = v;\n continue;\n }\n const attrName = toAttributeName(reactPropToAttrNameMap[k] ?? k);\n if (elementClass.prototype && k in elementClass.prototype && !(k in (((_a = globalThis.HTMLElement) == null ? void 0 : _a.prototype) ?? {})) && !((_b = elementClass.observedAttributes) == null ? void 0 : _b.some((attr) => attr === attrName))) {\n elementProps[k] = v;\n continue;\n }\n if (k.startsWith(\"on\")) {\n eventProps[k] = v;\n continue;\n }\n const attrValue = toAttributeValue(v);\n if (attrName && attrValue != null) {\n attrs[attrName] = String(attrValue);\n if (!IS_REACT_19_OR_NEWER) {\n reactProps[attrName] = attrValue;\n }\n }\n if (attrName && IS_REACT_19_OR_NEWER) {\n const attrValueFromDefault = defaultToAttributeValue(v);\n if (attrValue !== attrValueFromDefault) {\n reactProps[attrName] = attrValue;\n } else {\n reactProps[attrName] = v;\n }\n }\n }\n if (typeof window !== \"undefined\") {\n for (const propName in eventProps) {\n const callback = eventProps[propName];\n const useCapture = propName.endsWith(\"Capture\");\n const eventName = ((events == null ? void 0 : events[propName]) ?? propName.slice(2).toLowerCase()).slice(\n 0,\n useCapture ? -7 : void 0\n );\n React2.useLayoutEffect(() => {\n const eventTarget = elementRef == null ? void 0 : elementRef.current;\n if (!eventTarget || typeof callback !== \"function\") return;\n eventTarget.addEventListener(eventName, callback, useCapture);\n return () => {\n eventTarget.removeEventListener(eventName, callback, useCapture);\n };\n }, [elementRef == null ? void 0 : elementRef.current, callback]);\n }\n React2.useLayoutEffect(() => {\n if (elementRef.current === null) return;\n const newElemProps = /* @__PURE__ */ new Map();\n for (const key in elementProps) {\n setProperty(elementRef.current, key, elementProps[key]);\n prevElemPropsRef.current.delete(key);\n newElemProps.set(key, elementProps[key]);\n }\n for (const [key, _value] of prevElemPropsRef.current) {\n setProperty(elementRef.current, key, void 0);\n }\n prevElemPropsRef.current = newElemProps;\n });\n }\n if (typeof window === \"undefined\" && (elementClass == null ? void 0 : elementClass.getTemplateHTML) && (elementClass == null ? void 0 : elementClass.shadowRootOptions)) {\n const { mode, delegatesFocus } = elementClass.shadowRootOptions;\n const templateShadowRoot = React2.createElement(\"template\", {\n shadowrootmode: mode,\n shadowrootdelegatesfocus: delegatesFocus,\n dangerouslySetInnerHTML: {\n __html: elementClass.getTemplateHTML(attrs, props)\n },\n key: \"ce-la-react-ssr-template-shadow-root\"\n });\n reactProps.children = [templateShadowRoot, reactProps.children];\n }\n return React2.createElement(tagName, {\n ...defaultProps,\n ...reactProps,\n ref: React2.useCallback(\n (node) => {\n elementRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref !== null) {\n ref.current = node;\n }\n },\n [ref]\n )\n }, reactProps.children);\n });\n ReactComponent.displayName = displayName ?? elementClass.name;\n return ReactComponent;\n}\nfunction setProperty(node, name, value) {\n var _a;\n node[name] = value;\n if (value == null && name in (((_a = globalThis.HTMLElement) == null ? void 0 : _a.prototype) ?? {})) {\n node.removeAttribute(name);\n }\n}\n\n// dist/react.ts\nvar react_default = createComponent({\n react: React,\n tagName: \"dash-video\",\n elementClass: CustomMediaElement,\n toAttributeName(propName) {\n if (propName === \"muted\") return \"\";\n if (propName === \"defaultMuted\") return \"muted\";\n return defaultToAttributeName(propName);\n }\n});\nexport {\n react_default as default\n};\n/*! Bundled license information:\n\nce-la-react/dist/ce-la-react.js:\n (**\n * @license\n * Copyright 2018 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Modified version of `@lit/react` for vanilla custom elements with support for SSR.\n *)\n*/\n"],"names":["DashVideoElement","MediaTracksMixin","CustomVideoElement","__privateAdd","_apiInit","attrName","oldValue","newValue","representation","generateAllCues","totalThumbnails2","thumbnailDuration2","promises","timescale","startNumber","pto","tduration","thIndex","startTime","calculateThumbnailStartTime","endTime","promise","resolve","reject","url","width","height","x","y","cue","err","e","totalThumbnails","thumbnailDuration","calculateThumbnailTimes","cues","track","createThumbnailTrack","vttUrl","cuesToVttBlobUrl","__privateGet","__privateSet","Dash","bitrateList","videoTrack","rep","bitrate","rendition","selected","idx","__publicField","attrs","src","rest","_a","_b","essentialProp","htiles","vtiles","ttiles","periodDuration","tileDuration","thduration","tnumber","thnumber","tileStartTime","thumbnailStartTime","vtt","formatTime","blob","t","h","m","s","dash_video_element_default","reservedReactProps","reactPropToAttrNameMap","defaultToAttributeName","propName","defaultToAttributeValue","propValue","createComponent","React2","tagName","elementClass","events","displayName","defaultProps","toAttributeName","toAttributeValue","IS_REACT_19_OR_NEWER","ReactComponent","props","ref","elementRef","prevElemPropsRef","eventProps","reactProps","elementProps","k","v","attr","attrValue","attrValueFromDefault","callback","useCapture","eventName","eventTarget","newElemProps","key","setProperty","_value","mode","delegatesFocus","templateShadowRoot","node","name","value","react_default","React","CustomMediaElement"],"mappings":"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","x_google_ignoreList":[0,1]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/messaging-react",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.1-rc-1776055454",
|
|
4
4
|
"description": "React messaging components built on messaging-core for web applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"@linktr.ee/component-library": "*",
|
|
37
37
|
"@linktr.ee/messaging-core": "^1.5.0",
|
|
38
38
|
"@phosphor-icons/react": "^2.1.9",
|
|
39
|
+
"react-player": "^3.4.0",
|
|
39
40
|
"stream-chat-react": "^13.12.0"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
@@ -54,8 +54,21 @@ vi.mock('./CustomDateSeparator', () => ({
|
|
|
54
54
|
CustomDateSeparator: () => <div data-testid="custom-date-separator" />,
|
|
55
55
|
}))
|
|
56
56
|
|
|
57
|
+
vi.mock('./ChannelInfoDialog', () => ({
|
|
58
|
+
ChannelInfoDialog: () => <div data-testid="channel-info-dialog" />,
|
|
59
|
+
}))
|
|
60
|
+
|
|
61
|
+
const avatarRenderCalls: Array<Record<string, unknown>> = []
|
|
57
62
|
vi.mock('./Avatar', () => ({
|
|
58
|
-
Avatar: () =>
|
|
63
|
+
Avatar: (props: Record<string, unknown>) => {
|
|
64
|
+
avatarRenderCalls.push({ ...props })
|
|
65
|
+
return <div data-testid="avatar" />
|
|
66
|
+
},
|
|
67
|
+
}))
|
|
68
|
+
|
|
69
|
+
let mockIsStarred = false
|
|
70
|
+
vi.mock('../hooks/useChannelStar', () => ({
|
|
71
|
+
useChannelStar: () => mockIsStarred,
|
|
59
72
|
}))
|
|
60
73
|
|
|
61
74
|
const createChannel = () =>
|
|
@@ -83,6 +96,8 @@ const createChannel = () =>
|
|
|
83
96
|
describe('ChannelView', () => {
|
|
84
97
|
beforeEach(() => {
|
|
85
98
|
activeChannel = undefined
|
|
99
|
+
avatarRenderCalls.length = 0
|
|
100
|
+
mockIsStarred = false
|
|
86
101
|
})
|
|
87
102
|
|
|
88
103
|
it('renders conversation footer between message list and message input', () => {
|
|
@@ -122,6 +137,40 @@ describe('ChannelView', () => {
|
|
|
122
137
|
expect(screen.queryByTestId('conversation-footer')).not.toBeInTheDocument()
|
|
123
138
|
})
|
|
124
139
|
|
|
140
|
+
it('does not pass starred to avatar when showStarButton is false', () => {
|
|
141
|
+
mockIsStarred = true
|
|
142
|
+
const channel = createChannel()
|
|
143
|
+
|
|
144
|
+
renderWithProviders(
|
|
145
|
+
<ChannelView channel={channel} showStarButton={false} />
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
expect(avatarRenderCalls.length).toBeGreaterThan(0)
|
|
149
|
+
expect(avatarRenderCalls.every((call) => call.starred === false)).toBe(true)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('passes starred to avatar when showStarButton is true and channel is starred', () => {
|
|
153
|
+
mockIsStarred = true
|
|
154
|
+
const channel = createChannel()
|
|
155
|
+
|
|
156
|
+
renderWithProviders(
|
|
157
|
+
<ChannelView channel={channel} showStarButton={true} />
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
expect(avatarRenderCalls.length).toBeGreaterThan(0)
|
|
161
|
+
expect(avatarRenderCalls.every((call) => call.starred === true)).toBe(true)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('does not pass starred to avatar by default (showStarButton defaults to false)', () => {
|
|
165
|
+
mockIsStarred = true
|
|
166
|
+
const channel = createChannel()
|
|
167
|
+
|
|
168
|
+
renderWithProviders(<ChannelView channel={channel} />)
|
|
169
|
+
|
|
170
|
+
expect(avatarRenderCalls.length).toBeGreaterThan(0)
|
|
171
|
+
expect(avatarRenderCalls.every((call) => call.starred === false)).toBe(true)
|
|
172
|
+
})
|
|
173
|
+
|
|
125
174
|
it('keeps channel banner and input action renderers working', () => {
|
|
126
175
|
const channel = createChannel()
|
|
127
176
|
const renderMessageInputActions = vi.fn((currentChannel: Channel) => (
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from '@phosphor-icons/react'
|
|
6
6
|
import classNames from 'classnames'
|
|
7
7
|
import React, { useCallback, useRef } from 'react'
|
|
8
|
-
import { Channel as ChannelType } from 'stream-chat'
|
|
8
|
+
import { Channel as ChannelType, LocalMessage } from 'stream-chat'
|
|
9
9
|
import {
|
|
10
10
|
Channel,
|
|
11
11
|
Window,
|
|
@@ -97,7 +97,7 @@ const CustomChannelHeader: React.FC<{
|
|
|
97
97
|
id={participant?.user?.id || channel.id || 'unknown'}
|
|
98
98
|
name={participantName}
|
|
99
99
|
image={participantImage}
|
|
100
|
-
starred={isStarred}
|
|
100
|
+
starred={showStarButton && isStarred}
|
|
101
101
|
size={40}
|
|
102
102
|
/>
|
|
103
103
|
<h1 className="text-xs font-medium text-black/90">
|
|
@@ -150,7 +150,7 @@ const CustomChannelHeader: React.FC<{
|
|
|
150
150
|
id={participant?.user?.id || channel.id || 'unknown'}
|
|
151
151
|
name={participantName}
|
|
152
152
|
image={participantImage}
|
|
153
|
-
starred={isStarred}
|
|
153
|
+
starred={showStarButton && isStarred}
|
|
154
154
|
size={40}
|
|
155
155
|
/>
|
|
156
156
|
<div className="min-w-0">
|
|
@@ -211,6 +211,8 @@ const ChannelViewInner: React.FC<{
|
|
|
211
211
|
onReportParticipantClick?: () => void
|
|
212
212
|
showStarButton?: boolean
|
|
213
213
|
chatbotVotingEnabled?: boolean
|
|
214
|
+
onAttachmentUnlock?: (message: LocalMessage, channel: ChannelType) => Promise<string>
|
|
215
|
+
onAttachmentDownload?: (message: LocalMessage, channel: ChannelType) => void
|
|
214
216
|
renderChannelBanner?: () => React.ReactNode
|
|
215
217
|
customProfileContent?: React.ReactNode
|
|
216
218
|
customChannelActions?: React.ReactNode
|
|
@@ -231,6 +233,8 @@ const ChannelViewInner: React.FC<{
|
|
|
231
233
|
onReportParticipantClick,
|
|
232
234
|
showStarButton = false,
|
|
233
235
|
chatbotVotingEnabled = false,
|
|
236
|
+
onAttachmentUnlock,
|
|
237
|
+
onAttachmentDownload,
|
|
234
238
|
renderChannelBanner,
|
|
235
239
|
customProfileContent,
|
|
236
240
|
customChannelActions,
|
|
@@ -286,6 +290,8 @@ const ChannelViewInner: React.FC<{
|
|
|
286
290
|
<CustomMessage
|
|
287
291
|
{...props}
|
|
288
292
|
chatbotVotingEnabled={chatbotVotingEnabled}
|
|
293
|
+
onAttachmentUnlock={onAttachmentUnlock}
|
|
294
|
+
onAttachmentDownload={onAttachmentDownload}
|
|
289
295
|
/>
|
|
290
296
|
)
|
|
291
297
|
|
|
@@ -373,6 +379,8 @@ export const ChannelView = React.memo<ChannelViewProps>(
|
|
|
373
379
|
onMessageSent,
|
|
374
380
|
showStarButton = false,
|
|
375
381
|
chatbotVotingEnabled = false,
|
|
382
|
+
onAttachmentUnlock,
|
|
383
|
+
onAttachmentDownload,
|
|
376
384
|
renderChannelBanner,
|
|
377
385
|
customProfileContent,
|
|
378
386
|
customChannelActions,
|
|
@@ -451,6 +459,8 @@ export const ChannelView = React.memo<ChannelViewProps>(
|
|
|
451
459
|
onReportParticipantClick={onReportParticipantClick}
|
|
452
460
|
showStarButton={showStarButton}
|
|
453
461
|
chatbotVotingEnabled={chatbotVotingEnabled}
|
|
462
|
+
onAttachmentUnlock={onAttachmentUnlock}
|
|
463
|
+
onAttachmentDownload={onAttachmentDownload}
|
|
454
464
|
renderChannelBanner={renderChannelBanner}
|
|
455
465
|
customProfileContent={customProfileContent}
|
|
456
466
|
customChannelActions={customChannelActions}
|
|
@@ -93,8 +93,13 @@ interface TemplateProps {
|
|
|
93
93
|
type?: 'regular' | 'system'
|
|
94
94
|
attachments?: Array<Record<string, unknown>>
|
|
95
95
|
metadata?: {
|
|
96
|
-
custom_type?: 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT'
|
|
96
|
+
custom_type?: 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT' | 'MESSAGE_ATTACHMENT'
|
|
97
97
|
amount_text?: string
|
|
98
|
+
attachment_title?: string
|
|
99
|
+
attachment_mime_type?: string
|
|
100
|
+
|
|
101
|
+
attachment_thumbnail?: string
|
|
102
|
+
attachment_detail?: string
|
|
98
103
|
}
|
|
99
104
|
}>
|
|
100
105
|
}
|
|
@@ -113,6 +118,17 @@ const Template: StoryFn<TemplateProps> = ({ messages }) => {
|
|
|
113
118
|
createMockChannel(client, messages).then(setChannel)
|
|
114
119
|
}, [client, messages])
|
|
115
120
|
|
|
121
|
+
const MessageComponent = React.useMemo(() => {
|
|
122
|
+
const AttachmentMessage = (props: React.ComponentProps<typeof CustomMessage>) => (
|
|
123
|
+
<CustomMessage
|
|
124
|
+
{...props}
|
|
125
|
+
onAttachmentUnlock={async (msg) => { await new Promise(resolve => setTimeout(resolve, 1500)); return `https://example.com/unlocked/${msg.metadata?.attachment_title}` }}
|
|
126
|
+
onAttachmentDownload={(msg) => alert(`Download: ${msg.metadata?.attachment_title}`)}
|
|
127
|
+
/>
|
|
128
|
+
)
|
|
129
|
+
return AttachmentMessage
|
|
130
|
+
}, [])
|
|
131
|
+
|
|
116
132
|
if (!channel) {
|
|
117
133
|
return <div className="p-4">Loading...</div>
|
|
118
134
|
}
|
|
@@ -120,7 +136,7 @@ const Template: StoryFn<TemplateProps> = ({ messages }) => {
|
|
|
120
136
|
return (
|
|
121
137
|
<Chat client={client}>
|
|
122
138
|
<div className="h-screen w-full bg-white">
|
|
123
|
-
<Channel channel={channel} Message={
|
|
139
|
+
<Channel channel={channel} Message={MessageComponent}>
|
|
124
140
|
<Window>
|
|
125
141
|
<MessageList />
|
|
126
142
|
</Window>
|
|
@@ -208,6 +224,49 @@ MixedTags.args = {
|
|
|
208
224
|
],
|
|
209
225
|
}
|
|
210
226
|
|
|
227
|
+
export const PaidAttachment: StoryFn<TemplateProps> = Template.bind({})
|
|
228
|
+
PaidAttachment.args = {
|
|
229
|
+
messages: [
|
|
230
|
+
{ id: 'msg-1', text: 'Can I have your workout plan?', user: mockUser },
|
|
231
|
+
{ id: 'msg-2', text: 'Yes! I just uploaded it for you 🎉', user: participant },
|
|
232
|
+
{
|
|
233
|
+
id: 'msg-3',
|
|
234
|
+
text: '',
|
|
235
|
+
user: participant,
|
|
236
|
+
metadata: {
|
|
237
|
+
custom_type: 'MESSAGE_ATTACHMENT',
|
|
238
|
+
amount_text: 'AU$9.99',
|
|
239
|
+
attachment_title: "Alicia's Workout Plan",
|
|
240
|
+
attachment_mime_type: 'video/mp4',
|
|
241
|
+
attachment_thumbnail: '/video-thumbnail-blurred.jpg',
|
|
242
|
+
attachment_detail: '1:20',
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
{ id: 'msg-4', text: 'Looks amazing, unlocking now!', user: mockUser },
|
|
246
|
+
],
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export const PaidAttachmentWithText: StoryFn<TemplateProps> = Template.bind({})
|
|
250
|
+
PaidAttachmentWithText.args = {
|
|
251
|
+
messages: [
|
|
252
|
+
{
|
|
253
|
+
id: 'msg-1',
|
|
254
|
+
text: 'Hey! I just uploaded something for you 🎉',
|
|
255
|
+
user: participant,
|
|
256
|
+
metadata: {
|
|
257
|
+
custom_type: 'MESSAGE_ATTACHMENT',
|
|
258
|
+
amount_text: 'AU$9.99',
|
|
259
|
+
attachment_title: "Alicia's Workout Plan",
|
|
260
|
+
attachment_mime_type: 'video/mp4',
|
|
261
|
+
attachment_thumbnail: '/video-thumbnail-blurred.jpg',
|
|
262
|
+
attachment_detail: '1:20',
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
{ id: 'msg-2', text: 'Unlock it to get access!', user: participant },
|
|
266
|
+
{ id: 'msg-3', text: 'Looks amazing, unlocking now!', user: mockUser },
|
|
267
|
+
],
|
|
268
|
+
}
|
|
269
|
+
|
|
211
270
|
export const ChatbotVariants: StoryFn<TemplateProps> = Template.bind({})
|
|
212
271
|
ChatbotVariants.args = {
|
|
213
272
|
messages: [
|
|
@@ -42,6 +42,11 @@ export const isChatbotMessage = (message: LocalMessage): boolean => {
|
|
|
42
42
|
return message.metadata?.custom_type === 'MESSAGE_CHATBOT'
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/** Check if a message is a locked attachment */
|
|
46
|
+
export const isAttachmentMessage = (message: LocalMessage): boolean => {
|
|
47
|
+
return message.metadata?.custom_type === 'MESSAGE_ATTACHMENT'
|
|
48
|
+
}
|
|
49
|
+
|
|
45
50
|
/** Check if a message has a tip/paid tag (both render the same) */
|
|
46
51
|
export const isTipOrPaidMessage = (message: LocalMessage): boolean => {
|
|
47
52
|
return isTipMessage(message) || isPaidMessage(message)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
2
|
import React, { useMemo, useState } from 'react'
|
|
3
|
+
import { type Channel, type LocalMessage } from 'stream-chat'
|
|
3
4
|
import {
|
|
4
5
|
Attachment as DefaultAttachment,
|
|
5
6
|
EditMessageModal as DefaultEditMessageModal,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
isMessageBounced,
|
|
21
22
|
messageHasAttachments,
|
|
22
23
|
messageHasReactions,
|
|
24
|
+
useChannelStateContext,
|
|
23
25
|
useComponentContext,
|
|
24
26
|
useChatContext,
|
|
25
27
|
useMessageContext,
|
|
@@ -30,18 +32,23 @@ import {
|
|
|
30
32
|
|
|
31
33
|
import { useMessageVote } from '../../hooks/useMessageVote'
|
|
32
34
|
import { Avatar } from '../Avatar'
|
|
35
|
+
import LockedAttachmentCard from '../LockedAttachmentCard'
|
|
33
36
|
|
|
34
|
-
import { MessageTag, isChatbotMessage, isTipOnlyMessage } from './MessageTag'
|
|
37
|
+
import { MessageTag, isAttachmentMessage, isChatbotMessage, isTipOnlyMessage } from './MessageTag'
|
|
35
38
|
import { MessageVoteButtons } from './MessageVoteButtons'
|
|
36
39
|
|
|
37
40
|
type CustomMessageWithContextProps = MessageContextValue & {
|
|
38
41
|
chatbotVotingEnabled?: boolean
|
|
42
|
+
onAttachmentUnlock?: (message: LocalMessage, channel: Channel) => Promise<string>
|
|
43
|
+
onAttachmentDownload?: (message: LocalMessage, channel: Channel) => void
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
42
47
|
const {
|
|
43
48
|
additionalMessageInputProps,
|
|
44
49
|
chatbotVotingEnabled,
|
|
50
|
+
onAttachmentUnlock,
|
|
51
|
+
onAttachmentDownload,
|
|
45
52
|
editing,
|
|
46
53
|
endOfGroup,
|
|
47
54
|
firstOfGroup,
|
|
@@ -58,7 +65,10 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
58
65
|
} = props
|
|
59
66
|
|
|
60
67
|
const { client } = useChatContext('CustomMessage')
|
|
68
|
+
const { channel } = useChannelStateContext('CustomMessage')
|
|
61
69
|
const [isBounceDialogOpen, setIsBounceDialogOpen] = useState(false)
|
|
70
|
+
const [unlocking, setUnlocking] = useState(false)
|
|
71
|
+
const [attachmentSource, setAttachmentSource] = useState<string | undefined>(undefined)
|
|
62
72
|
const reminder = useMessageReminder(message.id)
|
|
63
73
|
const { selected: voteState, voteUp, voteDown } = useMessageVote(message)
|
|
64
74
|
|
|
@@ -144,6 +154,7 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
144
154
|
const poll = message.poll_id && client.polls.fromState(message.poll_id)
|
|
145
155
|
const isTipOnly = isTipOnlyMessage(message)
|
|
146
156
|
const isChatbot = isChatbotMessage(message)
|
|
157
|
+
const isAttachment = isAttachmentMessage(message)
|
|
147
158
|
const hasRenderableAttachments = !!(
|
|
148
159
|
finalAttachments?.length && !message.quoted_message
|
|
149
160
|
)
|
|
@@ -192,7 +203,29 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
192
203
|
marginInlineStart: 0,
|
|
193
204
|
}}
|
|
194
205
|
>
|
|
195
|
-
{
|
|
206
|
+
{isAttachment ? (
|
|
207
|
+
<div className="flex flex-col gap-1">
|
|
208
|
+
<LockedAttachmentCard
|
|
209
|
+
title={message.metadata?.attachment_title ?? ''}
|
|
210
|
+
mimeType={message.metadata?.attachment_mime_type ?? 'application/octet-stream'}
|
|
211
|
+
thumbnail={message.metadata?.attachment_thumbnail}
|
|
212
|
+
amountText={message.metadata?.amount_text}
|
|
213
|
+
detail={message.metadata?.attachment_detail}
|
|
214
|
+
source={attachmentSource}
|
|
215
|
+
isPurchased={message.metadata?.payment_status === 'paid'}
|
|
216
|
+
loading={unlocking}
|
|
217
|
+
onUnlock={onAttachmentUnlock ? async () => { setUnlocking(true); try { setAttachmentSource(await onAttachmentUnlock(message, channel)) } catch { /* caller handles errors (e.g. payment cancellation) */ } finally { setUnlocking(false) } } : undefined}
|
|
218
|
+
onDownload={attachmentSource && onAttachmentDownload ? () => onAttachmentDownload(message, channel) : undefined}
|
|
219
|
+
/>
|
|
220
|
+
{message.text && (
|
|
221
|
+
<div className="str-chat__message-bubble-wrapper">
|
|
222
|
+
<div className="str-chat__message-bubble">
|
|
223
|
+
<MessageText message={message} renderText={renderText} />
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
)}
|
|
227
|
+
</div>
|
|
228
|
+
) : isTipOnly ? (
|
|
196
229
|
/* Tip-only messages render as a standalone bubble */
|
|
197
230
|
<MessageTag message={message} standalone />
|
|
198
231
|
) : (
|
|
@@ -256,11 +289,20 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
256
289
|
|
|
257
290
|
const MemoizedCustomMessage = React.memo(
|
|
258
291
|
CustomMessageWithContext,
|
|
259
|
-
|
|
292
|
+
(prev, next) => {
|
|
293
|
+
if (prev.chatbotVotingEnabled !== next.chatbotVotingEnabled) return false
|
|
294
|
+
if (prev.onAttachmentUnlock !== next.onAttachmentUnlock) return false
|
|
295
|
+
if (prev.onAttachmentDownload !== next.onAttachmentDownload) return false
|
|
296
|
+
return areMessageUIPropsEqual(prev, next)
|
|
297
|
+
}
|
|
260
298
|
) as typeof CustomMessageWithContext
|
|
261
299
|
|
|
262
300
|
export const CustomMessage = (
|
|
263
|
-
props: MessageUIComponentProps & {
|
|
301
|
+
props: MessageUIComponentProps & {
|
|
302
|
+
chatbotVotingEnabled?: boolean
|
|
303
|
+
onAttachmentUnlock?: (message: LocalMessage, channel: Channel) => Promise<string>
|
|
304
|
+
onAttachmentDownload?: (message: LocalMessage, channel: Channel) => void
|
|
305
|
+
}
|
|
264
306
|
) => {
|
|
265
307
|
const messageContext = useMessageContext('CustomMessage')
|
|
266
308
|
return <MemoizedCustomMessage {...messageContext} {...props} />
|