From 8a815d040d85bef3aec91d0ee62ce8676206c74c Mon Sep 17 00:00:00 2001 From: Saket Kumar Date: Thu, 28 Dec 2017 23:10:10 +0530 Subject: [PATCH] Open link in customTabs on Android. (#168) * Open link in customTabs on Android. --- android/app/build.gradle | 1 + .../com/rocketchatrn/CustomTabsAndroid.java | 37 +++++++++++++++++++ .../rocketchatrn/RocketChatNativePackage.java | 33 +++++++++++++++++ app/containers/message/Audio.js | 2 + app/containers/message/Reply.js | 6 ++- app/containers/message/Url.js | 5 ++- app/containers/message/Video.js | 5 ++- app/nativeModules/CustomTabsAndroid.js | 9 +++++ app/utils/openLink.android.js | 5 +++ app/utils/openLink.ios.js | 5 +++ package-lock.json | 6 +-- 11 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java create mode 100644 android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java create mode 100644 app/nativeModules/CustomTabsAndroid.js create mode 100644 app/utils/openLink.android.js create mode 100644 app/utils/openLink.ios.js diff --git a/android/app/build.gradle b/android/app/build.gradle index 2842e0d2f..ea1b21a3f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,6 +155,7 @@ dependencies { compile project(':realm') compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.android.support:appcompat-v7:23.0.1" + compile 'com.android.support:customtabs:23.0.1' compile "com.facebook.react:react-native:+" // From node_modules } diff --git a/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java b/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java new file mode 100644 index 000000000..d365fbaab --- /dev/null +++ b/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java @@ -0,0 +1,37 @@ +package com.rocketchatrn; + +import android.net.Uri; +import android.support.customtabs.CustomTabsIntent; + + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; + + +/** + * Launches custom tabs. + */ + +public class CustomTabsAndroid extends ReactContextBaseJavaModule { + + public ReactApplicationContext context; + + + public CustomTabsAndroid(ReactApplicationContext reactContext) { + super(reactContext); + this.context = reactContext; + } + + @Override + public String getName() { + return "CustomTabsAndroid"; + } + + @ReactMethod + public void openURL(String url) throws NullPointerException { + CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); + CustomTabsIntent customTabsIntent = builder.build(); + customTabsIntent.launchUrl(getReactApplicationContext().getCurrentActivity(), Uri.parse(url)); + } +} diff --git a/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java b/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java new file mode 100644 index 000000000..bbc20f72c --- /dev/null +++ b/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java @@ -0,0 +1,33 @@ +package com.rocketchatrn; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class RocketChatNativePackage implements ReactPackage { + + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + List managers = new ArrayList<>(); + return managers; + } + + @Override + public List createNativeModules( + ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + modules.add(new CustomTabsAndroid(reactContext)); + return modules; + } + +} diff --git a/app/containers/message/Audio.js b/app/containers/message/Audio.js index fca05d995..27228806a 100644 --- a/app/containers/message/Audio.js +++ b/app/containers/message/Audio.js @@ -5,6 +5,8 @@ import Video from 'react-native-video'; import Icon from 'react-native-vector-icons/MaterialIcons'; import Slider from 'react-native-slider'; import Markdown from './Markdown'; +import openLink from '../../utils/openLink'; + const styles = StyleSheet.create({ audioContainer: { diff --git a/app/containers/message/Reply.js b/app/containers/message/Reply.js index 621c409e9..e5b2a1d58 100644 --- a/app/containers/message/Reply.js +++ b/app/containers/message/Reply.js @@ -1,11 +1,13 @@ import React from 'react'; -import { View, Text, TouchableOpacity, StyleSheet, Linking } from 'react-native'; +import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; import PropTypes from 'prop-types'; import moment from 'moment'; import Markdown from './Markdown'; import QuoteMark from './QuoteMark'; import Avatar from '../Avatar'; +import openLink from '../../utils/openLink'; + const styles = StyleSheet.create({ button: { @@ -60,7 +62,7 @@ const onPress = (attachment) => { if (!url) { return; } - Linking.openURL(attachment.title_link || attachment.author_link); + openLink(attachment.title_link || attachment.author_link); }; // Support diff --git a/app/containers/message/Url.js b/app/containers/message/Url.js index bd930a53d..6fe6cdddb 100644 --- a/app/containers/message/Url.js +++ b/app/containers/message/Url.js @@ -1,8 +1,9 @@ import React from 'react'; -import { View, Text, TouchableOpacity, Linking, StyleSheet, Image } from 'react-native'; +import { View, Text, TouchableOpacity, StyleSheet, Image } from 'react-native'; import PropTypes from 'prop-types'; import QuoteMark from './QuoteMark'; +import openLink from '../../utils/openLink'; const styles = StyleSheet.create({ button: { @@ -42,7 +43,7 @@ const styles = StyleSheet.create({ }); const onPress = (url) => { - Linking.openURL(url); + openLink(url); }; const Url = ({ url }) => { if (!url) { diff --git a/app/containers/message/Video.js b/app/containers/message/Video.js index 29a763799..e3c3114df 100644 --- a/app/containers/message/Video.js +++ b/app/containers/message/Video.js @@ -1,9 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { View, StyleSheet, TouchableOpacity, Image, Linking, Platform } from 'react-native'; +import { View, StyleSheet, TouchableOpacity, Image, Platform } from 'react-native'; import Modal from 'react-native-modal'; import VideoPlayer from 'react-native-video-controls'; import Markdown from './Markdown'; +import openLink from '../../utils/openLink'; const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(Platform.OS === 'ios' ? [] : ['video/webm', 'video/3gp', 'video/mkv'])]; const isTypeSupported = type => SUPPORTED_TYPES.indexOf(type) !== -1; @@ -53,7 +54,7 @@ export default class Video extends React.PureComponent { if (isTypeSupported(this.props.file.video_type)) { return this.toggleModal(); } - Linking.openURL(this.state.uri); + openLink(this.state.uri); } render() { diff --git a/app/nativeModules/CustomTabsAndroid.js b/app/nativeModules/CustomTabsAndroid.js new file mode 100644 index 000000000..54cd78c2c --- /dev/null +++ b/app/nativeModules/CustomTabsAndroid.js @@ -0,0 +1,9 @@ +/** + * This exposes the native CustomTabsAndroid module as a JS module. This has a + * function 'openURL' which takes the following parameters: + * + * 1. String url: A url to be opened in customTabs + */ +import { NativeModules } from 'react-native'; + +module.exports = NativeModules.CustomTabsAndroid; diff --git a/app/utils/openLink.android.js b/app/utils/openLink.android.js new file mode 100644 index 000000000..67f111d19 --- /dev/null +++ b/app/utils/openLink.android.js @@ -0,0 +1,5 @@ +import CustomTabsAndroid from '../nativeModules/CustomTabsAndroid'; + +const openLink = (url: string) => CustomTabsAndroid.openURL(url); + +export default openLink; diff --git a/app/utils/openLink.ios.js b/app/utils/openLink.ios.js new file mode 100644 index 000000000..dbae77718 --- /dev/null +++ b/app/utils/openLink.ios.js @@ -0,0 +1,5 @@ +import { Linking } from 'react-native'; + +const openLink = (url: string) => Linking.openURL(url); + +export default openLink; diff --git a/package-lock.json b/package-lock.json index ca3beb71c..1d8358aa8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -230,9 +230,9 @@ } }, "@storybook/addons": { - "version": "3.2.19", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-3.2.19.tgz", - "integrity": "sha512-HIJA+xlAZboKECTKaqLvrZZrvb0SVUKvGasxAd43mlS1+Un6sXXTs+f/5dI+fwUaBsCLalaTOJ1vQy3NoC5xoQ==" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-3.3.1.tgz", + "integrity": "sha512-fdKampdNVFUY+WPqI+Ci0bjurm3fpEwOomyHNJqU41CGlaxFon5dm7R2+LZUbUH8X/UAc9f1ECJUFETV7ZoVpA==" }, "@storybook/mantra-core": { "version": "1.7.2",