Skip to content

Commit e35da52

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 7fca5c5 commit e35da52

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

lib/model/autocomplete.dart

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -111,34 +111,57 @@ 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;
137+
}
138+
139+
void handleRealmUserAddEvent(RealmUserAddEvent event) {
140+
for (final view in _getViewsOfType<MentionAutocompleteView>()) {
141+
view.reassemble();
142+
}
126143
}
127144

128145
void handleRealmUserRemoveEvent(RealmUserRemoveEvent event) {
146+
for (final view in _getViewsOfType<MentionAutocompleteView>()) {
147+
view.reassemble();
148+
}
129149
autocompleteDataCache.invalidateUser(event.userId);
130150
}
131151

132152
void handleRealmUserUpdateEvent(RealmUserUpdateEvent event) {
153+
for (final view in _getViewsOfType<MentionAutocompleteView>()) {
154+
view.reassemble();
155+
}
133156
autocompleteDataCache.invalidateUser(event.userId);
134157
}
135158

136159
/// Called when the app is reassembled during debugging, e.g. for hot reload.
137160
///
138-
/// Calls [MentionAutocompleteView.reassemble] for all that are registered.
161+
/// Calls [AutocompleteView.reassemble] for all that are registered.
139162
///
140163
void reassemble() {
141-
for (final view in _mentionAutocompleteViews) {
164+
for (final view in _allViews) {
142165
view.reassemble();
143166
}
144167
}
@@ -185,7 +208,18 @@ abstract class AutocompleteView<Q extends AutocompleteQuery, R extends Autocompl
185208
final List<R> Function(List<R> results)? resultsFilter;
186209
final PerAccountStore store;
187210

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

190224
Q? get query => _query;
191225
Q? _query;
@@ -320,18 +354,7 @@ class MentionAutocompleteView extends AutocompleteView<MentionAutocompleteQuery,
320354
required Narrow narrow,
321355
}) : super(dataProvider: MentionAutocompleteDataProvider(
322356
store: store,
323-
narrow: narrow)) {
324-
store.autocompleteViewManager.registerMentionAutocomplete(this);
325-
}
326-
327-
@override
328-
void dispose() {
329-
store.autocompleteViewManager.unregisterMentionAutocomplete(this);
330-
// We cancel in-progress computations by checking [hasListeners] between tasks.
331-
// After [super.dispose] is called, [hasListeners] returns false.
332-
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
333-
super.dispose();
334-
}
357+
narrow: narrow));
335358
}
336359

337360
abstract class AutocompleteQuery {

0 commit comments

Comments
 (0)