/
connector.dart
104 lines (96 loc) · 2.95 KB
/
connector.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import 'basic.dart';
/// Define a basic connector for immutable state.
/// /// Example:
/// class State {
/// final SubState sub;
/// final String name;
/// const State({this.sub, this.name});
/// }
///
/// class SubState {}
///
/// class Conn<State, SubState> extends ImmutableConn<State, SubState> {
/// SubState get(State state) => state.sub;
/// State set(State state, SubState sub) => State(sub: sub, name: state.name);
/// }
abstract class ImmutableConn<T, P> implements AbstractConnector<T, P> {
const ImmutableConn();
T set(T state, P subState);
@override
SubReducer<T> subReducer(Reducer<P> reducer) {
return reducer == null
? null
: (T state, Action action, bool isStateCopied) {
final P props = get(state);
if (props == null) {
return state;
}
final P newProps = reducer(props, action);
final bool hasChanged = !identical(newProps, props);
if (hasChanged) {
final T result = set(state, newProps);
assert(result != null, 'Expected to return a non-null value.');
return result;
}
return state;
};
}
}
/// Definition of Cloneable
abstract class Cloneable<T extends Cloneable<T>> {
T clone();
}
/// how to clone an object
dynamic _clone<T>(T state) {
if (state is Cloneable) {
return state.clone();
} else if (state is List) {
return state.toList();
} else if (state is Map<String, dynamic>) {
return <String, dynamic>{}..addAll(state);
} else if (state == null) {
return null;
} else {
throw ArgumentError(
'Could not clone this state of type ${state.runtimeType}.');
}
}
/// Define a basic connector for mutable state.
/// /// Example:
/// class State implments Cloneable<State>{
/// SubState sub;
/// String name;
/// State({this.sub, this.name});
///
/// State clone() => State(sub: sub, name: name);
/// }
///
/// class SubState {}
///
/// class Conn<State, SubState> extends MutableConn<State, SubState> {
/// SubState get(State state) => state.sub;
/// void set(State state, SubState sub) => state.sub = sub;
/// }
abstract class MutableConn<T, P> implements AbstractConnector<T, P> {
const MutableConn();
void set(T state, P subState);
@override
SubReducer<T> subReducer(Reducer<P> reducer) {
return reducer == null
? null
: (T state, Action action, bool isStateCopied) {
final P props = get(state);
if (props == null) {
return state;
}
final P newProps = reducer(props, action);
final bool hasChanged = newProps != props;
final T copy =
(hasChanged && !isStateCopied) ? _clone<T>(state) : state;
if (hasChanged) {
set(copy, newProps);
}
return copy;
};
}
}