[FIX] Change notifications preferences (#2000)

* [FIX] Change notifications preferences

* [IMPROVEMENT] Picker View

* [I18N] Translations

* [FIX] Picker Selection

* [FIX] List border

* [FIX] Prevent crash

* [FIX] Not-Pref tablet

* [FIX] Use same style of LanguageView

* [IMPROVEMENT] Send listItem title

Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Djorkaeff Alexandre 2020-04-06 18:40:18 -03:00 committed by GitHub
parent 78441bf345
commit c313a63d8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 160 additions and 42 deletions

View File

@ -13,9 +13,10 @@ const styles = StyleSheet.create({
} }
}); });
const Check = React.memo(({ theme }) => <CustomIcon style={styles.icon} color={themes[theme].tintColor} size={22} name='check' />); const Check = React.memo(({ theme, style }) => <CustomIcon style={[styles.icon, style]} color={themes[theme].tintColor} size={22} name='check' />);
Check.propTypes = { Check.propTypes = {
style: PropTypes.object,
theme: PropTypes.string theme: PropTypes.string
}; };

View File

@ -52,7 +52,7 @@ const Button = React.memo(({
onPress, ...props onPress, ...props
}) => ( }) => (
<Touch <Touch
onPress={onPress} onPress={() => onPress(props.title)}
style={{ backgroundColor: themes[props.theme].backgroundColor }} style={{ backgroundColor: themes[props.theme].backgroundColor }}
enabled={!props.disabled} enabled={!props.disabled}
theme={props.theme} theme={props.theme}
@ -89,6 +89,7 @@ Content.propTypes = {
}; };
Button.propTypes = { Button.propTypes = {
title: PropTypes.string,
onPress: PropTypes.func, onPress: PropTypes.func,
disabled: PropTypes.bool, disabled: PropTypes.bool,
theme: PropTypes.string theme: PropTypes.string

View File

@ -414,6 +414,7 @@ export default {
Select_Server: 'Select Server', Select_Server: 'Select Server',
Select_Users: 'Select Users', Select_Users: 'Select Users',
Select_a_Channel: 'Select a Channel', Select_a_Channel: 'Select a Channel',
Select_an_option: 'Select an option',
Send: 'Send', Send: 'Send',
Send_audio_message: 'Send audio message', Send_audio_message: 'Send audio message',
Send_crash_report: 'Send crash report', Send_crash_report: 'Send crash report',

View File

@ -377,6 +377,7 @@ export default {
Select_Server: 'Selecionar Servidor', Select_Server: 'Selecionar Servidor',
Select_Users: 'Selecionar Usuários', Select_Users: 'Selecionar Usuários',
Select_a_Channel: 'Selecione um canal', Select_a_Channel: 'Selecione um canal',
Select_an_option: 'Selecione uma opção',
Send: 'Enviar', Send: 'Enviar',
Send_audio_message: 'Enviar mensagem de áudio', Send_audio_message: 'Enviar mensagem de áudio',
Send_message: 'Enviar mensagem', Send_message: 'Enviar mensagem',

View File

@ -166,6 +166,9 @@ const ChatsStack = createStackNavigator({
NotificationPrefView: { NotificationPrefView: {
getScreen: () => require('./views/NotificationPreferencesView').default getScreen: () => require('./views/NotificationPreferencesView').default
}, },
PickerView: {
getScreen: () => require('./views/PickerView').default
},
...RoomRoutes ...RoomRoutes
}, { }, {
defaultNavigationOptions: defaultHeader, defaultNavigationOptions: defaultHeader,
@ -448,6 +451,9 @@ const RoomActionsStack = createStackNavigator({
}, },
AttachmentView: { AttachmentView: {
getScreen: () => require('./views/AttachmentView').default getScreen: () => require('./views/AttachmentView').default
},
PickerView: {
getScreen: () => require('./views/PickerView').default
} }
}, { }, {
defaultNavigationOptions: defaultHeader, defaultNavigationOptions: defaultHeader,

View File

@ -3,9 +3,9 @@ import {
View, ScrollView, Switch, Text View, ScrollView, Switch, Text
} from 'react-native'; } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import RNPickerSelect from 'react-native-picker-select';
import { SafeAreaView } from 'react-navigation'; import { SafeAreaView } from 'react-navigation';
import database from '../../lib/database';
import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors'; import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors';
import StatusBar from '../../containers/StatusBar'; import StatusBar from '../../containers/StatusBar';
import ListItem from '../../containers/ListItem'; import ListItem from '../../containers/ListItem';
@ -15,9 +15,9 @@ import scrollPersistTaps from '../../utils/scrollPersistTaps';
import styles from './styles'; import styles from './styles';
import sharedStyles from '../Styles'; import sharedStyles from '../Styles';
import RocketChat from '../../lib/rocketchat'; import RocketChat from '../../lib/rocketchat';
import log from '../../utils/log';
import { withTheme } from '../../theme'; import { withTheme } from '../../theme';
import { themedHeader } from '../../utils/navigation'; import { themedHeader } from '../../utils/navigation';
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
const SectionTitle = React.memo(({ title, theme }) => ( const SectionTitle = React.memo(({ title, theme }) => (
<Text <Text
@ -181,43 +181,52 @@ class NotificationPreferencesView extends React.Component {
} }
} }
onValueChangeSwitch = async(key, value) => { saveNotificationSettings = async(key, value, params) => {
const params = { const { room } = this.state;
[key]: value ? '1' : '0' const db = database.active;
};
await db.action(async() => {
await room.update(protectedFunction((r) => {
r[key] = value;
}));
});
try { try {
await RocketChat.saveNotificationSettings(this.rid, params); const result = await RocketChat.saveNotificationSettings(this.rid, params);
} catch (e) { if (result.success) {
log(e); return;
}
} catch {
// do nothing
} }
await db.action(async() => {
await room.update(protectedFunction((r) => {
r[key] = room[key];
}));
});
} }
onValueChangePicker = async(key, value) => { onValueChangeSwitch = (key, value) => this.saveNotificationSettings(key, value, { [key]: value ? '1' : '0' });
const params = {
[key]: value.toString() onValueChangePicker = (key, value) => this.saveNotificationSettings(key, value, { [key]: value.toString() });
};
try { pickerSelection = (title, key) => {
await RocketChat.saveNotificationSettings(this.rid, params); const { room } = this.state;
} catch (e) { const { navigation } = this.props;
log(e); navigation.navigate('PickerView', {
} title,
data: OPTIONS[key],
value: room[key],
onChangeValue: value => this.onValueChangePicker(key, value)
});
} }
renderPicker = (key) => { renderPickerOption = (key) => {
const { room } = this.state; const { room } = this.state;
const { theme } = this.props; const { theme } = this.props;
return ( const text = room[key] ? OPTIONS[key].find(option => option.value === room[key]) : OPTIONS[key][0];
<RNPickerSelect return <Text style={[styles.pickerText, { color: themes[theme].actionTintColor }]}>{text?.label}</Text>;
testID={key}
style={{ viewContainer: styles.viewContainer }}
value={room[key]}
textInputProps={{ style: { ...styles.pickerText, color: themes[theme].actionTintColor } }}
useNativeAndroidPickerStyle={false}
placeholder={{}}
onValueChange={value => this.onValueChangePicker(key, value)}
items={OPTIONS[key]}
/>
);
} }
renderSwitch = (key) => { renderSwitch = (key) => {
@ -283,7 +292,8 @@ class NotificationPreferencesView extends React.Component {
<ListItem <ListItem
title={I18n.t('Alert')} title={I18n.t('Alert')}
testID='notification-preference-view-alert' testID='notification-preference-view-alert'
right={() => this.renderPicker('desktopNotifications')} onPress={title => this.pickerSelection(title, 'desktopNotifications')}
right={() => this.renderPickerOption('desktopNotifications')}
theme={theme} theme={theme}
/> />
<Separator theme={theme} /> <Separator theme={theme} />
@ -296,7 +306,8 @@ class NotificationPreferencesView extends React.Component {
<ListItem <ListItem
title={I18n.t('Alert')} title={I18n.t('Alert')}
testID='notification-preference-view-push-notification' testID='notification-preference-view-push-notification'
right={() => this.renderPicker('mobilePushNotifications')} onPress={title => this.pickerSelection(title, 'mobilePushNotifications')}
right={() => this.renderPickerOption('mobilePushNotifications')}
theme={theme} theme={theme}
/> />
<Separator theme={theme} /> <Separator theme={theme} />
@ -309,21 +320,24 @@ class NotificationPreferencesView extends React.Component {
<ListItem <ListItem
title={I18n.t('Audio')} title={I18n.t('Audio')}
testID='notification-preference-view-audio' testID='notification-preference-view-audio'
right={() => this.renderPicker('audioNotifications')} onPress={title => this.pickerSelection(title, 'audioNotifications')}
right={() => this.renderPickerOption('audioNotifications')}
theme={theme} theme={theme}
/> />
<Separator theme={theme} /> <Separator theme={theme} />
<ListItem <ListItem
title={I18n.t('Sound')} title={I18n.t('Sound')}
testID='notification-preference-view-sound' testID='notification-preference-view-sound'
right={() => this.renderPicker('audioNotificationValue')} onPress={title => this.pickerSelection(title, 'audioNotificationValue')}
right={() => this.renderPickerOption('audioNotificationValue')}
theme={theme} theme={theme}
/> />
<Separator theme={theme} /> <Separator theme={theme} />
<ListItem <ListItem
title={I18n.t('Notification_Duration')} title={I18n.t('Notification_Duration')}
testID='notification-preference-view-notification-duration' testID='notification-preference-view-notification-duration'
right={() => this.renderPicker('desktopNotificationDuration')} onPress={title => this.pickerSelection(title, 'desktopNotificationDuration')}
right={() => this.renderPickerOption('desktopNotificationDuration')}
theme={theme} theme={theme}
/> />
<Separator theme={theme} /> <Separator theme={theme} />
@ -335,7 +349,8 @@ class NotificationPreferencesView extends React.Component {
<ListItem <ListItem
title={I18n.t('Alert')} title={I18n.t('Alert')}
testID='notification-preference-view-email-alert' testID='notification-preference-view-email-alert'
right={() => this.renderPicker('emailNotifications')} onPress={title => this.pickerSelection(title, 'emailNotifications')}
right={() => this.renderPickerOption('emailNotifications')}
theme={theme} theme={theme}
/> />
<Separator theme={theme} /> <Separator theme={theme} />

View File

@ -24,9 +24,6 @@ export default StyleSheet.create({
paddingVertical: 10, paddingVertical: 10,
fontSize: 14 fontSize: 14
}, },
viewContainer: {
justifyContent: 'center'
},
pickerText: { pickerText: {
...sharedStyles.textRegular, ...sharedStyles.textRegular,
fontSize: 16 fontSize: 16

96
app/views/PickerView.js Normal file
View File

@ -0,0 +1,96 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FlatList, StyleSheet } from 'react-native';
import I18n from '../i18n';
import { themedHeader } from '../utils/navigation';
import { withTheme } from '../theme';
import { themes } from '../constants/colors';
import sharedStyles from './Styles';
import ListItem from '../containers/ListItem';
import Check from '../containers/Check';
import Separator from '../containers/Separator';
const styles = StyleSheet.create({
check: {
marginHorizontal: 0
}
});
const Item = React.memo(({
item,
selected,
onItemPress,
theme
}) => (
<ListItem
title={item.label}
right={selected && (() => <Check theme={theme} style={styles.check} />)}
onPress={onItemPress}
theme={theme}
/>
));
Item.propTypes = {
item: PropTypes.object,
selected: PropTypes.bool,
onItemPress: PropTypes.func,
theme: PropTypes.string
};
class PickerView extends React.PureComponent {
static navigationOptions = ({ navigation, screenProps }) => ({
title: navigation.getParam('title', I18n.t('Select_an_option')),
...themedHeader(screenProps.theme)
})
static propTypes = {
navigation: PropTypes.object,
theme: PropTypes.string
}
constructor(props) {
super(props);
const data = props.navigation.getParam('data', []);
const value = props.navigation.getParam('value');
this.state = { data, value };
}
onChangeValue = (value) => {
const { navigation } = this.props;
const onChange = navigation.getParam('onChangeValue', () => {});
onChange(value);
navigation.goBack();
}
render() {
const { data, value } = this.state;
const { theme } = this.props;
return (
<FlatList
data={data}
keyExtractor={item => item.value}
renderItem={({ item }) => (
<Item
item={item}
theme={theme}
selected={(value || data[0]?.value) === item.value}
onItemPress={() => this.onChangeValue(item.value)}
/>
)}
ItemSeparatorComponent={() => <Separator theme={theme} />}
contentContainerStyle={[
sharedStyles.listContentContainer,
{
backgroundColor: themes[theme].auxiliaryBackground,
borderColor: themes[theme].separatorColor
}
]}
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
/>
);
}
}
export default withTheme(PickerView);