fix: could not insert space sometimes on the web

This commit is contained in:
Lucas.Xu 2022-09-28 23:36:44 +08:00
parent 6ec93d49c2
commit 0a49a18280
7 changed files with 158 additions and 38 deletions

View File

@ -0,0 +1,34 @@
import 'dart:async';
import 'package:appflowy_editor/src/commands/text_command_infra.dart';
import 'package:appflowy_editor/src/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/operation/transaction_builder.dart';
import 'package:flutter/widgets.dart';
Future<void> insertContextInText(
EditorState editorState,
int index,
String content, {
Path? path,
TextNode? textNode,
}) async {
final result = getTextNodeToBeFormatted(
editorState,
path: path,
textNode: textNode,
);
final completer = Completer<void>();
TransactionBuilder(editorState)
..insertText(result, index, content)
..commit();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
completer.complete();
});
return completer.future;
}

View File

@ -1,4 +1,5 @@
import 'package:appflowy_editor/src/commands/format_text.dart';
import 'package:appflowy_editor/src/commands/text_command_infra.dart';
import 'package:appflowy_editor/src/document/attributes.dart';
import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
import 'package:appflowy_editor/src/document/node.dart';

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:appflowy_editor/src/commands/text_command_infra.dart';
import 'package:appflowy_editor/src/document/attributes.dart';
import 'package:appflowy_editor/src/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
@ -45,7 +46,7 @@ Future<void> updateTextNodeDeltaAttributes(
path: path,
textNode: textNode,
);
final newSelection = _getSelection(editorState, selection: selection);
final newSelection = getSelection(editorState, selection: selection);
final completer = Completer<void>();
@ -64,40 +65,3 @@ Future<void> updateTextNodeDeltaAttributes(
return completer.future;
}
// get formatted [TextNode]
TextNode getTextNodeToBeFormatted(
EditorState editorState, {
Path? path,
TextNode? textNode,
}) {
assert(!(path != null && textNode != null));
assert(!(path == null && textNode == null));
TextNode result;
if (textNode != null) {
result = textNode;
} else if (path != null) {
result = editorState.document.nodeAtPath(path) as TextNode;
} else {
throw Exception('path and textNode cannot be null at the same time');
}
return result;
}
Selection _getSelection(
EditorState editorState, {
Selection? selection,
}) {
final currentSelection =
editorState.service.selectionService.currentSelection.value;
Selection result;
if (selection != null) {
result = selection;
} else if (currentSelection != null) {
result = currentSelection;
} else {
throw Exception('path and textNode cannot be null at the same time');
}
return result;
}

View File

@ -0,0 +1,43 @@
import 'package:appflowy_editor/src/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart';
// get formatted [TextNode]
TextNode getTextNodeToBeFormatted(
EditorState editorState, {
Path? path,
TextNode? textNode,
}) {
final currentSelection =
editorState.service.selectionService.currentSelection.value;
TextNode result;
if (textNode != null) {
result = textNode;
} else if (path != null) {
result = editorState.document.nodeAtPath(path) as TextNode;
} else if (currentSelection != null && currentSelection.isCollapsed) {
result = editorState.document.nodeAtPath(currentSelection.start.path)
as TextNode;
} else {
throw Exception('path and textNode cannot be null at the same time');
}
return result;
}
Selection getSelection(
EditorState editorState, {
Selection? selection,
}) {
final currentSelection =
editorState.service.selectionService.currentSelection.value;
Selection result;
if (selection != null) {
result = selection;
} else if (currentSelection != null) {
result = currentSelection;
} else {
throw Exception('path and textNode cannot be null at the same time');
}
return result;
}

View File

@ -0,0 +1,21 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor/src/commands/edit_text.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
ShortcutEventHandler spaceOnWebHandler = (editorState, event) {
final selection = editorState.service.selectionService.currentSelection.value;
final textNodes = editorState.service.selectionService.currentSelectedNodes
.whereType<TextNode>()
.toList(growable: false);
if (selection == null ||
!selection.isCollapsed ||
!kIsWeb ||
textNodes.length != 1) {
return KeyEventResult.ignored;
}
insertContextInText(editorState, selection.startIndex, ' ');
return KeyEventResult.handled;
};

View File

@ -9,9 +9,11 @@ import 'package:appflowy_editor/src/service/internal_key_event_handlers/redo_und
import 'package:appflowy_editor/src/service/internal_key_event_handlers/select_all_handler.dart';
import 'package:appflowy_editor/src/service/internal_key_event_handlers/slash_handler.dart';
import 'package:appflowy_editor/src/service/internal_key_event_handlers/format_style_handler.dart';
import 'package:appflowy_editor/src/service/internal_key_event_handlers/space_on_web_handler.dart';
import 'package:appflowy_editor/src/service/internal_key_event_handlers/tab_handler.dart';
import 'package:appflowy_editor/src/service/internal_key_event_handlers/whitespace_handler.dart';
import 'package:appflowy_editor/src/service/shortcut_event/shortcut_event.dart';
import 'package:flutter/foundation.dart';
//
List<ShortcutEvent> builtInShortcutEvents = [
@ -249,4 +251,14 @@ List<ShortcutEvent> builtInShortcutEvents = [
command: 'tab',
handler: tabHandler,
),
// https://github.com/flutter/flutter/issues/104944
// Workaround: Using space editing on the web platform often results in errors,
// so adding a shortcut event to handle the space input instead of using the
// `input_service`.
if (kIsWeb)
ShortcutEvent(
key: 'Space on the Web',
command: 'space',
handler: spaceOnWebHandler,
),
];

View File

@ -0,0 +1,45 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../infra/test_editor.dart';
void main() async {
setUpAll(() {
TestWidgetsFlutterBinding.ensureInitialized();
});
group('space_on_web_handler.dart', () {
testWidgets('Presses space key on web', (tester) async {
if (!kIsWeb) return;
const count = 10;
const text = 'Welcome to Appflowy 😁';
final editor = tester.editor;
for (var i = 0; i < count; i++) {
editor.insertTextNode(text);
}
await editor.startTesting();
for (var i = 0; i < count; i++) {
await editor.updateSelection(
Selection.single(path: [i], startOffset: 1),
);
await editor.pressLogicKey(LogicalKeyboardKey.space);
expect(
(editor.nodeAtPath([i]) as TextNode).toRawString(),
'W elcome to Appflowy 😁',
);
}
for (var i = 0; i < count; i++) {
await editor.updateSelection(
Selection.single(path: [i], startOffset: text.length + 1),
);
await editor.pressLogicKey(LogicalKeyboardKey.space);
expect(
(editor.nodeAtPath([i]) as TextNode).toRawString(),
'W elcome to Appflowy 😁 ',
);
}
});
});
}