Skip to content

Commit 3187d37

Browse files
committed
new-dm: Show user status emoji
1 parent 00d7712 commit 3187d37

File tree

2 files changed

+87
-25
lines changed

2 files changed

+87
-25
lines changed

lib/widgets/new_dm_sheet.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ class _SelectedUserChip extends StatelessWidget {
314314
fontSize: 16,
315315
height: 16 / 16,
316316
color: designVariables.labelMenuButton)))),
317+
UserStatusEmoji(userId: userId, size: 16, notoColorEmojiTextSize: 13.3),
318+
SizedBox(width: 4),
317319
])));
318320
}
319321
}
@@ -412,7 +414,14 @@ class _NewDmUserListItem extends StatelessWidget {
412414
Avatar(userId: userId, size: 32, borderRadius: 3),
413415
SizedBox(width: 8),
414416
Expanded(
415-
child: Text(store.userDisplayName(userId),
417+
child: Text.rich(
418+
TextSpan(
419+
children: [
420+
TextSpan(text: store.userDisplayName(userId)),
421+
UserStatusEmoji.asWidgetSpan(userId: userId, size: 17,
422+
notoColorEmojiTextSize: 14),
423+
]
424+
),
416425
style: TextStyle(
417426
fontSize: 17,
418427
height: 19 / 17,

test/widgets/new_dm_sheet_test.dart

Lines changed: 77 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import 'package:flutter/material.dart';
33
import 'package:flutter_checks/flutter_checks.dart';
44
import 'package:flutter_test/flutter_test.dart';
55
import 'package:zulip/api/model/model.dart';
6+
import 'package:zulip/basic.dart';
67
import 'package:zulip/widgets/app_bar.dart';
78
import 'package:zulip/widgets/compose_box.dart';
89
import 'package:zulip/widgets/content.dart';
10+
import 'package:zulip/widgets/emoji.dart';
911
import 'package:zulip/widgets/home.dart';
1012
import 'package:zulip/widgets/icons.dart';
1113
import 'package:zulip/widgets/new_dm_sheet.dart';
@@ -21,6 +23,7 @@ import 'test_app.dart';
2123

2224
Future<void> setupSheet(WidgetTester tester, {
2325
required List<User> users,
26+
List<(int userId, UserStatusChange change)>? userStatuses,
2427
}) async {
2528
addTearDown(testBinding.reset);
2629

@@ -31,6 +34,7 @@ Future<void> setupSheet(WidgetTester tester, {
3134
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
3235
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
3336
await store.addUsers(users);
37+
await store.changeUserStatuses(userStatuses ?? []);
3438

3539
await tester.pumpWidget(TestZulipApp(
3640
navigatorObservers: [testNavObserver],
@@ -61,7 +65,8 @@ void main() {
6165
}
6266

6367
Finder findUserTile(User user) =>
64-
find.widgetWithText(InkWell, user.fullName).first;
68+
find.ancestor(of: find.textContaining(user.fullName),
69+
matching: find.byType(InkWell)).first;
6570

6671
Finder findUserChip(User user) {
6772
final findAvatar = find.byWidgetPredicate((widget) =>
@@ -114,18 +119,18 @@ void main() {
114119

115120
testWidgets('shows all users initially', (tester) async {
116121
await setupSheet(tester, users: testUsers);
117-
check(find.text('Alice Anderson')).findsOne();
118-
check(find.text('Bob Brown')).findsOne();
119-
check(find.text('Charlie Carter')).findsOne();
122+
check(find.textContaining('Alice Anderson')).findsOne();
123+
check(find.textContaining('Bob Brown')).findsOne();
124+
check(find.textContaining('Charlie Carter')).findsOne();
120125
});
121126

122127
testWidgets('shows filtered users based on search', (tester) async {
123128
await setupSheet(tester, users: testUsers);
124129
await tester.enterText(find.byType(TextField), 'Alice');
125130
await tester.pump();
126-
check(find.text('Alice Anderson')).findsOne();
127-
check(find.text('Charlie Carter')).findsNothing();
128-
check(find.text('Bob Brown')).findsNothing();
131+
check(find.textContaining('Alice Anderson')).findsOne();
132+
check(find.textContaining('Charlie Carter')).findsNothing();
133+
check(find.textContaining('Bob Brown')).findsNothing();
129134
});
130135

131136
// TODO test sorting by recent-DMs
@@ -135,43 +140,43 @@ void main() {
135140
await setupSheet(tester, users: testUsers);
136141
await tester.enterText(find.byType(TextField), 'alice');
137142
await tester.pump();
138-
check(find.text('Alice Anderson')).findsOne();
143+
check(find.textContaining('Alice Anderson')).findsOne();
139144

140145
await tester.enterText(find.byType(TextField), 'ALICE');
141146
await tester.pump();
142-
check(find.text('Alice Anderson')).findsOne();
147+
check(find.textContaining('Alice Anderson')).findsOne();
143148
});
144149

145150
testWidgets('partial name and last name search handling', (tester) async {
146151
await setupSheet(tester, users: testUsers);
147152

148153
await tester.enterText(find.byType(TextField), 'Ali');
149154
await tester.pump();
150-
check(find.text('Alice Anderson')).findsOne();
151-
check(find.text('Bob Brown')).findsNothing();
152-
check(find.text('Charlie Carter')).findsNothing();
155+
check(find.textContaining('Alice Anderson')).findsOne();
156+
check(find.textContaining('Bob Brown')).findsNothing();
157+
check(find.textContaining('Charlie Carter')).findsNothing();
153158

154159
await tester.enterText(find.byType(TextField), 'Anderson');
155160
await tester.pump();
156-
check(find.text('Alice Anderson')).findsOne();
157-
check(find.text('Charlie Carter')).findsNothing();
158-
check(find.text('Bob Brown')).findsNothing();
161+
check(find.textContaining('Alice Anderson')).findsOne();
162+
check(find.textContaining('Charlie Carter')).findsNothing();
163+
check(find.textContaining('Bob Brown')).findsNothing();
159164

160165
await tester.enterText(find.byType(TextField), 'son');
161166
await tester.pump();
162-
check(find.text('Alice Anderson')).findsOne();
163-
check(find.text('Charlie Carter')).findsNothing();
164-
check(find.text('Bob Brown')).findsNothing();
167+
check(find.textContaining('Alice Anderson')).findsOne();
168+
check(find.textContaining('Charlie Carter')).findsNothing();
169+
check(find.textContaining('Bob Brown')).findsNothing();
165170
});
166171

167172
testWidgets('shows empty state when no users match', (tester) async {
168173
await setupSheet(tester, users: testUsers);
169174
await tester.enterText(find.byType(TextField), 'Zebra');
170175
await tester.pump();
171-
check(find.text('No users found')).findsOne();
172-
check(find.text('Alice Anderson')).findsNothing();
173-
check(find.text('Bob Brown')).findsNothing();
174-
check(find.text('Charlie Carter')).findsNothing();
176+
check(find.textContaining('No users found')).findsOne();
177+
check(find.textContaining('Alice Anderson')).findsNothing();
178+
check(find.textContaining('Bob Brown')).findsNothing();
179+
check(find.textContaining('Charlie Carter')).findsNothing();
175180
});
176181

177182
testWidgets('search text clears when user is selected', (tester) async {
@@ -241,7 +246,7 @@ void main() {
241246
await tester.tap(findUserTile(eg.selfUser));
242247
await tester.pump();
243248
checkUserSelected(tester, eg.selfUser, true);
244-
check(find.text(eg.selfUser.fullName)).findsExactly(2);
249+
check(find.textContaining(eg.selfUser.fullName)).findsExactly(2);
245250

246251
await tester.tap(findUserTile(otherUser));
247252
await tester.pump();
@@ -253,7 +258,7 @@ void main() {
253258
final otherUser = eg.user(fullName: 'Other User');
254259
await setupSheet(tester, users: [eg.selfUser, otherUser]);
255260

256-
check(find.text(eg.selfUser.fullName)).findsOne();
261+
check(find.textContaining(eg.selfUser.fullName)).findsOne();
257262

258263
await tester.tap(findUserTile(otherUser));
259264
await tester.pump();
@@ -274,6 +279,54 @@ void main() {
274279
});
275280
});
276281

282+
testWidgets('status emoji is set -> emoji is displayed', (tester) async {
283+
void checkTileStatusEmoji(User user, {required bool isPresent}) {
284+
final statusEmojiFinder = find.ancestor(of: find.byType(UnicodeEmojiWidget),
285+
matching: find.byType(UserStatusEmoji));
286+
287+
final tileStatusFinder = find.descendant(of: findUserTile(user),
288+
matching: statusEmojiFinder);
289+
check(tileStatusFinder).findsExactly(isPresent ? 1 : 0);
290+
}
291+
292+
void checkChipStatusEmoji(User user, {required bool isPresent}) {
293+
final statusEmojiFinder = find.ancestor(of: find.byType(UnicodeEmojiWidget),
294+
matching: find.byType(UserStatusEmoji));
295+
296+
final chipStatusFinder = find.descendant(of: findUserChip(user),
297+
matching: statusEmojiFinder);
298+
check(chipStatusFinder).findsExactly(isPresent ? 1 : 0);
299+
}
300+
301+
final user1 = eg.user(userId: 1, fullName: 'User 1');
302+
final user2 = eg.user(userId: 2, fullName: 'User 2');
303+
await setupSheet(tester, users: [user1, user2], userStatuses: [
304+
(
305+
user1.userId,
306+
UserStatusChange(
307+
text: OptionSome('Busy'),
308+
emoji: OptionSome(StatusEmoji(emojiName: 'working_on_it',
309+
emojiCode: '1f6e0', reactionType: ReactionType.unicodeEmoji)))
310+
),
311+
]);
312+
313+
checkTileStatusEmoji(user1, isPresent: true);
314+
checkTileStatusEmoji(user2, isPresent: false);
315+
check(findUserChip(user1)).findsNothing();
316+
check(findUserChip(user2)).findsNothing();
317+
318+
await tester.tap(findUserTile(user1));
319+
await tester.tap(findUserTile(user2));
320+
await tester.pump();
321+
322+
checkTileStatusEmoji(user1, isPresent: true);
323+
checkTileStatusEmoji(user2, isPresent: false);
324+
check(findUserChip(user1)).findsOne();
325+
check(findUserChip(user2)).findsOne();
326+
checkChipStatusEmoji(user1, isPresent: true);
327+
checkChipStatusEmoji(user2, isPresent: false);
328+
});
329+
277330
group('navigation to DM Narrow', () {
278331
Future<void> runAndCheck(WidgetTester tester, {
279332
required List<User> users,

0 commit comments

Comments
 (0)