Tech Debt: selectors/search improvements #6358
1 changed files with 74 additions and 49 deletions
|
@ -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;
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue