1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-04-21 13:51:59 +02:00

Fix pasting content with newlines on Android (#5359)

* Improve InputEvent data type

* Fix insertion of content with newlines on Android

* Slice the trailing newline off of pasted text

* Add changeset
This commit is contained in:
Jason Cheatham 2023-03-16 09:02:15 -04:00 committed by GitHub
parent 4399935690
commit 9825d29b87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 8 deletions

View File

@ -0,0 +1,5 @@
---
'slate-react': patch
---
Fix an issue on Android where content containing a newline wouldn't be pasted properly

View File

@ -36,6 +36,10 @@ const FLUSH_DELAY = 200
// Replace with `const debug = console.log` to debug
const debug = (..._: unknown[]) => {}
// Type guard to check if a value is a DataTransfer
const isDataTransfer = (value: any): value is DataTransfer =>
value?.constructor.name === 'DataTransfer'
export type CreateAndroidInputManagerOptions = {
editor: ReactEditor
@ -343,7 +347,8 @@ export function createAndroidInputManager({
const { inputType: type } = event
let targetRange: Range | null = null
const data = (event as any).dataTransfer || event.data || undefined
const data: DataTransfer | string | undefined =
(event as any).dataTransfer || event.data || undefined
if (
insertPositionHint !== false &&
@ -577,18 +582,12 @@ export function createAndroidInputManager({
case 'insertFromYank':
case 'insertReplacementText':
case 'insertText': {
if (data?.constructor.name === 'DataTransfer') {
if (isDataTransfer(data)) {
return scheduleAction(() => ReactEditor.insertData(editor, data), {
at: targetRange,
})
}
if (typeof data === 'string' && data.includes('\n')) {
return scheduleAction(() => Editor.insertSoftBreak(editor), {
at: Range.end(targetRange),
})
}
let text = data ?? ''
// COMPAT: If we are writing inside a placeholder, the ime inserts the text inside
@ -597,6 +596,34 @@ export function createAndroidInputManager({
text = text.replace('\uFEFF', '')
}
// Pastes from the Android clipboard will generate `insertText` events.
// If the copied text contains any newlines, Android will append an
// extra newline to the end of the copied text.
if (type === 'insertText' && /.*\n.*\n$/.test(text)) {
text = text.slice(0, -1)
}
// If the text includes a newline, split it at newlines and paste each component
// string, with soft breaks in between each.
if (text.includes('\n')) {
return scheduleAction(
() => {
const parts = text.split('\n')
parts.forEach((line, i) => {
if (line) {
Editor.insertText(editor, line)
}
if (i !== parts.length - 1) {
Editor.insertSoftBreak(editor)
}
})
},
{
at: targetRange,
}
)
}
if (Path.equals(targetRange.anchor.path, targetRange.focus.path)) {
const [start, end] = Range.edges(targetRange)