From 8ec3d8c76e4ec94628ecb8b85eab1cbf83dcefe1 Mon Sep 17 00:00:00 2001
From: dan <dan.abramov@gmail.com>
Date: Wed, 24 Apr 2024 17:30:44 +0100
Subject: Rewrite the link detection (#3687)

* Rewrite the link detection

* Handle parens and colons
---
 src/view/com/composer/text-input/TextInput.web.tsx | 38 +++++++++-------------
 1 file changed, 16 insertions(+), 22 deletions(-)

(limited to 'src/view/com/composer/text-input/TextInput.web.tsx')

diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx
index 1b5d7a821..7f8dc2ed5 100644
--- a/src/view/com/composer/text-input/TextInput.web.tsx
+++ b/src/view/com/composer/text-input/TextInput.web.tsx
@@ -19,8 +19,8 @@ import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
 import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
 import {blobToDataUri, isUriImage} from 'lib/media/util'
 import {
-  addLinkCardIfNecessary,
-  findIndexInText,
+  LinkFacetMatch,
+  suggestLinkCardUri,
 } from 'view/com/composer/text-input/text-input-util'
 import {Portal} from '#/components/Portal'
 import {Text} from '../../util/text/Text'
@@ -61,8 +61,6 @@ export const TextInput = React.forwardRef(function TextInputImpl(
   ref,
 ) {
   const autocomplete = useActorAutocompleteFn()
-  const prevAddedLinks = useRef(new Set<string>())
-
   const pal = usePalette('default')
   const modeClass = useColorSchemeStyle('ProseMirror-light', 'ProseMirror-dark')
 
@@ -143,6 +141,8 @@ export const TextInput = React.forwardRef(function TextInputImpl(
     }
   }, [setIsDropping])
 
+  const pastSuggestedUris = useRef(new Set<string>())
+  const prevDetectedUris = useRef(new Map<string, LinkFacetMatch>())
   const editor = useEditor(
     {
       extensions,
@@ -185,38 +185,32 @@ export const TextInput = React.forwardRef(function TextInputImpl(
       onUpdate({editor: editorProp}) {
         const json = editorProp.getJSON()
         const newText = editorJsonToText(json)
-        const mayBePaste = window.event?.type === 'paste'
+        const isPaste = window.event?.type === 'paste'
 
         const newRt = new RichText({text: newText})
         newRt.detectFacetsWithoutResolution()
         setRichText(newRt)
 
+        const nextDetectedUris = new Map<string, LinkFacetMatch>()
         if (newRt.facets) {
           for (const facet of newRt.facets) {
             for (const feature of facet.features) {
               if (AppBskyRichtextFacet.isLink(feature)) {
-                // The TipTap editor shows the position as being one character ahead, as if the start index is 1.
-                // Subtracting 1 from the pos gives us the same behavior as the native impl.
-                let cursorLocation = editor?.state.selection.$anchor.pos ?? 1
-                cursorLocation -= 1
-
-                addLinkCardIfNecessary({
-                  uri: feature.uri,
-                  newText,
-                  cursorLocation,
-                  mayBePaste,
-                  onNewLink,
-                  prevAddedLinks: prevAddedLinks.current,
-                })
+                nextDetectedUris.set(feature.uri, {facet, rt: newRt})
               }
             }
           }
         }
 
-        for (const uri of prevAddedLinks.current.keys()) {
-          if (findIndexInText(uri, newText) === -1) {
-            prevAddedLinks.current.delete(uri)
-          }
+        const suggestedUri = suggestLinkCardUri(
+          isPaste,
+          nextDetectedUris,
+          prevDetectedUris.current,
+          pastSuggestedUris.current,
+        )
+        prevDetectedUris.current = nextDetectedUris
+        if (suggestedUri) {
+          onNewLink(suggestedUri)
         }
       },
     },
-- 
cgit 1.4.1

