From 46fbab557026bb229f04e00da7577197cec12a6b Mon Sep 17 00:00:00 2001 From: devkabiir Date: Sat, 6 Feb 2021 01:09:47 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=A5=20(Aspect)=20Fix=20AspectPatch=20d?= =?UTF-8?q?efinition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This provides value to patch callback. - Add common extensions - WIP AspectBatch for performant Inheritable mutation #time: 35 minutes --- lib/extensions.dart | 12 +++++++++++ lib/inheritable.dart | 50 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 lib/extensions.dart diff --git a/lib/extensions.dart b/lib/extensions.dart new file mode 100644 index 0000000..55f2d8c --- /dev/null +++ b/lib/extensions.dart @@ -0,0 +1,12 @@ +import 'package:flutter/widgets.dart'; + +import 'inheritable.dart'; + +extension BoolAspectOf on Aspect { + Aspect map({R onTrue, R onFalse, Key key}) { + return AspectChianingFn(this).map( + (b) => b ? onTrue : onFalse, + key, + ); + } +} diff --git a/lib/inheritable.dart b/lib/inheritable.dart index a9169b4..7b78785 100644 --- a/lib/inheritable.dart +++ b/lib/inheritable.dart @@ -6,6 +6,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; +export 'extensions.dart'; + /// Given [T] extract certain aspect [A] from [it] and return that. /// /// You can return anything as long as it satisfies type [A] @@ -574,7 +576,7 @@ extension InheritableAspectChainable on DependableAspect { ); } - Aspect withPatch(T Function(T) patch, [Key key]) { + Aspect withPatch(AspectPatch patch, [Key key]) { return Aspect._( ({next, prev, aspect}) => didUpdateWidget(prev: prev, next: next), (t) => t, @@ -985,6 +987,34 @@ mixin MutableInheritableAspect on InheritableAspect { } } +/// Allow mutating multiple [Inheritable]s at the same time while deferring +/// their updates to dependents. +abstract class AspectBatch { + /// Identifier for this batch. + Key get key; + + /// Inheritables satisfying this batch's aspects. + Set> get inheritables; + + /// InheritableAspects participating in this batch. + Set> get aspects; + + /// Apply this batch to [context] + void apply(BuildContext context) { + /// For every aspect, get the first satisfiable inheritable. There may not + /// be any present in current context. + /// + /// Which is fine, because we only dispatch updates for those that are + /// present and satisfiable. + /// + /// For all the satisfiable inheritables, mark as needing build. + /// + /// For each aspect -> inheritable pair, perform `valueFor(aspect)?.call(aspect.mutate(inheritable))` + /// + /// Finish batch transaction for each inheritable + } +} + extension ReplaceMutableInheritable on InheritableAspect { /// Creates an [AspectMutation] that unconditionally requests [T] to be /// replaced by [next]. @@ -1000,7 +1030,8 @@ extension PatchMutableInheritable on PatchableAspect { /// /// The newly created [AspectMutation] uses `this.key`, which means it is /// possible to override it by using `AspectOverride.key`. - AspectMutation replace(A next) => AspectMutation((_) => patch(next), key); + AspectMutation replace(A next) => + AspectMutation((w) => patch(w.valueFor(this), next), key); } // TODO: an Inheritable.mutable can be used to deny updates from certain @@ -1048,9 +1079,10 @@ class AspectMutation extends EquatableAspect } } +typedef AspectPatch = T Function(T value, A next); mixin PatchableAspect on TransformingAspect { /// Given a new [A] of [T], return the patched [T] - T patch(A next); + T patch(T value, A next); } class Aspect extends EquatableAspect @@ -1062,7 +1094,7 @@ class Aspect extends EquatableAspect @override final Key key; final A Function(T) mapper; - final T Function(A) _patch; + final AspectPatch _patch; final DidUpdateWidget _didUpdateWidgetImpl; final DefaultInheritableAspectOfContext _defaultValue; @@ -1073,7 +1105,7 @@ class Aspect extends EquatableAspect /// Create an aspect [A] of [T] using [transform], /// which can optionaly be later patched using [patch]. const Aspect.patchable({ - @required T Function(A) patch, + @required AspectPatch patch, Key key, A Function(T) transform, }) : this._(null, transform, key, null, patch); @@ -1102,8 +1134,8 @@ class Aspect extends EquatableAspect } @override - T patch(A next) { - if (_patch != null) return _patch(next); + T patch(T value, A next) { + if (_patch != null) return _patch(value, next); throw StateError('This aspect is not Patchable'); } @@ -1146,7 +1178,7 @@ class Aspect extends EquatableAspect Aspect clone({ Key key, final A Function(T) mapper, - final T Function(A) patch, + final AspectPatch patch, final DidUpdateWidget didUpdateWidget, final DefaultInheritableAspectOfContext defaultValue, }) { @@ -1182,7 +1214,7 @@ extension AspectChianingFn on Aspect { } /// Allow patching [R] of [T] using [patch] - Aspect withPatch(T Function(R) patch, [Key key]) { + Aspect withPatch(AspectPatch patch, [Key key]) { return clone(key: key, patch: patch); }