Skip to content

Commit

Permalink
feat: custom slice function
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasXu0 committed Oct 16, 2024
1 parent 8ae43d4 commit a0d9400
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 28 deletions.
63 changes: 63 additions & 0 deletions example/lib/pages/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ class _EditorState extends State<Editor> {
EditorState? editorState;
WordCountService? wordCountService;

@override
void initState() {
super.initState();

appflowyEditorSliceAttributes = sliceAttributes;
}

@override
void didUpdateWidget(covariant Editor oldWidget) {
if (oldWidget.jsonString != widget.jsonString) {
Expand Down Expand Up @@ -156,4 +163,60 @@ class _EditorState extends State<Editor> {
],
);
}

Attributes? sliceAttributes(Delta delta, int index) {
if (index < 0) {
return null;
}

// if the index == 0, slice the attributes from the next position.
if (index == 0 && delta.isNotEmpty) {
final attributes = delta.slice(index, index + 1).firstOrNull?.attributes;
if (attributes == null) {
return null;
}

if (!isSupportSliced(attributes)) {
return null;
}

return attributes;
}

// if the index is not 0, slice the attributes from the previous position.
final prevAttributes =
delta.slice(index - 1, index).firstOrNull?.attributes;
if (prevAttributes == null) {
return null;
}
// if the prevAttributes doesn't include the code, return it.
// Otherwise, check if the nextAttributes includes the code.
if (!prevAttributes.keys.any(
(element) => element == AppFlowyRichTextKeys.code,
)) {
return prevAttributes;
}

// check if the nextAttributes includes the code.
final nextAttributes =
delta.slice(index, index + 1).firstOrNull?.attributes;
if (nextAttributes == null) {
return prevAttributes..remove(AppFlowyRichTextKeys.code);
}

// if the nextAttributes doesn't include the code, exclude the code format.
if (!nextAttributes.keys.any(
(element) => element == AppFlowyRichTextKeys.code,
)) {
return prevAttributes..remove(AppFlowyRichTextKeys.code);
}

return prevAttributes;
}

bool isSupportSliced(Attributes attributes) {
return attributes.keys.every(
(element) => AppFlowyRichTextKeys.supportSliced.contains(element),
);
}
}
79 changes: 52 additions & 27 deletions lib/src/core/document/text_delta.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,57 @@ import 'package:diff_match_patch/diff_match_patch.dart' as diff_match_patch;
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

typedef AppFlowyEditorSliceAttributes = Attributes? Function(
Delta delta,
int index,
);

AppFlowyEditorSliceAttributes? defaultAppFlowyEditorSliceAttributes = (
delta,
index,
) {
if (index < 0) {
return null;
}

Attributes? attributes;

// if the index == 0, slice the attributes from the next position.
if (index == 0 && delta.isNotEmpty) {
attributes = delta.slice(index, index + 1).firstOrNull?.attributes;
} else {
attributes = delta.slice(index - 1, index).firstOrNull?.attributes;
}

if (attributes == null) {
return null;
}

if (!attributes.keys.every(
(element) => AppFlowyRichTextKeys.supportSliced.contains(element),
)) {
AppFlowyEditorLog.editor.info(
'The attributes: $attributes is not supported in sliceAttributes.',

Check warning on line 39 in lib/src/core/document/text_delta.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/core/document/text_delta.dart#L38-L39

Added lines #L38 - L39 were not covered by tests
);
return null;
}

return attributes;
};

/// Default slice attributes function.
///
/// You can override the default slice attributes function by customizing
/// different slice rules, and fallback to the default one if not specified.
///
/// Rules
/// 1. If the index is less than 0, return null.
/// 2. If the index is 0, slice the attributes from the next position.
/// 3. If the index is greater than 0, slice the attributes from the previous position.
/// 4. If the attributes is not supported, return null.
AppFlowyEditorSliceAttributes? appflowyEditorSliceAttributes =
defaultAppFlowyEditorSliceAttributes;

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

Expand Down Expand Up @@ -515,33 +566,7 @@ class Delta extends Iterable<TextOperation> {
}

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

Attributes? attributes;

// if the index == 0, slice the attributes from the next position.
if (index == 0 && length >= 1) {
attributes = slice(index, index + 1).firstOrNull?.attributes;
} else {
attributes = slice(index - 1, index).firstOrNull?.attributes;
}

if (attributes == null) {
return null;
}

if (!attributes.keys.every(
(element) => AppFlowyRichTextKeys.supportSliced.contains(element),
)) {
AppFlowyEditorLog.editor.info(
'The attributes: $attributes is not supported in sliceAttributes.',
);
return null;
}

return attributes;
return appflowyEditorSliceAttributes?.call(this, index);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ Future<bool> _checkIfBacktickPressed(
AppFlowyEditorLog.input.debug('format failed');
// revert the transaction
editorState.undoManager.undo();
} else {
editorState.sliceUpcomingAttributes = false;

Check warning on line 144 in lib/src/editor/editor_component/service/ime/delta_input_on_non_text_update_impl.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/ime/delta_input_on_non_text_update_impl.dart#L144

Added line #L144 was not covered by tests
}

return true;
Expand Down
10 changes: 9 additions & 1 deletion lib/src/editor_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,15 @@ class EditorState {
///
/// If the value is true, the upcoming attributes will be sliced.
/// If the value is false, the upcoming attributes will be skipped.
bool sliceUpcomingAttributes = true;
bool _sliceUpcomingAttributes = true;
bool get sliceUpcomingAttributes => _sliceUpcomingAttributes;
set sliceUpcomingAttributes(bool value) {
if (value == _sliceUpcomingAttributes) {
return;
}
AppFlowyEditorLog.input.debug('sliceUpcomingAttributes: $value');
_sliceUpcomingAttributes = value;
}

final UndoManager undoManager = UndoManager();

Expand Down

0 comments on commit a0d9400

Please sign in to comment.