'use client'; import React from 'react'; import { Image as ImageIcon, Video, Volume2 } from 'lucide-react'; import type { VideoAsset } from '@/components/video-page/types'; const URL_REGEX = /(https?:\/\/[^\s]+)/g; const ASSET_MENTION_REGEX = /@\[(.+?)\]\(asset:([a-z0-9]+)\)/gi; interface CommentRichTextProps { text: string; onAssetMentionClick?: (assetId: string) => void; assets?: VideoAsset[]; } // `keyPrefix` scopes the indices to this slice. The function runs once per gap between // mentions, so keying on the index alone emitted `txt-0` for several siblings and React // warned about duplicate keys. function renderUrls(text: string, keyPrefix: string): React.ReactNode[] { const parts = text.split(URL_REGEX); return parts.map((part, index) => { if (/^https?:\/\/[^\s]+$/.test(part)) { return ( event.stopPropagation()} > {part} ); } return {part}; }); } export function CommentRichText({ text, onAssetMentionClick, assets = [] }: CommentRichTextProps) { const nodes: React.ReactNode[] = []; let lastIndex = 0; for (const match of text.matchAll(ASSET_MENTION_REGEX)) { const mentionIndex = match.index ?? -1; if (mentionIndex < 0) continue; if (mentionIndex > lastIndex) { nodes.push(...renderUrls(text.slice(lastIndex, mentionIndex), `s${lastIndex}`)); } const fallbackLabel = match[1] || 'asset'; const assetId = match[2] || ''; const matchedAsset = assets.find((asset) => asset.id === assetId); const label = matchedAsset?.displayName || fallbackLabel; const assetKind = matchedAsset?.kind; nodes.push( ); lastIndex = mentionIndex + match[0].length; } if (lastIndex < text.length) { nodes.push(...renderUrls(text.slice(lastIndex), `s${lastIndex}`)); } return <>{nodes}; }