ajaxter-chat 3.0.16 → 3.1.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/dist/components/BlockList/index.d.ts +1 -0
- package/dist/components/BlockList/index.d.ts.map +1 -0
- package/dist/components/BlockList/index.js +55 -28
- package/dist/components/BlockList/index.js.map +1 -0
- package/dist/components/CallScreen/index.d.ts +3 -0
- package/dist/components/CallScreen/index.d.ts.map +1 -0
- package/dist/components/CallScreen/index.js +107 -29
- package/dist/components/CallScreen/index.js.map +1 -0
- package/dist/components/ChatScreen/index.d.ts +1 -0
- package/dist/components/ChatScreen/index.d.ts.map +1 -0
- package/dist/components/ChatScreen/index.js +493 -294
- package/dist/components/ChatScreen/index.js.map +1 -0
- package/dist/components/ChatWidget.d.ts +1 -0
- package/dist/components/ChatWidget.d.ts.map +1 -0
- package/dist/components/ChatWidget.js +359 -250
- package/dist/components/ChatWidget.js.map +1 -0
- package/dist/components/EmojiPicker/index.d.ts +1 -0
- package/dist/components/EmojiPicker/index.d.ts.map +1 -0
- package/dist/components/EmojiPicker/index.js +19 -7
- package/dist/components/EmojiPicker/index.js.map +1 -0
- package/dist/components/ErrorBoundary/index.d.ts +20 -0
- package/dist/components/ErrorBoundary/index.d.ts.map +1 -0
- package/dist/components/ErrorBoundary/index.js +76 -0
- package/dist/components/ErrorBoundary/index.js.map +1 -0
- package/dist/components/HomeScreen/index.d.ts +1 -0
- package/dist/components/HomeScreen/index.d.ts.map +1 -0
- package/dist/components/HomeScreen/index.js +236 -158
- package/dist/components/HomeScreen/index.js.map +1 -0
- package/dist/components/MaintenanceView/index.d.ts +1 -0
- package/dist/components/MaintenanceView/index.d.ts.map +1 -0
- package/dist/components/MaintenanceView/index.js +28 -12
- package/dist/components/MaintenanceView/index.js.map +1 -0
- package/dist/components/MiniCallBar/index.d.ts +15 -0
- package/dist/components/MiniCallBar/index.d.ts.map +1 -0
- package/dist/components/MiniCallBar/index.js +116 -0
- package/dist/components/MiniCallBar/index.js.map +1 -0
- package/dist/components/PermissionsGateScreen/index.d.ts +1 -0
- package/dist/components/PermissionsGateScreen/index.d.ts.map +1 -0
- package/dist/components/PermissionsGateScreen/index.js +82 -28
- package/dist/components/PermissionsGateScreen/index.js.map +1 -0
- package/dist/components/RecentChatsScreen/index.d.ts +1 -0
- package/dist/components/RecentChatsScreen/index.d.ts.map +1 -0
- package/dist/components/RecentChatsScreen/index.js +79 -19
- package/dist/components/RecentChatsScreen/index.js.map +1 -0
- package/dist/components/SlideNavMenu.d.ts +1 -0
- package/dist/components/SlideNavMenu.d.ts.map +1 -0
- package/dist/components/SlideNavMenu.js +82 -63
- package/dist/components/SlideNavMenu.js.map +1 -0
- package/dist/components/Tabs/BottomTabs.d.ts +1 -0
- package/dist/components/Tabs/BottomTabs.d.ts.map +1 -0
- package/dist/components/Tabs/BottomTabs.js +34 -19
- package/dist/components/Tabs/BottomTabs.js.map +1 -0
- package/dist/components/TicketDetailScreen/index.d.ts +1 -0
- package/dist/components/TicketDetailScreen/index.d.ts.map +1 -0
- package/dist/components/TicketDetailScreen/index.js +66 -27
- package/dist/components/TicketDetailScreen/index.js.map +1 -0
- package/dist/components/TicketFormScreen/index.d.ts +1 -0
- package/dist/components/TicketFormScreen/index.d.ts.map +1 -0
- package/dist/components/TicketFormScreen/index.js +99 -49
- package/dist/components/TicketFormScreen/index.js.map +1 -0
- package/dist/components/TicketScreen/index.d.ts +1 -0
- package/dist/components/TicketScreen/index.d.ts.map +1 -0
- package/dist/components/TicketScreen/index.js +95 -26
- package/dist/components/TicketScreen/index.js.map +1 -0
- package/dist/components/UserListScreen/index.d.ts +1 -0
- package/dist/components/UserListScreen/index.d.ts.map +1 -0
- package/dist/components/UserListScreen/index.js +127 -53
- package/dist/components/UserListScreen/index.js.map +1 -0
- package/dist/components/ViewerBlockedScreen/index.d.ts +1 -0
- package/dist/components/ViewerBlockedScreen/index.d.ts.map +1 -0
- package/dist/components/ViewerBlockedScreen/index.js +113 -61
- package/dist/components/ViewerBlockedScreen/index.js.map +1 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +7 -2
- package/dist/config/index.js.map +1 -0
- package/dist/hooks/useChat.d.ts +9 -1
- package/dist/hooks/useChat.d.ts.map +1 -0
- package/dist/hooks/useChat.js +60 -18
- package/dist/hooks/useChat.js.map +1 -0
- package/dist/hooks/useRemoteConfig.d.ts +1 -0
- package/dist/hooks/useRemoteConfig.d.ts.map +1 -0
- package/dist/hooks/useRemoteConfig.js +12 -8
- package/dist/hooks/useRemoteConfig.js.map +1 -0
- package/dist/hooks/useSocket.d.ts +40 -0
- package/dist/hooks/useSocket.d.ts.map +1 -0
- package/dist/hooks/useSocket.js +190 -0
- package/dist/hooks/useSocket.js.map +1 -0
- package/dist/hooks/useWebRTC.d.ts +10 -2
- package/dist/hooks/useWebRTC.d.ts.map +1 -0
- package/dist/hooks/useWebRTC.js +101 -69
- package/dist/hooks/useWebRTC.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -21
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -1
- package/dist/types/index.js.map +1 -0
- package/dist/utils/chat.d.ts +1 -0
- package/dist/utils/chat.d.ts.map +1 -0
- package/dist/utils/chat.js +17 -7
- package/dist/utils/chat.js.map +1 -0
- package/dist/utils/fileName.d.ts +1 -0
- package/dist/utils/fileName.d.ts.map +1 -0
- package/dist/utils/fileName.js +5 -1
- package/dist/utils/fileName.js.map +1 -0
- package/dist/utils/messageSound.d.ts +1 -0
- package/dist/utils/messageSound.d.ts.map +1 -0
- package/dist/utils/messageSound.js +9 -3
- package/dist/utils/messageSound.js.map +1 -0
- package/dist/utils/presenceStatus.d.ts +1 -0
- package/dist/utils/presenceStatus.d.ts.map +1 -0
- package/dist/utils/presenceStatus.js +11 -4
- package/dist/utils/presenceStatus.js.map +1 -0
- package/dist/utils/privacyConsent.d.ts +1 -0
- package/dist/utils/privacyConsent.d.ts.map +1 -0
- package/dist/utils/privacyConsent.js +9 -3
- package/dist/utils/privacyConsent.js.map +1 -0
- package/dist/utils/reenableRequest.d.ts +1 -0
- package/dist/utils/reenableRequest.d.ts.map +1 -0
- package/dist/utils/reenableRequest.js +5 -1
- package/dist/utils/reenableRequest.js.map +1 -0
- package/dist/utils/theme.d.ts +1 -0
- package/dist/utils/theme.d.ts.map +1 -0
- package/dist/utils/theme.js +10 -4
- package/dist/utils/theme.js.map +1 -0
- package/dist/utils/widgetPermissions.d.ts +1 -0
- package/dist/utils/widgetPermissions.d.ts.map +1 -0
- package/dist/utils/widgetPermissions.js +13 -5
- package/dist/utils/widgetPermissions.js.map +1 -0
- package/dist/utils/widgetSession.d.ts +1 -0
- package/dist/utils/widgetSession.d.ts.map +1 -0
- package/dist/utils/widgetSession.js +9 -3
- package/dist/utils/widgetSession.js.map +1 -0
- package/package.json +3 -3
- package/src/components/CallScreen/index.tsx +23 -1
- package/src/components/ChatScreen/index.tsx +2 -1
- package/src/components/ChatWidget.tsx +314 -263
- package/src/components/ErrorBoundary/index.tsx +62 -0
- package/src/components/HomeScreen/index.tsx +0 -3
- package/src/components/MiniCallBar/index.tsx +150 -0
- package/src/hooks/useChat.ts +59 -12
- package/src/hooks/useSocket.ts +228 -0
- package/src/hooks/useWebRTC.ts +99 -64
- package/src/index.ts +7 -2
|
@@ -1,58 +1,93 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ChatScreen = void 0;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const chat_1 = require("../../utils/chat");
|
|
39
|
+
const fileName_1 = require("../../utils/fileName");
|
|
40
|
+
const privacyConsent_1 = require("../../utils/privacyConsent");
|
|
41
|
+
const EmojiPicker_1 = require("../EmojiPicker");
|
|
42
|
+
const ChatScreen = ({ activeUser, messages, config, isPaused, isReported, isBlocked, onSend, onBack, onClose, onTogglePause, onReport, onBlock, onStartCall, onNavAction, otherDevelopers = [], onTransferToDeveloper, messageSoundEnabled = true, onToggleMessageSound, }) => {
|
|
43
|
+
const [text, setText] = (0, react_1.useState)('');
|
|
44
|
+
const [showEmoji, setShowEmoji] = (0, react_1.useState)(false);
|
|
45
|
+
const [showMenu, setShowMenu] = (0, react_1.useState)(false);
|
|
46
|
+
const [transferOpen, setTransferOpen] = (0, react_1.useState)(false);
|
|
47
|
+
const [isRecording, setIsRecording] = (0, react_1.useState)(false);
|
|
48
|
+
const [recordSec, setRecordSec] = (0, react_1.useState)(0);
|
|
49
|
+
const [showConfirm, setShowConfirm] = (0, react_1.useState)(null);
|
|
50
|
+
const [showPrivacy, setShowPrivacy] = (0, react_1.useState)(false);
|
|
51
|
+
const [pendingAttach, setPendingAttach] = (0, react_1.useState)(null);
|
|
52
|
+
const [waveBars, setWaveBars] = (0, react_1.useState)(() => Array(24).fill(0.08));
|
|
53
|
+
const endRef = (0, react_1.useRef)(null);
|
|
54
|
+
const inputRef = (0, react_1.useRef)(null);
|
|
55
|
+
const fileRef = (0, react_1.useRef)(null);
|
|
56
|
+
const recordTimer = (0, react_1.useRef)(null);
|
|
57
|
+
const mediaRecorder = (0, react_1.useRef)(null);
|
|
58
|
+
const recordChunks = (0, react_1.useRef)([]);
|
|
59
|
+
const discardRecordingRef = (0, react_1.useRef)(false);
|
|
60
|
+
const waveStreamRef = (0, react_1.useRef)(null);
|
|
61
|
+
const audioCtxRef = (0, react_1.useRef)(null);
|
|
62
|
+
const analyserRef = (0, react_1.useRef)(null);
|
|
63
|
+
const waveRafRef = (0, react_1.useRef)(0);
|
|
64
|
+
(0, react_1.useEffect)(() => { var _a; (_a = endRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: 'smooth' }); }, [messages]);
|
|
30
65
|
const privacyEnabled = config.showPrivacyNotice !== false;
|
|
31
|
-
useEffect(() => {
|
|
66
|
+
(0, react_1.useEffect)(() => {
|
|
32
67
|
if (!privacyEnabled)
|
|
33
68
|
return;
|
|
34
|
-
setShowPrivacy(shouldShowPrivacyNotice(config.id));
|
|
69
|
+
setShowPrivacy((0, privacyConsent_1.shouldShowPrivacyNotice)(config.id));
|
|
35
70
|
}, [config.id, privacyEnabled]);
|
|
36
|
-
useEffect(() => {
|
|
71
|
+
(0, react_1.useEffect)(() => {
|
|
37
72
|
if (!privacyEnabled)
|
|
38
73
|
return;
|
|
39
74
|
const id = window.setInterval(() => {
|
|
40
|
-
setShowPrivacy(shouldShowPrivacyNotice(config.id));
|
|
75
|
+
setShowPrivacy((0, privacyConsent_1.shouldShowPrivacyNotice)(config.id));
|
|
41
76
|
}, 60000);
|
|
42
77
|
return () => window.clearInterval(id);
|
|
43
78
|
}, [config.id, privacyEnabled]);
|
|
44
|
-
const dismissPrivacy = useCallback(() => {
|
|
45
|
-
dismissPrivacyNotice(config.id);
|
|
79
|
+
const dismissPrivacy = (0, react_1.useCallback)(() => {
|
|
80
|
+
(0, privacyConsent_1.dismissPrivacyNotice)(config.id);
|
|
46
81
|
setShowPrivacy(false);
|
|
47
82
|
}, [config.id]);
|
|
48
|
-
const clearPendingAttach = useCallback((revoke) => {
|
|
83
|
+
const clearPendingAttach = (0, react_1.useCallback)((revoke) => {
|
|
49
84
|
setPendingAttach(prev => {
|
|
50
85
|
if (prev && revoke)
|
|
51
86
|
URL.revokeObjectURL(prev.url);
|
|
52
87
|
return null;
|
|
53
88
|
});
|
|
54
89
|
}, []);
|
|
55
|
-
const handleSend = useCallback(() => {
|
|
90
|
+
const handleSend = (0, react_1.useCallback)(() => {
|
|
56
91
|
var _a, _b;
|
|
57
92
|
if (isPaused || isBlocked)
|
|
58
93
|
return;
|
|
@@ -82,8 +117,8 @@ export const ChatScreen = ({ activeUser, messages, config, isPaused, isReported,
|
|
|
82
117
|
handleSend();
|
|
83
118
|
}
|
|
84
119
|
};
|
|
85
|
-
const recordSecRef = useRef(0);
|
|
86
|
-
const stopWaveLoop = useCallback(() => {
|
|
120
|
+
const recordSecRef = (0, react_1.useRef)(0);
|
|
121
|
+
const stopWaveLoop = (0, react_1.useCallback)(() => {
|
|
87
122
|
var _a;
|
|
88
123
|
if (waveRafRef.current) {
|
|
89
124
|
cancelAnimationFrame(waveRafRef.current);
|
|
@@ -232,8 +267,8 @@ export const ChatScreen = ({ activeUser, messages, config, isPaused, isReported,
|
|
|
232
267
|
e.target.value = '';
|
|
233
268
|
};
|
|
234
269
|
const handleTranscript = () => {
|
|
235
|
-
const content = generateTranscript(messages, activeUser);
|
|
236
|
-
downloadText(content, `chat-${activeUser.name.replace(/\s+/g, '_')}-${Date.now()}.txt`);
|
|
270
|
+
const content = (0, chat_1.generateTranscript)(messages, activeUser);
|
|
271
|
+
(0, chat_1.downloadText)(content, `chat-${activeUser.name.replace(/\s+/g, '_')}-${Date.now()}.txt`);
|
|
237
272
|
setShowMenu(false);
|
|
238
273
|
};
|
|
239
274
|
const handleConfirm = (action) => {
|
|
@@ -246,235 +281,361 @@ export const ChatScreen = ({ activeUser, messages, config, isPaused, isReported,
|
|
|
246
281
|
if (action === 'pause')
|
|
247
282
|
onTogglePause();
|
|
248
283
|
};
|
|
249
|
-
const peerAvatar = avatarColor(activeUser.name);
|
|
250
|
-
const peerInit = initials(activeUser.name);
|
|
284
|
+
const peerAvatar = (0, chat_1.avatarColor)(activeUser.name);
|
|
285
|
+
const peerInit = (0, chat_1.initials)(activeUser.name);
|
|
251
286
|
const grouped = groupByDate(messages);
|
|
252
287
|
const viewerIsDev = config.viewerType === 'developer';
|
|
253
288
|
const headerRole = viewerIsDev
|
|
254
289
|
? (activeUser.type === 'user' ? 'Customer' : 'Developer')
|
|
255
290
|
: 'Support';
|
|
256
|
-
return (
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
291
|
+
return (react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', animation: 'cw-slideIn 0.22s ease', position: 'relative', overflow: 'hidden' } },
|
|
292
|
+
react_1.default.createElement("div", { style: {
|
|
293
|
+
background: `linear-gradient(135deg,${config.primaryColor},${config.primaryColor}cc)`,
|
|
294
|
+
padding: '10px 12px', display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0,
|
|
295
|
+
} },
|
|
296
|
+
react_1.default.createElement("button", { type: "button", onClick: onBack, style: hdrBtn, "aria-label": "Back" },
|
|
297
|
+
react_1.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none" },
|
|
298
|
+
react_1.default.createElement("path", { d: "M19 12H5M5 12L12 19M5 12L12 5", stroke: "#fff", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }))),
|
|
299
|
+
react_1.default.createElement("div", { style: { width: 36, height: 36, borderRadius: '50%', backgroundColor: peerAvatar, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontWeight: 700, fontSize: 13, flexShrink: 0, position: 'relative' } },
|
|
300
|
+
peerInit,
|
|
301
|
+
react_1.default.createElement("span", { style: { position: 'absolute', bottom: 0, right: 0, width: 9, height: 9, borderRadius: '50%', border: '2px solid', borderColor: 'transparent', backgroundColor: activeUser.status === 'online' ? '#22c55e' : activeUser.status === 'away' ? '#f59e0b' : '#9ca3af' } })),
|
|
302
|
+
react_1.default.createElement("div", { style: { flex: 1, minWidth: 0 } },
|
|
303
|
+
react_1.default.createElement("div", { style: { fontWeight: 700, fontSize: 14, color: '#fff', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, activeUser.name),
|
|
304
|
+
react_1.default.createElement("div", { style: { fontSize: 11, color: 'rgba(255,255,255,0.8)' } }, activeUser.designation)),
|
|
305
|
+
react_1.default.createElement("span", { style: { fontSize: 13, fontWeight: 700, color: '#fff', opacity: 0.95, flexShrink: 0 } }, headerRole),
|
|
306
|
+
onToggleMessageSound && (react_1.default.createElement("label", { style: {
|
|
307
|
+
display: 'flex',
|
|
308
|
+
alignItems: 'center',
|
|
309
|
+
gap: 6,
|
|
310
|
+
cursor: 'pointer',
|
|
311
|
+
flexShrink: 0,
|
|
312
|
+
marginLeft: 4,
|
|
313
|
+
} },
|
|
314
|
+
react_1.default.createElement("button", { type: "button", role: "switch", "aria-checked": messageSoundEnabled, onClick: () => onToggleMessageSound(!messageSoundEnabled), "aria-label": "Toggle message sound", title: "Toggle message sound", style: {
|
|
315
|
+
width: 36,
|
|
316
|
+
height: 20,
|
|
317
|
+
borderRadius: 10,
|
|
318
|
+
border: 'none',
|
|
319
|
+
background: messageSoundEnabled ? 'rgba(255,255,255,0.35)' : 'rgba(0,0,0,0.2)',
|
|
320
|
+
position: 'relative',
|
|
321
|
+
cursor: 'pointer',
|
|
322
|
+
padding: 0,
|
|
323
|
+
} },
|
|
324
|
+
react_1.default.createElement("span", { style: {
|
|
325
|
+
position: 'absolute',
|
|
326
|
+
top: 2,
|
|
327
|
+
left: messageSoundEnabled ? 18 : 2,
|
|
328
|
+
width: 16,
|
|
329
|
+
height: 16,
|
|
330
|
+
borderRadius: '50%',
|
|
331
|
+
background: '#fff',
|
|
332
|
+
transition: 'left 0.15s ease',
|
|
333
|
+
} })))),
|
|
334
|
+
config.allowWebCall && (react_1.default.createElement("button", { type: "button", onClick: () => onStartCall(false), style: hdrBtn, title: "Voice Call" },
|
|
335
|
+
react_1.default.createElement("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none" },
|
|
336
|
+
react_1.default.createElement("path", { d: "M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07A19.5 19.5 0 013.07 10.8a19.79 19.79 0 01-3.07-8.68A2 2 0 012 0h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L6.09 7.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 14.92v2z", fill: "#fff" })))),
|
|
337
|
+
react_1.default.createElement("button", { type: "button", onClick: () => setShowMenu(v => !v), style: Object.assign(Object.assign({}, hdrBtn), { background: 'rgba(255,255,255,0.2)' }), title: "More options", "aria-expanded": showMenu },
|
|
338
|
+
react_1.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none" },
|
|
339
|
+
react_1.default.createElement("circle", { cx: "12", cy: "5", r: "1.5", fill: "#fff" }),
|
|
340
|
+
react_1.default.createElement("circle", { cx: "12", cy: "12", r: "1.5", fill: "#fff" }),
|
|
341
|
+
react_1.default.createElement("circle", { cx: "12", cy: "19", r: "1.5", fill: "#fff" })))),
|
|
342
|
+
showMenu && (react_1.default.createElement("div", { style: { position: 'absolute', top: 52, right: 12, zIndex: 120, background: '#fff', borderRadius: 12, boxShadow: '0 8px 30px rgba(0,0,0,0.16)', padding: '6px', minWidth: 200, animation: 'cw-fadeUp 0.18s ease' } },
|
|
343
|
+
navEntriesForChat(config.chatType, viewerIsDev).map(item => (react_1.default.createElement(MenuItem, { key: item.key, icon: item.icon, label: item.label, onClick: () => { setShowMenu(false); onNavAction(item.key); } }))),
|
|
344
|
+
react_1.default.createElement("div", { style: { borderTop: '1px solid #f0f2f5', margin: '4px 0' } }),
|
|
345
|
+
config.allowTranscriptDownload && (react_1.default.createElement(MenuItem, { icon: "\uD83D\uDCE5", label: "Download Transcript", onClick: handleTranscript })),
|
|
346
|
+
viewerIsDev && activeUser.type === 'user' && otherDevelopers.length > 0 && onTransferToDeveloper && (react_1.default.createElement(MenuItem, { icon: "\uD83D\uDD00", label: "Transfer to developer", onClick: () => { setShowMenu(false); setTransferOpen(true); } })),
|
|
347
|
+
react_1.default.createElement(MenuItem, { icon: isPaused ? '▶️' : '⏸', label: isPaused ? 'Resume Chat' : 'Pause Chat', onClick: () => { setShowMenu(false); setShowConfirm('pause'); } }),
|
|
348
|
+
config.allowReport && !isReported && (react_1.default.createElement(MenuItem, { icon: "\u26A0\uFE0F", label: "Report Chat", onClick: () => { setShowMenu(false); setShowConfirm('report'); } })),
|
|
349
|
+
config.allowBlock && activeUser.type === 'user' && !isBlocked && (react_1.default.createElement(MenuItem, { icon: "\uD83D\uDEAB", label: "Block User", onClick: () => { setShowMenu(false); setShowConfirm('block'); }, danger: true })),
|
|
350
|
+
react_1.default.createElement("div", { style: { borderTop: '1px solid #f0f2f5', margin: '4px 0' } }),
|
|
351
|
+
react_1.default.createElement(MenuItem, { icon: "\u2715", label: "Close Chat", onClick: onClose }))),
|
|
352
|
+
isPaused && (react_1.default.createElement("div", { style: { background: '#fef3c7', padding: '8px 16px', fontSize: 12, fontWeight: 600, color: '#92400e', textAlign: 'center', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 } },
|
|
353
|
+
"\u23F8 Chat is paused \u2014 users cannot send messages",
|
|
354
|
+
react_1.default.createElement("button", { type: "button", onClick: onTogglePause, style: { background: '#92400e', color: '#fff', border: 'none', borderRadius: 6, padding: '2px 8px', fontSize: 11, cursor: 'pointer', marginLeft: 4 } }, "Resume"))),
|
|
355
|
+
isBlocked && (react_1.default.createElement("div", { style: { background: '#fee2e2', padding: '8px 16px', fontSize: 12, fontWeight: 600, color: '#991b1b', textAlign: 'center', flexShrink: 0 } }, "\uD83D\uDEAB This user is blocked")),
|
|
356
|
+
isReported && (react_1.default.createElement("div", { style: { background: '#fef3c7', padding: '6px 16px', fontSize: 11, color: '#92400e', textAlign: 'center', flexShrink: 0 } }, "\u26A0\uFE0F This chat has been reported")),
|
|
357
|
+
react_1.default.createElement("div", { style: { flex: 1, overflowY: 'auto', padding: '14px', display: 'flex', flexDirection: 'column', gap: 10, background: '#f8f9fc' }, className: "cw-scroll" },
|
|
358
|
+
grouped.map(({ date, msgs }) => (react_1.default.createElement(react_1.default.Fragment, { key: date },
|
|
359
|
+
react_1.default.createElement(DateDivider, { label: date }),
|
|
360
|
+
msgs.map(msg => (react_1.default.createElement(Bubble, { key: msg.id, msg: msg, primaryColor: config.primaryColor })))))),
|
|
361
|
+
messages.length === 0 && (react_1.default.createElement("div", { style: { margin: 'auto', textAlign: 'center', color: '#c4cad4', fontSize: 13 } },
|
|
362
|
+
react_1.default.createElement("div", { style: { fontSize: 28, marginBottom: 8 } }, "\uD83D\uDCAC"),
|
|
363
|
+
"Say hello to ",
|
|
364
|
+
activeUser.name,
|
|
365
|
+
"!")),
|
|
366
|
+
react_1.default.createElement("div", { ref: endRef })),
|
|
367
|
+
react_1.default.createElement("div", { style: { borderTop: '1px solid #eef0f5', padding: '10px 12px 8px', background: '#fff', flexShrink: 0, position: 'relative' } },
|
|
368
|
+
privacyEnabled && showPrivacy && (react_1.default.createElement("div", { style: {
|
|
369
|
+
position: 'relative',
|
|
370
|
+
marginBottom: 10,
|
|
371
|
+
padding: '12px 36px 12px 12px',
|
|
372
|
+
borderRadius: 12,
|
|
373
|
+
background: '#fff',
|
|
374
|
+
border: '1px solid #e8ecf1',
|
|
375
|
+
boxShadow: '0 1px 4px rgba(15,23,42,0.06)',
|
|
376
|
+
} },
|
|
377
|
+
react_1.default.createElement("button", { type: "button", "aria-label": "Dismiss privacy notice", onClick: dismissPrivacy, style: {
|
|
378
|
+
position: 'absolute',
|
|
379
|
+
top: 8,
|
|
380
|
+
right: 8,
|
|
381
|
+
width: 26,
|
|
382
|
+
height: 26,
|
|
383
|
+
borderRadius: '50%',
|
|
384
|
+
border: 'none',
|
|
385
|
+
background: '#f1f5f9',
|
|
386
|
+
cursor: 'pointer',
|
|
387
|
+
display: 'flex',
|
|
388
|
+
alignItems: 'center',
|
|
389
|
+
justifyContent: 'center',
|
|
390
|
+
padding: 0,
|
|
391
|
+
lineHeight: 1,
|
|
392
|
+
} },
|
|
393
|
+
react_1.default.createElement("span", { style: { fontSize: 14, color: '#475569', fontWeight: 700 } }, "\u00D7")),
|
|
394
|
+
react_1.default.createElement("p", { style: { margin: 0, fontSize: 12, color: '#64748b', lineHeight: 1.55 } },
|
|
395
|
+
"By chatting here, you agree we and authorized partners may process, monitor, and record this chat and your data in line with",
|
|
396
|
+
' ',
|
|
397
|
+
config.privacyPolicyUrl ? (react_1.default.createElement("a", { href: config.privacyPolicyUrl, target: "_blank", rel: "noopener noreferrer", style: { color: config.primaryColor, textDecoration: 'underline', fontWeight: 600 } }, "Privacy Policy")) : (react_1.default.createElement("span", { style: { textDecoration: 'underline', fontWeight: 600 } }, "Privacy Policy")),
|
|
398
|
+
"."))),
|
|
399
|
+
showEmoji && config.allowEmoji && (react_1.default.createElement(EmojiPicker_1.EmojiPicker, { primaryColor: config.primaryColor, onSelect: e => setText(t => t + e), onClose: () => setShowEmoji(false) })),
|
|
400
|
+
isRecording && (react_1.default.createElement("div", { style: {
|
|
401
|
+
marginBottom: 10,
|
|
402
|
+
padding: '12px 12px 14px',
|
|
403
|
+
background: '#fff',
|
|
404
|
+
borderRadius: 14,
|
|
405
|
+
border: '1px solid #e8ecf1',
|
|
406
|
+
boxShadow: '0 1px 4px rgba(15,23,42,0.06)',
|
|
407
|
+
} },
|
|
408
|
+
react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10, marginBottom: 10 } },
|
|
409
|
+
react_1.default.createElement("button", { type: "button", onClick: cancelRecording, title: "Discard recording", "aria-label": "Discard recording", style: {
|
|
410
|
+
background: 'none',
|
|
411
|
+
border: 'none',
|
|
412
|
+
cursor: 'pointer',
|
|
413
|
+
padding: 6,
|
|
414
|
+
lineHeight: 0,
|
|
415
|
+
flexShrink: 0,
|
|
416
|
+
} },
|
|
417
|
+
react_1.default.createElement("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none" },
|
|
418
|
+
react_1.default.createElement("path", { d: "M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6", stroke: "#ef4444", strokeWidth: "2", strokeLinecap: "round" }),
|
|
419
|
+
react_1.default.createElement("path", { d: "M10 11v6M14 11v6", stroke: "#ef4444", strokeWidth: "2", strokeLinecap: "round" }))),
|
|
420
|
+
react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'flex-end', gap: 3, height: 44, flex: 1, justifyContent: 'flex-end', minWidth: 0 } }, waveBars.map((h, i) => (react_1.default.createElement("span", { key: i, style: {
|
|
421
|
+
width: 3,
|
|
422
|
+
borderRadius: 2,
|
|
423
|
+
background: '#cbd5e1',
|
|
424
|
+
height: `${8 + h * 36}px`,
|
|
425
|
+
transition: 'height 0.05s ease-out',
|
|
426
|
+
} }))))),
|
|
427
|
+
react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 } },
|
|
428
|
+
react_1.default.createElement("div", { style: { flex: 1 } }),
|
|
429
|
+
react_1.default.createElement("div", { style: {
|
|
430
|
+
background: '#ef4444',
|
|
431
|
+
color: '#fff',
|
|
432
|
+
fontWeight: 700,
|
|
433
|
+
fontSize: 13,
|
|
434
|
+
padding: '6px 14px',
|
|
435
|
+
borderRadius: 999,
|
|
436
|
+
minWidth: 52,
|
|
437
|
+
textAlign: 'center',
|
|
438
|
+
} }, fmtTime(recordSec)),
|
|
439
|
+
react_1.default.createElement("button", { type: "button", onClick: stopRecordingSend, title: "Send voice message", "aria-label": "Send voice message", style: {
|
|
440
|
+
width: 44,
|
|
441
|
+
height: 44,
|
|
442
|
+
borderRadius: '50%',
|
|
443
|
+
border: 'none',
|
|
444
|
+
background: config.primaryColor,
|
|
445
|
+
cursor: 'pointer',
|
|
446
|
+
display: 'flex',
|
|
447
|
+
alignItems: 'center',
|
|
448
|
+
justifyContent: 'center',
|
|
449
|
+
flexShrink: 0,
|
|
450
|
+
boxShadow: `0 4px 14px ${config.primaryColor}55`,
|
|
451
|
+
} },
|
|
452
|
+
react_1.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none" },
|
|
453
|
+
react_1.default.createElement("path", { d: "M22 2L11 13M22 2L15 22L11 13L2 9L22 2Z", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })))))),
|
|
454
|
+
react_1.default.createElement("div", { style: {
|
|
455
|
+
border: `1.5px solid ${isPaused || isBlocked ? '#e5e7eb' : '#bfdbfe'}`,
|
|
456
|
+
borderRadius: 16,
|
|
457
|
+
padding: '10px 12px 8px',
|
|
458
|
+
background: isPaused || isBlocked ? '#f9fafb' : '#fff',
|
|
459
|
+
} },
|
|
460
|
+
pendingAttach && (react_1.default.createElement("div", { style: {
|
|
461
|
+
display: 'flex',
|
|
462
|
+
alignItems: 'center',
|
|
463
|
+
gap: 10,
|
|
464
|
+
marginBottom: 10,
|
|
465
|
+
padding: '8px 10px',
|
|
466
|
+
borderRadius: 10,
|
|
467
|
+
background: '#f8fafc',
|
|
468
|
+
border: '1px solid #fecaca',
|
|
469
|
+
position: 'relative',
|
|
470
|
+
} },
|
|
471
|
+
react_1.default.createElement("div", { style: {
|
|
472
|
+
width: 40,
|
|
473
|
+
height: 40,
|
|
474
|
+
borderRadius: 8,
|
|
475
|
+
background: config.primaryColor,
|
|
260
476
|
display: 'flex',
|
|
261
477
|
alignItems: 'center',
|
|
262
|
-
|
|
478
|
+
justifyContent: 'center',
|
|
479
|
+
flexShrink: 0,
|
|
480
|
+
} },
|
|
481
|
+
react_1.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none" },
|
|
482
|
+
react_1.default.createElement("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66L9.41 17.41a2 2 0 01-2.83-2.83l8.49-8.48", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }))),
|
|
483
|
+
react_1.default.createElement("div", { style: { flex: 1, minWidth: 0 } },
|
|
484
|
+
react_1.default.createElement("div", { style: { fontWeight: 700, fontSize: 13, color: '#1a2332', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, title: pendingAttach.file.name }, pendingAttach.file.name),
|
|
485
|
+
react_1.default.createElement("div", { style: { fontSize: 11, color: '#94a3b8', fontWeight: 600, textTransform: 'uppercase' } }, (pendingAttach.file.type.split('/')[1] || 'file').slice(0, 8))),
|
|
486
|
+
react_1.default.createElement("button", { type: "button", onClick: () => clearPendingAttach(true), title: "Remove attachment", "aria-label": "Remove attachment", style: {
|
|
487
|
+
position: 'absolute',
|
|
488
|
+
top: 6,
|
|
489
|
+
right: 6,
|
|
490
|
+
width: 22,
|
|
491
|
+
height: 22,
|
|
492
|
+
borderRadius: '50%',
|
|
493
|
+
border: 'none',
|
|
494
|
+
background: '#ef4444',
|
|
495
|
+
color: '#fff',
|
|
263
496
|
cursor: 'pointer',
|
|
497
|
+
fontSize: 15,
|
|
498
|
+
fontWeight: 700,
|
|
499
|
+
lineHeight: 1,
|
|
500
|
+
display: 'flex',
|
|
501
|
+
alignItems: 'center',
|
|
502
|
+
justifyContent: 'center',
|
|
503
|
+
padding: 0,
|
|
504
|
+
} }, "\u00D7"))),
|
|
505
|
+
react_1.default.createElement("textarea", { ref: inputRef, value: text, onChange: e => setText(e.target.value), onKeyDown: handleKey, onPaste: handlePaste, placeholder: isPaused || isBlocked ? 'Chat is unavailable' : 'Compose your message…', disabled: isPaused || isBlocked || isRecording, rows: 2, style: {
|
|
506
|
+
width: '100%',
|
|
507
|
+
resize: 'none',
|
|
508
|
+
border: 'none',
|
|
509
|
+
outline: 'none',
|
|
510
|
+
fontSize: 14,
|
|
511
|
+
lineHeight: 1.45,
|
|
512
|
+
color: '#1a2332',
|
|
513
|
+
background: 'transparent',
|
|
514
|
+
maxHeight: 88,
|
|
515
|
+
overflowY: 'auto',
|
|
516
|
+
fontFamily: 'inherit',
|
|
517
|
+
marginBottom: 8,
|
|
518
|
+
} }),
|
|
519
|
+
react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 } },
|
|
520
|
+
react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: 2 } },
|
|
521
|
+
config.allowEmoji && (react_1.default.createElement(ActionBtn, { onClick: () => setShowEmoji(v => !v), title: "Emoji" },
|
|
522
|
+
react_1.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none" },
|
|
523
|
+
react_1.default.createElement("circle", { cx: "12", cy: "12", r: "10", stroke: "#94a3b8", strokeWidth: "1.8" }),
|
|
524
|
+
react_1.default.createElement("path", { d: "M8 14s1.5 2 4 2 4-2 4-2", stroke: "#94a3b8", strokeWidth: "1.8", strokeLinecap: "round" }),
|
|
525
|
+
react_1.default.createElement("circle", { cx: "9", cy: "9", r: "1", fill: "#94a3b8" }),
|
|
526
|
+
react_1.default.createElement("circle", { cx: "15", cy: "9", r: "1", fill: "#94a3b8" })))),
|
|
527
|
+
config.allowAttachment && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
528
|
+
react_1.default.createElement("input", { ref: fileRef, type: "file", style: { display: 'none' }, onChange: handleFileChange }),
|
|
529
|
+
react_1.default.createElement(ActionBtn, { onClick: () => { var _a; return (_a = fileRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, title: "Attach file" },
|
|
530
|
+
react_1.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none" },
|
|
531
|
+
react_1.default.createElement("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66L9.41 17.41a2 2 0 01-2.83-2.83l8.49-8.48", stroke: "#94a3b8", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }))))),
|
|
532
|
+
config.allowVoiceMessage && !isRecording && (react_1.default.createElement(ActionBtn, { onClick: startRecording, title: "Voice message" },
|
|
533
|
+
react_1.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none" },
|
|
534
|
+
react_1.default.createElement("path", { d: "M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z", stroke: "#94a3b8", strokeWidth: "1.8", strokeLinecap: "round" }),
|
|
535
|
+
react_1.default.createElement("path", { d: "M19 10v2a7 7 0 01-14 0v-2M12 19v4M8 23h8", stroke: "#94a3b8", strokeWidth: "1.8", strokeLinecap: "round" }))))),
|
|
536
|
+
react_1.default.createElement("button", { type: "button", onClick: handleSend, disabled: (!text.trim() && !pendingAttach) || isPaused || isBlocked || isRecording, style: {
|
|
537
|
+
width: 36,
|
|
538
|
+
height: 36,
|
|
539
|
+
borderRadius: '50%',
|
|
540
|
+
backgroundColor: (text.trim() || pendingAttach) && !isPaused && !isBlocked ? config.primaryColor : '#e2e8f0',
|
|
541
|
+
border: 'none',
|
|
542
|
+
cursor: (text.trim() || pendingAttach) && !isPaused && !isBlocked ? 'pointer' : 'default',
|
|
543
|
+
display: 'flex',
|
|
544
|
+
alignItems: 'center',
|
|
545
|
+
justifyContent: 'center',
|
|
264
546
|
flexShrink: 0,
|
|
265
|
-
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
boxShadow: '0 1px 4px rgba(15,23,42,0.06)',
|
|
292
|
-
}, children: [_jsx("button", { type: "button", "aria-label": "Dismiss privacy notice", onClick: dismissPrivacy, style: {
|
|
293
|
-
position: 'absolute',
|
|
294
|
-
top: 8,
|
|
295
|
-
right: 8,
|
|
296
|
-
width: 26,
|
|
297
|
-
height: 26,
|
|
298
|
-
borderRadius: '50%',
|
|
299
|
-
border: 'none',
|
|
300
|
-
background: '#f1f5f9',
|
|
301
|
-
cursor: 'pointer',
|
|
302
|
-
display: 'flex',
|
|
303
|
-
alignItems: 'center',
|
|
304
|
-
justifyContent: 'center',
|
|
305
|
-
padding: 0,
|
|
306
|
-
lineHeight: 1,
|
|
307
|
-
}, children: _jsx("span", { style: { fontSize: 14, color: '#475569', fontWeight: 700 }, children: "\u00D7" }) }), _jsxs("p", { style: { margin: 0, fontSize: 12, color: '#64748b', lineHeight: 1.55 }, children: ["By chatting here, you agree we and authorized partners may process, monitor, and record this chat and your data in line with", ' ', config.privacyPolicyUrl ? (_jsx("a", { href: config.privacyPolicyUrl, target: "_blank", rel: "noopener noreferrer", style: { color: config.primaryColor, textDecoration: 'underline', fontWeight: 600 }, children: "Privacy Policy" })) : (_jsx("span", { style: { textDecoration: 'underline', fontWeight: 600 }, children: "Privacy Policy" })), "."] })] })), showEmoji && config.allowEmoji && (_jsx(EmojiPicker, { primaryColor: config.primaryColor, onSelect: e => setText(t => t + e), onClose: () => setShowEmoji(false) })), isRecording && (_jsxs("div", { style: {
|
|
308
|
-
marginBottom: 10,
|
|
309
|
-
padding: '12px 12px 14px',
|
|
310
|
-
background: '#fff',
|
|
311
|
-
borderRadius: 14,
|
|
312
|
-
border: '1px solid #e8ecf1',
|
|
313
|
-
boxShadow: '0 1px 4px rgba(15,23,42,0.06)',
|
|
314
|
-
}, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10, marginBottom: 10 }, children: [_jsx("button", { type: "button", onClick: cancelRecording, title: "Discard recording", "aria-label": "Discard recording", style: {
|
|
315
|
-
background: 'none',
|
|
316
|
-
border: 'none',
|
|
317
|
-
cursor: 'pointer',
|
|
318
|
-
padding: 6,
|
|
319
|
-
lineHeight: 0,
|
|
320
|
-
flexShrink: 0,
|
|
321
|
-
}, children: _jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [_jsx("path", { d: "M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6", stroke: "#ef4444", strokeWidth: "2", strokeLinecap: "round" }), _jsx("path", { d: "M10 11v6M14 11v6", stroke: "#ef4444", strokeWidth: "2", strokeLinecap: "round" })] }) }), _jsx("div", { style: { display: 'flex', alignItems: 'flex-end', gap: 3, height: 44, flex: 1, justifyContent: 'flex-end', minWidth: 0 }, children: waveBars.map((h, i) => (_jsx("span", { style: {
|
|
322
|
-
width: 3,
|
|
323
|
-
borderRadius: 2,
|
|
324
|
-
background: '#cbd5e1',
|
|
325
|
-
height: `${8 + h * 36}px`,
|
|
326
|
-
transition: 'height 0.05s ease-out',
|
|
327
|
-
} }, i))) })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }, children: [_jsx("div", { style: { flex: 1 } }), _jsx("div", { style: {
|
|
328
|
-
background: '#ef4444',
|
|
329
|
-
color: '#fff',
|
|
330
|
-
fontWeight: 700,
|
|
331
|
-
fontSize: 13,
|
|
332
|
-
padding: '6px 14px',
|
|
333
|
-
borderRadius: 999,
|
|
334
|
-
minWidth: 52,
|
|
335
|
-
textAlign: 'center',
|
|
336
|
-
}, children: fmtTime(recordSec) }), _jsx("button", { type: "button", onClick: stopRecordingSend, title: "Send voice message", "aria-label": "Send voice message", style: {
|
|
337
|
-
width: 44,
|
|
338
|
-
height: 44,
|
|
339
|
-
borderRadius: '50%',
|
|
340
|
-
border: 'none',
|
|
341
|
-
background: config.primaryColor,
|
|
342
|
-
cursor: 'pointer',
|
|
343
|
-
display: 'flex',
|
|
344
|
-
alignItems: 'center',
|
|
345
|
-
justifyContent: 'center',
|
|
346
|
-
flexShrink: 0,
|
|
347
|
-
boxShadow: `0 4px 14px ${config.primaryColor}55`,
|
|
348
|
-
}, children: _jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M22 2L11 13M22 2L15 22L11 13L2 9L22 2Z", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] })), _jsxs("div", { style: {
|
|
349
|
-
border: `1.5px solid ${isPaused || isBlocked ? '#e5e7eb' : '#bfdbfe'}`,
|
|
350
|
-
borderRadius: 16,
|
|
351
|
-
padding: '10px 12px 8px',
|
|
352
|
-
background: isPaused || isBlocked ? '#f9fafb' : '#fff',
|
|
353
|
-
}, children: [pendingAttach && (_jsxs("div", { style: {
|
|
354
|
-
display: 'flex',
|
|
355
|
-
alignItems: 'center',
|
|
356
|
-
gap: 10,
|
|
357
|
-
marginBottom: 10,
|
|
358
|
-
padding: '8px 10px',
|
|
359
|
-
borderRadius: 10,
|
|
360
|
-
background: '#f8fafc',
|
|
361
|
-
border: '1px solid #fecaca',
|
|
362
|
-
position: 'relative',
|
|
363
|
-
}, children: [_jsx("div", { style: {
|
|
364
|
-
width: 40,
|
|
365
|
-
height: 40,
|
|
366
|
-
borderRadius: 8,
|
|
367
|
-
background: config.primaryColor,
|
|
368
|
-
display: 'flex',
|
|
369
|
-
alignItems: 'center',
|
|
370
|
-
justifyContent: 'center',
|
|
371
|
-
flexShrink: 0,
|
|
372
|
-
}, children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66L9.41 17.41a2 2 0 01-2.83-2.83l8.49-8.48", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: { fontWeight: 700, fontSize: 13, color: '#1a2332', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, title: pendingAttach.file.name, children: pendingAttach.file.name }), _jsx("div", { style: { fontSize: 11, color: '#94a3b8', fontWeight: 600, textTransform: 'uppercase' }, children: (pendingAttach.file.type.split('/')[1] || 'file').slice(0, 8) })] }), _jsx("button", { type: "button", onClick: () => clearPendingAttach(true), title: "Remove attachment", "aria-label": "Remove attachment", style: {
|
|
373
|
-
position: 'absolute',
|
|
374
|
-
top: 6,
|
|
375
|
-
right: 6,
|
|
376
|
-
width: 22,
|
|
377
|
-
height: 22,
|
|
378
|
-
borderRadius: '50%',
|
|
379
|
-
border: 'none',
|
|
380
|
-
background: '#ef4444',
|
|
381
|
-
color: '#fff',
|
|
382
|
-
cursor: 'pointer',
|
|
383
|
-
fontSize: 15,
|
|
384
|
-
fontWeight: 700,
|
|
385
|
-
lineHeight: 1,
|
|
386
|
-
display: 'flex',
|
|
387
|
-
alignItems: 'center',
|
|
388
|
-
justifyContent: 'center',
|
|
389
|
-
padding: 0,
|
|
390
|
-
}, children: "\u00D7" })] })), _jsx("textarea", { ref: inputRef, value: text, onChange: e => setText(e.target.value), onKeyDown: handleKey, onPaste: handlePaste, placeholder: isPaused || isBlocked ? 'Chat is unavailable' : 'Compose your message…', disabled: isPaused || isBlocked || isRecording, rows: 2, style: {
|
|
391
|
-
width: '100%',
|
|
392
|
-
resize: 'none',
|
|
393
|
-
border: 'none',
|
|
394
|
-
outline: 'none',
|
|
395
|
-
fontSize: 14,
|
|
396
|
-
lineHeight: 1.45,
|
|
397
|
-
color: '#1a2332',
|
|
398
|
-
background: 'transparent',
|
|
399
|
-
maxHeight: 88,
|
|
400
|
-
overflowY: 'auto',
|
|
401
|
-
fontFamily: 'inherit',
|
|
402
|
-
marginBottom: 8,
|
|
403
|
-
} }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 2 }, children: [config.allowEmoji && (_jsx(ActionBtn, { onClick: () => setShowEmoji(v => !v), title: "Emoji", children: _jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [_jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "#94a3b8", strokeWidth: "1.8" }), _jsx("path", { d: "M8 14s1.5 2 4 2 4-2 4-2", stroke: "#94a3b8", strokeWidth: "1.8", strokeLinecap: "round" }), _jsx("circle", { cx: "9", cy: "9", r: "1", fill: "#94a3b8" }), _jsx("circle", { cx: "15", cy: "9", r: "1", fill: "#94a3b8" })] }) })), config.allowAttachment && (_jsxs(_Fragment, { children: [_jsx("input", { ref: fileRef, type: "file", style: { display: 'none' }, onChange: handleFileChange }), _jsx(ActionBtn, { onClick: () => { var _a; return (_a = fileRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, title: "Attach file", children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66L9.41 17.41a2 2 0 01-2.83-2.83l8.49-8.48", stroke: "#94a3b8", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })), config.allowVoiceMessage && !isRecording && (_jsx(ActionBtn, { onClick: startRecording, title: "Voice message", children: _jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [_jsx("path", { d: "M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z", stroke: "#94a3b8", strokeWidth: "1.8", strokeLinecap: "round" }), _jsx("path", { d: "M19 10v2a7 7 0 01-14 0v-2M12 19v4M8 23h8", stroke: "#94a3b8", strokeWidth: "1.8", strokeLinecap: "round" })] }) }))] }), _jsx("button", { type: "button", onClick: handleSend, disabled: (!text.trim() && !pendingAttach) || isPaused || isBlocked || isRecording, style: {
|
|
404
|
-
width: 36,
|
|
405
|
-
height: 36,
|
|
406
|
-
borderRadius: '50%',
|
|
407
|
-
backgroundColor: (text.trim() || pendingAttach) && !isPaused && !isBlocked ? config.primaryColor : '#e2e8f0',
|
|
408
|
-
border: 'none',
|
|
409
|
-
cursor: (text.trim() || pendingAttach) && !isPaused && !isBlocked ? 'pointer' : 'default',
|
|
410
|
-
display: 'flex',
|
|
411
|
-
alignItems: 'center',
|
|
412
|
-
justifyContent: 'center',
|
|
413
|
-
flexShrink: 0,
|
|
414
|
-
transition: 'background 0.15s',
|
|
415
|
-
}, title: "Send", children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M22 2L11 13M22 2L15 22L11 13L2 9L22 2Z", stroke: (text.trim() || pendingAttach) && !isPaused && !isBlocked ? '#fff' : '#94a3b8', strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), (config.footerPoweredBy || config.branch) && (_jsxs("p", { style: { margin: '10px 0 0', textAlign: 'center', fontSize: 12, color: '#94a3b8' }, children: [config.footerPoweredBy, config.footerPoweredBy && config.branch ? ' · ' : '', config.branch && _jsx("span", { style: { fontWeight: 600, color: '#64748b' }, children: config.branch })] }))] }), transferOpen && otherDevelopers.length > 0 && onTransferToDeveloper && (_jsx("div", { style: {
|
|
416
|
-
position: 'absolute',
|
|
417
|
-
inset: 0,
|
|
418
|
-
background: 'rgba(0,0,0,0.45)',
|
|
547
|
+
transition: 'background 0.15s',
|
|
548
|
+
}, title: "Send" },
|
|
549
|
+
react_1.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none" },
|
|
550
|
+
react_1.default.createElement("path", { d: "M22 2L11 13M22 2L15 22L11 13L2 9L22 2Z", stroke: (text.trim() || pendingAttach) && !isPaused && !isBlocked ? '#fff' : '#94a3b8', strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }))))),
|
|
551
|
+
(config.footerPoweredBy || config.branch) && (react_1.default.createElement("p", { style: { margin: '10px 0 0', textAlign: 'center', fontSize: 12, color: '#94a3b8' } },
|
|
552
|
+
config.footerPoweredBy,
|
|
553
|
+
config.footerPoweredBy && config.branch ? ' · ' : '',
|
|
554
|
+
config.branch && react_1.default.createElement("span", { style: { fontWeight: 600, color: '#64748b' } }, config.branch)))),
|
|
555
|
+
transferOpen && otherDevelopers.length > 0 && onTransferToDeveloper && (react_1.default.createElement("div", { style: {
|
|
556
|
+
position: 'absolute',
|
|
557
|
+
inset: 0,
|
|
558
|
+
background: 'rgba(0,0,0,0.45)',
|
|
559
|
+
display: 'flex',
|
|
560
|
+
alignItems: 'center',
|
|
561
|
+
justifyContent: 'center',
|
|
562
|
+
zIndex: 280,
|
|
563
|
+
padding: 16,
|
|
564
|
+
} },
|
|
565
|
+
react_1.default.createElement("div", { style: {
|
|
566
|
+
background: '#fff',
|
|
567
|
+
borderRadius: 16,
|
|
568
|
+
padding: '18px 16px',
|
|
569
|
+
width: '100%',
|
|
570
|
+
maxWidth: 320,
|
|
571
|
+
maxHeight: '70%',
|
|
572
|
+
overflow: 'hidden',
|
|
419
573
|
display: 'flex',
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
574
|
+
flexDirection: 'column',
|
|
575
|
+
boxShadow: '0 16px 48px rgba(0,0,0,0.22)',
|
|
576
|
+
} },
|
|
577
|
+
react_1.default.createElement("div", { style: { fontWeight: 800, fontSize: 16, color: '#1a2332', marginBottom: 6 } }, "Transfer chat to"),
|
|
578
|
+
react_1.default.createElement("p", { style: { fontSize: 12, color: '#7b8fa1', margin: '0 0 12px', lineHeight: 1.5 } }, "Assign this conversation to another developer. History is kept and a handoff note is added."),
|
|
579
|
+
react_1.default.createElement("div", { className: "cw-scroll", style: { flex: 1, overflowY: 'auto', margin: '0 -4px' } }, otherDevelopers.map(dev => (react_1.default.createElement("button", { key: dev.uid, type: "button", onClick: () => {
|
|
580
|
+
onTransferToDeveloper(dev);
|
|
581
|
+
setTransferOpen(false);
|
|
582
|
+
}, style: {
|
|
428
583
|
width: '100%',
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
584
|
+
textAlign: 'left',
|
|
585
|
+
padding: '12px 12px',
|
|
586
|
+
marginBottom: 6,
|
|
587
|
+
border: '1px solid #eef0f5',
|
|
588
|
+
borderRadius: 12,
|
|
589
|
+
background: '#f8fafc',
|
|
590
|
+
cursor: 'pointer',
|
|
591
|
+
fontSize: 14,
|
|
592
|
+
fontWeight: 600,
|
|
593
|
+
color: '#1e293b',
|
|
594
|
+
} },
|
|
595
|
+
dev.name,
|
|
596
|
+
react_1.default.createElement("span", { style: { display: 'block', fontSize: 11, fontWeight: 500, color: '#64748b', marginTop: 2 } }, dev.designation))))),
|
|
597
|
+
react_1.default.createElement("button", { type: "button", onClick: () => setTransferOpen(false), style: {
|
|
598
|
+
marginTop: 12,
|
|
599
|
+
padding: '10px',
|
|
600
|
+
borderRadius: 10,
|
|
601
|
+
border: '1.5px solid #e5e7eb',
|
|
602
|
+
background: '#fff',
|
|
603
|
+
fontWeight: 600,
|
|
604
|
+
fontSize: 13,
|
|
605
|
+
color: '#475569',
|
|
606
|
+
cursor: 'pointer',
|
|
607
|
+
} }, "Cancel")))),
|
|
608
|
+
showConfirm && (react_1.default.createElement("div", { style: {
|
|
609
|
+
position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.45)',
|
|
610
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 300,
|
|
611
|
+
borderRadius: 'inherit',
|
|
612
|
+
} },
|
|
613
|
+
react_1.default.createElement("div", { style: { background: '#fff', borderRadius: 16, padding: '24px 20px', width: 280, boxShadow: '0 16px 48px rgba(0,0,0,0.22)', animation: 'cw-fadeUp 0.2s ease' } },
|
|
614
|
+
react_1.default.createElement("div", { style: { fontWeight: 800, fontSize: 16, color: '#1a2332', marginBottom: 8 } },
|
|
615
|
+
showConfirm === 'pause' && (isPaused ? 'Resume Chat?' : 'Pause Chat?'),
|
|
616
|
+
showConfirm === 'report' && 'Report this chat?',
|
|
617
|
+
showConfirm === 'block' && 'Block this user?'),
|
|
618
|
+
react_1.default.createElement("p", { style: { fontSize: 13, color: '#7b8fa1', lineHeight: 1.6, margin: '0 0 18px' } },
|
|
619
|
+
showConfirm === 'pause' && (isPaused ? 'The user will be able to send messages again.' : 'The user will not be able to send new messages.'),
|
|
620
|
+
showConfirm === 'report' && 'This chat will be flagged for review by the admin team.',
|
|
621
|
+
showConfirm === 'block' && 'This user will be blocked and added to your block list. You can unblock them later.'),
|
|
622
|
+
react_1.default.createElement("div", { style: { display: 'flex', gap: 10 } },
|
|
623
|
+
react_1.default.createElement("button", { type: "button", onClick: () => setShowConfirm(null), style: { flex: 1, padding: '9px', borderRadius: 10, border: '1.5px solid #e5e7eb', background: '#fff', cursor: 'pointer', fontSize: 13, fontWeight: 600, color: '#374151' } }, "Cancel"),
|
|
624
|
+
react_1.default.createElement("button", { type: "button", onClick: () => handleConfirm(showConfirm), style: {
|
|
625
|
+
flex: 1, padding: '9px', borderRadius: 10, border: 'none',
|
|
626
|
+
background: showConfirm === 'block' ? '#ef4444' : config.primaryColor,
|
|
627
|
+
color: '#fff', cursor: 'pointer', fontSize: 13, fontWeight: 700,
|
|
628
|
+
} }, "Confirm")))))));
|
|
469
629
|
};
|
|
630
|
+
exports.ChatScreen = ChatScreen;
|
|
470
631
|
const VoiceRow = ({ msg, isMe, primaryColor }) => {
|
|
471
632
|
var _a;
|
|
472
|
-
const audioRef = useRef(null);
|
|
473
|
-
const [playing, setPlaying] = useState(false);
|
|
474
|
-
const [current, setCurrent] = useState(0);
|
|
475
|
-
const [dur, setDur] = useState((_a = msg.voiceDuration) !== null && _a !== void 0 ? _a : 0);
|
|
633
|
+
const audioRef = (0, react_1.useRef)(null);
|
|
634
|
+
const [playing, setPlaying] = (0, react_1.useState)(false);
|
|
635
|
+
const [current, setCurrent] = (0, react_1.useState)(0);
|
|
636
|
+
const [dur, setDur] = (0, react_1.useState)((_a = msg.voiceDuration) !== null && _a !== void 0 ? _a : 0);
|
|
476
637
|
const url = msg.voiceUrl;
|
|
477
|
-
useEffect(() => {
|
|
638
|
+
(0, react_1.useEffect)(() => {
|
|
478
639
|
const a = audioRef.current;
|
|
479
640
|
if (!a || !url)
|
|
480
641
|
return;
|
|
@@ -502,64 +663,101 @@ const VoiceRow = ({ msg, isMe, primaryColor }) => {
|
|
|
502
663
|
const pct = dur > 0 ? Math.min(100, (current / dur) * 100) : 0;
|
|
503
664
|
const timeLabel = fmtTime(Math.floor(current)) + ' / ' + fmtTime(Math.floor(dur || msg.voiceDuration || 0));
|
|
504
665
|
if (!url) {
|
|
505
|
-
return (
|
|
666
|
+
return (react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
667
|
+
react_1.default.createElement("span", { style: { fontSize: 13 } }, "\uD83C\uDFA4"),
|
|
668
|
+
react_1.default.createElement("span", { style: { fontSize: 13 } },
|
|
669
|
+
"Voice message",
|
|
670
|
+
msg.voiceDuration ? ` · ${msg.voiceDuration}s` : '')));
|
|
506
671
|
}
|
|
507
|
-
return (
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
672
|
+
return (react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: 10, minWidth: 200 } },
|
|
673
|
+
url && (react_1.default.createElement("audio", { ref: audioRef, src: url, preload: "metadata", onPlay: () => setPlaying(true), onPause: () => setPlaying(false), onEnded: () => { setPlaying(false); setCurrent(0); } })),
|
|
674
|
+
react_1.default.createElement("button", { type: "button", onClick: toggle, style: {
|
|
675
|
+
width: 36,
|
|
676
|
+
height: 36,
|
|
677
|
+
borderRadius: '50%',
|
|
678
|
+
border: 'none',
|
|
679
|
+
background: isMe ? 'rgba(255,255,255,0.95)' : '#fff',
|
|
680
|
+
color: isMe ? primaryColor : primaryColor,
|
|
681
|
+
cursor: 'pointer',
|
|
682
|
+
display: 'flex',
|
|
683
|
+
alignItems: 'center',
|
|
684
|
+
justifyContent: 'center',
|
|
685
|
+
flexShrink: 0,
|
|
686
|
+
boxShadow: '0 1px 4px rgba(0,0,0,0.12)',
|
|
687
|
+
}, "aria-label": playing ? 'Pause' : 'Play' }, playing ? (react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor" },
|
|
688
|
+
react_1.default.createElement("rect", { x: "6", y: "4", width: "4", height: "16" }),
|
|
689
|
+
react_1.default.createElement("rect", { x: "14", y: "4", width: "4", height: "16" }))) : (react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor" },
|
|
690
|
+
react_1.default.createElement("path", { d: "M8 5v14l11-7z" })))),
|
|
691
|
+
react_1.default.createElement("div", { style: { flex: 1, minWidth: 0 } },
|
|
692
|
+
react_1.default.createElement("div", { style: { height: 4, borderRadius: 2, background: isMe ? 'rgba(255,255,255,0.35)' : '#e2e8f0', overflow: 'hidden' } },
|
|
693
|
+
react_1.default.createElement("div", { style: { width: `${pct}%`, height: '100%', background: isMe ? '#fff' : primaryColor, borderRadius: 2, transition: 'width 0.1s linear' } })),
|
|
694
|
+
react_1.default.createElement("div", { style: { fontSize: 11, marginTop: 4, opacity: 0.9 } }, timeLabel))));
|
|
521
695
|
};
|
|
522
696
|
const AttachmentRow = ({ msg, isMe, primaryColor }) => {
|
|
523
697
|
var _a, _b;
|
|
524
698
|
const name = (_a = msg.attachmentName) !== null && _a !== void 0 ? _a : 'File';
|
|
525
699
|
const href = msg.attachmentUrl;
|
|
526
|
-
const label = shortAttachmentLabel(name, 10);
|
|
700
|
+
const label = (0, fileName_1.shortAttachmentLabel)(name, 10);
|
|
527
701
|
const mime = (_b = msg.attachmentMime) !== null && _b !== void 0 ? _b : '';
|
|
528
702
|
const isImage = mime.startsWith('image/') || /\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(name);
|
|
529
|
-
return (
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
703
|
+
return (react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'stretch', gap: 8, flexWrap: 'wrap' } },
|
|
704
|
+
isImage && href && (react_1.default.createElement("a", { href: href, download: name, title: name, style: { alignSelf: 'flex-start', lineHeight: 0 } },
|
|
705
|
+
react_1.default.createElement("img", { src: href, alt: "", style: { maxWidth: 220, maxHeight: 200, borderRadius: 10, objectFit: 'cover', display: 'block' } }))),
|
|
706
|
+
react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: 10 } },
|
|
707
|
+
!isImage && (react_1.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 } },
|
|
708
|
+
react_1.default.createElement("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66L9.41 17.41a2 2 0 01-2.83-2.83l8.49-8.48", stroke: isMe ? '#fff' : '#334155', strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }))),
|
|
709
|
+
react_1.default.createElement("div", { style: { flex: 1, minWidth: 0 } },
|
|
710
|
+
href ? (react_1.default.createElement("a", { href: href, download: name, title: name, style: {
|
|
711
|
+
fontWeight: 700,
|
|
712
|
+
fontSize: 14,
|
|
713
|
+
wordBreak: 'break-word',
|
|
714
|
+
color: isMe ? '#fff' : primaryColor,
|
|
715
|
+
textDecoration: 'underline',
|
|
716
|
+
} },
|
|
717
|
+
"[",
|
|
718
|
+
label,
|
|
719
|
+
"]")) : (react_1.default.createElement("div", { style: { fontWeight: 700, fontSize: 14, wordBreak: 'break-word' }, title: name },
|
|
720
|
+
"[",
|
|
721
|
+
label,
|
|
722
|
+
"]")),
|
|
723
|
+
msg.attachmentSize && react_1.default.createElement("div", { style: { fontSize: 11, opacity: 0.8 } }, msg.attachmentSize)))));
|
|
536
724
|
};
|
|
537
725
|
const Bubble = ({ msg, primaryColor }) => {
|
|
538
726
|
const isMe = msg.senderId === 'me';
|
|
539
727
|
const caption = msg.text.trim();
|
|
540
|
-
const content = msg.type === 'voice' ? (
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
728
|
+
const content = msg.type === 'voice' ? (react_1.default.createElement(VoiceRow, { msg: msg, isMe: isMe, primaryColor: primaryColor })) : msg.type === 'attachment' ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
729
|
+
react_1.default.createElement(AttachmentRow, { msg: msg, isMe: isMe, primaryColor: primaryColor }),
|
|
730
|
+
caption && caption !== ' ' && (react_1.default.createElement("div", { style: { marginTop: 6, fontSize: 14, whiteSpace: 'pre-wrap', wordBreak: 'break-word' } }, msg.text)))) : (react_1.default.createElement("span", null, msg.text));
|
|
731
|
+
return (react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: isMe ? 'flex-end' : 'flex-start', gap: 3 } },
|
|
732
|
+
react_1.default.createElement("div", { style: {
|
|
733
|
+
maxWidth: '85%', padding: '10px 13px',
|
|
734
|
+
borderRadius: isMe ? '18px 18px 4px 18px' : '18px 18px 18px 4px',
|
|
735
|
+
backgroundColor: isMe ? primaryColor : '#fff',
|
|
736
|
+
color: isMe ? '#fff' : '#1a2332',
|
|
737
|
+
fontSize: 14, lineHeight: 1.5,
|
|
738
|
+
boxShadow: '0 1px 4px rgba(0,0,0,0.07)',
|
|
739
|
+
wordBreak: 'break-word',
|
|
740
|
+
} }, content),
|
|
741
|
+
react_1.default.createElement("span", { style: { fontSize: 11, color: '#b0bec5', padding: '0 4px' } }, (0, chat_1.formatTime)(msg.timestamp))));
|
|
550
742
|
};
|
|
551
|
-
const DateDivider = ({ label }) => (
|
|
552
|
-
|
|
743
|
+
const DateDivider = ({ label }) => (react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: 10, margin: '4px 0' } },
|
|
744
|
+
react_1.default.createElement("div", { style: { flex: 1, height: 1, background: '#e5e7eb' } }),
|
|
745
|
+
react_1.default.createElement("span", { style: { fontSize: 11, fontWeight: 600, color: '#64748b', whiteSpace: 'nowrap' } }, label),
|
|
746
|
+
react_1.default.createElement("div", { style: { flex: 1, height: 1, background: '#e5e7eb' } })));
|
|
747
|
+
const MenuItem = ({ icon, label, onClick, danger }) => (react_1.default.createElement("button", { type: "button", onClick: onClick, style: {
|
|
553
748
|
display: 'flex', alignItems: 'center', gap: 10, width: '100%', padding: '9px 12px',
|
|
554
749
|
background: 'none', border: 'none', borderRadius: 8, cursor: 'pointer', textAlign: 'left',
|
|
555
750
|
fontSize: 13, fontWeight: 600, color: danger ? '#ef4444' : '#374151',
|
|
556
751
|
transition: 'background 0.12s',
|
|
557
|
-
}, onMouseEnter: e => e.currentTarget.style.background = danger ? '#fee2e2' : '#f3f4f6', onMouseLeave: e => e.currentTarget.style.background = 'none'
|
|
558
|
-
|
|
752
|
+
}, onMouseEnter: e => e.currentTarget.style.background = danger ? '#fee2e2' : '#f3f4f6', onMouseLeave: e => e.currentTarget.style.background = 'none' },
|
|
753
|
+
react_1.default.createElement("span", null, icon),
|
|
754
|
+
" ",
|
|
755
|
+
label));
|
|
756
|
+
const ActionBtn = ({ onClick, title, children }) => (react_1.default.createElement("button", { type: "button", onClick: onClick, title: title, style: {
|
|
559
757
|
background: 'none', border: 'none', cursor: 'pointer', padding: '8px',
|
|
560
758
|
borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
|
|
561
759
|
transition: 'background 0.13s',
|
|
562
|
-
}, onMouseEnter: e => e.currentTarget.style.background = '#f1f5f9', onMouseLeave: e => e.currentTarget.style.background = 'none', children
|
|
760
|
+
}, onMouseEnter: e => e.currentTarget.style.background = '#f1f5f9', onMouseLeave: e => e.currentTarget.style.background = 'none' }, children));
|
|
563
761
|
const hdrBtn = {
|
|
564
762
|
background: 'rgba(255,255,255,0.2)', border: 'none', borderRadius: '50%',
|
|
565
763
|
width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
@@ -579,7 +777,7 @@ function navEntriesForChat(chatType, isStaff) {
|
|
|
579
777
|
function groupByDate(messages) {
|
|
580
778
|
const map = new Map();
|
|
581
779
|
messages.forEach(m => {
|
|
582
|
-
const d = formatDate(m.timestamp);
|
|
780
|
+
const d = (0, chat_1.formatDate)(m.timestamp);
|
|
583
781
|
if (!map.has(d))
|
|
584
782
|
map.set(d, []);
|
|
585
783
|
map.get(d).push(m);
|
|
@@ -591,3 +789,4 @@ function fmtTime(sec) {
|
|
|
591
789
|
const s = Math.max(0, sec % 60);
|
|
592
790
|
return `${m}:${String(s).padStart(2, '0')}`;
|
|
593
791
|
}
|
|
792
|
+
//# sourceMappingURL=index.js.map
|