From 21405442f1866ec9df65fe7c29a9ab494f86057f Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 24 Apr 2024 06:15:44 +0100 Subject: [PATCH] More precise --- .../com/composer/text-input/TextInput.tsx | 3 +- .../com/composer/text-input/TextInput.web.tsx | 36 ++++++++++++------- .../composer/text-input/text-input-util.ts | 22 ++++-------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx index a95281959e..88c2405924 100644 --- a/src/view/com/composer/text-input/TextInput.tsx +++ b/src/view/com/composer/text-input/TextInput.tsx @@ -134,8 +134,7 @@ export const TextInput = forwardRef(function TextInputImpl( addLinkCardIfNecessary({ uri: feature.uri, - newText, - cursorLocation, + textBeforeCursor: newText.slice(0, cursorLocation), mayBePaste, onNewLink, prevAddedLinks: prevAddedLinks.current, diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx index f704f4c8cb..630f6b8c90 100644 --- a/src/view/com/composer/text-input/TextInput.web.tsx +++ b/src/view/com/composer/text-input/TextInput.web.tsx @@ -185,7 +185,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( }, onUpdate({editor: editorProp}) { const json = editorProp.getJSON() - const newText = editorJsonToText(json).trimEnd() // Otherwise we have \n\n at the end + const newText = editorJsonToText(json) const mayBePaste = window.event?.type === 'paste' const newRt = new RichText({text: newText}) @@ -196,15 +196,13 @@ export const TextInput = React.forwardRef(function TextInputImpl( 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, + textBeforeCursor: editorJsonToText( + editorProp.state.doc + .cut(0, editorProp.state.selection.$anchor.pos) + .toJSON(), + ), mayBePaste, onNewLink, prevAddedLinks: prevAddedLinks.current, @@ -279,15 +277,29 @@ export const TextInput = React.forwardRef(function TextInputImpl( ) }) -function editorJsonToText(json: JSONContent): string { +function editorJsonToText( + json: JSONContent, + isLastDocumentChild: boolean = false, +): string { let text = '' - if (json.type === 'doc' || json.type === 'paragraph') { + if (json.type === 'doc') { if (json.content?.length) { - for (const node of json.content) { + for (let i = 0; i < json.content.length; i++) { + const node = json.content[i] + const isLastNode = i === json.content.length - 1 + text += editorJsonToText(node, isLastNode) + } + } + } else if (json.type === 'paragraph') { + if (json.content?.length) { + for (let i = 0; i < json.content.length; i++) { + const node = json.content[i] text += editorJsonToText(node) } } - text += '\n' + if (!isLastDocumentChild) { + text += '\n' + } } else if (json.type === 'hardBreak') { text += '\n' } else if (json.type === 'text') { diff --git a/src/view/com/composer/text-input/text-input-util.ts b/src/view/com/composer/text-input/text-input-util.ts index a59db37767..56da921349 100644 --- a/src/view/com/composer/text-input/text-input-util.ts +++ b/src/view/com/composer/text-input/text-input-util.ts @@ -1,32 +1,24 @@ export function addLinkCardIfNecessary({ uri, - newText, - cursorLocation, + textBeforeCursor, mayBePaste, onNewLink, prevAddedLinks, endIndex, }: { uri: string - newText: string - cursorLocation: number + textBeforeCursor: string mayBePaste: boolean onNewLink: (uri: string) => void prevAddedLinks: Set endIndex: number }) { - newText = newText + ' ' + const isLeavingLink = + endIndex === textBeforeCursor.length - 2 || + (endIndex === textBeforeCursor.length - 1 && + /[^.,;!?]\s$/m.test(textBeforeCursor)) - let toAdd = 2 - - const backOne = newText.charAt(cursorLocation - 1) - const backTwo = newText.charAt(cursorLocation - 2) - - if (backOne === ' ' && /[^.!?]/.test(backTwo)) { - toAdd = 1 - } - - if (!mayBePaste && endIndex + toAdd !== cursorLocation) { + if (!mayBePaste && !isLeavingLink) { return }