Merge pull request #1818 from ecency/revert-1817-revert-search

Revert "Revert search changes"
This commit is contained in:
Feruz M 2021-01-07 11:20:18 +02:00 committed by GitHub
commit 2231393a28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 674 additions and 20 deletions

View File

@ -538,7 +538,6 @@
"more_replies": "more replies"
},
"search_result": {
"others": "Others",
"best": {
"title": "Best"
},

View File

@ -1130,8 +1130,7 @@ export const lookupAccounts = async (username) => {
return users;
} catch (error) {
console.log('lookup_accounts');
return [];
//throw error;
throw error;
}
};
@ -1140,8 +1139,8 @@ export const getTrendingTags = async (tag) => {
const tags = await client.database.call('get_trending_tags', [tag, 20]);
return tags;
} catch (error) {
return [];
//throw error;
console.log('get_trending_tags');
throw error;
}
};

View File

@ -6,9 +6,9 @@ import isEmpty from 'lodash/isEmpty';
import ROUTES from '../../../constants/routeNames';
import {
subscribeCommunity,
getCommunities,
getSubscriptions,
subscribeCommunity,
} from '../../../providers/hive/dhive';
const CommunitiesContainer = ({

View File

@ -20,10 +20,10 @@ const OtherResultContainer = (props) => {
setTags([]);
if (searchValue) {
lookupAccounts(searchValue.replace(/\s+/g, '')).then((res) => {
lookupAccounts(searchValue).then((res) => {
setUsers(res);
});
getTrendingTags(searchValue.replace(/\s+/g, '')).then((res) => {
getTrendingTags(searchValue).then((res) => {
setTags(res);
});
} else {

View File

@ -5,9 +5,9 @@ import { useIntl } from 'react-intl';
// Components
import { SearchInput, TabBar } from '../../../components';
import Communities from './communities';
import PostResult from './postResult';
import OtherResult from './otherResults';
import Communities from './tabs/communities/communities';
import PostResult from './tabs/best/postResult';
import OtherResult from './tabs/topics/otherResults';
// Styles
import styles from './searchResultStyles';
@ -36,6 +36,7 @@ const SearchResultScreen = ({ navigation }) => {
tabUnderlineDefaultWidth={80}
tabUnderlineScaleX={2}
tabBarPosition="overlayTop"
textStyle={styles.tabBarText}
/>
);
@ -53,21 +54,30 @@ const SearchResultScreen = ({ navigation }) => {
renderTabBar={_renderTabbar}
prerenderingSiblingsNumber={Infinity}
>
<View
tabLabel={intl.formatMessage({ id: 'search_result.best.title' })}
style={styles.tabbarItem}
>
<PostResult searchValue={searchValue} />
</View>
<View
tabLabel={intl.formatMessage({ id: 'search_result.people.title' })}
style={styles.tabbarItem}
>
<OtherResult searchValue={searchValue} />
</View>
<View
tabLabel={intl.formatMessage({ id: 'search_result.topics.title' })}
style={styles.tabbarItem}
>
<OtherResult searchValue={searchValue} />
</View>
<View
tabLabel={intl.formatMessage({ id: 'search_result.communities.title' })}
style={styles.tabbarItem}
>
<Communities searchValue={searchValue} />
</View>
<View tabLabel={intl.formatMessage({ id: 'search.posts' })} style={styles.tabbarItem}>
<PostResult searchValue={searchValue} />
</View>
<View
tabLabel={intl.formatMessage({ id: 'search_result.others' })}
style={styles.tabbarItem}
>
<OtherResult searchValue={searchValue} />
</View>
</ScrollableTabView>
</View>
);

View File

@ -28,4 +28,7 @@ export default EStyleSheet.create({
tabs: {
flex: 1,
},
tabBarText: {
fontSize: 14,
},
});

View File

@ -0,0 +1,115 @@
import React from 'react';
import { SafeAreaView, FlatList, View, Text, TouchableOpacity } from 'react-native';
import get from 'lodash/get';
import isUndefined from 'lodash/isUndefined';
import FastImage from 'react-native-fast-image';
import { useIntl } from 'react-intl';
// Components
import { PostHeaderDescription, FilterBar } from '../../../../../components';
import { TextWithIcon, CommunitiesPlaceHolder } from '../../../../../components/basicUIElements';
import PostResultContainer from '../../../container/postResultContainer';
import { getTimeFromNow } from '../../../../../utils/time';
import styles from './postResultStyles';
import DEFAULT_IMAGE from '../../../../../assets/no_image.png';
const filterOptions = ['relevance', 'popularity', 'newest'];
const PostResult = ({ navigation, searchValue }) => {
const intl = useIntl();
const _renderItem = (item, index) => {
return (
<View style={[styles.itemWrapper, index % 2 !== 0 && styles.itemWrapperGray]}>
<PostHeaderDescription
date={getTimeFromNow(get(item, 'created_at'))}
name={get(item, 'author')}
reputation={Math.floor(get(item, 'author_rep'))}
size={36}
tag={item.category}
/>
<FastImage source={item.img_url} style={styles.thumbnail} defaultSource={DEFAULT_IMAGE} />
<View style={[styles.postDescription]}>
<Text style={styles.title}>{item.title}</Text>
{!!item.body && (
<Text style={styles.summary} numberOfLines={2}>
{item.body}
</Text>
)}
</View>
<View style={styles.stats}>
{!isUndefined(item.payout) && (
<Text style={styles.postIconText}>{`$ ${item.payout}`}</Text>
)}
<TextWithIcon
iconName="heart-outline"
textStyle={styles.postIconText}
iconStyle={styles.postIcon}
iconType="MaterialCommunityIcons"
text={get(item, 'up_votes', 0)}
/>
<TextWithIcon
iconName="comment-outline"
iconStyle={styles.postIcon}
iconType="MaterialCommunityIcons"
text={get(item, 'children', 0)}
textStyle={styles.postIconText}
/>
</View>
</View>
);
};
const _renderEmptyContent = () => {
return (
<>
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
</>
);
};
return (
<PostResultContainer searchValue={searchValue}>
{({ data, filterIndex, handleFilterChanged, handleOnPress, loadMore }) => (
<SafeAreaView style={styles.container}>
<FilterBar
dropdownIconName="arrow-drop-down"
options={filterOptions.map((item) =>
intl.formatMessage({
id: `search_result.post_result_filter.${item}`,
}),
)}
defaultText={intl.formatMessage({
id: `search_result.post_result_filter.${filterOptions[filterIndex]}`,
})}
selectedOptionIndex={filterIndex}
onDropdownSelect={(index) => handleFilterChanged(index, filterOptions[index])}
/>
<FlatList
data={data}
keyExtractor={(item) => item.id && item.id.toString()}
renderItem={({ item, index }) => (
<TouchableOpacity onPress={() => handleOnPress(item)}>
{_renderItem(item, index)}
</TouchableOpacity>
)}
onEndReached={loadMore}
ListEmptyComponent={_renderEmptyContent}
ListFooterComponent={<CommunitiesPlaceHolder />}
/>
</SafeAreaView>
)}
</PostResultContainer>
);
};
export default PostResult;

View File

@ -0,0 +1,44 @@
import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
container: {
flex: 1,
backgroundColor: '$primaryBackgroundColor',
},
title: {
fontSize: 16,
fontWeight: 'bold',
marginVertical: 5,
color: '$primaryBlack',
},
summary: {
fontSize: 13,
color: '$primaryDarkGray',
},
itemWrapper: {
paddingHorizontal: 16,
paddingTop: 16,
paddingBottom: 8,
borderRadius: 8,
backgroundColor: '$primaryBackgroundColor',
},
itemWrapperGray: {
backgroundColor: '$primaryLightBackground',
},
stats: {
flexDirection: 'row',
},
postIcon: {
alignSelf: 'flex-start',
fontSize: 20,
color: '$iconColor',
margin: 0,
width: 20,
marginLeft: 25,
},
postIconText: {
color: '$primaryDarkGray',
fontSize: 13,
alignSelf: 'center',
},
});

View File

@ -0,0 +1,80 @@
import React, { useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { useIntl } from 'react-intl';
import styles from './communitiesListItemStyles';
import { Tag } from '../../../../../components/basicUIElements';
const UserListItem = ({
index,
handleOnPress,
handleOnLongPress,
title,
about,
admins,
id,
authors,
posts,
subscribers,
isNsfw,
name,
handleSubscribeButtonPress,
isSubscribed,
isLoggedIn,
}) => {
const [subscribed, setSubscribed] = useState(isSubscribed);
const intl = useIntl();
const _handleSubscribeButtonPress = () => {
handleSubscribeButtonPress({ subscribed: !subscribed, communityId: name }).then(() => {
setSubscribed(!subscribed);
});
};
return (
<TouchableOpacity
onLongPress={() => handleOnLongPress && handleOnLongPress()}
onPress={() => handleOnPress && handleOnPress(name)}
>
<View style={[styles.itemWrapper, index % 2 !== 0 && styles.itemWrapperGray]}>
<View style={styles.content}>
<View style={styles.header}>
<Text style={styles.title}>{title}</Text>
{isLoggedIn && (
<Tag
style={styles.subscribeButton}
textStyle={subscribed && styles.subscribeButtonText}
value={
!subscribed
? intl.formatMessage({
id: 'search_result.communities.subscribe',
})
: intl.formatMessage({
id: 'search_result.communities.unsubscribe',
})
}
isPin={!subscribed}
isFilter
onPress={_handleSubscribeButtonPress}
/>
)}
</View>
{!!about && <Text style={styles.about}>{about}</Text>}
<View style={styles.separator} />
<Text style={styles.stats}>
{`${subscribers.toString()} ${intl.formatMessage({
id: 'search_result.communities.subscribers',
})} ${authors.toString()} ${intl.formatMessage({
id: 'search_result.communities.posters',
})} ${posts} ${intl.formatMessage({
id: 'search_result.communities.posts',
})}`}
</Text>
</View>
</View>
</TouchableOpacity>
);
};
export default UserListItem;

View File

@ -0,0 +1,108 @@
import React from 'react';
import { useIntl } from 'react-intl';
import { FlatList, View, Text, TouchableOpacity } from 'react-native';
import get from 'lodash/get';
// Components
import { FilterBar, UserAvatar } from '../../../../../components';
import CommunitiesList from './communitiesList';
import { CommunitiesPlaceHolder } from '../../../../../components/basicUIElements';
import CommunitiesContainer from '../../../container/communitiesContainer';
import styles from '../topics/otherResultsStyles';
import DEFAULT_IMAGE from '../../../../../assets/no_image.png';
import Tag from '../../../../../components/basicUIElements/view/tag/tagView';
const filterOptions = ['my', 'rank', 'subs', 'new'];
const CommunitiesScreen = ({ navigation, searchValue }) => {
const intl = useIntl();
const activeVotes = get(navigation, 'state.params.activeVotes');
const _renderEmptyContent = () => {
return (
<>
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
</>
);
};
return (
<CommunitiesContainer data={activeVotes} searchValue={searchValue}>
{({
data,
filterIndex,
allSubscriptions,
handleOnVotersDropdownSelect,
handleOnPress,
handleSubscribeButtonPress,
isLoggedIn,
noResult,
}) => (
<>
<FilterBar
dropdownIconName="arrow-drop-down"
options={filterOptions.map((item) =>
intl.formatMessage({
id: `search_result.communities_filter.${item}`,
}),
)}
defaultText={intl.formatMessage({
id: `search_result.communities_filter.${filterOptions[filterIndex]}`,
})}
selectedOptionIndex={filterIndex}
onDropdownSelect={(index) => handleOnVotersDropdownSelect(index, filterOptions[index])}
/>
{filterIndex !== 0 && (
<CommunitiesList
votes={data}
allSubscriptions={allSubscriptions}
handleOnPress={handleOnPress}
handleSubscribeButtonPress={handleSubscribeButtonPress}
isLoggedIn={isLoggedIn}
noResult={noResult}
/>
)}
{filterIndex === 0 && allSubscriptions && allSubscriptions.length > 0 && (
<FlatList
data={allSubscriptions}
//keyExtractor={(item, ind) => `${item}-${ind}`}
renderItem={({ item, index }) => (
<View style={[styles.communityWrapper, index % 2 !== 0 && styles.itemWrapperGray]}>
<View style={{ flex: 3, flexDirection: 'row', alignItems: 'center' }}>
<TouchableOpacity onPress={() => handleOnPress(item[0])}>
<UserAvatar username={item[0]} defaultSource={DEFAULT_IMAGE} noAction />
</TouchableOpacity>
<TouchableOpacity onPress={() => handleOnPress(item[0])}>
<Text style={styles.community}>{item[1]}</Text>
</TouchableOpacity>
</View>
<View style={{ flex: 1 }}>
<Tag
style={styles.subscribeButton}
textStyle={styles.subscribeButtonText}
value={intl.formatMessage({
id: 'search_result.communities.unsubscribe',
})}
isPin={false}
isFilter
onPress={() =>
handleSubscribeButtonPress({ isSubscribed: true, communityId: item[0] })
}
/>
</View>
</View>
)}
ListEmptyComponent={_renderEmptyContent}
/>
)}
</>
)}
</CommunitiesContainer>
);
};
export default CommunitiesScreen;

View File

@ -0,0 +1,70 @@
import React from 'react';
import { SafeAreaView, FlatList } from 'react-native';
// Components
import { CommunityListItem } from '../../../../../components/basicUIElements';
import { CommunitiesPlaceHolder } from '../../../../../components/basicUIElements';
// Styles
import styles from './communitiesListStyles';
const CommunitiesList = ({
votes,
handleOnPress,
handleSubscribeButtonPress,
allSubscriptions,
isLoggedIn,
noResult,
}) => {
const _renderItem = ({ item, index }) => {
const isSubscribed = allSubscriptions.some((sub) => sub[0] === item.name);
return (
<CommunityListItem
index={index}
title={item.title}
about={item.about}
admins={item.admins}
id={item.id}
authors={item.num_authors}
posts={item.num_pending}
subscribers={item.subscribers}
isNsfw={item.is_nsfw}
name={item.name}
handleOnPress={handleOnPress}
handleSubscribeButtonPress={handleSubscribeButtonPress}
isSubscribed={isSubscribed}
isLoggedIn={isLoggedIn}
/>
);
};
const _renderEmptyContent = () => {
return (
<>
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
</>
);
};
return (
<SafeAreaView style={styles.container}>
{!noResult && (
<FlatList
data={votes}
keyExtractor={(item) => item.id && item.id.toString()}
renderItem={_renderItem}
ListEmptyComponent={_renderEmptyContent}
/>
)}
</SafeAreaView>
);
};
export default CommunitiesList;

View File

@ -0,0 +1,62 @@
import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
container: {
padding: 8,
flexDirection: 'row',
},
content: {
flexDirection: 'column',
marginLeft: 8,
width: '100%',
},
itemWrapper: {
alignItems: 'center',
padding: 16,
borderRadius: 8,
flexDirection: 'row',
backgroundColor: '$primaryBackgroundColor',
},
itemWrapperGray: {
backgroundColor: '$primaryLightBackground',
},
title: {
color: '$primaryBlue',
fontSize: 17,
fontWeight: 'bold',
fontFamily: '$primaryFont',
},
about: {
fontSize: 14,
fontFamily: '$primaryFont',
marginTop: 5,
paddingTop: 10,
color: '$primaryBlack',
},
separator: {
width: 100,
alignSelf: 'center',
backgroundColor: '$primaryDarkGray',
height: 1,
marginVertical: 10,
},
stats: {
fontSize: 14,
fontFamily: '$primaryFont',
color: '$primaryDarkGray',
paddingBottom: 10,
},
subscribeButton: {
borderWidth: 1,
maxWidth: 75,
borderColor: '$primaryBlue',
},
subscribeButtonText: {
textAlign: 'center',
color: '$primaryBlue',
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
},
});

View File

@ -0,0 +1,16 @@
import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
container: {
flex: 1,
padding: 8,
marginBottom: 40,
flexDirection: 'row',
backgroundColor: '$primaryBackgroundColor',
},
text: {
color: '$iconColor',
fontSize: 12,
fontFamily: '$primaryFont',
},
});

View File

@ -0,0 +1,100 @@
import React from 'react';
import { SafeAreaView, FlatList, View, Text, TouchableOpacity } from 'react-native';
import { useIntl } from 'react-intl';
// Components
import { FilterBar, UserAvatar } from '../../../../../components';
import { CommunitiesPlaceHolder, UserListItem } from '../../../../../components/basicUIElements';
import OtherResultContainer from '../../../container/otherResultContainer';
import styles from './otherResultsStyles';
const filterOptions = ['user', 'tag'];
const OtherResult = ({ navigation, searchValue }) => {
const intl = useIntl();
const _renderTagItem = (item, index) => (
<View style={[styles.itemWrapper, index % 2 !== 0 && styles.itemWrapperGray]}>
<Text style={styles.username}>{`#${item.name}`}</Text>
</View>
);
const _renderEmptyContent = () => {
return (
<>
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
<CommunitiesPlaceHolder />
</>
);
};
const _renderList = (users, tags, filterIndex, handleOnPress) => {
switch (filterIndex) {
case 0:
if (users && users.length > 0) {
return (
<FlatList
data={users}
keyExtractor={(item, ind) => `${item}-${ind}`}
renderItem={({ item, index }) => (
<UserListItem
handleOnPress={() => handleOnPress(item)}
index={index}
username={item}
/>
)}
ListEmptyComponent={_renderEmptyContent}
/>
);
}
case 1:
if (tags && tags.length > 0) {
return (
<FlatList
data={tags}
keyExtractor={(item) => item.id}
renderItem={({ item, index }) => (
<TouchableOpacity onPress={() => handleOnPress(item)}>
{_renderTagItem(item, index)}
</TouchableOpacity>
)}
ListEmptyComponent={_renderEmptyContent}
/>
);
}
default:
break;
}
};
return (
<OtherResultContainer searchValue={searchValue}>
{({ users, tags, filterIndex, handleFilterChanged, handleOnPress, loadMore }) => (
<SafeAreaView style={styles.container}>
<FilterBar
dropdownIconName="arrow-drop-down"
options={filterOptions.map((item) =>
intl.formatMessage({
id: `search_result.other_result_filter.${item}`,
}),
)}
defaultText={intl.formatMessage({
id: `search_result.other_result_filter.${filterOptions[filterIndex]}`,
})}
selectedOptionIndex={filterIndex}
onDropdownSelect={(index) => handleFilterChanged(index, filterOptions[index])}
/>
{_renderList(users, tags, filterIndex, handleOnPress)}
</SafeAreaView>
)}
</OtherResultContainer>
);
};
export default OtherResult;

View File

@ -0,0 +1,48 @@
import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
container: {
flex: 1,
backgroundColor: '$primaryBackgroundColor',
},
itemWrapper: {
paddingHorizontal: 16,
paddingTop: 16,
paddingBottom: 8,
borderRadius: 8,
backgroundColor: '$primaryBackgroundColor',
flexDirection: 'row',
alignItems: 'center',
},
itemWrapperGray: {
backgroundColor: '$primaryLightBackground',
},
username: {
marginLeft: 10,
color: '$primaryBlack',
},
communityWrapper: {
paddingHorizontal: 16,
paddingTop: 10,
paddingBottom: 10,
borderRadius: 8,
backgroundColor: '$primaryBackgroundColor',
flexDirection: 'row',
alignItems: 'center',
flex: 1,
},
subscribeButton: {
maxWidth: 75,
borderWidth: 1,
borderColor: '$primaryBlue',
},
subscribeButtonText: {
textAlign: 'center',
color: '$primaryBlue',
},
community: {
justifyContent: 'center',
marginLeft: 15,
color: '$primaryBlack',
},
});