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/components | |
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/components')
-rw-r--r-- | src/components/onboarding/SocialMediaLinker.tsx | 114 |
1 files changed, 108 insertions, 6 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) { |