mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[MM-56798] Smoothen animation and lazy load User Settings (#26168)
This commit is contained in:
parent
5758f234e5
commit
86c880cf87
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {lazy} from 'react';
|
||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import {bindActionCreators} from 'redux';
|
import {bindActionCreators} from 'redux';
|
||||||
import type {Dispatch} 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 {getPluginUserSettings} from 'selectors/plugins';
|
||||||
|
|
||||||
|
import {makeAsyncComponent} from 'components/async_load';
|
||||||
|
|
||||||
import type {GlobalState} from 'types/store';
|
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) {
|
function mapStateToProps(state: GlobalState) {
|
||||||
const config = getConfig(state);
|
const config = getConfig(state);
|
||||||
@ -37,4 +40,4 @@ function mapDispatchToProps(dispatch: Dispatch) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(UserSettingsModal);
|
export default connect(mapStateToProps, mapDispatchToProps)(UserSettingsModalAsync);
|
||||||
|
@ -4,75 +4,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Modal} from 'react-bootstrap';
|
import {Modal} from 'react-bootstrap';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import {
|
import {injectIntl} from 'react-intl';
|
||||||
defineMessages,
|
import type {IntlShape} from 'react-intl';
|
||||||
injectIntl,
|
|
||||||
} from 'react-intl';
|
|
||||||
import type {
|
|
||||||
IntlShape} from 'react-intl';
|
|
||||||
import {Provider} from 'react-redux';
|
|
||||||
|
|
||||||
import type {UserProfile} from '@mattermost/types/users';
|
import type {UserProfile} from '@mattermost/types/users';
|
||||||
|
|
||||||
import type {ActionResult} from 'mattermost-redux/types/actions';
|
import type {ActionResult} from 'mattermost-redux/types/actions';
|
||||||
|
|
||||||
import store from 'stores/redux_store';
|
|
||||||
|
|
||||||
import ConfirmModal from 'components/confirm_modal';
|
import ConfirmModal from 'components/confirm_modal';
|
||||||
|
import SettingsSidebar from 'components/settings_sidebar';
|
||||||
|
import UserSettings from 'components/user_settings';
|
||||||
|
|
||||||
import Constants from 'utils/constants';
|
import Constants from 'utils/constants';
|
||||||
import * as Keyboard from 'utils/keyboard';
|
import {cmdOrCtrlPressed, isKeyPressed} from 'utils/keyboard';
|
||||||
import * as NotificationSounds from 'utils/notification_sounds';
|
import {stopTryNotificationRing} from 'utils/notification_sounds';
|
||||||
import * as Utils from 'utils/utils';
|
|
||||||
|
|
||||||
import type {PluginConfiguration} from 'types/plugins/user_settings';
|
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 = {
|
export type Props = {
|
||||||
currentUser: UserProfile;
|
currentUser: UserProfile;
|
||||||
onExited: () => void;
|
onExited: () => void;
|
||||||
@ -150,7 +98,7 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown = (e: KeyboardEvent) => {
|
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();
|
e.preventDefault();
|
||||||
this.handleHide();
|
this.handleHide();
|
||||||
}
|
}
|
||||||
@ -164,7 +112,7 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cancel any ongoing notification sound, if any (from DesktopNotificationSettings)
|
// Cancel any ongoing notification sound, if any (from DesktopNotificationSettings)
|
||||||
NotificationSounds.stopTryNotificationRing();
|
stopTryNotificationRing();
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
show: false,
|
show: false,
|
||||||
@ -270,30 +218,68 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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() {
|
render() {
|
||||||
const {formatMessage} = this.props.intl;
|
const {formatMessage} = this.props.intl;
|
||||||
if (this.props.currentUser == null) {
|
if (this.props.currentUser == null) {
|
||||||
return (<div/>);
|
return (<div/>);
|
||||||
}
|
}
|
||||||
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',
|
id: 'global_header.productSettings',
|
||||||
defaultMessage: 'Settings',
|
defaultMessage: 'Settings',
|
||||||
}) : formatMessage({
|
}) : formatMessage({
|
||||||
@ -310,7 +296,7 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
|
|||||||
onExited={this.handleHidden}
|
onExited={this.handleHidden}
|
||||||
enforceFocus={this.state.enforceFocus}
|
enforceFocus={this.state.enforceFocus}
|
||||||
role='dialog'
|
role='dialog'
|
||||||
aria-label={title}
|
aria-label={modalTitle}
|
||||||
>
|
>
|
||||||
<Modal.Header
|
<Modal.Header
|
||||||
id='accountSettingsHeader'
|
id='accountSettingsHeader'
|
||||||
@ -320,52 +306,47 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
|
|||||||
componentClass='h1'
|
componentClass='h1'
|
||||||
id='accountSettingsModalLabel'
|
id='accountSettingsModalLabel'
|
||||||
>
|
>
|
||||||
{title}
|
{modalTitle}
|
||||||
</Modal.Title>
|
</Modal.Title>
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body ref={this.modalBodyRef}>
|
<Modal.Body ref={this.modalBodyRef}>
|
||||||
<div className='settings-table'>
|
<div className='settings-table'>
|
||||||
<div className='settings-links'>
|
<div className='settings-links'>
|
||||||
<React.Suspense fallback={null}>
|
<SettingsSidebar
|
||||||
<Provider store={store}>
|
tabs={this.props.isContentProductSettings ? this.getUserSettingsTabs() : this.getProfileSettingsTab()}
|
||||||
<SettingsSidebar
|
pluginTabs={this.props.isContentProductSettings ? this.getPluginsSettingsTab() : []}
|
||||||
tabs={tabs}
|
activeTab={this.state.active_tab}
|
||||||
pluginTabs={pluginTabs}
|
updateTab={this.updateTab}
|
||||||
activeTab={this.state.active_tab}
|
/>
|
||||||
updateTab={this.updateTab}
|
|
||||||
/>
|
|
||||||
</Provider>
|
|
||||||
</React.Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='settings-content minimize-settings'>
|
<div className='settings-content minimize-settings'>
|
||||||
<React.Suspense fallback={null}>
|
<UserSettings
|
||||||
<Provider store={store}>
|
activeTab={this.state.active_tab}
|
||||||
<UserSettings
|
activeSection={this.state.active_section}
|
||||||
activeTab={this.state.active_tab}
|
updateSection={this.updateSection}
|
||||||
activeSection={this.state.active_section}
|
updateTab={this.updateTab}
|
||||||
updateSection={this.updateSection}
|
closeModal={this.closeModal}
|
||||||
updateTab={this.updateTab}
|
collapseModal={this.collapseModal}
|
||||||
closeModal={this.closeModal}
|
setEnforceFocus={(enforceFocus?: boolean) => this.setState({enforceFocus})}
|
||||||
collapseModal={this.collapseModal}
|
setRequireConfirm={
|
||||||
setEnforceFocus={(enforceFocus?: boolean) => this.setState({enforceFocus})}
|
(requireConfirm?: boolean, customConfirmAction?: () => () => void) => {
|
||||||
setRequireConfirm={
|
this.requireConfirm = requireConfirm!;
|
||||||
(requireConfirm?: boolean, customConfirmAction?: () => () => void) => {
|
this.customConfirmAction = customConfirmAction!;
|
||||||
this.requireConfirm = requireConfirm!;
|
}
|
||||||
this.customConfirmAction = customConfirmAction!;
|
}
|
||||||
}
|
pluginSettings={this.props.pluginSettings}
|
||||||
}
|
user={this.props.currentUser}
|
||||||
pluginSettings={this.props.pluginSettings}
|
/>
|
||||||
user={this.props.currentUser}
|
|
||||||
/>
|
|
||||||
</Provider>
|
|
||||||
</React.Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
title={formatMessage(holders.confirmTitle)}
|
title={formatMessage({id: 'user.settings.modal.confirmTitle', defaultMessage: 'Discard Changes?'})}
|
||||||
message={formatMessage(holders.confirmMsg)}
|
message={formatMessage({
|
||||||
confirmButtonText={formatMessage(holders.confirmBtns)}
|
id: 'user.settings.modal.confirmMsg',
|
||||||
|
defaultMessage: 'You have unsaved changes, are you sure you want to discard them?',
|
||||||
|
})}
|
||||||
|
confirmButtonText={formatMessage({id: 'user.settings.modal.confirmBtns', defaultMessage: 'Yes, Discard'})}
|
||||||
show={this.state.showConfirmModal}
|
show={this.state.showConfirmModal}
|
||||||
onConfirm={this.handleConfirm}
|
onConfirm={this.handleConfirm}
|
||||||
onCancel={this.handleCancelConfirmation}
|
onCancel={this.handleCancelConfirmation}
|
||||||
|
@ -5561,7 +5561,6 @@
|
|||||||
"user.settings.display.theme.title": "Theme",
|
"user.settings.display.theme.title": "Theme",
|
||||||
"user.settings.display.timezone": "Timezone",
|
"user.settings.display.timezone": "Timezone",
|
||||||
"user.settings.display.title": "Display Settings",
|
"user.settings.display.title": "Display Settings",
|
||||||
"user.settings.general.checkEmail": "Check your email at {email} to verify the address. Cannot find the email?",
|
|
||||||
"user.settings.general.close": "Close",
|
"user.settings.general.close": "Close",
|
||||||
"user.settings.general.confirmEmail": "Confirm Email",
|
"user.settings.general.confirmEmail": "Confirm Email",
|
||||||
"user.settings.general.currentEmail": "Current Email",
|
"user.settings.general.currentEmail": "Current Email",
|
||||||
|
Loading…
Reference in New Issue
Block a user