From ad365005b0b33eace1f9fa90d413f6f6de1ebee5 Mon Sep 17 00:00:00 2001 From: Thito Yalasatria Sunarya Date: Fri, 25 Oct 2024 16:54:01 +0700 Subject: [PATCH] Refactor data and notifier --- lib/src/data.dart | 48 ++++--------------------------- lib/src/notifier.dart | 62 +++++------------------------------------ test/notifier_test.dart | 27 ++---------------- 3 files changed, 16 insertions(+), 121 deletions(-) diff --git a/lib/src/data.dart b/lib/src/data.dart index 61f509f..de0d08e 100644 --- a/lib/src/data.dart +++ b/lib/src/data.dart @@ -309,46 +309,6 @@ class DataNotifier extends StatelessWidget implements MultiDataItem { Type get dataType => T; } -class DataStream extends StatelessWidget implements MultiDataItem { - final Stream stream; - final Widget? child; - - const DataStream(this.stream, {super.key, this.child}); - - const DataStream.inherit({ - super.key, - required this.stream, - required this.child, - }); - - @override - Widget wrapWidget(Widget child) { - return DataStream.inherit( - stream: stream, - child: child, - ); - } - - @override - Widget build(BuildContext context) { - return StreamBuilder( - stream: stream, - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const SizedBox(); - } - return Data.inherit( - data: snapshot.data!, - child: child, - ); - }, - ); - } - - @override - Type get dataType => T; -} - /// A widget builder that receives the data from the ancestor Data widget. typedef DataWidgetBuilder = Widget Function( BuildContext context, T data, Widget? child); @@ -748,8 +708,12 @@ class _CaptureAllData extends StatelessWidget { } } +mixin MultiModelItem { + Model get normalized; +} + /// A mixin for all kinds of Model properties. -mixin ModelProperty { +mixin ModelProperty implements MultiModelItem { /// The data key of the model. Symbol get dataKey; @@ -1139,7 +1103,7 @@ class ModelKey { /// A widget that provides multiple models to its descendants. class MultiModel extends StatelessWidget { /// The list of models that will be provided to the descendants. - final List data; + final List data; /// The child widget. final Widget child; diff --git a/lib/src/notifier.dart b/lib/src/notifier.dart index 54e419d..b763def 100644 --- a/lib/src/notifier.dart +++ b/lib/src/notifier.dart @@ -3,46 +3,20 @@ import 'package:flutter/foundation.dart'; import '../data_widget.dart'; /// A notifier class that allows mutable updates and notifies listeners of changes. -class MutableNotifier implements ValueListenable { - final EventNotifier _notifier = EventNotifier(); - - @override - final T value; - +class MutableNotifier extends ValueNotifier { /// Constructs a [MutableNotifier] with an initial value. - MutableNotifier(this.value); + MutableNotifier(super.value); /// Updates the value using the provided [updater] function. /// If the [updater] returns `null` or `true`, listeners are notified. - void setValue(bool? Function(T) updater) { + void mutate(Function(T value) updater) { var result = updater(value); - if (result == null || result) { - _notifier.notify(); + if (result is T && result != value) { + value = result; + } else if (result == null || result == true) { + notifyListeners(); } } - - @override - void addListener(VoidCallback listener) { - _notifier.addListener(listener); - } - - @override - void removeListener(VoidCallback listener) { - _notifier.removeListener(listener); - } -} - -/// A notifier class that extends [ChangeNotifier] to provide custom notification logic. -class EventNotifier extends ChangeNotifier { - /// Notifies all registered listeners. - void notify() { - notifyListeners(); - } - - /// Creates a [ValueListenable] that hooks into the current notifier and provides a value. - ValueListenable hookWithValue(T Function() getValue) { - return _ValueHookListenable(getValue, this); - } } /// Extension on [ValueNotifier] to provide a read-only view. @@ -79,25 +53,3 @@ class ValueNotifierUnmodifiableView extends ValueListenable { _notifier.removeListener(listener); } } - -/// A [ValueListenable] that hooks into an [EventNotifier] and provides a value. -class _ValueHookListenable extends ValueListenable { - final T Function() _getValue; - final EventNotifier _notifier; - - /// Constructs a [_ValueHookListenable] with the given value getter and notifier. - _ValueHookListenable(this._getValue, this._notifier); - - @override - T get value => _getValue(); - - @override - void addListener(VoidCallback listener) { - _notifier.addListener(listener); - } - - @override - void removeListener(VoidCallback listener) { - _notifier.removeListener(listener); - } -} diff --git a/test/notifier_test.dart b/test/notifier_test.dart index a9dc817..db367f8 100644 --- a/test/notifier_test.dart +++ b/test/notifier_test.dart @@ -9,7 +9,8 @@ void main() { list.addListener(() { listenerCalled = true; }); - list.setValue((value) { + list.mutate((value) => value.add(12)); + list.mutate((value) { value.add(4); return true; }); @@ -22,23 +23,13 @@ void main() { list.addListener(() { listenerCalled = true; }); - list.setValue((value) { + list.mutate((value) { value.add(4); return false; }); expect(listenerCalled, false); }); - test('EventNotifier test', () { - EventNotifier notifier = EventNotifier(); - bool listenerCalled = false; - notifier.addListener(() { - listenerCalled = true; - }); - notifier.notify(); - expect(listenerCalled, true); - }); - test('ValueNotifierExtension test', () { ValueChangeNotifier valueNotifier = ValueChangeNotifier(1); ValueListenable readOnly = valueNotifier.readOnly(); @@ -50,16 +41,4 @@ void main() { valueNotifier.value = 2; expect(listenerCalled, true); }); - - test('EventNotifier hookWithValue test', () { - EventNotifier notifier = EventNotifier(); - ValueListenable valueListenable = notifier.hookWithValue(() => 1); - expect(valueListenable.value, 1); - bool listenerCalled = false; - valueListenable.addListener(() { - listenerCalled = true; - }); - notifier.notify(); - expect(listenerCalled, true); - }); }