mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Various improvements to preferences code (#27710)
* Add isPostFlagged selector * Remove unused code for actions_menu preferences * Improve types of Preference and getPreference * MM-58111 Change makeGetCategory to take category name once * Use shouldShowJoinLeaveMessages everywhere * Change makeGetCategory to better memoize its result * Fix test that needs EnableJoinLeaveMessageByDefault to be set * Remove more references to action_menu preferences
This commit is contained in:
parent
28939d84da
commit
6956923b6a
@ -126,18 +126,6 @@ declare namespace Cypress {
|
||||
*/
|
||||
apiSaveCloudTrialBannerPreference(userId: string, name: string, value: string): Chainable<Response>;
|
||||
|
||||
/**
|
||||
* Save actions menu preference.
|
||||
* See https://api.mattermost.com/#tag/preferences/paths/~1users~1{user_id}~1preferences/put
|
||||
* @param {string} userId - User ID
|
||||
* @param {string} value - true (default) or false
|
||||
* @returns {Response} response: Cypress-chainable response which should have successful HTTP status of 200 OK to continue or pass.
|
||||
*
|
||||
* @example
|
||||
* cy.apiSaveActionsMenuPreference('user-id', true);
|
||||
*/
|
||||
apiSaveActionsMenuPreference(userId: string, value: boolean): Chainable<Response>;
|
||||
|
||||
/**
|
||||
* Save show trial modal.
|
||||
* See https://api.mattermost.com/#tag/preferences/paths/~1users~1{user_id}~1preferences/put
|
||||
|
@ -256,17 +256,6 @@ Cypress.Commands.add('apiSaveCloudTrialBannerPreference', (userId, name, value)
|
||||
return cy.apiSaveUserPreference([preference], userId);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('apiSaveActionsMenuPreference', (userId, value = true) => {
|
||||
const preference = {
|
||||
user_id: userId,
|
||||
category: 'actions_menu',
|
||||
name: 'actions_menu_tutorial_state',
|
||||
value: JSON.stringify({actions_menu_modal_viewed: value}),
|
||||
};
|
||||
|
||||
return cy.apiSaveUserPreference([preference], userId);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('apiSaveStartTrialModal', (userId, value = 'true') => {
|
||||
const preference = {
|
||||
user_id: userId,
|
||||
@ -402,12 +391,6 @@ Cypress.Commands.add('apiDisableTutorials', (userId) => {
|
||||
name: userId,
|
||||
value: '999',
|
||||
},
|
||||
{
|
||||
user_id: userId,
|
||||
category: 'actions_menu',
|
||||
name: 'actions_menu_tutorial_state',
|
||||
value: '{"actions_menu_modal_viewed":true}',
|
||||
},
|
||||
{
|
||||
user_id: userId,
|
||||
category: 'drafts',
|
||||
|
@ -234,7 +234,6 @@ Cypress.Commands.add('apiCreateUser', ({
|
||||
prefix = 'user',
|
||||
createAt = 0,
|
||||
bypassTutorial = true,
|
||||
hideActionsMenu = true,
|
||||
hideOnboarding = true,
|
||||
bypassWhatsNewModal = true,
|
||||
user = null,
|
||||
@ -265,10 +264,6 @@ Cypress.Commands.add('apiCreateUser', ({
|
||||
cy.apiDisableTutorials(createdUser.id);
|
||||
}
|
||||
|
||||
if (hideActionsMenu) {
|
||||
cy.apiSaveActionsMenuPreference(createdUser.id, true);
|
||||
}
|
||||
|
||||
if (hideOnboarding) {
|
||||
cy.apiSaveOnboardingPreference(createdUser.id, 'hide', 'true');
|
||||
cy.apiSaveOnboardingPreference(createdUser.id, 'skip', 'true');
|
||||
|
@ -261,7 +261,6 @@ function resetUserPreference(userId) {
|
||||
cy.apiSaveOnboardingTaskListPreference(userId, 'onboarding_task_list_open', 'false');
|
||||
cy.apiSaveOnboardingTaskListPreference(userId, 'onboarding_task_list_show', 'false');
|
||||
cy.apiSaveCloudTrialBannerPreference(userId, 'trial', 'max_days_banner');
|
||||
cy.apiSaveActionsMenuPreference(userId);
|
||||
cy.apiSaveSkipStepsPreference(userId, 'true');
|
||||
cy.apiSaveStartTrialModal(userId, 'true');
|
||||
cy.apiSaveUnreadScrollPositionPreference(userId, 'start_from_left_off');
|
||||
|
@ -81,7 +81,9 @@ describe('channel view actions', () => {
|
||||
},
|
||||
},
|
||||
general: {
|
||||
config: {},
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
serverVersion: '5.12.0',
|
||||
},
|
||||
roles: {
|
||||
@ -589,7 +591,7 @@ describe('channel view actions', () => {
|
||||
|
||||
describe('markChannelAsReadOnFocus', () => {
|
||||
test('should mark channel as read when channel is not manually unread', async () => {
|
||||
test = mockStore(initialState);
|
||||
store = mockStore(initialState);
|
||||
|
||||
await store.dispatch(Actions.markChannelAsReadOnFocus(channel1.id));
|
||||
|
||||
|
@ -43,7 +43,7 @@ const CloudTrialBanner = ({trialEndDate}: Props): JSX.Element | null => {
|
||||
|
||||
// the banner when dismissed, will be dismissed for 10 days
|
||||
const bannerIsStillDismissed = diffDays < 0;
|
||||
shouldShowBanner = storedDismissedEndDate && bannerIsStillDismissed;
|
||||
shouldShowBanner = Boolean(storedDismissedEndDate) && bannerIsStillDismissed;
|
||||
}
|
||||
|
||||
const [showBanner, setShowBanner] = useState<boolean>(shouldShowBanner);
|
||||
|
@ -20,9 +20,9 @@ import type {GlobalState} from 'types/store';
|
||||
|
||||
import CloudTrialAnnouncementBar from './cloud_trial_announcement_bar';
|
||||
|
||||
function mapStateToProps(state: GlobalState) {
|
||||
const getCategory = makeGetCategory();
|
||||
const getCloudTrialBannerPreferences = makeGetCategory('getCloudTrialBannerPreferences', Preferences.CLOUD_TRIAL_BANNER);
|
||||
|
||||
function mapStateToProps(state: GlobalState) {
|
||||
const subscription = state.entities.cloud.subscription;
|
||||
const isCloud = getLicense(state).Cloud === 'true';
|
||||
let isFreeTrial = false;
|
||||
@ -43,7 +43,7 @@ function mapStateToProps(state: GlobalState) {
|
||||
currentUser: getCurrentUser(state),
|
||||
isCloud,
|
||||
subscription,
|
||||
preferences: getCategory(state, Preferences.CLOUD_TRIAL_BANNER),
|
||||
preferences: getCloudTrialBannerPreferences(state),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useMemo} from 'react';
|
||||
import React from 'react';
|
||||
import {FormattedMessage, defineMessages} from 'react-intl';
|
||||
import {useSelector, useDispatch} from 'react-redux';
|
||||
|
||||
@ -30,14 +30,13 @@ import type {GlobalState} from 'types/store';
|
||||
|
||||
import AnnouncementBar from '../default_announcement_bar';
|
||||
|
||||
const getCloudTrialEndBannerPreferences = makeGetCategory('getCloudTrialEndBannerPreferences', Preferences.CLOUD_TRIAL_END_BANNER);
|
||||
|
||||
const CloudTrialEndAnnouncementBar: React.FC = () => {
|
||||
const limits = useGetLimits();
|
||||
const subscription = useGetSubscription();
|
||||
const getCategory = useMemo(makeGetCategory, []);
|
||||
const dispatch = useDispatch();
|
||||
const preferences = useSelector((state: GlobalState) =>
|
||||
getCategory(state, Preferences.CLOUD_TRIAL_END_BANNER),
|
||||
);
|
||||
const preferences = useSelector(getCloudTrialEndBannerPreferences);
|
||||
const currentUser = useSelector((state: GlobalState) =>
|
||||
getCurrentUser(state),
|
||||
);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useMemo} from 'react';
|
||||
import React from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
|
||||
@ -10,7 +10,7 @@ import type {PreferenceType} from '@mattermost/types/preferences';
|
||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||
import {isCurrentLicenseCloud} from 'mattermost-redux/selectors/entities/cloud';
|
||||
import {getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getOverageBannerPreferences} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import AnnouncementBar from 'components/announcement_bar/default_announcement_bar';
|
||||
@ -46,9 +46,8 @@ const OverageUsersBanner = () => {
|
||||
const license = useSelector(getLicense);
|
||||
const seatsPurchased = parseInt(license.Users, 10);
|
||||
const isCloud = useSelector(isCurrentLicenseCloud);
|
||||
const getPreferencesCategory = useMemo(makeGetCategory, []);
|
||||
const currentUser = useSelector((state: GlobalState) => getCurrentUser(state));
|
||||
const overagePreferences = useSelector((state: GlobalState) => getPreferencesCategory(state, Preferences.OVERAGE_USERS_BANNER));
|
||||
const overagePreferences = useSelector(getOverageBannerPreferences);
|
||||
const activeUsers = ((stats || {})[StatTypes.TOTAL_USERS]) as number || 0;
|
||||
const {
|
||||
isBetween5PercerntAnd10PercentPurchasedSeats,
|
||||
|
@ -1,14 +1,12 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useEffect, useMemo} from 'react';
|
||||
import {useEffect} from 'react';
|
||||
import {useSelector, useDispatch} from 'react-redux';
|
||||
|
||||
import type {PreferenceType} from '@mattermost/types/preferences';
|
||||
|
||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getBool} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {trackEvent} from 'actions/telemetry_actions';
|
||||
@ -29,7 +27,6 @@ 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();
|
||||
|
||||
@ -40,7 +37,7 @@ const ShowStartTrialModal = () => {
|
||||
|
||||
const installationDate = useSelector((state: GlobalState) => getConfig(state).InstallationDate);
|
||||
const currentUser = useSelector((state: GlobalState) => getCurrentUser(state));
|
||||
const preferences = useSelector<GlobalState, PreferenceType[]>((state) => getCategory(state, Preferences.START_TRIAL_MODAL));
|
||||
const hadAdminDismissedModal = useSelector((state: GlobalState) => getBool(state, Preferences.START_TRIAL_MODAL, Constants.TRIAL_MODAL_AUTO_SHOWN));
|
||||
|
||||
const prevTrialLicense = useSelector((state: GlobalState) => state.entities.admin.prevTrialLicense);
|
||||
const currentLicense = useSelector(getLicense);
|
||||
@ -77,7 +74,6 @@ const ShowStartTrialModal = () => {
|
||||
const now = new Date().getTime();
|
||||
const hasEnvMoreThan6Hours = now > installationDatePlus6Hours;
|
||||
const hasEnvMoreThan10Users = Number(totalUsers) > userThreshold;
|
||||
const hadAdminDismissedModal = preferences.some((pref: PreferenceType) => pref.name === Constants.TRIAL_MODAL_AUTO_SHOWN && pref.value === TRUE);
|
||||
if (isUserAdmin && !isBenefitsModalOpened && hasEnvMoreThan10Users && hasEnvMoreThan6Hours && !hadAdminDismissedModal && !isLicensedOrPreviousLicensed) {
|
||||
openStartTrialFormModal({trackingLocation: 'show_start_trial_modal'}, handleOnClose);
|
||||
trackEvent(
|
||||
|
@ -8,18 +8,16 @@ import type {PreferenceType} from '@mattermost/types/preferences';
|
||||
|
||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/common';
|
||||
import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {get as getPreference} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import type {ActionResult} from 'mattermost-redux/types/actions';
|
||||
import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
export default function usePreference(category: string, name: string): [string | undefined, (value: string) => Promise<ActionResult>] {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const userId = useSelector(getCurrentUserId);
|
||||
const preferences = useSelector(getMyPreferences);
|
||||
|
||||
const key = getPreferenceKey(category, name);
|
||||
const preference = preferences[key];
|
||||
const preferenceValue = useSelector((state: GlobalState) => getPreference(state, category, name));
|
||||
|
||||
const setPreference = useCallback((value: string) => {
|
||||
const preference: PreferenceType = {
|
||||
@ -31,5 +29,5 @@ export default function usePreference(category: string, name: string): [string |
|
||||
return dispatch(savePreferences(userId, [preference]));
|
||||
}, [category, name, userId]);
|
||||
|
||||
return useMemo(() => ([preference?.value, setPreference]), [preference?.value, setPreference]);
|
||||
return useMemo(() => ([preferenceValue, setPreference]), [preferenceValue, setPreference]);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useMemo} from 'react';
|
||||
import React from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
|
||||
@ -10,7 +10,7 @@ import type {PreferenceType} from '@mattermost/types/preferences';
|
||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||
import {isCurrentLicenseCloud} from 'mattermost-redux/selectors/entities/cloud';
|
||||
import {getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getOverageBannerPreferences} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import AlertBanner from 'components/alert_banner';
|
||||
@ -42,9 +42,8 @@ const OverageUsersBannerNotice = () => {
|
||||
const isGovSku = getIsGovSku(license);
|
||||
const seatsPurchased = parseInt(license.Users, 10);
|
||||
const isCloud = useSelector(isCurrentLicenseCloud);
|
||||
const getPreferencesCategory = useMemo(makeGetCategory, []);
|
||||
const currentUser = useSelector((state: GlobalState) => getCurrentUser(state));
|
||||
const overagePreferences = useSelector((state: GlobalState) => getPreferencesCategory(state, Preferences.OVERAGE_USERS_BANNER));
|
||||
const overagePreferences = useSelector(getOverageBannerPreferences);
|
||||
const activeUsers = ((stats || {})[StatTypes.TOTAL_USERS]) as number || 0;
|
||||
|
||||
const {
|
||||
|
@ -9,7 +9,6 @@ import {matchPath, useLocation} from 'react-router-dom';
|
||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/common';
|
||||
import {getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {isCurrentUserGuestUser, isCurrentUserSystemAdmin, isFirstAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {trackEvent as trackEventAction} from 'actions/telemetry_actions';
|
||||
@ -22,6 +21,7 @@ import {
|
||||
} from 'actions/views/onboarding_tasks';
|
||||
import {setProductMenuSwitcherOpen} from 'actions/views/product_menu';
|
||||
import {setStatusDropdown} from 'actions/views/status_dropdown';
|
||||
import {getOnboardingTaskPreferences} from 'selectors/onboarding';
|
||||
|
||||
import Channels from 'components/common/svg_images_components/channels_svg';
|
||||
import Gears from 'components/common/svg_images_components/gears_svg';
|
||||
@ -46,8 +46,6 @@ import type {GlobalState} from 'types/store';
|
||||
import {OnboardingTaskCategory, OnboardingTaskList, OnboardingTasksName, TaskNameMapToSteps} from './constants';
|
||||
import {generateTelemetryTag} from './utils';
|
||||
|
||||
const getCategory = makeGetCategory();
|
||||
|
||||
const useGetTaskDetails = () => {
|
||||
const {formatMessage} = useIntl();
|
||||
return {
|
||||
@ -145,7 +143,7 @@ export const useTasksList = () => {
|
||||
};
|
||||
|
||||
export const useTasksListWithStatus = () => {
|
||||
const dataInDb = useSelector((state: GlobalState) => getCategory(state, OnboardingTaskCategory));
|
||||
const dataInDb = useSelector(getOnboardingTaskPreferences);
|
||||
const tasksList = useTasksList();
|
||||
const getTaskDetails = useGetTaskDetails();
|
||||
return useMemo(() =>
|
||||
|
@ -4,16 +4,15 @@
|
||||
import {connect} from 'react-redux';
|
||||
import type {ConnectedProps} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import type {AnyAction, Dispatch} from 'redux';
|
||||
import type {Dispatch} from 'redux';
|
||||
|
||||
import type {Emoji} from '@mattermost/types/emojis';
|
||||
import type {Post} from '@mattermost/types/posts';
|
||||
|
||||
import {setActionsMenuInitialisationState} from 'mattermost-redux/actions/preferences';
|
||||
import {General} from 'mattermost-redux/constants';
|
||||
import {getDirectTeammate} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getPost, makeGetCommentCountForPost, makeIsPostCommentMention, isPostAcknowledgementsEnabled, isPostPriorityEnabled} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {getPost, makeGetCommentCountForPost, makeIsPostCommentMention, isPostAcknowledgementsEnabled, isPostPriorityEnabled, isPostFlagged} from 'mattermost-redux/selectors/entities/posts';
|
||||
import type {UserActivityPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {
|
||||
get,
|
||||
@ -179,7 +178,7 @@ function makeMapStateToProps() {
|
||||
channelIsArchived: isArchivedChannel(channel),
|
||||
isConsecutivePost: isConsecutivePost(state, ownProps),
|
||||
previousPostIsComment,
|
||||
isFlagged: get(state, Preferences.CATEGORY_FLAGGED_POST, post.id, null) !== null,
|
||||
isFlagged: isPostFlagged(state, post.id),
|
||||
compactDisplay: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT,
|
||||
colorizeUsernames: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLORIZE_USERNAMES, Preferences.COLORIZE_USERNAMES_DEFAULT) === 'true',
|
||||
shouldShowActionsMenu: shouldShowActionsMenu(state, post),
|
||||
@ -220,12 +219,11 @@ function makeMapStateToProps() {
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch: Dispatch<AnyAction>) {
|
||||
function mapDispatchToProps(dispatch: Dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
markPostAsUnread,
|
||||
emitShortcutReactToLastPostFrom,
|
||||
setActionsMenuInitialisationState,
|
||||
selectPost,
|
||||
selectPostFromRightHandSideSearch,
|
||||
setRhsExpanded,
|
||||
|
@ -41,7 +41,6 @@ describe('PostComponent', () => {
|
||||
actions: {
|
||||
markPostAsUnread: jest.fn(),
|
||||
emitShortcutReactToLastPostFrom: jest.fn(),
|
||||
setActionsMenuInitialisationState: jest.fn(),
|
||||
selectPost: jest.fn(),
|
||||
selectPostFromRightHandSideSearch: jest.fn(),
|
||||
removePost: jest.fn(),
|
||||
|
@ -91,7 +91,6 @@ export type Props = {
|
||||
actions: {
|
||||
markPostAsUnread: (post: Post, location: string) => void;
|
||||
emitShortcutReactToLastPostFrom: (emittedFrom: 'CENTER' | 'RHS_ROOT' | 'NO_WHERE') => void;
|
||||
setActionsMenuInitialisationState: (viewed: Record<string, boolean>) => void;
|
||||
selectPost: (post: Post) => void;
|
||||
selectPostFromRightHandSideSearch: (post: Post) => void;
|
||||
removePost: (post: Post) => void;
|
||||
|
@ -8,8 +8,7 @@ import type {Dispatch} from 'redux';
|
||||
import type {GlobalState} from '@mattermost/types/store';
|
||||
|
||||
import {getMissingProfilesByIds, getMissingProfilesByUsernames} from 'mattermost-redux/actions/users';
|
||||
import {Preferences} from 'mattermost-redux/constants';
|
||||
import {getBool} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {shouldShowJoinLeaveMessages} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUser, makeGetProfilesByIdsAndUsernames} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import CombinedSystemMessage from './combined_system_message';
|
||||
@ -29,7 +28,7 @@ function makeMapStateToProps() {
|
||||
return {
|
||||
currentUserId: currentUser.id,
|
||||
currentUsername: currentUser.username,
|
||||
showJoinLeave: getBool(state, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE, true),
|
||||
showJoinLeave: shouldShowJoinLeaveMessages(state),
|
||||
userProfiles: getProfilesByIdsAndUsernames(state, {allUserIds, allUsernames}),
|
||||
};
|
||||
};
|
||||
|
@ -25,39 +25,36 @@ import {Preferences} from 'utils/constants';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
function makeMapStateToProps() {
|
||||
const getCategory = makeGetCategory();
|
||||
const getSystemNoticePreferences = makeGetCategory('getSystemNoticePreferences', Preferences.CATEGORY_SYSTEM_NOTICE);
|
||||
const getPreferenceNameMap = createSelector(
|
||||
'getPreferenceNameMap',
|
||||
getSystemNoticePreferences,
|
||||
(preferences) => {
|
||||
const nameMap: {[key: string]: PreferenceType} = {};
|
||||
preferences.forEach((p) => {
|
||||
nameMap[p.name] = p;
|
||||
});
|
||||
return nameMap;
|
||||
},
|
||||
);
|
||||
|
||||
const getPreferenceNameMap = createSelector(
|
||||
'getPreferenceNameMap',
|
||||
getCategory,
|
||||
(preferences) => {
|
||||
const nameMap: {[key: string]: PreferenceType} = {};
|
||||
preferences.forEach((p) => {
|
||||
nameMap[p.name] = p;
|
||||
});
|
||||
return nameMap;
|
||||
},
|
||||
);
|
||||
function mapStateToProps(state: GlobalState) {
|
||||
const license = getLicense(state);
|
||||
const config = getConfig(state);
|
||||
const serverVersion = state.entities.general.serverVersion;
|
||||
const analytics = state.entities.admin.analytics;
|
||||
|
||||
return function mapStateToProps(state: GlobalState) {
|
||||
const license = getLicense(state);
|
||||
const config = getConfig(state);
|
||||
const serverVersion = state.entities.general.serverVersion;
|
||||
const analytics = state.entities.admin.analytics;
|
||||
|
||||
return {
|
||||
currentUserId: state.entities.users.currentUserId,
|
||||
preferences: getPreferenceNameMap(state, Preferences.CATEGORY_SYSTEM_NOTICE),
|
||||
dismissedNotices: state.views.notice.hasBeenDismissed,
|
||||
isSystemAdmin: haveISystemPermission(state, {permission: Permissions.MANAGE_SYSTEM}),
|
||||
notices: Notices,
|
||||
config,
|
||||
license,
|
||||
serverVersion,
|
||||
analytics,
|
||||
currentChannel: getCurrentChannel(state),
|
||||
};
|
||||
return {
|
||||
currentUserId: state.entities.users.currentUserId,
|
||||
preferences: getPreferenceNameMap(state),
|
||||
dismissedNotices: state.views.notice.hasBeenDismissed,
|
||||
isSystemAdmin: haveISystemPermission(state, {permission: Permissions.MANAGE_SYSTEM}),
|
||||
notices: Notices,
|
||||
config,
|
||||
license,
|
||||
serverVersion,
|
||||
analytics,
|
||||
currentChannel: getCurrentChannel(state),
|
||||
};
|
||||
}
|
||||
|
||||
@ -71,4 +68,4 @@ function mapDispatchToProps(dispatch: Dispatch) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(makeMapStateToProps, mapDispatchToProps)(SystemNotice);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SystemNotice);
|
||||
|
@ -4,13 +4,12 @@
|
||||
import React, {memo, useCallback} from 'react';
|
||||
import type {ReactNode} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {useDispatch, useSelector, shallowEqual} from 'react-redux';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
|
||||
import type {UserThread} from '@mattermost/types/threads';
|
||||
|
||||
import {setThreadFollow, updateThreadRead, markLastPostInThreadAsUnread} from 'mattermost-redux/actions/threads';
|
||||
import {Preferences} from 'mattermost-redux/constants';
|
||||
import {get} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {isPostFlagged} from 'mattermost-redux/selectors/entities/posts';
|
||||
|
||||
import {
|
||||
flagPost as savePost,
|
||||
@ -56,7 +55,7 @@ function ThreadMenu({
|
||||
goToInChannel,
|
||||
} = useThreadRouting();
|
||||
|
||||
const isSaved = useSelector((state: GlobalState) => get(state, Preferences.CATEGORY_FLAGGED_POST, threadId, null) != null, shallowEqual);
|
||||
const isSaved = useSelector((state: GlobalState) => isPostFlagged(state, threadId));
|
||||
|
||||
const handleReadUnread = useCallback(() => {
|
||||
const lastViewedAt = hasUnreads ? Date.now() : unreadTimestamp;
|
||||
|
@ -24,8 +24,10 @@ import type {GlobalState} from 'types/store';
|
||||
import AdvancedSettingsDisplay from './user_settings_advanced';
|
||||
import type {OwnProps} from './user_settings_advanced';
|
||||
|
||||
function makeMapStateToProps(state: GlobalState, props: OwnProps) {
|
||||
const getAdvancedSettingsCategory = props.adminMode ? makeGetUserCategory(props.user.id) : makeGetCategory();
|
||||
const getAdvancedSettingsCategory = makeGetCategory('getAdvancedSettingsCategory', Preferences.CATEGORY_ADVANCED_SETTINGS);
|
||||
|
||||
function makeMapStateToProps() {
|
||||
const getUserAdvancedSettingsCategory = makeGetUserCategory('getAdvancedSettingsCategory', Preferences.CATEGORY_ADVANCED_SETTINGS);
|
||||
|
||||
return (state: GlobalState, props: OwnProps) => {
|
||||
const config = getConfig(state);
|
||||
@ -34,9 +36,10 @@ function makeMapStateToProps(state: GlobalState, props: OwnProps) {
|
||||
const enableJoinLeaveMessage = config.EnableJoinLeaveMessageByDefault === 'true';
|
||||
|
||||
const userPreferences = props.adminMode && props.userPreferences ? props.userPreferences : undefined;
|
||||
const advancedSettingsCategory = userPreferences ? getUserAdvancedSettingsCategory(state, props.user.id) : getAdvancedSettingsCategory(state);
|
||||
|
||||
return {
|
||||
advancedSettingsCategory: getAdvancedSettingsCategory(state, Preferences.CATEGORY_ADVANCED_SETTINGS),
|
||||
advancedSettingsCategory,
|
||||
sendOnCtrlEnter: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', 'false', userPreferences),
|
||||
codeBlockOnCtrlEnter: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'code_block_ctrl_enter', 'true', userPreferences),
|
||||
formatting: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', 'true', userPreferences),
|
||||
|
@ -25,7 +25,7 @@ export type OwnProps = {
|
||||
type Props = OwnProps & {
|
||||
active: boolean;
|
||||
areAllSectionsInactive: boolean;
|
||||
joinLeave?: string;
|
||||
joinLeave: string;
|
||||
onUpdateSection: (section?: string) => void;
|
||||
renderOnOffLabel: (label: string) => ReactNode;
|
||||
actions: {
|
||||
@ -34,7 +34,7 @@ type Props = OwnProps & {
|
||||
}
|
||||
|
||||
type State = {
|
||||
joinLeaveState?: string;
|
||||
joinLeaveState: string;
|
||||
isSaving?: boolean;
|
||||
serverError?: string;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
|
||||
user_id: userId,
|
||||
category: Constants.Preferences.CATEGORY_ADVANCED_SETTINGS,
|
||||
name: setting,
|
||||
value: this.state.settings[setting],
|
||||
value: this.state.settings[setting]!,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -6,27 +6,21 @@ import {bindActionCreators} from 'redux';
|
||||
import type {Dispatch} from 'redux';
|
||||
|
||||
import {saveTheme, deleteTeamSpecificThemes} from 'mattermost-redux/actions/preferences';
|
||||
import {getTheme, makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getTheme, getThemePreferences} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentTeamId, getMyTeamsCount} from 'mattermost-redux/selectors/entities/teams';
|
||||
|
||||
import {openModal} from 'actions/views/modals';
|
||||
|
||||
import {Preferences} from 'utils/constants';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
import UserSettingsTheme from './user_settings_theme';
|
||||
|
||||
function makeMapStateToProps() {
|
||||
const getThemeCategory = makeGetCategory();
|
||||
|
||||
return (state: GlobalState) => {
|
||||
return {
|
||||
currentTeamId: getCurrentTeamId(state),
|
||||
theme: getTheme(state),
|
||||
applyToAllTeams: getThemeCategory(state, Preferences.CATEGORY_THEME).length <= 1,
|
||||
showAllTeamsCheckbox: getMyTeamsCount(state) > 1,
|
||||
};
|
||||
function mapStateToProps(state: GlobalState) {
|
||||
return {
|
||||
currentTeamId: getCurrentTeamId(state),
|
||||
theme: getTheme(state),
|
||||
applyToAllTeams: getThemePreferences(state).length <= 1,
|
||||
showAllTeamsCheckbox: getMyTeamsCount(state) > 1,
|
||||
};
|
||||
}
|
||||
|
||||
@ -40,4 +34,4 @@ function mapDispatchToProps(dispatch: Dispatch) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(makeMapStateToProps, mapDispatchToProps)(UserSettingsTheme);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(UserSettingsTheme);
|
||||
|
@ -14,8 +14,8 @@ import {createCustomEmoji} from 'mattermost-redux/actions/emojis';
|
||||
import * as Actions from 'mattermost-redux/actions/posts';
|
||||
import {loadMe} from 'mattermost-redux/actions/users';
|
||||
import {Client4} from 'mattermost-redux/client';
|
||||
import {isPostFlagged} from 'mattermost-redux/selectors/entities/posts';
|
||||
import type {GetStateFunc} from 'mattermost-redux/types/actions';
|
||||
import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils';
|
||||
|
||||
import mockStore from 'tests/test_store';
|
||||
|
||||
@ -1038,10 +1038,8 @@ describe('Actions.Posts', () => {
|
||||
reply(200, OK_RESPONSE);
|
||||
|
||||
dispatch(Actions.flagPost(post1.id));
|
||||
const state = getState();
|
||||
const prefKey = getPreferenceKey(Preferences.CATEGORY_FLAGGED_POST, post1.id);
|
||||
const preference = state.entities.preferences.myPreferences[prefKey];
|
||||
expect(preference).toBeTruthy();
|
||||
|
||||
expect(isPostFlagged(getState(), post1.id)).toBe(true);
|
||||
});
|
||||
|
||||
it('unflagPost', async () => {
|
||||
@ -1069,20 +1067,15 @@ describe('Actions.Posts', () => {
|
||||
put(`/${TestHelper.basicUser!.id}/preferences`).
|
||||
reply(200, OK_RESPONSE);
|
||||
dispatch(Actions.flagPost(post1.id));
|
||||
let state = getState();
|
||||
const prefKey = getPreferenceKey(Preferences.CATEGORY_FLAGGED_POST, post1.id);
|
||||
const preference = state.entities.preferences.myPreferences[prefKey];
|
||||
expect(preference).toBeTruthy();
|
||||
|
||||
expect(isPostFlagged(getState(), post1.id)).toBe(true);
|
||||
|
||||
nock(Client4.getUsersRoute()).
|
||||
delete(`/${TestHelper.basicUser!.id}/preferences`).
|
||||
reply(200, OK_RESPONSE);
|
||||
dispatch(Actions.unflagPost(post1.id));
|
||||
state = getState();
|
||||
const unflagged = state.entities.preferences.myPreferences[prefKey];
|
||||
if (unflagged) {
|
||||
throw new Error('unexpected unflagged');
|
||||
}
|
||||
|
||||
expect(isPostFlagged(getState(), post1.id)).toBe(false);
|
||||
});
|
||||
|
||||
it('setUnreadPost', async () => {
|
||||
|
@ -1234,6 +1234,7 @@ export function unflagPost(postId: string): ActionFuncAsync {
|
||||
user_id: currentUserId,
|
||||
category: Preferences.CATEGORY_FLAGGED_POST,
|
||||
name: postId,
|
||||
value: 'true',
|
||||
};
|
||||
|
||||
Client4.trackEvent('action', 'action_posts_unflag');
|
||||
|
@ -5,7 +5,7 @@ import type {PreferenceType} from '@mattermost/types/preferences';
|
||||
|
||||
import {PreferenceTypes} from 'mattermost-redux/action_types';
|
||||
import {Client4} from 'mattermost-redux/client';
|
||||
import {getMyPreferences as getMyPreferencesSelector, makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getMyPreferences as getMyPreferencesSelector, getThemePreferences} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import type {Theme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
|
||||
@ -56,20 +56,6 @@ export function getUserPreferences(userID: string) {
|
||||
});
|
||||
}
|
||||
|
||||
export function setActionsMenuInitialisationState(initializationState: Record<string, boolean>): ThunkActionFunc<void> {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const currentUserId = getCurrentUserId(state);
|
||||
const preference: PreferenceType = {
|
||||
user_id: currentUserId,
|
||||
category: Preferences.CATEGORY_ACTIONS_MENU,
|
||||
name: Preferences.NAME_ACTIONS_MENU_TUTORIAL_STATE,
|
||||
value: JSON.stringify(initializationState),
|
||||
};
|
||||
await dispatch(savePreferences(currentUserId, [preference]));
|
||||
};
|
||||
}
|
||||
|
||||
export function setCustomStatusInitialisationState(initializationState: Record<string, boolean>): ThunkActionFunc<void> {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
@ -130,7 +116,7 @@ export function deleteTeamSpecificThemes(): ActionFuncAsync {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
||||
const themePreferences: PreferenceType[] = makeGetCategory()(state, Preferences.CATEGORY_THEME);
|
||||
const themePreferences: PreferenceType[] = getThemePreferences(state);
|
||||
const currentUserId = getCurrentUserId(state);
|
||||
|
||||
const toDelete = themePreferences.filter((pref) => pref.name !== '');
|
||||
|
@ -37,10 +37,6 @@ const Preferences = {
|
||||
MENTION_KEYS: 'mention_keys',
|
||||
USE_MILITARY_TIME: 'use_military_time',
|
||||
|
||||
CATEGORY_ACTIONS_MENU: 'actions_menu',
|
||||
NAME_ACTIONS_MENU_TUTORIAL_STATE: 'actions_menu_tutorial_state',
|
||||
ACTIONS_MENU_VIEWED: 'actions_menu_modal_viewed',
|
||||
|
||||
CATEGORY_CUSTOM_STATUS: 'custom_status',
|
||||
NAME_CUSTOM_STATUS_TUTORIAL_STATE: 'custom_status_tutorial_state',
|
||||
NAME_RECENT_CUSTOM_STATUSES: 'recent_custom_statuses',
|
||||
@ -82,6 +78,8 @@ const Preferences = {
|
||||
HIDE_BATCH_EXPORT_CONFIRM_MODAL: 'hide_batch_export_confirm_modal',
|
||||
HIDE_MYSQL_STATS_NOTIFICATION: 'hide_mysql_stats_notifcation',
|
||||
|
||||
CATEGORY_OVERAGE_USERS_BANNER: 'overage_users_banner',
|
||||
|
||||
CATEGORY_THEME: 'theme',
|
||||
THEMES: {
|
||||
denim: {
|
||||
|
@ -253,6 +253,11 @@ describe('Selectors.Posts', () => {
|
||||
|
||||
const testStateAny = deepFreezeAndThrowOnMutation({
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
users: {
|
||||
currentUserId: userAny.id,
|
||||
profiles: profilesAny,
|
||||
@ -372,6 +377,11 @@ describe('Selectors.Posts', () => {
|
||||
|
||||
const testStateRoot = deepFreezeAndThrowOnMutation({
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
users: {
|
||||
currentUserId: userRoot.id,
|
||||
profiles: profilesRoot,
|
||||
@ -485,6 +495,11 @@ describe('Selectors.Posts', () => {
|
||||
|
||||
const testStateNever = deepFreezeAndThrowOnMutation({
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
users: {
|
||||
currentUserId: userNever.id,
|
||||
profiles: profilesNever,
|
||||
@ -601,6 +616,11 @@ describe('Selectors.Posts', () => {
|
||||
|
||||
const testStateAny = deepFreezeAndThrowOnMutation({
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
users: {
|
||||
currentUserId: userAny.id,
|
||||
profiles: profilesAny,
|
||||
@ -678,6 +698,11 @@ describe('Selectors.Posts', () => {
|
||||
|
||||
const testStateAny = deepFreezeAndThrowOnMutation({
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
users: {
|
||||
currentUserId: userAny.id,
|
||||
profiles: profilesAny,
|
||||
@ -1823,6 +1848,11 @@ describe('Selectors.Posts', () => {
|
||||
};
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
posts: {
|
||||
posts: testPosts,
|
||||
postsInChannel: {
|
||||
@ -1852,6 +1882,11 @@ describe('Selectors.Posts', () => {
|
||||
};
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
posts: {
|
||||
posts: testPosts,
|
||||
postsInChannel: {
|
||||
@ -1880,6 +1915,11 @@ describe('Selectors.Posts', () => {
|
||||
channels: {
|
||||
currentChannelId: 'abcd',
|
||||
},
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
posts: {
|
||||
posts: {},
|
||||
postsInChannel: [],
|
||||
@ -1910,6 +1950,11 @@ describe('Selectors.Posts', () => {
|
||||
channels: {
|
||||
currentChannelId: 'abcd',
|
||||
},
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
posts: {
|
||||
posts: postsAny,
|
||||
postsInChannel: {
|
||||
@ -2147,6 +2192,11 @@ describe('getPostsInCurrentChannel', () => {
|
||||
channels: {
|
||||
currentChannelId: 'channel1',
|
||||
},
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
posts: {
|
||||
posts: {},
|
||||
postsInChannel: {},
|
||||
@ -2177,6 +2227,11 @@ describe('getPostsInCurrentChannel', () => {
|
||||
channels: {
|
||||
currentChannelId: 'channel1',
|
||||
},
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
posts: {
|
||||
posts: {
|
||||
post1,
|
||||
@ -2214,6 +2269,11 @@ describe('getPostsInCurrentChannel', () => {
|
||||
channels: {
|
||||
currentChannelId: 'channel1',
|
||||
},
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
posts: {
|
||||
posts: {
|
||||
post1,
|
||||
|
@ -24,11 +24,10 @@ import {createSelector} from 'mattermost-redux/selectors/create_selector';
|
||||
import {getChannel} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentChannelId, getCurrentUser} from 'mattermost-redux/selectors/entities/common';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getBool, shouldShowJoinLeaveMessages} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getUsers, getCurrentUserId, getUserStatuses} from 'mattermost-redux/selectors/entities/users';
|
||||
import {createIdsSelector} from 'mattermost-redux/utils/helpers';
|
||||
import {shouldShowJoinLeaveMessages} from 'mattermost-redux/utils/post_list';
|
||||
import {
|
||||
isPostEphemeral,
|
||||
isSystemMessage,
|
||||
@ -37,7 +36,6 @@ import {
|
||||
isPostPendingOrFailed,
|
||||
isPostCommentMention,
|
||||
} from 'mattermost-redux/utils/post_utils';
|
||||
import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils';
|
||||
import {isGuest} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
export function getAllPosts(state: GlobalState) {
|
||||
@ -53,6 +51,10 @@ export function getPost(state: GlobalState, postId: Post['id']): Post {
|
||||
return getAllPosts(state)[postId];
|
||||
}
|
||||
|
||||
export function isPostFlagged(state: GlobalState, postId: Post['id']): boolean {
|
||||
return getBool(state, Preferences.CATEGORY_FLAGGED_POST, postId);
|
||||
}
|
||||
|
||||
export function getPostRepliesCount(state: GlobalState, postId: Post['id']): number {
|
||||
return state.entities.posts.postsReplies[postId] || 0;
|
||||
}
|
||||
@ -344,18 +346,15 @@ export function makeGetPostsInChannel(): (state: GlobalState, channelId: Channel
|
||||
getPostsInThread,
|
||||
(state: GlobalState, channelId: Channel['id']) => getPostIdsInChannel(state, channelId),
|
||||
getCurrentUser,
|
||||
getMyPreferences,
|
||||
shouldShowJoinLeaveMessages,
|
||||
(state: GlobalState, channelId: Channel['id'], numPosts: number) => numPosts || Posts.POST_CHUNK_SIZE,
|
||||
(allPosts, postsInThread, allPostIds, currentUser, myPreferences, numPosts) => {
|
||||
(allPosts, postsInThread, allPostIds, currentUser, showJoinLeave, numPosts) => {
|
||||
if (!allPostIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const posts: PostWithFormatData[] = [];
|
||||
|
||||
const joinLeavePref = myPreferences[getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)];
|
||||
const showJoinLeave = joinLeavePref ? joinLeavePref.value !== 'false' : true;
|
||||
|
||||
const postIds = numPosts === -1 ? allPostIds : allPostIds.slice(0, numPosts);
|
||||
|
||||
for (let i = 0; i < postIds.length; i++) {
|
||||
@ -388,15 +387,13 @@ export function makeGetPostsAroundPost(): (state: GlobalState, postId: Post['id'
|
||||
getPostsInThread,
|
||||
(state: GlobalState, focusedPostId) => focusedPostId,
|
||||
getCurrentUser,
|
||||
getMyPreferences,
|
||||
(postIds, allPosts, postsInThread, focusedPostId, currentUser, myPreferences) => {
|
||||
shouldShowJoinLeaveMessages,
|
||||
(postIds, allPosts, postsInThread, focusedPostId, currentUser, showJoinLeave) => {
|
||||
if (!postIds || !currentUser) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const posts: PostWithFormatData[] = [];
|
||||
const joinLeavePref = myPreferences[getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)];
|
||||
const showJoinLeave = joinLeavePref ? joinLeavePref.value !== 'false' : true;
|
||||
|
||||
for (let i = 0; i < postIds.length; i++) {
|
||||
const post = allPosts[postIds[i]];
|
||||
@ -565,13 +562,11 @@ export const getMostRecentPostIdInChannel: (state: GlobalState, channelId: Chann
|
||||
'getMostRecentPostIdInChannel',
|
||||
getAllPosts,
|
||||
(state: GlobalState, channelId: string) => getPostIdsInChannel(state, channelId),
|
||||
getMyPreferences,
|
||||
(posts, postIdsInChannel, preferences) => {
|
||||
shouldShowJoinLeaveMessages,
|
||||
(posts, postIdsInChannel, allowSystemMessages) => {
|
||||
if (!postIdsInChannel) {
|
||||
return '';
|
||||
}
|
||||
const key = getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE);
|
||||
const allowSystemMessages = preferences[key] ? preferences[key].value === 'true' : true;
|
||||
|
||||
if (!allowSystemMessages) {
|
||||
// return the most recent non-system message in the channel
|
||||
|
@ -135,11 +135,6 @@ describe('Selectors.Preferences', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('get preferences by category', () => {
|
||||
const getCategory = Selectors.makeGetCategory();
|
||||
expect(getCategory(testState, category1)).toEqual([pref1]);
|
||||
});
|
||||
|
||||
it('get direct channel show preferences', () => {
|
||||
expect(Selectors.getDirectShowPreferences(testState)).toEqual([dmPref1, dmPref2]);
|
||||
});
|
||||
@ -599,6 +594,233 @@ describe('Selectors.Preferences', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('makeGetCategory', () => {
|
||||
const category1 = 'category1';
|
||||
const category2 = 'category2';
|
||||
const name1 = 'name1';
|
||||
const name2 = 'name2';
|
||||
|
||||
function getBaseState() {
|
||||
return deepFreezeAndThrowOnMutation({
|
||||
entities: {
|
||||
preferences: {
|
||||
myPreferences: {
|
||||
[getPreferenceKey(category1, name1)]: {
|
||||
category: category1,
|
||||
name: name1,
|
||||
value: 'value1',
|
||||
},
|
||||
[getPreferenceKey(category2, name1)]: {
|
||||
category: category2,
|
||||
name: name1,
|
||||
value: 'value2',
|
||||
},
|
||||
[getPreferenceKey(category1, name2)]: {
|
||||
category: category1,
|
||||
name: name2,
|
||||
value: 'value3',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as GlobalState;
|
||||
}
|
||||
|
||||
it('should return preferences in a category', () => {
|
||||
const state = getBaseState();
|
||||
|
||||
const getCategory1 = Selectors.makeGetCategory('getCategory1', category1);
|
||||
const getCategory2 = Selectors.makeGetCategory('getCategory2', category2);
|
||||
|
||||
expect(getCategory1(state)).toEqual([
|
||||
{
|
||||
category: category1,
|
||||
name: name1,
|
||||
value: 'value1',
|
||||
},
|
||||
{
|
||||
category: category1,
|
||||
name: name2,
|
||||
value: 'value3',
|
||||
},
|
||||
]);
|
||||
expect(getCategory2(state)).toEqual([
|
||||
{
|
||||
category: category2,
|
||||
name: name1,
|
||||
value: 'value2',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return the same preference objects unless they change', () => {
|
||||
let state = getBaseState();
|
||||
|
||||
const preference1 = state.entities.preferences.myPreferences[getPreferenceKey(category1, name1)];
|
||||
const preference2 = state.entities.preferences.myPreferences[getPreferenceKey(category1, name2)];
|
||||
|
||||
const getCategory1 = Selectors.makeGetCategory('getCategory1', category1);
|
||||
|
||||
expect(getCategory1(state)[0]).toBe(preference1);
|
||||
expect(getCategory1(state)[1]).toBe(preference2);
|
||||
|
||||
state = mergeObjects(state, {
|
||||
entities: {
|
||||
preferences: {
|
||||
myPreferences: {
|
||||
[getPreferenceKey(category1, name1)]: {
|
||||
category: category1,
|
||||
name: name1,
|
||||
value: 'new value',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(getCategory1(state)[0]).not.toBe(preference1);
|
||||
expect(getCategory1(state)[1]).toBe(preference2);
|
||||
});
|
||||
|
||||
it('should only return a new array when one of the preferences in that category changes', () => {
|
||||
let state = getBaseState();
|
||||
|
||||
const getCategory1 = Selectors.makeGetCategory('getCategory1', category1);
|
||||
const getCategory2 = Selectors.makeGetCategory('getCategory2', category2);
|
||||
|
||||
const originalResult1 = getCategory1(state);
|
||||
const originalResult2 = getCategory2(state);
|
||||
|
||||
expect(getCategory1(state)).toBe(originalResult1);
|
||||
|
||||
state = mergeObjects(state, {
|
||||
entities: {
|
||||
preferences: {
|
||||
myPreferences: {
|
||||
[getPreferenceKey(category2, name2)]: {
|
||||
category: category2,
|
||||
name: name2,
|
||||
value: 'value4',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(getCategory1(state)).toBe(originalResult1);
|
||||
expect(getCategory2(state)).not.toBe(originalResult2);
|
||||
|
||||
state = mergeObjects(state, {
|
||||
entities: {
|
||||
preferences: {
|
||||
myPreferences: {
|
||||
[getPreferenceKey(category1, name1)]: {
|
||||
category: category1,
|
||||
name: name1,
|
||||
value: 'new value',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(getCategory1(state)).not.toBe(originalResult1);
|
||||
expect(getCategory2(state)).not.toBe(originalResult2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldShowJoinLeaveMessages', () => {
|
||||
it('should default to true', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
myPreferences: {},
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
// Defaults to show post
|
||||
const show = Selectors.shouldShowJoinLeaveMessages(state);
|
||||
expect(show).toEqual(true);
|
||||
});
|
||||
|
||||
it('set config to false, return false', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'false',
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
myPreferences: {},
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
// Defaults to show post
|
||||
const show = Selectors.shouldShowJoinLeaveMessages(state);
|
||||
expect(show).toEqual(false);
|
||||
});
|
||||
|
||||
it('if user preference, set default wont be used', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'false',
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
myPreferences: {
|
||||
[getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)]: {
|
||||
category: Preferences.CATEGORY_ADVANCED_SETTINGS,
|
||||
name: Preferences.ADVANCED_FILTER_JOIN_LEAVE,
|
||||
value: 'true',
|
||||
},
|
||||
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
// Defaults to show post
|
||||
const show = Selectors.shouldShowJoinLeaveMessages(state);
|
||||
expect(show).toEqual(true);
|
||||
});
|
||||
|
||||
it('if user preference, set default wont be used', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
myPreferences: {
|
||||
[getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)]: {
|
||||
category: Preferences.CATEGORY_ADVANCED_SETTINGS,
|
||||
name: Preferences.ADVANCED_FILTER_JOIN_LEAVE,
|
||||
value: 'false',
|
||||
},
|
||||
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
// Defaults to show post
|
||||
const show = Selectors.shouldShowJoinLeaveMessages(state);
|
||||
expect(show).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldShowUnreadsCategory', () => {
|
||||
test('should return value from the preference if set', () => {
|
||||
const state = {
|
||||
|
@ -8,7 +8,7 @@ import type {GlobalState} from '@mattermost/types/store';
|
||||
import {General, Preferences} from 'mattermost-redux/constants';
|
||||
import {createSelector} from 'mattermost-redux/selectors/create_selector';
|
||||
import {getConfig, getFeatureFlagValue, getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {createShallowSelector} from 'mattermost-redux/utils/helpers';
|
||||
import {createIdsSelector, createShallowSelector} from 'mattermost-redux/utils/helpers';
|
||||
import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils';
|
||||
import {setThemeDefaults} from 'mattermost-redux/utils/theme_utils';
|
||||
|
||||
@ -20,19 +20,18 @@ export function getUserPreferences(state: GlobalState, userID: string): Preferen
|
||||
return state.entities.preferences.userPreferences[userID];
|
||||
}
|
||||
|
||||
export function get(state: GlobalState, category: string, name: string, defaultValue: any = '', preferences?: PreferencesType) {
|
||||
function getPreferenceObject(state: GlobalState, category: string, name: string): PreferenceType | undefined {
|
||||
return getMyPreferences(state)[getPreferenceKey(category, name)];
|
||||
}
|
||||
|
||||
export function get(state: GlobalState, category: string, name: string, defaultValue = '', preferences?: PreferencesType): string {
|
||||
if (preferences) {
|
||||
return getFromPreferences(preferences, category, name, defaultValue);
|
||||
}
|
||||
|
||||
const key = getPreferenceKey(category, name);
|
||||
const prefs = getMyPreferences(state);
|
||||
const pref = getPreferenceObject(state, category, name);
|
||||
|
||||
if (!(key in prefs)) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return prefs[key].value;
|
||||
return pref ? pref.value : defaultValue;
|
||||
}
|
||||
|
||||
export function getFromPreferences(preferences: PreferencesType, category: string, name: string, defaultValue: any = '') {
|
||||
@ -51,16 +50,15 @@ export function getBool(state: GlobalState, category: string, name: string, defa
|
||||
}
|
||||
|
||||
export function getInt(state: GlobalState, category: string, name: string, defaultValue = 0, userPreferences?: PreferencesType): number {
|
||||
const value = get(state, category, name, defaultValue, userPreferences);
|
||||
const value = get(state, category, name, String(defaultValue), userPreferences);
|
||||
return parseInt(value, 10);
|
||||
}
|
||||
|
||||
export function makeGetCategory(): (state: GlobalState, category: string) => PreferenceType[] {
|
||||
return createSelector(
|
||||
'makeGetCategory',
|
||||
export function makeGetCategory(selectorName: string, category: string): (state: GlobalState) => PreferenceType[] {
|
||||
return createIdsSelector(
|
||||
selectorName,
|
||||
getMyPreferences,
|
||||
(state: GlobalState, category: string) => category,
|
||||
(preferences, category) => {
|
||||
(preferences) => {
|
||||
const prefix = category + '--';
|
||||
const prefsInCategory: PreferenceType[] = [];
|
||||
|
||||
@ -75,12 +73,11 @@ export function makeGetCategory(): (state: GlobalState, category: string) => Pre
|
||||
);
|
||||
}
|
||||
|
||||
export function makeGetUserCategory(userID: string): (state: GlobalState, category: string) => PreferenceType[] {
|
||||
return createSelector(
|
||||
'makeGetCategory',
|
||||
(state) => getUserPreferences(state, userID),
|
||||
(state: GlobalState, category: string) => category,
|
||||
(preferences, category) => {
|
||||
export function makeGetUserCategory(selectorName: string, category: string): (state: GlobalState, userID: string) => PreferenceType[] {
|
||||
return createIdsSelector(
|
||||
selectorName,
|
||||
(state: GlobalState, userID: string) => getUserPreferences(state, userID),
|
||||
(preferences) => {
|
||||
const prefix = category + '--';
|
||||
const prefsInCategory: PreferenceType[] = [];
|
||||
|
||||
@ -95,28 +92,18 @@ export function makeGetUserCategory(userID: string): (state: GlobalState, catego
|
||||
);
|
||||
}
|
||||
|
||||
const getDirectShowCategory = makeGetCategory();
|
||||
|
||||
export function getDirectShowPreferences(state: GlobalState) {
|
||||
return getDirectShowCategory(state, Preferences.CATEGORY_DIRECT_CHANNEL_SHOW);
|
||||
}
|
||||
|
||||
const getGroupShowCategory = makeGetCategory();
|
||||
|
||||
export function getGroupShowPreferences(state: GlobalState) {
|
||||
return getGroupShowCategory(state, Preferences.CATEGORY_GROUP_CHANNEL_SHOW);
|
||||
}
|
||||
export const getDirectShowPreferences = makeGetCategory('getDirectShowPreferences', Preferences.CATEGORY_DIRECT_CHANNEL_SHOW);
|
||||
export const getGroupShowPreferences = makeGetCategory('getGroupShowPreferences', Preferences.CATEGORY_GROUP_CHANNEL_SHOW);
|
||||
|
||||
export const getTeammateNameDisplaySetting: (state: GlobalState) => string = createSelector(
|
||||
'getTeammateNameDisplaySetting',
|
||||
getConfig,
|
||||
getMyPreferences,
|
||||
(state) => getPreferenceObject(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT),
|
||||
getLicense,
|
||||
(config, preferences, license) => {
|
||||
(config, teammateNameDisplayPreference, license) => {
|
||||
const useAdminTeammateNameDisplaySetting = (license && license.LockTeammateNameDisplay === 'true') && config.LockTeammateNameDisplay === 'true';
|
||||
const key = getPreferenceKey(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT);
|
||||
if (preferences[key] && !useAdminTeammateNameDisplaySetting) {
|
||||
return preferences[key].value || '';
|
||||
if (teammateNameDisplayPreference && !useAdminTeammateNameDisplaySetting) {
|
||||
return teammateNameDisplayPreference.value || '';
|
||||
} else if (config.TeammateNameDisplay) {
|
||||
return config.TeammateNameDisplay;
|
||||
}
|
||||
@ -124,6 +111,8 @@ export const getTeammateNameDisplaySetting: (state: GlobalState) => string = cre
|
||||
},
|
||||
);
|
||||
|
||||
export const getThemePreferences = makeGetCategory('getThemePreferences', Preferences.CATEGORY_THEME);
|
||||
|
||||
const getThemePreference = createSelector(
|
||||
'getThemePreference',
|
||||
getMyPreferences,
|
||||
@ -218,6 +207,14 @@ export function makeGetStyleFromTheme<Style>(): (state: GlobalState, getStyleFro
|
||||
);
|
||||
}
|
||||
|
||||
export function shouldShowJoinLeaveMessages(state: GlobalState) {
|
||||
const config = getConfig(state);
|
||||
const enableJoinLeaveMessage = config.EnableJoinLeaveMessageByDefault === 'true';
|
||||
|
||||
// This setting is true or not set if join/leave messages are to be displayed
|
||||
return getBool(state, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE, enableJoinLeaveMessage);
|
||||
}
|
||||
|
||||
// shouldShowUnreadsCategory returns true if the user has unereads grouped separately with the new sidebar enabled.
|
||||
export const shouldShowUnreadsCategory: (state: GlobalState, userPreferences?: PreferencesType) => boolean = createSelector(
|
||||
'shouldShowUnreadsCategory',
|
||||
@ -336,3 +333,5 @@ export function moveThreadsEnabled(state: GlobalState): boolean {
|
||||
export function streamlinedMarketplaceEnabled(state: GlobalState): boolean {
|
||||
return getFeatureFlagValue(state, 'StreamlinedMarketplace') === 'true';
|
||||
}
|
||||
|
||||
export const getOverageBannerPreferences = makeGetCategory('getOverageBannerPreferences', Preferences.CATEGORY_OVERAGE_USERS_BANNER);
|
||||
|
@ -23,7 +23,6 @@ import {
|
||||
makeGenerateCombinedPost,
|
||||
extractUserActivityData,
|
||||
START_OF_NEW_MESSAGES,
|
||||
shouldShowJoinLeaveMessages,
|
||||
} from './post_list';
|
||||
|
||||
import TestHelper from '../../test/test_helper';
|
||||
@ -1688,95 +1687,3 @@ describe('combineUserActivityData', () => {
|
||||
expect(combineUserActivitySystemPost(posts)).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldShowJoinLeaveMessages', () => {
|
||||
it('should default to true', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
myPreferences: {},
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
// Defaults to show post
|
||||
const show = shouldShowJoinLeaveMessages(state);
|
||||
expect(show).toEqual(true);
|
||||
});
|
||||
|
||||
it('set config to false, return false', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'false',
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
myPreferences: {},
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
// Defaults to show post
|
||||
const show = shouldShowJoinLeaveMessages(state);
|
||||
expect(show).toEqual(false);
|
||||
});
|
||||
|
||||
it('if user preference, set default wont be used', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'false',
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
myPreferences: {
|
||||
[getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)]: {
|
||||
category: Preferences.CATEGORY_ADVANCED_SETTINGS,
|
||||
name: Preferences.ADVANCED_FILTER_JOIN_LEAVE,
|
||||
value: 'true',
|
||||
},
|
||||
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
// Defaults to show post
|
||||
const show = shouldShowJoinLeaveMessages(state);
|
||||
expect(show).toEqual(true);
|
||||
});
|
||||
|
||||
it('if user preference, set default wont be used', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
config: {
|
||||
EnableJoinLeaveMessageByDefault: 'true',
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
myPreferences: {
|
||||
[getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)]: {
|
||||
category: Preferences.CATEGORY_ADVANCED_SETTINGS,
|
||||
name: Preferences.ADVANCED_FILTER_JOIN_LEAVE,
|
||||
value: 'false',
|
||||
},
|
||||
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
// Defaults to show post
|
||||
const show = shouldShowJoinLeaveMessages(state);
|
||||
expect(show).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
@ -6,12 +6,11 @@ import moment from 'moment-timezone';
|
||||
import type {ActivityEntry, Post} from '@mattermost/types/posts';
|
||||
import type {GlobalState} from '@mattermost/types/store';
|
||||
|
||||
import {Posts, Preferences} from 'mattermost-redux/constants';
|
||||
import {Posts} from 'mattermost-redux/constants';
|
||||
import {createSelector} from 'mattermost-redux/selectors/create_selector';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {makeGetPostsForIds} from 'mattermost-redux/selectors/entities/posts';
|
||||
import type {UserActivityPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {getBool} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {shouldShowJoinLeaveMessages} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
|
||||
import {createIdsSelector, memoizeResult} from 'mattermost-redux/utils/helpers';
|
||||
import {isUserActivityPost, shouldFilterJoinLeavePost, isFromWebhook} from 'mattermost-redux/utils/post_utils';
|
||||
@ -23,14 +22,6 @@ export const DATE_LINE = 'date-';
|
||||
export const START_OF_NEW_MESSAGES = 'start-of-new-messages-';
|
||||
export const MAX_COMBINED_SYSTEM_POSTS = 100;
|
||||
|
||||
export function shouldShowJoinLeaveMessages(state: GlobalState) {
|
||||
const config = getConfig(state);
|
||||
const enableJoinLeaveMessage = config.EnableJoinLeaveMessageByDefault === 'true';
|
||||
|
||||
// This setting is true or not set if join/leave messages are to be displayed
|
||||
return getBool(state, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE, enableJoinLeaveMessage);
|
||||
}
|
||||
|
||||
interface PostFilterOptions {
|
||||
postIds: string[];
|
||||
lastViewedAt: number;
|
||||
|
@ -3,24 +3,14 @@
|
||||
|
||||
import type {Channel} from '@mattermost/types/channels';
|
||||
import type {Post, PostType, PostMetadata, PostEmbed} from '@mattermost/types/posts';
|
||||
import type {PreferenceType} from '@mattermost/types/preferences';
|
||||
import type {GlobalState} from '@mattermost/types/store';
|
||||
import type {Team} from '@mattermost/types/teams';
|
||||
import type {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
|
||||
|
||||
import {getPreferenceKey} from './preference_utils';
|
||||
|
||||
import {Posts, Preferences, Permissions} from '../constants';
|
||||
|
||||
export function isPostFlagged(postId: Post['id'], myPreferences: {
|
||||
[x: string]: PreferenceType;
|
||||
}): boolean {
|
||||
const key = getPreferenceKey(Preferences.CATEGORY_FLAGGED_POST, postId);
|
||||
return myPreferences.hasOwnProperty(key);
|
||||
}
|
||||
|
||||
export function isSystemMessage(post: Post): boolean {
|
||||
return Boolean(post.type && post.type.startsWith(Posts.SYSTEM_MESSAGE_PREFIX));
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Preferences} from 'mattermost-redux/constants';
|
||||
import {get} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
export function showActionsDropdownPulsatingDot(state: GlobalState): boolean {
|
||||
if (getIsMobileView(state)) {
|
||||
return false;
|
||||
}
|
||||
const actionsMenuTutorialState = get(state, Preferences.CATEGORY_ACTIONS_MENU, Preferences.NAME_ACTIONS_MENU_TUTORIAL_STATE, false);
|
||||
const modalAlreadyViewed = actionsMenuTutorialState && JSON.parse(actionsMenuTutorialState)[Preferences.ACTIONS_MENU_VIEWED];
|
||||
return !modalAlreadyViewed;
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {createSelector} from 'mattermost-redux/selectors/create_selector';
|
||||
import {makeGetCategory, getBool} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {get as getString, getBool, makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUser, isFirstAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
@ -13,21 +13,8 @@ import {RecommendedNextStepsLegacy, Preferences} from 'utils/constants';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
const getABTestCategory = makeGetCategory();
|
||||
export const getABTestPreferences = (() => {
|
||||
return (state: GlobalState) => getABTestCategory(state, Preferences.AB_TEST_PREFERENCE_VALUE);
|
||||
})();
|
||||
|
||||
const getFirstChannelNamePref = createSelector(
|
||||
'getFirstChannelNamePref',
|
||||
getABTestPreferences,
|
||||
(preferences) => {
|
||||
return preferences.find((pref) => pref.name === RecommendedNextStepsLegacy.CREATE_FIRST_CHANNEL);
|
||||
},
|
||||
);
|
||||
|
||||
export function getFirstChannelName(state: GlobalState) {
|
||||
return getFirstChannelNamePref(state)?.value || '';
|
||||
return getString(state, Preferences.AB_TEST_PREFERENCE_VALUE, RecommendedNextStepsLegacy.CREATE_FIRST_CHANNEL, '');
|
||||
}
|
||||
|
||||
export function getShowLaunchingWorkspace(state: GlobalState) {
|
||||
@ -91,13 +78,13 @@ const getSteps = createSelector(
|
||||
},
|
||||
);
|
||||
|
||||
const getNextStepsCategory = makeGetCategory();
|
||||
const getOnboardingTaskCategory = makeGetCategory();
|
||||
const getNextStepsPreferences = makeGetCategory('getNextStepsPreferences', Preferences.RECOMMENDED_NEXT_STEPS);
|
||||
export const getOnboardingTaskPreferences = makeGetCategory('getOnboardingTaskPreferences', OnboardingTaskCategory);
|
||||
|
||||
// Loop through all Steps. For each step, check that
|
||||
export const legacyNextStepsNotFinished = createSelector(
|
||||
'legacyNextStepsNotFinished',
|
||||
(state: GlobalState) => getNextStepsCategory(state, Preferences.RECOMMENDED_NEXT_STEPS),
|
||||
getNextStepsPreferences,
|
||||
(state: GlobalState) => getCurrentUser(state),
|
||||
(state: GlobalState) => isFirstAdmin(state),
|
||||
(state: GlobalState) => getSteps(state),
|
||||
@ -111,7 +98,7 @@ export const legacyNextStepsNotFinished = createSelector(
|
||||
// Loop through all Steps. For each step, check that
|
||||
export const hasLegacyNextStepsPreferences = createSelector(
|
||||
'hasLegacyNextStepsPreferences',
|
||||
(state: GlobalState) => getNextStepsCategory(state, Preferences.RECOMMENDED_NEXT_STEPS),
|
||||
getNextStepsPreferences,
|
||||
(state: GlobalState) => getSteps(state),
|
||||
(stepPreferences, mySteps) => {
|
||||
const checkPref = (step: StepType) => stepPreferences.some((pref) => (pref.name === step.id));
|
||||
@ -121,8 +108,8 @@ export const hasLegacyNextStepsPreferences = createSelector(
|
||||
|
||||
export const getShowTaskListBool = createSelector(
|
||||
'getShowTaskListBool',
|
||||
(state: GlobalState) => getOnboardingTaskCategory(state, OnboardingTaskCategory),
|
||||
(state: GlobalState) => getNextStepsCategory(state, Preferences.RECOMMENDED_NEXT_STEPS),
|
||||
getOnboardingTaskPreferences,
|
||||
getNextStepsPreferences,
|
||||
getIsMobileView,
|
||||
(state: GlobalState) => getBool(state, OnboardingTaskCategory, OnboardingTaskList.ONBOARDING_TASK_LIST_SHOW),
|
||||
(state: GlobalState) => hasLegacyNextStepsPreferences(state),
|
||||
|
@ -103,7 +103,6 @@ export const Preferences = {
|
||||
UNREAD_SCROLL_POSITION_START_FROM_LEFT: 'start_from_left_off',
|
||||
UNREAD_SCROLL_POSITION_START_FROM_NEWEST: 'start_from_newest',
|
||||
CATEGORY_THEME: 'theme',
|
||||
CATEGORY_FLAGGED_POST: 'flagged_post',
|
||||
CATEGORY_NOTIFICATIONS: 'notifications',
|
||||
EMAIL_INTERVAL: 'email_interval',
|
||||
INTERVAL_IMMEDIATE: 30, // "immediate" is a 30 second interval
|
||||
@ -147,7 +146,7 @@ export const Preferences = {
|
||||
DELINQUENCY_MODAL_CONFIRMED: 'delinquency_modal_confirmed',
|
||||
CONFIGURATION_BANNERS: 'configuration_banners',
|
||||
NOTIFY_ADMIN_REVOKE_DOWNGRADED_WORKSPACE: 'admin_revoke_downgraded_instance',
|
||||
OVERAGE_USERS_BANNER: 'overage_users_banner',
|
||||
OVERAGE_USERS_BANNER: ReduxPreferences.CATEGORY_OVERAGE_USERS_BANNER,
|
||||
TO_CLOUD_YEARLY_PLAN_NUDGE: 'to_cloud_yearly_plan_nudge',
|
||||
TO_PAID_PLAN_NUDGE: 'to_paid_plan_nudge',
|
||||
CLOUD_ANNUAL_RENEWAL_BANNER: 'cloud_annual_renewal_banner',
|
||||
|
@ -21,8 +21,8 @@ import {createSelector} from 'mattermost-redux/selectors/create_selector';
|
||||
import {getChannel} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getAllGroupsForReferenceByName} from 'mattermost-redux/selectors/entities/groups';
|
||||
import {makeGetReactionsForPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {get, getTeammateNameDisplaySetting, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {isPostFlagged, makeGetReactionsForPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {getTeammateNameDisplaySetting, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
|
||||
import {getCurrentTeamId, getTeam} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {makeGetDisplayName, getCurrentUserId, getUser, getUsersByUsername} from 'mattermost-redux/selectors/entities/users';
|
||||
@ -36,7 +36,7 @@ import {displayUsername} from 'mattermost-redux/utils/user_utils';
|
||||
import {getEmojiMap} from 'selectors/emojis';
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import Constants, {PostListRowListIds, Preferences} from 'utils/constants';
|
||||
import Constants, {PostListRowListIds} from 'utils/constants';
|
||||
import * as Keyboard from 'utils/keyboard';
|
||||
import {formatWithRenderer} from 'utils/markdown';
|
||||
import MentionableRenderer from 'utils/markdown/mentionable_renderer';
|
||||
@ -471,8 +471,8 @@ export function usePostAriaLabel(post: Post | undefined) {
|
||||
}
|
||||
|
||||
const authorDisplayName = getDisplayName(state, post.user_id);
|
||||
const reactions = getReactionsForPost(state, post?.id);
|
||||
const isFlagged = get(state, Preferences.CATEGORY_FLAGGED_POST, post.id, null) != null;
|
||||
const reactions = getReactionsForPost(state, post.id);
|
||||
const isFlagged = isPostFlagged(state, post.id);
|
||||
const emojiMap = getEmojiMap(state);
|
||||
const mentions = getMentionsFromMessage(state, post);
|
||||
const teammateNameDisplaySetting = getTeammateNameDisplaySetting(state);
|
||||
|
@ -5,7 +5,7 @@ export type PreferenceType = {
|
||||
category: string;
|
||||
name: string;
|
||||
user_id: string;
|
||||
value?: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type PreferencesType = {
|
||||
|
Loading…
Reference in New Issue
Block a user