Value Notifier Tools

Powered by Mason melos coverage

Helpful lightweight tools for working with ValueNotifiers

Installation ๐Ÿ’ป

โ— In order to start using History Value Notifier you must have the dart_install_link installed on your machine.

Install via dart pub add:

dart pub add value_notifier_tools

Features

This package adds helpful tools for working with ValueNotifiers. Currently, it offers the following:

  • ๐Ÿ• HistoryValueNotifier allows you to undo and redo changes to the state of the notifier. This is useful for implementing undo/redo functionality in your app.
  • ๐ŸŽฏ SelectValueNotifier allows you to select a subset of the state of a ValueNotifier. This is useful for when you only want to listen to a specific part of the state of and rebuild a widget when that changes.
  • ๐Ÿ”Ž WhereValueNotifier allows you to provide a custom predicate to determine whether a state change should be propagated to listeners. This is useful for when only certain state transitions should cause a rebuild.
  • ๐Ÿชถ No dependencies on any other packages and super lightweight.
  • ๐Ÿงฉ Easy to use and integrate into your existing projects.
  • ๐Ÿงช 100% test coverage

HistoryValueNotifier

  • โ†ฉ๏ธ Add undo() and redo() to ValueNotifier
  • ๐Ÿ• Limit the size of your history
  • ๐Ÿ’• Offers both a mixin that can be added to your existing ValueNotifiers and a class that you can extend
  • ๐Ÿ”Ž Choose which states get stored to the history
  • ๐Ÿ”„ Transform states before applying them from the history

Usage

Getting started is easy! There are three main ways in which you can add HistoryValueNotifier to your project:

Use it as-is

If you don't need any extra functionality, you can use HistoryValueNotifier as-is.

import 'package:history_value_notifier/history_value_notifier.dart';

final notifier = HistoryValueNotifier<int>(0);
notifier.value = 1;
notifier.undo(); // 0
notifier.redo(); // 1

Upgrade an existing ValueNotifier

class CounterNotifier extends ValueNotifier<int>
    with HistoryValueNotifierMixin<int> {
  CounterNotifier() : super(0) {
    // This is how you limit the size of your history.
    // Set it to null to keep all state (default)
    maxHistoryLength = 30;
  }

  void increment() => ++state;

  void decrement() => --state;

  // By using temporaryState setter, the change won't be stored in history
  void reset() => temporaryState = 0;

  // You can override this function to apply a transformation to a state
  // from the history before it gets applied.
  @override
  int transformHistoryState(int newState, int currentState) {
    return newState;
  }
}

Create a HistoryValueNotifier

If you prefer to create a HistoryValueNotifier directly, you can do this instead:

class CounterNotifier extends HistoryValueNotifier<int> {
  // ... Same as above
}

Use It!

You can now use the full functionality of the HistoryValueNotifier!

// Obtain a reference however you wish (Provider, GetIt, etc.)
final CounterNotifier notifier = context.read(counterNotifier);

notifier.increment(); // 1
notifier.undo(); // 0
notifier.redo(); // 1

notifier.decrement(); // 0
notifier.undo(); // 1
notifier.canRedo // true
notifier.increment // 2
notifier.canRedo // false

// ...

SelectValueNotifier

  • ๐ŸŽฏ Select a subset of the state of a ValueNotifier
  • ๐Ÿงฉ Only listen to the parts of the state that you care about
  • ๐Ÿƒ Micromanage rebuilds for maximum performance

Usage

Using SelectValueNotifier is super easy:

Use the convenient select extension method

This allows you to select a subset of the state of a ValueNotifier by providing a selector function anywhere you need.

final notifier = ValueNotifier({'a': 1, 'b': 2});

return ValueListenableBuilder<int>(
  valueListenable: notifier.select((value) => value['a']),
  builder: (context, value, child) {
    return Text(value.toString());
  },
);

Your selectNotifier will now only notify listeners when the value of 'a' changes.

WhereValueNotifier

  • ๐Ÿ”Ž Provide a custom predicate to determine whether a state change should be propagated to listeners
  • ๐Ÿงฉ Only listen to the state changes that you care about

Usage

There are two main ways to use WhereValueNotifier:

Use the where extension method

This allows you to dynamically filter the state changes that you care about from another notifier.

final notifier = ValueNotifier(0);

return ValueListenableBuilder<int>(
  valueListenable: notifier.where((oldState, newState) => newState > oldState),
  builder: (context, value, child) {
    return Text(value.toString());
  },
);

Now, your widget will only rebuild when the new state is greater than the old state.

Extend it for your own custom classes

You can also extend it and provide your own updateShouldNotify function.

class IncreasingValueNotifier<int> extends WhereValueNotifier<int> {
  IncreasingValueNotifier(super.value);

  @override
  bool updateShouldNotify(T oldState, T newState) {
    return oldState < newState;
  }
}

Libraries

value_notifier_tools
Helpful lightweight tools for working with ValueNotifiers