Skip to content

Mute muted users (Chris's revision, 2 of 2) #1561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from

Conversation

chrisbobbe
Copy link
Collaborator

Stacked on #1560.

Many thanks again to @sm-sayedi for your work on this! As with #1560, this is meant to take #1429 across the finish line in time for the upcoming app launch. Thanks again for making sure I had your latest revision of #1429 before you left for vacation. 🙂

In these new commits:

  • In "Direct messages" (the recent-DMs page), we exclude conversations where everyone is muted.
  • In "Combined feed", "Starred", and "Mentions", we exclude messages in those conversations.
  • In the typing-status text ("Chris Bobbe is typing…"), we exclude muted users.

Fixes: #296

@chrisbobbe chrisbobbe requested a review from gnprice June 10, 2025 20:51
@chrisbobbe chrisbobbe added the integration review Added by maintainers when PR may be ready for integration label Jun 10, 2025
@chrisbobbe chrisbobbe force-pushed the pr-chris-muted-users-2 branch from 9c82301 to 0acc63b Compare June 12, 2025 19:39
@chrisbobbe
Copy link
Collaborator Author

chrisbobbe commented Jun 12, 2025

Revision pushed; this one also excludes muted users from the new new-DM UI, which landed after my last revision.

Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I've read so far the first three commits:
8af150c recent-dms: Exclude DM conversations where all other recipients are muted
06937e2 msglist [nfc]: Place _allMessagesVisible right after _messageVisible
8339c64 msglist [nfc]: s/VisibilityEffect/UserTopicVisibilityEffect/

and the next one except for its tests:
898a2ad msglist: In combined/mentions/starred, exclude DMs if all recipients muted

Generally all looks good; a few small comments below.

That leaves four more commits that I haven't read (though I've skimmed them):
619eb24 autocomplete: Exclude muted users from user-mention autocomplete
87df780 msglist [nfc]: Represent nobody-is-typing as null, not empty list
c40cb89 msglist: Exclude muted users from typing-status text
0acc63b new-dm: Exclude muted users

Comment on lines -152 to +154
(false, true) => VisibilityEffect.unmuted,
(true, false) => VisibilityEffect.muted,
_ => VisibilityEffect.none,
(false, true) => UserTopicVisibilityEffect.unmuted,
(true, false) => UserTopicVisibilityEffect.muted,
_ => UserTopicVisibilityEffect.none,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awkwardly verbose, but we're about to add another kind of
visibility effect, and I think the code will end up clearer if we
make a separate enum for it.

Yeah, agreed.

Some of the verbosity (like in these lines) will at least get resolved by the upcoming Dart feature of "dot shorthands", expected later this year:
https://github.com/dart-lang/language/blob/main/working/3616%20-%20enum%20value%20shorthand/proposal-simple-lrhn.md

I believe with that feature we'll be able to say just .unmuted, .muted, .none here, without the name of the enum type.

Comment on lines 509 to 510
!store.shouldMuteDmConversation(DmNarrow(
allRecipientIds: allRecipientIds, selfUserId: store.selfUserId)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make another DmNarrow constructor for this:

Suggested change
!store.shouldMuteDmConversation(DmNarrow(
allRecipientIds: allRecipientIds, selfUserId: store.selfUserId)),
!store.shouldMuteDmConversation(DmNarrow.ofConversation(
message.conversation, selfUserId: store.selfUserId)),

Compare the comment at the top of that class:

// Zulip has many ways of representing a DM conversation; for example code
// handling many of them, see zulip-mobile:src/utils/recipient.js .
// Please add more constructors and getters here to handle any of those
// as we turn out to need them.
class DmNarrow extends Narrow implements SendableNarrow {

It'd be bad if this logic did something inefficient like copy the list of recipient IDs, because we're doing this for potentially a large fraction of the messages in this feed (if a user uses lots of DMs). I believe this in fact doesn't make such a copy — and a constructor on DmNarrow is a good place to centralize coming to that conclusion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh…it looks like DmNarrow.ofMessage, though, does copy the list of recipient IDs:

  factory DmNarrow.ofMessage(MessageBase<DmConversation> message, {
    required int selfUserId,
  }) {
    return DmNarrow(
      allRecipientIds: List.unmodifiable(message.conversation.allRecipientIds),
      selfUserId: selfUserId,
    );
  }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm indeed.

It looks like we don't currently call that one in any place that's as performance-sensitive as this. But it's a bit of a pitfall lying around.

Comment on lines 537 to 665
switch (narrow) {
case CombinedFeedNarrow():
case ChannelNarrow():
case MentionsNarrow():
case StarredMessagesNarrow():
return false;

case TopicNarrow():
case DmNarrow():
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's keep these cases in the same order as in _messageVisible, for ease of comparing the logic. It's important that the two align (that's this method's job); and it's potentially a bit subtle to confirm that, so it's good to make it as easy as possible.

It's fine for this to have two separate groups of cases that return the same thing.

Comment on lines +571 to 696
MutedUsersVisibilityEffect _mutedUsersEventCanAffectVisibility(MutedUsersEvent event) {
switch(narrow) {
case CombinedFeedNarrow():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similarly, put the cases in the same order as in _messageVisible

Comment on lines +161 to +164
final union = setUnion(sortedOld, sortedNew);

final willMuteSome = sortedOld.length < union.length;
final willUnmuteSome = sortedNew.length < union.length;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat, yeah, this logic works.

chrisbobbe added a commit to chrisbobbe/zulip-flutter that referenced this pull request Jun 13, 2025
This is awkwardly verbose, but we're about to add another kind of
visibility effect, and I think the code will end up clearer if we
make a separate enum for it.

Greg points out that an upcoming Dart feature "dot shorthands"
should help with this verbosity:
  zulip#1561 (comment)
@chrisbobbe chrisbobbe force-pushed the pr-chris-muted-users-2 branch from 0acc63b to ceb4e0f Compare June 13, 2025 02:15
@chrisbobbe
Copy link
Collaborator Author

Thanks! Revision pushed.

@gnprice
Copy link
Member

gnprice commented Jun 13, 2025

Thanks! Those changes look good.

There's a CI failure in build_runner.

(And there are parts of the branch I still need to read, per #1561 (review) .)

@chrisbobbe chrisbobbe force-pushed the pr-chris-muted-users-2 branch from ceb4e0f to f3f4df2 Compare June 13, 2025 02:51
chrisbobbe added a commit to chrisbobbe/zulip-flutter that referenced this pull request Jun 13, 2025
This is awkwardly verbose, but we're about to add another kind of
visibility effect, and I think the code will end up clearer if we
make a separate enum for it.

Greg points out that an upcoming Dart feature "dot shorthands"
should help with this verbosity:
  zulip#1561 (comment)
@chrisbobbe
Copy link
Collaborator Author

chrisbobbe commented Jun 13, 2025

I just rebased atop current main (after the dependency-upgrades PR), in case that fixes CI. 🤔

chrisbobbe and others added 16 commits June 12, 2025 23:25
Like userDisplayName does.

And remove a null-check `store.getUser(userId)!` at one of the
callers... I think that's *probably* NFC, for the reason given in a
comment ("must exist because UserMentionAutocompleteResult"). But
it's possible this is actually a small bugfix involving a rare race
involving our batch-processing of autocomplete results.

Related: zulip#716
We've now centralized on store.userDisplayName and
store.senderDisplayName for all the code that's responsible for
showing a user's name on the screen, except for a few places we use
`User.fullName` for (a) the self-user and (b) to create an @-mention
for the compose box. The "(unknown user)" and upcoming "Muted user"
placeholders aren't needed for (a) or (b).
(Done by adding an is-muted condition in store.userDisplayName and
store.senderDisplayName, with an opt-out param.)

If Chris is muted, we'll now show "Muted user" where before we would
show "Chris Bobbe", in the following places:

- Message-list page:
  - DM-narrow app bar.
  - DM recipient headers.
  - The sender row on messages. This and message content will get
    more treatment in a separate commit.
  - Emoji-reaction chips on messages.
  - Typing indicators ("Muted user is typing…"), but we'll be
    excluding muted users, coming up in a separate commit.
  - Voter names in poll messages.
- DM items in the Inbox page. (Messages from muted users are
  automatically marked as read, but they can end up in the inbox if
  you un-mark them as read.)
- The new-DM sheet, but we'll be excluding muted users, coming up in
  a separate commit.
- @-mention autocomplete, but we'll be excluding muted users, coming
  up in a separate commit.
- Items in the Direct messages ("recent DMs") page. We'll be
  excluding DMs where everyone is muted, coming up in a separate
  commit.
- User items in custom profile fields.

We *don't* do this replacement in the following places, i.e., we'll
still show "Chris Bobbe" if Chris is muted:

- Sender name in the header of the lightbox page. (This follows
  web.)
- The "hint text" for the compose box in a DM narrow: it will still
  say "Message @chris Bobbe", not "Message @muted user". (This
  follows web.)
- The user's name at the top of the Profile page.
- We won't generate malformed @-mention syntax like
  @_**Muted user|13313**.

Co-authored-by: Sayed Mahmood Sayedi <[email protected]>
We're free to rename these because they don't correspond to named
variables in the Figma.

These more general names will be used for an avatar placeholder for
muted users, coming up.

Co-authored-by: Sayed Mahmood Sayedi <[email protected]>
…able

(Done by adding an is-muted condition in Avatar and AvatarImage,
with an opt-out param. Similar to how we handled users' names in a
recent commit.)

If a user is muted, we'll now show a placeholder where before we
would have shown their real avatar, in the following places:

- The sender row on messages in the message list. This and message
  content will get more treatment in a separate commit.
- @-mention autocomplete, but we'll be excluding muted users, coming
  up in a separate commit.
- User items in custom profile fields.
- 1:1 DM items in the Direct messages ("recent DMs") page. But we'll be
  excluding those items there, coming up in a separate commit.

We *don't* do this replacement in the following places, i.e., we'll
still show the real avatar:

- The header of the lightbox page. (This follows web.)
- The big avatar at the top of the profile page.

Co-authored-by: Sayed Mahmood Sayedi <[email protected]>
…erRow

No-op because the child Flexible -> GestureDetector -> Row has the
default MainAxisSize.max, filling the available space, leaving none
that would be controlled by spaceBetween.
For muted-users, coming up.

This was ad hoc for mobile, for the "Reveal message" button on a
message from a muted sender:
  https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=6092-50786&m=dev
For muted-users, coming up.

This is consistent with the ad hoc design for muted-users, but also
consistent with the component in "Zulip Web UI Kit". (Modulo the
TODO for changing icon-to-label gap from 8px to 6px; that's tricky
with the Material widget we're working with.)
This is awkwardly verbose, but we're about to add another kind of
visibility effect, and I think the code will end up clearer if we
make a separate enum for it.

Greg points out that an upcoming Dart feature "dot shorthands"
should help with this verbosity:
  zulip#1561 (comment)
…muted

In the future, this should apply to the ReactionsNarrow from the Web
app too, once we have it.

Co-authored-by: Sayed Mahmood Sayedi <[email protected]>
chrisbobbe and others added 4 commits June 12, 2025 23:26
Just to skip the bit of extra work of creating new lists.
This completes the planned work for muting muted users (hooray!).

Fixes: zulip#296
@gnprice gnprice force-pushed the pr-chris-muted-users-2 branch from f3f4df2 to 5438a65 Compare June 13, 2025 06:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integration review Added by maintainers when PR may be ready for integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Mute muted users
3 participants