diff --git a/src/autocomplete/PeopleAutocomplete.js b/src/autocomplete/PeopleAutocomplete.js index 0e387d54992..3f92013c62c 100644 --- a/src/autocomplete/PeopleAutocomplete.js +++ b/src/autocomplete/PeopleAutocomplete.js @@ -3,9 +3,9 @@ import React, { PureComponent } from 'react'; import { SectionList } from 'react-native'; -import type { User, UserId, UserGroup, Dispatch } from '../types'; +import type { MutedUsersState, User, UserId, UserGroup, Dispatch } from '../types'; import { connect } from '../react-redux'; -import { getSortedUsers, getUserGroups } from '../selectors'; +import { getMutedUsers, getSortedUsers, getUserGroups } from '../selectors'; import { type AutocompleteOption, getAutocompleteSuggestion, @@ -20,6 +20,7 @@ type Props = $ReadOnly<{| dispatch: Dispatch, filter: string, onAutocomplete: (name: string) => void, + mutedUsers: MutedUsersState, ownUserId: UserId, users: User[], userGroups: UserGroup[], @@ -44,9 +45,9 @@ class PeopleAutocomplete extends PureComponent { }; render() { - const { filter, ownUserId, users, userGroups } = this.props; + const { filter, mutedUsers, ownUserId, users, userGroups } = this.props; const filteredUserGroups = getAutocompleteUserGroupSuggestions(userGroups, filter); - const filteredUsers = getAutocompleteSuggestion(users, filter, ownUserId); + const filteredUsers = getAutocompleteSuggestion(users, filter, ownUserId, mutedUsers); if (filteredUserGroups.length + filteredUsers.length === 0) { return null; @@ -105,6 +106,7 @@ class PeopleAutocomplete extends PureComponent { } export default connect(state => ({ + mutedUsers: getMutedUsers(state), ownUserId: getOwnUserId(state), users: getSortedUsers(state), userGroups: getUserGroups(state), diff --git a/src/users/__tests__/userHelpers-test.js b/src/users/__tests__/userHelpers-test.js index c41bd163d43..27440a0fb24 100644 --- a/src/users/__tests__/userHelpers-test.js +++ b/src/users/__tests__/userHelpers-test.js @@ -1,5 +1,6 @@ /* @flow strict-local */ import deepFreeze from 'deep-freeze'; +import Immutable from 'immutable'; import { sortUserList, @@ -61,7 +62,12 @@ describe('getAutocompleteSuggestion', () => { test('empty input results in empty list', () => { const users = deepFreeze([]); - const filteredUsers = getAutocompleteSuggestion(users, 'some filter', eg.selfUser.user_id); + const filteredUsers = getAutocompleteSuggestion( + users, + 'some filter', + eg.selfUser.user_id, + Immutable.Map(), + ); expect(filteredUsers).toBe(users); }); @@ -74,7 +80,20 @@ describe('getAutocompleteSuggestion', () => { { user_id: -1, full_name: 'all', email: '(Notify everyone)' }, someGuyUser, ]; - const filteredUsers = getAutocompleteSuggestion(users, '', meUser.user_id); + const filteredUsers = getAutocompleteSuggestion(users, '', meUser.user_id, Immutable.Map()); + expect(filteredUsers).toEqual(shouldMatch); + }); + + test('filters out muted user', () => { + const mutedUser = eg.makeUser({ name: 'Muted User' }); + const meUser = eg.makeUser({ name: 'Me' }); + const users = deepFreeze([mutedUser, meUser]); + + const mutedUsers = Immutable.Map([[mutedUser.user_id, 0]]); + + const shouldMatch = [{ user_id: -1, full_name: 'all', email: '(Notify everyone)' }]; + + const filteredUsers = getAutocompleteSuggestion(users, '', meUser.user_id, mutedUsers); expect(filteredUsers).toEqual(shouldMatch); }); @@ -87,7 +106,12 @@ describe('getAutocompleteSuggestion', () => { const allUsers = deepFreeze([user1, user2, user3, user4, user5]); const shouldMatch = [user1, user2, user3, user5]; - const filteredUsers = getAutocompleteSuggestion(allUsers, 'match', eg.selfUser.user_id); + const filteredUsers = getAutocompleteSuggestion( + allUsers, + 'match', + eg.selfUser.user_id, + Immutable.Map(), + ); expect(filteredUsers).toEqual(shouldMatch); }); @@ -127,7 +151,12 @@ describe('getAutocompleteSuggestion', () => { user11, // have priority because of 'ma' contains in name user4, // email contains 'ma' ]; - const filteredUsers = getAutocompleteSuggestion(allUsers, 'ma', eg.selfUser.user_id); + const filteredUsers = getAutocompleteSuggestion( + allUsers, + 'ma', + eg.selfUser.user_id, + Immutable.Map(), + ); expect(filteredUsers).toEqual(shouldMatch); }); }); diff --git a/src/users/userHelpers.js b/src/users/userHelpers.js index c1b2d531b8e..98a516c33c9 100644 --- a/src/users/userHelpers.js +++ b/src/users/userHelpers.js @@ -1,7 +1,15 @@ /* @flow strict-local */ import uniqby from 'lodash.uniqby'; -import type { UserPresence, User, UserId, UserGroup, PresenceState, UserOrBot } from '../types'; +import type { + MutedUsersState, + UserPresence, + User, + UserId, + UserGroup, + PresenceState, + UserOrBot, +} from '../types'; import { ensureUnreachable } from '../types'; import { statusFromPresence } from '../utils/presence'; import { makeUserId } from '../api/idTypes'; @@ -121,6 +129,7 @@ export const getAutocompleteSuggestion = ( users: $ReadOnlyArray, filter: string = '', ownUserId: UserId, + mutedUsers: MutedUsersState, ): $ReadOnlyArray => { if (users.length === 0) { return users; @@ -130,7 +139,8 @@ export const getAutocompleteSuggestion = ( const initials = filterUserByInitials(allAutocompleteOptions, filter, ownUserId); const contains = filterUserThatContains(allAutocompleteOptions, filter, ownUserId); const matchesEmail = filterUserMatchesEmail(users, filter, ownUserId); - return getUniqueUsers([...startWith, ...initials, ...contains, ...matchesEmail]); + const candidates = getUniqueUsers([...startWith, ...initials, ...contains, ...matchesEmail]); + return candidates.filter(user => !mutedUsers.has(user.user_id)); }; export const getAutocompleteUserGroupSuggestions = (