AppFlowy-IO / AppFlowy-IO/appflowy-editor

[Bug][Web] Unwanted space on click and overall space bugs

オープン
#1,029 コメント 5 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Dart
スター
684
フォーク
329
PR マージ指標
30日以内にマージされた PR はありません

説明

### Bug Description

Im running appflowy_editor in web platform and i encountered issue where multiple lines of text do weird stuff when i click within to edit. It seems like its happening only on web version.
When i load it up:
![Image](https://github.com/user-attachments/assets/9c5bbe69-f79d-46db-959c-07f8f348f8e3)

When i click "unchanged.**|**":
![Image](https://github.com/user-attachments/assets/0ecb9cc0-1e07-4bd2-acec-636d490315b4)

cursor ends up on " **|** It was popularised..." and i can just hold backspace, it removes the spaces and then creates the spaces again and this can go forever.

EDIT: also when i click within (ignoring the creation of spaces) and i do cmd+A -> everything is cleared out instead of selecting the text.

### How to Reproduce
EDIT: can be reproduced in example of appflowy, just replace example.json with the value of test variable below.

![Image](https://github.com/user-attachments/assets/c769c466-b82e-447e-9b60-f5ccebea534b)

Tested string, used like this:
```
var test = {
"document": {
"type": "page",
"children": [
{
"type": "paragraph",
"data": {
"delta": [
{
"insert":
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.\r"
}
]
}
},
]
}
};

EditorState(document: Document.fromJson(test))
```

Log output when i click within the text:

```
[DEBUG][editor]: 2025-01-28 17:32:00.602: keyboard service - attach text input service: TextEditingValue(text: ┤Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.├, selection: TextSelection.collapsed(offset: 366, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
[DEBUG][input]: 2025-01-28 17:32:00.626: attach text editing value: TextEditingValue(text: ┤Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting,
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.├, selection: TextSelection.collapsed(offset: 366, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
[DEBUG][editor]: 2025-01-28 17:32:00.638: keyboard service - request focus
[DEBUG][editor]: 2025-01-28 17:32:00.640: keyboard service - focus changed: true}
[DEBUG][input]: 2025-01-28 17:32:00.668: onReplace: TextEditingDeltaReplacement#2e28e(oldText: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum., textReplaced:, replacementText:
, replacedRange: TextRange(start: 574, end: 575), selection: TextSelection.collapsed(offset: 366, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
}]}}]}][editor]: 2025-01-28 17:32:00.677: apply op (local): {op: insert, path: [1], nodes: [{type: paragraph, data: {delta: [{insert: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
}]}, children: []) at path [1]}32:00.678: insert Node Node(id: 848Fc4, type: paragraph, attributes: {delta: [{insert: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
[DEBUG][editor]: 2025-01-28 17:32:00.680: apply op (local): {op: update, path: [0], attributes: {delta: [{insert: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged.}]}, oldAttributes: {delta: [{insert: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting,
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.}]}}
[DEBUG][editor]: 2025-01-28 17:32:00.683: keyboard service - attach text input service: TextEditingValue(text: ┤ It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.├, selection: TextSelection.collapsed(offset: 0, affinity: TextAffinity.downstream, isDirectional: false),
composing: TextRange(start: -1, end: -1))
[DEBUG][input]: 2025-01-28 17:32:00.686: attach text editing value: TextEditingValue(text: ┤ It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.├, selection: TextSelection.collapsed(offset: 0, affinity: TextAffinity.downstream, isDirectional: false), composing:
TextRange(start: -1, end: -1))
[DEBUG][editor]: 2025-01-28 17:32:00.687: keyboard service - selection changed: start = path = [1], offset = 0, end = path = [1], offset = 0
[DEBUG][input]: 2025-01-28 17:32:00.689: keyboard service - handled by character shortcut event: CharacterShortcutEvent(key: insert a new line, character:
, handler: Closure: (EditorState) => Future from: editorState => {
let t$3687;
let t$goto = 0, t$completer = async._makeAsyncAwaitCompleter(dart_rti._Universe.eval(dart_rti._theUniverse(), "core|bool", true)), t$returnValue, asyncScope = Object.create(null);
var t$36asyncBody = async._wrapJsFunctionForAsync((t$errorCode, t$result) => {
if (t$errorCode === 1) return async._asyncRethrow(t$result, t$completer);
while (true)
switch (t$goto) {
case 0:
// Function start
if (platform_extension['PlatformExtension|isNotMobile'] && hardware_keyboard.HardwareKeyboard.instance.isShiftPressed) {
t$returnValue = false;
// goto return
t$goto = 2;
break;
}
asyncScope.selection = (t$3687 = editorState.selection, t$3687 == null ? null : t$3687.normalized);
if (asyncScope.selection == null) {
t$returnValue = false;
// goto return
t$goto = 2;
break;
}
t$goto = 3;
return async._asyncAwait(selection_commands['SelectionTransform|deleteSelection'](editorState, asyncScope.selection), t$36asyncBody, t$completer);
case 3:
// returning from await.
t$goto = 4;
return async._asyncAwait(text_commands['TextTransforms|insertNewLine'](editorState, {position: asyncScope.selection.start}), t$36asyncBody, t$completer);
case 4:
// returning from await.
t$returnValue = true;
// goto return
t$goto = 2;
break;
case 2:
// return
return async._asyncReturn(t$returnValue, t$completer);
}
});
return async._asyncStartSync(t$36asyncBody, t$completer);
})
[DEBUG][editor]: 2025-01-28 17:32:00.701: node is rebuilding...: type: page
[DEBUG][editor]: 2025-01-28 17:32:00.709: node is rebuilding...: type: paragraph
[DEBUG][editor]: 2025-01-28 17:32:00.725: node is rebuilding...: type: paragraph
[DEBUG][input]: 2025-01-28 17:32:00.770: onReplace: TextEditingDeltaReplacement#573c9(oldText: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum., textReplaced:, replacementText:
, replacedRange: TextRange(start: 208, end: 209), selection: TextSelection.collapsed(offset: 0, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
}]}}]}][editor]: 2025-01-28 17:32:00.772: apply op (local): {op: insert, path: [2], nodes: [{type: paragraph, data: {delta: [{insert: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
}]}, children: []) at path [2]}32:00.772: insert Node Node(id: If_YYY, type: paragraph, attributes: {delta: [{insert: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
}]}}UG][editor]: 2025-01-28 17:32:00.773: apply op (local): {op: update, path: [1], attributes: {delta: []}, oldAttributes: {delta: [{insert: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
[DEBUG][editor]: 2025-01-28 17:32:00.774: keyboard service - attach text input service: TextEditingValue(text: ┤ It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.├, selection: TextSelection.collapsed(offset: 0, affinity: TextAffinity.downstream, isDirectional: false),
composing: TextRange(start: -1, end: -1))
[DEBUG][input]: 2025-01-28 17:32:00.774: attach text editing value: TextEditingValue(text: ┤ It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.├, selection: TextSelection.collapsed(offset: 0, affinity: TextAffinity.downstream, isDirectional: false), composing:
TextRange(start: -1, end: -1))
[DEBUG][editor]: 2025-01-28 17:32:00.775: keyboard service - selection changed: start = path = [2], offset = 0, end = path = [2], offset = 0
[DEBUG][input]: 2025-01-28 17:32:00.775: keyboard service - handled by character shortcut event: CharacterShortcutEvent(key: insert a new line, character:
, handler: Closure: (EditorState) => Future from: editorState => {
let t$3687;
let t$goto = 0, t$completer = async._makeAsyncAwaitCompleter(dart_rti._Universe.eval(dart_rti._theUniverse(), "core|bool", true)), t$returnValue, asyncScope = Object.create(null);
var t$36asyncBody = async._wrapJsFunctionForAsync((t$errorCode, t$result) => {
if (t$errorCode === 1) return async._asyncRethrow(t$result, t$completer);
while (true)
switch (t$goto) {
case 0:
// Function start
if (platform_extension['PlatformExtension|isNotMobile'] && hardware_keyboard.HardwareKeyboard.instance.isShiftPressed) {
t$returnValue = false;
// goto return
t$goto = 2;
break;
}
asyncScope.selection = (t$3687 = editorState.selection, t$3687 == null ? null : t$3687.normalized);
if (asyncScope.selection == null) {
t$returnValue = false;
// goto return
t$goto = 2;
break;
}
t$goto = 3;
return async._asyncAwait(selection_commands['SelectionTransform|deleteSelection'](editorState, asyncScope.selection), t$36asyncBody, t$completer);
case 3:
// returning from await.
t$goto = 4;
return async._asyncAwait(text_commands['TextTransforms|insertNewLine'](editorState, {position: asyncScope.selection.start}), t$36asyncBody, t$completer);
case 4:
// returning from await.
t$returnValue = true;
// goto return
t$goto = 2;
break;
case 2:
// return
return async._asyncReturn(t$returnValue, t$completer);
}
});
return async._asyncStartSync(t$36asyncBody, t$completer);
})
[DEBUG][input]: 2025-01-28 17:32:00.780: onReplace: TextEditingDeltaReplacement#bb5e1(oldText: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum., textReplaced:, replacementText:
, replacedRange: TextRange(start: 208, end: 209), selection: TextSelection.collapsed(offset: 0, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
}]}}]}][editor]: 2025-01-28 17:32:00.783: apply op (local): {op: insert, path: [3], nodes: [{type: paragraph, data: {delta: [{insert: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
}]}, children: []) at path [3]}32:00.783: insert Node Node(id: UEKp-_, type: paragraph, attributes: {delta: [{insert: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
}]}}UG][editor]: 2025-01-28 17:32:00.783: apply op (local): {op: update, path: [2], attributes: {delta: []}, oldAttributes: {delta: [{insert: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
[DEBUG][editor]: 2025-01-28 17:32:00.784: keyboard service - attach text input service: TextEditingValue(text: ┤ It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.├, selection: TextSelection.collapsed(offset: 0, affinity: TextAffinity.downstream, isDirectional: false),
composing: TextRange(start: -1, end: -1))
[DEBUG][input]: 2025-01-28 17:32:00.784: attach text editing value: TextEditingValue(text: ┤ It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.├, selection: TextSelection.collapsed(offset: 0, affinity: TextAffinity.downstream, isDirectional: false), composing:
TextRange(start: -1, end: -1))
[DEBUG][editor]: 2025-01-28 17:32:00.784: keyboard service - selection changed: start = path = [3], offset = 0, end = path = [3], offset = 0
[DEBUG][input]: 2025-01-28 17:32:00.784: keyboard service - handled by character shortcut event: CharacterShortcutEvent(key: insert a new line, character:
, handler: Closure: (EditorState) => Future from: editorState => {
let t$3687;
let t$goto = 0, t$completer = async._makeAsyncAwaitCompleter(dart_rti._Universe.eval(dart_rti._theUniverse(), "core|bool", true)), t$returnValue, asyncScope = Object.create(null);
var t$36asyncBody = async._wrapJsFunctionForAsync((t$errorCode, t$result) => {
if (t$errorCode === 1) return async._asyncRethrow(t$result, t$completer);
while (true)
switch (t$goto) {
case 0:
// Function start
if (platform_extension['PlatformExtension|isNotMobile'] && hardware_keyboard.HardwareKeyboard.instance.isShiftPressed) {
t$returnValue = false;
// goto return
t$goto = 2;
break;
}
asyncScope.selection = (t$3687 = editorState.selection, t$3687 == null ? null : t$3687.normalized);
if (asyncScope.selection == null) {
t$returnValue = false;
// goto return
t$goto = 2;
break;
}
t$goto = 3;
return async._asyncAwait(selection_commands['SelectionTransform|deleteSelection'](editorState, asyncScope.selection), t$36asyncBody, t$completer);
case 3:
// returning from await.
t$goto = 4;
return async._asyncAwait(text_commands['TextTransforms|insertNewLine'](editorState, {position: asyncScope.selection.start}), t$36asyncBody, t$completer);
case 4:
// returning from await.
t$returnValue = true;
// goto return
t$goto = 2;
break;
case 2:
// return
return async._asyncReturn(t$returnValue, t$completer);
}
});
return async._asyncStartSync(t$36asyncBody, t$completer);
})
[DEBUG][editor]: 2025-01-28 17:32:00.785: node is rebuilding...: type: page
[DEBUG][editor]: 2025-01-28 17:32:00.791: node is rebuilding...: type: paragraph
[DEBUG][editor]: 2025-01-28 17:32:00.797: node is rebuilding...: type: paragraph
[DEBUG][editor]: 2025-01-28 17:32:00.801: node is rebuilding...: type: paragraph
[DEBUG][editor]: 2025-01-28 17:32:00.807: node is rebuilding...: type: paragraph
[DEBUG][editor]: 2025-01-28 17:32:00.987: Seal history item
[DEBUG][editor]: 2025-01-28 17:32:10.421: keyboard service - focus changed: false}
```

### Expected Behavior

Without creating spaces and just work as it should.

### Operating System

MacOS - Chrome Version 120.0.6099.216 (Official Build) (arm64)

### AppFlowy Editor Version(s)

5.0.0

### Screenshots

Shown in the bug description.

### Additional Context

_No response_

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。