transcriptify 1.0.0
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/LICENSE +21 -0
- package/README.md +78 -0
- package/dist/src/generateHtml.d.ts +3 -0
- package/dist/src/generateHtml.js +303 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +252 -0
- package/dist/src/transcript.d.ts +12 -0
- package/dist/src/transcript.js +179 -0
- package/dist/src/types/entities.d.ts +30 -0
- package/dist/src/types/entities.js +2 -0
- package/dist/src/utils/assetManager.d.ts +12 -0
- package/dist/src/utils/assetManager.js +295 -0
- package/dist/src/utils/authors.d.ts +4 -0
- package/dist/src/utils/authors.js +115 -0
- package/dist/src/utils/cache.d.ts +16 -0
- package/dist/src/utils/cache.js +29 -0
- package/dist/src/utils/extractors.d.ts +112 -0
- package/dist/src/utils/extractors.js +223 -0
- package/dist/src/utils/polls.d.ts +2 -0
- package/dist/src/utils/polls.js +91 -0
- package/dist/src/utils/transformer.d.ts +6 -0
- package/dist/src/utils/transformer.js +78 -0
- package/dist/src/utils/user.d.ts +4 -0
- package/dist/src/utils/user.js +56 -0
- package/dist/src/web/client.d.ts +20 -0
- package/dist/src/web/client.js +21 -0
- package/dist/src/web/discord-components/AudioPlayer.d.ts +5 -0
- package/dist/src/web/discord-components/AudioPlayer.js +231 -0
- package/dist/src/web/discord-components/Button.d.ts +3 -0
- package/dist/src/web/discord-components/Button.js +27 -0
- package/dist/src/web/discord-components/ChannelPinnedMessage.d.ts +7 -0
- package/dist/src/web/discord-components/ChannelPinnedMessage.js +11 -0
- package/dist/src/web/discord-components/DateSeperator.d.ts +3 -0
- package/dist/src/web/discord-components/DateSeperator.js +19 -0
- package/dist/src/web/discord-components/Embed.d.ts +2 -0
- package/dist/src/web/discord-components/Embed.js +78 -0
- package/dist/src/web/discord-components/ForwardedMessage.d.ts +2 -0
- package/dist/src/web/discord-components/ForwardedMessage.js +44 -0
- package/dist/src/web/discord-components/Message.d.ts +2 -0
- package/dist/src/web/discord-components/Message.js +543 -0
- package/dist/src/web/discord-components/PinnedMessagesModal.d.ts +6 -0
- package/dist/src/web/discord-components/PinnedMessagesModal.js +119 -0
- package/dist/src/web/discord-components/PinnedMessagesOverview.d.ts +5 -0
- package/dist/src/web/discord-components/PinnedMessagesOverview.js +22 -0
- package/dist/src/web/discord-components/Reply.d.ts +2 -0
- package/dist/src/web/discord-components/Reply.js +42 -0
- package/dist/src/web/discord-components/StickerPreview.d.ts +6 -0
- package/dist/src/web/discord-components/StickerPreview.js +40 -0
- package/dist/src/web/discord-components/ThemeSwitcher.d.ts +2 -0
- package/dist/src/web/discord-components/ThemeSwitcher.js +54 -0
- package/dist/src/web/discord-components/Transcript.d.ts +2 -0
- package/dist/src/web/discord-components/Transcript.js +174 -0
- package/dist/src/web/discord-components/UserJoinMessage.d.ts +3 -0
- package/dist/src/web/discord-components/UserJoinMessage.js +33 -0
- package/dist/src/web/discord-components/VideoPlayer.d.ts +6 -0
- package/dist/src/web/discord-components/VideoPlayer.js +222 -0
- package/dist/src/web/discord-components/icons/ChevronDownIcon.d.ts +1 -0
- package/dist/src/web/discord-components/icons/ChevronDownIcon.js +7 -0
- package/dist/src/web/discord-components/icons/CloseIcon.d.ts +1 -0
- package/dist/src/web/discord-components/icons/CloseIcon.js +7 -0
- package/dist/src/web/discord-components/icons/ExternalLinkIcon.d.ts +1 -0
- package/dist/src/web/discord-components/icons/ExternalLinkIcon.js +7 -0
- package/dist/src/web/discord-components/icons/FileAudioIcon.d.ts +1 -0
- package/dist/src/web/discord-components/icons/FileAudioIcon.js +7 -0
- package/dist/src/web/discord-components/icons/FileCodeIcon.d.ts +1 -0
- package/dist/src/web/discord-components/icons/FileCodeIcon.js +7 -0
- package/dist/src/web/discord-components/icons/FileDocumentIcon.d.ts +1 -0
- package/dist/src/web/discord-components/icons/FileDocumentIcon.js +7 -0
- package/dist/src/web/discord-components/icons/PinIcon.d.ts +1 -0
- package/dist/src/web/discord-components/icons/PinIcon.js +7 -0
- package/dist/src/web/discord-components/icons/VerifiedIcon.d.ts +1 -0
- package/dist/src/web/discord-components/icons/VerifiedIcon.js +7 -0
- package/dist/src/web/discord-components/index.d.ts +11 -0
- package/dist/src/web/discord-components/index.js +24 -0
- package/dist/src/web/discord-components/messageHelpers.d.ts +8 -0
- package/dist/src/web/discord-components/messageHelpers.js +72 -0
- package/dist/src/web/discord-components/themeColors.d.ts +9 -0
- package/dist/src/web/discord-components/themeColors.js +320 -0
- package/dist/src/web/discord-components/transcriptHelpers.d.ts +19 -0
- package/dist/src/web/discord-components/transcriptHelpers.js +120 -0
- package/dist/src/web/discord-components/types.d.ts +1 -0
- package/dist/src/web/discord-components/types.js +2 -0
- package/dist/src/web/discord-components/utils/date.d.ts +3 -0
- package/dist/src/web/discord-components/utils/date.js +50 -0
- package/dist/src/web/discord-components/utils/markdown.d.ts +11 -0
- package/dist/src/web/discord-components/utils/markdown.js +538 -0
- package/dist/src/web/discord-components/utils/markdownUtils.d.ts +12 -0
- package/dist/src/web/discord-components/utils/markdownUtils.js +140 -0
- package/dist/src/web/helpers/avatarHelpers.d.ts +2 -0
- package/dist/src/web/helpers/avatarHelpers.js +15 -0
- package/dist/src/web/helpers/cdnHelpers.d.ts +5 -0
- package/dist/src/web/helpers/cdnHelpers.js +48 -0
- package/dist/src/web/helpers/contentHelpers.d.ts +9 -0
- package/dist/src/web/helpers/contentHelpers.js +41 -0
- package/dist/src/web/helpers/renderContent.d.ts +2 -0
- package/dist/src/web/helpers/renderContent.js +15 -0
- package/dist/src/web/helpers/scrollHelpers.d.ts +2 -0
- package/dist/src/web/helpers/scrollHelpers.js +31 -0
- package/dist/src/web/helpers/timestampHelpers.d.ts +6 -0
- package/dist/src/web/helpers/timestampHelpers.js +66 -0
- package/dist/src/web/hooks/useMessageContent.d.ts +5 -0
- package/dist/src/web/hooks/useMessageContent.js +37 -0
- package/dist/src/web/index.d.ts +1 -0
- package/dist/src/web/index.js +17 -0
- package/dist/src/web/types/attachment.d.ts +6 -0
- package/dist/src/web/types/attachment.js +2 -0
- package/dist/src/web/types/author.d.ts +14 -0
- package/dist/src/web/types/author.js +2 -0
- package/dist/src/web/types/channel.d.ts +8 -0
- package/dist/src/web/types/channel.js +2 -0
- package/dist/src/web/types/embed.d.ts +52 -0
- package/dist/src/web/types/embed.js +2 -0
- package/dist/src/web/types/interaction.d.ts +8 -0
- package/dist/src/web/types/interaction.js +2 -0
- package/dist/src/web/types/markdown.d.ts +5 -0
- package/dist/src/web/types/markdown.js +2 -0
- package/dist/src/web/types/message.d.ts +73 -0
- package/dist/src/web/types/message.js +2 -0
- package/dist/src/web/types/poll.d.ts +11 -0
- package/dist/src/web/types/poll.js +2 -0
- package/dist/src/web/types/props.d.ts +155 -0
- package/dist/src/web/types/props.js +2 -0
- package/dist/src/web/types/reaction.d.ts +6 -0
- package/dist/src/web/types/reaction.js +2 -0
- package/dist/src/web/types/theme.d.ts +14 -0
- package/dist/src/web/types/theme.js +2 -0
- package/dist/src/web/types/ui.d.ts +10 -0
- package/dist/src/web/types/ui.js +2 -0
- package/dist/types/download.d.ts +12 -0
- package/dist/types/download.js +2 -0
- package/dist/types/exportableTranscript.d.ts +169 -0
- package/dist/types/exportableTranscript.js +2 -0
- package/dist/types/general.d.ts +90 -0
- package/dist/types/general.js +2 -0
- package/package.json +46 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = AudioPlayer;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
9
|
+
const FileAudioIcon_1 = __importDefault(require("./icons/FileAudioIcon"));
|
|
10
|
+
const audioCache = new Map();
|
|
11
|
+
function AudioPlayer({ url, filename, filesize }) {
|
|
12
|
+
const audioRef = react_1.default.useRef(null);
|
|
13
|
+
const [isPlaying, setIsPlaying] = react_1.default.useState(false);
|
|
14
|
+
const [currentTime, setCurrentTime] = react_1.default.useState(0);
|
|
15
|
+
const [duration, setDuration] = react_1.default.useState(0);
|
|
16
|
+
const [isMuted, setIsMuted] = react_1.default.useState(false);
|
|
17
|
+
const [volume, setVolume] = react_1.default.useState(1);
|
|
18
|
+
const volTrackRef = react_1.default.useRef(null);
|
|
19
|
+
const draggingRef = react_1.default.useRef(false);
|
|
20
|
+
const [showVolPopover, setShowVolPopover] = react_1.default.useState(false);
|
|
21
|
+
const hideTimeoutRef = react_1.default.useRef(null);
|
|
22
|
+
const popoverContainerRef = react_1.default.useRef(null);
|
|
23
|
+
const popoverRef = react_1.default.useRef(null);
|
|
24
|
+
const cancelHide = () => {
|
|
25
|
+
if (hideTimeoutRef.current !== null) {
|
|
26
|
+
window.clearTimeout(hideTimeoutRef.current);
|
|
27
|
+
hideTimeoutRef.current = null;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const scheduleHide = (ms = 260) => {
|
|
31
|
+
cancelHide();
|
|
32
|
+
hideTimeoutRef.current = window.setTimeout(() => {
|
|
33
|
+
hideTimeoutRef.current = null;
|
|
34
|
+
setShowVolPopover(false);
|
|
35
|
+
}, ms);
|
|
36
|
+
};
|
|
37
|
+
react_1.default.useEffect(() => {
|
|
38
|
+
return () => {
|
|
39
|
+
cancelHide();
|
|
40
|
+
};
|
|
41
|
+
}, []);
|
|
42
|
+
react_1.default.useEffect(() => {
|
|
43
|
+
if (!showVolPopover)
|
|
44
|
+
return;
|
|
45
|
+
const onMove = (e) => {
|
|
46
|
+
const el = popoverContainerRef.current;
|
|
47
|
+
const pop = popoverRef.current;
|
|
48
|
+
if (!el && !pop)
|
|
49
|
+
return;
|
|
50
|
+
let left = Infinity, top = Infinity, right = -Infinity, bottom = -Infinity;
|
|
51
|
+
const addRect = (r) => {
|
|
52
|
+
if (!r)
|
|
53
|
+
return;
|
|
54
|
+
left = Math.min(left, r.left);
|
|
55
|
+
top = Math.min(top, r.top);
|
|
56
|
+
right = Math.max(right, r.right);
|
|
57
|
+
bottom = Math.max(bottom, r.bottom);
|
|
58
|
+
};
|
|
59
|
+
addRect(el ? el.getBoundingClientRect() : null);
|
|
60
|
+
addRect(pop ? pop.getBoundingClientRect() : null);
|
|
61
|
+
const expand = 20;
|
|
62
|
+
const inside = e.clientX >= left - expand && e.clientX <= right + expand && e.clientY >= top - expand && e.clientY <= bottom + expand;
|
|
63
|
+
if (inside) {
|
|
64
|
+
cancelHide();
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
scheduleHide(400);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
window.addEventListener("mousemove", onMove);
|
|
71
|
+
return () => window.removeEventListener("mousemove", onMove);
|
|
72
|
+
}, [showVolPopover]);
|
|
73
|
+
const handleVolPointer = (clientY) => {
|
|
74
|
+
const el = volTrackRef.current;
|
|
75
|
+
if (!el || !audioRef.current)
|
|
76
|
+
return;
|
|
77
|
+
const rect = el.getBoundingClientRect();
|
|
78
|
+
const y = clientY - rect.top;
|
|
79
|
+
const pct = 1 - y / rect.height;
|
|
80
|
+
const v = Math.max(0, Math.min(1, pct));
|
|
81
|
+
audioRef.current.volume = v;
|
|
82
|
+
audioRef.current.muted = v === 0;
|
|
83
|
+
setVolume(v);
|
|
84
|
+
setIsMuted(v === 0);
|
|
85
|
+
};
|
|
86
|
+
const onGlobalMouseMove = (e) => {
|
|
87
|
+
if (!draggingRef.current)
|
|
88
|
+
return;
|
|
89
|
+
handleVolPointer(e.clientY);
|
|
90
|
+
};
|
|
91
|
+
const onGlobalMouseUp = () => {
|
|
92
|
+
draggingRef.current = false;
|
|
93
|
+
window.removeEventListener("mousemove", onGlobalMouseMove);
|
|
94
|
+
window.removeEventListener("mouseup", onGlobalMouseUp);
|
|
95
|
+
};
|
|
96
|
+
const startDrag = (ev) => {
|
|
97
|
+
draggingRef.current = true;
|
|
98
|
+
handleVolPointer(ev.clientY);
|
|
99
|
+
window.addEventListener("mousemove", onGlobalMouseMove);
|
|
100
|
+
window.addEventListener("mouseup", onGlobalMouseUp);
|
|
101
|
+
};
|
|
102
|
+
const startTouchDrag = (touch) => {
|
|
103
|
+
draggingRef.current = true;
|
|
104
|
+
handleVolPointer(touch.clientY);
|
|
105
|
+
const onTouchMove = (e) => handleVolPointer(e.touches[0].clientY);
|
|
106
|
+
const onTouchEnd = () => {
|
|
107
|
+
draggingRef.current = false;
|
|
108
|
+
window.removeEventListener("touchmove", onTouchMove);
|
|
109
|
+
window.removeEventListener("touchend", onTouchEnd);
|
|
110
|
+
};
|
|
111
|
+
window.addEventListener("touchmove", onTouchMove);
|
|
112
|
+
window.addEventListener("touchend", onTouchEnd);
|
|
113
|
+
};
|
|
114
|
+
const formatTime = (seconds) => {
|
|
115
|
+
if (!isFinite(seconds))
|
|
116
|
+
return "0:00";
|
|
117
|
+
const mins = Math.floor(seconds / 60);
|
|
118
|
+
const secs = Math.floor(seconds % 60);
|
|
119
|
+
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
120
|
+
};
|
|
121
|
+
const togglePlay = () => {
|
|
122
|
+
if (audioRef.current) {
|
|
123
|
+
if (isPlaying) {
|
|
124
|
+
audioRef.current.pause();
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
audioRef.current.play().catch((err) => {
|
|
128
|
+
console.error("Playback failed:", err);
|
|
129
|
+
setIsPlaying(false);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const handlePlay = () => setIsPlaying(true);
|
|
135
|
+
const handlePause = () => setIsPlaying(false);
|
|
136
|
+
const handleTimeUpdate = () => {
|
|
137
|
+
if (audioRef.current)
|
|
138
|
+
setCurrentTime(audioRef.current.currentTime);
|
|
139
|
+
};
|
|
140
|
+
const handleLoadedMetadata = () => {
|
|
141
|
+
if (audioRef.current)
|
|
142
|
+
setDuration(audioRef.current.duration);
|
|
143
|
+
};
|
|
144
|
+
const handleEnded = () => setIsPlaying(false);
|
|
145
|
+
react_1.default.useEffect(() => {
|
|
146
|
+
let a = audioCache.get(url);
|
|
147
|
+
if (!a) {
|
|
148
|
+
a = new Audio(url);
|
|
149
|
+
audioCache.set(url, a);
|
|
150
|
+
}
|
|
151
|
+
audioRef.current = a;
|
|
152
|
+
setVolume(a.volume);
|
|
153
|
+
setIsMuted(a.muted);
|
|
154
|
+
setIsPlaying(!a.paused);
|
|
155
|
+
if (isFinite(a.duration) && a.duration > 0)
|
|
156
|
+
setDuration(a.duration);
|
|
157
|
+
setCurrentTime(a.currentTime);
|
|
158
|
+
a.addEventListener("timeupdate", handleTimeUpdate);
|
|
159
|
+
a.addEventListener("loadedmetadata", handleLoadedMetadata);
|
|
160
|
+
a.addEventListener("ended", handleEnded);
|
|
161
|
+
a.addEventListener("play", handlePlay);
|
|
162
|
+
a.addEventListener("pause", handlePause);
|
|
163
|
+
const handleVolumeChangeEvent = () => {
|
|
164
|
+
if (audioRef.current) {
|
|
165
|
+
setVolume(audioRef.current.volume);
|
|
166
|
+
setIsMuted(audioRef.current.muted);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
a.addEventListener("volumechange", handleVolumeChangeEvent);
|
|
170
|
+
return () => {
|
|
171
|
+
a.removeEventListener("timeupdate", handleTimeUpdate);
|
|
172
|
+
a.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
173
|
+
a.removeEventListener("ended", handleEnded);
|
|
174
|
+
a.removeEventListener("play", handlePlay);
|
|
175
|
+
a.removeEventListener("pause", handlePause);
|
|
176
|
+
a.removeEventListener("volumechange", handleVolumeChangeEvent);
|
|
177
|
+
audioRef.current = null;
|
|
178
|
+
};
|
|
179
|
+
}, [url]);
|
|
180
|
+
const handleSliderChange = (e) => {
|
|
181
|
+
const newTime = parseFloat(e.target.value);
|
|
182
|
+
if (audioRef.current) {
|
|
183
|
+
audioRef.current.currentTime = newTime;
|
|
184
|
+
setCurrentTime(newTime);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
const handleVolumeChange = (e) => {
|
|
188
|
+
if (audioRef.current) {
|
|
189
|
+
audioRef.current.volume = parseFloat(e.target.value);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "w-full max-w-[520px] bg-[#1e1f22] border border-[#111214] rounded-lg p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)(FileAudioIcon_1.default, { className: "h-10 w-8 flex-shrink-0" }), (0, jsx_runtime_1.jsxs)("div", { className: "min-w-0", children: [(0, jsx_runtime_1.jsx)("a", { href: url, download: true, className: "text-[15px] font-medium text-[#00a8fc] truncate hover:underline block", children: filename }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-[#b5bac1]", children: filesize })] })] }), (0, jsx_runtime_1.jsx)("a", { href: url, download: true, className: "ml-2 p-1 hover:bg-[#23252b] rounded transition-colors flex-shrink-0", title: "Download", children: (0, jsx_runtime_1.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { fill: "#b5bac1", d: "M12 2a1 1 0 0 1 1 1v10.59l3.3-3.3a1 1 0 1 1 1.4 1.42l-5 5a1 1 0 0 1-1.4 0l-5-5a1 1 0 1 1 1.4-1.42l3.3 3.3V3a1 1 0 0 1 1-1ZM3 20a1 1 0 1 0 0 2h18a1 1 0 1 0 0-2H3Z" }) }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: togglePlay, className: "p-2 hover:bg-[#23252b] rounded transition-colors flex-shrink-0", title: isPlaying ? "Pause" : "Play", children: isPlaying ? ((0, jsx_runtime_1.jsx)("svg", { className: "controlIcon_cf09d8", "aria-hidden": "true", role: "img", xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", fill: "none", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { fill: "currentColor", d: "M6 4a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H6ZM15 4a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-3Z", className: "" }) })) : ((0, jsx_runtime_1.jsx)("svg", { className: "controlIcon_cf09d8", "aria-hidden": "true", role: "img", xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", fill: "none", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { fill: "currentColor", d: "M9.25 3.35C7.87 2.45 6 3.38 6 4.96v14.08c0 1.58 1.87 2.5 3.25 1.61l10.85-7.04a1.9 1.9 0 0 0 0-3.22L9.25 3.35Z", className: "" }) })) }), (0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-[#b5bac1] min-w-[60px]", children: [formatTime(currentTime), " / ", formatTime(duration)] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 relative h-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute left-0 right-0 top-1/2 transform -translate-y-1/2 h-1 bg-[#23252b] rounded" }), (0, jsx_runtime_1.jsx)("div", { className: "absolute left-0 top-1/2 transform -translate-y-1/2 h-1 bg-[#7c5cff] rounded pointer-events-none", style: { width: `${duration > 0 ? (currentTime / duration) * 100 : 0}%` } }), (0, jsx_runtime_1.jsx)("input", { type: "range", min: 0, max: duration || 0, value: currentTime, onChange: handleSliderChange, className: "absolute left-0 top-0 w-full h-3 bg-transparent appearance-none cursor-pointer" })] }), (0, jsx_runtime_1.jsxs)("div", { ref: (el) => {
|
|
193
|
+
popoverContainerRef.current = el;
|
|
194
|
+
}, className: "relative flex-shrink-0", onMouseEnter: () => {
|
|
195
|
+
cancelHide();
|
|
196
|
+
setShowVolPopover(true);
|
|
197
|
+
}, onMouseLeave: () => {
|
|
198
|
+
scheduleHide(260);
|
|
199
|
+
}, children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => {
|
|
200
|
+
if (audioRef.current) {
|
|
201
|
+
const next = !audioRef.current.muted;
|
|
202
|
+
audioRef.current.muted = next;
|
|
203
|
+
setIsMuted(next);
|
|
204
|
+
}
|
|
205
|
+
}, className: "w-8 h-8 p-1 hover:bg-[#23252b] rounded transition-colors flex items-center justify-center", title: "Toggle mute", children: isMuted ? ((0, jsx_runtime_1.jsx)("svg", { className: "volumeButtonIcon_a8e786", "aria-hidden": "true", role: "img", xmlns: "http://www.w3.org/2000/svg", width: "100%", height: "100%", fill: "none", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { fill: "currentColor", d: "M12 3a1 1 0 0 0-1-1h-.06a1 1 0 0 0-.74.32L5.92 7H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2.92l4.28 4.68a1 1 0 0 0 .74.32H11a1 1 0 0 0 1-1V3ZM22.7 8.3a1 1 0 0 0-1.4 0L19 10.58l-2.3-2.3a1 1 0 1 0-1.4 1.42L17.58 12l-2.3 2.3a1 1 0 0 0 1.42 1.4L19 13.42l2.3 2.3a1 1 0 0 0 1.4-1.42L20.42 12l2.3-2.3a1 1 0 0 0 0-1.4Z", className: "" }) })) : ((0, jsx_runtime_1.jsx)("svg", { width: "100%", height: "100%", viewBox: "0 0 24 24", fill: "#b5bac1", children: (0, jsx_runtime_1.jsx)("path", { d: "M5 9v6h4l5 5V4L9 9H5z" }) })) }), (0, jsx_runtime_1.jsx)("div", { ref: (el) => {
|
|
206
|
+
popoverRef.current = el;
|
|
207
|
+
}, className: `absolute left-1/2 bottom-full volume-popover transition-opacity flex flex-col items-center z-50`, style: {
|
|
208
|
+
transform: "translate(-50%, -2px)",
|
|
209
|
+
width: 14,
|
|
210
|
+
padding: 2,
|
|
211
|
+
opacity: showVolPopover ? 1 : 0,
|
|
212
|
+
pointerEvents: showVolPopover ? "auto" : "none"
|
|
213
|
+
}, children: (0, jsx_runtime_1.jsx)("div", { ref: (el) => {
|
|
214
|
+
volTrackRef.current = el;
|
|
215
|
+
}, onClick: (e) => handleVolPointer(e.clientY), onMouseDown: (e) => {
|
|
216
|
+
cancelHide();
|
|
217
|
+
startDrag(e.nativeEvent);
|
|
218
|
+
}, onTouchStart: (e) => {
|
|
219
|
+
cancelHide();
|
|
220
|
+
startTouchDrag(e.touches[0]);
|
|
221
|
+
}, className: "relative h-28 overflow-visible cursor-pointer flex items-end justify-center", title: "Volume", style: { width: 10 }, children: (0, jsx_runtime_1.jsx)("div", { style: {
|
|
222
|
+
position: "absolute",
|
|
223
|
+
left: "50%",
|
|
224
|
+
transform: "translateX(-50%)",
|
|
225
|
+
bottom: 0,
|
|
226
|
+
width: 6,
|
|
227
|
+
borderRadius: 6,
|
|
228
|
+
background: "#7c5cff",
|
|
229
|
+
height: `${volume * 100}%`
|
|
230
|
+
} }) }) })] })] })] }));
|
|
231
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = Button;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const variantStyles = {
|
|
6
|
+
primary: "bg-[#5865F2] hover:bg-[#4752C4] text-white",
|
|
7
|
+
secondary: "bg-[#4E5058] hover:bg-[#6D6F78] text-white",
|
|
8
|
+
success: "bg-[#3BA55D] hover:bg-[#2D7D46] text-white",
|
|
9
|
+
danger: "bg-[#ED4245] hover:bg-[#C03537] text-white",
|
|
10
|
+
link: "bg-transparent hover:bg-[#4E5058] text-[#00AFF4]"
|
|
11
|
+
};
|
|
12
|
+
function Button({ label, url, variant = "primary", disabled = false, emoji, onClick }) {
|
|
13
|
+
const baseStyles = "px-4 py-2 rounded text-sm font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2";
|
|
14
|
+
const variantStyle = variantStyles[variant];
|
|
15
|
+
const handleClick = (e) => {
|
|
16
|
+
if (disabled)
|
|
17
|
+
return;
|
|
18
|
+
if (onClick) {
|
|
19
|
+
onClick(e);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (url) {
|
|
23
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
return ((0, jsx_runtime_1.jsxs)("button", { className: `${baseStyles} ${variantStyle}`, onClick: handleClick, disabled: disabled, type: "button", children: [emoji && (0, jsx_runtime_1.jsx)("span", { children: emoji }), label] }));
|
|
27
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MessageProps } from "../types/message";
|
|
2
|
+
export default function ChannelPinnedMessage({ message, referencedMessage, onOpenPinnedMessages, onNavigateToMessage }: {
|
|
3
|
+
message: MessageProps;
|
|
4
|
+
referencedMessage?: Partial<MessageProps> | null;
|
|
5
|
+
onOpenPinnedMessages: () => void;
|
|
6
|
+
onNavigateToMessage?: (id: string) => void;
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = ChannelPinnedMessage;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const PinIcon_1 = __importDefault(require("./icons/PinIcon"));
|
|
9
|
+
function ChannelPinnedMessage({ message, referencedMessage, onOpenPinnedMessages, onNavigateToMessage }) {
|
|
10
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 py-1 w-full text-base", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-10 shrink-0 flex items-start justify-start mt-0.5 relative", children: (0, jsx_runtime_1.jsx)("div", { className: "w-10 h-10 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(PinIcon_1.default, { className: "text-[#949BA4]", width: 16, height: 16 }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 text-base", children: [(0, jsx_runtime_1.jsx)("span", { onClick: () => referencedMessage && referencedMessage.id && onNavigateToMessage && onNavigateToMessage(String(referencedMessage.id)), className: "font-semibold text-base hover:underline cursor-pointer", style: { color: message.author.color ?? "#FFFFFF" }, children: message.author.username }), (0, jsx_runtime_1.jsx)("span", { className: "text-[#B5BAC1]", children: " pinned " }), (0, jsx_runtime_1.jsx)("span", { onClick: () => referencedMessage && referencedMessage.id && onNavigateToMessage && onNavigateToMessage(String(referencedMessage.id)), className: "text-white hover:underline cursor-pointer", children: "a message" }), (0, jsx_runtime_1.jsx)("span", { className: "text-[#B5BAC1]", children: " to this channel. " }), (0, jsx_runtime_1.jsx)("span", { className: "text-white hover:underline cursor-pointer", onClick: onOpenPinnedMessages, children: "See all pinned messages." })] })] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = DateSeparator;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
function DateSeparator({ date }) {
|
|
6
|
+
let display = date;
|
|
7
|
+
try {
|
|
8
|
+
const d = new Date(date);
|
|
9
|
+
if (!isNaN(d.getTime())) {
|
|
10
|
+
display = d.toLocaleDateString("en-US", {
|
|
11
|
+
month: "long",
|
|
12
|
+
day: "numeric",
|
|
13
|
+
year: "numeric"
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch (e) { }
|
|
18
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "w-full flex items-center my-4", children: [(0, jsx_runtime_1.jsx)("hr", { className: "flex-1 border-t border-[#29292d]" }), (0, jsx_runtime_1.jsx)("span", { className: "mx-4 text-sm text-[#72767D] text-center flex-none", children: display }), (0, jsx_runtime_1.jsx)("hr", { className: "flex-1 border-t border-[#29292d]" })] }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { EmbedProps } from "../types/embed";
|
|
2
|
+
export default function Embed({ title, description, url, color, timestamp, author, footer, image, thumbnail, fields, buttons, version, resolvedUsers, resolvedRoles, resolvedChannels, channelGuildId, interaction }: EmbedProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = Embed;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
9
|
+
const Button_1 = __importDefault(require("./Button"));
|
|
10
|
+
const date_1 = require("./utils/date");
|
|
11
|
+
const markdown_1 = require("./utils/markdown");
|
|
12
|
+
const messageHelpers_1 = require("./messageHelpers");
|
|
13
|
+
function Embed({ title, description, url, color = null, timestamp = null, author = null, footer = null, image = null, thumbnail = null, fields = [], buttons = [], version = "v1", resolvedUsers, resolvedRoles, resolvedChannels, channelGuildId, interaction }) {
|
|
14
|
+
const [brokenImages, setBrokenImages] = react_1.default.useState(new Set());
|
|
15
|
+
const parseWithContext = (value) => (0, markdown_1.parseMarkdown)(value, resolvedUsers, resolvedRoles, resolvedChannels, channelGuildId);
|
|
16
|
+
const imageUrl = typeof image === "string" ? image : image && image.url ? image.url : null;
|
|
17
|
+
const thumbnailUrl = typeof thumbnail === "string" ? thumbnail : thumbnail && thumbnail.url ? thumbnail.url : null;
|
|
18
|
+
const accent = react_1.default.useMemo(() => {
|
|
19
|
+
if (color === null || color === undefined)
|
|
20
|
+
return "#2b2d31";
|
|
21
|
+
const numColor = typeof color === "number" ? color : typeof color === "string" && /^\d+$/.test(color) ? Number(color) : null;
|
|
22
|
+
if (numColor !== null)
|
|
23
|
+
return `#${numColor.toString(16).padStart(6, "0")}`;
|
|
24
|
+
return color || "#2b2d31";
|
|
25
|
+
}, [color]);
|
|
26
|
+
const embedBg = "#2b2d31";
|
|
27
|
+
const formattedFooter = react_1.default.useMemo(() => {
|
|
28
|
+
if (interaction?.name && interaction?.user?.username && !footer?.text) {
|
|
29
|
+
return {
|
|
30
|
+
text: `Requested by ${interaction.user.username}`,
|
|
31
|
+
iconUrl: footer?.iconUrl
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return footer;
|
|
35
|
+
}, [interaction, footer]);
|
|
36
|
+
const handleImageError = (imgUrl) => {
|
|
37
|
+
if (!imgUrl)
|
|
38
|
+
return;
|
|
39
|
+
setBrokenImages((prev) => new Set([...prev, imgUrl]));
|
|
40
|
+
};
|
|
41
|
+
const renderFieldName = (rawName) => {
|
|
42
|
+
const s = (0, messageHelpers_1.sanitizeMarkdownString)(rawName);
|
|
43
|
+
if (!s || typeof s !== "string")
|
|
44
|
+
return parseWithContext(s);
|
|
45
|
+
if (/__/.test(s)) {
|
|
46
|
+
const nodes = [];
|
|
47
|
+
const regex = /__([\s\S]+?)__/g;
|
|
48
|
+
let lastIndex = 0;
|
|
49
|
+
let m;
|
|
50
|
+
while ((m = regex.exec(s)) !== null) {
|
|
51
|
+
if (m.index > lastIndex) {
|
|
52
|
+
nodes.push((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: parseWithContext(s.slice(lastIndex, m.index)) }, `seg-${lastIndex}`));
|
|
53
|
+
}
|
|
54
|
+
nodes.push((0, jsx_runtime_1.jsx)("u", { style: { textDecoration: "underline", textDecorationThickness: "1px" }, children: parseWithContext(m[1]) }, `u-${m.index}`));
|
|
55
|
+
lastIndex = regex.lastIndex;
|
|
56
|
+
}
|
|
57
|
+
if (lastIndex < s.length)
|
|
58
|
+
nodes.push((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: parseWithContext(s.slice(lastIndex)) }, `seg-${lastIndex}`));
|
|
59
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: nodes.map((n, i) => ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: n }, i))) }));
|
|
60
|
+
}
|
|
61
|
+
return parseWithContext(s);
|
|
62
|
+
};
|
|
63
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex w-auto max-w-[432px] my-2 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-1 rounded-l-md", style: { backgroundColor: accent } }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 rounded-r-md px-4 py-3", style: { backgroundColor: embedBg }, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-start gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-1 space-y-1.5 min-w-0", children: [author && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [author.iconUrl && !brokenImages.has(author.iconUrl) ? ((0, jsx_runtime_1.jsx)("img", { src: author.iconUrl, alt: "", className: "w-5 h-5 rounded-full", onError: () => handleImageError(author.iconUrl) })) : interaction?.name ? ((0, jsx_runtime_1.jsx)("svg", { className: "text-white", "aria-hidden": "true", role: "img", xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "none", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { fill: "currentColor", d: "M2.06 7.61c-.25.95.31 1.92 1.26 2.18l4.3 1.15c.94.25 1.91-.31 2.17-1.26l1.15-4.3c.25-.94-.31-1.91-1.26-2.17l-4.3-1.15c-.94-.25-1.91.31-2.17 1.26l-1.15 4.3ZM12.98 7.87a2 2 0 0 0 1.75 2.95H20a2 2 0 0 0 1.76-2.95l-2.63-4.83a2 2 0 0 0-3.51 0l-2.63 4.83ZM5.86 13.27a.89.89 0 0 1 1.28 0l.75.77a.9.9 0 0 0 .54.26l1.06.12c.5.06.85.52.8 1.02l-.13 1.08c-.02.2.03.42.14.6l.56.92c.27.43.14 1-.28 1.26l-.9.58a.92.92 0 0 0-.37.48l-.36 1.02a.9.9 0 0 1-1.15.57l-1-.36a.89.89 0 0 0-.6 0l-1 .36a.9.9 0 0 1-1.15-.57l-.36-1.02a.92.92 0 0 0-.37-.48l-.9-.58a.93.93 0 0 1-.28-1.26l.56-.93c.11-.17.16-.38.14-.59l-.12-1.08c-.06-.5.3-.96.8-1.02l1.05-.12a.9.9 0 0 0 .54-.26l.75-.77ZM18.52 13.71a1.1 1.1 0 0 0-2.04 0l-.46 1.24c-.19.5-.57.88-1.07 1.07l-1.24.46a1.1 1.1 0 0 0 0 2.04l1.24.46c.5.19.88.57 1.07 1.07l.46 1.24c.35.95 1.7.95 2.04 0l.46-1.24c.19-.5.57-.88 1.07-1.07l1.24-.46a1.1 1.1 0 0 0 0-2.04l-1.24-.46a1.8 1.8 0 0 1-1.07-1.07l-.46-1.24Z" }) })) : null, author.url ? ((0, jsx_runtime_1.jsx)("a", { href: author.url, className: "text-sm font-semibold text-white hover:underline", children: author.name })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-sm font-semibold text-white", children: author.name }))] })), title &&
|
|
64
|
+
(url ? ((0, jsx_runtime_1.jsx)("a", { href: url, className: "text-sky-400 hover:underline font-semibold text-base block", children: parseWithContext((0, messageHelpers_1.sanitizeMarkdownString)(title)) })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-sky-400 font-semibold text-base", children: parseWithContext((0, messageHelpers_1.sanitizeMarkdownString)(title)) }))), description ? ((0, jsx_runtime_1.jsx)("div", { className: "text-[14px] leading-[20px] text-[#DBDEE1] whitespace-pre-line break-words", children: parseWithContext((0, messageHelpers_1.sanitizeMarkdownString)(description)) })) : null, fields.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: `grid gap-x-3 gap-y-2 ${fields.some((f) => f.inline) ? "grid-cols-3" : "grid-cols-1"}`, children: fields.map((field, idx) => ((0, jsx_runtime_1.jsxs)("div", { className: field.inline ? "col-span-1" : "col-span-3", children: [typeof window !== "undefined" && window.location.href.includes("localhost")
|
|
65
|
+
? (() => {
|
|
66
|
+
try {
|
|
67
|
+
const raw = field.name;
|
|
68
|
+
const sanitized = (0, messageHelpers_1.sanitizeMarkdownString)(raw);
|
|
69
|
+
console.debug &&
|
|
70
|
+
console.debug("Embed field.name raw:", raw, "chars:", Array.from(String(raw || "")).map((c) => c.charCodeAt(0)));
|
|
71
|
+
console.debug &&
|
|
72
|
+
console.debug("Embed field.name sanitized:", sanitized, "chars:", Array.from(String(sanitized || "")).map((c) => c.charCodeAt(0)));
|
|
73
|
+
}
|
|
74
|
+
catch (e) { }
|
|
75
|
+
return null;
|
|
76
|
+
})()
|
|
77
|
+
: null, (0, jsx_runtime_1.jsx)("div", { className: "text-xs font-semibold text-white mb-0.5", children: (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: renderFieldName(field.name) }, `fieldname-${idx}`) }), (0, jsx_runtime_1.jsx)("div", { className: "text-[14px] leading-[20px] text-[#DBDEE1] whitespace-pre-line break-words", children: (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: parseWithContext((0, messageHelpers_1.sanitizeMarkdownString)(field.value)) }, `fieldvalue-${idx}`) })] }, idx))) })), imageUrl && !brokenImages.has(imageUrl) ? ((0, jsx_runtime_1.jsx)("div", { className: "mt-1", children: (0, jsx_runtime_1.jsx)("img", { src: imageUrl, alt: "", className: "rounded w-full object-cover", style: { maxHeight: "320px" }, onError: () => handleImageError(imageUrl) }) })) : null, (formattedFooter?.iconUrl || formattedFooter?.text || timestamp) && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-sm text-[#9ca3af]", children: [formattedFooter?.iconUrl && !brokenImages.has(formattedFooter.iconUrl) ? ((0, jsx_runtime_1.jsx)("img", { src: formattedFooter.iconUrl, alt: "", className: "w-5 h-5 rounded-full", onError: () => handleImageError(formattedFooter.iconUrl) })) : null, (0, jsx_runtime_1.jsxs)("span", { children: [formattedFooter?.text, formattedFooter?.text && timestamp && " • ", timestamp && (0, date_1.formatDate)(timestamp)] })] })), buttons.length > 0 && version === "v2" ? ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2 pt-2", children: buttons.map((btn, idx) => ((0, jsx_runtime_1.jsx)(Button_1.default, { ...btn }, idx))) })) : null] }), thumbnailUrl && !brokenImages.has(thumbnailUrl) ? ((0, jsx_runtime_1.jsx)("div", { className: "shrink-0 ml-2", children: (0, jsx_runtime_1.jsx)("img", { src: thumbnailUrl, alt: "", className: "rounded w-20 h-20 object-cover", onError: () => handleImageError(thumbnailUrl) }) })) : null] }) })] }));
|
|
78
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = ForwardedMessage;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const AudioPlayer_1 = __importDefault(require("./AudioPlayer"));
|
|
9
|
+
const Embed_1 = __importDefault(require("./Embed"));
|
|
10
|
+
const FileAudioIcon_1 = __importDefault(require("./icons/FileAudioIcon"));
|
|
11
|
+
const FileCodeIcon_1 = __importDefault(require("./icons/FileCodeIcon"));
|
|
12
|
+
const FileDocumentIcon_1 = __importDefault(require("./icons/FileDocumentIcon"));
|
|
13
|
+
const messageHelpers_1 = require("./messageHelpers");
|
|
14
|
+
function ForwardedMessage({ message, brokenImages, onImageError, renderContent, defaultAvatar }) {
|
|
15
|
+
const getAttachmentIcon = (kind) => {
|
|
16
|
+
switch (kind) {
|
|
17
|
+
case "audio":
|
|
18
|
+
return FileAudioIcon_1.default;
|
|
19
|
+
case "code":
|
|
20
|
+
return FileCodeIcon_1.default;
|
|
21
|
+
default:
|
|
22
|
+
return FileDocumentIcon_1.default;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "relative mt-2 pl-3 border-l-4", style: { borderColor: "#242427" }, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-xs text-[#949BA4] mb-2", children: [(0, jsx_runtime_1.jsx)("svg", { "aria-hidden": "true", role: "img", xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "none", viewBox: "0 0 24 24", className: "w-4 h-4", children: (0, jsx_runtime_1.jsx)("path", { fill: "var(--text-muted, #949BA4)", d: "M21.7 7.3a1 1 0 0 1 0 1.4l-5 5a1 1 0 0 1-1.4-1.4L18.58 9H13a7 7 0 0 0-7 7v4a1 1 0 1 1-2 0v-4a9 9 0 0 1 9-9h5.59l-3.3-3.3a1 1 0 0 1 1.42-1.4l5 5Z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "Forwarded" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0 ml-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "mt-1 text-sm text-[#DBDEE1] break-words", children: message.content ? renderContent(message.content) : null }), message.embeds && message.embeds.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "mt-2 space-y-2", children: message.embeds.map((e, i) => ((0, jsx_runtime_1.jsx)(Embed_1.default, { ...e }, `fwd-embed-${i}`))) })), message.attachments && message.attachments.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "mt-2 flex flex-col gap-2", children: message.attachments.map((a, i) => {
|
|
26
|
+
const url = typeof a === "string" ? a : a?.url || "";
|
|
27
|
+
let filename = typeof a === "string" ? undefined : a?.filename;
|
|
28
|
+
if (!filename)
|
|
29
|
+
filename = (0, messageHelpers_1.extractFilenameFromUrl)(url) || "file";
|
|
30
|
+
const filesize = typeof a === "string" ? "" : (0, messageHelpers_1.formatFileSize)(a?.size, a?.size_human);
|
|
31
|
+
const imageLike = (0, messageHelpers_1.isImageUrl)(url);
|
|
32
|
+
const audioLike = (0, messageHelpers_1.isAudioUrl)(url);
|
|
33
|
+
const isBroken = brokenImages.has(url);
|
|
34
|
+
if (imageLike && !isBroken) {
|
|
35
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "mb-2 max-w-[520px]", children: (0, jsx_runtime_1.jsx)("img", { src: url, alt: filename, className: `rounded w-full h-auto ${isBroken ? "image-error" : ""}`, onError: () => onImageError(url) }) }, `fwd-att-${i}`));
|
|
36
|
+
}
|
|
37
|
+
if (audioLike) {
|
|
38
|
+
return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(AudioPlayer_1.default, { url: url, filename: filename, filesize: filesize }) }, `fwd-att-audio-${i}`));
|
|
39
|
+
}
|
|
40
|
+
const kind = (0, messageHelpers_1.getAttachmentKind)(filename, url);
|
|
41
|
+
const Icon = getAttachmentIcon(kind);
|
|
42
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "group relative inline-block max-w-[520px]", children: (0, jsx_runtime_1.jsxs)("a", { href: url, className: "flex items-center gap-3 px-4 py-3 bg-[#1e1f22] hover:bg-[#23252b] border border-[#111214] rounded-lg transition-colors", target: "_blank", rel: "noreferrer", children: [(0, jsx_runtime_1.jsx)(Icon, { className: "h-10 w-8 flex-shrink-0" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-[15px] font-medium text-[#00a8fc] truncate hover:underline", children: filename }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-[#b5bac1] mt-1", children: filesize })] }), (0, jsx_runtime_1.jsx)("div", { className: "opacity-0 group-hover:opacity-100 transition-opacity", children: (0, jsx_runtime_1.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { fill: "#b5bac1", d: "M12 2a1 1 0 0 1 1 1v10.59l3.3-3.3a1 1 0 1 1 1.4 1.42l-5 5a1 1 0 0 1-1.4 0l-5-5a1 1 0 1 1 1.4-1.42l3.3 3.3V3a1 1 0 0 1 1-1ZM3 20a1 1 0 1 0 0 2h18a1 1 0 1 0 0-2H3Z" }) }) })] }) }, `fwd-att-${i}`));
|
|
43
|
+
}) }))] })] }));
|
|
44
|
+
}
|