@select-org/post-components 0.2.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-JPYOLIZH.js +439 -0
- package/dist/chunk-JPYOLIZH.js.map +1 -0
- package/dist/index.d.ts +321 -0
- package/dist/index.js +2932 -0
- package/dist/index.js.map +1 -0
- package/dist/resolver.d.ts +93 -0
- package/dist/resolver.js +9 -0
- package/dist/resolver.js.map +1 -0
- package/dist/types.d.ts +269 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/package.json +5 -6
package/dist/index.js
ADDED
|
@@ -0,0 +1,2932 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SPOTIFY_HEIGHT,
|
|
3
|
+
TruncateText,
|
|
4
|
+
hasMeaningfulHtml,
|
|
5
|
+
postItemType,
|
|
6
|
+
resolvePostContent
|
|
7
|
+
} from "./chunk-JPYOLIZH.js";
|
|
8
|
+
|
|
9
|
+
// src/components/PostCard.tsx
|
|
10
|
+
import React11, { useMemo as useMemo7, useState as useState5 } from "react";
|
|
11
|
+
|
|
12
|
+
// src/utils/cn.ts
|
|
13
|
+
import { clsx } from "clsx";
|
|
14
|
+
import { twMerge } from "tailwind-merge";
|
|
15
|
+
function cn(...inputs) {
|
|
16
|
+
return twMerge(clsx(inputs));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/components/PostHeader.tsx
|
|
20
|
+
import {
|
|
21
|
+
Avatar,
|
|
22
|
+
AvatarImage,
|
|
23
|
+
AvatarFallback,
|
|
24
|
+
AvatarBadge
|
|
25
|
+
} from "@select-org/ui";
|
|
26
|
+
|
|
27
|
+
// src/components/AppIcon.tsx
|
|
28
|
+
import {
|
|
29
|
+
AlarmClock,
|
|
30
|
+
Check,
|
|
31
|
+
CheckCircle2,
|
|
32
|
+
CirclePlay,
|
|
33
|
+
ExternalLink,
|
|
34
|
+
LoaderCircle,
|
|
35
|
+
MessageCircleMore,
|
|
36
|
+
Smile,
|
|
37
|
+
ThumbsDown,
|
|
38
|
+
ThumbsUp,
|
|
39
|
+
Trash2,
|
|
40
|
+
TriangleAlert,
|
|
41
|
+
Video,
|
|
42
|
+
X
|
|
43
|
+
} from "lucide-react";
|
|
44
|
+
import { jsx } from "react/jsx-runtime";
|
|
45
|
+
var ICON_MAP = {
|
|
46
|
+
video: Video,
|
|
47
|
+
circlePlay: CirclePlay,
|
|
48
|
+
cancel: X,
|
|
49
|
+
externalLink: ExternalLink,
|
|
50
|
+
sendEmoji: Smile,
|
|
51
|
+
alarmClock: AlarmClock,
|
|
52
|
+
messageCircleMore: MessageCircleMore,
|
|
53
|
+
chatErase: Trash2,
|
|
54
|
+
checkCircle2: CheckCircle2,
|
|
55
|
+
thumbUp: ThumbsUp,
|
|
56
|
+
thumbDown: ThumbsDown,
|
|
57
|
+
check: Check,
|
|
58
|
+
loader: LoaderCircle,
|
|
59
|
+
triangleAlert: TriangleAlert
|
|
60
|
+
};
|
|
61
|
+
function AppIcon({ name, ...props }) {
|
|
62
|
+
const Icon = ICON_MAP[name];
|
|
63
|
+
if (!Icon) return null;
|
|
64
|
+
return /* @__PURE__ */ jsx(Icon, { ...props });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/components/PostHeader.tsx
|
|
68
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
69
|
+
function formatRelativeTime(iso) {
|
|
70
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
71
|
+
const minutes = Math.floor(diff / 6e4);
|
|
72
|
+
if (minutes < 1) return "just now";
|
|
73
|
+
if (minutes < 60) return `${minutes}m`;
|
|
74
|
+
const hours = Math.floor(minutes / 60);
|
|
75
|
+
if (hours < 24) return `${hours}h`;
|
|
76
|
+
const days = Math.floor(hours / 24);
|
|
77
|
+
return `${days}d`;
|
|
78
|
+
}
|
|
79
|
+
var PostHeader = ({
|
|
80
|
+
author,
|
|
81
|
+
authorHref,
|
|
82
|
+
group,
|
|
83
|
+
groupHref,
|
|
84
|
+
postedAt,
|
|
85
|
+
postType,
|
|
86
|
+
isFeatured = false,
|
|
87
|
+
isPostPreview = false,
|
|
88
|
+
isAdmin = false,
|
|
89
|
+
isOwner = false,
|
|
90
|
+
onErasePress,
|
|
91
|
+
onCancelPost,
|
|
92
|
+
renderActionsMenu,
|
|
93
|
+
linkComponent: LinkComponent,
|
|
94
|
+
imageComponent,
|
|
95
|
+
labels
|
|
96
|
+
}) => {
|
|
97
|
+
const cancelLabel = labels?.cancelPost ?? "Cancel";
|
|
98
|
+
const badgeVariant = isOwner ? "owner" : isAdmin ? "admin" : void 0;
|
|
99
|
+
const authorNameNode = isPostPreview ? /* @__PURE__ */ jsx2("span", { className: "flex text-base font-semibold leading-[100%] text-foreground", children: author.name }) : LinkComponent ? /* @__PURE__ */ jsx2(
|
|
100
|
+
LinkComponent,
|
|
101
|
+
{
|
|
102
|
+
href: authorHref,
|
|
103
|
+
className: "flex text-base font-semibold leading-[100%] text-foreground hover:opacity-70 bg-transparent border-none p-0 cursor-pointer no-underline",
|
|
104
|
+
children: author.name
|
|
105
|
+
}
|
|
106
|
+
) : /* @__PURE__ */ jsx2(
|
|
107
|
+
"a",
|
|
108
|
+
{
|
|
109
|
+
href: authorHref,
|
|
110
|
+
onClick: (e) => e.stopPropagation(),
|
|
111
|
+
className: "flex text-base font-semibold leading-[100%] text-foreground hover:opacity-70 bg-transparent border-none p-0 cursor-pointer no-underline",
|
|
112
|
+
"aria-label": `View ${author.name}'s profile`,
|
|
113
|
+
children: author.name
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
const groupLinkNode = group && groupHref ? isPostPreview ? /* @__PURE__ */ jsxs("span", { className: "text-action-primary font-medium", children: [
|
|
117
|
+
"#",
|
|
118
|
+
group.name
|
|
119
|
+
] }) : LinkComponent ? /* @__PURE__ */ jsxs(
|
|
120
|
+
LinkComponent,
|
|
121
|
+
{
|
|
122
|
+
href: groupHref,
|
|
123
|
+
className: "text-action-primary font-medium hover:underline cursor-pointer bg-transparent border-none p-0",
|
|
124
|
+
children: [
|
|
125
|
+
"#",
|
|
126
|
+
group.name
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
) : /* @__PURE__ */ jsxs(
|
|
130
|
+
"a",
|
|
131
|
+
{
|
|
132
|
+
href: groupHref,
|
|
133
|
+
onClick: (e) => e.stopPropagation(),
|
|
134
|
+
className: "text-action-primary font-medium hover:underline cursor-pointer bg-transparent border-none p-0",
|
|
135
|
+
title: group.name,
|
|
136
|
+
"aria-label": `View group ${group.name}`,
|
|
137
|
+
children: [
|
|
138
|
+
"#",
|
|
139
|
+
group.name
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
) : null;
|
|
143
|
+
return /* @__PURE__ */ jsxs("section", { className: "not-prose relative flex flex-col justify-start p-4 pb-3", children: [
|
|
144
|
+
/* @__PURE__ */ jsxs("section", { className: "flex items-center gap-3", children: [
|
|
145
|
+
/* @__PURE__ */ jsxs(
|
|
146
|
+
Avatar,
|
|
147
|
+
{
|
|
148
|
+
size: "md",
|
|
149
|
+
disabled: isPostPreview,
|
|
150
|
+
className: "shrink-0 ring-1 ring-border-subtle",
|
|
151
|
+
children: [
|
|
152
|
+
/* @__PURE__ */ jsx2(
|
|
153
|
+
AvatarImage,
|
|
154
|
+
{
|
|
155
|
+
src: author.avatar,
|
|
156
|
+
alt: `${author.name}'s profile picture`,
|
|
157
|
+
placeholder: author.avatarPlaceholder,
|
|
158
|
+
imageComponent
|
|
159
|
+
}
|
|
160
|
+
),
|
|
161
|
+
/* @__PURE__ */ jsx2(AvatarFallback, { name: author.name }),
|
|
162
|
+
badgeVariant && /* @__PURE__ */ jsx2(AvatarBadge, { variant: badgeVariant })
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
),
|
|
166
|
+
/* @__PURE__ */ jsxs("section", { className: "flex flex-1 flex-col justify-center min-w-0", children: [
|
|
167
|
+
/* @__PURE__ */ jsx2("section", { className: "flex items-baseline justify-between gap-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
168
|
+
/* @__PURE__ */ jsx2("div", { className: "font-semibold text-foreground truncate", children: authorNameNode }),
|
|
169
|
+
isFeatured && /* @__PURE__ */ jsx2(
|
|
170
|
+
"svg",
|
|
171
|
+
{
|
|
172
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
173
|
+
viewBox: "0 0 24 24",
|
|
174
|
+
width: 14,
|
|
175
|
+
height: 14,
|
|
176
|
+
className: "text-feedback-warning fill-feedback-warning shrink-0",
|
|
177
|
+
"aria-label": "Featured post",
|
|
178
|
+
children: /* @__PURE__ */ jsx2("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" })
|
|
179
|
+
}
|
|
180
|
+
),
|
|
181
|
+
postedAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
182
|
+
/* @__PURE__ */ jsx2("span", { className: "text-muted-foreground font-bold shrink-0", children: "\xB7" }),
|
|
183
|
+
/* @__PURE__ */ jsx2(
|
|
184
|
+
"time",
|
|
185
|
+
{
|
|
186
|
+
title: postedAt,
|
|
187
|
+
className: "text-xs text-muted-foreground whitespace-nowrap shrink-0",
|
|
188
|
+
dateTime: postedAt,
|
|
189
|
+
children: formatRelativeTime(postedAt)
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
] })
|
|
193
|
+
] }) }),
|
|
194
|
+
/* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground truncate mt-0.5", children: [
|
|
195
|
+
/* @__PURE__ */ jsx2("span", { children: postType }),
|
|
196
|
+
groupLinkNode && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
197
|
+
/* @__PURE__ */ jsx2("span", { className: "mx-1" }),
|
|
198
|
+
groupLinkNode
|
|
199
|
+
] })
|
|
200
|
+
] })
|
|
201
|
+
] })
|
|
202
|
+
] }),
|
|
203
|
+
isPostPreview ? onCancelPost && /* @__PURE__ */ jsx2(
|
|
204
|
+
"button",
|
|
205
|
+
{
|
|
206
|
+
onClick: (e) => {
|
|
207
|
+
e.stopPropagation();
|
|
208
|
+
onCancelPost();
|
|
209
|
+
},
|
|
210
|
+
"aria-label": cancelLabel,
|
|
211
|
+
"data-testid": "cancel-pending-post",
|
|
212
|
+
className: "absolute right-4 top-4 leading-none rounded-full p-1.5 transition-colors hover:bg-feedback-danger/10 hover:text-feedback-danger",
|
|
213
|
+
children: /* @__PURE__ */ jsx2(AppIcon, { name: "cancel", width: 16, height: 16, strokeWidth: 1.75 })
|
|
214
|
+
}
|
|
215
|
+
) : renderActionsMenu ? /* @__PURE__ */ jsx2("div", { className: "absolute right-2 top-2", children: renderActionsMenu() }) : onErasePress ? /* @__PURE__ */ jsx2(
|
|
216
|
+
"button",
|
|
217
|
+
{
|
|
218
|
+
onClick: (e) => {
|
|
219
|
+
e.stopPropagation();
|
|
220
|
+
onErasePress();
|
|
221
|
+
},
|
|
222
|
+
"aria-label": "Delete post",
|
|
223
|
+
className: "absolute right-4 top-4 leading-none rounded-full p-1.5 transition-colors hover:bg-feedback-danger/10 hover:text-feedback-danger",
|
|
224
|
+
children: /* @__PURE__ */ jsx2(AppIcon, { name: "chatErase", width: 16, height: 16, strokeWidth: 1.75 })
|
|
225
|
+
}
|
|
226
|
+
) : null
|
|
227
|
+
] });
|
|
228
|
+
};
|
|
229
|
+
var PostHeader_default = PostHeader;
|
|
230
|
+
|
|
231
|
+
// src/components/AutoLink.tsx
|
|
232
|
+
import { useCallback, useMemo } from "react";
|
|
233
|
+
import Autolinker from "autolinker";
|
|
234
|
+
import { truncateSmart } from "autolinker/dist/commonjs/truncate/truncate-smart";
|
|
235
|
+
import { truncateEnd } from "autolinker/dist/commonjs/truncate/truncate-end";
|
|
236
|
+
import { truncateMiddle } from "autolinker/dist/commonjs/truncate/truncate-middle";
|
|
237
|
+
import emojiRegex from "emoji-regex";
|
|
238
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
239
|
+
var MENTION_TYPE = {
|
|
240
|
+
MENTION: "mention",
|
|
241
|
+
HASHTAG: "hashtag"
|
|
242
|
+
};
|
|
243
|
+
var EMOJI_REGEX = emojiRegex();
|
|
244
|
+
var getPureEmojiSize = (body) => {
|
|
245
|
+
let match;
|
|
246
|
+
let emojiCount = 0;
|
|
247
|
+
let emojiSize = 0;
|
|
248
|
+
while (match = EMOJI_REGEX.exec(body)) {
|
|
249
|
+
const emoji = match[0];
|
|
250
|
+
emojiSize += emoji.length;
|
|
251
|
+
emojiCount += 1;
|
|
252
|
+
}
|
|
253
|
+
if (emojiSize === body.length) {
|
|
254
|
+
return emojiCount;
|
|
255
|
+
}
|
|
256
|
+
return 0;
|
|
257
|
+
};
|
|
258
|
+
var checkMentionDataIndex = (mentionData = [], copyMentionData = [], body = "") => {
|
|
259
|
+
let mentionBody = body;
|
|
260
|
+
const newMentionData = [...mentionData, ...copyMentionData];
|
|
261
|
+
let lastMentionData = { index: 0, endIndex: 0 };
|
|
262
|
+
const formatNewMention = [];
|
|
263
|
+
for (let i = 0; i < newMentionData.length; i++) {
|
|
264
|
+
const mention = { ...newMentionData[i] };
|
|
265
|
+
if (mention.name && typeof mention.name === "string") {
|
|
266
|
+
mention.name = mention.name.trim();
|
|
267
|
+
} else {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (mentionBody.indexOf(mention.name) === -1) {
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const type = mention.type;
|
|
274
|
+
const name = (type === MENTION_TYPE.MENTION ? "@" : "#") + mention.name;
|
|
275
|
+
const index = mentionBody.indexOf(name) + lastMentionData.endIndex;
|
|
276
|
+
const endIndex = index + name.length;
|
|
277
|
+
mentionBody = body.substr(endIndex, body.length);
|
|
278
|
+
lastMentionData = { index, endIndex };
|
|
279
|
+
formatNewMention.push({
|
|
280
|
+
name,
|
|
281
|
+
type,
|
|
282
|
+
index,
|
|
283
|
+
endIndex,
|
|
284
|
+
data: mention
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
return formatNewMention;
|
|
288
|
+
};
|
|
289
|
+
var isLinkInternal = (url, supportDeepviewDomain) => {
|
|
290
|
+
if (!url) return false;
|
|
291
|
+
return supportDeepviewDomain.length > 0 && url.includes(supportDeepviewDomain);
|
|
292
|
+
};
|
|
293
|
+
var getUrl = (match, phone) => {
|
|
294
|
+
const type = match.getType();
|
|
295
|
+
switch (type) {
|
|
296
|
+
case "email": {
|
|
297
|
+
return [`mailto:${encodeURIComponent(match.getEmail())}`];
|
|
298
|
+
}
|
|
299
|
+
case "phone": {
|
|
300
|
+
const number = match.getNumber();
|
|
301
|
+
switch (phone) {
|
|
302
|
+
case "sms":
|
|
303
|
+
case "text":
|
|
304
|
+
return [`sms:${number}`];
|
|
305
|
+
default:
|
|
306
|
+
return [`tel:${number}`];
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
case "url": {
|
|
310
|
+
return [match.getAnchorHref()];
|
|
311
|
+
}
|
|
312
|
+
default: {
|
|
313
|
+
return [match.getMatchedText()];
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
var truncate = (text, { truncate: len = 32, truncateChars = "..", truncateLocation = "smart" } = {}) => {
|
|
318
|
+
let fn;
|
|
319
|
+
switch (truncateLocation) {
|
|
320
|
+
case "end":
|
|
321
|
+
fn = truncateEnd;
|
|
322
|
+
break;
|
|
323
|
+
case "middle":
|
|
324
|
+
fn = truncateMiddle;
|
|
325
|
+
break;
|
|
326
|
+
default:
|
|
327
|
+
fn = truncateSmart;
|
|
328
|
+
}
|
|
329
|
+
return fn(text, len, truncateChars);
|
|
330
|
+
};
|
|
331
|
+
var AutoLink = ({
|
|
332
|
+
text: textProp,
|
|
333
|
+
mentionData = [],
|
|
334
|
+
onNavigate,
|
|
335
|
+
supportDeepviewDomain = "",
|
|
336
|
+
phone = true,
|
|
337
|
+
email = true,
|
|
338
|
+
stripPrefix = false,
|
|
339
|
+
style = { fontSize: 12 },
|
|
340
|
+
mentionClassName: mentionClassNameProp,
|
|
341
|
+
className
|
|
342
|
+
}) => {
|
|
343
|
+
const mentionClassName = useMemo(
|
|
344
|
+
() => mentionClassNameProp || "font-bold text-action-primary",
|
|
345
|
+
[mentionClassNameProp]
|
|
346
|
+
);
|
|
347
|
+
const handleNavigate = useCallback(
|
|
348
|
+
(href, internal) => {
|
|
349
|
+
if (onNavigate) {
|
|
350
|
+
onNavigate(href, internal);
|
|
351
|
+
} else if (internal) {
|
|
352
|
+
window.location.href = href;
|
|
353
|
+
} else {
|
|
354
|
+
window.open(href, "_blank");
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
[onNavigate]
|
|
358
|
+
);
|
|
359
|
+
const renderDefaultLink = useCallback(
|
|
360
|
+
(text, match, index) => {
|
|
361
|
+
const [url] = getUrl(match, phone);
|
|
362
|
+
const internal = isLinkInternal(url, supportDeepviewDomain);
|
|
363
|
+
return /* @__PURE__ */ jsx3(
|
|
364
|
+
"a",
|
|
365
|
+
{
|
|
366
|
+
target: "_blank",
|
|
367
|
+
rel: `noreferrer noopener${!internal ? " nofollow" : ""}`,
|
|
368
|
+
href: url,
|
|
369
|
+
className: "items-center text-link",
|
|
370
|
+
onClick: (e) => {
|
|
371
|
+
e.stopPropagation();
|
|
372
|
+
handleNavigate(url, internal);
|
|
373
|
+
},
|
|
374
|
+
children: truncate(text, { truncate: 27, truncateLocation: "end" })
|
|
375
|
+
},
|
|
376
|
+
`${index}-autolink`
|
|
377
|
+
);
|
|
378
|
+
},
|
|
379
|
+
[phone, supportDeepviewDomain, handleNavigate]
|
|
380
|
+
);
|
|
381
|
+
const renderLink = useCallback(
|
|
382
|
+
(text, match, index) => {
|
|
383
|
+
const [url] = getUrl(match, phone);
|
|
384
|
+
if (supportDeepviewDomain && url.includes(supportDeepviewDomain)) {
|
|
385
|
+
const internal = true;
|
|
386
|
+
return /* @__PURE__ */ jsx3(
|
|
387
|
+
"a",
|
|
388
|
+
{
|
|
389
|
+
href: url,
|
|
390
|
+
className: "items-center text-link",
|
|
391
|
+
style: { alignSelf: "center" },
|
|
392
|
+
onClick: (e) => {
|
|
393
|
+
e.stopPropagation();
|
|
394
|
+
handleNavigate(url, internal);
|
|
395
|
+
},
|
|
396
|
+
children: text
|
|
397
|
+
},
|
|
398
|
+
`${index}-deeplink`
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
return renderDefaultLink(text, match, index);
|
|
402
|
+
},
|
|
403
|
+
[phone, supportDeepviewDomain, renderDefaultLink, handleNavigate]
|
|
404
|
+
);
|
|
405
|
+
const renderMentionData = useCallback(
|
|
406
|
+
(fmData, key) => {
|
|
407
|
+
const href = fmData.type === MENTION_TYPE.HASHTAG ? `/groups/${fmData.data.selectId}` : `/users/${fmData.data.selectId || fmData.data.id}`;
|
|
408
|
+
return /* @__PURE__ */ jsx3(
|
|
409
|
+
"a",
|
|
410
|
+
{
|
|
411
|
+
className: `context-menu-ios-disable cursor-pointer ${mentionClassName}`,
|
|
412
|
+
href,
|
|
413
|
+
onClick: (e) => {
|
|
414
|
+
e.stopPropagation();
|
|
415
|
+
e.nativeEvent.stopImmediatePropagation();
|
|
416
|
+
handleNavigate(href, true);
|
|
417
|
+
},
|
|
418
|
+
children: fmData.name
|
|
419
|
+
},
|
|
420
|
+
key + fmData.index
|
|
421
|
+
);
|
|
422
|
+
},
|
|
423
|
+
[mentionClassName, handleNavigate]
|
|
424
|
+
);
|
|
425
|
+
const renderTextNodes = useCallback(() => {
|
|
426
|
+
let text = textProp;
|
|
427
|
+
const uid = Math.floor(Math.random() * 1099511627776).toString(16);
|
|
428
|
+
const tokenRegexp = new RegExp(`(@__ELEMENT-${uid}-\\d+__@)`, "g");
|
|
429
|
+
const generateToken = /* @__PURE__ */ (() => {
|
|
430
|
+
let counter = 0;
|
|
431
|
+
return () => `@__ELEMENT-${uid}-${counter++}__@`;
|
|
432
|
+
})();
|
|
433
|
+
const matches = {};
|
|
434
|
+
try {
|
|
435
|
+
text = Autolinker.link(text || "", {
|
|
436
|
+
email,
|
|
437
|
+
phone,
|
|
438
|
+
urls: {
|
|
439
|
+
schemeMatches: true,
|
|
440
|
+
wwwMatches: true,
|
|
441
|
+
tldMatches: true
|
|
442
|
+
},
|
|
443
|
+
stripPrefix,
|
|
444
|
+
replaceFn: (match) => {
|
|
445
|
+
const token = generateToken();
|
|
446
|
+
matches[token] = match;
|
|
447
|
+
return token;
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
} catch {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
const newNodes = [];
|
|
454
|
+
text.split(tokenRegexp).filter((part) => !!part).forEach((part, index) => {
|
|
455
|
+
const match = matches[part];
|
|
456
|
+
if (!match) {
|
|
457
|
+
if (!mentionData || mentionData.length === 0) {
|
|
458
|
+
newNodes.push(part);
|
|
459
|
+
} else {
|
|
460
|
+
const newMentionData = checkMentionDataIndex(mentionData, [], part);
|
|
461
|
+
if (!newMentionData || newMentionData.length === 0) {
|
|
462
|
+
newNodes.push(part);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
for (let j = 0; j < newMentionData.length; j++) {
|
|
466
|
+
const curMentionData = newMentionData[j];
|
|
467
|
+
if (j === 0) {
|
|
468
|
+
const word = part.substring(0, curMentionData.index);
|
|
469
|
+
newNodes.push(word);
|
|
470
|
+
}
|
|
471
|
+
newNodes.push(renderMentionData(curMentionData, part + index));
|
|
472
|
+
const nextMentionData = j < newMentionData.length ? newMentionData[j + 1] : null;
|
|
473
|
+
if (nextMentionData) {
|
|
474
|
+
const word = part.substring(curMentionData.endIndex, nextMentionData.index);
|
|
475
|
+
newNodes.push(word);
|
|
476
|
+
} else {
|
|
477
|
+
const word = part.substring(curMentionData.endIndex, part.length);
|
|
478
|
+
newNodes.push(word);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
switch (match.getType()) {
|
|
485
|
+
case "email":
|
|
486
|
+
case "phone":
|
|
487
|
+
case "url":
|
|
488
|
+
newNodes.push(renderLink(match.getAnchorText(), match, index));
|
|
489
|
+
break;
|
|
490
|
+
default:
|
|
491
|
+
newNodes.push(part);
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
let textStyle = style;
|
|
496
|
+
const fontSize = style && style.fontSize ? style.fontSize : 12;
|
|
497
|
+
const pureEmojiCount = getPureEmojiSize(text.trim());
|
|
498
|
+
if (pureEmojiCount === 1) {
|
|
499
|
+
textStyle = { ...style, fontSize: fontSize * 2.5 };
|
|
500
|
+
} else if (pureEmojiCount === 2) {
|
|
501
|
+
textStyle = { ...style, fontSize: fontSize * 2 };
|
|
502
|
+
} else if (pureEmojiCount === 3) {
|
|
503
|
+
textStyle = { ...style, fontSize: fontSize * 1.5 };
|
|
504
|
+
}
|
|
505
|
+
return /* @__PURE__ */ jsx3("div", { style: textStyle, className, children: newNodes });
|
|
506
|
+
}, [
|
|
507
|
+
style,
|
|
508
|
+
email,
|
|
509
|
+
phone,
|
|
510
|
+
stripPrefix,
|
|
511
|
+
mentionData,
|
|
512
|
+
textProp,
|
|
513
|
+
className,
|
|
514
|
+
renderLink,
|
|
515
|
+
renderMentionData
|
|
516
|
+
]);
|
|
517
|
+
return renderTextNodes();
|
|
518
|
+
};
|
|
519
|
+
AutoLink.truncate = truncate;
|
|
520
|
+
var AutoLink_default = AutoLink;
|
|
521
|
+
|
|
522
|
+
// src/components/PostBody.tsx
|
|
523
|
+
import DOMPurify2 from "dompurify";
|
|
524
|
+
import { useMemo as useMemo3 } from "react";
|
|
525
|
+
|
|
526
|
+
// src/components/PostEmail.tsx
|
|
527
|
+
import { useEffect, useMemo as useMemo2, useRef } from "react";
|
|
528
|
+
import DOMPurify from "dompurify";
|
|
529
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
530
|
+
var EMAIL_PURIFY_CONFIG = {
|
|
531
|
+
ALLOWED_TAGS: [
|
|
532
|
+
// Structure
|
|
533
|
+
"html",
|
|
534
|
+
"head",
|
|
535
|
+
"body",
|
|
536
|
+
"style",
|
|
537
|
+
// Layout (email is table-based)
|
|
538
|
+
"table",
|
|
539
|
+
"thead",
|
|
540
|
+
"tbody",
|
|
541
|
+
"tr",
|
|
542
|
+
"th",
|
|
543
|
+
"td",
|
|
544
|
+
// Text
|
|
545
|
+
"p",
|
|
546
|
+
"span",
|
|
547
|
+
"div",
|
|
548
|
+
"h1",
|
|
549
|
+
"h2",
|
|
550
|
+
"h3",
|
|
551
|
+
"h4",
|
|
552
|
+
"h5",
|
|
553
|
+
"h6",
|
|
554
|
+
"b",
|
|
555
|
+
"strong",
|
|
556
|
+
"i",
|
|
557
|
+
"em",
|
|
558
|
+
"u",
|
|
559
|
+
"sub",
|
|
560
|
+
"sup",
|
|
561
|
+
"br",
|
|
562
|
+
"ul",
|
|
563
|
+
"ol",
|
|
564
|
+
"li",
|
|
565
|
+
// Media & links
|
|
566
|
+
"a",
|
|
567
|
+
"img"
|
|
568
|
+
],
|
|
569
|
+
ALLOWED_ATTR: [
|
|
570
|
+
// Styling — critical for email
|
|
571
|
+
"style",
|
|
572
|
+
"class",
|
|
573
|
+
"bgcolor",
|
|
574
|
+
"color",
|
|
575
|
+
// Table layout attributes (email-specific)
|
|
576
|
+
"width",
|
|
577
|
+
"height",
|
|
578
|
+
"align",
|
|
579
|
+
"valign",
|
|
580
|
+
"cellpadding",
|
|
581
|
+
"cellspacing",
|
|
582
|
+
"border",
|
|
583
|
+
"colspan",
|
|
584
|
+
"rowspan",
|
|
585
|
+
// Images
|
|
586
|
+
"src",
|
|
587
|
+
"alt",
|
|
588
|
+
// Links
|
|
589
|
+
"href",
|
|
590
|
+
"target",
|
|
591
|
+
"rel",
|
|
592
|
+
// Accessibility
|
|
593
|
+
"role",
|
|
594
|
+
"aria-label",
|
|
595
|
+
"aria-roledescription",
|
|
596
|
+
// Email-specific
|
|
597
|
+
"data-open-tracking",
|
|
598
|
+
"data-read-online-tooltip"
|
|
599
|
+
],
|
|
600
|
+
ALLOW_DATA_ATTR: false,
|
|
601
|
+
FORCE_BODY: false,
|
|
602
|
+
WHOLE_DOCUMENT: true
|
|
603
|
+
// preserves <head> with <style>
|
|
604
|
+
};
|
|
605
|
+
var sanitizeEmailHtml = (rawHtml) => {
|
|
606
|
+
const clean = DOMPurify.sanitize(rawHtml, EMAIL_PURIFY_CONFIG);
|
|
607
|
+
const doc = new DOMParser().parseFromString(clean, "text/html");
|
|
608
|
+
if (!doc.head) {
|
|
609
|
+
const head = doc.createElement("head");
|
|
610
|
+
doc.documentElement.insertBefore(head, doc.body);
|
|
611
|
+
}
|
|
612
|
+
const base = doc.createElement("base");
|
|
613
|
+
base.setAttribute("target", "_blank");
|
|
614
|
+
doc.head.appendChild(base);
|
|
615
|
+
const style = doc.createElement("style");
|
|
616
|
+
style.textContent = `
|
|
617
|
+
html, body {
|
|
618
|
+
margin: 0;
|
|
619
|
+
padding: 0;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
@media only screen and (max-width: 640px) {
|
|
623
|
+
table[style*="min-width"] {
|
|
624
|
+
min-width: 0 !important;
|
|
625
|
+
width: 100% !important;
|
|
626
|
+
max-width: 100% !important;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
td[style*="min-width"],
|
|
630
|
+
th[style*="min-width"],
|
|
631
|
+
div[style*="min-width"] {
|
|
632
|
+
min-width: 0 !important;
|
|
633
|
+
max-width: 100% !important;
|
|
634
|
+
box-sizing: border-box !important;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
img {
|
|
638
|
+
max-width: 100% !important;
|
|
639
|
+
height: auto !important;
|
|
640
|
+
}
|
|
641
|
+
}`;
|
|
642
|
+
doc.head.appendChild(style);
|
|
643
|
+
doc.querySelectorAll("a[href]").forEach((a) => {
|
|
644
|
+
a.setAttribute("target", "_blank");
|
|
645
|
+
a.setAttribute("rel", "noopener noreferrer nofollow");
|
|
646
|
+
});
|
|
647
|
+
return "<!DOCTYPE html>\n" + doc.documentElement.outerHTML;
|
|
648
|
+
};
|
|
649
|
+
var PostEmail = ({ html }) => {
|
|
650
|
+
const ref = useRef(null);
|
|
651
|
+
const cleanHtml = useMemo2(() => sanitizeEmailHtml(html), [html]);
|
|
652
|
+
useEffect(() => {
|
|
653
|
+
const iframe = ref.current;
|
|
654
|
+
if (!iframe) return;
|
|
655
|
+
let resizeObserver = null;
|
|
656
|
+
let rafId = null;
|
|
657
|
+
let timeoutIds = [];
|
|
658
|
+
const resizeIframe = () => {
|
|
659
|
+
try {
|
|
660
|
+
const doc = iframe.contentDocument;
|
|
661
|
+
if (!doc) return;
|
|
662
|
+
const body = doc.body;
|
|
663
|
+
const height = Math.max(
|
|
664
|
+
Math.ceil(body.scrollHeight),
|
|
665
|
+
Math.ceil(body.offsetHeight),
|
|
666
|
+
Math.ceil(body.getBoundingClientRect().height)
|
|
667
|
+
);
|
|
668
|
+
iframe.style.height = `${height + 2}px`;
|
|
669
|
+
} catch {
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
const scheduleResize = () => {
|
|
673
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
674
|
+
rafId = requestAnimationFrame(resizeIframe);
|
|
675
|
+
};
|
|
676
|
+
const handleLoad = () => {
|
|
677
|
+
scheduleResize();
|
|
678
|
+
try {
|
|
679
|
+
const doc = iframe.contentDocument;
|
|
680
|
+
if (!doc) return;
|
|
681
|
+
Array.from(doc.images).forEach((img) => {
|
|
682
|
+
img.addEventListener("load", scheduleResize);
|
|
683
|
+
img.addEventListener("error", scheduleResize);
|
|
684
|
+
});
|
|
685
|
+
resizeObserver = new ResizeObserver(() => {
|
|
686
|
+
scheduleResize();
|
|
687
|
+
});
|
|
688
|
+
resizeObserver.observe(doc.body);
|
|
689
|
+
timeoutIds = [
|
|
690
|
+
window.setTimeout(scheduleResize, 50),
|
|
691
|
+
window.setTimeout(scheduleResize, 150),
|
|
692
|
+
window.setTimeout(scheduleResize, 300),
|
|
693
|
+
window.setTimeout(scheduleResize, 600)
|
|
694
|
+
];
|
|
695
|
+
} catch {
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
const handleResize = () => {
|
|
699
|
+
scheduleResize();
|
|
700
|
+
};
|
|
701
|
+
iframe.addEventListener("load", handleLoad);
|
|
702
|
+
window.addEventListener("resize", handleResize);
|
|
703
|
+
return () => {
|
|
704
|
+
iframe.removeEventListener("load", handleLoad);
|
|
705
|
+
window.removeEventListener("resize", handleResize);
|
|
706
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
707
|
+
timeoutIds.forEach(clearTimeout);
|
|
708
|
+
resizeObserver?.disconnect();
|
|
709
|
+
try {
|
|
710
|
+
const doc = iframe.contentDocument;
|
|
711
|
+
if (!doc) return;
|
|
712
|
+
Array.from(doc.images).forEach((img) => {
|
|
713
|
+
img.removeEventListener("load", scheduleResize);
|
|
714
|
+
img.removeEventListener("error", scheduleResize);
|
|
715
|
+
});
|
|
716
|
+
} catch {
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
}, [cleanHtml]);
|
|
720
|
+
return /* @__PURE__ */ jsx4(
|
|
721
|
+
"iframe",
|
|
722
|
+
{
|
|
723
|
+
ref,
|
|
724
|
+
srcDoc: cleanHtml,
|
|
725
|
+
sandbox: "allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation",
|
|
726
|
+
className: "block w-full border-0"
|
|
727
|
+
}
|
|
728
|
+
);
|
|
729
|
+
};
|
|
730
|
+
var PostEmail_default = PostEmail;
|
|
731
|
+
|
|
732
|
+
// src/components/PostBody.tsx
|
|
733
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
734
|
+
var PURIFY_CONFIG = {
|
|
735
|
+
ALLOWED_TAGS: [
|
|
736
|
+
"p",
|
|
737
|
+
"br",
|
|
738
|
+
"b",
|
|
739
|
+
"i",
|
|
740
|
+
"em",
|
|
741
|
+
"strong",
|
|
742
|
+
"a",
|
|
743
|
+
"ul",
|
|
744
|
+
"ol",
|
|
745
|
+
"li",
|
|
746
|
+
"h1",
|
|
747
|
+
"h2",
|
|
748
|
+
"h3",
|
|
749
|
+
"h4",
|
|
750
|
+
"h5",
|
|
751
|
+
"h6",
|
|
752
|
+
"blockquote",
|
|
753
|
+
"code",
|
|
754
|
+
"pre",
|
|
755
|
+
"span",
|
|
756
|
+
"div",
|
|
757
|
+
"img",
|
|
758
|
+
"video",
|
|
759
|
+
"figure",
|
|
760
|
+
"figcaption",
|
|
761
|
+
"table",
|
|
762
|
+
"thead",
|
|
763
|
+
"tbody",
|
|
764
|
+
"tr",
|
|
765
|
+
"th",
|
|
766
|
+
"td",
|
|
767
|
+
"hr",
|
|
768
|
+
"sub",
|
|
769
|
+
"sup",
|
|
770
|
+
"s",
|
|
771
|
+
"u"
|
|
772
|
+
],
|
|
773
|
+
ALLOWED_ATTR: [
|
|
774
|
+
"href",
|
|
775
|
+
"controls",
|
|
776
|
+
"target",
|
|
777
|
+
"rel",
|
|
778
|
+
"class",
|
|
779
|
+
"id",
|
|
780
|
+
"src",
|
|
781
|
+
"alt",
|
|
782
|
+
"title",
|
|
783
|
+
"width",
|
|
784
|
+
"height",
|
|
785
|
+
"data-*"
|
|
786
|
+
],
|
|
787
|
+
ALLOW_DATA_ATTR: true,
|
|
788
|
+
ADD_ATTR: ["target"],
|
|
789
|
+
FORBID_TAGS: ["script", "style", "iframe", "object", "embed", "form"],
|
|
790
|
+
FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover"]
|
|
791
|
+
};
|
|
792
|
+
var VOID_TAGS = /* @__PURE__ */ new Set([
|
|
793
|
+
"BR",
|
|
794
|
+
"HR",
|
|
795
|
+
"IMG",
|
|
796
|
+
"VIDEO",
|
|
797
|
+
"INPUT",
|
|
798
|
+
"AREA",
|
|
799
|
+
"BASE",
|
|
800
|
+
"COL",
|
|
801
|
+
"LINK",
|
|
802
|
+
"META",
|
|
803
|
+
"PARAM",
|
|
804
|
+
"SOURCE",
|
|
805
|
+
"TRACK",
|
|
806
|
+
"WBR"
|
|
807
|
+
]);
|
|
808
|
+
var removeEmpty = (el) => {
|
|
809
|
+
Array.from(el.children).forEach(removeEmpty);
|
|
810
|
+
if (VOID_TAGS.has(el.tagName)) return;
|
|
811
|
+
if (!el.textContent?.trim() && el.children.length === 0) el.remove();
|
|
812
|
+
};
|
|
813
|
+
var PostBody = ({
|
|
814
|
+
textContent,
|
|
815
|
+
showFull = true,
|
|
816
|
+
isPostDetail,
|
|
817
|
+
isRichContent = false,
|
|
818
|
+
hideEmailDescription = false,
|
|
819
|
+
isEmailPost = false,
|
|
820
|
+
onNavigate,
|
|
821
|
+
supportDeepviewDomain
|
|
822
|
+
}) => {
|
|
823
|
+
const { plain, html, truncatedPlain, mentionData } = textContent;
|
|
824
|
+
const { sanitizedHtml, feedSanitizedHtml } = useMemo3(() => {
|
|
825
|
+
if (!html) return { sanitizedHtml: null, feedSanitizedHtml: null };
|
|
826
|
+
const sanitized = DOMPurify2.sanitize(html, PURIFY_CONFIG);
|
|
827
|
+
if (typeof document === "undefined") {
|
|
828
|
+
return { sanitizedHtml: sanitized, feedSanitizedHtml: sanitized };
|
|
829
|
+
}
|
|
830
|
+
const feedContainer = document.createElement("div");
|
|
831
|
+
feedContainer.innerHTML = sanitized;
|
|
832
|
+
let keptOne = false;
|
|
833
|
+
feedContainer.querySelectorAll("img, video").forEach((el) => {
|
|
834
|
+
if (!keptOne) {
|
|
835
|
+
keptOne = true;
|
|
836
|
+
} else {
|
|
837
|
+
el.remove();
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
removeEmpty(feedContainer);
|
|
841
|
+
return {
|
|
842
|
+
sanitizedHtml: sanitized,
|
|
843
|
+
feedSanitizedHtml: feedContainer.innerHTML
|
|
844
|
+
};
|
|
845
|
+
}, [html]);
|
|
846
|
+
const { subject } = textContent;
|
|
847
|
+
const displayText = showFull ? plain : truncatedPlain;
|
|
848
|
+
const hasHtml = !!sanitizedHtml;
|
|
849
|
+
const hasMeaningfulHtmlText = hasMeaningfulHtml(sanitizedHtml);
|
|
850
|
+
const detailProseElement = useMemo3(
|
|
851
|
+
() => sanitizedHtml ? /* @__PURE__ */ jsx5(
|
|
852
|
+
"div",
|
|
853
|
+
{
|
|
854
|
+
className: "prose prose-p:my-2! prose-a:text-action-primary! prose-a:no-underline! prose-img:my-4! prose-video:my-4! px-5! pb-4! max-w-full leading-relaxed overflow-hidden",
|
|
855
|
+
dangerouslySetInnerHTML: { __html: sanitizedHtml }
|
|
856
|
+
}
|
|
857
|
+
) : null,
|
|
858
|
+
[sanitizedHtml]
|
|
859
|
+
);
|
|
860
|
+
const feedProseElement = useMemo3(
|
|
861
|
+
() => feedSanitizedHtml ? /* @__PURE__ */ jsx5(
|
|
862
|
+
"div",
|
|
863
|
+
{
|
|
864
|
+
className: "prose *:px-4! *:data-[media='true']:px-0! *:data-link-preview:mx-4! [&>[data-media='true']>img]:rounded-none! [&>[data-media='true']>video]:rounded-none! [&>[data-media='true']>video]:size-full! prose-video:size-full! *:data-[media='true']:my-2 [&>div]:last-of-type:mb-0! prose-img:my-0! prose-img:w-full prose-video:my-0! prose-p:my-2! prose-a:text-action-primary! prose-a:no-underline! pb-4 max-w-full leading-relaxed line-clamp-4 overflow-hidden",
|
|
865
|
+
dangerouslySetInnerHTML: { __html: feedSanitizedHtml }
|
|
866
|
+
}
|
|
867
|
+
) : null,
|
|
868
|
+
[feedSanitizedHtml]
|
|
869
|
+
);
|
|
870
|
+
if ((!displayText || typeof displayText !== "string") && !hasHtml) {
|
|
871
|
+
return null;
|
|
872
|
+
}
|
|
873
|
+
const renderAutoLink = () => {
|
|
874
|
+
if (!displayText || typeof displayText !== "string") return null;
|
|
875
|
+
return /* @__PURE__ */ jsx5(
|
|
876
|
+
AutoLink_default,
|
|
877
|
+
{
|
|
878
|
+
text: displayText,
|
|
879
|
+
mentionData,
|
|
880
|
+
onNavigate,
|
|
881
|
+
supportDeepviewDomain,
|
|
882
|
+
className: "whitespace-normal px-4 pb-4 leading-relaxed text-gray-800",
|
|
883
|
+
style: {
|
|
884
|
+
whiteSpace: "pre-wrap",
|
|
885
|
+
wordBreak: "break-word"
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
);
|
|
889
|
+
};
|
|
890
|
+
if (isPostDetail) {
|
|
891
|
+
if (isEmailPost && html) {
|
|
892
|
+
return /* @__PURE__ */ jsxs2("div", { className: "relative flex-1 max-h-screen w-full overflow-x-hidden overflow-y-auto xl:px-0 px-5", children: [
|
|
893
|
+
/* @__PURE__ */ jsx5("h1", { className: "text-2xl font-semibold text-gray-900 leading-snug mt-5 mb-3 px-5", children: subject }),
|
|
894
|
+
/* @__PURE__ */ jsx5(PostEmail_default, { html })
|
|
895
|
+
] });
|
|
896
|
+
}
|
|
897
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex-1", children: [
|
|
898
|
+
!hasMeaningfulHtmlText && /* @__PURE__ */ jsx5("div", { children: renderAutoLink() }),
|
|
899
|
+
sanitizedHtml && hasMeaningfulHtmlText && /* @__PURE__ */ jsx5("div", { "data-theme": "select-post-builder", className: "w-full max-w-full", children: detailProseElement })
|
|
900
|
+
] });
|
|
901
|
+
}
|
|
902
|
+
if (isRichContent && feedSanitizedHtml && hasMeaningfulHtmlText) {
|
|
903
|
+
return /* @__PURE__ */ jsx5("div", { className: cn("flex-1 pb-4"), "data-theme": "select-post-builder", children: feedProseElement });
|
|
904
|
+
}
|
|
905
|
+
if (subject) {
|
|
906
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex-1 px-4 pb-4", children: [
|
|
907
|
+
/* @__PURE__ */ jsx5("h1", { className: "text-2xl font-semibold text-gray-900 leading-snug mb-1", children: subject }),
|
|
908
|
+
!hideEmailDescription && displayText && typeof displayText === "string" && /* @__PURE__ */ jsx5(
|
|
909
|
+
AutoLink_default,
|
|
910
|
+
{
|
|
911
|
+
text: displayText,
|
|
912
|
+
mentionData,
|
|
913
|
+
onNavigate,
|
|
914
|
+
supportDeepviewDomain,
|
|
915
|
+
className: "whitespace-normal leading-relaxed text-gray-600 line-clamp-3",
|
|
916
|
+
style: { whiteSpace: "pre-wrap", wordBreak: "break-word" }
|
|
917
|
+
}
|
|
918
|
+
)
|
|
919
|
+
] });
|
|
920
|
+
}
|
|
921
|
+
return /* @__PURE__ */ jsx5("div", { className: "flex-1", children: /* @__PURE__ */ jsx5("div", { children: renderAutoLink() }) });
|
|
922
|
+
};
|
|
923
|
+
var PostBody_default = PostBody;
|
|
924
|
+
|
|
925
|
+
// src/components/MediaView.tsx
|
|
926
|
+
import { useMemo as useMemo5 } from "react";
|
|
927
|
+
|
|
928
|
+
// src/components/AsyncImage.tsx
|
|
929
|
+
import { useCallback as useCallback2, useMemo as useMemo4 } from "react";
|
|
930
|
+
import { Gallery, Item } from "react-photoswipe-gallery";
|
|
931
|
+
import "photoswipe/dist/photoswipe.css";
|
|
932
|
+
|
|
933
|
+
// src/components/Loader.tsx
|
|
934
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
935
|
+
var Loader = ({
|
|
936
|
+
type = "page_loader",
|
|
937
|
+
fullScreen = false
|
|
938
|
+
}) => {
|
|
939
|
+
const style = {
|
|
940
|
+
page_loader: "after:border-border after:border-t-action-primary",
|
|
941
|
+
upload_loader: "after:border-foreground after:border-t-background bg-foreground rounded-full"
|
|
942
|
+
};
|
|
943
|
+
const showLoader = () => {
|
|
944
|
+
return /* @__PURE__ */ jsx6("div", { className: "absolute left-1/2 top-1/2 z-20 -translate-x-1/2 -translate-y-1/2", children: /* @__PURE__ */ jsx6(
|
|
945
|
+
"div",
|
|
946
|
+
{
|
|
947
|
+
className: `after:contents-[''] flex h-full items-center justify-center after:h-10 after:w-10 after:animate-spin after:rounded-[50%] after:border-4 ${style[type]} `
|
|
948
|
+
}
|
|
949
|
+
) });
|
|
950
|
+
};
|
|
951
|
+
if (fullScreen) {
|
|
952
|
+
return /* @__PURE__ */ jsx6("div", { className: "h-screen-safe-14 lg:h-screen-safe-16", children: showLoader() });
|
|
953
|
+
}
|
|
954
|
+
return showLoader();
|
|
955
|
+
};
|
|
956
|
+
var Loader_default = Loader;
|
|
957
|
+
|
|
958
|
+
// src/components/AsyncImage.tsx
|
|
959
|
+
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
960
|
+
var isVideo = (url) => {
|
|
961
|
+
return url?.toLowerCase().endsWith(".mp4") || url?.toLowerCase().endsWith(".webm") || url?.toLowerCase().endsWith(".ogg");
|
|
962
|
+
};
|
|
963
|
+
var isImage = (url) => {
|
|
964
|
+
return url?.toLowerCase().endsWith(".jpeg") || url?.toLowerCase().endsWith(".jpg") || url?.toLowerCase().endsWith(".png") || url?.toLowerCase().endsWith(".webp") || url?.toLowerCase().endsWith(".gif") || url?.toLowerCase().endsWith(".avif");
|
|
965
|
+
};
|
|
966
|
+
var calVideoRatio = (width, height) => {
|
|
967
|
+
let ratio = 1;
|
|
968
|
+
if (width > 0 && height > 0) {
|
|
969
|
+
ratio = width / height;
|
|
970
|
+
if (ratio < 0.7) {
|
|
971
|
+
ratio = 0.7;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return `${ratio}`;
|
|
975
|
+
};
|
|
976
|
+
var AsyncImage = ({
|
|
977
|
+
data,
|
|
978
|
+
ratio,
|
|
979
|
+
className,
|
|
980
|
+
isPostDetail,
|
|
981
|
+
item,
|
|
982
|
+
onCardPress,
|
|
983
|
+
src = "",
|
|
984
|
+
alt
|
|
985
|
+
}) => {
|
|
986
|
+
const {
|
|
987
|
+
placeholder = {
|
|
988
|
+
isBase64: false,
|
|
989
|
+
url: ""
|
|
990
|
+
}
|
|
991
|
+
} = item.sources || {};
|
|
992
|
+
const placeholderUrl = useMemo4(() => {
|
|
993
|
+
const url = placeholder.isBase64 ? `data:${item.imageType};base64,${placeholder.url}` : placeholder.url;
|
|
994
|
+
return url;
|
|
995
|
+
}, [placeholder.isBase64, placeholder.url, item.imageType]);
|
|
996
|
+
const handleClick = useCallback2(
|
|
997
|
+
(e) => {
|
|
998
|
+
e.stopPropagation();
|
|
999
|
+
if (onCardPress) {
|
|
1000
|
+
onCardPress();
|
|
1001
|
+
}
|
|
1002
|
+
},
|
|
1003
|
+
[onCardPress]
|
|
1004
|
+
);
|
|
1005
|
+
const showUploadImg = (item2) => {
|
|
1006
|
+
return item2.imageType === "image/heic" ? /* @__PURE__ */ jsx7(
|
|
1007
|
+
"img",
|
|
1008
|
+
{
|
|
1009
|
+
src,
|
|
1010
|
+
alt: alt ?? "",
|
|
1011
|
+
className,
|
|
1012
|
+
style: {
|
|
1013
|
+
aspectRatio: `${ratio}` || "auto"
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
) : /* @__PURE__ */ jsx7(
|
|
1017
|
+
"div",
|
|
1018
|
+
{
|
|
1019
|
+
className,
|
|
1020
|
+
style: {
|
|
1021
|
+
aspectRatio: `${ratio}` || "auto"
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
);
|
|
1025
|
+
};
|
|
1026
|
+
const uploadVideoPost = item.type.includes("ToUpload");
|
|
1027
|
+
const showUploadingMedia = () => /* @__PURE__ */ jsxs3(
|
|
1028
|
+
"div",
|
|
1029
|
+
{
|
|
1030
|
+
className: "relative h-full w-full",
|
|
1031
|
+
style: {
|
|
1032
|
+
aspectRatio: `${ratio}` || "auto"
|
|
1033
|
+
},
|
|
1034
|
+
children: [
|
|
1035
|
+
uploadVideoPost && /* @__PURE__ */ jsx7(Loader_default, { type: "upload_loader" }),
|
|
1036
|
+
/* @__PURE__ */ jsx7(
|
|
1037
|
+
"video",
|
|
1038
|
+
{
|
|
1039
|
+
title: "Video Upload Preview",
|
|
1040
|
+
width: "100%",
|
|
1041
|
+
height: "100%",
|
|
1042
|
+
className,
|
|
1043
|
+
style: {
|
|
1044
|
+
aspectRatio: `${ratio}` || "auto"
|
|
1045
|
+
},
|
|
1046
|
+
children: item.file instanceof Blob && /* @__PURE__ */ jsx7("source", { src: URL.createObjectURL(item.file), type: item.file.type })
|
|
1047
|
+
}
|
|
1048
|
+
),
|
|
1049
|
+
/* @__PURE__ */ jsx7(
|
|
1050
|
+
AppIcon,
|
|
1051
|
+
{
|
|
1052
|
+
name: "video",
|
|
1053
|
+
className: `absolute bottom-2 left-2 text-background`
|
|
1054
|
+
}
|
|
1055
|
+
)
|
|
1056
|
+
]
|
|
1057
|
+
}
|
|
1058
|
+
);
|
|
1059
|
+
const renderMediaItem = useCallback2(
|
|
1060
|
+
(media) => {
|
|
1061
|
+
const originalInfo = media?.sources?.original || {};
|
|
1062
|
+
let thumbnailInfo = media?.sources?.thumbnail;
|
|
1063
|
+
if (originalInfo?.url?.endsWith("gif") || !isImage(media?.sources?.thumbnail?.url)) {
|
|
1064
|
+
thumbnailInfo = originalInfo;
|
|
1065
|
+
}
|
|
1066
|
+
const aspectRatio = `${ratio}` || calVideoRatio(originalInfo.width, originalInfo.height) || "auto";
|
|
1067
|
+
const hasStableKeys = Boolean(media.key && item.key);
|
|
1068
|
+
const isCurrentItem = hasStableKeys ? media.key === item.key : originalInfo.url === src;
|
|
1069
|
+
const display = isCurrentItem ? "block" : "none";
|
|
1070
|
+
const isBlobVideo = originalInfo?.url?.startsWith("blob:") && typeof media.imageType === "string" && media.imageType.startsWith("video/");
|
|
1071
|
+
if (isBlobVideo) {
|
|
1072
|
+
return /* @__PURE__ */ jsxs3(
|
|
1073
|
+
"div",
|
|
1074
|
+
{
|
|
1075
|
+
onClick: handleClick,
|
|
1076
|
+
className: className + " media-item",
|
|
1077
|
+
style: { aspectRatio, display },
|
|
1078
|
+
children: [
|
|
1079
|
+
/* @__PURE__ */ jsx7(
|
|
1080
|
+
"video",
|
|
1081
|
+
{
|
|
1082
|
+
src: originalInfo.url,
|
|
1083
|
+
muted: true,
|
|
1084
|
+
playsInline: true,
|
|
1085
|
+
preload: "metadata",
|
|
1086
|
+
className,
|
|
1087
|
+
style: {
|
|
1088
|
+
aspectRatio,
|
|
1089
|
+
display: "block",
|
|
1090
|
+
width: "100%",
|
|
1091
|
+
height: "100%"
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
),
|
|
1095
|
+
/* @__PURE__ */ jsx7(
|
|
1096
|
+
AppIcon,
|
|
1097
|
+
{
|
|
1098
|
+
name: "video",
|
|
1099
|
+
className: "absolute bottom-2 left-2 text-background"
|
|
1100
|
+
}
|
|
1101
|
+
),
|
|
1102
|
+
/* @__PURE__ */ jsx7(
|
|
1103
|
+
AppIcon,
|
|
1104
|
+
{
|
|
1105
|
+
name: "circlePlay",
|
|
1106
|
+
className: "size-10 bg-foreground/20 hover:bg-foreground/40 transition-colors duration-300 rounded-full absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-3xl text-background"
|
|
1107
|
+
}
|
|
1108
|
+
)
|
|
1109
|
+
]
|
|
1110
|
+
},
|
|
1111
|
+
media.key
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
if (isVideo(originalInfo.url)) {
|
|
1115
|
+
return /* @__PURE__ */ jsx7(
|
|
1116
|
+
Item,
|
|
1117
|
+
{
|
|
1118
|
+
content: /* @__PURE__ */ jsx7(
|
|
1119
|
+
"div",
|
|
1120
|
+
{
|
|
1121
|
+
className: "flex h-full w-full items-center justify-center",
|
|
1122
|
+
style: {
|
|
1123
|
+
aspectRatio
|
|
1124
|
+
},
|
|
1125
|
+
children: /* @__PURE__ */ jsx7(
|
|
1126
|
+
"video",
|
|
1127
|
+
{
|
|
1128
|
+
height: "100%",
|
|
1129
|
+
width: "100%",
|
|
1130
|
+
className: "aspect-video",
|
|
1131
|
+
controls: true,
|
|
1132
|
+
autoPlay: true,
|
|
1133
|
+
children: /* @__PURE__ */ jsx7("source", { src: originalInfo.url, type: media.imageType })
|
|
1134
|
+
}
|
|
1135
|
+
)
|
|
1136
|
+
}
|
|
1137
|
+
),
|
|
1138
|
+
children: ({ ref, open }) => /* @__PURE__ */ jsxs3("div", { onClick: isPostDetail ? open : handleClick, children: [
|
|
1139
|
+
/* @__PURE__ */ jsx7(
|
|
1140
|
+
"img",
|
|
1141
|
+
{
|
|
1142
|
+
src: thumbnailInfo.url,
|
|
1143
|
+
ref,
|
|
1144
|
+
alt: alt ?? "",
|
|
1145
|
+
className: className + " media-item ",
|
|
1146
|
+
style: {
|
|
1147
|
+
aspectRatio,
|
|
1148
|
+
display
|
|
1149
|
+
},
|
|
1150
|
+
onClick: isPostDetail ? open : handleClick
|
|
1151
|
+
}
|
|
1152
|
+
),
|
|
1153
|
+
/* @__PURE__ */ jsx7(
|
|
1154
|
+
AppIcon,
|
|
1155
|
+
{
|
|
1156
|
+
name: "video",
|
|
1157
|
+
className: `absolute bottom-2 left-2 text-background`,
|
|
1158
|
+
onClick: isPostDetail ? open : handleClick,
|
|
1159
|
+
ref,
|
|
1160
|
+
style: {
|
|
1161
|
+
aspectRatio,
|
|
1162
|
+
display
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
),
|
|
1166
|
+
/* @__PURE__ */ jsx7(
|
|
1167
|
+
AppIcon,
|
|
1168
|
+
{
|
|
1169
|
+
name: "circlePlay",
|
|
1170
|
+
className: `size-10 bg-foreground/20 hover:bg-foreground/40 transition-colors duration-300 rounded-full absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-3xl text-background`,
|
|
1171
|
+
onClick: isPostDetail ? open : handleClick,
|
|
1172
|
+
ref,
|
|
1173
|
+
style: {
|
|
1174
|
+
aspectRatio,
|
|
1175
|
+
display
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
)
|
|
1179
|
+
] })
|
|
1180
|
+
},
|
|
1181
|
+
media.key
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
return /* @__PURE__ */ jsx7(
|
|
1185
|
+
Item,
|
|
1186
|
+
{
|
|
1187
|
+
width: originalInfo.width,
|
|
1188
|
+
height: originalInfo.height,
|
|
1189
|
+
original: originalInfo.url,
|
|
1190
|
+
thumbnail: thumbnailInfo.url,
|
|
1191
|
+
children: ({ open, ref }) => /* @__PURE__ */ jsx7(
|
|
1192
|
+
"img",
|
|
1193
|
+
{
|
|
1194
|
+
onClick: isPostDetail ? open : handleClick,
|
|
1195
|
+
ref,
|
|
1196
|
+
src: originalInfo.url || thumbnailInfo.url,
|
|
1197
|
+
alt: alt ?? "",
|
|
1198
|
+
className,
|
|
1199
|
+
style: {
|
|
1200
|
+
aspectRatio,
|
|
1201
|
+
display
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
)
|
|
1205
|
+
},
|
|
1206
|
+
media.key
|
|
1207
|
+
);
|
|
1208
|
+
},
|
|
1209
|
+
[className, handleClick, isPostDetail, item.key, ratio, src]
|
|
1210
|
+
);
|
|
1211
|
+
const handleMediaItems = () => {
|
|
1212
|
+
return /* @__PURE__ */ jsx7(Gallery, { options: { showHideAnimationType: "fade" }, children: data?.map((media) => renderMediaItem(media)) });
|
|
1213
|
+
};
|
|
1214
|
+
return /* @__PURE__ */ jsxs3(
|
|
1215
|
+
"div",
|
|
1216
|
+
{
|
|
1217
|
+
style: {
|
|
1218
|
+
backgroundImage: `url(${placeholderUrl})`
|
|
1219
|
+
},
|
|
1220
|
+
className: "h-full w-full bg-cover bg-center bg-no-repeat",
|
|
1221
|
+
children: [
|
|
1222
|
+
item.type === postItemType.MEDIA_ITEM_TO_UPLOAD && showUploadingMedia(),
|
|
1223
|
+
item.type === postItemType.IMAGE_ITEM_TO_UPLOAD && showUploadImg(item),
|
|
1224
|
+
item.type !== postItemType.IMAGE_ITEM_TO_UPLOAD && item.type !== postItemType.MEDIA_ITEM_TO_UPLOAD && handleMediaItems()
|
|
1225
|
+
]
|
|
1226
|
+
}
|
|
1227
|
+
);
|
|
1228
|
+
};
|
|
1229
|
+
var AsyncImage_default = AsyncImage;
|
|
1230
|
+
|
|
1231
|
+
// src/components/MediaView.tsx
|
|
1232
|
+
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1233
|
+
var MediaView = ({
|
|
1234
|
+
item,
|
|
1235
|
+
className,
|
|
1236
|
+
handleLightbox,
|
|
1237
|
+
additionalImagesCount,
|
|
1238
|
+
ratio,
|
|
1239
|
+
data,
|
|
1240
|
+
isPostDetail,
|
|
1241
|
+
onCardPress
|
|
1242
|
+
}) => {
|
|
1243
|
+
const mediaSrc = useMemo5(() => {
|
|
1244
|
+
if (item.type === postItemType.IMAGE_ITEM_TO_UPLOAD || item.type === postItemType.MEDIA_ITEM_TO_UPLOAD) {
|
|
1245
|
+
return URL.createObjectURL(item.file);
|
|
1246
|
+
}
|
|
1247
|
+
return item.sources?.original?.url ?? "";
|
|
1248
|
+
}, [item.file, item.sources?.original?.url, item.type]);
|
|
1249
|
+
if (item.type === postItemType.POLL_TEXT_ITEM) {
|
|
1250
|
+
const textViewClass = `${className} aspect-square`;
|
|
1251
|
+
return /* @__PURE__ */ jsx8(
|
|
1252
|
+
"div",
|
|
1253
|
+
{
|
|
1254
|
+
onClick: handleLightbox,
|
|
1255
|
+
className: textViewClass,
|
|
1256
|
+
style: {
|
|
1257
|
+
backgroundColor: item.option_color
|
|
1258
|
+
},
|
|
1259
|
+
children: /* @__PURE__ */ jsx8("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2", children: /* @__PURE__ */ jsx8("p", { className: "text-center text-lg font-bold text-background", children: item.text }) })
|
|
1260
|
+
},
|
|
1261
|
+
item.key
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
if (item.type === postItemType.IMAGE_ITEM || item.type === postItemType.POLL_IMAGE_ITEM || item.type === postItemType.GIF_ITEM || item.type === postItemType.IMAGE_ITEM_TO_UPLOAD || item.type === postItemType.MEDIA_ITEM || item.type === postItemType.MEDIA_ITEM_TO_UPLOAD || item.type === postItemType.POLL_MEDIA_ITEM) {
|
|
1265
|
+
return /* @__PURE__ */ jsxs4("div", { onClick: handleLightbox, className, children: [
|
|
1266
|
+
item.type.includes("ToUpload") && /* @__PURE__ */ jsx8(Loader_default, { type: "upload_loader" }),
|
|
1267
|
+
/* @__PURE__ */ jsx8(
|
|
1268
|
+
AsyncImage_default,
|
|
1269
|
+
{
|
|
1270
|
+
alt: mediaSrc,
|
|
1271
|
+
src: mediaSrc,
|
|
1272
|
+
className,
|
|
1273
|
+
ratio,
|
|
1274
|
+
item,
|
|
1275
|
+
data: data || [],
|
|
1276
|
+
isPostDetail,
|
|
1277
|
+
onCardPress
|
|
1278
|
+
}
|
|
1279
|
+
),
|
|
1280
|
+
additionalImagesCount && /* @__PURE__ */ jsx8("div", { className: "absolute right-1 top-0", children: /* @__PURE__ */ jsx8("p", { className: "text-4xl font-bold text-muted-foreground", children: `+${additionalImagesCount}` }) })
|
|
1281
|
+
] }, item.key);
|
|
1282
|
+
}
|
|
1283
|
+
return null;
|
|
1284
|
+
};
|
|
1285
|
+
var MediaView_default = MediaView;
|
|
1286
|
+
|
|
1287
|
+
// src/components/PostPollLayout/pollUtils.ts
|
|
1288
|
+
var getOptionRateV2 = (item, voteResult) => {
|
|
1289
|
+
if (!voteResult) return "0%";
|
|
1290
|
+
const voteItem = voteResult.options.find(
|
|
1291
|
+
(option) => option.option_id === item.option_id
|
|
1292
|
+
);
|
|
1293
|
+
const totalCount = voteResult.options.reduce(
|
|
1294
|
+
(total, option) => total + option.count,
|
|
1295
|
+
0
|
|
1296
|
+
);
|
|
1297
|
+
if (voteItem && totalCount > 0) {
|
|
1298
|
+
return (voteItem.count / totalCount * 100).toFixed(0) + "%";
|
|
1299
|
+
}
|
|
1300
|
+
return "0%";
|
|
1301
|
+
};
|
|
1302
|
+
var getVoteInfo = (item, voteResult) => {
|
|
1303
|
+
const isAppOwnerVoted = !!voteResult?.user_vote_option_id;
|
|
1304
|
+
const isVoteItem = !!voteResult?.options.find(
|
|
1305
|
+
(option) => option.option_id === item.option_id && option.option_id === voteResult.user_vote_option_id
|
|
1306
|
+
);
|
|
1307
|
+
return {
|
|
1308
|
+
rate: getOptionRateV2(item, voteResult),
|
|
1309
|
+
isAppOwnerVoted,
|
|
1310
|
+
isVoteItem
|
|
1311
|
+
};
|
|
1312
|
+
};
|
|
1313
|
+
|
|
1314
|
+
// src/components/PostPollLayout/PostPollIResultView.tsx
|
|
1315
|
+
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1316
|
+
var PostPollIResultView = ({
|
|
1317
|
+
type,
|
|
1318
|
+
item,
|
|
1319
|
+
voteResult,
|
|
1320
|
+
isPostOwner
|
|
1321
|
+
}) => {
|
|
1322
|
+
const voteInfo = getVoteInfo(item, voteResult);
|
|
1323
|
+
const textCss = voteInfo.isVoteItem ? "#FFFFFF" : item.option_color;
|
|
1324
|
+
const backgroundCss = voteInfo.isVoteItem ? item.option_color : "#FFFFFF";
|
|
1325
|
+
const totalVotes = voteResult?.options.reduce((sum, o) => sum + o.count, 0) ?? 0;
|
|
1326
|
+
if (!voteInfo.isAppOwnerVoted && !isPostOwner || totalVotes === 0) {
|
|
1327
|
+
return null;
|
|
1328
|
+
}
|
|
1329
|
+
if (type === "SINGLE_LEFT") {
|
|
1330
|
+
return /* @__PURE__ */ jsxs5(
|
|
1331
|
+
"div",
|
|
1332
|
+
{
|
|
1333
|
+
className: "absolute top-0 m-6 flex flex-row items-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md",
|
|
1334
|
+
style: { backgroundColor: backgroundCss },
|
|
1335
|
+
children: [
|
|
1336
|
+
/* @__PURE__ */ jsx9("p", { className: "text-sm font-bold", style: { color: textCss }, children: voteInfo.rate }),
|
|
1337
|
+
/* @__PURE__ */ jsx9(
|
|
1338
|
+
AppIcon,
|
|
1339
|
+
{
|
|
1340
|
+
name: "thumbUp",
|
|
1341
|
+
size: 16,
|
|
1342
|
+
className: "ml-2",
|
|
1343
|
+
style: { color: textCss }
|
|
1344
|
+
}
|
|
1345
|
+
)
|
|
1346
|
+
]
|
|
1347
|
+
}
|
|
1348
|
+
);
|
|
1349
|
+
}
|
|
1350
|
+
if (type === "SINGLE_RIGHT") {
|
|
1351
|
+
return /* @__PURE__ */ jsxs5(
|
|
1352
|
+
"div",
|
|
1353
|
+
{
|
|
1354
|
+
className: "absolute right-0 top-0 m-6 flex flex-row items-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md",
|
|
1355
|
+
style: { backgroundColor: backgroundCss },
|
|
1356
|
+
children: [
|
|
1357
|
+
/* @__PURE__ */ jsx9("p", { className: "text-sm font-bold", style: { color: textCss }, children: voteInfo.rate }),
|
|
1358
|
+
/* @__PURE__ */ jsx9(
|
|
1359
|
+
AppIcon,
|
|
1360
|
+
{
|
|
1361
|
+
name: "thumbDown",
|
|
1362
|
+
size: 16,
|
|
1363
|
+
className: "ml-2",
|
|
1364
|
+
style: { color: textCss }
|
|
1365
|
+
}
|
|
1366
|
+
)
|
|
1367
|
+
]
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
return /* @__PURE__ */ jsx9(
|
|
1372
|
+
"div",
|
|
1373
|
+
{
|
|
1374
|
+
className: "absolute top-0 m-3 flex items-center justify-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md",
|
|
1375
|
+
style: { backgroundColor: backgroundCss },
|
|
1376
|
+
children: /* @__PURE__ */ jsx9("p", { className: "text-sm font-bold", style: { color: textCss }, children: voteInfo.rate })
|
|
1377
|
+
}
|
|
1378
|
+
);
|
|
1379
|
+
};
|
|
1380
|
+
var PostPollIResultView_default = PostPollIResultView;
|
|
1381
|
+
|
|
1382
|
+
// src/components/PostPollLayout/PostPollIButtonView.tsx
|
|
1383
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1384
|
+
var PostPollIButtonView = ({
|
|
1385
|
+
type,
|
|
1386
|
+
item,
|
|
1387
|
+
voteResult,
|
|
1388
|
+
onVotePress
|
|
1389
|
+
}) => {
|
|
1390
|
+
const voteInfo = getVoteInfo(item, voteResult);
|
|
1391
|
+
const handleVoting = (e) => {
|
|
1392
|
+
e.stopPropagation();
|
|
1393
|
+
if (!voteInfo.isVoteItem) onVotePress(item);
|
|
1394
|
+
};
|
|
1395
|
+
const voteLabel = voteInfo.isVoteItem ? `Voted: ${item.text || "this option"}` : `Vote for ${item.text || "this option"}`;
|
|
1396
|
+
if (type === "SINGLE_LEFT") {
|
|
1397
|
+
const nonVoteClassName2 = "absolute bottom-0 left-0 m-6 flex size-11 items-center justify-center rounded-full bg-black/30 backdrop-blur-sm border border-background/20 cursor-pointer transition-all duration-200 hover:bg-black/50";
|
|
1398
|
+
const voteClassName2 = "absolute bottom-0 left-0 m-6 flex size-11 items-center justify-center rounded-full bg-background shadow-lg cursor-pointer transition-all duration-200";
|
|
1399
|
+
return /* @__PURE__ */ jsx10(
|
|
1400
|
+
"button",
|
|
1401
|
+
{
|
|
1402
|
+
className: voteInfo.isVoteItem ? voteClassName2 : nonVoteClassName2,
|
|
1403
|
+
onClick: handleVoting,
|
|
1404
|
+
"aria-label": voteLabel,
|
|
1405
|
+
"aria-pressed": voteInfo.isVoteItem,
|
|
1406
|
+
children: /* @__PURE__ */ jsx10(
|
|
1407
|
+
AppIcon,
|
|
1408
|
+
{
|
|
1409
|
+
name: "thumbUp",
|
|
1410
|
+
size: 20,
|
|
1411
|
+
"aria-hidden": "true",
|
|
1412
|
+
className: voteInfo.isVoteItem ? "" : "text-white",
|
|
1413
|
+
style: voteInfo.isVoteItem ? { color: item.option_color } : {}
|
|
1414
|
+
}
|
|
1415
|
+
)
|
|
1416
|
+
}
|
|
1417
|
+
);
|
|
1418
|
+
}
|
|
1419
|
+
if (type === "SINGLE_RIGHT") {
|
|
1420
|
+
const nonVoteClassName2 = "absolute bottom-0 right-0 m-6 flex size-11 items-center justify-center rounded-full bg-black/30 backdrop-blur-sm border border-background/20 cursor-pointer transition-all duration-200 hover:bg-black/50";
|
|
1421
|
+
const voteClassName2 = "absolute bottom-0 right-0 m-6 flex size-11 items-center justify-center rounded-full bg-background shadow-lg cursor-pointer transition-all duration-200";
|
|
1422
|
+
return /* @__PURE__ */ jsx10(
|
|
1423
|
+
"button",
|
|
1424
|
+
{
|
|
1425
|
+
className: voteInfo.isVoteItem ? voteClassName2 : nonVoteClassName2,
|
|
1426
|
+
onClick: handleVoting,
|
|
1427
|
+
"aria-label": voteLabel,
|
|
1428
|
+
"aria-pressed": voteInfo.isVoteItem,
|
|
1429
|
+
children: /* @__PURE__ */ jsx10(
|
|
1430
|
+
AppIcon,
|
|
1431
|
+
{
|
|
1432
|
+
name: "thumbDown",
|
|
1433
|
+
size: 20,
|
|
1434
|
+
"aria-hidden": "true",
|
|
1435
|
+
className: voteInfo.isVoteItem ? "" : "text-white",
|
|
1436
|
+
style: voteInfo.isVoteItem ? { color: item.option_color } : {}
|
|
1437
|
+
}
|
|
1438
|
+
)
|
|
1439
|
+
}
|
|
1440
|
+
);
|
|
1441
|
+
}
|
|
1442
|
+
const nonVoteClassName = "absolute bottom-3 right-3 rounded-full p-1 backdrop-blur-md border border-background/40 bg-background/20 hover:bg-background/30 scale-100 transition-all duration-300 z-20 cursor-pointer";
|
|
1443
|
+
const voteClassName = "absolute bottom-3 right-3 rounded-full p-1 backdrop-blur-md border border-action-primary bg-action-primary scale-110 transition-all duration-300 z-20 cursor-pointer";
|
|
1444
|
+
return /* @__PURE__ */ jsx10(
|
|
1445
|
+
"button",
|
|
1446
|
+
{
|
|
1447
|
+
className: voteInfo.isVoteItem ? voteClassName : nonVoteClassName,
|
|
1448
|
+
style: voteInfo.isVoteItem && item.option_color ? {
|
|
1449
|
+
backgroundColor: item.option_color,
|
|
1450
|
+
borderColor: item.option_color
|
|
1451
|
+
} : void 0,
|
|
1452
|
+
onClick: handleVoting,
|
|
1453
|
+
"aria-label": voteLabel,
|
|
1454
|
+
"aria-pressed": voteInfo.isVoteItem,
|
|
1455
|
+
children: /* @__PURE__ */ jsx10(
|
|
1456
|
+
AppIcon,
|
|
1457
|
+
{
|
|
1458
|
+
name: "checkCircle2",
|
|
1459
|
+
"aria-hidden": "true",
|
|
1460
|
+
className: `size-8 ${voteInfo.isVoteItem ? "text-white" : "text-white/90 drop-shadow-md"}`
|
|
1461
|
+
}
|
|
1462
|
+
)
|
|
1463
|
+
}
|
|
1464
|
+
);
|
|
1465
|
+
};
|
|
1466
|
+
var PostPollIButtonView_default = PostPollIButtonView;
|
|
1467
|
+
|
|
1468
|
+
// src/components/PostPollLayout/PostPollLayoutOne.tsx
|
|
1469
|
+
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1470
|
+
var PostPollLayoutOne = ({
|
|
1471
|
+
items,
|
|
1472
|
+
voteResult,
|
|
1473
|
+
onVotePress,
|
|
1474
|
+
onCardPress,
|
|
1475
|
+
isPostDetail,
|
|
1476
|
+
isInboxCard,
|
|
1477
|
+
isPostOwner
|
|
1478
|
+
}) => {
|
|
1479
|
+
const { sources } = items[0];
|
|
1480
|
+
let ratio = 1;
|
|
1481
|
+
if (!isInboxCard && sources && sources.original) {
|
|
1482
|
+
const { width, height } = sources.original;
|
|
1483
|
+
if (width > 0 && height > 0) {
|
|
1484
|
+
ratio = width / height;
|
|
1485
|
+
if (ratio < 0.7) {
|
|
1486
|
+
ratio = 0.7;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
const className = "object-cover w-full";
|
|
1491
|
+
return /* @__PURE__ */ jsx11("div", { className: "not-prose relative w-full box-border", children: /* @__PURE__ */ jsxs6("div", { className: "relative w-full bg-gray-100", children: [
|
|
1492
|
+
/* @__PURE__ */ jsx11(
|
|
1493
|
+
MediaView_default,
|
|
1494
|
+
{
|
|
1495
|
+
item: items[0],
|
|
1496
|
+
className,
|
|
1497
|
+
data: [items[0]],
|
|
1498
|
+
ratio,
|
|
1499
|
+
onCardPress,
|
|
1500
|
+
isPostDetail
|
|
1501
|
+
}
|
|
1502
|
+
),
|
|
1503
|
+
/* @__PURE__ */ jsx11(
|
|
1504
|
+
PostPollIResultView_default,
|
|
1505
|
+
{
|
|
1506
|
+
type: "SINGLE_LEFT",
|
|
1507
|
+
item: items[0],
|
|
1508
|
+
index: 0,
|
|
1509
|
+
voteResult,
|
|
1510
|
+
isPostOwner
|
|
1511
|
+
}
|
|
1512
|
+
),
|
|
1513
|
+
/* @__PURE__ */ jsx11(
|
|
1514
|
+
PostPollIButtonView_default,
|
|
1515
|
+
{
|
|
1516
|
+
type: "SINGLE_LEFT",
|
|
1517
|
+
item: items[0],
|
|
1518
|
+
voteResult,
|
|
1519
|
+
onVotePress
|
|
1520
|
+
}
|
|
1521
|
+
),
|
|
1522
|
+
/* @__PURE__ */ jsx11(
|
|
1523
|
+
PostPollIResultView_default,
|
|
1524
|
+
{
|
|
1525
|
+
type: "SINGLE_RIGHT",
|
|
1526
|
+
item: items[1],
|
|
1527
|
+
index: 1,
|
|
1528
|
+
voteResult,
|
|
1529
|
+
isPostOwner
|
|
1530
|
+
}
|
|
1531
|
+
),
|
|
1532
|
+
/* @__PURE__ */ jsx11(
|
|
1533
|
+
PostPollIButtonView_default,
|
|
1534
|
+
{
|
|
1535
|
+
type: "SINGLE_RIGHT",
|
|
1536
|
+
item: items[1],
|
|
1537
|
+
voteResult,
|
|
1538
|
+
onVotePress
|
|
1539
|
+
}
|
|
1540
|
+
)
|
|
1541
|
+
] }) });
|
|
1542
|
+
};
|
|
1543
|
+
var PostPollLayoutOne_default = PostPollLayoutOne;
|
|
1544
|
+
|
|
1545
|
+
// src/components/PostPollLayout/PostPollLayoutGrid.tsx
|
|
1546
|
+
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1547
|
+
var GRID_CLASS = {
|
|
1548
|
+
2: "grid grid-flow-col grid-cols-2 grid-rows-1 gap-0.5 bg-gray-100",
|
|
1549
|
+
3: "grid grid-cols-2 grid-rows-1 gap-0.5 bg-gray-100",
|
|
1550
|
+
4: "grid grid-flow-row grid-cols-2 grid-rows-2 gap-0.5 bg-gray-100"
|
|
1551
|
+
};
|
|
1552
|
+
var PostPollLayoutGrid = ({
|
|
1553
|
+
items,
|
|
1554
|
+
voteResult,
|
|
1555
|
+
onVotePress,
|
|
1556
|
+
onCardPress,
|
|
1557
|
+
isPostDetail,
|
|
1558
|
+
isPostOwner
|
|
1559
|
+
}) => {
|
|
1560
|
+
const gridClass = GRID_CLASS[items.length] ?? GRID_CLASS[4];
|
|
1561
|
+
return /* @__PURE__ */ jsx12("div", { className: "not-prose w-full box-border", children: /* @__PURE__ */ jsx12("div", { className: gridClass, children: items.map((item, index) => /* @__PURE__ */ jsxs7("div", { className: "relative group", children: [
|
|
1562
|
+
/* @__PURE__ */ jsx12(
|
|
1563
|
+
MediaView_default,
|
|
1564
|
+
{
|
|
1565
|
+
item,
|
|
1566
|
+
className: "aspect-[1] col-span-1 object-cover w-full",
|
|
1567
|
+
data: items,
|
|
1568
|
+
onCardPress,
|
|
1569
|
+
isPostDetail
|
|
1570
|
+
}
|
|
1571
|
+
),
|
|
1572
|
+
/* @__PURE__ */ jsx12(
|
|
1573
|
+
PostPollIResultView_default,
|
|
1574
|
+
{
|
|
1575
|
+
type: "NORMAL",
|
|
1576
|
+
item,
|
|
1577
|
+
index,
|
|
1578
|
+
voteResult,
|
|
1579
|
+
isPostOwner
|
|
1580
|
+
}
|
|
1581
|
+
),
|
|
1582
|
+
/* @__PURE__ */ jsx12(
|
|
1583
|
+
PostPollIButtonView_default,
|
|
1584
|
+
{
|
|
1585
|
+
type: "NORMAL",
|
|
1586
|
+
item,
|
|
1587
|
+
voteResult,
|
|
1588
|
+
onVotePress
|
|
1589
|
+
}
|
|
1590
|
+
)
|
|
1591
|
+
] }, item.option_id || index)) }) });
|
|
1592
|
+
};
|
|
1593
|
+
var PostPollLayoutGrid_default = PostPollLayoutGrid;
|
|
1594
|
+
|
|
1595
|
+
// src/components/PostPollView.tsx
|
|
1596
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1597
|
+
var PostPollView = ({
|
|
1598
|
+
items,
|
|
1599
|
+
voteResult,
|
|
1600
|
+
onVotePress,
|
|
1601
|
+
onCardPress,
|
|
1602
|
+
isPostDetail,
|
|
1603
|
+
isInboxCard,
|
|
1604
|
+
isPostOwner
|
|
1605
|
+
}) => {
|
|
1606
|
+
const isSingleChoicePoll = items.length === 2 && items[0].key === items[1].key;
|
|
1607
|
+
if (isSingleChoicePoll) {
|
|
1608
|
+
return /* @__PURE__ */ jsx13(
|
|
1609
|
+
PostPollLayoutOne_default,
|
|
1610
|
+
{
|
|
1611
|
+
isInboxCard,
|
|
1612
|
+
onVotePress,
|
|
1613
|
+
items,
|
|
1614
|
+
voteResult,
|
|
1615
|
+
onCardPress,
|
|
1616
|
+
isPostDetail,
|
|
1617
|
+
isPostOwner
|
|
1618
|
+
}
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
if (items.length >= 2 && items.length <= 4) {
|
|
1622
|
+
return /* @__PURE__ */ jsx13(
|
|
1623
|
+
PostPollLayoutGrid_default,
|
|
1624
|
+
{
|
|
1625
|
+
onVotePress,
|
|
1626
|
+
items,
|
|
1627
|
+
voteResult,
|
|
1628
|
+
onCardPress,
|
|
1629
|
+
isPostDetail,
|
|
1630
|
+
isPostOwner
|
|
1631
|
+
}
|
|
1632
|
+
);
|
|
1633
|
+
}
|
|
1634
|
+
return null;
|
|
1635
|
+
};
|
|
1636
|
+
var PostPollView_default = PostPollView;
|
|
1637
|
+
|
|
1638
|
+
// src/components/PostTextItem.tsx
|
|
1639
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1640
|
+
var PostTextItem = ({ textItems, showFullText }) => {
|
|
1641
|
+
return /* @__PURE__ */ jsx14("div", { className: "flex-1", children: /* @__PURE__ */ jsx14("div", { children: textItems.map((item, index) => {
|
|
1642
|
+
const text = "text" in item ? item.text ?? "" : "";
|
|
1643
|
+
const key = "key" in item ? item.key : index;
|
|
1644
|
+
const mentionData = "mentionData" in item ? item.mentionData : void 0;
|
|
1645
|
+
return /* @__PURE__ */ jsx14(
|
|
1646
|
+
AutoLink_default,
|
|
1647
|
+
{
|
|
1648
|
+
text: showFullText ? text : TruncateText(text, 300),
|
|
1649
|
+
mentionData,
|
|
1650
|
+
className: "whitespace-normal px-4 pb-4 leading-relaxed text-gray-800",
|
|
1651
|
+
style: {
|
|
1652
|
+
whiteSpace: "pre-wrap",
|
|
1653
|
+
wordBreak: "break-word"
|
|
1654
|
+
}
|
|
1655
|
+
},
|
|
1656
|
+
key
|
|
1657
|
+
);
|
|
1658
|
+
}) }) });
|
|
1659
|
+
};
|
|
1660
|
+
var PostTextItem_default = PostTextItem;
|
|
1661
|
+
|
|
1662
|
+
// src/components/PostLinkItem.tsx
|
|
1663
|
+
import { useState } from "react";
|
|
1664
|
+
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1665
|
+
var getHostFromUrl = (url) => {
|
|
1666
|
+
if (!url) return "";
|
|
1667
|
+
try {
|
|
1668
|
+
return new URL(url).host;
|
|
1669
|
+
} catch {
|
|
1670
|
+
return url;
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
var getLinkRel = (host, supportDeepviewDomain = "") => {
|
|
1674
|
+
const isInternal = supportDeepviewDomain.length > 0 && host.includes(supportDeepviewDomain);
|
|
1675
|
+
return isInternal ? "noreferrer" : "noreferrer nofollow";
|
|
1676
|
+
};
|
|
1677
|
+
var PostLinkItem = ({
|
|
1678
|
+
linkItems,
|
|
1679
|
+
imageComponent: ImageComponent,
|
|
1680
|
+
onCloseClick,
|
|
1681
|
+
type = "display",
|
|
1682
|
+
supportDeepviewDomain = ""
|
|
1683
|
+
}) => {
|
|
1684
|
+
const [imageError, setImageError] = useState(false);
|
|
1685
|
+
if (linkItems.length === 0) {
|
|
1686
|
+
return null;
|
|
1687
|
+
}
|
|
1688
|
+
const { linkUrl, linkTitle, linkDesc, linkImage } = linkItems[0] || {};
|
|
1689
|
+
const host = getHostFromUrl(linkUrl);
|
|
1690
|
+
const linkRel = getLinkRel(host, supportDeepviewDomain);
|
|
1691
|
+
const handleClick = (e) => {
|
|
1692
|
+
e.stopPropagation();
|
|
1693
|
+
e.nativeEvent.stopImmediatePropagation();
|
|
1694
|
+
if (linkUrl) window.open(linkUrl, "_blank", "noopener,noreferrer");
|
|
1695
|
+
};
|
|
1696
|
+
const renderImage = (src, alt, aspectClassName, containerClassName) => {
|
|
1697
|
+
if (imageError || !src) return null;
|
|
1698
|
+
return /* @__PURE__ */ jsx15("div", { className: containerClassName, children: /* @__PURE__ */ jsx15("div", { className: aspectClassName, children: ImageComponent ? /* @__PURE__ */ jsx15(
|
|
1699
|
+
ImageComponent,
|
|
1700
|
+
{
|
|
1701
|
+
src,
|
|
1702
|
+
alt,
|
|
1703
|
+
className: "w-full h-full object-cover rounded-t-md"
|
|
1704
|
+
}
|
|
1705
|
+
) : /* @__PURE__ */ jsx15(
|
|
1706
|
+
"img",
|
|
1707
|
+
{
|
|
1708
|
+
src,
|
|
1709
|
+
alt,
|
|
1710
|
+
className: "w-full h-full object-cover rounded-t-md",
|
|
1711
|
+
onError: () => setImageError(true)
|
|
1712
|
+
}
|
|
1713
|
+
) }) });
|
|
1714
|
+
};
|
|
1715
|
+
if (type === "preview") {
|
|
1716
|
+
const aspectRatio = linkImage && linkImage.height > linkImage.width && linkImage.height / linkImage.width > 0.7 ? "aspect-[0.7]" : "aspect-video";
|
|
1717
|
+
return /* @__PURE__ */ jsxs8(
|
|
1718
|
+
"section",
|
|
1719
|
+
{
|
|
1720
|
+
className: "not-prose min-w-96 relative cursor-pointer rounded-lg border border-border bg-background",
|
|
1721
|
+
onClick: handleClick,
|
|
1722
|
+
role: "link",
|
|
1723
|
+
tabIndex: 0,
|
|
1724
|
+
onKeyDown: (e) => {
|
|
1725
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1726
|
+
e.preventDefault();
|
|
1727
|
+
handleClick(e);
|
|
1728
|
+
}
|
|
1729
|
+
},
|
|
1730
|
+
children: [
|
|
1731
|
+
linkImage?.url && !imageError && /* @__PURE__ */ jsx15("div", { className: "relative w-full", children: ImageComponent ? /* @__PURE__ */ jsx15("div", { className: `relative w-full ${aspectRatio}`, children: /* @__PURE__ */ jsx15(
|
|
1732
|
+
ImageComponent,
|
|
1733
|
+
{
|
|
1734
|
+
src: linkImage.url,
|
|
1735
|
+
alt: linkTitle || "Link preview image",
|
|
1736
|
+
className: "w-full h-full object-cover rounded-t-md"
|
|
1737
|
+
}
|
|
1738
|
+
) }) : /* @__PURE__ */ jsx15("div", { className: `relative w-full ${aspectRatio}`, children: /* @__PURE__ */ jsx15(
|
|
1739
|
+
"img",
|
|
1740
|
+
{
|
|
1741
|
+
src: linkImage.url,
|
|
1742
|
+
alt: linkTitle || "Link preview image",
|
|
1743
|
+
className: "w-full h-full object-cover rounded-t-md",
|
|
1744
|
+
onError: () => setImageError(true)
|
|
1745
|
+
}
|
|
1746
|
+
) }) }),
|
|
1747
|
+
typeof onCloseClick === "function" && /* @__PURE__ */ jsx15(
|
|
1748
|
+
AppIcon,
|
|
1749
|
+
{
|
|
1750
|
+
name: "cancel",
|
|
1751
|
+
onClick: (e) => {
|
|
1752
|
+
e.stopPropagation();
|
|
1753
|
+
onCloseClick();
|
|
1754
|
+
},
|
|
1755
|
+
className: "absolute -right-2 -top-3 rounded-full bg-background size-4.5 hover:cursor-pointer hover:opacity-70"
|
|
1756
|
+
}
|
|
1757
|
+
),
|
|
1758
|
+
/* @__PURE__ */ jsxs8("section", { className: "flex flex-col gap-1 p-3", children: [
|
|
1759
|
+
/* @__PURE__ */ jsx15("a", { href: linkUrl, className: "hidden", rel: linkRel, tabIndex: -1 }),
|
|
1760
|
+
/* @__PURE__ */ jsx15(
|
|
1761
|
+
"p",
|
|
1762
|
+
{
|
|
1763
|
+
className: "wrap-break-word text-xs font-normal leading-4 text-muted-foreground",
|
|
1764
|
+
"data-test-id": "post-link-host",
|
|
1765
|
+
children: host
|
|
1766
|
+
}
|
|
1767
|
+
),
|
|
1768
|
+
/* @__PURE__ */ jsx15(
|
|
1769
|
+
"p",
|
|
1770
|
+
{
|
|
1771
|
+
className: "text-clip-1 text-ellipsis wrap-break-word text-base leading-6",
|
|
1772
|
+
"data-test-id": "post-link-title",
|
|
1773
|
+
children: linkTitle
|
|
1774
|
+
}
|
|
1775
|
+
),
|
|
1776
|
+
/* @__PURE__ */ jsx15(
|
|
1777
|
+
"p",
|
|
1778
|
+
{
|
|
1779
|
+
className: "text-clip-2 text-ellipsis wrap-break-word text-xs font-normal leading-5 tracking-tight text-muted-foreground",
|
|
1780
|
+
"data-test-id": "post-link-desc",
|
|
1781
|
+
children: linkDesc
|
|
1782
|
+
}
|
|
1783
|
+
)
|
|
1784
|
+
] })
|
|
1785
|
+
]
|
|
1786
|
+
}
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
return /* @__PURE__ */ jsx15(
|
|
1790
|
+
"section",
|
|
1791
|
+
{
|
|
1792
|
+
className: cn("not-prose relative cursor-pointer group overflow-hidden"),
|
|
1793
|
+
onClick: handleClick,
|
|
1794
|
+
role: "link",
|
|
1795
|
+
tabIndex: 0,
|
|
1796
|
+
onKeyDown: (e) => {
|
|
1797
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1798
|
+
e.preventDefault();
|
|
1799
|
+
handleClick(e);
|
|
1800
|
+
}
|
|
1801
|
+
},
|
|
1802
|
+
children: /* @__PURE__ */ jsxs8("div", { className: "aspect-video relative", children: [
|
|
1803
|
+
/* @__PURE__ */ jsx15("div", { className: "max-w-200 max-h-100 size-full relative", children: linkImage?.url && !imageError && /* @__PURE__ */ jsx15(Fragment2, { children: ImageComponent ? /* @__PURE__ */ jsx15(
|
|
1804
|
+
ImageComponent,
|
|
1805
|
+
{
|
|
1806
|
+
src: linkImage.url,
|
|
1807
|
+
alt: linkTitle || "Link preview image",
|
|
1808
|
+
className: "w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
|
|
1809
|
+
}
|
|
1810
|
+
) : /* @__PURE__ */ jsx15(
|
|
1811
|
+
"img",
|
|
1812
|
+
{
|
|
1813
|
+
src: linkImage.url,
|
|
1814
|
+
alt: linkTitle || "Link preview image",
|
|
1815
|
+
className: "w-full h-full object-cover transition-transform duration-700 group-hover:scale-105",
|
|
1816
|
+
onError: () => setImageError(true)
|
|
1817
|
+
}
|
|
1818
|
+
) }) }),
|
|
1819
|
+
/* @__PURE__ */ jsx15("div", { className: "absolute inset-0 bg-linear-to-t from-black/90 via-black/40 to-transparent opacity-90 group-hover:opacity-100 transition-opacity" }),
|
|
1820
|
+
typeof onCloseClick === "function" && /* @__PURE__ */ jsx15(
|
|
1821
|
+
"button",
|
|
1822
|
+
{
|
|
1823
|
+
onClick: (e) => {
|
|
1824
|
+
e.stopPropagation();
|
|
1825
|
+
onCloseClick();
|
|
1826
|
+
},
|
|
1827
|
+
className: "absolute top-2 right-2 bg-black/40 text-white rounded-full p-1 hover:bg-black/60 cursor-pointer border-none flex items-center justify-center transition-colors shadow-sm z-10",
|
|
1828
|
+
"aria-label": "Remove link preview",
|
|
1829
|
+
children: /* @__PURE__ */ jsx15(AppIcon, { name: "cancel", size: 16, strokeWidth: 2 })
|
|
1830
|
+
}
|
|
1831
|
+
),
|
|
1832
|
+
/* @__PURE__ */ jsxs8("div", { className: "absolute bottom-0 left-0 right-0 p-5 transform transition-transform duration-300 z-10 pointer-events-none", children: [
|
|
1833
|
+
/* @__PURE__ */ jsx15(
|
|
1834
|
+
"a",
|
|
1835
|
+
{
|
|
1836
|
+
href: linkUrl,
|
|
1837
|
+
className: "hidden pointer-events-auto",
|
|
1838
|
+
rel: linkRel,
|
|
1839
|
+
tabIndex: -1
|
|
1840
|
+
}
|
|
1841
|
+
),
|
|
1842
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 text-xs text-white/70 mb-2", children: [
|
|
1843
|
+
/* @__PURE__ */ jsx15(AppIcon, { name: "externalLink", className: "w-3.5 h-3.5" }),
|
|
1844
|
+
/* @__PURE__ */ jsx15("span", { className: "uppercase tracking-wider font-medium", children: host })
|
|
1845
|
+
] }),
|
|
1846
|
+
/* @__PURE__ */ jsx15("h3", { className: "font-semibold text-white text-xl leading-tight mb-1.5 group-hover:text-action-primary transition-colors line-clamp-2", children: linkTitle }),
|
|
1847
|
+
linkDesc && /* @__PURE__ */ jsx15("p", { className: "text-white/70 text-sm line-clamp-2", children: linkDesc })
|
|
1848
|
+
] })
|
|
1849
|
+
] })
|
|
1850
|
+
}
|
|
1851
|
+
);
|
|
1852
|
+
};
|
|
1853
|
+
var PostLinkItem_default = PostLinkItem;
|
|
1854
|
+
|
|
1855
|
+
// src/components/PostEmbedView.tsx
|
|
1856
|
+
import { useMemo as useMemo6, useState as useState2 } from "react";
|
|
1857
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1858
|
+
var TRUSTED_HOSTS = {
|
|
1859
|
+
youtube: ["www.youtube.com", "youtube.com"],
|
|
1860
|
+
spotify: ["open.spotify.com"]
|
|
1861
|
+
};
|
|
1862
|
+
var isTrustedEmbedUrl = (provider, url) => {
|
|
1863
|
+
try {
|
|
1864
|
+
const u = new URL(url);
|
|
1865
|
+
if (u.protocol !== "https:") return false;
|
|
1866
|
+
const allowed = TRUSTED_HOSTS[provider] ?? [];
|
|
1867
|
+
return allowed.includes(u.hostname.toLowerCase());
|
|
1868
|
+
} catch {
|
|
1869
|
+
return false;
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
var PostEmbedView = ({ embed }) => {
|
|
1873
|
+
const [hasError, setHasError] = useState2(false);
|
|
1874
|
+
const canRender = useMemo6(() => {
|
|
1875
|
+
return !hasError && !!embed.embedUrl && isTrustedEmbedUrl(embed.provider, embed.embedUrl);
|
|
1876
|
+
}, [hasError, embed.embedUrl, embed.provider]);
|
|
1877
|
+
const linkItem = {
|
|
1878
|
+
linkUrl: embed.originalUrl,
|
|
1879
|
+
linkTitle: embed.preview?.title || embed.originalUrl,
|
|
1880
|
+
linkDesc: embed.preview?.description || "",
|
|
1881
|
+
linkImage: embed.preview?.image ?? void 0,
|
|
1882
|
+
linkIcon: "",
|
|
1883
|
+
type: "linkItem"
|
|
1884
|
+
};
|
|
1885
|
+
if (!canRender) return /* @__PURE__ */ jsx16(PostLinkItem_default, { linkItems: [linkItem] });
|
|
1886
|
+
const isYouTube = embed.provider === "youtube";
|
|
1887
|
+
const isSpotify = embed.provider === "spotify";
|
|
1888
|
+
return /* @__PURE__ */ jsx16("div", { className: "w-full px-4 pb-4 not-first:pt-4", children: /* @__PURE__ */ jsx16(
|
|
1889
|
+
"div",
|
|
1890
|
+
{
|
|
1891
|
+
className: "relative w-full overflow-hidden rounded-xl",
|
|
1892
|
+
style: { height: embed.height || SPOTIFY_HEIGHT },
|
|
1893
|
+
children: /* @__PURE__ */ jsx16(
|
|
1894
|
+
"iframe",
|
|
1895
|
+
{
|
|
1896
|
+
src: embed.embedUrl,
|
|
1897
|
+
className: "absolute inset-0 h-full w-full",
|
|
1898
|
+
loading: "lazy",
|
|
1899
|
+
sandbox: "allow-scripts allow-same-origin allow-presentation",
|
|
1900
|
+
allow: isYouTube ? "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" : isSpotify ? "autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" : "",
|
|
1901
|
+
allowFullScreen: isYouTube,
|
|
1902
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
1903
|
+
title: embed.preview?.title || `${embed.provider} embed`,
|
|
1904
|
+
style: { border: 0 },
|
|
1905
|
+
onError: () => setHasError(true)
|
|
1906
|
+
}
|
|
1907
|
+
)
|
|
1908
|
+
}
|
|
1909
|
+
) });
|
|
1910
|
+
};
|
|
1911
|
+
var PostEmbedView_default = PostEmbedView;
|
|
1912
|
+
|
|
1913
|
+
// src/components/PostMediaLayout/MediaUploadStatusOverlay.tsx
|
|
1914
|
+
import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1915
|
+
var MediaUploadStatusOverlay = ({ status, tileWidth }) => {
|
|
1916
|
+
if (!status) return null;
|
|
1917
|
+
const showText = !tileWidth || tileWidth >= 100;
|
|
1918
|
+
if (status === "uploading" || status === "processing") {
|
|
1919
|
+
return /* @__PURE__ */ jsxs9("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-2 bg-overlay-scrim", children: [
|
|
1920
|
+
/* @__PURE__ */ jsx17(AppIcon, { name: "loader", className: "size-6 animate-spin text-background" }),
|
|
1921
|
+
showText && /* @__PURE__ */ jsx17("span", { className: "text-xs font-medium text-background", children: status === "uploading" ? "Uploading" : "Processing" })
|
|
1922
|
+
] });
|
|
1923
|
+
}
|
|
1924
|
+
if (status === "uploaded") {
|
|
1925
|
+
return /* @__PURE__ */ jsx17("div", { className: "absolute inset-0 flex items-center justify-center bg-feedback-success/15", children: /* @__PURE__ */ jsx17("div", { className: "flex size-8 items-center justify-center rounded-full bg-foreground/60", children: /* @__PURE__ */ jsx17(AppIcon, { name: "check", className: "size-5 text-background" }) }) });
|
|
1926
|
+
}
|
|
1927
|
+
return /* @__PURE__ */ jsx17("div", { className: "absolute inset-0 flex items-center justify-center bg-feedback-danger/20", children: /* @__PURE__ */ jsx17("div", { className: "flex size-8 items-center justify-center rounded-full bg-foreground/60", children: /* @__PURE__ */ jsx17("span", { className: "text-base font-bold text-background", children: "!" }) }) });
|
|
1928
|
+
};
|
|
1929
|
+
var MediaUploadStatusOverlay_default = MediaUploadStatusOverlay;
|
|
1930
|
+
|
|
1931
|
+
// src/components/PostMediaLayout/PostMediaLayoutCore.tsx
|
|
1932
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1933
|
+
var gridLayoutData = {
|
|
1934
|
+
1: {
|
|
1935
|
+
gridColsClass: "grid-cols-1",
|
|
1936
|
+
gridSpan: [1],
|
|
1937
|
+
colSpanClasses: ["col-span-1"],
|
|
1938
|
+
itemRatio: [1]
|
|
1939
|
+
},
|
|
1940
|
+
2: {
|
|
1941
|
+
gridColsClass: "grid-cols-2",
|
|
1942
|
+
gridSpan: [1, 1],
|
|
1943
|
+
colSpanClasses: ["col-span-1", "col-span-1"],
|
|
1944
|
+
itemRatio: [1, 1]
|
|
1945
|
+
},
|
|
1946
|
+
3: {
|
|
1947
|
+
gridColsClass: "grid-cols-2",
|
|
1948
|
+
gridSpan: [2, 1, 1],
|
|
1949
|
+
colSpanClasses: ["col-span-2", "col-span-1", "col-span-1"],
|
|
1950
|
+
itemRatio: [1.5, 1.5, 1.5]
|
|
1951
|
+
},
|
|
1952
|
+
4: {
|
|
1953
|
+
gridColsClass: "grid-cols-2",
|
|
1954
|
+
gridSpan: [1, 1, 1, 1],
|
|
1955
|
+
colSpanClasses: ["col-span-1", "col-span-1", "col-span-1", "col-span-1"],
|
|
1956
|
+
itemRatio: [1, 1, 1, 1]
|
|
1957
|
+
},
|
|
1958
|
+
5: {
|
|
1959
|
+
gridColsClass: "grid-cols-6",
|
|
1960
|
+
gridSpan: [3, 3, 2, 2, 2],
|
|
1961
|
+
colSpanClasses: [
|
|
1962
|
+
"col-span-3",
|
|
1963
|
+
"col-span-3",
|
|
1964
|
+
"col-span-2",
|
|
1965
|
+
"col-span-2",
|
|
1966
|
+
"col-span-2"
|
|
1967
|
+
],
|
|
1968
|
+
itemRatio: [1.5, 1.5, 1, 1, 1]
|
|
1969
|
+
}
|
|
1970
|
+
};
|
|
1971
|
+
var PostMediaLayoutCore = ({
|
|
1972
|
+
items,
|
|
1973
|
+
parentId: _parentId,
|
|
1974
|
+
isPostDetail,
|
|
1975
|
+
onCardPress,
|
|
1976
|
+
mediaItemStatuses
|
|
1977
|
+
}) => {
|
|
1978
|
+
if (!items?.length) {
|
|
1979
|
+
return null;
|
|
1980
|
+
}
|
|
1981
|
+
const slicedData = items.slice(0, 5);
|
|
1982
|
+
const { gridColsClass, colSpanClasses, itemRatio } = gridLayoutData[slicedData.length];
|
|
1983
|
+
return /* @__PURE__ */ jsx18("div", { className: "not-prose w-full box-border", children: /* @__PURE__ */ jsx18(
|
|
1984
|
+
"div",
|
|
1985
|
+
{
|
|
1986
|
+
className: `grid ${gridColsClass} cursor-pointer grid-rows-1 gap-0.5 bg-muted`,
|
|
1987
|
+
children: slicedData.map((slicedItem, index) => {
|
|
1988
|
+
let ratio = 1;
|
|
1989
|
+
if (slicedData.length === 1) {
|
|
1990
|
+
const { width, height } = slicedItem.type.includes("ToUpload") ? slicedItem.file : slicedItem.sources?.original ?? {};
|
|
1991
|
+
const safeWidth = width ?? 1;
|
|
1992
|
+
const safeHeight = height ?? 1;
|
|
1993
|
+
ratio = safeWidth / safeHeight;
|
|
1994
|
+
if (ratio < 0.7) {
|
|
1995
|
+
ratio = 0.7;
|
|
1996
|
+
}
|
|
1997
|
+
} else {
|
|
1998
|
+
ratio = itemRatio[index];
|
|
1999
|
+
}
|
|
2000
|
+
const className = `w-full h-full relative ${colSpanClasses[index]} object-cover`;
|
|
2001
|
+
return /* @__PURE__ */ jsxs10("div", { className: `relative ${colSpanClasses[index]}`, children: [
|
|
2002
|
+
/* @__PURE__ */ jsx18(
|
|
2003
|
+
MediaView_default,
|
|
2004
|
+
{
|
|
2005
|
+
item: slicedItem,
|
|
2006
|
+
ratio,
|
|
2007
|
+
className,
|
|
2008
|
+
additionalImagesCount: index === slicedData.length - 1 && items.length > 5 ? items.length - slicedData.length : void 0,
|
|
2009
|
+
data: items,
|
|
2010
|
+
isPostDetail,
|
|
2011
|
+
onCardPress
|
|
2012
|
+
}
|
|
2013
|
+
),
|
|
2014
|
+
/* @__PURE__ */ jsx18(
|
|
2015
|
+
MediaUploadStatusOverlay_default,
|
|
2016
|
+
{
|
|
2017
|
+
status: mediaItemStatuses?.[slicedItem.key]
|
|
2018
|
+
}
|
|
2019
|
+
)
|
|
2020
|
+
] }, index);
|
|
2021
|
+
})
|
|
2022
|
+
}
|
|
2023
|
+
) });
|
|
2024
|
+
};
|
|
2025
|
+
var PostMediaLayoutCore_default = PostMediaLayoutCore;
|
|
2026
|
+
|
|
2027
|
+
// src/components/PostItemsView.tsx
|
|
2028
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
2029
|
+
var PostItemsView = ({
|
|
2030
|
+
primaryContent,
|
|
2031
|
+
isPostDetail,
|
|
2032
|
+
onCardPress,
|
|
2033
|
+
onVotePress,
|
|
2034
|
+
isPostOwner,
|
|
2035
|
+
parentId,
|
|
2036
|
+
isCommentScope,
|
|
2037
|
+
imageComponent,
|
|
2038
|
+
mediaItemStatuses
|
|
2039
|
+
}) => {
|
|
2040
|
+
if (!primaryContent) return null;
|
|
2041
|
+
switch (primaryContent.type) {
|
|
2042
|
+
case "embed":
|
|
2043
|
+
return /* @__PURE__ */ jsx19(PostEmbedView_default, { embed: primaryContent });
|
|
2044
|
+
case "poll":
|
|
2045
|
+
return /* @__PURE__ */ jsx19(
|
|
2046
|
+
PostPollView_default,
|
|
2047
|
+
{
|
|
2048
|
+
items: primaryContent.items,
|
|
2049
|
+
voteResult: primaryContent.pollResult,
|
|
2050
|
+
onVotePress,
|
|
2051
|
+
onCardPress,
|
|
2052
|
+
isPostDetail,
|
|
2053
|
+
isPostOwner
|
|
2054
|
+
}
|
|
2055
|
+
);
|
|
2056
|
+
case "link":
|
|
2057
|
+
return /* @__PURE__ */ jsx19(
|
|
2058
|
+
PostLinkItem_default,
|
|
2059
|
+
{
|
|
2060
|
+
linkItems: [
|
|
2061
|
+
{
|
|
2062
|
+
linkUrl: primaryContent.linkUrl,
|
|
2063
|
+
linkTitle: primaryContent.title,
|
|
2064
|
+
linkDesc: primaryContent.description,
|
|
2065
|
+
linkImage: primaryContent.image ?? void 0,
|
|
2066
|
+
linkIcon: "",
|
|
2067
|
+
type: "linkItem"
|
|
2068
|
+
}
|
|
2069
|
+
],
|
|
2070
|
+
imageComponent
|
|
2071
|
+
}
|
|
2072
|
+
);
|
|
2073
|
+
case "media":
|
|
2074
|
+
return /* @__PURE__ */ jsx19(
|
|
2075
|
+
PostMediaLayoutCore_default,
|
|
2076
|
+
{
|
|
2077
|
+
items: primaryContent.items,
|
|
2078
|
+
parentId,
|
|
2079
|
+
isPostDetail,
|
|
2080
|
+
onCardPress,
|
|
2081
|
+
mediaItemStatuses
|
|
2082
|
+
}
|
|
2083
|
+
);
|
|
2084
|
+
case "textItem":
|
|
2085
|
+
return /* @__PURE__ */ jsx19(
|
|
2086
|
+
PostTextItem_default,
|
|
2087
|
+
{
|
|
2088
|
+
textItems: primaryContent.items,
|
|
2089
|
+
showFullText: isPostDetail,
|
|
2090
|
+
isPostDetail
|
|
2091
|
+
}
|
|
2092
|
+
);
|
|
2093
|
+
default:
|
|
2094
|
+
return null;
|
|
2095
|
+
}
|
|
2096
|
+
};
|
|
2097
|
+
var PostItemsView_default = PostItemsView;
|
|
2098
|
+
|
|
2099
|
+
// src/components/PostSectionsView.tsx
|
|
2100
|
+
import { useCallback as useCallback3 } from "react";
|
|
2101
|
+
|
|
2102
|
+
// src/utils/contentTypeConstants.ts
|
|
2103
|
+
var contentTypeRules = {
|
|
2104
|
+
NEW_MESSAGE: "new:message",
|
|
2105
|
+
NEW_POST: "new:post",
|
|
2106
|
+
NEW_COMMENT: "new:comment",
|
|
2107
|
+
EVENT: "event"
|
|
2108
|
+
};
|
|
2109
|
+
var contentTypeConstants = {
|
|
2110
|
+
TO_BE_DELETE: "tobedelete",
|
|
2111
|
+
NEW_GROUP: "new:group",
|
|
2112
|
+
LOAD_MORE_CONTENT: "loadMoreContent",
|
|
2113
|
+
NEW_MESSAGE: `${contentTypeRules.NEW_MESSAGE}:text`,
|
|
2114
|
+
NEW_MESSAGE_GUGGY: `${contentTypeRules.NEW_MESSAGE}:gif`,
|
|
2115
|
+
NEW_MESSAGE_VOICE: `${contentTypeRules.NEW_MESSAGE}:voice`,
|
|
2116
|
+
NEW_POST_IMAGE: `${contentTypeRules.NEW_POST}:image`,
|
|
2117
|
+
NEW_POST_MEDIA: `${contentTypeRules.NEW_POST}:media`,
|
|
2118
|
+
NEW_POST_POLL: `${contentTypeRules.NEW_POST}:poll`,
|
|
2119
|
+
NEW_POST_LINK: `${contentTypeRules.NEW_POST}:link`,
|
|
2120
|
+
NEW_POST_MESSAGE: `${contentTypeRules.NEW_POST}:text`,
|
|
2121
|
+
NEW_POST_THREAD: `${contentTypeRules.NEW_POST}:thread`,
|
|
2122
|
+
NEW_COMMENT: `${contentTypeRules.NEW_COMMENT}`,
|
|
2123
|
+
NEW_COMMENT_GUGGY: `${contentTypeRules.NEW_COMMENT}:gif`,
|
|
2124
|
+
NEW_COMMENT_VOICE: `${contentTypeRules.NEW_COMMENT}:voice`,
|
|
2125
|
+
NEW_COMMENT_IMAGE: `${contentTypeRules.NEW_COMMENT}:image`,
|
|
2126
|
+
NEW_COMMENT_MEDIA: `${contentTypeRules.NEW_COMMENT}:media`,
|
|
2127
|
+
ERASE_MESSAGE: "erase:message",
|
|
2128
|
+
EVENT_POLL_VOTE: "event:poll:vote",
|
|
2129
|
+
EVENT_NEW_GREETING_POST: "event:greeting:post",
|
|
2130
|
+
EVENT_UPDATE_GROUP: "event:update:group",
|
|
2131
|
+
EVENT_ERASE_GROUP_CONTENT: "event:erase:group:content",
|
|
2132
|
+
EVENT_ERASE_GROUP_COMMENT: "event:erase:group:comment",
|
|
2133
|
+
EVENT_NOT_A_CONTACT: "event:not:contact",
|
|
2134
|
+
EVENT_SCREENSHOT: "event:screenshot",
|
|
2135
|
+
EVENT_COMMENT_SCREENSHOT: "event:comment:screenshot",
|
|
2136
|
+
EVENT_TOAST_CONVERSATION: "event:toast:conversation",
|
|
2137
|
+
EVENT_TOAST_POST: "event:toast:post",
|
|
2138
|
+
UPDATE_GROUP_NAME: "group:update:name",
|
|
2139
|
+
UPDATE_GROUP_DESCRIPTION: "group:update:description",
|
|
2140
|
+
UPDATE_GROUP_BACKGROUND: "group:update:background",
|
|
2141
|
+
UPDATE_GROUP_DEFAULT_DEEPLINK: "group:update:default_deeplink",
|
|
2142
|
+
UPDATE_GROUP_AVATAR: "group:update:avatar",
|
|
2143
|
+
UPDATE_GROUP_NEW_USERS: "group:new:users",
|
|
2144
|
+
UPDATE_GROUP_REMOVE_USERS: "group:remove:users",
|
|
2145
|
+
UPDATE_GROUP_USER_LEAVE: "group:remove:users:leave",
|
|
2146
|
+
UPDATE_GROUP_NEW_OWNER: "group:new:owner",
|
|
2147
|
+
UPDATE_GROUP_SELECT_ID: "group:update:select_id",
|
|
2148
|
+
UPDATE_GROUP_SHOW_HISTORY: "group:update:show_history",
|
|
2149
|
+
UPDATE_GROUP_SHARE_TO_PUBLIC: "group:update:share_to_public",
|
|
2150
|
+
UPDATE_GROUP_PERMISSION: "group:update:permission",
|
|
2151
|
+
UPDATE_GROUP_NEW_FEATURED: "group:new:featured",
|
|
2152
|
+
UPDATE_GROUP_FEATURED_IN_GROUP: "group:featured:in:group",
|
|
2153
|
+
UPDATE_GROUP_FEATURED_BY_USER: "group:featured:by:user",
|
|
2154
|
+
UPDATE_RELATIONSHIP: "update:relationship",
|
|
2155
|
+
NEW_GROUP_REQUEST: "group:request:new",
|
|
2156
|
+
NEW_GROUP_REQUEST_ACCEPTED: "group:request:accepted",
|
|
2157
|
+
REMOVE_GROUP_ADMIN: "group:remove:admin",
|
|
2158
|
+
ADD_GROUP_ADMIN: "group:new:admin",
|
|
2159
|
+
UPDATE_CONTENT: "update:content",
|
|
2160
|
+
NEW_GROUP_REQUEST_REMOVE: "group:request:removed",
|
|
2161
|
+
AGGREGATED_MESSAGE_TIME: "aggregated:message:time",
|
|
2162
|
+
REQUEST_IMAGE_DOWNLOAD: "request:image:download"
|
|
2163
|
+
};
|
|
2164
|
+
|
|
2165
|
+
// src/components/PostSectionSourceInfoView.tsx
|
|
2166
|
+
import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2167
|
+
var PostSectionSourceInfoView = ({ sourceInfo }) => {
|
|
2168
|
+
if (!sourceInfo) {
|
|
2169
|
+
return null;
|
|
2170
|
+
}
|
|
2171
|
+
return /* @__PURE__ */ jsx20("div", { className: "mx-4 mb-3 mt-3 border-b border-gray-100 pb-3", children: /* @__PURE__ */ jsxs11("div", { className: "flex flex-row items-center", children: [
|
|
2172
|
+
/* @__PURE__ */ jsx20("div", { className: "size-7 shrink-0 rounded-full overflow-hidden border border-border-subtle bg-muted flex items-center justify-center", children: sourceInfo.avatar ? /* @__PURE__ */ jsx20(
|
|
2173
|
+
"img",
|
|
2174
|
+
{
|
|
2175
|
+
src: sourceInfo.avatar,
|
|
2176
|
+
alt: sourceInfo.username,
|
|
2177
|
+
className: "size-full object-cover"
|
|
2178
|
+
}
|
|
2179
|
+
) : /* @__PURE__ */ jsx20("span", { className: "text-xs font-semibold text-muted-foreground", children: sourceInfo.username?.charAt(0)?.toUpperCase() ?? "?" }) }),
|
|
2180
|
+
/* @__PURE__ */ jsxs11("div", { className: "ml-2 flex-col justify-center flex", children: [
|
|
2181
|
+
/* @__PURE__ */ jsx20("div", { className: "text-sm font-semibold text-foreground leading-none", children: sourceInfo.username }),
|
|
2182
|
+
/* @__PURE__ */ jsx20("div", { className: "text-xs text-muted-foreground mt-1 leading-none", children: sourceInfo.url })
|
|
2183
|
+
] })
|
|
2184
|
+
] }) });
|
|
2185
|
+
};
|
|
2186
|
+
var PostSectionSourceInfoView_default = PostSectionSourceInfoView;
|
|
2187
|
+
|
|
2188
|
+
// src/components/PostSectionsView.tsx
|
|
2189
|
+
import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2190
|
+
var PostSectionsView = ({
|
|
2191
|
+
sections,
|
|
2192
|
+
isPostDetail,
|
|
2193
|
+
onCardPress
|
|
2194
|
+
}) => {
|
|
2195
|
+
const renderSectionItem = useCallback3(
|
|
2196
|
+
(section, index) => {
|
|
2197
|
+
const { type, data } = section;
|
|
2198
|
+
if (type === contentTypeConstants.NEW_POST_MESSAGE) {
|
|
2199
|
+
return /* @__PURE__ */ jsx21(
|
|
2200
|
+
AutoLink_default,
|
|
2201
|
+
{
|
|
2202
|
+
text: data.body || "",
|
|
2203
|
+
className: "whitespace-normal px-4 pb-4 leading-relaxed text-gray-800",
|
|
2204
|
+
style: {
|
|
2205
|
+
whiteSpace: "pre-wrap",
|
|
2206
|
+
wordBreak: "break-word"
|
|
2207
|
+
},
|
|
2208
|
+
mentionData: data.mentionData
|
|
2209
|
+
},
|
|
2210
|
+
`${index} - ${data.body}`
|
|
2211
|
+
);
|
|
2212
|
+
}
|
|
2213
|
+
if (type === contentTypeConstants.NEW_POST_MEDIA) {
|
|
2214
|
+
return /* @__PURE__ */ jsxs12("div", { className: "my-3", children: [
|
|
2215
|
+
data.sourceInfo && /* @__PURE__ */ jsx21(PostSectionSourceInfoView_default, { sourceInfo: data.sourceInfo }),
|
|
2216
|
+
data.body && /* @__PURE__ */ jsx21(
|
|
2217
|
+
AutoLink_default,
|
|
2218
|
+
{
|
|
2219
|
+
text: data.body || "",
|
|
2220
|
+
className: "whitespace-normal px-4 pb-4 leading-relaxed text-gray-800",
|
|
2221
|
+
style: {
|
|
2222
|
+
whiteSpace: "pre-wrap",
|
|
2223
|
+
wordBreak: "break-word"
|
|
2224
|
+
},
|
|
2225
|
+
mentionData: data.mentionData
|
|
2226
|
+
},
|
|
2227
|
+
`${index} - ${data.body}`
|
|
2228
|
+
),
|
|
2229
|
+
data.items && /* @__PURE__ */ jsx21(
|
|
2230
|
+
PostMediaLayoutCore_default,
|
|
2231
|
+
{
|
|
2232
|
+
items: data.items,
|
|
2233
|
+
isPostDetail,
|
|
2234
|
+
onCardPress
|
|
2235
|
+
}
|
|
2236
|
+
)
|
|
2237
|
+
] }, `${index} - ${data.body}`);
|
|
2238
|
+
}
|
|
2239
|
+
return null;
|
|
2240
|
+
},
|
|
2241
|
+
[isPostDetail, onCardPress]
|
|
2242
|
+
);
|
|
2243
|
+
if (!sections || sections.length === 0) {
|
|
2244
|
+
return null;
|
|
2245
|
+
}
|
|
2246
|
+
return /* @__PURE__ */ jsx21("div", { className: "space-y-2", children: sections.map((section, index) => {
|
|
2247
|
+
return renderSectionItem(section, index);
|
|
2248
|
+
}) });
|
|
2249
|
+
};
|
|
2250
|
+
var PostSectionsView_default = PostSectionsView;
|
|
2251
|
+
|
|
2252
|
+
// src/components/PostFooter.tsx
|
|
2253
|
+
import { useState as useState3 } from "react";
|
|
2254
|
+
import { NotificationBadge } from "@select-org/ui";
|
|
2255
|
+
import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2256
|
+
var PostFooter = ({
|
|
2257
|
+
postHref,
|
|
2258
|
+
commentCount = 0,
|
|
2259
|
+
unreadCommentCount = 0,
|
|
2260
|
+
showFooterLink = false,
|
|
2261
|
+
footerLinkLabel = "Open in app",
|
|
2262
|
+
footerLinkHref = "/",
|
|
2263
|
+
isSnoozed = false,
|
|
2264
|
+
onSnoozeToggle,
|
|
2265
|
+
renderReactionTrigger,
|
|
2266
|
+
renderReactionModal
|
|
2267
|
+
}) => {
|
|
2268
|
+
const [isReactionOpen, setIsReactionOpen] = useState3(false);
|
|
2269
|
+
const handleOpen = () => setIsReactionOpen(true);
|
|
2270
|
+
const handleClose = () => setIsReactionOpen(false);
|
|
2271
|
+
const commentButtonClass = "relative text-muted-foreground hover:text-foreground hover:bg-muted p-2 rounded-full transition-all flex items-center justify-center cursor-pointer bg-transparent border-none select-none";
|
|
2272
|
+
const commentAriaLabel = `View comments${commentCount > 0 ? `, ${commentCount} comment${commentCount !== 1 ? "s" : ""}` : ""}`;
|
|
2273
|
+
const commentBadge = commentCount > 0 ? /* @__PURE__ */ jsx22("span", { className: "absolute top-0 right-0 -mt-0.5 -mr-0.5", children: /* @__PURE__ */ jsx22(
|
|
2274
|
+
NotificationBadge,
|
|
2275
|
+
{
|
|
2276
|
+
count: unreadCommentCount > 0 ? unreadCommentCount : commentCount,
|
|
2277
|
+
variant: unreadCommentCount > 0 ? "solid" : "neutral",
|
|
2278
|
+
size: "sm",
|
|
2279
|
+
className: "ring-2 ring-background"
|
|
2280
|
+
}
|
|
2281
|
+
) }) : null;
|
|
2282
|
+
return /* @__PURE__ */ jsxs13("section", { className: "flex items-center justify-between p-2 px-4 border-t border-border/50", children: [
|
|
2283
|
+
/* @__PURE__ */ jsxs13("div", { className: "relative flex items-center gap-1", children: [
|
|
2284
|
+
renderReactionTrigger ? renderReactionTrigger({ onOpen: handleOpen }) : /* @__PURE__ */ jsx22(
|
|
2285
|
+
"button",
|
|
2286
|
+
{
|
|
2287
|
+
onClick: (e) => {
|
|
2288
|
+
e.preventDefault();
|
|
2289
|
+
e.stopPropagation();
|
|
2290
|
+
handleOpen();
|
|
2291
|
+
},
|
|
2292
|
+
className: "text-muted-foreground hover:text-foreground hover:bg-muted p-2 rounded-full transition-all cursor-pointer bg-transparent border-none select-none",
|
|
2293
|
+
"aria-label": "Add reaction",
|
|
2294
|
+
"aria-expanded": isReactionOpen,
|
|
2295
|
+
"aria-haspopup": "true",
|
|
2296
|
+
children: /* @__PURE__ */ jsx22(AppIcon, { name: "sendEmoji", "aria-hidden": "true" })
|
|
2297
|
+
}
|
|
2298
|
+
),
|
|
2299
|
+
onSnoozeToggle && /* @__PURE__ */ jsx22(
|
|
2300
|
+
"button",
|
|
2301
|
+
{
|
|
2302
|
+
onClick: (e) => {
|
|
2303
|
+
e.preventDefault();
|
|
2304
|
+
e.stopPropagation();
|
|
2305
|
+
onSnoozeToggle();
|
|
2306
|
+
},
|
|
2307
|
+
className: cn(
|
|
2308
|
+
"p-2 rounded-full hover:bg-muted transition-all cursor-pointer bg-transparent border-none select-none",
|
|
2309
|
+
isSnoozed ? "text-feedback-warning" : "text-muted-foreground hover:text-foreground"
|
|
2310
|
+
),
|
|
2311
|
+
"aria-label": isSnoozed ? "Unsnooze post" : "Snooze post",
|
|
2312
|
+
title: isSnoozed ? "Unsnooze post" : "Snooze post (30 min)",
|
|
2313
|
+
children: /* @__PURE__ */ jsx22(AppIcon, { name: "alarmClock" })
|
|
2314
|
+
}
|
|
2315
|
+
),
|
|
2316
|
+
renderReactionModal && /* @__PURE__ */ jsx22("div", { className: "z-50 absolute bottom-full left-0 mb-2", children: renderReactionModal({
|
|
2317
|
+
isOpen: isReactionOpen,
|
|
2318
|
+
onClose: handleClose,
|
|
2319
|
+
onSend: (emoji) => {
|
|
2320
|
+
handleClose();
|
|
2321
|
+
}
|
|
2322
|
+
}) })
|
|
2323
|
+
] }),
|
|
2324
|
+
/* @__PURE__ */ jsx22("div", { className: "relative flex items-center ml-auto", children: postHref ? /* @__PURE__ */ jsxs13(
|
|
2325
|
+
"a",
|
|
2326
|
+
{
|
|
2327
|
+
href: postHref,
|
|
2328
|
+
className: cn(commentButtonClass, "no-underline"),
|
|
2329
|
+
onClick: (e) => {
|
|
2330
|
+
e.stopPropagation();
|
|
2331
|
+
},
|
|
2332
|
+
"aria-label": commentAriaLabel,
|
|
2333
|
+
children: [
|
|
2334
|
+
/* @__PURE__ */ jsx22(AppIcon, { name: "messageCircleMore", "aria-hidden": "true" }),
|
|
2335
|
+
commentBadge
|
|
2336
|
+
]
|
|
2337
|
+
}
|
|
2338
|
+
) : /* @__PURE__ */ jsxs13("button", { className: commentButtonClass, "aria-label": commentAriaLabel, children: [
|
|
2339
|
+
/* @__PURE__ */ jsx22(AppIcon, { name: "messageCircleMore", "aria-hidden": "true" }),
|
|
2340
|
+
commentBadge
|
|
2341
|
+
] }) }),
|
|
2342
|
+
showFooterLink && /* @__PURE__ */ jsx22("section", { className: "flex justify-center -mx-5 -mb-2.5 mt-2.5", children: /* @__PURE__ */ jsx22(
|
|
2343
|
+
"a",
|
|
2344
|
+
{
|
|
2345
|
+
href: footerLinkHref,
|
|
2346
|
+
className: "bg-action-primary/5 hover:bg-action-primary/10 transition-colors w-full text-center py-3 text-sm font-medium text-action-primary no-underline rounded-b-xl border-t border-action-primary/10",
|
|
2347
|
+
children: footerLinkLabel
|
|
2348
|
+
}
|
|
2349
|
+
) })
|
|
2350
|
+
] });
|
|
2351
|
+
};
|
|
2352
|
+
var PostFooter_default = PostFooter;
|
|
2353
|
+
|
|
2354
|
+
// src/components/PostMediaLayout/uploadStats.ts
|
|
2355
|
+
function deriveUploadStats(statuses) {
|
|
2356
|
+
let inFlight = 0;
|
|
2357
|
+
let done = 0;
|
|
2358
|
+
let failed = 0;
|
|
2359
|
+
for (const s of Object.values(statuses ?? {})) {
|
|
2360
|
+
if (s === "uploading" || s === "processing") inFlight++;
|
|
2361
|
+
else if (s === "uploaded") done++;
|
|
2362
|
+
else if (s === "error") failed++;
|
|
2363
|
+
}
|
|
2364
|
+
return { inFlight, done, failed, total: inFlight + done + failed };
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// src/components/PostUploadStrip.tsx
|
|
2368
|
+
import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2369
|
+
var PostUploadStrip = ({ statuses, labels }) => {
|
|
2370
|
+
const stats = deriveUploadStats(statuses);
|
|
2371
|
+
if (stats.total === 0) return null;
|
|
2372
|
+
if (stats.inFlight === 0 && stats.failed === 0) return null;
|
|
2373
|
+
const hasError = stats.failed > 0;
|
|
2374
|
+
const remaining = stats.inFlight;
|
|
2375
|
+
const remainingTemplate = labels?.uploadingRemaining ?? "Uploading {count} more";
|
|
2376
|
+
const doneLabel = labels?.uploadingDone ?? "All uploaded";
|
|
2377
|
+
const progressLabel = remaining > 0 ? remainingTemplate.replace("{count}", String(remaining)) : doneLabel;
|
|
2378
|
+
return /* @__PURE__ */ jsxs14(
|
|
2379
|
+
"div",
|
|
2380
|
+
{
|
|
2381
|
+
className: cn(
|
|
2382
|
+
"not-prose flex items-center gap-2.5 border-t border-border px-5 py-2.5",
|
|
2383
|
+
hasError ? "bg-feedback-danger/8" : "bg-feedback-info/8"
|
|
2384
|
+
),
|
|
2385
|
+
children: [
|
|
2386
|
+
remaining > 0 ? /* @__PURE__ */ jsx23(
|
|
2387
|
+
AppIcon,
|
|
2388
|
+
{
|
|
2389
|
+
name: "loader",
|
|
2390
|
+
className: cn(
|
|
2391
|
+
"size-4 shrink-0 animate-spin",
|
|
2392
|
+
hasError ? "text-feedback-danger" : "text-feedback-info"
|
|
2393
|
+
)
|
|
2394
|
+
}
|
|
2395
|
+
) : /* @__PURE__ */ jsx23(
|
|
2396
|
+
AppIcon,
|
|
2397
|
+
{
|
|
2398
|
+
name: "triangleAlert",
|
|
2399
|
+
className: "size-4 shrink-0 text-feedback-danger"
|
|
2400
|
+
}
|
|
2401
|
+
),
|
|
2402
|
+
/* @__PURE__ */ jsx23(
|
|
2403
|
+
"span",
|
|
2404
|
+
{
|
|
2405
|
+
className: cn(
|
|
2406
|
+
"truncate text-xs font-medium",
|
|
2407
|
+
hasError ? "text-feedback-danger" : "text-feedback-info"
|
|
2408
|
+
),
|
|
2409
|
+
children: progressLabel
|
|
2410
|
+
}
|
|
2411
|
+
),
|
|
2412
|
+
/* @__PURE__ */ jsxs14(
|
|
2413
|
+
"span",
|
|
2414
|
+
{
|
|
2415
|
+
className: cn(
|
|
2416
|
+
"ml-auto shrink-0 text-[11px]",
|
|
2417
|
+
hasError ? "text-feedback-danger/80" : "text-feedback-info/80"
|
|
2418
|
+
),
|
|
2419
|
+
children: [
|
|
2420
|
+
stats.done,
|
|
2421
|
+
" / ",
|
|
2422
|
+
stats.total,
|
|
2423
|
+
hasError && ` \xB7 ${stats.failed} failed`
|
|
2424
|
+
]
|
|
2425
|
+
}
|
|
2426
|
+
)
|
|
2427
|
+
]
|
|
2428
|
+
}
|
|
2429
|
+
);
|
|
2430
|
+
};
|
|
2431
|
+
var PostUploadStrip_default = PostUploadStrip;
|
|
2432
|
+
|
|
2433
|
+
// src/components/EraseConfirmModal.tsx
|
|
2434
|
+
import { useEffect as useEffect2, useState as useState4 } from "react";
|
|
2435
|
+
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2436
|
+
var EraseConfirmModal = ({
|
|
2437
|
+
onYesPress,
|
|
2438
|
+
onNoPress,
|
|
2439
|
+
itemType = "comment",
|
|
2440
|
+
isOpen,
|
|
2441
|
+
handleClose
|
|
2442
|
+
}) => {
|
|
2443
|
+
const [first, setFirst] = useState4(true);
|
|
2444
|
+
const [second, setSecond] = useState4(false);
|
|
2445
|
+
useEffect2(() => {
|
|
2446
|
+
if (!isOpen) return;
|
|
2447
|
+
const closeOnEscape = (e) => {
|
|
2448
|
+
if (e.key === "Escape") handleClose();
|
|
2449
|
+
};
|
|
2450
|
+
document.body.addEventListener("keydown", closeOnEscape);
|
|
2451
|
+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
2452
|
+
document.body.style.overflow = "hidden";
|
|
2453
|
+
document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
2454
|
+
return () => {
|
|
2455
|
+
document.body.removeEventListener("keydown", closeOnEscape);
|
|
2456
|
+
document.body.style.overflow = "";
|
|
2457
|
+
document.body.style.paddingRight = "";
|
|
2458
|
+
};
|
|
2459
|
+
}, [isOpen, handleClose]);
|
|
2460
|
+
if (!isOpen) return null;
|
|
2461
|
+
const handleFirst = (e) => {
|
|
2462
|
+
e.stopPropagation();
|
|
2463
|
+
e.nativeEvent.stopImmediatePropagation();
|
|
2464
|
+
setFirst(false);
|
|
2465
|
+
setSecond(true);
|
|
2466
|
+
};
|
|
2467
|
+
const handleNoPress = (e) => {
|
|
2468
|
+
onNoPress(e);
|
|
2469
|
+
setFirst(true);
|
|
2470
|
+
setSecond(false);
|
|
2471
|
+
};
|
|
2472
|
+
const eraseLabel = itemType === "Post" ? "Erase post" : "Erase comment";
|
|
2473
|
+
const confirmTitle = itemType === "Post" ? "Are you sure you want to erase this post?" : "Are you sure you want to erase this comment?";
|
|
2474
|
+
const confirmBody = itemType === "Post" ? "This action cannot be undone." : "This action cannot be undone.";
|
|
2475
|
+
return /* @__PURE__ */ jsxs15("div", { children: [
|
|
2476
|
+
/* @__PURE__ */ jsx24("div", { className: "fixed left-0 top-0 z-50 h-screen w-full bg-black/50" }),
|
|
2477
|
+
/* @__PURE__ */ jsx24(
|
|
2478
|
+
"div",
|
|
2479
|
+
{
|
|
2480
|
+
className: "fixed left-0 top-0 z-50 flex h-screen w-full items-center justify-center p-4",
|
|
2481
|
+
onClick: (e) => {
|
|
2482
|
+
e.stopPropagation();
|
|
2483
|
+
e.nativeEvent.stopImmediatePropagation();
|
|
2484
|
+
},
|
|
2485
|
+
children: /* @__PURE__ */ jsxs15("div", { className: "rounded-3xl bg-background px-8 py-6 text-center shadow-3", children: [
|
|
2486
|
+
first && /* @__PURE__ */ jsxs15(
|
|
2487
|
+
"div",
|
|
2488
|
+
{
|
|
2489
|
+
className: "flex w-[256px] flex-col justify-around",
|
|
2490
|
+
onClick: (e) => e.stopPropagation(),
|
|
2491
|
+
children: [
|
|
2492
|
+
/* @__PURE__ */ jsxs15(
|
|
2493
|
+
"div",
|
|
2494
|
+
{
|
|
2495
|
+
className: "mb-4 flex flex-row items-center hover:cursor-pointer hover:opacity-50",
|
|
2496
|
+
"data-testid": "modal-erase-post",
|
|
2497
|
+
onClick: (e) => handleFirst(e),
|
|
2498
|
+
children: [
|
|
2499
|
+
/* @__PURE__ */ jsx24("div", { children: /* @__PURE__ */ jsx24(AppIcon, { name: "chatErase", className: "size-7.5 cursor-pointer" }) }),
|
|
2500
|
+
/* @__PURE__ */ jsx24("p", { className: "ml-3 text-lg", children: eraseLabel })
|
|
2501
|
+
]
|
|
2502
|
+
}
|
|
2503
|
+
),
|
|
2504
|
+
/* @__PURE__ */ jsxs15(
|
|
2505
|
+
"div",
|
|
2506
|
+
{
|
|
2507
|
+
className: "flex flex-row items-center hover:cursor-pointer hover:opacity-50",
|
|
2508
|
+
onClick: handleNoPress,
|
|
2509
|
+
children: [
|
|
2510
|
+
/* @__PURE__ */ jsx24("div", { children: /* @__PURE__ */ jsx24(AppIcon, { name: "cancel", className: "cursor-pointer size-6" }) }),
|
|
2511
|
+
/* @__PURE__ */ jsx24("p", { className: "ml-3 text-lg", children: "Cancel" })
|
|
2512
|
+
]
|
|
2513
|
+
}
|
|
2514
|
+
)
|
|
2515
|
+
]
|
|
2516
|
+
}
|
|
2517
|
+
),
|
|
2518
|
+
second && /* @__PURE__ */ jsxs15(
|
|
2519
|
+
"div",
|
|
2520
|
+
{
|
|
2521
|
+
onClick: (e) => e.stopPropagation(),
|
|
2522
|
+
className: "flex w-[296px] flex-col items-center justify-around",
|
|
2523
|
+
children: [
|
|
2524
|
+
/* @__PURE__ */ jsxs15("div", { className: "mb-4", children: [
|
|
2525
|
+
/* @__PURE__ */ jsx24("h4", { className: "mb-2 text-lg font-bold", children: confirmTitle }),
|
|
2526
|
+
/* @__PURE__ */ jsx24("p", { className: "text-muted-foreground", children: confirmBody })
|
|
2527
|
+
] }),
|
|
2528
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-around", children: [
|
|
2529
|
+
/* @__PURE__ */ jsx24(
|
|
2530
|
+
"button",
|
|
2531
|
+
{
|
|
2532
|
+
className: "mr-6 py-2 text-muted-foreground",
|
|
2533
|
+
onClick: handleNoPress,
|
|
2534
|
+
children: "Cancel"
|
|
2535
|
+
}
|
|
2536
|
+
),
|
|
2537
|
+
/* @__PURE__ */ jsx24(
|
|
2538
|
+
"button",
|
|
2539
|
+
{
|
|
2540
|
+
className: "rounded-3xl bg-action-primary px-6 py-2 font-semibold text-white",
|
|
2541
|
+
onClick: onYesPress,
|
|
2542
|
+
"data-testid": "confirm-modal-erase",
|
|
2543
|
+
children: "Erase"
|
|
2544
|
+
}
|
|
2545
|
+
)
|
|
2546
|
+
] })
|
|
2547
|
+
]
|
|
2548
|
+
}
|
|
2549
|
+
)
|
|
2550
|
+
] })
|
|
2551
|
+
}
|
|
2552
|
+
)
|
|
2553
|
+
] });
|
|
2554
|
+
};
|
|
2555
|
+
var EraseConfirmModal_default = EraseConfirmModal;
|
|
2556
|
+
|
|
2557
|
+
// src/components/PostCard.tsx
|
|
2558
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2559
|
+
var PostCard = ({
|
|
2560
|
+
post,
|
|
2561
|
+
author,
|
|
2562
|
+
authorHref,
|
|
2563
|
+
group,
|
|
2564
|
+
groupHref,
|
|
2565
|
+
postHref,
|
|
2566
|
+
linkComponent,
|
|
2567
|
+
imageComponent,
|
|
2568
|
+
isAdmin,
|
|
2569
|
+
isOwner,
|
|
2570
|
+
isPostPreview,
|
|
2571
|
+
onPostPress,
|
|
2572
|
+
onErasePress,
|
|
2573
|
+
onCancelPost,
|
|
2574
|
+
onVotePress,
|
|
2575
|
+
onCardPress,
|
|
2576
|
+
renderActionsMenu,
|
|
2577
|
+
renderReactionTrigger,
|
|
2578
|
+
renderReactionModal,
|
|
2579
|
+
onNavigate,
|
|
2580
|
+
supportDeepviewDomain,
|
|
2581
|
+
labels,
|
|
2582
|
+
mode = "feed",
|
|
2583
|
+
commentCount = 0,
|
|
2584
|
+
unreadCommentCount = 0,
|
|
2585
|
+
isSnoozed = false,
|
|
2586
|
+
onSnoozeToggle,
|
|
2587
|
+
mediaItemStatuses,
|
|
2588
|
+
showFooterLink = false,
|
|
2589
|
+
footerLinkLabel,
|
|
2590
|
+
footerLinkHref,
|
|
2591
|
+
className
|
|
2592
|
+
}) => {
|
|
2593
|
+
const [eraseModalOpen, setEraseModalOpen] = useState5(false);
|
|
2594
|
+
const isPending = !!post.is_pending;
|
|
2595
|
+
const isPostDetail = mode === "detail";
|
|
2596
|
+
const sendingLabel = labels?.sending ?? "Sending...";
|
|
2597
|
+
const contextData = useMemo7(
|
|
2598
|
+
() => ({
|
|
2599
|
+
body: post.body ?? "",
|
|
2600
|
+
htmlBody: post.htmlBody,
|
|
2601
|
+
jsonBody: post.jsonBody,
|
|
2602
|
+
textBody: post.textBody,
|
|
2603
|
+
items: post.items,
|
|
2604
|
+
mentionData: post.mentionData,
|
|
2605
|
+
sections: post.sections
|
|
2606
|
+
}),
|
|
2607
|
+
[post.body, post.htmlBody, post.jsonBody, post.textBody, post.items, post.mentionData, post.sections]
|
|
2608
|
+
);
|
|
2609
|
+
const isEmailPost = Boolean(post.htmlBody && !post.jsonBody);
|
|
2610
|
+
const resolvedContent = useMemo7(
|
|
2611
|
+
() => resolvePostContent(contextData, {
|
|
2612
|
+
postType: post.postType,
|
|
2613
|
+
pollResult: post.poll_result ?? null,
|
|
2614
|
+
postSpecialType: post.isFeatured ? 1 : 0,
|
|
2615
|
+
mode: isPostDetail ? "detail" : mode,
|
|
2616
|
+
isEmailPost
|
|
2617
|
+
}),
|
|
2618
|
+
[contextData, post.postType, post.poll_result, post.isFeatured, isPostDetail, mode, isEmailPost]
|
|
2619
|
+
);
|
|
2620
|
+
const handleErasePress = () => {
|
|
2621
|
+
setEraseModalOpen(true);
|
|
2622
|
+
};
|
|
2623
|
+
const handleEraseConfirm = () => {
|
|
2624
|
+
setEraseModalOpen(false);
|
|
2625
|
+
onErasePress?.();
|
|
2626
|
+
};
|
|
2627
|
+
const handleEraseCancel = () => {
|
|
2628
|
+
setEraseModalOpen(false);
|
|
2629
|
+
};
|
|
2630
|
+
const handleCardClick = (e) => {
|
|
2631
|
+
e.stopPropagation();
|
|
2632
|
+
e.nativeEvent.stopImmediatePropagation();
|
|
2633
|
+
if (isPending) return;
|
|
2634
|
+
onPostPress?.();
|
|
2635
|
+
};
|
|
2636
|
+
const handleCardKeyDown = (e) => {
|
|
2637
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2638
|
+
e.preventDefault();
|
|
2639
|
+
e.stopPropagation();
|
|
2640
|
+
if (isPending) return;
|
|
2641
|
+
onPostPress?.();
|
|
2642
|
+
}
|
|
2643
|
+
};
|
|
2644
|
+
return /* @__PURE__ */ jsxs16(
|
|
2645
|
+
"article",
|
|
2646
|
+
{
|
|
2647
|
+
className: cn(
|
|
2648
|
+
"flex flex-col box-border bg-background",
|
|
2649
|
+
!isPostDetail && "cursor-pointer sm:border border-border rounded-xl sm:rounded-2xl overflow-hidden shadow-sm hover:shadow-md transition-shadow duration-300 relative mt-6",
|
|
2650
|
+
isPostDetail && "cursor-auto rounded-t-2xl w-full",
|
|
2651
|
+
post.isFeatured && !isPostDetail && "bg-surface-raised border-border-subtle sm:border-t-4",
|
|
2652
|
+
isPending && "cursor-default",
|
|
2653
|
+
className
|
|
2654
|
+
),
|
|
2655
|
+
onClick: !isPostDetail && onPostPress ? handleCardClick : void 0,
|
|
2656
|
+
onKeyDown: !isPostDetail && !isPending && onPostPress ? handleCardKeyDown : void 0,
|
|
2657
|
+
tabIndex: !isPostDetail && !isPending && onPostPress ? 0 : void 0,
|
|
2658
|
+
role: !isPostDetail && !isPending && onPostPress ? "button" : void 0,
|
|
2659
|
+
"aria-label": !isPostDetail && !isPending && onPostPress ? "View post details" : void 0,
|
|
2660
|
+
children: [
|
|
2661
|
+
!isPostDetail && !isPending && postHref && linkComponent && React11.createElement(linkComponent, {
|
|
2662
|
+
href: postHref,
|
|
2663
|
+
className: "sr-only",
|
|
2664
|
+
children: "View post details"
|
|
2665
|
+
}),
|
|
2666
|
+
!isPostDetail && !isPending && postHref && !linkComponent && /* @__PURE__ */ jsx25("a", { href: postHref, className: "sr-only", onClick: (e) => e.stopPropagation(), children: "View post details" }),
|
|
2667
|
+
isPending && /* @__PURE__ */ jsx25("div", { className: "absolute top-0 left-0 w-full z-10", children: /* @__PURE__ */ jsx25(
|
|
2668
|
+
"div",
|
|
2669
|
+
{
|
|
2670
|
+
className: "h-1 w-full overflow-hidden rounded bg-muted",
|
|
2671
|
+
"aria-label": sendingLabel,
|
|
2672
|
+
"data-testid": "post-loader",
|
|
2673
|
+
children: /* @__PURE__ */ jsx25("div", { className: "h-full animate-pulse bg-action-primary" })
|
|
2674
|
+
}
|
|
2675
|
+
) }),
|
|
2676
|
+
!isPending && eraseModalOpen && /* @__PURE__ */ jsx25(
|
|
2677
|
+
EraseConfirmModal_default,
|
|
2678
|
+
{
|
|
2679
|
+
isOpen: eraseModalOpen,
|
|
2680
|
+
itemType: "Post",
|
|
2681
|
+
onYesPress: handleEraseConfirm,
|
|
2682
|
+
onNoPress: handleEraseCancel,
|
|
2683
|
+
handleClose: handleEraseCancel
|
|
2684
|
+
}
|
|
2685
|
+
),
|
|
2686
|
+
/* @__PURE__ */ jsxs16("div", { className: cn(isPending && "opacity-50"), children: [
|
|
2687
|
+
/* @__PURE__ */ jsx25(
|
|
2688
|
+
PostHeader_default,
|
|
2689
|
+
{
|
|
2690
|
+
author,
|
|
2691
|
+
authorHref,
|
|
2692
|
+
group,
|
|
2693
|
+
groupHref,
|
|
2694
|
+
postedAt: post.postedAt,
|
|
2695
|
+
postType: post.postType,
|
|
2696
|
+
isFeatured: post.isFeatured,
|
|
2697
|
+
isPostPreview,
|
|
2698
|
+
isAdmin,
|
|
2699
|
+
isOwner,
|
|
2700
|
+
onErasePress: onErasePress ? handleErasePress : void 0,
|
|
2701
|
+
onCancelPost,
|
|
2702
|
+
renderActionsMenu,
|
|
2703
|
+
linkComponent,
|
|
2704
|
+
imageComponent,
|
|
2705
|
+
labels
|
|
2706
|
+
}
|
|
2707
|
+
),
|
|
2708
|
+
/* @__PURE__ */ jsx25(
|
|
2709
|
+
PostBody_default,
|
|
2710
|
+
{
|
|
2711
|
+
textContent: resolvedContent.textContent,
|
|
2712
|
+
showFull: isPostDetail,
|
|
2713
|
+
isPostDetail,
|
|
2714
|
+
isRichContent: resolvedContent.isRichContent,
|
|
2715
|
+
isEmailPost,
|
|
2716
|
+
hideEmailDescription: isEmailPost && !isPostDetail && resolvedContent.primaryContent?.type === "media",
|
|
2717
|
+
onNavigate,
|
|
2718
|
+
supportDeepviewDomain
|
|
2719
|
+
}
|
|
2720
|
+
),
|
|
2721
|
+
resolvedContent.sections && /* @__PURE__ */ jsx25(
|
|
2722
|
+
PostSectionsView_default,
|
|
2723
|
+
{
|
|
2724
|
+
sections: resolvedContent.sections.sections,
|
|
2725
|
+
isPostDetail,
|
|
2726
|
+
onCardPress: onCardPress ?? (() => {
|
|
2727
|
+
})
|
|
2728
|
+
}
|
|
2729
|
+
),
|
|
2730
|
+
/* @__PURE__ */ jsx25(
|
|
2731
|
+
PostItemsView_default,
|
|
2732
|
+
{
|
|
2733
|
+
primaryContent: resolvedContent.primaryContent,
|
|
2734
|
+
isPostDetail,
|
|
2735
|
+
onCardPress: onCardPress ?? (() => {
|
|
2736
|
+
}),
|
|
2737
|
+
onVotePress: onVotePress ?? (() => {
|
|
2738
|
+
}),
|
|
2739
|
+
isPostOwner: isOwner,
|
|
2740
|
+
parentId: post.context_id,
|
|
2741
|
+
isCommentScope: false,
|
|
2742
|
+
imageComponent,
|
|
2743
|
+
mediaItemStatuses
|
|
2744
|
+
}
|
|
2745
|
+
),
|
|
2746
|
+
/* @__PURE__ */ jsx25(
|
|
2747
|
+
PostUploadStrip_default,
|
|
2748
|
+
{
|
|
2749
|
+
statuses: mediaItemStatuses,
|
|
2750
|
+
labels: {
|
|
2751
|
+
uploadingRemaining: labels?.uploadingRemaining,
|
|
2752
|
+
uploadingDone: labels?.uploadingDone
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
)
|
|
2756
|
+
] }),
|
|
2757
|
+
/* @__PURE__ */ jsx25("div", { className: cn(isPending && "opacity-50 pointer-events-none"), children: /* @__PURE__ */ jsx25(
|
|
2758
|
+
PostFooter_default,
|
|
2759
|
+
{
|
|
2760
|
+
postHref,
|
|
2761
|
+
commentCount,
|
|
2762
|
+
unreadCommentCount,
|
|
2763
|
+
isSnoozed,
|
|
2764
|
+
onSnoozeToggle,
|
|
2765
|
+
showFooterLink,
|
|
2766
|
+
footerLinkLabel,
|
|
2767
|
+
footerLinkHref,
|
|
2768
|
+
renderReactionTrigger,
|
|
2769
|
+
renderReactionModal
|
|
2770
|
+
}
|
|
2771
|
+
) })
|
|
2772
|
+
]
|
|
2773
|
+
}
|
|
2774
|
+
);
|
|
2775
|
+
};
|
|
2776
|
+
var PostCard_default = PostCard;
|
|
2777
|
+
|
|
2778
|
+
// src/components/PostSectionsSummaryView.tsx
|
|
2779
|
+
import { useCallback as useCallback4, useMemo as useMemo8 } from "react";
|
|
2780
|
+
import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2781
|
+
var BODY_SIZE = 80;
|
|
2782
|
+
var PostSectionsSummaryView = ({
|
|
2783
|
+
sections,
|
|
2784
|
+
fontColor,
|
|
2785
|
+
onCardPress
|
|
2786
|
+
}) => {
|
|
2787
|
+
const imageItems = useMemo8(() => {
|
|
2788
|
+
if (!sections || sections.length === 0) return [];
|
|
2789
|
+
return sections.reduce((items, section) => {
|
|
2790
|
+
if (section.type === contentTypeConstants.NEW_POST_MEDIA) {
|
|
2791
|
+
return items.concat(section.data.items || []);
|
|
2792
|
+
}
|
|
2793
|
+
return items;
|
|
2794
|
+
}, []);
|
|
2795
|
+
}, [sections]);
|
|
2796
|
+
const textBody = useMemo8(() => {
|
|
2797
|
+
if (!sections || sections.length === 0) return "";
|
|
2798
|
+
const allBody = sections.reduce((body, section) => {
|
|
2799
|
+
if (section.type === contentTypeConstants.NEW_POST_MEDIA && section.data.body) {
|
|
2800
|
+
return body + (body ? "\n" : "") + section.data.body;
|
|
2801
|
+
}
|
|
2802
|
+
return body;
|
|
2803
|
+
}, "");
|
|
2804
|
+
return allBody ? `${allBody.slice(0, BODY_SIZE)}...` : "";
|
|
2805
|
+
}, [sections]);
|
|
2806
|
+
const renderSectionItem = useCallback4(
|
|
2807
|
+
(section, index) => {
|
|
2808
|
+
const { type, data } = section;
|
|
2809
|
+
if (type === contentTypeConstants.NEW_POST_MESSAGE) {
|
|
2810
|
+
return /* @__PURE__ */ jsx26(
|
|
2811
|
+
AutoLink_default,
|
|
2812
|
+
{
|
|
2813
|
+
text: data.body || "",
|
|
2814
|
+
className: "whitespace-normal px-4 pb-4 leading-relaxed text-gray-800",
|
|
2815
|
+
style: {
|
|
2816
|
+
color: fontColor || "var(--color-foreground)",
|
|
2817
|
+
whiteSpace: "pre-wrap",
|
|
2818
|
+
wordBreak: "break-word"
|
|
2819
|
+
},
|
|
2820
|
+
mentionData: data.mentionData
|
|
2821
|
+
},
|
|
2822
|
+
`${index} - ${data.body}`
|
|
2823
|
+
);
|
|
2824
|
+
}
|
|
2825
|
+
return null;
|
|
2826
|
+
},
|
|
2827
|
+
[fontColor]
|
|
2828
|
+
);
|
|
2829
|
+
if (!sections || sections.length === 0) {
|
|
2830
|
+
return null;
|
|
2831
|
+
}
|
|
2832
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex-col", children: [
|
|
2833
|
+
sections.map((section, index) => {
|
|
2834
|
+
return renderSectionItem(section, index);
|
|
2835
|
+
}),
|
|
2836
|
+
textBody && /* @__PURE__ */ jsx26(
|
|
2837
|
+
AutoLink_default,
|
|
2838
|
+
{
|
|
2839
|
+
text: textBody,
|
|
2840
|
+
className: "whitespace-normal px-4 pb-4 leading-relaxed text-gray-800",
|
|
2841
|
+
style: {
|
|
2842
|
+
color: fontColor || "var(--color-foreground)",
|
|
2843
|
+
whiteSpace: "pre-wrap",
|
|
2844
|
+
wordBreak: "break-word"
|
|
2845
|
+
},
|
|
2846
|
+
mentionData: []
|
|
2847
|
+
},
|
|
2848
|
+
"body"
|
|
2849
|
+
),
|
|
2850
|
+
/* @__PURE__ */ jsx26(
|
|
2851
|
+
PostMediaLayoutCore_default,
|
|
2852
|
+
{
|
|
2853
|
+
items: imageItems
|
|
2854
|
+
}
|
|
2855
|
+
)
|
|
2856
|
+
] });
|
|
2857
|
+
};
|
|
2858
|
+
var PostSectionsSummaryView_default = PostSectionsSummaryView;
|
|
2859
|
+
|
|
2860
|
+
// src/modals/ReactionModal.tsx
|
|
2861
|
+
import { useRef as useRef2, useEffect as useEffect3 } from "react";
|
|
2862
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
2863
|
+
var reactionList = ["\u{1F44D}", "\u{1F60D}", "\u{1F602}", "\u{1F631}", "\u{1F62D}", "\u{1F60E}"];
|
|
2864
|
+
var ReactionModal = ({ isOpen, close, sendReaction, onAnalyticsEvent }) => {
|
|
2865
|
+
const ref = useRef2(null);
|
|
2866
|
+
useEffect3(() => {
|
|
2867
|
+
if (!isOpen) return;
|
|
2868
|
+
onAnalyticsEvent?.("reaction");
|
|
2869
|
+
const handleOutsideClick = (e) => {
|
|
2870
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
2871
|
+
close();
|
|
2872
|
+
}
|
|
2873
|
+
};
|
|
2874
|
+
document.addEventListener("click", handleOutsideClick);
|
|
2875
|
+
return () => {
|
|
2876
|
+
document.removeEventListener("click", handleOutsideClick);
|
|
2877
|
+
};
|
|
2878
|
+
}, [isOpen, close, onAnalyticsEvent]);
|
|
2879
|
+
if (!isOpen) return null;
|
|
2880
|
+
return /* @__PURE__ */ jsx27("div", { className: "z-500 flex items-center justify-center", role: "dialog", "aria-modal": "true", "aria-label": "Reaction picker", children: /* @__PURE__ */ jsx27("div", { ref, className: "rounded-3xl bg-muted p-2", children: /* @__PURE__ */ jsx27("div", { className: "flex justify-around", children: reactionList.map((reaction, index) => {
|
|
2881
|
+
return /* @__PURE__ */ jsx27(
|
|
2882
|
+
"button",
|
|
2883
|
+
{
|
|
2884
|
+
type: "button",
|
|
2885
|
+
onClick: (e) => {
|
|
2886
|
+
e.preventDefault();
|
|
2887
|
+
e.stopPropagation();
|
|
2888
|
+
onAnalyticsEvent?.("reaction_send");
|
|
2889
|
+
sendReaction(reaction);
|
|
2890
|
+
close();
|
|
2891
|
+
},
|
|
2892
|
+
className: "cursor-pointer px-2 text-3xl hover:scale-125 transition-transform",
|
|
2893
|
+
children: reaction
|
|
2894
|
+
},
|
|
2895
|
+
reaction + index
|
|
2896
|
+
);
|
|
2897
|
+
}) }) }) });
|
|
2898
|
+
};
|
|
2899
|
+
export {
|
|
2900
|
+
AutoLink_default as AutoLink,
|
|
2901
|
+
EraseConfirmModal_default as EraseConfirmModal,
|
|
2902
|
+
MediaUploadStatusOverlay_default as MediaUploadStatusOverlay,
|
|
2903
|
+
PostBody_default as PostBody,
|
|
2904
|
+
PostCard_default as PostCard,
|
|
2905
|
+
PostEmail_default as PostEmail,
|
|
2906
|
+
PostEmbedView_default as PostEmbedView,
|
|
2907
|
+
PostFooter_default as PostFooter,
|
|
2908
|
+
PostHeader_default as PostHeader,
|
|
2909
|
+
PostItemsView_default as PostItemsView,
|
|
2910
|
+
PostLinkItem_default as PostLinkItem,
|
|
2911
|
+
PostMediaLayoutCore_default as PostMediaLayoutCore,
|
|
2912
|
+
PostPollView_default as PostPollView,
|
|
2913
|
+
PostSectionSourceInfoView_default as PostSectionSourceInfoView,
|
|
2914
|
+
PostSectionsSummaryView_default as PostSectionsSummaryView,
|
|
2915
|
+
PostSectionsView_default as PostSectionsView,
|
|
2916
|
+
PostTextItem_default as PostTextItem,
|
|
2917
|
+
PostUploadStrip_default as PostUploadStrip,
|
|
2918
|
+
ReactionModal,
|
|
2919
|
+
hasMeaningfulHtml,
|
|
2920
|
+
resolvePostContent
|
|
2921
|
+
};
|
|
2922
|
+
/*!
|
|
2923
|
+
* React Native Autolink
|
|
2924
|
+
*
|
|
2925
|
+
* Copyright 2016-2018 Josh Swan
|
|
2926
|
+
* Released under the MIT license
|
|
2927
|
+
* https://github.com/joshswan/react-native-autolink/blob/master/LICENSE
|
|
2928
|
+
*
|
|
2929
|
+
* Simplified and improved by Dean, to support mention list.
|
|
2930
|
+
* Ported to design-system post-components: routing and config dependencies removed.
|
|
2931
|
+
*/
|
|
2932
|
+
//# sourceMappingURL=index.js.map
|