Skip to content

Instantly share code, notes, and snippets.

@stargazing-dino
Created May 25, 2022 13:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stargazing-dino/1c40f3637dc7c4134f5d92ffa970164c to your computer and use it in GitHub Desktop.
Save stargazing-dino/1c40f3637dc7c4134f5d92ffa970164c to your computer and use it in GitHub Desktop.
initial attempt at undo redo state
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:tuple/tuple.dart';
@immutable
class UndoRedoHandler {
const UndoRedoHandler({
required this.resetState,
required this.index,
required this.lastIndex,
required this.goBack,
required this.goForward,
});
final void Function() resetState;
final int index;
final int lastIndex;
/// Allows you to go back (undo) N steps.
/// Tries to go back in the history, returns true if it was possible.
final bool Function(int) goBack;
/// Allows you to go forward (redo) N steps.
/// Tries to go forward in the history, returns true if it was possible.
final bool Function(int) goForward;
}
Tuple2<ValueNotifier<T>, UndoRedoHandler> useUndoRedoState<T>(
T initialData, {
int maxHistory = 10,
bool Function(T a, T b)? equals,
}) {
final index = useState<int>(0);
final history = useValueNotifier([initialData]);
bool pushValue(T value) {
final current = history.value[index.value];
if (equals != null) {
if (equals(current, value)) return false;
} else {
if (value == current) return false;
}
// Remove all values after the current index
final copy = history.value.sublist(0, index.value + 1);
// Trim the copy so it is only maxHistory long
if (copy.length > maxHistory) {
copy.removeRange(0, copy.length - maxHistory);
}
// Add the new value
copy.add(value);
// Update the state
history.value = copy;
index.value = copy.length - 1;
return true;
}
// Clear all state history
void resetState() {
index.value = 0;
history.value = [initialData];
}
bool goBack(int steps) {
final newIndex = math.max(0, index.value - steps);
if (newIndex == index.value) {
return false;
}
index.value = newIndex;
return true;
}
bool goForward(int steps) {
final newIndex = math.min(history.value.length - 1, index.value + steps);
if (newIndex == index.value) {
return false;
}
index.value = newIndex;
return true;
}
return Tuple2(
current,
UndoRedoHandler(
resetState: resetState,
index: index.value,
lastIndex: history.value.length - 1,
goBack: goBack,
goForward: goForward,
),
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment