aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Chen <ivan@thetaggid.com>2020-10-19 14:09:01 -0400
committerGitHub <noreply@github.com>2020-10-19 14:09:01 -0400
commitf5853b77ef9506df056029282c475e5628fb6ab0 (patch)
treefd6c50c0ef7b8c133897b6a5f8cac64ac5e6aa2b
parentab7fa09af967e0a8cf2ca53dfb24f8bc8a6886f7 (diff)
[TMA-272] Add browser login flow to Instagram social linking (#56)
* added in-app browser package and added social link for instagram * added comments and improved code clarity * added more skeleton code * Finished FB linking * updated facebook oauth to request for permission * finished twitter sign on * minor fixes
-rw-r--r--ios/Frontend/Info.plist13
-rw-r--r--package.json1
-rw-r--r--src/components/onboarding/SocialMediaLinker.tsx114
-rw-r--r--src/constants/api.ts11
-rw-r--r--src/screens/profile/SocialMediaTaggs.tsx4
5 files changed, 135 insertions, 8 deletions
diff --git a/ios/Frontend/Info.plist b/ios/Frontend/Info.plist
index e7ff5911..421f9fd0 100644
--- a/ios/Frontend/Info.plist
+++ b/ios/Frontend/Info.plist
@@ -20,6 +20,19 @@
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
+ <key>CFBundleURLTypes</key>
+ <array>
+ <dict>
+ <!-- <key>CFBundleTypeRole</key>
+ <string>Editor</string> -->
+ <key>CFBundleURLName</key>
+ <string>taggid</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>taggid</string>
+ </array>
+ </dict>
+ </array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
diff --git a/package.json b/package.json
index e12e1988..c95b8f3f 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
"react-native-elements": "^2.3.2",
"react-native-gesture-handler": "^1.6.1",
"react-native-image-crop-picker": "^0.32.2",
+ "react-native-inappbrowser-reborn": "^3.4.0",
"react-native-linear-gradient": "^2.5.6",
"react-native-picker-select": "^7.0.0",
"react-native-reanimated": "^1.9.0",
diff --git a/src/components/onboarding/SocialMediaLinker.tsx b/src/components/onboarding/SocialMediaLinker.tsx
index fc823979..e7f78834 100644
--- a/src/components/onboarding/SocialMediaLinker.tsx
+++ b/src/components/onboarding/SocialMediaLinker.tsx
@@ -1,12 +1,23 @@
+import AsyncStorage from '@react-native-community/async-storage';
import React from 'react';
import {
+ Alert,
+ Image,
StyleSheet,
- TouchableOpacityProps,
Text,
TouchableOpacity,
- Image,
+ TouchableOpacityProps,
} from 'react-native';
+import InAppBrowser from 'react-native-inappbrowser-reborn';
import {LinkerType} from 'src/types';
+import {
+ LINK_FB_ENDPOINT,
+ LINK_FB_OAUTH,
+ LINK_IG_ENDPOINT,
+ LINK_IG_OAUTH,
+ LINK_TWITTER_ENDPOINT,
+ LINK_TWITTER_OAUTH,
+} from '../../constants';
import {SOCIAL_FONT_COLORS} from '../../constants/constants';
import SocialIcon from '../common/SocialIcon';
@@ -17,15 +28,106 @@ interface SocialMediaLinkerProps extends TouchableOpacityProps {
const SocialMediaLinker: React.FC<SocialMediaLinkerProps> = ({
social: {label},
}) => {
+
const [state, setState] = React.useState({
authenticated: false,
});
- const handlePress = () => {
- setState({
- ...state,
- authenticated: !state.authenticated,
+ const integrated_endpoints: {[label: string]: [string, string]} = {
+ Instagram: [LINK_IG_OAUTH, LINK_IG_ENDPOINT],
+ Facebook: [LINK_FB_OAUTH, LINK_FB_ENDPOINT],
+ Twitter: [LINK_TWITTER_OAUTH, LINK_TWITTER_ENDPOINT]
+ };
+
+ const registerSocialLink: (token: string) => Promise<boolean> = async (
+ callback_url,
+ ) => {
+ if (!(label in integrated_endpoints)) {
+ // This error is already handled earlier, more of a safety check here
+ return false;
+ }
+ const user_token = await AsyncStorage.getItem('token');
+ const response = await fetch(integrated_endpoints[label][1], {
+ method: 'POST',
+ headers: {
+ Authorization: `Token ${user_token}`,
+ },
+ body: JSON.stringify({
+ callback_url: callback_url,
+ }),
});
+ if (!(response.status === 201)) {
+ console.log(await response.json());
+ }
+ return response.status === 201;
+ };
+
+ const handlePress = async () => {
+ try {
+ const isAvailable = await InAppBrowser.isAvailable();
+ if (!(label in integrated_endpoints)) {
+ // TODO handle non-integrated social links with a modal
+ // TODO remove the alert below
+ Alert.alert('Coming soon!');
+ return;
+ }
+ let url = integrated_endpoints[label][0]
+
+ // We will need to do an extra step for twitter sign-in
+ if (label === 'Twitter') {
+ const user_token = await AsyncStorage.getItem('token');
+ const response = await fetch(url, {
+ method: 'GET',
+ headers: {
+ Authorization: `Token ${user_token}`
+ }
+ });
+ url = response.url
+ }
+
+ if (isAvailable) {
+ InAppBrowser.openAuth(url, 'taggid://callback', {
+ ephemeralWebSession: true,
+ })
+ .then(async (response) => {
+ console.log(response)
+ if (response.type === 'success' && response.url) {
+ const success = await registerSocialLink(response.url);
+ if (!success) {
+ throw new Error('Unable to register with backend');
+ }
+ setState({
+ ...state,
+ authenticated: true,
+ });
+ Alert.alert(`Successfully linked ${label} 🎉`);
+ } else {
+ throw new Error(`Unable to link with ${label} API`);
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ Alert.alert(
+ `Something went wrong, we can't link with ${label} 😔`,
+ );
+ });
+ } else {
+ // Okay... to open an external browser and have it link back to
+ // the app is a bit tricky, we will need to have navigation routes
+ // setup for this screen and have it hooked up.
+ // See https://github.com/proyecto26/react-native-inappbrowser#authentication-flow-using-deep-linking
+ // Though this isn't the end of the world, from the documentation,
+ // the in-app browser should be supported from iOS 11, which
+ // is about 98.5% of all iOS devices in the world.
+ // See https://support.apple.com/en-gb/HT209574
+ Alert.alert(
+ 'Sorry! Your device was unable to open a browser to let you sign-in! 😔',
+ );
+ }
+ } catch (error) {
+ console.log(error);
+ Alert.alert(`Something went wrong, we can't link with ${label} 😔`);
+ }
};
switch (label) {
diff --git a/src/constants/api.ts b/src/constants/api.ts
index d5733592..8e935714 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -14,3 +14,14 @@ export const GET_IG_POSTS_ENDPOINT: string = API_URL + 'posts-ig/';
export const SEARCH_ENDPOINT: string = API_URL + 'search/';
export const MOMENTS_UPLOAD_ENDPOINT: string = API_URL + 'moments/';
export const VERIFY_INVITATION_CODE_ENDPOUNT: string = API_URL + 'verify-code/';
+
+// Social Link
+export const LINK_IG_ENDPOINT: string = API_URL + 'link-ig/';
+export const LINK_FB_ENDPOINT: string = API_URL + 'link-fb/';
+export const LINK_TWITTER_ENDPOINT: string = API_URL + 'link-twitter/';
+
+// Social Link OAuth
+export const DEEPLINK: string = 'https://tinyurl.com/y3o4aec5';
+export const LINK_IG_OAUTH: string = `https://www.instagram.com/oauth/authorize/?client_id=205466150510738&redirect_uri=${DEEPLINK}&scope=user_profile,user_media&response_type=code`;
+export const LINK_FB_OAUTH: string = `https://www.facebook.com/v8.0/dialog/oauth?client_id=1308555659343609&redirect_uri=${DEEPLINK}&scope=user_posts,public_profile&response_type=code`;
+export const LINK_TWITTER_OAUTH: string = API_URL + 'link-twitter-request/';
diff --git a/src/screens/profile/SocialMediaTaggs.tsx b/src/screens/profile/SocialMediaTaggs.tsx
index ddbebcea..c82a310e 100644
--- a/src/screens/profile/SocialMediaTaggs.tsx
+++ b/src/screens/profile/SocialMediaTaggs.tsx
@@ -43,10 +43,10 @@ const SocialMediaTaggs: React.FC<SocialMediaTaggsProps> = ({route}) => {
// const {socialMediaType, socialMediaHandle} = route.params;
const {instaPosts} = context;
const socialMediaType = 'Instagram';
- const socialMediaHandle = instaPosts[0].username;
+ const socialMediaHandle =
+ instaPosts ? instaPosts[0].username : '_';
const headerHeight = headerBarHeightWithImage();
- console.log(headerHeight);
return (
<LinearGradient