1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-26 16:44:22 +02:00

Android input handing rewrite (#4988)

* wip

* wip

* wip - fully working without hard marks

* fix editor crashes when inserting/deleting at the edges of marks

* fix various restore dom related crashes

* fix delete with pending changes, zero widths on android, mutation tracking

* track placeholder delete in detached strings, zero-widths

* wip mark placeholders

* get rid of mutation detection in favor of beforeinput

* fix various selection race conditions

* fix various crashes when deleting at the beginning of nodes

* wip diff transforms, selection handling fixes

* cleanup restoreDOM and fix noop restore edge-case

* fix mark placeholders

* fix toSlatePoint edge-case

* properly flush user select with pending changes

* Prevent editor crash when deleting before a non-contenteditable element

* wip markdown shortcut example

* transform pending changes and selection by remote changes, simplify pending actions, handle all input types

* improve change transform, mark(-placeholder) handling

* manually handle gboard bug, fix restoredom nested editor

* fix parent mutation condition

* cleanup, mark placeholder fixes

* mark placeholder fixes

* fix mark placeholder condition

* hide placeholder if we have pending diffs

* cleanup

* yarn install

* add workaround for swiftkey placeholder issue

* cleanup

* add changeset

* feat(slate-react): fix edge-case crash, add androidPendingDiffs, rename scheduleFlushPendingChanges

* flush pending selection on same line without pending changes/action

* keep formatting of pending diffs when adding/removing selection marks

* unref selection ref on unmatching dom state

* improve markdown shortcut example flush trigger to show how a more generic solution would work

* fix markdown shortcut example trigger logic

* fix isInsertAfterMarkPlaceholder logic
This commit is contained in:
Eric Meier
2022-07-29 13:04:33 +02:00
committed by GitHub
parent f273647984
commit fbab6331a5
33 changed files with 2689 additions and 2359 deletions

View File

@@ -1,15 +1,16 @@
import React, { useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react'
import {
Editor,
Transforms,
Range,
Point,
createEditor,
Element as SlateElement,
Descendant,
Editor,
Element as SlateElement,
Node as SlateNode,
Point,
Range,
Transforms,
} from 'slate'
import { withHistory } from 'slate-history'
import { Editable, ReactEditor, Slate, withReact } from 'slate-react'
import { BulletedListElement } from './custom-types'
const SHORTCUTS = {
@@ -31,9 +32,44 @@ const MarkdownShortcutsExample = () => {
() => withShortcuts(withReact(withHistory(createEditor()))),
[]
)
const handleDOMBeforeInput = useCallback((e: InputEvent) => {
queueMicrotask(() => {
const pendingDiffs = ReactEditor.androidPendingDiffs(editor)
const scheduleFlush = pendingDiffs?.some(({ diff, path }) => {
if (!diff.text.endsWith(' ')) {
return false
}
const { text } = SlateNode.leaf(editor, path)
const beforeText = text.slice(0, diff.start) + diff.text.slice(0, -1)
if (!(beforeText in SHORTCUTS)) {
return
}
const blockEntry = Editor.above(editor, {
at: path,
match: n => Editor.isBlock(editor, n),
})
if (!blockEntry) {
return false
}
const [, blockPath] = blockEntry
return Editor.isStart(editor, Editor.start(editor, path), blockPath)
})
if (scheduleFlush) {
ReactEditor.androidScheduleFlush(editor)
}
})
}, [])
return (
<Slate editor={editor} value={initialValue}>
<Editable
onDOMBeforeInput={handleDOMBeforeInput}
renderElement={renderElement}
placeholder="Write some markdown..."
spellCheck
@@ -49,7 +85,7 @@ const withShortcuts = editor => {
editor.insertText = text => {
const { selection } = editor
if (text === ' ' && selection && Range.isCollapsed(selection)) {
if (text.endsWith(' ') && selection && Range.isCollapsed(selection)) {
const { anchor } = selection
const block = Editor.above(editor, {
match: n => Editor.isBlock(editor, n),
@@ -57,12 +93,16 @@ const withShortcuts = editor => {
const path = block ? block[1] : []
const start = Editor.start(editor, path)
const range = { anchor, focus: start }
const beforeText = Editor.string(editor, range)
const beforeText = Editor.string(editor, range) + text.slice(0, -1)
const type = SHORTCUTS[beforeText]
if (type) {
Transforms.select(editor, range)
Transforms.delete(editor)
if (!Range.isCollapsed(range)) {
Transforms.delete(editor)
}
const newProperties: Partial<SlateElement> = {
type,
}