diff --git a/app/screens/advanced_settings/advanced_settings.js b/app/screens/advanced_settings/advanced_settings.js new file mode 100644 index 000000000..da7f38e42 --- /dev/null +++ b/app/screens/advanced_settings/advanced_settings.js @@ -0,0 +1,160 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React, {PureComponent} from 'react'; +import PropTypes from 'prop-types'; +import {injectIntl, intlShape} from 'react-intl'; +import { + Alert, + TouchableOpacity, + StyleSheet, + View +} from 'react-native'; +import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; + +import FormattedText from 'app/components/formatted_text'; +import StatusBar from 'app/components/status_bar'; +import {preventDoubleTap} from 'app/utils/tap'; +import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; + +class AdvancedSettings extends PureComponent { + static propTypes = { + actions: PropTypes.shape({ + purgeOfflineStore: PropTypes.func.isRequired + }).isRequired, + intl: intlShape.isRequired, + theme: PropTypes.object + }; + + buildItemRow = (icon, id, defaultMessage, action, separator = true, nextArrow = false) => { + const {theme} = this.props; + const style = getStyleSheet(theme); + + return ( + + this.handlePress(action)} + > + + + + + {nextArrow && + + } + + {separator && } + + ); + }; + + clearOfflineCache = () => { + const {actions, intl} = this.props; + + Alert.alert( + intl.formatMessage({id: 'mobile.advanced_settings.reset_title', defaultMessage: 'Reset Cache'}), + intl.formatMessage({id: 'mobile.advanced_settings.reset_message', defaultMessage: '\nThis will reset all offline data and restart the app. You will be automatically logged back in once the app restarts.\n'}), + [{ + text: intl.formatMessage({id: 'mobile.advanced_settings.reset_button', defaultMessage: 'Reset'}), + onPress: () => actions.purgeOfflineStore() + }, { + text: intl.formatMessage({id: 'channel_modal.cancel', defaultMessage: 'Cancel'}), + onPress: () => true + }] + ); + }; + + handlePress = (action) => { + preventDoubleTap(action, this); + }; + + renderItems = () => { + return [ + this.buildItemRow('storage', 'mobile.advanced_settings.reset_title', 'Reset Cache', this.clearOfflineCache, false, false) + ]; + }; + + render() { + const {theme} = this.props; + const style = getStyleSheet(theme); + + return ( + + + + + {this.renderItems()} + + + + ); + } +} + +const getStyleSheet = makeStyleSheetFromTheme((theme) => { + return StyleSheet.create({ + container: { + flex: 1, + backgroundColor: changeOpacity(theme.centerChannelColor, 0.03) + }, + item: { + height: 45, + flexDirection: 'row', + alignItems: 'center' + }, + itemLeftIcon: { + color: changeOpacity(theme.centerChannelColor, 0.5) + }, + itemLeftIconContainer: { + width: 18, + marginRight: 15, + alignItems: 'center', + justifyContent: 'center' + }, + itemText: { + fontSize: 16, + color: theme.centerChannelColor, + flex: 1 + }, + itemRightIcon: { + color: changeOpacity(theme.centerChannelColor, 0.5) + }, + itemsContainer: { + marginTop: 30, + backgroundColor: theme.centerChannelBg, + borderTopWidth: 1, + borderBottomWidth: 1, + borderTopColor: changeOpacity(theme.centerChannelColor, 0.1), + borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1) + }, + itemWrapper: { + marginHorizontal: 15 + }, + separator: { + height: 1, + backgroundColor: changeOpacity(theme.centerChannelColor, 0.1) + }, + wrapper: { + flex: 1, + backgroundColor: theme.centerChannelBg + } + }); +}); + +export default injectIntl(AdvancedSettings); diff --git a/app/screens/advanced_settings/index.js b/app/screens/advanced_settings/index.js new file mode 100644 index 000000000..c12ccf971 --- /dev/null +++ b/app/screens/advanced_settings/index.js @@ -0,0 +1,27 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {bindActionCreators} from 'redux'; +import {connect} from 'react-redux'; + +import {purgeOfflineStore} from 'app/actions/views/root'; +import {getTheme} from 'app/selectors/preferences'; + +import AdvancedSettings from './advanced_settings'; + +function mapStateToProps(state, ownProps) { + return { + ...ownProps, + theme: getTheme(state) + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + purgeOfflineStore + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(AdvancedSettings); diff --git a/app/screens/index.js b/app/screens/index.js index bb216b6f8..63c64a151 100644 --- a/app/screens/index.js +++ b/app/screens/index.js @@ -7,6 +7,7 @@ import {Navigation} from 'react-native-navigation'; import About from 'app/screens/about'; import AccountSettings from 'app/screens/account_settings'; import AccountNotifications from 'app/screens/account_notifications'; +import AdvancedSettings from 'app/screens/advanced_settings'; import Channel from 'app/screens/channel'; import ChannelAddMembers from 'app/screens/channel_add_members'; import ChannelInfo from 'app/screens/channel_info'; @@ -51,6 +52,7 @@ export function registerScreens(store, Provider) { Navigation.registerComponent('About', () => wrapWithContextProvider(About), store, Provider); Navigation.registerComponent('AccountSettings', () => wrapWithContextProvider(AccountSettings), store, Provider); Navigation.registerComponent('AccountNotifications', () => wrapWithContextProvider(AccountNotifications), store, Provider); + Navigation.registerComponent('AdvancedSettings', () => wrapWithContextProvider(AdvancedSettings), store, Provider); Navigation.registerComponent('Channel', () => wrapWithContextProvider(Channel), store, Provider); Navigation.registerComponent('ChannelAddMembers', () => wrapWithContextProvider(ChannelAddMembers), store, Provider); Navigation.registerComponent('ChannelInfo', () => wrapWithContextProvider(ChannelInfo), store, Provider); diff --git a/app/screens/settings/settings.js b/app/screens/settings/settings.js index 3bcd0d361..b72728520 100644 --- a/app/screens/settings/settings.js +++ b/app/screens/settings/settings.js @@ -5,7 +5,6 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import {injectIntl, intlShape} from 'react-intl'; import { - Alert, InteractionManager, Linking, Platform, @@ -100,6 +99,22 @@ class Settings extends PureComponent { }); }; + goToAdvancedSettings = () => { + const {intl, navigator, theme} = this.props; + navigator.push({ + screen: 'AdvancedSettings', + title: intl.formatMessage({id: 'mobile.advanced_settings.title', defaultMessage: 'Advanced Settings'}), + animated: true, + backButtonTitle: '', + navigatorStyle: { + navBarTextColor: theme.sidebarHeaderTextColor, + navBarBackgroundColor: theme.sidebarHeaderBg, + navBarButtonColor: theme.sidebarHeaderTextColor, + screenBackgroundColor: theme.centerChannelBg + } + }); + }; + goToSelectTeam = () => { const {currentUrl, intl, navigator, theme} = this.props; @@ -155,22 +170,6 @@ class Settings extends PureComponent { Linking.openURL(config.HelpLink.toLowerCase()); }; - clearOfflineCache = () => { - const {actions, intl} = this.props; - - Alert.alert( - intl.formatMessage({id: 'mobile.settings.clear', defaultMessage: 'Clear Offline Store'}), - intl.formatMessage({id: 'mobile.settings.clear_message', defaultMessage: '\nThis will clear all offline data and restart the app. You will be automatically logged back in once the app restarts.\n'}), - [{ - text: intl.formatMessage({id: 'mobile.settings.clear_button', defaultMessage: 'Clear'}), - onPress: () => actions.purgeOfflineStore() - }, { - text: intl.formatMessage({id: 'channel_modal.cancel', defaultMessage: 'Cancel'}), - onPress: () => true - }] - ); - } - render() { const {config, joinableTeams, theme} = this.props; const style = getStyleSheet(theme); @@ -196,7 +195,7 @@ class Settings extends PureComponent { i18nId='mobile.select_team.join_open' iconName='group' iconType='material' - onPress={() => preventDoubleTap(this.goToSelectTeam, this)} + onPress={() => this.handlePress(this.goToSelectTeam)} separator={true} theme={theme} /> @@ -222,11 +221,11 @@ class Settings extends PureComponent { theme={theme} /> this.handlePress(this.clearOfflineCache)} + defaultMessage='Advanced Settings' + i18nId='mobile.advanced_settings.title' + iconName='ios-construct' + iconType='ion' + onPress={() => this.handlePress(this.goToAdvancedSettings)} separator={true} theme={theme} /> diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index 5d002477a..e08cf0096 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -1709,6 +1709,10 @@ "mobile.account_notifications.threads_mentions": "Mentions in threads", "mobile.account_notifications.threads_start": "Threads that I start", "mobile.account_notifications.threads_start_participate": "Threads that I start or participate in", + "mobile.advanced_settings.reset_title": "Reset Cache", + "mobile.advanced_settings.reset_button": "Reset", + "mobile.advanced_settings.reset_message": "\nThis will reset all offline data and restart the app. You will be automatically logged back in once the app restarts.\n", + "mobile.advanced_settings.title": "Advanced Settings", "mobile.channel_drawer.search": "Jump to a conversation", "mobile.channel_info.alertMessageDeleteChannel": "Are you sure you want to delete the {term} {name}?", "mobile.channel_info.alertMessageLeaveChannel": "Are you sure you want to leave the {term} {name}?", @@ -1806,9 +1810,6 @@ "mobile.server_upgrade.title": "Server upgrade required", "mobile.server_url.invalid_format": "URL must start with http:// or https://", "mobile.session_expired": "Session Expired: Please log in to continue receiving notifications.", - "mobile.settings.clear": "Clear Offline Store", - "mobile.settings.clear_button": "Clear", - "mobile.settings.clear_message": "\nThis will clear all offline data and restart the app. You will be automatically logged back in once the app restarts.\n", "mobile.settings.team_selection": "Team Selection", "mobile.suggestion.members": "Members", "modal.manaul_status.ask": "Do not ask me again",