diff --git a/src/_EXAMPLES FOR DEVELOPERS/actions/.gitkeep b/src/_EXAMPLES_FOR_DEVELOPERS/actions/.gitkeep similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/actions/.gitkeep rename to src/_EXAMPLES_FOR_DEVELOPERS/actions/.gitkeep diff --git a/src/_EXAMPLES FOR DEVELOPERS/components/statefull/container/exampleContainer.js b/src/_EXAMPLES_FOR_DEVELOPERS/components/statefull/container/exampleContainer.js similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/components/statefull/container/exampleContainer.js rename to src/_EXAMPLES_FOR_DEVELOPERS/components/statefull/container/exampleContainer.js diff --git a/src/_EXAMPLES FOR DEVELOPERS/components/statefull/index.js b/src/_EXAMPLES_FOR_DEVELOPERS/components/statefull/index.js similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/components/statefull/index.js rename to src/_EXAMPLES_FOR_DEVELOPERS/components/statefull/index.js diff --git a/src/_EXAMPLES FOR DEVELOPERS/components/statefull/view/exampleStyles.js b/src/_EXAMPLES_FOR_DEVELOPERS/components/statefull/view/exampleStyles.js similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/components/statefull/view/exampleStyles.js rename to src/_EXAMPLES_FOR_DEVELOPERS/components/statefull/view/exampleStyles.js diff --git a/src/_EXAMPLES FOR DEVELOPERS/components/statefull/view/exampleView.js b/src/_EXAMPLES_FOR_DEVELOPERS/components/statefull/view/exampleView.js similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/components/statefull/view/exampleView.js rename to src/_EXAMPLES_FOR_DEVELOPERS/components/statefull/view/exampleView.js diff --git a/src/_EXAMPLES FOR DEVELOPERS/components/stateless/exampleStyles.js b/src/_EXAMPLES_FOR_DEVELOPERS/components/stateless/exampleStyles.js similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/components/stateless/exampleStyles.js rename to src/_EXAMPLES_FOR_DEVELOPERS/components/stateless/exampleStyles.js diff --git a/src/_EXAMPLES FOR DEVELOPERS/components/stateless/exampleView.js b/src/_EXAMPLES_FOR_DEVELOPERS/components/stateless/exampleView.js similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/components/stateless/exampleView.js rename to src/_EXAMPLES_FOR_DEVELOPERS/components/stateless/exampleView.js diff --git a/src/_EXAMPLES FOR DEVELOPERS/constant/.gitkeep b/src/_EXAMPLES_FOR_DEVELOPERS/constant/.gitkeep similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/constant/.gitkeep rename to src/_EXAMPLES_FOR_DEVELOPERS/constant/.gitkeep diff --git a/src/_EXAMPLES FOR DEVELOPERS/reducer/.gitkeep b/src/_EXAMPLES_FOR_DEVELOPERS/reducer/.gitkeep similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/reducer/.gitkeep rename to src/_EXAMPLES_FOR_DEVELOPERS/reducer/.gitkeep diff --git a/src/_EXAMPLES FOR DEVELOPERS/screen/.gitkeep b/src/_EXAMPLES_FOR_DEVELOPERS/screen/.gitkeep similarity index 100% rename from src/_EXAMPLES FOR DEVELOPERS/screen/.gitkeep rename to src/_EXAMPLES_FOR_DEVELOPERS/screen/.gitkeep diff --git a/src/components/basicUIElements/index.js b/src/components/basicUIElements/index.js index e4cf494d2..74f0174f9 100644 --- a/src/components/basicUIElements/index.js +++ b/src/components/basicUIElements/index.js @@ -20,6 +20,7 @@ import WalletUnclaimedPlaceHolder from './view/placeHolder/walletUnclaimedPlaceH import ListPlaceHolder from './view/placeHolder/listPlaceHolderView'; import BoostPlaceHolder from './view/placeHolder/boostPlaceHolderView'; import CommentPlaceHolder from './view/placeHolder/commentPlaceHolderView'; +import CommunitiesPlaceHolder from './view/placeHolder/communitiesPlaceHolder'; export { Card, @@ -42,4 +43,5 @@ export { WalletDetailsPlaceHolder, WalletLineItem, WalletUnclaimedPlaceHolder, + CommunitiesPlaceHolder, }; diff --git a/src/components/basicUIElements/view/placeHolder/communitiesPlaceHolder.js b/src/components/basicUIElements/view/placeHolder/communitiesPlaceHolder.js new file mode 100644 index 000000000..ddc91c269 --- /dev/null +++ b/src/components/basicUIElements/view/placeHolder/communitiesPlaceHolder.js @@ -0,0 +1,34 @@ +import React from 'react'; +import { View } from 'react-native'; +import Placeholder from 'rn-placeholder'; + +import { ThemeContainer } from '../../../../containers'; + +import styles from './postCardPlaceHolderStyles'; +// TODO: make container for place holder wrapper after alpha +const PostCardPlaceHolder = () => { + return ( + + {({ isDarkTheme }) => { + const color = isDarkTheme ? '#2e3d51' : '#f5f5f5'; + return ( + + + + + + ); + }} + + ); +}; +export default PostCardPlaceHolder; diff --git a/src/components/basicUIElements/view/placeHolder/communitiesPlaceHolderStyles.js b/src/components/basicUIElements/view/placeHolder/communitiesPlaceHolderStyles.js new file mode 100644 index 000000000..49e16a3d8 --- /dev/null +++ b/src/components/basicUIElements/view/placeHolder/communitiesPlaceHolderStyles.js @@ -0,0 +1,15 @@ +import EStyleSheet from 'react-native-extended-stylesheet'; + +export default EStyleSheet.create({ + container: { + backgroundColor: '$primaryBackgroundColor', + padding: 20, + borderStyle: 'solid', + borderWidth: 1, + borderTopWidth: 1, + borderColor: '$primaryLightBackground', + marginRight: 0, + marginLeft: 0, + marginTop: 0, + }, +}); diff --git a/src/components/basicUIElements/view/tag/tagContainer.js b/src/components/basicUIElements/view/tag/tagContainer.js index c7320358a..38bbadeba 100644 --- a/src/components/basicUIElements/view/tag/tagContainer.js +++ b/src/components/basicUIElements/view/tag/tagContainer.js @@ -48,7 +48,7 @@ class TagContainer extends PureComponent { onPress(); } else { navigation.navigate({ - routeName: ROUTES.SCREENS.SEARCH_RESULT, + routeName: ROUTES.SCREENS.TAG_RESULT, params: { tag: value, }, @@ -57,7 +57,7 @@ class TagContainer extends PureComponent { }; render() { - const { isPin, value, isPostCardTag, isFilter } = this.props; + const { isPin, value, isPostCardTag, isFilter, style, textStyle } = this.props; const { label } = this.state; return ( @@ -68,6 +68,8 @@ class TagContainer extends PureComponent { isPostCardTag={isPostCardTag} onPress={this._handleOnTagPress} isFilter={isFilter} + style={style} + textStyle={textStyle} /> ); } diff --git a/src/components/basicUIElements/view/tag/tagView.js b/src/components/basicUIElements/view/tag/tagView.js index 0b63db437..2bd9f7c82 100644 --- a/src/components/basicUIElements/view/tag/tagView.js +++ b/src/components/basicUIElements/view/tag/tagView.js @@ -2,14 +2,18 @@ import React from 'react'; import { Text, View, TouchableOpacity } from 'react-native'; import styles from './tagStyles'; -const Tag = ({ onPress, isPin, value, label, isPostCardTag, isFilter }) => ( - onPress && onPress(value)}> +const Tag = ({ onPress, isPin, value, label, isPostCardTag, isFilter, style, textStyle }) => ( + onPress && onPress(value)} + > ( styles.text, !isPin && isFilter && styles.isFilterTextUnPin, isPin && isFilter && styles.isFilterTextPin, + textStyle, ]} > {isPostCardTag ? label : value} diff --git a/src/components/basicUIElements/view/textWithIcon/textWithIconView.js b/src/components/basicUIElements/view/textWithIcon/textWithIconView.js index c6fe97bc9..30ac2102a 100644 --- a/src/components/basicUIElements/view/textWithIcon/textWithIconView.js +++ b/src/components/basicUIElements/view/textWithIcon/textWithIconView.js @@ -37,7 +37,7 @@ const TextWithIcon = ({ name={iconName} iconType={iconType} /> - {text} + {text} )} diff --git a/src/components/header/container/headerContainer.js b/src/components/header/container/headerContainer.js index 8b4a910d1..856768d16 100644 --- a/src/components/header/container/headerContainer.js +++ b/src/components/header/container/headerContainer.js @@ -8,7 +8,7 @@ import HeaderView from '../view/headerView'; import { AccountContainer, ThemeContainer } from '../../../containers'; -const HeaderContainer = ({ selectedUser, isReverse, navigation, handleOnBackPress }) => { +const HeaderContainer = ({ selectedUser, isReverse, navigation, handleOnBackPress, hideUser }) => { const _handleOpenDrawer = () => { if (has(navigation, 'openDrawer') && typeof get(navigation, 'openDrawer') === 'function') { navigation.openDrawer(); @@ -41,6 +41,7 @@ const HeaderContainer = ({ selectedUser, isReverse, navigation, handleOnBackPres isReverse={isReverse} reputation={get(_user, 'reputation')} username={get(_user, 'name')} + hideUser={hideUser} /> ); }} diff --git a/src/components/header/view/headerView.js b/src/components/header/view/headerView.js index 8f9bf0aa3..6074f5ee1 100644 --- a/src/components/header/view/headerView.js +++ b/src/components/header/view/headerView.js @@ -2,12 +2,16 @@ import React, { useState } from 'react'; import { View, Text, SafeAreaView, TouchableOpacity } from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; import { useIntl } from 'react-intl'; +import { withNavigation } from 'react-navigation'; // Components import { SearchModal } from '../../searchModal'; import { IconButton } from '../../iconButton'; import { UserAvatar } from '../../userAvatar'; +// Constants +import ROUTES from '../../../constants/routeNames'; + // Styles import styles from './headerStyles'; @@ -21,6 +25,8 @@ const HeaderView = ({ isReverse, reputation, username, + navigation, + hideUser, }) => { const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); const intl = useIntl(); @@ -32,54 +38,64 @@ const HeaderView = ({ gradientColor = isDarkTheme ? ['#081c36', '#43638e'] : ['#2d5aa0', '#357ce6']; } + const _onPressSearchButton = () => { + navigation.navigate({ + routeName: ROUTES.SCREENS.SEARCH_RESULT, + }); + }; + return ( - setIsSearchModalOpen(false)} - /> - - - + setIsSearchModalOpen(false)} /> - - - {displayName || username ? ( - - {displayName && {displayName}} - - {`@${username}`} - {reputation && ` (${reputation})`} - - - ) : ( - - {isLoginDone && !isLoggedIn && ( - - {intl.formatMessage({ - id: 'header.title', - })} - + + + + + + {displayName || username ? ( + + {displayName && {displayName}} + + {`@${username}`} + {reputation && ` (${reputation})`} + + + ) : ( + + {isLoginDone && !isLoggedIn && ( + + {intl.formatMessage({ + id: 'header.title', + })} + + )} + )} - + )} {isReverse ? ( @@ -93,15 +109,11 @@ const HeaderView = ({ ) : ( - setIsSearchModalOpen(true)} - /> + )} ); }; -export default HeaderView; +export default withNavigation(HeaderView); diff --git a/src/components/postElements/body/view/commentBodyView.js b/src/components/postElements/body/view/commentBodyView.js index 6de079b8e..c6586025b 100644 --- a/src/components/postElements/body/view/commentBodyView.js +++ b/src/components/postElements/body/view/commentBodyView.js @@ -180,7 +180,7 @@ const CommentBody = ({ const __handleTagPress = (tag) => { if (tag) { navigate({ - routeName: ROUTES.SCREENS.SEARCH_RESULT, + routeName: ROUTES.SCREENS.TAG_RESULT, params: { tag, }, diff --git a/src/components/postElements/body/view/postBodyView.js b/src/components/postElements/body/view/postBodyView.js index a63c213ec..5957de5f8 100644 --- a/src/components/postElements/body/view/postBodyView.js +++ b/src/components/postElements/body/view/postBodyView.js @@ -166,7 +166,7 @@ const PostBody = ({ const _handleTagPress = (tag) => { if (tag) { navigation.navigate({ - routeName: ROUTES.SCREENS.SEARCH_RESULT, + routeName: ROUTES.SCREENS.TAG_RESULT, params: { tag, }, diff --git a/src/components/posts/view/postsView.js b/src/components/posts/view/postsView.js index b69a2a20b..e3a63a15a 100644 --- a/src/components/posts/view/postsView.js +++ b/src/components/posts/view/postsView.js @@ -65,9 +65,6 @@ const PostsView = ({ fetchPromotePost(); _loadPosts(); } - return () => { - //unmounting - }; }, [ _getPromotePosts, _loadPosts, diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index b6b62ca06..f706f94de 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -503,5 +503,33 @@ "reveal_comment": "Reveal comment", "read_more": "Read more comments", "more_replies": "more replies" + }, + "search_result": { + "others": "Others", + "communities": { + "title": "Communities", + "subscribe": "Subscribe", + "unsubscribe": "Unsubscribe", + "subscribers": "Subscribers", + "posters": "Posters", + "posts": "Posts" + }, + "communities_filter": { + "rank": "Rank", + "subs": "Subscribers", + "new": "New" + }, + "post_result_filter": { + "popularity": "Popularity", + "newest": "Newest", + "relevance": "Relevance" + }, + "other_result_filter": { + "user": "User", + "tag": "Tag" + } + }, + "community": { + "new_post": "New Post" } } diff --git a/src/constants/routeNames.js b/src/constants/routeNames.js index 1022c3a9c..8089bdf38 100644 --- a/src/constants/routeNames.js +++ b/src/constants/routeNames.js @@ -21,12 +21,14 @@ export default { REDEEM: `Redeem${SCREEN_SUFFIX}`, REGISTER: `Register${SCREEN_SUFFIX}`, SEARCH_RESULT: `SearchResult${SCREEN_SUFFIX}`, + TAG_RESULT: `TagResult${SCREEN_SUFFIX}`, SETTINGS: `Settings${SCREEN_SUFFIX}`, STEEM_CONNECT: `SteemConnect${SCREEN_SUFFIX}`, TRANSFER: `Transfer${SCREEN_SUFFIX}`, VOTERS: `Voters${SCREEN_SUFFIX}`, COMMENTS: `Comments${SCREEN_SUFFIX}`, ACCOUNT_BOOST: `AccountBoost${SCREEN_SUFFIX}`, + COMMUNITY: `Community${SCREEN_SUFFIX}`, }, DRAWER: { MAIN: `Main${DRAWER_SUFFIX}`, diff --git a/src/navigation/routes.js b/src/navigation/routes.js index a6eb80538..77f1bf13b 100644 --- a/src/navigation/routes.js +++ b/src/navigation/routes.js @@ -35,6 +35,8 @@ import { Voters, Wallet, AccountBoost, + TagResult, + Community, } from '../screens'; const bottomTabNavigator = createBottomTabNavigator( @@ -124,12 +126,14 @@ const stackNavigator = createStackNavigator( [ROUTES.SCREENS.DRAFTS]: { screen: Drafts }, [ROUTES.SCREENS.BOOKMARKS]: { screen: Bookmarks }, [ROUTES.SCREENS.SEARCH_RESULT]: { screen: SearchResult }, + [ROUTES.SCREENS.TAG_RESULT]: { screen: TagResult }, [ROUTES.SCREENS.TRANSFER]: { screen: Transfer }, [ROUTES.SCREENS.BOOST]: { screen: Boost }, [ROUTES.SCREENS.REDEEM]: { screen: Redeem }, [ROUTES.SCREENS.REBLOGS]: { screen: Reblogs }, [ROUTES.SCREENS.SPIN_GAME]: { screen: SpinGame }, [ROUTES.SCREENS.ACCOUNT_BOOST]: { screen: AccountBoost }, + [ROUTES.SCREENS.COMMUNITY]: { screen: Community }, }, { headerMode: 'none', diff --git a/src/providers/steem/dsteem.js b/src/providers/steem/dsteem.js index e9d460a71..1c1253614 100644 --- a/src/providers/steem/dsteem.js +++ b/src/providers/steem/dsteem.js @@ -6,8 +6,6 @@ import { Client, PrivateKey, cryptoUtils } from '@esteemapp/dhive'; import hivesigner from 'hivesigner'; import Config from 'react-native-config'; import { get, has } from 'lodash'; -import axios from 'axios'; -import { getInputRangeFromIndexes } from 'react-native-snap-carousel'; import { getServer } from '../../realm/realm'; import { getUnreadActivityCount } from '../esteem/esteem'; import { userActivity } from '../esteem/ePoint'; @@ -1484,7 +1482,7 @@ export const profileUpdate = async (params, pin, currentAccount) => { .then((resp) => resp.result) .catch((error) => console.log(error)); } - console.log('priv key', key); + if (key) { const opArray = [ [ @@ -1521,6 +1519,34 @@ export const profileUpdate = async (params, pin, currentAccount) => { ); }; +export const subscribeCommunity = (currentAccount, pinCode, data) => { + const pin = getDigitPinCode(pinCode); + const key = getActiveKey(get(currentAccount, 'local'), pin); + const username = get(currentAccount, 'name'); + + const json = JSON.stringify([ + data.isSubscribed ? 'unsubscribe' : 'subscribe', + { community: data.communityId }, + ]); + + if (key) { + const privateKey = PrivateKey.fromString(key); + + const op = { + id: 'community', + json, + required_auths: [username], + required_posting_auths: [], + }; + + return client.broadcast.json(op, privateKey); + } + + return Promise.reject( + new Error('Check private key permission! Required private active key or above.'), + ); +}; + export const getBtcAddress = (pin, currentAccount) => { /*const digitPinCode = getDigitPinCode(pin); const key = getActiveKey(get(currentAccount, 'local'), digitPinCode); diff --git a/src/providers/steem/steem.js b/src/providers/steem/steem.js new file mode 100644 index 000000000..a1a74e033 --- /dev/null +++ b/src/providers/steem/steem.js @@ -0,0 +1,38 @@ +import axios from 'axios'; + +const DEFAULT_SERVER = [ + 'https://rpc.esteem.app', + 'https://anyx.io', + 'https://api.pharesim.me', + 'https://api.hive.blog', + 'https://api.hivekings.com', +]; + +const pickAServer = () => DEFAULT_SERVER.sort(() => 0.5 - Math.random())[0]; + +const bridgeApiCall = (endpoint, params) => + axios + .post(pickAServer(), { + jsonrpc: '2.0', + method: endpoint, + params: params, + id: 1, + }) + .then((resp) => { + return resp.data.result || null; + }); + +export const getCommunity = (name, observer = '') => + bridgeApiCall('bridge.get_community', { name, observer }); + +export const getCommunities = (last = '', limit = 100, query = '', sort = 'rank', observer = '') => + bridgeApiCall('bridge.list_communities', { + last, + limit, + query, + sort, + observer, + }); + +export const getSubscriptions = (account = '') => + bridgeApiCall('bridge.list_all_subscriptions', { account }); diff --git a/src/screens/community/container/communityContainer.js b/src/screens/community/container/communityContainer.js new file mode 100644 index 000000000..a7394f0d4 --- /dev/null +++ b/src/screens/community/container/communityContainer.js @@ -0,0 +1,67 @@ +import { useState, useEffect } from 'react'; +import { withNavigation } from 'react-navigation'; +import get from 'lodash/get'; +import { connect } from 'react-redux'; + +import { getCommunity, getSubscriptions } from '../../../providers/steem/steem'; +import { subscribeCommunity } from '../../../providers/steem/dsteem'; + +import ROUTES from '../../../constants/routeNames'; + +const CommunityContainer = ({ children, navigation, currentAccount, pinCode }) => { + const [data, setData] = useState(null); + const [isSubscribed, setIsSubscribed] = useState(false); + const tag = get(navigation, 'state.params.tag'); + + useEffect(() => { + getCommunity(tag).then((res) => { + setData(res); + }); + }, [tag]); + + useEffect(() => { + if (data) { + getSubscriptions(currentAccount.username).then((result) => { + const _isSubscribed = result.some((item) => item[0] === data.name); + setIsSubscribed(_isSubscribed); + }); + } + }, [data]); + + const _handleSubscribeButtonPress = () => { + const _data = { + isSubscribed: !isSubscribed, + communityId: data.name, + }; + + subscribeCommunity(currentAccount, pinCode, _data).then((result) => { + setIsSubscribed(!isSubscribed); + }); + }; + + const _handleNewPostButtonPress = () => { + navigation.navigate({ + routeName: ROUTES.SCREENS.EDITOR, + params: { + tags: [tag], + }, + }); + }; + + return ( + children && + children({ + data, + handleSubscribeButtonPress: _handleSubscribeButtonPress, + handleNewPostButtonPress: _handleNewPostButtonPress, + isSubscribed: isSubscribed, + }) + ); +}; + +const mapStateToProps = (state) => ({ + currentAccount: state.account.currentAccount, + pinCode: state.application.pin, +}); + +export default connect(mapStateToProps)(withNavigation(CommunityContainer)); diff --git a/src/screens/community/index.js b/src/screens/community/index.js new file mode 100644 index 000000000..ec9fc74ca --- /dev/null +++ b/src/screens/community/index.js @@ -0,0 +1,4 @@ +import Community from './screen/communityScreen'; + +export { Community }; +export default Community; diff --git a/src/screens/community/screen/communityScreen.js b/src/screens/community/screen/communityScreen.js new file mode 100644 index 000000000..bafcad5ca --- /dev/null +++ b/src/screens/community/screen/communityScreen.js @@ -0,0 +1,99 @@ +import React from 'react'; +import { View, Text } from 'react-native'; +import { useIntl } from 'react-intl'; + +// Components +import { Posts, CollapsibleCard, Header } from '../../../components'; +import { Tag, ProfileSummaryPlaceHolder } from '../../../components/basicUIElements'; + +import CommunityContainer from '../container/communityContainer'; + +// Styles +import styles from './communityStyles'; + +import { GLOBAL_POST_FILTERS, GLOBAL_POST_FILTERS_VALUE } from '../../../constants/options/filters'; + +const TagResultScreen = ({ navigation }) => { + const tag = navigation.getParam('tag', ''); + const filter = navigation.getParam('filter', ''); + + const intl = useIntl(); + + const _getSelectedIndex = () => { + if (filter) { + const selectedIndex = GLOBAL_POST_FILTERS_VALUE.indexOf(filter); + if (selectedIndex > 0) { + return selectedIndex; + } + } + return 0; + }; + + return ( + + {({ data, handleSubscribeButtonPress, handleNewPostButtonPress, isSubscribed }) => ( + +
+ {data ? ( + + + {data.description} + + + {`${data.subscribers} ${intl.formatMessage({ + id: 'search_result.communities.subscribers', + })} • ${data.num_authors} ${intl.formatMessage({ + id: 'search_result.communities.posters', + })} • ${data.num_pending} ${intl.formatMessage({ + id: 'search_result.communities.posts', + })}`} + + + + + + + + + ) : ( + + )} + + + + + )} + + ); +}; + +export default TagResultScreen; diff --git a/src/screens/community/screen/communityStyles.js b/src/screens/community/screen/communityStyles.js new file mode 100644 index 000000000..ae1c70f34 --- /dev/null +++ b/src/screens/community/screen/communityStyles.js @@ -0,0 +1,62 @@ +import EStyleSheet from 'react-native-extended-stylesheet'; + +export default EStyleSheet.create({ + container: { + flex: 1, + backgroundColor: '$primaryLightBackground', + }, + buttonContainer: { + width: '50%', + alignItems: 'center', + }, + tabbar: { + alignSelf: 'center', + height: 40, + backgroundColor: '$primaryBackgroundColor', + shadowOpacity: 0.2, + shadowColor: '$shadowColor', + shadowOffset: { height: 4 }, + zIndex: 99, + borderBottomColor: '$shadowColor', + borderBottomWidth: 0.1, + marginTop: 8, + }, + tabbarItem: { + flex: 1, + backgroundColor: '$primaryBackgroundColor', + minWidth: '$deviceWidth', + }, + tabs: { + flex: 1, + }, + tabView: { + backgroundColor: '$primaryGrayBackground', + }, + description: { + fontSize: 14, + fontFamily: '$primaryFont', + marginTop: 5, + color: '$primaryBlack', + textAlign: 'center', + }, + separator: { + width: 100, + alignSelf: 'center', + backgroundColor: '$primaryDarkGray', + height: 0.5, + marginVertical: 10, + }, + stats: { + fontSize: 14, + fontFamily: '$primaryFont', + color: '$primaryDarkGray', + }, + subscribeButton: { + borderWidth: 1, + borderColor: '$primaryBlue', + }, + collapsibleCard: { alignItems: 'center', marginBottom: 20 }, + subscribeButtonText: { + color: '$primaryBlue', + }, +}); diff --git a/src/screens/editor/container/editorContainer.js b/src/screens/editor/container/editorContainer.js index 64bd4d5d8..9fe8d0b34 100644 --- a/src/screens/editor/container/editorContainer.js +++ b/src/screens/editor/container/editorContainer.js @@ -716,7 +716,7 @@ class EditorContainer extends Component { } render() { - const { isLoggedIn, isDarkTheme } = this.props; + const { isLoggedIn, isDarkTheme, navigation } = this.props; const { autoFocusText, draftPost, @@ -731,6 +731,8 @@ class EditorContainer extends Component { uploadedImage, } = this.state; + const tags = navigation.state.params.tags; + return ( ); } diff --git a/src/screens/editor/screen/editorScreen.js b/src/screens/editor/screen/editorScreen.js index 15184c6d4..6c7eda92a 100644 --- a/src/screens/editor/screen/editorScreen.js +++ b/src/screens/editor/screen/editorScreen.js @@ -36,7 +36,7 @@ class EditorScreen extends Component { fields: { title: (props.draftPost && props.draftPost.title) || '', body: (props.draftPost && props.draftPost.body) || '', - tags: (props.draftPost && props.draftPost.tags) || [], + tags: (props.draftPost && props.draftPost.tags) || props.tags || [], isValid: false, }, }; @@ -50,6 +50,7 @@ class EditorScreen extends Component { fields: { ...prevState.fields, ...nextProps.draftPost, + tags: prevState.fields.tags, }, })); } diff --git a/src/screens/index.js b/src/screens/index.js index 4d6071cd9..e05918d15 100755 --- a/src/screens/index.js +++ b/src/screens/index.js @@ -22,6 +22,8 @@ import Transfer from './transfer'; import Voters from './voters'; import AccountBoost from './accountBoost/screen/accountBoostScreen'; import Register from './register/registerScreen'; +import TagResult from './tagResult'; +import { Community } from './community'; export { Bookmarks, @@ -48,4 +50,6 @@ export { Transfer, Voters, Wallet, + TagResult, + Community, }; diff --git a/src/screens/searchResult/container/communitiesContainer.js b/src/screens/searchResult/container/communitiesContainer.js new file mode 100644 index 000000000..c04967eba --- /dev/null +++ b/src/screens/searchResult/container/communitiesContainer.js @@ -0,0 +1,76 @@ +import { useState, useEffect } from 'react'; +import { withNavigation } from 'react-navigation'; +import { connect } from 'react-redux'; + +import ROUTES from '../../../constants/routeNames'; + +import { getCommunities, getSubscriptions } from '../../../providers/steem/steem'; +import { subscribeCommunity } from '../../../providers/steem/dsteem'; + +const CommunitiesContainer = ({ children, navigation, searchValue, currentAccount, pinCode }) => { + const [data, setData] = useState(); + const [filterIndex, setFilterIndex] = useState(0); + const [query, setQuery] = useState(''); + const [sort, setSort] = useState('rank'); + const [allSubscriptions, setAllSubscriptions] = useState([]); + + useEffect(() => { + setData([]); + getCommunities('', 100, query, sort).then((res) => { + if (res) { + setData(res); + } + }); + }, [query, sort]); + + useEffect(() => { + setData([]); + setQuery(searchValue); + }, [searchValue]); + + useEffect(() => { + if (data) { + getSubscriptions(currentAccount.username).then((result) => { + setAllSubscriptions(result); + }); + } + }, [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, + }) + ); +}; + +const mapStateToProps = (state) => ({ + currentAccount: state.account.currentAccount, + pinCode: state.application.pin, +}); + +export default connect(mapStateToProps)(withNavigation(CommunitiesContainer)); diff --git a/src/screens/searchResult/container/otherResultContainer.js b/src/screens/searchResult/container/otherResultContainer.js new file mode 100644 index 000000000..d801291ff --- /dev/null +++ b/src/screens/searchResult/container/otherResultContainer.js @@ -0,0 +1,83 @@ +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/steem/dsteem'; +import { getLeaderboard } from '../../../providers/esteem/esteem'; + +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).then((res) => { + setUsers(res); + }); + getTrendingTags(searchValue).then((res) => { + setTags(res); + }); + } else { + getLeaderboard().then((result) => { + setUsers(result.map((item) => item._id)); + }); + } + }, [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)); diff --git a/src/screens/searchResult/container/postResultContainer.js b/src/screens/searchResult/container/postResultContainer.js new file mode 100644 index 000000000..01d5c407b --- /dev/null +++ b/src/screens/searchResult/container/postResultContainer.js @@ -0,0 +1,90 @@ +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/esteem/esteem'; +import { getPost } from '../../../providers/steem/dsteem'; + +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; + 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)); diff --git a/src/screens/searchResult/screen/CommunitiesListItem.js b/src/screens/searchResult/screen/CommunitiesListItem.js new file mode 100644 index 000000000..1736d6616 --- /dev/null +++ b/src/screens/searchResult/screen/CommunitiesListItem.js @@ -0,0 +1,77 @@ +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, +}) => { + const [subscribed, setSubscribed] = useState(isSubscribed); + const intl = useIntl(); + + const _handleSubscribeButtonPress = () => { + handleSubscribeButtonPress({ subscribed: !subscribed, communityId: name }).then(() => { + setSubscribed(!subscribed); + }); + }; + + return ( + handleOnLongPress && handleOnLongPress()} + onPress={() => handleOnPress && handleOnPress(name)} + > + + + + {title} + + + {!!about && {about}} + + + {`${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', + })}`} + + + + + ); +}; + +export default UserListItem; diff --git a/src/screens/searchResult/screen/communities.js b/src/screens/searchResult/screen/communities.js new file mode 100644 index 000000000..a4824bfe0 --- /dev/null +++ b/src/screens/searchResult/screen/communities.js @@ -0,0 +1,54 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; +import get from 'lodash/get'; + +// Components +import { FilterBar } from '../../../components'; +import CommunitiesList from './communitiesList'; + +import CommunitiesContainer from '../container/communitiesContainer'; + +const filterOptions = ['rank', 'subs', 'new']; + +const CommunitiesScreen = ({ navigation, searchValue }) => { + const intl = useIntl(); + + const activeVotes = get(navigation, 'state.params.activeVotes'); + + return ( + + {({ + data, + filterIndex, + allSubscriptions, + handleOnVotersDropdownSelect, + handleOnPress, + handleSubscribeButtonPress, + }) => ( + <> + + 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])} + /> + + + )} + + ); +}; + +export default CommunitiesScreen; diff --git a/src/screens/searchResult/screen/communitiesList.js b/src/screens/searchResult/screen/communitiesList.js new file mode 100644 index 000000000..87abeb563 --- /dev/null +++ b/src/screens/searchResult/screen/communitiesList.js @@ -0,0 +1,65 @@ +import React from 'react'; +import { SafeAreaView, FlatList } from 'react-native'; + +// Components +import CommunitiesListItem from './CommunitiesListItem'; +import { CommunitiesPlaceHolder } from '../../../components/basicUIElements'; + +// Styles +import styles from './communitiesListStyles'; + +const VotersDisplayView = ({ + votes, + handleOnPress, + handleSubscribeButtonPress, + allSubscriptions, +}) => { + const _renderItem = (item, index) => { + const isSubscribed = allSubscriptions.some((sub) => sub[0] === item.name); + + return ( + + ); + }; + + const _renderEmptyContent = () => { + return ( + <> + + + + + + + + + ); + }; + + return ( + + item.id.toString()} + renderItem={({ item, index }) => _renderItem(item, index)} + ListEmptyComponent={_renderEmptyContent} + /> + + ); +}; + +export default VotersDisplayView; diff --git a/src/screens/searchResult/screen/communitiesListItemStyles.js b/src/screens/searchResult/screen/communitiesListItemStyles.js new file mode 100644 index 000000000..d28760b23 --- /dev/null +++ b/src/screens/searchResult/screen/communitiesListItemStyles.js @@ -0,0 +1,58 @@ +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, + color: '$primaryBlack', + }, + separator: { + width: 100, + alignSelf: 'center', + backgroundColor: '$primaryDarkGray', + height: 0.5, + marginVertical: 5, + }, + stats: { + fontSize: 14, + fontFamily: '$primaryFont', + color: '$primaryDarkGray', + }, + subscribeButton: { + borderWidth: 1, + borderColor: '$primaryBlue', + }, + subscribeButtonText: { + color: '$primaryBlue', + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + }, +}); diff --git a/src/screens/searchResult/screen/communitiesListStyles.js b/src/screens/searchResult/screen/communitiesListStyles.js new file mode 100644 index 000000000..8423a2e5e --- /dev/null +++ b/src/screens/searchResult/screen/communitiesListStyles.js @@ -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', + }, +}); diff --git a/src/screens/searchResult/screen/otherResults.js b/src/screens/searchResult/screen/otherResults.js new file mode 100644 index 000000000..2d9f36035 --- /dev/null +++ b/src/screens/searchResult/screen/otherResults.js @@ -0,0 +1,104 @@ +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) => ( + + + {item} + + ); + + const _renderTagItem = (item, index) => ( + + {`#${item.name}`} + + ); + + const _renderEmptyContent = () => { + return ( + <> + + + + + + + + + ); + }; + + const _renderList = (users, tags, filterIndex, handleOnPress) => { + switch (filterIndex) { + case 0: + return ( + item.id} + renderItem={({ item, index }) => ( + handleOnPress(item)}> + {_renderUserItem(item, index)} + + )} + ListEmptyComponent={_renderEmptyContent} + /> + ); + case 1: + return ( + item.id} + renderItem={({ item, index }) => ( + handleOnPress(item)}> + {_renderTagItem(item, index)} + + )} + ListEmptyComponent={_renderEmptyContent} + /> + ); + + default: + break; + } + }; + + return ( + + {({ users, tags, filterIndex, handleFilterChanged, handleOnPress, loadMore }) => ( + + + 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)} + + )} + + ); +}; + +export default OtherResult; diff --git a/src/screens/searchResult/screen/otherResultsStyles.js b/src/screens/searchResult/screen/otherResultsStyles.js new file mode 100644 index 000000000..82503bc86 --- /dev/null +++ b/src/screens/searchResult/screen/otherResultsStyles.js @@ -0,0 +1,24 @@ +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', + }, +}); diff --git a/src/screens/searchResult/screen/postResult.js b/src/screens/searchResult/screen/postResult.js new file mode 100644 index 000000000..937c3fa07 --- /dev/null +++ b/src/screens/searchResult/screen/postResult.js @@ -0,0 +1,110 @@ +import React from 'react'; +import { SafeAreaView, FlatList, View, Text, TouchableOpacity } from 'react-native'; +import get from 'lodash/get'; +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 ( + + + + + {item.title} + + {item.body} + + + + {item.payout && {`$ ${item.payout}`}} + + + + + ); + }; + + const _renderEmptyContent = () => { + return ( + <> + + + + + + + + + ); + }; + + return ( + + {({ data, filterIndex, handleFilterChanged, handleOnPress, loadMore }) => ( + + + 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])} + /> + item.id.toString()} + renderItem={({ item, index }) => ( + handleOnPress(item)}> + {_renderItem(item, index)} + + )} + onEndReached={loadMore} + ListEmptyComponent={_renderEmptyContent} + ListFooterComponent={} + /> + + )} + + ); +}; + +export default PostResult; diff --git a/src/screens/searchResult/screen/postResultStyles.js b/src/screens/searchResult/screen/postResultStyles.js new file mode 100644 index 000000000..db40ab8fe --- /dev/null +++ b/src/screens/searchResult/screen/postResultStyles.js @@ -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', + }, +}); diff --git a/src/screens/searchResult/screen/searchResultScreen.js b/src/screens/searchResult/screen/searchResultScreen.js index 567a12c6c..d174bfbca 100644 --- a/src/screens/searchResult/screen/searchResultScreen.js +++ b/src/screens/searchResult/screen/searchResultScreen.js @@ -1,23 +1,31 @@ -import React from 'react'; +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'; // Components -import { SearchInput, Posts, TabBar } from '../../../components'; +import { SearchInput, TabBar } from '../../../components'; +import Communities from './communities'; +import PostResult from './postResult'; +import OtherResult from './otherResults'; // Styles import styles from './searchResultStyles'; import globalStyles from '../../../globalStyles'; -import { GLOBAL_POST_FILTERS, GLOBAL_POST_FILTERS_VALUE } from '../../../constants/options/filters'; - const SearchResultScreen = ({ navigation }) => { - const tag = navigation.getParam('tag', ''); - const filter = navigation.getParam('filter', ''); - + 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(); }; @@ -31,34 +39,34 @@ const SearchResultScreen = ({ navigation }) => { /> ); - const _getSelectedIndex = () => { - if (filter) { - const selectedIndex = GLOBAL_POST_FILTERS_VALUE.indexOf(filter); - if (selectedIndex > 0) { - return selectedIndex; - } - } - return 0; - }; - return ( - + + + + - + + + + diff --git a/src/screens/tagResult/index.js b/src/screens/tagResult/index.js new file mode 100644 index 000000000..782c2c6b0 --- /dev/null +++ b/src/screens/tagResult/index.js @@ -0,0 +1,4 @@ +import SearchResult from './screen/tagResultScreen'; + +export { SearchResult }; +export default SearchResult; diff --git a/src/screens/tagResult/screen/tagResultScreen.js b/src/screens/tagResult/screen/tagResultScreen.js new file mode 100644 index 000000000..e38663774 --- /dev/null +++ b/src/screens/tagResult/screen/tagResultScreen.js @@ -0,0 +1,68 @@ +import React from 'react'; +import { View, SafeAreaView } from 'react-native'; +import ScrollableTabView from 'react-native-scrollable-tab-view'; +import { useIntl } from 'react-intl'; + +// Components +import { SearchInput, Posts, TabBar } from '../../../components'; + +// Styles +import styles from './tagResultStyles'; +import globalStyles from '../../../globalStyles'; + +import { GLOBAL_POST_FILTERS, GLOBAL_POST_FILTERS_VALUE } from '../../../constants/options/filters'; + +const TagResultScreen = ({ navigation }) => { + const tag = navigation.getParam('tag', ''); + const filter = navigation.getParam('filter', ''); + + const intl = useIntl(); + + const _navigationGoBack = () => { + navigation.goBack(); + }; + + const _renderTabbar = () => ( + + ); + + const _getSelectedIndex = () => { + if (filter) { + const selectedIndex = GLOBAL_POST_FILTERS_VALUE.indexOf(filter); + if (selectedIndex > 0) { + return selectedIndex; + } + } + return 0; + }; + + return ( + + + + + + + + + + + ); +}; + +export default TagResultScreen; diff --git a/src/screens/tagResult/screen/tagResultStyles.js b/src/screens/tagResult/screen/tagResultStyles.js new file mode 100644 index 000000000..0ef7bc05b --- /dev/null +++ b/src/screens/tagResult/screen/tagResultStyles.js @@ -0,0 +1,31 @@ +import EStyleSheet from 'react-native-extended-stylesheet'; + +export default EStyleSheet.create({ + container: { + flex: 1, + backgroundColor: '$primaryBackgroundColor', + }, + buttonContainer: { + width: '50%', + alignItems: 'center', + }, + tabbar: { + alignSelf: 'center', + height: 40, + backgroundColor: '$primaryBackgroundColor', + shadowOpacity: 0.2, + shadowColor: '$shadowColor', + shadowOffset: { height: 4 }, + zIndex: 99, + borderBottomColor: '$shadowColor', + borderBottomWidth: 0.1, + }, + tabbarItem: { + flex: 1, + backgroundColor: '$primaryBackgroundColor', + minWidth: '$deviceWidth', + }, + tabs: { + flex: 1, + }, +}); diff --git a/src/screens/voters/screen/votersScreen.js b/src/screens/voters/screen/votersScreen.js index 4ee5d912f..7ab64820c 100644 --- a/src/screens/voters/screen/votersScreen.js +++ b/src/screens/voters/screen/votersScreen.js @@ -24,7 +24,7 @@ const VotersScreen = ({ navigation }) => { return ( {({ data, filterResult, filterIndex, handleOnVotersDropdownSelect, handleSearch }) => ( - + <> { onDropdownSelect={handleOnVotersDropdownSelect} /> - + )} );