Skip to content

Commit a54bd67

Browse files
committed
Merge remote-tracking branch 'pr/1560'
2 parents 83e7d17 + c90fa9d commit a54bd67

36 files changed

+888
-260
lines changed

assets/l10n/app_en.arb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,17 +1007,13 @@
10071007
"@noEarlierMessages": {
10081008
"description": "Text to show at the start of a message list if there are no earlier messages."
10091009
},
1010-
"mutedSender": "Muted sender",
1011-
"@mutedSender": {
1012-
"description": "Name for a muted user to display in message list."
1013-
},
1014-
"revealButtonLabel": "Reveal message for muted sender",
1010+
"revealButtonLabel": "Reveal message",
10151011
"@revealButtonLabel": {
10161012
"description": "Label for the button revealing hidden message from a muted sender in message list."
10171013
},
10181014
"mutedUser": "Muted user",
10191015
"@mutedUser": {
1020-
"description": "Name for a muted user to display all over the app."
1016+
"description": "Text to display in place of a muted user's name."
10211017
},
10221018
"scrollToBottomTooltip": "Scroll to bottom",
10231019
"@scrollToBottomTooltip": {

lib/generated/l10n/zulip_localizations.dart

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,19 +1499,13 @@ abstract class ZulipLocalizations {
14991499
/// **'No earlier messages'**
15001500
String get noEarlierMessages;
15011501

1502-
/// Name for a muted user to display in message list.
1503-
///
1504-
/// In en, this message translates to:
1505-
/// **'Muted sender'**
1506-
String get mutedSender;
1507-
15081502
/// Label for the button revealing hidden message from a muted sender in message list.
15091503
///
15101504
/// In en, this message translates to:
1511-
/// **'Reveal message for muted sender'**
1505+
/// **'Reveal message'**
15121506
String get revealButtonLabel;
15131507

1514-
/// Name for a muted user to display all over the app.
1508+
/// Text to display in place of a muted user's name.
15151509
///
15161510
/// In en, this message translates to:
15171511
/// **'Muted user'**

lib/generated/l10n/zulip_localizations_ar.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,7 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
820820
String get noEarlierMessages => 'No earlier messages';
821821

822822
@override
823-
String get mutedSender => 'Muted sender';
824-
825-
@override
826-
String get revealButtonLabel => 'Reveal message for muted sender';
823+
String get revealButtonLabel => 'Reveal message';
827824

828825
@override
829826
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_de.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,7 @@ class ZulipLocalizationsDe extends ZulipLocalizations {
820820
String get noEarlierMessages => 'No earlier messages';
821821

822822
@override
823-
String get mutedSender => 'Muted sender';
824-
825-
@override
826-
String get revealButtonLabel => 'Reveal message for muted sender';
823+
String get revealButtonLabel => 'Reveal message';
827824

828825
@override
829826
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_en.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,7 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
820820
String get noEarlierMessages => 'No earlier messages';
821821

822822
@override
823-
String get mutedSender => 'Muted sender';
824-
825-
@override
826-
String get revealButtonLabel => 'Reveal message for muted sender';
823+
String get revealButtonLabel => 'Reveal message';
827824

828825
@override
829826
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_ja.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,7 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
820820
String get noEarlierMessages => 'No earlier messages';
821821

822822
@override
823-
String get mutedSender => 'Muted sender';
824-
825-
@override
826-
String get revealButtonLabel => 'Reveal message for muted sender';
823+
String get revealButtonLabel => 'Reveal message';
827824

828825
@override
829826
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_nb.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,7 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
820820
String get noEarlierMessages => 'No earlier messages';
821821

822822
@override
823-
String get mutedSender => 'Muted sender';
824-
825-
@override
826-
String get revealButtonLabel => 'Reveal message for muted sender';
823+
String get revealButtonLabel => 'Reveal message';
827824

828825
@override
829826
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_pl.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -831,10 +831,7 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
831831
String get noEarlierMessages => 'Brak historii';
832832

833833
@override
834-
String get mutedSender => 'Muted sender';
835-
836-
@override
837-
String get revealButtonLabel => 'Reveal message for muted sender';
834+
String get revealButtonLabel => 'Reveal message';
838835

839836
@override
840837
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_ru.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -834,10 +834,7 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
834834
String get noEarlierMessages => 'Предшествующих сообщений нет';
835835

836836
@override
837-
String get mutedSender => 'Muted sender';
838-
839-
@override
840-
String get revealButtonLabel => 'Reveal message for muted sender';
837+
String get revealButtonLabel => 'Reveal message';
841838

842839
@override
843840
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_sk.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -822,10 +822,7 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
822822
String get noEarlierMessages => 'No earlier messages';
823823

824824
@override
825-
String get mutedSender => 'Muted sender';
826-
827-
@override
828-
String get revealButtonLabel => 'Reveal message for muted sender';
825+
String get revealButtonLabel => 'Reveal message';
829826

830827
@override
831828
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_uk.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -834,10 +834,7 @@ class ZulipLocalizationsUk extends ZulipLocalizations {
834834
String get noEarlierMessages => 'Немає попередніх повідомлень';
835835

836836
@override
837-
String get mutedSender => 'Muted sender';
838-
839-
@override
840-
String get revealButtonLabel => 'Reveal message for muted sender';
837+
String get revealButtonLabel => 'Reveal message';
841838

842839
@override
843840
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_zh.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,7 @@ class ZulipLocalizationsZh extends ZulipLocalizations {
820820
String get noEarlierMessages => 'No earlier messages';
821821

822822
@override
823-
String get mutedSender => 'Muted sender';
824-
825-
@override
826-
String get revealButtonLabel => 'Reveal message for muted sender';
823+
String get revealButtonLabel => 'Reveal message';
827824

828825
@override
829826
String get mutedUser => 'Muted user';

lib/model/compose.dart

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,33 @@ String wrapWithBacktickFence({required String content, String? infoString}) {
130130
/// To omit the user ID part ("|13313") whenever the name part is unambiguous,
131131
/// pass the full UserStore. This means accepting a linear scan
132132
/// through all users; avoid it in performance-sensitive codepaths.
133+
///
134+
/// See also [userMentionFromMessage].
133135
String userMention(User user, {bool silent = false, UserStore? users}) {
134136
bool includeUserId = users == null
135137
|| users.allUsers.where((u) => u.fullName == user.fullName)
136138
.take(2).length == 2;
137-
138-
return '@${silent ? '_' : ''}**${user.fullName}${includeUserId ? '|${user.userId}' : ''}**';
139+
return _userMentionImpl(
140+
silent: silent,
141+
fullName: user.fullName,
142+
userId: includeUserId ? user.userId : null);
139143
}
140144

145+
/// An @-mention of an individual user, like @**Chris Bobbe|13313**,
146+
/// from sender data in a [Message].
147+
///
148+
/// The user ID part ("|13313") is always included.
149+
///
150+
/// See also [userMention].
151+
String userMentionFromMessage(Message message, {bool silent = false, required UserStore users}) =>
152+
_userMentionImpl(
153+
silent: silent,
154+
fullName: users.senderDisplayName(message, replaceIfMuted: false),
155+
userId: message.senderId);
156+
157+
String _userMentionImpl({required bool silent, required String fullName, int? userId}) =>
158+
'@${silent ? '_' : ''}**$fullName${userId != null ? '|$userId' : ''}**';
159+
141160
/// An @-mention of all the users in a conversation, like @**channel**.
142161
String wildcardMention(WildcardMentionOption wildcardOption, {
143162
required PerAccountStore store,
@@ -190,13 +209,11 @@ String quoteAndReplyPlaceholder(
190209
PerAccountStore store, {
191210
required Message message,
192211
}) {
193-
final sender = store.getUser(message.senderId);
194-
assert(sender != null); // TODO(#716): should use `store.senderDisplayName`
195212
final url = narrowLink(store,
196213
SendableNarrow.ofMessage(message, selfUserId: store.selfUserId),
197214
nearMessageId: message.id);
198-
// See note in [quoteAndReply] about asking `mention` to omit the |<id> part.
199-
return '${userMention(sender!, silent: true)} ${inlineLink('said', url)}: ' // TODO(#1285)
215+
return '${userMentionFromMessage(message, silent: true, users: store)} '
216+
'${inlineLink('said', url)}: ' // TODO(#1285)
200217
'*${zulipLocalizations.composeBoxLoadingMessage(message.id)}*\n';
201218
}
202219

@@ -212,14 +229,10 @@ String quoteAndReply(PerAccountStore store, {
212229
required Message message,
213230
required String rawContent,
214231
}) {
215-
final sender = store.getUser(message.senderId);
216-
assert(sender != null); // TODO(#716): should use `store.senderDisplayName`
217232
final url = narrowLink(store,
218233
SendableNarrow.ofMessage(message, selfUserId: store.selfUserId),
219234
nearMessageId: message.id);
220-
// Could ask `mention` to omit the |<id> part unless the mention is ambiguous…
221-
// but that would mean a linear scan through all users, and the extra noise
222-
// won't much matter with the already probably-long message link in there too.
223-
return '${userMention(sender!, silent: true)} ${inlineLink('said', url)}:\n' // TODO(#1285)
235+
return '${userMentionFromMessage(message, silent: true, users: store)} '
236+
'${inlineLink('said', url)}:\n' // TODO(#1285)
224237
'${wrapWithBacktickFence(content: rawContent, infoString: 'quote')}';
225238
}

lib/model/store.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -675,10 +675,13 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
675675
return byDate.difference(dateJoined).inDays >= realmWaitingPeriodThreshold;
676676
}
677677

678-
/// The given user's real email address, if known, for displaying in the UI.
678+
/// The user's real email address, if known, for displaying in the UI.
679679
///
680-
/// Returns null if self-user isn't able to see [user]'s real email address.
681-
String? userDisplayEmail(User user) {
680+
/// Returns null if self-user isn't able to see the user's real email address,
681+
/// or if the user isn't actually a user we know about.
682+
String? userDisplayEmail(int userId) {
683+
final user = getUser(userId);
684+
if (user == null) return null;
682685
if (zulipFeatureLevel >= 163) { // TODO(server-7)
683686
// A non-null value means self-user has access to [user]'s real email,
684687
// while a null value means it doesn't have access to the email.

lib/model/user.dart

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,27 +44,40 @@ mixin UserStore on PerAccountStoreBase {
4444

4545
/// The name to show the given user as in the UI, even for unknown users.
4646
///
47-
/// This is the user's [User.fullName] if the user is known,
48-
/// and otherwise a translation of "(unknown user)".
47+
/// If the user is muted and [replaceIfMuted] is true (the default),
48+
/// this is [ZulipLocalizations.mutedUser].
49+
///
50+
/// Otherwise this is the user's [User.fullName] if the user is known,
51+
/// or (if unknown) [ZulipLocalizations.unknownUserName].
4952
///
5053
/// When a [Message] is available which the user sent,
5154
/// use [senderDisplayName] instead for a better-informed fallback.
52-
String userDisplayName(int userId) {
55+
String userDisplayName(int userId, {bool replaceIfMuted = true}) {
56+
if (replaceIfMuted && isUserMuted(userId)) {
57+
return GlobalLocalizations.zulipLocalizations.mutedUser;
58+
}
5359
return getUser(userId)?.fullName
5460
?? GlobalLocalizations.zulipLocalizations.unknownUserName;
5561
}
5662

5763
/// The name to show for the given message's sender in the UI.
5864
///
59-
/// If the user is known (see [getUser]), this is their current [User.fullName].
65+
/// If the sender is muted and [replaceIfMuted] is true (the default),
66+
/// this is [ZulipLocalizations.mutedUser].
67+
///
68+
/// Otherwise, if the user is known (see [getUser]),
69+
/// this is their current [User.fullName].
6070
/// If unknown, this uses the fallback value conveniently provided on the
6171
/// [Message] object itself, namely [Message.senderFullName].
6272
///
6373
/// For a user who isn't the sender of some known message,
6474
/// see [userDisplayName].
65-
String senderDisplayName(Message message) {
66-
return getUser(message.senderId)?.fullName
67-
?? message.senderFullName;
75+
String senderDisplayName(Message message, {bool replaceIfMuted = true}) {
76+
final senderId = message.senderId;
77+
if (replaceIfMuted && isUserMuted(senderId)) {
78+
return GlobalLocalizations.zulipLocalizations.mutedUser;
79+
}
80+
return getUser(senderId)?.fullName ?? message.senderFullName;
6881
}
6982

7083
/// Whether the user with [userId] is muted by the self-user.

lib/widgets/action_sheet.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,8 @@ void showMessageActionSheet({required BuildContext context, required Message mes
589589
final markAsUnreadSupported = store.zulipFeatureLevel >= 155; // TODO(server-6)
590590
final showMarkAsUnreadButton = markAsUnreadSupported && isMessageRead;
591591

592+
final isSenderMuted = store.isUserMuted(message.senderId);
593+
592594
final optionButtons = [
593595
if (popularEmojiLoaded)
594596
ReactionButtons(message: message, pageContext: pageContext),
@@ -597,6 +599,8 @@ void showMessageActionSheet({required BuildContext context, required Message mes
597599
QuoteAndReplyButton(message: message, pageContext: pageContext),
598600
if (showMarkAsUnreadButton)
599601
MarkAsUnreadButton(message: message, pageContext: pageContext),
602+
if (isSenderMuted)
603+
UnrevealMutedMessageButton(message: message, pageContext: pageContext),
600604
CopyMessageTextButton(message: message, pageContext: pageContext),
601605
CopyMessageLinkButton(message: message, pageContext: pageContext),
602606
ShareButton(message: message, pageContext: pageContext),
@@ -902,6 +906,27 @@ class MarkAsUnreadButton extends MessageActionSheetMenuItemButton {
902906
}
903907
}
904908

909+
class UnrevealMutedMessageButton extends MessageActionSheetMenuItemButton {
910+
UnrevealMutedMessageButton({
911+
super.key,
912+
required super.message,
913+
required super.pageContext,
914+
});
915+
916+
@override
917+
IconData get icon => ZulipIcons.eye_off;
918+
919+
@override
920+
String label(ZulipLocalizations zulipLocalizations) {
921+
return zulipLocalizations.actionSheetOptionHideMutedMessage;
922+
}
923+
924+
@override
925+
void onPressed() {
926+
findMessageListPage().unrevealMutedMessage(message.id);
927+
}
928+
}
929+
905930
class CopyMessageTextButton extends MessageActionSheetMenuItemButton {
906931
CopyMessageTextButton({super.key, required super.message, required super.pageContext});
907932

lib/widgets/autocomplete.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,9 @@ class _MentionAutocompleteItem extends StatelessWidget {
275275
String? sublabel;
276276
switch (option) {
277277
case UserMentionAutocompleteResult(:var userId):
278-
final user = store.getUser(userId)!; // must exist because UserMentionAutocompleteResult
279278
avatar = Avatar(userId: userId, size: 36, borderRadius: 4);
280-
label = user.fullName;
281-
sublabel = store.userDisplayEmail(user);
279+
label = store.userDisplayName(userId);
280+
sublabel = store.userDisplayEmail(userId);
282281
case WildcardMentionAutocompleteResult(:var wildcardOption):
283282
avatar = SizedBox.square(dimension: 36,
284283
child: const Icon(ZulipIcons.three_person, size: 24));

0 commit comments

Comments
 (0)