Skip to content

Commit 8150d7f

Browse files
feat(replay_bloc): add suppport for undo/redo multiple steps
1 parent 8a40870 commit 8150d7f

File tree

4 files changed

+349
-14
lines changed

4 files changed

+349
-14
lines changed

packages/replay_bloc/lib/src/change_stack.dart

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,55 @@ class _ChangeStack<T> {
3131
_redos.clear();
3232
}
3333

34-
void redo() {
35-
if (canRedo) {
36-
final change = _redos.removeFirst();
37-
_history.addLast(change);
38-
return _shouldReplay(change._newValue) ? change.execute() : redo();
34+
void redo(int steps) {
35+
if (steps <= 0) return;
36+
37+
var effectiveSteps = steps;
38+
while (effectiveSteps > 0 && canRedo) {
39+
_Change<T>? changeToExecute;
40+
while (_redos.isNotEmpty) {
41+
final change = _redos.first;
42+
if (_shouldReplay(change._newValue)) {
43+
changeToExecute = _redos.removeFirst();
44+
break;
45+
} else {
46+
_history.addLast(_redos.removeFirst());
47+
}
48+
}
49+
50+
if (changeToExecute != null) {
51+
_history.addLast(changeToExecute);
52+
changeToExecute.execute();
53+
effectiveSteps--;
54+
} else {
55+
break;
56+
}
3957
}
4058
}
4159

42-
void undo() {
43-
if (canUndo) {
44-
final change = _history.removeLast();
45-
_redos.addFirst(change);
46-
return _shouldReplay(change._oldValue) ? change.undo() : undo();
60+
void undo(int steps) {
61+
if (steps <= 0) return;
62+
63+
var effectiveSteps = steps;
64+
while (effectiveSteps > 0 && canUndo) {
65+
_Change<T>? changeToUndo;
66+
while (_history.isNotEmpty) {
67+
final change = _history.last;
68+
if (_shouldReplay(change._oldValue)) {
69+
changeToUndo = _history.removeLast();
70+
break;
71+
} else {
72+
_redos.addFirst(_history.removeLast());
73+
}
74+
}
75+
76+
if (changeToUndo != null) {
77+
_redos.addFirst(changeToUndo);
78+
changeToUndo.undo();
79+
effectiveSteps--;
80+
} else {
81+
break;
82+
}
4783
}
4884
}
4985
}

packages/replay_bloc/lib/src/replay_bloc.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,10 @@ mixin ReplayBlocMixin<Event extends ReplayEvent, State> on Bloc<Event, State> {
132132
}
133133

134134
/// Undo the last change.
135-
void undo() => _changeStack.undo();
135+
void undo([int steps = 1]) => _changeStack.undo(steps);
136136

137137
/// Redo the previous change.
138-
void redo() => _changeStack.redo();
138+
void redo([int steps = 1]) => _changeStack.redo(steps);
139139

140140
/// Checks whether the undo/redo stack is empty.
141141
bool get canUndo => _changeStack.canUndo;

packages/replay_bloc/lib/src/replay_cubit.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ mixin ReplayCubitMixin<State> on Cubit<State> {
7676
}
7777

7878
/// Undo the last change.
79-
void undo() => _changeStack.undo();
79+
void undo([int steps = 1]) => _changeStack.undo(steps);
8080

8181
/// Redo the previous change.
82-
void redo() => _changeStack.redo();
82+
void redo([int steps = 1]) => _changeStack.redo(steps);
8383

8484
/// Checks whether the undo/redo stack is empty.
8585
bool get canUndo => _changeStack.canUndo;

0 commit comments

Comments
 (0)