[NEW] User notification preferences (#2403)

* Button to preferences view

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Create screen to preferences and listItem to notifications

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Refactoring NotificationPreferencesView

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* List notification preferences

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Adding translations to labels

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* SetUserPreferences api call

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Saving new user preference in API

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Fix lint

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Add in-app notification test

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Fix in app mentions preference

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Improve object in testInAppNotification

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Removing improper options for NotificationpreferencesView

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Adding API version

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Use redux in UserNotificationPrefView

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Remove in app test

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Use components from another view

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Removing verification for testing in-app notifications

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Move to ProfileView

Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Ezequiel de Oliveira 2020-08-21 10:30:11 -03:00 committed by GitHub
parent a07b4cf81d
commit 54c4614e2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 578 additions and 121 deletions

View File

@ -61,6 +61,12 @@ export const SaveButton = React.memo(({ onPress, testID, ...props }) => (
</CustomHeaderButtons> </CustomHeaderButtons>
)); ));
export const PreferencesButton = React.memo(({ onPress, testID, ...props }) => (
<CustomHeaderButtons>
<Item title='preferences' iconName='settings' onPress={onPress} testID={testID} {...props} />
</CustomHeaderButtons>
));
export const LegalButton = React.memo(({ navigation, testID }) => ( export const LegalButton = React.memo(({ navigation, testID }) => (
<MoreButton onPress={() => navigation.navigate('LegalView')} testID={testID} /> <MoreButton onPress={() => navigation.navigate('LegalView')} testID={testID} />
)); ));
@ -89,6 +95,10 @@ SaveButton.propTypes = {
onPress: PropTypes.func.isRequired, onPress: PropTypes.func.isRequired,
testID: PropTypes.string.isRequired testID: PropTypes.string.isRequired
}; };
PreferencesButton.propTypes = {
onPress: PropTypes.func.isRequired,
testID: PropTypes.string.isRequired
};
LegalButton.propTypes = { LegalButton.propTypes = {
navigation: PropTypes.object.isRequired, navigation: PropTypes.object.isRequired,
testID: PropTypes.string.isRequired testID: PropTypes.string.isRequired

View File

@ -181,6 +181,8 @@ export default {
description: 'description', description: 'description',
Description: 'Description', Description: 'Description',
DESKTOP_OPTIONS: 'DESKTOP OPTIONS', DESKTOP_OPTIONS: 'DESKTOP OPTIONS',
DESKTOP_NOTIFICATIONS: 'DESKTOP NOTIFICATIONS',
Desktop_Alert_info: 'These notifications are delivered in desktop',
Directory: 'Directory', Directory: 'Directory',
Direct_Messages: 'Direct Messages', Direct_Messages: 'Direct Messages',
Disable_notifications: 'Disable notifications', Disable_notifications: 'Disable notifications',
@ -197,6 +199,8 @@ export default {
Edit: 'Edit', Edit: 'Edit',
Edit_Status: 'Edit Status', Edit_Status: 'Edit Status',
Edit_Invite: 'Edit Invite', Edit_Invite: 'Edit Invite',
Email_Notification_Mode_All: 'Every Mention/DM',
Email_Notification_Mode_Disabled: 'Disabled',
Email_or_password_field_is_empty: 'Email or password field is empty', Email_or_password_field_is_empty: 'Email or password field is empty',
Email: 'Email', Email: 'Email',
EMAIL: 'EMAIL', EMAIL: 'EMAIL',
@ -567,6 +571,7 @@ export default {
You: 'You', You: 'You',
Logged_out_by_server: 'You\'ve been logged out by the server. Please log in again.', Logged_out_by_server: 'You\'ve been logged out by the server. Please log in again.',
You_need_to_access_at_least_one_RocketChat_server_to_share_something: 'You need to access at least one Rocket.Chat server to share something.', You_need_to_access_at_least_one_RocketChat_server_to_share_something: 'You need to access at least one Rocket.Chat server to share something.',
You_need_to_verifiy_your_email_address_to_get_notications: 'You need to verify your email address to get notifications',
Your_certificate: 'Your Certificate', Your_certificate: 'Your Certificate',
Your_message: 'Your message', Your_message: 'Your message',
Your_invite_link_will_expire_after__usesLeft__uses: 'Your invite link will expire after {{usesLeft}} uses.', Your_invite_link_will_expire_after__usesLeft__uses: 'Your invite link will expire after {{usesLeft}} uses.',

View File

@ -175,6 +175,8 @@ export default {
deleting_room: 'excluindo sala', deleting_room: 'excluindo sala',
Direct_Messages: 'Mensagens Diretas', Direct_Messages: 'Mensagens Diretas',
DESKTOP_OPTIONS: 'OPÇÕES DE ÁREA DE TRABALHO', DESKTOP_OPTIONS: 'OPÇÕES DE ÁREA DE TRABALHO',
DESKTOP_NOTIFICATIONS: 'NOTIFICAÇÕES DE ÁREA DE TRABALHO',
Desktop_Alert_info: 'Essas notificações são entregues a você na área de trabalho',
Directory: 'Diretório', Directory: 'Diretório',
description: 'descrição', description: 'descrição',
Description: 'Descrição', Description: 'Descrição',
@ -195,6 +197,8 @@ export default {
Email: 'Email', Email: 'Email',
email: 'e-mail', email: 'e-mail',
Empty_title: 'Título vazio', Empty_title: 'Título vazio',
Email_Notification_Mode_All: 'Cada Menção / Mensagem Direta',
Email_Notification_Mode_Disabled: 'Desativado',
Enable_Auto_Translate: 'Ativar a tradução automática', Enable_Auto_Translate: 'Ativar a tradução automática',
Enable_notifications: 'Habilitar notificações', Enable_notifications: 'Habilitar notificações',
Everyone_can_access_this_channel: 'Todos podem acessar este canal', Everyone_can_access_this_channel: 'Todos podem acessar este canal',
@ -508,6 +512,7 @@ export default {
You_are_offline: 'Você está offline', You_are_offline: 'Você está offline',
You_can_search_using_RegExp_eg: 'Você pode usar expressões regulares, por exemplo `/^text$/i`', You_can_search_using_RegExp_eg: 'Você pode usar expressões regulares, por exemplo `/^text$/i`',
Your_message: 'Sua mensagem', Your_message: 'Sua mensagem',
You_need_to_verifiy_your_email_address_to_get_notications: 'Você precisa confirmar seu endereço de e-mail para obter notificações',
You_colon: 'Você: ', You_colon: 'Você: ',
you_were_mentioned: 'você foi mencionado', you_were_mentioned: 'você foi mencionado',
You_were_removed_from_channel: 'Você foi removido de {{channel}}', You_were_removed_from_channel: 'Você foi removido de {{channel}}',

View File

@ -726,6 +726,10 @@ const RocketChat = {
setUserPresenceOnline() { setUserPresenceOnline() {
return this.methodCall('UserPresence:online'); return this.methodCall('UserPresence:online');
}, },
setUserPreferences(userId, data) {
// RC 0.62.0
return this.sdk.post('users.setPreferences', { userId, data });
},
setUserStatus(status, message) { setUserStatus(status, message) {
// RC 1.2.0 // RC 1.2.0
return this.post('users.setStatus', { status, message }); return this.post('users.setStatus', { status, message });
@ -780,6 +784,10 @@ const RocketChat = {
// RC 0.48.0 // RC 0.48.0
return this.sdk.get('users.info', { userId }); return this.sdk.get('users.info', { userId });
}, },
getUserPreferences(userId) {
// RC 0.62.0
return this.sdk.get('users.getPreferences', { userId });
},
getRoomInfo(roomId) { getRoomInfo(roomId) {
// RC 0.72.0 // RC 0.72.0
return this.sdk.get('rooms.info', { roomId }); return this.sdk.get('rooms.info', { roomId });

View File

@ -41,6 +41,8 @@ import LanguageView from '../views/LanguageView';
import ThemeView from '../views/ThemeView'; import ThemeView from '../views/ThemeView';
import DefaultBrowserView from '../views/DefaultBrowserView'; import DefaultBrowserView from '../views/DefaultBrowserView';
import ScreenLockConfigView from '../views/ScreenLockConfigView'; import ScreenLockConfigView from '../views/ScreenLockConfigView';
import PreferencesView from '../views/PreferencesView';
import UserNotificationPrefView from '../views/UserNotificationPreferencesView';
// Admin Stack // Admin Stack
import AdminPanelView from '../views/AdminPanelView'; import AdminPanelView from '../views/AdminPanelView';
@ -220,6 +222,21 @@ const SettingsStackNavigator = () => {
component={ScreenLockConfigView} component={ScreenLockConfigView}
options={ScreenLockConfigView.navigationOptions} options={ScreenLockConfigView.navigationOptions}
/> />
<SettingsStack.Screen
name='PreferencesView'
component={PreferencesView}
options={PreferencesView.navigationOptions}
/>
<SettingsStack.Screen
name='UserNotificationPrefView'
component={UserNotificationPrefView}
options={UserNotificationPrefView.navigationOptions}
/>
<SettingsStack.Screen
name='PickerView'
component={PickerView}
options={PickerView.navigationOptions}
/>
</SettingsStack.Navigator> </SettingsStack.Navigator>
); );
}; };

View File

@ -42,6 +42,8 @@ import AdminPanelView from '../../views/AdminPanelView';
import NewMessageView from '../../views/NewMessageView'; import NewMessageView from '../../views/NewMessageView';
import CreateChannelView from '../../views/CreateChannelView'; import CreateChannelView from '../../views/CreateChannelView';
import QueueListView from '../../views/QueueListView'; import QueueListView from '../../views/QueueListView';
import PreferencesView from '../../views/PreferencesView';
import UserNotificationPrefView from '../../views/UserNotificationPreferencesView';
// InsideStackNavigator // InsideStackNavigator
import AttachmentView from '../../views/AttachmentView'; import AttachmentView from '../../views/AttachmentView';
@ -253,6 +255,16 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
name='CreateDiscussionView' name='CreateDiscussionView'
component={CreateDiscussionView} component={CreateDiscussionView}
/> />
<ModalStack.Screen
name='PreferencesView'
component={PreferencesView}
options={PreferencesView.navigationOptions}
/>
<ModalStack.Screen
name='UserNotificationPrefView'
component={UserNotificationPrefView}
options={UserNotificationPrefView.navigationOptions}
/>
</ModalStack.Navigator> </ModalStack.Navigator>
</ModalContainer> </ModalContainer>
); );

View File

@ -0,0 +1,29 @@
import React from 'react';
import {
Text
} from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
const Info = React.memo(({ info, theme }) => (
<Text
style={[
styles.infoText,
{
color: themes[theme].infoText,
backgroundColor: themes[theme].auxiliaryBackground
}
]}
>
{info}
</Text>
));
Info.propTypes = {
info: PropTypes.string,
theme: PropTypes.string
};
export default Info;

View File

@ -0,0 +1,23 @@
import React from 'react';
import {
View
} from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
const SectionSeparator = React.memo(({ theme }) => (
<View
style={[
styles.sectionSeparatorBorder,
{ backgroundColor: themes[theme].auxiliaryBackground }
]}
/>
));
SectionSeparator.propTypes = {
theme: PropTypes.string
};
export default SectionSeparator;

View File

@ -0,0 +1,29 @@
import React from 'react';
import {
Text
} from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
const SectionTitle = React.memo(({ title, theme }) => (
<Text
style={[
styles.sectionTitle,
{
backgroundColor: themes[theme].auxiliaryBackground,
color: themes[theme].infoText
}
]}
>
{title}
</Text>
));
SectionTitle.propTypes = {
title: PropTypes.string,
theme: PropTypes.string
};
export default SectionTitle;

View File

@ -17,126 +17,10 @@ import { withTheme } from '../../theme';
import protectedFunction from '../../lib/methods/helpers/protectedFunction'; import protectedFunction from '../../lib/methods/helpers/protectedFunction';
import SafeAreaView from '../../containers/SafeAreaView'; import SafeAreaView from '../../containers/SafeAreaView';
import log, { events, logEvent } from '../../utils/log'; import log, { events, logEvent } from '../../utils/log';
import SectionTitle from './SectionTitle';
const SectionTitle = React.memo(({ title, theme }) => ( import SectionSeparator from './SectionSeparator';
<Text import Info from './Info';
style={[ import { OPTIONS } from './options';
styles.sectionTitle,
{
backgroundColor: themes[theme].auxiliaryBackground,
color: themes[theme].infoText
}
]}
>
{title}
</Text>
));
const SectionSeparator = React.memo(({ theme }) => (
<View
style={[
styles.sectionSeparatorBorder,
{ backgroundColor: themes[theme].auxiliaryBackground }
]}
/>
));
const Info = React.memo(({ info, theme }) => (
<Text
style={[
styles.infoText,
{
color: themes[theme].infoText,
backgroundColor: themes[theme].auxiliaryBackground
}
]}
>
{info}
</Text>
));
SectionTitle.propTypes = {
title: PropTypes.string,
theme: PropTypes.string
};
SectionSeparator.propTypes = {
theme: PropTypes.string
};
Info.propTypes = {
info: PropTypes.string,
theme: PropTypes.string
};
const OPTIONS = {
desktopNotifications: [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}],
audioNotifications: [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}],
mobilePushNotifications: [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}],
emailNotifications: [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}],
desktopNotificationDuration: [{
label: 'Default', value: 0
}, {
label: 'Seconds', second: 1, value: 1
}, {
label: 'Seconds', second: 2, value: 2
}, {
label: 'Seconds', second: 3, value: 3
}, {
label: 'Seconds', second: 4, value: 4
}, {
label: 'Seconds', second: 5, value: 5
}],
audioNotificationValue: [{
label: 'None', value: 'none None'
}, {
label: 'Default', value: '0 Default'
}, {
label: 'Beep', value: 'beep Beep'
}, {
label: 'Ding', value: 'ding Ding'
}, {
label: 'Chelle', value: 'chelle Chelle'
}, {
label: 'Droplet', value: 'droplet Droplet'
}, {
label: 'Highbell', value: 'highbell Highbell'
}, {
label: 'Seasons', value: 'seasons Seasons'
}]
};
class NotificationPreferencesView extends React.Component { class NotificationPreferencesView extends React.Component {
static navigationOptions = () => ({ static navigationOptions = () => ({

View File

@ -0,0 +1,68 @@
export const OPTIONS = {
desktopNotifications: [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}],
audioNotifications: [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}],
mobilePushNotifications: [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}],
emailNotifications: [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}],
desktopNotificationDuration: [{
label: 'Default', value: 0
}, {
label: 'Seconds', second: 1, value: 1
}, {
label: 'Seconds', second: 2, value: 2
}, {
label: 'Seconds', second: 3, value: 3
}, {
label: 'Seconds', second: 4, value: 4
}, {
label: 'Seconds', second: 5, value: 5
}],
audioNotificationValue: [{
label: 'None', value: 'none None'
}, {
label: 'Default', value: '0 Default'
}, {
label: 'Beep', value: 'beep Beep'
}, {
label: 'Ding', value: 'ding Ding'
}, {
label: 'Chelle', value: 'chelle Chelle'
}, {
label: 'Droplet', value: 'droplet Droplet'
}, {
label: 'Highbell', value: 'highbell Highbell'
}, {
label: 'Seasons', value: 'seasons Seasons'
}]
};

View File

@ -0,0 +1,65 @@
import React from 'react';
import { ScrollView } from 'react-native';
import PropTypes from 'prop-types';
import I18n from '../../i18n';
import {
logEvent, events
} from '../../utils/log';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import Separator from '../../containers/Separator';
import SafeAreaView from '../../containers/SafeAreaView';
import StatusBar from '../../containers/StatusBar';
import ListItem from '../../containers/ListItem';
import { DisclosureImage } from '../../containers/DisclosureIndicator';
import { withTheme } from '../../theme';
class PreferencesView extends React.Component {
static navigationOptions = () => ({
title: I18n.t('Preferences')
});
static propTypes = {
navigation: PropTypes.object,
theme: PropTypes.string
}
renderDisclosure = () => {
const { theme } = this.props;
return <DisclosureImage theme={theme} />;
}
navigateToScreen = (screen, params) => {
logEvent(events[`SE_GO_${ screen.replace('View', '').toUpperCase() }`]);
const { navigation } = this.props;
navigation.navigate(screen, params);
}
render() {
const { theme } = this.props;
return (
<SafeAreaView testID='preferences-view' theme={theme}>
<StatusBar theme={theme} />
<ScrollView
{...scrollPersistTaps}
contentContainerStyle={{ paddingVertical: 36 }}
showsVerticalScrollIndicator={false}
testID='preferences-view-list'
>
<ListItem
title={I18n.t('Notifications')}
onPress={() => this.navigateToScreen('UserNotificationPrefView')}
showActionIndicator
testID='preferences-view-notifications'
right={this.renderDisclosure}
theme={theme}
/>
<Separator theme={theme} />
</ScrollView>
</SafeAreaView>
);
}
}
export default withTheme(PreferencesView);

View File

@ -24,7 +24,7 @@ import Button from '../../containers/Button';
import Avatar from '../../containers/Avatar'; import Avatar from '../../containers/Avatar';
import { setUser as setUserAction } from '../../actions/login'; import { setUser as setUserAction } from '../../actions/login';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import { DrawerButton } from '../../containers/HeaderButton'; import { DrawerButton, PreferencesButton } from '../../containers/HeaderButton';
import StatusBar from '../../containers/StatusBar'; import StatusBar from '../../containers/StatusBar';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { withTheme } from '../../theme'; import { withTheme } from '../../theme';
@ -39,6 +39,9 @@ class ProfileView extends React.Component {
if (!isMasterDetail) { if (!isMasterDetail) {
options.headerLeft = () => <DrawerButton navigation={navigation} />; options.headerLeft = () => <DrawerButton navigation={navigation} />;
} }
options.headerRight = () => (
<PreferencesButton onPress={() => navigation.navigate('PreferencesView')} testID='preferences-view-open' />
);
return options; return options;
} }

View File

@ -0,0 +1,29 @@
import React from 'react';
import {
Text
} from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
const Info = React.memo(({ info, theme }) => (
<Text
style={[
styles.infoText,
{
color: themes[theme].infoText,
backgroundColor: themes[theme].auxiliaryBackground
}
]}
>
{info}
</Text>
));
Info.propTypes = {
info: PropTypes.string,
theme: PropTypes.string
};
export default Info;

View File

@ -0,0 +1,23 @@
import React from 'react';
import {
View
} from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
const SectionSeparator = React.memo(({ theme }) => (
<View
style={[
styles.sectionSeparatorBorder,
{ backgroundColor: themes[theme].auxiliaryBackground }
]}
/>
));
SectionSeparator.propTypes = {
theme: PropTypes.string
};
export default SectionSeparator;

View File

@ -0,0 +1,29 @@
import React from 'react';
import {
Text
} from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
const SectionTitle = React.memo(({ title, theme }) => (
<Text
style={[
styles.sectionTitle,
{
backgroundColor: themes[theme].auxiliaryBackground,
color: themes[theme].infoText
}
]}
>
{title}
</Text>
));
SectionTitle.propTypes = {
title: PropTypes.string,
theme: PropTypes.string
};
export default SectionTitle;

View File

@ -0,0 +1,168 @@
import React from 'react';
import {
View, ScrollView, Text
} from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { themes } from '../../constants/colors';
import StatusBar from '../../containers/StatusBar';
import ListItem from '../../containers/ListItem';
import Separator from '../../containers/Separator';
import I18n from '../../i18n';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import styles from './styles';
import RocketChat from '../../lib/rocketchat';
import { withTheme } from '../../theme';
import SafeAreaView from '../../containers/SafeAreaView';
import SectionTitle from './SectionTitle';
import SectionSeparator from './SectionSeparator';
import Info from './Info';
import { OPTIONS } from './options';
import ActivityIndicator from '../../containers/ActivityIndicator';
import { DisclosureImage } from '../../containers/DisclosureIndicator';
import { getUserSelector } from '../../selectors/login';
class UserNotificationPreferencesView extends React.Component {
static navigationOptions = () => ({
title: I18n.t('Notification_Preferences')
})
static propTypes = {
navigation: PropTypes.object,
route: PropTypes.object,
theme: PropTypes.string,
user: PropTypes.shape({
id: PropTypes.string
})
};
constructor(props) {
super(props);
this.state = {
preferences: {},
loading: false
};
}
async componentDidMount() {
const { user } = this.props;
const { id } = user;
const result = await RocketChat.getUserPreferences(id);
const { preferences } = result;
this.setState({ preferences, loading: true });
}
findOption = (key) => {
const { preferences } = this.state;
const option = preferences[key] ? OPTIONS[key].find(item => item.value === preferences[key]) : OPTIONS[key][0];
return option;
}
renderPickerOption = (key) => {
const { theme } = this.props;
const text = this.findOption(key);
return <Text style={[styles.pickerText, { color: themes[theme].actionTintColor }]}>{I18n.t(text?.label, { defaultValue: text?.label, second: text?.second })}</Text>;
}
pickerSelection = (title, key) => {
const { preferences } = this.state;
const { navigation } = this.props;
let values = OPTIONS[key];
if (OPTIONS[key][0]?.value !== 'default') {
values = [{ label: `${ I18n.t('Default') } (${ I18n.t(this.findOption(key).label) })`, value: preferences[key]?.value }, ...OPTIONS[key]];
}
navigation.navigate('PickerView', {
title,
data: values,
value: preferences[key],
onChangeValue: value => this.onValueChangePicker(key, value)
});
}
onValueChangePicker = (key, value) => this.saveNotificationPreferences({ [key]: value.toString() });
saveNotificationPreferences = async(params) => {
const { user } = this.props;
const { id } = user;
const result = await RocketChat.setUserPreferences(id, params);
const { user: { settings } } = result;
this.setState({ preferences: settings.preferences });
}
renderDisclosure = () => {
const { theme } = this.props;
return <DisclosureImage theme={theme} />;
}
render() {
const { theme } = this.props;
const { loading } = this.state;
return (
<SafeAreaView testID='user-notification-preference-view' theme={theme}>
<StatusBar theme={theme} />
<ScrollView
{...scrollPersistTaps}
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
contentContainerStyle={styles.contentContainer}
testID='user-notification-preference-view-list'
>
{loading
? (
<>
<SectionSeparator theme={theme} />
<SectionTitle title={I18n.t('DESKTOP_NOTIFICATIONS')} theme={theme} />
<ListItem
title={I18n.t('Alert')}
testID='user-notification-preference-view-alert'
onPress={title => this.pickerSelection(title, 'desktopNotifications')}
right={() => this.renderPickerOption('desktopNotifications')}
theme={theme}
/>
<Separator theme={theme} />
<Info info={I18n.t('Desktop_Alert_info')} theme={theme} />
<SectionSeparator theme={theme} />
<SectionTitle title={I18n.t('PUSH_NOTIFICATIONS')} theme={theme} />
<Separator theme={theme} />
<ListItem
title={I18n.t('Alert')}
testID='user-notification-preference-view-push-notification'
onPress={title => this.pickerSelection(title, 'mobileNotifications')}
right={() => this.renderPickerOption('mobileNotifications')}
theme={theme}
/>
<Separator theme={theme} />
<Info info={I18n.t('Push_Notifications_Alert_Info')} theme={theme} />
<SectionSeparator theme={theme} />
<SectionTitle title={I18n.t('EMAIL')} theme={theme} />
<Separator theme={theme} />
<ListItem
title={I18n.t('Alert')}
testID='user-notification-preference-view-email-alert'
onPress={title => this.pickerSelection(title, 'emailNotificationMode')}
right={() => this.renderPickerOption('emailNotificationMode')}
theme={theme}
/>
<Separator theme={theme} />
<Info info={I18n.t('You_need_to_verifiy_your_email_address_to_get_notications')} theme={theme} />
</>
) : <ActivityIndicator theme={theme} />
}
<View style={[styles.marginBottom, { backgroundColor: themes[theme].auxiliaryBackground }]} />
</ScrollView>
</SafeAreaView>
);
}
}
const mapStateToProps = state => ({
user: getUserSelector(state)
});
export default connect(mapStateToProps)(withTheme(UserNotificationPreferencesView));

View File

@ -0,0 +1,19 @@
const commonOptions = [{
label: 'Default', value: 'default'
}, {
label: 'All_Messages', value: 'all'
}, {
label: 'Mentions', value: 'mentions'
}, {
label: 'Nothing', value: 'nothing'
}];
export const OPTIONS = {
desktopNotifications: commonOptions,
mobileNotifications: commonOptions,
emailNotificationMode: [{
label: 'Email_Notification_Mode_All', value: 'mentions'
}, {
label: 'Email_Notification_Mode_Disabled', value: 'nothing'
}]
};

View File

@ -0,0 +1,31 @@
import { StyleSheet } from 'react-native';
import sharedStyles from '../Styles';
export default StyleSheet.create({
sectionSeparatorBorder: {
height: 10
},
marginBottom: {
height: 30
},
contentContainer: {
marginVertical: 10
},
infoText: {
...sharedStyles.textRegular,
fontSize: 13,
paddingHorizontal: 15,
paddingVertical: 10
},
sectionTitle: {
...sharedStyles.separatorBottom,
paddingHorizontal: 15,
paddingVertical: 10,
fontSize: 14
},
pickerText: {
...sharedStyles.textRegular,
fontSize: 16
}
});