Use Rocket.Chat JS SDK (#481)

* JS SDK

* API working

* Multiple servers
This commit is contained in:
Diego Mello 2018-10-15 17:22:42 -03:00 committed by GitHub
parent 8db5723da8
commit 5a3ba40a9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 335 additions and 612 deletions

View File

@ -128,7 +128,8 @@ module.exports = {
"consistent-return": 0, "consistent-return": 0,
"global-require": "off", "global-require": "off",
"react-native/no-unused-styles": 2, "react-native/no-unused-styles": 2,
"react/jsx-one-expression-per-line": 0 "react/jsx-one-expression-per-line": 0,
"func-names": 0
}, },
"globals": { "globals": {
"__DEV__": true "__DEV__": true

View File

@ -97,7 +97,7 @@ export default {
Allow_Reactions: 'Permitir reagir', Allow_Reactions: 'Permitir reagir',
Alphabetical: 'Alfabético', Alphabetical: 'Alfabético',
and_more: 'e mais', and_more: 'e mais',
and: 'a', and: 'e',
announcement: 'anúncio', announcement: 'anúncio',
Announcement: 'Anúncio', Announcement: 'Anúncio',
ARCHIVE: 'ARQUIVAR', ARCHIVE: 'ARQUIVAR',

View File

@ -1,338 +0,0 @@
import EJSON from 'ejson';
import { AppState } from 'react-native';
import debounce from '../utils/debounce';
import log from '../utils/log';
// import { AppState, NativeModules } from 'react-native';
// const { WebSocketModule, BlobManager } = NativeModules;
// class WS extends WebSocket {
// _close(code?: number, reason?: string): void {
// if (Platform.OS === 'android') {
// WebSocketModule.close(code, reason, this._socketId);
// } else {
// WebSocketModule.close(this._socketId);
// }
//
// if (BlobManager.isAvailable && this._binaryType === 'blob') {
// BlobManager.removeWebSocketHandler(this._socketId);
// }
// }
// }
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (typeof this.events[event] !== 'object') {
this.events[event] = [];
}
this.events[event].push(listener);
return listener;
}
removeListener(event, listener) {
if (typeof this.events[event] === 'object') {
const idx = this.events[event].indexOf(listener);
if (idx > -1) {
this.events[event].splice(idx, 1);
}
if (this.events[event].length === 0) {
delete this.events[event];
}
}
}
emit(event, ...args) {
if (typeof this.events[event] === 'object') {
this.events[event].forEach((listener) => {
try {
listener.apply(this, args);
} catch (e) {
log('EventEmitter.emit', e);
}
});
}
}
once(event, listener) {
return this.on(event, function g(...args) {
this.removeListener(event, g);
listener.apply(this, args);
});
}
}
export default class Socket extends EventEmitter {
constructor(url, login) {
super();
this.state = 'active';
this.lastping = new Date();
this._login = login;
this.url = url;// .replace(/^http/, 'ws');
this.id = 0;
this.subscriptions = {};
this.ddp = new EventEmitter();
this._logged = false;
this.forceDisconnect = false;
this.connected = false;
const waitTimeout = () => setTimeout(() => {
// this.connection.ping();
this.send({ msg: 'ping' }).catch(e => log('ping', e));
this.timeout = setTimeout(() => this.reconnect(), 1000);
}, 40000);
const handlePing = () => {
this.lastping = new Date();
this.send({ msg: 'pong' }, true).catch(e => log('pong', e));
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = waitTimeout();
};
const handlePong = () => {
this.lastping = new Date();
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = waitTimeout();
};
AppState.addEventListener('change', async(nextAppState) => {
if (this.state && this.state.match(/inactive/) && nextAppState === 'active') {
try {
await this.send({ msg: 'ping' }, true);
// this.connection.ping();
} catch (e) {
this.reconnect();
}
}
if (this.state && this.state.match(/background/) && nextAppState === 'active') {
this.emit('background');
}
this.state = nextAppState;
});
this.on('pong', handlePong);
this.on('ping', handlePing);
this.on('result', data => this.ddp.emit(data.id, { id: data.id, result: data.result, error: data.error }));
this.on('ready', data => this.ddp.emit(data.subs[0], data));
// this.on('error', () => this.reconnect());
this.on('disconnected', debounce(() => this.reconnect(), 300));
this.on('logged', () => {
this._logged = true;
Object.keys(this.subscriptions || {}).forEach((key) => {
const { name, params } = this.subscriptions[key];
this.subscriptions[key].unsubscribe().catch(e => log('this.on(logged) unsub', e));
this.subscribe(name, ...params).catch(e => log('this.on(logged) sub', e));
});
});
this.on('open', async() => {
this._logged = false;
this.send({ msg: 'connect', version: '1', support: ['1', 'pre2', 'pre1'] }).catch(e => log('this.on(open)', e));
});
this._connect().catch(e => log('ddp.constructor._connect', e));
}
check() {
if (!this.lastping) {
return false;
}
if ((Math.abs(this.lastping.getTime() - new Date().getTime()) / 1000) > 50) {
return false;
}
return true;
}
async login(params) {
try {
this.emit('login', params);
const result = await this.call('login', params);
// this._login = { resume: result.token, ...result };
this._login = { resume: result.token, ...result, ...params };
this._logged = true;
// this.emit('logged', result);
this.emit('logged', this._login);
return result;
} catch (err) {
const error = { ...err };
if (/user not found/i.test(error.reason)) {
error.error = 1;
error.reason = 'User or Password incorrect';
error.message = 'User or Password incorrect';
}
this.emit('loginError', error);
return Promise.reject(error);
}
}
async send(obj, ignore) {
console.log('send', obj);
return new Promise((resolve, reject) => {
if (!this.connected) {
return reject();
}
this.id += 1;
const id = obj.id || `ddp-react-native-${ this.id }`;
// console.log('send', { ...obj, id });
this.connection.send(EJSON.stringify({ ...obj, id }));
if (ignore) {
return;
}
const cancel = this.once('disconnected', () => {
this.removeListener('disconnected', cancel);
reject();
});
this.ddp.once(id, (data) => {
// console.log(data);
this.lastping = new Date();
this.removeListener('disconnected', cancel);
return (data.error ? reject(data.error) : resolve({ id, ...data }));
});
});
}
get status() {
return this.connection && this.connection.readyState === 1 && this.check() && !!this._logged;
}
_close() {
try {
// this.connection && this.connection.readyState > 1 && this.connection.close && this.connection.close(300, 'disconnect');
if (this.connection && this.connection.close) {
this.connection.close();
delete this.connection;
}
} catch (e) {
// console.log(e);
}
}
_connect() {
return new Promise((resolve) => {
this.lastping = new Date();
this._close();
clearInterval(this.reconnect_timeout);
this.reconnect_timeout = setInterval(() => {
if (!this.connection || this.connection.readyState > 1 || !this.check()) {
this.reconnect();
}
}, 5000);
this.connection = new WebSocket(`${ this.url }/websocket`, null);
this.connection.onopen = async() => {
this.connected = true;
this.forceDisconnect = false;
this.emit('open');
resolve();
this.ddp.emit('open');
console.log(`Connected to: ${ this.url }`);
if (this._login) {
return this.login(this._login).catch(e => console.warn(e));
}
};
this.connection.onclose = debounce((e) => {
this.emit('disconnected', e);
this.connected = false;
}, 300);
this.connection.onmessage = (e) => {
try {
// console.log('received', e.data, e.target.readyState);
const data = EJSON.parse(e.data);
this.emit(data.msg, data);
return data.collection && this.emit(data.collection, data);
} catch (err) {
log('EJSON parse', err);
}
};
});
}
logout() {
this._login = null;
return this.call('logout')
.catch(e => log('logout', e))
.finally(() => this.subscriptions = {});
}
disconnect() {
this._logged = false;
this._login = null;
this.subscriptions = {};
this.forceDisconnect = true;
this._close();
if (this.timeout) {
clearTimeout(this.timeout);
}
}
async reconnect() {
if (this._timer || this.forceDisconnect) {
return;
}
// this._close();
this._logged = false;
this._timer = setTimeout(async() => {
delete this._timer;
try {
await this._connect();
} catch (e) {
log('ddp.reconnect._connect', e);
}
}, 1000);
}
call(method, ...params) {
return this.send({
msg: 'method', method, params
}).then(data => data.result || data.subs).catch((err) => {
log('DDP call Error', err);
if (err && /you've been logged out by the server/i.test(err.reason)) {
return this.emit('forbidden');
}
return Promise.reject(err);
});
}
unsubscribe(id) {
if (!this.subscriptions[id]) {
return Promise.reject(id);
}
delete this.subscriptions[id];
return this.send({
msg: 'unsub',
id
}).then(data => data.result || data.subs).catch((err) => {
log('DDP unsubscribe Error', err);
return Promise.reject(err);
});
}
subscribe(name, ...params) {
console.log(name, params);
return this.send({
msg: 'sub', name, params
}).then(({ id }) => {
const args = {
id,
name,
params,
unsubscribe: () => this.unsubscribe(id)
};
this.subscriptions[id] = args;
// console.log(args);
return args;
}).catch((err) => {
log('DDP subscribe Error', err);
return Promise.reject(err);
});
}
}

View File

@ -1,7 +1,7 @@
import { post } from './helpers/rest'; import * as SDK from '@rocket.chat/sdk';
import database from '../realm'; import database from '../realm';
import log from '../../utils/log'; import log from '../../utils/log';
import store from '../createStore';
// TODO: api fix // TODO: api fix
const ddpTypes = { const ddpTypes = {
@ -13,10 +13,7 @@ const restTypes = {
async function canOpenRoomREST({ type, rid }) { async function canOpenRoomREST({ type, rid }) {
try { try {
const { user } = store.getState().login; await SDK.api.post(`${ restTypes[type] }.open`, { roomId: rid });
const { token, id } = user;
const server = this.ddp.url.replace(/^ws/, 'http');
await post({ token, id, server }, `${ restTypes[type] }.open`, { roomId: rid });
return true; return true;
} catch (error) { } catch (error) {
// TODO: workround for 'already open for the sender' error // TODO: workround for 'already open for the sender' error
@ -30,7 +27,7 @@ async function canOpenRoomREST({ type, rid }) {
async function canOpenRoomDDP(...args) { async function canOpenRoomDDP(...args) {
try { try {
const [{ type, name }] = args; const [{ type, name }] = args;
await this.ddp.call('getRoomByTypeAndName', ddpTypes[type], name); await SDK.driver.asyncCall('getRoomByTypeAndName', ddpTypes[type], name);
return true; return true;
} catch (error) { } catch (error) {
if (error.isClientSafe) { if (error.isClientSafe) {
@ -51,8 +48,7 @@ export default async function canOpenRoom({ rid, path }) {
const [type, name] = path.split('/'); const [type, name] = path.split('/');
try { try {
// eslint-disable-next-line const data = await (SDK.driver.ddp ? canOpenRoomDDP.call(this, { rid, type, name }) : canOpenRoomREST.call(this, { type, rid }));
const data = await (this.ddp && this.ddp.status ? canOpenRoomDDP.call(this, { rid, type, name }) : canOpenRoomREST.call(this, { type, rid }));
return data; return data;
} catch (e) { } catch (e) {
log('canOpenRoom', e); log('canOpenRoom', e);

View File

@ -1,7 +1,7 @@
import { InteractionManager } from 'react-native'; import { InteractionManager } from 'react-native';
import * as SDK from '@rocket.chat/sdk';
import reduxStore from '../createStore'; import reduxStore from '../createStore';
// import { get } from './helpers/rest';
import database from '../realm'; import database from '../realm';
import * as actions from '../../actions'; import * as actions from '../../actions';
@ -12,16 +12,11 @@ const getLastMessage = () => {
return setting && setting._updatedAt; return setting && setting._updatedAt;
}; };
// TODO: fix api (get emojis by date/version....)
export default async function() { export default async function() {
try { try {
if (!this.ddp) {
// TODO: should implement loop or get from rest?
return;
}
const lastMessage = getLastMessage(); const lastMessage = getLastMessage();
let emojis = await this.ddp.call('listEmojiCustom'); let emojis = await SDK.driver.asyncCall('listEmojiCustom');
emojis = emojis.filter(emoji => !lastMessage || emoji._updatedAt > lastMessage); emojis = emojis.filter(emoji => !lastMessage || emoji._updatedAt > lastMessage);
emojis = this._prepareEmojis(emojis); emojis = this._prepareEmojis(emojis);
InteractionManager.runAfterInteractions(() => database.write(() => { InteractionManager.runAfterInteractions(() => database.write(() => {

View File

@ -1,4 +1,5 @@
import { InteractionManager } from 'react-native'; import { InteractionManager } from 'react-native';
import * as SDK from '@rocket.chat/sdk';
import database from '../realm'; import database from '../realm';
import log from '../../utils/log'; import log from '../../utils/log';
@ -11,13 +12,10 @@ const getLastUpdate = () => {
export default async function() { export default async function() {
try { try {
if (!this.ddp) {
// TODO: should implement loop or get from rest?
return;
}
const lastUpdate = getLastUpdate(); const lastUpdate = getLastUpdate();
const result = await (!lastUpdate ? this.ddp.call('permissions/get') : this.ddp.call('permissions/get', new Date(lastUpdate))); const result = await (!lastUpdate
? SDK.driver.asyncCall('permissions/get')
: SDK.driver.asyncCall('permissions/get', new Date(lastUpdate)));
const permissions = (result.update || result).filter(permission => defaultPermissions.includes(permission._id)); const permissions = (result.update || result).filter(permission => defaultPermissions.includes(permission._id));
permissions permissions
.map((permission) => { .map((permission) => {
@ -27,9 +25,13 @@ export default async function() {
}); });
InteractionManager.runAfterInteractions( InteractionManager.runAfterInteractions(
() => database.write( () => database.write(() => permissions.forEach((permission) => {
() => permissions.forEach(permission => database.create('permissions', permission, true)) try {
) database.create('permissions', permission, true);
} catch (e) {
log('getPermissions create', e);
}
}))
); );
} catch (e) { } catch (e) {
log('getPermissions', e); log('getPermissions', e);

View File

@ -1,33 +1,30 @@
import { InteractionManager } from 'react-native'; import { InteractionManager } from 'react-native';
import * as SDK from '@rocket.chat/sdk';
// import { showToast } from '../../utils/info';
import { get } from './helpers/rest';
import mergeSubscriptionsRooms, { merge } from './helpers/mergeSubscriptionsRooms'; import mergeSubscriptionsRooms, { merge } from './helpers/mergeSubscriptionsRooms';
import database from '../realm'; import database from '../realm';
import log from '../../utils/log'; import log from '../../utils/log';
import store from '../createStore';
const lastMessage = () => { const lastMessage = () => {
const message = database const message = database
.objects('subscriptions') .objects('subscriptions')
.sorted('roomUpdatedAt', true)[0]; .sorted('roomUpdatedAt', true)[0];
return message && new Date(message.roomUpdatedAt); return message && new Date(message.roomUpdatedAt).toISOString();
}; };
const getRoomRest = async function() { const getRoomRest = async function() {
const updatedSince = lastMessage(); const updatedSince = lastMessage();
const { user } = store.getState().login; const [subscriptions, rooms] = await (updatedSince
const { token, id } = user; ? Promise.all([SDK.api.get('subscriptions.get', { updatedSince }), SDK.api.get('rooms.get', { updatedSince })])
const server = this.ddp.url.replace(/^ws/, 'http'); : Promise.all([SDK.api.get('subscriptions.get'), SDK.api.get('rooms.get')])
const [subscriptions, rooms] = await Promise.all([get({ token, id, server }, 'subscriptions.get', { updatedSince }), get({ token, id, server }, 'rooms.get', { updatedSince })]); );
return mergeSubscriptionsRooms(subscriptions, rooms); return mergeSubscriptionsRooms(subscriptions, rooms);
}; };
const getRoomDpp = async function() { const getRoomDpp = async function() {
try { try {
const { ddp } = this;
const updatedSince = lastMessage(); const updatedSince = lastMessage();
const [subscriptions, rooms] = await Promise.all([ddp.call('subscriptions/get', updatedSince), ddp.call('rooms/get', updatedSince)]); const [subscriptions, rooms] = await Promise.all([SDK.driver.asyncCall('subscriptions/get', updatedSince), SDK.driver.asyncCall('rooms/get', updatedSince)]);
return mergeSubscriptionsRooms(subscriptions, rooms); return mergeSubscriptionsRooms(subscriptions, rooms);
} catch (e) { } catch (e) {
return getRoomRest.apply(this); return getRoomRest.apply(this);
@ -39,8 +36,7 @@ export default async function() {
return new Promise(async(resolve, reject) => { return new Promise(async(resolve, reject) => {
try { try {
// eslint-disable-next-line const { subscriptions, rooms } = await (SDK.driver.ddp ? getRoomDpp.apply(this) : getRoomRest.apply(this));
const { subscriptions, rooms } = await (this.ddp && this.ddp.status ? getRoomDpp.apply(this) : getRoomRest.apply(this));
const data = rooms.map(room => ({ room, sub: database.objects('subscriptions').filtered('rid == $0', room._id) })); const data = rooms.map(room => ({ room, sub: database.objects('subscriptions').filtered('rid == $0', room._id) }));

View File

@ -1,7 +1,7 @@
import { InteractionManager } from 'react-native'; import { InteractionManager } from 'react-native';
import * as SDK from '@rocket.chat/sdk';
import reduxStore from '../createStore'; import reduxStore from '../createStore';
// import { get } from './helpers/rest';
import database from '../realm'; import database from '../realm';
import * as actions from '../../actions'; import * as actions from '../../actions';
import log from '../../utils/log'; import log from '../../utils/log';
@ -14,20 +14,22 @@ const getLastUpdate = () => {
function updateServer(param) { function updateServer(param) {
database.databases.serversDB.write(() => { database.databases.serversDB.write(() => {
database.databases.serversDB.create('servers', { id: this.ddp.url, ...param }, true); database.databases.serversDB.create('servers', { id: reduxStore.getState().server.server, ...param }, true);
}); });
} }
export default async function() { export default async function() {
try { try {
if (!this.ddp) { // if (!SDK.driver.dd) {
// TODO: should implement loop or get from rest? // // TODO: should implement loop or get from rest?
return; // return;
} // }
const lastUpdate = getLastUpdate(); const lastUpdate = getLastUpdate();
const fetchNewSettings = lastUpdate < settingsUpdatedAt; const fetchNewSettings = lastUpdate < settingsUpdatedAt;
const result = await ((!lastUpdate || fetchNewSettings) ? this.ddp.call('public-settings/get') : this.ddp.call('public-settings/get', new Date(lastUpdate))); const result = await ((!lastUpdate || fetchNewSettings)
? SDK.driver.asyncCall('public-settings/get')
: SDK.driver.asyncCall('public-settings/get', new Date(lastUpdate)));
const data = result.update || result || []; const data = result.update || result || [];
const filteredSettings = this._prepareSettings(this._filterSettings(data)); const filteredSettings = this._prepareSettings(this._filterSettings(data));
@ -47,7 +49,8 @@ export default async function() {
const iconSetting = data.find(item => item._id === 'Assets_favicon_512'); const iconSetting = data.find(item => item._id === 'Assets_favicon_512');
if (iconSetting) { if (iconSetting) {
const iconURL = `${ this.ddp.url }/${ iconSetting.value.url || iconSetting.value.defaultUrl }`; const baseUrl = reduxStore.getState().server.server;
const iconURL = `${ baseUrl }/${ iconSetting.value.url || iconSetting.value.defaultUrl }`;
updateServer.call(this, { iconURL }); updateServer.call(this, { iconURL });
} }
} catch (e) { } catch (e) {

View File

@ -22,10 +22,13 @@ export default (msg) => {
msg = normalizeAttachments(msg); msg = normalizeAttachments(msg);
msg.reactions = msg.reactions || []; msg.reactions = msg.reactions || [];
// TODO: api problems // TODO: api problems
if (Array.isArray(msg.reactions)) { // if (Array.isArray(msg.reactions)) {
msg.reactions = msg.reactions.map((value, key) => ({ emoji: key, usernames: value.usernames.map(username => ({ value: username })) })); // msg.reactions = msg.reactions.map((value, key) => ({ emoji: key, usernames: value.usernames.map(username => ({ value: username })) }));
} else { // } else {
msg.reactions = Object.keys(msg.reactions).map(key => ({ emoji: key, usernames: msg.reactions[key].usernames.map(username => ({ value: username })) })); // msg.reactions = Object.keys(msg.reactions).map(key => ({ emoji: key, usernames: msg.reactions[key].usernames.map(username => ({ value: username })) }));
// }
if (!Array.isArray(msg.reactions)) {
msg.reactions = Object.keys(msg.reactions).map(key => ({ _id: `${ msg._id }${ key }`, emoji: key, usernames: msg.reactions[key].usernames.map(username => ({ value: username })) }));
} }
msg.urls = msg.urls ? parseUrls(msg.urls) : []; msg.urls = msg.urls ? parseUrls(msg.urls) : [];
msg._updatedAt = new Date(); msg._updatedAt = new Date();

View File

@ -1,8 +1,8 @@
import { Answers } from 'react-native-fabric'; import { Answers } from 'react-native-fabric';
export default fn => (params) => { export default fn => (...params) => {
try { try {
fn(params); fn(...params);
} catch (e) { } catch (e) {
let error = e; let error = e;
if (typeof error !== 'object') { if (typeof error !== 'object') {

View File

@ -1,40 +0,0 @@
import toQuery from './toQuery';
const handleSuccess = (msg) => {
if ((msg.success !== undefined && !msg.success) || (msg.status && msg.status === 'error')) {
return Promise.reject(msg);
}
return msg;
};
export const get = function({
token, id, server
}, method, params = {}) {
return fetch(`${ server }/api/v1/${ method }/?${ toQuery(params) }`, {
method: 'get',
headers: {
// 'Accept-Encoding': 'gzip',
'Content-Type': 'application/json',
'X-Auth-Token': token,
'X-User-Id': id
}
}).then(response => response.json()).then(handleSuccess);
};
export const post = function({
token, id, server
}, method, params = {}) {
return fetch(`${ server }/api/v1/${ method }`, {
method: 'post',
body: JSON.stringify(params),
headers: {
// 'Accept-Encoding': 'gzip',
'Content-Type': 'application/json',
Accept: 'application/json',
'X-Auth-Token': token,
'X-User-Id': id
}
}).then(response => response.json()).then(handleSuccess);
};

View File

@ -1,3 +0,0 @@
export default function(obj) {
return Object.keys(obj).filter(p => obj[p] !== undefined && obj[p] !== null).map(p => `${ encodeURIComponent(p) }=${ encodeURIComponent(obj[p]) }`).join('&');
}

View File

@ -1,10 +1,9 @@
import { InteractionManager } from 'react-native'; import { InteractionManager } from 'react-native';
import * as SDK from '@rocket.chat/sdk';
import { get } from './helpers/rest';
import buildMessage from './helpers/buildMessage'; import buildMessage from './helpers/buildMessage';
import database from '../realm'; import database from '../realm';
import log from '../../utils/log'; import log from '../../utils/log';
import store from '../createStore';
// TODO: api fix // TODO: api fix
const types = { const types = {
@ -12,10 +11,10 @@ const types = {
}; };
async function loadMessagesForRoomRest({ rid: roomId, latest, t }) { async function loadMessagesForRoomRest({ rid: roomId, latest, t }) {
const { user } = store.getState().login; if (latest) {
const { token, id } = user; latest = new Date(latest).toISOString();
const server = this.ddp.url.replace(/^ws/, 'http'); }
const data = await get({ token, id, server }, `${ types[t] }.history`, { roomId, latest }); const data = await SDK.api.get(`${ types[t] }.history`, { roomId, latest });
if (!data || data.status === 'error') { if (!data || data.status === 'error') {
return []; return [];
} }
@ -25,13 +24,12 @@ async function loadMessagesForRoomRest({ rid: roomId, latest, t }) {
async function loadMessagesForRoomDDP(...args) { async function loadMessagesForRoomDDP(...args) {
const [{ rid: roomId, latest }] = args; const [{ rid: roomId, latest }] = args;
try { try {
const data = await this.ddp.call('loadHistory', roomId, latest, 50); const data = await SDK.driver.asyncCall('loadHistory', roomId, latest, 50);
if (!data || !data.messages.length) { if (!data || !data.messages.length) {
return []; return [];
} }
return data.messages; return data.messages;
} catch (e) { } catch (e) {
console.warn('loadMessagesForRoomDDP', e);
return loadMessagesForRoomRest.call(this, ...args); return loadMessagesForRoomRest.call(this, ...args);
} }
} }
@ -40,11 +38,15 @@ export default async function loadMessagesForRoom(...args) {
const { database: db } = database; const { database: db } = database;
return new Promise(async(resolve, reject) => { return new Promise(async(resolve, reject) => {
try { try {
const data = (await (this.ddp && this.ddp.status ? loadMessagesForRoomDDP.call(this, ...args) : loadMessagesForRoomRest.call(this, ...args))).map(buildMessage); const data = (await (SDK.driver.ddp
? loadMessagesForRoomDDP.call(this, ...args)
: loadMessagesForRoomRest.call(this, ...args))).map(buildMessage);
if (data && data.length) { if (data && data.length) {
InteractionManager.runAfterInteractions(() => { InteractionManager.runAfterInteractions(() => {
db.write(() => data.forEach(message => db.create('messages', message, true))); db.write(() => data.forEach((message) => {
db.create('messages', message, true);
}));
return resolve(data); return resolve(data);
}); });
} else { } else {

View File

@ -1,16 +1,16 @@
import { InteractionManager } from 'react-native'; import { InteractionManager } from 'react-native';
import * as SDK from '@rocket.chat/sdk';
import { get } from './helpers/rest';
import buildMessage from './helpers/buildMessage'; import buildMessage from './helpers/buildMessage';
import database from '../realm'; import database from '../realm';
import log from '../../utils/log'; import log from '../../utils/log';
import store from '../createStore';
async function loadMissedMessagesRest({ rid: roomId, lastOpen: lastUpdate }) { async function loadMissedMessagesRest({ rid: roomId, lastOpen }) {
const { user } = store.getState().login; let lastUpdate;
const { token, id } = user; if (lastOpen) {
const server = this.ddp.url.replace(/^ws/, 'http'); lastUpdate = new Date(lastOpen).toISOString();
const { result } = await get({ token, id, server }, 'chat.syncMessages', { roomId, lastUpdate }); }
const { result } = await SDK.api.get('chat.syncMessages', { roomId, lastUpdate });
return result; return result;
} }
@ -18,7 +18,7 @@ async function loadMissedMessagesDDP(...args) {
const [{ rid, lastOpen: lastUpdate }] = args; const [{ rid, lastOpen: lastUpdate }] = args;
try { try {
const result = await this.ddp.call('messages/get', rid, { lastUpdate: new Date(lastUpdate) }); const result = await SDK.driver.asyncCall('messages/get', rid, { lastUpdate: new Date(lastUpdate) });
return result; return result;
} catch (e) { } catch (e) {
return loadMissedMessagesRest.call(this, ...args); return loadMissedMessagesRest.call(this, ...args);
@ -29,7 +29,7 @@ export default async function loadMissedMessages(...args) {
const { database: db } = database; const { database: db } = database;
return new Promise(async(resolve, reject) => { return new Promise(async(resolve, reject) => {
try { try {
const data = (await (this.ddp && this.ddp.status ? loadMissedMessagesDDP.call(this, ...args) : loadMissedMessagesRest.call(this, ...args))); const data = (await (SDK.driver.ddp ? loadMissedMessagesDDP.call(this, ...args) : loadMissedMessagesRest.call(this, ...args)));
if (data) { if (data) {
if (data.updated && data.updated.length) { if (data.updated && data.updated.length) {

View File

@ -1,28 +1,25 @@
import { post } from './helpers/rest'; import * as SDK from '@rocket.chat/sdk';
import database from '../realm'; import database from '../realm';
import log from '../../utils/log'; import log from '../../utils/log';
import store from '../createStore';
const readMessagesREST = function readMessagesREST(rid) { const readMessagesREST = function readMessagesREST(rid) {
const { user } = store.getState().login; return SDK.api.post('subscriptions.read', { rid });
const { token, id } = user;
const server = this.ddp.url.replace(/^ws/, 'http');
return post({ token, id, server }, 'subscriptions.read', { rid });
}; };
const readMessagesDDP = function readMessagesDDP(rid) { const readMessagesDDP = function readMessagesDDP(rid) {
try { try {
return this.ddp.call('readMessages', rid); return SDK.driver.asyncCall('readMessages', rid);
} catch (e) { } catch (e) {
return readMessagesREST.call(this, rid); return readMessagesREST.call(this, rid);
} }
}; };
export default async function readMessages(rid) { export default async function readMessages(rid) {
const ls = new Date();
const { database: db } = database; const { database: db } = database;
try { try {
// eslint-disable-next-line const data = await (SDK.driver.ddp ? readMessagesDDP.call(this, rid) : readMessagesREST.call(this, rid));
const data = await (this.ddp && this.ddp.status ? readMessagesDDP.call(this, rid) : readMessagesREST.call(this, rid));
const [subscription] = db.objects('subscriptions').filtered('rid = $0', rid); const [subscription] = db.objects('subscriptions').filtered('rid = $0', rid);
db.write(() => { db.write(() => {
subscription.open = true; subscription.open = true;
@ -30,8 +27,8 @@ export default async function readMessages(rid) {
subscription.unread = 0; subscription.unread = 0;
subscription.userMentions = 0; subscription.userMentions = 0;
subscription.groupMentions = 0; subscription.groupMentions = 0;
subscription.ls = new Date(); subscription.ls = ls;
subscription.lastOpen = new Date(); subscription.lastOpen = ls;
}); });
return data; return data;
} catch (e) { } catch (e) {

View File

@ -1,4 +1,5 @@
import RNFetchBlob from 'rn-fetch-blob'; import RNFetchBlob from 'rn-fetch-blob';
import * as SDK from '@rocket.chat/sdk';
import reduxStore from '../createStore'; import reduxStore from '../createStore';
import database from '../realm'; import database from '../realm';
@ -6,15 +7,15 @@ import database from '../realm';
const promises = {}; const promises = {};
function _ufsCreate(fileInfo) { function _ufsCreate(fileInfo) {
return this.ddp.call('ufsCreate', fileInfo); return SDK.driver.asyncCall('ufsCreate', fileInfo);
} }
function _ufsComplete(fileId, store, token) { function _ufsComplete(fileId, store, token) {
return this.ddp.call('ufsComplete', fileId, store, token); return SDK.driver.asyncCall('ufsComplete', fileId, store, token);
} }
function _sendFileMessage(rid, data, msg = {}) { function _sendFileMessage(rid, data, msg = {}) {
return this.ddp.call('sendFileMessage', rid, null, data, msg); return SDK.driver.asyncCall('sendFileMessage', rid, null, data, msg);
} }
export function isUploadActive(path) { export function isUploadActive(path) {

View File

@ -1,8 +1,8 @@
import Random from 'react-native-meteor/lib/Random'; import Random from 'react-native-meteor/lib/Random';
import * as SDK from '@rocket.chat/sdk';
import messagesStatus from '../../constants/messagesStatus'; import messagesStatus from '../../constants/messagesStatus';
import buildMessage from './helpers/buildMessage'; import buildMessage from './helpers/buildMessage';
import { post } from './helpers/rest';
import database from '../realm'; import database from '../realm';
import reduxStore from '../createStore'; import reduxStore from '../createStore';
import log from '../../utils/log'; import log from '../../utils/log';
@ -32,21 +32,18 @@ export const getMessage = (rid, msg = {}) => {
}; };
function sendMessageByRest(message) { function sendMessageByRest(message) {
const { token, id } = this.ddp._login;
const server = this.ddp.url.replace(/^ws/, 'http');
const { _id, rid, msg } = message; const { _id, rid, msg } = message;
return post({ token, id, server }, 'chat.sendMessage', { message: { _id, rid, msg } }); return SDK.api.post('chat.sendMessage', { message: { _id, rid, msg } });
} }
function sendMessageByDDP(message) { function sendMessageByDDP(message) {
const { _id, rid, msg } = message; const { _id, rid, msg } = message;
return this.ddp.call('sendMessage', { _id, rid, msg }); return SDK.driver.asyncCall('sendMessage', { _id, rid, msg });
} }
export async function _sendMessageCall(message) { export async function _sendMessageCall(message) {
try { try {
// eslint-disable-next-line const data = await (SDK.driver.ddp ? sendMessageByDDP.call(this, message) : sendMessageByRest.call(this, message));
const data = await (this.ddp && this.ddp.status ? sendMessageByDDP.call(this, message) : sendMessageByRest.call(this, message));
return data; return data;
} catch (e) { } catch (e) {
database.write(() => { database.write(() => {

View File

@ -1,14 +1,11 @@
// import database from '../../realm'; import * as SDK from '@rocket.chat/sdk';
// import reduxStore from '../../createStore';
// import normalizeMessage from '../helpers/normalizeMessage';
// import _buildMessage from '../helpers/buildMessage';
// import protectedFunction from '../helpers/protectedFunction';
import log from '../../../utils/log'; import log from '../../../utils/log';
const subscribe = (ddp, rid) => Promise.all([ const subscribe = rid => Promise.all([
ddp.subscribe('stream-room-messages', rid, false), SDK.driver.subscribe('stream-room-messages', rid, false),
ddp.subscribe('stream-notify-room', `${ rid }/typing`, false), SDK.driver.subscribe('stream-notify-room', `${ rid }/typing`, false),
ddp.subscribe('stream-notify-room', `${ rid }/deleteMessage`, false) SDK.driver.subscribe('stream-notify-room', `${ rid }/deleteMessage`, false)
]); ]);
const unsubscribe = subscriptions => subscriptions.forEach(sub => sub.unsubscribe().catch((e) => { const unsubscribe = subscriptions => subscriptions.forEach(sub => sub.unsubscribe().catch((e) => {
log('unsubscribeRoom', e); log('unsubscribeRoom', e);
@ -16,23 +13,13 @@ const unsubscribe = subscriptions => subscriptions.forEach(sub => sub.unsubscrib
let timer = null; let timer = null;
let promises; let promises;
let logged;
let disconnected;
const stop = (ddp) => { const stop = () => {
if (promises) { if (promises) {
promises.then(unsubscribe); promises.then(unsubscribe);
promises = false; promises = false;
} }
if (ddp) {
ddp.removeListener('logged', logged);
ddp.removeListener('disconnected', disconnected);
}
logged = false;
disconnected = false;
clearTimeout(timer); clearTimeout(timer);
}; };
@ -47,7 +34,7 @@ export default async function subscribeRoom({ rid, t }) {
} }
timer = setTimeout(async() => { timer = setTimeout(async() => {
try { try {
await this.loadMissedMessages({ rid, t, lastOpen: timer }); await this.loadMissedMessages({ rid, t });
timer = false; timer = false;
loop(); loop();
} catch (e) { } catch (e) {
@ -56,29 +43,28 @@ export default async function subscribeRoom({ rid, t }) {
}, 5000); }, 5000);
}; };
if (!this.ddp || !this.ddp.status) { if (!SDK.driver.ddp && SDK.driver.userId) {
loop(); loop();
} else { } else {
logged = this.ddp.on('logged', () => { SDK.driver.on('logged', () => {
clearTimeout(timer); clearTimeout(timer);
timer = false; timer = false;
// promises = subscribe(this.ddp, rid);
}); });
disconnected = this.ddp.on('disconnected', () => { SDK.driver.on('disconnected', () => {
if (this._login) { if (SDK.driver.userId) {
loop(); loop();
} }
}); });
try { try {
promises = subscribe(this.ddp, rid); promises = subscribe(rid);
} catch (e) { } catch (e) {
log('subscribeRoom', e); log('subscribeRoom', e);
} }
} }
return { return {
stop: () => stop(this.ddp) stop: () => stop()
}; };
} }

View File

@ -1,4 +1,6 @@
import Random from 'react-native-meteor/lib/Random'; import Random from 'react-native-meteor/lib/Random';
import * as SDK from '@rocket.chat/sdk';
import database from '../../realm'; import database from '../../realm';
import { merge } from '../helpers/mergeSubscriptionsRooms'; import { merge } from '../helpers/mergeSubscriptionsRooms';
import protectedFunction from '../helpers/protectedFunction'; import protectedFunction from '../helpers/protectedFunction';
@ -7,9 +9,9 @@ import log from '../../../utils/log';
export default async function subscribeRooms(id) { export default async function subscribeRooms(id) {
const promises = Promise.all([ const promises = Promise.all([
this.ddp.subscribe('stream-notify-user', `${ id }/subscriptions-changed`, false), SDK.driver.subscribe('stream-notify-user', `${ id }/subscriptions-changed`, false),
this.ddp.subscribe('stream-notify-user', `${ id }/rooms-changed`, false), SDK.driver.subscribe('stream-notify-user', `${ id }/rooms-changed`, false),
this.ddp.subscribe('stream-notify-user', `${ id }/message`, false) SDK.driver.subscribe('stream-notify-user', `${ id }/message`, false)
]); ]);
let timer = null; let timer = null;
@ -28,26 +30,29 @@ export default async function subscribeRooms(id) {
}, 5000); }, 5000);
}; };
if (!this.ddp && this._login) { if (!SDK.driver.ddp && SDK.driver.userId) {
loop(); loop();
} else { } else {
this.ddp.on('logged', () => { SDK.driver.on('logged', () => {
clearTimeout(timer); clearTimeout(timer);
timer = false; timer = false;
}); });
this.ddp.on('logout', () => { SDK.driver.on('logout', () => {
clearTimeout(timer); clearTimeout(timer);
timer = true; timer = true;
}); });
this.ddp.on('disconnected', () => { SDK.driver.on('disconnected', () => {
if (this._login) { if (this._login) {
loop(); loop();
} }
}); });
this.ddp.on('stream-notify-user', protectedFunction((ddpMessage) => { SDK.driver.on('stream-notify-user', protectedFunction((e, ddpMessage) => {
if (ddpMessage.msg === 'added') {
return;
}
const [type, data] = ddpMessage.fields.args; const [type, data] = ddpMessage.fields.args;
const [, ev] = ddpMessage.fields.eventName.split('/'); const [, ev] = ddpMessage.fields.eventName.split('/');
if (/subscriptions/.test(ev)) { if (/subscriptions/.test(ev)) {

View File

@ -177,8 +177,9 @@ const messagesReactionsUsernamesSchema = {
const messagesReactionsSchema = { const messagesReactionsSchema = {
name: 'messagesReactions', name: 'messagesReactions',
primaryKey: 'emoji', primaryKey: '_id',
properties: { properties: {
_id: 'string',
emoji: 'string', emoji: 'string',
usernames: { type: 'list', objectType: 'messagesReactionsUsernames' } usernames: { type: 'list', objectType: 'messagesReactionsUsernames' }
} }

View File

@ -1,7 +1,7 @@
import { AsyncStorage, Platform } from 'react-native'; import { AsyncStorage, Platform } from 'react-native';
import { hashPassword } from 'react-native-meteor/lib/utils';
import foreach from 'lodash/forEach'; import foreach from 'lodash/forEach';
import RNFetchBlob from 'rn-fetch-blob'; import RNFetchBlob from 'rn-fetch-blob';
import * as SDK from '@rocket.chat/sdk';
import reduxStore from './createStore'; import reduxStore from './createStore';
import defaultSettings from '../constants/settings'; import defaultSettings from '../constants/settings';
@ -13,7 +13,7 @@ import log from '../utils/log';
import { import {
setUser, setLoginServices, removeLoginServices, loginRequest, loginSuccess, loginFailure, logout setUser, setLoginServices, removeLoginServices, loginRequest, loginSuccess, loginFailure, logout
} from '../actions/login'; } from '../actions/login';
import { disconnect, connectSuccess, connectFailure } from '../actions/connect'; import { disconnect, connectSuccess } from '../actions/connect';
import { setActiveUser } from '../actions/activeUsers'; import { setActiveUser } from '../actions/activeUsers';
import { starredMessagesReceived, starredMessageUnstarred } from '../actions/starredMessages'; import { starredMessagesReceived, starredMessageUnstarred } from '../actions/starredMessages';
import { pinnedMessagesReceived, pinnedMessageUnpinned } from '../actions/pinnedMessages'; import { pinnedMessagesReceived, pinnedMessageUnpinned } from '../actions/pinnedMessages';
@ -22,7 +22,6 @@ import { snippetedMessagesReceived } from '../actions/snippetedMessages';
import { roomFilesReceived } from '../actions/roomFiles'; import { roomFilesReceived } from '../actions/roomFiles';
import { someoneTyping, roomMessageReceived } from '../actions/room'; import { someoneTyping, roomMessageReceived } from '../actions/room';
import { setRoles } from '../actions/roles'; import { setRoles } from '../actions/roles';
import Ddp from './ddp';
import subscribeRooms from './methods/subscriptions/rooms'; import subscribeRooms from './methods/subscriptions/rooms';
import subscribeRoom from './methods/subscriptions/room'; import subscribeRoom from './methods/subscriptions/room';
@ -47,7 +46,7 @@ import { getDeviceToken } from '../push';
const TOKEN_KEY = 'reactnativemeteor_usertoken'; const TOKEN_KEY = 'reactnativemeteor_usertoken';
const SORT_PREFS_KEY = 'RC_SORT_PREFS_KEY'; const SORT_PREFS_KEY = 'RC_SORT_PREFS_KEY';
const call = (method, ...params) => RocketChat.ddp.call(method, ...params); // eslint-disable-line const call = (method, ...params) => SDK.driver.asyncCall(method, ...params);
const returnAnArray = obj => obj || []; const returnAnArray = obj => obj || [];
const RocketChat = { const RocketChat = {
@ -135,63 +134,84 @@ const RocketChat = {
// TODO: one api call // TODO: one api call
// call /me only one time // call /me only one time
if (!user.username) { if (!user.username) {
const me = await this.me({ token: user.token, userId: user.id }); const me = await SDK.api.get('me');
user = { ...user, ...me }; user = { ...user, ...me };
} }
if (user.username) { if (user.username) {
const userInfo = await this.userInfo({ token: user.token, userId: user.id }); const userInfo = await SDK.api.get('users.info', { userId: user.id });
user = { ...user, ...userInfo.user }; user = { ...user, ...userInfo.user };
} }
RocketChat.registerPushToken(user.id); RocketChat.registerPushToken(user.id);
reduxStore.dispatch(setUser(user));
reduxStore.dispatch(loginSuccess(user)); reduxStore.dispatch(loginSuccess(user));
this.ddp.subscribe('userData'); this.ddp.subscribe('userData');
} catch (e) { } catch (e) {
log('rocketchat.loginSuccess', e); log('SDK.loginSuccess', e);
} }
}, },
connect(url, login) { connect(url, login) {
return new Promise((resolve) => { return new Promise(async() => {
if (this.ddp) { if (this.ddp) {
this.ddp.disconnect(); RocketChat.disconnect();
delete this.ddp; this.ddp = null;
} }
this.ddp = new Ddp(url, login);
if (login) { if (login) {
protectedFunction(() => RocketChat.getRooms()); SDK.api.setAuth({ authToken: login.token, userId: login.id });
} }
this.ddp.on('login', protectedFunction(() => reduxStore.dispatch(loginRequest()))); SDK.api.setBaseUrl(url);
SDK.driver.connect({ host: url, useSsl: true }, (err, ddp) => {
if (err) {
return console.warn(err);
}
this.ddp = ddp;
if (login) {
SDK.driver.ddp.login({ resume: login.resume });
}
});
this.ddp.on('loginError', protectedFunction(err => reduxStore.dispatch(loginFailure(err)))); SDK.driver.on('connected', () => {
reduxStore.dispatch(connectSuccess());
SDK.driver.subscribe('meteor.loginServiceConfiguration');
SDK.driver.subscribe('activeUsers');
SDK.driver.subscribe('roles');
RocketChat.getSettings();
RocketChat.getPermissions();
RocketChat.getCustomEmoji();
});
this.ddp.on('forbidden', protectedFunction(() => reduxStore.dispatch(logout()))); SDK.driver.on('login', protectedFunction(() => reduxStore.dispatch(loginRequest())));
this.ddp.on('users', protectedFunction(ddpMessage => RocketChat._setUser(ddpMessage))); SDK.driver.on('forbidden', protectedFunction(() => reduxStore.dispatch(logout())));
this.ddp.on('background', () => this.getRooms().catch(e => log('background getRooms', e))); SDK.driver.on('users', protectedFunction((error, ddpMessage) => RocketChat._setUser(ddpMessage)));
this.ddp.on('logged', protectedFunction((user) => { // SDK.driver.on('background', () => this.getRooms().catch(e => log('background getRooms', e)));
SDK.driver.on('logged', protectedFunction((error, user) => {
SDK.api.setAuth({ authToken: user.token, userId: user.id });
SDK.api.currentLogin = {
userId: user.id,
authToken: user.token
};
this.loginSuccess(user); this.loginSuccess(user);
this.getRooms().catch(e => log('logged getRooms', e)); this.getRooms().catch(e => log('logged getRooms', e));
})); this.subscribeRooms(user.id);
this.ddp.once('logged', protectedFunction(({ id }) => {
this.subscribeRooms(id);
// this.ddp.subscribe('stream-notify-logged', 'updateAvatar', false);
})); }));
this.ddp.on('disconnected', protectedFunction(() => { SDK.driver.on('disconnected', protectedFunction(() => {
reduxStore.dispatch(disconnect()); reduxStore.dispatch(disconnect());
console.log('disconnected', this.ddp);
})); }));
this.ddp.on('stream-room-messages', (ddpMessage) => { SDK.driver.on('stream-room-messages', (error, ddpMessage) => {
// TODO: debounce // TODO: debounce
const message = _buildMessage(ddpMessage.fields.args[0]); const message = _buildMessage(ddpMessage.fields.args[0]);
requestAnimationFrame(() => reduxStore.dispatch(roomMessageReceived(message))); requestAnimationFrame(() => reduxStore.dispatch(roomMessageReceived(message)));
}); });
this.ddp.on('stream-notify-room', protectedFunction((ddpMessage) => { SDK.driver.on('stream-notify-room', protectedFunction((error, ddpMessage) => {
const [_rid, ev] = ddpMessage.fields.eventName.split('/'); const [_rid, ev] = ddpMessage.fields.eventName.split('/');
if (ev === 'typing') { if (ev === 'typing') {
reduxStore.dispatch(someoneTyping({ _rid, username: ddpMessage.fields.args[0], typing: ddpMessage.fields.args[1] })); reduxStore.dispatch(someoneTyping({ _rid, username: ddpMessage.fields.args[0], typing: ddpMessage.fields.args[1] }));
@ -206,7 +226,7 @@ const RocketChat = {
} }
})); }));
this.ddp.on('rocketchat_starred_message', protectedFunction((ddpMessage) => { SDK.driver.on('rocketchat_starred_message', protectedFunction((error, ddpMessage) => {
if (ddpMessage.msg === 'added') { if (ddpMessage.msg === 'added') {
this.starredMessages = this.starredMessages || []; this.starredMessages = this.starredMessages || [];
@ -232,7 +252,7 @@ const RocketChat = {
} }
})); }));
this.ddp.on('rocketchat_pinned_message', protectedFunction((ddpMessage) => { SDK.driver.on('rocketchat_pinned_message', protectedFunction((error, ddpMessage) => {
if (ddpMessage.msg === 'added') { if (ddpMessage.msg === 'added') {
this.pinnedMessages = this.pinnedMessages || []; this.pinnedMessages = this.pinnedMessages || [];
@ -258,7 +278,7 @@ const RocketChat = {
} }
})); }));
this.ddp.on('rocketchat_mentioned_message', protectedFunction((ddpMessage) => { SDK.driver.on('rocketchat_mentioned_message', protectedFunction((error, ddpMessage) => {
if (ddpMessage.msg === 'added') { if (ddpMessage.msg === 'added') {
this.mentionedMessages = this.mentionedMessages || []; this.mentionedMessages = this.mentionedMessages || [];
@ -279,7 +299,7 @@ const RocketChat = {
} }
})); }));
this.ddp.on('rocketchat_snippeted_message', protectedFunction((ddpMessage) => { SDK.driver.on('rocketchat_snippeted_message', protectedFunction((error, ddpMessage) => {
if (ddpMessage.msg === 'added') { if (ddpMessage.msg === 'added') {
this.snippetedMessages = this.snippetedMessages || []; this.snippetedMessages = this.snippetedMessages || [];
@ -300,7 +320,7 @@ const RocketChat = {
} }
})); }));
this.ddp.on('room_files', protectedFunction((ddpMessage) => { SDK.driver.on('room_files', protectedFunction((error, ddpMessage) => {
if (ddpMessage.msg === 'added') { if (ddpMessage.msg === 'added') {
this.roomFiles = this.roomFiles || []; this.roomFiles = this.roomFiles || [];
@ -344,7 +364,7 @@ const RocketChat = {
} }
})); }));
this.ddp.on('meteor_accounts_loginServiceConfiguration', protectedFunction((ddpMessage) => { SDK.driver.on('meteor_accounts_loginServiceConfiguration', (error, ddpMessage) => {
if (ddpMessage.msg === 'added') { if (ddpMessage.msg === 'added') {
this.loginServices = this.loginServices || {}; this.loginServices = this.loginServices || {};
if (this.loginServiceTimer) { if (this.loginServiceTimer) {
@ -364,9 +384,9 @@ const RocketChat = {
} }
this.loginServiceTimer = setTimeout(() => reduxStore.dispatch(removeLoginServices()), 1000); this.loginServiceTimer = setTimeout(() => reduxStore.dispatch(removeLoginServices()), 1000);
} }
})); });
this.ddp.on('rocketchat_roles', protectedFunction((ddpMessage) => { SDK.driver.on('rocketchat_roles', protectedFunction((error, ddpMessage) => {
this.roles = this.roles || {}; this.roles = this.roles || {};
if (this.roleTimer) { if (this.roleTimer) {
@ -388,27 +408,25 @@ const RocketChat = {
this.roles[ddpMessage.id] = (ddpMessage.fields && ddpMessage.fields.description) || undefined; this.roles[ddpMessage.id] = (ddpMessage.fields && ddpMessage.fields.description) || undefined;
})); }));
this.ddp.on('error', (err) => { // SDK.driver.on('error', (err) => {
log('rocketchat.onerror', err); // log('SDK.onerror', err);
reduxStore.dispatch(connectFailure()); // reduxStore.dispatch(connectFailure());
}); // });
// TODO: fix api (get emojis by date/version....) // SDK.driver.on('open', protectedFunction(() => {
// RocketChat.getSettings();
// RocketChat.getPermissions();
// reduxStore.dispatch(connectSuccess());
// resolve();
// }));
this.ddp.on('open', protectedFunction(() => { // this.ddp.once('open', protectedFunction(() => {
RocketChat.getSettings(); // this.ddp.subscribe('activeUsers');
RocketChat.getPermissions(); // this.ddp.subscribe('roles');
reduxStore.dispatch(connectSuccess()); // RocketChat.getCustomEmoji();
resolve(); // }));
}));
this.ddp.once('open', protectedFunction(() => {
this.ddp.subscribe('activeUsers');
this.ddp.subscribe('roles');
RocketChat.getCustomEmoji();
}));
}).catch((e) => { }).catch((e) => {
log('rocketchat.connect catch', e); log('SDK.connect catch', e);
}); });
}, },
@ -424,7 +442,7 @@ const RocketChat = {
return call('sendForgotPasswordEmail', email); return call('sendForgotPasswordEmail', email);
}, },
loginWithPassword({ username, password, code }, callback) { async loginWithPassword({ username, password, code }) {
let params = {}; let params = {};
const state = reduxStore.getState(); const state = reduxStore.getState();
@ -443,14 +461,12 @@ const RocketChat = {
}; };
} else { } else {
params = { params = {
password: hashPassword(password), username, password
user: {
username
}
}; };
if (typeof username === 'string' && username.indexOf('@') !== -1) { if (typeof username === 'string' && username.indexOf('@') !== -1) {
params.user = { email: username }; params.email = username;
delete params.username;
} }
} }
@ -463,25 +479,45 @@ const RocketChat = {
}; };
} }
return this.login(params, callback); try {
return await this.login(params);
} catch (error) {
throw error;
}
}, },
login(params) { async login(params) {
return this.ddp.login(params); try {
await SDK.driver.login(params);
} catch (e) {
reduxStore.dispatch(loginFailure(e));
throw e;
}
}, },
logout({ server }) { logout({ server }) {
if (this.ddp) {
try { try {
this.ddp.logout(); RocketChat.disconnect();
} catch (e) { SDK.driver.logout();
log('rocketchat.logout', e); } catch (error) {
} console.warn(error);
} }
AsyncStorage.removeItem(TOKEN_KEY); AsyncStorage.removeItem(TOKEN_KEY);
AsyncStorage.removeItem(`${ TOKEN_KEY }-${ server }`); AsyncStorage.removeItem(`${ TOKEN_KEY }-${ server }`);
setTimeout(() => { setTimeout(() => {
database.deleteAll(); database.deleteAll();
}, 1000); }, 300);
},
disconnect() {
try {
SDK.driver.unsubscribeAll();
} catch (error) {
console.warn(error);
}
SDK.api.setAuth({ authToken: null, userId: null });
SDK.api.currentLogin = {
userId: null,
authToken: null
};
}, },
registerPushToken(userId) { registerPushToken(userId) {
@ -508,27 +544,6 @@ const RocketChat = {
sendMessage, sendMessage,
getRooms, getRooms,
readMessages, readMessages,
me({ server = reduxStore.getState().server.server, token, userId }) {
return fetch(`${ server }/api/v1/me`, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': token,
'X-User-Id': userId
}
}).then(response => response.json());
},
userInfo({ server = reduxStore.getState().server.server, token, userId }) {
return fetch(`${ server }/api/v1/users.info?userId=${ userId }`, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': token,
'X-User-Id': userId
}
}).then(response => response.json());
},
async resendMessage(messageId) { async resendMessage(messageId) {
const message = await database.objects('messages').filtered('_id = $0', messageId)[0]; const message = await database.objects('messages').filtered('_id = $0', messageId)[0];
database.write(() => { database.write(() => {
@ -657,7 +672,7 @@ const RocketChat = {
try { try {
room = await RocketChat.getRoom(message.rid); room = await RocketChat.getRoom(message.rid);
} catch (e) { } catch (e) {
log('rocketchat.getPermalink', e); log('SDK.getPermalink', e);
return null; return null;
} }
const { server } = reduxStore.getState().server; const { server } = reduxStore.getState().server;
@ -669,7 +684,10 @@ const RocketChat = {
return `${ server }/${ roomType }/${ room.name }?msg=${ message._id }`; return `${ server }/${ roomType }/${ room.name }?msg=${ message._id }`;
}, },
subscribe(...args) { subscribe(...args) {
return this.ddp.subscribe(...args); return SDK.driver.subscribe(...args);
},
unsubscribe(subscription) {
return SDK.driver.unsubscribe(subscription);
}, },
emitTyping(room, t = true) { emitTyping(room, t = true) {
const { login } = reduxStore.getState(); const { login } = reduxStore.getState();

View File

@ -34,7 +34,7 @@ const test = function* test() {
const user = yield call(getToken); const user = yield call(getToken);
// const response = // const response =
// yield all([call(connect, server, user && user.token ? { resume: user.token, ...user.user } : undefined)]);// , put(loginRequest({ resume: user.token }))]); // yield all([call(connect, server, user && user.token ? { resume: user.token, ...user.user } : undefined)]);// , put(loginRequest({ resume: user.token }))]);
yield call(connect, server, user && user.token ? { resume: user.token, ...user.user } : undefined); yield call(connect, server, user && user.token ? { resume: user.token, ...user } : null);
// yield put(connectSuccess(response)); // yield put(connectSuccess(response));
} catch (err) { } catch (err) {
console.warn('test', err); console.warn('test', err);

View File

@ -29,7 +29,11 @@ const restore = function* restore() {
} }
yield put(selectServerRequest(currentServer)); yield put(selectServerRequest(currentServer));
yield put(setUser(userParsed)); yield put(setUser(userParsed));
} else {
yield put(actions.appStart('outside'));
} }
} else {
yield put(actions.appStart('outside'));
} }
const sortPreferences = yield RocketChat.getSortPreferences(); const sortPreferences = yield RocketChat.getSortPreferences();

View File

@ -10,7 +10,7 @@ let newSub;
const openRoomFiles = function* openRoomFiles({ rid, limit }) { const openRoomFiles = function* openRoomFiles({ rid, limit }) {
try { try {
newSub = yield RocketChat.subscribe('roomFiles', rid, limit); sub = yield RocketChat.subscribe('roomFiles', rid, limit);
yield put(readyRoomFiles()); yield put(readyRoomFiles());
if (sub) { if (sub) {
sub.unsubscribe().catch(err => console.warn(err)); sub.unsubscribe().catch(err => console.warn(err));
@ -23,6 +23,8 @@ const openRoomFiles = function* openRoomFiles({ rid, limit }) {
const closeRoomFiles = function* closeRoomFiles() { const closeRoomFiles = function* closeRoomFiles() {
try { try {
// yield sub.unsubscribe(sub);
// sub = null;
if (sub) { if (sub) {
yield sub.unsubscribe(); yield sub.unsubscribe();
} }

View File

@ -68,10 +68,10 @@ export default class RoomInfoEditView extends LoggedView {
async componentDidMount() { async componentDidMount() {
const { room } = this.state;
await this.updateRoom(); await this.updateRoom();
this.init(); this.init();
this.rooms.addListener(this.updateRoom); this.rooms.addListener(this.updateRoom);
const { room } = this.state;
this.permissions = RocketChat.hasPermission(PERMISSIONS_ARRAY, room.rid); this.permissions = RocketChat.hasPermission(PERMISSIONS_ARRAY, room.rid);
} }

View File

@ -5,6 +5,7 @@ import {
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect, Provider } from 'react-redux'; import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation'; import { Navigation } from 'react-native-navigation';
import * as SDK from '@rocket.chat/sdk';
import { toggleServerDropdown as toggleServerDropdownAction } from '../../actions/rooms'; import { toggleServerDropdown as toggleServerDropdownAction } from '../../actions/rooms';
import { selectServerRequest as selectServerRequestAction } from '../../actions/server'; import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
@ -106,15 +107,19 @@ export default class ServerDropdown extends Component {
select = async(server) => { select = async(server) => {
const { const {
server: serverProp, selectServerRequest, appStart, navigator server: currentServer, selectServerRequest, appStart, navigator
} = this.props; } = this.props;
this.close(); this.close();
if (serverProp !== server) { if (currentServer !== server) {
selectServerRequest(server);
const token = await AsyncStorage.getItem(`${ RocketChat.TOKEN_KEY }-${ server }`); const token = await AsyncStorage.getItem(`${ RocketChat.TOKEN_KEY }-${ server }`);
if (!token) { if (!token) {
appStart(); appStart();
try {
SDK.driver.disconnect();
} catch (error) {
console.warn(error);
}
if (NewServerView == null) { if (NewServerView == null) {
NewServerView = require('../NewServerView').default; NewServerView = require('../NewServerView').default;
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider); Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
@ -131,6 +136,8 @@ export default class ServerDropdown extends Component {
} }
}); });
}, 1000); }, 1000);
} else {
selectServerRequest(server);
} }
} }
} }
@ -149,6 +156,7 @@ export default class ServerDropdown extends Component {
source={{ uri: item.iconURL }} source={{ uri: item.iconURL }}
defaultSource={{ uri: 'logo' }} defaultSource={{ uri: 'logo' }}
style={styles.serverIcon} style={styles.serverIcon}
onError={() => console.warn('error loading serverIcon')}
/> />
) )
: ( : (

90
package-lock.json generated
View File

@ -1820,6 +1820,30 @@
"resolved": "https://registry.npmjs.org/@remobile/react-native-toast/-/react-native-toast-1.0.7.tgz", "resolved": "https://registry.npmjs.org/@remobile/react-native-toast/-/react-native-toast-1.0.7.tgz",
"integrity": "sha512-iOD1PRnTSVr9sDWQdesIpfRrwJhHfeEQe5BpalQxC5OhM9thpiE6cu2NlW1KBWl0RJG4ZiJaF1xLlCo9YxU6dA==" "integrity": "sha512-iOD1PRnTSVr9sDWQdesIpfRrwJhHfeEQe5BpalQxC5OhM9thpiE6cu2NlW1KBWl0RJG4ZiJaF1xLlCo9YxU6dA=="
}, },
"@rocket.chat/sdk": {
"version": "git+https://github.com/RocketChat/Rocket.Chat.js.SDK.git#a2af4675174ce53076ba587693e5210c05ee767d",
"from": "git+https://github.com/RocketChat/Rocket.Chat.js.SDK.git#ddp",
"requires": {
"@types/lru-cache": "^4.1.0",
"@types/node": "^9.4.6",
"axios": "^0.18.0",
"ejson": "^2.1.2",
"isomorphic-ws": "^4.0.1",
"lru-cache": "^4.1.1",
"universal-websocket-client": "^1.0.2",
"ws": "^5.2.0"
},
"dependencies": {
"ws": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
"requires": {
"async-limiter": "~1.0.0"
}
}
}
},
"@storybook/addon-actions": { "@storybook/addon-actions": {
"version": "3.4.11", "version": "3.4.11",
"resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-3.4.11.tgz", "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-3.4.11.tgz",
@ -2210,11 +2234,21 @@
"react-treebeard": "2.1.0" "react-treebeard": "2.1.0"
} }
}, },
"@types/lru-cache": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.1.tgz",
"integrity": "sha512-8mNEUG6diOrI6pMqOHrHPDBB1JsrpedeMK9AWGzVCQ7StRRribiT9BRvUmF8aUws9iBbVlgVekOT5Sgzc1MTKw=="
},
"@types/markdown-it": { "@types/markdown-it": {
"version": "0.0.4", "version": "0.0.4",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.4.tgz",
"integrity": "sha512-FWR7QB7EqBRq1s9BMk0ccOSOuRLfVEWYpHQYpFPaXtCoqN6dJx2ttdsdQbUxLLnAlKpYeVjveGGhQ3583TTa7g==" "integrity": "sha512-FWR7QB7EqBRq1s9BMk0ccOSOuRLfVEWYpHQYpFPaXtCoqN6dJx2ttdsdQbUxLLnAlKpYeVjveGGhQ3583TTa7g=="
}, },
"@types/node": {
"version": "9.6.34",
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.34.tgz",
"integrity": "sha512-PzJpSs2afoYqBA4yLBgaKUdZRk8+1yvkxcUBW6958h4vYOC+pc4k4C+QmQ6AO5Pt7uA4EIIboFog6YNCuITD0g=="
},
"@types/react": { "@types/react": {
"version": "16.4.6", "version": "16.4.6",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.6.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.6.tgz",
@ -2934,6 +2968,15 @@
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
}, },
"axios": {
"version": "0.18.0",
"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": {
"follow-redirects": "^1.3.0",
"is-buffer": "^1.1.5"
}
},
"axobject-query": { "axobject-query": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.1.tgz", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.1.tgz",
@ -8354,6 +8397,24 @@
"readable-stream": "2.3.5" "readable-stream": "2.3.5"
} }
}, },
"follow-redirects": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz",
"integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==",
"requires": {
"debug": "=3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
}
}
},
"for-in": { "for-in": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@ -10697,6 +10758,11 @@
"whatwg-fetch": "2.0.3" "whatwg-fetch": "2.0.3"
} }
}, },
"isomorphic-ws": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
"integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w=="
},
"isstream": { "isstream": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@ -13737,7 +13803,7 @@
}, },
"rimraf": { "rimraf": {
"version": "2.4.5", "version": "2.4.5",
"resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
"dev": true, "dev": true,
"optional": true, "optional": true,
@ -13873,7 +13939,7 @@
}, },
"ncp": { "ncp": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
"dev": true, "dev": true,
"optional": true "optional": true
@ -20472,6 +20538,26 @@
"crypto-random-string": "1.0.0" "crypto-random-string": "1.0.0"
} }
}, },
"universal-websocket-client": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/universal-websocket-client/-/universal-websocket-client-1.0.2.tgz",
"integrity": "sha512-Pi6BdJtEAISb77GTbOLBLIWdYGezXgnJejrVBYKXxzNTsLcjJS+mWIJ2BRZElSlOG/wc7+yfOe5y30bzTu3Qqg==",
"requires": {
"ws": "^3.3.3"
},
"dependencies": {
"ws": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
"requires": {
"async-limiter": "~1.0.0",
"safe-buffer": "~5.1.0",
"ultron": "~1.1.0"
}
}
}
},
"universalify": { "universalify": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",

View File

@ -23,6 +23,7 @@
}, },
"dependencies": { "dependencies": {
"@remobile/react-native-toast": "^1.0.7", "@remobile/react-native-toast": "^1.0.7",
"@rocket.chat/sdk": "git+https://github.com/RocketChat/Rocket.Chat.js.SDK.git#ddp",
"deep-equal": "^1.0.1", "deep-equal": "^1.0.1",
"ejson": "^2.1.2", "ejson": "^2.1.2",
"js-base64": "^2.4.9", "js-base64": "^2.4.9",