From e416fe0c68896af108f9bb8e410d011ff655fbf2 Mon Sep 17 00:00:00 2001
From: Pranay Ankit <pranayankit414@gmail.com>
Date: Wed, 30 Jan 2019 17:41:02 +0530
Subject: [PATCH] [FIX] Better message actions (#567)

---
 android/app/build.gradle                      |  1 +
 .../rocket/reactnative/MainApplication.java   |  2 +
 android/settings.gradle                       |  2 +
 app/containers/MessageActions.js              | 27 ++++-----
 app/containers/MessageBox/FilesActions.js     | 24 ++++----
 app/containers/MessageErrorActions.js         | 48 ++++++++--------
 app/views/PinnedMessagesView/index.js         | 23 ++++----
 app/views/RoomMembersView/index.js            | 55 +++++++++----------
 app/views/StarredMessagesView/index.js        | 23 ++++----
 package-lock.json                             | 20 +++----
 package.json                                  |  2 +-
 11 files changed, 117 insertions(+), 110 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index be575bdfc..0cb7c0add 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -190,6 +190,7 @@ configurations.all {
 }
 
 dependencies {
+    implementation project(':react-native-action-sheet')
     implementation project(':react-native-device-info')
     implementation project(':react-native-gesture-handler')
     implementation project(':react-native-image-crop-picker')
diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
index 48a05a70c..e5865755e 100644
--- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
+++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
@@ -28,6 +28,7 @@ import com.wix.reactnativenotifications.core.notification.INotificationsApplicat
 import com.wix.reactnativenotifications.core.notification.IPushNotification;
 import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
 import com.learnium.RNDeviceInfo.RNDeviceInfo;
+import com.actionsheet.ActionSheetPackage;
 
 import java.util.Arrays;
 import java.util.List;
@@ -71,6 +72,7 @@ public class MainApplication extends NavigationApplication implements INotificat
     public List<ReactPackage> createAdditionalReactPackages() {
         return Arrays.<ReactPackage>asList(
                 new MainReactPackage(),
+                new ActionSheetPackage(),
                 new RNDeviceInfo(),
                 new RNGestureHandlerPackage(),
                 new PickerPackage(),
diff --git a/android/settings.gradle b/android/settings.gradle
index 1a592d3bf..4a6e6fa64 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,4 +1,6 @@
 rootProject.name = 'RocketChatRN'
+include ':react-native-action-sheet'
+project(':react-native-action-sheet').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-action-sheet/android')
 include ':react-native-device-info'
 project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
 include ':react-native-gesture-handler'
diff --git a/app/containers/MessageActions.js b/app/containers/MessageActions.js
index 36f257b7d..2527d052b 100644
--- a/app/containers/MessageActions.js
+++ b/app/containers/MessageActions.js
@@ -4,7 +4,7 @@ import {
 	Alert, Clipboard, Vibration, Share
 } from 'react-native';
 import { connect } from 'react-redux';
-import ActionSheet from 'react-native-actionsheet';
+import ActionSheet from 'react-native-action-sheet';
 import * as moment from 'moment';
 
 import {
@@ -125,9 +125,7 @@ export default class MessageActions extends React.Component {
 			this.DELETE_INDEX = this.options.length - 1;
 		}
 		setTimeout(() => {
-			if (this.actionSheet && this.actionSheet.show) {
-				this.actionSheet.show();
-			}
+			this.showActionSheet();
 			Vibration.vibrate(50);
 		});
 	}
@@ -141,6 +139,17 @@ export default class MessageActions extends React.Component {
 		this.hasForceDeletePermission = result[permissions[2]];
 	}
 
+	showActionSheet = () => {
+		ActionSheet.showActionSheetWithOptions({
+			options: this.options,
+			cancelButtonIndex: this.CANCEL_INDEX,
+			destructiveButtonIndex: this.DELETE_INDEX,
+			title: I18n.t('Message_actions')
+		}, (actionIndex) => {
+			this.handleActionPress(actionIndex);
+		});
+	}
+
 	getPermalink = async(message) => {
 		try {
 			return await RocketChat.getPermalink(message);
@@ -326,15 +335,7 @@ export default class MessageActions extends React.Component {
 
 	render() {
 		return (
-			<ActionSheet
-				ref={o => this.actionSheet = o}
-				title={I18n.t('Message_actions')}
-				testID='message-actions'
-				options={this.options}
-				cancelButtonIndex={this.CANCEL_INDEX}
-				destructiveButtonIndex={this.DELETE_INDEX}
-				onPress={this.handleActionPress}
-			/>
+			null
 		);
 	}
 }
diff --git a/app/containers/MessageBox/FilesActions.js b/app/containers/MessageBox/FilesActions.js
index 8973595fe..1850bacf8 100644
--- a/app/containers/MessageBox/FilesActions.js
+++ b/app/containers/MessageBox/FilesActions.js
@@ -1,6 +1,6 @@
-import React, { PureComponent } from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
-import ActionSheet from 'react-native-actionsheet';
+import ActionSheet from 'react-native-action-sheet';
 
 import I18n from '../../i18n';
 
@@ -27,9 +27,16 @@ export default class FilesActions extends PureComponent {
 		this.LIBRARY_INDEX = 2;
 
 		setTimeout(() => {
-			if (this.actionSheet && this.actionSheet.show) {
-				this.actionSheet.show();
-			}
+			this.showActionSheet();
+		});
+	}
+
+	showActionSheet = () => {
+		ActionSheet.showActionSheetWithOptions({
+			options: this.options,
+			cancelButtonIndex: this.CANCEL_INDEX
+		}, (actionIndex) => {
+			this.handleActionPress(actionIndex);
 		});
 	}
 
@@ -50,12 +57,7 @@ export default class FilesActions extends PureComponent {
 
 	render() {
 		return (
-			<ActionSheet
-				ref={o => this.actionSheet = o}
-				options={this.options}
-				cancelButtonIndex={this.CANCEL_INDEX}
-				onPress={this.handleActionPress}
-			/>
+			null
 		);
 	}
 }
diff --git a/app/containers/MessageErrorActions.js b/app/containers/MessageErrorActions.js
index e87753657..9fc56355e 100644
--- a/app/containers/MessageErrorActions.js
+++ b/app/containers/MessageErrorActions.js
@@ -1,7 +1,7 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
-import ActionSheet from 'react-native-actionsheet';
+import ActionSheet from 'react-native-action-sheet';
 
 import { errorActionsHide as errorActionsHideAction } from '../actions/messages';
 import RocketChat from '../lib/rocketchat';
@@ -23,6 +23,19 @@ export default class MessageErrorActions extends React.Component {
 		actionMessage: PropTypes.object
 	};
 
+	handleResend = protectedFunction(() => {
+		const { actionMessage } = this.props;
+		RocketChat.resendMessage(actionMessage._id);
+	});
+
+	handleDelete = protectedFunction(() => {
+		const { actionMessage } = this.props;
+		database.write(() => {
+			const msg = database.objects('messages').filtered('_id = $0', actionMessage._id);
+			database.delete(msg);
+		});
+	})
+
 	// eslint-disable-next-line react/sort-comp
 	constructor(props) {
 		super(props);
@@ -32,24 +45,20 @@ export default class MessageErrorActions extends React.Component {
 		this.DELETE_INDEX = 1;
 		this.RESEND_INDEX = 2;
 		setTimeout(() => {
-			if (this.actionSheet && this.actionSheet.show) {
-				this.actionSheet.show();
-			}
+			this.showActionSheet();
 		});
 	}
 
-	handleResend = protectedFunction(() => {
-		const { actionMessage } = this.props;
-		RocketChat.resendMessage(actionMessage._id);
-	});
-
-	handleDelete = protectedFunction(() => {
-		const { actionMessage } = this.props;
-		database.write(() => {
-			const msg = database.objects('messages').filtered('_id = $0', actionMessage._id);
-			database.delete(msg);
+	showActionSheet = () => {
+		ActionSheet.showActionSheetWithOptions({
+			options: this.options,
+			cancelButtonIndex: this.CANCEL_INDEX,
+			destructiveButtonIndex: this.DELETE_INDEX,
+			title: I18n.t('Message_actions')
+		}, (actionIndex) => {
+			this.handleActionPress(actionIndex);
 		});
-	})
+	}
 
 	handleActionPress = (actionIndex) => {
 		const { errorActionsHide } = this.props;
@@ -68,14 +77,7 @@ export default class MessageErrorActions extends React.Component {
 
 	render() {
 		return (
-			<ActionSheet
-				ref={o => this.actionSheet = o}
-				title={I18n.t('Message_actions')}
-				options={this.options}
-				cancelButtonIndex={this.CANCEL_INDEX}
-				destructiveButtonIndex={this.DELETE_INDEX}
-				onPress={this.handleActionPress}
-			/>
+			null
 		);
 	}
 }
diff --git a/app/views/PinnedMessagesView/index.js b/app/views/PinnedMessagesView/index.js
index 80ede9b34..2a3dc112d 100644
--- a/app/views/PinnedMessagesView/index.js
+++ b/app/views/PinnedMessagesView/index.js
@@ -2,7 +2,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { FlatList, View, Text } from 'react-native';
 import { connect } from 'react-redux';
-import ActionSheet from 'react-native-actionsheet';
+import ActionSheet from 'react-native-action-sheet';
 import SafeAreaView from 'react-native-safe-area-view';
 import equal from 'deep-equal';
 
@@ -71,9 +71,17 @@ export default class PinnedMessagesView extends LoggedView {
 
 	onLongPress = (message) => {
 		this.setState({ message });
-		if (this.actionSheet && this.actionSheet.show) {
-			this.actionSheet.show();
-		}
+		this.showActionSheet();
+	}
+
+	showActionSheet = () => {
+		ActionSheet.showActionSheetWithOptions({
+			options,
+			cancelButtonIndex: CANCEL_INDEX,
+			title: I18n.t('Actions')
+		}, (actionIndex) => {
+			this.handleActionPress(actionIndex);
+		});
 	}
 
 	handleActionPress = (actionIndex) => {
@@ -169,13 +177,6 @@ export default class PinnedMessagesView extends LoggedView {
 					onEndReached={this.load}
 					ListFooterComponent={loading ? <RCActivityIndicator /> : null}
 				/>
-				<ActionSheet
-					ref={o => this.actionSheet = o}
-					title={I18n.t('Actions')}
-					options={options}
-					cancelButtonIndex={CANCEL_INDEX}
-					onPress={this.handleActionPress}
-				/>
 			</SafeAreaView>
 		);
 	}
diff --git a/app/views/RoomMembersView/index.js b/app/views/RoomMembersView/index.js
index 8286480f9..cdca9e2bc 100644
--- a/app/views/RoomMembersView/index.js
+++ b/app/views/RoomMembersView/index.js
@@ -1,7 +1,9 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import { FlatList, View, Vibration } from 'react-native';
-import ActionSheet from 'react-native-actionsheet';
+import {
+	FlatList, View, Vibration
+} from 'react-native';
+import ActionSheet from 'react-native-action-sheet';
 import { connect } from 'react-redux';
 import { Navigation } from 'react-native-navigation';
 import SafeAreaView from 'react-native-safe-area-view';
@@ -161,26 +163,30 @@ export default class RoomMembersView extends LoggedView {
 		if (!this.permissions['mute-user']) {
 			return;
 		}
-		try {
-			const { room } = this.state;
-			const { muted } = room;
+		const { room } = this.state;
+		const { muted } = room;
 
-			const options = [I18n.t('Cancel')];
-			const userIsMuted = !!muted.find(m => m.value === user.username);
-			user.muted = userIsMuted;
-			if (userIsMuted) {
-				options.push(I18n.t('Unmute'));
-			} else {
-				options.push(I18n.t('Mute'));
-			}
-			this.setState({ userLongPressed: user, options });
-			Vibration.vibrate(50);
-			if (this.actionSheet && this.actionSheet.show) {
-				this.actionSheet.show();
-			}
-		} catch (error) {
-			console.log('onLongPressUser -> catch -> error', error);
+		this.actionSheetOptions = [I18n.t('Cancel')];
+		const userIsMuted = !!muted.find(m => m.value === user.username);
+		user.muted = userIsMuted;
+		if (userIsMuted) {
+			this.actionSheetOptions.push(I18n.t('Unmute'));
+		} else {
+			this.actionSheetOptions.push(I18n.t('Mute'));
 		}
+		this.setState({ userLongPressed: user });
+		Vibration.vibrate(50);
+		this.showActionSheet();
+	}
+
+	showActionSheet = () => {
+		ActionSheet.showActionSheetWithOptions({
+			options: this.actionSheetOptions,
+			cancelButtonIndex: this.CANCEL_INDEX,
+			title: I18n.t('Actions')
+		}, (actionIndex) => {
+			this.handleActionPress(actionIndex);
+		});
 	}
 
 	fetchMembers = async(status) => {
@@ -253,7 +259,7 @@ export default class RoomMembersView extends LoggedView {
 
 	render() {
 		const {
-			filtering, members, membersFiltered, options
+			filtering, members, membersFiltered
 		} = this.state;
 		return (
 			<SafeAreaView style={styles.list} testID='room-members-view' forceInset={{ bottom: 'never' }}>
@@ -266,13 +272,6 @@ export default class RoomMembersView extends LoggedView {
 					ListHeaderComponent={this.renderSearchBar}
 					{...scrollPersistTaps}
 				/>
-				<ActionSheet
-					ref={o => this.actionSheet = o}
-					title={I18n.t('Actions')}
-					options={options}
-					cancelButtonIndex={this.CANCEL_INDEX}
-					onPress={this.handleActionPress}
-				/>
 			</SafeAreaView>
 		);
 	}
diff --git a/app/views/StarredMessagesView/index.js b/app/views/StarredMessagesView/index.js
index 45be568de..fe2ba86c2 100644
--- a/app/views/StarredMessagesView/index.js
+++ b/app/views/StarredMessagesView/index.js
@@ -2,7 +2,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { FlatList, View, Text } from 'react-native';
 import { connect } from 'react-redux';
-import ActionSheet from 'react-native-actionsheet';
+import ActionSheet from 'react-native-action-sheet';
 import SafeAreaView from 'react-native-safe-area-view';
 import equal from 'deep-equal';
 
@@ -71,9 +71,17 @@ export default class StarredMessagesView extends LoggedView {
 
 	onLongPress = (message) => {
 		this.setState({ message });
-		if (this.actionSheet && this.actionSheet.show) {
-			this.actionSheet.show();
-		}
+		this.showActionSheet();
+	}
+
+	showActionSheet = () => {
+		ActionSheet.showActionSheetWithOptions({
+			options,
+			cancelButtonIndex: CANCEL_INDEX,
+			title: I18n.t('Actions')
+		}, (actionIndex) => {
+			this.handleActionPress(actionIndex);
+		});
 	}
 
 	handleActionPress = (actionIndex) => {
@@ -175,13 +183,6 @@ export default class StarredMessagesView extends LoggedView {
 					onEndReached={this.load}
 					ListFooterComponent={loading ? <RCActivityIndicator /> : null}
 				/>
-				<ActionSheet
-					ref={o => this.actionSheet = o}
-					title={I18n.t('Actions')}
-					options={options}
-					cancelButtonIndex={CANCEL_INDEX}
-					onPress={this.handleActionPress}
-				/>
 			</SafeAreaView>
 		);
 	}
diff --git a/package-lock.json b/package-lock.json
index ee0ff10c8..0824cfb72 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6710,7 +6710,6 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
       "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
-      "optional": true,
       "requires": {
         "tweetnacl": "^0.14.3"
       }
@@ -9403,7 +9402,6 @@
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
       "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
-      "optional": true,
       "requires": {
         "jsbn": "~0.1.0"
       }
@@ -15346,8 +15344,7 @@
     "jsbn": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
-      "optional": true
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
     },
     "jsc-android": {
       "version": "236355.1.1",
@@ -20543,12 +20540,11 @@
     "safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
     "sane": {
       "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.0.tgz",
+      "resolved": "http://registry.npmjs.org/sane/-/sane-2.5.0.tgz",
       "integrity": "sha512-glfKd7YH4UCrh/7dD+UESsr8ylKWRE7UQPoXuz28FgmcF0ViJQhCTCCZHICRKxf8G8O1KdLEn20dcICK54c7ew==",
       "requires": {
         "anymatch": "^2.0.0",
@@ -21846,9 +21842,9 @@
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
     },
     "sshpk": {
-      "version": "1.13.1",
-      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
-      "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
+      "version": "1.15.2",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
+      "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==",
       "requires": {
         "asn1": "~0.2.3",
         "assert-plus": "^1.0.0",
@@ -21857,6 +21853,7 @@
         "ecc-jsbn": "~0.1.1",
         "getpass": "^0.1.1",
         "jsbn": "~0.1.0",
+        "safer-buffer": "^2.0.2",
         "tweetnacl": "~0.14.0"
       }
     },
@@ -22904,8 +22901,7 @@
     "tweetnacl": {
       "version": "0.14.5",
       "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
-      "optional": true
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
     },
     "type-check": {
       "version": "0.3.2",
diff --git a/package.json b/package.json
index b15361db8..bbc7a0ad9 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
     "react": "16.6.3",
     "react-emojione": "^5.0.1",
     "react-native": "^0.57.8",
-    "react-native-actionsheet": "^2.4.2",
+    "react-native-action-sheet": "^2.1.0",
     "react-native-audio": "^4.3.0",
     "react-native-device-info": "^0.25.1",
     "react-native-dialog": "^5.5.0",
-- 
GitLab