Skip to content

Commit 552404e

Browse files
committed
autocomplete[nfc]: Use generic fields in AutocompleteViewManager
As we introduce new types of AutocompleteView, managing them could become increasingly challenging without using more generic approach. This uses a map for the polymorphic views to enable storing a set of managed views for each AutocompleteView subtype.
1 parent a14add6 commit 552404e

File tree

1 file changed

+38
-26
lines changed

1 file changed

+38
-26
lines changed

lib/model/autocomplete.dart

+38-26
Original file line numberDiff line numberDiff line change
@@ -110,46 +110,59 @@ class AutocompleteIntent<Q extends AutocompleteQuery> {
110110
///
111111
/// On reassemble, call [reassemble].
112112
class AutocompleteViewManager {
113-
final Set<MentionAutocompleteView> _mentionAutocompleteViews = {};
113+
final Map<Type, Set<AutocompleteView>> _views = {};
114114

115115
AutocompleteDataCache autocompleteDataCache = AutocompleteDataCache();
116116

117-
void registerMentionAutocomplete(MentionAutocompleteView view) {
118-
final added = _mentionAutocompleteViews.add(view);
117+
Set<AutocompleteView> get _allViews => _views.values.fold(
118+
{},
119+
(previousValue, element) => previousValue..addAll(element)
120+
);
121+
122+
Set<T> _getViewsOfType<T extends AutocompleteView>() {
123+
return _views[T]?.cast() ?? {};
124+
}
125+
126+
void register<T extends AutocompleteView>(T view) {
127+
final typedViews = _views[view.runtimeType] ?? {};
128+
final added = typedViews.add(view);
119129
assert(added);
130+
_views[view.runtimeType] = typedViews;
120131
}
121132

122-
void unregisterMentionAutocomplete(MentionAutocompleteView view) {
123-
final removed = _mentionAutocompleteViews.remove(view);
133+
void unregister<T extends AutocompleteView>(T view) {
134+
final typedViews = _views[view.runtimeType] ?? {};
135+
final removed = typedViews.remove(view);
124136
assert(removed);
137+
_views[view.runtimeType] = typedViews;
125138
}
126139

127140
void handleRealmUserAddEvent(RealmUserAddEvent event) {
128-
for (final view in _mentionAutocompleteViews) {
141+
for (final view in _getViewsOfType<MentionAutocompleteView>()) {
129142
view.refreshStaleUserResults();
130143
}
131144
}
132145

133146
void handleRealmUserRemoveEvent(RealmUserRemoveEvent event) {
134-
for (final view in _mentionAutocompleteViews) {
147+
for (final view in _getViewsOfType<MentionAutocompleteView>()) {
135148
view.refreshStaleUserResults();
136149
}
137150
autocompleteDataCache.invalidateUser(event.userId);
138151
}
139152

140153
void handleRealmUserUpdateEvent(RealmUserUpdateEvent event) {
141-
for (final view in _mentionAutocompleteViews) {
154+
for (final view in _getViewsOfType<MentionAutocompleteView>()) {
142155
view.refreshStaleUserResults();
143156
}
144157
autocompleteDataCache.invalidateUser(event.userId);
145158
}
146159

147160
/// Called when the app is reassembled during debugging, e.g. for hot reload.
148161
///
149-
/// Calls [MentionAutocompleteView.reassemble] for all that are registered.
162+
/// Calls [AutocompleteView.reassemble] for all that are registered.
150163
///
151164
void reassemble() {
152-
for (final view in _mentionAutocompleteViews) {
165+
for (final view in _allViews) {
153166
view.reassemble();
154167
}
155168
}
@@ -188,7 +201,19 @@ abstract class AutocompleteView<Q extends AutocompleteQuery, R extends Autocompl
188201
final List<R> Function(List<R> results)? resultsFilter;
189202
final PerAccountStore store;
190203

191-
AutocompleteView({required this.dataProvider, this.resultsFilter, required this.store});
204+
AutocompleteView({required this.dataProvider, this.resultsFilter, required this.store}) {
205+
store.autocompleteViewManager.register(this);
206+
}
207+
208+
209+
@override
210+
void dispose() {
211+
store.autocompleteViewManager.unregister(this);
212+
// We cancel in-progress computations by checking [hasListeners] between tasks.
213+
// After [super.dispose] is called, [hasListeners] returns false.
214+
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
215+
super.dispose();
216+
}
192217

193218
Q? get query => _query;
194219
Q? _query;
@@ -283,21 +308,8 @@ class MentionAutocompleteDataProvider extends AutocompleteDataProvider<Object, M
283308

284309
class MentionAutocompleteView extends AutocompleteView<MentionAutocompleteQuery, MentionAutocompleteResult> {
285310

286-
MentionAutocompleteView.init({
287-
required super.store,
288-
}) : super(dataProvider: MentionAutocompleteDataProvider(store: store)) {
289-
store.autocompleteViewManager.registerMentionAutocomplete(this);
290-
}
291-
292-
293-
@override
294-
void dispose() {
295-
store.autocompleteViewManager.unregisterMentionAutocomplete(this);
296-
// We cancel in-progress computations by checking [hasListeners] between tasks.
297-
// After [super.dispose] is called, [hasListeners] returns false.
298-
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
299-
super.dispose();
300-
}
311+
MentionAutocompleteView.init({required super.store}) : super(
312+
dataProvider: MentionAutocompleteDataProvider(store: store));
301313

302314
/// Recompute user results for the current query, if any.
303315
///

0 commit comments

Comments
 (0)