diff --git a/app/screens/channel_notification_preference/__snapshots__/channel_notification_preference.test.js.snap b/app/screens/channel_notification_preference/__snapshots__/channel_notification_preference.test.js.snap
index 911dd5ac5..68c1b2274 100644
--- a/app/screens/channel_notification_preference/__snapshots__/channel_notification_preference.test.js.snap
+++ b/app/screens/channel_notification_preference/__snapshots__/channel_notification_preference.test.js.snap
@@ -24,10 +24,11 @@ exports[`ChannelNotificationPreference should match snapshot 1`] = `
id="channel_notifications.preference.header"
style={
Object {
+ "backgroundColor": "rgba(63,67,80,0.03)",
"color": "rgba(63,67,80,0.56)",
"fontSize": 13,
- "marginTop": 10,
"padding": 16,
+ "paddingTop": 26,
"textTransform": "uppercase",
}
}
diff --git a/app/screens/channel_notification_preference/channel_notification_preference.android.js b/app/screens/channel_notification_preference/channel_notification_preference.android.js
index 60611635c..e48bd3c45 100644
--- a/app/screens/channel_notification_preference/channel_notification_preference.android.js
+++ b/app/screens/channel_notification_preference/channel_notification_preference.android.js
@@ -4,12 +4,14 @@
import React from 'react';
import {
ScrollView,
+ Switch,
View,
} from 'react-native';
import FormattedText from '@components/formatted_text';
import RadioButtonGroup from '@components/radio_button';
import StatusBar from '@components/status_bar';
+import {ViewTypes} from '@constants';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import ChannelNotificationPreferenceBase from './channel_notification_preference_base';
@@ -34,7 +36,8 @@ export default class ChannelNotificationPreferenceAndroid extends ChannelNotific
}
render() {
- const {theme} = this.props;
+ const {theme, isCollapsedThreadsEnabled} = this.props;
+ const {notificationLevel, notificationThreadsLevel} = this.state;
const style = getStyleSheet(theme);
const options = this.getRadioItems();
@@ -59,6 +62,27 @@ export default class ChannelNotificationPreferenceAndroid extends ChannelNotific
onSelect={this.handlePress}
options={options}
/>
+
+ {isCollapsedThreadsEnabled && notificationLevel === ViewTypes.NotificationLevels.MENTION && (
+ <>
+
+
+
+
+
+ >
+ )}
);
@@ -80,5 +104,25 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
marginTop: 10,
padding: 16,
},
+ switchContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingRight: 16,
+ },
+ switchHeader: {
+ color: changeOpacity(theme.centerChannelColor, 0.56),
+ fontSize: 13,
+ marginTop: 10,
+ marginBottom: 16,
+ },
+ switchLabel: {
+ color: theme.centerChannelColor,
+ flex: 1,
+ fontSize: 17,
+ paddingRight: 10,
+ textAlignVertical: 'center',
+ includeFontPadding: false,
+ },
};
});
diff --git a/app/screens/channel_notification_preference/channel_notification_preference.ios.js b/app/screens/channel_notification_preference/channel_notification_preference.ios.js
index 2b6f58af4..36b4292ef 100644
--- a/app/screens/channel_notification_preference/channel_notification_preference.ios.js
+++ b/app/screens/channel_notification_preference/channel_notification_preference.ios.js
@@ -10,6 +10,7 @@ import {SafeAreaView} from 'react-native-safe-area-context';
import FormattedText from '@components/formatted_text';
import StatusBar from '@components/status_bar';
+import {ViewTypes} from '@constants';
import SectionItem from '@screens/settings/section_item';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@@ -17,7 +18,8 @@ import ChannelNotificationPreferenceBase from './channel_notification_preference
export default class ChannelNotificationPreferenceIos extends ChannelNotificationPreferenceBase {
render() {
- const {theme} = this.props;
+ const {theme, isCollapsedThreadsEnabled} = this.props;
+ const {notificationLevel, notificationThreadsLevel} = this.state;
const style = getStyleSheet(theme);
const items = this.getItems();
@@ -60,6 +62,29 @@ export default class ChannelNotificationPreferenceIos extends ChannelNotificatio
/>
),
)}
+ {isCollapsedThreadsEnabled && notificationLevel === ViewTypes.NotificationLevels.MENTION && (
+
+
+
+
+ )}
+ description={}
+ action={this.handleThreadsPress}
+ actionType='toggle'
+ selected={notificationThreadsLevel === ViewTypes.NotificationLevels.ALL}
+ theme={theme}
+ />
+
+ )}
@@ -76,11 +101,12 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.03),
},
header: {
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.03),
color: changeOpacity(theme.centerChannelColor, 0.56),
fontSize: 13,
textTransform: 'uppercase',
- marginTop: 10,
padding: 16,
+ paddingTop: 26,
},
divider: {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
diff --git a/app/screens/channel_notification_preference/channel_notification_preference.test.js b/app/screens/channel_notification_preference/channel_notification_preference.test.js
index e76ec3fd8..2b637b099 100644
--- a/app/screens/channel_notification_preference/channel_notification_preference.test.js
+++ b/app/screens/channel_notification_preference/channel_notification_preference.test.js
@@ -10,7 +10,7 @@ import {shallowWithIntlMessages} from '@test/intl-test-helper';
import ChannelNotificationPreference from './channel_notification_preference';
-function makeProps(pushNotificationLevel) {
+function makeProps(pushNotificationLevel, pushThreadsNotificationLevel, isCollapsedThreadsEnabled = false) {
return {
actions: {
updateChannelNotifyProps: jest.fn(),
@@ -22,8 +22,10 @@ function makeProps(pushNotificationLevel) {
userId: 'user_id',
notifyProps: {
push: pushNotificationLevel,
+ push_threads: pushThreadsNotificationLevel,
},
theme: Preferences.THEMES.denim,
+ isCollapsedThreadsEnabled,
};
}
@@ -62,7 +64,7 @@ describe('ChannelNotificationPreference', () => {
checkNotificationSelected(ViewTypes.NotificationLevels.NONE, 3);
});
- test('should save on click', () => {
+ test('should save on click, when CRT off', () => {
const props = makeProps('default');
const wrapper = shallowWithIntlMessages(
,
@@ -78,4 +80,47 @@ describe('ChannelNotificationPreference', () => {
{push: ViewTypes.NotificationLevels.NONE},
);
});
+
+ test('should save on click, when CRT on', () => {
+ const props = makeProps('default', undefined, true);
+ const wrapper = shallowWithIntlMessages(
+ ,
+ );
+
+ // click on 'Never' -- last item
+ wrapper.find(SectionItem).at(3).dive().simulate('press');
+
+ expect(props.actions.updateChannelNotifyProps).toHaveBeenCalledTimes(1);
+ expect(props.actions.updateChannelNotifyProps).toBeCalledWith(
+ props.userId,
+ props.channelId,
+ {
+ push: ViewTypes.NotificationLevels.NONE,
+ push_threads: ViewTypes.NotificationLevels.ALL,
+ },
+ );
+ });
+
+ test('should show push_threads switch, when CRT is on and notifyLevel is mention', () => {
+ const props = makeProps('all', undefined, true);
+ const wrapper = shallowWithIntlMessages(
+ ,
+ );
+
+ expect(wrapper.find(SectionItem)).toHaveLength(4);
+
+ wrapper.setState({
+ notificationLevel: 'mention',
+ });
+
+ expect(wrapper.find(SectionItem)).toHaveLength(5);
+ });
+
+ test('should show push_threads switch, when CRT is off and notifyLevel is mention', () => {
+ const props = makeProps('mention', undefined, false);
+ const wrapper = shallowWithIntlMessages(
+ ,
+ );
+ expect(wrapper.find(SectionItem)).toHaveLength(4);
+ });
});
diff --git a/app/screens/channel_notification_preference/channel_notification_preference_base.js b/app/screens/channel_notification_preference/channel_notification_preference_base.js
index 2f7f23ff0..16f2a92f0 100644
--- a/app/screens/channel_notification_preference/channel_notification_preference_base.js
+++ b/app/screens/channel_notification_preference/channel_notification_preference_base.js
@@ -20,6 +20,7 @@ export default class ChannelNotificationPreferenceBase extends PureComponent {
notifyProps: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
userId: PropTypes.string.isRequired,
+ isCollapsedThreadsEnabled: PropTypes.bool.isRequired,
};
static contextTypes = {
@@ -31,6 +32,7 @@ export default class ChannelNotificationPreferenceBase extends PureComponent {
this.state = {
notificationLevel: props.notifyProps?.push || ViewTypes.NotificationLevels.DEFAULT,
+ notificationThreadsLevel: props.notifyProps?.push_threads || ViewTypes.NotificationLevels.ALL,
};
}
@@ -67,9 +69,54 @@ export default class ChannelNotificationPreferenceBase extends PureComponent {
}];
}
+ handleSubmit = (push, push_threads) => {
+ const {actions, channelId, userId, isCollapsedThreadsEnabled} = this.props;
+
+ const props = {
+ push,
+ };
+
+ if (isCollapsedThreadsEnabled) {
+ props.push_threads = push_threads;
+ }
+
+ return actions.updateChannelNotifyProps(userId, channelId, props);
+ };
+
+ handleThreadsPress = preventDoubleTap(async (value) => {
+ const newNotificationLevel = value ? ViewTypes.NotificationLevels.ALL : ViewTypes.NotificationLevels.MENTION;
+ const {notificationThreadsLevel, notificationLevel} = this.state;
+
+ if (newNotificationLevel === notificationThreadsLevel) {
+ // tapped on current selection.
+ return;
+ }
+
+ this.setState({
+ notificationThreadsLevel: newNotificationLevel,
+ });
+
+ const {error} = await this.handleSubmit(notificationLevel, newNotificationLevel);
+ if (error) {
+ const {intl} = this.context;
+ alertErrorWithFallback(
+ intl,
+ error,
+ {
+ id: t('channel_notifications.preference.save_error'),
+ defaultMessage: "We couldn't save notification preference. Please check your connection and try again.",
+ },
+ );
+
+ // restore old value.
+ this.setState({
+ notificationThreadsLevel,
+ });
+ }
+ });
+
handlePress = preventDoubleTap(async (newNotificationLevel) => {
- const {actions, channelId, userId} = this.props;
- const {notificationLevel} = this.state;
+ const {notificationLevel, notificationThreadsLevel} = this.state;
if (newNotificationLevel === notificationLevel) {
// tapped on current selection.
@@ -80,9 +127,7 @@ export default class ChannelNotificationPreferenceBase extends PureComponent {
notificationLevel: newNotificationLevel,
});
- const props = {push: newNotificationLevel};
-
- const {error} = await actions.updateChannelNotifyProps(userId, channelId, props);
+ const {error} = await this.handleSubmit(newNotificationLevel, notificationThreadsLevel);
if (error) {
const {intl} = this.context;
alertErrorWithFallback(
diff --git a/app/screens/channel_notification_preference/index.js b/app/screens/channel_notification_preference/index.js
index 42dad93f2..4b72e7afb 100644
--- a/app/screens/channel_notification_preference/index.js
+++ b/app/screens/channel_notification_preference/index.js
@@ -5,7 +5,7 @@ import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {updateChannelNotifyProps} from '@mm-redux/actions/channels';
-import {getTheme} from '@mm-redux/selectors/entities/preferences';
+import {getTheme, isCollapsedThreadsEnabled} from '@mm-redux/selectors/entities/preferences';
import {getCurrentUser} from '@mm-redux/selectors/entities/users';
import {isLandscape} from '@selectors/device';
@@ -15,6 +15,7 @@ function mapStateToProps(state) {
return {
globalNotifyProps: getCurrentUser(state)?.notify_props,
isLandscape: isLandscape(state),
+ isCollapsedThreadsEnabled: isCollapsedThreadsEnabled(state),
theme: getTheme(state),
};
}