From 5caa859b3fa3a2f6e91fe5b811ad11414df8aa5f Mon Sep 17 00:00:00 2001 From: Sayed Mahmood Sayedi Date: Wed, 19 Feb 2025 22:21:46 +0430 Subject: [PATCH 1/4] api: Add InitialSnapshot.mutedUsers Co-authored-by: Chris Bobbe --- lib/api/model/initial_snapshot.dart | 3 +++ lib/api/model/initial_snapshot.g.dart | 4 ++++ lib/api/model/model.dart | 19 +++++++++++++++++++ lib/api/model/model.g.dart | 6 ++++++ test/example_data.dart | 2 ++ 5 files changed, 34 insertions(+) diff --git a/lib/api/model/initial_snapshot.dart b/lib/api/model/initial_snapshot.dart index f4cc2fe5fc..cb3df052ac 100644 --- a/lib/api/model/initial_snapshot.dart +++ b/lib/api/model/initial_snapshot.dart @@ -44,6 +44,8 @@ class InitialSnapshot { // final List<…> mutedTopics; // TODO(#422) we ignore this feature on older servers + final List mutedUsers; + final Map realmEmoji; final List recentPrivateConversations; @@ -132,6 +134,7 @@ class InitialSnapshot { required this.serverTypingStartedExpiryPeriodMilliseconds, required this.serverTypingStoppedWaitPeriodMilliseconds, required this.serverTypingStartedWaitPeriodMilliseconds, + required this.mutedUsers, required this.realmEmoji, required this.recentPrivateConversations, required this.savedSnippets, diff --git a/lib/api/model/initial_snapshot.g.dart b/lib/api/model/initial_snapshot.g.dart index 5574f8dde7..2cdd365ec5 100644 --- a/lib/api/model/initial_snapshot.g.dart +++ b/lib/api/model/initial_snapshot.g.dart @@ -38,6 +38,9 @@ InitialSnapshot _$InitialSnapshotFromJson( (json['server_typing_started_wait_period_milliseconds'] as num?) ?.toInt() ?? 10000, + mutedUsers: (json['muted_users'] as List) + .map((e) => MutedUserItem.fromJson(e as Map)) + .toList(), realmEmoji: (json['realm_emoji'] as Map).map( (k, e) => MapEntry(k, RealmEmojiItem.fromJson(e as Map)), ), @@ -122,6 +125,7 @@ Map _$InitialSnapshotToJson(InitialSnapshot instance) => instance.serverTypingStoppedWaitPeriodMilliseconds, 'server_typing_started_wait_period_milliseconds': instance.serverTypingStartedWaitPeriodMilliseconds, + 'muted_users': instance.mutedUsers, 'realm_emoji': instance.realmEmoji, 'recent_private_conversations': instance.recentPrivateConversations, 'saved_snippets': instance.savedSnippets, diff --git a/lib/api/model/model.dart b/lib/api/model/model.dart index 131a51991b..87a617dc4d 100644 --- a/lib/api/model/model.dart +++ b/lib/api/model/model.dart @@ -110,6 +110,25 @@ class CustomProfileFieldExternalAccountData { Map toJson() => _$CustomProfileFieldExternalAccountDataToJson(this); } +/// An item in the [InitialSnapshot.mutedUsers]. +/// +/// For docs, search for "muted_users:" +/// in . +@JsonSerializable(fieldRename: FieldRename.snake) +class MutedUserItem { + final int id; + + // Mobile doesn't use the timestamp; ignore. + // final int timestamp; + + const MutedUserItem({required this.id}); + + factory MutedUserItem.fromJson(Map json) => + _$MutedUserItemFromJson(json); + + Map toJson() => _$MutedUserItemToJson(this); +} + /// An item in [InitialSnapshot.realmEmoji] or [RealmEmojiUpdateEvent]. /// /// For docs, search for "realm_emoji:" diff --git a/lib/api/model/model.g.dart b/lib/api/model/model.g.dart index 6f351d0a6f..8c56b4b7fb 100644 --- a/lib/api/model/model.g.dart +++ b/lib/api/model/model.g.dart @@ -68,6 +68,12 @@ Map _$CustomProfileFieldExternalAccountDataToJson( 'url_pattern': instance.urlPattern, }; +MutedUserItem _$MutedUserItemFromJson(Map json) => + MutedUserItem(id: (json['id'] as num).toInt()); + +Map _$MutedUserItemToJson(MutedUserItem instance) => + {'id': instance.id}; + RealmEmojiItem _$RealmEmojiItemFromJson(Map json) => RealmEmojiItem( emojiCode: json['id'] as String, diff --git a/test/example_data.dart b/test/example_data.dart index 79b92bdda8..3185fce269 100644 --- a/test/example_data.dart +++ b/test/example_data.dart @@ -1098,6 +1098,7 @@ InitialSnapshot initialSnapshot({ int? serverTypingStartedExpiryPeriodMilliseconds, int? serverTypingStoppedWaitPeriodMilliseconds, int? serverTypingStartedWaitPeriodMilliseconds, + List? mutedUsers, Map? realmEmoji, List? recentPrivateConversations, List? savedSnippets, @@ -1134,6 +1135,7 @@ InitialSnapshot initialSnapshot({ serverTypingStoppedWaitPeriodMilliseconds ?? 5000, serverTypingStartedWaitPeriodMilliseconds: serverTypingStartedWaitPeriodMilliseconds ?? 10000, + mutedUsers: mutedUsers ?? [], realmEmoji: realmEmoji ?? {}, recentPrivateConversations: recentPrivateConversations ?? [], savedSnippets: savedSnippets ?? [], From 37a5948794e6146484873a4cb600044d10b9dcba Mon Sep 17 00:00:00 2001 From: Sayed Mahmood Sayedi Date: Thu, 1 May 2025 22:18:27 +0430 Subject: [PATCH 2/4] api: Add muted_users event --- lib/api/model/events.dart | 19 +++++++++++++++++++ lib/api/model/events.g.dart | 15 +++++++++++++++ lib/api/model/model.dart | 2 +- lib/model/store.dart | 4 ++++ test/example_data.dart | 5 +++++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/api/model/events.dart b/lib/api/model/events.dart index 62789333e1..2904173e81 100644 --- a/lib/api/model/events.dart +++ b/lib/api/model/events.dart @@ -62,6 +62,7 @@ sealed class Event { } // case 'muted_topics': … // TODO(#422) we ignore this feature on older servers case 'user_topic': return UserTopicEvent.fromJson(json); + case 'muted_users': return MutedUsersEvent.fromJson(json); case 'message': return MessageEvent.fromJson(json); case 'update_message': return UpdateMessageEvent.fromJson(json); case 'delete_message': return DeleteMessageEvent.fromJson(json); @@ -733,6 +734,24 @@ class UserTopicEvent extends Event { Map toJson() => _$UserTopicEventToJson(this); } +/// A Zulip event of type `muted_users`: https://zulip.com/api/get-events#muted_users +@JsonSerializable(fieldRename: FieldRename.snake) +class MutedUsersEvent extends Event { + @override + @JsonKey(includeToJson: true) + String get type => 'muted_users'; + + final List mutedUsers; + + MutedUsersEvent({required super.id, required this.mutedUsers}); + + factory MutedUsersEvent.fromJson(Map json) => + _$MutedUsersEventFromJson(json); + + @override + Map toJson() => _$MutedUsersEventToJson(this); +} + /// A Zulip event of type `message`: https://zulip.com/api/get-events#message @JsonSerializable(fieldRename: FieldRename.snake) class MessageEvent extends Event { diff --git a/lib/api/model/events.g.dart b/lib/api/model/events.g.dart index ef8a214566..bb8119e8ed 100644 --- a/lib/api/model/events.g.dart +++ b/lib/api/model/events.g.dart @@ -468,6 +468,21 @@ const _$UserTopicVisibilityPolicyEnumMap = { UserTopicVisibilityPolicy.unknown: null, }; +MutedUsersEvent _$MutedUsersEventFromJson(Map json) => + MutedUsersEvent( + id: (json['id'] as num).toInt(), + mutedUsers: (json['muted_users'] as List) + .map((e) => MutedUserItem.fromJson(e as Map)) + .toList(), + ); + +Map _$MutedUsersEventToJson(MutedUsersEvent instance) => + { + 'id': instance.id, + 'type': instance.type, + 'muted_users': instance.mutedUsers, + }; + MessageEvent _$MessageEventFromJson(Map json) => MessageEvent( id: (json['id'] as num).toInt(), message: Message.fromJson( diff --git a/lib/api/model/model.dart b/lib/api/model/model.dart index 87a617dc4d..f284d336da 100644 --- a/lib/api/model/model.dart +++ b/lib/api/model/model.dart @@ -110,7 +110,7 @@ class CustomProfileFieldExternalAccountData { Map toJson() => _$CustomProfileFieldExternalAccountDataToJson(this); } -/// An item in the [InitialSnapshot.mutedUsers]. +/// An item in the [InitialSnapshot.mutedUsers] or [MutedUsersEvent]. /// /// For docs, search for "muted_users:" /// in . diff --git a/lib/model/store.dart b/lib/model/store.dart index 18a09e32ce..af1c41e857 100644 --- a/lib/model/store.dart +++ b/lib/model/store.dart @@ -949,6 +949,10 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor assert(debugLog("server event: reaction/${event.op}")); _messages.handleReactionEvent(event); + case MutedUsersEvent(): + // TODO handle + break; + case UnexpectedEvent(): assert(debugLog("server event: ${jsonEncode(event.toJson())}")); // TODO log better } diff --git a/test/example_data.dart b/test/example_data.dart index 3185fce269..2a2fd2bc1f 100644 --- a/test/example_data.dart +++ b/test/example_data.dart @@ -814,6 +814,11 @@ UserTopicEvent userTopicEvent( ); } +MutedUsersEvent mutedUsersEvent(List userIds) { + return MutedUsersEvent(id: 1, + mutedUsers: userIds.map((id) => MutedUserItem(id: id)).toList()); +} + MessageEvent messageEvent(Message message, {int? localMessageId}) => MessageEvent(id: 0, message: message, localMessageId: localMessageId?.toString()); From 425926301846d7c177ec0399b49d31c1ff40f4d3 Mon Sep 17 00:00:00 2001 From: Sayed Mahmood Sayedi Date: Sat, 22 Feb 2025 21:44:16 +0430 Subject: [PATCH 3/4] user: Add UserStore.isUserMuted, with event updates Co-authored-by: Chris Bobbe --- lib/model/store.dart | 9 +++++++-- lib/model/user.dart | 21 ++++++++++++++++++++- test/model/user_test.dart | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/model/store.dart b/lib/model/store.dart index af1c41e857..5171807a8e 100644 --- a/lib/model/store.dart +++ b/lib/model/store.dart @@ -645,6 +645,10 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor @override Iterable get allUsers => _users.allUsers; + @override + bool isUserMuted(int userId, {MutedUsersEvent? event}) => + _users.isUserMuted(userId, event: event); + final UserStoreImpl _users; final TypingStatus typingStatus; @@ -950,8 +954,9 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor _messages.handleReactionEvent(event); case MutedUsersEvent(): - // TODO handle - break; + assert(debugLog("server event: muted_users")); + _users.handleMutedUsersEvent(event); + notifyListeners(); case UnexpectedEvent(): assert(debugLog("server event: ${jsonEncode(event.toJson())}")); // TODO log better diff --git a/lib/model/user.dart b/lib/model/user.dart index 05ab2747df..f5079bfd31 100644 --- a/lib/model/user.dart +++ b/lib/model/user.dart @@ -66,6 +66,12 @@ mixin UserStore on PerAccountStoreBase { return getUser(message.senderId)?.fullName ?? message.senderFullName; } + + /// Whether the user with [userId] is muted by the self-user. + /// + /// Looks for [userId] in a private [Set], + /// or in [event.mutedUsers] instead if event is non-null. + bool isUserMuted(int userId, {MutedUsersEvent? event}); } /// The implementation of [UserStore] that does the work. @@ -81,7 +87,8 @@ class UserStoreImpl extends PerAccountStoreBase with UserStore { initialSnapshot.realmUsers .followedBy(initialSnapshot.realmNonActiveUsers) .followedBy(initialSnapshot.crossRealmBots) - .map((user) => MapEntry(user.userId, user))); + .map((user) => MapEntry(user.userId, user))), + _mutedUsers = Set.from(initialSnapshot.mutedUsers.map((item) => item.id)); final Map _users; @@ -91,6 +98,13 @@ class UserStoreImpl extends PerAccountStoreBase with UserStore { @override Iterable get allUsers => _users.values; + final Set _mutedUsers; + + @override + bool isUserMuted(int userId, {MutedUsersEvent? event}) { + return (event?.mutedUsers.map((item) => item.id) ?? _mutedUsers).contains(userId); + } + void handleRealmUserEvent(RealmUserEvent event) { switch (event) { case RealmUserAddEvent(): @@ -129,4 +143,9 @@ class UserStoreImpl extends PerAccountStoreBase with UserStore { } } } + + void handleMutedUsersEvent(MutedUsersEvent event) { + _mutedUsers.clear(); + _mutedUsers.addAll(event.mutedUsers.map((item) => item.id)); + } } diff --git a/test/model/user_test.dart b/test/model/user_test.dart index 63ac1589c7..27b07c129d 100644 --- a/test/model/user_test.dart +++ b/test/model/user_test.dart @@ -79,4 +79,27 @@ void main() { check(getUser()).deliveryEmail.equals('c@mail.example'); }); }); + + testWidgets('MutedUsersEvent', (tester) async { + final user1 = eg.user(userId: 1); + final user2 = eg.user(userId: 2); + final user3 = eg.user(userId: 3); + + final store = eg.store(initialSnapshot: eg.initialSnapshot( + realmUsers: [user1, user2, user3], + mutedUsers: [MutedUserItem(id: 2), MutedUserItem(id: 1)])); + check(store.isUserMuted(1)).isTrue(); + check(store.isUserMuted(2)).isTrue(); + check(store.isUserMuted(3)).isFalse(); + + await store.handleEvent(eg.mutedUsersEvent([2, 1, 3])); + check(store.isUserMuted(1)).isTrue(); + check(store.isUserMuted(2)).isTrue(); + check(store.isUserMuted(3)).isTrue(); + + await store.handleEvent(eg.mutedUsersEvent([2, 3])); + check(store.isUserMuted(1)).isFalse(); + check(store.isUserMuted(2)).isTrue(); + check(store.isUserMuted(3)).isTrue(); + }); } From adaa571165dfe4578baf222827563144f9eeaee9 Mon Sep 17 00:00:00 2001 From: Sayed Mahmood Sayedi Date: Tue, 25 Feb 2025 22:05:26 +0430 Subject: [PATCH 4/4] icons: Add "person", "eye", and "eye_off" icons Also renamed "user" to "two_person" to make it consistent with other icons of the same purpose. Icon resources: - Zulip Mobile Figma File: https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=5968-237884&t=dku3J5Fv2dmWo7ht-0 - Zulip Web Figma File: https://www.figma.com/design/jbNOiBWvbtLuHaiTj4CW0G/Zulip-Web-App?node-id=7752-46450&t=VkypsIaTZqSSptcS-0 https://www.figma.com/design/jbNOiBWvbtLuHaiTj4CW0G/Zulip-Web-App?node-id=7352-981&t=VkypsIaTZqSSptcS-0 --- assets/icons/ZulipIcons.ttf | Bin 14968 -> 15748 bytes assets/icons/eye.svg | 3 + assets/icons/eye_off.svg | 3 + assets/icons/person.svg | 10 +++ assets/icons/{user.svg => two_person.svg} | 0 lib/widgets/home.dart | 4 +- lib/widgets/icons.dart | 73 ++++++++++-------- lib/widgets/inbox.dart | 2 +- lib/widgets/message_list.dart | 2 +- test/widgets/home_test.dart | 2 +- test/widgets/message_list_test.dart | 2 +- test/widgets/new_dm_sheet_test.dart | 2 +- .../widgets/recent_dm_conversations_test.dart | 2 +- 13 files changed, 65 insertions(+), 40 deletions(-) create mode 100644 assets/icons/eye.svg create mode 100644 assets/icons/eye_off.svg create mode 100644 assets/icons/person.svg rename assets/icons/{user.svg => two_person.svg} (100%) diff --git a/assets/icons/ZulipIcons.ttf b/assets/icons/ZulipIcons.ttf index 5df791a6c94a92bc57f4d26323f8f5550914fe91..ea32825d15deb9c293d8a6c565e18c7dd74f61a7 100644 GIT binary patch delta 2720 zcmb7GYfM|`8GgTW>~kDrb8&1ONN@nh7ffovKAdxG@ReXYkmjO%3pr{W9Z%m)Hy8Jm}MN} zJHWoVh1ILS{PfEQL{cZt*neU1Ols!-ed}E!#~+~ZorRgJOY96&vAGNL&Wke(70*wy zF(Uo@M1r=oxUw2pwf>nX`6tZZ-nip;j@KeU6hF;Ad1&LW18m&zvDvDnotkJLy-mNN z&zPI#*)8@l`&V4Q=oYO#B9*$CKo)Hu%lvqs0tpox<1BP^>W9uCMvt%d zQI$I?;_w_4qe%7kj5}?oAdcPxzB=4;XPjgkv^XUmT|34)aE- zH46VK0vsU^v^nKGEP04N@>Wrm7>?!@;m%`F;AD2uj{mN2mq13Q!q7QPPtzo2Hn!F!0>Va(r);tf~s{;QakV(RJ7;|2pEIe7E6{xF4YBBMKNFrtn-Z~uhV#F!M zjem%3Rh|J}M-}fBoabuVD&o^I-rnT|cA#|I^Z(U;T+@M$;+ln8rgZpz)UXY;Vs4)q zuR?7Eu@oR15e=_uy_Xfa`M}La8oqu0;k6nhA`(ld(EtkqQfo732#$=X9hq_2eJAJuezK3ct2{* zeb7o^KMVaPp6yy*`L(WJ=`2X(X~YhdB0e@2;kL1E&9DJu%X-C#N;V@eMFjD-aad9< z;;+7ZXuKtzGaBUPzK3wg|Gq$+e6%0Zj!)J@9JqzK9eEP)l<7RJ-5W5*WdDE)0(l&$ zf#4AOBm)u$KxhO(@XQ?qy)3AWq7H*-`jYX6e0oP8?$-c3OE`OGH+3zfo)<$ zSBeMY+2PT`;8@9c(RR)FktA0goS66x{>I-JP&R>&D$SU{2bG>Rk%v5EA_sZaga%nL zk%XKzF$8(eL>h9=LH54G9H!%o#)dbJbnu*fpustH|yVpm=L0tCNfjZDV zRDy$7#5n5+R9}}mrI(~1*wVIZw!1qNd)U5i|GZ(T;Uh=T@r>h+Q+IAPh8s^b{<|sI z{Iixq%WJNP>zl5vows&=>OSfIyXW=)|EYJL@QLsy37Zz@vb|~nAre0kPvY`+;Y*A1 zuOW- zgd>sg#_8#eaL*sP$(}vjZX$lFW-)gvj{CyNe<)tT=PHQXF#+-+H7J8-Jl5)QOI}Vm z%KY7uxrSielHAC|P$O1@p(=Q*8k7*68uPMNx75ve_;8?Vb)`Wi!-RKpmN6~o3hq3% zEWely4ttaj*7hpxh5b+U-~Lxh5JjP_m^A|9!P-m^TT_7vCudS_RpXS8%&D{ESLaaz-+Efi7t%2+Pl>rdt0nezC2p3?P-2E!5`PrZ{% z`Fqp3vE!xDp2)0ewpi9Se;X`2HeXTt*=A3Cifz6(I4R(tutxpc5*uUV?2z$>{zHdY uS*yrEd2x2uIFxu*mX<1)Ru(TBzfU~tvadeBSgy~d%NG|euU3p)Quz<=pS*tn delta 1969 zcmb7FT})e59RJ_;wzu@dmX9H9x}mVS;iSE7Z*OUPX(^?!7q$$y5L1D|U`#3CCt0-~FF+ z{@)+>^u=e(MV$m9a?v@mQlM|}M0(_}(VIj&nI_M9cyf*kdk?lOBM#l^Jxf5^S zew|2i;4F7~dU^7#4`2F`$XzBnxIQ(JKehPFl}{l16A+ogfkP1cv0ew-rV7QS&yL*r z8@kL#%k=EHmfzTSEe8XqAh24|18?g^69Cr-DSvB_fMDH#=Ya+41Y6 zMCvB?uU=Sh_4Jz=Ad8yb)%_PXWuf2LD@^Lv8|0-ndY`_gTT~Vf2xG!U;j(bsGGje% z9kzaI{hn;(rVh%|Fcrx{J__KGDM%rTkV;YN#412BicE2^|Dv3+jCc_$t}bwMr! zy%_X$6=6C5r4TkvDF1JKHG^%a5o)*mEA~6fj-k>LEKBa&2-HoZGwtINvQQv zGn5pRNalGpz&$H^8YV-?AVu|%W}zja$#UOIyHH?1T(jab<9_g&`$np{dtR-kgf{u^j2r`b7{RpNi^$^x6aF~88 z(oi82hBMI&DFAy7NMoAL(>rvD^vm=uZJ{bg@?Icb&2fQ^>Ce^d4l$dRm!QHeM1+><6E9&JQljw-T<0 zH-d%kMV74Vz2>mlF*R(KSpVB`I)Em5p{3!e3}=Y+o$>BNOgjal*t4AP=cPCEqjwg(xlFwg;HTL@x39{8;P$%x9GQ3^I-iZQP@QlzI zTK=QMSdm)g5WFYhER5Kq=2a0x!6I<2m?g_1VhvfP(SRVnfL`N<^f=7h;WfVp+R3i4 z8jUBQ6-g;_CL7Q?(>=kyUhtn;l{~teMPy~yBm4CMBOD>nJcl22j3Ws;&d~+RbQ!|H z1cwSb$$`6`PIJUTr#KRzXLR-gV!)Fe-JsJPxT~qakpi9JP(WunWY9Sd){dt*vY=-< z0-*C88fcM2>%?M#BMrL9(F6K42mT;viGx*WnWMM#va{V{Tz9wXYqoEsoODszavZP8 z)_mY>aIQFib7fr5yEfb>-M2iAo^{Vn?>V2tm-B7b9;;oc8>)M^zN!9d!|?xq;NF}h z%XP~d=7j`T={ZlqS^B7X$Xoj2P|jUCqUMBBb0i>?-ir=d@Sn96d&77${;@HTc*Xc3 YG3K@}%oG-i6XL@B#98B*7Pi9XKO#ON;s5{u diff --git a/assets/icons/eye.svg b/assets/icons/eye.svg new file mode 100644 index 0000000000..c5cc095bbe --- /dev/null +++ b/assets/icons/eye.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/eye_off.svg b/assets/icons/eye_off.svg new file mode 100644 index 0000000000..cc2c3587d7 --- /dev/null +++ b/assets/icons/eye_off.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/person.svg b/assets/icons/person.svg new file mode 100644 index 0000000000..6a35686e46 --- /dev/null +++ b/assets/icons/person.svg @@ -0,0 +1,10 @@ + + + diff --git a/assets/icons/user.svg b/assets/icons/two_person.svg similarity index 100% rename from assets/icons/user.svg rename to assets/icons/two_person.svg diff --git a/lib/widgets/home.dart b/lib/widgets/home.dart index 404472f7d0..4e70bb1e76 100644 --- a/lib/widgets/home.dart +++ b/lib/widgets/home.dart @@ -111,7 +111,7 @@ class _HomePageState extends State { narrow: const CombinedFeedNarrow()))), button(_HomePageTab.channels, ZulipIcons.hash_italic), // TODO(#1094): Users - button(_HomePageTab.directMessages, ZulipIcons.user), + button(_HomePageTab.directMessages, ZulipIcons.two_person), _NavigationBarButton( icon: ZulipIcons.menu, selected: false, onPressed: () => _showMainMenu(context, tabNotifier: _tab)), @@ -549,7 +549,7 @@ class _DirectMessagesButton extends _NavigationBarMenuButton { const _DirectMessagesButton({required super.tabNotifier}); @override - IconData get icon => ZulipIcons.user; + IconData get icon => ZulipIcons.two_person; @override String label(ZulipLocalizations zulipLocalizations) { diff --git a/lib/widgets/icons.dart b/lib/widgets/icons.dart index 8f31630de2..9df1289101 100644 --- a/lib/widgets/icons.dart +++ b/lib/widgets/icons.dart @@ -72,95 +72,104 @@ abstract final class ZulipIcons { /// The Zulip custom icon "edit". static const IconData edit = IconData(0xf110, fontFamily: "Zulip Icons"); + /// The Zulip custom icon "eye". + static const IconData eye = IconData(0xf111, fontFamily: "Zulip Icons"); + + /// The Zulip custom icon "eye_off". + static const IconData eye_off = IconData(0xf112, fontFamily: "Zulip Icons"); + /// The Zulip custom icon "follow". - static const IconData follow = IconData(0xf111, fontFamily: "Zulip Icons"); + static const IconData follow = IconData(0xf113, fontFamily: "Zulip Icons"); /// The Zulip custom icon "format_quote". - static const IconData format_quote = IconData(0xf112, fontFamily: "Zulip Icons"); + static const IconData format_quote = IconData(0xf114, fontFamily: "Zulip Icons"); /// The Zulip custom icon "globe". - static const IconData globe = IconData(0xf113, fontFamily: "Zulip Icons"); + static const IconData globe = IconData(0xf115, fontFamily: "Zulip Icons"); /// The Zulip custom icon "group_dm". - static const IconData group_dm = IconData(0xf114, fontFamily: "Zulip Icons"); + static const IconData group_dm = IconData(0xf116, fontFamily: "Zulip Icons"); /// The Zulip custom icon "hash_italic". - static const IconData hash_italic = IconData(0xf115, fontFamily: "Zulip Icons"); + static const IconData hash_italic = IconData(0xf117, fontFamily: "Zulip Icons"); /// The Zulip custom icon "hash_sign". - static const IconData hash_sign = IconData(0xf116, fontFamily: "Zulip Icons"); + static const IconData hash_sign = IconData(0xf118, fontFamily: "Zulip Icons"); /// The Zulip custom icon "image". - static const IconData image = IconData(0xf117, fontFamily: "Zulip Icons"); + static const IconData image = IconData(0xf119, fontFamily: "Zulip Icons"); /// The Zulip custom icon "inbox". - static const IconData inbox = IconData(0xf118, fontFamily: "Zulip Icons"); + static const IconData inbox = IconData(0xf11a, fontFamily: "Zulip Icons"); /// The Zulip custom icon "info". - static const IconData info = IconData(0xf119, fontFamily: "Zulip Icons"); + static const IconData info = IconData(0xf11b, fontFamily: "Zulip Icons"); /// The Zulip custom icon "inherit". - static const IconData inherit = IconData(0xf11a, fontFamily: "Zulip Icons"); + static const IconData inherit = IconData(0xf11c, fontFamily: "Zulip Icons"); /// The Zulip custom icon "language". - static const IconData language = IconData(0xf11b, fontFamily: "Zulip Icons"); + static const IconData language = IconData(0xf11d, fontFamily: "Zulip Icons"); /// The Zulip custom icon "lock". - static const IconData lock = IconData(0xf11c, fontFamily: "Zulip Icons"); + static const IconData lock = IconData(0xf11e, fontFamily: "Zulip Icons"); /// The Zulip custom icon "menu". - static const IconData menu = IconData(0xf11d, fontFamily: "Zulip Icons"); + static const IconData menu = IconData(0xf11f, fontFamily: "Zulip Icons"); /// The Zulip custom icon "message_checked". - static const IconData message_checked = IconData(0xf11e, fontFamily: "Zulip Icons"); + static const IconData message_checked = IconData(0xf120, fontFamily: "Zulip Icons"); /// The Zulip custom icon "message_feed". - static const IconData message_feed = IconData(0xf11f, fontFamily: "Zulip Icons"); + static const IconData message_feed = IconData(0xf121, fontFamily: "Zulip Icons"); /// The Zulip custom icon "mute". - static const IconData mute = IconData(0xf120, fontFamily: "Zulip Icons"); + static const IconData mute = IconData(0xf122, fontFamily: "Zulip Icons"); + + /// The Zulip custom icon "person". + static const IconData person = IconData(0xf123, fontFamily: "Zulip Icons"); /// The Zulip custom icon "plus". - static const IconData plus = IconData(0xf121, fontFamily: "Zulip Icons"); + static const IconData plus = IconData(0xf124, fontFamily: "Zulip Icons"); /// The Zulip custom icon "read_receipts". - static const IconData read_receipts = IconData(0xf122, fontFamily: "Zulip Icons"); + static const IconData read_receipts = IconData(0xf125, fontFamily: "Zulip Icons"); /// The Zulip custom icon "send". - static const IconData send = IconData(0xf123, fontFamily: "Zulip Icons"); + static const IconData send = IconData(0xf126, fontFamily: "Zulip Icons"); /// The Zulip custom icon "settings". - static const IconData settings = IconData(0xf124, fontFamily: "Zulip Icons"); + static const IconData settings = IconData(0xf127, fontFamily: "Zulip Icons"); /// The Zulip custom icon "share". - static const IconData share = IconData(0xf125, fontFamily: "Zulip Icons"); + static const IconData share = IconData(0xf128, fontFamily: "Zulip Icons"); /// The Zulip custom icon "share_ios". - static const IconData share_ios = IconData(0xf126, fontFamily: "Zulip Icons"); + static const IconData share_ios = IconData(0xf129, fontFamily: "Zulip Icons"); /// The Zulip custom icon "smile". - static const IconData smile = IconData(0xf127, fontFamily: "Zulip Icons"); + static const IconData smile = IconData(0xf12a, fontFamily: "Zulip Icons"); /// The Zulip custom icon "star". - static const IconData star = IconData(0xf128, fontFamily: "Zulip Icons"); + static const IconData star = IconData(0xf12b, fontFamily: "Zulip Icons"); /// The Zulip custom icon "star_filled". - static const IconData star_filled = IconData(0xf129, fontFamily: "Zulip Icons"); + static const IconData star_filled = IconData(0xf12c, fontFamily: "Zulip Icons"); /// The Zulip custom icon "three_person". - static const IconData three_person = IconData(0xf12a, fontFamily: "Zulip Icons"); + static const IconData three_person = IconData(0xf12d, fontFamily: "Zulip Icons"); /// The Zulip custom icon "topic". - static const IconData topic = IconData(0xf12b, fontFamily: "Zulip Icons"); + static const IconData topic = IconData(0xf12e, fontFamily: "Zulip Icons"); /// The Zulip custom icon "topics". - static const IconData topics = IconData(0xf12c, fontFamily: "Zulip Icons"); + static const IconData topics = IconData(0xf12f, fontFamily: "Zulip Icons"); - /// The Zulip custom icon "unmute". - static const IconData unmute = IconData(0xf12d, fontFamily: "Zulip Icons"); + /// The Zulip custom icon "two_person". + static const IconData two_person = IconData(0xf130, fontFamily: "Zulip Icons"); - /// The Zulip custom icon "user". - static const IconData user = IconData(0xf12e, fontFamily: "Zulip Icons"); + /// The Zulip custom icon "unmute". + static const IconData unmute = IconData(0xf131, fontFamily: "Zulip Icons"); // END GENERATED ICON DATA } diff --git a/lib/widgets/inbox.dart b/lib/widgets/inbox.dart index 702e4135bf..cd1822bbac 100644 --- a/lib/widgets/inbox.dart +++ b/lib/widgets/inbox.dart @@ -327,7 +327,7 @@ class _AllDmsHeaderItem extends _HeaderItem { @override String title(ZulipLocalizations zulipLocalizations) => zulipLocalizations.recentDmConversationsSectionHeader; - @override IconData get icon => ZulipIcons.user; + @override IconData get icon => ZulipIcons.two_person; // TODO(design) check if this is the right variable for these @override Color collapsedIconColor(context) => DesignVariables.of(context).labelMenuButton; diff --git a/lib/widgets/message_list.dart b/lib/widgets/message_list.dart index a34a25bb37..14c33ad5fd 100644 --- a/lib/widgets/message_list.dart +++ b/lib/widgets/message_list.dart @@ -1389,7 +1389,7 @@ class DmRecipientHeader extends StatelessWidget { child: Icon( color: designVariables.title, size: 16, - ZulipIcons.user)), + ZulipIcons.two_person)), Expanded( child: Text(title, style: recipientHeaderTextStyle(context), diff --git a/test/widgets/home_test.dart b/test/widgets/home_test.dart index efad9e6b9a..1b5c8ad8b5 100644 --- a/test/widgets/home_test.dart +++ b/test/widgets/home_test.dart @@ -125,7 +125,7 @@ void main () { of: find.byType(ZulipAppBar), matching: find.text('Channels'))).findsOne(); - await tester.tap(find.byIcon(ZulipIcons.user)); + await tester.tap(find.byIcon(ZulipIcons.two_person)); await tester.pump(); check(find.descendant( of: find.byType(ZulipAppBar), diff --git a/test/widgets/message_list_test.dart b/test/widgets/message_list_test.dart index 8ead103d68..f048bf437d 100644 --- a/test/widgets/message_list_test.dart +++ b/test/widgets/message_list_test.dart @@ -1431,7 +1431,7 @@ void main() { final textSpan = tester.renderObject(find.text( zulipLocalizations.messageListGroupYouAndOthers( zulipLocalizations.unknownUserName))).text; - final icon = tester.widget(find.byIcon(ZulipIcons.user)); + final icon = tester.widget(find.byIcon(ZulipIcons.two_person)); check(textSpan).style.isNotNull().color.isNotNull().isSameColorAs(icon.color!); }); }); diff --git a/test/widgets/new_dm_sheet_test.dart b/test/widgets/new_dm_sheet_test.dart index f1f72d272d..65d92f72a2 100644 --- a/test/widgets/new_dm_sheet_test.dart +++ b/test/widgets/new_dm_sheet_test.dart @@ -38,7 +38,7 @@ Future setupSheet(WidgetTester tester, { child: const HomePage())); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(ZulipIcons.user)); + await tester.tap(find.byIcon(ZulipIcons.two_person)); await tester.pumpAndSettle(); await tester.tap(find.widgetWithText(GestureDetector, 'New DM')); diff --git a/test/widgets/recent_dm_conversations_test.dart b/test/widgets/recent_dm_conversations_test.dart index 6bd01b40c8..b7307ef6f2 100644 --- a/test/widgets/recent_dm_conversations_test.dart +++ b/test/widgets/recent_dm_conversations_test.dart @@ -58,7 +58,7 @@ Future setupPage(WidgetTester tester, { // Switch to direct messages tab. await tester.tap(find.descendant( of: find.byType(Center), - matching: find.byIcon(ZulipIcons.user))); + matching: find.byIcon(ZulipIcons.two_person))); await tester.pump(); }