Chore: Dehydrate share extension from rocketchat.js (#3753)

Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
This commit is contained in:
Gerzon Z 2022-03-16 16:40:32 -04:00 committed by GitHub
parent e792f2a49b
commit a754983ac8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 152 additions and 102 deletions

View File

@ -37,6 +37,21 @@ class AvatarContainer extends React.Component<IAvatar, any> {
}
}
shouldComponentUpdate(nextProps: IAvatar, nextState: { avatarETag: string }) {
const { avatarETag } = this.state;
const { text, type } = this.props;
if (nextState.avatarETag !== avatarETag) {
return true;
}
if (nextProps.text !== text) {
return true;
}
if (nextProps.type !== type) {
return true;
}
return false;
}
componentWillUnmount() {
if (this.subscription?.unsubscribe) {
this.subscription.unsubscribe();

View File

@ -1,4 +1,5 @@
export interface ICredentials {
resume?: string;
user?: string;
password?: string;
username?: string;

View File

@ -66,7 +66,7 @@ export const getDatabase = (database = ''): Database => {
};
interface IDatabases {
shareDB?: TAppDatabase;
shareDB?: TAppDatabase | null;
serversDB: TServerDatabase;
activeDB?: TAppDatabase;
}

View File

@ -2,13 +2,10 @@ import { Q } from '@nozbe/watermelondb';
import AsyncStorage from '@react-native-community/async-storage';
import { InteractionManager } from 'react-native';
import { setActiveUsers } from '../../actions/activeUsers';
import { encryptionInit } from '../../actions/encryption';
import { setUser } from '../../actions/login';
import { shareSelectServer, shareSetSettings, shareSetUser } from '../../actions/share';
import defaultSettings from '../../constants/settings';
import { getDeviceToken } from '../../notifications/push';
import log from '../../utils/log';
import SSLPinning from '../../utils/sslPinning';
import database from '../database';
import triggerBlockAction, { triggerCancel, triggerSubmitView } from '../methods/actions';
import callJitsi, { callJitsiWithoutServer } from '../methods/callJitsi';
@ -65,7 +62,8 @@ import {
stopListener,
connect
} from './services/connect';
import * as restAPis from './services/restApi';
import { shareExtensionInit, closeShareExtension } from './services/shareExtension';
import * as restApis from './services/restApi';
const TOKEN_KEY = 'reactnativemeteor_usertoken';
const CURRENT_SERVER = 'currentServer';
@ -81,7 +79,7 @@ const RocketChat = {
TOKEN_KEY,
CURRENT_SERVER,
CERTIFICATE_KEY,
...restAPis,
...restApis,
...search,
callJitsi,
callJitsiWithoutServer,
@ -109,81 +107,11 @@ const RocketChat = {
checkAndReopen,
disconnect,
connect,
async shareExtensionInit(server) {
database.setShareDB(server);
try {
const certificate = UserPreferences.getString(`${RocketChat.CERTIFICATE_KEY}-${server}`);
SSLPinning.setCertificate(certificate, server);
} catch {
// Do nothing
}
this.shareSDK = sdk.disconnect();
this.shareSDK = sdk.initialize(server);
// set Server
const currentServer = { server };
const serversDB = database.servers;
const serversCollection = serversDB.get('servers');
try {
const serverRecord = await serversCollection.find(server);
currentServer.version = serverRecord.version;
} catch {
// Record not found
}
reduxStore.dispatch(shareSelectServer(currentServer));
RocketChat.setCustomEmojis();
try {
// set Settings
const settings = ['Accounts_AvatarBlockUnauthenticatedAccess'];
const db = database.active;
const settingsCollection = db.get('settings');
const settingsRecords = await settingsCollection.query(Q.where('id', Q.oneOf(settings))).fetch();
const parsed = Object.values(settingsRecords).map(item => ({
_id: item.id,
valueAsString: item.valueAsString,
valueAsBoolean: item.valueAsBoolean,
valueAsNumber: item.valueAsNumber,
valueAsArray: item.valueAsArray,
_updatedAt: item._updatedAt
}));
reduxStore.dispatch(shareSetSettings(this.parseSettings(parsed)));
// set User info
const userId = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${server}`);
const userCollections = serversDB.get('users');
let user = null;
if (userId) {
const userRecord = await userCollections.find(userId);
user = {
id: userRecord.id,
token: userRecord.token,
username: userRecord.username,
roles: userRecord.roles
};
}
reduxStore.dispatch(shareSetUser(user));
await RocketChat.login({ resume: user.token });
reduxStore.dispatch(encryptionInit());
} catch (e) {
log(e);
}
},
closeShareExtension() {
this.shareSDK = sdk.disconnect();
database.share = null;
reduxStore.dispatch(shareSelectServer({}));
reduxStore.dispatch(shareSetUser({}));
reduxStore.dispatch(shareSetSettings({}));
},
shareExtensionInit,
closeShareExtension,
async e2eFetchMyKeys() {
// RC 0.70.0
const sdk = this.shareSDK || this.sdk;
const result = await sdk.get('e2e.fetchMyKeys');
// snake_case -> camelCase
if (result.success) {

View File

@ -9,19 +9,27 @@ import { Serialized, MatchPathPattern, OperationParams, PathFor, ResultFor } fro
class Sdk {
private sdk: typeof Rocketchat;
private shareSdk?: typeof Rocketchat;
private code: any;
private initializeSdk(server: string): typeof Rocketchat {
// The app can't reconnect if reopen interval is 5s while in development
return new Rocketchat({ host: server, protocol: 'ddp', useSsl: useSsl(server), reopen: __DEV__ ? 20000 : 5000 });
}
// TODO: We need to stop returning the SDK after all methods are dehydrated
initialize(server: string) {
this.code = null;
// The app can't reconnect if reopen interval is 5s while in development
this.sdk = new Rocketchat({ host: server, protocol: 'ddp', useSsl: useSsl(server), reopen: __DEV__ ? 20000 : 5000 });
this.sdk = this.initializeSdk(server);
return this.sdk;
}
initializeShareExtension(server: string) {
this.shareSdk = this.initializeSdk(server);
}
get current() {
return this.sdk;
return this.shareSdk || this.sdk;
}
/**
@ -29,6 +37,11 @@ class Sdk {
* I'm returning "null" because we need to remove both instances of this.sdk here and on rocketchat.js
*/
disconnect() {
if (this.shareSdk) {
this.shareSdk.disconnect();
this.shareSdk = null;
return null;
}
if (this.sdk) {
this.sdk.disconnect();
this.sdk = null;
@ -47,7 +60,7 @@ class Sdk {
? void
: Serialized<OperationParams<'GET', MatchPathPattern<TPath>>>
): Promise<Serialized<ResultFor<'GET', MatchPathPattern<TPath>>>> {
return this.sdk.get(endpoint, params);
return this.current.get(endpoint, params);
}
post<TPath extends PathFor<'POST'>>(
@ -64,7 +77,7 @@ class Sdk {
return new Promise(async (resolve, reject) => {
const isMethodCall = endpoint?.startsWith('method.call/');
try {
const result = await this.sdk.post(endpoint, params);
const result = await this.current.post(endpoint, params);
/**
* if API_Use_REST_For_DDP_Calls is enabled and it's a method call,
@ -101,7 +114,7 @@ class Sdk {
methodCall(...args: any[]): Promise<any> {
return new Promise(async (resolve, reject) => {
try {
const result = await this.sdk?.methodCall(...args, this.code || '');
const result = await this.current.methodCall(...args, this.code || '');
return resolve(result);
} catch (e: any) {
if (e.error && (e.error === 'totp-required' || e.error === 'totp-invalid')) {
@ -140,23 +153,23 @@ class Sdk {
}
subscribe(...args: any[]) {
return this.sdk.subscribe(...args);
return this.current.subscribe(...args);
}
subscribeRaw(...args: any[]) {
return this.sdk.subscribeRaw(...args);
return this.current.subscribeRaw(...args);
}
subscribeRoom(...args: any[]) {
return this.sdk.subscribeRoom(...args);
return this.current.subscribeRoom(...args);
}
unsubscribe(subscription: any[]) {
return this.sdk.unsubscribe(subscription);
return this.current.unsubscribe(subscription);
}
onStreamData(...args: any[]) {
return this.sdk.onStreamData(...args);
return this.current.onStreamData(...args);
}
}

View File

@ -0,0 +1,92 @@
import { Q } from '@nozbe/watermelondb';
import { shareSetSettings, shareSelectServer, shareSetUser } from '../../../actions/share';
import SSLPinning from '../../../utils/sslPinning';
import log from '../../../utils/log';
import { IShareServer, IShareUser } from '../../../reducers/share';
import UserPreferences from '../../userPreferences';
import database from '../../database';
import RocketChat from '../rocketchat';
import { encryptionInit } from '../../../actions/encryption';
import { store } from '../../auxStore';
import sdk from './sdk';
export async function shareExtensionInit(server: string) {
database.setShareDB(server);
try {
const certificate = UserPreferences.getString(`${RocketChat.CERTIFICATE_KEY}-${server}`);
if (SSLPinning && certificate) {
await SSLPinning.setCertificate(certificate, server);
}
} catch {
// Do nothing
}
// sdk.current.disconnect();
sdk.initializeShareExtension(server);
// set Server
const currentServer: IShareServer = {
server,
version: ''
};
const serversDB = database.servers;
const serversCollection = serversDB.get('servers');
try {
const serverRecord = await serversCollection.find(server);
currentServer.version = serverRecord.version;
} catch {
// Record not found
}
store.dispatch(shareSelectServer(currentServer));
RocketChat.setCustomEmojis();
try {
// set Settings
const settings = ['Accounts_AvatarBlockUnauthenticatedAccess'];
const db = database.active;
const settingsCollection = db.get('settings');
const settingsRecords = await settingsCollection.query(Q.where('id', Q.oneOf(settings))).fetch();
const parsed = Object.values(settingsRecords).map(item => ({
_id: item.id,
valueAsString: item.valueAsString,
valueAsBoolean: item.valueAsBoolean,
valueAsNumber: item.valueAsNumber,
valueAsArray: item.valueAsArray,
_updatedAt: item._updatedAt
}));
store.dispatch(shareSetSettings(RocketChat.parseSettings(parsed)));
// set User info
const userId = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${server}`);
const userCollections = serversDB.get('users');
let user = null;
if (userId) {
const userRecord = await userCollections.find(userId);
user = {
id: userRecord.id,
token: userRecord.token,
username: userRecord.username,
roles: userRecord.roles
};
}
store.dispatch(shareSetUser(user as IShareUser));
if (user) {
await RocketChat.login({ resume: user.token });
}
store.dispatch(encryptionInit());
} catch (e) {
log(e);
}
}
export function closeShareExtension() {
sdk.disconnect();
database.share = null;
store.dispatch(shareSelectServer({}));
store.dispatch(shareSetUser({}));
store.dispatch(shareSetSettings({}));
}

View File

@ -2,17 +2,17 @@ import { TActionsShare } from '../actions/share';
import { SHARE } from '../actions/actionsTypes';
export interface IShareServer {
server: string;
version: string;
server?: string;
version?: string;
}
export type TShareSettings = Record<string, string | number | boolean>;
export interface IShareUser {
id: string;
token: string;
username: string;
roles: string[];
id?: string;
token?: string;
username?: string;
roles?: string[];
}
export interface IShare {
@ -22,8 +22,8 @@ export interface IShare {
}
export const initialState: IShare = {
user: {} as IShareUser,
server: {} as IShareServer,
user: {},
server: {},
settings: {}
};

View File

@ -10,6 +10,7 @@ import UserPreferences from './lib/userPreferences';
import Navigation from './lib/ShareNavigation';
import store from './lib/createStore';
import { initStore } from './lib/auxStore';
import { closeShareExtension, shareExtensionInit } from './lib/rocketchat/services/shareExtension';
import { defaultHeader, getActiveRouteName, navigationTheme, themedHeader } from './utils/navigation';
import RocketChat from './lib/rocketchat';
import { ThemeContext } from './theme';
@ -107,7 +108,7 @@ class Root extends React.Component<{}, IState> {
}
componentWillUnmount(): void {
RocketChat.closeShareExtension();
closeShareExtension();
unsubscribeTheme();
}
@ -117,7 +118,7 @@ class Root extends React.Component<{}, IState> {
if (currentServer) {
await localAuthenticate(currentServer);
this.setState({ root: 'inside' });
await RocketChat.shareExtensionInit(currentServer);
await shareExtensionInit(currentServer);
} else {
this.setState({ root: 'outside' });
}

View File

@ -7,7 +7,7 @@ import { Q, Model } from '@nozbe/watermelondb';
import I18n from '../i18n';
import StatusBar from '../containers/StatusBar';
import ServerItem, { ROW_HEIGHT } from '../presentation/ServerItem';
import RocketChat from '../lib/rocketchat';
import { shareExtensionInit } from '../lib/rocketchat/services/shareExtension';
import database from '../lib/database';
import SafeAreaView from '../containers/SafeAreaView';
import * as List from '../containers/List';
@ -50,7 +50,7 @@ class SelectServerView extends React.Component<ISelectServerViewProps, ISelectSe
navigation.navigate('ShareListView');
if (currentServer !== server) {
await RocketChat.shareExtensionInit(server);
await shareExtensionInit(server);
}
};