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 {
selectViewCount,
makeSelectViewCountForUri,
makeSelectSubCountForUri,
selectViewCountForUri,
// makeSelectViewCountForUri, // deprecated
selectSubCountForUri,
// makeSelectSubCountForUri, // deprecated
} from './redux/selectors/stats';
export { selectBanStateForUri } from './redux/selectors/ban';
export {
selectHasSyncedWallet,
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 { makeSelectClaimForUri } from 'redux/selectors/claims';
import { selectClaimIdForUri } from 'redux/selectors/claims';
type State = { claims: any };
const selectState = state => state.stats || {};
export const selectViewCount = createSelector(selectState, state => state.viewCountById);
export const selectSubCount = createSelector(selectState, state => state.subCountById);
export const makeSelectViewCountForUri = uri =>
createSelector(
makeSelectClaimForUri(uri),
selectViewCount,
(claim, viewCountById) => (claim ? viewCountById[claim.claim_id] || 0 : 0)
);
export const selectViewCountForUri = (state: State, uri: string) => {
const claimId = selectClaimIdForUri(state, uri);
const viewCountById = selectViewCount(state);
return claimId ? viewCountById[claimId] || 0 : 0;
};
export const makeSelectSubCountForUri = uri =>
createSelector(
makeSelectClaimForUri(uri),
selectSubCount,
(claim, subCountById) => (claim ? subCountById[claim.claim_id] || 0 : 0)
);
export const selectSubCountForUri = (state: State, uri: string) => {
const claimId = selectClaimIdForUri(state, uri);
const subCountById = selectSubCount(state);
return claimId ? subCountById[claimId] || 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.",
"Content: Limit (GB)": "Content: Limit (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--"
}

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { makeSelectClaimIdForUri } from 'redux/selectors/claims';
import { selectClaimIdForUri } from 'redux/selectors/claims';
import {
doCommentModUnBlock,
doCommentModBlock,
@ -43,7 +43,7 @@ const select = (state, props) => {
isBlocked,
isToggling,
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 {
makeSelectClaimsInChannelForPage,
makeSelectFetchingChannelClaims,
makeSelectClaimIsMine,
selectClaimIsMine,
makeSelectTotalPagesInChannelSearch,
makeSelectClaimForUri,
selectClaimForUri,
} from 'redux/selectors/claims';
import { doResolveUris } from 'redux/actions/claims';
import * as SETTINGS from 'constants/settings';
@ -20,13 +20,15 @@ const select = (state, props) => {
const { search } = props.location;
const urlParams = new URLSearchParams(search);
const page = urlParams.get('page') || 0;
const claim = props.uri && selectClaimForUri(state, props.uri);
return {
pageOfClaimsInChannel: makeSelectClaimsInChannelForPage(props.uri, page)(state),
fetching: makeSelectFetchingChannelClaims(props.uri)(state),
totalPages: makeSelectTotalPagesInChannelSearch(props.uri, PAGE_SIZE)(state),
channelIsMine: makeSelectClaimIsMine(props.uri)(state),
channelIsMine: selectClaimIsMine(state, claim),
channelIsBlocked: makeSelectChannelIsMuted(props.uri)(state),
claim: props.uri && makeSelectClaimForUri(props.uri)(state),
claim,
isAuthenticated: selectUserVerifiedEmail(state),
showMature: selectShowMatureContent(state),
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),

View file

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

View file

@ -1,5 +1,5 @@
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 { doPrepareEdit } from 'redux/actions/publish';
import {
@ -34,7 +34,7 @@ import ClaimPreview from './view';
import fs from 'fs';
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 repostedClaim = claim && claim.reposted_claim;
const contentClaim = repostedClaim || claim;
@ -51,7 +51,7 @@ const select = (state, props) => {
contentClaim,
contentSigningChannel,
contentChannelUri,
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
claimIsMine: selectClaimIsMine(state, claim),
hasClaimInWatchLater: makeSelectCollectionForIdHasClaimUrl(
COLLECTIONS_CONSTS.WATCH_LATER_ID,
contentPermanentUri
@ -92,7 +92,7 @@ const perform = (dispatch) => ({
doChannelUnmute: (channelUri) => dispatch(doChannelUnmute(channelUri)),
doCommentModBlock: (channelUri) => dispatch(doCommentModBlock(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) =>
dispatch(doCommentModUnBlockAsAdmin(commenterUri, blockerId)),
doChannelSubscribe: (subscription) => dispatch(doChannelSubscribe(subscription)),

View file

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import {
selectClaimForUri,
makeSelectIsUriResolving,
makeSelectClaimIsMine,
selectClaimIsMine,
makeSelectClaimIsPending,
makeSelectClaimIsNsfw,
makeSelectReflectingClaimForUri,
@ -20,12 +20,10 @@ import {
import { doResolveUri } from 'redux/actions/claims';
import { doCollectionEdit } from 'redux/actions/collections';
import { doFileGet } from 'redux/actions/file';
import { selectMutedChannels, makeSelectChannelIsMuted } from 'redux/selectors/blocked';
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
import { selectBanStateForUri } from 'lbryinc';
import { selectShowMatureContent } from 'redux/selectors/settings';
import { makeSelectHasVisitedUri } from 'redux/selectors/content';
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
import { selectModerationBlockList } from 'redux/selectors/comments';
import ClaimPreview from './view';
import formatMediaDuration from 'util/formatMediaDuration';
@ -42,16 +40,12 @@ const select = (state, props) => {
pending: props.uri && makeSelectClaimIsPending(props.uri)(state),
reflectingProgress: props.uri && makeSelectReflectingClaimForUri(props.uri)(state),
obscureNsfw: selectShowMatureContent(state) === false,
claimIsMine: props.uri && makeSelectClaimIsMine(props.uri)(state),
claimIsMine: props.uri && selectClaimIsMine(state, claim),
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
isResolvingRepost: props.uri && makeSelectIsUriResolving(props.repostUrl)(state),
nsfw: props.uri && makeSelectClaimIsNsfw(props.uri)(state),
blackListedOutpoints: selectBlackListedOutpoints(state),
filteredOutpoints: selectFilteredOutpoints(state),
mutedUris: selectMutedChannels(state),
blockedUris: selectModerationBlockList(state),
banState: selectBanStateForUri(state, props.uri),
hasVisitedUri: props.uri && makeSelectHasVisitedUri(props.uri)(state),
channelIsBlocked: props.uri && makeSelectChannelIsMuted(props.uri)(state),
isSubscribed: props.uri && makeSelectIsSubscribed(props.uri, true)(state),
streamingUrl: props.uri && makeSelectStreamingUrlForUri(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 { isEmpty } from 'util/object';
import classnames from 'classnames';
import { isURIEqual, isURIValid } from 'util/lbryURI';
import { isURIValid } from 'util/lbryURI';
import * as COLLECTIONS_CONSTS from 'constants/collections';
import { formatLbryUrlForWeb } from 'util/url';
import { formatClaimPreviewTitle } from 'util/formatAriaLabel';
@ -46,17 +46,8 @@ type Props = {
nsfw: boolean,
placeholder: string,
type: string,
banState: { blacklisted?: boolean, filtered?: boolean, muted?: boolean, blocked?: boolean },
hasVisitedUri: boolean,
blackListedOutpoints: Array<{
txid: string,
nout: number,
}>,
filteredOutpoints: Array<{
txid: string,
nout: number,
}>,
mutedUris: Array<string>,
blockedUris: Array<string>,
channelIsBlocked: boolean,
actions: boolean | Node | string | number,
properties: boolean | Node | string | number | ((Claim) => Node),
@ -131,10 +122,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
properties,
onClick,
actions,
mutedUris,
blockedUris,
blackListedOutpoints,
filteredOutpoints,
banState,
includeSupportAction,
renderActions,
hideMenu = false,
@ -236,28 +224,13 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
((abandoned && !showUnresolvedClaim) || (!claimIsMine && obscureNsfw && nsfw));
// This will be replaced once blocking is done at the wallet server level
if (claim && !claimIsMine && !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 && !claimIsMine && !shouldHide && filteredOutpoints) {
shouldHide = filteredOutpoints.some(
(outpoint) =>
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
);
if (claim && !claimIsMine && (banState.blacklisted || banState.filtered)) {
shouldHide = true;
}
// block stream claims
if (claim && !shouldHide && !showUserBlocked && mutedUris.length && signingChannel) {
shouldHide = mutedUris.some((blockedUri) => isURIEqual(blockedUri, signingChannel.permanent_url));
}
if (claim && !shouldHide && !showUserBlocked && blockedUris.length && signingChannel) {
shouldHide = blockedUris.some((blockedUri) => isURIEqual(blockedUri, signingChannel.permanent_url));
if (!shouldHide && !showUserBlocked && (banState.muted || banState.blocked)) {
shouldHide = true;
}
if (!shouldHide && customShouldHide && claim) {

View file

@ -11,7 +11,7 @@ import {
import { doFileGet } from 'redux/actions/file';
import { doResolveUri } from 'redux/actions/claims';
import { selectMutedChannels } from 'redux/selectors/blocked';
import { makeSelectViewCountForUri, selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
import { selectViewCountForUri, selectBanStateForUri } from 'lbryinc';
import { selectShowMatureContent } from 'redux/selectors/settings';
import ClaimPreviewTile from './view';
import formatMediaDuration from 'util/formatMediaDuration';
@ -29,12 +29,11 @@ const select = (state, props) => {
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state),
title: props.uri && makeSelectTitleForUri(props.uri)(state),
blackListedOutpoints: selectBlackListedOutpoints(state),
filteredOutpoints: selectFilteredOutpoints(state),
banState: selectBanStateForUri(state, props.uri),
blockedChannelUris: selectMutedChannels(state),
showMature: selectShowMatureContent(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 { formatLbryUrlForWeb, generateListSearchUrlParams } from 'util/url';
import { formatClaimPreviewTitle } from 'util/formatAriaLabel';
import { parseURI, isURIEqual } from 'util/lbryURI';
import { parseURI } from 'util/lbryURI';
import PreviewOverlayProperties from 'component/previewOverlayProperties';
import FileDownloadLink from 'component/fileDownloadLink';
import FileWatchLaterLink from 'component/fileWatchLaterLink';
@ -33,15 +33,7 @@ type Props = {
thumbnail: string,
title: string,
placeholder: boolean,
blackListedOutpoints: Array<{
txid: string,
nout: number,
}>,
filteredOutpoints: Array<{
txid: string,
nout: number,
}>,
blockedChannelUris: Array<string>,
banState: { blacklisted?: boolean, filtered?: boolean, muted?: boolean, blocked?: boolean },
getFile: (string) => void,
streamingUrl: string,
isMature: boolean,
@ -64,11 +56,9 @@ function ClaimPreviewTile(props: Props) {
resolveUri,
claim,
placeholder,
blackListedOutpoints,
filteredOutpoints,
banState,
getFile,
streamingUrl,
blockedChannelUris,
isMature,
showMature,
showHiddenByUser,
@ -139,34 +129,9 @@ function ClaimPreviewTile(props: Props) {
// Unfortunately needed until this is resolved
// https://github.com/lbryio/lbry-sdk/issues/2785
shouldHide = true;
}
// This will be replaced once blocking is done at the wallet server level
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));
} else {
shouldHide =
banState.blacklisted || banState.filtered || (!showHiddenByUser && (banState.muted || banState.blocked));
}
if (shouldHide) {
@ -280,34 +245,4 @@ function ClaimPreviewTile(props: Props) {
);
}
export default React.memo<Props>(withRouter(ClaimPreviewTile), areEqual);
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;
}
export default withRouter(ClaimPreviewTile);

View file

@ -1,12 +1,16 @@
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 ClaimProperties from './view';
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
});
const select = (state, props) => {
const claim = selectClaimForUri(state, props.uri);
return {
claim,
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
claimIsMine: selectClaimIsMine(state, claim),
};
};
export default connect(select, null)(ClaimProperties);

View file

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

View file

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

View file

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

View file

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

View file

@ -1,8 +1,8 @@
import { connect } from 'react-redux';
import {
makeSelectClaimForUri,
makeSelectClaimIsMine,
selectMyChannelClaims,
selectClaimForUri,
selectClaimIsMine,
selectHasChannels,
selectFetchingMyChannels,
makeSelectTagInClaimOrChannelForUri,
} from 'redux/selectors/claims';
@ -14,15 +14,18 @@ import { CommentCreate } from './view';
import { doToast } from 'redux/actions/notifications';
import { DISABLE_SUPPORT_TAG } from 'constants/tags';
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
channels: selectMyChannelClaims(state),
isFetchingChannels: selectFetchingMyChannels(state),
activeChannelClaim: selectActiveChannelClaim(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
settingsByChannelId: selectSettingsByChannelId(state),
supportDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_SUPPORT_TAG)(state),
});
const select = (state, props) => {
const claim = selectClaimForUri(state, props.uri);
return {
activeChannelClaim: selectActiveChannelClaim(state),
hasChannels: selectHasChannels(state),
claim,
claimIsMine: selectClaimIsMine(state, claim),
isFetchingChannels: selectFetchingMyChannels(state),
settingsByChannelId: selectSettingsByChannelId(state),
supportDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_SUPPORT_TAG)(state),
};
};
const perform = (dispatch, ownProps) => ({
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 { doSetPlayingUri } from 'redux/actions/content';
import { doToast } from 'redux/actions/notifications';
import {
makeSelectChannelPermUrlForClaimUri,
makeSelectClaimIsMine,
makeSelectClaimForUri,
} from 'redux/selectors/claims';
import { selectClaimIsMine, selectClaimForUri } from 'redux/selectors/claims';
import { selectActiveChannelClaim } from 'redux/selectors/app';
import { selectModerationDelegatorsById } from 'redux/selectors/comments';
import { selectPlayingUri } from 'redux/selectors/content';
import CommentMenuList from './view';
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
contentChannelPermanentUrl: makeSelectChannelPermUrlForClaimUri(props.uri)(state),
activeChannelClaim: selectActiveChannelClaim(state),
playingUri: selectPlayingUri(state),
moderationDelegatorsById: selectModerationDelegatorsById(state),
});
const select = (state, props) => {
const claim = selectClaimForUri(state, props.uri);
return {
claim,
claimIsMine: selectClaimIsMine(state, claim),
activeChannelClaim: selectActiveChannelClaim(state),
playingUri: selectPlayingUri(state),
moderationDelegatorsById: selectModerationDelegatorsById(state),
};
};
const perform = (dispatch) => ({
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,18 +1,18 @@
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 FilePrice from './view';
const select = (state, props) => ({
costInfo: makeSelectCostInfoForUri(props.uri)(state),
fetching: makeSelectFetchingCostInfoForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state),
claimWasPurchased: makeSelectClaimWasPurchased(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
});
const select = (state, props) => {
const claim = selectClaimForUri(state, props.uri);
const perform = (dispatch) => ({
fetchCostInfo: (uri) => dispatch(doFetchCostInfoForUri(uri)),
});
return {
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 = {
showFullPrice: boolean,
costInfo: ?{ includesData: boolean, cost: number },
fetchCostInfo: string => void,
doFetchCostInfoForUri: (string) => void,
uri: string,
fetching: boolean,
claim: ?{},
@ -35,10 +35,10 @@ class FilePrice extends React.PureComponent<Props> {
}
fetchCost = (props: Props) => {
const { costInfo, fetchCostInfo, uri, fetching, claim } = props;
const { costInfo, doFetchCostInfoForUri, uri, fetching, claim } = props;
if (costInfo === undefined && !fetching && claim) {
fetchCostInfo(uri);
doFetchCostInfoForUri(uri);
}
};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,19 +1,20 @@
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 { makeSelectEditedCollectionForId } from 'redux/selectors/collections';
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
import PreviewOverlayProperties from './view';
const select = (state, props) => {
const claim = makeSelectClaimForUri(props.uri)(state);
const claim = selectClaimForUri(state, props.uri);
const claimId = claim && claim.claim_id;
return {
claim,
editedCollection: makeSelectEditedCollectionForId(claimId)(state),
downloaded: makeSelectFilePartlyDownloaded(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 { 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 ModalConfirmTransaction from './view';
import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.destination)(state),
claim: selectClaimForUri(state, props.destination)(state),
activeChannelClaim: selectActiveChannelClaim(state),
incognito: selectIncognito(state),
});

View file

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

View file

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

View file

@ -5,7 +5,7 @@ import CollectionPage from './view';
import {
makeSelectTitleForUri,
makeSelectThumbnailForUri,
makeSelectClaimIsMine,
selectClaimIsMine,
makeSelectClaimIsPending,
makeSelectClaimForClaimId,
makeSelectChannelForClaimUri,
@ -20,11 +20,7 @@ import {
makeSelectEditedCollectionForId,
} from 'redux/selectors/collections';
import {
doFetchItemsInCollection,
doCollectionDelete,
doCollectionEdit,
} from 'redux/actions/collections';
import { doFetchItemsInCollection, doCollectionDelete, doCollectionEdit } from 'redux/actions/collections';
import { selectUser } from 'redux/selectors/user';
const select = (state, props) => {
@ -44,7 +40,7 @@ const select = (state, props) => {
isResolvingCollection: makeSelectIsResolvingCollectionForId(collectionId)(state),
title: makeSelectTitleForUri(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),
claimIsPending: makeSelectClaimIsPending(uri)(state),
collectionHasEdits: Boolean(makeSelectEditedCollectionForId(collectionId)(state)),

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,7 +3,7 @@ import { Lbryio } from 'lbryinc';
import * as ACTIONS from 'constants/action_types';
import * as REACTION_TYPES from 'constants/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) => {
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) => {
const state = getState();
const myReaction = makeSelectMyReactionForUri(uri)(state);
const claim = makeSelectClaimForUri(uri)(state);
const claim = selectClaimForUri(state, uri);
const claimId = claim.claim_id;
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) => {
const state = getState();
const myReaction = makeSelectMyReactionForUri(uri)(state);
const claim = makeSelectClaimForUri(uri)(state);
const claim = selectClaimForUri(state, uri);
const claimId = claim.claim_id;
const shouldRemove = myReaction === REACTION_TYPES.DISLIKE;

View file

@ -1,7 +1,7 @@
// @flow
import * as ACTIONS from 'constants/action_types';
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 { buildURI, isURIValid } from 'util/lbryURI';
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) => {
const state = getState();
const claim = makeSelectClaimForUri(uri)(state);
const claim = selectClaimForUri(state, uri);
const matureEnabled = selectShowMatureContent(state);
const claimIsMature = makeSelectClaimIsNsfw(uri)(state);

View file

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

View file

@ -1,5 +1,5 @@
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 || {};
@ -127,7 +127,7 @@ export const selectActiveChannelStakedLevel = createSelector(
}
const uri = activeChannelClaim.permanent_url;
const stakedLevel = makeSelectStakedLevelForChannelUri(uri)(state);
const stakedLevel = selectTotalStakedAmountForChannelUri(state, uri)(state);
return stakedLevel;
}

View file

@ -8,7 +8,7 @@ import * as CLAIM from 'constants/claim';
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 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 selectCurrentChannelPage = createSelector(selectState, (state) => state.currentChannelPage || 1);
export const selectCreatingChannel = createSelector(selectState, (state) => state.creatingChannel);
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 selectCurrentChannelPage = (state: State) => selectState(state).currentChannelPage || 1;
export const selectCreatingChannel = (state: State) => selectState(state).creatingChannel;
export const selectCreateChannelError = (state: State) => selectState(state).createChannelError;
export const selectRepostLoading = (state: State) => selectState(state).repostLoading;
export const selectRepostError = (state: State) => selectState(state).repostError;
export const selectClaimsByUri = createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => {
const claims = {};
@ -48,6 +43,21 @@ export const selectClaimsByUri = createSelector(selectClaimIdsByUri, selectClaim
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 selectPendingIds = createSelector(selectState, (state) => Object.keys(state.pendingById) || []);
@ -69,10 +79,9 @@ export const makeSelectClaimIdIsPending = (claimId: string) =>
return Boolean(pendingById[claimId]);
});
export const makeSelectClaimIdForUri = (uri: string) =>
createSelector(selectClaimIdsByUri, (claimIds) => claimIds[uri]);
export const selectClaimIdForUri = (state: State, uri: string) => selectClaimIdsByUri(state)[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]);
@ -85,7 +94,8 @@ export const selectClaimForUri = createCachedSelector(
const validUri = isURIValid(uri);
if (validUri && byUri) {
const claimId = uri && byUri[normalizeURI(uri)];
const normalizedUri = normalizeURI(uri);
const claimId = uri && byUri[normalizedUri];
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)
@ -102,7 +112,7 @@ export const selectClaimForUri = createCachedSelector(
return {
...repostedClaim,
repost_url: normalizeURI(uri),
repost_url: normalizedUri,
repost_channel_url: channelUrl,
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) =>
createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => {
const validUri = isURIValid(uri);
if (validUri && byUri) {
const claimId = uri && byUri[normalizeURI(uri)];
const normalizedUri = normalizeURI(uri);
const claimId = uri && byUri[normalizedUri];
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)
@ -135,7 +147,7 @@ export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true)
return {
...repostedClaim,
repost_url: normalizeURI(uri),
repost_url: normalizedUri,
repost_channel_url: channelUrl,
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) => {
const ids = state.myClaims;
if (!ids) {
@ -161,7 +176,10 @@ export const selectMyClaimsRaw = createSelector(selectState, selectClaimsById, (
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) =>
createSelector(selectAbandoningIds, (ids) => ids.includes(claimId));
@ -173,12 +191,63 @@ export const makeSelectIsAbandoningClaimForUri = (uri: string) =>
});
export const selectMyActiveClaims = createSelector(
selectMyClaimsRaw,
selectMyClaimIdsRaw,
selectAbandoningIds,
(claims, abandoningIds) =>
new Set(claims && claims.map((claim) => claim.claim_id).filter((claimId) => !abandoningIds.includes(claimId)))
(myClaimIds, abandoningIds) => {
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) => {
let uri;
try {
@ -198,15 +267,11 @@ export const makeSelectClaimIsMine = (rawUri: string) => {
});
};
export const selectMyPurchases = createSelector(selectState, (state) => state.myPurchases);
export const selectPurchaseUriSuccess = createSelector(selectState, (state) => state.purchaseUriSuccess);
export const selectMyPurchasesCount = createSelector(selectState, (state) => state.myPurchasesPageTotalResults);
export const selectIsFetchingMyPurchases = createSelector(selectState, (state) => state.fetchingMyPurchases);
export const selectFetchingMyPurchasesError = createSelector(selectState, (state) => state.fetchingMyPurchasesError);
export const selectMyPurchases = (state: State) => selectState(state).myPurchases;
export const selectPurchaseUriSuccess = (state: State) => selectState(state).purchaseUriSuccess;
export const selectMyPurchasesCount = (state: State) => selectState(state).myPurchasesPageTotalResults;
export const selectIsFetchingMyPurchases = (state: State) => selectState(state).fetchingMyPurchases;
export const selectFetchingMyPurchasesError = (state: State) => selectState(state).fetchingMyPurchasesError;
export const makeSelectMyPurchasesForPage = (query: ?string, page: number = 1) =>
createSelector(
@ -270,7 +335,7 @@ export const makeSelectTotalPagesInChannelSearch = (uri: string) =>
export const selectMetadataForUri = createCachedSelector(selectClaimForUri, (claim, uri) => {
const metadata = claim && claim.value;
return metadata || (claim === undefined ? undefined : null);
})((state, uri) => uri);
})((state, uri) => String(uri));
export const makeSelectMetadataForUri = (uri: string) =>
createSelector(makeSelectClaimForUri(uri), (claim) => {
@ -303,7 +368,7 @@ export const selectDateForUri = createCachedSelector(
const dateObj = new Date(timestamp);
return dateObj;
}
)((state, uri) => uri);
)((state, uri) => String(uri));
export const makeSelectAmountForUri = (uri: string) =>
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;
});
export const selectIsFetchingClaimListMine = createSelector(selectState, (state) => state.isFetchingClaimListMine);
export const selectIsFetchingClaimListMine = (state: State) => selectState(state).isFetchingClaimListMine;
export const selectMyClaimsPage = createSelector(selectState, (state) => state.myClaimsPageResults || []);
@ -346,12 +411,8 @@ export const selectMyClaimsPageNumber = createSelector(
(state) => (state.txoPage && state.txoPage.page) || 1
);
export const selectMyClaimsPageItemCount = createSelector(selectState, (state) => state.myClaimsPageTotalResults || 1);
export const selectFetchingMyClaimsPageError = createSelector(
selectState,
(state) => state.fetchingClaimListMinePageError
);
export const selectMyClaimsPageItemCount = (state: State) => selectState(state).myClaimsPageTotalResults || 1;
export const selectFetchingMyClaimsPageError = (state: State) => selectState(state).fetchingClaimListMinePageError;
export const selectMyClaims = createSelector(
selectMyActiveClaims,
@ -403,18 +464,31 @@ export const selectMyClaimsOutpoints = createSelector(selectMyClaims, (myClaims)
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) => {
const ids = state.myChannelClaims;
if (!ids) {
return ids;
export const selectMyChannelClaims = createSelector(selectMyChannelClaimIds, (myChannelClaimIds) => {
if (!myChannelClaimIds) {
return myChannelClaimIds;
}
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 = [];
ids.forEach((id) => {
myChannelClaimIds.forEach((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
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
);
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 selectChannelImportPending = createSelector(selectState, (state) => state.pendingChannelImport);
export const selectChannelImportPending = (state: State) => selectState(state).pendingChannelImport;
export const makeSelectIsUriResolving = (uri: string) =>
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 || {});
@ -541,7 +620,7 @@ export const makeSelectMyChannelPermUrlForName = (name: string) =>
export const selectTagsForUri = createCachedSelector(selectMetadataForUri, (metadata: ?GenericMetadata) => {
return (metadata && metadata.tags) || [];
})((state, uri) => uri);
})((state, uri) => String(uri));
export const makeSelectTagsForUri = (uri: string) =>
createSelector(makeSelectMetadataForUri(uri), (metadata: ?GenericMetadata) => {
@ -592,9 +671,8 @@ export const makeSelectSupportsForUri = (uri: string) =>
return total;
});
export const selectUpdatingChannel = createSelector(selectState, (state) => state.updatingChannel);
export const selectUpdateChannelError = createSelector(selectState, (state) => state.updateChannelError);
export const selectUpdatingChannel = (state: State) => selectState(state).updatingChannel;
export const selectUpdateChannelError = (state: State) => selectState(state).updateChannelError;
export const makeSelectReflectingClaimForUri = (uri: string) =>
createSelector(selectClaimIdsByUri, selectReflectingById, (claimIdsByUri, reflectingById) => {
@ -638,39 +716,34 @@ export const makeSelectClaimIsStreamPlaceholder = (uri: string) =>
return Boolean(claim.value_type === 'stream' && !claim.value.source);
});
export const makeSelectTotalStakedAmountForChannelUri = (uri: string) =>
createSelector(makeSelectClaimForUri(uri), (claim) => {
if (!claim || !claim.amount || !claim.meta || !claim.meta.support_amount) {
return 0;
}
export const selectTotalStakedAmountForChannelUri = createCachedSelector(selectClaimForUri, (claim) => {
if (!claim || !claim.amount || !claim.meta || !claim.meta.support_amount) {
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) =>
createSelector(makeSelectTotalStakedAmountForChannelUri(uri), (amount) => {
let level = 1;
switch (true) {
case amount >= CLAIM.LEVEL_2_STAKED_AMOUNT && amount < CLAIM.LEVEL_3_STAKED_AMOUNT:
level = 2;
break;
case amount >= CLAIM.LEVEL_3_STAKED_AMOUNT && amount < CLAIM.LEVEL_4_STAKED_AMOUNT:
level = 3;
break;
case amount >= CLAIM.LEVEL_4_STAKED_AMOUNT && amount < CLAIM.LEVEL_5_STAKED_AMOUNT:
level = 4;
break;
case amount >= CLAIM.LEVEL_5_STAKED_AMOUNT:
level = 5;
break;
}
return level;
});
export const selectStakedLevelForChannelUri = createCachedSelector(selectTotalStakedAmountForChannelUri, (amount) => {
let level = 1;
switch (true) {
case amount >= CLAIM.LEVEL_2_STAKED_AMOUNT && amount < CLAIM.LEVEL_3_STAKED_AMOUNT:
level = 2;
break;
case amount >= CLAIM.LEVEL_3_STAKED_AMOUNT && amount < CLAIM.LEVEL_4_STAKED_AMOUNT:
level = 3;
break;
case amount >= CLAIM.LEVEL_4_STAKED_AMOUNT && amount < CLAIM.LEVEL_5_STAKED_AMOUNT:
level = 4;
break;
case amount >= CLAIM.LEVEL_5_STAKED_AMOUNT:
level = 5;
break;
}
return level;
})((state, uri) => String(uri));
export const selectUpdatingCollection = createSelector(selectState, (state) => state.updatingCollection);
export const selectUpdateCollectionError = createSelector(selectState, (state) => state.updateCollectionError);
export const selectCreatingCollection = createSelector(selectState, (state) => state.creatingCollection);
export const selectCreateCollectionError = createSelector(selectState, (state) => state.createCollectionError);
export const selectUpdatingCollection = (state: State) => selectState(state).updatingCollection;
export const selectUpdateCollectionError = (state: State) => selectState(state).updateCollectionError;
export const selectCreatingCollection = (state: State) => selectState(state).creatingCollection;
export const selectCreateCollectionError = (state: State) => selectState(state).createCollectionError;

View file

@ -4,14 +4,15 @@ import { createCachedSelector } from 're-reselect';
import { selectMutedChannels } from 'redux/selectors/blocked';
import { selectShowMatureContent } from 'redux/selectors/settings';
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';
type State = { comments: CommentsState };
type State = { comments: CommentsState, claims: any };
const selectState = (state) => state.comments || {};
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 selectIsFetchingCommentsById = (state: State) => selectState(state).isLoadingById;
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 selectCommentIdsForUri = (state: State, uri: string) => {
const claimId = selectClaimIdForUri(state, uri);
const commentIdsByClaimId = selectCommentIdsByClaimId(state);
return commentIdsByClaimId[claimId];
};
export const makeSelectCommentIdsForUri = (uri: string) =>
createSelector(selectState, selectCommentsByUri, selectClaimsById, (state, byUri) => {
const claimId = byUri[uri];