Skip to content

Commit 83e7d17

Browse files
committed
Merge remote-tracking branch 'pr/1530'
2 parents 888b043 + 3669b15 commit 83e7d17

23 files changed

+192
-41
lines changed

assets/icons/ZulipIcons.ttf

804 Bytes
Binary file not shown.

assets/icons/eye.svg

Lines changed: 3 additions & 0 deletions
Loading

assets/icons/eye_off.svg

Lines changed: 3 additions & 0 deletions
Loading

assets/icons/person.svg

Lines changed: 10 additions & 0 deletions
Loading
File renamed without changes.

lib/api/model/events.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ sealed class Event {
6262
}
6363
// case 'muted_topics': … // TODO(#422) we ignore this feature on older servers
6464
case 'user_topic': return UserTopicEvent.fromJson(json);
65+
case 'muted_users': return MutedUsersEvent.fromJson(json);
6566
case 'message': return MessageEvent.fromJson(json);
6667
case 'update_message': return UpdateMessageEvent.fromJson(json);
6768
case 'delete_message': return DeleteMessageEvent.fromJson(json);
@@ -733,6 +734,24 @@ class UserTopicEvent extends Event {
733734
Map<String, dynamic> toJson() => _$UserTopicEventToJson(this);
734735
}
735736

737+
/// A Zulip event of type `muted_users`: https://zulip.com/api/get-events#muted_users
738+
@JsonSerializable(fieldRename: FieldRename.snake)
739+
class MutedUsersEvent extends Event {
740+
@override
741+
@JsonKey(includeToJson: true)
742+
String get type => 'muted_users';
743+
744+
final List<MutedUserItem> mutedUsers;
745+
746+
MutedUsersEvent({required super.id, required this.mutedUsers});
747+
748+
factory MutedUsersEvent.fromJson(Map<String, dynamic> json) =>
749+
_$MutedUsersEventFromJson(json);
750+
751+
@override
752+
Map<String, dynamic> toJson() => _$MutedUsersEventToJson(this);
753+
}
754+
736755
/// A Zulip event of type `message`: https://zulip.com/api/get-events#message
737756
@JsonSerializable(fieldRename: FieldRename.snake)
738757
class MessageEvent extends Event {

lib/api/model/events.g.dart

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/api/model/initial_snapshot.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class InitialSnapshot {
4444

4545
// final List<…> mutedTopics; // TODO(#422) we ignore this feature on older servers
4646

47+
final List<MutedUserItem> mutedUsers;
48+
4749
final Map<String, RealmEmojiItem> realmEmoji;
4850

4951
final List<RecentDmConversation> recentPrivateConversations;
@@ -132,6 +134,7 @@ class InitialSnapshot {
132134
required this.serverTypingStartedExpiryPeriodMilliseconds,
133135
required this.serverTypingStoppedWaitPeriodMilliseconds,
134136
required this.serverTypingStartedWaitPeriodMilliseconds,
137+
required this.mutedUsers,
135138
required this.realmEmoji,
136139
required this.recentPrivateConversations,
137140
required this.savedSnippets,

lib/api/model/initial_snapshot.g.dart

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/api/model/model.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,25 @@ class CustomProfileFieldExternalAccountData {
110110
Map<String, dynamic> toJson() => _$CustomProfileFieldExternalAccountDataToJson(this);
111111
}
112112

113+
/// An item in the [InitialSnapshot.mutedUsers] or [MutedUsersEvent].
114+
///
115+
/// For docs, search for "muted_users:"
116+
/// in <https://zulip.com/api/register-queue>.
117+
@JsonSerializable(fieldRename: FieldRename.snake)
118+
class MutedUserItem {
119+
final int id;
120+
121+
// Mobile doesn't use the timestamp; ignore.
122+
// final int timestamp;
123+
124+
const MutedUserItem({required this.id});
125+
126+
factory MutedUserItem.fromJson(Map<String, dynamic> json) =>
127+
_$MutedUserItemFromJson(json);
128+
129+
Map<String, dynamic> toJson() => _$MutedUserItemToJson(this);
130+
}
131+
113132
/// An item in [InitialSnapshot.realmEmoji] or [RealmEmojiUpdateEvent].
114133
///
115134
/// For docs, search for "realm_emoji:"

lib/api/model/model.g.dart

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/model/store.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,10 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
645645
@override
646646
Iterable<User> get allUsers => _users.allUsers;
647647

648+
@override
649+
bool isUserMuted(int userId, {Set<int>? mutedUsers}) =>
650+
_users.isUserMuted(userId, mutedUsers: mutedUsers);
651+
648652
final UserStoreImpl _users;
649653

650654
final TypingStatus typingStatus;
@@ -949,6 +953,11 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
949953
assert(debugLog("server event: reaction/${event.op}"));
950954
_messages.handleReactionEvent(event);
951955

956+
case MutedUsersEvent():
957+
assert(debugLog("server event: muted_users"));
958+
_users.handleMutedUsersEvent(event);
959+
notifyListeners();
960+
952961
case UnexpectedEvent():
953962
assert(debugLog("server event: ${jsonEncode(event.toJson())}")); // TODO log better
954963
}

lib/model/user.dart

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ mixin UserStore on PerAccountStoreBase {
6666
return getUser(message.senderId)?.fullName
6767
?? message.senderFullName;
6868
}
69+
70+
/// Whether the user with [userId] is muted by the self-user.
71+
///
72+
/// Looks for [userId] in a private [Set],
73+
/// or in [mutedUsers] instead if that's non-null.
74+
bool isUserMuted(int userId, {Set<int>? mutedUsers});
6975
}
7076

7177
/// The implementation of [UserStore] that does the work.
@@ -81,7 +87,8 @@ class UserStoreImpl extends PerAccountStoreBase with UserStore {
8187
initialSnapshot.realmUsers
8288
.followedBy(initialSnapshot.realmNonActiveUsers)
8389
.followedBy(initialSnapshot.crossRealmBots)
84-
.map((user) => MapEntry(user.userId, user)));
90+
.map((user) => MapEntry(user.userId, user))),
91+
_mutedUsers = Set.from(initialSnapshot.mutedUsers.map((item) => item.id));
8592

8693
final Map<int, User> _users;
8794

@@ -91,6 +98,13 @@ class UserStoreImpl extends PerAccountStoreBase with UserStore {
9198
@override
9299
Iterable<User> get allUsers => _users.values;
93100

101+
final Set<int> _mutedUsers;
102+
103+
@override
104+
bool isUserMuted(int userId, {Set<int>? mutedUsers}) {
105+
return (mutedUsers ?? _mutedUsers).contains(userId);
106+
}
107+
94108
void handleRealmUserEvent(RealmUserEvent event) {
95109
switch (event) {
96110
case RealmUserAddEvent():
@@ -129,4 +143,9 @@ class UserStoreImpl extends PerAccountStoreBase with UserStore {
129143
}
130144
}
131145
}
146+
147+
void handleMutedUsersEvent(MutedUsersEvent event) {
148+
_mutedUsers.clear();
149+
_mutedUsers.addAll(event.mutedUsers.map((item) => item.id));
150+
}
132151
}

lib/widgets/home.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class _HomePageState extends State<HomePage> {
111111
narrow: const CombinedFeedNarrow()))),
112112
button(_HomePageTab.channels, ZulipIcons.hash_italic),
113113
// TODO(#1094): Users
114-
button(_HomePageTab.directMessages, ZulipIcons.user),
114+
button(_HomePageTab.directMessages, ZulipIcons.two_person),
115115
_NavigationBarButton( icon: ZulipIcons.menu,
116116
selected: false,
117117
onPressed: () => _showMainMenu(context, tabNotifier: _tab)),
@@ -549,7 +549,7 @@ class _DirectMessagesButton extends _NavigationBarMenuButton {
549549
const _DirectMessagesButton({required super.tabNotifier});
550550

551551
@override
552-
IconData get icon => ZulipIcons.user;
552+
IconData get icon => ZulipIcons.two_person;
553553

554554
@override
555555
String label(ZulipLocalizations zulipLocalizations) {

lib/widgets/icons.dart

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -72,95 +72,104 @@ abstract final class ZulipIcons {
7272
/// The Zulip custom icon "edit".
7373
static const IconData edit = IconData(0xf110, fontFamily: "Zulip Icons");
7474

75+
/// The Zulip custom icon "eye".
76+
static const IconData eye = IconData(0xf111, fontFamily: "Zulip Icons");
77+
78+
/// The Zulip custom icon "eye_off".
79+
static const IconData eye_off = IconData(0xf112, fontFamily: "Zulip Icons");
80+
7581
/// The Zulip custom icon "follow".
76-
static const IconData follow = IconData(0xf111, fontFamily: "Zulip Icons");
82+
static const IconData follow = IconData(0xf113, fontFamily: "Zulip Icons");
7783

7884
/// The Zulip custom icon "format_quote".
79-
static const IconData format_quote = IconData(0xf112, fontFamily: "Zulip Icons");
85+
static const IconData format_quote = IconData(0xf114, fontFamily: "Zulip Icons");
8086

8187
/// The Zulip custom icon "globe".
82-
static const IconData globe = IconData(0xf113, fontFamily: "Zulip Icons");
88+
static const IconData globe = IconData(0xf115, fontFamily: "Zulip Icons");
8389

8490
/// The Zulip custom icon "group_dm".
85-
static const IconData group_dm = IconData(0xf114, fontFamily: "Zulip Icons");
91+
static const IconData group_dm = IconData(0xf116, fontFamily: "Zulip Icons");
8692

8793
/// The Zulip custom icon "hash_italic".
88-
static const IconData hash_italic = IconData(0xf115, fontFamily: "Zulip Icons");
94+
static const IconData hash_italic = IconData(0xf117, fontFamily: "Zulip Icons");
8995

9096
/// The Zulip custom icon "hash_sign".
91-
static const IconData hash_sign = IconData(0xf116, fontFamily: "Zulip Icons");
97+
static const IconData hash_sign = IconData(0xf118, fontFamily: "Zulip Icons");
9298

9399
/// The Zulip custom icon "image".
94-
static const IconData image = IconData(0xf117, fontFamily: "Zulip Icons");
100+
static const IconData image = IconData(0xf119, fontFamily: "Zulip Icons");
95101

96102
/// The Zulip custom icon "inbox".
97-
static const IconData inbox = IconData(0xf118, fontFamily: "Zulip Icons");
103+
static const IconData inbox = IconData(0xf11a, fontFamily: "Zulip Icons");
98104

99105
/// The Zulip custom icon "info".
100-
static const IconData info = IconData(0xf119, fontFamily: "Zulip Icons");
106+
static const IconData info = IconData(0xf11b, fontFamily: "Zulip Icons");
101107

102108
/// The Zulip custom icon "inherit".
103-
static const IconData inherit = IconData(0xf11a, fontFamily: "Zulip Icons");
109+
static const IconData inherit = IconData(0xf11c, fontFamily: "Zulip Icons");
104110

105111
/// The Zulip custom icon "language".
106-
static const IconData language = IconData(0xf11b, fontFamily: "Zulip Icons");
112+
static const IconData language = IconData(0xf11d, fontFamily: "Zulip Icons");
107113

108114
/// The Zulip custom icon "lock".
109-
static const IconData lock = IconData(0xf11c, fontFamily: "Zulip Icons");
115+
static const IconData lock = IconData(0xf11e, fontFamily: "Zulip Icons");
110116

111117
/// The Zulip custom icon "menu".
112-
static const IconData menu = IconData(0xf11d, fontFamily: "Zulip Icons");
118+
static const IconData menu = IconData(0xf11f, fontFamily: "Zulip Icons");
113119

114120
/// The Zulip custom icon "message_checked".
115-
static const IconData message_checked = IconData(0xf11e, fontFamily: "Zulip Icons");
121+
static const IconData message_checked = IconData(0xf120, fontFamily: "Zulip Icons");
116122

117123
/// The Zulip custom icon "message_feed".
118-
static const IconData message_feed = IconData(0xf11f, fontFamily: "Zulip Icons");
124+
static const IconData message_feed = IconData(0xf121, fontFamily: "Zulip Icons");
119125

120126
/// The Zulip custom icon "mute".
121-
static const IconData mute = IconData(0xf120, fontFamily: "Zulip Icons");
127+
static const IconData mute = IconData(0xf122, fontFamily: "Zulip Icons");
128+
129+
/// The Zulip custom icon "person".
130+
static const IconData person = IconData(0xf123, fontFamily: "Zulip Icons");
122131

123132
/// The Zulip custom icon "plus".
124-
static const IconData plus = IconData(0xf121, fontFamily: "Zulip Icons");
133+
static const IconData plus = IconData(0xf124, fontFamily: "Zulip Icons");
125134

126135
/// The Zulip custom icon "read_receipts".
127-
static const IconData read_receipts = IconData(0xf122, fontFamily: "Zulip Icons");
136+
static const IconData read_receipts = IconData(0xf125, fontFamily: "Zulip Icons");
128137

129138
/// The Zulip custom icon "send".
130-
static const IconData send = IconData(0xf123, fontFamily: "Zulip Icons");
139+
static const IconData send = IconData(0xf126, fontFamily: "Zulip Icons");
131140

132141
/// The Zulip custom icon "settings".
133-
static const IconData settings = IconData(0xf124, fontFamily: "Zulip Icons");
142+
static const IconData settings = IconData(0xf127, fontFamily: "Zulip Icons");
134143

135144
/// The Zulip custom icon "share".
136-
static const IconData share = IconData(0xf125, fontFamily: "Zulip Icons");
145+
static const IconData share = IconData(0xf128, fontFamily: "Zulip Icons");
137146

138147
/// The Zulip custom icon "share_ios".
139-
static const IconData share_ios = IconData(0xf126, fontFamily: "Zulip Icons");
148+
static const IconData share_ios = IconData(0xf129, fontFamily: "Zulip Icons");
140149

141150
/// The Zulip custom icon "smile".
142-
static const IconData smile = IconData(0xf127, fontFamily: "Zulip Icons");
151+
static const IconData smile = IconData(0xf12a, fontFamily: "Zulip Icons");
143152

144153
/// The Zulip custom icon "star".
145-
static const IconData star = IconData(0xf128, fontFamily: "Zulip Icons");
154+
static const IconData star = IconData(0xf12b, fontFamily: "Zulip Icons");
146155

147156
/// The Zulip custom icon "star_filled".
148-
static const IconData star_filled = IconData(0xf129, fontFamily: "Zulip Icons");
157+
static const IconData star_filled = IconData(0xf12c, fontFamily: "Zulip Icons");
149158

150159
/// The Zulip custom icon "three_person".
151-
static const IconData three_person = IconData(0xf12a, fontFamily: "Zulip Icons");
160+
static const IconData three_person = IconData(0xf12d, fontFamily: "Zulip Icons");
152161

153162
/// The Zulip custom icon "topic".
154-
static const IconData topic = IconData(0xf12b, fontFamily: "Zulip Icons");
163+
static const IconData topic = IconData(0xf12e, fontFamily: "Zulip Icons");
155164

156165
/// The Zulip custom icon "topics".
157-
static const IconData topics = IconData(0xf12c, fontFamily: "Zulip Icons");
166+
static const IconData topics = IconData(0xf12f, fontFamily: "Zulip Icons");
158167

159-
/// The Zulip custom icon "unmute".
160-
static const IconData unmute = IconData(0xf12d, fontFamily: "Zulip Icons");
168+
/// The Zulip custom icon "two_person".
169+
static const IconData two_person = IconData(0xf130, fontFamily: "Zulip Icons");
161170

162-
/// The Zulip custom icon "user".
163-
static const IconData user = IconData(0xf12e, fontFamily: "Zulip Icons");
171+
/// The Zulip custom icon "unmute".
172+
static const IconData unmute = IconData(0xf131, fontFamily: "Zulip Icons");
164173

165174
// END GENERATED ICON DATA
166175
}

0 commit comments

Comments
 (0)