diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx index 0d63ff37ef..5ccf2e44b5 100644 --- a/src/view/com/composer/text-input/TextInput.tsx +++ b/src/view/com/composer/text-input/TextInput.tsx @@ -13,11 +13,12 @@ import { type TextInputSelectionChangeEventData, View, } from 'react-native' -import {AppBskyRichtextFacet, RichText} from '@atproto/api' +import {AppBskyRichtextFacet, RichText, UnicodeString} from '@atproto/api' import PasteInput, { type PastedFile, type PasteInputRef, // @ts-expect-error no types when installing from github } from '@mattermost/react-native-paste-input' +import Graphemer from 'graphemer' import {MAX_GRAPHEME_LENGTH, POST_IMG_MAX} from '#/lib/constants' import {downloadAndResize} from '#/lib/media/manip' @@ -211,13 +212,15 @@ export const TextInput = forwardRef(function TextInputImpl( return style }, [t, fonts]) + const splitter = useMemo(() => new Graphemer(), []) const textDecorated = useMemo(() => { let excess - let truncatedRichtext = richtext if (richtext.graphemeLength > MAX_GRAPHEME_LENGTH) { - truncatedRichtext = richtext.clone() - const excessText = - truncatedRichtext.unicodeText.slice(MAX_GRAPHEME_LENGTH) + const split = splitter.splitGraphemes(richtext.text) + const validText = split.slice(0, MAX_GRAPHEME_LENGTH).join('') + const validUnicode = new UnicodeString(validText) + const excessText = split.slice(MAX_GRAPHEME_LENGTH).join('') + richtext.delete(validUnicode.utf8.byteLength, richtext.length) excess = ( ) - truncatedRichtext.delete( - MAX_GRAPHEME_LENGTH, - truncatedRichtext.graphemeLength, - ) } let i = 0 - const segments = Array.from(truncatedRichtext.segments()).map(segment => { + const segments = Array.from(richtext.segments()).map(segment => { return (