diff --git a/app/ee/LICENSE b/app/ee/LICENSE new file mode 100644 index 000000000..38288b74c --- /dev/null +++ b/app/ee/LICENSE @@ -0,0 +1,43 @@ +The Rocket.Chat Enterprise Edition (EE) license (the "EE License") +Copyright (c) 2015-2020 Rocket.Chat Technologies Corp. + +With regard to the Rocket.Chat Software: + +This software and associated documentation files (the "Software") may only be +used in production, if you (and any entity that you represent) have agreed to, +and are in compliance with, the Rocket.Chat Subscription Terms of Service, +available at https://rocket.chat/terms (the "EE Terms"), or other agreement +governing the use of the Software, as agreed by you and Rocket.Chat, and otherwise +have a valid Rocket.Chat Enterprise Edition subscription for the correct number +of user seats. Subject to the foregoing sentence, you are free to modify this +Software and publish patches to the Software. You agree that Rocket.Chat and/or +its licensors (as applicable) retain all right, title and interest in and to all +such modifications and/or patches, and all such modifications and/or patches may +only be used, copied, modified, displayed, distributed, or otherwise exploited +with a valid Rocket.Chat Enterprise Edition subscription for the correct number +of user seats. Notwithstanding the foregoing, you may copy and modify the Software +for development and testing purposes, without requiring a Subscription. You agree +that Rocket.Chat and/or its licensors (as applicable) retain all right, title and +interest in and to all such modifications. You are not granted any other rights +beyond what is expressly stated herein. Subject to the foregoing, it is forbidden +to copy, merge, publish, distribute, sublicense, and/or sell the Software. + +This EE License applies only to the part of this Software that is not distributed +as part of Rocket.Chat Community Edition (CE). Any part of this Software distributed +as part of Rocket.Chat CE or is served client-side as an image, font, cascading +stylesheet (CSS), file which produces or is compiled, arranged, augmented, or combined +into client-side JavaScript, in whole or in part, is copyrighted under the MIT Expat +license. The full text of this EE License shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +For all third-party components incorporated into the Rocket.Chat Software, +those components are licensed under the original license provided by the owner +of the applicable component. \ No newline at end of file diff --git a/app/ee/README.md b/app/ee/README.md new file mode 100644 index 000000000..568825f93 --- /dev/null +++ b/app/ee/README.md @@ -0,0 +1,4 @@ +### How to remove ee folder + +If you're willing to remove Enterprise Edition features from your app, follow this diff: +https://github.com/RocketChat/Rocket.Chat.ReactNative/compare/develop...no-ee?expand=1 \ No newline at end of file diff --git a/app/actions/inquiry.js b/app/ee/omnichannel/actions/inquiry.js similarity index 93% rename from app/actions/inquiry.js rename to app/ee/omnichannel/actions/inquiry.js index 0f3402119..ef3e88c13 100644 --- a/app/actions/inquiry.js +++ b/app/ee/omnichannel/actions/inquiry.js @@ -1,4 +1,4 @@ -import * as types from './actionsTypes'; +import * as types from '../../../actions/actionsTypes'; export function inquirySetEnabled(enabled) { return { diff --git a/app/views/RoomsListView/ListHeader/OmnichannelStatus.js b/app/ee/omnichannel/containers/OmnichannelStatus.js similarity index 87% rename from app/views/RoomsListView/ListHeader/OmnichannelStatus.js rename to app/ee/omnichannel/containers/OmnichannelStatus.js index cc3df2ad9..b0763d76e 100644 --- a/app/views/RoomsListView/ListHeader/OmnichannelStatus.js +++ b/app/ee/omnichannel/containers/OmnichannelStatus.js @@ -7,11 +7,12 @@ import PropTypes from 'prop-types'; import Touch from '../../../utils/touch'; import { CustomIcon } from '../../../lib/Icons'; import I18n from '../../../i18n'; -import styles from '../styles'; +import styles from '../../../views/RoomsListView/styles'; import { themes, SWITCH_TRACK_COLOR } from '../../../constants/colors'; import { withTheme } from '../../../theme'; import UnreadBadge from '../../../presentation/UnreadBadge'; import RocketChat from '../../../lib/rocketchat'; +import { isOmnichannelStatusAvailable, changeLivechatStatus } from '../lib'; const OmnichannelStatus = memo(({ searching, goQueue, theme, queueSize, inquiryEnabled, user @@ -19,16 +20,16 @@ const OmnichannelStatus = memo(({ if (searching > 0 || !(RocketChat.isOmnichannelModuleAvailable() && user?.roles?.includes('livechat-agent'))) { return null; } - const [status, setStatus] = useState(user?.statusLivechat === 'available'); + const [status, setStatus] = useState(isOmnichannelStatusAvailable(user)); useEffect(() => { - setStatus(user.statusLivechat === 'available'); + setStatus(isOmnichannelStatusAvailable(user)); }, [user.statusLivechat]); const toggleLivechat = async() => { try { setStatus(v => !v); - await RocketChat.changeLivechatStatus(); + await changeLivechatStatus(); } catch { setStatus(v => !v); } diff --git a/app/ee/omnichannel/lib/index.js b/app/ee/omnichannel/lib/index.js new file mode 100644 index 000000000..7492675eb --- /dev/null +++ b/app/ee/omnichannel/lib/index.js @@ -0,0 +1,40 @@ +import subscribeInquiry from './subscriptions/inquiry'; +import RocketChat from '../../../lib/rocketchat'; +import EventEmitter from '../../../utils/events'; + +export const isOmnichannelStatusAvailable = user => user?.statusLivechat === 'available'; + +// RC 0.26.0 +export const changeLivechatStatus = () => RocketChat.methodCallWrapper('livechat:changeLivechatStatus'); + +// RC 2.4.0 +export const getInquiriesQueued = () => RocketChat.sdk.get('livechat/inquiries.queued'); + +// this inquiry is added to the db by the subscriptions stream +// and will be removed by the queue stream +// RC 2.4.0 +export const takeInquiry = inquiryId => RocketChat.methodCallWrapper('livechat:takeInquiry', inquiryId); + +class Omnichannel { + constructor() { + this.inquirySub = null; + EventEmitter.addEventListener('INQUIRY_SUBSCRIBE', this.subscribeInquiry); + EventEmitter.addEventListener('INQUIRY_UNSUBSCRIBE', this.unsubscribeInquiry); + } + + subscribeInquiry = async() => { + console.log('[RCRN] Subscribing to inquiry'); + this.inquirySub = await subscribeInquiry(); + } + + unsubscribeInquiry = () => { + if (this.inquirySub) { + console.log('[RCRN] Unsubscribing from inquiry'); + this.inquirySub.stop(); + this.inquirySub = null; + } + } +} + +// eslint-disable-next-line no-unused-vars +const omnichannel = new Omnichannel(); diff --git a/app/lib/methods/subscriptions/inquiry.js b/app/ee/omnichannel/lib/subscriptions/inquiry.js similarity index 77% rename from app/lib/methods/subscriptions/inquiry.js rename to app/ee/omnichannel/lib/subscriptions/inquiry.js index 014335dc1..02eafb8a9 100644 --- a/app/lib/methods/subscriptions/inquiry.js +++ b/app/ee/omnichannel/lib/subscriptions/inquiry.js @@ -1,12 +1,12 @@ -import log from '../../../utils/log'; -import store from '../../createStore'; -import RocketChat from '../../rocketchat'; +import log from '../../../../utils/log'; +import store from '../../../../lib/createStore'; +import RocketChat from '../../../../lib/rocketchat'; import { inquiryRequest, inquiryQueueAdd, inquiryQueueUpdate, inquiryQueueRemove -} from '../../../actions/inquiry'; +} from '../../actions/inquiry'; const removeListener = listener => listener.stop(); @@ -63,9 +63,9 @@ export default function subscribeInquiry() { } }; - connectedListener = this.sdk.onStreamData('connected', handleConnection); - disconnectedListener = this.sdk.onStreamData('close', handleConnection); - queueListener = this.sdk.onStreamData(streamTopic, handleQueueMessageReceived); + connectedListener = RocketChat.onStreamData('connected', handleConnection); + disconnectedListener = RocketChat.onStreamData('close', handleConnection); + queueListener = RocketChat.onStreamData(streamTopic, handleQueueMessageReceived); try { const { user } = store.getState().login; @@ -74,13 +74,13 @@ export default function subscribeInquiry() { const { departments } = result; if (!departments.length || RocketChat.hasRole('livechat-manager')) { - this.sdk.subscribe(streamTopic, 'public').catch(e => console.log(e)); + RocketChat.subscribe(streamTopic, 'public').catch(e => console.log(e)); } const departmentIds = departments.map(({ departmentId }) => departmentId); departmentIds.forEach((departmentId) => { // subscribe to all departments of the agent - this.sdk.subscribe(streamTopic, `department/${ departmentId }`).catch(e => console.log(e)); + RocketChat.subscribe(streamTopic, `department/${ departmentId }`).catch(e => console.log(e)); }); } }); diff --git a/app/reducers/inquiry.js b/app/ee/omnichannel/reducers/inquiry.js similarity index 94% rename from app/reducers/inquiry.js rename to app/ee/omnichannel/reducers/inquiry.js index 230280c83..156c9633d 100644 --- a/app/reducers/inquiry.js +++ b/app/ee/omnichannel/reducers/inquiry.js @@ -1,4 +1,4 @@ -import { INQUIRY } from '../actions/actionsTypes'; +import { INQUIRY } from '../../../actions/actionsTypes'; const initialState = { enabled: false, diff --git a/app/sagas/inquiry.js b/app/ee/omnichannel/sagas/inquiry.js similarity index 65% rename from app/sagas/inquiry.js rename to app/ee/omnichannel/sagas/inquiry.js index 9ee7e27fe..6140e2f65 100644 --- a/app/sagas/inquiry.js +++ b/app/ee/omnichannel/sagas/inquiry.js @@ -1,24 +1,26 @@ import { put, takeLatest, select } from 'redux-saga/effects'; -import * as types from '../actions/actionsTypes'; -import RocketChat from '../lib/rocketchat'; +import * as types from '../../../actions/actionsTypes'; +import RocketChat from '../../../lib/rocketchat'; +import EventEmitter from '../../../utils/events'; import { inquirySuccess, inquiryFailure, inquirySetEnabled } from '../actions/inquiry'; +import { isOmnichannelStatusAvailable, getInquiriesQueued } from '../lib'; const handleRequest = function* handleRequest() { try { const routingConfig = yield RocketChat.getRoutingConfig(); - const statusLivechat = yield select(state => state.login.user.statusLivechat); + const user = yield select(state => state.login.user); // if routingConfig showQueue is enabled and omnichannel is enabled - const showQueue = routingConfig.showQueue && statusLivechat === 'available'; + const showQueue = routingConfig.showQueue && isOmnichannelStatusAvailable(user); if (showQueue) { // get all the current chats on the queue - const result = yield RocketChat.getInquiriesQueued(); + const result = yield getInquiriesQueued(); if (result.success) { const { inquiries } = result; // subscribe to inquiry queue changes - RocketChat.subscribeInquiry(); + EventEmitter.emit('INQUIRY_SUBSCRIBE'); // put request result on redux state yield put(inquirySuccess(inquiries)); diff --git a/app/selectors/inquiry.js b/app/ee/omnichannel/selectors/inquiry.js similarity index 100% rename from app/selectors/inquiry.js rename to app/ee/omnichannel/selectors/inquiry.js diff --git a/app/views/QueueListView.js b/app/ee/omnichannel/views/QueueListView.js similarity index 82% rename from app/views/QueueListView.js rename to app/ee/omnichannel/views/QueueListView.js index 301f09a0f..67ee16009 100644 --- a/app/views/QueueListView.js +++ b/app/ee/omnichannel/views/QueueListView.js @@ -4,20 +4,20 @@ import { FlatList } from 'react-native'; import { connect } from 'react-redux'; import isEqual from 'react-fast-compare'; -import I18n from '../i18n'; -import RoomItem, { ROW_HEIGHT } from '../presentation/RoomItem'; -import { MAX_SIDEBAR_WIDTH } from '../constants/tablet'; -import { isTablet, isIOS } from '../utils/deviceInfo'; -import { getUserSelector } from '../selectors/login'; -import { withTheme } from '../theme'; -import { withDimensions } from '../dimensions'; -import SafeAreaView from '../containers/SafeAreaView'; -import { themes } from '../constants/colors'; -import StatusBar from '../containers/StatusBar'; -import { goRoom } from '../utils/goRoom'; -import { CloseModalButton } from '../containers/HeaderButton'; -import RocketChat from '../lib/rocketchat'; -import { logEvent, events } from '../utils/log'; +import I18n from '../../../i18n'; +import RoomItem, { ROW_HEIGHT } from '../../../presentation/RoomItem'; +import { MAX_SIDEBAR_WIDTH } from '../../../constants/tablet'; +import { isTablet, isIOS } from '../../../utils/deviceInfo'; +import { getUserSelector } from '../../../selectors/login'; +import { withTheme } from '../../../theme'; +import { withDimensions } from '../../../dimensions'; +import SafeAreaView from '../../../containers/SafeAreaView'; +import { themes } from '../../../constants/colors'; +import StatusBar from '../../../containers/StatusBar'; +import { goRoom } from '../../../utils/goRoom'; +import { CloseModalButton } from '../../../containers/HeaderButton'; +import RocketChat from '../../../lib/rocketchat'; +import { logEvent, events } from '../../../utils/log'; import { getInquiryQueueSelector } from '../selectors/inquiry'; const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12; diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index e2130cbf6..2ccd1073a 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -19,7 +19,6 @@ import { } from '../actions/share'; import subscribeRooms from './methods/subscriptions/rooms'; -import subscribeInquiry from './methods/subscriptions/inquiry'; import getUsersPresence, { getUserPresence, subscribeUsersPresence } from './methods/getUsersPresence'; import protectedFunction from './methods/helpers/protectedFunction'; @@ -54,6 +53,7 @@ import { twoFactor } from '../utils/twoFactor'; import { selectServerFailure } from '../actions/server'; import { useSsl } from '../utils/url'; import UserPreferences from './userPreferences'; +import EventEmitter from '../utils/events'; const TOKEN_KEY = 'reactnativemeteor_usertoken'; const CURRENT_SERVER = 'currentServer'; @@ -78,15 +78,6 @@ const RocketChat = { } } }, - async subscribeInquiry() { - if (!this.inquirySub) { - try { - this.inquirySub = await subscribeInquiry.call(this); - } catch (e) { - log(e); - } - } - }, canOpenRoom, createChannel({ name, users, type, readOnly, broadcast @@ -211,10 +202,7 @@ const RocketChat = { this.roomsSub = null; } - if (this.inquirySub) { - this.inquirySub.stop(); - this.inquirySub = null; - } + EventEmitter.emit('INQUIRY_UNSUBSCRIBE'); if (this.sdk) { this.sdk.disconnect(); @@ -858,20 +846,6 @@ const RocketChat = { // RC 2.2.0 return this.sdk.get('livechat/custom-fields'); }, - changeLivechatStatus() { - // RC 0.26.0 - return this.methodCallWrapper('livechat:changeLivechatStatus'); - }, - getInquiriesQueued() { - // RC 2.4.0 - return this.sdk.get('livechat/inquiries.queued'); - }, - takeInquiry(inquiryId) { - // this inquiry is added to the db by the subscriptions stream - // and will be removed by the queue stream - // RC 2.4.0 - return this.methodCallWrapper('livechat:takeInquiry', inquiryId); - }, getUidDirectMessage(room) { const { id: userId } = reduxStore.getState().login.user; diff --git a/app/reducers/index.js b/app/reducers/index.js index 05bcb534f..d047450a6 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -16,9 +16,10 @@ import activeUsers from './activeUsers'; import usersTyping from './usersTyping'; import inviteLinks from './inviteLinks'; import createDiscussion from './createDiscussion'; -import inquiry from './inquiry'; import enterpriseModules from './enterpriseModules'; +import inquiry from '../ee/omnichannel/reducers/inquiry'; + export default combineReducers({ settings, login, diff --git a/app/sagas/index.js b/app/sagas/index.js index 772df5717..af339c743 100644 --- a/app/sagas/index.js +++ b/app/sagas/index.js @@ -10,7 +10,8 @@ import state from './state'; import deepLinking from './deepLinking'; import inviteLinks from './inviteLinks'; import createDiscussion from './createDiscussion'; -import inquiry from './inquiry'; + +import inquiry from '../ee/omnichannel/sagas/inquiry'; const root = function* root() { yield all([ diff --git a/app/sagas/login.js b/app/sagas/login.js index f98a06e7c..d1a6a5b50 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -14,7 +14,6 @@ import { loginFailure, loginSuccess, setUser, logout } from '../actions/login'; import { roomsRequest } from '../actions/rooms'; -import { inquiryRequest, inquiryReset } from '../actions/inquiry'; import { toMomentLocale } from '../utils/moment'; import RocketChat from '../lib/rocketchat'; import log, { logEvent, events } from '../utils/log'; @@ -27,6 +26,9 @@ import { localAuthenticate } from '../utils/localAuthentication'; import { setActiveUsers } from '../actions/activeUsers'; import UserPreferences from '../lib/userPreferences'; +import { inquiryRequest, inquiryReset } from '../ee/omnichannel/actions/inquiry'; +import { isOmnichannelStatusAvailable } from '../ee/omnichannel/lib'; + const getServer = state => state.server.server; const loginWithPasswordCall = args => RocketChat.loginWithPassword(args); const loginCall = args => RocketChat.login(args); @@ -88,7 +90,7 @@ const fetchUsersPresence = function* fetchUserPresence() { const fetchEnterpriseModules = function* fetchEnterpriseModules({ user }) { yield RocketChat.getEnterpriseModules(); - if (user && user.statusLivechat === 'available' && RocketChat.isOmnichannelModuleAvailable()) { + if (isOmnichannelStatusAvailable(user) && RocketChat.isOmnichannelModuleAvailable()) { yield put(inquiryRequest()); } }; @@ -221,7 +223,7 @@ const handleSetUser = function* handleSetUser({ user }) { } if (user?.statusLivechat && RocketChat.isOmnichannelModuleAvailable()) { - if (user.statusLivechat === 'available') { + if (isOmnichannelStatusAvailable(user)) { yield put(inquiryRequest()); } else { yield put(inquiryReset()); diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index 81b3f7548..3b777777a 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -18,7 +18,8 @@ import I18n from '../i18n'; import { BASIC_AUTH_KEY, setBasicAuth } from '../utils/fetch'; import { appStart, ROOT_INSIDE, ROOT_OUTSIDE } from '../actions/app'; import UserPreferences from '../lib/userPreferences'; -import { inquiryReset } from '../actions/inquiry'; + +import { inquiryReset } from '../ee/omnichannel/actions/inquiry'; const getServerInfo = function* getServerInfo({ server, raiseError = true }) { try { diff --git a/app/stacks/InsideStack.js b/app/stacks/InsideStack.js index 7e96293e6..82e9f8ad4 100644 --- a/app/stacks/InsideStack.js +++ b/app/stacks/InsideStack.js @@ -30,7 +30,6 @@ import PickerView from '../views/PickerView'; import ThreadMessagesView from '../views/ThreadMessagesView'; import MarkdownTableView from '../views/MarkdownTableView'; import ReadReceiptsView from '../views/ReadReceiptView'; -import QueueListView from '../views/QueueListView'; // Profile Stack import ProfileView from '../views/ProfileView'; @@ -59,6 +58,8 @@ import StatusView from '../views/StatusView'; import ShareView from '../views/ShareView'; import CreateDiscussionView from '../views/CreateDiscussionView'; +import QueueListView from '../ee/omnichannel/views/QueueListView'; + // ChatsStackNavigator const ChatsStack = createStackNavigator(); const ChatsStackNavigator = () => { diff --git a/app/stacks/MasterDetailStack/index.js b/app/stacks/MasterDetailStack/index.js index 424f57bc2..bf97cd2ac 100644 --- a/app/stacks/MasterDetailStack/index.js +++ b/app/stacks/MasterDetailStack/index.js @@ -41,7 +41,6 @@ import ScreenLockConfigView from '../../views/ScreenLockConfigView'; import AdminPanelView from '../../views/AdminPanelView'; import NewMessageView from '../../views/NewMessageView'; import CreateChannelView from '../../views/CreateChannelView'; -import QueueListView from '../../views/QueueListView'; import UserPreferencesView from '../../views/UserPreferencesView'; import UserNotificationPrefView from '../../views/UserNotificationPreferencesView'; @@ -55,6 +54,8 @@ import CreateDiscussionView from '../../views/CreateDiscussionView'; import { setKeyCommands, deleteKeyCommands } from '../../commands'; import ShareView from '../../views/ShareView'; +import QueueListView from '../../ee/omnichannel/views/QueueListView'; + // ChatsStackNavigator const ChatsStack = createStackNavigator(); const ChatsStackNavigator = React.memo(() => { diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 00df625f1..ece024a0f 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -56,6 +56,8 @@ import SafeAreaView from '../../containers/SafeAreaView'; import { withDimensions } from '../../dimensions'; import { getHeaderTitlePosition } from '../../containers/Header'; +import { takeInquiry } from '../../ee/omnichannel/lib'; + const stateAttrsUpdate = [ 'joined', 'lastOpen', @@ -689,7 +691,7 @@ class RoomView extends React.Component { const { room } = this.state; if (this.isOmnichannel) { - await RocketChat.takeInquiry(room._id); + await takeInquiry(room._id); } else { await RocketChat.joinRoom(this.rid, this.t); } diff --git a/app/views/RoomsListView/ListHeader/index.js b/app/views/RoomsListView/ListHeader/index.js index 5fe4462fc..0ce38d079 100644 --- a/app/views/RoomsListView/ListHeader/index.js +++ b/app/views/RoomsListView/ListHeader/index.js @@ -2,7 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import Sort from './Sort'; -import OmnichannelStatus from './OmnichannelStatus'; + +import OmnichannelStatus from '../../../ee/omnichannel/containers/OmnichannelStatus'; const ListHeader = React.memo(({ searching, diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index 8279c6ca4..099b94bf1 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -63,7 +63,9 @@ import SafeAreaView from '../../containers/SafeAreaView'; import Header, { getHeaderTitlePosition } from '../../containers/Header'; import { withDimensions } from '../../dimensions'; import { showErrorAlert, showConfirmationAlert } from '../../utils/info'; -import { getInquiryQueueSelector } from '../../selectors/inquiry'; + +import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry'; +import { changeLivechatStatus, isOmnichannelStatusAvailable } from '../../ee/omnichannel/lib'; const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12; const CHATS_HEADER = 'Chats'; @@ -701,13 +703,13 @@ class RoomsListView extends React.Component { } = this.props; // if not-available, prompt to change to available - if (user?.statusLivechat !== 'available') { + if (!isOmnichannelStatusAvailable(user)) { showConfirmationAlert({ message: I18n.t('Omnichannel_enable_alert'), confirmationText: I18n.t('Yes'), onPress: async() => { try { - await RocketChat.changeLivechatStatus(); + await changeLivechatStatus(); } catch { // Do nothing }