Merge branch 'develop' into new.add-discusions-roomactionsview

This commit is contained in:
Gerzon Z 2021-08-23 15:01:45 -04:00 committed by GitHub
commit 618eb53932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 196 additions and 229 deletions

View File

@ -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 SNIPPETED_MESSAGES = createRequestTypes('SNIPPETED_MESSAGES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']);
export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN']); export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN']);
export const SORT_PREFERENCES = createRequestTypes('SORT_PREFERENCES', ['SET_ALL', 'SET']); 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_CUSTOM_EMOJIS = 'SET_CUSTOM_EMOJIS';
export const SET_ACTIVE_USERS = 'SET_ACTIVE_USERS'; export const SET_ACTIVE_USERS = 'SET_ACTIVE_USERS';
export const USERS_TYPING = createRequestTypes('USERS_TYPING', ['ADD', 'REMOVE', 'CLEAR']); export const USERS_TYPING = createRequestTypes('USERS_TYPING', ['ADD', 'REMOVE', 'CLEAR']);

View File

@ -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
};
}

View File

@ -157,7 +157,7 @@ export const MultiSelect = React.memo(({
disabled={disabled} disabled={disabled}
inputStyle={inputStyle} inputStyle={inputStyle}
> >
{items.length ? <Chips items={items} onSelect={onSelect} theme={theme} /> : <Text style={[styles.pickerText, { color: themes[theme].auxiliaryText }]}>{placeholder.text}</Text>} {items.length ? <Chips items={items} onSelect={item => (disabled ? {} : onSelect(item))} theme={theme} /> : <Text style={[styles.pickerText, { color: themes[theme].auxiliaryText }]}>{placeholder.text}</Text>}
</Input> </Input>
); );
} }

View File

@ -19,7 +19,7 @@ import { deepLinkingOpen } from './actions/deepLinking';
import parseQuery from './lib/methods/helpers/parseQuery'; import parseQuery from './lib/methods/helpers/parseQuery';
import { initializePushNotifications, onNotification } from './notifications/push'; import { initializePushNotifications, onNotification } from './notifications/push';
import store from './lib/createStore'; import store from './lib/createStore';
import { loggerConfig, analytics } from './utils/log'; import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './utils/log';
import { ThemeContext } from './theme'; import { ThemeContext } from './theme';
import { DimensionsContext } from './dimensions'; import { DimensionsContext } from './dimensions';
import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat'; import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat';
@ -188,11 +188,11 @@ export default class Root extends React.Component {
initCrashReport = () => { initCrashReport = () => {
RocketChat.getAllowCrashReport() RocketChat.getAllowCrashReport()
.then((allowCrashReport) => { .then((allowCrashReport) => {
if (!allowCrashReport) { toggleCrashErrorsReport(allowCrashReport);
loggerConfig.autoNotify = false; });
loggerConfig.registerBeforeSendCallback(() => false); RocketChat.getAllowAnalyticsEvents()
analytics().setAnalyticsCollectionEnabled(false); .then((allowAnalyticsEvents) => {
} toggleAnalyticsEventsReport(allowAnalyticsEvents);
}); });
} }

View File

@ -48,7 +48,9 @@ const PERMISSIONS = [
'view-user-administration', 'view-user-administration',
'view-all-teams', 'view-all-teams',
'view-all-team-channels', 'view-all-team-channels',
'convert-team' 'convert-team',
'edit-omnichannel-contact',
'edit-livechat-room-customfields'
]; ];
export async function setPermissions() { export async function setPermissions() {

View File

@ -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;
}
};

View File

@ -10,7 +10,6 @@ import createChannel from './createChannel';
import app from './app'; import app from './app';
import sortPreferences from './sortPreferences'; import sortPreferences from './sortPreferences';
import share from './share'; import share from './share';
import crashReport from './crashReport';
import customEmojis from './customEmojis'; import customEmojis from './customEmojis';
import activeUsers from './activeUsers'; import activeUsers from './activeUsers';
import usersTyping from './usersTyping'; import usersTyping from './usersTyping';
@ -35,7 +34,6 @@ export default combineReducers({
rooms, rooms,
sortPreferences, sortPreferences,
share, share,
crashReport,
customEmojis, customEmojis,
activeUsers, activeUsers,
usersTyping, usersTyping,

View File

@ -4,7 +4,6 @@ import RNBootSplash from 'react-native-bootsplash';
import UserPreferences from '../lib/userPreferences'; import UserPreferences from '../lib/userPreferences';
import { selectServerRequest } from '../actions/server'; import { selectServerRequest } from '../actions/server';
import { setAllPreferences } from '../actions/sortPreferences'; import { setAllPreferences } from '../actions/sortPreferences';
import { toggleCrashReport, toggleAnalyticsEvents } from '../actions/crashReport';
import { APP } from '../actions/actionsTypes'; import { APP } from '../actions/actionsTypes';
import RocketChat from '../lib/rocketchat'; import RocketChat from '../lib/rocketchat';
import log from '../utils/log'; import log from '../utils/log';
@ -15,12 +14,6 @@ import { appStart, ROOT_OUTSIDE, appReady } from '../actions/app';
export const initLocalSettings = function* initLocalSettings() { export const initLocalSettings = function* initLocalSettings() {
const sortPreferences = yield RocketChat.getSortPreferences(); const sortPreferences = yield RocketChat.getSortPreferences();
yield put(setAllPreferences(sortPreferences)); 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() { const restore = function* restore() {

View File

@ -5,10 +5,24 @@ import events from './events';
const analytics = firebaseAnalytics || ''; const analytics = firebaseAnalytics || '';
let bugsnag = ''; let bugsnag = '';
let crashlytics; let crashlytics;
let reportCrashErrors = true;
let reportAnalyticsEvents = true;
export const getReportCrashErrorsValue = () => reportCrashErrors;
export const getReportAnalyticsEventsValue = () => reportAnalyticsEvents;
if (!isFDroidBuild) { if (!isFDroidBuild) {
bugsnag = require('@bugsnag/react-native').default; 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; 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) => { export default (e) => {
if (e instanceof Error && bugsnag && e.message !== 'Aborted' && !__DEV__) { if (e instanceof Error && bugsnag && e.message !== 'Aborted' && !__DEV__) {
bugsnag.notify(e, (event) => { bugsnag.notify(e, (event) => {

View File

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Text, StyleSheet, ScrollView } from 'react-native'; import { Text, StyleSheet, ScrollView } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
import { withTheme } from '../theme'; import { withTheme } from '../theme';
import { themes } from '../constants/colors'; import { themes } from '../constants/colors';
@ -15,9 +16,9 @@ import { LISTENER } from '../containers/Toast';
import EventEmitter from '../utils/events'; import EventEmitter from '../utils/events';
import scrollPersistTaps from '../utils/scrollPersistTaps'; import scrollPersistTaps from '../utils/scrollPersistTaps';
import { getUserSelector } from '../selectors/login'; import { getUserSelector } from '../selectors/login';
import Chips from '../containers/UIKit/MultiSelect/Chips';
import Button from '../containers/Button'; import Button from '../containers/Button';
import SafeAreaView from '../containers/SafeAreaView'; import SafeAreaView from '../containers/SafeAreaView';
import { MultiSelect } from '../containers/UIKit/MultiSelect';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
@ -27,6 +28,14 @@ const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
paddingVertical: 10, paddingVertical: 10,
...sharedStyles.textMedium ...sharedStyles.textMedium
},
label: {
marginBottom: 10,
fontSize: 14,
...sharedStyles.textSemibold
},
multiSelect: {
marginBottom: 10
} }
}); });
@ -37,10 +46,11 @@ Title.propTypes = {
}; };
const LivechatEditView = ({ const LivechatEditView = ({
user, navigation, route, theme user, navigation, route, theme, editOmnichannelContact, editLivechatRoomCustomfields
}) => { }) => {
const [customFields, setCustomFields] = useState({}); const [customFields, setCustomFields] = useState({});
const [availableUserTags, setAvailableUserTags] = useState([]); const [availableUserTags, setAvailableUserTags] = useState([]);
const [permissions, setPermissions] = useState([]);
const params = {}; const params = {};
const inputs = {}; const inputs = {};
@ -54,21 +64,24 @@ const LivechatEditView = ({
const visitorCustomFields = result.customFields const visitorCustomFields = result.customFields
.filter(field => field.visibility !== 'hidden' && field.scope === 'visitor') .filter(field => field.visibility !== 'hidden' && field.scope === 'visitor')
.map(field => ({ [field._id]: (visitor.livechatData && visitor.livechatData[field._id]) || '' })) .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 const livechatCustomFields = result.customFields
.filter(field => field.visibility !== 'hidden' && field.scope === 'room') .filter(field => field.visibility !== 'hidden' && field.scope === 'room')
.map(field => ({ [field._id]: (livechat.livechatData && livechat.livechatData[field._id]) || '' })) .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 }); return setCustomFields({ visitor: visitorCustomFields, livechat: livechatCustomFields });
} }
}; };
const [tagParam, setTags] = useState(livechat?.tags || []); const [tagParam, setTags] = useState(livechat?.tags || []);
const [tagParamSelected, setTagParamSelected] = useState(livechat?.tags || []);
useEffect(() => { useEffect(() => {
setTags([...tagParam, ...availableUserTags]); const arr = [...tagParam, ...availableUserTags];
const uniqueArray = arr.filter((val, i) => arr.indexOf(val) === i);
setTags(uniqueArray);
}, [availableUserTags]); }, [availableUserTags]);
const getTagsList = async(agentDepartments) => { const getTagsList = async(agentDepartments) => {
@ -115,7 +128,7 @@ const LivechatEditView = ({
roomData.topic = params.topic; roomData.topic = params.topic;
} }
roomData.tags = tagParam; roomData.tags = tagParamSelected;
roomData.livechatData = {}; roomData.livechatData = {};
Object.entries(customFields?.livechat || {}).forEach(([key]) => { Object.entries(customFields?.livechat || {}).forEach(([key]) => {
@ -139,9 +152,15 @@ const LivechatEditView = ({
const onChangeText = (key, text) => { params[key] = text; }; const onChangeText = (key, text) => { params[key] = text; };
const getPermissions = async() => {
const permissionsArray = await RocketChat.hasPermission([editOmnichannelContact, editLivechatRoomCustomfields], livechat.rid);
setPermissions(permissionsArray);
};
useEffect(() => { useEffect(() => {
getAgentDepartments(); getAgentDepartments();
getCustomFields(); getCustomFields();
getPermissions();
}, []); }, []);
return ( return (
@ -162,6 +181,7 @@ const LivechatEditView = ({
onChangeText={text => onChangeText('name', text)} onChangeText={text => onChangeText('name', text)}
onSubmitEditing={() => { inputs.name.focus(); }} onSubmitEditing={() => { inputs.name.focus(); }}
theme={theme} theme={theme}
editable={!!permissions[0]}
/> />
<TextInput <TextInput
label={I18n.t('Email')} label={I18n.t('Email')}
@ -170,6 +190,7 @@ const LivechatEditView = ({
onChangeText={text => onChangeText('email', text)} onChangeText={text => onChangeText('email', text)}
onSubmitEditing={() => { inputs.phone.focus(); }} onSubmitEditing={() => { inputs.phone.focus(); }}
theme={theme} theme={theme}
editable={!!permissions[0]}
/> />
<TextInput <TextInput
label={I18n.t('Phone')} label={I18n.t('Phone')}
@ -179,13 +200,14 @@ const LivechatEditView = ({
onSubmitEditing={() => { onSubmitEditing={() => {
const keys = Object.keys(customFields?.visitor || {}); const keys = Object.keys(customFields?.visitor || {});
if (keys.length > 0) { if (keys.length > 0) {
const key = keys.pop(); const key = keys[0];
inputs[key].focus(); inputs[key].focus();
} else { } else {
inputs.topic.focus(); inputs.topic.focus();
} }
}} }}
theme={theme} theme={theme}
editable={!!permissions[0]}
/> />
{Object.entries(customFields?.visitor || {}).map(([key, value], index, array) => ( {Object.entries(customFields?.visitor || {}).map(([key, value], index, array) => (
<TextInput <TextInput
@ -195,11 +217,12 @@ const LivechatEditView = ({
onChangeText={text => onChangeText(key, text)} onChangeText={text => onChangeText(key, text)}
onSubmitEditing={() => { onSubmitEditing={() => {
if (array.length - 1 > index) { if (array.length - 1 > index) {
return inputs[array[index + 1]].focus(); return inputs[array[index + 1][0]].focus();
} }
inputs.topic.focus(); inputs.topic.focus();
}} }}
theme={theme} theme={theme}
editable={!!permissions[0]}
/> />
))} ))}
<Title <Title
@ -213,35 +236,29 @@ const LivechatEditView = ({
onChangeText={text => onChangeText('topic', text)} onChangeText={text => onChangeText('topic', text)}
onSubmitEditing={() => inputs.tags.focus()} onSubmitEditing={() => inputs.tags.focus()}
theme={theme} theme={theme}
editable={!!permissions[1]}
/> />
<TextInput <Text
inputRef={(e) => { inputs.tags = e; }} style={[
label={I18n.t('Tags')} styles.label,
iconRight='add' { color: themes[theme].titleText }
onIconRightPress={() => { ]}
const lastText = inputs.tags._lastNativeText || ''; >
if (lastText.length) { { I18n.t('Tags') }
setTags([...tagParam.filter(t => t !== lastText), lastText]); </Text>
inputs.tags.clear(); <MultiSelect
} options={tagParam.map(tag => ({ text: { text: tag }, value: tag }))}
}} onChange={({ value }) => {
onSubmitEditing={() => { setTagParamSelected([...value]);
const keys = Object.keys(customFields?.livechat || {});
if (keys.length > 0) {
const key = keys.pop();
inputs[key].focus();
} else {
submit();
}
}} }}
placeholder={{ text: I18n.t('Tags') }}
value={tagParamSelected}
context={BLOCK_CONTEXT.FORM}
multiselect
theme={theme} theme={theme}
/> disabled={!permissions[1]}
<Chips inputStyle={styles.multiSelect}
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}
/> />
{Object.entries(customFields?.livechat || {}).map(([key, value], index, array) => ( {Object.entries(customFields?.livechat || {}).map(([key, value], index, array) => (
@ -257,6 +274,7 @@ const LivechatEditView = ({
submit(); submit();
}} }}
theme={theme} theme={theme}
editable={!!permissions[1]}
/> />
))} ))}
@ -274,15 +292,19 @@ LivechatEditView.propTypes = {
user: PropTypes.object, user: PropTypes.object,
navigation: PropTypes.object, navigation: PropTypes.object,
route: PropTypes.object, route: PropTypes.object,
theme: PropTypes.string theme: PropTypes.string,
editOmnichannelContact: PropTypes.array,
editLivechatRoomCustomfields: PropTypes.array
}; };
LivechatEditView.navigationOptions = ({ LivechatEditView.navigationOptions = ({
title: I18n.t('Livechat_edit') title: I18n.t('Edit')
}); });
const mapStateToProps = state => ({ const mapStateToProps = state => ({
server: state.server.server, 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)); export default connect(mapStateToProps)(withTheme(LivechatEditView));

View File

@ -55,6 +55,8 @@ class RoomInfoView extends React.Component {
isMasterDetail: PropTypes.bool, isMasterDetail: PropTypes.bool,
jitsiEnabled: PropTypes.bool, jitsiEnabled: PropTypes.bool,
editRoomPermission: PropTypes.array, editRoomPermission: PropTypes.array,
editOmnichannelContact: PropTypes.array,
editLivechatRoomCustomfields: PropTypes.array,
roles: PropTypes.array roles: PropTypes.array
} }
@ -184,7 +186,9 @@ class RoomInfoView extends React.Component {
loadRoom = async() => { loadRoom = async() => {
const { room: roomState } = this.state; const { room: roomState } = this.state;
const { route, editRoomPermission } = this.props; const {
route, editRoomPermission, editOmnichannelContact, editLivechatRoomCustomfields
} = this.props;
let room = route.params?.room; let room = route.params?.room;
if (room && room.observe) { if (room && room.observe) {
this.roomObservable = room.observe(); this.roomObservable = room.observe();
@ -204,8 +208,10 @@ class RoomInfoView extends React.Component {
} }
} }
const permissions = await RocketChat.hasPermission([editRoomPermission], room.rid); const permissionToEdit = this.isLivechat ? [editOmnichannelContact, editLivechatRoomCustomfields] : [editRoomPermission];
if (permissions[0]) {
const permissions = await RocketChat.hasPermission(permissionToEdit, room.rid);
if (permissions.some(Boolean)) {
this.setState({ showEdit: true }, () => this.setHeader()); this.setState({ showEdit: true }, () => this.setHeader());
} }
} }
@ -370,6 +376,8 @@ const mapStateToProps = state => ({
isMasterDetail: state.app.isMasterDetail, isMasterDetail: state.app.isMasterDetail,
jitsiEnabled: state.settings.Jitsi_Enabled || false, jitsiEnabled: state.settings.Jitsi_Enabled || false,
editRoomPermission: state.permissions['edit-room'], editRoomPermission: state.permissions['edit-room'],
editOmnichannelContact: state.permissions['edit-omnichannel-contact'],
editLivechatRoomCustomfields: state.permissions['edit-livechat-room-customfields'],
roles: state.roles roles: state.roles
}); });

View File

@ -739,7 +739,7 @@ class RoomView extends React.Component {
const { room } = this.state; const { room } = this.state;
if (rid === this.rid) { if (rid === this.rid) {
Navigation.navigate('RoomsListView'); 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) { if (this.isOmnichannel) {
await takeInquiry(room._id); await takeInquiry(room._id);
this.onJoin();
} else { } else {
const { joinCodeRequired } = room; const { joinCodeRequired } = room;
if (joinCodeRequired) { if (joinCodeRequired) {

View File

@ -1,158 +1,119 @@
import React from 'react'; import React, { useEffect, useState } from 'react';
import { Switch } from 'react-native'; import { Switch } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import AsyncStorage from '@react-native-community/async-storage'; 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 { SWITCH_TRACK_COLOR } from '../constants/colors';
import StatusBar from '../containers/StatusBar'; import StatusBar from '../containers/StatusBar';
import * as List from '../containers/List'; import * as List from '../containers/List';
import I18n from '../i18n'; import I18n from '../i18n';
import { CRASH_REPORT_KEY, ANALYTICS_EVENTS_KEY } from '../lib/rocketchat'; import { CRASH_REPORT_KEY, ANALYTICS_EVENTS_KEY } from '../lib/rocketchat';
import { import {
loggerConfig, analytics, logEvent, events logEvent, events, toggleCrashErrorsReport, toggleAnalyticsEventsReport, getReportCrashErrorsValue, getReportAnalyticsEventsValue
} from '../utils/log'; } from '../utils/log';
import SafeAreaView from '../containers/SafeAreaView'; import SafeAreaView from '../containers/SafeAreaView';
import { isFDroidBuild } from '../constants/environment'; import { isFDroidBuild } from '../constants/environment';
import { getUserSelector } from '../selectors/login';
class SecurityPrivacyView extends React.Component { const SecurityPrivacyView = ({ navigation }) => {
static navigationOptions = () => ({ const [crashReportState, setCrashReportState] = useState(getReportCrashErrorsValue());
title: I18n.t('Security_and_privacy') const [analyticsEventsState, setAnalyticsEventsState] = useState(getReportAnalyticsEventsValue());
});
static propTypes = { const { e2eEnabled } = useSelector(state => state.settings);
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
})
}
toggleCrashReport = (value) => { useEffect(() => {
navigation.setOptions({
title: I18n.t('Security_and_privacy')
});
}, []);
const toggleCrashReport = (value) => {
logEvent(events.SE_TOGGLE_CRASH_REPORT); logEvent(events.SE_TOGGLE_CRASH_REPORT);
AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value)); AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
const { toggleCrashReport } = this.props; setCrashReportState(value);
toggleCrashReport(value); toggleCrashErrorsReport(value);
if (!isFDroidBuild) { };
loggerConfig.autoNotify = value;
if (value) {
loggerConfig.clearBeforeSendCallbacks();
} else {
loggerConfig.registerBeforeSendCallback(() => false);
}
}
}
toggleAnalyticsEvents = (value) => { const toggleAnalyticsEvents = (value) => {
logEvent(events.SE_TOGGLE_ANALYTICS_EVENTS); logEvent(events.SE_TOGGLE_ANALYTICS_EVENTS);
const { toggleAnalyticsEvents } = this.props;
AsyncStorage.setItem(ANALYTICS_EVENTS_KEY, JSON.stringify(value)); AsyncStorage.setItem(ANALYTICS_EVENTS_KEY, JSON.stringify(value));
toggleAnalyticsEvents(value); setAnalyticsEventsState(value);
analytics().setAnalyticsCollectionEnabled(value); toggleAnalyticsEventsReport(value);
} };
navigateToScreen = (screen) => { const navigateToScreen = (screen) => {
logEvent(events[`SP_GO_${ screen.replace('View', '').toUpperCase() }`]); logEvent(events[`SP_GO_${ screen.replace('View', '').toUpperCase() }`]);
const { navigation } = this.props;
navigation.navigate(screen); navigation.navigate(screen);
} };
renderCrashReportSwitch = () => { return (
const { allowCrashReport } = this.props; <SafeAreaView testID='security-privacy-view'>
return ( <StatusBar />
<Switch <List.Container testID='security-privacy-view-list'>
value={allowCrashReport} <List.Section>
trackColor={SWITCH_TRACK_COLOR} <List.Separator />
onValueChange={this.toggleCrashReport} {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 = () => { {!isFDroidBuild ? (
const { allowAnalyticsEvents } = this.props; <>
return ( <List.Section>
<Switch <List.Separator />
value={allowAnalyticsEvents} <List.Item
trackColor={SWITCH_TRACK_COLOR} title='Log_analytics_events'
onValueChange={this.toggleAnalyticsEvents} testID='security-privacy-view-analytics-events'
/> right={() => (
); <Switch
} value={analyticsEventsState}
trackColor={SWITCH_TRACK_COLOR}
render() { onValueChange={toggleAnalyticsEvents}
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'
/> />
<List.Separator /> )}
</> />
) <List.Separator />
: null <List.Item
} title='Send_crash_report'
<List.Item testID='security-privacy-view-crash-report'
title='Screen_lock' right={() => (
showActionIndicator <Switch
onPress={() => this.navigateToScreen('ScreenLockConfigView')} value={crashReportState}
testID='security-privacy-view-screen-lock' trackColor={SWITCH_TRACK_COLOR}
/> onValueChange={toggleCrashReport}
<List.Separator /> />
</List.Section> )}
/>
<List.Separator />
<List.Info info='Crash_report_disclaimer' />
</List.Section>
</>
) : null}
</List.Container>
</SafeAreaView>
);
};
{!isFDroidBuild ? ( SecurityPrivacyView.propTypes = {
<> navigation: PropTypes.object
<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>
);
}
}
const mapStateToProps = state => ({ export default SecurityPrivacyView;
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);