Skip to content

Commit 033e3b7

Browse files
committed
autocomplete [nfc]: Factor out generic AutocompleteView
The mechanism of query and results, is tricky. It's also generic to the idea of autocomplete in general, is not specific to autocomplete on @-mentions vs. topics vs. anything else. So this commit factors it out into the generic class AutocompleteView which MentionAutocompleteView uses.
1 parent ba74abd commit 033e3b7

File tree

1 file changed

+44
-33
lines changed

1 file changed

+44
-33
lines changed

lib/model/autocomplete.dart

+44-33
Original file line numberDiff line numberDiff line change
@@ -156,45 +156,22 @@ class AutocompleteViewManager {
156156
}
157157
}
158158

159-
/// A view-model for a mention-autocomplete interaction.
159+
/// A generic view-model for an autocomplete interaction.
160160
///
161161
/// The owner of one of these objects must call [dispose] when the object
162162
/// will no longer be used, in order to free resources on the [PerAccountStore].
163163
///
164164
/// Lifecycle:
165-
/// * Create with [init].
165+
/// * Instantiate.
166166
/// * Add listeners with [addListener].
167167
/// * Use the [query] setter to start a search for a query.
168168
/// * On reassemble, call [reassemble].
169169
/// * When the object will no longer be used, call [dispose] to free
170170
/// resources on the [PerAccountStore].
171-
class MentionAutocompleteView extends ChangeNotifier {
172-
MentionAutocompleteView._({required this.store, required this.narrow});
173-
174-
factory MentionAutocompleteView.init({
175-
required PerAccountStore store,
176-
required Narrow narrow,
177-
}) {
178-
final view = MentionAutocompleteView._(store: store, narrow: narrow);
179-
store.autocompleteViewManager.registerMentionAutocomplete(view);
180-
return view;
181-
}
182-
183-
@override
184-
void dispose() {
185-
store.autocompleteViewManager.unregisterMentionAutocomplete(this);
186-
// We cancel in-progress computations by checking [hasListeners] between tasks.
187-
// After [super.dispose] is called, [hasListeners] returns false.
188-
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
189-
super.dispose();
190-
}
191-
192-
final PerAccountStore store;
193-
final Narrow narrow;
194-
195-
MentionAutocompleteQuery? get query => _query;
196-
MentionAutocompleteQuery? _query;
197-
set query(MentionAutocompleteQuery? query) {
171+
abstract class AutocompleteView<Q, R> extends ChangeNotifier {
172+
Q? get query => _query;
173+
Q? _query;
174+
set query(Q? query) {
198175
_query = query;
199176
if (query != null) {
200177
_startSearch(query);
@@ -219,11 +196,11 @@ class MentionAutocompleteView extends ChangeNotifier {
219196
}
220197
}
221198

222-
Iterable<MentionAutocompleteResult> get results => _results;
223-
List<MentionAutocompleteResult> _results = [];
199+
Iterable<R> get results => _results;
200+
List<R> _results = [];
224201

225-
_startSearch(MentionAutocompleteQuery query) async {
226-
List<MentionAutocompleteResult>? newResults;
202+
_startSearch(Q query) async {
203+
List<R>? newResults;
227204

228205
while (true) {
229206
try {
@@ -244,6 +221,40 @@ class MentionAutocompleteView extends ChangeNotifier {
244221
notifyListeners();
245222
}
246223

224+
Future<List<R>?> _computeResults(Q query);
225+
}
226+
227+
/// A view-model for a mention-autocomplete interaction.
228+
///
229+
/// The owner of one of these objects must call [dispose] when the object
230+
/// will no longer be used, in order to free resources on the [PerAccountStore].
231+
///
232+
/// resources on the [PerAccountStore].
233+
class MentionAutocompleteView extends AutocompleteView<MentionAutocompleteQuery, MentionAutocompleteResult> {
234+
MentionAutocompleteView._({required this.store, required this.narrow});
235+
236+
factory MentionAutocompleteView.init({
237+
required PerAccountStore store,
238+
required Narrow narrow,
239+
}) {
240+
final view = MentionAutocompleteView._(store: store, narrow: narrow);
241+
store.autocompleteViewManager.registerMentionAutocomplete(view);
242+
return view;
243+
}
244+
245+
@override
246+
void dispose() {
247+
store.autocompleteViewManager.unregisterMentionAutocomplete(this);
248+
// We cancel in-progress computations by checking [hasListeners] between tasks.
249+
// After [super.dispose] is called, [hasListeners] returns false.
250+
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
251+
super.dispose();
252+
}
253+
254+
final PerAccountStore store;
255+
final Narrow narrow;
256+
257+
@override
247258
Future<List<MentionAutocompleteResult>?> _computeResults(MentionAutocompleteQuery query) async {
248259
final List<MentionAutocompleteResult> results = [];
249260
final Iterable<User> users = store.users.values;

0 commit comments

Comments
 (0)