Skip to content

Muted users prep #1530

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 4 commits into
base: main
Choose a base branch
from
Open

Conversation

sm-sayedi
Copy link
Collaborator

The first four prep commits of #1429 (decided in 1429 comment), towards #296.

@sm-sayedi sm-sayedi requested a review from gnprice May 24, 2025 03:25
@sm-sayedi sm-sayedi added the integration review Added by maintainers when PR may be ready for integration label May 24, 2025
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! Generally this looks good. Comments below.

Comment on lines 111 to 113
}


/// An item in the [InitialSnapshot.mutedUsers] or [MutedUsersEvent].
Copy link
Member

Choose a reason for hiding this comment

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

nit: single blank line

@@ -66,6 +68,24 @@ mixin UserStore on PerAccountStoreBase {
return getUser(message.senderId)?.fullName
?? message.senderFullName;
}

/// All the users muted by [selfUser], sorted by [MutedUserItem.id] ascending.
List<MutedUserItem> get mutedUsers;
Copy link
Member

Choose a reason for hiding this comment

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

Do we ever use the timestamps on these? I think we don't have a need to use them.

The user store can then just have a Set<int> for the muted users by user ID.

Copy link
Member

Choose a reason for hiding this comment

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

In fact I think the Set can remain private on UserStoreImpl, and UserStore itself just offer the bool isUserMuted method. That keeps things a bit more encapsulated.

///
/// By default, looks for the user id in [UserStore.mutedUsers] unless
/// [mutedUsers] is non-null, in which case looks in the latter.
bool isUserMuted(int id, {List<MutedUserItem>? mutedUsers});
Copy link
Member

Choose a reason for hiding this comment

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

What's the use case for having this take a mutedUsers argument? Is it about deciding whether a given event will affect a given user? There might be another way to arrange the API for that which might feel cleaner.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, it's used in MessageListView.handleMutedUsersEvent to remove all the messages of a conversation whose all recipients are just muted by the event. We're removing those messages before the new muted users data is tracked in store, so we can't compare with the store's muted users data.

Comment on lines 107 to 102
final Map<int, User> _users;

@override
final List<MutedUserItem> mutedUsers;

@override
User? getUser(int userId) => _users[userId];
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 group the mutedUsers data structure with the isUserMuted method that operates on it, and _users with getUser and allUsers (the same way as in the interface/mixin definition UserStore)

Comment on lines 119 to 126
bool isUserMuted(int id, {List<MutedUserItem>? mutedUsers}) {
return binarySearchByKey(
mutedUsers == null ? this.mutedUsers : _sortMutedUsers(mutedUsers), id,
(item, id) => item.id.compareTo(id)) >= 0;
}

static List<MutedUserItem> _sortMutedUsers(List<MutedUserItem> mutedUsers) {
return mutedUsers..sort((a, b) => a.id.compareTo(b.id));
Copy link
Member

Choose a reason for hiding this comment

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

This logic should get tests. (Doesn't need very many.)

Copy link
Collaborator Author

@sm-sayedi sm-sayedi Jun 4, 2025

Choose a reason for hiding this comment

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

From the start, I was intimidated by using a sorted list (now Set) for storing the muted users' data. In practice, there will probably be very few muted users to keep track of, and binary-searching an item in a small list will probably not gain much. Last night, Chris and I discussed it and decided to go with an unsorted Set. Looking online, I think for most cases looking up in a Set takes linear time anyway.
If using a sorted Set is better, I will be happy to revert to this version. 🙂

Comment on lines 86 to 87
bool allRecipientsMuted(DmNarrow narrow, {List<MutedUserItem>? mutedUsers}) {
return !narrow.otherRecipientIds.any((id) => !isUserMuted(id, mutedUsers: mutedUsers));
Copy link
Member

Choose a reason for hiding this comment

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

This returns true for the self-1:1 thread. That seems undesired 🙂

(Noticed that when making a draft-release branch with #1429.)

Copy link
Member

Choose a reason for hiding this comment

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

This method could be left out of this PR, and added in a later commit in the same PR where it ends up getting used. That would probably be helpful for choosing a name and docs that match its desired behavior. (Which is probably more like "should mute this DM conversation", i.e. in terms of the desired effect in the UI, given that this wrinkle means it won't match a mathematically clean description like "all recipients are muted".)

@sm-sayedi
Copy link
Collaborator Author

sm-sayedi commented Jun 4, 2025

Thanks @gnprice for the review. New revision pushed, PTAL.

@sm-sayedi sm-sayedi requested a review from gnprice June 4, 2025 02:04
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.

2 participants