about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2023-09-27 11:15:50 -0500
committerGitHub <noreply@github.com>2023-09-27 09:15:50 -0700
commitb030d94a64e46ae9ac8bf0f4c2ad502b99d4adc1 (patch)
tree9eeaac27a61d152fd21ea59a514946d075b07dc6 /src
parent6d4ad59416e81f437cbfc9f9a75eff2c8e1d8442 (diff)
downloadvoidsky-b030d94a64e46ae9ac8bf0f4c2ad502b99d4adc1.tar.zst
fix link highlighting with mention present (#1544)
Diffstat (limited to 'src')
-rw-r--r--src/view/com/composer/text-input/TextInput.web.tsx96
-rw-r--r--src/view/com/composer/text-input/web/LinkDecorator.ts13
2 files changed, 29 insertions, 80 deletions
diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx
index 7eea904ab..31e372567 100644
--- a/src/view/com/composer/text-input/TextInput.web.tsx
+++ b/src/view/com/composer/text-input/TextInput.web.tsx
@@ -17,6 +17,7 @@ import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
 import {isUriImage, blobToDataUri} from 'lib/media/util'
 import {Emoji} from './web/EmojiPicker.web'
 import {LinkDecorator} from './web/LinkDecorator'
+import {generateJSON} from '@tiptap/html'
 
 export interface TextInputRef {
   focus: () => void
@@ -52,6 +53,26 @@ export const TextInput = React.forwardRef(function TextInputImpl(
   ref,
 ) {
   const modeClass = useColorSchemeStyle('ProseMirror-light', 'ProseMirror-dark')
+  const extensions = React.useMemo(
+    () => [
+      Document,
+      LinkDecorator,
+      Mention.configure({
+        HTMLAttributes: {
+          class: 'mention',
+        },
+        suggestion: createSuggestion({autocompleteView}),
+      }),
+      Paragraph,
+      Placeholder.configure({
+        placeholder,
+      }),
+      Text,
+      History,
+      Hardbreak,
+    ],
+    [autocompleteView, placeholder],
+  )
 
   React.useEffect(() => {
     textInputWebEmitter.addListener('publish', onPressPublish)
@@ -68,23 +89,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
 
   const editor = useEditor(
     {
-      extensions: [
-        Document,
-        LinkDecorator,
-        Mention.configure({
-          HTMLAttributes: {
-            class: 'mention',
-          },
-          suggestion: createSuggestion({autocompleteView}),
-        }),
-        Paragraph,
-        Placeholder.configure({
-          placeholder,
-        }),
-        Text,
-        History,
-        Hardbreak,
-      ],
+      extensions,
       editorProps: {
         attributes: {
           class: modeClass,
@@ -107,7 +112,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
           }
         },
       },
-      content: textToEditorJson(richtext.text.toString()),
+      content: generateJSON(richtext.text.toString(), extensions),
       autofocus: 'end',
       editable: true,
       injectCSS: true,
@@ -182,61 +187,6 @@ function editorJsonToText(json: JSONContent): string {
   return text
 }
 
-function textToEditorJson(text: string): JSONContent {
-  if (text === '' || text.length === 0) {
-    return {
-      text: '',
-    }
-  }
-
-  const lines = text.split('\n')
-  const docContent: JSONContent[] = []
-
-  for (const line of lines) {
-    if (line.trim() === '') {
-      continue // skip empty lines
-    }
-
-    const paragraphContent: JSONContent[] = []
-    let position = 0
-
-    while (position < line.length) {
-      if (line[position] === '@') {
-        // Handle mentions
-        let endPosition = position + 1
-        while (endPosition < line.length && /\S/.test(line[endPosition])) {
-          endPosition++
-        }
-        const mentionId = line.substring(position + 1, endPosition)
-        paragraphContent.push({
-          type: 'mention',
-          attrs: {id: mentionId},
-        })
-        position = endPosition
-      } else {
-        // Handle regular text
-        let endPosition = line.indexOf('@', position)
-        if (endPosition === -1) endPosition = line.length
-        paragraphContent.push({
-          type: 'text',
-          text: line.substring(position, endPosition),
-        })
-        position = endPosition
-      }
-    }
-
-    docContent.push({
-      type: 'paragraph',
-      content: paragraphContent,
-    })
-  }
-
-  return {
-    type: 'doc',
-    content: docContent,
-  }
-}
-
 const styles = StyleSheet.create({
   container: {
     flex: 1,
diff --git a/src/view/com/composer/text-input/web/LinkDecorator.ts b/src/view/com/composer/text-input/web/LinkDecorator.ts
index 531e8d5a0..19945de08 100644
--- a/src/view/com/composer/text-input/web/LinkDecorator.ts
+++ b/src/view/com/composer/text-input/web/LinkDecorator.ts
@@ -16,7 +16,6 @@
 
 import {Mark} from '@tiptap/core'
 import {Plugin, PluginKey} from '@tiptap/pm/state'
-import {findChildren} from '@tiptap/core'
 import {Node as ProsemirrorNode} from '@tiptap/pm/model'
 import {Decoration, DecorationSet} from '@tiptap/pm/view'
 import {isValidDomain} from 'lib/strings/url-helpers'
@@ -36,20 +35,20 @@ export const LinkDecorator = Mark.create({
 function getDecorations(doc: ProsemirrorNode) {
   const decorations: Decoration[] = []
 
-  findChildren(doc, node => node.type.name === 'paragraph').forEach(
-    paragraphNode => {
-      const textContent = paragraphNode.node.textContent
+  doc.descendants((node, pos) => {
+    if (node.isText && node.text) {
+      const textContent = node.textContent
 
       // links
       iterateUris(textContent, (from, to) => {
         decorations.push(
-          Decoration.inline(paragraphNode.pos + from, paragraphNode.pos + to, {
+          Decoration.inline(pos + from, pos + to, {
             class: 'autolink',
           }),
         )
       })
-    },
-  )
+    }
+  })
 
   return DecorationSet.create(doc, decorations)
 }