feat: redo

This commit is contained in:
Vincent Chan 2022-07-21 20:07:51 +08:00
parent 7ae153f5da
commit a120853d06
3 changed files with 54 additions and 2 deletions

View File

@ -43,6 +43,7 @@ class __TextNodeWidgetState extends State<_TextNodeWidget>
TextNode get node => widget.node as TextNode;
EditorState get editorState => widget.editorState;
bool _metaKeyDown = false;
bool _shiftKeyDown = false;
TextInputConnection? _textInputConnection;
@ -79,6 +80,7 @@ class __TextNodeWidgetState extends State<_TextNodeWidget>
}
KeyEventResult _onKey(FocusNode focusNode, RawKeyEvent event) {
debugPrint('key: $event');
if (event is RawKeyDownEvent) {
final sel = _globalSelectionToLocal(node, editorState.cursorSelection);
if (event.logicalKey == LogicalKeyboardKey.backspace) {
@ -90,14 +92,25 @@ class __TextNodeWidgetState extends State<_TextNodeWidget>
} else if (event.logicalKey == LogicalKeyboardKey.metaLeft ||
event.logicalKey == LogicalKeyboardKey.metaRight) {
_metaKeyDown = true;
} else if (event.logicalKey == LogicalKeyboardKey.shiftLeft ||
event.logicalKey == LogicalKeyboardKey.shiftRight) {
_shiftKeyDown = true;
} else if (event.logicalKey == LogicalKeyboardKey.keyZ && _metaKeyDown) {
editorState.undoManager.undo();
if (_shiftKeyDown) {
editorState.undoManager.redo();
} else {
editorState.undoManager.undo();
}
}
} else if (event is RawKeyUpEvent) {
if (event.logicalKey == LogicalKeyboardKey.metaLeft ||
event.logicalKey == LogicalKeyboardKey.metaRight) {
_metaKeyDown = false;
}
if (event.logicalKey == LogicalKeyboardKey.shiftLeft ||
event.logicalKey == LogicalKeyboardKey.shiftRight) {
_shiftKeyDown = false;
}
}
return KeyEventResult.ignored;
}

View File

@ -10,8 +10,10 @@ class ApplyOptions {
/// whether the transaction should be recorded into
/// the undo stack.
final bool recordUndo;
final bool recordRedo;
const ApplyOptions({
this.recordUndo = true,
this.recordRedo = false,
});
}
@ -57,6 +59,12 @@ class EditorState {
}
undoItem.afterSelection = transaction.afterSelection;
_debouncedSealHistoryItem();
} else if (options.recordRedo) {
final redoItem = HistoryItem();
redoItem.addAll(transaction.operations);
redoItem.beforeSelection = transaction.beforeSelection;
redoItem.afterSelection = transaction.afterSelection;
undoManager.redoStack.push(redoItem);
}
}

View File

@ -5,6 +5,7 @@ import 'package:flowy_editor/operation/operation.dart';
import 'package:flowy_editor/operation/transaction_builder.dart';
import 'package:flowy_editor/operation/transaction.dart';
import 'package:flowy_editor/editor_state.dart';
import 'package:flutter/foundation.dart';
/// This class contains operations committed by users.
/// If a [HistoryItem] is not sealed, operations can be added sequentially.
@ -68,6 +69,10 @@ class FixedSizeStack {
return last;
}
clear() {
_list.clear();
}
HistoryItem get last => _list.last;
bool get isEmpty => _list.isEmpty;
@ -92,6 +97,7 @@ class UndoManager {
}
final last = undoStack.last;
if (last.sealed) {
redoStack.clear();
final item = HistoryItem();
undoStack.push(item);
return item;
@ -100,6 +106,7 @@ class UndoManager {
}
undo() {
debugPrint('undo');
final s = state;
if (s == null) {
return;
@ -109,6 +116,30 @@ class UndoManager {
return;
}
final transaction = historyItem.toTransaction(s);
s.apply(transaction, const ApplyOptions(recordUndo: false));
s.apply(
transaction,
const ApplyOptions(
recordUndo: false,
recordRedo: true,
));
}
redo() {
debugPrint('redo');
final s = state;
if (s == null) {
return;
}
final historyItem = redoStack.pop();
if (historyItem == null) {
return;
}
final transaction = historyItem.toTransaction(s);
s.apply(
transaction,
const ApplyOptions(
recordUndo: true,
recordRedo: false,
));
}
}