Skip to content

Commit 686130f

Browse files
committed
profile: Show user status
Fixes: #197
1 parent e1e0552 commit 686130f

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

lib/widgets/profile.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'page.dart';
1616
import 'remote_settings.dart';
1717
import 'store.dart';
1818
import 'text.dart';
19+
import 'theme.dart';
1920

2021
class _TextStyles {
2122
static const primaryFieldText = TextStyle(fontSize: 20);
@@ -51,6 +52,7 @@ class ProfilePage extends StatelessWidget {
5152
final nameStyle = _TextStyles.primaryFieldText
5253
.merge(weightVariableTextStyle(context, wght: 700));
5354

55+
final userStatus = store.getUserStatus(userId);
5456
final displayEmail = store.userDisplayEmail(userId);
5557
final items = [
5658
Center(
@@ -73,17 +75,27 @@ class ProfilePage extends StatelessWidget {
7375
),
7476
// TODO write a test where the user is muted; check this and avatar
7577
TextSpan(text: store.userDisplayName(userId, replaceIfMuted: false)),
78+
UserStatusEmoji.asWidgetSpan(
79+
userId: userId,
80+
fontSize: nameStyle.fontSize!,
81+
textScaler: MediaQuery.textScalerOf(context),
82+
neverAnimate: false,
83+
),
7684
]),
7785
textAlign: TextAlign.center,
7886
style: nameStyle),
87+
if (userStatus.text != null)
88+
Text(userStatus.text!,
89+
textAlign: TextAlign.center,
90+
style: TextStyle(fontSize: 18, height: 22 / 18,
91+
color: DesignVariables.of(context).userStatusText)),
7992
if (displayEmail != null)
8093
Text(displayEmail,
8194
textAlign: TextAlign.center,
8295
style: _TextStyles.primaryFieldText),
8396
Text(roleToLabel(user.role, zulipLocalizations),
8497
textAlign: TextAlign.center,
8598
style: _TextStyles.primaryFieldText),
86-
// TODO(#197) render user status
8799
// TODO(#196) render active status
88100
// TODO(#292) render user local time
89101

lib/widgets/theme.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
213213
subscriptionListHeaderLine: const HSLColor.fromAHSL(0.2, 240, 0.1, 0.5).toColor(),
214214
subscriptionListHeaderText: const HSLColor.fromAHSL(1.0, 240, 0.1, 0.5).toColor(),
215215
unreadCountBadgeTextForChannel: Colors.black.withValues(alpha: 0.9),
216+
userStatusText: const Color(0xff808080),
216217
);
217218

218219
static final dark = DesignVariables._(
@@ -309,6 +310,8 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
309310
// TODO(design-dark) need proper dark-theme color (this is ad hoc)
310311
subscriptionListHeaderText: const HSLColor.fromAHSL(1.0, 240, 0.1, 0.75).toColor(),
311312
unreadCountBadgeTextForChannel: Colors.white.withValues(alpha: 0.9),
313+
// TODO(design-dark) unchanged in dark theme?
314+
userStatusText: const Color(0xff808080),
312315
);
313316

314317
DesignVariables._({
@@ -388,6 +391,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
388391
required this.subscriptionListHeaderLine,
389392
required this.subscriptionListHeaderText,
390393
required this.unreadCountBadgeTextForChannel,
394+
required this.userStatusText,
391395
});
392396

393397
/// The [DesignVariables] from the context's active theme.
@@ -480,6 +484,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
480484
final Color subscriptionListHeaderLine;
481485
final Color subscriptionListHeaderText;
482486
final Color unreadCountBadgeTextForChannel;
487+
final Color userStatusText; // In Figma, but unnamed.
483488

484489
@override
485490
DesignVariables copyWith({
@@ -559,6 +564,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
559564
Color? subscriptionListHeaderLine,
560565
Color? subscriptionListHeaderText,
561566
Color? unreadCountBadgeTextForChannel,
567+
Color? userStatusText,
562568
}) {
563569
return DesignVariables._(
564570
background: background ?? this.background,
@@ -637,6 +643,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
637643
subscriptionListHeaderLine: subscriptionListHeaderLine ?? this.subscriptionListHeaderLine,
638644
subscriptionListHeaderText: subscriptionListHeaderText ?? this.subscriptionListHeaderText,
639645
unreadCountBadgeTextForChannel: unreadCountBadgeTextForChannel ?? this.unreadCountBadgeTextForChannel,
646+
userStatusText: userStatusText ?? this.userStatusText,
640647
);
641648
}
642649

@@ -722,6 +729,7 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
722729
subscriptionListHeaderLine: Color.lerp(subscriptionListHeaderLine, other.subscriptionListHeaderLine, t)!,
723730
subscriptionListHeaderText: Color.lerp(subscriptionListHeaderText, other.subscriptionListHeaderText, t)!,
724731
unreadCountBadgeTextForChannel: Color.lerp(unreadCountBadgeTextForChannel, other.unreadCountBadgeTextForChannel, t)!,
732+
userStatusText: Color.lerp(userStatusText, other.userStatusText, t)!,
725733
);
726734
}
727735
}

test/widgets/profile_test.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import 'package:url_launcher/url_launcher.dart';
99
import 'package:zulip/api/model/events.dart';
1010
import 'package:zulip/api/model/initial_snapshot.dart';
1111
import 'package:zulip/api/model/model.dart';
12+
import 'package:zulip/basic.dart';
1213
import 'package:zulip/model/narrow.dart';
1314
import 'package:zulip/model/store.dart';
1415
import 'package:zulip/widgets/button.dart';
1516
import 'package:zulip/widgets/content.dart';
17+
import 'package:zulip/widgets/emoji.dart';
1618
import 'package:zulip/widgets/icons.dart';
1719
import 'package:zulip/widgets/message_list.dart';
1820
import 'package:zulip/widgets/page.dart';
@@ -96,9 +98,22 @@ void main() {
9698
deliveryEmail: '[email protected]');
9799

98100
await setupPage(tester, users: [user], pageUserId: user.userId);
101+
await store.changeUserStatuses({
102+
user.userId: UserStatusChange(
103+
text: OptionSome('Busy'),
104+
emoji: OptionSome(StatusEmoji(emojiName: 'working_on_it',
105+
emojiCode: '1f6e0', reactionType: ReactionType.unicodeEmoji))),
106+
});
107+
await tester.pump();
99108

100109
check(because: 'find user avatar', find.byType(Avatar).evaluate()).length.equals(1);
101110
check(because: 'find user name', find.text('test user').evaluate()).isNotEmpty();
111+
final statusEmojiFinder = find.ancestor(of: find.byType(UnicodeEmojiWidget),
112+
matching: find.byType(UserStatusEmoji));
113+
check(tester.firstWidget<UserStatusEmoji>(statusEmojiFinder)
114+
.neverAnimate).isFalse();
115+
check(because: 'find user status emoji', statusEmojiFinder).findsOne();
116+
check(because: 'find user status text', find.text('Busy')).findsOne();
102117
check(because: 'find user delivery email', find.text('[email protected]').evaluate()).isNotEmpty();
103118
});
104119

0 commit comments

Comments
 (0)