Skip to content

Commit

Permalink
Merge pull request AppFlowy-IO#14 from LucasXu0/fix_#10
Browse files Browse the repository at this point in the history
chore: fix some known issues
  • Loading branch information
LucasXu0 authored Mar 15, 2023
2 parents 495e085 + bdd5fa7 commit 58330cd
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 22 deletions.
1 change: 1 addition & 0 deletions lib/appflowy_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export 'src/render/rich_text/flowy_rich_text.dart';
export 'src/render/selection_menu/selection_menu_widget.dart';
export 'src/l10n/l10n.dart';
export 'src/render/style/plugin_styles.dart';
export 'src/render/style/editor_style.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';
Expand Down
5 changes: 4 additions & 1 deletion lib/src/commands/command_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ extension CommandExtension on EditorState {
Selection selection,
) {
List<String> res = [];
if (!selection.isCollapsed) {
if (selection.isSingle) {
final plainText = textNodes.first.toPlainText();
res.add(plainText.substring(selection.startIndex, selection.endIndex));
} else if (!selection.isCollapsed) {
for (var i = 0; i < textNodes.length; i++) {
final plainText = textNodes[i].toPlainText();
if (i == 0) {
Expand Down
119 changes: 99 additions & 20 deletions lib/src/core/transform/transaction.dart
Original file line number Diff line number Diff line change
Expand Up @@ -264,19 +264,19 @@ extension TextTransaction on Transaction {
if (index != 0 && attributes == null) {
newAttributes =
textNode.delta.slice(max(index - 1, 0), index).first.attributes;
if (newAttributes != null) {
newAttributes = {...newAttributes}; // make a copy
} else {
newAttributes =
textNode.delta.slice(index, index + length).first.attributes;
if (newAttributes == null) {
final slicedDelta = textNode.delta.slice(index, index + length);
if (slicedDelta.isNotEmpty) {
newAttributes = slicedDelta.first.attributes;
}
}
}
updateText(
textNode,
Delta()
..retain(index)
..delete(length)
..insert(text, attributes: newAttributes),
..insert(text, attributes: {...newAttributes ?? {}}),
);
afterSelection = Selection.collapsed(
Position(
Expand All @@ -291,46 +291,125 @@ extension TextTransaction on Transaction {
Selection selection,
List<String> texts,
) {
if (textNodes.isEmpty) {
if (textNodes.isEmpty || texts.isEmpty) {
return;
}

if (selection.isSingle) {
assert(textNodes.length == 1 && texts.length == 1);
replaceText(
textNodes.first,
selection.startIndex,
selection.length,
texts.first,
);
} else {
if (textNodes.length == texts.length) {
final length = textNodes.length;
for (var i = 0; i < length; i++) {

if (length == 1) {
replaceText(
textNodes.first,
selection.startIndex,
selection.endIndex - selection.startIndex,
texts.first,
);
return;
}

for (var i = 0; i < textNodes.length; i++) {
final textNode = textNodes[i];
final text = texts[i];
if (i == 0) {
replaceText(
textNode,
selection.startIndex,
textNode.toPlainText().length,
text,
texts.first,
);
} else if (i == length - 1) {
replaceText(
textNode,
0,
selection.endIndex,
text,
texts.last,
);
} else {
replaceText(
textNode,
0,
textNode.toPlainText().length,
texts[i],
);
}
}
return;
}

if (textNodes.length > texts.length) {
final length = textNodes.length;
for (var i = 0; i < textNodes.length; i++) {
final textNode = textNodes[i];
if (i == 0) {
replaceText(
textNode,
selection.startIndex,
textNode.toPlainText().length,
texts.first,
);
} else if (i == length - 1) {
replaceText(
textNode,
0,
selection.endIndex,
texts.last,
);
} else {
if (i < texts.length - 1) {
replaceText(
textNode,
0,
textNode.toPlainText().length,
texts[i],
);
} else {
deleteNode(textNode);
}
}
}
afterSelection = null;
return;
}

if (textNodes.length < texts.length) {
final length = texts.length;
for (var i = 0; i < texts.length; i++) {
final text = texts[i];
if (i == 0) {
replaceText(
textNodes.first,
selection.startIndex,
textNodes.first.toPlainText().length,
text,
);
} else if (i == length - 1) {
replaceText(
textNodes.last,
0,
selection.endIndex,
text,
);
} else {
if (i < textNodes.length - 1) {
replaceText(
textNodes[i],
0,
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--;
}
insertNode(path, TextNode(delta: Delta()..insert(text)));
}
}
}
afterSelection = null;
return;
}
}
}
1 change: 1 addition & 0 deletions lib/src/service/keyboard_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class _AppFlowyKeyboardState extends State<AppFlowyKeyboard>
isFocus = false;
this.showCursor = showCursor;
_focusNode.unfocus(disposition: disposition);
_onFocusChange(false);
}

@override
Expand Down
36 changes: 35 additions & 1 deletion test/service/internal_key_event_handlers/slash_handler_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ void main() async {
});

group('slash_handler.dart', () {
testWidgets('Presses / to trigger selection menu', (tester) async {
testWidgets('Presses / to trigger selection menu in 0 index',
(tester) async {
const text = 'Welcome to Appflowy 😁';
const lines = 3;
final editor = tester.editor;
Expand Down Expand Up @@ -41,5 +42,38 @@ void main() async {
findsNothing,
);
});

testWidgets('Presses / to trigger selection menu in not 0 index',
(tester) async {
const text = 'Welcome to Appflowy 😁';
const lines = 3;
final editor = tester.editor;
for (var i = 0; i < lines; i++) {
editor.insertTextNode(text);
}
await editor.startTesting();
await editor.updateSelection(Selection.single(path: [1], startOffset: 5));
await editor.pressLogicKey(LogicalKeyboardKey.slash);

await tester.pumpAndSettle(const Duration(milliseconds: 1000));

expect(
find.byType(SelectionMenuWidget, skipOffstage: false),
findsOneWidget,
);

for (final item in defaultSelectionMenuItems) {
expect(find.text(item.name), findsOneWidget);
}

await editor.updateSelection(Selection.single(path: [1], startOffset: 0));

await tester.pumpAndSettle(const Duration(milliseconds: 200));

expect(
find.byType(SelectionMenuItemWidget, skipOffstage: false),
findsNothing,
);
});
});
}

0 comments on commit 58330cd

Please sign in to comment.