Tech Debt: selectors/search improvements #6358

Closed
DispatchCommit wants to merge 1 commit from tech-debt/selectors-search into master

View file

@ -1,6 +1,4 @@
// @flow // @flow
import { getSearchQueryString } from 'util/query-params';
import { selectShowMatureContent } from 'redux/selectors/settings';
import { import {
parseURI, parseURI,
makeSelectClaimForUri, makeSelectClaimForUri,
@ -10,28 +8,68 @@ import {
makeSelectPendingClaimForUri, makeSelectPendingClaimForUri,
makeSelectIsUriResolving, makeSelectIsUriResolving,
} from 'lbry-redux'; } from 'lbry-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { getSearchQueryString } from 'util/query-params';
import { createNormalizedSearchKey } from 'util/search'; import { createNormalizedSearchKey } from 'util/search';
import { selectShowMatureContent } from 'redux/selectors/settings';
type State = { search: SearchState }; /**
* Search State related type declarations
*/
type CustomOptions = {
isBackgroundSearch?: boolean,
size?: number,
from?: number,
related_to?: string,
nsfw?: boolean,
};
export const selectState = (state: State): SearchState => state.search; type UrisByQuery = {
[string]: Array<string>,
};
export const selectSearchValue: (state: State) => string = createSelector(selectState, (state) => state.searchQuery); type HasReachedMaxResultsLength = {
[string]: boolean,
};
export const selectSearchOptions: (state: State) => SearchOptions = createSelector( type SearchState = {
selectState, options: CustomOptions,
(state) => state.options urisByQuery: UrisByQuery,
); hasReachedMaxResultsLength: HasReachedMaxResultsLength,
searching: boolean,
};
export const selectIsSearching: (state: State) => boolean = createSelector(selectState, (state) => state.searching); type State = {
search: SearchState,
};
export const selectSearchUrisByQuery: (state: State) => { [string]: Array<string> } = createSelector( /**
* Gets search state from redux state
*/
type iSelectSearchState = (state: State) => SearchState;
export const selectState: iSelectSearchState = (state) => state.search;
/**
* Custom Selectors
*/
type iSelectSearchValue = (state: State) => string;
export const selectSearchValue: iSelectSearchValue = createSelector(selectState, (state) => state.searchQuery);
type iSelectSearchOptions = (state: State) => SearchOptions;
export const selectSearchOptions: iSelectSearchOptions = createSelector(selectState, (state) => state.options);
type iSelectIsSearching = (state: State) => boolean;
export const selectIsSearching: iSelectIsSearching = createSelector(selectState, (state) => state.searching);
type iSelectSearchUrisByQuery = (state: State) => { [string]: Array<string> };
export const selectSearchUrisByQuery: iSelectSearchUrisByQuery = createSelector(
selectState, selectState,
(state) => state.urisByQuery (state) => state.urisByQuery
); );
export const selectHasReachedMaxResultsLength: (state: State) => { [boolean]: Array<boolean> } = createSelector( type iSelectHasReachedMaxResultsLength = (state: State) => { [boolean]: Array<boolean> };
export const selectHasReachedMaxResultsLength: iSelectHasReachedMaxResultsLength = createSelector(
selectState, selectState,
(state) => state.hasReachedMaxResultsLength (state) => state.hasReachedMaxResultsLength
); );
@ -58,22 +96,12 @@ export const makeSelectHasReachedMaxResultsLength = (query: string): ((state: St
}); });
// Creates a query string based on the state in the search reducer // Creates a query string based on the state in the search reducer
// Can be overrided by passing in custom sizes/from values for other areas pagination // Can be overridden by passing in custom sizes/from values for other areas pagination
type CustomOptions = {
isBackgroundSearch?: boolean,
size?: number,
from?: number,
related_to?: string,
nsfw?: boolean,
};
export const makeSelectQueryWithOptions = (customQuery: ?string, options: CustomOptions) => export const makeSelectQueryWithOptions = (customQuery: ?string, options: CustomOptions) =>
createSelector(selectSearchValue, selectSearchOptions, (query, defaultOptions) => { createSelector(selectSearchValue, selectSearchOptions, (query, defaultOptions) => {
const searchOptions = { ...defaultOptions, ...options }; const searchOptions: CustomOptions = { ...defaultOptions, ...options };
const queryString = getSearchQueryString(customQuery || query, searchOptions); return getSearchQueryString(customQuery || query, searchOptions);
return queryString;
}); });
export const makeSelectRecommendedContentForUri = (uri: string) => export const makeSelectRecommendedContentForUri = (uri: string) =>
@ -85,28 +113,27 @@ export const makeSelectRecommendedContentForUri = (uri: string) =>
let recommendedContent; let recommendedContent;
if (claim) { if (claim) {
// always grab full URL - this can change once search returns canonical // always grab full URL - this can change once search returns canonical
const currentUri = buildURI({ streamClaimId: claim.claim_id, streamName: claim.name }); const currentUri = buildURI({
streamClaimId: claim.claim_id,
streamName: claim.name,
});
const { title } = claim.value; const { title } = claim.value;
if (!title) { if (!title) return;
return;
}
const options: { const options: CustomOptions = {
related_to?: string, related_to: claim.claim_id,
nsfw?: boolean, isBackgroundSearch: true,
isBackgroundSearch?: boolean, nsfw: isMature,
} = { related_to: claim.claim_id, isBackgroundSearch: true }; };
options['nsfw'] = isMature;
const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options); const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options);
const normalizedSearchQuery = createNormalizedSearchKey(searchQuery); const normalizedSearchQuery = createNormalizedSearchKey(searchQuery);
let searchUris = searchUrisByQuery[normalizedSearchQuery]; let searchUris = searchUrisByQuery[normalizedSearchQuery];
if (searchUris) { if (searchUris) {
searchUris = searchUris.filter((searchUri) => searchUri !== currentUri); recommendedContent = searchUris.filter((searchUri) => searchUri !== currentUri);
recommendedContent = searchUris;
} }
} }
return recommendedContent; return recommendedContent;
@ -115,7 +142,6 @@ export const makeSelectRecommendedContentForUri = (uri: string) =>
export const makeSelectWinningUriForQuery = (query: string) => { export const makeSelectWinningUriForQuery = (query: string) => {
const uriFromQuery = `lbry://${query}`; const uriFromQuery = `lbry://${query}`;
let channelUriFromQuery; let channelUriFromQuery;
try { try {
const { isChannel } = parseURI(uriFromQuery); const { isChannel } = parseURI(uriFromQuery);
@ -134,11 +160,13 @@ export const makeSelectWinningUriForQuery = (query: string) => {
const claim2Mature = claim2 && isClaimNsfw(claim2); const claim2Mature = claim2 && isClaimNsfw(claim2);
let pendingAmount = pendingClaim && pendingClaim.amount; let pendingAmount = pendingClaim && pendingClaim.amount;
if (!claim1 && !claim2) { if (!claim1 && !claim2) return undefined;
return undefined;
} else if (!claim1 && claim2) { if (!claim1 && claim2) {
return matureEnabled ? claim2.canonical_url : claim2Mature ? undefined : claim2.canonical_url; return matureEnabled ? claim2.canonical_url : claim2Mature ? undefined : claim2.canonical_url;
} else if (claim1 && !claim2) { }
if (claim1 && !claim2) {
return matureEnabled return matureEnabled
? claim1.repost_url || claim1.canonical_url ? claim1.repost_url || claim1.canonical_url
: claim1Mature : claim1Mature
@ -146,8 +174,8 @@ export const makeSelectWinningUriForQuery = (query: string) => {
: claim1.repost_url || claim1.canonical_url; : claim1.repost_url || claim1.canonical_url;
} }
const effectiveAmount1 = claim1 && (claim1.repost_bid_amount || claim1.meta.effective_amount);
// claim2 will never have a repost_bid_amount because reposts never start with "@" // claim2 will never have a repost_bid_amount because reposts never start with "@"
const effectiveAmount1 = claim1 && (claim1.repost_bid_amount || claim1.meta.effective_amount);
const effectiveAmount2 = claim2 && claim2.meta.effective_amount; const effectiveAmount2 = claim2 && claim2.meta.effective_amount;
if (!matureEnabled) { if (!matureEnabled) {
@ -164,6 +192,7 @@ export const makeSelectWinningUriForQuery = (query: string) => {
Number(effectiveAmount1) > Number(effectiveAmount2) Number(effectiveAmount1) > Number(effectiveAmount2)
? claim1.repost_url || claim1.canonical_url ? claim1.repost_url || claim1.canonical_url
: claim2.canonical_url; : claim2.canonical_url;
if (pendingAmount && pendingAmount > effectiveAmount1 && pendingAmount > effectiveAmount2) { if (pendingAmount && pendingAmount > effectiveAmount1 && pendingAmount > effectiveAmount2) {
return pendingAmount.permanent_url; return pendingAmount.permanent_url;
} else { } else {
@ -178,16 +207,12 @@ export const makeSelectIsResolvingWinningUri = (query: string = '') => {
let channelUriFromQuery; let channelUriFromQuery;
try { try {
const { isChannel } = parseURI(uriFromQuery); const { isChannel } = parseURI(uriFromQuery);
if (!isChannel) { if (!isChannel) channelUriFromQuery = `lbry://@${query}`;
channelUriFromQuery = `lbry://@${query}`;
}
} catch (e) {} } catch (e) {}
return createSelector( return createSelector(
makeSelectIsUriResolving(uriFromQuery), makeSelectIsUriResolving(uriFromQuery),
channelUriFromQuery ? makeSelectIsUriResolving(channelUriFromQuery) : () => {}, channelUriFromQuery ? makeSelectIsUriResolving(channelUriFromQuery) : () => {},
(claim1IsResolving, claim2IsResolving) => { (claim1IsResolving, claim2IsResolving) => claim1IsResolving || claim2IsResolving
return claim1IsResolving || claim2IsResolving;
}
); );
}; };