Skip to content

Commit 5c31630

Browse files
committed
add tests and travis
1 parent 6e3a88c commit 5c31630

File tree

9 files changed

+871
-111
lines changed

9 files changed

+871
-111
lines changed

.travis.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
os:
2+
- linux
3+
sudo: false
4+
addons:
5+
apt:
6+
sources:
7+
- ubuntu-toolchain-r-test
8+
packages:
9+
- libstdc++6
10+
- fonts-droid
11+
before_script:
12+
- git clone https://github.com/flutter/flutter.git -b alpha --depth 1
13+
- ./flutter/bin/flutter doctor
14+
script:
15+
- dart tool/build.dart
16+
- ./flutter/bin/flutter test --coverage --coverage-path=lcov.info
17+
after_success:
18+
- bash <(curl -s https://codecov.io/bash)
19+
cache:
20+
directories:
21+
- $HOME/.pub-cache

lib/flutter_built_redux.dart

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,109 @@
1-
export 'src/store_connector.dart';
1+
import 'dart:async';
2+
3+
import 'package:meta/meta.dart';
4+
import 'package:flutter/widgets.dart' hide Builder;
5+
import 'package:built_redux/built_redux.dart';
6+
7+
/// [StoreConnector] is a widget that rebuilds when the redux store
8+
/// has triggered and the connect function yields a new result.
9+
/// [LocalState] should be comparable. It is recommended to only use primitive and built types.
10+
abstract class StoreConnector<StoreState, Actions extends ReduxActions,
11+
LocalState> extends StatefulWidget {
12+
StoreConnector({Key key}) : super(key: key);
13+
14+
/// [connect] takes the current state of the redux store and retuns an object that contains
15+
/// the subset of the redux state tree that this component cares about.
16+
@protected
17+
LocalState connect(StoreState state);
18+
19+
@override
20+
StoreConnectorState<StoreState, Actions, LocalState> createState() =>
21+
new StoreConnectorState<StoreState, Actions, LocalState>();
22+
23+
@protected
24+
Widget build(BuildContext context, LocalState state, Actions actions);
25+
}
26+
27+
class StoreConnectorState<StoreState, Actions extends ReduxActions, LocalState>
28+
extends State<StoreConnector<StoreState, Actions, LocalState>> {
29+
StreamSubscription<SubstateChange<LocalState>> _storeSub;
30+
31+
/// [LocalState] is an object that contains the subset of the redux state tree that this component
32+
/// cares about.
33+
LocalState _state;
34+
35+
Store get _store {
36+
// get the store from the ReduxProvider ancestor
37+
final ReduxProvider reduxProvider =
38+
context.inheritFromWidgetOfExactType(ReduxProvider);
39+
40+
// if it is not found raise an error
41+
if (reduxProvider == null) {
42+
throw new Exception(
43+
'Store was not found, make sure ReduxProvider is an ancestor of this component.');
44+
}
45+
46+
if (reduxProvider.store.state is! StoreState) {
47+
throw new Exception(
48+
'Store found was not the correct type, make sure StoreConnector\'s generic for StoreState matches the state type of your built_redux store.');
49+
}
50+
51+
if (reduxProvider.store.actions is! Actions) {
52+
throw new Exception(
53+
'Store found was not the correct type, make sure StoreConnector\'s generic for Actions matches the actions type of your built_redux store.');
54+
}
55+
56+
return reduxProvider.store;
57+
}
58+
59+
/// setup a subscription to the store
60+
@override
61+
@mustCallSuper
62+
void didChangeDependencies() {
63+
super.didChangeDependencies();
64+
65+
// if the store has already been subscribed to return early. didChangeDependencies
66+
// will be called every time the dependencies of the widget change, but we only
67+
// want to subscribe to the store the first time it is called. Subscriptions are setup
68+
// in didChangeDependencies, rather than initState, because inheritFromWidgetOfExactType
69+
// cannot be called before initState completes.
70+
// See https://github.com/flutter/flutter/blob/0.0.20/packages/flutter/lib/src/widgets/framework.dart#L3721
71+
if (_storeSub != null) return;
72+
73+
// set the initial state
74+
_state = widget.connect(_store.state as StoreState);
75+
76+
// listen to changes
77+
_storeSub = _store
78+
.substateStream((state) => widget.connect(state as StoreState))
79+
.listen((change) {
80+
setState(() {
81+
_state = change.next;
82+
});
83+
});
84+
}
85+
86+
/// Cancel the store subscription.
87+
@override
88+
@mustCallSuper
89+
void dispose() {
90+
_storeSub.cancel();
91+
super.dispose();
92+
}
93+
94+
@override
95+
Widget build(BuildContext context) =>
96+
widget.build(context, _state, _store.actions);
97+
}
98+
99+
/// [ReduxProvider] provides access to the redux store to descendant widgets.
100+
class ReduxProvider extends InheritedWidget {
101+
ReduxProvider({Key key, @required this.store, @required Widget child})
102+
: super(key: key, child: child);
103+
104+
/// [store] is a reference to the redux store
105+
final Store store;
106+
107+
@override
108+
bool updateShouldNotify(ReduxProvider old) => store != old.store;
109+
}

lib/src/store_connector.dart

Lines changed: 0 additions & 110 deletions
This file was deleted.

pubspec.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,11 @@ dependencies:
1111
built_redux: ">=6.1.1 <8.0.0"
1212
built_value: ^4.0.0
1313

14+
dev_dependencies:
15+
flutter_test:
16+
sdk: flutter
17+
build_runner: ^0.6.0
18+
built_value_generator: ^4.1.0
19+
1420
environment:
1521
sdk: ">=1.19.0 <2.0.0"

0 commit comments

Comments
 (0)