Skip to content

Instantly share code, notes, and snippets.

@rodydavis
Created August 3, 2020 18:47
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 rodydavis/8430de62a29760f793971993fdb13b08 to your computer and use it in GitHub Desktop.
Save rodydavis/8430de62a29760f793971993fdb13b08 to your computer and use it in GitHub Desktop.
Tracked Flutter ValueNotifer
@@ -1,94 +0,0 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:undo/undo.dart';
class TrackedValueNotifier<T> extends ChangeNotifier
implements ValueListenable<T> {
/// Creates a [ChangeNotifier] that wraps this value.
TrackedValueNotifier(
this._value, {
int maxUndoStack,
this.debounce,
this.onRedo,
this.onUndo,
}) {
_changeStack = ChangeStack(max: maxUndoStack);
debounce ??= Duration.zero;
}
/// Debounce delay to commit changes to a group
Duration debounce;
ChangeStack _changeStack;
Timer _debounce;
T _value;
final ValueChanged<T> onUndo, onRedo;
/// The current value stored in this notifier.
///
/// When the value is replaced with something that is not equal to the old
/// value as evaluated by the equality operator ==, this class notifies its
/// listeners.
///
/// Every new change will be added to the undo stack.
/// Committing a change will clear the redo stack.
@override
T get value => _value;
@override
void dispose() {
_changeStack.dispose();
super.dispose();
}
@override
String toString() {
return '${describeIdentity(this)}($value)';
}
set value(T newValue) {
if (_value == newValue) return;
if (_debounce == null || !_debounce.isActive) {
_changeStack.group();
}
_changeStack.add(Change.property(_value, () {
_value = newValue;
notifyListeners();
}, (oldValue) {
_value = oldValue;
notifyListeners();
}));
_debounce?.cancel();
_debounce = Timer(debounce, () => _changeStack.commit());
}
/// Undo the last change
void undo() {
_changeStack.undo();
if (onUndo != null) {
onUndo(_value);
}
}
// Redo the previous change
void redo() {
_changeStack.redo();
if (onRedo != null) {
onRedo(_value);
}
}
// Checks whether the undo/redo stack is empty
bool get canUndo => _changeStack.canUndo;
// Checks wether the undo/redo stack is at the current change
bool get canRedo => _changeStack.canRedo;
/// Clear undo history
void clear() {
_changeStack.clear();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment