feat: adjust the text command
This commit is contained in:
parent
c0fb77ad4c
commit
1d0055d0b1
9 changed files with 399 additions and 304 deletions
|
|
@ -44,7 +44,7 @@ class TextRobot {
|
||||||
|
|
||||||
// insert new line
|
// insert new line
|
||||||
if (lines.length > 1) {
|
if (lines.length > 1) {
|
||||||
await editorState.insertNewLineAtCurrentSelection();
|
await editorState.insertNewLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ export 'src/plugins/markdown/encoder/parser/image_node_parser.dart';
|
||||||
export 'src/plugins/markdown/decoder/delta_markdown_decoder.dart';
|
export 'src/plugins/markdown/decoder/delta_markdown_decoder.dart';
|
||||||
export 'src/plugins/markdown/document_markdown.dart';
|
export 'src/plugins/markdown/document_markdown.dart';
|
||||||
export 'src/plugins/quill_delta/delta_document_encoder.dart';
|
export 'src/plugins/quill_delta/delta_document_encoder.dart';
|
||||||
export 'src/commands/text/text_commands.dart';
|
// export 'src/commands/text/text_commands.dart';
|
||||||
export 'src/commands/command_extension.dart';
|
export 'src/commands/command_extension.dart';
|
||||||
export 'src/render/toolbar/toolbar_item.dart';
|
export 'src/render/toolbar/toolbar_item.dart';
|
||||||
export 'src/render/action_menu/action_menu.dart';
|
export 'src/render/action_menu/action_menu.dart';
|
||||||
|
|
|
||||||
|
|
@ -190,4 +190,36 @@ extension TextTransforms on EditorState {
|
||||||
|
|
||||||
return apply(transaction);
|
return apply(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Insert text at the given index of the given [TextNode] or the [Path].
|
||||||
|
///
|
||||||
|
/// [Path] and [TextNode] are mutually exclusive.
|
||||||
|
/// One of these two parameters must have a value.
|
||||||
|
Future<void> insertText(
|
||||||
|
int index,
|
||||||
|
String text, {
|
||||||
|
Path? path,
|
||||||
|
Node? node,
|
||||||
|
}) async {
|
||||||
|
node ??= getNodeAtPath(path!);
|
||||||
|
if (node == null) {
|
||||||
|
assert(false, 'node is null');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return apply(
|
||||||
|
transaction..insertText(node, index, text),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> insertTextAtCurrentSelection(String text) async {
|
||||||
|
final selection = this.selection;
|
||||||
|
if (selection == null || !selection.isCollapsed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return insertText(
|
||||||
|
selection.startIndex,
|
||||||
|
text,
|
||||||
|
path: selection.end.path,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,10 @@ class _CheckboxNodeWidgetState extends State<CheckboxNodeWidget>
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await widget.editorState.formatTextToCheckbox(
|
// await widget.editorState.formatTextToCheckbox(
|
||||||
!check,
|
// !check,
|
||||||
textNode: widget.textNode,
|
// textNode: widget.textNode,
|
||||||
);
|
// );
|
||||||
},
|
},
|
||||||
child: icon,
|
child: icon,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -429,10 +429,10 @@ void showLinkMenu(
|
||||||
await safeLaunchUrl(linkText);
|
await safeLaunchUrl(linkText);
|
||||||
},
|
},
|
||||||
onSubmitted: (text) async {
|
onSubmitted: (text) async {
|
||||||
await editorState.formatLinkInText(
|
// await editorState.formatLinkInText(
|
||||||
text,
|
// text,
|
||||||
textNode: textNode,
|
// textNode: textNode,
|
||||||
);
|
// );
|
||||||
|
|
||||||
_dismissOverlay();
|
_dismissOverlay();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ ShortcutEventHandler spaceOnWebHandler = (editorState, event) {
|
||||||
editorState.insertText(
|
editorState.insertText(
|
||||||
selection.startIndex,
|
selection.startIndex,
|
||||||
' ',
|
' ',
|
||||||
textNode: textNodes.first,
|
node: textNodes.first,
|
||||||
);
|
);
|
||||||
|
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
|
|
|
||||||
|
|
@ -1,218 +1,218 @@
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
// import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
// import 'package:flutter_test/flutter_test.dart';
|
||||||
import '../infra/test_editor.dart';
|
// import '../infra/test_editor.dart';
|
||||||
|
|
||||||
void main() {
|
// void main() {
|
||||||
group('TextCommands extension tests', () {
|
// group('TextCommands extension tests', () {
|
||||||
testWidgets('insertText', (tester) async {
|
// testWidgets('insertText', (tester) async {
|
||||||
final editor = tester.editor
|
// final editor = tester.editor
|
||||||
..insertEmptyTextNode()
|
// ..insertEmptyTextNode()
|
||||||
..insertTextNode('World');
|
// ..insertTextNode('World');
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
editor.editorState.insertText(0, 'Hello', path: [0]);
|
// editor.editorState.insertText(0, 'Hello', path: [0]);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(
|
// expect(
|
||||||
(editor.editorState.getTextNode(path: [0]).delta.first as TextInsert)
|
// (editor.editorState.getTextNode(path: [0]).delta.first as TextInsert)
|
||||||
.text,
|
// .text,
|
||||||
'Hello',
|
// 'Hello',
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('insertTextAtCurrentSelection', (tester) async {
|
// testWidgets('insertTextAtCurrentSelection', (tester) async {
|
||||||
final editor = tester.editor..insertTextNode('Helrld!');
|
// final editor = tester.editor..insertTextNode('Helrld!');
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
final selection = Selection(
|
// final selection = Selection(
|
||||||
start: Position(path: [0], offset: 3),
|
// start: Position(path: [0], offset: 3),
|
||||||
end: Position(path: [0], offset: 3),
|
// end: Position(path: [0], offset: 3),
|
||||||
);
|
// );
|
||||||
|
|
||||||
await editor.updateSelection(selection);
|
// await editor.updateSelection(selection);
|
||||||
|
|
||||||
editor.editorState.insertTextAtCurrentSelection('lo Wo');
|
// editor.editorState.insertTextAtCurrentSelection('lo Wo');
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(
|
// expect(
|
||||||
(editor.editorState.getTextNode(path: [0]).delta.first as TextInsert)
|
// (editor.editorState.getTextNode(path: [0]).delta.first as TextInsert)
|
||||||
.text,
|
// .text,
|
||||||
'Hello World!',
|
// 'Hello World!',
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('formatText', (tester) async {
|
// testWidgets('formatText', (tester) async {
|
||||||
final editor = tester.editor..insertTextNode('Hello');
|
// final editor = tester.editor..insertTextNode('Hello');
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
final selection = Selection(
|
// final selection = Selection(
|
||||||
start: Position(path: [0]),
|
// start: Position(path: [0]),
|
||||||
end: Position(path: [0], offset: 5),
|
// end: Position(path: [0], offset: 5),
|
||||||
);
|
// );
|
||||||
|
|
||||||
await editor.updateSelection(selection);
|
// await editor.updateSelection(selection);
|
||||||
|
|
||||||
editor.editorState
|
// editor.editorState
|
||||||
.formatText(null, {BuiltInAttributeKey.bold: true}, path: [0]);
|
// .formatText(null, {BuiltInAttributeKey.bold: true}, path: [0]);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
final textNode = editor.editorState.getTextNode(path: [0]);
|
// final textNode = editor.editorState.getTextNode(path: [0]);
|
||||||
final textInsert = textNode.delta.first as TextInsert;
|
// final textInsert = textNode.delta.first as TextInsert;
|
||||||
|
|
||||||
expect(textInsert.text, 'Hello');
|
// expect(textInsert.text, 'Hello');
|
||||||
expect(textInsert.attributes?[BuiltInAttributeKey.bold], true);
|
// expect(textInsert.attributes?[BuiltInAttributeKey.bold], true);
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('formatTextWithBuiltInAttribute w/ Partial Style Key',
|
// testWidgets('formatTextWithBuiltInAttribute w/ Partial Style Key',
|
||||||
(tester) async {
|
// (tester) async {
|
||||||
final editor = tester.editor..insertTextNode('Hello');
|
// final editor = tester.editor..insertTextNode('Hello');
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
final selection = Selection(
|
// final selection = Selection(
|
||||||
start: Position(path: [0]),
|
// start: Position(path: [0]),
|
||||||
end: Position(path: [0], offset: 5),
|
// end: Position(path: [0], offset: 5),
|
||||||
);
|
// );
|
||||||
|
|
||||||
await editor.updateSelection(selection);
|
// await editor.updateSelection(selection);
|
||||||
|
|
||||||
editor.editorState.formatTextWithBuiltInAttribute(
|
// editor.editorState.formatTextWithBuiltInAttribute(
|
||||||
BuiltInAttributeKey.underline,
|
// BuiltInAttributeKey.underline,
|
||||||
{BuiltInAttributeKey.underline: true},
|
// {BuiltInAttributeKey.underline: true},
|
||||||
path: [0],
|
// path: [0],
|
||||||
);
|
// );
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
final textNode = editor.editorState.getTextNode(path: [0]);
|
// final textNode = editor.editorState.getTextNode(path: [0]);
|
||||||
final textInsert = textNode.delta.first as TextInsert;
|
// final textInsert = textNode.delta.first as TextInsert;
|
||||||
|
|
||||||
expect(textInsert.text, 'Hello');
|
// expect(textInsert.text, 'Hello');
|
||||||
expect(textInsert.attributes?[BuiltInAttributeKey.underline], true);
|
// expect(textInsert.attributes?[BuiltInAttributeKey.underline], true);
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('formatTextWithBuiltInAttribute w/ Global Style Key',
|
// testWidgets('formatTextWithBuiltInAttribute w/ Global Style Key',
|
||||||
(tester) async {
|
// (tester) async {
|
||||||
final editor = tester.editor
|
// final editor = tester.editor
|
||||||
..insertTextNode(
|
// ..insertTextNode(
|
||||||
'Hello',
|
// 'Hello',
|
||||||
|
|
||||||
/// Formatting global style over another global style,
|
// /// Formatting global style over another global style,
|
||||||
/// will remove the existing one before adding the new one
|
// /// will remove the existing one before adding the new one
|
||||||
attributes: {BuiltInAttributeKey.checkbox: true},
|
// attributes: {BuiltInAttributeKey.checkbox: true},
|
||||||
);
|
// );
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
editor.editorState.formatTextWithBuiltInAttribute(
|
// editor.editorState.formatTextWithBuiltInAttribute(
|
||||||
BuiltInAttributeKey.heading,
|
// BuiltInAttributeKey.heading,
|
||||||
{BuiltInAttributeKey.heading: BuiltInAttributeKey.h1},
|
// {BuiltInAttributeKey.heading: BuiltInAttributeKey.h1},
|
||||||
path: [0],
|
// path: [0],
|
||||||
);
|
// );
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
final textNode = editor.editorState.getTextNode(path: [0]);
|
// final textNode = editor.editorState.getTextNode(path: [0]);
|
||||||
final textInsert = textNode.delta.first as TextInsert;
|
// final textInsert = textNode.delta.first as TextInsert;
|
||||||
|
|
||||||
expect(textInsert.text, 'Hello');
|
// expect(textInsert.text, 'Hello');
|
||||||
expect(textNode.attributes.heading, BuiltInAttributeKey.h1);
|
// expect(textNode.attributes.heading, BuiltInAttributeKey.h1);
|
||||||
expect(textNode.attributes['subtype'], BuiltInAttributeKey.heading);
|
// expect(textNode.attributes['subtype'], BuiltInAttributeKey.heading);
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('formatTextToCheckbox', (tester) async {
|
// testWidgets('formatTextToCheckbox', (tester) async {
|
||||||
final editor = tester.editor..insertTextNode('TextNode to Checkbox');
|
// final editor = tester.editor..insertTextNode('TextNode to Checkbox');
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
editor.editorState.formatTextToCheckbox(false, path: [0]);
|
// editor.editorState.formatTextToCheckbox(false, path: [0]);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
final checkboxNode = editor.editorState.getNode(path: [0]);
|
// final checkboxNode = editor.editorState.getNode(path: [0]);
|
||||||
|
|
||||||
expect(checkboxNode.attributes.check, false);
|
// expect(checkboxNode.attributes.check, false);
|
||||||
expect(checkboxNode.attributes['subtype'], BuiltInAttributeKey.checkbox);
|
// expect(checkboxNode.attributes['subtype'], BuiltInAttributeKey.checkbox);
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('formatLinkInText', (tester) async {
|
// testWidgets('formatLinkInText', (tester) async {
|
||||||
const href = "https://appflowy.io/";
|
// const href = "https://appflowy.io/";
|
||||||
|
|
||||||
final editor = tester.editor..insertTextNode('TextNode to Link');
|
// final editor = tester.editor..insertTextNode('TextNode to Link');
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
final selection = Selection(
|
// final selection = Selection(
|
||||||
start: Position(path: [0]),
|
// start: Position(path: [0]),
|
||||||
end: Position(path: [0], offset: 5),
|
// end: Position(path: [0], offset: 5),
|
||||||
);
|
// );
|
||||||
|
|
||||||
await editor.updateSelection(selection);
|
// await editor.updateSelection(selection);
|
||||||
|
|
||||||
editor.editorState.formatLinkInText(href, path: [0]);
|
// editor.editorState.formatLinkInText(href, path: [0]);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
final textNode = editor.editorState.getTextNode(path: [0]);
|
// final textNode = editor.editorState.getTextNode(path: [0]);
|
||||||
final textInsert = textNode.delta.first as TextInsert;
|
// final textInsert = textNode.delta.first as TextInsert;
|
||||||
|
|
||||||
expect(textInsert.attributes?[BuiltInAttributeKey.href], href);
|
// expect(textInsert.attributes?[BuiltInAttributeKey.href], href);
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('insertNewLine', (tester) async {
|
// testWidgets('insertNewLine', (tester) async {
|
||||||
final editor = tester.editor;
|
// final editor = tester.editor;
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
expect(editor.documentLength, 0);
|
// expect(editor.documentLength, 0);
|
||||||
|
|
||||||
editor.editorState.insertNewLine(path: [0]);
|
// editor.editorState.insertNewLine(path: [0]);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(editor.documentLength, 1);
|
// expect(editor.documentLength, 1);
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('insertNewLine without path', (tester) async {
|
// testWidgets('insertNewLine without path', (tester) async {
|
||||||
final editor = tester.editor..insertTextNode('Hello World');
|
// final editor = tester.editor..insertTextNode('Hello World');
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
expect(editor.documentLength, 1);
|
// expect(editor.documentLength, 1);
|
||||||
|
|
||||||
final selection = Selection(
|
// final selection = Selection(
|
||||||
start: Position(path: [0], offset: 5),
|
// start: Position(path: [0], offset: 5),
|
||||||
end: Position(path: [0], offset: 5),
|
// end: Position(path: [0], offset: 5),
|
||||||
);
|
// );
|
||||||
|
|
||||||
await editor.updateSelection(selection);
|
// await editor.updateSelection(selection);
|
||||||
|
|
||||||
editor.editorState.insertNewLine(path: null);
|
// editor.editorState.insertNewLine(path: null);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(editor.documentLength, 2);
|
// expect(editor.documentLength, 2);
|
||||||
|
|
||||||
final textNode = editor.editorState.getTextNode(path: [0]);
|
// final textNode = editor.editorState.getTextNode(path: [0]);
|
||||||
final textInsert = textNode.delta.first as TextInsert;
|
// final textInsert = textNode.delta.first as TextInsert;
|
||||||
|
|
||||||
expect(textInsert.text, 'Hello World');
|
// expect(textInsert.text, 'Hello World');
|
||||||
});
|
// });
|
||||||
|
|
||||||
testWidgets('insertNewLineAtCurrentSelection', (tester) async {
|
// testWidgets('insertNewLineAtCurrentSelection', (tester) async {
|
||||||
final editor = tester.editor..insertTextNode('HelloWorld');
|
// final editor = tester.editor..insertTextNode('HelloWorld');
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
|
|
||||||
final selection = Selection(
|
// final selection = Selection(
|
||||||
start: Position(path: [0], offset: 5),
|
// start: Position(path: [0], offset: 5),
|
||||||
end: Position(path: [0], offset: 5),
|
// end: Position(path: [0], offset: 5),
|
||||||
);
|
// );
|
||||||
|
|
||||||
await editor.updateSelection(selection);
|
// await editor.updateSelection(selection);
|
||||||
|
|
||||||
expect(editor.documentLength, 1);
|
// expect(editor.documentLength, 1);
|
||||||
|
|
||||||
editor.editorState.insertNewLineAtCurrentSelection();
|
// editor.editorState.insertNewLineAtCurrentSelection();
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(editor.documentLength, 2);
|
// expect(editor.documentLength, 2);
|
||||||
|
|
||||||
final firstTextNode = editor.editorState.getTextNode(path: [0]);
|
// final firstTextNode = editor.editorState.getTextNode(path: [0]);
|
||||||
final firstTextInsert = firstTextNode.delta.first as TextInsert;
|
// final firstTextInsert = firstTextNode.delta.first as TextInsert;
|
||||||
expect(firstTextInsert.text, 'Hello');
|
// expect(firstTextInsert.text, 'Hello');
|
||||||
|
|
||||||
final secondTextNode = editor.editorState.getTextNode(path: [1]);
|
// final secondTextNode = editor.editorState.getTextNode(path: [1]);
|
||||||
final secondTextInsert = secondTextNode.delta.first as TextInsert;
|
// final secondTextInsert = secondTextNode.delta.first as TextInsert;
|
||||||
|
|
||||||
expect(secondTextInsert.text, 'World');
|
// expect(secondTextInsert.text, 'World');
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -177,4 +177,67 @@ void main() async {
|
||||||
expect(editorState.getNodeAtPath([1, 0])?.delta?.toPlainText(), text);
|
expect(editorState.getNodeAtPath([1, 0])?.delta?.toPlainText(), text);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('insertText', () {
|
||||||
|
const text = 'Welcome to AppFlowy Editor 🔥!';
|
||||||
|
|
||||||
|
/// Before
|
||||||
|
/// |
|
||||||
|
/// Welcome to AppFlowy Editor 🔥!
|
||||||
|
///
|
||||||
|
/// After
|
||||||
|
/// Hello|
|
||||||
|
/// Welcome to AppFlowy Editor 🔥!
|
||||||
|
test('insertText', () async {
|
||||||
|
final document = Document.blank()
|
||||||
|
.addParagraph(
|
||||||
|
initialText: '',
|
||||||
|
)
|
||||||
|
.addParagraph(
|
||||||
|
initialText: text,
|
||||||
|
decorator: (index, node) {
|
||||||
|
node.addParagraph(
|
||||||
|
initialText: text,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
final editorState = EditorState(document: document);
|
||||||
|
|
||||||
|
const hello = 'Hello';
|
||||||
|
await editorState.insertText(0, hello, path: [0]);
|
||||||
|
|
||||||
|
expect(editorState.getNodeAtPath([0])?.delta?.toPlainText(), hello);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('insertTextAtCurrentSelection', () async {
|
||||||
|
final document = Document.blank()
|
||||||
|
.addParagraph(
|
||||||
|
initialText: '',
|
||||||
|
)
|
||||||
|
.addParagraph(
|
||||||
|
initialText: text,
|
||||||
|
decorator: (index, node) {
|
||||||
|
node.addParagraph(
|
||||||
|
initialText: text,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
final selection = Selection.collapsed(
|
||||||
|
Position(path: [0], offset: 0),
|
||||||
|
);
|
||||||
|
final editorState = EditorState(document: document);
|
||||||
|
editorState.selection = selection;
|
||||||
|
|
||||||
|
const hello = 'Hello';
|
||||||
|
await editorState.insertTextAtCurrentSelection(hello);
|
||||||
|
|
||||||
|
expect(editorState.getNodeAtPath([0])?.delta?.toPlainText(), hello);
|
||||||
|
expect(
|
||||||
|
editorState.selection,
|
||||||
|
Selection.collapsed(
|
||||||
|
Position(path: [0], offset: hello.length),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,133 +1,133 @@
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
// import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:flutter/services.dart';
|
// import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
// import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import '../../infra/test_editor.dart';
|
// import '../../infra/test_editor.dart';
|
||||||
|
|
||||||
void main() async {
|
// void main() async {
|
||||||
setUpAll(() {
|
// setUpAll(() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
// TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
});
|
// });
|
||||||
|
|
||||||
group('checkbox_text_handler.dart', () {
|
// group('checkbox_text_handler.dart', () {
|
||||||
testWidgets('Click checkbox icon', (tester) async {
|
// testWidgets('Click checkbox icon', (tester) async {
|
||||||
// Before
|
// // Before
|
||||||
//
|
// //
|
||||||
// [BIUS]Welcome to Appflowy 😁[BIUS]
|
// // [BIUS]Welcome to Appflowy 😁[BIUS]
|
||||||
//
|
// //
|
||||||
// After
|
// // After
|
||||||
//
|
// //
|
||||||
// [checkbox]Welcome to Appflowy 😁
|
// // [checkbox]Welcome to Appflowy 😁
|
||||||
//
|
// //
|
||||||
const text = 'Welcome to Appflowy 😁';
|
// const text = 'Welcome to Appflowy 😁';
|
||||||
final editor = tester.editor
|
// final editor = tester.editor
|
||||||
..insertTextNode(
|
// ..insertTextNode(
|
||||||
'',
|
// '',
|
||||||
attributes: {
|
// attributes: {
|
||||||
BuiltInAttributeKey.subtype: BuiltInAttributeKey.checkbox,
|
// BuiltInAttributeKey.subtype: BuiltInAttributeKey.checkbox,
|
||||||
BuiltInAttributeKey.checkbox: false,
|
// BuiltInAttributeKey.checkbox: false,
|
||||||
},
|
// },
|
||||||
delta: Delta(
|
// delta: Delta(
|
||||||
operations: [
|
// operations: [
|
||||||
TextInsert(
|
// TextInsert(
|
||||||
text,
|
// text,
|
||||||
attributes: {
|
// attributes: {
|
||||||
BuiltInAttributeKey.bold: true,
|
// BuiltInAttributeKey.bold: true,
|
||||||
BuiltInAttributeKey.italic: true,
|
// BuiltInAttributeKey.italic: true,
|
||||||
BuiltInAttributeKey.underline: true,
|
// BuiltInAttributeKey.underline: true,
|
||||||
BuiltInAttributeKey.strikethrough: true,
|
// BuiltInAttributeKey.strikethrough: true,
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
await editor.updateSelection(
|
// await editor.updateSelection(
|
||||||
Selection.single(path: [0], startOffset: 0),
|
// Selection.single(path: [0], startOffset: 0),
|
||||||
);
|
// );
|
||||||
|
|
||||||
final selection =
|
// final selection =
|
||||||
Selection.single(path: [0], startOffset: 0, endOffset: text.length);
|
// Selection.single(path: [0], startOffset: 0, endOffset: text.length);
|
||||||
var node = editor.nodeAtPath([0]) as TextNode;
|
// var node = editor.nodeAtPath([0]) as TextNode;
|
||||||
var state = node.key.currentState as DefaultSelectable;
|
// var state = node.key.currentState as DefaultSelectable;
|
||||||
var checkboxWidget = find.byKey(state.iconKey!);
|
// var checkboxWidget = find.byKey(state.iconKey!);
|
||||||
await tester.tap(checkboxWidget);
|
// await tester.tap(checkboxWidget);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(node.attributes.check, true);
|
// expect(node.attributes.check, true);
|
||||||
|
|
||||||
expect(node.allSatisfyBoldInSelection(selection), true);
|
// expect(node.allSatisfyBoldInSelection(selection), true);
|
||||||
expect(node.allSatisfyItalicInSelection(selection), true);
|
// expect(node.allSatisfyItalicInSelection(selection), true);
|
||||||
expect(node.allSatisfyUnderlineInSelection(selection), true);
|
// expect(node.allSatisfyUnderlineInSelection(selection), true);
|
||||||
expect(node.allSatisfyStrikethroughInSelection(selection), true);
|
// expect(node.allSatisfyStrikethroughInSelection(selection), true);
|
||||||
|
|
||||||
node = editor.nodeAtPath([0]) as TextNode;
|
// node = editor.nodeAtPath([0]) as TextNode;
|
||||||
state = node.key.currentState as DefaultSelectable;
|
// state = node.key.currentState as DefaultSelectable;
|
||||||
await tester.ensureVisible(find.byKey(state.iconKey!));
|
// await tester.ensureVisible(find.byKey(state.iconKey!));
|
||||||
await tester.tap(find.byKey(state.iconKey!));
|
// await tester.tap(find.byKey(state.iconKey!));
|
||||||
await tester.pump();
|
// await tester.pump();
|
||||||
|
|
||||||
expect(node.attributes.check, false);
|
// expect(node.attributes.check, false);
|
||||||
expect(node.allSatisfyBoldInSelection(selection), true);
|
// expect(node.allSatisfyBoldInSelection(selection), true);
|
||||||
expect(node.allSatisfyItalicInSelection(selection), true);
|
// expect(node.allSatisfyItalicInSelection(selection), true);
|
||||||
expect(node.allSatisfyUnderlineInSelection(selection), true);
|
// expect(node.allSatisfyUnderlineInSelection(selection), true);
|
||||||
expect(node.allSatisfyStrikethroughInSelection(selection), true);
|
// expect(node.allSatisfyStrikethroughInSelection(selection), true);
|
||||||
});
|
// });
|
||||||
|
|
||||||
// https://github.com/AppFlowy-IO/AppFlowy/issues/1763
|
// // https://github.com/AppFlowy-IO/AppFlowy/issues/1763
|
||||||
// // [Bug] Mouse unable to click a certain area #1763
|
// // // [Bug] Mouse unable to click a certain area #1763
|
||||||
testWidgets('insert a new checkbox after an existing checkbox',
|
// testWidgets('insert a new checkbox after an existing checkbox',
|
||||||
(tester) async {
|
// (tester) async {
|
||||||
// Before
|
// // Before
|
||||||
//
|
// //
|
||||||
// [checkbox] Welcome to Appflowy 😁
|
// // [checkbox] Welcome to Appflowy 😁
|
||||||
//
|
// //
|
||||||
// After
|
// // After
|
||||||
//
|
// //
|
||||||
// [checkbox] Welcome to Appflowy 😁
|
// // [checkbox] Welcome to Appflowy 😁
|
||||||
//
|
// //
|
||||||
// [checkbox] Welcome to Appflowy 😁
|
// // [checkbox] Welcome to Appflowy 😁
|
||||||
//
|
// //
|
||||||
const text = 'Welcome to Appflowy 😁';
|
// const text = 'Welcome to Appflowy 😁';
|
||||||
final editor = tester.editor
|
// final editor = tester.editor
|
||||||
..insertTextNode(
|
// ..insertTextNode(
|
||||||
'',
|
// '',
|
||||||
attributes: {
|
// attributes: {
|
||||||
BuiltInAttributeKey.subtype: BuiltInAttributeKey.checkbox,
|
// BuiltInAttributeKey.subtype: BuiltInAttributeKey.checkbox,
|
||||||
BuiltInAttributeKey.checkbox: false,
|
// BuiltInAttributeKey.checkbox: false,
|
||||||
},
|
// },
|
||||||
delta: Delta(
|
// delta: Delta(
|
||||||
operations: [TextInsert(text)],
|
// operations: [TextInsert(text)],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
await editor.startTesting();
|
// await editor.startTesting();
|
||||||
await editor.updateSelection(
|
// await editor.updateSelection(
|
||||||
Selection.single(path: [0], startOffset: text.length),
|
// Selection.single(path: [0], startOffset: text.length),
|
||||||
);
|
// );
|
||||||
|
|
||||||
await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
|
// await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
|
||||||
await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
|
// await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
|
||||||
await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
|
// await editor.pressLogicKey(key: LogicalKeyboardKey.enter);
|
||||||
|
|
||||||
expect(
|
// expect(
|
||||||
editor.documentSelection,
|
// editor.documentSelection,
|
||||||
Selection.single(path: [2], startOffset: 0),
|
// Selection.single(path: [2], startOffset: 0),
|
||||||
);
|
// );
|
||||||
|
|
||||||
await editor.pressLogicKey(key: LogicalKeyboardKey.slash);
|
// await editor.pressLogicKey(key: LogicalKeyboardKey.slash);
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 1000));
|
// await tester.pumpAndSettle(const Duration(milliseconds: 1000));
|
||||||
|
|
||||||
expect(
|
// expect(
|
||||||
find.byType(SelectionMenuWidget, skipOffstage: false),
|
// find.byType(SelectionMenuWidget, skipOffstage: false),
|
||||||
findsOneWidget,
|
// findsOneWidget,
|
||||||
);
|
// );
|
||||||
|
|
||||||
final checkboxMenuItem = find.text('Checkbox', findRichText: true);
|
// final checkboxMenuItem = find.text('Checkbox', findRichText: true);
|
||||||
await tester.tap(checkboxMenuItem);
|
// await tester.tap(checkboxMenuItem);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
|
|
||||||
final checkboxNode = editor.nodeAtPath([2]) as TextNode;
|
// final checkboxNode = editor.nodeAtPath([2]) as TextNode;
|
||||||
expect(checkboxNode.subtype, BuiltInAttributeKey.checkbox);
|
// expect(checkboxNode.subtype, BuiltInAttributeKey.checkbox);
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue