Skip to content

Commit c0f1951

Browse files
committed
autocomplete: Implement new design for @-mention autocomplete items
Implemented new design for @-mention autocomplete items. Added new `contextMenuItemLabel` and `contextMenuItemMeta` color variables to `designVariables` class. Updated autocomplete tests. Fixes: zulip#913
1 parent 49ac433 commit c0f1951

File tree

3 files changed

+67
-10
lines changed

3 files changed

+67
-10
lines changed

lib/widgets/autocomplete.dart

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import 'package:flutter/material.dart';
22

3-
import 'content.dart';
4-
import 'store.dart';
3+
import '../api/model/model.dart';
54
import '../model/autocomplete.dart';
65
import '../model/compose.dart';
76
import '../model/narrow.dart';
87
import 'compose_box.dart';
8+
import 'content.dart';
9+
import 'store.dart';
10+
import 'text.dart';
11+
import 'theme.dart';
912

1013
abstract class AutocompleteField<QueryT extends AutocompleteQuery, ResultT extends AutocompleteResult> extends StatefulWidget {
1114
const AutocompleteField({
@@ -195,24 +198,56 @@ class ComposeAutocomplete extends AutocompleteField<MentionAutocompleteQuery, Me
195198

196199
@override
197200
Widget buildItem(BuildContext context, int index, MentionAutocompleteResult option) {
201+
final designVariables = DesignVariables.of(context);
198202
Widget avatar;
199203
String label;
204+
String? metadata;
205+
200206
switch (option) {
201207
case UserMentionAutocompleteResult(:var userId):
202-
avatar = Avatar(userId: userId, size: 32, borderRadius: 3);
203-
label = PerAccountStoreWidget.of(context).users[userId]!.fullName;
208+
final store = PerAccountStoreWidget.of(context);
209+
final user = store.users[userId]!;
210+
avatar = Avatar(userId: userId, size: 36, borderRadius: 4);
211+
label = user.fullName;
212+
metadata = getDisplayEmailFor(user, store: store);
204213
}
205214
return InkWell(
206215
onTap: () {
207216
_onTapOption(context, option);
208217
},
218+
highlightColor: designVariables.editorButtonPressedBg,
219+
splashFactory: NoSplash.splashFactory,
220+
borderRadius: BorderRadius.circular(5),
209221
child: Padding(
210-
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
222+
padding: const EdgeInsetsDirectional.only(start: 4, end: 8, top: 4, bottom: 4),
211223
child: Row(
212224
children: [
213225
avatar,
214-
const SizedBox(width: 8),
215-
Text(label),
226+
const SizedBox(width: 6),
227+
Expanded(child: Column(
228+
mainAxisSize: MainAxisSize.min,
229+
crossAxisAlignment: CrossAxisAlignment.start,
230+
children: [
231+
Text(
232+
style: TextStyle(
233+
fontSize: 18,
234+
height: 20 / 18,
235+
color: designVariables.contextMenuItemLabel,
236+
)
237+
.merge(weightVariableTextStyle(context, wght: 600)),
238+
overflow: TextOverflow.ellipsis,
239+
maxLines: 1,
240+
label),
241+
if (metadata != null) Text(
242+
style: TextStyle(
243+
fontSize: 14,
244+
height: 16 / 14,
245+
color: designVariables.contextMenuItemMeta,
246+
),
247+
overflow: TextOverflow.ellipsis,
248+
maxLines: 1,
249+
metadata),
250+
])),
216251
])));
217252
}
218253
}

lib/widgets/theme.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,10 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
120120
borderBar: const Color(0x33000000),
121121
contextMenuCancelText: const Color(0xff222222),
122122
contextMenuItemBg: const Color(0xff6159e1),
123+
contextMenuItemLabel: const Color(0xff242631),
124+
contextMenuItemMeta: const Color(0xff626573),
123125
contextMenuItemText: const Color(0xff381da7),
126+
editorButtonPressedBg: const Color(0xff000000).withValues(alpha: 0.06),
124127
icon: const Color(0xff666699),
125128
labelCounterUnread: const Color(0xff222222),
126129
labelEdited: const HSLColor.fromAHSL(0.35, 0, 0, 0).toColor(),
@@ -156,7 +159,10 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
156159
borderBar: Colors.black.withValues(alpha: 0.41),
157160
contextMenuCancelText: const Color(0xffffffff).withValues(alpha: 0.75),
158161
contextMenuItemBg: const Color(0xff7977fe),
162+
contextMenuItemLabel: const Color(0xffdfe1e8),
163+
contextMenuItemMeta: const Color(0xff9194a3),
159164
contextMenuItemText: const Color(0xff9398fd),
165+
editorButtonPressedBg: const Color(0xffffffff).withValues(alpha: 0.06),
160166
icon: const Color(0xff7070c2),
161167
labelCounterUnread: const Color(0xffffffff).withValues(alpha: 0.7),
162168
labelEdited: const HSLColor.fromAHSL(0.35, 0, 0, 1).toColor(),
@@ -199,7 +205,10 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
199205
required this.borderBar,
200206
required this.contextMenuCancelText,
201207
required this.contextMenuItemBg,
208+
required this.contextMenuItemLabel,
209+
required this.contextMenuItemMeta,
202210
required this.contextMenuItemText,
211+
required this.editorButtonPressedBg,
203212
required this.icon,
204213
required this.labelCounterUnread,
205214
required this.labelEdited,
@@ -243,7 +252,10 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
243252
final Color borderBar;
244253
final Color contextMenuCancelText;
245254
final Color contextMenuItemBg;
255+
final Color contextMenuItemLabel;
256+
final Color contextMenuItemMeta;
246257
final Color contextMenuItemText;
258+
final Color editorButtonPressedBg;
247259
final Color icon;
248260
final Color labelCounterUnread;
249261
final Color labelEdited;
@@ -282,7 +294,10 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
282294
Color? borderBar,
283295
Color? contextMenuCancelText,
284296
Color? contextMenuItemBg,
297+
Color? contextMenuItemLabel,
298+
Color? contextMenuItemMeta,
285299
Color? contextMenuItemText,
300+
Color? editorButtonPressedBg,
286301
Color? icon,
287302
Color? labelCounterUnread,
288303
Color? labelEdited,
@@ -316,7 +331,10 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
316331
borderBar: borderBar ?? this.borderBar,
317332
contextMenuCancelText: contextMenuCancelText ?? this.contextMenuCancelText,
318333
contextMenuItemBg: contextMenuItemBg ?? this.contextMenuItemBg,
334+
contextMenuItemLabel: contextMenuItemLabel ?? this.contextMenuItemLabel,
335+
contextMenuItemMeta: contextMenuItemMeta ?? this.contextMenuItemMeta,
319336
contextMenuItemText: contextMenuItemText ?? this.contextMenuItemBg,
337+
editorButtonPressedBg: editorButtonPressedBg ?? this.editorButtonPressedBg,
320338
icon: icon ?? this.icon,
321339
labelCounterUnread: labelCounterUnread ?? this.labelCounterUnread,
322340
labelEdited: labelEdited ?? this.labelEdited,
@@ -357,7 +375,10 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
357375
borderBar: Color.lerp(borderBar, other.borderBar, t)!,
358376
contextMenuCancelText: Color.lerp(contextMenuCancelText, other.contextMenuCancelText, t)!,
359377
contextMenuItemBg: Color.lerp(contextMenuItemBg, other.contextMenuItemBg, t)!,
378+
contextMenuItemLabel: Color.lerp(contextMenuItemLabel, other.contextMenuItemLabel, t)!,
379+
contextMenuItemMeta: Color.lerp(contextMenuItemMeta, other.contextMenuItemMeta, t)!,
360380
contextMenuItemText: Color.lerp(contextMenuItemText, other.contextMenuItemBg, t)!,
381+
editorButtonPressedBg: Color.lerp(editorButtonPressedBg, other.editorButtonPressedBg, t)!,
361382
icon: Color.lerp(icon, other.icon, t)!,
362383
labelCounterUnread: Color.lerp(labelCounterUnread, other.labelCounterUnread, t)!,
363384
labelEdited: Color.lerp(labelEdited, other.labelEdited, t)!,

test/widgets/autocomplete_test.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,16 @@ void main() {
114114

115115
void checkUserShown(User user, PerAccountStore store, {required bool expected}) {
116116
check(find.text(user.fullName).evaluate().length).equals(expected ? 1 : 0);
117+
check(find.text(user.deliveryEmail!).evaluate().length).equals(expected ? 1 : 0);
117118
final avatarFinder =
118119
findAvatarImage(user.userId);
119120
check(avatarFinder.evaluate().length).equals(expected ? 1 : 0);
120121
}
121122

122123
testWidgets('options appear, disappear, and change correctly', (tester) async {
123-
final user1 = eg.user(userId: 1, fullName: 'User One', avatarUrl: 'user1.png');
124-
final user2 = eg.user(userId: 2, fullName: 'User Two', avatarUrl: 'user2.png');
125-
final user3 = eg.user(userId: 3, fullName: 'User Three', avatarUrl: 'user3.png');
124+
final user1 = eg.user(userId: 1, fullName: 'User One', avatarUrl: 'user1.png',deliveryEmail: '[email protected]');
125+
final user2 = eg.user(userId: 2, fullName: 'User Two', avatarUrl: 'user2.png', deliveryEmail: '[email protected]');
126+
final user3 = eg.user(userId: 3, fullName: 'User Three', avatarUrl: 'user3.png', deliveryEmail: '[email protected]');
126127
final composeInputFinder = await setupToComposeInput(tester, users: [user1, user2, user3]);
127128
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
128129

0 commit comments

Comments
 (0)