@esvndev/es-react-template-chat 0.0.90 → 0.0.92

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/index.js CHANGED
@@ -72139,7 +72139,7 @@ const ChatLog = (props) => {
72139
72139
  const prevListLength = React.useRef(0);
72140
72140
  React.useState(0);
72141
72141
  React.useState(true);
72142
- React.useState(new Set());
72142
+ const [expandedMessages, setExpandedMessages] = React.useState(new Set());
72143
72143
  const [clickedImageFile, setClickedImageFile] = React.useState(null);
72144
72144
  React.useState(false);
72145
72145
  React.useState(new Set());
@@ -72184,7 +72184,7 @@ const ChatLog = (props) => {
72184
72184
  scrollToBottom();
72185
72185
  }
72186
72186
  }, [messageByGroup, checkScroll]);
72187
- React.useMemo(() => {
72187
+ const mentionItems = React.useMemo(() => {
72188
72188
  if (!groupChatUsers) {
72189
72189
  return [];
72190
72190
  }
@@ -72202,7 +72202,7 @@ const ChatLog = (props) => {
72202
72202
  });
72203
72203
  return [{ id: "all", name: "All" }, ...mappedUsers];
72204
72204
  }, [groupChatUsers]);
72205
- React.useCallback((mes) => {
72205
+ const handlePreview = React.useCallback((mes) => {
72206
72206
  setSelectedMessage(mes);
72207
72207
  setOpenModalPreview(true);
72208
72208
  }, []);
@@ -72335,322 +72335,174 @@ const ChatLog = (props) => {
72335
72335
  }
72336
72336
  }
72337
72337
  }, []);
72338
- // const onKeyDown = (event: any) => {
72339
- // if (event.code === 'NumpadEnter') {
72340
- // event.preventDefault()
72341
- // const baseOptions = {
72342
- // key: 'Enter',
72343
- // code: 'Enter',
72344
- // which: 13,
72345
- // keyCode: 13,
72346
- // bubbles: true,
72347
- // shiftKey: event.shiftKey,
72348
- // altKey: event.altKey,
72349
- // ctrlKey: event.ctrlKey,
72350
- // metaKey: event.metaKey
72351
- // }
72352
- // const newEvent = new KeyboardEvent('keydown', baseOptions)
72353
- // event.target.dispatchEvent(newEvent)
72354
- // }
72355
- // }
72356
- // const useParsedChatData = (chatMsg: string) => {
72357
- // if (!chatMsg) { return {} }
72358
- // try {
72359
- // return typeof chatMsg === 'string' ? JSON.parse(chatMsg) : chatMsg
72360
- // } catch (err) {
72361
- // console.error('JSON parse error:', err)
72362
- // return {}
72363
- // }
72364
- // }
72365
- // const renderChatText = useCallback((chat: any) => {
72366
- // const isPath = Array.isArray(chat?.path) && typeof chat.path[0]?.path === "string" ? chat.path[0].path.trim() : ""
72367
- // const img = isPath ? `${CDN_URL_VIEW}/${isPath}` : ""
72368
- // const toggleExpanded = (messageId: string) => {
72369
- // const newExpanded = new Set(expandedMessages)
72370
- // if (newExpanded.has(messageId)) {
72371
- // newExpanded.delete(messageId)
72372
- // } else {
72373
- // newExpanded.add(messageId)
72374
- // }
72375
- // setExpandedMessages(newExpanded)
72376
- // }
72377
- // const formatMentionsReact = (text: string, mentions: any[], messageId: string) => {
72378
- // if (!text || !mentions || mentions.length === 0) { return text }
72379
- // const maxLength = 200
72380
- // const isExpanded = expandedMessages.has(messageId)
72381
- // let displayText = text
72382
- // let isTruncated = false
72383
- // if (!isExpanded && text.length > maxLength) {
72384
- // displayText = text.substring(0, maxLength)
72385
- // isTruncated = true
72386
- // }
72387
- // // Chỉ highlight những mention có trong danh sách
72388
- // let result: any = displayText
72389
- // // Hàm helper để xử lý mention trong cả string và array
72390
- // const processMention = (text: string, mention: any): any => {
72391
- // const escapedName = mention?.name?.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
72392
- // const mentionRegex = new RegExp(`@${escapedName}(?=\\s|$|[.,;:!?()[\\]{}'"\`~@])`, 'g')
72393
- // const parts = text.split(mentionRegex)
72394
- // const matches = text.match(mentionRegex) || []
72395
- // if (matches.length === 0) {
72396
- // return text
72397
- // }
72398
- // const newParts: any[] = []
72399
- // parts.forEach((part: any, index: any) => {
72400
- // newParts.push(part)
72401
- // if (matches[index]) {
72402
- // newParts.push(
72403
- // <span key={`mention-${messageId}-${mention.id || mention.name}-${index}`} className="chat-mention">
72404
- // {matches[index]}
72405
- // </span>
72406
- // )
72407
- // }
72408
- // })
72409
- // return newParts
72410
- // }
72411
- // mentions.forEach((mention: any) => {
72412
- // if (typeof result === 'string') {
72413
- // result = processMention(result, mention)
72414
- // } else if (Array.isArray(result)) {
72415
- // // Xử từng phần tử trong array
72416
- // const processedArray: any[] = []
72417
- // result.forEach((item: any) => {
72418
- // if (typeof item === 'string') {
72419
- // const processed = processMention(item, mention)
72420
- // if (Array.isArray(processed)) {
72421
- // processedArray.push(...processed)
72422
- // } else {
72423
- // processedArray.push(processed)
72424
- // }
72425
- // } else {
72426
- // // Giữ nguyên các React elements đã được xử
72427
- // processedArray.push(item)
72428
- // }
72429
- // })
72430
- // result = processedArray
72431
- // }
72432
- // })
72433
- // // Add expand/collapse functionality
72434
- // if (isTruncated || (isExpanded && text.length > maxLength)) {
72435
- // const expandButton = (
72436
- // <span
72437
- // key={`expand-${messageId}`}
72438
- // onClick={() => toggleExpanded(messageId)}
72439
- // style={{
72440
- // color: '#006edc',
72441
- // cursor: 'pointer',
72442
- // fontWeight: 500,
72443
- // marginLeft: 5
72444
- // }}
72445
- // >
72446
- // {isExpanded ? ' Thu gọn' : '... Mở rộng'}
72447
- // </span>
72448
- // )
72449
- // if (Array.isArray(result)) {
72450
- // result.push(expandButton)
72451
- // } else {
72452
- // result = [result, expandButton]
72453
- // }
72454
- // }
72455
- // return result
72456
- // }
72457
- // return (
72458
- // <>
72459
- // <div>
72460
- // <div>
72461
- // {chat.path && chat.path.length === 1 && (
72462
- // <div className="image-container">
72463
- // {img && <img src={img} alt="" />}
72464
- // </div>
72465
- // )}
72466
- // {isValidUrl(chat.msg) && renderLinkPreview(chat.msg)}
72467
- // {chat.msg && !isValidUrl(chat.msg) ? (
72468
- // <div>{formatMentionsReact(chat.msg, mentionItems, chat.id)}</div>
72469
- // ) : (
72470
- // <></>
72471
- // )}
72472
- // {chat.path && chat.path.length > 1 && (
72473
- // <div className="group-image">
72474
- // {chat.path.map((it: any, index: any) => {
72475
- // return (
72476
- // <div
72477
- // key={index}
72478
- // className="group-image-item image-container"
72479
- // >
72480
- // <img
72481
- // style={{ maxWidth: "100%", maxHeight: 360 }}
72482
- // src={`${CDN_URL_VIEW}/${it.path.trim()}`}
72483
- // onClick={() => handlePreview(it)}
72484
- // alt=""
72485
- // />
72486
- // </div>
72487
- // )
72488
- // })}
72489
- // </div>
72490
- // )}
72491
- // <div className="" style={{ fontSize: "12px", color: "#476285" }}>
72492
- // {moment(chat.time).format("HH:mm")}
72493
- // </div>
72494
- // </div>
72495
- // </div>
72496
- // </>
72497
- // )
72498
- // }, [expandedMessages, handlePreview, mentionItems])
72499
- // const getLinkPreviewData = (urlString: string) => {
72500
- // try {
72501
- // const hasProtocol = /^https?:\/\//i.test(urlString)
72502
- // const href = hasProtocol ? urlString : `https://${urlString}`
72503
- // const url = new URL(href)
72504
- // const displayUrl =
72505
- // urlString.length > 80 ? `${urlString.slice(0, 77)}...` : urlString
72506
- // return {
72507
- // href,
72508
- // displayUrl,
72509
- // host: url.host
72510
- // }
72511
- // } catch (e) {
72512
- // return {
72513
- // href: urlString,
72514
- // displayUrl: urlString,
72515
- // host: ''
72516
- // }
72517
- // }
72518
- // }
72519
- // const renderLinkPreview = (urlString: string) => {
72520
- // const { href, displayUrl, host } = getLinkPreviewData(urlString)
72521
- // return (
72522
- // <>
72523
- // <a
72524
- // href={href}
72525
- // target="_blank"
72526
- // rel="noreferrer"
72527
- // style={{
72528
- // textDecoration: 'none',
72529
- // color: 'inherit'
72530
- // }}
72531
- // >
72532
- // <div
72533
- // style={{
72534
- // marginTop: 4,
72535
- // marginBottom: 4,
72536
- // padding: '8px 10px',
72537
- // borderRadius: 8,
72538
- // backgroundColor: '#eef5ff',
72539
- // border: '1px solid #d3e2ff',
72540
- // maxWidth: 420
72541
- // }}
72542
- // >
72543
- // <div
72544
- // style={{
72545
- // fontSize: 14,
72546
- // fontWeight: 500,
72547
- // color: '#1d4f91',
72548
- // wordBreak: 'break-word'
72549
- // }}
72550
- // >
72551
- // {displayUrl}
72552
- // </div>
72553
- // {host && (
72554
- // <div
72555
- // style={{
72556
- // marginTop: 4,
72557
- // fontSize: 12,
72558
- // color: '#6f6b7d'
72559
- // }}
72560
- // >
72561
- // {host}
72562
- // </div>
72563
- // )}
72564
- // </div>
72565
- // </a>
72566
- // </>
72567
- // )
72568
- // }
72569
- // const renderNotifyLeaveGroup = useCallback((chat: any) => {
72570
- // const msg = JSON.parse(chat?.msg)
72571
- // if (chat?.createdById === dataProfile?.id) {
72572
- // return (
72573
- // <>
72574
- // <div>
72575
- // <span style={{ fontWeight: "bold", marginRight: "5px" }}>
72576
- // {msg?.name}
72577
- // </span>
72578
- // <span>được bạn xoá khỏi nhóm</span>
72579
- // </div>
72580
- // </>
72581
- // )
72582
- // }
72583
- // if (chat?.createdById === msg?.id) {
72584
- // return (
72585
- // <>
72586
- // <div>
72587
- // <span style={{ fontWeight: "bold", marginRight: "5px" }}>
72588
- // {msg?.name}
72589
- // </span>
72590
- // <span>đã rời khỏi nhóm</span>
72591
- // </div>
72592
- // </>
72593
- // )
72594
- // }
72595
- // return (
72596
- // <>
72597
- // <div>
72598
- // <span style={{ fontWeight: "bold", marginRight: "5px" }}>
72599
- // {msg?.name}
72600
- // </span>
72601
- // <span>được <span style={{ fontWeight: "bold", marginRight: "5px" }}>{chat?.createdBy?.name}</span> xoá khỏi nhóm</span>
72602
- // </div>
72603
- // </>
72604
- // )
72605
- // }, [dataProfile])
72606
- // const renderChatNotification = useCallback((chat: any) => {
72607
- // const parseChatMsg = (msg: string) => {
72608
- // if (!msg) { return [] }
72609
- // try {
72610
- // const parsed = typeof msg === 'string' ? JSON.parse(msg) : msg
72611
- // return Array.isArray(parsed) ? parsed : [parsed]
72612
- // } catch (err) {
72613
- // console.error('JSON parse error:', err)
72614
- // return []
72615
- // }
72616
- // }
72617
- // const dataParse = parseChatMsg(chat.msg)
72618
- // // ✅ FIX: Kiểm tra array trước khi dùng slice
72619
- // if (!Array.isArray(dataParse) || dataParse.length === 0) {
72620
- // return (
72621
- // <div>
72622
- // <span>Đã có thay đổi trong nhóm</span>
72623
- // </div>
72624
- // )
72625
- // }
72626
- // const displayedItems = dataParse.slice(0, 2)
72627
- // const extraCount = Math.max(0, dataParse.length - displayedItems.length)
72628
- // return (
72629
- // <>
72630
- // <div>
72631
- // {displayedItems.map((item: any, index: any) => (
72632
- // <strong key={index}>
72633
- // {item.name}
72634
- // {index < displayedItems.length - 1 && ", "}
72635
- // </strong>
72636
- // ))}
72637
- // {dataParse.length > 3 && (
72638
- // <strong>
72639
- // <span style={{ fontWeight: "normal" }}>{" và "}</span>{" "}
72640
- // {extraCount} người khác
72641
- // </strong>
72642
- // )}
72643
- // {" được "}
72644
- // {chat?.createdBy?.id === dataProfile?.id ? (
72645
- // <span>bạn </span>
72646
- // ) : (
72647
- // <strong style={{ marginRight: "5px" }}>{chat?.createdByName}</strong>
72648
- // )}
72649
- // thêm vào nhóm
72650
- // </div>
72651
- // </>
72652
- // )
72653
- // }, [dataProfile])
72338
+ React.useCallback((chat) => {
72339
+ const isPath = Array.isArray(chat?.path) && typeof chat.path[0]?.path === "string" ? chat.path[0].path.trim() : "";
72340
+ const img = isPath ? `${CDN_URL_VIEW}/${isPath}` : "";
72341
+ const toggleExpanded = (messageId) => {
72342
+ const newExpanded = new Set(expandedMessages);
72343
+ if (newExpanded.has(messageId)) {
72344
+ newExpanded.delete(messageId);
72345
+ }
72346
+ else {
72347
+ newExpanded.add(messageId);
72348
+ }
72349
+ setExpandedMessages(newExpanded);
72350
+ };
72351
+ const formatMentionsReact = (text, mentions, messageId) => {
72352
+ if (!text || !mentions || mentions.length === 0) {
72353
+ return text;
72354
+ }
72355
+ const maxLength = 200;
72356
+ const isExpanded = expandedMessages.has(messageId);
72357
+ let displayText = text;
72358
+ let isTruncated = false;
72359
+ if (!isExpanded && text.length > maxLength) {
72360
+ displayText = text.substring(0, maxLength);
72361
+ isTruncated = true;
72362
+ }
72363
+ // Chỉ highlight những mention có trong danh sách
72364
+ let result = displayText;
72365
+ // Hàm helper để xử mention trong cả string và array
72366
+ const processMention = (text, mention) => {
72367
+ const escapedName = mention?.name?.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
72368
+ const mentionRegex = new RegExp(`@${escapedName}(?=\\s|$|[.,;:!?()[\\]{}'"\`~@])`, 'g');
72369
+ const parts = text.split(mentionRegex);
72370
+ const matches = text.match(mentionRegex) || [];
72371
+ if (matches.length === 0) {
72372
+ return text;
72373
+ }
72374
+ const newParts = [];
72375
+ parts.forEach((part, index) => {
72376
+ newParts.push(part);
72377
+ if (matches[index]) {
72378
+ newParts.push(jsxRuntime.jsx("span", { className: "chat-mention", children: matches[index] }, `mention-${messageId}-${mention.id || mention.name}-${index}`));
72379
+ }
72380
+ });
72381
+ return newParts;
72382
+ };
72383
+ mentions.forEach((mention) => {
72384
+ if (typeof result === 'string') {
72385
+ result = processMention(result, mention);
72386
+ }
72387
+ else if (Array.isArray(result)) {
72388
+ // Xử từng phần tử trong array
72389
+ const processedArray = [];
72390
+ result.forEach((item) => {
72391
+ if (typeof item === 'string') {
72392
+ const processed = processMention(item, mention);
72393
+ if (Array.isArray(processed)) {
72394
+ processedArray.push(...processed);
72395
+ }
72396
+ else {
72397
+ processedArray.push(processed);
72398
+ }
72399
+ }
72400
+ else {
72401
+ // Giữ nguyên các React elements đã được xử lý
72402
+ processedArray.push(item);
72403
+ }
72404
+ });
72405
+ result = processedArray;
72406
+ }
72407
+ });
72408
+ // Add expand/collapse functionality
72409
+ if (isTruncated || (isExpanded && text.length > maxLength)) {
72410
+ const expandButton = (jsxRuntime.jsx("span", { onClick: () => toggleExpanded(messageId), style: {
72411
+ color: '#006edc',
72412
+ cursor: 'pointer',
72413
+ fontWeight: 500,
72414
+ marginLeft: 5
72415
+ }, children: isExpanded ? ' Thu gọn' : '... Mở rộng' }, `expand-${messageId}`));
72416
+ if (Array.isArray(result)) {
72417
+ result.push(expandButton);
72418
+ }
72419
+ else {
72420
+ result = [result, expandButton];
72421
+ }
72422
+ }
72423
+ return result;
72424
+ };
72425
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx("div", { children: jsxRuntime.jsxs("div", { children: [chat.path && chat.path.length === 1 && (jsxRuntime.jsx("div", { className: "image-container", children: img && jsxRuntime.jsx("img", { src: img, alt: "" }) })), isValidUrl(chat.msg) && renderLinkPreview(chat.msg), chat.msg && !isValidUrl(chat.msg) ? (jsxRuntime.jsx("div", { children: formatMentionsReact(chat.msg, mentionItems, chat.id) })) : (jsxRuntime.jsx(jsxRuntime.Fragment, {})), chat.path && chat.path.length > 1 && (jsxRuntime.jsx("div", { className: "group-image", children: chat.path.map((it, index) => {
72426
+ return (jsxRuntime.jsx("div", { className: "group-image-item image-container", children: jsxRuntime.jsx("img", { style: { maxWidth: "100%", maxHeight: 360 }, src: `${CDN_URL_VIEW}/${it.path.trim()}`, onClick: () => handlePreview(it), alt: "" }) }, index));
72427
+ }) })), jsxRuntime.jsx("div", { className: "", style: { fontSize: "12px", color: "#476285" }, children: moment(chat.time).format("HH:mm") })] }) }) }));
72428
+ }, [expandedMessages, handlePreview, mentionItems]);
72429
+ const getLinkPreviewData = (urlString) => {
72430
+ try {
72431
+ const hasProtocol = /^https?:\/\//i.test(urlString);
72432
+ const href = hasProtocol ? urlString : `https://${urlString}`;
72433
+ const url = new URL(href);
72434
+ const displayUrl = urlString.length > 80 ? `${urlString.slice(0, 77)}...` : urlString;
72435
+ return {
72436
+ href,
72437
+ displayUrl,
72438
+ host: url.host
72439
+ };
72440
+ }
72441
+ catch (e) {
72442
+ return {
72443
+ href: urlString,
72444
+ displayUrl: urlString,
72445
+ host: ''
72446
+ };
72447
+ }
72448
+ };
72449
+ const renderLinkPreview = (urlString) => {
72450
+ const { href, displayUrl, host } = getLinkPreviewData(urlString);
72451
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx("a", { href: href, target: "_blank", rel: "noreferrer", style: {
72452
+ textDecoration: 'none',
72453
+ color: 'inherit'
72454
+ }, children: jsxRuntime.jsxs("div", { style: {
72455
+ marginTop: 4,
72456
+ marginBottom: 4,
72457
+ padding: '8px 10px',
72458
+ borderRadius: 8,
72459
+ backgroundColor: '#eef5ff',
72460
+ border: '1px solid #d3e2ff',
72461
+ maxWidth: 420
72462
+ }, children: [jsxRuntime.jsx("div", { style: {
72463
+ fontSize: 14,
72464
+ fontWeight: 500,
72465
+ color: '#1d4f91',
72466
+ wordBreak: 'break-word'
72467
+ }, children: displayUrl }), host && (jsxRuntime.jsx("div", { style: {
72468
+ marginTop: 4,
72469
+ fontSize: 12,
72470
+ color: '#6f6b7d'
72471
+ }, children: host }))] }) }) }));
72472
+ };
72473
+ React.useCallback((chat) => {
72474
+ const msg = JSON.parse(chat?.msg);
72475
+ if (chat?.createdById === dataProfile?.id) {
72476
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("span", { style: { fontWeight: "bold", marginRight: "5px" }, children: msg?.name }), jsxRuntime.jsx("span", { children: "\u0111\u01B0\u1EE3c b\u1EA1n xo\u00E1 kh\u1ECFi nh\u00F3m" })] }) }));
72477
+ }
72478
+ if (chat?.createdById === msg?.id) {
72479
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("span", { style: { fontWeight: "bold", marginRight: "5px" }, children: msg?.name }), jsxRuntime.jsx("span", { children: "\u0111\u00E3 r\u1EDDi kh\u1ECFi nh\u00F3m" })] }) }));
72480
+ }
72481
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("span", { style: { fontWeight: "bold", marginRight: "5px" }, children: msg?.name }), jsxRuntime.jsxs("span", { children: ["\u0111\u01B0\u1EE3c ", jsxRuntime.jsx("span", { style: { fontWeight: "bold", marginRight: "5px" }, children: chat?.createdBy?.name }), " xo\u00E1 kh\u1ECFi nh\u00F3m"] })] }) }));
72482
+ }, [dataProfile]);
72483
+ React.useCallback((chat) => {
72484
+ const parseChatMsg = (msg) => {
72485
+ if (!msg) {
72486
+ return [];
72487
+ }
72488
+ try {
72489
+ const parsed = typeof msg === 'string' ? JSON.parse(msg) : msg;
72490
+ return Array.isArray(parsed) ? parsed : [parsed];
72491
+ }
72492
+ catch (err) {
72493
+ console.error('JSON parse error:', err);
72494
+ return [];
72495
+ }
72496
+ };
72497
+ const dataParse = parseChatMsg(chat.msg);
72498
+ // FIX: Kiểm tra array trước khi dùng slice
72499
+ if (!Array.isArray(dataParse) || dataParse.length === 0) {
72500
+ return (jsxRuntime.jsx("div", { children: jsxRuntime.jsx("span", { children: "\u0110\u00E3 c\u00F3 thay \u0111\u1ED5i trong nh\u00F3m" }) }));
72501
+ }
72502
+ const displayedItems = dataParse.slice(0, 2);
72503
+ const extraCount = Math.max(0, dataParse.length - displayedItems.length);
72504
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs("div", { children: [displayedItems.map((item, index) => (jsxRuntime.jsxs("strong", { children: [item.name, index < displayedItems.length - 1 && ", "] }, index))), dataParse.length > 3 && (jsxRuntime.jsxs("strong", { children: [jsxRuntime.jsx("span", { style: { fontWeight: "normal" }, children: " và " }), " ", extraCount, " ng\u01B0\u1EDDi kh\u00E1c"] })), " được ", chat?.createdBy?.id === dataProfile?.id ? (jsxRuntime.jsx("span", { children: "b\u1EA1n " })) : (jsxRuntime.jsx("strong", { style: { marginRight: "5px" }, children: chat?.createdByName })), "th\u00EAm v\u00E0o nh\u00F3m"] }) }));
72505
+ }, [dataProfile]);
72654
72506
  // const renderChatImage = useCallback((chat: any) => {
72655
72507
  // const files = chat.path
72656
72508
  // if (!files || !Array.isArray(files) || files.length === 0) {