Merge branch 'develop' into new.add-discusions-roomactionsview
This commit is contained in:
commit
618eb53932
|
@ -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']);
|
||||||
|
|
|
@ -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
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
12
app/index.js
12
app/index.js
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
Loading…
Reference in New Issue