PremiumBadge: retrieve membership db internally instead of from parent (#1764)

* DRY up membership selector

Selectors should be chained up, not copy/pasted.

* PremiumBadge: retrieve membership db internally instead of from parent

## Ticket
1753 odyseeMembershipByUri function causing unnecessary renders

## Issue
While the rendering issue in the ticket is due to the way the props are defined, it also surfaced a prop-drilling issue with PremiumBadge.

Instead of asking the parent for the membership db, it can retrieve from Redux itself. This prevents the prop from polluting 2 levels of components and causing unnecessary renders.

## Approach
- Make `PremiumBadge` accept `uri` like most other components.
- I still leave the `membership` prop as (i.e. parent can still pass it directly). In some cases (e.g. `livestreamComment`, `page/odyseeMembership`), the parent itself needs the same data, so we don't need to derive it twice.
This commit is contained in:
infinite-persistence 2022-07-02 03:40:06 +08:00 committed by GitHub
parent 6ceb0d7d8f
commit dbb9ee7ac6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 46 additions and 85 deletions

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectMyChannelClaims, selectClaimsByUri, selectOdyseeMembershipForUri } from 'redux/selectors/claims'; import { selectMyChannelClaims, selectClaimsByUri } from 'redux/selectors/claims';
import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app'; import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
import { doSetActiveChannel, doSetIncognito } from 'redux/actions/app'; import { doSetActiveChannel, doSetIncognito } from 'redux/actions/app';
import { doFetchUserMemberships } from 'redux/actions/user'; import { doFetchUserMemberships } from 'redux/actions/user';
@ -16,7 +16,6 @@ const select = (state, props) => {
channels: selectMyChannelClaims(state), channels: selectMyChannelClaims(state),
activeChannelClaim: storeSelection ? defaultChannelClaim : activeChannelClaim, activeChannelClaim: storeSelection ? defaultChannelClaim : activeChannelClaim,
incognito: selectIncognito(state), incognito: selectIncognito(state),
odyseeMembershipByUri: (uri) => selectOdyseeMembershipForUri(state, uri),
claimsByUri: selectClaimsByUri(state), claimsByUri: selectClaimsByUri(state),
}; };
}; };

View file

@ -9,7 +9,7 @@ import ChannelTitle from 'component/channelTitle';
import Icon from 'component/common/icon'; import Icon from 'component/common/icon';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
import useGetUserMemberships from 'effects/use-get-user-memberships'; import useGetUserMemberships from 'effects/use-get-user-memberships';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
type Props = { type Props = {
selectedChannelUrl: string, // currently selected channel selectedChannelUrl: string, // currently selected channel
@ -138,13 +138,10 @@ type ListItemProps = {
isSelected?: boolean, isSelected?: boolean,
claimsByUri: { [string]: any }, claimsByUri: { [string]: any },
doFetchUserMemberships: (claimIdCsv: string) => void, doFetchUserMemberships: (claimIdCsv: string) => void,
odyseeMembershipByUri: (uri: string) => string,
}; };
function ChannelListItem(props: ListItemProps) { function ChannelListItem(props: ListItemProps) {
const { uri, isSelected = false, claimsByUri, doFetchUserMemberships, odyseeMembershipByUri } = props; const { uri, isSelected = false, claimsByUri, doFetchUserMemberships } = props;
const membership = odyseeMembershipByUri(uri);
const shouldFetchUserMemberships = true; const shouldFetchUserMemberships = true;
useGetUserMemberships(shouldFetchUserMemberships, [uri], claimsByUri, doFetchUserMemberships, [uri]); useGetUserMemberships(shouldFetchUserMemberships, [uri], claimsByUri, doFetchUserMemberships, [uri]);
@ -153,7 +150,7 @@ function ChannelListItem(props: ListItemProps) {
<div className={classnames('channel__list-item', { 'channel__list-item--selected': isSelected })}> <div className={classnames('channel__list-item', { 'channel__list-item--selected': isSelected })}>
<ChannelThumbnail uri={uri} hideStakedIndicator xsmall noLazyLoad /> <ChannelThumbnail uri={uri} hideStakedIndicator xsmall noLazyLoad />
<ChannelTitle uri={uri} /> <ChannelTitle uri={uri} />
<PremiumBadge membership={membership} /> <PremiumBadge uri={uri} />
{isSelected && <Icon icon={ICONS.DOWN} />} {isSelected && <Icon icon={ICONS.DOWN} />}
</div> </div>
); );

View file

@ -4,7 +4,6 @@ import {
selectClaimForUri, selectClaimForUri,
selectIsUriResolving, selectIsUriResolving,
selectClaimsByUri, selectClaimsByUri,
selectOdyseeMembershipForUri,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { doResolveUri } from 'redux/actions/claims'; import { doResolveUri } from 'redux/actions/claims';
import { doFetchUserMemberships } from 'redux/actions/user'; import { doFetchUserMemberships } from 'redux/actions/user';
@ -14,7 +13,6 @@ const select = (state, props) => ({
thumbnail: selectThumbnailForUri(state, props.uri), thumbnail: selectThumbnailForUri(state, props.uri),
claim: selectClaimForUri(state, props.uri), claim: selectClaimForUri(state, props.uri),
isResolving: selectIsUriResolving(state, props.uri), isResolving: selectIsUriResolving(state, props.uri),
odyseeMembership: selectOdyseeMembershipForUri(state, props.uri),
claimsByUri: selectClaimsByUri(state), claimsByUri: selectClaimsByUri(state),
}); });

View file

@ -8,7 +8,7 @@ import FreezeframeWrapper from 'component/fileThumbnail/FreezeframeWrapper';
import OptimizedImage from 'component/optimizedImage'; import OptimizedImage from 'component/optimizedImage';
import { AVATAR_DEFAULT } from 'config'; import { AVATAR_DEFAULT } from 'config';
import useGetUserMemberships from 'effects/use-get-user-memberships'; import useGetUserMemberships from 'effects/use-get-user-memberships';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
type Props = { type Props = {
thumbnail: ?string, thumbnail: ?string,
@ -29,7 +29,6 @@ type Props = {
setThumbUploadError: (boolean) => void, setThumbUploadError: (boolean) => void,
ThumbUploadError: boolean, ThumbUploadError: boolean,
claimsByUri: { [string]: any }, claimsByUri: { [string]: any },
odyseeMembership: string,
doFetchUserMemberships: (claimIdCsv: string) => void, doFetchUserMemberships: (claimIdCsv: string) => void,
showMemberBadge?: boolean, showMemberBadge?: boolean,
isChannel?: boolean, isChannel?: boolean,
@ -55,7 +54,6 @@ function ChannelThumbnail(props: Props) {
setThumbUploadError, setThumbUploadError,
ThumbUploadError, ThumbUploadError,
claimsByUri, claimsByUri,
odyseeMembership,
doFetchUserMemberships, doFetchUserMemberships,
showMemberBadge, showMemberBadge,
isChannel, isChannel,
@ -71,7 +69,7 @@ function ChannelThumbnail(props: Props) {
const showThumb = (!obscure && !!thumbnail) || thumbnailPreview; const showThumb = (!obscure && !!thumbnail) || thumbnailPreview;
const badgeProps = { const badgeProps = {
membership: odyseeMembership, uri,
linkPage: isChannel, linkPage: isChannel,
placement: isChannel ? 'bottom' : undefined, placement: isChannel ? 'bottom' : undefined,
hideTooltip, hideTooltip,

View file

@ -46,7 +46,7 @@ import OptimizedImage from 'component/optimizedImage';
import { getChannelFromClaim } from 'util/claim'; import { getChannelFromClaim } from 'util/claim';
import { parseSticker } from 'util/comments'; import { parseSticker } from 'util/comments';
import { useIsMobile } from 'effects/use-screensize'; import { useIsMobile } from 'effects/use-screensize';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
import Spinner from 'component/spinner'; import Spinner from 'component/spinner';
const AUTO_EXPAND_ALL_REPLIES = false; const AUTO_EXPAND_ALL_REPLIES = false;

View file

@ -17,7 +17,7 @@ import Icon from 'component/common/icon';
import MarkdownPreview from 'component/common/markdown-preview'; import MarkdownPreview from 'component/common/markdown-preview';
import OptimizedImage from 'component/optimizedImage'; import OptimizedImage from 'component/optimizedImage';
import React from 'react'; import React from 'react';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
type Props = { type Props = {
comment: Comment, comment: Comment,

View file

@ -0,0 +1,9 @@
import { connect } from 'react-redux';
import PremiumBadge from './view';
import { selectOdyseeMembershipForUri } from 'redux/selectors/claims';
const select = (state, props) => ({
membership: props.uri ? selectOdyseeMembershipForUri(state, props.uri) : props.membership,
});
export default connect(select)(PremiumBadge);

View file

@ -1,14 +1,15 @@
// @flow // @flow
import 'scss/component/_comment-badge.scss'; import 'scss/component/_comment-badge.scss';
import React from 'react';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import React from 'react'; import CommentBadge from 'component/common/comment-badge';
import CommentBadge from './comment-badge';
import Button from 'component/button'; import Button from 'component/button';
type Props = { type Props = {
membership: ?string, uri?: string,
membership: ?string, // Retrieved from redux if `uri` is provided; else uses the given `membership` directly.
linkPage?: boolean, linkPage?: boolean,
placement?: string, placement?: string,
className?: string, className?: string,

View file

@ -8,7 +8,7 @@ import { selectUserVerifiedEmail, selectUser, selectOdyseeMembershipName } from
import { selectHomepageData } from 'redux/selectors/settings'; import { selectHomepageData } from 'redux/selectors/settings';
import { doSignOut } from 'redux/actions/app'; import { doSignOut } from 'redux/actions/app';
import { selectUnseenNotificationCount } from 'redux/selectors/notifications'; import { selectUnseenNotificationCount } from 'redux/selectors/notifications';
import { selectPurchaseUriSuccess, selectOdyseeMembershipForUri } from 'redux/selectors/claims'; import { selectPurchaseUriSuccess } from 'redux/selectors/claims';
import SideNavigation from './view'; import SideNavigation from './view';
@ -22,7 +22,6 @@ const select = (state) => ({
user: selectUser(state), user: selectUser(state),
homepageData: selectHomepageData(state), homepageData: selectHomepageData(state),
odyseeMembership: selectOdyseeMembershipName(state), odyseeMembership: selectOdyseeMembershipName(state),
odyseeMembershipByUri: (uri) => selectOdyseeMembershipForUri(state, uri),
}); });
export default connect(select, { export default connect(select, {

View file

@ -17,7 +17,7 @@ import { useIsMobile, useIsLargeScreen } from 'effects/use-screensize';
import { GetLinksData } from 'util/buildHomepage'; import { GetLinksData } from 'util/buildHomepage';
import { platform } from 'util/platform'; import { platform } from 'util/platform';
import { DOMAIN, ENABLE_UI_NOTIFICATIONS, ENABLE_NO_SOURCE_CLAIMS } from 'config'; import { DOMAIN, ENABLE_UI_NOTIFICATIONS, ENABLE_NO_SOURCE_CLAIMS } from 'config';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
const touch = platform.isTouch(); const touch = platform.isTouch();
@ -146,7 +146,6 @@ type Props = {
homepageData: any, homepageData: any,
doClearClaimSearch: () => void, doClearClaimSearch: () => void,
odyseeMembership: ?string, odyseeMembership: ?string,
odyseeMembershipByUri: (uri: string) => string,
doFetchLastActiveSubs: (force?: boolean, count?: number) => void, doFetchLastActiveSubs: (force?: boolean, count?: number) => void,
}; };
@ -168,7 +167,6 @@ function SideNavigation(props: Props) {
followedTags, followedTags,
doClearClaimSearch, doClearClaimSearch,
odyseeMembership, odyseeMembership,
odyseeMembershipByUri,
doFetchLastActiveSubs, doFetchLastActiveSubs,
} = props; } = props;
@ -352,11 +350,7 @@ function SideNavigation(props: Props) {
</li> </li>
)} )}
{displayedSubscriptions.map((subscription) => ( {displayedSubscriptions.map((subscription) => (
<SubscriptionListItem <SubscriptionListItem key={subscription.uri} subscription={subscription} />
key={subscription.uri}
subscription={subscription}
odyseeMembershipByUri={odyseeMembershipByUri}
/>
))} ))}
{!!subscriptionFilter && !displayedSubscriptions.length && ( {!!subscriptionFilter && !displayedSubscriptions.length && (
<li> <li>
@ -577,15 +571,12 @@ function SideNavigation(props: Props) {
type SubItemProps = { type SubItemProps = {
subscription: Subscription, subscription: Subscription,
odyseeMembershipByUri: (uri: string) => string,
}; };
function SubscriptionListItem(props: SubItemProps) { function SubscriptionListItem(props: SubItemProps) {
const { subscription, odyseeMembershipByUri } = props; const { subscription } = props;
const { uri, channelName } = subscription; const { uri, channelName } = subscription;
const membership = odyseeMembershipByUri(uri);
return ( return (
<li className="navigation-link__wrapper navigation__subscription"> <li className="navigation-link__wrapper navigation__subscription">
<Button <Button
@ -598,7 +589,7 @@ function SubscriptionListItem(props: SubItemProps) {
<ClaimPreviewTitle uri={uri} /> <ClaimPreviewTitle uri={uri} />
<span dir="auto" className="channel-name"> <span dir="auto" className="channel-name">
{channelName} {channelName}
<PremiumBadge membership={membership} /> <PremiumBadge uri={uri} />
</span> </span>
</div> </div>
</Button> </Button>

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectClaimForUri, selectOdyseeMembershipForUri } from 'redux/selectors/claims'; import { selectClaimForUri } from 'redux/selectors/claims';
import TextareaSuggestionsItem from './view'; import TextareaSuggestionsItem from './view';
import { formatLbryChannelName } from 'util/url'; import { formatLbryChannelName } from 'util/url';
import { getClaimTitle } from 'util/claim'; import { getClaimTitle } from 'util/claim';
@ -12,7 +12,6 @@ const select = (state, props) => {
return { return {
claimLabel: claim && formatLbryChannelName(claim.canonical_url), claimLabel: claim && formatLbryChannelName(claim.canonical_url),
claimTitle: claim && getClaimTitle(claim), claimTitle: claim && getClaimTitle(claim),
odyseeMembershipByUri: selectOdyseeMembershipForUri(state, uri),
}; };
}; };

View file

@ -1,18 +1,17 @@
// @flow // @flow
import ChannelThumbnail from 'component/channelThumbnail'; import ChannelThumbnail from 'component/channelThumbnail';
import React from 'react'; import React from 'react';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
type Props = { type Props = {
claimLabel?: string, claimLabel?: string,
claimTitle?: string, claimTitle?: string,
emote?: any, emote?: any,
uri?: string, uri?: string,
odyseeMembershipByUri: ?string,
}; };
export default function TextareaSuggestionsItem(props: Props) { export default function TextareaSuggestionsItem(props: Props) {
const { claimLabel, claimTitle, emote, uri, odyseeMembershipByUri, ...autocompleteProps } = props; const { claimLabel, claimTitle, emote, uri, ...autocompleteProps } = props;
if (emote) { if (emote) {
const { name: value, url, unicode } = emote; const { name: value, url, unicode } = emote;
@ -41,7 +40,7 @@ export default function TextareaSuggestionsItem(props: Props) {
<span className="textarea-suggestion__title">{claimTitle || value}</span> <span className="textarea-suggestion__title">{claimTitle || value}</span>
<span className="textarea-suggestion__value"> <span className="textarea-suggestion__value">
{value} {value}
<PremiumBadge membership={odyseeMembershipByUri} /> <PremiumBadge uri={uri} />
</span> </span>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { normalizeURI } from 'util/lbryURI'; import { normalizeURI } from 'util/lbryURI';
import { doResolveUri } from 'redux/actions/claims'; import { doResolveUri } from 'redux/actions/claims';
import { selectIsUriResolving, selectClaimForUri, selectOdyseeMembershipForUri } from 'redux/selectors/claims'; import { selectIsUriResolving, selectClaimForUri } from 'redux/selectors/claims';
import UriIndicator from './view'; import UriIndicator from './view';
const select = (state, props) => { const select = (state, props) => {
@ -14,7 +14,6 @@ const select = (state, props) => {
claim: selectClaimForUri(state, props.uri), claim: selectClaimForUri(state, props.uri),
isResolvingUri: selectIsUriResolving(state, props.uri), isResolvingUri: selectIsUriResolving(state, props.uri),
uri, uri,
odyseeMembership: selectOdyseeMembershipForUri(state, props.uri),
}; };
}; };

View file

@ -3,7 +3,7 @@ import type { Node } from 'react';
import React from 'react'; import React from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import Button from 'component/button'; import Button from 'component/button';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
import { stripLeadingAtSign } from 'util/string'; import { stripLeadingAtSign } from 'util/string';
type ChannelInfo = { uri: string, name: string, title: string }; type ChannelInfo = { uri: string, name: string, title: string };
@ -23,7 +23,6 @@ type Props = {
// --- redux --- // --- redux ---
claim: ?Claim, claim: ?Claim,
isResolvingUri: boolean, isResolvingUri: boolean,
odyseeMembership: string,
comment?: boolean, comment?: boolean,
resolveUri: (string) => void, resolveUri: (string) => void,
}; };
@ -94,7 +93,6 @@ class UriIndicator extends React.PureComponent<Props> {
hideAnonymous = false, hideAnonymous = false,
showAtSign, showAtSign,
className, className,
odyseeMembership,
comment, comment,
showMemberBadge = true, showMemberBadge = true,
} = this.props; } = this.props;
@ -127,7 +125,7 @@ class UriIndicator extends React.PureComponent<Props> {
const inner = ( const inner = (
<span dir="auto" className={classnames('channel-name', { 'channel-name--inline': inline })}> <span dir="auto" className={classnames('channel-name', { 'channel-name--inline': inline })}>
<p>{showAtSign ? channelName : stripLeadingAtSign(channelTitle)}</p> <p>{showAtSign ? channelName : stripLeadingAtSign(channelTitle)}</p>
{!comment && showMemberBadge && <PremiumBadge membership={odyseeMembership} />} {!comment && showMemberBadge && <PremiumBadge uri={uri} />}
</span> </span>
); );

View file

@ -1,10 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import { selectClaimForUri, selectGeoRestrictionForUri, selectIsUriResolving } from 'redux/selectors/claims';
selectClaimForUri,
selectGeoRestrictionForUri,
selectIsUriResolving,
selectOdyseeMembershipForUri,
} from 'redux/selectors/claims';
import WunderbarSuggestion from './view'; import WunderbarSuggestion from './view';
const select = (state, props) => { const select = (state, props) => {
@ -14,7 +9,6 @@ const select = (state, props) => {
claim: selectClaimForUri(state, uri), claim: selectClaimForUri(state, uri),
isResolvingUri: selectIsUriResolving(state, uri), isResolvingUri: selectIsUriResolving(state, uri),
geoRestriction: selectGeoRestrictionForUri(state, props.uri), geoRestriction: selectGeoRestrictionForUri(state, props.uri),
odyseeMembership: selectOdyseeMembershipForUri(state, uri),
}; };
}; };

View file

@ -6,18 +6,17 @@ import FileThumbnail from 'component/fileThumbnail';
import ChannelThumbnail from 'component/channelThumbnail'; import ChannelThumbnail from 'component/channelThumbnail';
import FileProperties from 'component/previewOverlayProperties'; import FileProperties from 'component/previewOverlayProperties';
import ClaimProperties from 'component/claimProperties'; import ClaimProperties from 'component/claimProperties';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
type Props = { type Props = {
claim: ?Claim, claim: ?Claim,
uri: string, uri: string,
isResolvingUri: boolean, isResolvingUri: boolean,
geoRestriction: ?GeoRestriction, geoRestriction: ?GeoRestriction,
odyseeMembership: ?string,
}; };
export default function WunderbarSuggestion(props: Props) { export default function WunderbarSuggestion(props: Props) {
const { claim, uri, isResolvingUri, odyseeMembership, geoRestriction } = props; const { claim, uri, isResolvingUri, geoRestriction } = props;
if (isResolvingUri) { if (isResolvingUri) {
return ( return (
@ -69,7 +68,7 @@ export default function WunderbarSuggestion(props: Props) {
<div className="wunderbar__suggestion-title">{claim.value.title}</div> <div className="wunderbar__suggestion-title">{claim.value.title}</div>
<div className="wunderbar__suggestion-name"> <div className="wunderbar__suggestion-name">
{isChannel ? claim.name : (claim.signing_channel && claim.signing_channel.name) || __('Anonymous')} {isChannel ? claim.name : (claim.signing_channel && claim.signing_channel.name) || __('Anonymous')}
<PremiumBadge membership={odyseeMembership} /> <PremiumBadge uri={uri} />
</div> </div>
</span> </span>
</div> </div>

View file

@ -6,7 +6,6 @@ import {
selectCurrentChannelPage, selectCurrentChannelPage,
selectClaimForUri, selectClaimForUri,
makeSelectClaimIsPending, makeSelectClaimIsPending,
selectOdyseeMembershipForChannelId,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { selectMyUnpublishedCollections } from 'redux/selectors/collections'; import { selectMyUnpublishedCollections } from 'redux/selectors/collections';
import { selectBlacklistedOutpointMap, doFetchSubCount, selectSubCountForUri } from 'lbryinc'; import { selectBlacklistedOutpointMap, doFetchSubCount, selectSubCountForUri } from 'lbryinc';
@ -38,7 +37,6 @@ const select = (state, props) => {
mutedChannels: selectMutedChannels(state), mutedChannels: selectMutedChannels(state),
unpublishedCollections: selectMyUnpublishedCollections(state), unpublishedCollections: selectMyUnpublishedCollections(state),
lang: selectLanguage(state), lang: selectLanguage(state),
odyseeMembership: selectOdyseeMembershipForChannelId(state, claim.claim_id),
}; };
}; };

View file

@ -28,7 +28,7 @@ import TruncatedText from 'component/common/truncated-text';
import PlaceholderTx from 'static/img/placeholderTx.gif'; import PlaceholderTx from 'static/img/placeholderTx.gif';
import Tooltip from 'component/common/tooltip'; import Tooltip from 'component/common/tooltip';
import { toCompactNotation } from 'util/string'; import { toCompactNotation } from 'util/string';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
export const PAGE_VIEW_QUERY = `view`; export const PAGE_VIEW_QUERY = `view`;
export const DISCUSSION_PAGE = `discussion`; export const DISCUSSION_PAGE = `discussion`;
@ -61,7 +61,6 @@ type Props = {
mutedChannels: Array<string>, mutedChannels: Array<string>,
unpublishedCollections: CollectionGroup, unpublishedCollections: CollectionGroup,
lang: string, lang: string,
odyseeMembership: string,
}; };
function ChannelPage(props: Props) { function ChannelPage(props: Props) {
@ -82,7 +81,6 @@ function ChannelPage(props: Props) {
mutedChannels, mutedChannels,
unpublishedCollections, unpublishedCollections,
lang, lang,
odyseeMembership,
} = props; } = props;
const { const {
push, push,
@ -251,7 +249,7 @@ function ChannelPage(props: Props) {
<TruncatedText lines={2} showTooltip> <TruncatedText lines={2} showTooltip>
{title || (channelName && '@' + channelName)} {title || (channelName && '@' + channelName)}
</TruncatedText> </TruncatedText>
<PremiumBadge membership={odyseeMembership} /> <PremiumBadge uri={uri} />
</h1> </h1>
<div className="channel__meta"> <div className="channel__meta">
<Tooltip title={formattedSubCount} followCursor placement="top"> <Tooltip title={formattedSubCount} followCursor placement="top">

View file

@ -14,7 +14,7 @@ import Card from 'component/common/card';
import MembershipSplash from 'component/membershipSplash'; import MembershipSplash from 'component/membershipSplash';
import Button from 'component/button'; import Button from 'component/button';
import ChannelSelector from 'component/channelSelector'; import ChannelSelector from 'component/channelSelector';
import PremiumBadge from 'component/common/premium-badge'; import PremiumBadge from 'component/premiumBadge';
import I18nMessage from 'component/i18nMessage'; import I18nMessage from 'component/i18nMessage';
import useGetUserMemberships from 'effects/use-get-user-memberships'; import useGetUserMemberships from 'effects/use-get-user-memberships';
import usePersistedState from 'effects/use-persisted-state'; import usePersistedState from 'effects/use-persisted-state';

View file

@ -820,41 +820,26 @@ export const selectIsMyChannelCountOverLimit = createSelector(
); );
/** /**
* Given a uri of a channel, check if there an Odysee membership value * Given a uri of a channel, check if there is an Odysee membership value.
* @param state * @param state
* @param uri * @param uri
* @returns {*} * @returns {*}
*/ */
export const selectOdyseeMembershipForUri = (state: State, uri: string) => { export const selectOdyseeMembershipForUri = (state: State, uri: string) => {
const claim = selectClaimForUri(state, uri); const claim = selectClaimForUri(state, uri);
const channelId = getChannelIdFromClaim(claim);
const uploaderChannelClaimId = getChannelIdFromClaim(claim); return channelId ? selectOdyseeMembershipForChannelId(state, channelId) : undefined;
// looks for the uploader id
if (uploaderChannelClaimId) {
const matchingMembershipOfUser =
state.user &&
state.user.odyseeMembershipsPerClaimIds &&
state.user.odyseeMembershipsPerClaimIds[uploaderChannelClaimId];
return matchingMembershipOfUser;
}
return undefined;
}; };
/** /**
* Given a uri of a channel, check if there an Odysee membership value * Given a channel ID, check if there is an Odysee membership value.
* @param state * @param state
* @param channelId * @param channelId
* @returns {*} * @returns {*}
*/ */
export const selectOdyseeMembershipForChannelId = (state: State, channelId: string) => { export const selectOdyseeMembershipForChannelId = (state: State, channelId: string) => {
// looks for the uploader id // TODO: should access via selector, not from `state` directly.
const matchingMembershipOfUser = return state.user && state.user.odyseeMembershipsPerClaimIds && state.user.odyseeMembershipsPerClaimIds[channelId];
state.user && state.user.odyseeMembershipsPerClaimIds && state.user.odyseeMembershipsPerClaimIds[channelId];
return matchingMembershipOfUser;
}; };
export const selectGeoRestrictionForUri = createCachedSelector( export const selectGeoRestrictionForUri = createCachedSelector(