Skip to content

Commit 14093b2

Browse files
committed
recent-dms: Show user status emoji in recent DMs page
Status emojis are only shown for self-1:1 and 1:1 conversation items. They're ignored for group conversations as that's what the Web does.
1 parent 463b938 commit 14093b2

File tree

2 files changed

+105
-4
lines changed

2 files changed

+105
-4
lines changed

lib/widgets/recent_dm_conversations.dart

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,31 @@ class RecentDmConversationsItem extends StatelessWidget {
148148
const SizedBox(width: 8),
149149
Expanded(child: Padding(
150150
padding: const EdgeInsets.symmetric(vertical: 4),
151-
child: Text(
151+
child: Text.rich(
152+
TextSpan(
153+
children: [
154+
TextSpan(text: title),
155+
...(switch (narrow.otherRecipientIds) {
156+
// self-DM
157+
[] => [UserStatusEmoji.asWidgetSpan(userId: store.selfUserId,
158+
fontSize: 17, textScaler: MediaQuery.textScalerOf(context))],
159+
// 1:1-DM
160+
[final otherUserId] =>
161+
[UserStatusEmoji.asWidgetSpan(userId: otherUserId,
162+
fontSize: 17, textScaler: MediaQuery.textScalerOf(context))],
163+
// group-DM - show nothing
164+
[...] => [],
165+
}),
166+
]
167+
),
152168
style: TextStyle(
153169
fontSize: 17,
154170
height: (20 / 17),
155171
// TODO(design) check if this is the right variable
156172
color: designVariables.labelMenuButton,
157173
),
158174
maxLines: 2,
159-
overflow: TextOverflow.ellipsis,
160-
title))),
175+
overflow: TextOverflow.ellipsis))),
161176
const SizedBox(width: 12),
162177
unreadCount > 0
163178
? Padding(padding: const EdgeInsetsDirectional.only(end: 16),

test/widgets/recent_dm_conversations_test.dart

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import 'package:flutter_checks/flutter_checks.dart';
55
import 'package:flutter_test/flutter_test.dart';
66
import 'package:zulip/api/model/events.dart';
77
import 'package:zulip/api/model/model.dart';
8+
import 'package:zulip/basic.dart';
89
import 'package:zulip/model/narrow.dart';
910
import 'package:zulip/widgets/content.dart';
11+
import 'package:zulip/widgets/emoji.dart';
1012
import 'package:zulip/widgets/home.dart';
1113
import 'package:zulip/widgets/icons.dart';
1214
import 'package:zulip/widgets/message_list.dart';
@@ -21,13 +23,15 @@ import '../model/test_store.dart';
2123
import '../test_navigation.dart';
2224
import 'content_checks.dart';
2325
import 'message_list_checks.dart';
26+
import 'message_list_test.dart';
2427
import 'page_checks.dart';
2528
import 'test_app.dart';
2629

2730
Future<void> setupPage(WidgetTester tester, {
2831
required List<DmMessage> dmMessages,
2932
required List<User> users,
3033
List<int>? mutedUserIds,
34+
List<(int userId, UserStatusChange change)>? userStatuses,
3135
NavigatorObserver? navigatorObserver,
3236
String? newNameForSelfUser,
3337
}) async {
@@ -44,6 +48,8 @@ Future<void> setupPage(WidgetTester tester, {
4448
await store.setMutedUsers(mutedUserIds);
4549
}
4650

51+
await store.changeUserStatuses(userStatuses ?? []);
52+
4753
await store.addMessages(dmMessages);
4854

4955
if (newNameForSelfUser != null) {
@@ -176,7 +182,7 @@ void main() {
176182
// TODO(#232): syntax like `check(find(…), findsOneWidget)`
177183
final widget = tester.widget(find.descendant(
178184
of: find.byType(RecentDmConversationsItem),
179-
matching: find.text(expectedText),
185+
matching: find.textContaining(expectedText),
180186
));
181187
if (expectedLines != null) {
182188
final renderObject = tester.renderObject<RenderParagraph>(find.byWidget(widget));
@@ -186,6 +192,17 @@ void main() {
186192
}
187193
}
188194

195+
void checkStatusEmoji({required bool isPresent}) {
196+
final statusEmojiFinder = findStatusEmoji(UnicodeEmojiWidget);
197+
if (isPresent) {
198+
checkUserStatusEmoji(statusEmojiFinder, isAnimated: false);
199+
}
200+
final itemFinder = find.descendant(
201+
of: find.byType(RecentDmConversationsItem),
202+
matching: statusEmojiFinder);
203+
check(itemFinder).findsExactly(isPresent ? 1 : 0);
204+
}
205+
189206
Future<void> markMessageAsRead(WidgetTester tester, Message message) async {
190207
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
191208
await store.handleEvent(UpdateMessageFlagsAddEvent(
@@ -231,6 +248,28 @@ void main() {
231248
checkTitle(tester, name, 2);
232249
});
233250

251+
testWidgets('status emoji is set -> emoji is displayed', (tester) async {
252+
final message = eg.dmMessage(from: eg.selfUser, to: []);
253+
await setupPage(tester, dmMessages: [message], users: [],
254+
userStatuses: [
255+
(
256+
eg.selfUser.userId,
257+
UserStatusChange(
258+
text: OptionSome('Busy'),
259+
emoji: OptionSome(StatusEmoji(emojiName: 'working_on_it',
260+
emojiCode: '1f6e0', reactionType: ReactionType.unicodeEmoji)))
261+
),
262+
]);
263+
checkStatusEmoji(isPresent: true);
264+
});
265+
266+
testWidgets('status emoji is not set -> emoji is not displayed', (tester) async {
267+
final message = eg.dmMessage(from: eg.selfUser, to: []);
268+
await setupPage(tester, dmMessages: [message], users: [],
269+
userStatuses: []);
270+
checkStatusEmoji(isPresent: false);
271+
});
272+
234273
testWidgets('unread counts', (tester) async {
235274
final message = eg.dmMessage(from: eg.selfUser, to: []);
236275
await setupPage(tester, users: [], dmMessages: [message]);
@@ -291,6 +330,30 @@ void main() {
291330
checkTitle(tester, user.fullName, 2);
292331
});
293332

333+
testWidgets('status emoji is set -> emoji is displayed', (tester) async {
334+
final user = eg.user();
335+
final message = eg.dmMessage(from: eg.selfUser, to: [user]);
336+
await setupPage(tester, users: [user], dmMessages: [message],
337+
userStatuses: [
338+
(
339+
user.userId,
340+
UserStatusChange(
341+
text: OptionSome('Busy'),
342+
emoji: OptionSome(StatusEmoji(emojiName: 'working_on_it',
343+
emojiCode: '1f6e0', reactionType: ReactionType.unicodeEmoji)))
344+
),
345+
]);
346+
checkStatusEmoji(isPresent: true);
347+
});
348+
349+
testWidgets('status emoji is not set -> emoji is not displayed', (tester) async {
350+
final user = eg.user();
351+
final message = eg.dmMessage(from: eg.selfUser, to: [user]);
352+
await setupPage(tester, users: [user], dmMessages: [message],
353+
userStatuses: []);
354+
checkStatusEmoji(isPresent: false);
355+
});
356+
294357
testWidgets('unread counts', (tester) async {
295358
final message = eg.dmMessage(from: eg.otherUser, to: [eg.selfUser]);
296359
await setupPage(tester, users: [], dmMessages: [message]);
@@ -379,6 +442,29 @@ void main() {
379442
checkTitle(tester, users.map((u) => u.fullName).join(', '), 2);
380443
});
381444

445+
testWidgets('status emojis are set -> emoji are not displayed', (tester) async {
446+
final users = usersList(3);
447+
final message = eg.dmMessage(from: eg.selfUser, to: users);
448+
await setupPage(tester, users: users, dmMessages: [message],
449+
userStatuses: [
450+
(
451+
users.first.userId,
452+
UserStatusChange(
453+
text: OptionSome('Busy'),
454+
emoji: OptionSome(StatusEmoji(emojiName: 'working_on_it',
455+
emojiCode: '1f6e0', reactionType: ReactionType.unicodeEmoji)))
456+
),
457+
(
458+
users.last.userId,
459+
UserStatusChange(
460+
text: OptionSome('In a meeting'),
461+
emoji: OptionSome(StatusEmoji(emojiName: 'calendar',
462+
emojiCode: '1f4c5', reactionType: ReactionType.unicodeEmoji)))
463+
),
464+
]);
465+
checkStatusEmoji(isPresent: false);
466+
});
467+
382468
testWidgets('unread counts', (tester) async {
383469
final message = eg.dmMessage(from: eg.thirdUser, to: [eg.selfUser, eg.otherUser]);
384470
await setupPage(tester, users: [], dmMessages: [message]);

0 commit comments

Comments
 (0)