diff options
author | Ivan Chen <ivan@thetaggid.com> | 2021-01-27 19:32:21 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-27 19:32:21 -0500 |
commit | 19d2a861f260c02031d951f3d43bff8ac672146d (patch) | |
tree | 253abceb267dfb75ac9118995886ff152c1ba74b | |
parent | 60d3d97ad6913369762877a9dbfdaac0473deb28 (diff) | |
parent | dc9556867dd44b706c43678d40802a335ff40658 (diff) |
Merge pull request #203 from IvanIFChen/tma577-profile-slowness
[TMA-577] Profile Slowness
-rw-r--r-- | src/components/comments/CommentTile.tsx | 7 | ||||
-rw-r--r-- | src/components/moments/MomentTile.tsx | 3 | ||||
-rw-r--r-- | src/components/notifications/Notification.tsx | 46 | ||||
-rw-r--r-- | src/components/profile/FriendsCount.tsx | 6 | ||||
-rw-r--r-- | src/components/profile/ProfilePreview.tsx | 42 | ||||
-rw-r--r-- | src/components/search/Explore.tsx | 7 | ||||
-rw-r--r-- | src/components/search/ExploreSection.tsx | 15 | ||||
-rw-r--r-- | src/components/search/ExploreSectionUser.tsx | 18 | ||||
-rw-r--r-- | src/screens/profile/IndividualMoment.tsx | 2 | ||||
-rw-r--r-- | src/screens/search/SearchScreen.tsx | 10 | ||||
-rw-r--r-- | src/services/CommonService.ts | 22 | ||||
-rw-r--r-- | src/services/ExploreService.ts (renamed from src/services/ExploreServices.ts) | 1 | ||||
-rw-r--r-- | src/services/MomentService.ts (renamed from src/services/MomentServices.ts) | 0 | ||||
-rw-r--r-- | src/services/UserFriendsService.ts (renamed from src/services/UserFriendsServices.ts) | 0 | ||||
-rw-r--r-- | src/services/index.ts | 7 | ||||
-rw-r--r-- | src/types/types.ts | 4 |
16 files changed, 87 insertions, 103 deletions
diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index c6dd9fc1..b631a985 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -123,12 +123,7 @@ const CommentTile: React.FC<CommentTileProps> = ({ <View style={[styles.container, isThread ? styles.moreMarginWithThread : {}]}> <ProfilePreview - profilePreview={{ - id: comment_object.commenter.id, - username: comment_object.commenter.username, - first_name: comment_object.commenter.first_name, - last_name: comment_object.commenter.last_name, - }} + profilePreview={comment_object.commenter} previewType={'Comment'} screenType={screenType} /> diff --git a/src/components/moments/MomentTile.tsx b/src/components/moments/MomentTile.tsx index 16e91c82..69701192 100644 --- a/src/components/moments/MomentTile.tsx +++ b/src/components/moments/MomentTile.tsx @@ -15,7 +15,6 @@ const MomentTile: React.FC<MomentTileProps> = ({ }) => { const navigation = useNavigation(); - const {path_hash} = moment; return ( <TouchableOpacity onPress={() => { @@ -26,7 +25,7 @@ const MomentTile: React.FC<MomentTileProps> = ({ }); }}> <View style={styles.image}> - <Image style={styles.image} source={{uri: path_hash}} /> + <Image style={styles.image} source={{uri: moment.thumbnail_url}} /> </View> </TouchableOpacity> ); diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index e6d16f82..e648b554 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -1,25 +1,19 @@ import {useNavigation} from '@react-navigation/native'; import React, {useEffect, useState} from 'react'; import {Image, StyleSheet, Text, View} from 'react-native'; -import {Button} from 'react-native-elements'; import {TouchableWithoutFeedback} from 'react-native-gesture-handler'; import {useDispatch, useStore} from 'react-redux'; +import {loadImageFromURL, loadMomentThumbnail} from '../../services'; import { + acceptFriendRequest, declineFriendRequest, loadUserNotifications, updateUserXFriends, } from '../../store/actions'; -import {acceptFriendRequest} from '../../store/actions'; -import {NotificationType, ProfilePreviewType, ScreenType, MomentType} from '../../types'; -import { - fetchUserX, - SCREEN_HEIGHT, - SCREEN_WIDTH, - userXInStore, -} from '../../utils'; +import {RootState} from '../../store/rootReducer'; +import {MomentType, NotificationType, ScreenType} from '../../types'; +import {fetchUserX, SCREEN_HEIGHT, userXInStore} from '../../utils'; import AcceptDeclineButtons from '../common/AcceptDeclineButtons'; -import {loadAvatar, loadMomentThumbnail} from '../../services'; - interface NotificationProps { item: NotificationType; @@ -30,7 +24,7 @@ interface NotificationProps { const Notification: React.FC<NotificationProps> = (props) => { const { item: { - actor: {id, username, first_name, last_name}, + actor: {id, username, first_name, last_name, thumbnail_url}, verbage, notification_type, notification_object, @@ -44,22 +38,18 @@ const Notification: React.FC<NotificationProps> = (props) => { const state: RootState = useStore().getState(); const dispatch = useDispatch(); - const [avatarURI, setAvatarURI] = useState<string | undefined>(undefined); + const [avatar, setAvatar] = useState<string | undefined>(undefined); const [momentURI, setMomentURI] = useState<string | undefined>(undefined); const backgroundColor = unread ? '#DCF1F1' : 'rgba(0,0,0,0)'; + useEffect(() => { - let mounted = true; - const loadAvatarImage = async (user_id: string) => { - const response = await loadAvatar(user_id, true); - if (mounted) { - setAvatarURI(response); + (async () => { + const response = await loadImageFromURL(thumbnail_url); + if (response) { + setAvatar(response); } - }; - loadAvatarImage(id); - return () => { - mounted = false; - }; - }, [id]); + })(); + }, []); useEffect(() => { let mounted = true; @@ -137,8 +127,8 @@ const Notification: React.FC<NotificationProps> = (props) => { <Image style={styles.avatar} source={ - avatarURI - ? {uri: avatarURI, cache: 'only-if-cached'} + avatar + ? {uri: avatar, cache: 'only-if-cached'} : require('../../assets/images/avatar-placeholder.png') } /> @@ -159,8 +149,8 @@ const Notification: React.FC<NotificationProps> = (props) => { </View> )} {notification_type === 'CMT' && notification_object && ( - <Image style={styles.moment} source={{uri: momentURI}} /> - )} + <Image style={styles.moment} source={{uri: momentURI}} /> + )} </TouchableWithoutFeedback> </> ); diff --git a/src/components/profile/FriendsCount.tsx b/src/components/profile/FriendsCount.tsx index 9647710e..851dbc3b 100644 --- a/src/components/profile/FriendsCount.tsx +++ b/src/components/profile/FriendsCount.tsx @@ -17,10 +17,10 @@ const FriendsCount: React.FC<FriendsCountProps> = ({ userXId, screenType, }) => { - const count = (userXId + const {friends} = userXId ? useSelector((state: RootState) => state.userX[screenType][userXId]) - : useSelector((state: RootState) => state.friends) - )?.friends.length; + : useSelector((state: RootState) => state.friends); + const count = friends ? friends.length : 0; const displayedCount: string = count < 5e3 diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index 389ca367..38defb8d 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -12,21 +12,11 @@ import { } from 'react-native'; import {useDispatch, useSelector, useStore} from 'react-redux'; import {ERROR_UNABLE_TO_VIEW_PROFILE} from '../../constants/strings'; -import {loadAvatar} from '../../services'; +import {loadImageFromURL} from '../../services'; import {RootState} from '../../store/rootreducer'; -import { - PreviewType, - ProfilePreviewType, - ScreenType, - UserType, -} from '../../types'; +import {PreviewType, ProfilePreviewType, ScreenType} from '../../types'; import {checkIfUserIsBlocked, fetchUserX, userXInStore} from '../../utils'; -const NO_USER: UserType = { - userId: '', - username: '', -}; - /** * This component returns user's profile picture friended by username as a touchable component. * What happens when someone clicks on this component is partly decided by the prop isComment. @@ -43,28 +33,23 @@ interface ProfilePreviewProps extends ViewProps { } const ProfilePreview: React.FC<ProfilePreviewProps> = ({ - profilePreview: {username, first_name, last_name, id}, + profilePreview: {username, first_name, last_name, id, thumbnail_url}, previewType, screenType, }) => { const navigation = useNavigation(); const {user: loggedInUser} = useSelector((state: RootState) => state.user); - const [avatarURI, setAvatarURI] = useState<string | null>(null); - const [user, setUser] = useState<UserType>(NO_USER); + const [avatar, setAvatar] = useState<string | null>(null); const dispatch = useDispatch(); + useEffect(() => { - let mounted = true; - const loadAvatarImage = async () => { - const response = await loadAvatar(id, true); - if (mounted) { - setAvatarURI(response); + (async () => { + const response = await loadImageFromURL(thumbnail_url); + if (response) { + setAvatar(response); } - }; - loadAvatarImage(); - return () => { - mounted = false; - }; - }, [id]); + })(); + }, []); /** * Adds a searched user to the recently searched cache if they're tapped on. @@ -80,6 +65,7 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ username, first_name, last_name, + thumbnail_url, }; try { @@ -211,8 +197,8 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ <Image style={avatarStyle} source={ - avatarURI - ? {uri: avatarURI} + avatar + ? {uri: avatar} : require('../../assets/images/avatar-placeholder.png') } /> diff --git a/src/components/search/Explore.tsx b/src/components/search/Explore.tsx index 4a71249b..2a3bc749 100644 --- a/src/components/search/Explore.tsx +++ b/src/components/search/Explore.tsx @@ -12,9 +12,10 @@ const Explore: React.FC = () => { return ( <View style={styles.container}> <Text style={styles.header}>Search Profiles</Text> - {EXPLORE_SECTION_TITLES.map((title: ExploreSectionType) => ( - <ExploreSection key={title} title={title} users={explores[title]} /> - ))} + {explores && + EXPLORE_SECTION_TITLES.map((title: ExploreSectionType) => ( + <ExploreSection key={title} title={title} users={explores[title]} /> + ))} </View> ); }; diff --git a/src/components/search/ExploreSection.tsx b/src/components/search/ExploreSection.tsx index 17079e77..025c8c3c 100644 --- a/src/components/search/ExploreSection.tsx +++ b/src/components/search/ExploreSection.tsx @@ -1,5 +1,5 @@ import React, {Fragment} from 'react'; -import {ScrollView, StyleSheet, Text, View} from 'react-native'; +import {FlatList, StyleSheet, Text, View} from 'react-native'; import {ProfilePreviewType} from '../../types'; import {normalize} from '../../utils'; import ExploreSectionUser from './ExploreSectionUser'; @@ -17,12 +17,15 @@ const ExploreSection: React.FC<ExploreSectionProps> = ({title, users}) => { return users.length !== 0 ? ( <View style={styles.container}> <Text style={styles.header}>{title}</Text> - <ScrollView horizontal showsHorizontalScrollIndicator={false}> - <View style={styles.padding} /> - {users.map((user) => ( + <FlatList + data={users} + ListHeaderComponent={<View style={styles.padding} />} + renderItem={({item: user}: {item: ProfilePreviewType}) => ( <ExploreSectionUser key={user.id} user={user} style={styles.user} /> - ))} - </ScrollView> + )} + showsHorizontalScrollIndicator={false} + horizontal + /> </View> ) : ( <Fragment /> diff --git a/src/components/search/ExploreSectionUser.tsx b/src/components/search/ExploreSectionUser.tsx index 68e077e3..b0cfe5c6 100644 --- a/src/components/search/ExploreSectionUser.tsx +++ b/src/components/search/ExploreSectionUser.tsx @@ -9,7 +9,7 @@ import { } from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; import {useDispatch, useSelector, useStore} from 'react-redux'; -import {loadAvatar} from '../../services'; +import {loadImageFromURL} from '../../services'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType} from '../../types'; import {fetchUserX, normalize, userXInStore} from '../../utils'; @@ -36,18 +36,13 @@ const ExploreSectionUser: React.FC<ExploreSectionUserProps> = ({ const dispatch = useDispatch(); useEffect(() => { - let mounted = true; - const loadAvatarImage = async () => { - const response = await loadAvatar(id, true); - if (mounted) { + (async () => { + const response = await loadImageFromURL(user.thumbnail_url); + if (response) { setAvatar(response); } - }; - loadAvatarImage(); - return () => { - mounted = false; - }; - }, [user]); + })(); + }, []); const handlePress = async () => { if (!userXInStore(state, screenType, user.id)) { @@ -63,7 +58,6 @@ const ExploreSectionUser: React.FC<ExploreSectionUserProps> = ({ screenType, }); }; - return ( <TouchableOpacity style={[styles.container, style]} onPress={handlePress}> <LinearGradient diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx index 6b82b31c..ea0c8fb6 100644 --- a/src/screens/profile/IndividualMoment.tsx +++ b/src/screens/profile/IndividualMoment.tsx @@ -70,7 +70,7 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({ style={styles.postContent} momentId={item.moment_id} caption={item.caption} - pathHash={item.path_hash} + pathHash={item.moment_url} dateTime={item.date_created} screenType={screenType} /> diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx index 059bd968..f0be7c9e 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -2,7 +2,6 @@ import AsyncStorage from '@react-native-community/async-storage'; import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useState} from 'react'; import { - Dimensions, Keyboard, RefreshControl, ScrollView, @@ -37,9 +36,7 @@ const NO_USER: UserType = { */ const SearchScreen: React.FC = () => { - const {recentSearches, explores} = useSelector( - (state: RootState) => state.taggUsers, - ); + const {recentSearches} = useSelector((state: RootState) => state.taggUsers); const [query, setQuery] = useState<string>(''); const [results, setResults] = useState<Array<ProfilePreviewType>>([]); const [recents, setRecents] = useState<Array<ProfilePreviewType>>( @@ -47,7 +44,6 @@ const SearchScreen: React.FC = () => { ); const [searching, setSearching] = useState(false); const top = Animated.useValue(-SCREEN_HEIGHT); - const [user, setUser] = useState<UserType>(NO_USER); const [refreshing, setRefreshing] = useState<boolean>(false); const dispatch = useDispatch(); @@ -70,10 +66,6 @@ const SearchScreen: React.FC = () => { const loadResults = async (q: string) => { try { const token = await AsyncStorage.getItem('token'); - if (!token) { - setUser(NO_USER); - return; - } const response = await fetch(`${SEARCH_ENDPOINT}?query=${q}`, { method: 'GET', headers: { diff --git a/src/services/CommonService.ts b/src/services/CommonService.ts new file mode 100644 index 00000000..4f9fb47a --- /dev/null +++ b/src/services/CommonService.ts @@ -0,0 +1,22 @@ +import RNFetchBlob from 'rn-fetch-blob'; + +export const loadImageFromURL = async (url: string) => { + try { + if (!url) { + return undefined; + } + const response = await RNFetchBlob.config({ + fileCache: true, + appendExt: 'jpg', + }).fetch('GET', url); + const status = response.info().status; + if (status === 200) { + return response.path(); + } else { + return undefined; + } + } catch (error) { + console.log(error); + return undefined; + } +}; diff --git a/src/services/ExploreServices.ts b/src/services/ExploreService.ts index ca4f1b69..980258be 100644 --- a/src/services/ExploreServices.ts +++ b/src/services/ExploreService.ts @@ -1,5 +1,4 @@ import AsyncStorage from '@react-native-community/async-storage'; -import {getDeviceToken} from 'react-native-device-info'; import {ALL_USERS_ENDPOINT, DISCOVER_ENDPOINT} from '../constants'; import {EMPTY_EXPLORE_SECTIONS} from '../store/initialStates'; import {ExploreSectionType, ProfilePreviewType} from '../types'; diff --git a/src/services/MomentServices.ts b/src/services/MomentService.ts index 0110a0d6..0110a0d6 100644 --- a/src/services/MomentServices.ts +++ b/src/services/MomentService.ts diff --git a/src/services/UserFriendsServices.ts b/src/services/UserFriendsService.ts index f2e15824..f2e15824 100644 --- a/src/services/UserFriendsServices.ts +++ b/src/services/UserFriendsService.ts diff --git a/src/services/index.ts b/src/services/index.ts index f558247f..9c168d4f 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,12 +1,13 @@ export * from './UserProfileService'; export * from './SocialLinkingService'; -export * from './MomentServices'; -export * from './ExploreServices'; -export * from './UserFriendsServices'; +export * from './MomentService'; +export * from './ExploreService'; +export * from './UserFriendsService'; export * from './ReportingService'; export * from './BlockUserService'; export * from './MomentCategoryService'; export * from './NotificationService'; export * from './FCMService'; export * from './WaitlistUserService'; +export * from './CommonService'; export * from './CommentService'; diff --git a/src/types/types.ts b/src/types/types.ts index 0c0f9d8b..1d800423 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -11,6 +11,7 @@ export interface ProfilePreviewType { username: string; first_name: string; last_name: string; + thumbnail_url: string; } export type FriendshipStatusType = 'friends' | 'requested' | 'no_record'; @@ -83,7 +84,8 @@ export interface MomentType { caption: string; date_created: string; moment_category: string; - path_hash: string; + moment_url: string; + thumbnail_url: string; } export interface CommentType { |