|
@@ -4,6 +4,33 @@ import 'package:appflowy_editor/src/document/node_iterator.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:rich_clipboard/rich_clipboard.dart';
|
|
import 'package:rich_clipboard/rich_clipboard.dart';
|
|
|
|
|
|
|
|
+int _textLengthOfNode(Node node) {
|
|
|
|
+ if (node is TextNode) {
|
|
|
|
+ return node.delta.length;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Selection _computeSelectionAfterPasteMultipleNodes(
|
|
|
|
+ EditorState editorState, List<Node> nodes) {
|
|
|
|
+ final currentSelection = editorState.cursorSelection!;
|
|
|
|
+ final currentCursor = currentSelection.start;
|
|
|
|
+ final currentNode = editorState.document.nodeAtPath(currentCursor.path)!;
|
|
|
|
+ final currentPath = [...currentCursor.path];
|
|
|
|
+ if (currentNode is TextNode) {
|
|
|
|
+ currentPath[currentPath.length - 1] += nodes.length;
|
|
|
|
+ int lenOfLastNode = _textLengthOfNode(nodes.last);
|
|
|
|
+ return Selection.collapsed(
|
|
|
|
+ Position(path: currentPath, offset: lenOfLastNode));
|
|
|
|
+ } else {
|
|
|
|
+ currentPath[currentPath.length - 1] += nodes.length;
|
|
|
|
+ int lenOfLastNode = _textLengthOfNode(nodes.last);
|
|
|
|
+ return Selection.collapsed(
|
|
|
|
+ Position(path: currentPath, offset: lenOfLastNode));
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
_handleCopy(EditorState editorState) async {
|
|
_handleCopy(EditorState editorState) async {
|
|
final selection = editorState.cursorSelection?.normalize;
|
|
final selection = editorState.cursorSelection?.normalize;
|
|
if (selection == null || selection.isCollapsed) {
|
|
if (selection == null || selection.isCollapsed) {
|
|
@@ -80,6 +107,9 @@ _pasteHTML(EditorState editorState, String html) {
|
|
|
|
|
|
_pasteMultipleLinesInText(
|
|
_pasteMultipleLinesInText(
|
|
EditorState editorState, List<int> path, int offset, List<Node> nodes) {
|
|
EditorState editorState, List<int> path, int offset, List<Node> nodes) {
|
|
|
|
+ final afterSelection =
|
|
|
|
+ _computeSelectionAfterPasteMultipleNodes(editorState, nodes);
|
|
|
|
+
|
|
final tb = TransactionBuilder(editorState);
|
|
final tb = TransactionBuilder(editorState);
|
|
|
|
|
|
final firstNode = nodes[0];
|
|
final firstNode = nodes[0];
|
|
@@ -112,6 +142,7 @@ _pasteMultipleLinesInText(
|
|
tailNodes.add(TextNode(type: "text", delta: remain));
|
|
tailNodes.add(TextNode(type: "text", delta: remain));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ tb.setAfterSelection(afterSelection);
|
|
tb.insertNodes(path, tailNodes);
|
|
tb.insertNodes(path, tailNodes);
|
|
tb.commit();
|
|
tb.commit();
|
|
return;
|
|
return;
|
|
@@ -219,16 +250,21 @@ _handlePastePlainText(EditorState editorState, String plainText) {
|
|
final insertedLineSuffix = node.delta.slice(beginOffset);
|
|
final insertedLineSuffix = node.delta.slice(beginOffset);
|
|
|
|
|
|
path[path.length - 1]++;
|
|
path[path.length - 1]++;
|
|
- var index = 0;
|
|
|
|
final tb = TransactionBuilder(editorState);
|
|
final tb = TransactionBuilder(editorState);
|
|
- final nodes = remains.map((e) {
|
|
|
|
- if (index++ == remains.length - 1) {
|
|
|
|
- return TextNode(
|
|
|
|
- type: "text",
|
|
|
|
- delta: _lineContentToDelta(e)..addAll(insertedLineSuffix));
|
|
|
|
- }
|
|
|
|
- return TextNode(type: "text", delta: _lineContentToDelta(e));
|
|
|
|
- }).toList();
|
|
|
|
|
|
+ final List<TextNode> nodes = remains
|
|
|
|
+ .map((e) => TextNode(type: "text", delta: _lineContentToDelta(e)))
|
|
|
|
+ .toList();
|
|
|
|
+
|
|
|
|
+ final afterSelection =
|
|
|
|
+ _computeSelectionAfterPasteMultipleNodes(editorState, nodes);
|
|
|
|
+
|
|
|
|
+ // append remain text to the last line
|
|
|
|
+ if (nodes.isNotEmpty) {
|
|
|
|
+ final last = nodes.last;
|
|
|
|
+ nodes[nodes.length - 1] =
|
|
|
|
+ TextNode(type: "text", delta: last.delta..addAll(insertedLineSuffix));
|
|
|
|
+ }
|
|
|
|
+
|
|
// insert first line
|
|
// insert first line
|
|
tb.textEdit(
|
|
tb.textEdit(
|
|
node,
|
|
node,
|
|
@@ -238,11 +274,8 @@ _handlePastePlainText(EditorState editorState, String plainText) {
|
|
..delete(node.delta.length - beginOffset));
|
|
..delete(node.delta.length - beginOffset));
|
|
// insert remains
|
|
// insert remains
|
|
tb.insertNodes(path, nodes);
|
|
tb.insertNodes(path, nodes);
|
|
|
|
+ tb.setAfterSelection(afterSelection);
|
|
tb.commit();
|
|
tb.commit();
|
|
-
|
|
|
|
- // fixme: don't set the cursor manually
|
|
|
|
- editorState.updateCursorSelection(Selection.collapsed(
|
|
|
|
- Position(path: nodes.last.path, offset: lines.last.length)));
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|