From 86c880cf875d0fe504db9065f395ecd5c9e093bf Mon Sep 17 00:00:00 2001 From: M-ZubairAhmed Date: Thu, 15 Feb 2024 09:54:54 +0000 Subject: [PATCH] [MM-56798] Smoothen animation and lazy load User Settings (#26168) --- .../components/user_settings/modal/index.ts | 7 +- .../modal/user_settings_modal.tsx | 209 ++++++++---------- webapp/channels/src/i18n/en.json | 1 - 3 files changed, 100 insertions(+), 117 deletions(-) diff --git a/webapp/channels/src/components/user_settings/modal/index.ts b/webapp/channels/src/components/user_settings/modal/index.ts index 687ef6e424..46799ce0d0 100644 --- a/webapp/channels/src/components/user_settings/modal/index.ts +++ b/webapp/channels/src/components/user_settings/modal/index.ts @@ -1,6 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +import {lazy} from 'react'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; import type {Dispatch} from 'redux'; @@ -11,9 +12,11 @@ import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; import {getPluginUserSettings} from 'selectors/plugins'; +import {makeAsyncComponent} from 'components/async_load'; + import type {GlobalState} from 'types/store'; -import UserSettingsModal from './user_settings_modal'; +const UserSettingsModalAsync = makeAsyncComponent('UserSettingsModal', lazy(() => import('./user_settings_modal'))); function mapStateToProps(state: GlobalState) { const config = getConfig(state); @@ -37,4 +40,4 @@ function mapDispatchToProps(dispatch: Dispatch) { }; } -export default connect(mapStateToProps, mapDispatchToProps)(UserSettingsModal); +export default connect(mapStateToProps, mapDispatchToProps)(UserSettingsModalAsync); diff --git a/webapp/channels/src/components/user_settings/modal/user_settings_modal.tsx b/webapp/channels/src/components/user_settings/modal/user_settings_modal.tsx index eb2105dfac..472035fff8 100644 --- a/webapp/channels/src/components/user_settings/modal/user_settings_modal.tsx +++ b/webapp/channels/src/components/user_settings/modal/user_settings_modal.tsx @@ -4,75 +4,23 @@ import React from 'react'; import {Modal} from 'react-bootstrap'; import ReactDOM from 'react-dom'; -import { - defineMessages, - injectIntl, -} from 'react-intl'; -import type { - IntlShape} from 'react-intl'; -import {Provider} from 'react-redux'; +import {injectIntl} from 'react-intl'; +import type {IntlShape} from 'react-intl'; import type {UserProfile} from '@mattermost/types/users'; import type {ActionResult} from 'mattermost-redux/types/actions'; -import store from 'stores/redux_store'; - import ConfirmModal from 'components/confirm_modal'; +import SettingsSidebar from 'components/settings_sidebar'; +import UserSettings from 'components/user_settings'; import Constants from 'utils/constants'; -import * as Keyboard from 'utils/keyboard'; -import * as NotificationSounds from 'utils/notification_sounds'; -import * as Utils from 'utils/utils'; +import {cmdOrCtrlPressed, isKeyPressed} from 'utils/keyboard'; +import {stopTryNotificationRing} from 'utils/notification_sounds'; import type {PluginConfiguration} from 'types/plugins/user_settings'; -const UserSettings = React.lazy(() => import(/* webpackPrefetch: true */ 'components/user_settings')); -const SettingsSidebar = React.lazy(() => import(/* webpackPrefetch: true */ 'components/settings_sidebar')); - -const holders = defineMessages({ - profile: { - id: 'user.settings.modal.profile', - defaultMessage: 'Profile', - }, - security: { - id: 'user.settings.modal.security', - defaultMessage: 'Security', - }, - notifications: { - id: 'user.settings.modal.notifications', - defaultMessage: 'Notifications', - }, - display: { - id: 'user.settings.modal.display', - defaultMessage: 'Display', - }, - sidebar: { - id: 'user.settings.modal.sidebar', - defaultMessage: 'Sidebar', - }, - advanced: { - id: 'user.settings.modal.advanced', - defaultMessage: 'Advanced', - }, - checkEmail: { - id: 'user.settings.general.checkEmail', - defaultMessage: 'Check your email at {email} to verify the address. Cannot find the email?', - }, - confirmTitle: { - id: 'user.settings.modal.confirmTitle', - defaultMessage: 'Discard Changes?', - }, - confirmMsg: { - id: 'user.settings.modal.confirmMsg', - defaultMessage: 'You have unsaved changes, are you sure you want to discard them?', - }, - confirmBtns: { - id: 'user.settings.modal.confirmBtns', - defaultMessage: 'Yes, Discard', - }, -}); - export type Props = { currentUser: UserProfile; onExited: () => void; @@ -150,7 +98,7 @@ class UserSettingsModal extends React.PureComponent { } handleKeyDown = (e: KeyboardEvent) => { - if (Keyboard.cmdOrCtrlPressed(e) && e.shiftKey && Keyboard.isKeyPressed(e, Constants.KeyCodes.A)) { + if (cmdOrCtrlPressed(e) && e.shiftKey && isKeyPressed(e, Constants.KeyCodes.A)) { e.preventDefault(); this.handleHide(); } @@ -164,7 +112,7 @@ class UserSettingsModal extends React.PureComponent { } // Cancel any ongoing notification sound, if any (from DesktopNotificationSettings) - NotificationSounds.stopTryNotificationRing(); + stopTryNotificationRing(); this.setState({ show: false, @@ -270,30 +218,68 @@ class UserSettingsModal extends React.PureComponent { } }; + getUserSettingsTabs = () => { + return [ + { + name: 'notifications', + uiName: this.props.intl.formatMessage({id: 'user.settings.modal.notifications', defaultMessage: 'Notifications'}), + icon: 'icon icon-bell-outline', + iconTitle: this.props.intl.formatMessage({id: 'user.settings.notifications.icon', defaultMessage: 'Notification Settings Icon'}), + }, + { + name: 'display', + uiName: this.props.intl.formatMessage({id: 'user.settings.modal.display', defaultMessage: 'Display'}), + icon: 'icon icon-eye-outline', + iconTitle: this.props.intl.formatMessage({id: 'user.settings.display.icon', defaultMessage: 'Display Settings Icon'}), + }, + { + name: 'sidebar', + uiName: this.props.intl.formatMessage({id: 'user.settings.modal.sidebar', defaultMessage: 'Sidebar'}), + icon: 'icon icon-dock-left', + iconTitle: this.props.intl.formatMessage({id: 'user.settings.sidebar.icon', defaultMessage: 'Sidebar Settings Icon'}), + }, + { + name: 'advanced', + uiName: this.props.intl.formatMessage({id: 'user.settings.modal.advanced', defaultMessage: 'Advanced'}), + icon: 'icon icon-tune', + iconTitle: this.props.intl.formatMessage({id: 'user.settings.advance.icon', defaultMessage: 'Advanced Settings Icon'}), + }, + ]; + }; + + getProfileSettingsTab = () => { + return [ + { + name: 'profile', + uiName: this.props.intl.formatMessage({id: 'user.settings.modal.profile', defaultMessage: 'Profile'}), + icon: 'icon icon-settings-outline', + iconTitle: this.props.intl.formatMessage({id: 'user.settings.profile.icon', defaultMessage: 'Profile Settings Icon'}), + }, + { + name: 'security', + uiName: this.props.intl.formatMessage({id: 'user.settings.modal.security', defaultMessage: 'Security'}), + icon: 'icon icon-lock-outline', + iconTitle: this.props.intl.formatMessage({id: 'user.settings.security.icon', defaultMessage: 'Security Settings Icon'}), + }, + ]; + }; + + getPluginsSettingsTab = () => { + return Object.values(this.props.pluginSettings).map((v) => ({ + name: v.id, + uiName: v.uiName, + icon: v.icon ? {url: v.icon} : 'icon-power-plug-outline', + iconTitle: v.uiName, + })); + }; + render() { const {formatMessage} = this.props.intl; if (this.props.currentUser == null) { return (
); } - const tabs = []; - let pluginTabs; - if (this.props.isContentProductSettings) { - tabs.push({name: 'notifications', uiName: formatMessage(holders.notifications), icon: 'icon icon-bell-outline', iconTitle: Utils.localizeMessage('user.settings.notifications.icon', 'Notification Settings Icon')}); - tabs.push({name: 'display', uiName: formatMessage(holders.display), icon: 'icon icon-eye-outline', iconTitle: Utils.localizeMessage('user.settings.display.icon', 'Display Settings Icon')}); - tabs.push({name: 'sidebar', uiName: formatMessage(holders.sidebar), icon: 'icon icon-dock-left', iconTitle: Utils.localizeMessage('user.settings.sidebar.icon', 'Sidebar Settings Icon')}); - tabs.push({name: 'advanced', uiName: formatMessage(holders.advanced), icon: 'icon icon-tune', iconTitle: Utils.localizeMessage('user.settings.advance.icon', 'Advanced Settings Icon')}); - pluginTabs = Object.values(this.props.pluginSettings).map((v) => ({ - icon: v.icon ? {url: v.icon} : 'icon-power-plug-outline', - iconTitle: v.uiName, - name: v.id, - uiName: v.uiName, - })); - } else { - tabs.push({name: 'profile', uiName: formatMessage(holders.profile), icon: 'icon icon-settings-outline', iconTitle: Utils.localizeMessage('user.settings.profile.icon', 'Profile Settings Icon')}); - tabs.push({name: 'security', uiName: formatMessage(holders.security), icon: 'icon icon-lock-outline', iconTitle: Utils.localizeMessage('user.settings.security.icon', 'Security Settings Icon')}); - } - const title = this.props.isContentProductSettings ? formatMessage({ + const modalTitle = this.props.isContentProductSettings ? formatMessage({ id: 'global_header.productSettings', defaultMessage: 'Settings', }) : formatMessage({ @@ -310,7 +296,7 @@ class UserSettingsModal extends React.PureComponent { onExited={this.handleHidden} enforceFocus={this.state.enforceFocus} role='dialog' - aria-label={title} + aria-label={modalTitle} > { componentClass='h1' id='accountSettingsModalLabel' > - {title} + {modalTitle}
- - - - - +
- - - this.setState({enforceFocus})} - setRequireConfirm={ - (requireConfirm?: boolean, customConfirmAction?: () => () => void) => { - this.requireConfirm = requireConfirm!; - this.customConfirmAction = customConfirmAction!; - } - } - pluginSettings={this.props.pluginSettings} - user={this.props.currentUser} - /> - - + this.setState({enforceFocus})} + setRequireConfirm={ + (requireConfirm?: boolean, customConfirmAction?: () => () => void) => { + this.requireConfirm = requireConfirm!; + this.customConfirmAction = customConfirmAction!; + } + } + pluginSettings={this.props.pluginSettings} + user={this.props.currentUser} + />