Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

Commit

Permalink
Merge pull request #23 from jimbeveridge/dynamic
Browse files Browse the repository at this point in the history
Fix build errors with Flutter beta
  • Loading branch information
jimbeveridge committed Mar 23, 2018
2 parents ff41504 + 404bcc0 commit 8595064
Show file tree
Hide file tree
Showing 8 changed files with 26 additions and 68 deletions.
17 changes: 0 additions & 17 deletions README.md
Expand Up @@ -102,23 +102,6 @@ class RandomColorStore extends Store {
trigger();
}
}
```

**BONUS:** `Stores` can be initialized with a stream transformer to modify the standard behavior of the `trigger` stream.
This can be useful for throttling UI rendering in response to high frequency `Store` mutations.

```dart
import 'package:rate_limit/rate_limit.dart';
import 'package:flutter_flux/flutter_flux.dart';
class ThrottledStore extends Store {
...
ThrottledStore(this._actions) : super.withTransformer(new Throttler(const Duration(milliseconds: 30))) {
...
}
}
```
**BONUS:** `Stores` provide an optional terse syntax for action -> data mutation -> trigger operations.
Expand Down
6 changes: 6 additions & 0 deletions analysis_options.yaml
@@ -0,0 +1,6 @@
# This file is required to fix the "flutter analyze" error that says:
# mixin_inherits_from_not_object
analyzer:
language:
enableSuperMixins: true
enableAssertInitializer: true
7 changes: 5 additions & 2 deletions example/lib/main.dart
Expand Up @@ -58,8 +58,11 @@ class ChatScreenState extends State<ChatScreen>
chatUserStore = listenToStore(userStoreToken);
}

void handleChatMessageStoreChanged(ChatMessageStore messageStore) {
msgController.text = messageStore.currentMessage;
void handleChatMessageStoreChanged(Store store) {
ChatMessageStore messageStore = store;
if (messageStore.currentMessage.isEmpty) {
msgController.clear();
}
setState(() {});
}

Expand Down
8 changes: 4 additions & 4 deletions lib/src/action.dart
Expand Up @@ -14,7 +14,7 @@

import 'dart:async';

typedef void OnData(dynamic event);
typedef void OnData<T>(T event);

/// A command that can be dispatched and listened to.
///
Expand Down Expand Up @@ -42,7 +42,7 @@ typedef void OnData(dynamic event);
/// action.
///
class Action<T> implements Function {
List<OnData> _listeners = <OnData>[];
List<OnData<T>> _listeners = <OnData<T>>[];

/// Dispatch this [Action] to all listeners. If a payload is supplied, it will
/// be passed to each listener's callback, otherwise null will be passed.
Expand All @@ -60,7 +60,7 @@ class Action<T> implements Function {
// for stream-based actions vs. 0.14 ms for this action implementation.
return Future.wait<dynamic>(
_listeners.map(
(OnData l) => new Future<dynamic>.microtask(() => l(payload))
(OnData<T> l) => new Future<dynamic>.microtask(() => l(payload))
),
);
}
Expand All @@ -74,7 +74,7 @@ class Action<T> implements Function {
/// dispatched. A payload of type [T] will be passed to the callback if
/// supplied at dispatch time, otherwise null will be passed. Returns an
/// [ActionSubscription] which provides means to cancel the subscription.
ActionSubscription listen(OnData onData) {
ActionSubscription listen(OnData<T> onData) {
_listeners.add(onData);
return new ActionSubscription(() => _listeners.remove(onData));
}
Expand Down
20 changes: 8 additions & 12 deletions lib/src/store.dart
Expand Up @@ -77,16 +77,12 @@ class Store {
}

/// A convenience method for listening to an [action] and triggering
/// automatically once the callback for said action has completed.
///
/// If [onAction] is provided, it will be called every time [action] is
/// dispatched. If [onAction] returns a [Future], [trigger] will not be
/// called until that future has resolved and the function returns either
/// void (null) or true.
void triggerOnAction(Action<dynamic> action,
[dynamic onAction(dynamic payload)]) {
/// automatically. The callback doesn't call return, so the return
/// type of onAction is null.
void triggerOnAction<T>(Action<T> action,
[dynamic onAction(T payload)]) {
if (onAction != null) {
action.listen((dynamic payload) async {
action.listen((T payload) async {
await onAction(payload);
trigger();
});
Expand All @@ -104,8 +100,8 @@ class Store {
/// If [onAction] returns a [Future], [trigger] will not be
/// called until that future has resolved and the function returns either
/// void (null) or true.
void triggerOnConditionalAction(
Action<dynamic> action, bool onAction(dynamic payload)) {
void triggerOnConditionalAction<T>(
Action<T> action, bool onAction(T payload)) {
assert(action != null);
action.listen((dynamic payload) async {
// Action functions must return bool, or a Future<bool>.
Expand All @@ -116,7 +112,7 @@ class Store {
} else {
wasChanged = result;
}
if (wasChanged == true) {
if (wasChanged) {
trigger();
}
});
Expand Down
2 changes: 1 addition & 1 deletion lib/src/store_watcher.dart
Expand Up @@ -79,7 +79,7 @@ class StoreWatcherState extends State<StoreWatcher> with StoreWatcherMixin<Store
/// Listens to changes in a number of different stores.
///
/// Used by [StoreWatcher] to track which stores the widget is listening to.
abstract class StoreWatcherMixin<T extends StatefulWidget> implements State<T>{
abstract class StoreWatcherMixin<T extends StatefulWidget> extends State<T>{
final Map<Store, StreamSubscription<Store>> _streamSubscriptions = <Store, StreamSubscription<Store>>{};

/// Start receiving notifications from the given store, optionally routed
Expand Down
5 changes: 2 additions & 3 deletions pubspec.yaml
@@ -1,17 +1,16 @@
# Important: Use "flutter packages get", not "pub get".
name: flutter_flux
author: Flutter Authors <flutter-dev@googlegroups.com>
version: 4.0.1
version: 4.1.0
description: Flux library for Flutter, featuring unidirectional dataflow inspired by reflux and Facebook's flux architecture.
homepage: https://github.com/flutter/flutter_flux
homepage: https://github.com/google/flutter_flux
dependencies:
meta: ^1.0.3
flutter:
sdk: flutter

dev_dependencies:
quiver: ">=0.24.0 <1.0.0"
rate_limit: ^0.1.0
test: ^0.12.13
flutter_test:
sdk: flutter
Expand Down
29 changes: 0 additions & 29 deletions test/store_test.dart
Expand Up @@ -18,7 +18,6 @@ import 'dart:async';
import 'package:flutter_flux/src/action.dart';
import 'package:flutter_flux/src/store.dart';
import 'package:quiver/testing/async.dart';
import 'package:rate_limit/rate_limit.dart';
import 'package:test/test.dart';

void main() {
Expand All @@ -44,34 +43,6 @@ void main() {
store.trigger();
});

test('should support stream transforms', () {
new FakeAsync().run((FakeAsync async) {
// ensure that multiple trigger executions emit
// exactly 2 throttled triggers to external listeners
// (1 for the initial trigger and 1 as the aggregate of
// all others that occurred within the throttled duration)
int count = 0;
store = new Store.withTransformer(
new Throttler<Store>(const Duration(milliseconds: 30)));
store.listen((Store listenedStore) {
count++;
});

store.trigger();
store.trigger();
store.trigger();
store.trigger();
store.trigger();
async.elapse(new Duration(milliseconds: 20));
expect(count, equals(1));
async.elapse(new Duration(milliseconds: 30));
expect(count, equals(2));
// Make sure that there aren't any queued up.
async.elapse(new Duration(milliseconds: 500));
expect(count, equals(2));
});
});

test('should trigger in response to an action', () {
store.triggerOnAction(action);
store.listen(expectAsync1((Store listenedStore) {
Expand Down

0 comments on commit 8595064

Please sign in to comment.