Skip to content

Commit 83e473a

Browse files
committed
new-dm: Show user status emoji
1 parent 90e3683 commit 83e473a

File tree

2 files changed

+108
-28
lines changed

2 files changed

+108
-28
lines changed

lib/widgets/new_dm_sheet.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ class _SelectedUserChip extends StatelessWidget {
317317
fontSize: 16,
318318
height: 16 / 16,
319319
color: designVariables.labelMenuButton)))),
320+
UserStatusEmoji(userId: userId, size: 16,
321+
padding: EdgeInsetsDirectional.only(end: 4)),
320322
])));
321323
}
322324
}
@@ -415,7 +417,11 @@ class _NewDmUserListItem extends StatelessWidget {
415417
Avatar(userId: userId, size: 32, borderRadius: 3),
416418
SizedBox(width: 8),
417419
Expanded(
418-
child: Text(store.userDisplayName(userId),
420+
child: Text.rich(
421+
TextSpan(text: store.userDisplayName(userId), children: [
422+
UserStatusEmoji.asWidgetSpan(userId: userId, fontSize: 17,
423+
textScaler: MediaQuery.textScalerOf(context)),
424+
]),
419425
style: TextStyle(
420426
fontSize: 17,
421427
height: 19 / 17,

test/widgets/new_dm_sheet_test.dart

Lines changed: 101 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ 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';
7+
import 'package:zulip/model/store.dart';
68
import 'package:zulip/widgets/app_bar.dart';
79
import 'package:zulip/widgets/compose_box.dart';
810
import 'package:zulip/widgets/content.dart';
@@ -19,6 +21,8 @@ import '../model/test_store.dart';
1921
import '../test_navigation.dart';
2022
import 'test_app.dart';
2123

24+
late PerAccountStore store;
25+
2226
Future<void> setupSheet(WidgetTester tester, {
2327
required List<User> users,
2428
List<int>? mutedUserIds,
@@ -30,7 +34,7 @@ Future<void> setupSheet(WidgetTester tester, {
3034
..onPushed = (route, _) => lastPushedRoute = route;
3135

3236
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
33-
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
37+
store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
3438
await store.addUsers(users);
3539
if (mutedUserIds != null) {
3640
await store.setMutedUsers(mutedUserIds);
@@ -65,7 +69,8 @@ void main() {
6569
}
6670

6771
Finder findUserTile(User user) =>
68-
find.widgetWithText(InkWell, user.fullName).first;
72+
find.ancestor(of: find.textContaining(user.fullName),
73+
matching: find.byType(InkWell)).first;
6974

7075
Finder findUserChip(User user) {
7176
final findAvatar = find.byWidgetPredicate((widget) =>
@@ -120,23 +125,23 @@ void main() {
120125

121126
testWidgets('shows all non-muted users initially', (tester) async {
122127
await setupSheet(tester, users: testUsers, mutedUserIds: [mutedUser.userId]);
123-
check(find.text('Alice Anderson')).findsOne();
124-
check(find.text('Bob Brown')).findsOne();
125-
check(find.text('Charlie Carter')).findsOne();
128+
check(find.textContaining('Alice Anderson')).findsOne();
129+
check(find.textContaining('Bob Brown')).findsOne();
130+
check(find.textContaining('Charlie Carter')).findsOne();
126131

127132
check(find.byIcon(ZulipIcons.check_circle_unchecked)).findsExactly(3);
128133
check(find.byIcon(ZulipIcons.check_circle_checked)).findsNothing();
129-
check(find.text('Someone Muted')).findsNothing();
130-
check(find.text('Muted user')).findsNothing();
134+
check(find.textContaining('Someone Muted')).findsNothing();
135+
check(find.textContaining('Muted user')).findsNothing();
131136
});
132137

133138
testWidgets('shows filtered users based on search', (tester) async {
134139
await setupSheet(tester, users: testUsers);
135140
await tester.enterText(find.byType(TextField), 'Alice');
136141
await tester.pump();
137-
check(find.text('Alice Anderson')).findsOne();
138-
check(find.text('Charlie Carter')).findsNothing();
139-
check(find.text('Bob Brown')).findsNothing();
142+
check(find.textContaining('Alice Anderson')).findsOne();
143+
check(find.textContaining('Charlie Carter')).findsNothing();
144+
check(find.textContaining('Bob Brown')).findsNothing();
140145
});
141146

142147
// TODO test sorting by recent-DMs
@@ -146,43 +151,43 @@ void main() {
146151
await setupSheet(tester, users: testUsers);
147152
await tester.enterText(find.byType(TextField), 'alice');
148153
await tester.pump();
149-
check(find.text('Alice Anderson')).findsOne();
154+
check(find.textContaining('Alice Anderson')).findsOne();
150155

151156
await tester.enterText(find.byType(TextField), 'ALICE');
152157
await tester.pump();
153-
check(find.text('Alice Anderson')).findsOne();
158+
check(find.textContaining('Alice Anderson')).findsOne();
154159
});
155160

156161
testWidgets('partial name and last name search handling', (tester) async {
157162
await setupSheet(tester, users: testUsers);
158163

159164
await tester.enterText(find.byType(TextField), 'Ali');
160165
await tester.pump();
161-
check(find.text('Alice Anderson')).findsOne();
162-
check(find.text('Bob Brown')).findsNothing();
163-
check(find.text('Charlie Carter')).findsNothing();
166+
check(find.textContaining('Alice Anderson')).findsOne();
167+
check(find.textContaining('Bob Brown')).findsNothing();
168+
check(find.textContaining('Charlie Carter')).findsNothing();
164169

165170
await tester.enterText(find.byType(TextField), 'Anderson');
166171
await tester.pump();
167-
check(find.text('Alice Anderson')).findsOne();
168-
check(find.text('Charlie Carter')).findsNothing();
169-
check(find.text('Bob Brown')).findsNothing();
172+
check(find.textContaining('Alice Anderson')).findsOne();
173+
check(find.textContaining('Charlie Carter')).findsNothing();
174+
check(find.textContaining('Bob Brown')).findsNothing();
170175

171176
await tester.enterText(find.byType(TextField), 'son');
172177
await tester.pump();
173-
check(find.text('Alice Anderson')).findsOne();
174-
check(find.text('Charlie Carter')).findsNothing();
175-
check(find.text('Bob Brown')).findsNothing();
178+
check(find.textContaining('Alice Anderson')).findsOne();
179+
check(find.textContaining('Charlie Carter')).findsNothing();
180+
check(find.textContaining('Bob Brown')).findsNothing();
176181
});
177182

178183
testWidgets('shows empty state when no users match', (tester) async {
179184
await setupSheet(tester, users: testUsers);
180185
await tester.enterText(find.byType(TextField), 'Zebra');
181186
await tester.pump();
182-
check(find.text('No users found')).findsOne();
183-
check(find.text('Alice Anderson')).findsNothing();
184-
check(find.text('Bob Brown')).findsNothing();
185-
check(find.text('Charlie Carter')).findsNothing();
187+
check(find.textContaining('No users found')).findsOne();
188+
check(find.textContaining('Alice Anderson')).findsNothing();
189+
check(find.textContaining('Bob Brown')).findsNothing();
190+
check(find.textContaining('Charlie Carter')).findsNothing();
186191
});
187192

188193
testWidgets('search text clears when user is selected', (tester) async {
@@ -252,7 +257,7 @@ void main() {
252257
await tester.tap(findUserTile(eg.selfUser));
253258
await tester.pump();
254259
checkUserSelected(tester, eg.selfUser, true);
255-
check(find.text(eg.selfUser.fullName)).findsExactly(2);
260+
check(find.textContaining(eg.selfUser.fullName)).findsExactly(2);
256261

257262
await tester.tap(findUserTile(otherUser));
258263
await tester.pump();
@@ -264,7 +269,7 @@ void main() {
264269
final otherUser = eg.user(fullName: 'Other User');
265270
await setupSheet(tester, users: [eg.selfUser, otherUser]);
266271

267-
check(find.text(eg.selfUser.fullName)).findsOne();
272+
check(find.textContaining(eg.selfUser.fullName)).findsOne();
268273

269274
await tester.tap(findUserTile(otherUser));
270275
await tester.pump();
@@ -285,6 +290,75 @@ void main() {
285290
});
286291
});
287292

293+
group('User status', () {
294+
void checkFindsTileStatusEmoji(WidgetTester tester, User user, Finder emojiFinder) {
295+
final statusEmojiFinder = find.ancestor(of: emojiFinder,
296+
matching: find.byType(UserStatusEmoji));
297+
final tileStatusEmojiFinder = find.descendant(of: findUserTile(user),
298+
matching: statusEmojiFinder);
299+
check(tester.widget<UserStatusEmoji>(tileStatusEmojiFinder)
300+
.neverAnimate).isTrue();
301+
check(tileStatusEmojiFinder).findsOne();
302+
}
303+
304+
void checkFindsChipStatusEmoji(WidgetTester tester, User user, Finder emojiFinder) {
305+
final statusEmojiFinder = find.ancestor(of: emojiFinder,
306+
matching: find.byType(UserStatusEmoji));
307+
final chipStatusEmojiFinder = find.descendant(of: findUserChip(user),
308+
matching: statusEmojiFinder);
309+
check(tester.widget<UserStatusEmoji>(chipStatusEmojiFinder)
310+
.neverAnimate).isTrue();
311+
check(chipStatusEmojiFinder).findsOne();
312+
}
313+
314+
testWidgets('status emoji & text are set -> emoji is displayed, text is not', (tester) async {
315+
final user = eg.user();
316+
await setupSheet(tester, users: [user]);
317+
await store.changeUserStatus(user.userId, UserStatusChange(
318+
text: OptionSome('Busy'),
319+
emoji: OptionSome(StatusEmoji(emojiName: 'working_on_it',
320+
emojiCode: '1f6e0', reactionType: ReactionType.unicodeEmoji))));
321+
await tester.pump();
322+
323+
checkFindsTileStatusEmoji(tester, user, find.text('\u{1f6e0}'));
324+
check(find.descendant(of: findUserTile(user),
325+
matching: find.textContaining('Busy'))).findsNothing();
326+
check(findUserChip(user)).findsNothing();
327+
328+
await tester.tap(findUserTile(user));
329+
await tester.pump();
330+
331+
checkFindsTileStatusEmoji(tester, user, find.text('\u{1f6e0}'));
332+
check(find.descendant(of: findUserTile(user),
333+
matching: find.textContaining('Busy'))).findsNothing();
334+
check(findUserChip(user)).findsOne();
335+
checkFindsChipStatusEmoji(tester, user, find.text('\u{1f6e0}'));
336+
check(find.descendant(of: findUserChip(user),
337+
matching: find.text('Busy'))).findsNothing();
338+
});
339+
340+
testWidgets('status emoji is not set, text is set -> text is not displayed', (tester) async {
341+
final user = eg.user();
342+
await setupSheet(tester, users: [user]);
343+
await store.changeUserStatus(user.userId, UserStatusChange(
344+
text: OptionSome('Busy'), emoji: OptionNone()));
345+
await tester.pump();
346+
347+
check(find.descendant(of: findUserTile(user),
348+
matching: find.textContaining('Busy'))).findsNothing();
349+
check(findUserChip(user)).findsNothing();
350+
351+
await tester.tap(findUserTile(user));
352+
await tester.pump();
353+
354+
check(find.descendant(of: findUserTile(user),
355+
matching: find.textContaining('Busy'))).findsNothing();
356+
check(findUserChip(user)).findsOne();
357+
check(find.descendant(of: findUserChip(user),
358+
matching: find.text('Busy'))).findsNothing();
359+
});
360+
});
361+
288362
group('navigation to DM Narrow', () {
289363
Future<void> runAndCheck(WidgetTester tester, {
290364
required List<User> users,

0 commit comments

Comments
 (0)