Skip to content

Commit

Permalink
Merge branch 'main' into feat-zhiya
Browse files Browse the repository at this point in the history
* main: (48 commits)
  chore: comment suggesting use of deprecated method (AppFlowy-IO#417)
  fix: replace matches on the same node (AppFlowy-IO#418)
  fix: rect of the divider block is incorrect (AppFlowy-IO#415)
  chore: bump version 1.2.4 (AppFlowy-IO#414)
  feat: migrate copy paste command from AppFlowy (AppFlowy-IO#413)
  feat: added support for custom parser for markdown to document (AppFlowy-IO#403)
  feat: improve CJK IME support
  feat: add support for context menu items to the editor
  fix: refactor _onSelectionChange method to update _showPlaceholder state more efficiently
  fix: typo (AppFlowy-IO#408)
  Fix selected nodes (AppFlowy-IO#407)
  fix: miss the nested node when copying (AppFlowy-IO#406)
  feat: skip whitespace between words while navigating with CTRL+ARROW keys (AppFlowy-IO#363)
  feat: double hyphen to em dash (AppFlowy-IO#395)
  fix: add variable to hold editor selection for colour menu (AppFlowy-IO#400)
  test: open link command
  refactor: show link command test
  refactor: show link menu command
  feat: open link command
  fix: placeholder on paragraph when selected (AppFlowy-IO#390)
  ...
  • Loading branch information
q200892907 committed Aug 28, 2023
2 parents 0dad902 + c722ec1 commit 4e2b29f
Show file tree
Hide file tree
Showing 158 changed files with 5,080 additions and 1,260 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 1.2.4
* feat: improve CJK IME support by @LucasXu0 in ([#412](https://github.com/AppFlowy-IO/appflowy-editor/pull/412))
* feat: implement find dialog by @MayurSMahajan in ([#106](https://github.com/AppFlowy-IO/appflowy-editor/pull/106))
* feat: improve functionality for pasting from html by @LucasXu0 in ([#391](https://github.com/AppFlowy-IO/appflowy-editor/pull/391))
* feat: placeholder on paragraph when selected by @Xazin in ([#390](https://github.com/AppFlowy-IO/appflowy-editor/pull/390))
* feat: double hyphen to em dash by @Xazin in ([#395](https://github.com/AppFlowy-IO/appflowy-editor/pull/395))
* feat: skip whitespace between words while navigating with CTRL+ARROW keys by @johansutrisno in ([#363](https://github.com/AppFlowy-IO/appflowy-editor/pull/363))
* feat: add support for context menu items to the editor by @LucasXu0 in ([#410](https://github.com/AppFlowy-IO/appflowy-editor/pull/410))
* feat: add support for custom parser for markdown to document by @Mukund-Tandon in ([#403](https://github.com/AppFlowy-IO/appflowy-editor/pull/403))
* fix: miss the nested node when copying by @LucasXu0 in ([#406](https://github.com/AppFlowy-IO/appflowy-editor/pull/406))
* fix: refactor _onSelectionChange to update _showPlaceholder state more efficiently by @LucasXu0 in ([#409](https://github.com/AppFlowy-IO/appflowy-editor/pull/409))

## 1.2.3
* feat: add edit link menu on mobile by @hyj1204 in ([#320](https://github.com/AppFlowy-IO/appflowy-editor/pull/320))
* feat: html encode parser added by @alihassan143 in ([#314](https://github.com/AppFlowy-IO/appflowy-editor/pull/314))
Expand Down
15 changes: 14 additions & 1 deletion example/lib/pages/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,20 @@ class Editor extends StatelessWidget {
editorState: editorState,
scrollController: scrollController,
blockComponentBuilders: customBlockComponentBuilders,
commandShortcutEvents: standardCommandShortcutEvents,
commandShortcutEvents: [
...standardCommandShortcutEvents,
...findAndReplaceCommands(
context: context,
localizations: FindReplaceLocalizations(
find: 'Find',
previousMatch: 'Previous match',
nextMatch: 'Next match',
close: 'Close',
replace: 'Replace',
replaceAll: 'Replace all',
),
),
],
characterShortcutEvents: standardCharacterShortcutEvents,
);
}
Expand Down
7 changes: 7 additions & 0 deletions example/windows/runner/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ add_executable(${BINARY_NAME} WIN32
# that need different build settings.
apply_standard_settings(${BINARY_NAME})

# Add preprocessor definitions for the build version.
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")

# Disable Windows macros that collide with C++ standard library functions.
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")

Expand Down
10 changes: 5 additions & 5 deletions example/windows/runner/Runner.rc
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ IDI_APP_ICON ICON "resources\\app_icon.ico"
// Version
//

#ifdef FLUTTER_BUILD_NUMBER
#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
#else
#define VERSION_AS_NUMBER 1,0,0
#define VERSION_AS_NUMBER 1,0,0,0
#endif

#ifdef FLUTTER_BUILD_NAME
#define VERSION_AS_STRING #FLUTTER_BUILD_NAME
#if defined(FLUTTER_VERSION)
#define VERSION_AS_STRING FLUTTER_VERSION
#else
#define VERSION_AS_STRING "1.0.0"
#endif
Expand Down
1 change: 1 addition & 0 deletions lib/appflowy_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export 'src/l10n/l10n.dart';
export 'src/plugins/plugins.dart';
export 'src/render/selection/selectable.dart';
export 'src/render/toolbar/toolbar_item.dart';
export 'src/service/context_menu/context_menu.dart';
export 'src/service/internal_key_event_handlers/copy_paste_handler.dart';
export 'src/service/shortcut_event/key_mapping.dart';
export 'src/service/shortcut_event/keybinding.dart';
43 changes: 39 additions & 4 deletions lib/src/core/document/document.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,40 @@ import 'dart:collection';

import 'package:appflowy_editor/appflowy_editor.dart';

/// [Document] represents a AppFlowy Editor document structure.
/// [Document] represents an AppFlowy Editor document structure.
///
/// It stores the root of the document.
///
/// DO NOT directly mutate the properties of a [Document] object.
/// **DO NOT** directly mutate the properties of a [Document] object.
///
class Document {
Document({
required this.root,
});

/// Constructs a [Document] from a JSON strcuture.
///
/// _Example of a [Document] in JSON format:_
/// ```
/// {
/// 'document': {
/// 'type': 'page',
/// 'children': [
/// {
/// 'type': 'paragraph',
/// 'data': {
/// 'delta': [
/// { 'insert': 'Welcome ' },
/// { 'insert': 'to ' },
/// { 'insert': 'AppFlowy!' }
/// ]
/// }
/// }
/// ]
/// }
/// }
/// ```
///
factory Document.fromJson(Map<String, dynamic> json) {
assert(json['document'] is Map);

Expand All @@ -32,6 +56,11 @@ class Document {
);
}

/// Creates a blank [Document] containing an empty root [Node].
///
/// If [withInitialText] is true, the document will contain an empty
/// paragraph [Node].
///
factory Document.blank({bool withInitialText = false}) {
final root = Node(
type: 'page',
Expand All @@ -42,12 +71,13 @@ class Document {
);
}

/// The root [Node] of the [Document]
final Node root;

/// first node of the document.
/// First node of the document.
Node? get first => root.children.first;

/// last node of the document.
/// Last node of the document.
Node? get last {
var last = root.children.last;
while (last.children.isNotEmpty) {
Expand Down Expand Up @@ -133,6 +163,9 @@ class Document {
return true;
}

/// Returns whether the root [Node] does not contain
/// any text.
///
bool get isEmpty {
if (root.children.isEmpty) {
return true;
Expand All @@ -151,6 +184,8 @@ class Document {
return false;
}

/// Encodes the [Document] into a JSON structure.
///
Map<String, Object> toJson() {
return {
'document': root.toJson(),
Expand Down
16 changes: 14 additions & 2 deletions lib/src/core/document/node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import 'package:nanoid/nanoid.dart';
///
///
/// Json format:
/// ```
/// {
/// 'type': string,
/// 'type': String,
/// 'data': Map<String, Object>
/// 'children': List<Node>,
/// }
/// ```
///
final class Node extends ChangeNotifier with LinkedListEntry<Node> {
Node({
required this.type,
Expand All @@ -38,6 +41,8 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
}
}

/// Parses a [Map] into a [Node]
///
factory Node.fromJson(Map<String, Object> json) {
final node = Node(
type: json['type'] as String,
Expand Down Expand Up @@ -90,13 +95,15 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {

/// Update the attributes of the node.
///
///
void updateAttributes(Attributes attributes) {
_attributes = composeAttributes(this.attributes, attributes) ?? {};

notifyListeners();
}

/// Grabs the [Node] from this [Node]s children
/// at a given index, if the index exists.
///
Node? childAtIndexOrNull(int index) {
if (children.length <= index || index < 0) {
return null;
Expand All @@ -115,6 +122,11 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
return child?.childAtPath(path.sublist(1));
}

/// Inserts a [Node] at a given [index]
///
/// If no [index] is supplied, inserts at the
/// end of the [Node].
///
void insert(Node entry, {int? index}) {
final length = _children.length;
index ??= length;
Expand Down
3 changes: 3 additions & 0 deletions lib/src/core/document/node_iterator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class NodeIterator implements Iterator<Node> {
return _currentNode != null;
}

/// Transforms the [NodeIterator] into an
/// [Iterable] containing all of the relevant [Node]'s
///
List<Node> toList() {
final List<Node> result = [];
while (moveNext()) {
Expand Down
44 changes: 29 additions & 15 deletions lib/src/core/document/text_delta.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import 'package:flutter/foundation.dart';
import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:flutter/services.dart';

import '../../editor/block_component/rich_text/appflowy_rich_text_keys.dart';

// constant number: 2^53 - 1
const int _maxInt = 9007199254740991;

abstract class TextOperation {
sealed class TextOperation {
Attributes? get attributes;
int get length;

Expand Down Expand Up @@ -439,6 +441,22 @@ class Delta extends Iterable<TextOperation> {

return operation;
}

Attributes? sliceAttributes(int index) {
if (index <= 0) {
return null;
}

final attributes = slice(index - 1, index).first.attributes;
if (attributes == null ||
!attributes.keys.every(
(element) => AppFlowyRichTextKeys.supportSliced.contains(element),
)) {
return null;
}

return attributes;
}
}

class _OpIterator {
Expand Down Expand Up @@ -488,22 +506,18 @@ class _OpIterator {
} else {
_offset += length;
}
if (nextOp is TextDelete) {
return TextDelete(length: length);
}

if (nextOp is TextRetain) {
return TextRetain(length, attributes: nextOp.attributes);
}

if (nextOp is TextInsert) {
return TextInsert(
nextOp.text.substring(offset, offset + length),
attributes: nextOp.attributes,
);
switch (nextOp) {
case TextDelete _:
return TextDelete(length: length);
case TextRetain _:
return TextRetain(length, attributes: nextOp.attributes);
case TextInsert _:
return TextInsert(
nextOp.text.substring(offset, offset + length),
attributes: nextOp.attributes,
);
}

return TextRetain(_maxInt);
}

List<TextOperation> rest() {
Expand Down
3 changes: 1 addition & 2 deletions lib/src/core/location/selection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,13 @@ class Selection {
}) : start = Position(path: path, offset: startOffset),
end = Position(path: path, offset: endOffset ?? startOffset);

/// deprecated: use [Selection.collapse] instead.
/// Create a collapsed selection with [position].
///
Selection.collapsed(Position position)
: start = position,
end = position;

/// Create a collapsed selection with [position].
@Deprecated('use Selection.collapsed() instead')
Selection.collapse(Path path, int offset)
: start = Position(path: path, offset: offset),
end = Position(path: path, offset: offset);
Expand Down
12 changes: 6 additions & 6 deletions lib/src/core/transform/operation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/foundation.dart';

/// [Operation] represents a change to a [Document].
abstract class Operation {
Operation(
sealed class Operation {
const Operation(
this.path,
);

Expand All @@ -24,7 +24,7 @@ abstract class Operation {

/// [InsertOperation] represents an insert operation.
class InsertOperation extends Operation {
InsertOperation(
const InsertOperation(
super.path,
this.nodes,
);
Expand Down Expand Up @@ -71,7 +71,7 @@ class InsertOperation extends Operation {

/// [DeleteOperation] represents a delete operation.
class DeleteOperation extends Operation {
DeleteOperation(
const DeleteOperation(
super.path,
this.nodes,
);
Expand Down Expand Up @@ -118,7 +118,7 @@ class DeleteOperation extends Operation {

/// [UpdateOperation] represents an attributes update operation.
class UpdateOperation extends Operation {
UpdateOperation(
const UpdateOperation(
super.path,
this.attributes,
this.oldAttributes,
Expand Down Expand Up @@ -181,7 +181,7 @@ class UpdateOperation extends Operation {

/// [UpdateTextOperation] represents a text update operation.
class UpdateTextOperation extends Operation {
UpdateTextOperation(
const UpdateTextOperation(
super.path,
this.delta,
this.inverted,
Expand Down
Loading

0 comments on commit 4e2b29f

Please sign in to comment.