aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/common/DateLabel.tsx58
-rw-r--r--src/components/common/index.ts1
-rw-r--r--src/components/onboarding/SocialMediaLinker.tsx17
-rw-r--r--src/components/profile/Feed.tsx30
-rw-r--r--src/components/profile/index.ts1
-rw-r--r--src/components/taggs/SocialMediaInfo.tsx8
-rw-r--r--src/components/taggs/Tagg.tsx5
-rw-r--r--src/components/taggs/TaggPost.tsx63
-rw-r--r--src/components/taggs/TaggPostFooter.tsx29
-rw-r--r--src/components/taggs/TaggsBar.tsx35
-rw-r--r--src/components/taggs/TaggsFeed.tsx29
-rw-r--r--src/components/taggs/TwitterTaggPost.tsx213
-rw-r--r--src/components/taggs/index.ts2
13 files changed, 377 insertions, 114 deletions
diff --git a/src/components/common/DateLabel.tsx b/src/components/common/DateLabel.tsx
new file mode 100644
index 00000000..145c614c
--- /dev/null
+++ b/src/components/common/DateLabel.tsx
@@ -0,0 +1,58 @@
+import React from 'react';
+import {StyleSheet, Text} from 'react-native';
+import moment from 'moment';
+
+interface DateLabelProps {
+ timestamp: string;
+ type: 'default' | 'short' | 'small';
+ decorate?: (date: string) => string;
+}
+
+const DateLabel: React.FC<DateLabelProps> = ({
+ timestamp,
+ type,
+ decorate = (date) => `${date}`,
+}) => {
+ let parsedDate = moment(timestamp);
+
+ if (!parsedDate) {
+ return <React.Fragment />;
+ }
+
+ switch (type) {
+ case 'default':
+ return (
+ <Text style={styles.default}>
+ {decorate(parsedDate.format('h:mm a • MMM D, YYYY'))}
+ </Text>
+ );
+
+ case 'short':
+ return (
+ <Text style={styles.default}>
+ {decorate(parsedDate.format('MMM D'))}
+ </Text>
+ );
+
+ case 'small':
+ return (
+ <Text style={styles.smallAndBlue}>
+ {decorate(parsedDate.format('MMM D'))}
+ </Text>
+ );
+ }
+};
+
+const styles = StyleSheet.create({
+ default: {
+ fontSize: 15,
+ color: '#c4c4c4',
+ },
+ smallAndBlue: {
+ fontSize: 14,
+ fontWeight: 'bold',
+ color: '#8FA9C2',
+ },
+});
+
+export default DateLabel;
diff --git a/src/components/common/index.ts b/src/components/common/index.ts
index cb9d641b..cd72a70b 100644
--- a/src/components/common/index.ts
+++ b/src/components/common/index.ts
@@ -8,4 +8,5 @@ export {default as SocialIcon} from './SocialIcon';
export {default as TabsGradient} from './TabsGradient';
export {default as RecentSearches} from '../search/RecentSearches';
export {default as LoadingIndicator} from './LoadingIndicator';
+export {default as DateLabel} from './DateLabel';
export * from './post';
diff --git a/src/components/onboarding/SocialMediaLinker.tsx b/src/components/onboarding/SocialMediaLinker.tsx
index e7f78834..15afb731 100644
--- a/src/components/onboarding/SocialMediaLinker.tsx
+++ b/src/components/onboarding/SocialMediaLinker.tsx
@@ -28,7 +28,6 @@ interface SocialMediaLinkerProps extends TouchableOpacityProps {
const SocialMediaLinker: React.FC<SocialMediaLinkerProps> = ({
social: {label},
}) => {
-
const [state, setState] = React.useState({
authenticated: false,
});
@@ -36,7 +35,7 @@ const SocialMediaLinker: React.FC<SocialMediaLinkerProps> = ({
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]
+ Twitter: [LINK_TWITTER_OAUTH, LINK_TWITTER_ENDPOINT],
};
const registerSocialLink: (token: string) => Promise<boolean> = async (
@@ -71,7 +70,7 @@ const SocialMediaLinker: React.FC<SocialMediaLinkerProps> = ({
Alert.alert('Coming soon!');
return;
}
- let url = integrated_endpoints[label][0]
+ let url = integrated_endpoints[label][0];
// We will need to do an extra step for twitter sign-in
if (label === 'Twitter') {
@@ -79,10 +78,10 @@ const SocialMediaLinker: React.FC<SocialMediaLinkerProps> = ({
const response = await fetch(url, {
method: 'GET',
headers: {
- Authorization: `Token ${user_token}`
- }
+ Authorization: `Token ${user_token}`,
+ },
});
- url = response.url
+ url = response.url;
}
if (isAvailable) {
@@ -90,7 +89,7 @@ const SocialMediaLinker: React.FC<SocialMediaLinkerProps> = ({
ephemeralWebSession: true,
})
.then(async (response) => {
- console.log(response)
+ console.log(response);
if (response.type === 'success' && response.url) {
const success = await registerSocialLink(response.url);
if (!success) {
@@ -107,9 +106,7 @@ const SocialMediaLinker: React.FC<SocialMediaLinkerProps> = ({
})
.catch((error) => {
console.log(error);
- Alert.alert(
- `Something went wrong, we can't link with ${label} 😔`,
- );
+ Alert.alert(`Something went wrong, we can't link with ${label} 😔`);
});
} else {
// Okay... to open an external browser and have it link back to
diff --git a/src/components/profile/Feed.tsx b/src/components/profile/Feed.tsx
deleted file mode 100644
index 3353d25b..00000000
--- a/src/components/profile/Feed.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import {PostType, UserType} from '../../types';
-import {Post} from '../common';
-import {AuthContext} from '../../routes/authentication';
-
-interface FeedProps {
- user: UserType;
-}
-const Feed: React.FC<FeedProps> = ({user}) => {
- const {instaPosts} = React.useContext(AuthContext);
- const posts: Array<PostType> = [];
- for (let i = 0; i < 10; i++) {
- const testPost: PostType = {
- owner: user,
- social: 'Instagram',
- socialHandle: 'igHandle',
- data: instaPosts[i],
- };
- posts.push(testPost);
- }
- return (
- <>
- {posts.map((post, index) => (
- <Post key={index} post={post} />
- ))}
- </>
- );
-};
-
-export default Feed;
diff --git a/src/components/profile/index.ts b/src/components/profile/index.ts
index 4eb435df..e2063e26 100644
--- a/src/components/profile/index.ts
+++ b/src/components/profile/index.ts
@@ -4,5 +4,4 @@ export {default as Moment} from './Moment';
export {default as ProfileCutout} from './ProfileCutout';
export {default as ProfileBody} from './ProfileBody';
export {default as ProfileHeader} from './ProfileHeader';
-export {default as Feed} from './Feed';
export {default as CaptionScreenHeader} from './CaptionScreenHeader';
diff --git a/src/components/taggs/SocialMediaInfo.tsx b/src/components/taggs/SocialMediaInfo.tsx
index 0e93660d..a7ed6fe6 100644
--- a/src/components/taggs/SocialMediaInfo.tsx
+++ b/src/components/taggs/SocialMediaInfo.tsx
@@ -5,7 +5,7 @@ import {SocialIcon} from '..';
interface SocialMediaInfoProps {
fullname: string;
type: string;
- handle: string;
+ handle?: string;
}
const SocialMediaInfo: React.FC<SocialMediaInfoProps> = ({
@@ -15,7 +15,11 @@ const SocialMediaInfo: React.FC<SocialMediaInfoProps> = ({
}) => {
return (
<View style={styles.container}>
- <Text style={styles.handle}> @{handle} </Text>
+ {handle && type !== 'Facebook' ? (
+ <Text style={styles.handle}> @{handle} </Text>
+ ) : (
+ <></>
+ )}
<View style={styles.row}>
<View />
<SocialIcon style={styles.icon} social={type} />
diff --git a/src/components/taggs/Tagg.tsx b/src/components/taggs/Tagg.tsx
index d6cffee5..9274e0eb 100644
--- a/src/components/taggs/Tagg.tsx
+++ b/src/components/taggs/Tagg.tsx
@@ -6,17 +6,18 @@ import {TAGGS_GRADIENT} from '../../constants';
interface TaggProps {
style: object;
+ social: string;
isProfileView: boolean;
}
-const Tagg: React.FC<TaggProps> = ({style, isProfileView}) => {
+const Tagg: React.FC<TaggProps> = ({style, social, isProfileView}) => {
const navigation = useNavigation();
return (
<TouchableOpacity
onPress={() =>
navigation.navigate('SocialMediaTaggs', {
- socialMediaType: 'Instagram',
+ socialMediaType: social,
isProfileView: isProfileView,
})
}>
diff --git a/src/components/taggs/TaggPost.tsx b/src/components/taggs/TaggPost.tsx
index 73f15268..0d3aee50 100644
--- a/src/components/taggs/TaggPost.tsx
+++ b/src/components/taggs/TaggPost.tsx
@@ -1,38 +1,59 @@
-import moment from 'moment';
import React from 'react';
-import {Image, StyleSheet, View} from 'react-native';
-import {PostType} from '../../types';
+import {Image, StyleSheet, Text, View} from 'react-native';
+import {SimplePostType} from '../../types';
import {SCREEN_WIDTH} from '../../utils';
+import {DateLabel} from '../common';
import TaggPostFooter from './TaggPostFooter';
interface TaggPostProps {
- post: PostType;
+ post: SimplePostType;
}
-const TaggPost: React.FC<TaggPostProps> = ({post: {socialHandle, data}}) => {
- const parsedDate = moment(data?.timestamp || '');
- const date = parsedDate.isValid() ? parsedDate.format('MMM d') : '';
-
- return (
- <>
- <View style={styles.image}>
- {data && <Image style={styles.image} source={{uri: data.media_url}} />}
+const TaggPost: React.FC<TaggPostProps> = ({post}) => {
+ if (post.media_type === 'photo') {
+ // Post with image and footer that shows caption
+ return (
+ <View style={styles.photoContainer}>
+ <View style={styles.image}>
+ {post && (
+ <Image style={styles.image} source={{uri: post.media_url}} />
+ )}
+ </View>
+ <TaggPostFooter
+ // we currently don't have a way to retreive num of likes information
+ likes={undefined}
+ handle={post.username}
+ caption={post.caption || ''}
+ timestamp={post.timestamp}
+ />
+ </View>
+ );
+ } else {
+ // Post with large text
+ return (
+ <View style={styles.textContianer}>
+ <Text style={styles.text}>{post.caption}</Text>
+ <DateLabel timestamp={post.timestamp} type={'default'} />
</View>
- <TaggPostFooter
- // we currently don't have a way to retreive num of likes information
- likes={109}
- handle={socialHandle}
- caption={data?.caption || ''}
- date={date}
- />
- </>
- );
+ );
+ }
};
const styles = StyleSheet.create({
+ photoContainer: {
+ marginBottom: 50,
+ },
image: {
width: SCREEN_WIDTH,
height: SCREEN_WIDTH,
backgroundColor: '#eee',
+ marginBottom: 30,
+ },
+ textContianer: {marginBottom: 50, paddingHorizontal: 10},
+ text: {
+ marginBottom: 30,
+ fontSize: 18,
+ color: 'white',
+ flexWrap: 'wrap',
},
});
diff --git a/src/components/taggs/TaggPostFooter.tsx b/src/components/taggs/TaggPostFooter.tsx
index 024670a8..8371a847 100644
--- a/src/components/taggs/TaggPostFooter.tsx
+++ b/src/components/taggs/TaggPostFooter.tsx
@@ -1,30 +1,32 @@
import React from 'react';
import {StyleSheet, View} from 'react-native';
import {Text} from 'react-native-animatable';
+import {DateLabel} from '../common';
interface TaggPostFooterProps {
- likes: number;
- handle: string;
+ likes?: number;
+ handle?: string;
caption: string;
- date: string;
+ timestamp: string;
}
const TaggPostFooter: React.FC<TaggPostFooterProps> = ({
likes,
handle,
caption,
- date,
+ timestamp,
}) => {
+ const handleText = handle ? handle : '';
return (
<View>
<View style={styles.container}>
- <Text style={styles.likeText}>{likes} likes</Text>
+ {likes ? <Text style={styles.likeText}>{likes} likes</Text> : <></>}
<View style={styles.captionContainer}>
<Text style={styles.handleText}>
- {handle}
+ {handleText}
<Text style={styles.captionText}> {caption}</Text>
</Text>
</View>
- <Text style={styles.dateText}>{date}</Text>
+ <DateLabel timestamp={timestamp} type={'small'} />
</View>
</View>
);
@@ -33,11 +35,11 @@ const TaggPostFooter: React.FC<TaggPostFooterProps> = ({
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
- padding: 10,
- paddingBottom: '10%',
+ paddingHorizontal: 10,
+ marginBottom: 50,
},
captionContainer: {
- paddingVertical: 10,
+ paddingBottom: 30,
},
likeText: {
fontSize: 14,
@@ -51,15 +53,10 @@ const styles = StyleSheet.create({
},
captionText: {
fontSize: 14,
- fontWeight: 'bold',
+ fontWeight: 'normal',
color: 'white',
flexWrap: 'wrap',
},
- dateText: {
- fontSize: 14,
- fontWeight: 'bold',
- color: '#8FA9C2',
- },
});
export default TaggPostFooter;
diff --git a/src/components/taggs/TaggsBar.tsx b/src/components/taggs/TaggsBar.tsx
index 933f355d..88f670b5 100644
--- a/src/components/taggs/TaggsBar.tsx
+++ b/src/components/taggs/TaggsBar.tsx
@@ -18,9 +18,40 @@ const TaggsBar: React.FC<TaggsBarProps> = ({
isProfileView,
}) => {
const taggs: Array<JSX.Element> = [];
- for (let i = 0; i < 10; i++) {
+
+ taggs.push(
+ <Tagg
+ key={0}
+ style={styles.tagg}
+ social={'Instagram'}
+ isProfileView={isProfileView}
+ />,
+ );
+ taggs.push(
+ <Tagg
+ key={1}
+ style={styles.tagg}
+ social={'Facebook'}
+ isProfileView={isProfileView}
+ />,
+ );
+ taggs.push(
+ <Tagg
+ key={2}
+ style={styles.tagg}
+ social={'Twitter'}
+ isProfileView={isProfileView}
+ />,
+ );
+
+ for (let i = 3; i < 10; i++) {
taggs.push(
- <Tagg key={i} style={styles.tagg} isProfileView={isProfileView} />,
+ <Tagg
+ key={i}
+ style={styles.tagg}
+ social={'Instagram'}
+ isProfileView={isProfileView}
+ />,
);
}
const shadowOpacity: Animated.Node<number> = interpolate(y, {
diff --git a/src/components/taggs/TaggsFeed.tsx b/src/components/taggs/TaggsFeed.tsx
deleted file mode 100644
index 3f27e248..00000000
--- a/src/components/taggs/TaggsFeed.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import {InstagramPostType, UserType} from '../../types';
-import {TaggPost} from './';
-
-interface TaggsFeedProps {
- user: UserType;
- socialHandle: string;
- posts: Array<InstagramPostType>;
-}
-
-const TaggsFeed: React.FC<TaggsFeedProps> = ({user, socialHandle, posts}) => {
- return (
- <>
- {posts?.map((post, index) => (
- <TaggPost
- key={index}
- post={{
- owner: user,
- social: 'Instagram',
- socialHandle: socialHandle,
- data: post,
- }}
- />
- ))}
- </>
- );
-};
-
-export default TaggsFeed;
diff --git a/src/components/taggs/TwitterTaggPost.tsx b/src/components/taggs/TwitterTaggPost.tsx
new file mode 100644
index 00000000..2cc23bcf
--- /dev/null
+++ b/src/components/taggs/TwitterTaggPost.tsx
@@ -0,0 +1,213 @@
+import React from 'react';
+import {Image, Linking, StyleSheet, View} from 'react-native';
+import {Text} from 'react-native-animatable';
+import LinearGradient from 'react-native-linear-gradient';
+import {AVATAR_DIM, TAGGS_GRADIENT} from '../../constants';
+import {TwitterPostType} from '../../types';
+import {SCREEN_WIDTH} from '../../utils';
+import {DateLabel} from '../common';
+
+interface TwitterTaggPostProps {
+ ownerHandle: string;
+ post: TwitterPostType;
+}
+const TwitterTaggPost: React.FC<TwitterTaggPostProps> = ({
+ ownerHandle,
+ post,
+}) => {
+ return (
+ <View style={styles.mainContainer}>
+ {/* Retweeted? */}
+ {post.type === 'retweet' ? (
+ <Text style={styles.retweetedText}>@{ownerHandle} retweeted</Text>
+ ) : (
+ <React.Fragment />
+ )}
+ {/* Post header (avatar and handle) */}
+ <View style={styles.header}>
+ <Image
+ style={styles.avatar}
+ source={
+ post.profile_pic
+ ? {uri: post.profile_pic}
+ : require('../../assets/images/avatar-placeholder.png')
+ }
+ />
+ <Text style={styles.headerText}>@{post.handle}</Text>
+ </View>
+ {/* Tweet/Reply/Retweet Content */}
+ <View style={styles.contentContainer}>
+ {/* First part of content is text or empty */}
+ {post.text ? (
+ <Text style={styles.contentText}>{post.text}</Text>
+ ) : (
+ <React.Fragment />
+ )}
+ {/* Second part of content is an image or empty */}
+ {post.media_url ? (
+ <View style={styles.imageContainer}>
+ <Image style={styles.image} source={{uri: post.media_url}} />
+ </View>
+ ) : (
+ <React.Fragment />
+ )}
+ {/* Third part of content is the reply/retweet container or empty */}
+ {(post.type === 'reply' || post.type === 'retweet') &&
+ post.in_reply_to ? (
+ <LinearGradient
+ colors={[TAGGS_GRADIENT.start, TAGGS_GRADIENT.end]}
+ useAngle={true}
+ angle={300}
+ angleCenter={{x: 0.5, y: 0.5}}
+ style={[styles.replyGradient]}>
+ <View style={styles.replyPostContainer}>
+ <View style={styles.replyHeader}>
+ <Image
+ style={styles.replyAvatar}
+ source={
+ post.in_reply_to.profile_pic
+ ? {uri: post.in_reply_to.profile_pic}
+ : require('../../assets/images/avatar-placeholder.png')
+ }
+ />
+ <Text style={styles.replyHandleText}>
+ @{post.in_reply_to.handle}
+ </Text>
+ <DateLabel
+ timestamp={post.in_reply_to.timestamp}
+ type={'short'}
+ decorate={(date) => ` • ${date}`}
+ />
+ </View>
+ <Text style={styles.replyText} numberOfLines={2}>
+ {post.in_reply_to.text}
+ </Text>
+ <Text
+ style={styles.replyShowThisThread}
+ onPress={() => {
+ if (post.in_reply_to?.permalink) {
+ Linking.openURL(post.in_reply_to.permalink);
+ }
+ }}>
+ Show this thread
+ </Text>
+ </View>
+ </LinearGradient>
+ ) : (
+ <React.Fragment />
+ )}
+ </View>
+ {/* Footer */}
+ <View style={styles.footer}>
+ <DateLabel timestamp={post.timestamp} type={'default'} />
+ <Text
+ style={styles.viewOnTwitterText}
+ onPress={() => {
+ if (post.permalink) {
+ Linking.openURL(post.permalink);
+ }
+ }}>
+ View on Twitter
+ </Text>
+ </View>
+ </View>
+ );
+};
+
+const styles = StyleSheet.create({
+ mainContainer: {
+ marginHorizontal: 10,
+ marginBottom: 50,
+ },
+ retweetedText: {
+ fontSize: 12,
+ color: 'grey',
+ marginBottom: 20,
+ },
+ header: {
+ alignItems: 'center',
+ flexDirection: 'row',
+ marginBottom: 30,
+ },
+ avatar: {
+ width: AVATAR_DIM,
+ height: AVATAR_DIM,
+ borderRadius: AVATAR_DIM / 2,
+ },
+ headerText: {
+ fontSize: 15,
+ fontWeight: 'bold',
+ color: 'white',
+ paddingHorizontal: 12,
+ },
+ contentContainer: {},
+ contentText: {
+ fontSize: 18,
+ color: 'white',
+ marginBottom: 30,
+ },
+ // image media
+ imageContainer: {
+ marginBottom: 30,
+ },
+ image: {
+ width: SCREEN_WIDTH - 20,
+ height: SCREEN_WIDTH - 20,
+ backgroundColor: '#eee',
+ borderRadius: 15,
+ },
+ // footer
+ footer: {
+ height: 50,
+ flexDirection: 'column',
+ justifyContent: 'space-between',
+ marginBottom: 50,
+ },
+ viewOnTwitterText: {
+ fontSize: 12,
+ color: '#6ee7e7',
+ },
+ // reply post
+ replyPostContainer: {
+ flex: 1,
+ marginVertical: 1,
+ paddingHorizontal: 10,
+ width: SCREEN_WIDTH - 22,
+ justifyContent: 'space-between',
+ paddingTop: 10,
+ paddingBottom: 20,
+ borderRadius: 15,
+ backgroundColor: '#1d0034',
+ },
+ replyGradient: {
+ height: 150,
+ borderRadius: 15,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: 30,
+ },
+ replyHeader: {
+ alignItems: 'center',
+ flexDirection: 'row',
+ },
+ replyAvatar: {
+ height: AVATAR_DIM / 2,
+ width: AVATAR_DIM / 2,
+ borderRadius: AVATAR_DIM / 2 / 2,
+ },
+ replyHandleText: {
+ fontSize: 15,
+ color: '#c4c4c4',
+ paddingLeft: 7,
+ },
+ replyText: {
+ fontSize: 15,
+ color: 'white',
+ },
+ replyShowThisThread: {
+ fontSize: 15,
+ color: '#698dd3',
+ },
+});
+
+export default TwitterTaggPost;
diff --git a/src/components/taggs/index.ts b/src/components/taggs/index.ts
index 1cb0c412..5d0a4d48 100644
--- a/src/components/taggs/index.ts
+++ b/src/components/taggs/index.ts
@@ -1,4 +1,4 @@
export {default as TaggsBar} from './TaggsBar';
export {default as SocialMediaInfo} from './SocialMediaInfo';
-export {default as TaggsFeed} from './TaggsFeed';
export {default as TaggPost} from './TaggPost';
+export {default as TwitterTaggPost} from './TwitterTaggPost';