diff --git a/app/components/radio_button/radio_button_group.js b/app/components/radio_button/radio_button_group.js
index 92728608b..b7dd3bda2 100644
--- a/app/components/radio_button/radio_button_group.js
+++ b/app/components/radio_button/radio_button_group.js
@@ -17,34 +17,30 @@ export default class RadioButtonGroup extends PureComponent {
options: []
};
- state = {};
-
constructor(props) {
super(props);
- this.selected = null;
- if (this.props.options.length) {
- this.props.options.forEach((option) => {
- const {
- value,
- checked,
- } = option;
+ this.state = {
+ selected: this.getSelectedValue(props.options),
+ };
+ }
- if (!this.state.selected && checked) {
- this.selected = value;
- }
- });
+ componentWillReceiveProps(nextProps) {
+ if (this.props.options !== nextProps.options) {
+ this.setState({selected: this.getSelectedValue(nextProps.options)});
+ }
+ }
+
+ getSelectedValue = (options = []) => {
+ let selected;
+ for (const option in options) {
+ if (option.checked) {
+ selected = option.value;
+ break;
+ }
}
- this.state = {selected: this.selected};
- }
-
- get value() {
- return this.state.selected;
- }
-
- set value(value) {
- this.onChange(value);
+ return selected;
}
onChange = (value) => {
@@ -81,7 +77,7 @@ export default class RadioButtonGroup extends PureComponent {
label={label}
disabled={disabled}
onCheck={this.onChange}
- checked={this.state.selected && value === this.state.selected}
+ checked={option.checked}
/>
);
});
diff --git a/app/screens/settings/notification_settings/notification_settings.js b/app/screens/settings/notification_settings/notification_settings.js
index 4b3a5ad90..fe0c5c634 100644
--- a/app/screens/settings/notification_settings/notification_settings.js
+++ b/app/screens/settings/notification_settings/notification_settings.js
@@ -6,19 +6,14 @@ import PropTypes from 'prop-types';
import {injectIntl, intlShape} from 'react-intl';
import {
Alert,
- Modal,
Platform,
ScrollView,
- TouchableOpacity,
View,
} from 'react-native';
import deepEqual from 'deep-equal';
-import {General, Preferences, RequestStatus} from 'mattermost-redux/constants';
-import {getPreferencesByCategory} from 'mattermost-redux/utils/preference_utils';
+import {General, RequestStatus} from 'mattermost-redux/constants';
-import FormattedText from 'app/components/formatted_text';
-import RadioButtonGroup from 'app/components/radio_button';
import StatusBar from 'app/components/status_bar';
import NotificationPreferences from 'app/notification_preferences';
import SettingsItem from 'app/screens/settings/settings_item';
@@ -31,10 +26,8 @@ class NotificationSettings extends PureComponent {
actions: PropTypes.shape({
handleUpdateUserNotifyProps: PropTypes.func.isRequired,
}),
- config: PropTypes.object.isRequired,
currentUser: PropTypes.object.isRequired,
intl: intlShape.isRequired,
- myPreferences: PropTypes.object.isRequired,
navigator: PropTypes.object,
theme: PropTypes.object.isRequired,
updateMeRequest: PropTypes.object.isRequired,
@@ -42,10 +35,6 @@ class NotificationSettings extends PureComponent {
enableAutoResponder: PropTypes.bool.isRequired,
};
- state = {
- showEmailNotificationsModal: false,
- };
-
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
@@ -94,30 +83,25 @@ class NotificationSettings extends PureComponent {
};
goToNotificationSettingsEmail = () => {
- if (Platform.OS === 'ios') {
- const {currentUser, intl, navigator, theme} = this.props;
- navigator.push({
- backButtonTitle: '',
- screen: 'NotificationSettingsEmail',
- title: intl.formatMessage({
- id: 'mobile.notification_settings.email_title',
- defaultMessage: 'Email Notifications',
- }),
- animated: true,
- navigatorStyle: {
- navBarTextColor: theme.sidebarHeaderTextColor,
- navBarBackgroundColor: theme.sidebarHeaderBg,
- navBarButtonColor: theme.sidebarHeaderTextColor,
- screenBackgroundColor: theme.centerChannelBg,
- },
- passProps: {
- currentUser,
- onBack: this.saveNotificationProps,
- },
- });
- } else {
- this.setState({showEmailNotificationsModal: true});
- }
+ const {currentUser, intl, navigator, theme} = this.props;
+ navigator.push({
+ backButtonTitle: '',
+ screen: 'NotificationSettingsEmail',
+ title: intl.formatMessage({
+ id: 'mobile.notification_settings.email_title',
+ defaultMessage: 'Email Notifications',
+ }),
+ animated: true,
+ navigatorStyle: {
+ navBarTextColor: theme.sidebarHeaderTextColor,
+ navBarBackgroundColor: theme.sidebarHeaderBg,
+ navBarButtonColor: theme.sidebarHeaderTextColor,
+ screenBackgroundColor: theme.centerChannelBg,
+ },
+ passProps: {
+ currentUserId: currentUser.id,
+ },
+ });
};
goToNotificationSettingsMentions = () => {
@@ -168,34 +152,6 @@ class NotificationSettings extends PureComponent {
});
};
- setEmailNotifications = (emailSetting) => {
- this.setState({emailSetting});
- };
-
- saveEmailNotifications = () => {
- const {config, currentUser} = this.props;
- const {emailSetting} = this.state;
-
- this.setState({showEmailNotificationsModal: false});
-
- if (emailSetting) {
- let email = emailSetting;
- let interval;
-
- const emailBatchingEnabled = config.EnableEmailBatching === 'true';
- if (emailBatchingEnabled && emailSetting !== 'false') {
- interval = emailSetting;
- email = 'true';
- }
-
- this.saveNotificationProps({
- ...getNotificationProps(currentUser),
- email,
- interval,
- });
- }
- };
-
saveNotificationProps = (notifyProps) => {
const {currentUser} = this.props;
const {user_id: userId} = notifyProps;
@@ -204,10 +160,6 @@ class NotificationSettings extends PureComponent {
user_id: userId,
};
- if (notifyProps.interval) {
- previousProps.interval = notifyProps.interval;
- }
-
if (!deepEqual(previousProps, notifyProps)) {
this.props.actions.handleUpdateUserNotifyProps(notifyProps);
}
@@ -247,154 +199,6 @@ class NotificationSettings extends PureComponent {
}
};
- renderEmailNotificationSettings = (style) => {
- if (Platform.OS === 'ios') {
- return null;
- }
-
- const {config, currentUser, intl, myPreferences} = this.props;
- const notifyProps = getNotificationProps(currentUser);
- const sendEmailNotifications = config.SendEmailNotifications === 'true';
- const emailBatchingEnabled = sendEmailNotifications && config.EnableEmailBatching === 'true';
-
- const never = notifyProps.email === 'false';
- let sendImmediatley = notifyProps.email === 'true';
- let sendImmediatleyValue = 'true';
- let fifteenMinutes;
- let hourly;
- let interval;
-
- if (emailBatchingEnabled) {
- const emailPreferences = getPreferencesByCategory(myPreferences, Preferences.CATEGORY_NOTIFICATIONS);
- if (emailPreferences.size) {
- interval = emailPreferences.get(Preferences.EMAIL_INTERVAL).value;
- }
- }
-
- if (emailBatchingEnabled && notifyProps.email !== 'false') {
- sendImmediatley = interval === Preferences.INTERVAL_IMMEDIATE.toString();
- fifteenMinutes = interval === Preferences.INTERVAL_FIFTEEN_MINUTES.toString();
- hourly = interval === Preferences.INTERVAL_HOUR.toString();
- sendImmediatleyValue = Preferences.INTERVAL_IMMEDIATE.toString();
- }
-
- let helpText;
- if (sendEmailNotifications) {
- helpText = (
-
- );
- }
-
- const emailOptions = [{
- label: intl.formatMessage({
- id: 'user.settings.notifications.email.immediately',
- defaultMessage: 'Immediately',
- }),
- value: sendImmediatleyValue,
- checked: sendImmediatley,
- }];
-
- if (emailBatchingEnabled) {
- emailOptions.push({
- label: intl.formatMessage({
- id: 'user.settings.notifications.email.everyXMinutes',
- defaultMessage: 'Every {count, plural, one {minute} other {{count, number} minutes}}',
- }, {count: Preferences.INTERVAL_FIFTEEN_MINUTES / 60}),
- value: Preferences.INTERVAL_FIFTEEN_MINUTES.toString(),
- checked: fifteenMinutes,
- }, {
- label: intl.formatMessage({
- id: 'user.settings.notifications.email.everyHour',
- defaultMessage: 'Every hour',
- }),
- value: Preferences.INTERVAL_HOUR.toString(),
- checked: hourly,
- });
- }
-
- emailOptions.push({
- label: intl.formatMessage({
- id: 'user.settings.notifications.email.never',
- defaultMessage: 'Never',
- }),
- value: 'false',
- checked: never,
- });
-
- return (
- this.setState({showEmailNotificationsModal: false})}
- >
-
-
-
-
-
-
- {!sendEmailNotifications &&
-
- }
- {sendEmailNotifications &&
-
- }
- {helpText}
-
-
-
-
-
-
-
- {sendEmailNotifications &&
-
-
-
-
-
-
- }
-
-
-
-
-
- );
- };
-
render() {
const {theme, enableAutoResponder} = this.props;
const style = getStyleSheet(theme);
@@ -458,7 +262,6 @@ class NotificationSettings extends PureComponent {
{autoResponder}
- {this.renderEmailNotificationSettings(style)}
);
}
@@ -483,60 +286,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
height: 1,
width: '100%',
},
- modalOverlay: {
- backgroundColor: changeOpacity('#000000', 0.6),
- alignItems: 'center',
- flex: 1,
- },
- modal: {
- backgroundColor: theme.centerChannelBg,
- borderRadius: 4,
- marginTop: 20,
- width: '95%',
- },
- modalBody: {
- paddingHorizontal: 24,
- },
- modalTitleContainer: {
- marginBottom: 30,
- marginTop: 20,
- },
- modalTitle: {
- color: theme.centerChannelColor,
- fontSize: 19,
- },
- modalOptionDisabled: {
- color: changeOpacity(theme.centerChannelColor, 0.5),
- fontSize: 17,
- },
- modalHelpText: {
- color: changeOpacity(theme.centerChannelColor, 0.5),
- fontSize: 13,
- marginTop: 20,
- },
- modalFooter: {
- alignItems: 'flex-end',
- height: 58,
- marginTop: 40,
- width: '100%',
- },
- modalFooterContainer: {
- alignItems: 'center',
- flex: 1,
- flexDirection: 'row',
- paddingRight: 24,
- },
- modalFooterOptionContainer: {
- alignItems: 'center',
- height: 40,
- justifyContent: 'center',
- paddingHorizontal: 10,
- paddingVertical: 5,
- },
- modalFooterOption: {
- color: theme.linkColor,
- fontSize: 14,
- },
};
});
diff --git a/app/screens/settings/notification_settings_email/__snapshots__/notification_settings_email.android.test.js.snap b/app/screens/settings/notification_settings_email/__snapshots__/notification_settings_email.android.test.js.snap
new file mode 100644
index 000000000..5dd411882
--- /dev/null
+++ b/app/screens/settings/notification_settings_email/__snapshots__/notification_settings_email.android.test.js.snap
@@ -0,0 +1,128 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NotificationSettingsMobileAndroid should match snapshot 1`] = `
+
+ }
+ label={
+
+ }
+ theme={
+ Object {
+ "centerChannelBg": "#aaa",
+ "centerChannelColor": "#aaa",
+ }
+ }
+/>
+`;
+
+exports[`NotificationSettingsMobileAndroid should match snapshot 2`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/app/screens/settings/notification_settings_email/__snapshots__/notification_settings_email.ios.test.js.snap b/app/screens/settings/notification_settings_email/__snapshots__/notification_settings_email.ios.test.js.snap
new file mode 100644
index 000000000..2f1513e61
--- /dev/null
+++ b/app/screens/settings/notification_settings_email/__snapshots__/notification_settings_email.ios.test.js.snap
@@ -0,0 +1,71 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NotificationSettingsEmailIos should match snapshot, renderEmailSection 1`] = `
+
+
+
+ }
+ selected={true}
+ theme={
+ Object {
+ "centerChannelBg": "#aaa",
+ "centerChannelColor": "#aaa",
+ }
+ }
+ />
+
+
+ }
+ selected={false}
+ theme={
+ Object {
+ "centerChannelBg": "#aaa",
+ "centerChannelColor": "#aaa",
+ }
+ }
+ />
+
+
+`;
diff --git a/app/screens/settings/notification_settings_email/index.js b/app/screens/settings/notification_settings_email/index.js
index 6d50d6103..9a6a58b42 100644
--- a/app/screens/settings/notification_settings_email/index.js
+++ b/app/screens/settings/notification_settings_email/index.js
@@ -1,19 +1,47 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
+import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
+import {Preferences} from 'mattermost-redux/constants';
+
+import {savePreferences} from 'mattermost-redux/actions/preferences';
+
import {getConfig} from 'mattermost-redux/selectors/entities/general';
-import {getMyPreferences, getTheme} from 'mattermost-redux/selectors/entities/preferences';
+import {
+ get as getPreference,
+ getTheme,
+} from 'mattermost-redux/selectors/entities/preferences';
import NotificationSettingsEmail from './notification_settings_email';
function mapStateToProps(state) {
+ const config = getConfig(state);
+ const sendEmailNotifications = config.SendEmailNotifications === 'true';
+ const enableEmailBatching = config.EnableEmailBatching === 'true';
+ const emailInterval = getPreference(
+ state,
+ Preferences.CATEGORY_NOTIFICATIONS,
+ Preferences.EMAIL_INTERVAL,
+ Preferences.INTERVAL_NEVER
+ ).toString();
+
return {
- config: getConfig(state),
- myPreferences: getMyPreferences(state),
+ enableEmailBatching,
+ emailInterval,
+ sendEmailNotifications,
+ siteName: config.siteName || '',
theme: getTheme(state),
};
}
-export default connect(mapStateToProps)(NotificationSettingsEmail);
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ savePreferences,
+ }, dispatch),
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(NotificationSettingsEmail);
diff --git a/app/screens/settings/notification_settings_email/notification_settings_email.android.js b/app/screens/settings/notification_settings_email/notification_settings_email.android.js
new file mode 100644
index 000000000..3c30d77a3
--- /dev/null
+++ b/app/screens/settings/notification_settings_email/notification_settings_email.android.js
@@ -0,0 +1,321 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {intlShape} from 'react-intl';
+import {
+ Modal,
+ ScrollView,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+
+import {Preferences} from 'mattermost-redux/constants';
+
+import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
+
+import FormattedText from 'app/components/formatted_text';
+import RadioButtonGroup from 'app/components/radio_button';
+import SectionItem from 'app/screens/settings/section_item';
+
+import NotificationSettingsEmailBase from './notification_settings_email_base';
+
+class NotificationSettingsEmailAndroid extends NotificationSettingsEmailBase {
+ static contextTypes = {
+ intl: intlShape,
+ };
+
+ handleClose = () => {
+ this.setState({showEmailNotificationsModal: false});
+ }
+
+ handleSaveEmailNotification = () => {
+ this.saveEmailNotifyProps();
+ this.handleClose();
+ };
+
+ showEmailModal = () => {
+ this.setState({showEmailNotificationsModal: true});
+ };
+
+ renderEmailSection() {
+ const {
+ sendEmailNotifications,
+ theme,
+ } = this.props;
+ const {interval} = this.state;
+ let i18nId;
+ let i18nMessage;
+ if (sendEmailNotifications) {
+ switch (interval) {
+ case Preferences.INTERVAL_IMMEDIATE.toString():
+ i18nId = 'user.settings.notifications.email.immediately';
+ i18nMessage = 'Immediately';
+ break;
+ case Preferences.INTERVAL_HOUR.toString():
+ i18nId = 'user.settings.notifications.email.everyHour';
+ i18nMessage = 'Every hour';
+ break;
+ case Preferences.INTERVAL_FIFTEEN_MINUTES.toString():
+ i18nId = 'mobile.user.settings.notifications.email.fifteenMinutes';
+ i18nMessage = 'Every 15 minutes';
+ break;
+ case Preferences.INTERVAL_NEVER.toString():
+ default:
+ i18nId = 'user.settings.notifications.email.never';
+ i18nMessage = 'Never';
+ break;
+ }
+ } else {
+ i18nId = 'user.settings.notifications.email.disabled';
+ i18nMessage = 'Email notifications are not enabled';
+ }
+
+ return (
+
+ )}
+ label={(
+
+ )}
+ action={this.showEmailModal}
+ actionType='default'
+ theme={theme}
+ />
+ );
+ }
+
+ renderEmailNotificationsModal(style) {
+ const {intl} = this.context;
+ const {
+ enableEmailBatching,
+ sendEmailNotifications,
+ siteName,
+ } = this.props;
+ const {interval} = this.state;
+
+ let helpText;
+ if (sendEmailNotifications) {
+ helpText = (
+
+ );
+ }
+
+ const emailOptions = [{
+ label: intl.formatMessage({
+ id: 'user.settings.notifications.email.immediately',
+ defaultMessage: 'Immediately',
+ }),
+ value: Preferences.INTERVAL_IMMEDIATE.toString(),
+ checked: interval === Preferences.INTERVAL_IMMEDIATE.toString(),
+ }];
+
+ if (enableEmailBatching) {
+ emailOptions.push({
+ label: intl.formatMessage({
+ id: 'mobile.user.settings.notifications.email.fifteenMinutes',
+ defaultMessage: 'Every 15 minutes',
+ }),
+ value: Preferences.INTERVAL_FIFTEEN_MINUTES.toString(),
+ checked: interval === Preferences.INTERVAL_FIFTEEN_MINUTES.toString(),
+ }, {
+ label: intl.formatMessage({
+ id: 'user.settings.notifications.email.everyHour',
+ defaultMessage: 'Every hour',
+ }),
+ value: Preferences.INTERVAL_HOUR.toString(),
+ checked: interval === Preferences.INTERVAL_HOUR.toString(),
+ });
+ }
+
+ emailOptions.push({
+ label: intl.formatMessage({
+ id: 'user.settings.notifications.email.never',
+ defaultMessage: 'Never',
+ }),
+ value: Preferences.INTERVAL_NEVER.toString(),
+ checked: interval === Preferences.INTERVAL_NEVER.toString(),
+ });
+
+ return (
+
+
+
+
+
+
+
+ {!sendEmailNotifications &&
+
+ }
+ {sendEmailNotifications &&
+
+ }
+ {helpText}
+
+
+
+
+
+
+
+ {sendEmailNotifications &&
+
+
+
+
+
+
+ }
+
+
+
+
+
+ );
+ }
+
+ render() {
+ const {theme} = this.props;
+ const style = getStyleSheet(theme);
+
+ return (
+
+
+ {this.renderEmailSection()}
+
+ {this.renderEmailNotificationsModal(style)}
+
+
+ );
+ }
+}
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ container: {
+ flex: 1,
+ backgroundColor: theme.centerChannelBg,
+ },
+ separator: {
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
+ height: 1,
+ width: '100%',
+ },
+ divider: {
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
+ height: 1,
+ width: '100%',
+ },
+ scrollView: {
+ flex: 1,
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
+ },
+ scrollViewContent: {
+ paddingVertical: 0,
+ },
+ modalOverlay: {
+ backgroundColor: changeOpacity('#000000', 0.6),
+ alignItems: 'center',
+ flex: 1,
+ },
+ modal: {
+ backgroundColor: theme.centerChannelBg,
+ borderRadius: 4,
+ marginTop: 20,
+ width: '95%',
+ },
+ modalBody: {
+ paddingHorizontal: 24,
+ },
+ modalTitleContainer: {
+ marginBottom: 30,
+ marginTop: 20,
+ },
+ modalTitle: {
+ color: theme.centerChannelColor,
+ fontSize: 19,
+ },
+ modalOptionDisabled: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 17,
+ },
+ modalHelpText: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 13,
+ marginTop: 20,
+ },
+ modalFooter: {
+ alignItems: 'flex-end',
+ height: 58,
+ marginTop: 40,
+ width: '100%',
+ },
+ modalFooterContainer: {
+ alignItems: 'center',
+ flex: 1,
+ flexDirection: 'row',
+ paddingRight: 24,
+ },
+ modalFooterOptionContainer: {
+ alignItems: 'center',
+ height: 40,
+ justifyContent: 'center',
+ paddingHorizontal: 10,
+ paddingVertical: 5,
+ },
+ modalFooterOption: {
+ color: theme.linkColor,
+ fontSize: 14,
+ },
+ };
+});
+
+export default NotificationSettingsEmailAndroid;
diff --git a/app/screens/settings/notification_settings_email/notification_settings_email.android.test.js b/app/screens/settings/notification_settings_email/notification_settings_email.android.test.js
new file mode 100644
index 000000000..062f7ac24
--- /dev/null
+++ b/app/screens/settings/notification_settings_email/notification_settings_email.android.test.js
@@ -0,0 +1,102 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {configure} from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
+configure({adapter: new Adapter()});
+
+import {shallowWithIntl} from 'test/intl-test-helper';
+
+import NotificationSettingsMobileAndroid from './notification_settings_email.android.js';
+
+describe('NotificationSettingsMobileAndroid', () => {
+ const baseProps = {
+ currentUserId: 'current_user_id',
+ emailInterval: '30',
+ enableEmailBatching: false,
+ navigator: {setOnNavigatorEvent: () => {}}, // eslint-disable-line no-empty-function
+ actions: {
+ savePreferences: () => {}, // eslint-disable-line no-empty-function
+ },
+ sendEmailNotifications: true,
+ siteName: 'Mattermost',
+ theme: {
+ centerChannelBg: '#aaa',
+ centerChannelColor: '#aaa',
+ },
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallowWithIntl(
+
+ );
+
+ const style = {
+ divider: {},
+ modal: {},
+ modalBody: {},
+ modalTitleContainer: {},
+ modalTitle: {},
+ modalOptionDisabled: {},
+ modalHelpText: {},
+ modalFooter: {},
+ modalFooterContainer: {},
+ modalFooterOptionContainer: {},
+ modalFooterOption: {},
+ };
+
+ expect(wrapper.instance().renderEmailSection()).toMatchSnapshot();
+ expect(wrapper.instance().renderEmailNotificationsModal(style)).toMatchSnapshot();
+ });
+
+ test('should match state on setEmailNotifications', () => {
+ const wrapper = shallowWithIntl(
+
+ );
+
+ wrapper.setState({email: 'false', interval: '0'});
+ wrapper.instance().setEmailNotifications('30');
+ expect(wrapper.state({email: 'true', interval: '30'}));
+
+ wrapper.instance().setEmailNotifications('0');
+ expect(wrapper.state({email: 'false', interval: '0'}));
+
+ wrapper.instance().setEmailNotifications('3600');
+ expect(wrapper.state({email: 'true', interval: '3600'}));
+ });
+
+ test('should match state on handleClose', () => {
+ const wrapper = shallowWithIntl(
+
+ );
+
+ wrapper.setState({showEmailNotificationsModal: true});
+ wrapper.instance().handleClose();
+ expect(wrapper.state('showEmailNotificationsModal')).toEqual(false);
+ });
+
+ test('should saveEmailNotifyProps and handleClose on handleSaveEmailNotification', () => {
+ const wrapper = shallowWithIntl(
+
+ );
+
+ const instance = wrapper.instance();
+ instance.saveEmailNotifyProps = jest.fn();
+ instance.handleClose = jest.fn();
+
+ instance.handleSaveEmailNotification();
+ expect(instance.saveEmailNotifyProps).toHaveBeenCalledTimes(1);
+ expect(instance.handleClose).toHaveBeenCalledTimes(1);
+ });
+
+ test('should match state on showEmailModal', () => {
+ const wrapper = shallowWithIntl(
+
+ );
+
+ wrapper.setState({showEmailNotificationsModal: false});
+ wrapper.instance().showEmailModal();
+ expect(wrapper.state('showEmailNotificationsModal')).toEqual(true);
+ });
+});
diff --git a/app/screens/settings/notification_settings_email/notification_settings_email.js b/app/screens/settings/notification_settings_email/notification_settings_email.ios.js
similarity index 53%
rename from app/screens/settings/notification_settings_email/notification_settings_email.js
rename to app/screens/settings/notification_settings_email/notification_settings_email.ios.js
index e29778335..dccb96804 100644
--- a/app/screens/settings/notification_settings_email/notification_settings_email.js
+++ b/app/screens/settings/notification_settings_email/notification_settings_email.ios.js
@@ -1,8 +1,7 @@
// 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 React from 'react';
import {
ScrollView,
@@ -10,120 +9,34 @@ import {
} from 'react-native';
import {Preferences} from 'mattermost-redux/constants';
-import {getPreferencesByCategory} from 'mattermost-redux/utils/preference_utils';
import FormattedText from 'app/components/formatted_text';
import StatusBar from 'app/components/status_bar';
-import {getNotificationProps} from 'app/utils/notify_props';
-import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/utils/theme';
+import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import Section from 'app/screens/settings/section';
import SectionItem from 'app/screens/settings/section_item';
-export default class NotificationSettingsEmail extends PureComponent {
- static propTypes = {
- config: PropTypes.object.isRequired,
- currentUser: PropTypes.object.isRequired,
- myPreferences: PropTypes.object.isRequired,
- navigator: PropTypes.object,
- onBack: PropTypes.func.isRequired,
- theme: PropTypes.object.isRequired,
- };
+import NotificationSettingsEmailBase from './notification_settings_email_base';
- constructor(props) {
- super(props);
-
- const {currentUser} = props;
- const notifyProps = getNotificationProps(currentUser);
-
- props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
- this.state = this.setStateFromNotifyProps(notifyProps);
- }
-
- componentWillReceiveProps(nextProps) {
- if (this.props.theme !== nextProps.theme) {
- setNavigatorStyles(this.props.navigator, nextProps.theme);
- }
- }
-
- onNavigatorEvent = (event) => {
- if (event.type === 'ScreenChangedEvent') {
- switch (event.id) {
- case 'willDisappear':
- this.saveUserNotifyProps();
- break;
- }
- }
- };
-
- setEmailNotifications = (value) => {
- const {config} = this.props;
- let email = value;
- let interval;
-
- const emailBatchingEnabled = config.EnableEmailBatching === 'true';
- if (emailBatchingEnabled && value !== 'false') {
- interval = value;
- email = 'true';
- }
-
- this.setState({
- email,
- interval,
- });
- };
-
- setStateFromNotifyProps = (notifyProps) => {
- const {config, myPreferences} = this.props;
- let interval;
- if (config.SendEmailNotifications === 'true' && config.EnableEmailBatching === 'true') {
- const emailPreferences = getPreferencesByCategory(myPreferences, Preferences.CATEGORY_NOTIFICATIONS);
- if (emailPreferences.size) {
- interval = emailPreferences.get(Preferences.EMAIL_INTERVAL).value;
- }
- }
-
- return {
- ...notifyProps,
- interval,
- };
- };
-
- saveUserNotifyProps = () => {
- this.props.onBack({
- ...this.state,
- user_id: this.props.currentUser.id,
- });
- };
-
- renderEmailSection = () => {
- const {config, theme} = this.props;
+class NotificationSettingsEmailIos extends NotificationSettingsEmailBase {
+ renderEmailSection() {
+ const {
+ enableEmailBatching,
+ sendEmailNotifications,
+ siteName,
+ theme,
+ } = this.props;
+ const {interval} = this.state;
const style = getStyleSheet(theme);
- const sendEmailNotifications = config.SendEmailNotifications === 'true';
- const emailBatchingEnabled = sendEmailNotifications && config.EnableEmailBatching === 'true';
-
- let sendImmediatley = this.state.email === 'true';
- let sendImmediatleyValue = 'true';
- let fifteenMinutes;
- let hourly;
- const never = this.state.email === 'false';
-
- if (emailBatchingEnabled && this.state.email !== 'false') {
- sendImmediatley = this.state.interval === Preferences.INTERVAL_IMMEDIATE.toString();
- fifteenMinutes = this.state.interval === Preferences.INTERVAL_FIFTEEN_MINUTES.toString();
- hourly = this.state.interval === Preferences.INTERVAL_HOUR.toString();
-
- sendImmediatleyValue = Preferences.INTERVAL_IMMEDIATE.toString();
- }
-
return (
@@ -138,25 +51,24 @@ export default class NotificationSettingsEmail extends PureComponent {
)}
action={this.setEmailNotifications}
actionType='select'
- actionValue={sendImmediatleyValue}
- selected={sendImmediatley}
+ actionValue={Preferences.INTERVAL_IMMEDIATE.toString()}
+ selected={interval === Preferences.INTERVAL_IMMEDIATE.toString()}
theme={theme}
/>
- {emailBatchingEnabled &&
+ {enableEmailBatching &&
)}
action={this.setEmailNotifications}
actionType='select'
actionValue={Preferences.INTERVAL_FIFTEEN_MINUTES.toString()}
- selected={fifteenMinutes}
+ selected={interval === Preferences.INTERVAL_FIFTEEN_MINUTES.toString()}
theme={theme}
/>
@@ -170,7 +82,7 @@ export default class NotificationSettingsEmail extends PureComponent {
action={this.setEmailNotifications}
actionType='select'
actionValue={Preferences.INTERVAL_HOUR.toString()}
- selected={hourly}
+ selected={interval === Preferences.INTERVAL_HOUR.toString()}
theme={theme}
/>
@@ -185,8 +97,8 @@ export default class NotificationSettingsEmail extends PureComponent {
)}
action={this.setEmailNotifications}
actionType='select'
- actionValue='false'
- selected={never}
+ actionValue={Preferences.INTERVAL_NEVER.toString()}
+ selected={interval === Preferences.INTERVAL_NEVER.toString()}
theme={theme}
/>
@@ -200,7 +112,7 @@ export default class NotificationSettingsEmail extends PureComponent {
}
);
- };
+ }
render() {
const {theme} = this.props;
@@ -227,11 +139,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
flex: 1,
backgroundColor: theme.centerChannelBg,
},
- input: {
- color: theme.centerChannelColor,
- fontSize: 12,
- height: 40,
- },
separator: {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
flex: 1,
@@ -253,3 +160,5 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
};
});
+
+export default NotificationSettingsEmailIos;
diff --git a/app/screens/settings/notification_settings_email/notification_settings_email.ios.test.js b/app/screens/settings/notification_settings_email/notification_settings_email.ios.test.js
new file mode 100644
index 000000000..044bc5837
--- /dev/null
+++ b/app/screens/settings/notification_settings_email/notification_settings_email.ios.test.js
@@ -0,0 +1,89 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {configure, shallow} from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
+configure({adapter: new Adapter()});
+
+import NotificationSettingsEmailIos from './notification_settings_email.ios.js';
+
+jest.mock('app/utils/theme', () => {
+ const original = require.requireActual('app/utils/theme');
+ return {
+ ...original,
+ changeOpacity: jest.fn(),
+ };
+});
+
+describe('NotificationSettingsEmailIos', () => {
+ const baseProps = {
+ currentUserId: 'current_user_id',
+ emailInterval: '30',
+ enableEmailBatching: false,
+ navigator: {setOnNavigatorEvent: () => {}}, // eslint-disable-line no-empty-function
+ actions: {
+ savePreferences: () => {}, // eslint-disable-line no-empty-function
+ },
+ sendEmailNotifications: true,
+ siteName: 'Mattermost',
+ theme: {
+ centerChannelBg: '#aaa',
+ centerChannelColor: '#aaa',
+ },
+ };
+
+ test('should match snapshot, renderEmailSection', () => {
+ const wrapper = shallow(
+
+ );
+
+ expect(wrapper.instance().renderEmailSection()).toMatchSnapshot();
+ });
+
+ test('should call saveEmailNotifyProps on onNavigatorEvent', () => {
+ const wrapper = shallow(
+
+ );
+
+ const instance = wrapper.instance();
+ instance.saveEmailNotifyProps = jest.fn();
+ instance.onNavigatorEvent({type: 'ScreenChangedEvent', id: 'willDisappear'});
+
+ expect(instance.saveEmailNotifyProps).toHaveBeenCalledTimes(1);
+ });
+
+ test('should macth state on setEmailNotifications', () => {
+ const wrapper = shallow(
+
+ );
+
+ wrapper.setState({email: 'false', interval: '0'});
+ wrapper.instance().setEmailNotifications('30');
+ expect(wrapper.state({email: 'true', interval: '30'}));
+
+ wrapper.instance().setEmailNotifications('0');
+ expect(wrapper.state({email: 'false', interval: '0'}));
+
+ wrapper.instance().setEmailNotifications('3600');
+ expect(wrapper.state({email: 'true', interval: '3600'}));
+ });
+
+ test('should call props.actions.savePreferences on saveUserNotifyProps', () => {
+ const props = {...baseProps, actions: {savePreferences: jest.fn()}};
+ const wrapper = shallow(
+
+ );
+
+ wrapper.setState({email: 'true', interval: '3600'});
+ wrapper.instance().saveEmailNotifyProps();
+ expect(props.actions.savePreferences).toHaveBeenCalledTimes(1);
+ expect(props.actions.savePreferences).toBeCalledWith(
+ 'current_user_id',
+ [
+ {category: 'notifications', name: 'email', user_id: 'current_user_id', value: 'true'},
+ {category: 'notifications', name: 'email_interval', user_id: 'current_user_id', value: '3600'},
+ ]
+ );
+ });
+});
diff --git a/app/screens/settings/notification_settings_email/notification_settings_email_base.js b/app/screens/settings/notification_settings_email/notification_settings_email_base.js
new file mode 100644
index 000000000..7b9114080
--- /dev/null
+++ b/app/screens/settings/notification_settings_email/notification_settings_email_base.js
@@ -0,0 +1,99 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {PureComponent} from 'react';
+import PropTypes from 'prop-types';
+
+import {Preferences} from 'mattermost-redux/constants';
+import {getEmailInterval} from 'mattermost-redux/utils/notify_props';
+
+import {setNavigatorStyles} from 'app/utils/theme';
+
+export default class NotificationSettingsEmailBase extends PureComponent {
+ static propTypes = {
+ actions: PropTypes.shape({
+ savePreferences: PropTypes.func.isRequired,
+ }),
+ currentUserId: PropTypes.string.isRequired,
+ emailInterval: PropTypes.string.isRequired,
+ enableEmailBatching: PropTypes.bool.isRequired,
+ navigator: PropTypes.object,
+ sendEmailNotifications: PropTypes.bool.isRequired,
+ siteName: PropTypes.string,
+ theme: PropTypes.object.isRequired,
+ };
+
+ constructor(props) {
+ super(props);
+
+ const {
+ emailInterval,
+ enableEmailBatching,
+ navigator,
+ sendEmailNotifications,
+ } = props;
+
+ this.state = {
+ interval: getEmailInterval(
+ sendEmailNotifications,
+ enableEmailBatching,
+ parseInt(emailInterval, 10),
+ ).toString(),
+ showEmailNotificationsModal: false,
+ };
+
+ navigator.setOnNavigatorEvent(this.onNavigatorEvent);
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (this.props.theme !== nextProps.theme) {
+ setNavigatorStyles(this.props.navigator, nextProps.theme);
+ }
+
+ if (
+ this.props.sendEmailNotifications !== nextProps.sendEmailNotifications ||
+ this.props.enableEmailBatching !== nextProps.enableEmailBatching ||
+ this.props.emailInterval !== nextProps.emailInterval
+ ) {
+ this.setState({
+ interval: getEmailInterval(
+ nextProps.sendEmailNotifications,
+ nextProps.enableEmailBatching,
+ parseInt(nextProps.emailInterval, 10),
+ ).toString(),
+ });
+ }
+ }
+
+ onNavigatorEvent = (event) => {
+ if (event.type === 'ScreenChangedEvent') {
+ switch (event.id) {
+ case 'willDisappear':
+ this.saveEmailNotifyProps();
+ break;
+ }
+ }
+ };
+
+ setEmailNotifications = (interval) => {
+ const {sendEmailNotifications} = this.props;
+
+ let email = 'false';
+ if (sendEmailNotifications && interval !== Preferences.INTERVAL_NEVER.toString()) {
+ email = 'true';
+ }
+
+ this.setState({
+ email,
+ interval,
+ });
+ };
+
+ saveEmailNotifyProps = () => {
+ const {currentUserId} = this.props;
+ const {email, interval} = this.state;
+ const emailNotify = {category: Preferences.CATEGORY_NOTIFICATIONS, user_id: currentUserId, name: 'email', value: email};
+ const emailInterval = {category: Preferences.CATEGORY_NOTIFICATIONS, user_id: currentUserId, name: Preferences.EMAIL_INTERVAL, value: interval};
+ this.props.actions.savePreferences(currentUserId, [emailNotify, emailInterval]);
+ };
+}
diff --git a/app/screens/settings/notification_settings_mentions/notification_settings_mentions.android.js b/app/screens/settings/notification_settings_mentions/notification_settings_mentions.android.js
index 20e32fb6a..d49ab0d09 100644
--- a/app/screens/settings/notification_settings_mentions/notification_settings_mentions.android.js
+++ b/app/screens/settings/notification_settings_mentions/notification_settings_mentions.android.js
@@ -20,7 +20,7 @@ import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import NotificationSettingsMentionsBase from './notification_settings_mention_base';
-class NotificationSettingsMentionsIos extends NotificationSettingsMentionsBase {
+class NotificationSettingsMentionsAndroid extends NotificationSettingsMentionsBase {
cancelMentionKeys = () => {
this.setState({showKeywordsModal: false});
this.keywords = this.state.mention_keys;
@@ -442,4 +442,4 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
};
});
-export default injectIntl(NotificationSettingsMentionsIos);
+export default injectIntl(NotificationSettingsMentionsAndroid);
diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json
index 481edc80f..03a5aceff 100644
--- a/assets/base/i18n/en.json
+++ b/assets/base/i18n/en.json
@@ -3318,6 +3318,7 @@
"user.settings.notifications.email.disabled_long": "Email notifications have not been enabled by your System Administrator.",
"user.settings.notifications.email.everyHour": "Every hour",
"user.settings.notifications.email.everyXMinutes": "Every {count, plural, one {minute} other {{count, number} minutes}}",
+ "mobile.user.settings.notifications.email.fifteenMinutes": "Every 15 minutes",
"user.settings.notifications.email.immediately": "Immediately",
"user.settings.notifications.email.never": "Never",
"user.settings.notifications.email.send": "Send email notifications",