Skip to content

Commit 005ca86

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 5cc07b9 commit 005ca86

File tree

1 file changed

+39
-26
lines changed

1 file changed

+39
-26
lines changed

lib/model/autocomplete.dart

+39-26
Original file line numberDiff line numberDiff line change
@@ -110,46 +110,60 @@ 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 _foldedViews => _views.values.fold(
118+
<AutocompleteView>{},
119+
(previousValue, element) => previousValue..addAll(element)
120+
);
121+
122+
void register<T extends AutocompleteView>(T view) {
123+
final typedViews = _views[T] ?? {};
124+
final added = typedViews.add(view);
119125
assert(added);
126+
_views[T] = typedViews;
120127
}
121128

122-
void unregisterMentionAutocomplete(MentionAutocompleteView view) {
123-
final removed = _mentionAutocompleteViews.remove(view);
129+
void unregister<T extends AutocompleteView>(T view) {
130+
final typedViews = _views[T] ?? {};
131+
final removed = typedViews.remove(view);
124132
assert(removed);
133+
_views[T] = typedViews;
134+
}
135+
136+
Set<T> getTypedViews<T extends AutocompleteView>() {
137+
final res = _views[T] ?? {};
138+
return res.cast();
125139
}
126140

127141
void handleRealmUserAddEvent(RealmUserAddEvent event) {
128-
for (final view in _mentionAutocompleteViews) {
142+
for (final view in getTypedViews<MentionAutocompleteView>()) {
129143
view.refreshStaleUserResults();
130144
}
131145
}
132146

133147
void handleRealmUserRemoveEvent(RealmUserRemoveEvent event) {
134-
for (final view in _mentionAutocompleteViews) {
148+
for (final view in getTypedViews<MentionAutocompleteView>()) {
135149
view.refreshStaleUserResults();
136150
}
137151
autocompleteDataCache.invalidateUser(event.userId);
138152
}
139153

140154
void handleRealmUserUpdateEvent(RealmUserUpdateEvent event) {
141-
for (final view in _mentionAutocompleteViews) {
155+
for (final view in getTypedViews<MentionAutocompleteView>()) {
142156
view.refreshStaleUserResults();
143157
}
144158
autocompleteDataCache.invalidateUser(event.userId);
145159
}
146160

147161
/// Called when the app is reassembled during debugging, e.g. for hot reload.
148162
///
149-
/// Calls [MentionAutocompleteView.reassemble] for all that are registered.
163+
/// Calls [AutocompleteView.reassemble] for all that are registered.
150164
///
151165
void reassemble() {
152-
for (final view in _mentionAutocompleteViews) {
166+
for (final view in _foldedViews) {
153167
view.reassemble();
154168
}
155169
}
@@ -188,7 +202,19 @@ abstract class AutocompleteView<Q extends AutocompleteQuery, R extends Autocompl
188202
final List<R> Function(List<R> results)? resultsFilter;
189203
final PerAccountStore store;
190204

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

193219
Q? get query => _query;
194220
Q? _query;
@@ -283,21 +309,8 @@ class MentionAutocompleteDataProvider extends AutocompleteDataProvider<Object, M
283309

284310
class MentionAutocompleteView extends AutocompleteView<MentionAutocompleteQuery, MentionAutocompleteResult> {
285311

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-
}
312+
MentionAutocompleteView.init({required super.store}) : super(
313+
dataProvider: MentionAutocompleteDataProvider(store: store));
301314

302315
/// Recompute user results for the current query, if any.
303316
///

0 commit comments

Comments
 (0)