aboutsummaryrefslogtreecommitdiff
path: root/src/components/onboarding/LinkSocialMedia.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/onboarding/LinkSocialMedia.tsx')
-rw-r--r--src/components/onboarding/LinkSocialMedia.tsx204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/components/onboarding/LinkSocialMedia.tsx b/src/components/onboarding/LinkSocialMedia.tsx
new file mode 100644
index 00000000..5f95fac8
--- /dev/null
+++ b/src/components/onboarding/LinkSocialMedia.tsx
@@ -0,0 +1,204 @@
+/**
+ * This is a duplicate file, adding this now to avoid conflicts with incoming changes on the original 'SocialMediaLinker'
+ */
+
+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<SocialMediaLinkerProps> = ({
+ 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<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) {
+ 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 (
+ <TouchableOpacity
+ activeOpacity={0.7}
+ onPress={handlePress}
+ style={styles.container}>
+ <SocialIcon social={label} style={styles.icon} />
+ <Text style={[styles.label, {color: font_color}]}>{label}</Text>
+ {state.authenticated && (
+ <Image
+ source={require('../../assets/images/link-tick.png')}
+ style={styles.tick}
+ />
+ )}
+ </TouchableOpacity>
+ );
+};
+
+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;