From 68f5a94f5a7b0362b3fd8e649c8cbca6800008c3 Mon Sep 17 00:00:00 2001
From: Diego Mello <diegolmello@gmail.com>
Date: Tue, 12 Feb 2019 14:14:11 -0200
Subject: [PATCH] [FIX] SDK issues (#621)

* Remove listeners from room
* Properly close connections on change server
* Minor layout change on connecting badge
---
 app/containers/ConnectionBadge.js     | 50 +++++++++++++------------
 app/lib/methods/subscriptions/room.js | 53 ++++++++++++++++-----------
 app/lib/rocketchat.js                 |  7 +++-
 app/reducers/connect.js               |  3 +-
 app/reducers/rooms.js                 |  2 +-
 package.json                          |  2 +-
 yarn.lock                             |  8 ++--
 7 files changed, 73 insertions(+), 52 deletions(-)

diff --git a/app/containers/ConnectionBadge.js b/app/containers/ConnectionBadge.js
index c357e980a..e2f9818a9 100644
--- a/app/containers/ConnectionBadge.js
+++ b/app/containers/ConnectionBadge.js
@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
 import {
-	Text, StyleSheet, ActivityIndicator, Animated, TouchableWithoutFeedback, Easing
+	Text, StyleSheet, ActivityIndicator, Animated, Easing
 } from 'react-native';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
@@ -50,20 +50,30 @@ class ConnectionBadge extends Component {
 	static propTypes = {
 		connecting: PropTypes.bool,
 		connected: PropTypes.bool,
-		disconnected: PropTypes.bool // eslint-disable-line
+		disconnected: PropTypes.bool
 	}
 
 	constructor(props) {
 		super(props);
 		this.animatedValue = new Animated.Value(0);
+		if (props.connecting) {
+			this.show();
+		}
 	}
 
 	componentDidUpdate() {
-		this.show();
+		const { connected, disconnected } = this.props;
+		this.show(connected || disconnected);
+	}
+
+	componentWillUnmount() {
+		if (this.timeout) {
+			clearTimeout(this.timeout);
+		}
 	}
 
 	// eslint-disable-next-line react/sort-comp
-	animate = debounce((toValue) => {
+	animate = debounce((toValue, autoHide) => {
 		Animated.timing(
 			this.animatedValue,
 			{
@@ -73,7 +83,7 @@ class ConnectionBadge extends Component {
 				useNativeDriver: true
 			},
 		).start(() => {
-			if (toValue === 1) {
+			if (toValue === 1 && autoHide) {
 				if (this.timeout) {
 					clearTimeout(this.timeout);
 				}
@@ -84,8 +94,8 @@ class ConnectionBadge extends Component {
 		});
 	}, 300);
 
-	show = () => {
-		this.animate(1);
+	show = (autoHide) => {
+		this.animate(1, autoHide);
 	}
 
 	hide = () => {
@@ -102,29 +112,23 @@ class ConnectionBadge extends Component {
 
 		if (connecting) {
 			return (
-				<TouchableWithoutFeedback onPress={this.hide}>
-					<Animated.View style={[styles.container, { transform: [{ translateY }] }]}>
-						<ActivityIndicator color='#9EA2A8' style={styles.activityIndicator} />
-						<Text style={[styles.text, styles.textConnecting]}>{I18n.t('Connecting')}</Text>
-					</Animated.View>
-				</TouchableWithoutFeedback>
+				<Animated.View style={[styles.container, { transform: [{ translateY }] }]}>
+					<ActivityIndicator color='#9EA2A8' style={styles.activityIndicator} />
+					<Text style={[styles.text, styles.textConnecting]}>{I18n.t('Connecting')}</Text>
+				</Animated.View>
 			);
 		} else if (connected) {
 			return (
-				<TouchableWithoutFeedback onPress={this.hide}>
-					<Animated.View style={[styles.container, styles.containerConnected, { transform: [{ translateY }] }]}>
-						<Text style={styles.text}>{I18n.t('Connected')}</Text>
-					</Animated.View>
-				</TouchableWithoutFeedback>
+				<Animated.View style={[styles.container, styles.containerConnected, { transform: [{ translateY }] }]}>
+					<Text style={styles.text}>{I18n.t('Connected')}</Text>
+				</Animated.View>
 			);
 		}
 
 		return (
-			<TouchableWithoutFeedback onPress={this.hide}>
-				<Animated.View style={[styles.container, styles.containerOffline, { transform: [{ translateY }] }]}>
-					<Text style={styles.text}>{I18n.t('Offline')}</Text>
-				</Animated.View>
-			</TouchableWithoutFeedback>
+			<Animated.View style={[styles.container, styles.containerOffline, { transform: [{ translateY }] }]}>
+				<Text style={styles.text}>{I18n.t('Offline')}</Text>
+			</Animated.View>
 		);
 	}
 }
diff --git a/app/lib/methods/subscriptions/room.js b/app/lib/methods/subscriptions/room.js
index 43df59c36..fa3508361 100644
--- a/app/lib/methods/subscriptions/room.js
+++ b/app/lib/methods/subscriptions/room.js
@@ -1,18 +1,12 @@
 import log from '../../../utils/log';
 
 const unsubscribe = subscriptions => subscriptions.forEach(sub => sub.unsubscribe().catch(() => console.log('unsubscribeRoom')));
+const removeListener = listener => listener.stop();
 
 let promises;
 let timer = null;
-
-const stop = () => {
-	if (promises) {
-		promises.then(unsubscribe);
-		promises = false;
-	}
-
-	clearTimeout(timer);
-};
+let connectedListener;
+let disconnectedListener;
 
 export default function subscribeRoom({ rid }) {
 	if (promises) {
@@ -23,31 +17,48 @@ export default function subscribeRoom({ rid }) {
 		if (timer) {
 			return;
 		}
-		timer = setTimeout(async() => {
+		timer = setTimeout(() => {
 			try {
 				clearTimeout(timer);
 				timer = false;
-				if (this.sdk.userId) {
-					await this.loadMissedMessages({ rid });
-					loop();
-				}
+				this.loadMissedMessages({ rid });
+				loop();
 			} catch (e) {
 				loop();
 			}
 		}, 5000);
 	};
 
-	this.sdk.onStreamData('connected', () => {
+	const handleConnected = () => {
+		this.loadMissedMessages({ rid });
+		clearTimeout(timer);
+		timer = false;
+	};
+
+	const handleDisconnected = () => {
 		if (this.sdk.userId) {
-			this.loadMissedMessages({ rid });
+			loop();
+		}
+	};
+
+	const stop = () => {
+		if (promises) {
+			promises.then(unsubscribe);
+			promises = false;
+		}
+		if (connectedListener) {
+			connectedListener.then(removeListener);
+			connectedListener = false;
+		}
+		if (disconnectedListener) {
+			disconnectedListener.then(removeListener);
+			disconnectedListener = false;
 		}
 		clearTimeout(timer);
-		timer = false;
-	});
+	};
 
-	this.sdk.onStreamData('close', () => {
-		loop();
-	});
+	connectedListener = this.sdk.onStreamData('connected', handleConnected);
+	disconnectedListener = this.sdk.onStreamData('close', handleDisconnected);
 
 	try {
 		promises = this.sdk.subscribeRoom(rid);
diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js
index da4c82746..9d4f673b1 100644
--- a/app/lib/rocketchat.js
+++ b/app/lib/rocketchat.js
@@ -141,7 +141,7 @@ const RocketChat = {
 		this.sdk.subscribe('roles');
 		this.getPermissions();
 		this.getCustomEmoji();
-		this.registerPushToken().then(result => console.log(result)).catch(e => console.log(e));
+		this.registerPushToken().catch(e => console.log(e));
 	},
 	connect({ server, user }) {
 		database.setActiveDB(server);
@@ -151,6 +151,11 @@ const RocketChat = {
 			clearTimeout(this.connectTimeout);
 		}
 
+		if (this.sdk) {
+			this.sdk.disconnect();
+			this.sdk = null;
+		}
+
 		// Use useSsl: false only if server url starts with http://
 		const useSsl = !/http:\/\//.test(server);
 
diff --git a/app/reducers/connect.js b/app/reducers/connect.js
index 324cb710a..a8ef2bea1 100644
--- a/app/reducers/connect.js
+++ b/app/reducers/connect.js
@@ -10,7 +10,8 @@ export default function connect(state = initialState, action) {
 		case METEOR.REQUEST:
 			return {
 				...state,
-				connecting: true
+				connecting: true,
+				connected: false
 			};
 		case METEOR.SUCCESS:
 			return {
diff --git a/app/reducers/rooms.js b/app/reducers/rooms.js
index f9931babc..5903c0891 100644
--- a/app/reducers/rooms.js
+++ b/app/reducers/rooms.js
@@ -1,7 +1,7 @@
 import * as types from '../actions/actionsTypes';
 
 const initialState = {
-	isFetching: true,
+	isFetching: false,
 	failure: false,
 	errorMessage: {},
 	searchText: '',
diff --git a/package.json b/package.json
index 24ea281ef..2bb76fc8a 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,7 @@
   },
   "dependencies": {
     "@remobile/react-native-toast": "^1.0.7",
-    "@rocket.chat/sdk": "1.0.0-alpha.24",
+    "@rocket.chat/sdk": "1.0.0-alpha.25",
     "deep-equal": "^1.0.1",
     "ejson": "^2.1.2",
     "js-base64": "^2.5.1",
diff --git a/yarn.lock b/yarn.lock
index b0040c680..49be735b9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -988,10 +988,10 @@
   resolved "https://registry.yarnpkg.com/@remobile/react-native-toast/-/react-native-toast-1.0.7.tgz#b2e3684cdb13e1c9d9b4ed08e667157d4ad0fab2"
   integrity sha512-iOD1PRnTSVr9sDWQdesIpfRrwJhHfeEQe5BpalQxC5OhM9thpiE6cu2NlW1KBWl0RJG4ZiJaF1xLlCo9YxU6dA==
 
-"@rocket.chat/sdk@1.0.0-alpha.24":
-  version "1.0.0-alpha.24"
-  resolved "https://registry.yarnpkg.com/@rocket.chat/sdk/-/sdk-1.0.0-alpha.24.tgz#8a6d3ff869c050b34f62bb7ef972d14c1a4d4f79"
-  integrity sha512-5EXVWkzQLGyKB5EdLZdpH86/gQ2rYY12OZ1ClRpAqYZs8svBKOn9pGBEWBW9i0C6ZowedFm8SdQjX4VHw+60hg==
+"@rocket.chat/sdk@1.0.0-alpha.25":
+  version "1.0.0-alpha.25"
+  resolved "https://registry.yarnpkg.com/@rocket.chat/sdk/-/sdk-1.0.0-alpha.25.tgz#7fd6fce64e29c2ab9eb77000f1a65bdd3b0379bb"
+  integrity sha512-/IfiLhTZooJQX1kimPZiY0FNSDw3kZcL/yquxD14kZbKRKm0ZSg5BJeWFpkinQq5Y9XjySX+k3mjmXX3Es97Cg==
   dependencies:
     "@types/event-emitter" "^0.3.2"
     "@types/eventemitter3" "^2.0.2"
-- 
GitLab