supply static method

Widget supply({
  1. required List<Inheritable<Object?>> inheritables,
  2. Widget? child,
  3. bool strict = true,
})

Convenience method to supply multiple Inheritables holding different values to child

For example supply both a User and their UserPreferences to child.

Inheritable.supply(
  inheritables: [
    Inheritable<User>(value: _currentUser),
    Inheritable<UserPreferences>(value: _preferences),
  ]
  child: MyWidget(),
)

It is possible to use Inheritable.mutable or Inheritable.override as well.

This is equivalent to

Inheritable<A>(
  value: A(),
  child: Inheritable<B>(
    value: B(),
    child: MyWidget(),
  )
)

Optionally specify strict (defaults to true) to verify all inheritables can be uniquely used as dependency. This checks the runtimeType and key combination of all inheritables, upon finding a duplicate, this will throw. It is primarily used to detect un-intentional Inheritable overrides, as well as allowing two Inheritables of the same type to co-exist.

strict is only used in debug mode.

Implementation

static Widget supply({
  required List<Inheritable<Object?>> inheritables,
  Widget? child,
  bool strict = true,
}) {
  Widget? result = child;
  Map<Type, Set<Key?>>? _;

  // TODO: Add further optimizations to Inheritable.supply
  for (var inheritable in inheritables.reversed) {
    assert(!strict ||
        (() {
          _ ??= <Type, Set<Key?>>{};
          final type = inheritable.runtimeType;
          final key = inheritable.key;
          final keys = _?[type] ??= HashSet(
            equals: (a, b) => a == b,
            hashCode: (a) => a.hashCode,
            isValidKey: (_) => true, // null is also valid
          );

          if (keys!.contains(key)) {
            throw StateError(
              'Found duplicate inheritable [$type] with key [$key] in $keys. '
              'This is essentially overriding access to the original inheritable. '
              'Specify a key to distinguish between them, it can then be used by '
              '[InheritableAspect.didUpdateWidget] or [InheritableAspect.satisfiedBy]',
            );
          } else {
            keys.add(key);
          }

          return true;
        })());

    result = inheritable.copyWith(child: result);
  }

  assert((() {
    _ = null;
    return true;
  })());

  return result!;
}