Skip to content

Commit 42dec2d

Browse files
committed
profile: Show user status
Fixes: #197
1 parent 1449497 commit 42dec2d

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

lib/widgets/profile.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'message_list.dart';
1212
import 'page.dart';
1313
import 'store.dart';
1414
import 'text.dart';
15+
import 'theme.dart';
1516

1617
class _TextStyles {
1718
static const primaryFieldText = TextStyle(fontSize: 20);
@@ -43,6 +44,7 @@ class ProfilePage extends StatelessWidget {
4344
if (user == null) {
4445
return const _ProfileErrorPage();
4546
}
47+
final userStatus = store.getUserStatus(userId);
4648

4749
final nameStyle = _TextStyles.primaryFieldText
4850
.merge(weightVariableTextStyle(context, wght: 700));
@@ -69,9 +71,20 @@ class ProfilePage extends StatelessWidget {
6971
),
7072
// TODO write a test where the user is muted; check this and avatar
7173
TextSpan(text: store.userDisplayName(userId, replaceIfMuted: false)),
74+
UserStatusEmoji.asWidgetSpan(
75+
userId: userId,
76+
size: 20,
77+
notoColorEmojiTextSize: 16.6,
78+
noAnimation: false,
79+
),
7280
]),
7381
textAlign: TextAlign.center,
7482
style: nameStyle),
83+
if (userStatus.text != null)
84+
Text(userStatus.text!,
85+
textAlign: TextAlign.center,
86+
style: TextStyle(fontSize: 16, color: DesignVariables.of(context).userStatusText)),
87+
7588
if (displayEmail != null)
7689
Text(displayEmail,
7790
textAlign: TextAlign.center,

lib/widgets/theme.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
203203
subscriptionListHeaderLine: const HSLColor.fromAHSL(0.2, 240, 0.1, 0.5).toColor(),
204204
subscriptionListHeaderText: const HSLColor.fromAHSL(1.0, 240, 0.1, 0.5).toColor(),
205205
unreadCountBadgeTextForChannel: Colors.black.withValues(alpha: 0.9),
206+
userStatusText: const Color(0xff808080),
206207
);
207208

208209
static final dark = DesignVariables._(
@@ -289,6 +290,8 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
289290
// TODO(design-dark) need proper dark-theme color (this is ad hoc)
290291
subscriptionListHeaderText: const HSLColor.fromAHSL(1.0, 240, 0.1, 0.75).toColor(),
291292
unreadCountBadgeTextForChannel: Colors.white.withValues(alpha: 0.9),
293+
// TODO(design-dark) unchanged in dark theme?
294+
userStatusText: const Color(0xff808080),
292295
);
293296

294297
DesignVariables._({
@@ -363,6 +366,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
363366
required this.subscriptionListHeaderLine,
364367
required this.subscriptionListHeaderText,
365368
required this.unreadCountBadgeTextForChannel,
369+
required this.userStatusText,
366370
});
367371

368372
/// The [DesignVariables] from the context's active theme.
@@ -450,6 +454,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
450454
final Color subscriptionListHeaderLine;
451455
final Color subscriptionListHeaderText;
452456
final Color unreadCountBadgeTextForChannel;
457+
final Color userStatusText; // In Figma, but unnamed.
453458

454459
@override
455460
DesignVariables copyWith({
@@ -524,6 +529,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
524529
Color? subscriptionListHeaderLine,
525530
Color? subscriptionListHeaderText,
526531
Color? unreadCountBadgeTextForChannel,
532+
Color? userStatusText,
527533
}) {
528534
return DesignVariables._(
529535
background: background ?? this.background,
@@ -597,6 +603,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
597603
subscriptionListHeaderLine: subscriptionListHeaderLine ?? this.subscriptionListHeaderLine,
598604
subscriptionListHeaderText: subscriptionListHeaderText ?? this.subscriptionListHeaderText,
599605
unreadCountBadgeTextForChannel: unreadCountBadgeTextForChannel ?? this.unreadCountBadgeTextForChannel,
606+
userStatusText: userStatusText ?? this.userStatusText,
600607
);
601608
}
602609

@@ -677,6 +684,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
677684
subscriptionListHeaderLine: Color.lerp(subscriptionListHeaderLine, other.subscriptionListHeaderLine, t)!,
678685
subscriptionListHeaderText: Color.lerp(subscriptionListHeaderText, other.subscriptionListHeaderText, t)!,
679686
unreadCountBadgeTextForChannel: Color.lerp(unreadCountBadgeTextForChannel, other.unreadCountBadgeTextForChannel, t)!,
687+
userStatusText: Color.lerp(userStatusText, other.userStatusText, t)!,
680688
);
681689
}
682690
}

test/widgets/profile_test.dart

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import 'package:flutter_test/flutter_test.dart';
55
import 'package:url_launcher/url_launcher.dart';
66
import 'package:zulip/api/model/initial_snapshot.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/model/store.dart';
1011
import 'package:zulip/widgets/content.dart';
12+
import 'package:zulip/widgets/emoji.dart';
1113
import 'package:zulip/widgets/icons.dart';
1214
import 'package:zulip/widgets/message_list.dart';
1315
import 'package:zulip/widgets/page.dart';
@@ -29,6 +31,7 @@ Future<void> setupPage(WidgetTester tester, {
2931
required int pageUserId,
3032
List<User>? users,
3133
List<int>? mutedUserIds,
34+
List<(int userId, UserStatusChange change)>? userStatuses,
3235
List<CustomProfileField>? customProfileFields,
3336
Map<String, RealmDefaultExternalAccount>? realmDefaultExternalAccounts,
3437
NavigatorObserver? navigatorObserver,
@@ -48,6 +51,7 @@ Future<void> setupPage(WidgetTester tester, {
4851
if (mutedUserIds != null) {
4952
await store.setMutedUsers(mutedUserIds);
5053
}
54+
await store.changeUserStatuses(userStatuses ?? []);
5155

5256
await tester.pumpWidget(TestZulipApp(
5357
accountId: eg.selfAccount.id,
@@ -84,11 +88,24 @@ void main() {
8488
final user = eg.user(userId: 1, fullName: 'test user',
8589
deliveryEmail: '[email protected]');
8690

87-
await setupPage(tester, users: [user], pageUserId: user.userId);
91+
await setupPage(tester, users: [user], pageUserId: user.userId,
92+
userStatuses: [
93+
(
94+
user.userId,
95+
UserStatusChange(
96+
text: OptionSome('Busy'),
97+
emoji: OptionSome(StatusEmoji(emojiName: 'working_on_it',
98+
emojiCode: '1f6e0', reactionType: ReactionType.unicodeEmoji)))
99+
),
100+
]);
88101

89102
check(because: 'find user avatar', find.byType(Avatar).evaluate()).length.equals(1);
90103
check(because: 'find user name', find.text('test user').evaluate()).isNotEmpty();
91104
check(because: 'find user delivery email', find.text('[email protected]').evaluate()).isNotEmpty();
105+
final statusEmojiFinder = find.ancestor(of: find.byType(UnicodeEmojiWidget),
106+
matching: find.byType(UserStatusEmoji));
107+
check(because: 'find user status emoji', statusEmojiFinder).findsOne();
108+
check(because: 'find user status text', find.text('Busy')).findsOne();
92109
});
93110

94111
testWidgets('page builds; profile page renders with profileData', (tester) async {

0 commit comments

Comments
 (0)