Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions super_editor/lib/src/default_editor/common_editor_operations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ class CommonEditorOperations {
}) {
DocumentPosition? position;
if (findNearestPosition) {
position = documentLayoutResolver().getDocumentPositionNearestToOffset(documentOffset);
position = documentLayoutResolver()
.getDocumentPositionNearestToOffset(documentOffset);
} else {
position = documentLayoutResolver().getDocumentPositionAtOffset(documentOffset);
}
Expand Down Expand Up @@ -2510,17 +2511,31 @@ class PasteEditorCommand extends EditCommand {
]);
}

// Place the caret at the end of the pasted content.
final pastedNode = document.getNodeById(previousNode.id)!;
// ^ re-query the node where we pasted content because nodes are immutable.

late DocumentPosition documentPositionAfterPaste;
if (parsedContent.length > 1) {
// Place the caret at the end of the pasted content.
final pastedNode = document.getNodeById(previousNode.id)!;
// ^ re-query the node where we pasted content because nodes are immutable.
documentPositionAfterPaste = DocumentPosition(
nodeId: pastedNode.id,
nodePosition: pastedNode.endPosition,
);
} else {
// The user only pasted content without any newlines in it. Place the
// caret in the existing node at the end of the pasted text. This is
// guaranteed to be a TextNode.
documentPositionAfterPaste = DocumentPosition(
nodeId: _pastePosition.nodeId,
nodePosition: TextNodePosition(
offset:
pasteTextOffset + (_parsedContent!.first as TextNode).text.length,
),
);
}
executor.executeCommand(
ChangeSelectionCommand(
DocumentSelection.collapsed(
position: DocumentPosition(
nodeId: pastedNode.id,
nodePosition: pastedNode.endPosition,
),
position: documentPositionAfterPaste,
),
SelectionChangeType.insertContent,
SelectionReason.userInteraction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:super_editor/super_editor.dart';
import 'package:super_editor/super_editor_test.dart';

import '../test_runners.dart';
import '../test_tools.dart';
import 'supereditor_test_tools.dart';

void main() {
Expand Down Expand Up @@ -36,6 +37,56 @@ void main() {
expect(SuperEditorInspector.findTextInComponent(nodeId).toPlainText(), "Pasted text: This was pasted here");
});

testAllInputsOnDesktop(
'pastes some text in the middle of a paragraph, correctly placing the caret at the end of the pasted text',
(
tester, {
required TextInputSource inputSource,
}) async {
final testContext = await tester //
.createDocument()
.withSingleEmptyParagraph()
.withInputSource(inputSource)
.pump();

// Place the caret at the empty paragraph.
await tester.placeCaretInParagraph('1', 0);

// Type some text.
switch (inputSource) {
case TextInputSource.keyboard:
await tester.typeKeyboardText('This is a paragraph');
case TextInputSource.ime:
await tester.typeImeText('This is a paragraph');
}

// Place the cursor somewhere in the middle of the text.
await tester.placeCaretInParagraph('1', 8);

// Simulate pasting multiple lines.
tester
..simulateClipboard()
..setSimulatedClipboardContent('some content in ');
if (defaultTargetPlatform == TargetPlatform.macOS) {
await tester.pressCmdV();
} else {
await tester.pressCtlV();
}

// Ensure the text is correctly pasted and the caret is placed at the
// end of the pasted text.
final doc = testContext.document;
expect(doc.nodeCount, 1);
expect((doc.getNodeAt(0)! as ParagraphNode).text.toPlainText(), 'This is some content in a paragraph');
expect(testContext.composer.selection, selectionEquivalentTo(const DocumentSelection.collapsed(
position: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 24),
),
)));
});


testWidgetsOnApple('pastes within a list item', (tester) async {
await tester //
.createDocument()
Expand Down
Loading