diff --git a/packages/app/ui/components/BareChatInput/index.tsx b/packages/app/ui/components/BareChatInput/index.tsx index 637005f8ca..e93e932592 100644 --- a/packages/app/ui/components/BareChatInput/index.tsx +++ b/packages/app/ui/components/BareChatInput/index.tsx @@ -3,7 +3,6 @@ import { JSONContent, Story, pathToCite } from '@tloncorp/api/urbit'; import { Attachment, JSONToInlines, - LinkAttachment, REF_REGEX, createDevLogger, diaryMixedToJSON, @@ -66,6 +65,16 @@ const bareChatInputLogger = createDevLogger('bareChatInput', false); const DEFAULT_KEYBOARD_HEIGHT = 300; +function normalizePreviewUrl(url: string) { + try { + const parsedUrl = new URL(url); + parsedUrl.hash = ''; + return parsedUrl.toString(); + } catch { + return url; + } +} + function useKeyboardHeight(maxInputHeightBasic: number) { const [maxInputHeight, setMaxInputHeight] = useState(maxInputHeightBasic); @@ -558,34 +567,23 @@ function BareChatInput( const matches = textOutsideCodeBlocks.match(urlRegex) || []; // Normalize URLs (remove hash) and deduplicate - const currentUrls = [ - ...new Set( - matches.map((url) => { - try { - const parsedUrl = new URL(url); - parsedUrl.hash = ''; - return parsedUrl.toString(); - } catch { - return url; - } - }) - ), - ]; + const currentUrls = [...new Set(matches.map(normalizePreviewUrl))]; const prevUrls = prevUrlsRef.current; - const currentAttachments = attachmentsRef.current; + const linksByUrl = new Map( + attachmentsRef.current + .filter((a) => a.type === 'link') + .map((a) => [normalizePreviewUrl(a.url), a] as const) + ); - // Find URLs that were removed from text const removedUrls = prevUrls.filter((url) => !currentUrls.includes(url)); - - // Find URLs that were added to text - const addedUrls = currentUrls.filter((url) => !prevUrls.includes(url)); + const addedUrls = currentUrls.filter( + (url) => !prevUrls.includes(url) && !linksByUrl.has(url) + ); // Remove attachments for URLs no longer in text removedUrls.forEach((url) => { - const attachment = currentAttachments.find( - (a): a is LinkAttachment => a.type === 'link' && a.url === url - ); + const attachment = linksByUrl.get(url); if (attachment) { bareChatInputLogger.log('removing stale link attachment', { url }); removeAttachment(attachment);