RC #72

Merged
akinwale merged 5 commits from rc into master 2019-10-30 10:35:43 +01:00
4 changed files with 82 additions and 13 deletions

View file

@ -72,7 +72,9 @@ class SuggestedSubscriptionItem extends React.PureComponent {
)} )}
</View> </View>
<SubscribeButton style={subscriptionsStyle.suggestedItemSubscribe} uri={normalizeURI(uri)} /> {claim && (
<SubscribeButton style={subscriptionsStyle.suggestedItemSubscribe} uri={normalizeURI(claim.permanent_url)} />
)}
</View> </View>
); );
} }

View file

@ -1,8 +1,10 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
doClaimSearch,
doSearch, doSearch,
doUpdateSearchQuery, doUpdateSearchQuery,
makeSelectSearchUris, makeSelectSearchUris,
selectClaimSearchByQuery,
selectIsSearching, selectIsSearching,
selectSearchValue, selectSearchValue,
makeSelectQueryWithOptions, makeSelectQueryWithOptions,
@ -13,9 +15,10 @@ import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import SearchPage from './view'; import SearchPage from './view';
const numSearchResults = 50; const numSearchResults = 25;
const select = state => ({ const select = state => ({
claimSearchByQuery: selectClaimSearchByQuery(state),
currentRoute: selectCurrentRoute(state), currentRoute: selectCurrentRoute(state),
isSearching: selectIsSearching(state), isSearching: selectIsSearching(state),
query: selectSearchValue(state), query: selectSearchValue(state),
@ -25,6 +28,7 @@ const select = state => ({
const perform = dispatch => ({ const perform = dispatch => ({
search: query => dispatch(doSearch(query, numSearchResults)), search: query => dispatch(doSearch(query, numSearchResults)),
claimSearch: options => dispatch(doClaimSearch(options)),
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)), updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SEARCH)), pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SEARCH)),
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)), setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),

View file

@ -1,6 +1,15 @@
import React from 'react'; import React from 'react';
import { Lbry, parseURI, normalizeURI, isURIValid } from 'lbry-redux'; import { Lbry, createNormalizedClaimSearchKey, parseURI, normalizeURI, isURIValid } from 'lbry-redux';
import { ActivityIndicator, Button, FlatList, NativeModules, Text, TextInput, View } from 'react-native'; import {
ActivityIndicator,
Button,
FlatList,
NativeModules,
Text,
TextInput,
TouchableOpacity,
View,
} from 'react-native';
import { navigateToUri } from 'utils/helper'; import { navigateToUri } from 'utils/helper';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
@ -14,6 +23,9 @@ class SearchPage extends React.PureComponent {
state = { state = {
currentQuery: null, currentQuery: null,
currentUri: null, currentUri: null,
showTagResult: false,
claimSearchRun: false,
claimSearchOptions: null,
}; };
static navigationOptions = { static navigationOptions = {
@ -43,6 +55,9 @@ class SearchPage extends React.PureComponent {
this.setState({ this.setState({
currentQuery: searchQuery, currentQuery: searchQuery,
currentUri: isURIValid(searchQuery) ? normalizeURI(searchQuery) : null, currentUri: isURIValid(searchQuery) ? normalizeURI(searchQuery) : null,
claimSearchOptions: null,
claimSearchRun: false,
showTagResult: false,
}); });
search(searchQuery); search(searchQuery);
} }
@ -80,7 +95,12 @@ class SearchPage extends React.PureComponent {
handleSearchSubmitted = keywords => { handleSearchSubmitted = keywords => {
const { search } = this.props; 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); search(keywords);
}; };
@ -96,15 +116,45 @@ class SearchPage extends React.PureComponent {
); );
}; };
listHeaderComponent = () => { listHeaderComponent = showTagResult => {
const { navigation } = this.props; const { navigation, claimSearch, claimSearchByQuery } = this.props;
const { currentUri } = this.state; 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 ( return (
<FileListItem uri={currentUri} featuredResult style={searchStyle.featuredResultItem} navigation={navigation} /> <View>
<FileListItem uri={currentUri} featuredResult style={searchStyle.featuredResultItem} navigation={navigation} />
{showTagResult && (
<TouchableOpacity style={searchStyle.tagResultItem} onPress={() => this.handleTagResultPressed(query)}>
<Text style={searchStyle.tagResultTitle}>#{query}</Text>
<Text style={searchStyle.tagResultDescription}>Explore content for this tag</Text>
</TouchableOpacity>
)}
</View>
); );
}; };
handleTagResultPressed = tag => {
const { navigation } = this.props;
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TAG, key: `tagPage`, params: { tag } });
};
render() { render() {
const { isSearching, navigation, query, uris, urisByQuery } = this.props; const { isSearching, navigation, query, uris, urisByQuery } = this.props;
@ -119,6 +169,7 @@ class SearchPage extends React.PureComponent {
)} )}
<FlatList <FlatList
extraData={this.state}
style={searchStyle.scrollContainer} style={searchStyle.scrollContainer}
contentContainerStyle={searchStyle.scrollPadding} contentContainerStyle={searchStyle.scrollPadding}
keyboardShouldPersistTaps={'handled'} keyboardShouldPersistTaps={'handled'}
@ -128,7 +179,7 @@ class SearchPage extends React.PureComponent {
maxToRenderPerBatch={20} maxToRenderPerBatch={20}
removeClippedSubviews removeClippedSubviews
ListEmptyComponent={!isSearching ? this.listEmptyComponent() : null} ListEmptyComponent={!isSearching ? this.listEmptyComponent() : null}
ListHeaderComponent={this.state.currentUri ? this.listHeaderComponent() : null} ListHeaderComponent={this.state.currentUri ? this.listHeaderComponent(this.state.showTagResult) : null}
renderItem={({ item }) => ( renderItem={({ item }) => (
<FileListItem key={item} uri={item} style={searchStyle.resultItem} navigation={navigation} /> <FileListItem key={item} uri={item} style={searchStyle.resultItem} navigation={navigation} />
)} )}

View file

@ -35,12 +35,24 @@ const searchStyle = StyleSheet.create({
flex: 1, flex: 1,
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
paddingTop: 8, padding: 8,
paddingBottom: 8,
paddingLeft: 8,
paddingRight: 8,
backgroundColor: Colors.Black, 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: { searchInput: {
width: '100%', width: '100%',
height: '100%', height: '100%',