Rocket.Chat.ReactNative/app/views/SettingsView/index.js

357 lines
10 KiB
JavaScript
Raw Normal View History

2018-06-05 01:17:02 +00:00
import React from 'react';
import {
2020-02-05 15:12:40 +00:00
View, Linking, ScrollView, AsyncStorage, Switch, Text, Share, Clipboard
} from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
2020-02-05 15:12:40 +00:00
import { SafeAreaView } from 'react-navigation';
2018-06-05 01:17:02 +00:00
2020-02-05 15:12:40 +00:00
import { logout as logoutAction, loginRequest as loginRequestAction } from '../../actions/login';
import { toggleCrashReport as toggleCrashReportAction } from '../../actions/crashReport';
2019-12-04 16:39:53 +00:00
import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors';
2019-11-25 20:01:17 +00:00
import { DrawerButton, CloseModalButton } from '../../containers/HeaderButton';
2019-03-12 16:23:06 +00:00
import StatusBar from '../../containers/StatusBar';
import ListItem from '../../containers/ListItem';
import { DisclosureImage } from '../../containers/DisclosureIndicator';
import Separator from '../../containers/Separator';
import I18n from '../../i18n';
import RocketChat, { CRASH_REPORT_KEY } from '../../lib/rocketchat';
2019-11-25 20:01:17 +00:00
import {
getReadableVersion, getDeviceModel, isAndroid
} from '../../utils/deviceInfo';
import openLink from '../../utils/openLink';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { showErrorAlert, showConfirmationAlert } from '../../utils/info';
import styles from './styles';
import sharedStyles from '../Styles';
import { loggerConfig, analytics } from '../../utils/log';
2019-08-08 18:28:51 +00:00
import { PLAY_MARKET_LINK, APP_STORE_LINK, LICENSE_LINK } from '../../constants/links';
2019-12-04 16:39:53 +00:00
import { withTheme } from '../../theme';
import { themedHeader } from '../../utils/navigation';
2019-11-25 20:01:17 +00:00
import SidebarView from '../SidebarView';
import { withSplit } from '../../split';
import Navigation from '../../lib/Navigation';
import { LISTENER } from '../../containers/Toast';
import EventEmitter from '../../utils/events';
2020-02-05 15:12:40 +00:00
import { appStart as appStartAction } from '../../actions';
2020-02-03 18:28:18 +00:00
import { onReviewPress } from '../../utils/review';
2020-02-11 14:09:14 +00:00
import { getUserSelector } from '../../selectors/login';
2019-12-04 16:39:53 +00:00
const SectionSeparator = React.memo(({ theme }) => (
<View
style={[
styles.sectionSeparatorBorder,
{
borderColor: themes[theme].separatorColor,
backgroundColor: themes[theme].auxiliaryBackground
}
]}
/>
));
SectionSeparator.propTypes = {
theme: PropTypes.string
};
const ItemInfo = React.memo(({ info, theme }) => (
<View style={[styles.infoContainer, { backgroundColor: themes[theme].auxiliaryBackground }]}>
<Text style={[styles.infoText, { color: themes[theme].infoText }]}>{info}</Text>
</View>
));
ItemInfo.propTypes = {
2019-12-04 16:39:53 +00:00
info: PropTypes.string,
theme: PropTypes.string
};
2018-06-05 01:17:02 +00:00
class SettingsView extends React.Component {
2019-11-25 20:01:17 +00:00
static navigationOptions = ({ navigation, screenProps }) => ({
2019-12-04 16:39:53 +00:00
...themedHeader(screenProps.theme),
2019-11-25 20:01:17 +00:00
headerLeft: screenProps.split ? (
<CloseModalButton navigation={navigation} testID='settings-view-close' />
) : (
<DrawerButton navigation={navigation} />
),
2019-03-12 16:23:06 +00:00
title: I18n.t('Settings')
});
static propTypes = {
navigation: PropTypes.object,
server: PropTypes.object,
allowCrashReport: PropTypes.bool,
2019-11-25 20:01:17 +00:00
toggleCrashReport: PropTypes.func,
2019-12-04 16:39:53 +00:00
theme: PropTypes.string,
2019-11-25 20:01:17 +00:00
split: PropTypes.bool,
2020-02-05 15:12:40 +00:00
logout: PropTypes.func.isRequired,
loginRequest: PropTypes.func,
token: PropTypes.string,
appStart: PropTypes.func
2019-11-25 20:01:17 +00:00
}
handleLogout = () => {
showConfirmationAlert({
message: I18n.t('You_will_be_logged_out_of_this_application'),
callToAction: I18n.t('Logout'),
onPress: () => {
const { logout, split } = this.props;
if (split) {
Navigation.navigate('RoomView');
}
logout();
}
});
}
handleClearCache = () => {
showConfirmationAlert({
message: I18n.t('This_will_clear_all_your_offline_data'),
callToAction: I18n.t('Clear'),
onPress: async() => {
const {
server: { server }, loginRequest, token, appStart
} = this.props;
await appStart('loading', I18n.t('Clear_cache_loading'));
await RocketChat.clearCache({ server });
await loginRequest({ resume: token }, true);
}
});
2020-02-05 15:12:40 +00:00
}
toggleCrashReport = (value) => {
AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
const { toggleCrashReport } = this.props;
toggleCrashReport(value);
loggerConfig.autoNotify = value;
analytics().setAnalyticsCollectionEnabled(value);
if (value) {
loggerConfig.clearBeforeSendCallbacks();
} else {
loggerConfig.registerBeforeSendCallback(() => false);
}
}
navigateToScreen = (screen) => {
const { navigation } = this.props;
navigation.navigate(screen);
}
sendEmail = async() => {
const subject = encodeURI('React Native App Support');
const email = encodeURI('support@rocket.chat');
const description = encodeURI(`
version: ${ getReadableVersion }
device: ${ getDeviceModel }
`);
try {
await Linking.openURL(`mailto:${ email }?subject=${ subject }&body=${ description }`);
} catch (e) {
showErrorAlert(I18n.t('error-email-send-failed', { message: 'support@rocket.chat' }));
}
2018-06-05 01:17:02 +00:00
}
2019-08-08 18:28:51 +00:00
shareApp = () => {
Share.share({ message: isAndroid ? PLAY_MARKET_LINK : APP_STORE_LINK });
}
copyServerVersion = () => {
const { server } = this.props;
this.saveToClipboard(server.version);
}
copyAppVersion = () => {
this.saveToClipboard(getReadableVersion);
}
saveToClipboard = async(content) => {
await Clipboard.setString(content);
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
}
2019-12-04 16:39:53 +00:00
onPressLicense = () => {
const { theme } = this.props;
openLink(LICENSE_LINK, theme);
}
2019-12-04 16:39:53 +00:00
renderDisclosure = () => {
const { theme } = this.props;
return <DisclosureImage theme={theme} />;
}
renderCrashReportSwitch = () => {
const { allowCrashReport } = this.props;
return (
<Switch
value={allowCrashReport}
trackColor={SWITCH_TRACK_COLOR}
onValueChange={this.toggleCrashReport}
/>
);
}
2018-06-05 01:17:02 +00:00
render() {
2019-12-04 16:39:53 +00:00
const { server, split, theme } = this.props;
2018-06-05 01:17:02 +00:00
return (
2019-12-04 16:39:53 +00:00
<SafeAreaView
style={[sharedStyles.container, { backgroundColor: themes[theme].auxiliaryBackground }]}
testID='settings-view'
2020-02-05 15:12:40 +00:00
forceInset={{ vertical: 'never' }}
2019-12-04 16:39:53 +00:00
>
<StatusBar theme={theme} />
<ScrollView
{...scrollPersistTaps}
2020-02-05 15:12:40 +00:00
contentContainerStyle={styles.listPadding}
showsVerticalScrollIndicator={false}
testID='settings-view-list'
>
2019-11-25 20:01:17 +00:00
{split ? (
<>
2020-02-05 15:12:40 +00:00
<Separator theme={theme} />
2019-12-04 16:39:53 +00:00
<SidebarView theme={theme} />
<SectionSeparator theme={theme} />
2019-11-25 20:01:17 +00:00
<ListItem
title={I18n.t('Profile')}
onPress={() => this.navigateToScreen('ProfileView')}
2019-11-25 20:01:17 +00:00
showActionIndicator
testID='settings-profile'
right={this.renderDisclosure}
2019-12-04 16:39:53 +00:00
theme={theme}
2019-11-25 20:01:17 +00:00
/>
</>
) : null}
2020-02-05 15:12:40 +00:00
<Separator theme={theme} />
<ListItem
title={I18n.t('Contact_us')}
onPress={this.sendEmail}
showActionIndicator
testID='settings-view-contact'
right={this.renderDisclosure}
2019-12-04 16:39:53 +00:00
theme={theme}
/>
2019-12-04 16:39:53 +00:00
<Separator theme={theme} />
<ListItem
title={I18n.t('Language')}
onPress={() => this.navigateToScreen('LanguageView')}
showActionIndicator
testID='settings-view-language'
right={this.renderDisclosure}
2019-12-04 16:39:53 +00:00
theme={theme}
/>
2019-12-04 16:39:53 +00:00
<Separator theme={theme} />
2020-02-03 18:28:18 +00:00
<ListItem
title={I18n.t('Review_this_app')}
showActionIndicator
onPress={onReviewPress}
testID='settings-view-review-app'
right={this.renderDisclosure}
theme={theme}
/>
<Separator theme={theme} />
<ListItem
2019-09-24 20:15:13 +00:00
title={I18n.t('Share_this_app')}
showActionIndicator
2019-09-24 20:15:13 +00:00
onPress={this.shareApp}
testID='settings-view-share-app'
right={this.renderDisclosure}
2019-12-04 16:39:53 +00:00
theme={theme}
/>
2019-12-04 16:39:53 +00:00
<Separator theme={theme} />
<ListItem
title={I18n.t('Default_browser')}
showActionIndicator
onPress={() => this.navigateToScreen('DefaultBrowserView')}
testID='settings-view-default-browser'
right={this.renderDisclosure}
theme={theme}
/>
<Separator theme={theme} />
<ListItem
2019-09-24 20:15:13 +00:00
title={I18n.t('Theme')}
showActionIndicator
onPress={() => this.navigateToScreen('ThemeView')}
2019-09-24 20:15:13 +00:00
testID='settings-view-theme'
2019-12-04 16:39:53 +00:00
right={this.renderDisclosure}
theme={theme}
/>
2019-12-04 16:39:53 +00:00
<SectionSeparator theme={theme} />
<ListItem
title={I18n.t('License')}
onPress={this.onPressLicense}
showActionIndicator
testID='settings-view-license'
right={this.renderDisclosure}
2019-12-04 16:39:53 +00:00
theme={theme}
/>
2019-12-04 16:39:53 +00:00
<Separator theme={theme} />
<ListItem
title={I18n.t('Version_no', { version: getReadableVersion })}
onPress={this.copyAppVersion}
testID='settings-view-version'
theme={theme}
/>
2019-12-04 16:39:53 +00:00
<Separator theme={theme} />
<ListItem
title={I18n.t('Server_version', { version: server.version })}
onPress={this.copyServerVersion}
subtitle={`${ server.server.split('//')[1] }`}
testID='settings-view-server-version'
2019-12-04 16:39:53 +00:00
theme={theme}
/>
2019-12-04 16:39:53 +00:00
<SectionSeparator theme={theme} />
<ListItem
title={I18n.t('Send_crash_report')}
testID='settings-view-crash-report'
right={() => this.renderCrashReportSwitch()}
2019-12-04 16:39:53 +00:00
theme={theme}
/>
2019-12-04 16:39:53 +00:00
<Separator theme={theme} />
<ItemInfo
info={I18n.t('Crash_report_disclaimer')}
2019-12-04 16:39:53 +00:00
theme={theme}
/>
2019-11-25 20:01:17 +00:00
2020-02-05 15:12:40 +00:00
<Separator theme={theme} />
<ListItem
title={I18n.t('Clear_cache')}
testID='settings-clear-cache'
onPress={this.handleClearCache}
2020-02-05 15:12:40 +00:00
right={this.renderDisclosure}
color={themes[theme].dangerColor}
theme={theme}
/>
<Separator theme={theme} />
<ListItem
title={I18n.t('Logout')}
testID='settings-logout'
onPress={this.handleLogout}
2020-02-05 15:12:40 +00:00
right={this.renderDisclosure}
color={themes[theme].dangerColor}
theme={theme}
/>
<Separator theme={theme} />
</ScrollView>
</SafeAreaView>
2018-06-05 01:17:02 +00:00
);
}
}
const mapStateToProps = state => ({
server: state.server,
2020-02-11 14:09:14 +00:00
token: getUserSelector(state).token,
allowCrashReport: state.crashReport.allowCrashReport
});
const mapDispatchToProps = dispatch => ({
2019-11-25 20:01:17 +00:00
logout: () => dispatch(logoutAction()),
2020-02-05 15:12:40 +00:00
loginRequest: (...params) => dispatch(loginRequestAction(...params)),
toggleCrashReport: params => dispatch(toggleCrashReportAction(params)),
appStart: (...params) => dispatch(appStartAction(...params))
});
2019-12-04 16:39:53 +00:00
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(withSplit(SettingsView)));