allow scrolling for displaying more search results #110
6 changed files with 52 additions and 15 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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',
|
||||||
|
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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 {
|
||||||
)}
|
)}
|
||||||
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{this.state.currentFrom > 0 && isSearching && (
|
||||||
|
<View style={searchStyle.moreLoading}>
|
||||||
|
<ActivityIndicator size="small" color={Colors.NextLbryGreen} />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
<FloatingWalletBalance navigation={navigation} />
|
<FloatingWalletBalance navigation={navigation} />
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue
color typo