mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-12 13:05:41 +03:00
Merge pull request #1815 from ecency/feature/reorganize-search-screen
Feature/reorganize search screen
This commit is contained in:
commit
e5822fd831
@ -27,7 +27,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath('com.android.tools.build:gradle:3.5.2')
|
||||
classpath('com.android.tools.build:gradle:4.0.1')
|
||||
|
||||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
classpath 'com.bugsnag:bugsnag-android-gradle-plugin:4.+'
|
||||
|
1
src/assets/animations/empty_screen.json
Normal file
1
src/assets/animations/empty_screen.json
Normal file
File diff suppressed because one or more lines are too long
@ -11,6 +11,7 @@ import UserListItem from './view/userListItem/userListItem';
|
||||
import WalletLineItem from './view/walletLineItem/walletLineItemView';
|
||||
import CommunityListItem from './view/communityListItem/communityListItem';
|
||||
import Separator from './view/separator/separatorView';
|
||||
import EmptyScreen from './view/emptyScreen/emptyScreenView';
|
||||
|
||||
// Placeholders
|
||||
import ListItemPlaceHolder from './view/placeHolder/listItemPlaceHolderView';
|
||||
@ -48,4 +49,5 @@ export {
|
||||
WalletUnclaimedPlaceHolder,
|
||||
CommunitiesPlaceHolder,
|
||||
Separator,
|
||||
EmptyScreen,
|
||||
};
|
||||
|
@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
import LottieView from 'lottie-react-native';
|
||||
import globalStyles from '../../../../globalStyles';
|
||||
|
||||
const EmptyScreenView = ({ style, textStyle }) => (
|
||||
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
||||
<LottieView
|
||||
style={[{ width: 150, height: 150, marginBottom: 12 }, style]}
|
||||
source={require('../../../../assets/animations/empty_screen.json')}
|
||||
autoPlay
|
||||
loop={true}
|
||||
/>
|
||||
<Text style={[globalStyles.title, textStyle]}>Nothing found!</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default EmptyScreenView;
|
3
src/components/communitiesList/index.js
Normal file
3
src/components/communitiesList/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import CommunitiesList from './view/communitiesList';
|
||||
|
||||
export default CommunitiesList;
|
@ -2,23 +2,22 @@ import React from 'react';
|
||||
import { SafeAreaView, FlatList } from 'react-native';
|
||||
|
||||
// Components
|
||||
import CommunitiesListItem from './CommunitiesListItem';
|
||||
import { CommunitiesPlaceHolder } from '../../../components/basicUIElements';
|
||||
import { CommunitiesPlaceHolder } from '../../basicUIElements';
|
||||
import CommunitiesListItem from './communitiesListItem';
|
||||
|
||||
// Styles
|
||||
import styles from './communitiesListStyles';
|
||||
|
||||
const CommunitiesList = ({
|
||||
votes,
|
||||
data,
|
||||
subscribingCommunities,
|
||||
handleOnPress,
|
||||
handleSubscribeButtonPress,
|
||||
allSubscriptions,
|
||||
isLoggedIn,
|
||||
noResult,
|
||||
screen,
|
||||
}) => {
|
||||
const _renderItem = ({ item, index }) => {
|
||||
const isSubscribed = allSubscriptions.some((sub) => sub[0] === item.name);
|
||||
|
||||
return (
|
||||
<CommunitiesListItem
|
||||
index={index}
|
||||
@ -33,8 +32,13 @@ const CommunitiesList = ({
|
||||
name={item.name}
|
||||
handleOnPress={handleOnPress}
|
||||
handleSubscribeButtonPress={handleSubscribeButtonPress}
|
||||
isSubscribed={isSubscribed}
|
||||
isSubscribed={item.isSubscribed}
|
||||
isLoggedIn={isLoggedIn}
|
||||
loading={
|
||||
subscribingCommunities.hasOwnProperty(item.name) &&
|
||||
subscribingCommunities[item.name].loading
|
||||
}
|
||||
screen={screen}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -57,8 +61,8 @@ const CommunitiesList = ({
|
||||
<SafeAreaView style={styles.container}>
|
||||
{!noResult && (
|
||||
<FlatList
|
||||
data={votes}
|
||||
keyExtractor={(item) => item.id && item.id.toString()}
|
||||
data={data}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={_renderItem}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
/>
|
@ -0,0 +1,3 @@
|
||||
import CommunitiesListItem from './view/CommunitiesListItem';
|
||||
|
||||
export default CommunitiesListItem;
|
@ -1,12 +1,12 @@
|
||||
import React, { useState } from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
import { View, Text, TouchableOpacity, ActivityIndicator } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import styles from './communitiesListItemStyles';
|
||||
|
||||
import { Tag } from '../../../components/basicUIElements';
|
||||
import { Tag } from '../../../../basicUIElements';
|
||||
|
||||
const UserListItem = ({
|
||||
const CommunitiesListItem = ({
|
||||
index,
|
||||
handleOnPress,
|
||||
handleOnLongPress,
|
||||
@ -22,14 +22,13 @@ const UserListItem = ({
|
||||
handleSubscribeButtonPress,
|
||||
isSubscribed,
|
||||
isLoggedIn,
|
||||
loading,
|
||||
screen,
|
||||
}) => {
|
||||
const [subscribed, setSubscribed] = useState(isSubscribed);
|
||||
const intl = useIntl();
|
||||
|
||||
const _handleSubscribeButtonPress = () => {
|
||||
handleSubscribeButtonPress({ subscribed: !subscribed, communityId: name }).then(() => {
|
||||
setSubscribed(!subscribed);
|
||||
});
|
||||
handleSubscribeButtonPress({ isSubscribed: isSubscribed, communityId: name }, screen);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -41,24 +40,29 @@ const UserListItem = ({
|
||||
<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}
|
||||
/>
|
||||
)}
|
||||
{isLoggedIn &&
|
||||
(loading ? (
|
||||
<View style={styles.indicatorView}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
<Tag
|
||||
style={styles.subscribeButton}
|
||||
textStyle={isSubscribed && styles.subscribeButtonText}
|
||||
value={
|
||||
!isSubscribed
|
||||
? intl.formatMessage({
|
||||
id: 'search_result.communities.subscribe',
|
||||
})
|
||||
: intl.formatMessage({
|
||||
id: 'search_result.communities.unsubscribe',
|
||||
})
|
||||
}
|
||||
isPin={!isSubscribed}
|
||||
isFilter
|
||||
onPress={_handleSubscribeButtonPress}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
{!!about && <Text style={styles.about}>{about}</Text>}
|
||||
<View style={styles.separator} />
|
||||
@ -77,4 +81,4 @@ const UserListItem = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default UserListItem;
|
||||
export default CommunitiesListItem;
|
@ -59,4 +59,9 @@ export default EStyleSheet.create({
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
indicatorView: {
|
||||
width: 65,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
@ -64,6 +64,8 @@ import ScaleSlider from './scaleSlider/scaleSliderView';
|
||||
import { ProductItemLine } from './productItemLine/productItemLineView';
|
||||
import { HorizontalIconList } from './horizontalIconList/horizontalIconListView';
|
||||
import { PopoverWrapper } from './popoverWrapper/popoverWrapperView';
|
||||
import CommunitiesList from './communitiesList';
|
||||
import SubscribedCommunitiesList from './subscribedCommunitiesList';
|
||||
|
||||
// View
|
||||
import { Comment } from './comment';
|
||||
@ -104,6 +106,7 @@ import {
|
||||
WalletLineItem,
|
||||
WalletUnclaimedPlaceHolder,
|
||||
Separator,
|
||||
EmptyScreen,
|
||||
} from './basicUIElements';
|
||||
|
||||
export {
|
||||
@ -206,6 +209,9 @@ export {
|
||||
WalletLineItem,
|
||||
WalletUnclaimedPlaceHolder,
|
||||
Separator,
|
||||
EmptyScreen,
|
||||
HorizontalIconList,
|
||||
PopoverWrapper,
|
||||
CommunitiesList,
|
||||
SubscribedCommunitiesList,
|
||||
};
|
||||
|
@ -462,7 +462,9 @@ const PostsContainer = ({
|
||||
});
|
||||
}
|
||||
|
||||
dispatch(subscribeAction(currentAccount, pinCode, data, successToastText, failToastText));
|
||||
dispatch(
|
||||
subscribeAction(currentAccount, pinCode, data, successToastText, failToastText, 'feedScreen'),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
4
src/components/subscribedCommunitiesList/index.js
Normal file
4
src/components/subscribedCommunitiesList/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import SubscribedCommunitiesListView from './view/subscribedCommunitiesListView';
|
||||
import SubscribedCommunitiesList from './view/subscribedCommunitiesListView';
|
||||
|
||||
export default SubscribedCommunitiesList;
|
@ -0,0 +1,51 @@
|
||||
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',
|
||||
},
|
||||
tabbarItem: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
@ -0,0 +1,82 @@
|
||||
import React from 'react';
|
||||
import { View, FlatList, TouchableOpacity, Text, ActivityIndicator } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import { Tag, UserAvatar } from '../../index';
|
||||
import { ListPlaceHolder } from '../../basicUIElements';
|
||||
|
||||
import DEFAULT_IMAGE from '../../../assets/no_image.png';
|
||||
|
||||
import styles from './subscribedCommunitiesListStyles';
|
||||
|
||||
const SubscribedCommunitiesListView = ({
|
||||
data,
|
||||
subscribingCommunities,
|
||||
handleOnPress,
|
||||
handleSubscribeButtonPress,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const _renderEmptyContent = () => {
|
||||
return (
|
||||
<>
|
||||
<ListPlaceHolder />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
data={data}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
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>
|
||||
{subscribingCommunities.hasOwnProperty(item[0]) &&
|
||||
subscribingCommunities[item[0]].loading ? (
|
||||
<View style={{ width: 65, alignItems: 'center', justifyContent: 'center' }}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
<Tag
|
||||
style={styles.subscribeButton}
|
||||
textStyle={item[4] && styles.subscribeButtonText}
|
||||
value={
|
||||
!item[4]
|
||||
? intl.formatMessage({
|
||||
id: 'search_result.communities.subscribe',
|
||||
})
|
||||
: intl.formatMessage({
|
||||
id: 'search_result.communities.unsubscribe',
|
||||
})
|
||||
}
|
||||
isPin={!item[4]}
|
||||
isFilter
|
||||
onPress={() =>
|
||||
handleSubscribeButtonPress(
|
||||
{
|
||||
isSubscribed: item[4],
|
||||
communityId: item[0],
|
||||
},
|
||||
'communitiesScreenJoinedTab',
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubscribedCommunitiesListView;
|
@ -252,6 +252,7 @@
|
||||
"schedules": "Schedules",
|
||||
"gallery": "Gallery",
|
||||
"settings": "Settings",
|
||||
"communities": "Communities",
|
||||
"add_account": "Add Account",
|
||||
"logout": "Logout",
|
||||
"cancel": "Cancel",
|
||||
@ -549,7 +550,7 @@
|
||||
"title": "Topics"
|
||||
},
|
||||
"communities": {
|
||||
"title": "Communities",
|
||||
"title": "Groups",
|
||||
"subscribe": "Join",
|
||||
"unsubscribe": "Leave",
|
||||
"subscribers": "Members",
|
||||
@ -580,5 +581,9 @@
|
||||
"user": {
|
||||
"follow": "Follow",
|
||||
"unfollow": "Unfollow"
|
||||
},
|
||||
"communities": {
|
||||
"joined": "Membership",
|
||||
"discover": "Discover"
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ export default {
|
||||
COMMENTS: `Comments${SCREEN_SUFFIX}`,
|
||||
ACCOUNT_BOOST: `AccountBoost${SCREEN_SUFFIX}`,
|
||||
COMMUNITY: `Community${SCREEN_SUFFIX}`,
|
||||
COMMUNITIES: `Communities${SCREEN_SUFFIX}`,
|
||||
},
|
||||
DRAWER: {
|
||||
MAIN: `Main${DRAWER_SUFFIX}`,
|
||||
|
@ -25,6 +25,12 @@ const authMenuItems = [
|
||||
// icon: 'photo-library',
|
||||
// id: 'gallery',
|
||||
// },
|
||||
{
|
||||
name: 'Communities',
|
||||
route: ROUTES.SCREENS.COMMUNITIES,
|
||||
icon: 'people',
|
||||
id: 'communities',
|
||||
},
|
||||
{
|
||||
name: 'Settings',
|
||||
route: ROUTES.SCREENS.SETTINGS,
|
||||
|
@ -37,6 +37,7 @@ import {
|
||||
AccountBoost,
|
||||
TagResult,
|
||||
Community,
|
||||
Communities,
|
||||
} from '../screens';
|
||||
|
||||
const bottomTabNavigator = createBottomTabNavigator(
|
||||
@ -148,6 +149,7 @@ const stackNavigator = createStackNavigator(
|
||||
[ROUTES.SCREENS.SPIN_GAME]: { screen: SpinGame },
|
||||
[ROUTES.SCREENS.ACCOUNT_BOOST]: { screen: AccountBoost },
|
||||
[ROUTES.SCREENS.COMMUNITY]: { screen: Community },
|
||||
[ROUTES.SCREENS.COMMUNITIES]: { screen: Communities },
|
||||
},
|
||||
{
|
||||
headerMode: 'none',
|
||||
|
@ -314,7 +314,8 @@ export const getCommunities = async (
|
||||
resolve({});
|
||||
}
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
console.log(error);
|
||||
resolve({});
|
||||
}
|
||||
});
|
||||
|
||||
@ -1138,9 +1139,9 @@ export const lookupAccounts = async (username) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const getTrendingTags = async (tag) => {
|
||||
export const getTrendingTags = async (tag, number = 20) => {
|
||||
try {
|
||||
const tags = await client.database.call('get_trending_tags', [tag, 20]);
|
||||
const tags = await client.database.call('get_trending_tags', [tag, number]);
|
||||
return tags;
|
||||
} catch (error) {
|
||||
return [];
|
||||
|
@ -61,19 +61,26 @@ export const fetchSubscribedCommunitiesFail = (payload) => ({
|
||||
});
|
||||
|
||||
// Subscribe Community
|
||||
export const subscribeCommunity = (currentAccount, pin, data, successToastText, failToastText) => {
|
||||
export const subscribeCommunity = (
|
||||
currentAccount,
|
||||
pin,
|
||||
data,
|
||||
successToastText,
|
||||
failToastText,
|
||||
screen,
|
||||
) => {
|
||||
return (dispatch) => {
|
||||
dispatch({ type: SUBSCRIBE_COMMUNITY, payload: data });
|
||||
dispatch({ type: SUBSCRIBE_COMMUNITY, payload: { ...data, screen } });
|
||||
subscribeCommunityReq(currentAccount, pin, data)
|
||||
.then((res) => dispatch(subscribeCommunitySuccess(data, successToastText)))
|
||||
.catch((err) => dispatch(subscribeCommunityFail(err, data, failToastText)));
|
||||
.then((res) => dispatch(subscribeCommunitySuccess(data, successToastText, screen)))
|
||||
.catch((err) => dispatch(subscribeCommunityFail(err, data, failToastText, screen)));
|
||||
};
|
||||
};
|
||||
|
||||
export const subscribeCommunitySuccess = (data, successToastText) => {
|
||||
export const subscribeCommunitySuccess = (data, successToastText, screen) => {
|
||||
return (dispatch) => [
|
||||
dispatch({
|
||||
payload: data,
|
||||
payload: { ...data, screen },
|
||||
type: SUBSCRIBE_COMMUNITY_SUCCESS,
|
||||
}),
|
||||
dispatch({
|
||||
@ -83,10 +90,10 @@ export const subscribeCommunitySuccess = (data, successToastText) => {
|
||||
];
|
||||
};
|
||||
|
||||
export const subscribeCommunityFail = (error, data, failToastText) => {
|
||||
export const subscribeCommunityFail = (error, data, failToastText, screen) => {
|
||||
return (dispatch) => [
|
||||
dispatch({
|
||||
payload: data,
|
||||
payload: { ...data, screen },
|
||||
type: SUBSCRIBE_COMMUNITY_FAIL,
|
||||
}),
|
||||
dispatch({
|
||||
@ -97,19 +104,26 @@ export const subscribeCommunityFail = (error, data, failToastText) => {
|
||||
};
|
||||
|
||||
// Leave Community
|
||||
export const leaveCommunity = (currentAccount, pin, data, successToastText, failToastText) => {
|
||||
export const leaveCommunity = (
|
||||
currentAccount,
|
||||
pin,
|
||||
data,
|
||||
successToastText,
|
||||
failToastText,
|
||||
screen,
|
||||
) => {
|
||||
return (dispatch) => {
|
||||
dispatch({ type: LEAVE_COMMUNITY, payload: data });
|
||||
dispatch({ type: LEAVE_COMMUNITY, payload: { ...data, screen } });
|
||||
subscribeCommunityReq(currentAccount, pin, data)
|
||||
.then((res) => dispatch(leaveCommunitySuccess(data, successToastText)))
|
||||
.catch((err) => dispatch(leaveCommunityFail(err, data, failToastText)));
|
||||
.then((res) => dispatch(leaveCommunitySuccess(data, successToastText, screen)))
|
||||
.catch((err) => dispatch(leaveCommunityFail(err, data, failToastText, screen)));
|
||||
};
|
||||
};
|
||||
|
||||
export const leaveCommunitySuccess = (data, successToastText) => {
|
||||
export const leaveCommunitySuccess = (data, successToastText, screen) => {
|
||||
return (dispatch) => [
|
||||
dispatch({
|
||||
payload: data,
|
||||
payload: { ...data, screen },
|
||||
type: LEAVE_COMMUNITY_SUCCESS,
|
||||
}),
|
||||
dispatch({
|
||||
@ -119,10 +133,10 @@ export const leaveCommunitySuccess = (data, successToastText) => {
|
||||
];
|
||||
};
|
||||
|
||||
export const leaveCommunityFail = (error, data, failToastText) => {
|
||||
export const leaveCommunityFail = (error, data, failToastText, screen) => {
|
||||
return (dispatch) => [
|
||||
dispatch({
|
||||
payload: data,
|
||||
payload: { ...data, screen },
|
||||
type: LEAVE_COMMUNITY_FAIL,
|
||||
}),
|
||||
dispatch({
|
||||
|
@ -31,6 +31,27 @@ const initialState = {
|
||||
// error: false,
|
||||
//}
|
||||
},
|
||||
subscribingCommunitiesInCommunitiesScreenDiscoverTab: {
|
||||
//['name']: {
|
||||
// isSubscribed: false,
|
||||
// loading: false,
|
||||
// error: false,
|
||||
//}
|
||||
},
|
||||
subscribingCommunitiesInCommunitiesScreenJoinedTab: {
|
||||
//['name']: {
|
||||
// isSubscribed: false,
|
||||
// loading: false,
|
||||
// error: false,
|
||||
//}
|
||||
},
|
||||
subscribingCommunitiesInSearchResultsScreen: {
|
||||
//['name']: {
|
||||
// isSubscribed: false,
|
||||
// loading: false,
|
||||
// error: false,
|
||||
//}
|
||||
},
|
||||
};
|
||||
|
||||
export default function (state = initialState, action) {
|
||||
@ -90,77 +111,323 @@ export default function (state = initialState, action) {
|
||||
},
|
||||
};
|
||||
case SUBSCRIBE_COMMUNITY:
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
switch (action.payload.screen) {
|
||||
case 'communitiesScreenDiscoverTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenDiscoverTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'communitiesScreenJoinedTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenJoinedTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenJoinedTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'feedScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'searchResultsScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInSearchResultsScreen: {
|
||||
...state.subscribingCommunitiesInSearchResultsScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
case SUBSCRIBE_COMMUNITY_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
switch (action.payload.screen) {
|
||||
case 'communitiesScreenDiscoverTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenDiscoverTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'communitiesScreenJoinedTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenJoinedTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenJoinedTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'feedScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'searchResultsScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInSearchResultsScreen: {
|
||||
...state.subscribingCommunitiesInSearchResultsScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
case SUBSCRIBE_COMMUNITY_FAIL:
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
switch (action.payload.screen) {
|
||||
case 'communitiesScreenDiscoverTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenDiscoverTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'communitiesScreenJoinedTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenJoinedTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenJoinedTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'feedScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'searchResultsScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInSearchResultsScreen: {
|
||||
...state.subscribingCommunitiesInSearchResultsScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
case LEAVE_COMMUNITY:
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
switch (action.payload.screen) {
|
||||
case 'communitiesScreenDiscoverTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenDiscoverTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'communitiesScreenJoinedTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenJoinedTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenJoinedTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'feedScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'searchResultsScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInSearchResultsScreen: {
|
||||
...state.subscribingCommunitiesInSearchResultsScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
case LEAVE_COMMUNITY_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
switch (action.payload.screen) {
|
||||
case 'communitiesScreenDiscoverTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenDiscoverTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'communitiesScreenJoinedTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenJoinedTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenJoinedTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'feedScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'searchResultsScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInSearchResultsScreen: {
|
||||
...state.subscribingCommunitiesInSearchResultsScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
case LEAVE_COMMUNITY_FAIL:
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
switch (action.payload.screen) {
|
||||
case 'communitiesScreenDiscoverTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenDiscoverTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'communitiesScreenJoinedTab':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInCommunitiesScreenJoinedTab: {
|
||||
...state.subscribingCommunitiesInCommunitiesScreenJoinedTab,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'feedScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
...state.subscribingCommunitiesInFeedScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
case 'searchResultsScreen':
|
||||
return {
|
||||
...state,
|
||||
subscribingCommunitiesInSearchResultsScreen: {
|
||||
...state.subscribingCommunitiesInSearchResultsScreen,
|
||||
[action.payload.communityId]: {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
153
src/screens/communities/container/communitiesContainer.js
Normal file
153
src/screens/communities/container/communitiesContainer.js
Normal file
@ -0,0 +1,153 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { shuffle } from 'lodash';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
import { getCommunities, getSubscriptions } from '../../../providers/hive/dhive';
|
||||
|
||||
import { toastNotification } from '../../../redux/actions/uiAction';
|
||||
import { subscribeCommunity, leaveCommunity } from '../../../redux/actions/communitiesAction';
|
||||
|
||||
const CommunitiesContainer = ({ children, navigation }) => {
|
||||
const dispatch = useDispatch();
|
||||
const intl = useIntl();
|
||||
|
||||
const [discovers, setDiscovers] = useState([]);
|
||||
const [subscriptions, setSubscriptions] = useState([]);
|
||||
|
||||
const currentAccount = useSelector((state) => state.account.currentAccount);
|
||||
const pinCode = useSelector((state) => state.application.pin);
|
||||
const subscribingCommunitiesInDiscoverTab = useSelector(
|
||||
(state) => state.communities.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
);
|
||||
const subscribingCommunitiesInJoinedTab = useSelector(
|
||||
(state) => state.communities.subscribingCommunitiesInCommunitiesScreenJoinedTab,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getSubscriptions(currentAccount.username).then((subs) => {
|
||||
subs.forEach((item) => item.push(true));
|
||||
getCommunities('', 50, '', 'rank').then((communities) => {
|
||||
communities.forEach((community) =>
|
||||
Object.assign(community, {
|
||||
isSubscribed: subs.some(
|
||||
(subscribedCommunity) => subscribedCommunity[0] === community.name,
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
setSubscriptions(subs);
|
||||
setDiscovers(shuffle(communities));
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const discoversData = [...discovers];
|
||||
|
||||
Object.keys(subscribingCommunitiesInDiscoverTab).map((communityId) => {
|
||||
if (!subscribingCommunitiesInDiscoverTab[communityId].loading) {
|
||||
if (!subscribingCommunitiesInDiscoverTab[communityId].error) {
|
||||
if (subscribingCommunitiesInDiscoverTab[communityId].isSubscribed) {
|
||||
discoversData.forEach((item) => {
|
||||
if (item.name === communityId) {
|
||||
item.isSubscribed = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
discoversData.forEach((item) => {
|
||||
if (item.name === communityId) {
|
||||
item.isSubscribed = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setDiscovers(discoversData);
|
||||
}, [subscribingCommunitiesInDiscoverTab]);
|
||||
|
||||
useEffect(() => {
|
||||
const subscribedsData = [...subscriptions];
|
||||
|
||||
Object.keys(subscribingCommunitiesInJoinedTab).map((communityId) => {
|
||||
if (!subscribingCommunitiesInJoinedTab[communityId].loading) {
|
||||
if (!subscribingCommunitiesInJoinedTab[communityId].error) {
|
||||
if (subscribingCommunitiesInJoinedTab[communityId].isSubscribed) {
|
||||
subscribedsData.forEach((item) => {
|
||||
if (item[0] === communityId) {
|
||||
item[4] = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
subscribedsData.forEach((item) => {
|
||||
if (item[0] === communityId) {
|
||||
item[4] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setSubscriptions(subscribedsData);
|
||||
}, [subscribingCommunitiesInJoinedTab]);
|
||||
|
||||
// Component Functions
|
||||
const _handleOnPress = (name) => {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.COMMUNITY,
|
||||
params: {
|
||||
tag: name,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const _handleSubscribeButtonPress = (data, screen) => {
|
||||
let subscribeAction;
|
||||
let successToastText = '';
|
||||
let failToastText = '';
|
||||
|
||||
if (!data.isSubscribed) {
|
||||
subscribeAction = subscribeCommunity;
|
||||
|
||||
successToastText = intl.formatMessage({
|
||||
id: 'alert.success_subscribe',
|
||||
});
|
||||
failToastText = intl.formatMessage({
|
||||
id: 'alert.fail_subscribe',
|
||||
});
|
||||
} else {
|
||||
subscribeAction = leaveCommunity;
|
||||
|
||||
successToastText = intl.formatMessage({
|
||||
id: 'alert.success_leave',
|
||||
});
|
||||
failToastText = intl.formatMessage({
|
||||
id: 'alert.fail_leave',
|
||||
});
|
||||
}
|
||||
|
||||
dispatch(
|
||||
subscribeAction(currentAccount, pinCode, data, successToastText, failToastText, screen),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
subscriptions,
|
||||
discovers,
|
||||
subscribingCommunitiesInDiscoverTab,
|
||||
subscribingCommunitiesInJoinedTab,
|
||||
handleOnPress: _handleOnPress,
|
||||
handleSubscribeButtonPress: _handleSubscribeButtonPress,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export default withNavigation(CommunitiesContainer);
|
3
src/screens/communities/index.js
Normal file
3
src/screens/communities/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import Communities from './view/communitiesScreen';
|
||||
|
||||
export default Communities;
|
106
src/screens/communities/view/communitiesScreen.js
Normal file
106
src/screens/communities/view/communitiesScreen.js
Normal file
@ -0,0 +1,106 @@
|
||||
import React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { FlatList, View, Text, TouchableOpacity } from 'react-native';
|
||||
import get from 'lodash/get';
|
||||
import { SafeAreaView } from 'react-navigation';
|
||||
import ScrollableTabView from 'react-native-scrollable-tab-view';
|
||||
|
||||
// Components
|
||||
import {
|
||||
FilterBar,
|
||||
UserAvatar,
|
||||
TabBar,
|
||||
BasicHeader,
|
||||
CommunitiesList,
|
||||
SubscribedCommunitiesList,
|
||||
} from '../../../components';
|
||||
import { CommunitiesPlaceHolder } from '../../../components/basicUIElements';
|
||||
|
||||
import CommunitiesContainer from '../container/communitiesContainer';
|
||||
import DEFAULT_IMAGE from '../../../assets/no_image.png';
|
||||
import Tag from '../../../components/basicUIElements/view/tag/tagView';
|
||||
|
||||
import styles from './communitiesScreenStyles';
|
||||
import globalStyles from '../../../globalStyles';
|
||||
|
||||
const CommunitiesScreen = ({ navigation, searchValue }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const _renderEmptyContent = () => {
|
||||
return (
|
||||
<>
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const _renderTabbar = () => (
|
||||
<TabBar
|
||||
style={styles.tabbar}
|
||||
tabUnderlineDefaultWidth={80}
|
||||
tabUnderlineScaleX={2}
|
||||
tabBarPosition="overlayTop"
|
||||
textStyle={styles.tabBarText}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<CommunitiesContainer>
|
||||
{({
|
||||
subscriptions,
|
||||
discovers,
|
||||
handleOnPress,
|
||||
handleSubscribeButtonPress,
|
||||
subscribingCommunitiesInDiscoverTab,
|
||||
subscribingCommunitiesInJoinedTab,
|
||||
}) => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<SafeAreaView forceInset={{ bottom: 'never' }} style={{ flex: 1 }}>
|
||||
<BasicHeader
|
||||
title={intl.formatMessage({
|
||||
id: 'side_menu.communities',
|
||||
})}
|
||||
/>
|
||||
<ScrollableTabView
|
||||
style={globalStyles.tabView}
|
||||
renderTabBar={_renderTabbar}
|
||||
prerenderingSiblingsNumber={Infinity}
|
||||
>
|
||||
<View
|
||||
tabLabel={intl.formatMessage({ id: 'communities.joined' })}
|
||||
style={styles.tabbarItem}
|
||||
>
|
||||
<SubscribedCommunitiesList
|
||||
data={subscriptions}
|
||||
subscribingCommunities={subscribingCommunitiesInJoinedTab}
|
||||
handleSubscribeButtonPress={handleSubscribeButtonPress}
|
||||
handleOnPress={handleOnPress}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
tabLabel={intl.formatMessage({ id: 'communities.discover' })}
|
||||
style={styles.tabbarItem}
|
||||
>
|
||||
<CommunitiesList
|
||||
data={discovers}
|
||||
subscribingCommunities={subscribingCommunitiesInDiscoverTab}
|
||||
handleOnPress={handleOnPress}
|
||||
handleSubscribeButtonPress={handleSubscribeButtonPress}
|
||||
isLoggedIn={true}
|
||||
noResult={discovers.length === 0}
|
||||
screen="communitiesScreenDiscoverTab"
|
||||
/>
|
||||
</View>
|
||||
</ScrollableTabView>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
);
|
||||
}}
|
||||
</CommunitiesContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default CommunitiesScreen;
|
51
src/screens/communities/view/communitiesScreenStyles.js
Normal file
51
src/screens/communities/view/communitiesScreenStyles.js
Normal file
@ -0,0 +1,51 @@
|
||||
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',
|
||||
},
|
||||
tabbarItem: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
@ -13,7 +13,7 @@ import styles from './communityStyles';
|
||||
|
||||
import { GLOBAL_POST_FILTERS, GLOBAL_POST_FILTERS_VALUE } from '../../../constants/options/filters';
|
||||
|
||||
const TagResultScreen = ({ navigation }) => {
|
||||
const CommunityScreen = ({ navigation }) => {
|
||||
const tag = navigation.getParam('tag', '');
|
||||
const filter = navigation.getParam('filter', '');
|
||||
|
||||
@ -114,4 +114,4 @@ const TagResultScreen = ({ navigation }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default TagResultScreen;
|
||||
export default CommunityScreen;
|
||||
|
@ -24,6 +24,7 @@ import AccountBoost from './accountBoost/screen/accountBoostScreen';
|
||||
import Register from './register/registerScreen';
|
||||
import TagResult from './tagResult';
|
||||
import { Community } from './community';
|
||||
import Communities from './communities';
|
||||
|
||||
export {
|
||||
Bookmarks,
|
||||
@ -52,4 +53,5 @@ export {
|
||||
Wallet,
|
||||
TagResult,
|
||||
Community,
|
||||
Communities,
|
||||
};
|
||||
|
@ -1,111 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
import {
|
||||
subscribeCommunity,
|
||||
getCommunities,
|
||||
getSubscriptions,
|
||||
} from '../../../providers/hive/dhive';
|
||||
|
||||
const CommunitiesContainer = ({
|
||||
children,
|
||||
navigation,
|
||||
searchValue,
|
||||
currentAccount,
|
||||
pinCode,
|
||||
isLoggedIn,
|
||||
}) => {
|
||||
const [data, setData] = useState();
|
||||
const [filterIndex, setFilterIndex] = useState(1);
|
||||
const [query, setQuery] = useState('');
|
||||
const [sort, setSort] = useState('rank');
|
||||
const [allSubscriptions, setAllSubscriptions] = useState([]);
|
||||
const [noResult, setNoResult] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let isCancelled = false;
|
||||
setData([]);
|
||||
if (sort === 'my') {
|
||||
setNoResult(true);
|
||||
} else {
|
||||
getCommunities('', 100, query, sort).then((res) => {
|
||||
if (!isCancelled) {
|
||||
if (!isEmpty(res)) {
|
||||
setData(res);
|
||||
setNoResult(false);
|
||||
} else {
|
||||
setNoResult(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
isCancelled = true;
|
||||
};
|
||||
}, [query, sort]);
|
||||
|
||||
useEffect(() => {
|
||||
setData([]);
|
||||
setQuery(searchValue);
|
||||
setNoResult(false);
|
||||
}, [searchValue]);
|
||||
|
||||
useEffect(() => {
|
||||
let isCancelled = false;
|
||||
if (data && !isCancelled) {
|
||||
getSubscriptions(currentAccount.username).then((result) => {
|
||||
if (result) {
|
||||
setAllSubscriptions(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
isCancelled = true;
|
||||
};
|
||||
}, [data]);
|
||||
|
||||
// Component Functions
|
||||
const _handleOnVotersDropdownSelect = (index, value) => {
|
||||
setFilterIndex(index);
|
||||
setSort(value);
|
||||
};
|
||||
|
||||
const _handleOnPress = (name) => {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.COMMUNITY,
|
||||
params: {
|
||||
tag: name,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const _handleSubscribeButtonPress = (_data) => {
|
||||
return subscribeCommunity(currentAccount, pinCode, _data);
|
||||
};
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
data,
|
||||
filterIndex,
|
||||
allSubscriptions,
|
||||
handleOnVotersDropdownSelect: _handleOnVotersDropdownSelect,
|
||||
handleOnPress: _handleOnPress,
|
||||
handleSubscribeButtonPress: _handleSubscribeButtonPress,
|
||||
isLoggedIn,
|
||||
noResult,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
currentAccount: state.account.currentAccount,
|
||||
pinCode: state.application.pin,
|
||||
isLoggedIn: state.application.isLoggedIn,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withNavigation(CommunitiesContainer));
|
@ -1,84 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
import { lookupAccounts, getTrendingTags } from '../../../providers/hive/dhive';
|
||||
import { getLeaderboard } from '../../../providers/ecency/ecency';
|
||||
|
||||
const OtherResultContainer = (props) => {
|
||||
const [users, setUsers] = useState([]);
|
||||
const [tags, setTags] = useState([]);
|
||||
const [filterIndex, setFilterIndex] = useState(0);
|
||||
|
||||
const { children, navigation, searchValue, username } = props;
|
||||
|
||||
useEffect(() => {
|
||||
setUsers([]);
|
||||
setTags([]);
|
||||
|
||||
if (searchValue) {
|
||||
lookupAccounts(searchValue.replace(/\s+/g, '')).then((res) => {
|
||||
setUsers(res);
|
||||
});
|
||||
getTrendingTags(searchValue.replace(/\s+/g, '')).then((res) => {
|
||||
setTags(res);
|
||||
});
|
||||
} else {
|
||||
getLeaderboard().then((result) => {
|
||||
const sos = result.map((item) => item._id);
|
||||
setUsers(sos);
|
||||
});
|
||||
}
|
||||
}, [searchValue]);
|
||||
|
||||
// Component Functions
|
||||
|
||||
const _handleOnPress = (item) => {
|
||||
switch (filterIndex) {
|
||||
case 0:
|
||||
navigation.navigate({
|
||||
routeName: item === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE,
|
||||
params: {
|
||||
username: item,
|
||||
},
|
||||
key: item.text,
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.TAG_RESULT,
|
||||
params: {
|
||||
tag: get(item, 'name', ''),
|
||||
},
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const _handleFilterChanged = (index, value) => {
|
||||
setFilterIndex(index);
|
||||
};
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
users,
|
||||
tags,
|
||||
filterIndex,
|
||||
handleOnPress: _handleOnPress,
|
||||
handleFilterChanged: _handleFilterChanged,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
username: state.account.currentAccount.name,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withNavigation(OtherResultContainer));
|
@ -1,91 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
import { search, getPromotePosts } from '../../../providers/ecency/ecency';
|
||||
import { getPost } from '../../../providers/hive/dhive';
|
||||
|
||||
const PostResultContainer = ({ children, navigation, searchValue, currentAccountUsername }) => {
|
||||
const [data, setData] = useState([]);
|
||||
const [filterIndex, setFilterIndex] = useState(0);
|
||||
const [sort, setSort] = useState('relevance');
|
||||
const [scrollId, setScrollId] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
setData([]);
|
||||
|
||||
if (searchValue) {
|
||||
search({ q: searchValue, sort }).then((res) => {
|
||||
setScrollId(res.scroll_id);
|
||||
setData(res.results);
|
||||
});
|
||||
} else {
|
||||
getPromotePosts()
|
||||
.then((result) => {
|
||||
return Promise.all(
|
||||
result.map((item) =>
|
||||
getPost(
|
||||
get(item, 'author'),
|
||||
get(item, 'permlink'),
|
||||
currentAccountUsername,
|
||||
true,
|
||||
).then((post) => {
|
||||
post.author_rep = post.author_reputation;
|
||||
post.body = (post.summary && post.summary.substring(0, 130)) || '';
|
||||
return post;
|
||||
}),
|
||||
),
|
||||
);
|
||||
})
|
||||
.then((result) => {
|
||||
setData(result);
|
||||
});
|
||||
}
|
||||
}, [searchValue, sort]);
|
||||
|
||||
// Component Functions
|
||||
|
||||
const _handleOnPress = (item) => {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.POST,
|
||||
params: {
|
||||
author: get(item, 'author'),
|
||||
permlink: get(item, 'permlink'),
|
||||
},
|
||||
key: get(item, 'permlink'),
|
||||
});
|
||||
};
|
||||
|
||||
const _handleFilterChanged = (index, value) => {
|
||||
setFilterIndex(index);
|
||||
setSort(value);
|
||||
};
|
||||
|
||||
const _loadMore = (index, value) => {
|
||||
if (scrollId) {
|
||||
search({ q: searchValue, sort, scroll_id: scrollId }).then((res) => {
|
||||
setData([...data, ...res.results]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
data,
|
||||
filterIndex,
|
||||
handleOnPress: _handleOnPress,
|
||||
handleFilterChanged: _handleFilterChanged,
|
||||
loadMore: _loadMore,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
currentAccountUsername: state.account.currentAccount.username,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withNavigation(PostResultContainer));
|
@ -1,108 +0,0 @@
|
||||
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 './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;
|
@ -1,107 +0,0 @@
|
||||
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 } from '../../../components/basicUIElements';
|
||||
import OtherResultContainer from '../container/otherResultContainer';
|
||||
|
||||
import styles from './otherResultsStyles';
|
||||
|
||||
import DEFAULT_IMAGE from '../../../assets/no_image.png';
|
||||
|
||||
const filterOptions = ['user', 'tag'];
|
||||
|
||||
const OtherResult = ({ navigation, searchValue }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const _renderUserItem = (item, index) => (
|
||||
<View style={[styles.itemWrapper, index % 2 !== 0 && styles.itemWrapperGray]}>
|
||||
<UserAvatar username={item} defaultSource={DEFAULT_IMAGE} noAction />
|
||||
<Text style={styles.username}>{item}</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
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 }) => (
|
||||
<TouchableOpacity onPress={() => handleOnPress(item)}>
|
||||
{_renderUserItem(item, index)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
case 1:
|
||||
if (tags && tags.length > 0) {
|
||||
return (
|
||||
<FlatList
|
||||
data={tags}
|
||||
keyExtractor={(item) => `${item.name}-${item.comments}`}
|
||||
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;
|
@ -2,12 +2,14 @@ import React, { useState, useEffect } from 'react';
|
||||
import { View, SafeAreaView } from 'react-native';
|
||||
import ScrollableTabView from 'react-native-scrollable-tab-view';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
// Components
|
||||
import { SearchInput, TabBar } from '../../../components';
|
||||
import Communities from './communities';
|
||||
import PostResult from './postResult';
|
||||
import OtherResult from './otherResults';
|
||||
import { SearchInput, TabBar, IconButton } from '../../../components';
|
||||
import Communities from './tabs/communities/view/communitiesResults';
|
||||
import PostsResults from './tabs/best/view/postsResults';
|
||||
import TopicsResults from './tabs/topics/view/topicsResults';
|
||||
import PeopleResults from './tabs/people/view/peopleResults';
|
||||
|
||||
// Styles
|
||||
import styles from './searchResultStyles';
|
||||
@ -15,17 +17,8 @@ import globalStyles from '../../../globalStyles';
|
||||
|
||||
const SearchResultScreen = ({ navigation }) => {
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const [text, setText] = useState('');
|
||||
const intl = useIntl();
|
||||
|
||||
useEffect(() => {
|
||||
const delayDebounceFn = setTimeout(() => {
|
||||
setSearchValue(text);
|
||||
}, 100);
|
||||
|
||||
return () => clearTimeout(delayDebounceFn);
|
||||
}, [text]);
|
||||
|
||||
const _navigationGoBack = () => {
|
||||
navigation.goBack();
|
||||
};
|
||||
@ -36,38 +29,64 @@ const SearchResultScreen = ({ navigation }) => {
|
||||
tabUnderlineDefaultWidth={80}
|
||||
tabUnderlineScaleX={2}
|
||||
tabBarPosition="overlayTop"
|
||||
textStyle={styles.tabBarText}
|
||||
/>
|
||||
);
|
||||
|
||||
const _handleChangeText = debounce((value) => {
|
||||
setSearchValue(value);
|
||||
}, 250);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<SafeAreaView>
|
||||
<SearchInput
|
||||
handleOnModalClose={_navigationGoBack}
|
||||
placeholder={intl.formatMessage({ id: 'header.search' })}
|
||||
onChangeText={setText}
|
||||
/>
|
||||
<View style={styles.headerContainer}>
|
||||
<View style={{ flex: 11 }}>
|
||||
<SearchInput
|
||||
//handleOnModalClose={_navigationGoBack}
|
||||
placeholder={intl.formatMessage({ id: 'header.search' })}
|
||||
onChangeText={_handleChangeText}
|
||||
/>
|
||||
</View>
|
||||
<View style={{ flex: 1, marginTop: 20 }}>
|
||||
<IconButton
|
||||
iconType="Ionicons"
|
||||
name="ios-close-circle-outline"
|
||||
iconStyle={styles.backIcon}
|
||||
onPress={_navigationGoBack}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
<ScrollableTabView
|
||||
style={globalStyles.tabView}
|
||||
renderTabBar={_renderTabbar}
|
||||
prerenderingSiblingsNumber={Infinity}
|
||||
>
|
||||
<View
|
||||
tabLabel={intl.formatMessage({ id: 'search_result.best.title' })}
|
||||
style={styles.tabbarItem}
|
||||
>
|
||||
<PostsResults searchValue={searchValue} />
|
||||
</View>
|
||||
<View
|
||||
tabLabel={intl.formatMessage({ id: 'search_result.people.title' })}
|
||||
style={styles.tabbarItem}
|
||||
>
|
||||
<PeopleResults searchValue={searchValue} />
|
||||
</View>
|
||||
<View
|
||||
tabLabel={intl.formatMessage({ id: 'search_result.topics.title' })}
|
||||
style={styles.tabbarItem}
|
||||
>
|
||||
<TopicsResults 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>
|
||||
);
|
||||
|
@ -5,6 +5,11 @@ export default EStyleSheet.create({
|
||||
flex: 1,
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
},
|
||||
headerContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingRight: 12,
|
||||
},
|
||||
buttonContainer: {
|
||||
width: '50%',
|
||||
alignItems: 'center',
|
||||
@ -28,4 +33,12 @@ export default EStyleSheet.create({
|
||||
tabs: {
|
||||
flex: 1,
|
||||
},
|
||||
tabBarText: {
|
||||
fontSize: 14,
|
||||
},
|
||||
backIcon: {
|
||||
fontSize: 24,
|
||||
color: '$iconColor',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
|
@ -0,0 +1,106 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import ROUTES from '../../../../../../constants/routeNames';
|
||||
|
||||
import { search, getPromotePosts } from '../../../../../../providers/ecency/ecency';
|
||||
import { getPost, getAccountPosts } from '../../../../../../providers/hive/dhive';
|
||||
|
||||
const PostsResultsContainer = ({ children, navigation, searchValue, currentAccountUsername }) => {
|
||||
const [data, setData] = useState([]);
|
||||
const [sort, setSort] = useState('newest');
|
||||
const [scrollId, setScrollId] = useState('');
|
||||
const [noResult, setNoResult] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setNoResult(false);
|
||||
setData([]);
|
||||
|
||||
if (searchValue) {
|
||||
search({ q: `${searchValue} type:post`, sort })
|
||||
.then((res) => {
|
||||
setScrollId(res.scroll_id);
|
||||
setData(res.results);
|
||||
if (res.results.length === 0) {
|
||||
setNoResult(true);
|
||||
}
|
||||
})
|
||||
.catch((err) => console.log(err, 'search error'));
|
||||
} else {
|
||||
getInitialPosts();
|
||||
}
|
||||
}, [searchValue]);
|
||||
|
||||
const getInitialPosts = async () => {
|
||||
// const promoteds = await getPromotePosts();
|
||||
// return await Promise.all(
|
||||
// promoteds.map(async (item) => {
|
||||
// const post = await getPost(
|
||||
// get(item, 'author'),
|
||||
// get(item, 'permlink'),
|
||||
// currentAccountUsername,
|
||||
// true,
|
||||
// );
|
||||
// post.author_rep = post.author_reputation;
|
||||
// post.body = (post.summary && post.summary.substring(0, 130)) || '';
|
||||
// // return await call to your function
|
||||
// return post;
|
||||
// }),
|
||||
// );
|
||||
try {
|
||||
const options = {
|
||||
observer: currentAccountUsername,
|
||||
account: 'ecency',
|
||||
limit: 7,
|
||||
sort: 'blog',
|
||||
};
|
||||
const _data = await getAccountPosts(options);
|
||||
|
||||
if (_data.length === 0) {
|
||||
setNoResult(true);
|
||||
}
|
||||
setData(_data);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
// Component Functions
|
||||
|
||||
const _handleOnPress = (item) => {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.POST,
|
||||
params: {
|
||||
author: get(item, 'author'),
|
||||
permlink: get(item, 'permlink'),
|
||||
},
|
||||
key: get(item, 'permlink'),
|
||||
});
|
||||
};
|
||||
|
||||
const _loadMore = (index, value) => {
|
||||
if (scrollId) {
|
||||
search({ q: `${searchValue} type:post`, sort, scroll_id: scrollId }).then((res) => {
|
||||
setData([...data, ...res.results]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
data,
|
||||
handleOnPress: _handleOnPress,
|
||||
loadMore: _loadMore,
|
||||
noResult,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
currentAccountUsername: state.account.currentAccount.username,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withNavigation(PostsResultsContainer));
|
@ -6,28 +6,35 @@ 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 { PostHeaderDescription, FilterBar } from '../../../../../../components';
|
||||
import {
|
||||
TextWithIcon,
|
||||
CommunitiesPlaceHolder,
|
||||
EmptyScreen,
|
||||
} from '../../../../../../components/basicUIElements';
|
||||
import PostsResultsContainer from '../container/postsResultsContainer';
|
||||
|
||||
import { getTimeFromNow } from '../../../utils/time';
|
||||
import { getTimeFromNow } from '../../../../../../utils/time';
|
||||
|
||||
import styles from './postResultStyles';
|
||||
import styles from './postsResultsStyles';
|
||||
|
||||
import DEFAULT_IMAGE from '../../../assets/no_image.png';
|
||||
import DEFAULT_IMAGE from '../../../../../../assets/no_image.png';
|
||||
|
||||
const filterOptions = ['relevance', 'popularity', 'newest'];
|
||||
|
||||
const PostResult = ({ navigation, searchValue }) => {
|
||||
const PostsResults = ({ navigation, searchValue }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const _renderItem = (item, index) => {
|
||||
const reputation =
|
||||
get(item, 'author_rep', undefined) || get(item, 'author_reputation', undefined);
|
||||
|
||||
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'))}
|
||||
reputation={Math.floor(reputation)}
|
||||
size={36}
|
||||
tag={item.category}
|
||||
/>
|
||||
@ -78,38 +85,29 @@ const PostResult = ({ navigation, searchValue }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<PostResultContainer searchValue={searchValue}>
|
||||
{({ data, filterIndex, handleFilterChanged, handleOnPress, loadMore }) => (
|
||||
<PostsResultsContainer searchValue={searchValue}>
|
||||
{({ data, handleOnPress, loadMore, noResult }) => (
|
||||
<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 />}
|
||||
/>
|
||||
{noResult ? (
|
||||
<EmptyScreen />
|
||||
) : (
|
||||
<FlatList
|
||||
data={data}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={({ item, index }) => (
|
||||
<TouchableOpacity onPress={() => handleOnPress(item)}>
|
||||
{_renderItem(item, index)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
onEndReached={loadMore}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
ListFooterComponent={<CommunitiesPlaceHolder />}
|
||||
/>
|
||||
)}
|
||||
</SafeAreaView>
|
||||
)}
|
||||
</PostResultContainer>
|
||||
</PostsResultsContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default PostResult;
|
||||
export default PostsResults;
|
@ -0,0 +1,150 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { shuffle } from 'lodash';
|
||||
|
||||
import ROUTES from '../../../../../../constants/routeNames';
|
||||
|
||||
import { getCommunities, getSubscriptions } from '../../../../../../providers/hive/dhive';
|
||||
|
||||
import {
|
||||
subscribeCommunity,
|
||||
leaveCommunity,
|
||||
} from '../../../../../../redux/actions/communitiesAction';
|
||||
|
||||
// const DEFAULT_COMMUNITIES = [
|
||||
// 'hive-125125',
|
||||
// 'hive-174301',
|
||||
// 'hive-140217',
|
||||
// 'hive-179017',
|
||||
// 'hive-160545',
|
||||
// 'hive-194913',
|
||||
// 'hive-166847',
|
||||
// 'hive-176853',
|
||||
// 'hive-183196',
|
||||
// 'hive-163772',
|
||||
// 'hive-106444',
|
||||
// ];
|
||||
|
||||
const CommunitiesResultsContainer = ({ children, navigation, searchValue }) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [noResult, setNoResult] = useState(false);
|
||||
|
||||
const pinCode = useSelector((state) => state.application.pin);
|
||||
const currentAccount = useSelector((state) => state.account.currentAccount);
|
||||
const isLoggedIn = useSelector((state) => state.application.isLoggedIn);
|
||||
const subscribingCommunities = useSelector(
|
||||
(state) => state.communities.subscribingCommunitiesInSearchResultsScreen,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setData([]);
|
||||
setNoResult(false);
|
||||
|
||||
getSubscriptions(currentAccount.username).then((subs) => {
|
||||
getCommunities('', searchValue ? 100 : 20, searchValue, 'rank').then((communities) => {
|
||||
communities.forEach((community) =>
|
||||
Object.assign(community, {
|
||||
isSubscribed: subs.some(
|
||||
(subscribedCommunity) => subscribedCommunity[0] === community.name,
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
if (searchValue) {
|
||||
setData(communities);
|
||||
} else {
|
||||
setData(shuffle(communities));
|
||||
}
|
||||
|
||||
if (communities.length === 0) {
|
||||
setNoResult(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, [searchValue]);
|
||||
|
||||
useEffect(() => {
|
||||
const communitiesData = [...data];
|
||||
|
||||
Object.keys(subscribingCommunities).map((communityId) => {
|
||||
if (!subscribingCommunities[communityId].loading) {
|
||||
if (!subscribingCommunities[communityId].error) {
|
||||
if (subscribingCommunities[communityId].isSubscribed) {
|
||||
communitiesData.forEach((item) => {
|
||||
if (item.name === communityId) {
|
||||
item.isSubscribed = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
communitiesData.forEach((item) => {
|
||||
if (item.name === communityId) {
|
||||
item.isSubscribed = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setData(communitiesData);
|
||||
}, [subscribingCommunities]);
|
||||
|
||||
// Component Functions
|
||||
const _handleOnPress = (name) => {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.COMMUNITY,
|
||||
params: {
|
||||
tag: name,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const _handleSubscribeButtonPress = (_data, screen) => {
|
||||
let subscribeAction;
|
||||
let successToastText = '';
|
||||
let failToastText = '';
|
||||
|
||||
if (!_data.isSubscribed) {
|
||||
subscribeAction = subscribeCommunity;
|
||||
|
||||
successToastText = intl.formatMessage({
|
||||
id: 'alert.success_subscribe',
|
||||
});
|
||||
failToastText = intl.formatMessage({
|
||||
id: 'alert.fail_subscribe',
|
||||
});
|
||||
} else {
|
||||
subscribeAction = leaveCommunity;
|
||||
|
||||
successToastText = intl.formatMessage({
|
||||
id: 'alert.success_leave',
|
||||
});
|
||||
failToastText = intl.formatMessage({
|
||||
id: 'alert.fail_leave',
|
||||
});
|
||||
}
|
||||
|
||||
dispatch(
|
||||
subscribeAction(currentAccount, pinCode, _data, successToastText, failToastText, screen),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
data,
|
||||
subscribingCommunities,
|
||||
handleOnPress: _handleOnPress,
|
||||
handleSubscribeButtonPress: _handleSubscribeButtonPress,
|
||||
isLoggedIn,
|
||||
noResult,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export default withNavigation(CommunitiesResultsContainer);
|
@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import get from 'lodash/get';
|
||||
|
||||
// Components
|
||||
import { CommunitiesList, EmptyScreen } from '../../../../../../components';
|
||||
|
||||
import CommunitiesResultsContainer from '../container/communitiesResultsContainer';
|
||||
|
||||
const CommunitiesResultsScreen = ({ navigation, searchValue }) => {
|
||||
const activeVotes = get(navigation, 'state.params.activeVotes');
|
||||
|
||||
return (
|
||||
<CommunitiesResultsContainer data={activeVotes} searchValue={searchValue}>
|
||||
{({
|
||||
data,
|
||||
subscribingCommunities,
|
||||
handleOnPress,
|
||||
handleSubscribeButtonPress,
|
||||
isLoggedIn,
|
||||
noResult,
|
||||
}) =>
|
||||
noResult ? (
|
||||
<EmptyScreen />
|
||||
) : (
|
||||
<CommunitiesList
|
||||
data={data}
|
||||
subscribingCommunities={subscribingCommunities}
|
||||
handleOnPress={handleOnPress}
|
||||
handleSubscribeButtonPress={handleSubscribeButtonPress}
|
||||
isLoggedIn={isLoggedIn}
|
||||
noResult={noResult}
|
||||
screen="searchResultsScreen"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</CommunitiesResultsContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default CommunitiesResultsScreen;
|
@ -0,0 +1,65 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import ROUTES from '../../../../../../constants/routeNames';
|
||||
|
||||
import { lookupAccounts } from '../../../../../../providers/hive/dhive';
|
||||
import { getLeaderboard } from '../../../../../../providers/ecency/ecency';
|
||||
|
||||
const PeopleResultsContainer = (props) => {
|
||||
const [users, setUsers] = useState([]);
|
||||
const [noResult, setNoResult] = useState(false);
|
||||
|
||||
const { children, navigation, searchValue, username } = props;
|
||||
|
||||
useEffect(() => {
|
||||
setNoResult(false);
|
||||
setUsers([]);
|
||||
|
||||
if (searchValue) {
|
||||
lookupAccounts(searchValue).then((res) => {
|
||||
if (res.length === 0) {
|
||||
setNoResult(true);
|
||||
}
|
||||
setUsers(res);
|
||||
});
|
||||
} else {
|
||||
getLeaderboard().then((result) => {
|
||||
const sos = result.map((item) => item._id);
|
||||
if (sos.length === 0) {
|
||||
setNoResult(true);
|
||||
}
|
||||
setUsers(sos);
|
||||
});
|
||||
}
|
||||
}, [searchValue]);
|
||||
|
||||
// Component Functions
|
||||
|
||||
const _handleOnPress = (item) => {
|
||||
navigation.navigate({
|
||||
routeName: item === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE,
|
||||
params: {
|
||||
username: item,
|
||||
},
|
||||
key: item.text,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
users,
|
||||
handleOnPress: _handleOnPress,
|
||||
noResult,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
username: state.account.currentAccount.name,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withNavigation(PeopleResultsContainer));
|
@ -0,0 +1,52 @@
|
||||
import React from 'react';
|
||||
import { SafeAreaView, FlatList } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
// Components
|
||||
import {
|
||||
ListPlaceHolder,
|
||||
EmptyScreen,
|
||||
UserListItem,
|
||||
} from '../../../../../../components/basicUIElements';
|
||||
import PeopleResultsContainer from '../container/peopleResultsContainer';
|
||||
|
||||
import styles from './peopleResultsStyles';
|
||||
|
||||
const PeopleResults = ({ navigation, searchValue }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const _renderEmptyContent = () => {
|
||||
return (
|
||||
<>
|
||||
<ListPlaceHolder />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<PeopleResultsContainer searchValue={searchValue}>
|
||||
{({ users, handleOnPress, noResult }) => (
|
||||
<SafeAreaView style={styles.container}>
|
||||
{noResult ? (
|
||||
<EmptyScreen />
|
||||
) : (
|
||||
<FlatList
|
||||
data={users}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={({ item, index }) => (
|
||||
<UserListItem
|
||||
handleOnPress={() => handleOnPress(item)}
|
||||
index={index}
|
||||
username={item}
|
||||
/>
|
||||
)}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
/>
|
||||
)}
|
||||
</SafeAreaView>
|
||||
)}
|
||||
</PeopleResultsContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default PeopleResults;
|
@ -0,0 +1,57 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import ROUTES from '../../../../../../constants/routeNames';
|
||||
|
||||
import { getTrendingTags } from '../../../../../../providers/hive/dhive';
|
||||
import { getLeaderboard } from '../../../../../../providers/ecency/ecency';
|
||||
import { isCommunity } from '../../../../../../utils/communityValidation';
|
||||
|
||||
const OtherResultContainer = (props) => {
|
||||
const [tags, setTags] = useState([]);
|
||||
const [noResult, setNoResult] = useState(false);
|
||||
|
||||
const { children, navigation, searchValue } = props;
|
||||
|
||||
useEffect(() => {
|
||||
if (searchValue.length <= 10) {
|
||||
setNoResult(false);
|
||||
setTags([]);
|
||||
getTrendingTags(searchValue.trim(), 100).then((res) => {
|
||||
const data = res?.filter((item) => !isCommunity(item.name));
|
||||
if (data.length === 0) {
|
||||
setNoResult(true);
|
||||
}
|
||||
setTags(data);
|
||||
});
|
||||
}
|
||||
}, [searchValue]);
|
||||
|
||||
// Component Functions
|
||||
|
||||
const _handleOnPress = (item) => {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.TAG_RESULT,
|
||||
params: {
|
||||
tag: get(item, 'name', ''),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
tags,
|
||||
handleOnPress: _handleOnPress,
|
||||
noResult,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
username: state.account.currentAccount.name,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withNavigation(OtherResultContainer));
|
@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import { SafeAreaView, FlatList, View, Text, TouchableOpacity } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
// Components
|
||||
import { ListPlaceHolder, EmptyScreen } from '../../../../../../components/basicUIElements';
|
||||
import TopicsResultsContainer from '../container/topicsResultsContainer';
|
||||
|
||||
import styles from './topicsResultsStyles';
|
||||
|
||||
const filterOptions = ['user', 'tag'];
|
||||
|
||||
const TopicsResults = ({ 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 (
|
||||
<>
|
||||
<ListPlaceHolder />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<TopicsResultsContainer searchValue={searchValue}>
|
||||
{({ tags, handleOnPress, noResult }) => (
|
||||
<SafeAreaView style={styles.container}>
|
||||
{noResult ? (
|
||||
<EmptyScreen />
|
||||
) : (
|
||||
<FlatList
|
||||
data={tags}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={({ item, index }) => (
|
||||
<TouchableOpacity onPress={() => handleOnPress(item)}>
|
||||
{_renderTagItem(item, index)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
/>
|
||||
)}
|
||||
</SafeAreaView>
|
||||
)}
|
||||
</TopicsResultsContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopicsResults;
|
@ -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',
|
||||
},
|
||||
});
|
@ -1,5 +1,7 @@
|
||||
import { isNumber } from 'lodash';
|
||||
|
||||
export const isCommunity = (text) => {
|
||||
if (/^hive-\d+/.test(text) && text.length === 11) {
|
||||
if (/hive-[1-3]\d{4,6}$/.test(text) && isNumber(Number(text.split('-')[1]))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user