Skip to content
Snippets Groups Projects
rocketchat.js 28 KiB
Newer Older
import { AsyncStorage, InteractionManager } from 'react-native';
import semver from 'semver';
import { Rocketchat as RocketchatClient, settings as RocketChatSettings } from '@rocket.chat/sdk';
import RNUserDefaults from 'rn-user-defaults';
import { Q } from '@nozbe/watermelondb';
import * as FileSystem from 'expo-file-system';
import reduxStore from './createStore';
import defaultSettings from '../constants/settings';
import messagesStatus from '../constants/messagesStatus';
import database from './database';
import log from '../utils/log';
import { isIOS, getBundleId } from '../utils/deviceInfo';
import { extractHostname } from '../utils/server';
import fetch, { headers } from '../utils/fetch';
Guilherme Gazzo's avatar
Guilherme Gazzo committed

Diego Mello's avatar
Diego Mello committed
import {
Diego Mello's avatar
Diego Mello committed
	setUser, setLoginServices, loginRequest, loginFailure, logout
Diego Mello's avatar
Diego Mello committed
} from '../actions/login';
Diego Mello's avatar
Diego Mello committed
import { disconnect, connectSuccess, connectRequest } from '../actions/connect';
import {
	shareSelectServer, shareSetUser
} from '../actions/share';
Guilherme Gazzo's avatar
Guilherme Gazzo committed
import subscribeRooms from './methods/subscriptions/rooms';
import subscribeRoom from './methods/subscriptions/room';
Guilherme Gazzo's avatar
Guilherme Gazzo committed

Guilherme Gazzo's avatar
Guilherme Gazzo committed
import protectedFunction from './methods/helpers/protectedFunction';
import readMessages from './methods/readMessages';
import getSettings from './methods/getSettings';
Guilherme Gazzo's avatar
Guilherme Gazzo committed
import getRooms from './methods/getRooms';
import getPermissions from './methods/getPermissions';
import { getCustomEmojis, setCustomEmojis } from './methods/getCustomEmojis';
import getSlashCommands from './methods/getSlashCommands';
import getRoles from './methods/getRoles';
Diego Mello's avatar
Diego Mello committed
import canOpenRoom from './methods/canOpenRoom';
Guilherme Gazzo's avatar
Guilherme Gazzo committed

import loadMessagesForRoom from './methods/loadMessagesForRoom';
import loadMissedMessages from './methods/loadMissedMessages';
Diego Mello's avatar
Diego Mello committed
import loadThreadMessages from './methods/loadThreadMessages';
import sendMessage, { sendMessageCall } from './methods/sendMessage';
import { sendFileMessage, cancelUpload, isUploadActive } from './methods/sendFileMessage';
Guilherme Gazzo's avatar
Guilherme Gazzo committed

import callJitsi from './methods/callJitsi';

import { getDeviceToken } from '../notifications/push';
import { SERVERS, SERVER_URL } from '../constants/userDefaults';
import { setActiveUsers } from '../actions/activeUsers';
Guilherme Gazzo's avatar
Guilherme Gazzo committed
const TOKEN_KEY = 'reactnativemeteor_usertoken';
const SORT_PREFS_KEY = 'RC_SORT_PREFS_KEY';
export const MARKDOWN_KEY = 'RC_MARKDOWN_KEY';
export const CRASH_REPORT_KEY = 'RC_CRASH_REPORT_KEY';
Guilherme Gazzo's avatar
Guilherme Gazzo committed
const returnAnArray = obj => obj || [];
const MIN_ROCKETCHAT_VERSION = '0.70.0';
const STATUSES = ['offline', 'online', 'away', 'busy'];

RocketChatSettings.customHeaders = headers;

Rodrigo Nascimento's avatar
Rodrigo Nascimento committed
const RocketChat = {
Diego Mello's avatar
Diego Mello committed
	TOKEN_KEY,
	async subscribeRooms() {
		if (this.roomsSub) {
			this.roomsSub.stop();
		}
		try {
			this.roomsSub = await subscribeRooms.call(this);
		} catch (e) {
			log(e);
		}
Guilherme Gazzo's avatar
Guilherme Gazzo committed
	subscribeRoom,
Diego Mello's avatar
Diego Mello committed
	canOpenRoom,
	createChannel({
		name, users, type, readOnly, broadcast
	}) {
		// RC 0.51.0
		return this.sdk.methodCall(type ? 'createPrivateGroup' : 'createChannel', name, users, readOnly, {}, { broadcast });
Rodrigo Nascimento's avatar
Rodrigo Nascimento committed
	async getUserToken() {
		try {
			return await RNUserDefaults.get(TOKEN_KEY);
Rodrigo Nascimento's avatar
Rodrigo Nascimento committed
		} catch (error) {
			console.warn(`RNUserDefaults error: ${ error.message }`);
Diego Mello's avatar
Diego Mello committed
	async getServerInfo(server) {
Diego Mello's avatar
Diego Mello committed
			const result = await fetch(`${ server }/api/info`).then(response => response.json());
			if (result.success) {
				if (semver.lt(result.version, MIN_ROCKETCHAT_VERSION)) {
					return {
						success: false,
						message: 'Invalid_server_version',
						messageOptions: {
Diego Mello's avatar
Diego Mello committed
							currentVersion: result.version,
							minVersion: MIN_ROCKETCHAT_VERSION
						}
					};
				}
Diego Mello's avatar
Diego Mello committed
				return result;
		} catch (e) {
		return {
			success: false,
			message: 'The_URL_is_invalid'
		};
	stopListener(listener) {
		return listener && listener.stop();
Diego Mello's avatar
Diego Mello committed
	},
Diego Mello's avatar
Diego Mello committed
	connect({ server, user }) {
		return new Promise((resolve) => {
			if (!this.sdk || this.sdk.client.host !== server) {
				database.setActiveDB(server);
			}
			reduxStore.dispatch(connectRequest());
Guilherme Gazzo's avatar
Guilherme Gazzo committed

			if (this.connectTimeout) {
				clearTimeout(this.connectTimeout);
			}
			if (this.connectedListener) {
				this.connectedListener.then(this.stopListener);
			}

			if (this.closeListener) {
				this.closeListener.then(this.stopListener);
			}

			if (this.usersListener) {
				this.usersListener.then(this.stopListener);
			}

			if (this.notifyLoggedListener) {
				this.notifyLoggedListener.then(this.stopListener);
			}

			if (this.roomsSub) {
				this.roomsSub.stop();
			}

			if (this.sdk) {
				this.sdk.disconnect();
				this.sdk = null;
			}
			// Use useSsl: false only if server url starts with http://
			const useSsl = !/http:\/\//.test(server);

			this.sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl });
			this.getSettings();

			this.sdk.connect()
				.then(() => {
					if (user && user.token) {
						reduxStore.dispatch(loginRequest({ resume: user.token }));
					}
				})
				.catch((err) => {
					console.log('connect error', err);

					// when `connect` raises an error, we try again in 10 seconds
					this.connectTimeout = setTimeout(() => {
						this.connect({ server, user });
					}, 10000);
				});
			this.connectedListener = this.sdk.onStreamData('connected', () => {
				reduxStore.dispatch(connectSuccess());
Guilherme Gazzo's avatar
Guilherme Gazzo committed

			this.closeListener = this.sdk.onStreamData('close', () => {
				reduxStore.dispatch(disconnect());
			});
			this.usersListener = this.sdk.onStreamData('users', protectedFunction(ddpMessage => RocketChat._setUser(ddpMessage)));
			this.notifyLoggedListener = this.sdk.onStreamData('stream-notify-logged', protectedFunction((ddpMessage) => {
				const { eventName } = ddpMessage.fields;
				if (eventName === 'user-status') {
					this.activeUsers = this.activeUsers || {};
					if (!this._setUserTimer) {
						this._setUserTimer = setTimeout(() => {
							const activeUsersBatch = this.activeUsers;
							InteractionManager.runAfterInteractions(() => {
								reduxStore.dispatch(setActiveUsers(activeUsersBatch));
							});
							this._setUserTimer = null;
							return this.activeUsers = {};
						}, 10000);
					}
					const userStatus = ddpMessage.fields.args[0];
					const [id,, status] = userStatus;
Loading
Loading full blame...