Optimize selectClaimIsMine (#7370)

Frequently used; top in perf profile

Most of the time, you already have the claim object in the current context. `selectClaimIsMineForUri` will retrieve the claim again, which is wasteful, even if it is memoized (looking up the cache still takes time).

Break apart the logic and added the alternative `selectClaimIsMine` for faster lookup.

Co-authored-by: infinite-persistence <inf.persistence@gmail.com>
This commit is contained in:
jessopb 2021-12-31 12:52:26 -05:00 committed by GitHub
parent 4fc050fdad
commit a3398843c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 514 additions and 424 deletions

View file

@ -50,9 +50,12 @@ export {
export { selectFilteredOutpoints, selectFilteredOutpointMap } from './redux/selectors/filtered'; export { selectFilteredOutpoints, selectFilteredOutpointMap } from './redux/selectors/filtered';
export { export {
selectViewCount, selectViewCount,
makeSelectViewCountForUri, selectViewCountForUri,
makeSelectSubCountForUri, // makeSelectViewCountForUri, // deprecated
selectSubCountForUri,
// makeSelectSubCountForUri, // deprecated
} from './redux/selectors/stats'; } from './redux/selectors/stats';
export { selectBanStateForUri } from './redux/selectors/ban';
export { export {
selectHasSyncedWallet, selectHasSyncedWallet,
selectSyncData, selectSyncData,

View file

@ -0,0 +1,68 @@
// @flow
// TODO: This should be in 'redux/selectors/claim.js'. Temporarily putting it
// here to get past importing issues with 'lbryinc', which the real fix might
// involve moving it from 'extras' to 'ui' (big change).
import { createCachedSelector } from 're-reselect';
import { selectClaimForUri } from 'redux/selectors/claims';
import { selectMutedChannels } from 'redux/selectors/blocked';
import { selectModerationBlockList } from 'redux/selectors/comments';
import { selectBlacklistedOutpointMap, selectFilteredOutpointMap } from 'lbryinc';
import { getChannelFromClaim } from 'util/claim';
import { isURIEqual } from 'util/lbryURI';
export const selectBanStateForUri = createCachedSelector(
selectClaimForUri,
selectBlacklistedOutpointMap,
selectFilteredOutpointMap,
selectMutedChannels,
selectModerationBlockList,
(claim, blackListedOutpointMap, filteredOutpointMap, mutedChannelUris, personalBlocklist) => {
const banState = {};
if (!claim) {
return banState;
}
const channelClaim = getChannelFromClaim(claim);
// This will be replaced once blocking is done at the wallet server level.
if (blackListedOutpointMap) {
if (
(channelClaim && blackListedOutpointMap[`${channelClaim.txid}:${channelClaim.nout}`]) ||
blackListedOutpointMap[`${claim.txid}:${claim.nout}`]
) {
banState['blacklisted'] = true;
}
}
// We're checking to see if the stream outpoint or signing channel outpoint
// is in the filter list.
if (filteredOutpointMap) {
if (
(channelClaim && filteredOutpointMap[`${channelClaim.txid}:${channelClaim.nout}`]) ||
filteredOutpointMap[`${claim.txid}:${claim.nout}`]
) {
banState['filtered'] = true;
}
}
// block stream claims
// block channel claims if we can't control for them in claim search
if (mutedChannelUris.length && channelClaim) {
if (mutedChannelUris.some((blockedUri) => isURIEqual(blockedUri, channelClaim.permanent_url))) {
banState['muted'] = true;
}
}
// Commentron blocklist
if (personalBlocklist.length && channelClaim) {
if (personalBlocklist.some((blockedUri) => isURIEqual(blockedUri, channelClaim.permanent_url))) {
banState['blocked'] = true;
}
}
return banState;
}
)((state, uri) => String(uri));

View file

@ -1,20 +1,20 @@
// @flow
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimIdForUri } from 'redux/selectors/claims';
type State = { claims: any };
const selectState = state => state.stats || {}; const selectState = state => state.stats || {};
export const selectViewCount = createSelector(selectState, state => state.viewCountById); export const selectViewCount = createSelector(selectState, state => state.viewCountById);
export const selectSubCount = createSelector(selectState, state => state.subCountById); export const selectSubCount = createSelector(selectState, state => state.subCountById);
export const makeSelectViewCountForUri = uri => export const selectViewCountForUri = (state: State, uri: string) => {
createSelector( const claimId = selectClaimIdForUri(state, uri);
makeSelectClaimForUri(uri), const viewCountById = selectViewCount(state);
selectViewCount, return claimId ? viewCountById[claimId] || 0 : 0;
(claim, viewCountById) => (claim ? viewCountById[claim.claim_id] || 0 : 0) };
);
export const makeSelectSubCountForUri = uri => export const selectSubCountForUri = (state: State, uri: string) => {
createSelector( const claimId = selectClaimIdForUri(state, uri);
makeSelectClaimForUri(uri), const subCountById = selectSubCount(state);
selectSubCount, return claimId ? subCountById[claimId] || 0 : 0;
(claim, subCountById) => (claim ? subCountById[claim.claim_id] || 0 : 0) };
);

View file

@ -2235,5 +2235,8 @@
"Network Data Hosting allows the p2p network to store blobs unrelated to your browsing.": "Network Data Hosting allows the p2p network to store blobs unrelated to your browsing.", "Network Data Hosting allows the p2p network to store blobs unrelated to your browsing.": "Network Data Hosting allows the p2p network to store blobs unrelated to your browsing.",
"Content: Limit (GB)": "Content: Limit (GB)", "Content: Limit (GB)": "Content: Limit (GB)",
"Network: Allow (GB)": "Network: Allow (GB)", "Network: Allow (GB)": "Network: Allow (GB)",
"Failed to view lbry://@Destiny#6/destiny-crashes-conservative-panel-w#a, please try again. If this problem persists, visit https://lbry.com/faq/support for support.": "Failed to view lbry://@Destiny#6/destiny-crashes-conservative-panel-w#a, please try again. If this problem persists, visit https://lbry.com/faq/support for support.",
"A channel is required to repost on LBRY": "A channel is required to repost on LBRY",
"Failed to view lbry://@gatogalactico#9/gato-galactico-e-as-estrelas-ninja-dos#1, please try again. If this problem persists, visit https://lbry.com/faq/support for support.": "Failed to view lbry://@gatogalactico#9/gato-galactico-e-as-estrelas-ninja-dos#1, please try again. If this problem persists, visit https://lbry.com/faq/support for support.",
"--end--": "--end--" "--end--": "--end--"
} }

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimIdForUri } from 'redux/selectors/claims'; import { selectClaimIdForUri } from 'redux/selectors/claims';
import { import {
doCommentModUnBlock, doCommentModUnBlock,
doCommentModBlock, doCommentModBlock,
@ -43,7 +43,7 @@ const select = (state, props) => {
isBlocked, isBlocked,
isToggling, isToggling,
isBlockingOrUnBlocking: makeSelectUriIsBlockingOrUnBlocking(props.uri)(state), isBlockingOrUnBlocking: makeSelectUriIsBlockingOrUnBlocking(props.uri)(state),
creatorId: makeSelectClaimIdForUri(props.creatorUri)(state), creatorId: selectClaimIdForUri(state, props.creatorUri),
}; };
}; };

View file

@ -3,9 +3,9 @@ import { PAGE_SIZE } from 'constants/claim';
import { import {
makeSelectClaimsInChannelForPage, makeSelectClaimsInChannelForPage,
makeSelectFetchingChannelClaims, makeSelectFetchingChannelClaims,
makeSelectClaimIsMine, selectClaimIsMine,
makeSelectTotalPagesInChannelSearch, makeSelectTotalPagesInChannelSearch,
makeSelectClaimForUri, selectClaimForUri,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { doResolveUris } from 'redux/actions/claims'; import { doResolveUris } from 'redux/actions/claims';
import * as SETTINGS from 'constants/settings'; import * as SETTINGS from 'constants/settings';
@ -20,13 +20,15 @@ const select = (state, props) => {
const { search } = props.location; const { search } = props.location;
const urlParams = new URLSearchParams(search); const urlParams = new URLSearchParams(search);
const page = urlParams.get('page') || 0; const page = urlParams.get('page') || 0;
const claim = props.uri && selectClaimForUri(state, props.uri);
return { return {
pageOfClaimsInChannel: makeSelectClaimsInChannelForPage(props.uri, page)(state), pageOfClaimsInChannel: makeSelectClaimsInChannelForPage(props.uri, page)(state),
fetching: makeSelectFetchingChannelClaims(props.uri)(state), fetching: makeSelectFetchingChannelClaims(props.uri)(state),
totalPages: makeSelectTotalPagesInChannelSearch(props.uri, PAGE_SIZE)(state), totalPages: makeSelectTotalPagesInChannelSearch(props.uri, PAGE_SIZE)(state),
channelIsMine: makeSelectClaimIsMine(props.uri)(state), channelIsMine: selectClaimIsMine(state, claim),
channelIsBlocked: makeSelectChannelIsMuted(props.uri)(state), channelIsBlocked: makeSelectChannelIsMuted(props.uri)(state),
claim: props.uri && makeSelectClaimForUri(props.uri)(state), claim,
isAuthenticated: selectUserVerifiedEmail(state), isAuthenticated: selectUserVerifiedEmail(state),
showMature: selectShowMatureContent(state), showMature: selectShowMatureContent(state),
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state), tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),

View file

@ -1,15 +1,15 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectStakedLevelForChannelUri, selectTotalStakedAmountForChannelUri,
makeSelectTotalStakedAmountForChannelUri, selectStakedLevelForChannelUri,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import ChannelStakedIndicator from './view'; import ChannelStakedIndicator from './view';
const select = (state, props) => ({ const select = (state, props) => ({
channelClaim: makeSelectClaimForUri(props.uri)(state), channelClaim: makeSelectClaimForUri(props.uri)(state),
amount: makeSelectTotalStakedAmountForChannelUri(props.uri)(state), amount: selectTotalStakedAmountForChannelUri(state, props.uri),
level: makeSelectStakedLevelForChannelUri(props.uri)(state), level: selectStakedLevelForChannelUri(state, props.uri),
}); });
export default connect(select)(ChannelStakedIndicator); export default connect(select)(ChannelStakedIndicator);

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimForUri, makeSelectClaimIsMine } from 'redux/selectors/claims'; import { selectClaimForUri, selectClaimIsMine } from 'redux/selectors/claims';
import { doCollectionEdit, doFetchItemsInCollection } from 'redux/actions/collections'; import { doCollectionEdit, doFetchItemsInCollection } from 'redux/actions/collections';
import { doPrepareEdit } from 'redux/actions/publish'; import { doPrepareEdit } from 'redux/actions/publish';
import { import {
@ -34,7 +34,7 @@ import ClaimPreview from './view';
import fs from 'fs'; import fs from 'fs';
const select = (state, props) => { const select = (state, props) => {
const claim = makeSelectClaimForUri(props.uri, false)(state); const claim = selectClaimForUri(state, props.uri, false); // @KP test no repost!
const collectionId = props.collectionId; const collectionId = props.collectionId;
const repostedClaim = claim && claim.reposted_claim; const repostedClaim = claim && claim.reposted_claim;
const contentClaim = repostedClaim || claim; const contentClaim = repostedClaim || claim;
@ -51,7 +51,7 @@ const select = (state, props) => {
contentClaim, contentClaim,
contentSigningChannel, contentSigningChannel,
contentChannelUri, contentChannelUri,
claimIsMine: makeSelectClaimIsMine(props.uri)(state), claimIsMine: selectClaimIsMine(state, claim),
hasClaimInWatchLater: makeSelectCollectionForIdHasClaimUrl( hasClaimInWatchLater: makeSelectCollectionForIdHasClaimUrl(
COLLECTIONS_CONSTS.WATCH_LATER_ID, COLLECTIONS_CONSTS.WATCH_LATER_ID,
contentPermanentUri contentPermanentUri
@ -92,7 +92,7 @@ const perform = (dispatch) => ({
doChannelUnmute: (channelUri) => dispatch(doChannelUnmute(channelUri)), doChannelUnmute: (channelUri) => dispatch(doChannelUnmute(channelUri)),
doCommentModBlock: (channelUri) => dispatch(doCommentModBlock(channelUri)), doCommentModBlock: (channelUri) => dispatch(doCommentModBlock(channelUri)),
doCommentModUnBlock: (channelUri) => dispatch(doCommentModUnBlock(channelUri)), doCommentModUnBlock: (channelUri) => dispatch(doCommentModUnBlock(channelUri)),
doCommentModBlockAsAdmin: (commenterUri, blockerId) => dispatch(doCommentModBlockAsAdmin(commenterUri, blockerId)), doCommentModBlockAsAdmin: (a, b, c) => dispatch(doCommentModBlockAsAdmin(a, b, c)),
doCommentModUnBlockAsAdmin: (commenterUri, blockerId) => doCommentModUnBlockAsAdmin: (commenterUri, blockerId) =>
dispatch(doCommentModUnBlockAsAdmin(commenterUri, blockerId)), dispatch(doCommentModUnBlockAsAdmin(commenterUri, blockerId)),
doChannelSubscribe: (subscription) => dispatch(doChannelSubscribe(subscription)), doChannelSubscribe: (subscription) => dispatch(doChannelSubscribe(subscription)),

View file

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import { import {
selectClaimForUri, selectClaimForUri,
makeSelectIsUriResolving, makeSelectIsUriResolving,
makeSelectClaimIsMine, selectClaimIsMine,
makeSelectClaimIsPending, makeSelectClaimIsPending,
makeSelectClaimIsNsfw, makeSelectClaimIsNsfw,
makeSelectReflectingClaimForUri, makeSelectReflectingClaimForUri,
@ -20,12 +20,10 @@ import {
import { doResolveUri } from 'redux/actions/claims'; import { doResolveUri } from 'redux/actions/claims';
import { doCollectionEdit } from 'redux/actions/collections'; import { doCollectionEdit } from 'redux/actions/collections';
import { doFileGet } from 'redux/actions/file'; import { doFileGet } from 'redux/actions/file';
import { selectMutedChannels, makeSelectChannelIsMuted } from 'redux/selectors/blocked'; import { selectBanStateForUri } from 'lbryinc';
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
import { selectShowMatureContent } from 'redux/selectors/settings'; import { selectShowMatureContent } from 'redux/selectors/settings';
import { makeSelectHasVisitedUri } from 'redux/selectors/content'; import { makeSelectHasVisitedUri } from 'redux/selectors/content';
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions'; import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
import { selectModerationBlockList } from 'redux/selectors/comments';
import ClaimPreview from './view'; import ClaimPreview from './view';
import formatMediaDuration from 'util/formatMediaDuration'; import formatMediaDuration from 'util/formatMediaDuration';
@ -42,16 +40,12 @@ const select = (state, props) => {
pending: props.uri && makeSelectClaimIsPending(props.uri)(state), pending: props.uri && makeSelectClaimIsPending(props.uri)(state),
reflectingProgress: props.uri && makeSelectReflectingClaimForUri(props.uri)(state), reflectingProgress: props.uri && makeSelectReflectingClaimForUri(props.uri)(state),
obscureNsfw: selectShowMatureContent(state) === false, obscureNsfw: selectShowMatureContent(state) === false,
claimIsMine: props.uri && makeSelectClaimIsMine(props.uri)(state), claimIsMine: props.uri && selectClaimIsMine(state, claim),
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state), isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
isResolvingRepost: props.uri && makeSelectIsUriResolving(props.repostUrl)(state), isResolvingRepost: props.uri && makeSelectIsUriResolving(props.repostUrl)(state),
nsfw: props.uri && makeSelectClaimIsNsfw(props.uri)(state), nsfw: props.uri && makeSelectClaimIsNsfw(props.uri)(state),
blackListedOutpoints: selectBlackListedOutpoints(state), banState: selectBanStateForUri(state, props.uri),
filteredOutpoints: selectFilteredOutpoints(state),
mutedUris: selectMutedChannels(state),
blockedUris: selectModerationBlockList(state),
hasVisitedUri: props.uri && makeSelectHasVisitedUri(props.uri)(state), hasVisitedUri: props.uri && makeSelectHasVisitedUri(props.uri)(state),
channelIsBlocked: props.uri && makeSelectChannelIsMuted(props.uri)(state),
isSubscribed: props.uri && makeSelectIsSubscribed(props.uri, true)(state), isSubscribed: props.uri && makeSelectIsSubscribed(props.uri, true)(state),
streamingUrl: props.uri && makeSelectStreamingUrlForUri(props.uri)(state), streamingUrl: props.uri && makeSelectStreamingUrlForUri(props.uri)(state),
wasPurchased: props.uri && makeSelectClaimWasPurchased(props.uri)(state), wasPurchased: props.uri && makeSelectClaimWasPurchased(props.uri)(state),

View file

@ -4,7 +4,7 @@ import React, { useEffect, forwardRef } from 'react';
import { NavLink, withRouter } from 'react-router-dom'; import { NavLink, withRouter } from 'react-router-dom';
import { isEmpty } from 'util/object'; import { isEmpty } from 'util/object';
import classnames from 'classnames'; import classnames from 'classnames';
import { isURIEqual, isURIValid } from 'util/lbryURI'; import { isURIValid } from 'util/lbryURI';
import * as COLLECTIONS_CONSTS from 'constants/collections'; import * as COLLECTIONS_CONSTS from 'constants/collections';
import { formatLbryUrlForWeb } from 'util/url'; import { formatLbryUrlForWeb } from 'util/url';
import { formatClaimPreviewTitle } from 'util/formatAriaLabel'; import { formatClaimPreviewTitle } from 'util/formatAriaLabel';
@ -46,17 +46,8 @@ type Props = {
nsfw: boolean, nsfw: boolean,
placeholder: string, placeholder: string,
type: string, type: string,
banState: { blacklisted?: boolean, filtered?: boolean, muted?: boolean, blocked?: boolean },
hasVisitedUri: boolean, hasVisitedUri: boolean,
blackListedOutpoints: Array<{
txid: string,
nout: number,
}>,
filteredOutpoints: Array<{
txid: string,
nout: number,
}>,
mutedUris: Array<string>,
blockedUris: Array<string>,
channelIsBlocked: boolean, channelIsBlocked: boolean,
actions: boolean | Node | string | number, actions: boolean | Node | string | number,
properties: boolean | Node | string | number | ((Claim) => Node), properties: boolean | Node | string | number | ((Claim) => Node),
@ -131,10 +122,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
properties, properties,
onClick, onClick,
actions, actions,
mutedUris, banState,
blockedUris,
blackListedOutpoints,
filteredOutpoints,
includeSupportAction, includeSupportAction,
renderActions, renderActions,
hideMenu = false, hideMenu = false,
@ -236,28 +224,13 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
((abandoned && !showUnresolvedClaim) || (!claimIsMine && obscureNsfw && nsfw)); ((abandoned && !showUnresolvedClaim) || (!claimIsMine && obscureNsfw && nsfw));
// This will be replaced once blocking is done at the wallet server level // This will be replaced once blocking is done at the wallet server level
if (claim && !claimIsMine && !shouldHide && blackListedOutpoints) { if (claim && !claimIsMine && (banState.blacklisted || banState.filtered)) {
shouldHide = blackListedOutpoints.some( shouldHide = true;
(outpoint) =>
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
);
}
// We're checking to see if the stream outpoint
// or signing channel outpoint is in the filter list
if (claim && !claimIsMine && !shouldHide && filteredOutpoints) {
shouldHide = filteredOutpoints.some(
(outpoint) =>
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
);
} }
// block stream claims // block stream claims
if (claim && !shouldHide && !showUserBlocked && mutedUris.length && signingChannel) { if (!shouldHide && !showUserBlocked && (banState.muted || banState.blocked)) {
shouldHide = mutedUris.some((blockedUri) => isURIEqual(blockedUri, signingChannel.permanent_url)); shouldHide = true;
}
if (claim && !shouldHide && !showUserBlocked && blockedUris.length && signingChannel) {
shouldHide = blockedUris.some((blockedUri) => isURIEqual(blockedUri, signingChannel.permanent_url));
} }
if (!shouldHide && customShouldHide && claim) { if (!shouldHide && customShouldHide && claim) {

View file

@ -11,7 +11,7 @@ import {
import { doFileGet } from 'redux/actions/file'; import { doFileGet } from 'redux/actions/file';
import { doResolveUri } from 'redux/actions/claims'; import { doResolveUri } from 'redux/actions/claims';
import { selectMutedChannels } from 'redux/selectors/blocked'; import { selectMutedChannels } from 'redux/selectors/blocked';
import { makeSelectViewCountForUri, selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc'; import { selectViewCountForUri, selectBanStateForUri } from 'lbryinc';
import { selectShowMatureContent } from 'redux/selectors/settings'; import { selectShowMatureContent } from 'redux/selectors/settings';
import ClaimPreviewTile from './view'; import ClaimPreviewTile from './view';
import formatMediaDuration from 'util/formatMediaDuration'; import formatMediaDuration from 'util/formatMediaDuration';
@ -29,12 +29,11 @@ const select = (state, props) => {
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state), isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state), thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state),
title: props.uri && makeSelectTitleForUri(props.uri)(state), title: props.uri && makeSelectTitleForUri(props.uri)(state),
blackListedOutpoints: selectBlackListedOutpoints(state), banState: selectBanStateForUri(state, props.uri),
filteredOutpoints: selectFilteredOutpoints(state),
blockedChannelUris: selectMutedChannels(state), blockedChannelUris: selectMutedChannels(state),
showMature: selectShowMatureContent(state), showMature: selectShowMatureContent(state),
isMature: makeSelectClaimIsNsfw(props.uri)(state), isMature: makeSelectClaimIsNsfw(props.uri)(state),
viewCount: makeSelectViewCountForUri(props.uri)(state), viewCount: selectViewCountForUri(state, props.uri),
}; };
}; };

View file

@ -12,7 +12,7 @@ import SubscribeButton from 'component/subscribeButton';
import useGetThumbnail from 'effects/use-get-thumbnail'; import useGetThumbnail from 'effects/use-get-thumbnail';
import { formatLbryUrlForWeb, generateListSearchUrlParams } from 'util/url'; import { formatLbryUrlForWeb, generateListSearchUrlParams } from 'util/url';
import { formatClaimPreviewTitle } from 'util/formatAriaLabel'; import { formatClaimPreviewTitle } from 'util/formatAriaLabel';
import { parseURI, isURIEqual } from 'util/lbryURI'; import { parseURI } from 'util/lbryURI';
import PreviewOverlayProperties from 'component/previewOverlayProperties'; import PreviewOverlayProperties from 'component/previewOverlayProperties';
import FileDownloadLink from 'component/fileDownloadLink'; import FileDownloadLink from 'component/fileDownloadLink';
import FileWatchLaterLink from 'component/fileWatchLaterLink'; import FileWatchLaterLink from 'component/fileWatchLaterLink';
@ -33,15 +33,7 @@ type Props = {
thumbnail: string, thumbnail: string,
title: string, title: string,
placeholder: boolean, placeholder: boolean,
blackListedOutpoints: Array<{ banState: { blacklisted?: boolean, filtered?: boolean, muted?: boolean, blocked?: boolean },
txid: string,
nout: number,
}>,
filteredOutpoints: Array<{
txid: string,
nout: number,
}>,
blockedChannelUris: Array<string>,
getFile: (string) => void, getFile: (string) => void,
streamingUrl: string, streamingUrl: string,
isMature: boolean, isMature: boolean,
@ -64,11 +56,9 @@ function ClaimPreviewTile(props: Props) {
resolveUri, resolveUri,
claim, claim,
placeholder, placeholder,
blackListedOutpoints, banState,
filteredOutpoints,
getFile, getFile,
streamingUrl, streamingUrl,
blockedChannelUris,
isMature, isMature,
showMature, showMature,
showHiddenByUser, showHiddenByUser,
@ -139,34 +129,9 @@ function ClaimPreviewTile(props: Props) {
// Unfortunately needed until this is resolved // Unfortunately needed until this is resolved
// https://github.com/lbryio/lbry-sdk/issues/2785 // https://github.com/lbryio/lbry-sdk/issues/2785
shouldHide = true; shouldHide = true;
} } else {
shouldHide =
// This will be replaced once blocking is done at the wallet server level banState.blacklisted || banState.filtered || (!showHiddenByUser && (banState.muted || banState.blocked));
if (claim && !shouldHide && blackListedOutpoints) {
shouldHide = blackListedOutpoints.some(
(outpoint) =>
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
);
}
// We're checking to see if the stream outpoint
// or signing channel outpoint is in the filter list
if (claim && !shouldHide && filteredOutpoints) {
shouldHide = filteredOutpoints.some(
(outpoint) =>
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
);
}
// block stream claims
if (claim && !shouldHide && !showHiddenByUser && blockedChannelUris.length && signingChannel) {
shouldHide = blockedChannelUris.some((blockedUri) => isURIEqual(blockedUri, signingChannel.permanent_url));
}
// block channel claims if we can't control for them in claim search
// e.g. fetchRecommendedSubscriptions
if (claim && isChannel && !shouldHide && !showHiddenByUser && blockedChannelUris.length && signingChannel) {
shouldHide = blockedChannelUris.some((blockedUri) => isURIEqual(blockedUri, signingChannel.permanent_url));
} }
if (shouldHide) { if (shouldHide) {
@ -280,34 +245,4 @@ function ClaimPreviewTile(props: Props) {
); );
} }
export default React.memo<Props>(withRouter(ClaimPreviewTile), areEqual); export default withRouter(ClaimPreviewTile);
const BLOCKLIST_KEYS = ['blackListedOutpoints', 'filteredOutpoints', 'blockedChannelUris'];
const HANDLED_KEYS = [...BLOCKLIST_KEYS, 'date'];
function areEqual(prev: Props, next: Props) {
for (let i = 0; i < BLOCKLIST_KEYS.length; ++i) {
const key = BLOCKLIST_KEYS[i];
const a = prev[key];
const b = next[key];
if (((!a || !b) && a !== b) || (a && b && a.length !== b.length)) {
// The arrays are huge, so just compare the length instead of each entry.
return false;
}
}
if (Number(prev.date) !== Number(next.date)) {
return false;
}
const propKeys = Object.keys(next);
for (let i = 0; i < propKeys.length; ++i) {
const pk = propKeys[i];
if (!HANDLED_KEYS.includes(pk) && prev[pk] !== next[pk]) {
return false;
}
}
return true;
}

View file

@ -1,12 +1,16 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimIsMine, makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimIsMine, selectClaimForUri } from 'redux/selectors/claims';
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions'; import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
import ClaimProperties from './view'; import ClaimProperties from './view';
const select = (state, props) => ({ const select = (state, props) => {
claim: makeSelectClaimForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state), return {
}); claim,
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
claimIsMine: selectClaimIsMine(state, claim),
};
};
export default connect(select, null)(ClaimProperties); export default connect(select, null)(ClaimProperties);

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import CollectionContent from './view'; import CollectionContent from './view';
import { makeSelectClaimForUri, makeSelectClaimIsMine } from 'redux/selectors/claims'; import { selectClaimForUri, selectClaimIsMine } from 'redux/selectors/claims';
import { import {
makeSelectUrlsForCollectionId, makeSelectUrlsForCollectionId,
makeSelectNameForCollectionId, makeSelectNameForCollectionId,
@ -12,7 +12,7 @@ import { doToggleLoopList, doToggleShuffleList } from 'redux/actions/content';
const select = (state, props) => { const select = (state, props) => {
const playingUri = selectPlayingUri(state); const playingUri = selectPlayingUri(state);
const playingUrl = playingUri && playingUri.uri; const playingUrl = playingUri && playingUri.uri;
const claim = makeSelectClaimForUri(playingUrl)(state); const claim = selectClaimForUri(state, playingUrl);
const url = claim && claim.permanent_url; const url = claim && claim.permanent_url;
const loopList = selectListLoop(state); const loopList = selectListLoop(state);
const loop = loopList && loopList.collectionId === props.id && loopList.loop; const loop = loopList && loopList.collectionId === props.id && loopList.loop;
@ -24,7 +24,7 @@ const select = (state, props) => {
collection: makeSelectCollectionForId(props.id)(state), collection: makeSelectCollectionForId(props.id)(state),
collectionUrls: makeSelectUrlsForCollectionId(props.id)(state), collectionUrls: makeSelectUrlsForCollectionId(props.id)(state),
collectionName: makeSelectNameForCollectionId(props.id)(state), collectionName: makeSelectNameForCollectionId(props.id)(state),
isMine: makeSelectClaimIsMine(url)(state), isMine: selectClaimIsMine(state, claim),
loop, loop,
shuffle, shuffle,
}; };

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectIsUriResolving, makeSelectClaimIdForUri, makeSelectClaimForClaimId } from 'redux/selectors/claims'; import { makeSelectIsUriResolving, selectClaimIdForUri, makeSelectClaimForClaimId } from 'redux/selectors/claims';
import { import {
makeSelectUrlsForCollectionId, makeSelectUrlsForCollectionId,
makeSelectNameForCollectionId, makeSelectNameForCollectionId,
@ -10,7 +10,7 @@ import { doFetchItemsInCollection } from 'redux/actions/collections';
import CollectionPreviewOverlay from './view'; import CollectionPreviewOverlay from './view';
const select = (state, props) => { const select = (state, props) => {
const collectionId = props.collectionId || (props.uri && makeSelectClaimIdForUri(props.uri)(state)); const collectionId = props.collectionId || (props.uri && selectClaimIdForUri(state, props.uri));
const claim = props.collectionId && makeSelectClaimForClaimId(props.collectionId)(state); const claim = props.collectionId && makeSelectClaimForClaimId(props.collectionId)(state);
const collectionUri = props.uri || (claim && (claim.canonical_url || claim.permanent_url)) || null; const collectionUri = props.uri || (claim && (claim.canonical_url || claim.permanent_url)) || null;

View file

@ -5,7 +5,7 @@ import {
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectChannelForClaimUri, makeSelectChannelForClaimUri,
makeSelectClaimIsNsfw, makeSelectClaimIsNsfw,
makeSelectClaimIdForUri, selectClaimIdForUri,
makeSelectClaimForClaimId, makeSelectClaimForClaimId,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { import {
@ -24,7 +24,7 @@ import { selectShowMatureContent } from 'redux/selectors/settings';
import CollectionPreviewTile from './view'; import CollectionPreviewTile from './view';
const select = (state, props) => { const select = (state, props) => {
const collectionId = props.collectionId || (props.uri && makeSelectClaimIdForUri(props.uri)(state)); const collectionId = props.collectionId || (props.uri && selectClaimIdForUri(state, props.uri));
const claim = props.collectionId && makeSelectClaimForClaimId(props.collectionId)(state); const claim = props.collectionId && makeSelectClaimForClaimId(props.collectionId)(state);
const collectionUri = props.uri || (claim && (claim.canonical_url || claim.permanent_url)) || null; const collectionUri = props.uri || (claim && (claim.canonical_url || claim.permanent_url)) || null;

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
makeSelectStakedLevelForChannelUri, selectTotalStakedAmountForChannelUri,
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectThumbnailForUri, makeSelectThumbnailForUri,
selectMyChannelClaims, selectMyChannelClaims,
@ -33,7 +33,7 @@ const select = (state, props) => {
activeChannelClaim, activeChannelClaim,
myChannels: selectMyChannelClaims(state), myChannels: selectMyChannelClaims(state),
playingUri: selectPlayingUri(state), playingUri: selectPlayingUri(state),
stakedLevel: makeSelectStakedLevelForChannelUri(props.authorUri)(state), stakedLevel: selectTotalStakedAmountForChannelUri(state, props.authorUri),
linkedCommentAncestors: selectLinkedCommentAncestors(state), linkedCommentAncestors: selectLinkedCommentAncestors(state),
totalReplyPages: makeSelectTotalReplyPagesForParentId(props.commentId)(state), totalReplyPages: makeSelectTotalReplyPagesForParentId(props.commentId)(state),
}; };

View file

@ -1,8 +1,8 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
makeSelectClaimForUri, selectClaimForUri,
makeSelectClaimIsMine, selectClaimIsMine,
selectMyChannelClaims, selectHasChannels,
selectFetchingMyChannels, selectFetchingMyChannels,
makeSelectTagInClaimOrChannelForUri, makeSelectTagInClaimOrChannelForUri,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
@ -14,15 +14,18 @@ import { CommentCreate } from './view';
import { doToast } from 'redux/actions/notifications'; import { doToast } from 'redux/actions/notifications';
import { DISABLE_SUPPORT_TAG } from 'constants/tags'; import { DISABLE_SUPPORT_TAG } from 'constants/tags';
const select = (state, props) => ({ const select = (state, props) => {
claim: makeSelectClaimForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
channels: selectMyChannelClaims(state), return {
isFetchingChannels: selectFetchingMyChannels(state), activeChannelClaim: selectActiveChannelClaim(state),
activeChannelClaim: selectActiveChannelClaim(state), hasChannels: selectHasChannels(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state), claim,
settingsByChannelId: selectSettingsByChannelId(state), claimIsMine: selectClaimIsMine(state, claim),
supportDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_SUPPORT_TAG)(state), isFetchingChannels: selectFetchingMyChannels(state),
}); settingsByChannelId: selectSettingsByChannelId(state),
supportDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_SUPPORT_TAG)(state),
};
};
const perform = (dispatch, ownProps) => ({ const perform = (dispatch, ownProps) => ({
createComment: (comment, claimId, parentId, txid, payment_intent_id, environment) => createComment: (comment, claimId, parentId, txid, payment_intent_id, environment) =>

View file

@ -4,24 +4,22 @@ import { doCommentPin, doCommentModAddDelegate } from 'redux/actions/comments';
import { doOpenModal } from 'redux/actions/app'; import { doOpenModal } from 'redux/actions/app';
import { doSetPlayingUri } from 'redux/actions/content'; import { doSetPlayingUri } from 'redux/actions/content';
import { doToast } from 'redux/actions/notifications'; import { doToast } from 'redux/actions/notifications';
import { import { selectClaimIsMine, selectClaimForUri } from 'redux/selectors/claims';
makeSelectChannelPermUrlForClaimUri,
makeSelectClaimIsMine,
makeSelectClaimForUri,
} from 'redux/selectors/claims';
import { selectActiveChannelClaim } from 'redux/selectors/app'; import { selectActiveChannelClaim } from 'redux/selectors/app';
import { selectModerationDelegatorsById } from 'redux/selectors/comments'; import { selectModerationDelegatorsById } from 'redux/selectors/comments';
import { selectPlayingUri } from 'redux/selectors/content'; import { selectPlayingUri } from 'redux/selectors/content';
import CommentMenuList from './view'; import CommentMenuList from './view';
const select = (state, props) => ({ const select = (state, props) => {
claim: makeSelectClaimForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
claimIsMine: makeSelectClaimIsMine(props.uri)(state), return {
contentChannelPermanentUrl: makeSelectChannelPermUrlForClaimUri(props.uri)(state), claim,
activeChannelClaim: selectActiveChannelClaim(state), claimIsMine: selectClaimIsMine(state, claim),
playingUri: selectPlayingUri(state), activeChannelClaim: selectActiveChannelClaim(state),
moderationDelegatorsById: selectModerationDelegatorsById(state), playingUri: selectPlayingUri(state),
}); moderationDelegatorsById: selectModerationDelegatorsById(state),
};
};
const perform = (dispatch) => ({ const perform = (dispatch) => ({
openModal: (modal, props) => dispatch(doOpenModal(modal, props)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)),

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import Comment from './view'; import Comment from './view';
import { makeSelectClaimIsMine, makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimIsMine, selectClaimForUri } from 'redux/selectors/claims';
import { doResolveUri } from 'redux/actions/claims'; import { doResolveUri } from 'redux/actions/claims';
import { doToast } from 'redux/actions/notifications'; import { doToast } from 'redux/actions/notifications';
import { selectMyReactsForComment, selectOthersReactsForComment } from 'redux/selectors/comments'; import { selectMyReactsForComment, selectOthersReactsForComment } from 'redux/selectors/comments';
@ -11,10 +11,11 @@ const select = (state, props) => {
const activeChannelClaim = selectActiveChannelClaim(state); const activeChannelClaim = selectActiveChannelClaim(state);
const activeChannelId = activeChannelClaim && activeChannelClaim.claim_id; const activeChannelId = activeChannelClaim && activeChannelClaim.claim_id;
const reactionKey = activeChannelId ? `${props.commentId}:${activeChannelId}` : props.commentId; const reactionKey = activeChannelId ? `${props.commentId}:${activeChannelId}` : props.commentId;
const claim = selectClaimForUri(state, props.uri);
return { return {
claim: makeSelectClaimForUri(props.uri)(state), claim,
claimIsMine: makeSelectClaimIsMine(props.uri)(state), claimIsMine: selectClaimIsMine(state, claim),
myReacts: selectMyReactsForComment(state, reactionKey), myReacts: selectMyReactsForComment(state, reactionKey),
othersReacts: selectOthersReactsForComment(state, reactionKey), othersReacts: selectOthersReactsForComment(state, reactionKey),
activeChannelId, activeChannelId,

View file

@ -1,10 +1,11 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doResolveUris } from 'redux/actions/claims'; import { doResolveUris } from 'redux/actions/claims';
import { import {
selectClaimForUri,
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectClaimIsMine, selectClaimIsMine,
selectFetchingMyChannels, selectFetchingMyChannels,
selectMyChannelClaims, selectMyClaimIdsRaw,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { import {
selectTopLevelCommentsForUri, selectTopLevelCommentsForUri,
@ -15,7 +16,7 @@ import {
makeSelectTotalCommentsCountForUri, makeSelectTotalCommentsCountForUri,
selectOthersReacts, selectOthersReacts,
selectMyReacts, selectMyReacts,
makeSelectCommentIdsForUri, selectCommentIdsForUri,
selectSettingsByChannelId, selectSettingsByChannelId,
selectPinnedCommentsForUri, selectPinnedCommentsForUri,
} from 'redux/selectors/comments'; } from 'redux/selectors/comments';
@ -24,6 +25,7 @@ import { selectActiveChannelClaim } from 'redux/selectors/app';
import CommentsList from './view'; import CommentsList from './view';
const select = (state, props) => { const select = (state, props) => {
const claim = selectClaimForUri(state, props.uri);
const activeChannelClaim = selectActiveChannelClaim(state); const activeChannelClaim = selectActiveChannelClaim(state);
const topLevelComments = selectTopLevelCommentsForUri(state, props.uri); const topLevelComments = selectTopLevelCommentsForUri(state, props.uri);
@ -35,13 +37,13 @@ const select = (state, props) => {
return { return {
topLevelComments, topLevelComments,
resolvedComments, resolvedComments,
myChannels: selectMyChannelClaims(state), myChannelIds: selectMyClaimIdsRaw(state),
allCommentIds: makeSelectCommentIdsForUri(props.uri)(state), allCommentIds: selectCommentIdsForUri(state, props.uri),
pinnedComments: selectPinnedCommentsForUri(state, props.uri), pinnedComments: selectPinnedCommentsForUri(state, props.uri),
topLevelTotalPages: makeSelectTopLevelTotalPagesForUri(props.uri)(state), topLevelTotalPages: makeSelectTopLevelTotalPagesForUri(props.uri)(state),
totalComments: makeSelectTotalCommentsCountForUri(props.uri)(state), totalComments: makeSelectTotalCommentsCountForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state), claim,
claimIsMine: makeSelectClaimIsMine(props.uri)(state), claimIsMine: selectClaimIsMine(state, claim),
isFetchingComments: selectIsFetchingComments(state), isFetchingComments: selectIsFetchingComments(state),
isFetchingCommentsById: selectIsFetchingCommentsById(state), isFetchingCommentsById: selectIsFetchingCommentsById(state),
isFetchingReacts: selectIsFetchingReacts(state), isFetchingReacts: selectIsFetchingReacts(state),

View file

@ -1,8 +1,8 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
makeSelectClaimIsMine, selectClaimIsMine,
makeSelectClaimForUri, selectClaimForUri,
selectMyChannelClaims, selectHasChannels,
makeSelectTagInClaimOrChannelForUri, makeSelectTagInClaimOrChannelForUri,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { makeSelectStreamingUrlForUri, makeSelectFileInfoForUri } from 'redux/selectors/file_info'; import { makeSelectStreamingUrlForUri, makeSelectFileInfoForUri } from 'redux/selectors/file_info';
@ -16,16 +16,20 @@ import fs from 'fs';
import FileActions from './view'; import FileActions from './view';
import { makeSelectFileRenderModeForUri } from 'redux/selectors/content'; import { makeSelectFileRenderModeForUri } from 'redux/selectors/content';
const select = (state, props) => ({ const select = (state, props) => {
claim: makeSelectClaimForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
fileInfo: makeSelectFileInfoForUri(props.uri)(state), return {
renderMode: makeSelectFileRenderModeForUri(props.uri)(state), claim,
costInfo: makeSelectCostInfoForUri(props.uri)(state), claimIsMine: selectClaimIsMine(state, claim),
myChannels: selectMyChannelClaims(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state),
reactionsDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_COMMENTS_TAG)(state), renderMode: makeSelectFileRenderModeForUri(props.uri)(state),
streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state), costInfo: makeSelectCostInfoForUri(props.uri)(state),
}); hasChannels: selectHasChannels(state),
reactionsDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_COMMENTS_TAG)(state),
streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state),
};
};
const perform = (dispatch) => ({ const perform = (dispatch) => ({
openModal: (modal, props) => dispatch(doOpenModal(modal, props)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)),

View file

@ -1,23 +1,27 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
makeSelectClaimForUri, selectClaimForUri,
makeSelectMetadataForUri, makeSelectMetadataForUri,
selectClaimIsMine,
makeSelectTagsForUri, makeSelectTagsForUri,
makeSelectClaimIsMine,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { makeSelectPendingAmountByUri } from 'redux/selectors/wallet'; import { makeSelectPendingAmountByUri } from 'redux/selectors/wallet';
import { doOpenModal } from 'redux/actions/app'; import { doOpenModal } from 'redux/actions/app';
import { selectUser } from 'redux/selectors/user'; import { selectUser } from 'redux/selectors/user';
import FileDescription from './view'; import FileDescription from './view';
const select = (state, props) => ({ const select = (state, props) => {
claim: makeSelectClaimForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
metadata: makeSelectMetadataForUri(props.uri)(state), return {
user: selectUser(state), claim,
tags: makeSelectTagsForUri(props.uri)(state), claimIsMine: selectClaimIsMine(state, claim),
pendingAmount: makeSelectPendingAmountByUri(props.uri)(state), metadata: makeSelectMetadataForUri(props.uri)(state),
}); user: selectUser(state),
pendingAmount: makeSelectPendingAmountByUri(props.uri)(state),
tags: makeSelectTagsForUri(props.uri)(state),
};
};
export default connect(select, { export default connect(select, {
doOpenModal, doOpenModal,

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimIsMine, makeSelectClaimForUri, makeSelectClaimWasPurchased } from 'redux/selectors/claims'; import { selectClaimIsMine, selectClaimForUri, makeSelectClaimWasPurchased } from 'redux/selectors/claims';
import { import {
makeSelectFileInfoForUri, makeSelectFileInfoForUri,
makeSelectDownloadingForUri, makeSelectDownloadingForUri,
@ -11,16 +11,20 @@ import { doOpenModal, doAnalyticsView } from 'redux/actions/app';
import { doSetPlayingUri, doPlayUri } from 'redux/actions/content'; import { doSetPlayingUri, doPlayUri } from 'redux/actions/content';
import FileDownloadLink from './view'; import FileDownloadLink from './view';
const select = (state, props) => ({ const select = (state, props) => {
fileInfo: makeSelectFileInfoForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
downloading: makeSelectDownloadingForUri(props.uri)(state),
loading: makeSelectLoadingForUri(props.uri)(state), return {
claimIsMine: makeSelectClaimIsMine(props.uri)(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state), downloading: makeSelectDownloadingForUri(props.uri)(state),
costInfo: makeSelectCostInfoForUri(props.uri)(state), loading: makeSelectLoadingForUri(props.uri)(state),
claimWasPurchased: makeSelectClaimWasPurchased(props.uri)(state), claimIsMine: selectClaimIsMine(state, claim),
streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state), claim,
}); costInfo: makeSelectCostInfoForUri(props.uri)(state),
claimWasPurchased: makeSelectClaimWasPurchased(props.uri)(state),
streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state),
};
};
const perform = (dispatch) => ({ const perform = (dispatch) => ({
openModal: (modal, props) => dispatch(doOpenModal(modal, props)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)),

View file

@ -1,18 +1,18 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimForUri, makeSelectClaimWasPurchased, makeSelectClaimIsMine } from 'redux/selectors/claims'; import { selectClaimForUri, makeSelectClaimWasPurchased, selectClaimIsMine } from 'redux/selectors/claims';
import { makeSelectCostInfoForUri, doFetchCostInfoForUri, makeSelectFetchingCostInfoForUri } from 'lbryinc'; import { makeSelectCostInfoForUri, doFetchCostInfoForUri, makeSelectFetchingCostInfoForUri } from 'lbryinc';
import FilePrice from './view'; import FilePrice from './view';
const select = (state, props) => ({ const select = (state, props) => {
costInfo: makeSelectCostInfoForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
fetching: makeSelectFetchingCostInfoForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state),
claimWasPurchased: makeSelectClaimWasPurchased(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
});
const perform = (dispatch) => ({ return {
fetchCostInfo: (uri) => dispatch(doFetchCostInfoForUri(uri)), claim,
}); claimIsMine: selectClaimIsMine(state, claim),
claimWasPurchased: makeSelectClaimWasPurchased(props.uri)(state),
costInfo: makeSelectCostInfoForUri(props.uri)(state),
fetching: makeSelectFetchingCostInfoForUri(props.uri)(state),
};
};
export default connect(select, perform)(FilePrice); export default connect(select, { doFetchCostInfoForUri })(FilePrice);

View file

@ -8,7 +8,7 @@ import Icon from 'component/common/icon';
type Props = { type Props = {
showFullPrice: boolean, showFullPrice: boolean,
costInfo: ?{ includesData: boolean, cost: number }, costInfo: ?{ includesData: boolean, cost: number },
fetchCostInfo: string => void, doFetchCostInfoForUri: (string) => void,
uri: string, uri: string,
fetching: boolean, fetching: boolean,
claim: ?{}, claim: ?{},
@ -35,10 +35,10 @@ class FilePrice extends React.PureComponent<Props> {
} }
fetchCost = (props: Props) => { fetchCost = (props: Props) => {
const { costInfo, fetchCostInfo, uri, fetching, claim } = props; const { costInfo, doFetchCostInfoForUri, uri, fetching, claim } = props;
if (costInfo === undefined && !fetching && claim) { if (costInfo === undefined && !fetching && claim) {
fetchCostInfo(uri); doFetchCostInfoForUri(uri);
} }
}; };

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doFetchSubCount, makeSelectSubCountForUri } from 'lbryinc'; import { doFetchSubCount, selectSubCountForUri } from 'lbryinc';
import { makeSelectTitleForUri, makeSelectClaimForUri } from 'redux/selectors/claims'; import { makeSelectTitleForUri, makeSelectClaimForUri } from 'redux/selectors/claims';
import { makeSelectInsufficientCreditsForUri } from 'redux/selectors/content'; import { makeSelectInsufficientCreditsForUri } from 'redux/selectors/content';
import FileTitleSection from './view'; import FileTitleSection from './view';
@ -8,7 +8,7 @@ const select = (state, props) => {
const claim = makeSelectClaimForUri(props.uri)(state); const claim = makeSelectClaimForUri(props.uri)(state);
const channelClaimId = claim && claim.signing_channel ? claim.signing_channel.claim_id : undefined; const channelClaimId = claim && claim.signing_channel ? claim.signing_channel.claim_id : undefined;
const channelUri = claim && claim.signing_channel ? claim.signing_channel.canonical_url : undefined; const channelUri = claim && claim.signing_channel ? claim.signing_channel.canonical_url : undefined;
const subCount = channelUri && makeSelectSubCountForUri(channelUri)(state); const subCount = channelUri && selectSubCountForUri(state, channelUri);
return { return {
isInsufficientCredits: makeSelectInsufficientCreditsForUri(props.uri)(state), isInsufficientCredits: makeSelectInsufficientCreditsForUri(props.uri)(state),

View file

@ -1,9 +1,9 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
makeSelectClaimForUri, selectClaimForUri,
makeSelectContentTypeForUri, makeSelectContentTypeForUri,
makeSelectMetadataForUri, makeSelectMetadataForUri,
makeSelectClaimIsMine, selectClaimIsMine,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { makeSelectPendingAmountByUri } from 'redux/selectors/wallet'; import { makeSelectPendingAmountByUri } from 'redux/selectors/wallet';
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info'; import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
@ -12,15 +12,19 @@ import { doOpenModal } from 'redux/actions/app';
import FileValues from './view'; import FileValues from './view';
const select = (state, props) => ({ const select = (state, props) => {
claim: makeSelectClaimForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
contentType: makeSelectContentTypeForUri(props.uri)(state),
fileInfo: makeSelectFileInfoForUri(props.uri)(state), return {
metadata: makeSelectMetadataForUri(props.uri)(state), claim,
user: selectUser(state), contentType: makeSelectContentTypeForUri(props.uri)(state),
pendingAmount: makeSelectPendingAmountByUri(props.uri)(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state), metadata: makeSelectMetadataForUri(props.uri)(state),
}); user: selectUser(state),
pendingAmount: makeSelectPendingAmountByUri(props.uri)(state),
claimIsMine: selectClaimIsMine(state, claim),
};
};
const perform = (dispatch) => ({ const perform = (dispatch) => ({
openModal: (modal, props) => dispatch(doOpenModal(modal, props)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)),

View file

@ -1,12 +1,12 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimForUri } from 'redux/selectors/claims';
import { doFetchViewCount, makeSelectViewCountForUri } from 'lbryinc'; import { doFetchViewCount, selectViewCountForUri } from 'lbryinc';
import { doAnalyticsView } from 'redux/actions/app'; import { doAnalyticsView } from 'redux/actions/app';
import FileViewCount from './view'; import FileViewCount from './view';
const select = (state, props) => ({ const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state), claim: selectClaimForUri(state, props.uri),
viewCount: makeSelectViewCountForUri(props.uri)(state), viewCount: selectViewCountForUri(state, props.uri),
}); });
const perform = (dispatch) => ({ const perform = (dispatch) => ({

View file

@ -1,13 +1,13 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimForUri } from 'redux/selectors/claims';
import { makeSelectViewCountForUri } from 'lbryinc'; import { selectViewCountForUri } from 'lbryinc';
import { selectLanguage } from 'redux/selectors/settings'; import { selectLanguage } from 'redux/selectors/settings';
import FileViewCountInline from './view'; import FileViewCountInline from './view';
const select = (state, props) => { const select = (state, props) => {
return { return {
claim: makeSelectClaimForUri(props.uri)(state), claim: selectClaimForUri(state, props.uri),
viewCount: makeSelectViewCountForUri(props.uri)(state), viewCount: selectViewCountForUri(state, props.uri),
lang: selectLanguage(state), lang: selectLanguage(state),
}; };
}; };

View file

@ -1,9 +1,9 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
makeSelectClaimIsMine, selectClaimIsMine,
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectThumbnailForUri, makeSelectThumbnailForUri,
makeSelectClaimForUri, selectClaimForUri,
makeSelectIsUriResolving, makeSelectIsUriResolving,
makeSelectMetadataItemForUri, makeSelectMetadataItemForUri,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
@ -12,13 +12,15 @@ import { selectBlackListedOutpoints } from 'lbryinc';
import PreviewLink from './view'; import PreviewLink from './view';
const select = (state, props) => { const select = (state, props) => {
const claim = selectClaimForUri(state, props.uri);
return { return {
uri: props.uri, uri: props.uri,
claim: makeSelectClaimForUri(props.uri)(state), claim,
title: makeSelectTitleForUri(props.uri)(state), title: makeSelectTitleForUri(props.uri)(state),
thumbnail: makeSelectThumbnailForUri(props.uri)(state), thumbnail: makeSelectThumbnailForUri(props.uri)(state),
description: makeSelectMetadataItemForUri(props.uri, 'description')(state), description: makeSelectMetadataItemForUri(props.uri, 'description')(state),
channelIsMine: makeSelectClaimIsMine(props.uri)(state), channelIsMine: selectClaimIsMine(state, claim),
isResolvingUri: makeSelectIsUriResolving(props.uri)(state), isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
blackListedOutpoints: selectBlackListedOutpoints(state), blackListedOutpoints: selectBlackListedOutpoints(state),
}; };

View file

@ -1,19 +1,20 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimIsMine, makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimIsMine, selectClaimForUri } from 'redux/selectors/claims';
import { makeSelectFilePartlyDownloaded } from 'redux/selectors/file_info'; import { makeSelectFilePartlyDownloaded } from 'redux/selectors/file_info';
import { makeSelectEditedCollectionForId } from 'redux/selectors/collections'; import { makeSelectEditedCollectionForId } from 'redux/selectors/collections';
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions'; import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
import PreviewOverlayProperties from './view'; import PreviewOverlayProperties from './view';
const select = (state, props) => { const select = (state, props) => {
const claim = makeSelectClaimForUri(props.uri)(state); const claim = selectClaimForUri(state, props.uri);
const claimId = claim && claim.claim_id; const claimId = claim && claim.claim_id;
return { return {
claim, claim,
editedCollection: makeSelectEditedCollectionForId(claimId)(state), editedCollection: makeSelectEditedCollectionForId(claimId)(state),
downloaded: makeSelectFilePartlyDownloaded(props.uri)(state), downloaded: makeSelectFilePartlyDownloaded(props.uri)(state),
isSubscribed: makeSelectIsSubscribed(props.uri)(state), isSubscribed: makeSelectIsSubscribed(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state), claimIsMine: selectClaimIsMine(state, claim),
}; };
}; };

View file

@ -1,12 +1,12 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doSendDraftTransaction, doSendTip } from 'redux/actions/wallet'; import { doSendDraftTransaction, doSendTip } from 'redux/actions/wallet';
import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimForUri } from 'redux/selectors/claims';
import { doHideModal } from 'redux/actions/app'; import { doHideModal } from 'redux/actions/app';
import ModalConfirmTransaction from './view'; import ModalConfirmTransaction from './view';
import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app'; import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
const select = (state, props) => ({ const select = (state, props) => ({
claim: makeSelectClaimForUri(props.destination)(state), claim: selectClaimForUri(state, props.destination)(state),
activeChannelClaim: selectActiveChannelClaim(state), activeChannelClaim: selectActiveChannelClaim(state),
incognito: selectIncognito(state), incognito: selectIncognito(state),
}); });

View file

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import { doDeleteFileAndMaybeGoBack } from 'redux/actions/file'; import { doDeleteFileAndMaybeGoBack } from 'redux/actions/file';
import { import {
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectClaimForUri, selectClaimForUri,
makeSelectIsAbandoningClaimForUri, makeSelectIsAbandoningClaimForUri,
makeSelectClaimIsMine, makeSelectClaimIsMine,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
@ -13,7 +13,7 @@ import ModalRemoveFile from './view';
const select = (state, props) => ({ const select = (state, props) => ({
claimIsMine: makeSelectClaimIsMine(props.uri)(state), claimIsMine: makeSelectClaimIsMine(props.uri)(state),
title: makeSelectTitleForUri(props.uri)(state), title: makeSelectTitleForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state), claim: selectClaimForUri(state, props.uri),
isAbandoning: makeSelectIsAbandoningClaimForUri(props.uri)(state), isAbandoning: makeSelectIsAbandoningClaimForUri(props.uri)(state),
}); });

View file

@ -1,15 +1,15 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
makeSelectClaimIsMine, selectClaimIsMine,
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectThumbnailForUri, makeSelectThumbnailForUri,
makeSelectCoverForUri, makeSelectCoverForUri,
selectCurrentChannelPage, selectCurrentChannelPage,
makeSelectClaimForUri, selectClaimForUri,
makeSelectClaimIsPending, makeSelectClaimIsPending,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { selectMyUnpublishedCollections } from 'redux/selectors/collections'; import { selectMyUnpublishedCollections } from 'redux/selectors/collections';
import { selectBlackListedOutpoints, doFetchSubCount, makeSelectSubCountForUri } from 'lbryinc'; import { selectBlackListedOutpoints, doFetchSubCount, selectSubCountForUri } from 'lbryinc'; // ban state
import { selectYoutubeChannels } from 'redux/selectors/user'; import { selectYoutubeChannels } from 'redux/selectors/user';
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions'; import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
import { selectModerationBlockList } from 'redux/selectors/comments'; import { selectModerationBlockList } from 'redux/selectors/comments';
@ -17,22 +17,26 @@ import { selectMutedChannels } from 'redux/selectors/blocked';
import { doOpenModal } from 'redux/actions/app'; import { doOpenModal } from 'redux/actions/app';
import ChannelPage from './view'; import ChannelPage from './view';
const select = (state, props) => ({ const select = (state, props) => {
title: makeSelectTitleForUri(props.uri)(state), const claim = selectClaimForUri(state, props.uri);
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
cover: makeSelectCoverForUri(props.uri)(state), return {
channelIsMine: makeSelectClaimIsMine(props.uri)(state), title: makeSelectTitleForUri(props.uri)(state),
page: selectCurrentChannelPage(state), thumbnail: makeSelectThumbnailForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state), cover: makeSelectCoverForUri(props.uri)(state),
isSubscribed: makeSelectIsSubscribed(props.uri, true)(state), channelIsMine: selectClaimIsMine(state, claim),
blackListedOutpoints: selectBlackListedOutpoints(state), page: selectCurrentChannelPage(state),
subCount: makeSelectSubCountForUri(props.uri)(state), claim,
pending: makeSelectClaimIsPending(props.uri)(state), isSubscribed: makeSelectIsSubscribed(props.uri, true)(state),
youtubeChannels: selectYoutubeChannels(state), blackListedOutpoints: selectBlackListedOutpoints(state),
blockedChannels: selectModerationBlockList(state), subCount: selectSubCountForUri(state, props.uri),
mutedChannels: selectMutedChannels(state), pending: makeSelectClaimIsPending(props.uri)(state),
unpublishedCollections: selectMyUnpublishedCollections(state), youtubeChannels: selectYoutubeChannels(state),
}); blockedChannels: selectModerationBlockList(state), // banlist
mutedChannels: selectMutedChannels(state),
unpublishedCollections: selectMyUnpublishedCollections(state),
};
};
const perform = (dispatch) => ({ const perform = (dispatch) => ({
openModal: (modal, props) => dispatch(doOpenModal(modal, props)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)),

View file

@ -5,7 +5,7 @@ import CollectionPage from './view';
import { import {
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectThumbnailForUri, makeSelectThumbnailForUri,
makeSelectClaimIsMine, selectClaimIsMine,
makeSelectClaimIsPending, makeSelectClaimIsPending,
makeSelectClaimForClaimId, makeSelectClaimForClaimId,
makeSelectChannelForClaimUri, makeSelectChannelForClaimUri,
@ -20,11 +20,7 @@ import {
makeSelectEditedCollectionForId, makeSelectEditedCollectionForId,
} from 'redux/selectors/collections'; } from 'redux/selectors/collections';
import { import { doFetchItemsInCollection, doCollectionDelete, doCollectionEdit } from 'redux/actions/collections';
doFetchItemsInCollection,
doCollectionDelete,
doCollectionEdit,
} from 'redux/actions/collections';
import { selectUser } from 'redux/selectors/user'; import { selectUser } from 'redux/selectors/user';
const select = (state, props) => { const select = (state, props) => {
@ -44,7 +40,7 @@ const select = (state, props) => {
isResolvingCollection: makeSelectIsResolvingCollectionForId(collectionId)(state), isResolvingCollection: makeSelectIsResolvingCollectionForId(collectionId)(state),
title: makeSelectTitleForUri(uri)(state), title: makeSelectTitleForUri(uri)(state),
thumbnail: makeSelectThumbnailForUri(uri)(state), thumbnail: makeSelectThumbnailForUri(uri)(state),
isMyClaim: makeSelectClaimIsMine(uri)(state), // or collection is mine? isMyClaim: selectClaimIsMine(state, claim), // or collection is mine?
isMyCollection: makeSelectCollectionIsMine(collectionId)(state), isMyCollection: makeSelectCollectionIsMine(collectionId)(state),
claimIsPending: makeSelectClaimIsPending(uri)(state), claimIsPending: makeSelectClaimIsPending(uri)(state),
collectionHasEdits: Boolean(makeSelectEditedCollectionForId(collectionId)(state)), collectionHasEdits: Boolean(makeSelectEditedCollectionForId(collectionId)(state)),

View file

@ -1,7 +1,7 @@
import * as CS from 'constants/claim_search'; import * as CS from 'constants/claim_search';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doResolveUri } from 'redux/actions/claims'; import { doResolveUri } from 'redux/actions/claims';
import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimForUri } from 'redux/selectors/claims';
import * as SETTINGS from 'constants/settings'; import * as SETTINGS from 'constants/settings';
import { selectUserVerifiedEmail } from 'redux/selectors/user'; import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectFollowedTags } from 'redux/selectors/tags'; import { selectFollowedTags } from 'redux/selectors/tags';
@ -17,7 +17,7 @@ const select = (state, props) => {
return { return {
followedTags: selectFollowedTags(state), followedTags: selectFollowedTags(state),
repostedUri: repostedUri, repostedUri: repostedUri,
repostedClaim: repostedUri ? makeSelectClaimForUri(repostedUri)(state) : null, repostedClaim: repostedUri ? selectClaimForUri(state, repostedUri) : null,
isAuthenticated: selectUserVerifiedEmail(state), isAuthenticated: selectUserVerifiedEmail(state),
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state), tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
}; };

View file

@ -4,11 +4,11 @@ import { connect } from 'react-redux';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
import { PAGE_SIZE } from 'constants/claim'; import { PAGE_SIZE } from 'constants/claim';
import { import {
makeSelectClaimForUri, selectClaimForUri,
makeSelectIsUriResolving, makeSelectIsUriResolving,
makeSelectTotalPagesForChannel, makeSelectTotalPagesForChannel,
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectClaimIsMine, selectClaimIsMine,
makeSelectClaimIsPending, makeSelectClaimIsPending,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { import {
@ -62,7 +62,7 @@ const select = (state, props) => {
props.history.replace(`/${path.slice(0, match.index)}`); props.history.replace(`/${path.slice(0, match.index)}`);
} }
} }
const claim = makeSelectClaimForUri(uri)(state); const claim = selectClaimForUri(state, uri);
const collectionId = const collectionId =
urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) || urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) ||
(claim && claim.value_type === 'collection' && claim.claim_id) || (claim && claim.value_type === 'collection' && claim.claim_id) ||
@ -76,7 +76,7 @@ const select = (state, props) => {
totalPages: makeSelectTotalPagesForChannel(uri, PAGE_SIZE)(state), totalPages: makeSelectTotalPagesForChannel(uri, PAGE_SIZE)(state),
isSubscribed: makeSelectChannelInSubscriptions(uri)(state), isSubscribed: makeSelectChannelInSubscriptions(uri)(state),
title: makeSelectTitleForUri(uri)(state), title: makeSelectTitleForUri(uri)(state),
claimIsMine: makeSelectClaimIsMine(uri)(state), claimIsMine: selectClaimIsMine(state, claim),
claimIsPending: makeSelectClaimIsPending(uri)(state), claimIsPending: makeSelectClaimIsPending(uri)(state),
collection: makeSelectCollectionForId(collectionId)(state), collection: makeSelectCollectionForId(collectionId)(state),
collectionId: collectionId, collectionId: collectionId,

View file

@ -9,7 +9,7 @@ import * as SHARED_PREFERENCES from 'constants/shared_preferences';
import { DOMAIN } from 'config'; import { DOMAIN } from 'config';
import Lbry from 'lbry'; import Lbry from 'lbry';
import { doFetchChannelListMine, doFetchCollectionListMine, doCheckPendingClaims } from 'redux/actions/claims'; import { doFetchChannelListMine, doFetchCollectionListMine, doCheckPendingClaims } from 'redux/actions/claims';
import { makeSelectClaimForUri, makeSelectClaimIsMine, selectMyChannelClaims } from 'redux/selectors/claims'; import { selectClaimForUri, selectClaimIsMineForUri, selectMyChannelClaims } from 'redux/selectors/claims';
import { doFetchFileInfos } from 'redux/actions/file_info'; import { doFetchFileInfos } from 'redux/actions/file_info';
import { doClearSupport, doBalanceSubscribe } from 'redux/actions/wallet'; import { doClearSupport, doBalanceSubscribe } from 'redux/actions/wallet';
import { doClearPublish } from 'redux/actions/publish'; import { doClearPublish } from 'redux/actions/publish';
@ -434,8 +434,9 @@ export function doToggleSearchExpanded() {
export function doAnalyticsView(uri, timeToStart) { export function doAnalyticsView(uri, timeToStart) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const { txid, nout, claim_id: claimId } = makeSelectClaimForUri(uri)(state); const claim = selectClaimForUri(state, uri);
const claimIsMine = makeSelectClaimIsMine(uri)(state); const { txid, nout, claim_id: claimId } = claim;
const claimIsMine = selectClaimIsMineForUri(state, claim);
const outpoint = `${txid}:${nout}`; const outpoint = `${txid}:${nout}`;
if (claimIsMine) { if (claimIsMine) {
@ -449,13 +450,13 @@ export function doAnalyticsView(uri, timeToStart) {
export function doAnalyticsBuffer(uri, bufferData) { export function doAnalyticsBuffer(uri, bufferData) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const claim = makeSelectClaimForUri(uri)(state); const claim = selectClaimForUri(state, uri);
const user = selectUser(state); const user = selectUser(state);
const { const {
value: { video, audio, source }, value: { video, audio, source },
} = claim; } = claim;
const timeAtBuffer = parseInt(bufferData.currentTime * 1000); const timeAtBuffer = parseInt(bufferData.currentTime ? bufferData.currentTime * 1000 : 0);
const bufferDuration = parseInt(bufferData.secondsToLoad * 1000); const bufferDuration = parseInt(bufferData.secondsToLoad ? bufferData.secondsToLoad * 1000 : 0);
const fileDurationInSeconds = (video && video.duration) || (audio && audio.duration); const fileDurationInSeconds = (video && video.duration) || (audio && audio.duration);
const fileSize = source.size; // size in bytes const fileSize = source.size; // size in bytes
const fileSizeInBits = fileSize * 8; const fileSizeInBits = fileSize * 8;
@ -501,7 +502,7 @@ export function doSignIn() {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const user = selectUser(state); const user = selectUser(state);
const notificationsEnabled = user.experimental_ui; // what is notifications? const notificationsEnabled = user.experimental_ui;
dispatch(doNotificationSocketConnect(notificationsEnabled)); dispatch(doNotificationSocketConnect(notificationsEnabled));

View file

@ -5,7 +5,12 @@ import * as MODALS from 'constants/modal_types';
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
// @endif // @endif
import { doOpenModal } from 'redux/actions/app'; import { doOpenModal } from 'redux/actions/app';
import { makeSelectClaimForUri, makeSelectClaimIsMine, makeSelectClaimWasPurchased } from 'redux/selectors/claims'; import {
makeSelectClaimForUri,
selectClaimForUri,
makeSelectClaimIsMine,
makeSelectClaimWasPurchased,
} from 'redux/selectors/claims';
import { import {
makeSelectFileInfoForUri, makeSelectFileInfoForUri,
selectFileInfosByOutpoint, selectFileInfosByOutpoint,
@ -216,7 +221,7 @@ export function doPlayUri(
export function savePosition(uri: string, position: number) { export function savePosition(uri: string, position: number) {
return (dispatch: Dispatch, getState: () => any) => { return (dispatch: Dispatch, getState: () => any) => {
const state = getState(); const state = getState();
const claim = makeSelectClaimForUri(uri)(state); const claim = selectClaimForUri(state, uri)(state);
const { claim_id: claimId, txid, nout } = claim; const { claim_id: claimId, txid, nout } = claim;
const outpoint = `${txid}:${nout}`; const outpoint = `${txid}:${nout}`;

View file

@ -5,7 +5,7 @@ import * as ABANDON_STATES from 'constants/abandon_states';
import { shell } from 'electron'; import { shell } from 'electron';
// @endif // @endif
import Lbry from 'lbry'; import Lbry from 'lbry';
import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimForUri } from 'redux/selectors/claims';
import { doAbandonClaim } from 'redux/actions/claims'; import { doAbandonClaim } from 'redux/actions/claims';
import { batchActions } from 'util/batch-actions'; import { batchActions } from 'util/batch-actions';
@ -71,7 +71,7 @@ export function doDeleteFileAndMaybeGoBack(
const state = getState(); const state = getState();
const playingUri = selectPlayingUri(state); const playingUri = selectPlayingUri(state);
const { outpoint } = makeSelectFileInfoForUri(uri)(state) || ''; const { outpoint } = makeSelectFileInfoForUri(uri)(state) || '';
const { nout, txid } = makeSelectClaimForUri(uri)(state); const { nout, txid } = selectClaimForUri(state, uri);
const claimOutpoint = `${txid}:${nout}`; const claimOutpoint = `${txid}:${nout}`;
const actions = []; const actions = [];
@ -105,7 +105,7 @@ export function doDeleteFileAndMaybeGoBack(
export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: (GetResponse) => any) { export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: (GetResponse) => any) {
return (dispatch: Dispatch, getState: () => any) => { return (dispatch: Dispatch, getState: () => any) => {
const state = getState(); const state = getState();
const { nout, txid } = makeSelectClaimForUri(uri)(state); const { nout, txid } = selectClaimForUri(state, uri);
const outpoint = `${txid}:${nout}`; const outpoint = `${txid}:${nout}`;
dispatch({ dispatch({

View file

@ -3,7 +3,7 @@ import { Lbryio } from 'lbryinc';
import * as ACTIONS from 'constants/action_types'; import * as ACTIONS from 'constants/action_types';
import * as REACTION_TYPES from 'constants/reactions'; import * as REACTION_TYPES from 'constants/reactions';
import { makeSelectMyReactionForUri } from 'redux/selectors/reactions'; import { makeSelectMyReactionForUri } from 'redux/selectors/reactions';
import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimForUri } from 'redux/selectors/claims';
export const doFetchReactions = (claimId: string) => (dispatch: Dispatch) => { export const doFetchReactions = (claimId: string) => (dispatch: Dispatch) => {
dispatch({ type: ACTIONS.REACTIONS_LIST_STARTED }); dispatch({ type: ACTIONS.REACTIONS_LIST_STARTED });
@ -20,7 +20,7 @@ export const doFetchReactions = (claimId: string) => (dispatch: Dispatch) => {
export const doReactionLike = (uri: string) => (dispatch: Dispatch, getState: GetState) => { export const doReactionLike = (uri: string) => (dispatch: Dispatch, getState: GetState) => {
const state = getState(); const state = getState();
const myReaction = makeSelectMyReactionForUri(uri)(state); const myReaction = makeSelectMyReactionForUri(uri)(state);
const claim = makeSelectClaimForUri(uri)(state); const claim = selectClaimForUri(state, uri);
const claimId = claim.claim_id; const claimId = claim.claim_id;
const shouldRemove = myReaction === REACTION_TYPES.LIKE; const shouldRemove = myReaction === REACTION_TYPES.LIKE;
@ -46,7 +46,7 @@ export const doReactionLike = (uri: string) => (dispatch: Dispatch, getState: Ge
export const doReactionDislike = (uri: string) => (dispatch: Dispatch, getState: GetState) => { export const doReactionDislike = (uri: string) => (dispatch: Dispatch, getState: GetState) => {
const state = getState(); const state = getState();
const myReaction = makeSelectMyReactionForUri(uri)(state); const myReaction = makeSelectMyReactionForUri(uri)(state);
const claim = makeSelectClaimForUri(uri)(state); const claim = selectClaimForUri(state, uri);
const claimId = claim.claim_id; const claimId = claim.claim_id;
const shouldRemove = myReaction === REACTION_TYPES.DISLIKE; const shouldRemove = myReaction === REACTION_TYPES.DISLIKE;

View file

@ -1,7 +1,7 @@
// @flow // @flow
import * as ACTIONS from 'constants/action_types'; import * as ACTIONS from 'constants/action_types';
import { selectShowMatureContent } from 'redux/selectors/settings'; import { selectShowMatureContent } from 'redux/selectors/settings';
import { makeSelectClaimForUri, makeSelectClaimIsNsfw } from 'redux/selectors/claims'; import { selectClaimForUri, makeSelectClaimIsNsfw } from 'redux/selectors/claims';
import { doResolveUris } from 'redux/actions/claims'; import { doResolveUris } from 'redux/actions/claims';
import { buildURI, isURIValid } from 'util/lbryURI'; import { buildURI, isURIValid } from 'util/lbryURI';
import { batchActions } from 'util/batch-actions'; import { batchActions } from 'util/batch-actions';
@ -131,7 +131,7 @@ export const doUpdateSearchOptions = (newOptions: SearchOptions, additionalOptio
export const doFetchRecommendedContent = (uri: string) => (dispatch: Dispatch, getState: GetState) => { export const doFetchRecommendedContent = (uri: string) => (dispatch: Dispatch, getState: GetState) => {
const state = getState(); const state = getState();
const claim = makeSelectClaimForUri(uri)(state); const claim = selectClaimForUri(state, uri);
const matureEnabled = selectShowMatureContent(state); const matureEnabled = selectShowMatureContent(state);
const claimIsMature = makeSelectClaimIsNsfw(uri)(state); const claimIsMature = makeSelectClaimIsNsfw(uri)(state);

View file

@ -1,5 +1,5 @@
import Lbry from 'lbry'; import Lbry from 'lbry';
import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { selectClaimForUri } from 'redux/selectors/claims';
import { doFetchChannelListMine } from 'redux/actions/claims'; import { doFetchChannelListMine } from 'redux/actions/claims';
import { isURIValid, normalizeURI } from 'util/lbryURI'; import { isURIValid, normalizeURI } from 'util/lbryURI';
import { batchActions } from 'util/batch-actions'; import { batchActions } from 'util/batch-actions';
@ -657,7 +657,7 @@ export function doUserSetReferrer(referrer, shouldClaim) {
const isValid = isURIValid(referrer); const isValid = isURIValid(referrer);
if (isValid) { if (isValid) {
const uri = normalizeURI(referrer); const uri = normalizeURI(referrer);
claim = makeSelectClaimForUri(uri)(getState()); claim = selectClaimForUri(getState(), uri);
if (!claim) { if (!claim) {
try { try {
const response = await Lbry.resolve({ urls: [uri] }); const response = await Lbry.resolve({ urls: [uri] });

View file

@ -1,5 +1,5 @@
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { selectClaimsById, selectMyChannelClaims, makeSelectStakedLevelForChannelUri } from 'redux/selectors/claims'; import { selectClaimsById, selectMyChannelClaims, selectTotalStakedAmountForChannelUri } from 'redux/selectors/claims';
export const selectState = (state) => state.app || {}; export const selectState = (state) => state.app || {};
@ -127,7 +127,7 @@ export const selectActiveChannelStakedLevel = createSelector(
} }
const uri = activeChannelClaim.permanent_url; const uri = activeChannelClaim.permanent_url;
const stakedLevel = makeSelectStakedLevelForChannelUri(uri)(state); const stakedLevel = selectTotalStakedAmountForChannelUri(state, uri)(state);
return stakedLevel; return stakedLevel;
} }

View file

@ -8,7 +8,7 @@ import * as CLAIM from 'constants/claim';
type State = { claims: any }; type State = { claims: any };
const selectState = (state) => state.claims || {}; const selectState = (state: State) => state.claims || {};
export const selectById = (state: State) => selectState(state).byId || {}; export const selectById = (state: State) => selectState(state).byId || {};
export const selectPendingClaimsById = (state: State) => selectState(state).pendingById || {}; export const selectPendingClaimsById = (state: State) => selectState(state).pendingById || {};
@ -18,16 +18,11 @@ export const selectClaimsById = createSelector(selectById, selectPendingClaimsBy
}); });
export const selectClaimIdsByUri = (state: State) => selectState(state).claimsByUri || {}; export const selectClaimIdsByUri = (state: State) => selectState(state).claimsByUri || {};
export const selectCurrentChannelPage = (state: State) => selectState(state).currentChannelPage || 1;
export const selectCurrentChannelPage = createSelector(selectState, (state) => state.currentChannelPage || 1); export const selectCreatingChannel = (state: State) => selectState(state).creatingChannel;
export const selectCreateChannelError = (state: State) => selectState(state).createChannelError;
export const selectCreatingChannel = createSelector(selectState, (state) => state.creatingChannel); export const selectRepostLoading = (state: State) => selectState(state).repostLoading;
export const selectRepostError = (state: State) => selectState(state).repostError;
export const selectCreateChannelError = createSelector(selectState, (state) => state.createChannelError);
export const selectRepostLoading = createSelector(selectState, (state) => state.repostLoading);
export const selectRepostError = createSelector(selectState, (state) => state.repostError);
export const selectClaimsByUri = createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => { export const selectClaimsByUri = createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => {
const claims = {}; const claims = {};
@ -48,6 +43,21 @@ export const selectClaimsByUri = createSelector(selectClaimIdsByUri, selectClaim
return claims; return claims;
}); });
/**
* Returns the claim with the specified ID. The claim could be undefined if does
* not exist or have not fetched. Take note of the second parameter, which means
* an inline function or helper would be required when used as an input to
* 'createSelector'.
*
* @param state
* @param claimId
* @returns {*}
*/
export const selectClaimWithId = (state: State, claimId: string) => {
const byId = selectClaimsById(state);
return byId[claimId];
};
export const selectAllClaimsByChannel = createSelector(selectState, (state) => state.paginatedClaimsByChannel || {}); export const selectAllClaimsByChannel = createSelector(selectState, (state) => state.paginatedClaimsByChannel || {});
export const selectPendingIds = createSelector(selectState, (state) => Object.keys(state.pendingById) || []); export const selectPendingIds = createSelector(selectState, (state) => Object.keys(state.pendingById) || []);
@ -69,10 +79,9 @@ export const makeSelectClaimIdIsPending = (claimId: string) =>
return Boolean(pendingById[claimId]); return Boolean(pendingById[claimId]);
}); });
export const makeSelectClaimIdForUri = (uri: string) => export const selectClaimIdForUri = (state: State, uri: string) => selectClaimIdsByUri(state)[uri];
createSelector(selectClaimIdsByUri, (claimIds) => claimIds[uri]);
export const selectReflectingById = createSelector(selectState, (state) => state.reflectingById); export const selectReflectingById = (state: State) => selectState(state).reflectingById;
export const makeSelectClaimForClaimId = (claimId: string) => createSelector(selectClaimsById, (byId) => byId[claimId]); export const makeSelectClaimForClaimId = (claimId: string) => createSelector(selectClaimsById, (byId) => byId[claimId]);
@ -85,7 +94,8 @@ export const selectClaimForUri = createCachedSelector(
const validUri = isURIValid(uri); const validUri = isURIValid(uri);
if (validUri && byUri) { if (validUri && byUri) {
const claimId = uri && byUri[normalizeURI(uri)]; const normalizedUri = normalizeURI(uri);
const claimId = uri && byUri[normalizedUri];
const claim = byId[claimId]; const claim = byId[claimId];
// Make sure to return the claim as is so apps can check if it's been resolved before (null) or still needs to be resolved (undefined) // Make sure to return the claim as is so apps can check if it's been resolved before (null) or still needs to be resolved (undefined)
@ -102,7 +112,7 @@ export const selectClaimForUri = createCachedSelector(
return { return {
...repostedClaim, ...repostedClaim,
repost_url: normalizeURI(uri), repost_url: normalizedUri,
repost_channel_url: channelUrl, repost_channel_url: channelUrl,
repost_bid_amount: claim && claim.meta && claim.meta.effective_amount, repost_bid_amount: claim && claim.meta && claim.meta.effective_amount,
}; };
@ -111,14 +121,16 @@ export const selectClaimForUri = createCachedSelector(
} }
} }
} }
)((state, uri, returnRepost = true) => `${uri}:${returnRepost ? '1' : '0'}`); )((state, uri, returnRepost = true) => `${String(uri)}:${returnRepost ? '1' : '0'}`);
// Note: this is deprecated. Use "selectClaimForUri(state, uri)" instead.
export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true) => export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true) =>
createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => { createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => {
const validUri = isURIValid(uri); const validUri = isURIValid(uri);
if (validUri && byUri) { if (validUri && byUri) {
const claimId = uri && byUri[normalizeURI(uri)]; const normalizedUri = normalizeURI(uri);
const claimId = uri && byUri[normalizedUri];
const claim = byId[claimId]; const claim = byId[claimId];
// Make sure to return the claim as is so apps can check if it's been resolved before (null) or still needs to be resolved (undefined) // Make sure to return the claim as is so apps can check if it's been resolved before (null) or still needs to be resolved (undefined)
@ -135,7 +147,7 @@ export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true)
return { return {
...repostedClaim, ...repostedClaim,
repost_url: normalizeURI(uri), repost_url: normalizedUri,
repost_channel_url: channelUrl, repost_channel_url: channelUrl,
repost_bid_amount: claim && claim.meta && claim.meta.effective_amount, repost_bid_amount: claim && claim.meta && claim.meta.effective_amount,
}; };
@ -145,6 +157,9 @@ export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true)
} }
}); });
// Returns your claim IDs without handling pending and abandoned claims.
export const selectMyClaimIdsRaw = (state: State) => selectState(state).myClaims;
export const selectMyClaimsRaw = createSelector(selectState, selectClaimsById, (state, byId) => { export const selectMyClaimsRaw = createSelector(selectState, selectClaimsById, (state, byId) => {
const ids = state.myClaims; const ids = state.myClaims;
if (!ids) { if (!ids) {
@ -161,7 +176,10 @@ export const selectMyClaimsRaw = createSelector(selectState, selectClaimsById, (
return claims; return claims;
}); });
export const selectAbandoningIds = createSelector(selectState, (state) => Object.keys(state.abandoningById || {})); export const selectAbandoningById = (state: State) => selectState(state).abandoningById || {};
export const selectAbandoningIds = createSelector(selectAbandoningById, (abandoningById) =>
Object.keys(abandoningById)
);
export const makeSelectAbandoningClaimById = (claimId: string) => export const makeSelectAbandoningClaimById = (claimId: string) =>
createSelector(selectAbandoningIds, (ids) => ids.includes(claimId)); createSelector(selectAbandoningIds, (ids) => ids.includes(claimId));
@ -173,12 +191,63 @@ export const makeSelectIsAbandoningClaimForUri = (uri: string) =>
}); });
export const selectMyActiveClaims = createSelector( export const selectMyActiveClaims = createSelector(
selectMyClaimsRaw, selectMyClaimIdsRaw,
selectAbandoningIds, selectAbandoningIds,
(claims, abandoningIds) => (myClaimIds, abandoningIds) => {
new Set(claims && claims.map((claim) => claim.claim_id).filter((claimId) => !abandoningIds.includes(claimId))) return new Set(myClaimIds && myClaimIds.filter((claimId) => !abandoningIds.includes(claimId)));
}
); );
// Helper for 'selectClaimIsMineForUri'.
// Returns undefined string if unable to normalize or is not valid.
const selectNormalizedAndVerifiedUri = createCachedSelector(
(state, rawUri) => rawUri,
(rawUri) => {
try {
const uri = normalizeURI(rawUri);
if (isURIValid(uri)) {
return uri;
}
} catch (e) {}
return undefined;
}
)((state, rawUri) => String(rawUri));
export const selectClaimIsMine = (state: State, claim: ?Claim) => {
if (claim) {
// The original code seems to imply that 'is_my_output' could be false even
// when it is yours and there is a need to double-check with 'myActiveClaims'.
// I'm retaining that logic. Otherwise, we could have just return
// is_my_output directly when it is defined and skip the fallback.
if (claim.is_my_output) {
return true;
} else {
// 'is_my_output' is false or undefined.
const myActiveClaims = selectMyActiveClaims(state);
return claim.claim_id && myActiveClaims.has(claim.claim_id);
}
} else {
return false;
}
};
export const selectClaimIsMineForUri = (state: State, rawUri: string) => {
// Not memoizing this selector because:
// (1) The workload is somewhat lightweight.
// (2) Since it depends on 'selectClaimsByUri', memoization won't work anyway
// because the array is constantly invalidated.
const uri = selectNormalizedAndVerifiedUri(state, rawUri);
if (!uri) {
return false;
}
const claimsByUri = selectClaimsByUri(state);
return selectClaimIsMine(state, claimsByUri && claimsByUri[uri]);
};
// DEPRECATED - use selectClaimIsMineForUri instead.
export const makeSelectClaimIsMine = (rawUri: string) => { export const makeSelectClaimIsMine = (rawUri: string) => {
let uri; let uri;
try { try {
@ -198,15 +267,11 @@ export const makeSelectClaimIsMine = (rawUri: string) => {
}); });
}; };
export const selectMyPurchases = createSelector(selectState, (state) => state.myPurchases); export const selectMyPurchases = (state: State) => selectState(state).myPurchases;
export const selectPurchaseUriSuccess = (state: State) => selectState(state).purchaseUriSuccess;
export const selectPurchaseUriSuccess = createSelector(selectState, (state) => state.purchaseUriSuccess); export const selectMyPurchasesCount = (state: State) => selectState(state).myPurchasesPageTotalResults;
export const selectIsFetchingMyPurchases = (state: State) => selectState(state).fetchingMyPurchases;
export const selectMyPurchasesCount = createSelector(selectState, (state) => state.myPurchasesPageTotalResults); export const selectFetchingMyPurchasesError = (state: State) => selectState(state).fetchingMyPurchasesError;
export const selectIsFetchingMyPurchases = createSelector(selectState, (state) => state.fetchingMyPurchases);
export const selectFetchingMyPurchasesError = createSelector(selectState, (state) => state.fetchingMyPurchasesError);
export const makeSelectMyPurchasesForPage = (query: ?string, page: number = 1) => export const makeSelectMyPurchasesForPage = (query: ?string, page: number = 1) =>
createSelector( createSelector(
@ -270,7 +335,7 @@ export const makeSelectTotalPagesInChannelSearch = (uri: string) =>
export const selectMetadataForUri = createCachedSelector(selectClaimForUri, (claim, uri) => { export const selectMetadataForUri = createCachedSelector(selectClaimForUri, (claim, uri) => {
const metadata = claim && claim.value; const metadata = claim && claim.value;
return metadata || (claim === undefined ? undefined : null); return metadata || (claim === undefined ? undefined : null);
})((state, uri) => uri); })((state, uri) => String(uri));
export const makeSelectMetadataForUri = (uri: string) => export const makeSelectMetadataForUri = (uri: string) =>
createSelector(makeSelectClaimForUri(uri), (claim) => { createSelector(makeSelectClaimForUri(uri), (claim) => {
@ -303,7 +368,7 @@ export const selectDateForUri = createCachedSelector(
const dateObj = new Date(timestamp); const dateObj = new Date(timestamp);
return dateObj; return dateObj;
} }
)((state, uri) => uri); )((state, uri) => String(uri));
export const makeSelectAmountForUri = (uri: string) => export const makeSelectAmountForUri = (uri: string) =>
createSelector(makeSelectClaimForUri(uri), (claim) => { createSelector(makeSelectClaimForUri(uri), (claim) => {
@ -335,7 +400,7 @@ export const makeSelectCoverForUri = (uri: string) =>
return cover && cover.url ? cover.url.trim().replace(/^http:\/\//i, 'https://') : undefined; return cover && cover.url ? cover.url.trim().replace(/^http:\/\//i, 'https://') : undefined;
}); });
export const selectIsFetchingClaimListMine = createSelector(selectState, (state) => state.isFetchingClaimListMine); export const selectIsFetchingClaimListMine = (state: State) => selectState(state).isFetchingClaimListMine;
export const selectMyClaimsPage = createSelector(selectState, (state) => state.myClaimsPageResults || []); export const selectMyClaimsPage = createSelector(selectState, (state) => state.myClaimsPageResults || []);
@ -346,12 +411,8 @@ export const selectMyClaimsPageNumber = createSelector(
(state) => (state.txoPage && state.txoPage.page) || 1 (state) => (state.txoPage && state.txoPage.page) || 1
); );
export const selectMyClaimsPageItemCount = createSelector(selectState, (state) => state.myClaimsPageTotalResults || 1); export const selectMyClaimsPageItemCount = (state: State) => selectState(state).myClaimsPageTotalResults || 1;
export const selectFetchingMyClaimsPageError = (state: State) => selectState(state).fetchingClaimListMinePageError;
export const selectFetchingMyClaimsPageError = createSelector(
selectState,
(state) => state.fetchingClaimListMinePageError
);
export const selectMyClaims = createSelector( export const selectMyClaims = createSelector(
selectMyActiveClaims, selectMyActiveClaims,
@ -403,18 +464,31 @@ export const selectMyClaimsOutpoints = createSelector(selectMyClaims, (myClaims)
return outpoints; return outpoints;
}); });
export const selectFetchingMyChannels = createSelector(selectState, (state) => state.fetchingMyChannels); export const selectFetchingMyChannels = (state: State) => selectState(state).fetchingMyChannels;
export const selectFetchingMyCollections = (state: State) => selectState(state).fetchingMyCollections;
export const selectFetchingMyCollections = createSelector(selectState, (state) => state.fetchingMyCollections); export const selectMyChannelClaimIds = (state: State) => selectState(state).myChannelClaims;
export const selectMyChannelClaims = createSelector(selectState, selectClaimsById, (state, byId) => { export const selectMyChannelClaims = createSelector(selectMyChannelClaimIds, (myChannelClaimIds) => {
const ids = state.myChannelClaims; if (!myChannelClaimIds) {
if (!ids) { return myChannelClaimIds;
return ids;
} }
if (!window || !window.store) {
return undefined;
}
// Note: Grabbing the store and running the selector this way is anti-pattern,
// but it is _needed_ and works only because we know for sure that 'byId[]'
// will be populated with the same claims as when 'myChannelClaimIds' is populated.
// If we put 'state' or 'byId' as the input selector, it essentially
// recalculates every time. Putting 'state' as input to createSelector() is
// always wrong from a memoization standpoint.
const state = window.store.getState();
const byId = selectClaimsById(state);
const claims = []; const claims = [];
ids.forEach((id) => { myChannelClaimIds.forEach((id) => {
if (byId[id]) { if (byId[id]) {
// I'm not sure why this check is necessary, but it ought to be a quick fix for https://github.com/lbryio/lbry-desktop/issues/544 // I'm not sure why this check is necessary, but it ought to be a quick fix for https://github.com/lbryio/lbry-desktop/issues/544
claims.push(byId[id]); claims.push(byId[id]);
@ -428,16 +502,21 @@ export const selectMyChannelUrls = createSelector(selectMyChannelClaims, (claims
claims ? claims.map((claim) => claim.canonical_url || claim.permanent_url) : undefined claims ? claims.map((claim) => claim.canonical_url || claim.permanent_url) : undefined
); );
export const selectMyCollectionIds = createSelector(selectState, (state) => state.myCollectionClaims); export const selectHasChannels = (state: State) => {
const myChannelClaimIds = selectMyChannelClaimIds(state);
return myChannelClaimIds ? myChannelClaimIds.length > 0 : false;
};
export const selectMyCollectionIds = (state: State) => selectState(state).myCollectionClaims;
export const selectResolvingUris = createSelector(selectState, (state) => state.resolvingUris || []); export const selectResolvingUris = createSelector(selectState, (state) => state.resolvingUris || []);
export const selectChannelImportPending = createSelector(selectState, (state) => state.pendingChannelImport); export const selectChannelImportPending = (state: State) => selectState(state).pendingChannelImport;
export const makeSelectIsUriResolving = (uri: string) => export const makeSelectIsUriResolving = (uri: string) =>
createSelector(selectResolvingUris, (resolvingUris) => resolvingUris && resolvingUris.indexOf(uri) !== -1); createSelector(selectResolvingUris, (resolvingUris) => resolvingUris && resolvingUris.indexOf(uri) !== -1);
export const selectPlayingUri = createSelector(selectState, (state) => state.playingUri); export const selectPlayingUri = (state: State) => selectState(state).playingUri;
export const selectChannelClaimCounts = createSelector(selectState, (state) => state.channelClaimCounts || {}); export const selectChannelClaimCounts = createSelector(selectState, (state) => state.channelClaimCounts || {});
@ -541,7 +620,7 @@ export const makeSelectMyChannelPermUrlForName = (name: string) =>
export const selectTagsForUri = createCachedSelector(selectMetadataForUri, (metadata: ?GenericMetadata) => { export const selectTagsForUri = createCachedSelector(selectMetadataForUri, (metadata: ?GenericMetadata) => {
return (metadata && metadata.tags) || []; return (metadata && metadata.tags) || [];
})((state, uri) => uri); })((state, uri) => String(uri));
export const makeSelectTagsForUri = (uri: string) => export const makeSelectTagsForUri = (uri: string) =>
createSelector(makeSelectMetadataForUri(uri), (metadata: ?GenericMetadata) => { createSelector(makeSelectMetadataForUri(uri), (metadata: ?GenericMetadata) => {
@ -592,9 +671,8 @@ export const makeSelectSupportsForUri = (uri: string) =>
return total; return total;
}); });
export const selectUpdatingChannel = createSelector(selectState, (state) => state.updatingChannel); export const selectUpdatingChannel = (state: State) => selectState(state).updatingChannel;
export const selectUpdateChannelError = (state: State) => selectState(state).updateChannelError;
export const selectUpdateChannelError = createSelector(selectState, (state) => state.updateChannelError);
export const makeSelectReflectingClaimForUri = (uri: string) => export const makeSelectReflectingClaimForUri = (uri: string) =>
createSelector(selectClaimIdsByUri, selectReflectingById, (claimIdsByUri, reflectingById) => { createSelector(selectClaimIdsByUri, selectReflectingById, (claimIdsByUri, reflectingById) => {
@ -638,39 +716,34 @@ export const makeSelectClaimIsStreamPlaceholder = (uri: string) =>
return Boolean(claim.value_type === 'stream' && !claim.value.source); return Boolean(claim.value_type === 'stream' && !claim.value.source);
}); });
export const makeSelectTotalStakedAmountForChannelUri = (uri: string) => export const selectTotalStakedAmountForChannelUri = createCachedSelector(selectClaimForUri, (claim) => {
createSelector(makeSelectClaimForUri(uri), (claim) => { if (!claim || !claim.amount || !claim.meta || !claim.meta.support_amount) {
if (!claim || !claim.amount || !claim.meta || !claim.meta.support_amount) { return 0;
return 0; }
}
return parseFloat(claim.amount) + parseFloat(claim.meta.support_amount) || 0; return parseFloat(claim.amount) + parseFloat(claim.meta.support_amount) || 0;
}); })((state, uri) => String(uri));
export const makeSelectStakedLevelForChannelUri = (uri: string) => export const selectStakedLevelForChannelUri = createCachedSelector(selectTotalStakedAmountForChannelUri, (amount) => {
createSelector(makeSelectTotalStakedAmountForChannelUri(uri), (amount) => { let level = 1;
let level = 1; switch (true) {
switch (true) { case amount >= CLAIM.LEVEL_2_STAKED_AMOUNT && amount < CLAIM.LEVEL_3_STAKED_AMOUNT:
case amount >= CLAIM.LEVEL_2_STAKED_AMOUNT && amount < CLAIM.LEVEL_3_STAKED_AMOUNT: level = 2;
level = 2; break;
break; case amount >= CLAIM.LEVEL_3_STAKED_AMOUNT && amount < CLAIM.LEVEL_4_STAKED_AMOUNT:
case amount >= CLAIM.LEVEL_3_STAKED_AMOUNT && amount < CLAIM.LEVEL_4_STAKED_AMOUNT: level = 3;
level = 3; break;
break; case amount >= CLAIM.LEVEL_4_STAKED_AMOUNT && amount < CLAIM.LEVEL_5_STAKED_AMOUNT:
case amount >= CLAIM.LEVEL_4_STAKED_AMOUNT && amount < CLAIM.LEVEL_5_STAKED_AMOUNT: level = 4;
level = 4; break;
break; case amount >= CLAIM.LEVEL_5_STAKED_AMOUNT:
case amount >= CLAIM.LEVEL_5_STAKED_AMOUNT: level = 5;
level = 5; break;
break; }
} return level;
return level; })((state, uri) => String(uri));
});
export const selectUpdatingCollection = createSelector(selectState, (state) => state.updatingCollection); export const selectUpdatingCollection = (state: State) => selectState(state).updatingCollection;
export const selectUpdateCollectionError = (state: State) => selectState(state).updateCollectionError;
export const selectUpdateCollectionError = createSelector(selectState, (state) => state.updateCollectionError); export const selectCreatingCollection = (state: State) => selectState(state).creatingCollection;
export const selectCreateCollectionError = (state: State) => selectState(state).createCollectionError;
export const selectCreatingCollection = createSelector(selectState, (state) => state.creatingCollection);
export const selectCreateCollectionError = createSelector(selectState, (state) => state.createCollectionError);

View file

@ -4,14 +4,15 @@ import { createCachedSelector } from 're-reselect';
import { selectMutedChannels } from 'redux/selectors/blocked'; import { selectMutedChannels } from 'redux/selectors/blocked';
import { selectShowMatureContent } from 'redux/selectors/settings'; import { selectShowMatureContent } from 'redux/selectors/settings';
import { selectBlacklistedOutpointMap, selectFilteredOutpointMap } from 'lbryinc'; import { selectBlacklistedOutpointMap, selectFilteredOutpointMap } from 'lbryinc';
import { selectClaimsById, selectMyActiveClaims } from 'redux/selectors/claims'; import { selectClaimsById, selectMyActiveClaims, selectClaimIdForUri } from 'redux/selectors/claims';
import { isClaimNsfw } from 'util/claim'; import { isClaimNsfw } from 'util/claim';
type State = { comments: CommentsState }; type State = { comments: CommentsState, claims: any };
const selectState = (state) => state.comments || {}; const selectState = (state) => state.comments || {};
export const selectCommentsById = (state: State) => selectState(state).commentById || {}; export const selectCommentsById = (state: State) => selectState(state).commentById || {};
export const selectCommentIdsByClaimId = (state: State) => selectState(state).byId;
export const selectIsFetchingComments = (state: State) => selectState(state).isLoading; export const selectIsFetchingComments = (state: State) => selectState(state).isLoading;
export const selectIsFetchingCommentsById = (state: State) => selectState(state).isLoadingById; export const selectIsFetchingCommentsById = (state: State) => selectState(state).isLoadingById;
export const selectIsFetchingCommentsByParentId = (state: State) => selectState(state).isLoadingByParentId; export const selectIsFetchingCommentsByParentId = (state: State) => selectState(state).isLoadingByParentId;
@ -173,6 +174,12 @@ export const selectRepliesByParentId = createSelector(selectState, selectComment
export const selectLinkedCommentAncestors = (state: State) => selectState(state).linkedCommentAncestors; export const selectLinkedCommentAncestors = (state: State) => selectState(state).linkedCommentAncestors;
export const selectCommentIdsForUri = (state: State, uri: string) => {
const claimId = selectClaimIdForUri(state, uri);
const commentIdsByClaimId = selectCommentIdsByClaimId(state);
return commentIdsByClaimId[claimId];
};
export const makeSelectCommentIdsForUri = (uri: string) => export const makeSelectCommentIdsForUri = (uri: string) =>
createSelector(selectState, selectCommentsByUri, selectClaimsById, (state, byUri) => { createSelector(selectState, selectCommentsByUri, selectClaimsById, (state, byUri) => {
const claimId = byUri[uri]; const claimId = byUri[uri];