diff options
author | Ivan Chen <ivan@thetaggid.com> | 2020-10-19 14:09:01 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-19 14:09:01 -0400 |
commit | f5853b77ef9506df056029282c475e5628fb6ab0 (patch) | |
tree | fd6c50c0ef7b8c133897b6a5f8cac64ac5e6aa2b /src | |
parent | ab7fa09af967e0a8cf2ca53dfb24f8bc8a6886f7 (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
Diffstat (limited to 'src')
-rw-r--r-- | src/components/onboarding/SocialMediaLinker.tsx | 114 | ||||
-rw-r--r-- | src/constants/api.ts | 11 | ||||
-rw-r--r-- | src/screens/profile/SocialMediaTaggs.tsx | 4 |
3 files changed, 121 insertions, 8 deletions
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 |