about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/view/com/composer/text-input/TextInput.web.tsx21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx
index d5db7bcb6..f76c07036 100644
--- a/src/view/com/composer/text-input/TextInput.web.tsx
+++ b/src/view/com/composer/text-input/TextInput.web.tsx
@@ -13,6 +13,7 @@ import {Text as TiptapText} from '@tiptap/extension-text'
 import {generateJSON} from '@tiptap/html'
 import {Fragment, Node, Slice} from '@tiptap/pm/model'
 import {EditorContent, type JSONContent, useEditor} from '@tiptap/react'
+import Graphemer from 'graphemer'
 
 import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle'
 import {usePalette} from '#/lib/hooks/usePalette'
@@ -214,11 +215,29 @@ export const TextInput = React.forwardRef(function TextInputImpl(
             }
           }
         },
-        handleKeyDown: (_, event) => {
+        handleKeyDown: (view, event) => {
           if ((event.metaKey || event.ctrlKey) && event.code === 'Enter') {
             textInputWebEmitter.emit('publish')
             return true
           }
+          if (event.code === 'Backspace') {
+            const isNotSelection = view.state.selection.empty
+            if (isNotSelection) {
+              const cursorPosition = view.state.selection.$anchor.pos
+              const textBefore = view.state.doc.textBetween(0, cursorPosition)
+              const graphemes = new Graphemer().splitGraphemes(textBefore)
+
+              if (graphemes.length > 0) {
+                const lastGrapheme = graphemes[graphemes.length - 1]
+                const deleteFrom = cursorPosition - lastGrapheme.length
+                editor?.commands.deleteRange({
+                  from: deleteFrom,
+                  to: cursorPosition,
+                })
+                return true
+              }
+            }
+          }
         },
       },
       content: generateJSON(richtext.text.toString(), extensions, {