Skip to content

Commit 8bbae46

Browse files
committed
feat: add rules for editorstate.apply
1 parent a507fb8 commit 8bbae46

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

frontend/app_flowy/packages/appflowy_editor/lib/src/editor_state.dart

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:async';
2+
import 'package:appflowy_editor/src/core/document/node.dart';
23
import 'package:appflowy_editor/src/infra/log.dart';
34
import 'package:appflowy_editor/src/render/selection_menu/selection_menu_widget.dart';
45
import 'package:appflowy_editor/src/render/style/editor_style.dart';
@@ -119,8 +120,11 @@ class EditorState {
119120
///
120121
/// The options can be used to determine whether the editor
121122
/// should record the transaction in undo/redo stack.
122-
apply(Transaction transaction,
123-
[ApplyOptions options = const ApplyOptions(recordUndo: true)]) {
123+
void apply(
124+
Transaction transaction, {
125+
ApplyOptions options = const ApplyOptions(recordUndo: true),
126+
ruleCount = 0,
127+
}) {
124128
if (!editable) {
125129
return;
126130
}
@@ -132,6 +136,7 @@ class EditorState {
132136
_observer.add(transaction);
133137

134138
WidgetsBinding.instance.addPostFrameCallback((_) {
139+
_applyRules(ruleCount);
135140
updateCursorSelection(transaction.afterSelection);
136141
});
137142

@@ -153,7 +158,7 @@ class EditorState {
153158
}
154159
}
155160

156-
_debouncedSealHistoryItem() {
161+
void _debouncedSealHistoryItem() {
157162
if (disableSealTimer) {
158163
return;
159164
}
@@ -168,7 +173,7 @@ class EditorState {
168173
});
169174
}
170175

171-
_applyOperation(Operation op) {
176+
void _applyOperation(Operation op) {
172177
if (op is InsertOperation) {
173178
document.insert(op.path, op.nodes);
174179
} else if (op is UpdateOperation) {
@@ -179,4 +184,27 @@ class EditorState {
179184
document.updateText(op.path, op.delta);
180185
}
181186
}
187+
188+
void _applyRules(int ruleCount) {
189+
// Set a maximum count to prevent a dead loop.
190+
if (ruleCount >= 5) {
191+
return;
192+
}
193+
194+
final tr = transaction;
195+
196+
// Rules
197+
_insureLastNodeEditable(tr);
198+
199+
if (tr.operations.isNotEmpty) {
200+
apply(tr, ruleCount: ruleCount + 1);
201+
}
202+
}
203+
204+
void _insureLastNodeEditable(Transaction tr) {
205+
if (document.root.children.isEmpty ||
206+
document.root.children.last.id != 'text') {
207+
tr.insertNode([document.root.children.length], TextNode.empty());
208+
}
209+
}
182210
}

frontend/app_flowy/packages/appflowy_editor/lib/src/history/undo_manager.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class UndoManager {
123123
final transaction = historyItem.toTransaction(s);
124124
s.apply(
125125
transaction,
126-
const ApplyOptions(
126+
options: const ApplyOptions(
127127
recordUndo: false,
128128
recordRedo: true,
129129
),
@@ -143,7 +143,7 @@ class UndoManager {
143143
final transaction = historyItem.toTransaction(s);
144144
s.apply(
145145
transaction,
146-
const ApplyOptions(
146+
options: const ApplyOptions(
147147
recordUndo: true,
148148
recordRedo: false,
149149
),

frontend/app_flowy/packages/appflowy_editor_plugins/lib/src/code_block/code_block_shortcut_event.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ SelectionMenuItem codeBlockMenuItem = SelectionMenuItem(
9797
return;
9898
}
9999
final transaction = editorState.transaction;
100-
if (textNodes.first.toPlainText().isEmpty) {
100+
final textNode = textNodes.first;
101+
if (textNode.toPlainText().isEmpty && textNode.next is TextNode) {
101102
transaction.updateNode(textNodes.first, {
102103
BuiltInAttributeKey.subtype: kCodeBlockSubType,
103104
kCodeBlockAttrTheme: 'vs',

0 commit comments

Comments
 (0)