Skip to content

Commit 42f6cff

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 84b8e50 commit 42f6cff

File tree

1 file changed

+37
-20
lines changed

1 file changed

+37
-20
lines changed

lib/model/autocomplete.dart

+37-20
Original file line numberDiff line numberDiff line change
@@ -111,34 +111,51 @@ class AutocompleteIntent<Q extends AutocompleteQuery> {
111111
///
112112
/// On reassemble, call [reassemble].
113113
class AutocompleteViewManager {
114-
final Set<MentionAutocompleteView> _mentionAutocompleteViews = {};
114+
final Map<Type, Set<AutocompleteView>> _views = {};
115115

116116
AutocompleteDataCache autocompleteDataCache = AutocompleteDataCache();
117117

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

123-
void unregisterMentionAutocomplete(MentionAutocompleteView view) {
124-
final removed = _mentionAutocompleteViews.remove(view);
132+
void unregister<T extends AutocompleteView>(T view) {
133+
final typedViews = _views[view.runtimeType] ?? {};
134+
final removed = typedViews.remove(view);
125135
assert(removed);
136+
_views[view.runtimeType] = typedViews;
126137
}
127138

128139
void handleRealmUserRemoveEvent(RealmUserRemoveEvent event) {
140+
for (final view in _getViewsOfType<MentionAutocompleteView>()) {
141+
view.reassemble();
142+
}
129143
autocompleteDataCache.invalidateUser(event.userId);
130144
}
131145

132146
void handleRealmUserUpdateEvent(RealmUserUpdateEvent event) {
147+
for (final view in _getViewsOfType<MentionAutocompleteView>()) {
148+
view.reassemble();
149+
}
133150
autocompleteDataCache.invalidateUser(event.userId);
134151
}
135152

136153
/// Called when the app is reassembled during debugging, e.g. for hot reload.
137154
///
138-
/// Calls [MentionAutocompleteView.reassemble] for all that are registered.
155+
/// Calls [AutocompleteView.reassemble] for all that are registered.
139156
///
140157
void reassemble() {
141-
for (final view in _mentionAutocompleteViews) {
158+
for (final view in _allViews) {
142159
view.reassemble();
143160
}
144161
}
@@ -185,7 +202,18 @@ abstract class AutocompleteView<Q extends AutocompleteQuery, R extends Autocompl
185202
final List<R> Function(List<R> results)? resultsFilter;
186203
final PerAccountStore store;
187204

188-
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+
@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+
}
189217

190218
Q? get query => _query;
191219
Q? _query;
@@ -319,18 +347,7 @@ class MentionAutocompleteView extends AutocompleteView<MentionAutocompleteQuery,
319347
required Narrow narrow,
320348
}) : super(dataProvider: MentionAutocompleteDataProvider(
321349
store: store,
322-
narrow: narrow)) {
323-
store.autocompleteViewManager.registerMentionAutocomplete(this);
324-
}
325-
326-
@override
327-
void dispose() {
328-
store.autocompleteViewManager.unregisterMentionAutocomplete(this);
329-
// We cancel in-progress computations by checking [hasListeners] between tasks.
330-
// After [super.dispose] is called, [hasListeners] returns false.
331-
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
332-
super.dispose();
333-
}
350+
narrow: narrow));
334351
}
335352

336353
abstract class AutocompleteQuery {

0 commit comments

Comments
 (0)