import AsyncStorage from '@react-native-community/async-storage'; import React from 'react'; import { Alert, Image, StyleSheet, Text, TouchableOpacity, 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'; interface SocialMediaLinkerProps extends TouchableOpacityProps { social: LinkerType; } const SocialMediaLinker: React.FC = ({ social: {label}, }) => { const [state, setState] = React.useState({ authenticated: false, }); 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 = 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) { case 'Instagram': var font_color = SOCIAL_FONT_COLORS.INSTAGRAM; break; case 'Facebook': var font_color = SOCIAL_FONT_COLORS.FACEBOOK; break; case 'Twitter': var font_color = SOCIAL_FONT_COLORS.TWITTER; break; case 'Twitch': var font_color = SOCIAL_FONT_COLORS.TWITCH; break; case 'Pinterest': var font_color = SOCIAL_FONT_COLORS.PINTEREST; break; case 'Whatsapp': var font_color = SOCIAL_FONT_COLORS.WHATSAPP; break; case 'Linkedin': var font_color = SOCIAL_FONT_COLORS.LINKEDIN; break; case 'Snapchat': var font_color = SOCIAL_FONT_COLORS.SNAPCHAT; break; case 'Youtube': var font_color = SOCIAL_FONT_COLORS.YOUTUBE; break; default: var font_color = '#fff'; } return ( {label} {state.authenticated && ( )} ); }; const styles = StyleSheet.create({ container: { width: '28%', height: '100%', backgroundColor: '#4c409a', borderRadius: 8, marginHorizontal: '2%', marginVertical: '2%', alignItems: 'center', }, icon: { top: '15%', }, label: { fontWeight: '500', top: '25%', }, tick: { top: '30%', }, }); export default SocialMediaLinker;