diff --git a/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/index.tsx b/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/index.tsx index 8d285fbaa580b..2679152467637 100644 --- a/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/index.tsx +++ b/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/index.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React from 'react'; +import React, {useMemo} from 'react'; import {FormattedMessage} from 'react-intl'; import {useSelector, useDispatch} from 'react-redux'; @@ -34,7 +34,7 @@ import AnnouncementBar from '../default_announcement_bar'; const CloudTrialEndAnnouncementBar: React.FC = () => { const limits = useGetLimits(); const subscription = useGetSubscription(); - const getCategory = makeGetCategory(); + const getCategory = useMemo(makeGetCategory, []); const dispatch = useDispatch(); const preferences = useSelector((state: GlobalState) => getCategory(state, Preferences.CLOUD_TRIAL_END_BANNER), diff --git a/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.tsx b/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.tsx index 6d38b74156b09..3ccad07cbc134 100644 --- a/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.tsx +++ b/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {useEffect} from 'react'; +import {useEffect, useMemo} from 'react'; import {useSelector, useDispatch} from 'react-redux'; import type {PreferenceType} from '@mattermost/types/preferences'; @@ -29,9 +29,9 @@ import type {GlobalState} from 'types/store'; const ShowStartTrialModal = () => { const isUserAdmin = useSelector((state: GlobalState) => isCurrentUserSystemAdmin(state)); const openStartTrialFormModal = useOpenStartTrialFormModal(); + const getCategory = useMemo(makeGetCategory, []); const dispatch = useDispatch(); - const getCategory = makeGetCategory(); const userThreshold = 10; const TRUE = 'true'; diff --git a/webapp/channels/src/components/forward_post_modal/index.tsx b/webapp/channels/src/components/forward_post_modal/index.tsx index 7499c255101d6..6c306a0637303 100644 --- a/webapp/channels/src/components/forward_post_modal/index.tsx +++ b/webapp/channels/src/components/forward_post_modal/index.tsx @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import classNames from 'classnames'; -import React, {useCallback, useRef, useState} from 'react'; +import React, {useCallback, useRef, useState, useMemo} from 'react'; import {FormattedList, FormattedMessage, useIntl} from 'react-intl'; import {useDispatch, useSelector} from 'react-redux'; import type {ValueType} from 'react-select'; @@ -50,7 +50,7 @@ const ForwardPostModal = ({onExited, post}: Props) => { const {formatMessage} = useIntl(); const dispatch = useDispatch(); - const getChannel = makeGetChannel(); + const getChannel = useMemo(makeGetChannel, []); const channel = useSelector((state: GlobalState) => getChannel(state, {id: post.channel_id})); const currentTeam = useSelector(getCurrentTeam); diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index 74fa42eff0ef2..8fb8339b9c184 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React from 'react'; +import React, {useMemo} from 'react'; import {FormattedMessage} from 'react-intl'; import {useDispatch, useSelector} from 'react-redux'; @@ -42,7 +42,7 @@ const OverageUsersBannerNotice = () => { const isGovSku = getIsGovSku(license); const seatsPurchased = parseInt(license.Users, 10); const isCloud = useSelector(isCurrentLicenseCloud); - const getPreferencesCategory = makeGetCategory(); + const getPreferencesCategory = useMemo(makeGetCategory, []); const currentUser = useSelector((state: GlobalState) => getCurrentUser(state)); const overagePreferences = useSelector((state: GlobalState) => getPreferencesCategory(state, Preferences.OVERAGE_USERS_BANNER)); const activeUsers = ((stats || {})[StatTypes.TOTAL_USERS]) as number || 0; diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_link/index.ts b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_link/index.ts index b781ad9bebdd9..e2f070646ed7f 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_link/index.ts +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_link/index.ts @@ -41,7 +41,6 @@ function makeMapStateToProps() { return (state: GlobalState, ownProps: OwnProps) => { const member = getMyChannelMemberships(state)[ownProps.channel.id]; const unreadCount = getUnreadCount(state, ownProps.channel.id); - const firstChannelName = getFirstChannelName(state); const config = getConfig(state); const enableTutorial = config.EnableTutorial === 'true'; const currentUserId = getCurrentUserId(state); @@ -58,7 +57,7 @@ function makeMapStateToProps() { isMuted: isChannelMuted(member), hasUrgent: unreadCount.hasUrgent, isChannelSelected: isChannelSelected(state, ownProps.channel.id), - firstChannelName: showChannelsTutorialStep ? firstChannelName : '', + firstChannelName: showChannelsTutorialStep ? getFirstChannelName(state) : '', showChannelsTutorialStep, rhsState: getRhsState(state), rhsOpen: getIsRhsOpen(state), diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/channels.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/channels.ts index 44f06e31a0437..6f13671d968c1 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/channels.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/channels.ts @@ -684,16 +684,12 @@ export const getTeamsUnreadStatuses: (state: GlobalState) => [Set, M getAllChannels, getMyChannelMemberships, getChannelMessageCounts, - getUsers, - getCurrentUserId, isCollapsedThreadsEnabled, getThreadCounts, ( channels, channelMemberships, channelMessageCounts, - users, - currentUserId, collapsedThreadsEnabled, teamThreadCounts, ) => { diff --git a/webapp/channels/src/selectors/drafts.ts b/webapp/channels/src/selectors/drafts.ts index ebe6e0066b1ec..c67b31c761aad 100644 --- a/webapp/channels/src/selectors/drafts.ts +++ b/webapp/channels/src/selectors/drafts.ts @@ -71,14 +71,14 @@ export function makeGetDraftsByPrefix(prefix: string): DraftSelector { ); } +const getChannelDrafts = makeGetDraftsByPrefix(StoragePrefixes.DRAFT); +const getRHSDrafts = makeGetDraftsByPrefix(StoragePrefixes.COMMENT_DRAFT); + /** * Gets all local drafts in storage. * @param excludeInactive determines if we filter drafts based on active channels. */ export function makeGetDrafts(excludeInactive = true): DraftSelector { - const getChannelDrafts = makeGetDraftsByPrefix(StoragePrefixes.DRAFT); - const getRHSDrafts = makeGetDraftsByPrefix(StoragePrefixes.COMMENT_DRAFT); - return createSelector( 'makeGetDrafts', getChannelDrafts, @@ -93,8 +93,6 @@ export function makeGetDrafts(excludeInactive = true): DraftSelector { } export function makeGetDraftsCount(): DraftCountSelector { - const getChannelDrafts = makeGetDraftsByPrefix(StoragePrefixes.DRAFT); - const getRHSDrafts = makeGetDraftsByPrefix(StoragePrefixes.COMMENT_DRAFT); return createSelector( 'makeGetDraftsCount', getChannelDrafts, diff --git a/webapp/channels/src/selectors/onboarding.ts b/webapp/channels/src/selectors/onboarding.ts index 6ec6afad53da2..c8de38028524b 100644 --- a/webapp/channels/src/selectors/onboarding.ts +++ b/webapp/channels/src/selectors/onboarding.ts @@ -13,9 +13,9 @@ import {RecommendedNextStepsLegacy, Preferences} from 'utils/constants'; import type {GlobalState} from 'types/store'; -const getCategory = makeGetCategory(); +const getABTestCategory = makeGetCategory(); export const getABTestPreferences = (() => { - return (state: GlobalState) => getCategory(state, Preferences.AB_TEST_PREFERENCE_VALUE); + return (state: GlobalState) => getABTestCategory(state, Preferences.AB_TEST_PREFERENCE_VALUE); })(); const getFirstChannelNamePref = createSelector( @@ -91,10 +91,13 @@ const getSteps = createSelector( }, ); +const getNextStepsCategory = makeGetCategory(); +const getOnboardingTaskCategory = makeGetCategory(); + // Loop through all Steps. For each step, check that export const legacyNextStepsNotFinished = createSelector( 'legacyNextStepsNotFinished', - (state: GlobalState) => getCategory(state, Preferences.RECOMMENDED_NEXT_STEPS), + (state: GlobalState) => getNextStepsCategory(state, Preferences.RECOMMENDED_NEXT_STEPS), (state: GlobalState) => getCurrentUser(state), (state: GlobalState) => isFirstAdmin(state), (state: GlobalState) => getSteps(state), @@ -108,7 +111,7 @@ export const legacyNextStepsNotFinished = createSelector( // Loop through all Steps. For each step, check that export const hasLegacyNextStepsPreferences = createSelector( 'hasLegacyNextStepsPreferences', - (state: GlobalState) => getCategory(state, Preferences.RECOMMENDED_NEXT_STEPS), + (state: GlobalState) => getNextStepsCategory(state, Preferences.RECOMMENDED_NEXT_STEPS), (state: GlobalState) => getSteps(state), (stepPreferences, mySteps) => { const checkPref = (step: StepType) => stepPreferences.some((pref) => (pref.name === step.id)); @@ -118,18 +121,17 @@ export const hasLegacyNextStepsPreferences = createSelector( export const getShowTaskListBool = createSelector( 'getShowTaskListBool', - (state: GlobalState) => state, - (state: GlobalState) => getCategory(state, OnboardingTaskCategory), - (state: GlobalState) => getCategory(state, Preferences.RECOMMENDED_NEXT_STEPS), + (state: GlobalState) => getOnboardingTaskCategory(state, OnboardingTaskCategory), + (state: GlobalState) => getNextStepsCategory(state, Preferences.RECOMMENDED_NEXT_STEPS), getIsMobileView, - (state, onboardingPreferences, legacyStepsPreferences, isMobileView) => { + (state: GlobalState) => getBool(state, OnboardingTaskCategory, OnboardingTaskList.ONBOARDING_TASK_LIST_SHOW), + (state: GlobalState) => hasLegacyNextStepsPreferences(state), + (onboardingPreferences, legacyStepsPreferences, isMobileView, taskListStatus, hasAnyOfTheLegacyStepsPreferences) => { // conditions to validate scenario where users (initially first_admins) had already set any of the onboarding task list preferences values. // We check wether the preference value exists meaning the onboarding tasks list already started no matter what the state of the process is const hasUserStartedOnboardingTaskListProcess = onboardingPreferences?.some((pref) => pref.name === OnboardingTaskList.ONBOARDING_TASK_LIST_SHOW || pref.name === OnboardingTaskList.ONBOARDING_TASK_LIST_OPEN); - const taskListStatus = getBool(state, OnboardingTaskCategory, OnboardingTaskList.ONBOARDING_TASK_LIST_SHOW); - if (hasUserStartedOnboardingTaskListProcess) { return [(taskListStatus && !isMobileView), false]; } @@ -143,7 +145,6 @@ export const getShowTaskListBool = createSelector( // This condition verifies existing users hasn't finished nor skipped legacy next steps or there are still steps not completed const hasSkipLegacyStepsPreference = legacyStepsPreferences.some((pref) => (pref.name === RecommendedNextStepsLegacy.SKIP)); const hideLegacyStepsSetToFalse = legacyStepsPreferences.some((pref) => (pref.name === RecommendedNextStepsLegacy.HIDE && pref.value === 'false')); - const hasAnyOfTheLegacyStepsPreferences = hasLegacyNextStepsPreferences(state); const areFirstUserPrefs = !hasSkipLegacyStepsPreference && hideLegacyStepsSetToFalse && !hasAnyOfTheLegacyStepsPreferences; const completelyNewUserForOnboarding = !hasUserStartedOnboardingTaskListProcess && areFirstUserPrefs;