@@ -39,16 +39,23 @@ class _AutocompleteFieldState<QueryT extends AutocompleteQuery, ResultT extends
39
39
40
40
void _handleControllerChange () {
41
41
final newQuery = widget.autocompleteIntent ()? .query;
42
+ // First, tear down the old view-model if necessary.
43
+ if (_viewModel != null
44
+ && (newQuery == null
45
+ || ! _viewModel! .acceptsQuery (newQuery))) {
46
+ // The autocomplete interaction has ended, or has switched to a
47
+ // different kind of autocomplete (e.g. @-mention vs. emoji).
48
+ _viewModel! .dispose (); // removes our listener
49
+ _viewModel = null ;
50
+ _resultsToDisplay = [];
51
+ }
52
+ // Then, update the view-model or build a new one.
42
53
if (newQuery != null ) {
43
54
if (_viewModel == null ) {
44
55
_initViewModel (newQuery);
45
- }
46
- _viewModel! .query = newQuery;
47
- } else {
48
- if (_viewModel != null ) {
49
- _viewModel! .dispose (); // removes our listener
50
- _viewModel = null ;
51
- _resultsToDisplay = [];
56
+ } else {
57
+ assert (_viewModel! .acceptsQuery (newQuery));
58
+ _viewModel! .query = newQuery;
52
59
}
53
60
}
54
61
}
@@ -144,7 +151,7 @@ class _AutocompleteFieldState<QueryT extends AutocompleteQuery, ResultT extends
144
151
}
145
152
}
146
153
147
- class ComposeAutocomplete extends AutocompleteField <MentionAutocompleteQuery , MentionAutocompleteResult > {
154
+ class ComposeAutocomplete extends AutocompleteField <ComposeAutocompleteQuery , ComposeAutocompleteResult > {
148
155
const ComposeAutocomplete ({
149
156
super .key,
150
157
required this .narrow,
@@ -159,30 +166,34 @@ class ComposeAutocomplete extends AutocompleteField<MentionAutocompleteQuery, Me
159
166
ComposeContentController get controller => super .controller as ComposeContentController ;
160
167
161
168
@override
162
- AutocompleteIntent <MentionAutocompleteQuery >? autocompleteIntent () => controller.autocompleteIntent ();
169
+ AutocompleteIntent <ComposeAutocompleteQuery >? autocompleteIntent () => controller.autocompleteIntent ();
163
170
164
171
@override
165
- MentionAutocompleteView initViewModel (BuildContext context, MentionAutocompleteQuery query) {
172
+ ComposeAutocompleteView initViewModel (BuildContext context, ComposeAutocompleteQuery query) {
166
173
final store = PerAccountStoreWidget .of (context);
167
- return MentionAutocompleteView . init (store: store , narrow: narrow, query : query );
174
+ return query. initViewModel (store, narrow);
168
175
}
169
176
170
- void _onTapOption (BuildContext context, MentionAutocompleteResult option) {
177
+ void _onTapOption (BuildContext context, ComposeAutocompleteResult option) {
171
178
// Probably the same intent that brought up the option that was tapped.
172
179
// If not, it still shouldn't be off by more than the time it takes
173
180
// to compute the autocomplete results, which we do asynchronously.
174
181
final intent = autocompleteIntent ();
175
182
if (intent == null ) {
176
183
return ; // Shrug.
177
184
}
185
+ final query = intent.query;
178
186
179
187
final store = PerAccountStoreWidget .of (context);
180
188
final String replacementString;
181
189
switch (option) {
182
190
case UserMentionAutocompleteResult (: var userId):
191
+ if (query is ! MentionAutocompleteQuery ) {
192
+ return ; // Shrug; similar to `intent == null` case above.
193
+ }
183
194
// TODO(i18n) language-appropriate space character; check active keyboard?
184
195
// (maybe handle centrally in `controller`)
185
- replacementString = '${mention (store .users [userId ]!, silent : intent . query .silent , users : store .users )} ' ;
196
+ replacementString = '${mention (store .users [userId ]!, silent : query .silent , users : store .users )} ' ;
186
197
}
187
198
188
199
controller.value = intent.textEditingValue.replaced (
@@ -194,26 +205,40 @@ class ComposeAutocomplete extends AutocompleteField<MentionAutocompleteQuery, Me
194
205
}
195
206
196
207
@override
197
- Widget buildItem (BuildContext context, int index, MentionAutocompleteResult option) {
208
+ Widget buildItem (BuildContext context, int index, ComposeAutocompleteResult option) {
209
+ final child = switch (option) {
210
+ MentionAutocompleteResult () => _MentionAutocompleteItem (option: option),
211
+ };
212
+ return InkWell (
213
+ onTap: () {
214
+ _onTapOption (context, option);
215
+ },
216
+ child: child);
217
+ }
218
+ }
219
+
220
+ class _MentionAutocompleteItem extends StatelessWidget {
221
+ const _MentionAutocompleteItem ({required this .option});
222
+
223
+ final MentionAutocompleteResult option;
224
+
225
+ @override
226
+ Widget build (BuildContext context) {
198
227
Widget avatar;
199
228
String label;
200
229
switch (option) {
201
230
case UserMentionAutocompleteResult (: var userId):
202
231
avatar = Avatar (userId: userId, size: 32 , borderRadius: 3 );
203
232
label = PerAccountStoreWidget .of (context).users[userId]! .fullName;
204
233
}
205
- return InkWell (
206
- onTap: () {
207
- _onTapOption (context, option);
208
- },
209
- child: Padding (
210
- padding: const EdgeInsets .symmetric (horizontal: 16.0 , vertical: 8.0 ),
211
- child: Row (
212
- children: [
213
- avatar,
214
- const SizedBox (width: 8 ),
215
- Text (label),
216
- ])));
234
+
235
+ return Padding (
236
+ padding: const EdgeInsets .symmetric (horizontal: 16.0 , vertical: 8.0 ),
237
+ child: Row (children: [
238
+ avatar,
239
+ const SizedBox (width: 8 ),
240
+ Text (label),
241
+ ]));
217
242
}
218
243
}
219
244
0 commit comments