mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-12 10:14:02 +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:
5
.changeset/rude-bikes-rule.md
Normal file
5
.changeset/rude-bikes-rule.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'slate-react': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix an issue on Android where content containing a newline wouldn't be pasted properly
|
@@ -36,6 +36,10 @@ const FLUSH_DELAY = 200
|
|||||||
// Replace with `const debug = console.log` to debug
|
// Replace with `const debug = console.log` to debug
|
||||||
const debug = (..._: unknown[]) => {}
|
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 = {
|
export type CreateAndroidInputManagerOptions = {
|
||||||
editor: ReactEditor
|
editor: ReactEditor
|
||||||
|
|
||||||
@@ -343,7 +347,8 @@ export function createAndroidInputManager({
|
|||||||
|
|
||||||
const { inputType: type } = event
|
const { inputType: type } = event
|
||||||
let targetRange: Range | null = null
|
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 (
|
if (
|
||||||
insertPositionHint !== false &&
|
insertPositionHint !== false &&
|
||||||
@@ -577,18 +582,12 @@ export function createAndroidInputManager({
|
|||||||
case 'insertFromYank':
|
case 'insertFromYank':
|
||||||
case 'insertReplacementText':
|
case 'insertReplacementText':
|
||||||
case 'insertText': {
|
case 'insertText': {
|
||||||
if (data?.constructor.name === 'DataTransfer') {
|
if (isDataTransfer(data)) {
|
||||||
return scheduleAction(() => ReactEditor.insertData(editor, data), {
|
return scheduleAction(() => ReactEditor.insertData(editor, data), {
|
||||||
at: targetRange,
|
at: targetRange,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data === 'string' && data.includes('\n')) {
|
|
||||||
return scheduleAction(() => Editor.insertSoftBreak(editor), {
|
|
||||||
at: Range.end(targetRange),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let text = data ?? ''
|
let text = data ?? ''
|
||||||
|
|
||||||
// COMPAT: If we are writing inside a placeholder, the ime inserts the text inside
|
// 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', '')
|
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)) {
|
if (Path.equals(targetRange.anchor.path, targetRange.focus.path)) {
|
||||||
const [start, end] = Range.edges(targetRange)
|
const [start, end] = Range.edges(targetRange)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user