Skip to content

Commit a6bd24c

Browse files
authored
Merge pull request #91 from mfulgo/issue-88
Adds NestedMiddlewareBuilder
2 parents c3512b7 + c0cb8dc commit a6bd24c

File tree

4 files changed

+255
-18
lines changed

4 files changed

+255
-18
lines changed

Diff for: lib/src/middleware.dart

+63-5
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@ class MiddlewareApi<
1010
State extends Built<State, StateBuilder>,
1111
StateBuilder extends Builder<State, StateBuilder>,
1212
Actions extends ReduxActions> {
13-
Store<State, StateBuilder, Actions> _store;
14-
MiddlewareApi(this._store);
13+
final State Function() _state;
14+
final Actions Function() _actions;
15+
16+
MiddlewareApi._(this._state, this._actions);
17+
18+
factory MiddlewareApi(Store<State, StateBuilder, Actions> _store) =>
19+
MiddlewareApi._(() => _store.state, () => _store.actions);
1520

1621
/// [state] returns the current state
17-
State get state => _store.state;
22+
State get state => _state();
1823

1924
/// [actions] returns the actions synced with this redux store
20-
Actions get actions => _store.actions;
25+
Actions get actions => _actions();
2126
}
2227

2328
/// [MiddlewareBuilder] allows you to build a reducer that handles many different actions
@@ -44,6 +49,16 @@ class MiddlewareBuilder<
4449
_map.addAll(other._map);
4550
}
4651

52+
void combineNested<
53+
NestedState extends Built<NestedState, NestedStateBuilder>,
54+
NestedStateBuilder extends Builder<NestedState, NestedStateBuilder>,
55+
NestedActions extends ReduxActions>(
56+
NestedMiddlewareBuilder<State, StateBuilder, Actions, NestedState,
57+
NestedStateBuilder, NestedActions>
58+
other) {
59+
_map.addAll(other._map);
60+
}
61+
4762
/// [build] returns a [Middleware] function that handles all actions added with [add]
4863
Middleware<State, StateBuilder, Actions> build() =>
4964
(MiddlewareApi<State, StateBuilder, Actions> api) =>
@@ -58,9 +73,52 @@ class MiddlewareBuilder<
5873
};
5974
}
6075

76+
class NestedMiddlewareBuilder<
77+
State extends Built<State, StateBuilder>,
78+
StateBuilder extends Builder<State, StateBuilder>,
79+
Actions extends ReduxActions,
80+
NestedState extends Built<NestedState, NestedStateBuilder>,
81+
NestedStateBuilder extends Builder<NestedState, NestedStateBuilder>,
82+
NestedActions extends ReduxActions> {
83+
final _map =
84+
Map<String, MiddlewareHandler<State, StateBuilder, Actions, dynamic>>();
85+
86+
final NestedState Function(State) _stateMapper;
87+
final NestedActions Function(Actions) _actionsMapper;
88+
89+
NestedMiddlewareBuilder(this._stateMapper, this._actionsMapper);
90+
91+
void add<Payload>(
92+
ActionName<Payload> aMgr,
93+
MiddlewareHandler<NestedState, NestedStateBuilder, NestedActions, Payload>
94+
handler) {
95+
_map[aMgr.name] = (api, next, action) {
96+
handler(
97+
MiddlewareApi._(
98+
() => _stateMapper(api.state), () => _actionsMapper(api.actions)),
99+
next,
100+
action as Action<Payload>);
101+
};
102+
}
103+
104+
void addAll(
105+
MiddlewareBuilder<NestedState, NestedStateBuilder, NestedActions> other) {
106+
var adapted = other._map.map((name, handler) => MapEntry(
107+
name,
108+
(MiddlewareApi<State, StateBuilder, Actions> api, ActionHandler next,
109+
Action action) =>
110+
handler(
111+
MiddlewareApi._(() => _stateMapper(api.state),
112+
() => _actionsMapper(api.actions)),
113+
next,
114+
action)));
115+
_map.addAll(adapted);
116+
}
117+
}
118+
61119
/// [MiddlewareHandler] is a function that handles an action in a middleware. Its is only for
62120
/// use with [MiddlewareBuilder]. If you are not using [MiddlewareBuilder] middleware must be
63-
/// decalred as a [Middleware] function.
121+
/// declared as a [Middleware] function.
64122
typedef void MiddlewareHandler<
65123
State extends Built<State, StateBuilder>,
66124
StateBuilder extends Builder<State, StateBuilder>,

Diff for: test/unit/middleware_test.dart

+7
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,12 @@ void main() {
6767
store.actions.middlewareActions.tripleIt(0);
6868
expect(store.state.count, 4);
6969
});
70+
71+
test('combineNested works with SubCounter doubleIt', () async {
72+
setup();
73+
expect(store.state.subCounter.subCount, 1);
74+
store.actions.subCounterActions.doubleIt(0);
75+
expect(store.state.subCounter.subCount, 3);
76+
});
7077
});
7178
}

Diff for: test/unit/test_counter.dart

+48-7
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,34 @@ abstract class CounterActions extends ReduxActions {
1515

1616
ActionDispatcher<int> increment;
1717
ActionDispatcher<int> incrementOther;
18+
SubCounterActions subCounterActions;
1819
MiddlewareActions middlewareActions;
1920
}
2021

22+
abstract class SubCounterActions extends ReduxActions {
23+
SubCounterActions._();
24+
factory SubCounterActions() => new _$SubCounterActions();
25+
26+
ActionDispatcher<int> increment;
27+
ActionDispatcher<int> doubleIt;
28+
}
29+
2130
void _increment(Counter state, Action<int> action, CounterBuilder builder) =>
2231
builder.count = state.count + action.payload;
2332

2433
void _incrementOther(
2534
Counter state, Action<int> action, CounterBuilder builder) =>
2635
builder.otherCount = state.otherCount + action.payload;
2736

37+
void _incrementSubCount(
38+
Counter state, Action<int> action, CounterBuilder builder) =>
39+
builder.subCounter.subCount = state.subCounter.subCount + action.payload;
40+
2841
final reducer = (new ReducerBuilder<Counter, CounterBuilder>()
2942
..add(CounterActionsNames.increment, _increment)
30-
..combine(_otherReducer))
31-
.build();
43+
..combine(_otherReducer)
44+
..add(SubCounterActionsNames.increment, _incrementSubCount)
45+
).build();
3246

3347
final _otherReducer = (new ReducerBuilder<Counter, CounterBuilder>()
3448
..add(CounterActionsNames.incrementOther, _incrementOther));
@@ -38,9 +52,21 @@ abstract class Counter implements Built<Counter, CounterBuilder> {
3852

3953
int get otherCount;
4054

55+
SubCounter get subCounter;
56+
4157
// Built value constructor
4258
Counter._();
43-
factory Counter() => new _$Counter._(count: 1, otherCount: 1);
59+
60+
factory Counter() =>
61+
new _$Counter._(count: 1, otherCount: 1, subCounter: SubCounter());
62+
}
63+
64+
abstract class SubCounter implements Built<SubCounter, SubCounterBuilder> {
65+
int get subCount;
66+
67+
SubCounter._();
68+
69+
factory SubCounter() => new _$SubCounter._(subCount: 1);
4470
}
4571

4672
// Middleware
@@ -54,10 +80,11 @@ abstract class MiddlewareActions extends ReduxActions {
5480
}
5581

5682
var counterMiddleware =
57-
(new MiddlewareBuilder<Counter, CounterBuilder, CounterActions>()
58-
..add(MiddlewareActionsNames.doubleIt, _doubleIt)
59-
..combine(tripleItMiddlewareBuilder))
60-
.build();
83+
(new MiddlewareBuilder<Counter, CounterBuilder, CounterActions>()
84+
..add(MiddlewareActionsNames.doubleIt, _doubleIt)
85+
..combine(tripleItMiddlewareBuilder)
86+
..combineNested(subCountNested)
87+
).build();
6188

6289
void _doubleIt(MiddlewareApi<Counter, CounterBuilder, CounterActions> api,
6390
ActionHandler next, Action<int> action) {
@@ -75,6 +102,20 @@ void _tripleIt(MiddlewareApi<Counter, CounterBuilder, CounterActions> api,
75102
next(action);
76103
}
77104

105+
var subCountNested = NestedMiddlewareBuilder<Counter, CounterBuilder,
106+
CounterActions, SubCounter, SubCounterBuilder, SubCounterActions>(
107+
(c) => c.subCounter, (a) => a.subCounterActions)
108+
..addAll(subCountMiddlewareBuilder);
109+
110+
var subCountMiddlewareBuilder = new MiddlewareBuilder<SubCounter, SubCounterBuilder, SubCounterActions>()
111+
..add(SubCounterActionsNames.doubleIt, _subCounterDoubleIt);
112+
113+
void _subCounterDoubleIt(MiddlewareApi<SubCounter, SubCounterBuilder, SubCounterActions> api,
114+
ActionHandler next, Action<int> action) {
115+
api.actions.increment(api.state.subCount * 2);
116+
next(action);
117+
}
118+
78119
// Change handler
79120

80121
StoreChangeHandlerBuilder<Counter, CounterBuilder,

0 commit comments

Comments
 (0)