support for multiple pages of resolved search results

This commit is contained in:
Akinwale Ariwodola 2020-01-08 09:09:45 +01:00
parent e8f29f1c47
commit c910cd2b80
7 changed files with 96 additions and 20 deletions
dist
flow-typed
src
index.js
redux
actions
reducers
selectors

46
dist/bundle.es.js vendored
View file

@ -1338,10 +1338,16 @@ reselect.createSelector(selectSearchUrisByQuery, byQuery => byQuery[query ? quer
const selectResolvedSearchResultsByQuery = reselect.createSelector(selectState, state => state.resolvedResultsByQuery); const selectResolvedSearchResultsByQuery = reselect.createSelector(selectState, state => state.resolvedResultsByQuery);
const selectResolvedSearchResultsByQueryLastPageReached = reselect.createSelector(selectState, state => state.resolvedResultsByQueryLastPageReached);
const makeSelectResolvedSearchResults = query => const makeSelectResolvedSearchResults = query =>
// replace statement below is kind of ugly, and repeated in doSearch action // replace statement below is kind of ugly, and repeated in doSearch action
reselect.createSelector(selectResolvedSearchResultsByQuery, byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]); reselect.createSelector(selectResolvedSearchResultsByQuery, byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]);
const makeSelectResolvedSearchResultsLastPageReached = query =>
// replace statement below is kind of ugly, and repeated in doSearch action
reselect.createSelector(selectResolvedSearchResultsByQueryLastPageReached, byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]);
const selectSearchBarFocused = reselect.createSelector(selectState, state => state.focused); const selectSearchBarFocused = reselect.createSelector(selectState, state => state.focused);
const selectSearchSuggestions = reselect.createSelector(selectSearchValue, selectSuggestions, (query, suggestions) => { const selectSearchSuggestions = reselect.createSelector(selectSearchValue, selectSuggestions, (query, suggestions) => {
@ -4049,11 +4055,15 @@ from, isBackgroundSearch = false, options = {}) => (dispatch, getState) => {
const state = getState(); const state = getState();
let queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch, options)(state); let queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch, options)(state);
// make from null so that we can maintain a reference to the same query for multiple pages and simply append the found results
let queryWithoutFrom = makeSelectQueryWithOptions(query, size, null, isBackgroundSearch, options)(state);
// If we have already searched for something, we don't need to do anything // If we have already searched for something, we don't need to do anything
const resultsForQuery = makeSelectResolvedSearchResults(queryWithOptions)(state); // TODO: Tweak this check for multiple page results
if (resultsForQuery && !!resultsForQuery.length) { /* const resultsForQuery = makeSelectResolvedSearchResults(queryWithOptions)(state);
if (resultsForQuery && resultsForQuery.length && resultsForQuery.length > (from * size)) {
return; return;
} } */
dispatch({ dispatch({
type: RESOLVED_SEARCH_START type: RESOLVED_SEARCH_START
@ -4075,8 +4085,10 @@ from, isBackgroundSearch = false, options = {}) => (dispatch, getState) => {
dispatch({ dispatch({
type: RESOLVED_SEARCH_SUCCESS, type: RESOLVED_SEARCH_SUCCESS,
data: { data: {
query: queryWithOptions, query: queryWithoutFrom,
results results,
pageSize: size,
append: parseInt(from, 10) > parseInt(size, 10) - 1
} }
}); });
}).catch(e => { }).catch(e => {
@ -5091,7 +5103,8 @@ const defaultState$7 = {
}, },
suggestions: {}, suggestions: {},
urisByQuery: {}, urisByQuery: {},
resolvedResultsByQuery: {} resolvedResultsByQuery: {},
resolvedResultsByQueryLastPageReached: {}
}; };
const searchReducer = handleActions({ const searchReducer = handleActions({
@ -5115,13 +5128,24 @@ const searchReducer = handleActions({
searching: true searching: true
}), }),
[RESOLVED_SEARCH_SUCCESS]: (state, action) => { [RESOLVED_SEARCH_SUCCESS]: (state, action) => {
const { query, results } = action.data; const resolvedResultsByQuery = Object.assign({}, state.resolvedResultsByQuery);
const resolvedResultsByQueryLastPageReached = Object.assign({}, state.resolvedResultsByQueryLastPageReached);
const { append, query, results, pageSize } = action.data;
if (append) {
// todo: check for duplicates when concatenating?
resolvedResultsByQuery[query] = resolvedResultsByQuery[query] && resolvedResultsByQuery[query].length ? resolvedResultsByQuery[query].concat(results) : results;
} else {
resolvedResultsByQuery[query] = results;
}
// the returned number of urls is less than the page size, so we're on the last page
resolvedResultsByQueryLastPageReached[query] = results.length < pageSize;
return _extends$c({}, state, { return _extends$c({}, state, {
searching: false, searching: false,
resolvedResultsByQuery: Object.assign({}, state.resolvedResultsByQuery, { resolvedResultsByQuery,
[query]: results resolvedResultsByQueryLastPageReached
})
}); });
}, },
@ -5768,6 +5792,7 @@ exports.makeSelectQueryWithOptions = makeSelectQueryWithOptions;
exports.makeSelectRecommendedContentForUri = makeSelectRecommendedContentForUri; exports.makeSelectRecommendedContentForUri = makeSelectRecommendedContentForUri;
exports.makeSelectResolvedRecommendedContentForUri = makeSelectResolvedRecommendedContentForUri; exports.makeSelectResolvedRecommendedContentForUri = makeSelectResolvedRecommendedContentForUri;
exports.makeSelectResolvedSearchResults = makeSelectResolvedSearchResults; exports.makeSelectResolvedSearchResults = makeSelectResolvedSearchResults;
exports.makeSelectResolvedSearchResultsLastPageReached = makeSelectResolvedSearchResultsLastPageReached;
exports.makeSelectSearchDownloadUrlsCount = makeSelectSearchDownloadUrlsCount; exports.makeSelectSearchDownloadUrlsCount = makeSelectSearchDownloadUrlsCount;
exports.makeSelectSearchDownloadUrlsForPage = makeSelectSearchDownloadUrlsForPage; exports.makeSelectSearchDownloadUrlsForPage = makeSelectSearchDownloadUrlsForPage;
exports.makeSelectSearchUris = makeSelectSearchUris; exports.makeSelectSearchUris = makeSelectSearchUris;
@ -5861,6 +5886,7 @@ exports.selectReceiveAddress = selectReceiveAddress;
exports.selectRecentTransactions = selectRecentTransactions; exports.selectRecentTransactions = selectRecentTransactions;
exports.selectReservedBalance = selectReservedBalance; exports.selectReservedBalance = selectReservedBalance;
exports.selectResolvedSearchResultsByQuery = selectResolvedSearchResultsByQuery; exports.selectResolvedSearchResultsByQuery = selectResolvedSearchResultsByQuery;
exports.selectResolvedSearchResultsByQueryLastPageReached = selectResolvedSearchResultsByQueryLastPageReached;
exports.selectResolvingUris = selectResolvingUris; exports.selectResolvingUris = selectResolvingUris;
exports.selectSearchBarFocused = selectSearchBarFocused; exports.selectSearchBarFocused = selectSearchBarFocused;
exports.selectSearchOptions = selectSearchOptions; exports.selectSearchOptions = selectSearchOptions;

View file

@ -29,6 +29,7 @@ declare type SearchState = {
suggestions: { [string]: Array<SearchSuggestion> }, suggestions: { [string]: Array<SearchSuggestion> },
urisByQuery: {}, urisByQuery: {},
resolvedResultsByQuery: {}, resolvedResultsByQuery: {},
resolvedResultsByQueryLastPageReached: {},
}; };
declare type SearchSuccess = { declare type SearchSuccess = {
@ -75,7 +76,9 @@ declare type ResolvedSearchResult = {
declare type ResolvedSearchSuccess = { declare type ResolvedSearchSuccess = {
type: ACTIONS.RESOLVED_SEARCH_SUCCESS, type: ACTIONS.RESOLVED_SEARCH_SUCCESS,
data: { data: {
query: string, append: boolean,
pageSize: number,
results: Array<ResolvedSearchResult>, results: Array<ResolvedSearchResult>,
query: string,
}, },
}; };

View file

@ -29,6 +29,7 @@ declare type SearchState = {
suggestions: { [string]: Array<SearchSuggestion> }, suggestions: { [string]: Array<SearchSuggestion> },
urisByQuery: {}, urisByQuery: {},
resolvedResultsByQuery: {}, resolvedResultsByQuery: {},
resolvedResultsByQueryLastPageReached: {},
}; };
declare type SearchSuccess = { declare type SearchSuccess = {
@ -75,7 +76,9 @@ declare type ResolvedSearchResult = {
declare type ResolvedSearchSuccess = { declare type ResolvedSearchSuccess = {
type: ACTIONS.RESOLVED_SEARCH_SUCCESS, type: ACTIONS.RESOLVED_SEARCH_SUCCESS,
data: { data: {
query: string, append: boolean,
pageSize: number,
results: Array<ResolvedSearchResult>, results: Array<ResolvedSearchResult>,
query: string,
}, },
}; };

View file

@ -268,10 +268,12 @@ export { selectSearchState };
export { export {
makeSelectSearchUris, makeSelectSearchUris,
makeSelectResolvedSearchResults, makeSelectResolvedSearchResults,
makeSelectResolvedSearchResultsLastPageReached,
selectSearchValue, selectSearchValue,
selectSearchOptions, selectSearchOptions,
selectIsSearching, selectIsSearching,
selectResolvedSearchResultsByQuery, selectResolvedSearchResultsByQuery,
selectResolvedSearchResultsByQueryLastPageReached,
selectSearchUrisByQuery, selectSearchUrisByQuery,
selectSearchBarFocused, selectSearchBarFocused,
selectSearchSuggestions, selectSearchSuggestions,

View file

@ -183,11 +183,17 @@ export const doResolvedSearch = (
state state
); );
// make from null so that we can maintain a reference to the same query for multiple pages and simply append the found results
let queryWithoutFrom = makeSelectQueryWithOptions(query, size, null, isBackgroundSearch, options)(
state
);
// If we have already searched for something, we don't need to do anything // If we have already searched for something, we don't need to do anything
const resultsForQuery = makeSelectResolvedSearchResults(queryWithOptions)(state); // TODO: Tweak this check for multiple page results
if (resultsForQuery && !!resultsForQuery.length) { /* const resultsForQuery = makeSelectResolvedSearchResults(queryWithOptions)(state);
if (resultsForQuery && resultsForQuery.length && resultsForQuery.length > (from * size)) {
return; return;
} } */
dispatch({ dispatch({
type: ACTIONS.RESOLVED_SEARCH_START, type: ACTIONS.RESOLVED_SEARCH_START,
@ -211,8 +217,10 @@ export const doResolvedSearch = (
dispatch({ dispatch({
type: ACTIONS.RESOLVED_SEARCH_SUCCESS, type: ACTIONS.RESOLVED_SEARCH_SUCCESS,
data: { data: {
query: queryWithOptions, query: queryWithoutFrom,
results, results,
pageSize: size,
append: parseInt(from, 10) > parseInt(size, 10) - 1,
}, },
}); });
}) })

View file

@ -19,6 +19,7 @@ const defaultState = {
suggestions: {}, suggestions: {},
urisByQuery: {}, urisByQuery: {},
resolvedResultsByQuery: {}, resolvedResultsByQuery: {},
resolvedResultsByQueryLastPageReached: {},
}; };
export const searchReducer = handleActions( export const searchReducer = handleActions(
@ -50,14 +51,31 @@ export const searchReducer = handleActions(
state: SearchState, state: SearchState,
action: ResolvedSearchSuccess action: ResolvedSearchSuccess
): SearchState => { ): SearchState => {
const { query, results } = action.data; const resolvedResultsByQuery = Object.assign({}, state.resolvedResultsByQuery);
const resolvedResultsByQueryLastPageReached = Object.assign(
{},
state.resolvedResultsByQueryLastPageReached
);
const { append, query, results, pageSize } = action.data;
if (append) {
// todo: check for duplicates when concatenating?
resolvedResultsByQuery[query] =
resolvedResultsByQuery[query] && resolvedResultsByQuery[query].length
? resolvedResultsByQuery[query].concat(results)
: results;
} else {
resolvedResultsByQuery[query] = results;
}
// the returned number of urls is less than the page size, so we're on the last page
resolvedResultsByQueryLastPageReached[query] = results.length < pageSize;
return { return {
...state, ...state,
searching: false, searching: false,
resolvedResultsByQuery: Object.assign({}, state.resolvedResultsByQuery, { resolvedResultsByQuery,
[query]: results, resolvedResultsByQueryLastPageReached,
}),
}; };
}, },

View file

@ -51,6 +51,13 @@ export const selectResolvedSearchResultsByQuery: (
state => state.resolvedResultsByQuery state => state.resolvedResultsByQuery
); );
export const selectResolvedSearchResultsByQueryLastPageReached: (
state: State
) => { [string]: Array<boolean> } = createSelector(
selectState,
state => state.resolvedResultsByQueryLastPageReached
);
export const makeSelectResolvedSearchResults = ( export const makeSelectResolvedSearchResults = (
query: string query: string
): ((state: State) => Array<ResolvedSearchResult>) => ): ((state: State) => Array<ResolvedSearchResult>) =>
@ -60,6 +67,15 @@ export const makeSelectResolvedSearchResults = (
byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query] byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]
); );
export const makeSelectResolvedSearchResultsLastPageReached = (
query: string
): ((state: State) => boolean) =>
// replace statement below is kind of ugly, and repeated in doSearch action
createSelector(
selectResolvedSearchResultsByQueryLastPageReached,
byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]
);
export const selectSearchBarFocused: boolean = createSelector( export const selectSearchBarFocused: boolean = createSelector(
selectState, selectState,
state => state.focused state => state.focused