chore: sync the latest code from AppFlowy (#41)

* chore: sync latest code from appflowy

* chore: sync latest tests from appflowy
This commit is contained in:
Lucas.Xu 2023-04-06 15:55:23 +08:00 • committed by GitHub
commit 7885d5f1ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 723 additions and 304 deletions

View file

@ -1,51 +1,51 @@
/// AppFlowyEditor library
library appflowy_editor;
export 'src/commands/command_extension.dart';
export 'src/commands/text/text_commands.dart';
export 'src/core/document/attributes.dart';
export 'src/core/document/document.dart';
export 'src/infra/log.dart';
export 'src/render/style/editor_style.dart';
export 'src/core/document/node.dart';
export 'src/core/document/node_iterator.dart';
export 'src/core/document/path.dart';
export 'src/core/document/text_delta.dart';
export 'src/core/legacy/built_in_attribute_keys.dart';
export 'src/core/location/position.dart';
export 'src/core/location/selection.dart';
export 'src/core/document/document.dart';
export 'src/core/document/text_delta.dart';
export 'src/core/document/attributes.dart';
export 'src/core/legacy/built_in_attribute_keys.dart';
export 'src/editor_state.dart';
export 'src/core/transform/operation.dart';
export 'src/core/transform/transaction.dart';
export 'src/editor_state.dart';
export 'src/extensions/attributes_extension.dart';
export 'src/extensions/node_extensions.dart';
export 'src/infra/log.dart';
export 'src/l10n/l10n.dart';
export 'src/plugins/markdown/decoder/delta_markdown_decoder.dart';
export 'src/plugins/markdown/document_markdown.dart';
export 'src/plugins/markdown/encoder/delta_markdown_encoder.dart';
export 'src/plugins/markdown/encoder/document_markdown_encoder.dart';
export 'src/plugins/markdown/encoder/parser/image_node_parser.dart';
export 'src/plugins/markdown/encoder/parser/node_parser.dart';
export 'src/plugins/markdown/encoder/parser/text_node_parser.dart';
export 'src/plugins/quill_delta/delta_document_encoder.dart';
export 'src/render/action_menu/action_menu.dart';
export 'src/render/action_menu/action_menu_item.dart';
export 'src/render/rich_text/default_selectable.dart';
export 'src/render/rich_text/flowy_rich_text.dart';
export 'src/render/selection/selectable.dart';
export 'src/render/selection_menu/selection_menu_item_widget.dart';
export 'src/render/selection_menu/selection_menu_service.dart';
export 'src/render/selection_menu/selection_menu_widget.dart';
export 'src/render/style/editor_style.dart';
export 'src/render/style/plugin_styles.dart';
export 'src/render/toolbar/toolbar_item.dart';
export 'src/service/editor_service.dart';
export 'src/service/input_service.dart';
export 'src/service/keyboard_service.dart';
export 'src/service/render_plugin_service.dart';
export 'src/service/scroll_service.dart';
export 'src/service/selection_service.dart';
export 'src/service/service.dart';
export 'src/service/selection_service.dart';
export 'src/service/scroll_service.dart';
export 'src/service/toolbar_service.dart';
export 'src/service/keyboard_service.dart';
export 'src/service/input_service.dart';
export 'src/service/shortcut_event/keybinding.dart';
export 'src/service/shortcut_event/shortcut_event.dart';
export 'src/service/shortcut_event/shortcut_event_handler.dart';
export 'src/service/toolbar_service.dart';
export 'src/extensions/attributes_extension.dart';
export 'src/render/rich_text/default_selectable.dart';
export 'src/render/rich_text/flowy_rich_text.dart';
export 'src/render/selection_menu/selection_menu_widget.dart';
export 'src/render/selection_menu/selection_menu_item_widget.dart';
export 'src/l10n/l10n.dart';
export 'src/render/style/plugin_styles.dart';
export 'src/plugins/markdown/encoder/delta_markdown_encoder.dart';
export 'src/plugins/markdown/encoder/document_markdown_encoder.dart';
export 'src/plugins/markdown/encoder/parser/node_parser.dart';
export 'src/plugins/markdown/encoder/parser/text_node_parser.dart';
export 'src/plugins/markdown/encoder/parser/image_node_parser.dart';
export 'src/plugins/markdown/decoder/delta_markdown_decoder.dart';
export 'src/plugins/markdown/document_markdown.dart';
export 'src/plugins/quill_delta/delta_document_encoder.dart';
export 'src/commands/text/text_commands.dart';
export 'src/commands/command_extension.dart';
export 'src/render/toolbar/toolbar_item.dart';
export 'src/extensions/node_extensions.dart';
export 'src/render/action_menu/action_menu.dart';
export 'src/render/action_menu/action_menu_item.dart';
export 'src/core/document/node_iterator.dart';

View file

@ -363,6 +363,19 @@ extension TextTransaction on Transaction {
);
} else {
deleteNode(textNode);
if (i == textNodes.length - 1) {
final delta = Delta()
..insert(texts[0])
..addAll(
textNodes.last.delta.slice(selection.end.offset),
);
replaceText(
textNode,
selection.start.offset,
texts[0].length,
delta.toPlainText(),
);
}
}
}
afterSelection = null;
@ -371,6 +384,8 @@ extension TextTransaction on Transaction {
if (textNodes.length < texts.length) {
final length = texts.length;
var path = textNodes.first.path;
for (var i = 0; i < texts.length; i++) {
final text = texts[i];
if (i == 0) {
@ -380,13 +395,15 @@ extension TextTransaction on Transaction {
textNodes.first.toPlainText().length,
text,
);
} else if (i == length - 1) {
path = path.next;
} else if (i == length - 1 && textNodes.length >= 2) {
replaceText(
textNodes.last,
0,
selection.endIndex,
text,
);
path = path.next;
} else {
if (i < textNodes.length - 1) {
replaceText(
@ -395,14 +412,28 @@ extension TextTransaction on Transaction {
textNodes[i].toPlainText().length,
text,
);
} else {
var path = textNodes.first.path;
var j = i - textNodes.length + length - 1;
while (j > 0) {
path = path.next;
j--;
} else {
if (i == texts.length - 1) {
final delta = Delta()
..insert(text)
..addAll(
textNodes.last.delta.slice(selection.end.offset),
);
insertNode(
path,
TextNode(
delta: delta,
),
);
} else {
insertNode(
path,
TextNode(
delta: Delta()..insert(text),
),
);
}
insertNode(path, TextNode(delta: Delta()..insert(text)));
}
}
}

View file

@ -8,6 +8,7 @@ import 'package:appflowy_editor/src/render/link_menu/link_menu.dart';
import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
import 'package:appflowy_editor/src/extensions/editor_state_extensions.dart';
import 'package:appflowy_editor/src/service/default_text_operations/format_rich_text_style.dart';
import 'dart:io' show Platform;
import 'package:flutter/material.dart' hide Overlay, OverlayEntry;
@ -127,7 +128,8 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem(
id: 'appflowy.toolbar.bold',
type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.bold,
tooltipsMessage:
"${AppFlowyEditorLocalizations.current.bold}\n${Platform.isMacOS ? "⌘ + B" : "CTRL + B"}",
iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/bold',
color: isHighlight ? Colors.lightBlue : null,
@ -143,7 +145,8 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem(
id: 'appflowy.toolbar.italic',
type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.italic,
tooltipsMessage:
"${AppFlowyEditorLocalizations.current.italic}\n${Platform.isMacOS ? "⌘ + I" : "CTRL + I"}",
iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/italic',
color: isHighlight ? Colors.lightBlue : null,
@ -159,7 +162,8 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem(
id: 'appflowy.toolbar.underline',
type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.underline,
tooltipsMessage:
"${AppFlowyEditorLocalizations.current.underline}\n${Platform.isMacOS ? "⌘ + U" : "CTRL + U"}",
iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/underline',
color: isHighlight ? Colors.lightBlue : null,
@ -175,7 +179,8 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem(
id: 'appflowy.toolbar.strikethrough',
type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.strikethrough,
tooltipsMessage:
"${AppFlowyEditorLocalizations.current.strikethrough}\n${Platform.isMacOS ? "⌘ + SHIFT + S" : "CTRL + SHIFT + S"}",
iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/strikethrough',
color: isHighlight ? Colors.lightBlue : null,
@ -191,7 +196,8 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem(
id: 'appflowy.toolbar.code',
type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.embedCode,
tooltipsMessage:
"${AppFlowyEditorLocalizations.current.embedCode}\n${Platform.isMacOS ? "⌘ + E" : "CTRL + E"}",
iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/code',
color: isHighlight ? Colors.lightBlue : null,
@ -241,7 +247,8 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem(
id: 'appflowy.toolbar.link',
type: 4,
tooltipsMessage: AppFlowyEditorLocalizations.current.link,
tooltipsMessage:
"${AppFlowyEditorLocalizations.current.link}\n${Platform.isMacOS ? "⌘ + K" : "CTRL + K"}",
iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/link',
color: isHighlight ? Colors.lightBlue : null,
@ -257,7 +264,8 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem(
id: 'appflowy.toolbar.highlight',
type: 4,
tooltipsMessage: AppFlowyEditorLocalizations.current.highlight,
tooltipsMessage:
"${AppFlowyEditorLocalizations.current.highlight}\n${Platform.isMacOS ? "⌘ + SHIFT + H" : "CTRL + SHIFT + H"}",
iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/highlight',
color: isHighlight ? Colors.lightBlue : null,
@ -393,7 +401,6 @@ void showLinkMenu(
top: matchRect.bottom + 5.0,
left: matchRect.left,
child: Material(
borderRadius: BorderRadius.circular(6.0),
child: LinkMenu(
linkText: linkText,
editorState: editorState,

View file

@ -21,6 +21,7 @@ class ToolbarItemWidget extends StatelessWidget {
width: 28,
height: 28,
child: Tooltip(
textAlign: TextAlign.center,
preferBelow: false,
message: item.tooltipsMessage,
child: MouseRegion(

View file

@ -232,7 +232,7 @@ void _pasteSingleLine(
/// parse url from the line text
/// reference: https://stackoverflow.com/questions/59444837/flutter-dart-regex-to-extract-urls-from-a-string
Delta _lineContentToDelta(String lineContent) {
final exp = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+');
final exp = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\#\w/\-?=%.]+');
final Iterable<RegExpMatch> matches = exp.allMatches(lineContent);
final delta = Delta();

View file

@ -310,7 +310,7 @@ ShortcutEventHandler underscoreToItalicHandler = (editorState, event) {
return KeyEventResult.handled;
};
ShortcutEventHandler doubleAsteriskToBoldHanlder = (editorState, event) {
ShortcutEventHandler doubleAsteriskToBoldHandler = (editorState, event) {
final selectionService = editorState.service.selectionService;
final selection = selectionService.currentSelection.value;
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
@ -367,7 +367,7 @@ ShortcutEventHandler doubleAsteriskToBoldHanlder = (editorState, event) {
};
//Implement in the same way as doubleAsteriskToBoldHanlder
ShortcutEventHandler doubleUnderscoreToBoldHanlder = (editorState, event) {
ShortcutEventHandler doubleUnderscoreToBoldHandler = (editorState, event) {
final selectionService = editorState.service.selectionService;
final selection = selectionService.currentSelection.value;
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();

View file

@ -121,15 +121,13 @@ class _AppFlowyKeyboardState extends State<AppFlowyKeyboard>
return KeyEventResult.ignored;
}
Log.keyboard.debug('on keyboard event $event');
if (event is! RawKeyDownEvent) {
return KeyEventResult.ignored;
}
// TODO: use cache to optimize the searching time.
for (final shortcutEvent in widget.shortcutEvents) {
if (shortcutEvent.keybindings.containsKeyEvent(event)) {
if (shortcutEvent.canRespondToRawKeyEvent(event)) {
final result = shortcutEvent.handler(widget.editorState, event);
if (result == KeyEventResult.handled) {
return KeyEventResult.handled;
@ -157,3 +155,10 @@ class _AppFlowyKeyboardState extends State<AppFlowyKeyboard>
return onKey(event);
}
}
extension on ShortcutEvent {
bool canRespondToRawKeyEvent(RawKeyEvent event) {
return ((character?.isNotEmpty ?? false) && character == event.character) ||
keybindings.containsKeyEvent(event);
}
}

View file

@ -54,20 +54,6 @@ List<ShortcutEvent> builtInShortcutEvents = [
linuxCommand: 'shift+alt+arrow left',
handler: cursorLeftWordSelect,
),
ShortcutEvent(
key: 'Move cursor left one word',
command: 'alt+arrow left',
windowsCommand: 'alt+arrow left',
linuxCommand: 'alt+arrow left',
handler: cursorLeftWordMove,
),
ShortcutEvent(
key: 'Move cursor right one word',
command: 'alt+arrow right',
windowsCommand: 'alt+arrow right',
linuxCommand: 'alt+arrow right',
handler: cursorRightWordMove,
),
ShortcutEvent(
key: 'Cursor right word select',
command: 'shift+alt+arrow right',
@ -261,7 +247,7 @@ List<ShortcutEvent> builtInShortcutEvents = [
),
ShortcutEvent(
key: 'selection menu',
command: 'slash,shift+slash',
character: '/',
handler: slashShortcutHandler,
),
ShortcutEvent(
@ -303,7 +289,7 @@ List<ShortcutEvent> builtInShortcutEvents = [
),
ShortcutEvent(
key: 'Double tilde to strikethrough',
command: 'tilde,shift+tilde',
character: '~',
handler: doubleTildeToStrikethrough,
),
ShortcutEvent(
@ -318,19 +304,34 @@ List<ShortcutEvent> builtInShortcutEvents = [
),
ShortcutEvent(
key: 'Underscore to italic',
command: 'shift+underscore',
character: '_',
handler: underscoreToItalicHandler,
),
ShortcutEvent(
key: 'Double asterisk to bold',
command: 'shift+digit 8',
handler: doubleAsteriskToBoldHanlder,
character: '*',
handler: doubleAsteriskToBoldHandler,
),
ShortcutEvent(
key: 'Double underscore to bold',
command: 'shift+underscore',
handler: doubleUnderscoreToBoldHanlder,
character: '_',
handler: doubleUnderscoreToBoldHandler,
),
ShortcutEvent(
key: 'Move cursor left one word',
command: 'alt+arrow left',
windowsCommand: 'alt+arrow left',
linuxCommand: 'alt+arrow left',
handler: cursorLeftWordMove,
),
ShortcutEvent(
key: 'Move cursor right one word',
command: 'alt+arrow right',
windowsCommand: 'alt+arrow right',
linuxCommand: 'alt+arrow right',
handler: cursorRightWordMove,
),
// 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

View file

@ -8,12 +8,29 @@ import 'package:flutter/foundation.dart';
class ShortcutEvent {
ShortcutEvent({
required this.key,
required this.command,
this.character,
this.command,
required this.handler,
String? windowsCommand,
String? macOSCommand,
String? linuxCommand,
}) {
// character and command cannot be null at the same time
assert(
!(character == null &&
command == null &&
windowsCommand == null &&
macOSCommand == null &&
linuxCommand == null),
'character and command cannot be null at the same time');
assert(
!(character != null &&
(command != null &&
windowsCommand != null &&
macOSCommand != null &&
linuxCommand != null)),
'character and command cannot be set at the same time');
updateCommand(
command: command,
windowsCommand: windowsCommand,
@ -43,7 +60,9 @@ class ShortcutEvent {
///
/// Like, 'ctrl+c,cmd+c'
///
String command;
String? command;
String? character;
final ShortcutEventHandler handler;
@ -80,9 +99,9 @@ class ShortcutEvent {
matched = true;
}
if (matched) {
if (matched && this.command != null) {
_keybindings = this
.command
.command!
.split(',')
.map((e) => Keybinding.parse(e))
.toList(growable: false);

View file

@ -0,0 +1,36 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
import '../infra/test_editor.dart';
void main() {
group('command_extension.dart', () {
testWidgets('insert a new checkbox after an existing checkbox',
(tester) async {
final editor = tester.editor
..insertTextNode(
'Welcome',
)
..insertTextNode(
'to',
)
..insertTextNode(
'Appflowy 😁',
);
await editor.startTesting();
final selection = Selection(
start: Position(path: [2], offset: 5),
end: Position(path: [0], offset: 5),
);
await editor.updateSelection(selection);
final textNodes = editor
.editorState.service.selectionService.currentSelectedNodes
.whereType<TextNode>()
.toList(growable: false);
final texts = editor.editorState.getTextInSelection(
textNodes.normalized,
selection.normalized,
);
expect(texts, ['me', 'to', 'Appfl']);
});
});
}

View file

@ -28,5 +28,29 @@ void main() async {
}
expect(nodes.moveNext(), false);
});
test('toList - when we have at least three level nested nodes (children)',
() {
final root = Node(type: 'root'),
n1 = Node(type: 'node_1'),
n2 = Node(type: 'node_2');
root.insert(n1);
root.insert(n2);
n1.insert(Node(type: 'node_1_1'));
n1.insert(Node(type: 'node_1_2'));
n1.childAtIndex(0)?.insert(Node(type: 'node_1_1_1'));
n1.childAtIndex(1)?.insert(Node(type: 'node_1_2_1'));
final nodes = NodeIterator(
document: Document(root: root),
startNode: root.childAtPath([0])!,
endNode: root.childAtPath([1]),
).toList();
expect(nodes[0].id, n1.id);
expect(nodes[1].id, n1.childAtIndex(0)!.id);
expect(nodes[nodes.length - 1].id, n2.id);
});
});
}

View file

@ -75,9 +75,5 @@ void main() async {
expect(op.invert().invert(), op);
expect(op.copyWith(), op);
});
test('Operation.fromJson throws', () {
expect(() => Operation.fromJson(), throwsA(isA<UnimplementedError>()));
});
});
}

View file

@ -0,0 +1,206 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../infra/test_editor.dart';
Document createEmptyDocument() {
return Document(
root: Node(
type: 'editor',
),
);
}
void main() async {
group('transaction.dart', () {
testWidgets('test replaceTexts, textNodes.length == texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();
final editor = tester.editor
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789');
await editor.startTesting();
await tester.pumpAndSettle();
expect(editor.documentLength, 4);
final selection = Selection(
start: Position(path: [0], offset: 4),
end: Position(path: [3], offset: 4),
);
final transaction = editor.editorState.transaction;
var textNodes = [0, 1, 2, 3]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC', 'ABC', 'ABC', 'ABC'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();
expect(editor.documentLength, 4);
textNodes = [0, 1, 2, 3]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), '0123ABC');
expect(textNodes[1].toPlainText(), 'ABC');
expect(textNodes[2].toPlainText(), 'ABC');
expect(textNodes[3].toPlainText(), 'ABC456789');
});
testWidgets('test replaceTexts, textNodes.length > texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();
final editor = tester.editor
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789');
await editor.startTesting();
await tester.pumpAndSettle();
expect(editor.documentLength, 5);
final selection = Selection(
start: Position(path: [0], offset: 4),
end: Position(path: [4], offset: 4),
);
final transaction = editor.editorState.transaction;
var textNodes = [0, 1, 2, 3, 4]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC', 'ABC', 'ABC', 'ABC'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();
expect(editor.documentLength, 4);
textNodes = [0, 1, 2, 3]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), '0123ABC');
expect(textNodes[1].toPlainText(), 'ABC');
expect(textNodes[2].toPlainText(), 'ABC');
expect(textNodes[3].toPlainText(), 'ABC456789');
});
testWidgets('test replaceTexts, textNodes.length >> texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();
final editor = tester.editor
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789');
await editor.startTesting();
await tester.pumpAndSettle();
expect(editor.documentLength, 5);
final selection = Selection(
start: Position(path: [0], offset: 4),
end: Position(path: [4], offset: 4),
);
final transaction = editor.editorState.transaction;
var textNodes = [0, 1, 2, 3, 4]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();
expect(editor.documentLength, 1);
textNodes = [0]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), '0123ABC456789');
});
testWidgets('test replaceTexts, textNodes.length < texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();
final editor = tester.editor
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789');
await editor.startTesting();
await tester.pumpAndSettle();
expect(editor.documentLength, 3);
final selection = Selection(
start: Position(path: [0], offset: 4),
end: Position(path: [2], offset: 4),
);
final transaction = editor.editorState.transaction;
var textNodes = [0, 1, 2]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC', 'ABC', 'ABC', 'ABC'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();
expect(editor.documentLength, 4);
textNodes = [0, 1, 2, 3]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), '0123ABC');
expect(textNodes[1].toPlainText(), 'ABC');
expect(textNodes[2].toPlainText(), 'ABC');
expect(textNodes[3].toPlainText(), 'ABC456789');
});
testWidgets('test replaceTexts, textNodes.length << texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();
final editor = tester.editor..insertTextNode('Welcome to AppFlowy!');
await editor.startTesting();
await tester.pumpAndSettle();
expect(editor.documentLength, 1);
// select 'to'
final selection = Selection(
start: Position(path: [0], offset: 8),
end: Position(path: [0], offset: 10),
);
final transaction = editor.editorState.transaction;
var textNodes = [0]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC1', 'ABC2', 'ABC3', 'ABC4', 'ABC5'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();
expect(editor.documentLength, 5);
textNodes = [0, 1, 2, 3, 4]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), 'Welcome ABC1');
expect(textNodes[1].toPlainText(), 'ABC2');
expect(textNodes[2].toPlainText(), 'ABC3');
expect(textNodes[3].toPlainText(), 'ABC4');
expect(textNodes[4].toPlainText(), 'ABC5 AppFlowy!');
});
});
}

View file

@ -124,8 +124,9 @@ class EditorWidgetTester {
await tester.pumpAndSettle();
}
Future<void> pressLogicKey(
LogicalKeyboardKey key, {
Future<void> pressLogicKey({
String? character,
LogicalKeyboardKey? key,
bool isControlPressed = false,
bool isShiftPressed = false,
bool isAltPressed = false,
@ -134,11 +135,13 @@ class EditorWidgetTester {
if (!isControlPressed &&
!isShiftPressed &&
!isAltPressed &&
!isMetaPressed) {
!isMetaPressed &&
key != null) {
await tester.sendKeyDownEvent(key);
} else {
final testRawKeyEventData = TestRawKeyEventData(
logicalKey: key,
logicalKey: key ?? LogicalKeyboardKey.nonConvert,
character: character,
isControlPressed: isControlPressed,
isShiftPressed: isShiftPressed,
isAltPressed: isAltPressed,

View file

@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
class TestRawKeyEvent extends RawKeyDownEvent {
const TestRawKeyEvent({
required super.data,
required super.character,
this.isControlPressed = false,
this.isShiftPressed = false,
this.isAltPressed = false,
@ -24,7 +25,9 @@ class TestRawKeyEvent extends RawKeyDownEvent {
class TestRawKeyEventData extends RawKeyEventData {
const TestRawKeyEventData({
required this.logicalKey,
this.logicalKey =
LogicalKeyboardKey.nonConvert, // use nonConvert as placeholder.
this.character,
this.isControlPressed = false,
this.isShiftPressed = false,
this.isAltPressed = false,
@ -46,6 +49,8 @@ class TestRawKeyEventData extends RawKeyEventData {
@override
final LogicalKeyboardKey logicalKey;
final String? character;
@override
PhysicalKeyboardKey get physicalKey => logicalKey.toPhysicalKey;
@ -55,8 +60,10 @@ class TestRawKeyEventData extends RawKeyEventData {
}
@override
bool isModifierPressed(ModifierKey key,
{KeyboardSide side = KeyboardSide.any}) {
bool isModifierPressed(
ModifierKey key, {
KeyboardSide side = KeyboardSide.any,
}) {
throw UnimplementedError();
}
@ -66,6 +73,7 @@ class TestRawKeyEventData extends RawKeyEventData {
RawKeyEvent get toKeyEvent {
return TestRawKeyEvent(
data: this,
character: character,
isAltPressed: isAltPressed,
isControlPressed: isControlPressed,
isMetaPressed: isMetaPressed,

View file

@ -71,7 +71,7 @@ void main() async {
// https://github.com/AppFlowy-IO/AppFlowy/issues/1763
// // [Bug] Mouse unable to click a certain area #1763
testWidgets('insert a new checkbox after an exsiting checkbox',
testWidgets('insert a new checkbox after an existing checkbox',
(tester) async {
// Before
//
@ -100,16 +100,16 @@ void main() async {
Selection.single(path: [0], startOffset: text.length),
);
await editor.pressLogicKey(LogicalKeyboardKey.enter);
await editor.pressLogicKey(LogicalKeyboardKey.enter);
await editor.pressLogicKey(LogicalKeyboardKey.enter);
await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
expect(
editor.documentSelection,
Selection.single(path: [2], startOffset: 0),
);
await editor.pressLogicKey(LogicalKeyboardKey.slash);
await editor.pressLogicKey(key: LogicalKeyboardKey.slash);
await tester.pumpAndSettle(const Duration(milliseconds: 1000));
expect(

View file

@ -21,10 +21,10 @@ void main() async {
(tester) async {
final editor = await _prepare(tester);
for (var j = 0; j < i; j++) {
await editor.pressLogicKey(LogicalKeyboardKey.arrowDown);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowDown);
}
await editor.pressLogicKey(LogicalKeyboardKey.enter);
await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
expect(
find.byType(SelectionMenuWidget, skipOffstage: false),
findsNothing,
@ -51,33 +51,33 @@ void main() async {
testWidgets('Search item in selection menu util no results',
(tester) async {
final editor = await _prepare(tester);
await editor.pressLogicKey(LogicalKeyboardKey.keyT);
await editor.pressLogicKey(LogicalKeyboardKey.keyE);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyT);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyE);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNWidgets(3),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNWidgets(5),
);
await editor.pressLogicKey(LogicalKeyboardKey.keyE);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyE);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNWidgets(3),
);
await editor.pressLogicKey(LogicalKeyboardKey.keyX);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyX);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNWidgets(1),
);
await editor.pressLogicKey(LogicalKeyboardKey.keyT);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyT);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNWidgets(1),
);
await editor.pressLogicKey(LogicalKeyboardKey.keyT);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyT);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNothing,
@ -87,13 +87,13 @@ void main() async {
testWidgets('Search item in selection menu and presses esc',
(tester) async {
final editor = await _prepare(tester);
await editor.pressLogicKey(LogicalKeyboardKey.keyT);
await editor.pressLogicKey(LogicalKeyboardKey.keyE);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyT);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyE);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNWidgets(3),
);
await editor.pressLogicKey(LogicalKeyboardKey.escape);
await editor.pressLogicKey(key: LogicalKeyboardKey.escape);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNothing,
@ -103,20 +103,92 @@ void main() async {
testWidgets('Search item in selection menu and presses backspace',
(tester) async {
final editor = await _prepare(tester);
await editor.pressLogicKey(LogicalKeyboardKey.keyT);
await editor.pressLogicKey(LogicalKeyboardKey.keyE);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyT);
await editor.pressLogicKey(key: LogicalKeyboardKey.keyE);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNWidgets(3),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNothing,
);
});
group('tab and arrow keys move selection in desired direction', () {
testWidgets('left and right keys move selection in desired direction',
(tester) async {
final editor = await _prepare(tester);
var initialSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(initialSelection.item), 0);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowRight);
var newSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(newSelection.item), 5);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowLeft);
var finalSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(finalSelection.item), 0);
});
testWidgets('up and down keys move selection in desired direction',
(tester) async {
final editor = await _prepare(tester);
var initialSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(initialSelection.item), 0);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowDown);
var newSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(newSelection.item), 1);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowUp);
var finalSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(finalSelection.item), 0);
});
testWidgets('arrow keys and tab move same selection', (tester) async {
final editor = await _prepare(tester);
var initialSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(initialSelection.item), 0);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowDown);
var newSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(newSelection.item), 1);
await editor.pressLogicKey(key: LogicalKeyboardKey.tab);
var finalSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(finalSelection.item), 6);
});
testWidgets(
'tab moves selection to next row Item on reaching end of current row',
(tester) async {
final editor = await _prepare(tester);
final initialSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(initialSelection.item), 0);
await editor.pressLogicKey(key: LogicalKeyboardKey.tab);
await editor.pressLogicKey(key: LogicalKeyboardKey.tab);
final finalSelection = getSelectedMenuItem(tester);
expect(defaultSelectionMenuItems.indexOf(finalSelection.item), 1);
});
});
});
}
@ -129,7 +201,7 @@ Future<EditorWidgetTester> _prepare(WidgetTester tester) async {
}
await editor.startTesting();
await editor.updateSelection(Selection.single(path: [1], startOffset: 0));
await editor.pressLogicKey(LogicalKeyboardKey.slash);
await editor.pressLogicKey(key: LogicalKeyboardKey.slash);
await tester.pumpAndSettle(const Duration(milliseconds: 1000));
@ -177,3 +249,11 @@ Future<void> _testDefaultSelectionMenuItems(
expect(node?.attributes.check, false);
}
}
SelectionMenuItemWidget getSelectedMenuItem(WidgetTester tester) {
return tester
.state(find.byWidgetPredicate(
(widget) => widget is SelectionMenuItemWidget && widget.isSelected,
))
.widget as SelectionMenuItemWidget;
}

View file

@ -25,7 +25,7 @@ void main() async {
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.pressLogicKey(LogicalKeyboardKey.arrowRight);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowRight);
if (i == text.length - 1) {
// Wrap to next node if the cursor is at the end of the current node.
@ -63,7 +63,7 @@ void main() async {
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isAltPressed: true,
);
@ -76,11 +76,11 @@ void main() async {
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isAltPressed: true,
);
@ -93,7 +93,7 @@ void main() async {
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isAltPressed: true,
);
@ -130,7 +130,7 @@ void main() async {
await editor.updateSelection(selection);
for (var i = offset - 1; i >= 0; i--) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
);
expect(
@ -142,7 +142,7 @@ void main() async {
}
for (var i = text.length; i >= 0; i--) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
);
expect(
@ -154,7 +154,7 @@ void main() async {
}
for (var i = 1; i <= text.length; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
);
expect(
@ -166,7 +166,7 @@ void main() async {
}
for (var i = 0; i < text.length; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
);
expect(
@ -196,7 +196,7 @@ void main() async {
await editor.updateSelection(selection);
for (var i = end + 1; i <= text.length; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
);
expect(
@ -208,7 +208,7 @@ void main() async {
}
for (var i = text.length - 1; i >= 0; i--) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
);
expect(
@ -238,7 +238,7 @@ void main() async {
await editor.updateSelection(selection);
for (var i = end - 1; i >= 0; i--) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
);
expect(
@ -250,7 +250,7 @@ void main() async {
}
for (var i = 1; i <= text.length; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
);
expect(
@ -295,7 +295,7 @@ void main() async {
await editor.updateSelection(selection);
for (int i = 0; i < 3; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowUp,
key: LogicalKeyboardKey.arrowUp,
isShiftPressed: true,
);
}
@ -307,7 +307,7 @@ void main() async {
);
for (int i = 0; i < 7; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowDown,
key: LogicalKeyboardKey.arrowDown,
isShiftPressed: true,
);
}
@ -319,7 +319,7 @@ void main() async {
);
for (int i = 0; i < 3; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowUp,
key: LogicalKeyboardKey.arrowUp,
isShiftPressed: true,
);
}
@ -341,18 +341,18 @@ void main() async {
final selection = Selection.single(path: [0], startOffset: 8);
await editor.updateSelection(selection);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowDown,
key: LogicalKeyboardKey.arrowDown,
isShiftPressed: true,
);
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
isMetaPressed: true,
);
@ -375,18 +375,18 @@ void main() async {
final selection = Selection.single(path: [1], startOffset: 8);
await editor.updateSelection(selection);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowUp,
key: LogicalKeyboardKey.arrowUp,
isShiftPressed: true,
);
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
isMetaPressed: true,
);
@ -409,7 +409,7 @@ void main() async {
final selection = Selection.single(path: [1], startOffset: 10);
await editor.updateSelection(selection);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
isAltPressed: true,
);
@ -421,7 +421,7 @@ void main() async {
),
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
isAltPressed: true,
);
@ -433,7 +433,7 @@ void main() async {
),
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
isAltPressed: true,
);
@ -445,7 +445,7 @@ void main() async {
),
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isShiftPressed: true,
isAltPressed: true,
);
@ -469,7 +469,7 @@ void main() async {
final selection = Selection.single(path: [0], startOffset: 10);
await editor.updateSelection(selection);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
isAltPressed: true,
);
@ -481,7 +481,7 @@ void main() async {
),
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
isAltPressed: true,
);
@ -493,12 +493,12 @@ void main() async {
),
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
isAltPressed: true,
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
isAltPressed: true,
);
@ -510,7 +510,7 @@ void main() async {
),
);
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isShiftPressed: true,
isAltPressed: true,
);
@ -535,12 +535,12 @@ void main() async {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isMetaPressed: true,
);
}
@ -556,12 +556,12 @@ void main() async {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isMetaPressed: true,
);
}
@ -578,12 +578,12 @@ void main() async {
for (var i = 0; i < words.length; i++) {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isMetaPressed: true,
);
}
@ -607,12 +607,12 @@ void main() async {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isMetaPressed: true,
);
}
@ -632,12 +632,12 @@ void main() async {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
isMetaPressed: true,
);
}
@ -667,11 +667,11 @@ Future<void> _testPressArrowKeyInNotCollapsedSelection(
end: isBackward ? end : start,
);
await editor.updateSelection(selection);
await editor.pressLogicKey(LogicalKeyboardKey.arrowLeft);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowLeft);
expect(editor.documentSelection?.start, start);
await editor.updateSelection(selection);
await editor.pressLogicKey(LogicalKeyboardKey.arrowRight);
await editor.pressLogicKey(key: LogicalKeyboardKey.arrowRight);
expect(editor.documentSelection?.end, end);
}
@ -709,12 +709,12 @@ Future<void> _testPressArrowKeyWithMetaInSelection(
await editor.updateSelection(selection);
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowLeft,
key: LogicalKeyboardKey.arrowLeft,
isMetaPressed: true,
);
}
@ -726,12 +726,12 @@ Future<void> _testPressArrowKeyWithMetaInSelection(
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowRight,
key: LogicalKeyboardKey.arrowRight,
isMetaPressed: true,
);
}
@ -743,12 +743,12 @@ Future<void> _testPressArrowKeyWithMetaInSelection(
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowUp,
key: LogicalKeyboardKey.arrowUp,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowUp,
key: LogicalKeyboardKey.arrowUp,
isMetaPressed: true,
);
}
@ -760,12 +760,12 @@ Future<void> _testPressArrowKeyWithMetaInSelection(
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowDown,
key: LogicalKeyboardKey.arrowDown,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.arrowDown,
key: LogicalKeyboardKey.arrowDown,
isMetaPressed: true,
);
}

View file

@ -30,7 +30,7 @@ void main() async {
// Pressing the backspace key continuously.
for (int i = 1; i <= 1; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
);
expect(editor.documentLength, 1);
expect(editor.documentSelection,
@ -112,7 +112,7 @@ void main() async {
await editor.updateSelection(
Selection.single(path: [0], startOffset: text.length),
);
await editor.pressLogicKey(LogicalKeyboardKey.delete);
await editor.pressLogicKey(key: LogicalKeyboardKey.delete);
expect(editor.documentLength, 1);
expect(editor.documentSelection,
@ -207,7 +207,7 @@ void main() async {
),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.documentLength, 3);
expect(find.byType(ImageNodeWidget), findsNothing);
expect(
@ -249,20 +249,20 @@ void main() async {
final textNode = editor.nodeAtPath([0]) as TextNode;
await editor.insertText(textNode, '#', 0);
await editor.pressLogicKey(LogicalKeyboardKey.space);
await editor.pressLogicKey(key: LogicalKeyboardKey.space);
expect(
(editor.nodeAtPath([0]) as TextNode).attributes.heading,
BuiltInAttributeKey.h1,
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(
textNode.attributes.heading,
null,
);
await editor.insertText(textNode, '#', 0);
await editor.pressLogicKey(LogicalKeyboardKey.space);
await editor.pressLogicKey(key: LogicalKeyboardKey.space);
expect(
(editor.nodeAtPath([0]) as TextNode).attributes.heading,
BuiltInAttributeKey.h1,
@ -296,17 +296,17 @@ void main() async {
await editor.updateSelection(
Selection.single(path: [0, 0, 0], startOffset: 0),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.nodeAtPath([0, 0, 0])?.subtype, null);
await editor.updateSelection(
Selection.single(path: [0, 0, 0], startOffset: 0),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.nodeAtPath([0, 1]) != null, true);
await editor.updateSelection(
Selection.single(path: [0, 1], startOffset: 0),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.nodeAtPath([1]) != null, true);
await editor.updateSelection(
Selection.single(path: [1], startOffset: 0),
@ -314,7 +314,7 @@ void main() async {
// * Welcome to Appflowy 😁
// * Welcome to Appflowy 😁Welcome to Appflowy 😁
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(
editor.documentSelection,
Selection.single(path: [0, 0], startOffset: text.length),
@ -356,7 +356,7 @@ void main() async {
await editor.updateSelection(
Selection.single(path: [0, 1], startOffset: 0),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(
editor.nodeAtPath([0, 1])!.subtype != BuiltInAttributeKey.bulletedList,
true,
@ -382,7 +382,7 @@ void main() async {
// * Welcome to Appflowy 😁Welcome to Appflowy 😁
// * Welcome to Appflowy 😁
// * Welcome to Appflowy 😁
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(
editor.nodeAtPath([0, 0])!.subtype == BuiltInAttributeKey.bulletedList,
true,
@ -424,7 +424,7 @@ Future<void> _deleteFirstImage(WidgetTester tester, bool isBackward) async {
),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.documentLength, 2);
expect(find.byType(ImageNodeWidget), findsNothing);
expect(editor.documentSelection, Selection.collapsed(start));
@ -453,7 +453,7 @@ Future<void> _deleteLastImage(WidgetTester tester, bool isBackward) async {
),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.documentLength, 2);
expect(find.byType(ImageNodeWidget), findsNothing);
expect(editor.documentSelection, Selection.collapsed(start));
@ -483,12 +483,12 @@ Future<void> _deleteStyledTextByBackspace(
Selection.single(path: [2], startOffset: 0),
);
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
);
expect(editor.documentSelection, Selection.single(path: [2], startOffset: 0));
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
);
expect(editor.documentLength, 2);
expect(editor.documentSelection,
@ -500,7 +500,7 @@ Future<void> _deleteStyledTextByBackspace(
Selection.single(path: [1], startOffset: 0),
);
await editor.pressLogicKey(
LogicalKeyboardKey.backspace,
key: LogicalKeyboardKey.backspace,
);
expect(editor.documentLength, 2);
expect(editor.documentSelection, Selection.single(path: [1], startOffset: 0));
@ -531,7 +531,7 @@ Future<void> _deleteStyledTextByDelete(
);
for (var i = 1; i < text.length; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.delete,
key: LogicalKeyboardKey.delete,
);
expect(
editor.documentSelection, Selection.single(path: [1], startOffset: 0));
@ -541,7 +541,7 @@ Future<void> _deleteStyledTextByDelete(
}
await editor.pressLogicKey(
LogicalKeyboardKey.delete,
key: LogicalKeyboardKey.delete,
);
expect(editor.documentLength, 2);
expect(editor.documentSelection, Selection.single(path: [1], startOffset: 0));
@ -562,7 +562,7 @@ Future<void> _deleteTextByBackspace(
await editor.updateSelection(
Selection.single(path: [1], startOffset: 10),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.documentLength, 3);
expect(editor.documentSelection, Selection.single(path: [1], startOffset: 9));
@ -573,7 +573,7 @@ Future<void> _deleteTextByBackspace(
await editor.updateSelection(
Selection.single(path: [2], startOffset: 8, endOffset: 11),
);
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.documentLength, 3);
expect(editor.documentSelection, Selection.single(path: [2], startOffset: 8));
expect((editor.nodeAtPath([2]) as TextNode).toPlainText(),
@ -587,7 +587,7 @@ Future<void> _deleteTextByBackspace(
await editor.updateSelection(Selection(
start: isBackwardSelection ? start : end,
end: isBackwardSelection ? end : start));
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
await editor.pressLogicKey(key: LogicalKeyboardKey.backspace);
expect(editor.documentLength, 1);
expect(
editor.documentSelection, Selection.single(path: [0], startOffset: 11));
@ -608,7 +608,7 @@ Future<void> _deleteTextByDelete(
await editor.updateSelection(
Selection.single(path: [1], startOffset: 9),
);
await editor.pressLogicKey(LogicalKeyboardKey.delete);
await editor.pressLogicKey(key: LogicalKeyboardKey.delete);
expect(editor.documentLength, 3);
expect(editor.documentSelection, Selection.single(path: [1], startOffset: 9));
@ -619,7 +619,7 @@ Future<void> _deleteTextByDelete(
await editor.updateSelection(
Selection.single(path: [2], startOffset: 8, endOffset: 11),
);
await editor.pressLogicKey(LogicalKeyboardKey.delete);
await editor.pressLogicKey(key: LogicalKeyboardKey.delete);
expect(editor.documentLength, 3);
expect(editor.documentSelection, Selection.single(path: [2], startOffset: 8));
expect((editor.nodeAtPath([2]) as TextNode).toPlainText(),
@ -633,7 +633,7 @@ Future<void> _deleteTextByDelete(
await editor.updateSelection(Selection(
start: isBackwardSelection ? start : end,
end: isBackwardSelection ? end : start));
await editor.pressLogicKey(LogicalKeyboardKey.delete);
await editor.pressLogicKey(key: LogicalKeyboardKey.delete);
expect(editor.documentLength, 1);
expect(
editor.documentSelection, Selection.single(path: [0], startOffset: 11));

View file

@ -47,12 +47,12 @@ void main() async {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.enter,
key: LogicalKeyboardKey.enter,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.enter,
key: LogicalKeyboardKey.enter,
isMetaPressed: true,
);
}
@ -65,12 +65,12 @@ void main() async {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.enter,
key: LogicalKeyboardKey.enter,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.enter,
key: LogicalKeyboardKey.enter,
isMetaPressed: true,
);
}
@ -145,12 +145,12 @@ void main() async {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.enter,
key: LogicalKeyboardKey.enter,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.enter,
key: LogicalKeyboardKey.enter,
isMetaPressed: true,
);
}
@ -223,12 +223,12 @@ void main() async {
if (Platform.isWindows || Platform.isLinux) {
await editor.pressLogicKey(
LogicalKeyboardKey.enter,
key: LogicalKeyboardKey.enter,
isControlPressed: true,
);
} else {
await editor.pressLogicKey(
LogicalKeyboardKey.enter,
key: LogicalKeyboardKey.enter,
isMetaPressed: true,
);
}

Some files were not shown because too many files have changed in this diff Show more