mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: bump version 0.3.0 (#3252)
This commit is contained in:
@ -52,6 +52,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
...codeBlockCommands,
|
||||
customCopyCommand,
|
||||
customPasteCommand,
|
||||
customCutCommand,
|
||||
...standardCommandShortcutEvents,
|
||||
];
|
||||
|
||||
|
@ -22,6 +22,7 @@ final inAppJsonFormat = CustomValueFormat<String>(
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onEncode: (value, platformType) => utf8.encode(value),
|
||||
);
|
||||
|
||||
class ClipboardServiceData {
|
||||
|
@ -0,0 +1,24 @@
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/editor_state_paste_node_extension.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// cut.
|
||||
///
|
||||
/// - support
|
||||
/// - desktop
|
||||
/// - web
|
||||
/// - mobile
|
||||
///
|
||||
final CommandShortcutEvent customCutCommand = CommandShortcutEvent(
|
||||
key: 'cut the selected content',
|
||||
command: 'ctrl+x',
|
||||
macOSCommand: 'cmd+x',
|
||||
handler: _cutCommandHandler,
|
||||
);
|
||||
|
||||
CommandShortcutEventHandler _cutCommandHandler = (editorState) {
|
||||
customCopyCommand.execute(editorState);
|
||||
editorState.deleteSelectionIfNeeded();
|
||||
return KeyEventResult.handled;
|
||||
};
|
@ -14,25 +14,29 @@ extension PasteNodes on EditorState {
|
||||
final transaction = this.transaction;
|
||||
final insertedDelta = insertedNode.delta;
|
||||
// if the node is empty, replace it with the inserted node.
|
||||
if (delta.isEmpty || insertedDelta == null) {
|
||||
if (delta.isEmpty) {
|
||||
transaction.insertNode(
|
||||
selection.end.path.next,
|
||||
node.copyWith(
|
||||
type: node.type,
|
||||
attributes: {
|
||||
...node.attributes,
|
||||
...insertedNode.attributes,
|
||||
},
|
||||
),
|
||||
insertedDelta == null
|
||||
? node.copyWith(
|
||||
type: node.type,
|
||||
attributes: {
|
||||
...node.attributes,
|
||||
...insertedNode.attributes,
|
||||
},
|
||||
)
|
||||
: insertedNode,
|
||||
);
|
||||
transaction.deleteNode(node);
|
||||
final path = calculatePath(selection.end.path, [insertedNode]);
|
||||
final offset = calculateLength([insertedNode]);
|
||||
transaction.afterSelection = Selection.collapsed(
|
||||
Position(
|
||||
path: selection.end.path,
|
||||
offset: insertedDelta?.length ?? 0,
|
||||
path: path,
|
||||
offset: offset,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
} else if (insertedDelta != null) {
|
||||
// if the node is not empty, insert the delta from inserted node after the selection.
|
||||
transaction.insertTextDelta(node, selection.endIndex, insertedDelta);
|
||||
}
|
||||
@ -53,7 +57,7 @@ extension PasteNodes on EditorState {
|
||||
}
|
||||
final transaction = this.transaction;
|
||||
|
||||
final lastNodeLength = nodes.last.delta?.length ?? 0;
|
||||
final lastNodeLength = calculateLength(nodes);
|
||||
// merge the current selected node delta into the nodes.
|
||||
if (delta.isNotEmpty) {
|
||||
nodes.first.insertDelta(
|
||||
@ -86,13 +90,10 @@ extension PasteNodes on EditorState {
|
||||
// delete the current node.
|
||||
transaction.deleteNode(node);
|
||||
|
||||
var path = selection.end.path;
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
path = path.next;
|
||||
}
|
||||
final path = calculatePath(selection.start.path, nodes);
|
||||
transaction.afterSelection = Selection.collapsed(
|
||||
Position(
|
||||
path: path.previous, // because a node is deleted.
|
||||
path: path,
|
||||
offset: lastNodeLength,
|
||||
),
|
||||
);
|
||||
@ -116,6 +117,28 @@ extension PasteNodes on EditorState {
|
||||
assert(this.selection?.isCollapsed == true);
|
||||
return this.selection;
|
||||
}
|
||||
|
||||
Path calculatePath(Path start, List<Node> nodes) {
|
||||
var path = start;
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
path = path.next;
|
||||
}
|
||||
path = path.previous;
|
||||
if (nodes.last.children.isNotEmpty) {
|
||||
return [
|
||||
...path,
|
||||
...calculatePath([0], nodes.last.children.toList())
|
||||
];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
int calculateLength(List<Node> nodes) {
|
||||
if (nodes.last.children.isNotEmpty) {
|
||||
return calculateLength(nodes.last.children.toList());
|
||||
}
|
||||
return nodes.last.delta?.length ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
extension on Node {
|
||||
|
@ -4,6 +4,7 @@ export 'callout/callout_block_component.dart';
|
||||
export 'code_block/code_block_component.dart';
|
||||
export 'code_block/code_block_shortcut_event.dart';
|
||||
export 'copy_and_paste/custom_copy_command.dart';
|
||||
export 'copy_and_paste/custom_cut_command.dart';
|
||||
export 'copy_and_paste/custom_paste_command.dart';
|
||||
export 'database/database_view_block_component.dart';
|
||||
export 'database/inline_database_menu_item.dart';
|
||||
|
Reference in New Issue
Block a user