diff --git a/app/mm-redux/types/users.ts b/app/mm-redux/types/users.ts
index b1e8fda43..5051548ee 100644
--- a/app/mm-redux/types/users.ts
+++ b/app/mm-redux/types/users.ts
@@ -5,7 +5,10 @@ import {Team} from './teams';
import {PostType} from './posts';
import {$ID, IDMappedObjects, RelationOneToMany, RelationOneToOne} from './utilities';
export type UserNotifyProps = {
+ auto_responder_active?: 'true' | 'false';
+ auto_responder_message?: string;
desktop: 'default' | 'all' | 'mention' | 'none';
+ desktop_notification_sound?: string;
desktop_sound: 'true' | 'false';
email: 'true' | 'false';
mark_unread: 'all' | 'mention';
@@ -15,6 +18,7 @@ export type UserNotifyProps = {
first_name: 'true' | 'false';
channel: 'true' | 'false';
mention_keys: string;
+ user_id?: string;
};
export type UserProfile = {
id: string;
diff --git a/app/screens/settings/notification_settings/__snapshots__/notification_settings.test.js.snap b/app/screens/settings/notification_settings/__snapshots__/notification_settings.test.js.snap
index 02f5fdf22..936af58cb 100644
--- a/app/screens/settings/notification_settings/__snapshots__/notification_settings.test.js.snap
+++ b/app/screens/settings/notification_settings/__snapshots__/notification_settings.test.js.snap
@@ -99,6 +99,7 @@ NotificationSettings {
"updateMeRequest": Object {},
},
"refs": Object {},
+ "sanitizeNotificationProps": [Function],
"saveAutoResponder": [Function],
"saveNotificationProps": [Function],
"setState": [Function],
diff --git a/app/screens/settings/notification_settings/notification_settings.js b/app/screens/settings/notification_settings/notification_settings.js
index e7ac2b59b..ad1b4ffe7 100644
--- a/app/screens/settings/notification_settings/notification_settings.js
+++ b/app/screens/settings/notification_settings/notification_settings.js
@@ -127,6 +127,22 @@ export default class NotificationSettings extends PureComponent {
});
};
+ saveAutoResponder = (notifyProps) => {
+ const {intl} = this.context;
+
+ if (!notifyProps.auto_responder_message) {
+ notifyProps.auto_responder_message = intl.formatMessage({
+ id: 'mobile.notification_settings.auto_responder.default_message',
+ defaultMessage: 'Hello, I am out of office and unable to respond to messages.',
+ });
+ }
+
+ if (this.shouldSaveAutoResponder(notifyProps)) {
+ const notify_props = this.sanitizeNotificationProps(notifyProps);
+ this.props.actions.updateMe({notify_props});
+ }
+ };
+
saveNotificationProps = (notifyProps) => {
const {currentUser} = this.props;
const prevProps = getNotificationProps(currentUser);
@@ -136,10 +152,22 @@ export default class NotificationSettings extends PureComponent {
};
if (!deepEqual(prevProps, notifyProps)) {
- this.props.actions.updateMe({notify_props: updatedProps});
+ const notify_props = this.sanitizeNotificationProps(updatedProps);
+ this.props.actions.updateMe({notify_props});
}
};
+ sanitizeNotificationProps = (notifyProps) => {
+ const sanitized = {...notifyProps};
+ Reflect.deleteProperty(sanitized, 'showKeywordsModal');
+ Reflect.deleteProperty(sanitized, 'showReplyModal');
+ Reflect.deleteProperty(sanitized, 'androidKeywords');
+ Reflect.deleteProperty(sanitized, 'newReplyValue');
+ Reflect.deleteProperty(sanitized, 'user_id');
+
+ return sanitized;
+ }
+
/**
* shouldSaveAutoResponder
*
@@ -150,28 +178,15 @@ export default class NotificationSettings extends PureComponent {
* for some reason the update does not get received on mobile, it does for web
*/
shouldSaveAutoResponder = (notifyProps) => {
- const {currentUserStatus} = this.props;
+ const {currentUser, currentUserStatus} = this.props;
const {auto_responder_active: autoResponderActive} = notifyProps;
+ const prevProps = getNotificationProps(currentUser);
const enabling = currentUserStatus !== General.OUT_OF_OFFICE && autoResponderActive === 'true';
const disabling = currentUserStatus === General.OUT_OF_OFFICE && autoResponderActive === 'false';
+ const updatedMsg = prevProps.auto_responder_message !== notifyProps.auto_responder_message;
- return enabling || disabling;
- };
-
- saveAutoResponder = (notifyProps) => {
- const {intl} = this.context;
-
- if (!notifyProps.auto_responder_message || notifyProps.auto_responder_message === '') {
- notifyProps.auto_responder_message = intl.formatMessage({
- id: 'mobile.notification_settings.auto_responder.default_message',
- defaultMessage: 'Hello, I am out of office and unable to respond to messages.',
- });
- }
-
- if (this.shouldSaveAutoResponder(notifyProps)) {
- this.props.actions.updateMe({notify_props: notifyProps});
- }
+ return enabling || disabling || updatedMsg;
};
render() {
diff --git a/app/screens/settings/notification_settings_auto_responder/index.js b/app/screens/settings/notification_settings_auto_responder/index.ts
similarity index 87%
rename from app/screens/settings/notification_settings_auto_responder/index.js
rename to app/screens/settings/notification_settings_auto_responder/index.ts
index 48ef14232..db03f34a2 100644
--- a/app/screens/settings/notification_settings_auto_responder/index.js
+++ b/app/screens/settings/notification_settings_auto_responder/index.ts
@@ -5,9 +5,10 @@ import {connect} from 'react-redux';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {getCurrentUserId, getStatusForUserId} from '@mm-redux/selectors/entities/users';
+import {GlobalState} from '@mm-redux/types/store';
import NotificationSettingsAutoResponder from './notification_settings_auto_responder';
-function mapStateToProps(state) {
+function mapStateToProps(state: GlobalState) {
const currentUserId = getCurrentUserId(state);
const currentUserStatus = getStatusForUserId(state, currentUserId);
diff --git a/app/screens/settings/notification_settings_auto_responder/notification_settings_auto_responder.js b/app/screens/settings/notification_settings_auto_responder/notification_settings_auto_responder.js
deleted file mode 100644
index c8a7ee35a..000000000
--- a/app/screens/settings/notification_settings_auto_responder/notification_settings_auto_responder.js
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-import React, {PureComponent} from 'react';
-import PropTypes from 'prop-types';
-
-import {
- View,
-} from 'react-native';
-import {intlShape} from 'react-intl';
-import {SafeAreaView} from 'react-native-safe-area-context';
-
-import {General} from '@mm-redux/constants';
-import FormattedText from 'app/components/formatted_text';
-import StatusBar from 'app/components/status_bar';
-import TextInputWithLocalizedPlaceholder from 'app/components/text_input_with_localized_placeholder';
-import {getNotificationProps} from 'app/utils/notify_props';
-import {
- changeOpacity,
- makeStyleSheetFromTheme,
- getKeyboardAppearanceFromTheme,
-} from 'app/utils/theme';
-import {t} from 'app/utils/i18n';
-
-import Section from 'app/screens/settings/section';
-import SectionItem from 'app/screens/settings/section_item';
-
-export default class NotificationSettingsAutoResponder extends PureComponent {
- static propTypes = {
- currentUser: PropTypes.object.isRequired,
- onBack: PropTypes.func.isRequired,
- theme: PropTypes.object.isRequired,
- currentUserStatus: PropTypes.string.isRequired,
- };
-
- static contextTypes = {
- intl: intlShape,
- };
-
- constructor(props, context) {
- super(props, context);
- const {currentUser} = props;
- const {intl} = this.context;
- const notifyProps = getNotificationProps(currentUser);
-
- this.autoresponderRef = React.createRef();
-
- const autoResponderDefault = intl.formatMessage({
- id: 'mobile.notification_settings.auto_responder.default_message',
- defaultMessage: 'Hello, I am out of office and unable to respond to messages.',
- });
-
- let autoResponderActive = 'false';
- if (props.currentUserStatus === General.OUT_OF_OFFICE && notifyProps.auto_responder_active) {
- autoResponderActive = 'true';
- }
-
- this.state = {
- ...notifyProps,
- auto_responder_active: autoResponderActive,
- auto_responder_message: notifyProps.auto_responder_message || autoResponderDefault,
- };
- }
-
- componentWillUnmount() {
- this.saveUserNotifyProps();
- }
-
- componentDidMount() {
- setTimeout(() => {
- requestAnimationFrame(() => {
- if (this.autoresponderRef.current) {
- this.autoresponderRef.current.focus();
- }
- });
- }, 500);
- }
-
- saveUserNotifyProps = () => {
- this.props.onBack({
- ...this.state,
- user_id: this.props.currentUser.id,
- });
- };
-
- onAutoResponseToggle = (active) => {
- if (active) {
- this.setState({auto_responder_active: 'true'});
- return;
- }
- this.setState({auto_responder_active: 'false'});
- };
-
- onAutoResponseChangeText = (message) => {
- this.setState({auto_responder_message: message});
- };
-
- render() {
- const {theme} = this.props;
- const {
- auto_responder_active: autoResponderActive,
- auto_responder_message: autoResponderMessage,
- } = this.state;
- const style = getStyleSheet(theme);
-
- const autoResponderActiveLabel = (
-
- );
-
- return (
-
-
-
-
- {autoResponderActive === 'true' && (
-
- )}
-
-
-
- );
- }
-}
-
-const getStyleSheet = makeStyleSheetFromTheme((theme) => {
- return {
- container: {
- flex: 1,
- backgroundColor: theme.centerChannelBg,
- },
- wrapper: {
- backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
- flex: 1,
- paddingTop: 35,
- },
- inputContainer: {
- borderTopWidth: 1,
- borderBottomWidth: 1,
- borderTopColor: changeOpacity(theme.centerChannelColor, 0.1),
- borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1),
- backgroundColor: theme.centerChannelBg,
- },
- input: {
- color: theme.centerChannelColor,
- fontSize: 15,
- height: 150,
- paddingHorizontal: 15,
- paddingVertical: 10,
- },
- footer: {
- marginHorizontal: 15,
- fontSize: 12,
- color: changeOpacity(theme.centerChannelColor, 0.5),
- },
- };
-});
diff --git a/app/screens/settings/notification_settings_auto_responder/notification_settings_auto_responder.tsx b/app/screens/settings/notification_settings_auto_responder/notification_settings_auto_responder.tsx
new file mode 100644
index 000000000..e920d52ff
--- /dev/null
+++ b/app/screens/settings/notification_settings_auto_responder/notification_settings_auto_responder.tsx
@@ -0,0 +1,186 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {useEffect, useRef, useState} from 'react';
+
+import {View} from 'react-native';
+import {intlShape, injectIntl} from 'react-intl';
+import {SafeAreaView} from 'react-native-safe-area-context';
+
+import {popTopScreen} from '@actions/navigation';
+import FormattedText from '@components/formatted_text';
+import StatusBar from '@components/status_bar';
+import TextInputWithLocalizedPlaceholder from '@components/text_input_with_localized_placeholder';
+import {General} from '@mm-redux/constants';
+import Section from '@screens/settings/section';
+import SectionItem from '@screens/settings/section_item';
+import {t} from '@utils/i18n';
+import {getNotificationProps} from '@utils/notify_props';
+import {
+ changeOpacity,
+ makeStyleSheetFromTheme,
+ getKeyboardAppearanceFromTheme,
+} from '@utils/theme';
+import {UserNotifyProps, UserProfile} from '@mm-redux/types/users';
+import {Theme} from '@mm-redux/types/preferences';
+
+interface NotificationSettingsAutoResponderProps {
+ currentUser: UserProfile;
+ currentUserStatus: string;
+ intl: typeof intlShape;
+ onBack: (notifyProps: UserNotifyProps) => void;
+ theme: Theme;
+}
+
+const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
+ return {
+ container: {
+ flex: 1,
+ backgroundColor: theme.centerChannelBg,
+ },
+ wrapper: {
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
+ flex: 1,
+ paddingTop: 35,
+ },
+ inputContainer: {
+ borderTopWidth: 1,
+ borderBottomWidth: 1,
+ borderTopColor: changeOpacity(theme.centerChannelColor, 0.1),
+ borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1),
+ backgroundColor: theme.centerChannelBg,
+ },
+ input: {
+ color: theme.centerChannelColor,
+ fontSize: 15,
+ height: 150,
+ paddingHorizontal: 15,
+ paddingVertical: 10,
+ },
+ footer: {
+ marginHorizontal: 15,
+ fontSize: 12,
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ },
+ };
+});
+
+const NotificationSettingsAutoResponder = ({currentUser, currentUserStatus, intl, onBack, theme} : NotificationSettingsAutoResponderProps) => {
+ const autoresponderRef = useRef(null);
+ const [notifyProps, setNotifyProps] = useState(getNotificationProps(currentUser));
+ const style = getStyleSheet(theme);
+
+ const onAutoResponseToggle = (active: boolean) => {
+ setNotifyProps({
+ ...notifyProps,
+ auto_responder_active: active ? 'true' : 'false',
+ });
+ };
+
+ const onAutoResponseChangeText = (message: string) => {
+ setNotifyProps({
+ ...notifyProps,
+ auto_responder_message: message,
+ });
+ };
+
+ const onSubmitEditing = () => {
+ popTopScreen();
+ };
+
+ useEffect(() => {
+ const autoResponderDefault = intl.formatMessage({
+ id: 'mobile.notification_settings.auto_responder.default_message',
+ defaultMessage: 'Hello, I am out of office and unable to respond to messages.',
+ });
+
+ setNotifyProps({
+ ...notifyProps,
+ auto_responder_active: (currentUserStatus === General.OUT_OF_OFFICE && notifyProps.auto_responder_active) ? 'true' : 'false',
+ auto_responder_message: notifyProps.auto_responder_message || autoResponderDefault,
+ });
+ }, []);
+
+ useEffect(() => {
+ const autoresponderTimeout = setTimeout(() => {
+ autoresponderRef.current?.focus();
+ }, 500);
+
+ return () => {
+ clearTimeout(autoresponderTimeout);
+
+ onBack({
+ ...notifyProps,
+ user_id: currentUser.id,
+ });
+ };
+ }, [notifyProps]);
+
+ const autoResponderActiveLabel = (
+
+ );
+ const {
+ auto_responder_active: autoResponderActive,
+ auto_responder_message: autoResponderMessage,
+ } = notifyProps;
+
+ return (
+
+
+
+
+ {autoResponderActive === 'true' && (
+
+ )}
+
+
+
+ );
+};
+
+export default injectIntl(NotificationSettingsAutoResponder);
diff --git a/app/screens/settings/notification_settings_mentions/notification_settings_mention_base.js b/app/screens/settings/notification_settings_mentions/notification_settings_mention_base.js
index 7d8c6e20d..dc15f8526 100644
--- a/app/screens/settings/notification_settings_mentions/notification_settings_mention_base.js
+++ b/app/screens/settings/notification_settings_mentions/notification_settings_mention_base.js
@@ -111,8 +111,6 @@ export default class NotificationSettingsMentionsBase extends PureComponent {
}
mentionKeys = mentionKeys.join(',');
- Reflect.deleteProperty(notifyProps, 'showKeywordsModal');
- Reflect.deleteProperty(notifyProps, 'showReplyModal');
this.props.onBack({
...notifyProps,