From 9052b086a93ba2f51993c1dc64533d7ea5055348 Mon Sep 17 00:00:00 2001 From: Chetanya Kandhari Date: Wed, 26 May 2021 10:11:48 +0530 Subject: [PATCH] Fix custom emojis for statuses not loaded on page refresh (#7638) --- actions/emoji_actions.js | 164 ++++++++++++++++++ actions/emoji_actions.jsx | 74 -------- actions/emoji_actions.mock.test.js | 2 +- actions/emoji_actions.test.js | 2 +- actions/status_actions.jsx | 5 +- actions/status_actions.test.js | 6 + actions/user_actions.jsx | 10 ++ actions/views/channel.js | 6 +- actions/websocket_actions.jsx | 5 + .../custom_status_emoji.test.tsx | 3 - .../custom_status/custom_status_emoji.tsx | 9 +- .../custom_status/custom_status_modal.tsx | 12 +- components/emoji_picker/index.js | 2 +- components/more_direct_channels/index.ts | 7 +- .../more_direct_channels.test.jsx | 22 +-- .../more_direct_channels.tsx | 4 +- components/root/root.jsx | 2 +- 17 files changed, 230 insertions(+), 105 deletions(-) create mode 100644 actions/emoji_actions.js delete mode 100644 actions/emoji_actions.jsx diff --git a/actions/emoji_actions.js b/actions/emoji_actions.js new file mode 100644 index 000000000000..96621689cedd --- /dev/null +++ b/actions/emoji_actions.js @@ -0,0 +1,164 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import * as EmojiActions from 'mattermost-redux/actions/emojis'; +import {getCustomEmojisByName} from 'mattermost-redux/selectors/entities/emojis'; +import {getConfig} from 'mattermost-redux/selectors/entities/general'; + +import {setRecentEmojis} from 'actions/local_storage'; +import {getEmojiMap, getRecentEmojis, isCustomEmojiEnabled} from 'selectors/emojis'; +import {isCustomStatusEnabled, makeGetCustomStatus} from 'selectors/views/custom_status'; + +import {ActionTypes} from 'utils/constants'; +import {EmojiIndicesByAlias} from 'utils/emoji'; + +export function loadRecentlyUsedCustomEmojis() { + return async (dispatch, getState) => { + const state = getState(); + const config = getConfig(state); + + if (config.EnableCustomEmoji !== 'true') { + return {data: true}; + } + + const recentEmojis = getRecentEmojis(state); + const emojiMap = getEmojiMap(state); + const missingEmojis = recentEmojis.filter((name) => !emojiMap.has(name)); + + missingEmojis.forEach((name) => { + dispatch(EmojiActions.getCustomEmojiByName(name)); + }); + + return {data: true}; + }; +} + +export function incrementEmojiPickerPage() { + return async (dispatch) => { + dispatch({ + type: ActionTypes.INCREMENT_EMOJI_PICKER_PAGE, + }); + + return {data: true}; + }; +} + +const MAXIMUM_RECENT_EMOJI = 27; + +export function addRecentEmoji(alias) { + return (dispatch, getState) => { + const state = getState(); + const recentEmojis = getRecentEmojis(state); + const emojiMap = getEmojiMap(state); + + let name; + const emoji = emojiMap.get(alias); + if (!emoji) { + return; + } else if (emoji.name) { + name = emoji.name; + } else { + name = emoji.aliases[0]; + } + + const index = recentEmojis.indexOf(name); + if (index !== -1) { + recentEmojis.splice(index, 1); + } + + recentEmojis.push(name); + + if (recentEmojis.length > MAXIMUM_RECENT_EMOJI) { + recentEmojis.splice(0, recentEmojis.length - MAXIMUM_RECENT_EMOJI); + } + + dispatch(setRecentEmojis(recentEmojis)); + }; +} + +export function loadCustomEmojisForCustomStatusesByUserIds(userIds) { + return (dispatch, getState) => { + const state = getState(); + const customEmojiEnabled = isCustomEmojiEnabled(state); + const customStatusEnabled = isCustomStatusEnabled(state); + if (!customEmojiEnabled || !customStatusEnabled) { + return {data: false}; + } + + const getCustomStatus = makeGetCustomStatus(); + const emojisToLoad = new Set(); + + userIds.forEach((userId) => { + const customStatus = getCustomStatus(state, userId); + if (!customStatus || !customStatus.emoji) { + return; + } + + emojisToLoad.add(customStatus.emoji); + }); + + return dispatch(loadCustomEmojisIfNeeded(Array.from(emojisToLoad))); + }; +} + +export function loadCustomEmojisIfNeeded(emojis) { + return (dispatch, getState) => { + if (!emojis || emojis.length === 0) { + return {data: false}; + } + + const state = getState(); + const customEmojiEnabled = isCustomEmojiEnabled(state); + if (!customEmojiEnabled) { + return {data: false}; + } + + const systemEmojis = EmojiIndicesByAlias; + const customEmojisByName = getCustomEmojisByName(state); + const nonExistentCustomEmoji = state.entities.emojis.nonExistentEmoji; + const emojisToLoad = []; + + emojis.forEach((emoji) => { + if (!emoji) { + return; + } + + if (systemEmojis.has(emoji)) { + // It's a system emoji, no need to fetch + return; + } + + if (nonExistentCustomEmoji.has(emoji)) { + // We've previously confirmed this is not a custom emoji + return; + } + + if (customEmojisByName.has(emoji)) { + // We have the emoji, no need to fetch + return; + } + + emojisToLoad.push(emoji); + }); + + return dispatch(EmojiActions.getCustomEmojisByName(emojisToLoad)); + }; +} + +export function loadCustomStatusEmojisForPostList(posts) { + return (dispatch) => { + if (!posts || posts.length === 0) { + return {data: false}; + } + + const userIds = new Set(); + Object.keys(posts).forEach((postId) => { + const post = posts[postId]; + if (post.user_id) { + userIds.add(post.user_id); + } + }); + return dispatch(loadCustomEmojisForCustomStatusesByUserIds(userIds)); + }; +} + diff --git a/actions/emoji_actions.jsx b/actions/emoji_actions.jsx deleted file mode 100644 index 3a58b2fc2012..000000000000 --- a/actions/emoji_actions.jsx +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import * as EmojiActions from 'mattermost-redux/actions/emojis'; -import {getConfig} from 'mattermost-redux/selectors/entities/general'; - -import {setRecentEmojis} from 'actions/local_storage'; -import {getEmojiMap, getRecentEmojis} from 'selectors/emojis'; - -import {ActionTypes} from 'utils/constants'; - -export function loadRecentlyUsedCustomEmojis() { - return async (dispatch, getState) => { - const state = getState(); - const config = getConfig(state); - - if (config.EnableCustomEmoji !== 'true') { - return {data: true}; - } - - const recentEmojis = getRecentEmojis(state); - const emojiMap = getEmojiMap(state); - const missingEmojis = recentEmojis.filter((name) => !emojiMap.has(name)); - - missingEmojis.forEach((name) => { - dispatch(EmojiActions.getCustomEmojiByName(name)); - }); - - return {data: true}; - }; -} - -export function incrementEmojiPickerPage() { - return async (dispatch) => { - dispatch({ - type: ActionTypes.INCREMENT_EMOJI_PICKER_PAGE, - }); - - return {data: true}; - }; -} - -const MAXIMUM_RECENT_EMOJI = 27; - -export function addRecentEmoji(alias) { - return (dispatch, getState) => { - const state = getState(); - const recentEmojis = getRecentEmojis(state); - const emojiMap = getEmojiMap(state); - - let name; - const emoji = emojiMap.get(alias); - if (!emoji) { - return; - } else if (emoji.name) { - name = emoji.name; - } else { - name = emoji.aliases[0]; - } - - const index = recentEmojis.indexOf(name); - if (index !== -1) { - recentEmojis.splice(index, 1); - } - - recentEmojis.push(name); - - if (recentEmojis.length > MAXIMUM_RECENT_EMOJI) { - recentEmojis.splice(0, recentEmojis.length - MAXIMUM_RECENT_EMOJI); - } - - dispatch(setRecentEmojis(recentEmojis)); - }; -} diff --git a/actions/emoji_actions.mock.test.js b/actions/emoji_actions.mock.test.js index 9041cf3facba..5ba2ca749b8d 100644 --- a/actions/emoji_actions.mock.test.js +++ b/actions/emoji_actions.mock.test.js @@ -4,7 +4,7 @@ import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; -import * as Actions from 'actions/emoji_actions.jsx'; +import * as Actions from 'actions/emoji_actions'; import {getEmojiMap, getRecentEmojis} from 'selectors/emojis'; const mockStore = configureStore([thunk]); diff --git a/actions/emoji_actions.test.js b/actions/emoji_actions.test.js index ea5bec7bfa5c..83489c2d2fd6 100644 --- a/actions/emoji_actions.test.js +++ b/actions/emoji_actions.test.js @@ -4,7 +4,7 @@ import assert from 'assert'; import {getRecentEmojis} from 'selectors/emojis'; -import * as Actions from 'actions/emoji_actions.jsx'; +import * as Actions from 'actions/emoji_actions'; import configureStore from 'store'; describe('Actions.Emojis', () => { diff --git a/actions/status_actions.jsx b/actions/status_actions.jsx index 5c58b02d9f0d..c75d9ac6bf16 100644 --- a/actions/status_actions.jsx +++ b/actions/status_actions.jsx @@ -7,6 +7,7 @@ import {getPostsInCurrentChannel} from 'mattermost-redux/selectors/entities/post import {getDirectShowPreferences} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; +import {loadCustomEmojisForCustomStatusesByUserIds} from 'actions/emoji_actions'; import store from 'stores/redux_store.jsx'; import {Constants} from 'utils/constants'; @@ -79,10 +80,12 @@ export function loadStatusesForProfilesMap(users) { export function loadStatusesByIds(userIds) { return (dispatch) => { if (userIds.length === 0) { - return; + return {data: false}; } dispatch(getStatusesByIds(userIds)); + dispatch(loadCustomEmojisForCustomStatusesByUserIds(userIds)); + return {data: true}; }; } diff --git a/actions/status_actions.test.js b/actions/status_actions.test.js index 1c2fd04ff701..f6effc0f6eef 100644 --- a/actions/status_actions.test.js +++ b/actions/status_actions.test.js @@ -32,6 +32,12 @@ describe('actions/status_actions', () => { myMembers: {channel_id1: {channel_id: 'channel_id1', user_id: 'current_user_id'}}, channelsInTeam: {team_id1: ['channel_id1']}, }, + general: { + config: { + EnableCustomEmoji: 'true', + EnableCustomUserStatuses: 'true', + }, + }, teams: { currentTeamId: 'team_id1', teams: { diff --git a/actions/user_actions.jsx b/actions/user_actions.jsx index 03f9fb5ef7ee..6bea00011b8c 100644 --- a/actions/user_actions.jsx +++ b/actions/user_actions.jsx @@ -23,6 +23,7 @@ import * as Selectors from 'mattermost-redux/selectors/entities/users'; import {legacyMakeFilterAutoclosedDMs, makeFilterManuallyClosedDMs} from 'mattermost-redux/selectors/entities/channel_categories'; import {CategoryTypes} from 'mattermost-redux/constants/channel_categories'; +import {loadCustomEmojisForCustomStatusesByUserIds} from 'actions/emoji_actions'; import {loadStatusesForProfilesList, loadStatusesForProfilesMap} from 'actions/status_actions.jsx'; import {trackEvent} from 'actions/telemetry_actions.jsx'; @@ -328,8 +329,12 @@ export async function loadProfilesForGM() { const userIdsInChannels = Selectors.getUserIdsInChannels(state); const currentUserId = Selectors.getCurrentUserId(state); + const userIdsForLoadingCustomEmojis = new Set(); for (const channel of getGMsForLoading(state)) { const userIds = userIdsInChannels[channel.id] || new Set(); + + userIds.forEach((userId) => userIdsForLoadingCustomEmojis.add(userId)); + if (userIds.size >= Constants.MIN_USERS_IN_GM) { continue; } @@ -355,6 +360,10 @@ export async function loadProfilesForGM() { } await queue.onEmpty(); + + if (userIdsForLoadingCustomEmojis.size > 0) { + dispatch(loadCustomEmojisForCustomStatusesByUserIds(userIdsForLoadingCustomEmojis)); + } if (newPreferences.length > 0) { dispatch(savePreferences(currentUserId, newPreferences)); } @@ -404,6 +413,7 @@ export async function loadProfilesForDM() { if (profilesToLoad.length > 0) { await UserActions.getProfilesByIds(profilesToLoad)(dispatch, getState); } + await loadCustomEmojisForCustomStatusesByUserIds(profileIds)(dispatch, getState); } export function autocompleteUsersInTeam(username) { diff --git a/actions/views/channel.js b/actions/views/channel.js index 6f94b086ddec..27fc8aaf886e 100644 --- a/actions/views/channel.js +++ b/actions/views/channel.js @@ -35,6 +35,7 @@ import {getChannelByName} from 'mattermost-redux/utils/channel_utils'; import EventEmitter from 'mattermost-redux/utils/event_emitter'; import {openDirectChannelToUserId} from 'actions/channel_actions.jsx'; +import {loadCustomStatusEmojisForPostList} from 'actions/emoji_actions'; import {getLastViewedChannelName} from 'selectors/local_storage'; import {getLastPostsApiTimeForChannel} from 'selectors/views/channel'; import {getSocketStatus} from 'selectors/views/websocket'; @@ -230,8 +231,9 @@ export function loadUnreads(channelId, prefetch = false) { atOldestmessage: false, }; } - const actions = []; + dispatch(loadCustomStatusEmojisForPostList(data.posts)); + const actions = []; actions.push({ type: ActionTypes.INCREASE_POST_VISIBILITY, data: channelId, @@ -345,6 +347,8 @@ export function loadPosts({channelId, postId, type}) { moreToLoad: true, }; } + + dispatch(loadCustomStatusEmojisForPostList(data.posts)); actions.push({ type: ActionTypes.INCREASE_POST_VISIBILITY, data: channelId, diff --git a/actions/websocket_actions.jsx b/actions/websocket_actions.jsx index 6ae8f60c98bb..6331fe91bfa8 100644 --- a/actions/websocket_actions.jsx +++ b/actions/websocket_actions.jsx @@ -82,6 +82,7 @@ import {syncPostsInChannel} from 'actions/views/channel'; import {browserHistory} from 'utils/browser_history'; import {loadChannelsForCurrentUser} from 'actions/channel_actions.jsx'; +import {loadCustomEmojisIfNeeded} from 'actions/emoji_actions'; import {redirectUserToDefaultTeam} from 'actions/global_actions'; import {handleNewPost} from 'actions/post_actions.jsx'; import * as StatusActions from 'actions/status_actions.jsx'; @@ -975,6 +976,10 @@ export async function handleUserUpdatedEvent(msg) { const state = getState(); const currentUser = getCurrentUser(state); const user = msg.data.user; + if (user && user.props) { + const customStatus = user.props.customStatus ? JSON.parse(user.props.customStatus) : undefined; + dispatch(loadCustomEmojisIfNeeded([customStatus?.emoji])); + } const config = getConfig(state); const license = getLicense(state); diff --git a/components/custom_status/custom_status_emoji.test.tsx b/components/custom_status/custom_status_emoji.test.tsx index 2e54eeedd8d8..9912b5e77029 100644 --- a/components/custom_status/custom_status_emoji.test.tsx +++ b/components/custom_status/custom_status_emoji.test.tsx @@ -7,12 +7,10 @@ import configureStore from 'redux-mock-store'; import {Provider} from 'react-redux'; import * as CustomStatusSelectors from 'selectors/views/custom_status'; -import * as EmojiSelectors from 'selectors/emojis'; import CustomStatusEmoji from './custom_status_emoji'; jest.mock('selectors/views/custom_status'); -jest.mock('selectors/emojis'); describe('components/custom_status/custom_status_emoji', () => { const mockStore = configureStore(); @@ -22,7 +20,6 @@ describe('components/custom_status/custom_status_emoji', () => { return null; }; (CustomStatusSelectors.makeGetCustomStatus as jest.Mock).mockReturnValue(getCustomStatus); - (EmojiSelectors.isCustomEmojiEnabled as jest.Mock).mockReturnValue(false); it('should match snapshot', () => { const wrapper = mount(, {wrappingComponent: Provider, wrappingComponentProps: {store}}); expect(wrapper).toMatchSnapshot(); diff --git a/components/custom_status/custom_status_emoji.tsx b/components/custom_status/custom_status_emoji.tsx index bf52ec9a1139..78c777f4fd06 100644 --- a/components/custom_status/custom_status_emoji.tsx +++ b/components/custom_status/custom_status_emoji.tsx @@ -23,11 +23,12 @@ interface ComponentProps { const CustomStatusEmoji = (props: ComponentProps) => { const getCustomStatus = makeGetCustomStatus(); const {emojiSize, emojiStyle, spanStyle, showTooltip, tooltipDirection, userID, onClick} = props; + const customStatusEnabled = useSelector(isCustomStatusEnabled); - const customStatus = useSelector((state: GlobalState) => { - return getCustomStatus(state, userID); - }); - if (!(customStatusEnabled && customStatus && customStatus.emoji)) { + const customStatus = useSelector((state: GlobalState) => getCustomStatus(state, userID)); + const isCustomStatusSet = Boolean(customStatusEnabled && customStatus && customStatus.emoji); + + if (!isCustomStatusSet) { return null; } diff --git a/components/custom_status/custom_status_modal.tsx b/components/custom_status/custom_status_modal.tsx index 868e60f1f2ba..eb35af8ec5ea 100644 --- a/components/custom_status/custom_status_modal.tsx +++ b/components/custom_status/custom_status_modal.tsx @@ -11,6 +11,7 @@ import {Preferences} from 'mattermost-redux/constants'; import {UserCustomStatus} from 'mattermost-redux/types/users'; import {Emoji} from 'mattermost-redux/types/emojis'; +import {loadCustomEmojisIfNeeded} from 'actions/emoji_actions'; import GenericModal from 'components/generic_modal'; import EmojiIcon from 'components/widgets/icons/emoji_icon'; import EmojiPickerOverlay from 'components/emoji_picker/emoji_picker_overlay.jsx'; @@ -66,7 +67,16 @@ const CustomStatusModal: React.FC = (props: Props) => { } }; - useEffect(handleCustomStatusInitializationState, []); + const loadCustomEmojisForRecentStatuses = () => { + const emojisToLoad = new Set(); + recentCustomStatuses.forEach((customStatus: UserCustomStatus) => emojisToLoad.add(customStatus.emoji)); + dispatch(loadCustomEmojisIfNeeded(Array.from(emojisToLoad))); + }; + + useEffect(() => { + handleCustomStatusInitializationState(); + loadCustomEmojisForRecentStatuses(); + }, []); const handleSetStatus = () => { const customStatus = { diff --git a/components/emoji_picker/index.js b/components/emoji_picker/index.js index 098fb0ffa223..886fcc80345c 100644 --- a/components/emoji_picker/index.js +++ b/components/emoji_picker/index.js @@ -6,7 +6,7 @@ import {bindActionCreators} from 'redux'; import {getCustomEmojis, searchCustomEmojis} from 'mattermost-redux/actions/emojis'; -import {incrementEmojiPickerPage} from 'actions/emoji_actions.jsx'; +import {incrementEmojiPickerPage} from 'actions/emoji_actions'; import {getEmojiMap, getRecentEmojis} from 'selectors/emojis'; import EmojiPicker from './emoji_picker.jsx'; diff --git a/components/more_direct_channels/index.ts b/components/more_direct_channels/index.ts index 5731975a289a..c1e40e0bc523 100644 --- a/components/more_direct_channels/index.ts +++ b/components/more_direct_channels/index.ts @@ -10,7 +10,6 @@ import {intersectionBy} from 'lodash'; import { getProfiles, getProfilesInTeam, - getStatusesByIds, getTotalUsersStats, searchProfiles, } from 'mattermost-redux/actions/users'; @@ -38,7 +37,7 @@ import {memoizeResult} from 'mattermost-redux/utils/helpers'; import {Constants} from 'utils/constants'; import {openDirectChannelToUserId, openGroupChannelToUserIds} from 'actions/channel_actions'; -import {loadStatusesForProfilesList} from 'actions/status_actions.jsx'; +import {loadStatusesForProfilesList, loadStatusesByIds} from 'actions/status_actions.jsx'; import {loadProfilesForGroupChannels} from 'actions/user_actions.jsx'; import {setModalSearchTerm} from 'actions/views/search'; @@ -137,7 +136,7 @@ const filterDirectChannels = memoizeResult((channels: Record, u type Actions = { getProfiles: (page?: number | undefined, perPage?: number | undefined, options?: any) => Promise; getProfilesInTeam: (teamId: string, page: number, perPage?: number | undefined, sort?: string | undefined, options?: any) => Promise; - getStatusesByIds: (userIds: string[]) => ActionFunc; + loadStatusesByIds: (userIds: string[]) => ActionFunc; getTotalUsersStats: () => ActionFunc; loadStatusesForProfilesList: (users: any) => { data: boolean; @@ -155,7 +154,7 @@ function mapDispatchToProps(dispatch: Dispatch) { actions: bindActionCreators, Actions>({ getProfiles, getProfilesInTeam, - getStatusesByIds, + loadStatusesByIds, getTotalUsersStats, loadStatusesForProfilesList, loadProfilesForGroupChannels, diff --git a/components/more_direct_channels/more_direct_channels.test.jsx b/components/more_direct_channels/more_direct_channels.test.jsx index 847c9895b032..277d30731b96 100644 --- a/components/more_direct_channels/more_direct_channels.test.jsx +++ b/components/more_direct_channels/more_direct_channels.test.jsx @@ -62,7 +62,7 @@ describe('components/MoreDirectChannels', () => { }); }), getProfilesInTeam: emptyFunction, - getStatusesByIds: emptyFunction, + loadStatusesByIds: emptyFunction, searchProfiles: emptyFunction, searchGroupChannels: emptyFunction, setModalSearchTerm: emptyFunction, @@ -79,13 +79,13 @@ describe('components/MoreDirectChannels', () => { }; test('should match snapshot', () => { - const props = {...baseProps, actions: {...baseProps.actions, getStatusesByIds: jest.fn()}}; + const props = {...baseProps, actions: {...baseProps.actions, loadStatusesByIds: jest.fn()}}; const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); test('should call for modal data on callback of modal onEntered', () => { - const props = {...baseProps, actions: {...baseProps.actions, getStatusesByIds: jest.fn()}}; + const props = {...baseProps, actions: {...baseProps.actions, loadStatusesByIds: jest.fn()}}; const wrapper = shallow(); wrapper.find(Modal).prop('onEntered')(); @@ -93,26 +93,26 @@ describe('components/MoreDirectChannels', () => { expect(props.actions.getProfiles).toHaveBeenCalledTimes(1); expect(props.actions.getTotalUsersStats).toHaveBeenCalledTimes(1); expect(props.actions.getProfiles).toBeCalledWith(0, 100); - expect(props.actions.getStatusesByIds).toHaveBeenCalledTimes(1); - expect(props.actions.getStatusesByIds).toBeCalledWith(['user_id_3']); + expect(props.actions.loadStatusesByIds).toHaveBeenCalledTimes(1); + expect(props.actions.loadStatusesByIds).toBeCalledWith(['user_id_3']); // on componentWillReceiveProps wrapper.setProps({statuses: {user_id_1: 'online', user_id_2: 'away', user_id_3: 'offline'}}); - expect(props.actions.getStatusesByIds).toHaveBeenCalledTimes(1); + expect(props.actions.loadStatusesByIds).toHaveBeenCalledTimes(1); }); - test('should call actions.getStatusesByIds on loadProfilesMissingStatus', () => { - const props = {...baseProps, actions: {...baseProps.actions, getStatusesByIds: jest.fn()}}; + test('should call actions.loadStatusesByIds on loadProfilesMissingStatus', () => { + const props = {...baseProps, actions: {...baseProps.actions, loadStatusesByIds: jest.fn()}}; const wrapper = shallow(); wrapper.find(Modal).prop('onEntered')(); wrapper.instance().loadProfilesMissingStatus(props.users, props.statuses); - expect(props.actions.getStatusesByIds).toHaveBeenCalledTimes(2); - expect(props.actions.getStatusesByIds).toBeCalledWith(['user_id_3']); + expect(props.actions.loadStatusesByIds).toHaveBeenCalledTimes(2); + expect(props.actions.loadStatusesByIds).toBeCalledWith(['user_id_3']); props.statuses = {user_id_1: 'online', user_id_2: 'away', user_id_3: 'offline'}; wrapper.instance().loadProfilesMissingStatus(props.users, props.statuses); - expect(props.actions.getStatusesByIds).toHaveBeenCalledTimes(2); + expect(props.actions.loadStatusesByIds).toHaveBeenCalledTimes(2); }); test('should call actions.setModalSearchTerm and match state on handleHide', () => { diff --git a/components/more_direct_channels/more_direct_channels.tsx b/components/more_direct_channels/more_direct_channels.tsx index 002f205a7d90..5291878a076f 100644 --- a/components/more_direct_channels/more_direct_channels.tsx +++ b/components/more_direct_channels/more_direct_channels.tsx @@ -89,7 +89,7 @@ type Props = { actions: { getProfiles: (page?: number | undefined, perPage?: number | undefined, options?: any) => Promise; getProfilesInTeam: (teamId: string, page: number, perPage?: number | undefined, sort?: string | undefined, options?: any) => Promise; - getStatusesByIds: (userIds: string[]) => void; + loadStatusesByIds: (userIds: string[]) => void; getTotalUsersStats: () => void; loadStatusesForProfilesList: (users: any) => { data: boolean; @@ -201,7 +201,7 @@ export default class MoreDirectChannels extends React.PureComponent user.id); if (missingStatusByIds.length > 0) { - this.props.actions.getStatusesByIds(missingStatusByIds); + this.props.actions.loadStatusesByIds(missingStatusByIds); } } diff --git a/components/root/root.jsx b/components/root/root.jsx index 09f501c937db..eb3828d37167 100644 --- a/components/root/root.jsx +++ b/components/root/root.jsx @@ -18,7 +18,7 @@ import {EmojiIndicesByAlias} from 'utils/emoji.jsx'; import {trackLoadTime} from 'actions/telemetry_actions.jsx'; import * as GlobalActions from 'actions/global_actions'; import BrowserStore from 'stores/browser_store'; -import {loadRecentlyUsedCustomEmojis} from 'actions/emoji_actions.jsx'; +import {loadRecentlyUsedCustomEmojis} from 'actions/emoji_actions'; import {initializePlugins} from 'plugins'; import 'plugins/export.js'; import Pluggable from 'plugins/pluggable';