Skip to content

Commit c90fa9d

Browse files
chrisbobbesm-sayedi
andcommitted
msglist: Hide content of muted messages, with a "Reveal message" button
Figma design: https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=6089-28385&t=28DdYiTs6fXWR9ua-0 Co-authored-by: Sayed Mahmood Sayedi <[email protected]>
1 parent d5553a4 commit c90fa9d

16 files changed

+221
-39
lines changed

assets/l10n/app_en.arb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@
983983
"@noEarlierMessages": {
984984
"description": "Text to show at the start of a message list if there are no earlier messages."
985985
},
986-
"revealButtonLabel": "Reveal message for muted sender",
986+
"revealButtonLabel": "Reveal message",
987987
"@revealButtonLabel": {
988988
"description": "Label for the button revealing hidden message from a muted sender in message list."
989989
},

lib/generated/l10n/zulip_localizations.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,7 @@ abstract class ZulipLocalizations {
14661466
/// Label for the button revealing hidden message from a muted sender in message list.
14671467
///
14681468
/// In en, this message translates to:
1469-
/// **'Reveal message for muted sender'**
1469+
/// **'Reveal message'**
14701470
String get revealButtonLabel;
14711471

14721472
/// Text to display in place of a muted user's name.

lib/generated/l10n/zulip_localizations_ar.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
797797
String get noEarlierMessages => 'No earlier messages';
798798

799799
@override
800-
String get revealButtonLabel => 'Reveal message for muted sender';
800+
String get revealButtonLabel => 'Reveal message';
801801

802802
@override
803803
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_de.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ class ZulipLocalizationsDe extends ZulipLocalizations {
797797
String get noEarlierMessages => 'No earlier messages';
798798

799799
@override
800-
String get revealButtonLabel => 'Reveal message for muted sender';
800+
String get revealButtonLabel => 'Reveal message';
801801

802802
@override
803803
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_en.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
797797
String get noEarlierMessages => 'No earlier messages';
798798

799799
@override
800-
String get revealButtonLabel => 'Reveal message for muted sender';
800+
String get revealButtonLabel => 'Reveal message';
801801

802802
@override
803803
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_ja.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
797797
String get noEarlierMessages => 'No earlier messages';
798798

799799
@override
800-
String get revealButtonLabel => 'Reveal message for muted sender';
800+
String get revealButtonLabel => 'Reveal message';
801801

802802
@override
803803
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_nb.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
797797
String get noEarlierMessages => 'No earlier messages';
798798

799799
@override
800-
String get revealButtonLabel => 'Reveal message for muted sender';
800+
String get revealButtonLabel => 'Reveal message';
801801

802802
@override
803803
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_pl.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
808808
String get noEarlierMessages => 'Brak historii';
809809

810810
@override
811-
String get revealButtonLabel => 'Reveal message for muted sender';
811+
String get revealButtonLabel => 'Reveal message';
812812

813813
@override
814814
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_ru.dart

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

813813
@override
814-
String get revealButtonLabel => 'Reveal message for muted sender';
814+
String get revealButtonLabel => 'Reveal message';
815815

816816
@override
817817
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_sk.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
799799
String get noEarlierMessages => 'No earlier messages';
800800

801801
@override
802-
String get revealButtonLabel => 'Reveal message for muted sender';
802+
String get revealButtonLabel => 'Reveal message';
803803

804804
@override
805805
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_uk.dart

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

813813
@override
814-
String get revealButtonLabel => 'Reveal message for muted sender';
814+
String get revealButtonLabel => 'Reveal message';
815815

816816
@override
817817
String get mutedUser => 'Muted user';

lib/generated/l10n/zulip_localizations_zh.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ class ZulipLocalizationsZh extends ZulipLocalizations {
797797
String get noEarlierMessages => 'No earlier messages';
798798

799799
@override
800-
String get revealButtonLabel => 'Reveal message for muted sender';
800+
String get revealButtonLabel => 'Reveal message';
801801

802802
@override
803803
String get mutedUser => 'Muted 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/message_list.dart

Lines changed: 83 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import '../model/typing_status.dart';
1212
import 'action_sheet.dart';
1313
import 'actions.dart';
1414
import 'app_bar.dart';
15+
import 'button.dart';
1516
import 'color.dart';
1617
import 'compose_box.dart';
1718
import 'content.dart';
@@ -138,6 +139,19 @@ abstract class MessageListPageState {
138139
///
139140
/// This is null if [MessageList] has not mounted yet.
140141
MessageListView? get model;
142+
143+
/// The "revealed" state of a message from a muted sender.
144+
///
145+
/// See also: [revealMutedMessage], [unrevealMutedMessage].
146+
bool isMutedMessageRevealed(int messageId);
147+
148+
/// For a message from a muted sender, reveal the sender and content,
149+
/// replacing the "Muted user" placeholder.
150+
void revealMutedMessage(int messageId);
151+
152+
/// For a message from a muted sender, hide the sender and content again
153+
/// with the "Muted user" placeholder.
154+
void unrevealMutedMessage(int messageId);
141155
}
142156

143157
class MessageListPage extends StatefulWidget {
@@ -183,6 +197,25 @@ class _MessageListPageState extends State<MessageListPage> implements MessageLis
183197
MessageListView? get model => _messageListKey.currentState?.model;
184198
final GlobalKey<_MessageListState> _messageListKey = GlobalKey();
185199

200+
@override
201+
bool isMutedMessageRevealed(int messageId) =>
202+
_revealedMutedMessages.contains(messageId);
203+
final Set<int> _revealedMutedMessages = {};
204+
205+
@override
206+
void revealMutedMessage(int messageId) {
207+
setState(() {
208+
_revealedMutedMessages.add(messageId);
209+
});
210+
}
211+
212+
@override
213+
void unrevealMutedMessage(int messageId) {
214+
setState(() {
215+
_revealedMutedMessages.remove(messageId);
216+
});
217+
}
218+
186219
@override
187220
void initState() {
188221
super.initState();
@@ -1447,12 +1480,18 @@ class _SenderRow extends StatelessWidget {
14471480
@override
14481481
Widget build(BuildContext context) {
14491482
final store = PerAccountStoreWidget.of(context);
1483+
final messageListPage = MessageListPage.ancestorOf(context);
14501484
final messageListTheme = MessageListTheme.of(context);
14511485
final designVariables = DesignVariables.of(context);
14521486

14531487
final sender = store.getUser(message.senderId);
14541488
final time = _kMessageTimestampFormat
14551489
.format(DateTime.fromMillisecondsSinceEpoch(1000 * message.timestamp));
1490+
1491+
final showAsMuted = store.isUserMuted(message.senderId)
1492+
&& message is Message // i.e., not an outbox message
1493+
&& !messageListPage.isMutedMessageRevealed((message as Message).id);
1494+
14561495
return Padding(
14571496
padding: const EdgeInsets.fromLTRB(16, 2, 16, 0),
14581497
child: Row(
@@ -1461,22 +1500,26 @@ class _SenderRow extends StatelessWidget {
14611500
children: [
14621501
Flexible(
14631502
child: GestureDetector(
1464-
onTap: () => Navigator.push(context,
1503+
onTap: () => showAsMuted ? null : Navigator.push(context,
14651504
ProfilePage.buildRoute(context: context,
14661505
userId: message.senderId)),
14671506
child: Row(
14681507
children: [
14691508
Avatar(size: 32, borderRadius: 3,
1470-
userId: message.senderId),
1509+
userId: message.senderId,
1510+
replaceIfMuted: showAsMuted),
14711511
const SizedBox(width: 8),
14721512
Flexible(
14731513
child: Text(message is Message
1474-
? store.senderDisplayName(message as Message)
1514+
? store.senderDisplayName(message as Message,
1515+
replaceIfMuted: showAsMuted)
14751516
: store.userDisplayName(message.senderId),
14761517
style: TextStyle(
14771518
fontSize: 18,
14781519
height: (22 / 18),
1479-
color: designVariables.title,
1520+
color: showAsMuted
1521+
? designVariables.title.withFadedAlpha(0.5)
1522+
: designVariables.title,
14801523
).merge(weightVariableTextStyle(context, wght: 600)),
14811524
overflow: TextOverflow.ellipsis)),
14821525
if (sender?.isBot ?? false) ...[
@@ -1514,6 +1557,7 @@ class MessageWithPossibleSender extends StatelessWidget {
15141557
@override
15151558
Widget build(BuildContext context) {
15161559
final store = PerAccountStoreWidget.of(context);
1560+
final messageListPage = MessageListPage.ancestorOf(context);
15171561
final designVariables = DesignVariables.of(context);
15181562
final message = item.message;
15191563

@@ -1557,6 +1601,9 @@ class MessageWithPossibleSender extends StatelessWidget {
15571601
}
15581602
}
15591603

1604+
final showAsMuted = store.isUserMuted(message.senderId)
1605+
&& !messageListPage.isMutedMessageRevealed(message.id);
1606+
15601607
return GestureDetector(
15611608
behavior: HitTestBehavior.translucent,
15621609
onLongPress: () => showMessageActionSheet(context: context, message: message),
@@ -1570,28 +1617,38 @@ class MessageWithPossibleSender extends StatelessWidget {
15701617
textBaseline: localizedTextBaseline(context),
15711618
children: [
15721619
const SizedBox(width: 16),
1573-
Expanded(child: Column(
1574-
crossAxisAlignment: CrossAxisAlignment.stretch,
1575-
children: [
1576-
content,
1577-
if ((message.reactions?.total ?? 0) > 0)
1578-
ReactionChipsList(messageId: message.id, reactions: message.reactions!),
1579-
if (editMessageErrorStatus != null)
1580-
_EditMessageStatusRow(messageId: message.id, status: editMessageErrorStatus)
1581-
else if (editStateText != null)
1582-
Padding(
1583-
padding: const EdgeInsets.only(bottom: 4),
1584-
child: Text(editStateText,
1585-
textAlign: TextAlign.end,
1586-
style: TextStyle(
1587-
color: designVariables.labelEdited,
1588-
fontSize: 12,
1589-
height: (12 / 12),
1590-
letterSpacing: proportionalLetterSpacing(context,
1591-
0.05, baseFontSize: 12))))
1592-
else
1593-
Padding(padding: const EdgeInsets.only(bottom: 4))
1594-
])),
1620+
Expanded(child: showAsMuted
1621+
? Align(
1622+
alignment: AlignmentDirectional.topStart,
1623+
child: ZulipWebUiKitButton(
1624+
label: zulipLocalizations.revealButtonLabel,
1625+
icon: ZulipIcons.eye,
1626+
size: ZulipWebUiKitButtonSize.small,
1627+
intent: ZulipWebUiKitButtonIntent.neutral,
1628+
attention: ZulipWebUiKitButtonAttention.minimal,
1629+
onPressed: () => messageListPage.revealMutedMessage(message.id)))
1630+
: Column(
1631+
crossAxisAlignment: CrossAxisAlignment.stretch,
1632+
children: [
1633+
content,
1634+
if ((message.reactions?.total ?? 0) > 0)
1635+
ReactionChipsList(messageId: message.id, reactions: message.reactions!),
1636+
if (editMessageErrorStatus != null)
1637+
_EditMessageStatusRow(messageId: message.id, status: editMessageErrorStatus)
1638+
else if (editStateText != null)
1639+
Padding(
1640+
padding: const EdgeInsets.only(bottom: 4),
1641+
child: Text(editStateText,
1642+
textAlign: TextAlign.end,
1643+
style: TextStyle(
1644+
color: designVariables.labelEdited,
1645+
fontSize: 12,
1646+
height: (12 / 12),
1647+
letterSpacing: proportionalLetterSpacing(context,
1648+
0.05, baseFontSize: 12))))
1649+
else
1650+
Padding(padding: const EdgeInsets.only(bottom: 4))
1651+
])),
15951652
SizedBox(width: 16,
15961653
child: star),
15971654
]),

0 commit comments

Comments
 (0)