diff --git a/src/component/suggestedSubscriptionItem/view.js b/src/component/suggestedSubscriptionItem/view.js index aa22439..35b60a1 100644 --- a/src/component/suggestedSubscriptionItem/view.js +++ b/src/component/suggestedSubscriptionItem/view.js @@ -72,7 +72,9 @@ class SuggestedSubscriptionItem extends React.PureComponent { )} - + {claim && ( + + )} ); } diff --git a/src/page/search/index.js b/src/page/search/index.js index b86cc92..dc39f39 100644 --- a/src/page/search/index.js +++ b/src/page/search/index.js @@ -1,8 +1,10 @@ import { connect } from 'react-redux'; import { + doClaimSearch, doSearch, doUpdateSearchQuery, makeSelectSearchUris, + selectClaimSearchByQuery, selectIsSearching, selectSearchValue, makeSelectQueryWithOptions, @@ -13,9 +15,10 @@ import { selectCurrentRoute } from 'redux/selectors/drawer'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import SearchPage from './view'; -const numSearchResults = 50; +const numSearchResults = 25; const select = state => ({ + claimSearchByQuery: selectClaimSearchByQuery(state), currentRoute: selectCurrentRoute(state), isSearching: selectIsSearching(state), query: selectSearchValue(state), @@ -25,6 +28,7 @@ const select = state => ({ const perform = dispatch => ({ search: query => dispatch(doSearch(query, numSearchResults)), + claimSearch: options => dispatch(doClaimSearch(options)), updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)), pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SEARCH)), setPlayerVisible: () => dispatch(doSetPlayerVisible(false)), diff --git a/src/page/search/view.js b/src/page/search/view.js index d6580c0..1f5a8f4 100644 --- a/src/page/search/view.js +++ b/src/page/search/view.js @@ -1,6 +1,15 @@ import React from 'react'; -import { Lbry, parseURI, normalizeURI, isURIValid } from 'lbry-redux'; -import { ActivityIndicator, Button, FlatList, NativeModules, Text, TextInput, View } from 'react-native'; +import { Lbry, createNormalizedClaimSearchKey, parseURI, normalizeURI, isURIValid } from 'lbry-redux'; +import { + ActivityIndicator, + Button, + FlatList, + NativeModules, + Text, + TextInput, + TouchableOpacity, + View, +} from 'react-native'; import { navigateToUri } from 'utils/helper'; import Colors from 'styles/colors'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api @@ -14,6 +23,9 @@ class SearchPage extends React.PureComponent { state = { currentQuery: null, currentUri: null, + showTagResult: false, + claimSearchRun: false, + claimSearchOptions: null, }; static navigationOptions = { @@ -43,6 +55,9 @@ class SearchPage extends React.PureComponent { this.setState({ currentQuery: searchQuery, currentUri: isURIValid(searchQuery) ? normalizeURI(searchQuery) : null, + claimSearchOptions: null, + claimSearchRun: false, + showTagResult: false, }); search(searchQuery); } @@ -80,7 +95,12 @@ class SearchPage extends React.PureComponent { handleSearchSubmitted = keywords => { const { search } = this.props; - this.setState({ currentUri: isURIValid(keywords) ? normalizeURI(keywords) : null }); + this.setState({ + currentUri: isURIValid(keywords) ? normalizeURI(keywords) : null, + claimSearchOptions: null, + claimSearchRun: false, + showTagResult: false, + }); search(keywords); }; @@ -96,15 +116,45 @@ class SearchPage extends React.PureComponent { ); }; - listHeaderComponent = () => { - const { navigation } = this.props; + listHeaderComponent = showTagResult => { + const { navigation, claimSearch, claimSearchByQuery } = this.props; const { currentUri } = this.state; + const query = this.getSearchQuery(); + + const canBeTag = query && query.trim().length > 0 && isURIValid(query); + if (canBeTag && !this.state.claimSearchRun) { + const options = { + any_tags: [query], + page: 1, + no_totals: true, + }; + this.setState({ claimSearchOptions: options, claimSearchRun: true }, () => claimSearch(options)); + } + + if (this.state.claimSearchRun && this.state.claimSearchOptions) { + const claimSearchKey = createNormalizedClaimSearchKey(this.state.claimSearchOptions); + const claimSearchUris = claimSearchByQuery[claimSearchKey]; + this.setState({ showTagResult: claimSearchUris && claimSearchUris.length > 0 }); + } return ( - + + + {showTagResult && ( + this.handleTagResultPressed(query)}> + #{query} + Explore content for this tag + + )} + ); }; + handleTagResultPressed = tag => { + const { navigation } = this.props; + navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TAG, key: `tagPage`, params: { tag } }); + }; + render() { const { isSearching, navigation, query, uris, urisByQuery } = this.props; @@ -119,6 +169,7 @@ class SearchPage extends React.PureComponent { )} ( )} diff --git a/src/styles/search.js b/src/styles/search.js index df62e8c..559d0a1 100644 --- a/src/styles/search.js +++ b/src/styles/search.js @@ -35,12 +35,24 @@ const searchStyle = StyleSheet.create({ flex: 1, flexDirection: 'row', justifyContent: 'space-between', - paddingTop: 8, - paddingBottom: 8, - paddingLeft: 8, - paddingRight: 8, + padding: 8, backgroundColor: Colors.Black, }, + tagResultItem: { + flex: 1, + padding: 16, + backgroundColor: Colors.DarkerGrey, + }, + tagResultTitle: { + fontFamily: 'Inter-UI-SemiBold', + fontSize: 24, + color: Colors.White, + }, + tagResultDescription: { + fontFamily: 'Inter-UI-Regular', + fontSize: 14, + color: Colors.VeryLightGrey, + }, searchInput: { width: '100%', height: '100%',