allow scrolling for displaying more search results #110

Merged
akinwale merged 3 commits from search-results into master 2020-01-09 16:49:15 +01:00
6 changed files with 52 additions and 15 deletions

4
package-lock.json generated
View file

@ -7067,8 +7067,8 @@
} }
}, },
"lbry-redux": { "lbry-redux": {
"version": "github:lbryio/lbry-redux#e8f29f1c47b136669df265babb109d2488a37db0", "version": "github:lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
"from": "github:lbryio/lbry-redux#e8f29f1c47b136669df265babb109d2488a37db0", "from": "github:lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
"requires": { "requires": {
"proxy-polyfill": "0.1.6", "proxy-polyfill": "0.1.6",
"reselect": "^3.0.0", "reselect": "^3.0.0",

View file

@ -12,7 +12,7 @@
"base-64": "^0.1.0", "base-64": "^0.1.0",
"@expo/vector-icons": "^8.1.0", "@expo/vector-icons": "^8.1.0",
"gfycat-style-urls": "^1.0.3", "gfycat-style-urls": "^1.0.3",
"lbry-redux": "lbryio/lbry-redux#e8f29f1c47b136669df265babb109d2488a37db0", "lbry-redux": "lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
"lbryinc": "lbryio/lbryinc#053ca52f4f7f9bf8eb62a3581b183671a475ad1c", "lbryinc": "lbryio/lbryinc#053ca52f4f7f9bf8eb62a3581b183671a475ad1c",
"lodash": ">=4.17.11", "lodash": ">=4.17.11",
"merge": ">=1.2.1", "merge": ">=1.2.1",

View file

@ -134,7 +134,7 @@ const Constants = {
ORDER_BY_EFFECTIVE_AMOUNT: 'effective_amount', ORDER_BY_EFFECTIVE_AMOUNT: 'effective_amount',
DEFAULT_PAGE_SIZE: 10, DEFAULT_PAGE_SIZE: 20,
ALL_PLACEHOLDER: '_all', ALL_PLACEHOLDER: '_all',

View file

@ -5,6 +5,7 @@ import {
doResolvedSearch, doResolvedSearch,
doUpdateSearchQuery, doUpdateSearchQuery,
makeSelectResolvedSearchResults, makeSelectResolvedSearchResults,
makeSelectResolvedSearchResultsLastPageReached,
makeSelectSearchUris, makeSelectSearchUris,
selectClaimSearchByQuery, selectClaimSearchByQuery,
selectIsSearching, selectIsSearching,
@ -17,20 +18,21 @@ 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 = 25;
const select = state => ({ const select = state => ({
claimSearchByQuery: selectClaimSearchByQuery(state), claimSearchByQuery: selectClaimSearchByQuery(state),
currentRoute: selectCurrentRoute(state), currentRoute: selectCurrentRoute(state),
isSearching: selectIsSearching(state), isSearching: selectIsSearching(state),
query: selectSearchValue(state), query: selectSearchValue(state),
resolvingUris: selectResolvingUris(state), resolvingUris: selectResolvingUris(state),
uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, numSearchResults)(state))(state), uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
results: makeSelectResolvedSearchResults(makeSelectQueryWithOptions(null, numSearchResults)(state))(state), results: makeSelectResolvedSearchResults(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
lastPageReached: makeSelectResolvedSearchResultsLastPageReached(
makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state),
)(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({
search: query => dispatch(doResolvedSearch(query, numSearchResults, null, false, {})), search: (query, from) => dispatch(doResolvedSearch(query, Constants.DEFAULT_PAGE_SIZE, from, false, {})),
claimSearch: options => dispatch(doClaimSearch(options)), 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)),

View file

@ -20,9 +20,12 @@ import FloatingWalletBalance from 'component/floatingWalletBalance';
import UriBar from 'component/uriBar'; import UriBar from 'component/uriBar';
import searchStyle from 'styles/search'; import searchStyle from 'styles/search';
const softLimit = 500;
class SearchPage extends React.PureComponent { class SearchPage extends React.PureComponent {
state = { state = {
currentQuery: null, currentQuery: null,
currentFrom: 0,
currentUri: null, currentUri: null,
showTagResult: false, showTagResult: false,
claimSearchRun: false, claimSearchRun: false,
@ -56,6 +59,7 @@ class SearchPage extends React.PureComponent {
const searchQuery = query || this.getSearchQuery(); const searchQuery = query || this.getSearchQuery();
if (searchQuery && searchQuery.trim().length > 0) { if (searchQuery && searchQuery.trim().length > 0) {
this.setState({ this.setState({
currentFrom: 0,
currentQuery: searchQuery, currentQuery: searchQuery,
currentUri: isURIValid(searchQuery) ? normalizeURI(searchQuery) : null, currentUri: isURIValid(searchQuery) ? normalizeURI(searchQuery) : null,
claimSearchOptions: null, claimSearchOptions: null,
@ -64,7 +68,7 @@ class SearchPage extends React.PureComponent {
resultsResolved: false, resultsResolved: false,
tagResultDisplayed: false, tagResultDisplayed: false,
}); });
search(searchQuery); search(searchQuery, 0);
} }
}); });
}; };
@ -83,12 +87,13 @@ class SearchPage extends React.PureComponent {
if (query && query.trim().length > 0 && query !== this.state.currentQuery) { if (query && query.trim().length > 0 && query !== this.state.currentQuery) {
this.setState({ this.setState({
currentFrom: 0,
currentQuery: query, currentQuery: query,
currentUri: isURIValid(query) ? normalizeURI(query) : null, currentUri: isURIValid(query) ? normalizeURI(query) : null,
resultsResolved: false, resultsResolved: false,
tagResultDisplayed: false, tagResultDisplayed: false,
}); });
search(query); search(query, 0);
} }
} }
@ -134,13 +139,15 @@ class SearchPage extends React.PureComponent {
const { search } = this.props; const { search } = this.props;
this.setState({ this.setState({
currentUri: isURIValid(keywords) ? normalizeURI(keywords) : null, currentUri: isURIValid(keywords) ? normalizeURI(keywords) : null,
currentFrom: 0,
currentQuery: keywords,
claimSearchOptions: null, claimSearchOptions: null,
claimSearchRun: false, claimSearchRun: false,
showTagResult: false, showTagResult: false,
resultsResolved: false, resultsResolved: false,
tagResultDisplayed: false, tagResultDisplayed: false,
}); });
search(keywords); search(keywords, 0);
}; };
listEmptyComponent = () => { listEmptyComponent = () => {
@ -186,6 +193,21 @@ class SearchPage extends React.PureComponent {
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TAG, key: `tagPage`, params: { tag: tag.toLowerCase() } }); navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TAG, key: `tagPage`, params: { tag: tag.toLowerCase() } });
}; };
handleVerticalEndReached = () => {
// fetch more results
const { lastPageReached, results, search, isSearching } = this.props;
if (lastPageReached || (results && results.length > softLimit)) {
return;
}
if (!isSearching) {
const from = results ? results.length : 0;
this.setState({ currentFrom: from }, () => {
search(this.state.currentQuery, from);
});
}
};
render() { render() {
const { isSearching, navigation, query, results } = this.props; const { isSearching, navigation, query, results } = this.props;
@ -193,13 +215,13 @@ class SearchPage extends React.PureComponent {
<View style={searchStyle.container}> <View style={searchStyle.container}>
<UriBar value={query} navigation={navigation} onSearchSubmitted={this.handleSearchSubmitted} /> <UriBar value={query} navigation={navigation} onSearchSubmitted={this.handleSearchSubmitted} />
{isSearching && ( {isSearching && this.state.currentFrom === 0 && (
<View style={searchStyle.busyContainer}> <View style={searchStyle.busyContainer}>
<ActivityIndicator size="large" color={Colors.NextLbryGreen} style={searchStyle.loading} /> <ActivityIndicator size="large" color={Colors.NextLbryGreen} style={searchStyle.loading} />
</View> </View>
)} )}
{!isSearching && ( {(!isSearching || this.state.currentFrom > 0) && (
<FlatList <FlatList
extraData={this.state} extraData={this.state}
style={searchStyle.scrollContainer} style={searchStyle.scrollContainer}
@ -207,8 +229,10 @@ class SearchPage extends React.PureComponent {
keyboardShouldPersistTaps={'handled'} keyboardShouldPersistTaps={'handled'}
data={results} data={results}
keyExtractor={(item, index) => item.claimId} keyExtractor={(item, index) => item.claimId}
initialNumToRender={8} initialNumToRender={10}
maxToRenderPerBatch={20} maxToRenderPerBatch={20}
onEndReached={this.handleVerticalEndReached}
onEndReachedThreshold={0.2}
removeClippedSubviews removeClippedSubviews
ListEmptyComponent={!isSearching ? this.listEmptyComponent() : null} ListEmptyComponent={!isSearching ? this.listEmptyComponent() : null}
ListHeaderComponent={this.listHeaderComponent(this.state.showTagResult, this.state.currentQuery)} ListHeaderComponent={this.listHeaderComponent(this.state.showTagResult, this.state.currentQuery)}
@ -217,6 +241,11 @@ class SearchPage extends React.PureComponent {
)} )}
kauffj commented 2020-01-09 16:36:02 +01:00 (Migrated from github.com)
Review

color typo

color typo
/> />
)} )}
{this.state.currentFrom > 0 && isSearching && (
<View style={searchStyle.moreLoading}>
<ActivityIndicator size="small" color={Colors.NextLbryGreen} />
</View>
)}
<FloatingWalletBalance navigation={navigation} /> <FloatingWalletBalance navigation={navigation} />
</View> </View>
); );

View file

@ -80,6 +80,12 @@ const searchStyle = StyleSheet.create({
loading: { loading: {
position: 'absolute', position: 'absolute',
}, },
moreLoading: {
width: '100%',
height: 48,
alignItems: 'center',
justifyContent: 'center',
},
}); });
export default searchStyle; export default searchStyle;