diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index 0790b7bad..70555acb8 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -53,8 +53,6 @@ export const LOGOUT = 'LOGOUT'; // logout is always success export const SNIPPETED_MESSAGES = createRequestTypes('SNIPPETED_MESSAGES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']); export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN']); export const SORT_PREFERENCES = createRequestTypes('SORT_PREFERENCES', ['SET_ALL', 'SET']); -export const TOGGLE_CRASH_REPORT = 'TOGGLE_CRASH_REPORT'; -export const TOGGLE_ANALYTICS_EVENTS = 'TOGGLE_ANALYTICS_EVENTS'; export const SET_CUSTOM_EMOJIS = 'SET_CUSTOM_EMOJIS'; export const SET_ACTIVE_USERS = 'SET_ACTIVE_USERS'; export const USERS_TYPING = createRequestTypes('USERS_TYPING', ['ADD', 'REMOVE', 'CLEAR']); diff --git a/app/actions/crashReport.js b/app/actions/crashReport.js deleted file mode 100644 index 8577b33e7..000000000 --- a/app/actions/crashReport.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as types from './actionsTypes'; - -export function toggleCrashReport(value) { - return { - type: types.TOGGLE_CRASH_REPORT, - payload: value - }; -} - -export function toggleAnalyticsEvents(value) { - return { - type: types.TOGGLE_ANALYTICS_EVENTS, - payload: value - }; -} diff --git a/app/containers/UIKit/MultiSelect/index.js b/app/containers/UIKit/MultiSelect/index.js index 0d366b6d7..d1e42aaa5 100644 --- a/app/containers/UIKit/MultiSelect/index.js +++ b/app/containers/UIKit/MultiSelect/index.js @@ -157,7 +157,7 @@ export const MultiSelect = React.memo(({ disabled={disabled} inputStyle={inputStyle} > - {items.length ? : {placeholder.text}} + {items.length ? (disabled ? {} : onSelect(item))} theme={theme} /> : {placeholder.text}} ); } diff --git a/app/index.js b/app/index.js index efcf1557e..54985c3c5 100644 --- a/app/index.js +++ b/app/index.js @@ -19,7 +19,7 @@ import { deepLinkingOpen } from './actions/deepLinking'; import parseQuery from './lib/methods/helpers/parseQuery'; import { initializePushNotifications, onNotification } from './notifications/push'; import store from './lib/createStore'; -import { loggerConfig, analytics } from './utils/log'; +import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './utils/log'; import { ThemeContext } from './theme'; import { DimensionsContext } from './dimensions'; import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat'; @@ -188,11 +188,11 @@ export default class Root extends React.Component { initCrashReport = () => { RocketChat.getAllowCrashReport() .then((allowCrashReport) => { - if (!allowCrashReport) { - loggerConfig.autoNotify = false; - loggerConfig.registerBeforeSendCallback(() => false); - analytics().setAnalyticsCollectionEnabled(false); - } + toggleCrashErrorsReport(allowCrashReport); + }); + RocketChat.getAllowAnalyticsEvents() + .then((allowAnalyticsEvents) => { + toggleAnalyticsEventsReport(allowAnalyticsEvents); }); } diff --git a/app/lib/methods/getPermissions.js b/app/lib/methods/getPermissions.js index 1c4c56b46..764b725e0 100644 --- a/app/lib/methods/getPermissions.js +++ b/app/lib/methods/getPermissions.js @@ -48,7 +48,9 @@ const PERMISSIONS = [ 'view-user-administration', 'view-all-teams', 'view-all-team-channels', - 'convert-team' + 'convert-team', + 'edit-omnichannel-contact', + 'edit-livechat-room-customfields' ]; export async function setPermissions() { diff --git a/app/reducers/crashReport.js b/app/reducers/crashReport.js deleted file mode 100644 index 8465897e3..000000000 --- a/app/reducers/crashReport.js +++ /dev/null @@ -1,25 +0,0 @@ -import { TOGGLE_CRASH_REPORT, TOGGLE_ANALYTICS_EVENTS } from '../actions/actionsTypes'; - -const initialState = { - allowCrashReport: false, - allowAnalyticsEvents: false -}; - - -export default (state = initialState, action) => { - switch (action.type) { - case TOGGLE_CRASH_REPORT: - return { - ...state, - allowCrashReport: action.payload - }; - - case TOGGLE_ANALYTICS_EVENTS: - return { - ...state, - allowAnalyticsEvents: action.payload - }; - default: - return state; - } -}; diff --git a/app/reducers/index.js b/app/reducers/index.js index eb8f09d82..c0f5a9953 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -10,7 +10,6 @@ import createChannel from './createChannel'; import app from './app'; import sortPreferences from './sortPreferences'; import share from './share'; -import crashReport from './crashReport'; import customEmojis from './customEmojis'; import activeUsers from './activeUsers'; import usersTyping from './usersTyping'; @@ -35,7 +34,6 @@ export default combineReducers({ rooms, sortPreferences, share, - crashReport, customEmojis, activeUsers, usersTyping, diff --git a/app/sagas/init.js b/app/sagas/init.js index 57bc33423..f8cce6804 100644 --- a/app/sagas/init.js +++ b/app/sagas/init.js @@ -4,7 +4,6 @@ import RNBootSplash from 'react-native-bootsplash'; import UserPreferences from '../lib/userPreferences'; import { selectServerRequest } from '../actions/server'; import { setAllPreferences } from '../actions/sortPreferences'; -import { toggleCrashReport, toggleAnalyticsEvents } from '../actions/crashReport'; import { APP } from '../actions/actionsTypes'; import RocketChat from '../lib/rocketchat'; import log from '../utils/log'; @@ -15,12 +14,6 @@ import { appStart, ROOT_OUTSIDE, appReady } from '../actions/app'; export const initLocalSettings = function* initLocalSettings() { const sortPreferences = yield RocketChat.getSortPreferences(); yield put(setAllPreferences(sortPreferences)); - - const allowCrashReport = yield RocketChat.getAllowCrashReport(); - yield put(toggleCrashReport(allowCrashReport)); - - const allowAnalyticsEvents = yield RocketChat.getAllowAnalyticsEvents(); - yield put(toggleAnalyticsEvents(allowAnalyticsEvents)); }; const restore = function* restore() { diff --git a/app/utils/log/index.js b/app/utils/log/index.js index 361ce7055..266f4bd44 100644 --- a/app/utils/log/index.js +++ b/app/utils/log/index.js @@ -5,10 +5,24 @@ import events from './events'; const analytics = firebaseAnalytics || ''; let bugsnag = ''; let crashlytics; +let reportCrashErrors = true; +let reportAnalyticsEvents = true; + +export const getReportCrashErrorsValue = () => reportCrashErrors; +export const getReportAnalyticsEventsValue = () => reportAnalyticsEvents; + if (!isFDroidBuild) { bugsnag = require('@bugsnag/react-native').default; - bugsnag.start(); + bugsnag.start({ + onBreadcrumb() { + return reportAnalyticsEvents; + }, + onError(error) { + if (!reportAnalyticsEvents) { error.breadcrumbs = []; } + return reportCrashErrors; + } + }); crashlytics = require('@react-native-firebase/crashlytics').default; } @@ -42,6 +56,16 @@ export const setCurrentScreen = (currentScreen) => { } }; +export const toggleCrashErrorsReport = (value) => { + crashlytics().setCrashlyticsCollectionEnabled(value); + return reportCrashErrors = value; +}; + +export const toggleAnalyticsEventsReport = (value) => { + analytics().setAnalyticsCollectionEnabled(value); + return reportAnalyticsEvents = value; +}; + export default (e) => { if (e instanceof Error && bugsnag && e.message !== 'Aborted' && !__DEV__) { bugsnag.notify(e, (event) => { diff --git a/app/views/LivechatEditView.js b/app/views/LivechatEditView.js index 6ba4143e7..d5bae1a15 100644 --- a/app/views/LivechatEditView.js +++ b/app/views/LivechatEditView.js @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { Text, StyleSheet, ScrollView } from 'react-native'; import { connect } from 'react-redux'; +import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit'; import { withTheme } from '../theme'; import { themes } from '../constants/colors'; @@ -15,9 +16,9 @@ import { LISTENER } from '../containers/Toast'; import EventEmitter from '../utils/events'; import scrollPersistTaps from '../utils/scrollPersistTaps'; import { getUserSelector } from '../selectors/login'; -import Chips from '../containers/UIKit/MultiSelect/Chips'; import Button from '../containers/Button'; import SafeAreaView from '../containers/SafeAreaView'; +import { MultiSelect } from '../containers/UIKit/MultiSelect'; const styles = StyleSheet.create({ container: { @@ -27,6 +28,14 @@ const styles = StyleSheet.create({ fontSize: 20, paddingVertical: 10, ...sharedStyles.textMedium + }, + label: { + marginBottom: 10, + fontSize: 14, + ...sharedStyles.textSemibold + }, + multiSelect: { + marginBottom: 10 } }); @@ -37,10 +46,11 @@ Title.propTypes = { }; const LivechatEditView = ({ - user, navigation, route, theme + user, navigation, route, theme, editOmnichannelContact, editLivechatRoomCustomfields }) => { const [customFields, setCustomFields] = useState({}); const [availableUserTags, setAvailableUserTags] = useState([]); + const [permissions, setPermissions] = useState([]); const params = {}; const inputs = {}; @@ -54,21 +64,24 @@ const LivechatEditView = ({ const visitorCustomFields = result.customFields .filter(field => field.visibility !== 'hidden' && field.scope === 'visitor') .map(field => ({ [field._id]: (visitor.livechatData && visitor.livechatData[field._id]) || '' })) - .reduce((ret, field) => ({ [field]: field, ...ret })); + .reduce((ret, field) => ({ ...field, ...ret })); const livechatCustomFields = result.customFields .filter(field => field.visibility !== 'hidden' && field.scope === 'room') .map(field => ({ [field._id]: (livechat.livechatData && livechat.livechatData[field._id]) || '' })) - .reduce((ret, field) => ({ [field]: field, ...ret })); + .reduce((ret, field) => ({ ...field, ...ret })); return setCustomFields({ visitor: visitorCustomFields, livechat: livechatCustomFields }); } }; const [tagParam, setTags] = useState(livechat?.tags || []); + const [tagParamSelected, setTagParamSelected] = useState(livechat?.tags || []); useEffect(() => { - setTags([...tagParam, ...availableUserTags]); + const arr = [...tagParam, ...availableUserTags]; + const uniqueArray = arr.filter((val, i) => arr.indexOf(val) === i); + setTags(uniqueArray); }, [availableUserTags]); const getTagsList = async(agentDepartments) => { @@ -115,7 +128,7 @@ const LivechatEditView = ({ roomData.topic = params.topic; } - roomData.tags = tagParam; + roomData.tags = tagParamSelected; roomData.livechatData = {}; Object.entries(customFields?.livechat || {}).forEach(([key]) => { @@ -139,9 +152,15 @@ const LivechatEditView = ({ const onChangeText = (key, text) => { params[key] = text; }; + const getPermissions = async() => { + const permissionsArray = await RocketChat.hasPermission([editOmnichannelContact, editLivechatRoomCustomfields], livechat.rid); + setPermissions(permissionsArray); + }; + useEffect(() => { getAgentDepartments(); getCustomFields(); + getPermissions(); }, []); return ( @@ -162,6 +181,7 @@ const LivechatEditView = ({ onChangeText={text => onChangeText('name', text)} onSubmitEditing={() => { inputs.name.focus(); }} theme={theme} + editable={!!permissions[0]} /> onChangeText('email', text)} onSubmitEditing={() => { inputs.phone.focus(); }} theme={theme} + editable={!!permissions[0]} /> { const keys = Object.keys(customFields?.visitor || {}); if (keys.length > 0) { - const key = keys.pop(); + const key = keys[0]; inputs[key].focus(); } else { inputs.topic.focus(); } }} theme={theme} + editable={!!permissions[0]} /> {Object.entries(customFields?.visitor || {}).map(([key, value], index, array) => ( onChangeText(key, text)} onSubmitEditing={() => { if (array.length - 1 > index) { - return inputs[array[index + 1]].focus(); + return inputs[array[index + 1][0]].focus(); } inputs.topic.focus(); }} theme={theme} + editable={!!permissions[0]} /> ))} onChangeText('topic', text)} onSubmitEditing={() => inputs.tags.focus()} theme={theme} + editable={!!permissions[1]} /> - <TextInput - inputRef={(e) => { inputs.tags = e; }} - label={I18n.t('Tags')} - iconRight='add' - onIconRightPress={() => { - const lastText = inputs.tags._lastNativeText || ''; - if (lastText.length) { - setTags([...tagParam.filter(t => t !== lastText), lastText]); - inputs.tags.clear(); - } - }} - onSubmitEditing={() => { - const keys = Object.keys(customFields?.livechat || {}); - if (keys.length > 0) { - const key = keys.pop(); - inputs[key].focus(); - } else { - submit(); - } + <Text + style={[ + styles.label, + { color: themes[theme].titleText } + ]} + > + { I18n.t('Tags') } + </Text> + <MultiSelect + options={tagParam.map(tag => ({ text: { text: tag }, value: tag }))} + onChange={({ value }) => { + setTagParamSelected([...value]); }} + placeholder={{ text: I18n.t('Tags') }} + value={tagParamSelected} + context={BLOCK_CONTEXT.FORM} + multiselect theme={theme} - /> - <Chips - items={tagParam.map(tag => ({ text: { text: tag }, value: tag }))} - onSelect={tag => setTags(tagParam.filter(t => t !== tag.value) || [])} - style={{ backgroundColor: themes[theme].backgroundColor }} - theme={theme} + disabled={!permissions[1]} + inputStyle={styles.multiSelect} /> {Object.entries(customFields?.livechat || {}).map(([key, value], index, array) => ( @@ -257,6 +274,7 @@ const LivechatEditView = ({ submit(); }} theme={theme} + editable={!!permissions[1]} /> ))} @@ -274,15 +292,19 @@ LivechatEditView.propTypes = { user: PropTypes.object, navigation: PropTypes.object, route: PropTypes.object, - theme: PropTypes.string + theme: PropTypes.string, + editOmnichannelContact: PropTypes.array, + editLivechatRoomCustomfields: PropTypes.array }; LivechatEditView.navigationOptions = ({ - title: I18n.t('Livechat_edit') + title: I18n.t('Edit') }); const mapStateToProps = state => ({ server: state.server.server, - user: getUserSelector(state) + user: getUserSelector(state), + editOmnichannelContact: state.permissions['edit-omnichannel-contact'], + editLivechatRoomCustomfields: state.permissions['edit-livechat-room-customfields'] }); export default connect(mapStateToProps)(withTheme(LivechatEditView)); diff --git a/app/views/RoomInfoView/index.js b/app/views/RoomInfoView/index.js index a966463bf..6d0918f16 100644 --- a/app/views/RoomInfoView/index.js +++ b/app/views/RoomInfoView/index.js @@ -55,6 +55,8 @@ class RoomInfoView extends React.Component { isMasterDetail: PropTypes.bool, jitsiEnabled: PropTypes.bool, editRoomPermission: PropTypes.array, + editOmnichannelContact: PropTypes.array, + editLivechatRoomCustomfields: PropTypes.array, roles: PropTypes.array } @@ -184,7 +186,9 @@ class RoomInfoView extends React.Component { loadRoom = async() => { const { room: roomState } = this.state; - const { route, editRoomPermission } = this.props; + const { + route, editRoomPermission, editOmnichannelContact, editLivechatRoomCustomfields + } = this.props; let room = route.params?.room; if (room && room.observe) { this.roomObservable = room.observe(); @@ -204,8 +208,10 @@ class RoomInfoView extends React.Component { } } - const permissions = await RocketChat.hasPermission([editRoomPermission], room.rid); - if (permissions[0]) { + const permissionToEdit = this.isLivechat ? [editOmnichannelContact, editLivechatRoomCustomfields] : [editRoomPermission]; + + const permissions = await RocketChat.hasPermission(permissionToEdit, room.rid); + if (permissions.some(Boolean)) { this.setState({ showEdit: true }, () => this.setHeader()); } } @@ -370,6 +376,8 @@ const mapStateToProps = state => ({ isMasterDetail: state.app.isMasterDetail, jitsiEnabled: state.settings.Jitsi_Enabled || false, editRoomPermission: state.permissions['edit-room'], + editOmnichannelContact: state.permissions['edit-omnichannel-contact'], + editLivechatRoomCustomfields: state.permissions['edit-livechat-room-customfields'], roles: state.roles }); diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index d6e94a9a0..d03d4488a 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -739,7 +739,7 @@ class RoomView extends React.Component { const { room } = this.state; if (rid === this.rid) { Navigation.navigate('RoomsListView'); - showErrorAlert(I18n.t('You_were_removed_from_channel', { channel: RocketChat.getRoomTitle(room) }), I18n.t('Oops')); + !this.isOmnichannel && showErrorAlert(I18n.t('You_were_removed_from_channel', { channel: RocketChat.getRoomTitle(room) }), I18n.t('Oops')); } } @@ -786,6 +786,7 @@ class RoomView extends React.Component { if (this.isOmnichannel) { await takeInquiry(room._id); + this.onJoin(); } else { const { joinCodeRequired } = room; if (joinCodeRequired) { diff --git a/app/views/SecurityPrivacyView.js b/app/views/SecurityPrivacyView.js index 937a02504..a21ae00fd 100644 --- a/app/views/SecurityPrivacyView.js +++ b/app/views/SecurityPrivacyView.js @@ -1,158 +1,119 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Switch } from 'react-native'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; import AsyncStorage from '@react-native-community/async-storage'; +import { useSelector } from 'react-redux'; -import { toggleCrashReport as toggleCrashReportAction, toggleAnalyticsEvents as toggleAnalyticsEventsAction } from '../actions/crashReport'; import { SWITCH_TRACK_COLOR } from '../constants/colors'; import StatusBar from '../containers/StatusBar'; import * as List from '../containers/List'; import I18n from '../i18n'; import { CRASH_REPORT_KEY, ANALYTICS_EVENTS_KEY } from '../lib/rocketchat'; import { - loggerConfig, analytics, logEvent, events + logEvent, events, toggleCrashErrorsReport, toggleAnalyticsEventsReport, getReportCrashErrorsValue, getReportAnalyticsEventsValue } from '../utils/log'; import SafeAreaView from '../containers/SafeAreaView'; import { isFDroidBuild } from '../constants/environment'; -import { getUserSelector } from '../selectors/login'; -class SecurityPrivacyView extends React.Component { - static navigationOptions = () => ({ - title: I18n.t('Security_and_privacy') - }); +const SecurityPrivacyView = ({ navigation }) => { + const [crashReportState, setCrashReportState] = useState(getReportCrashErrorsValue()); + const [analyticsEventsState, setAnalyticsEventsState] = useState(getReportAnalyticsEventsValue()); - static propTypes = { - navigation: PropTypes.object, - allowCrashReport: PropTypes.bool, - allowAnalyticsEvents: PropTypes.bool, - e2eEnabled: PropTypes.bool, - toggleCrashReport: PropTypes.func, - toggleAnalyticsEvents: PropTypes.func, - user: PropTypes.shape({ - roles: PropTypes.array, - id: PropTypes.string - }) - } + const { e2eEnabled } = useSelector(state => state.settings); - toggleCrashReport = (value) => { + useEffect(() => { + navigation.setOptions({ + title: I18n.t('Security_and_privacy') + }); + }, []); + + const toggleCrashReport = (value) => { logEvent(events.SE_TOGGLE_CRASH_REPORT); AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value)); - const { toggleCrashReport } = this.props; - toggleCrashReport(value); - if (!isFDroidBuild) { - loggerConfig.autoNotify = value; - if (value) { - loggerConfig.clearBeforeSendCallbacks(); - } else { - loggerConfig.registerBeforeSendCallback(() => false); - } - } - } + setCrashReportState(value); + toggleCrashErrorsReport(value); + }; - toggleAnalyticsEvents = (value) => { + const toggleAnalyticsEvents = (value) => { logEvent(events.SE_TOGGLE_ANALYTICS_EVENTS); - const { toggleAnalyticsEvents } = this.props; AsyncStorage.setItem(ANALYTICS_EVENTS_KEY, JSON.stringify(value)); - toggleAnalyticsEvents(value); - analytics().setAnalyticsCollectionEnabled(value); - } + setAnalyticsEventsState(value); + toggleAnalyticsEventsReport(value); + }; - navigateToScreen = (screen) => { + const navigateToScreen = (screen) => { logEvent(events[`SP_GO_${ screen.replace('View', '').toUpperCase() }`]); - const { navigation } = this.props; navigation.navigate(screen); - } + }; - renderCrashReportSwitch = () => { - const { allowCrashReport } = this.props; - return ( - <Switch - value={allowCrashReport} - trackColor={SWITCH_TRACK_COLOR} - onValueChange={this.toggleCrashReport} - /> - ); - } + return ( + <SafeAreaView testID='security-privacy-view'> + <StatusBar /> + <List.Container testID='security-privacy-view-list'> + <List.Section> + <List.Separator /> + {e2eEnabled + ? ( + <> + <List.Item + title='E2E_Encryption' + showActionIndicator + onPress={() => navigateToScreen('E2EEncryptionSecurityView')} + testID='security-privacy-view-e2e-encryption' + /> + <List.Separator /> + </> + ) + : null + } + <List.Item + title='Screen_lock' + showActionIndicator + onPress={() => navigateToScreen('ScreenLockConfigView')} + testID='security-privacy-view-screen-lock' + /> + <List.Separator /> + </List.Section> - renderAnalyticsEventsSwitch = () => { - const { allowAnalyticsEvents } = this.props; - return ( - <Switch - value={allowAnalyticsEvents} - trackColor={SWITCH_TRACK_COLOR} - onValueChange={this.toggleAnalyticsEvents} - /> - ); - } - - render() { - const { e2eEnabled } = this.props; - return ( - <SafeAreaView testID='security-privacy-view'> - <StatusBar /> - <List.Container testID='security-privacy-view-list'> - <List.Section> - <List.Separator /> - {e2eEnabled - ? ( - <> - <List.Item - title='E2E_Encryption' - showActionIndicator - onPress={() => this.navigateToScreen('E2EEncryptionSecurityView')} - testID='security-privacy-view-e2e-encryption' + {!isFDroidBuild ? ( + <> + <List.Section> + <List.Separator /> + <List.Item + title='Log_analytics_events' + testID='security-privacy-view-analytics-events' + right={() => ( + <Switch + value={analyticsEventsState} + trackColor={SWITCH_TRACK_COLOR} + onValueChange={toggleAnalyticsEvents} /> - <List.Separator /> - </> - ) - : null - } - <List.Item - title='Screen_lock' - showActionIndicator - onPress={() => this.navigateToScreen('ScreenLockConfigView')} - testID='security-privacy-view-screen-lock' - /> - <List.Separator /> - </List.Section> + )} + /> + <List.Separator /> + <List.Item + title='Send_crash_report' + testID='security-privacy-view-crash-report' + right={() => ( + <Switch + value={crashReportState} + trackColor={SWITCH_TRACK_COLOR} + onValueChange={toggleCrashReport} + /> + )} + /> + <List.Separator /> + <List.Info info='Crash_report_disclaimer' /> + </List.Section> + </> + ) : null} + </List.Container> + </SafeAreaView> + ); +}; - {!isFDroidBuild ? ( - <> - <List.Section> - <List.Separator /> - <List.Item - title='Log_analytics_events' - testID='security-privacy-view-analytics-events' - right={() => this.renderAnalyticsEventsSwitch()} - /> - <List.Separator /> - <List.Item - title='Send_crash_report' - testID='security-privacy-view-crash-report' - right={() => this.renderCrashReportSwitch()} - /> - <List.Separator /> - <List.Info info='Crash_report_disclaimer' /> - </List.Section> - </> - ) : null} - </List.Container> - </SafeAreaView> - ); - } -} +SecurityPrivacyView.propTypes = { + navigation: PropTypes.object +}; -const mapStateToProps = state => ({ - user: getUserSelector(state), - allowCrashReport: state.crashReport.allowCrashReport, - allowAnalyticsEvents: state.crashReport.allowAnalyticsEvents, - e2eEnabled: state.settings.E2E_Enable -}); - -const mapDispatchToProps = dispatch => ({ - toggleCrashReport: params => dispatch(toggleCrashReportAction(params)), - toggleAnalyticsEvents: params => dispatch(toggleAnalyticsEventsAction(params)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(SecurityPrivacyView); +export default SecurityPrivacyView;