6e34282cdc
As of this commit, only the Channel Page is fetching the data through the new API, which has the viewer count correctly populated. For both "0" and "undefined", continue to show as "LIVE".
298 lines
10 KiB
JavaScript
298 lines
10 KiB
JavaScript
// @flow
|
|
import React from 'react';
|
|
import classnames from 'classnames';
|
|
import { NavLink, withRouter } from 'react-router-dom';
|
|
import ClaimPreviewProgress from 'component/claimPreviewProgress';
|
|
import FileThumbnail from 'component/fileThumbnail';
|
|
import UriIndicator from 'component/uriIndicator';
|
|
import Icon from 'component/common/icon';
|
|
import TruncatedText from 'component/common/truncated-text';
|
|
import DateTime from 'component/dateTime';
|
|
import LivestreamDateTime from 'component/livestreamDateTime';
|
|
import ChannelThumbnail from 'component/channelThumbnail';
|
|
import FileViewCountInline from 'component/fileViewCountInline';
|
|
// 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 } from 'util/lbryURI';
|
|
import PreviewOverlayProperties from 'component/previewOverlayProperties';
|
|
import FileDownloadLink from 'component/fileDownloadLink';
|
|
import FileHideRecommendation from 'component/fileHideRecommendation';
|
|
import FileWatchLaterLink from 'component/fileWatchLaterLink';
|
|
import ClaimRepostAuthor from 'component/claimRepostAuthor';
|
|
import ClaimMenuList from 'component/claimMenuList';
|
|
import CollectionPreviewOverlay from 'component/collectionPreviewOverlay';
|
|
import * as ICONS from 'constants/icons';
|
|
import { FYP_ID } from 'constants/urlParams';
|
|
// $FlowFixMe cannot resolve ...
|
|
import PlaceholderTx from 'static/img/placeholderTx.gif';
|
|
|
|
type Props = {
|
|
uri: string,
|
|
date?: any,
|
|
claim: ?Claim,
|
|
mediaDuration?: string,
|
|
resolveUri: (string) => void,
|
|
isResolvingUri: boolean,
|
|
history: { push: (string) => void },
|
|
thumbnail: string,
|
|
title: string,
|
|
placeholder: boolean,
|
|
banState: { blacklisted?: boolean, filtered?: boolean, muted?: boolean, blocked?: boolean },
|
|
getFile: (string) => void,
|
|
streamingUrl: string,
|
|
isMature: boolean,
|
|
showMature: boolean,
|
|
showHiddenByUser?: boolean,
|
|
properties?: (Claim) => void,
|
|
collectionId?: string,
|
|
fypId?: string,
|
|
showNoSourceClaims?: boolean,
|
|
isLivestream: boolean,
|
|
viewCount: string,
|
|
isLivestreamActive: boolean,
|
|
livestreamViewerCount: ?number,
|
|
swipeLayout: boolean,
|
|
};
|
|
|
|
// preview image cards used in related video functionality, channel overview page and homepage
|
|
function ClaimPreviewTile(props: Props) {
|
|
const {
|
|
history,
|
|
uri,
|
|
date,
|
|
isResolvingUri,
|
|
thumbnail,
|
|
title,
|
|
resolveUri,
|
|
claim,
|
|
placeholder,
|
|
banState,
|
|
getFile,
|
|
streamingUrl,
|
|
isMature,
|
|
showMature,
|
|
showHiddenByUser,
|
|
properties,
|
|
showNoSourceClaims,
|
|
isLivestream,
|
|
isLivestreamActive,
|
|
livestreamViewerCount,
|
|
collectionId,
|
|
fypId,
|
|
mediaDuration,
|
|
viewCount,
|
|
swipeLayout = false,
|
|
} = props;
|
|
const isRepost = claim && claim.repost_channel_url;
|
|
const isCollection = claim && claim.value_type === 'collection';
|
|
const isStream = claim && claim.value_type === 'stream';
|
|
// $FlowFixMe
|
|
const isPlayable =
|
|
claim &&
|
|
// $FlowFixMe
|
|
claim.value &&
|
|
// $FlowFixMe
|
|
claim.value.stream_type &&
|
|
// $FlowFixMe
|
|
(claim.value.stream_type === 'audio' || claim.value.stream_type === 'video');
|
|
const collectionClaimId = isCollection && claim && claim.claim_id;
|
|
const shouldFetch = claim === undefined;
|
|
const thumbnailUrl = useGetThumbnail(uri, claim, streamingUrl, getFile, placeholder) || thumbnail;
|
|
const canonicalUrl = claim && claim.canonical_url;
|
|
const repostedContentUri = claim && (claim.reposted_claim ? claim.reposted_claim.permanent_url : claim.permanent_url);
|
|
const listId = collectionId || collectionClaimId;
|
|
const navigateUrl =
|
|
formatLbryUrlForWeb(canonicalUrl || uri || '/') +
|
|
(listId ? generateListSearchUrlParams(listId) : '') +
|
|
(fypId ? `?${FYP_ID}=${fypId}` : ''); // sigh...
|
|
const navLinkProps = {
|
|
to: navigateUrl,
|
|
onClick: (e) => e.stopPropagation(),
|
|
};
|
|
|
|
let isValid = false;
|
|
if (uri) {
|
|
try {
|
|
parseURI(uri);
|
|
isValid = true;
|
|
} catch (e) {
|
|
isValid = false;
|
|
}
|
|
}
|
|
|
|
const signingChannel = claim && claim.signing_channel;
|
|
const isChannel = claim && claim.value_type === 'channel';
|
|
const channelUri = !isChannel ? signingChannel && signingChannel.permanent_url : claim && claim.permanent_url;
|
|
const channelTitle = signingChannel && ((signingChannel.value && signingChannel.value.title) || signingChannel.name);
|
|
|
|
// Aria-label value for claim preview
|
|
let ariaLabelData = isChannel ? title : formatClaimPreviewTitle(title, channelTitle, date, mediaDuration);
|
|
|
|
function handleClick(e) {
|
|
if (navigateUrl) {
|
|
history.push(navigateUrl);
|
|
}
|
|
}
|
|
|
|
React.useEffect(() => {
|
|
if (isValid && !isResolvingUri && shouldFetch && uri) {
|
|
resolveUri(uri);
|
|
}
|
|
}, [isValid, isResolvingUri, uri, resolveUri, shouldFetch]);
|
|
|
|
let shouldHide = false;
|
|
|
|
if (isMature && !showMature) {
|
|
// Unfortunately needed until this is resolved
|
|
// https://github.com/lbryio/lbry-sdk/issues/2785
|
|
shouldHide = true;
|
|
} else {
|
|
shouldHide =
|
|
banState.blacklisted || banState.filtered || (!showHiddenByUser && (banState.muted || banState.blocked));
|
|
}
|
|
|
|
if (shouldHide || (isLivestream && !showNoSourceClaims)) {
|
|
return null;
|
|
}
|
|
|
|
const isChannelPage = window.location.pathname.startsWith('/@');
|
|
|
|
const shouldShowViewCount = !(!viewCount || (claim && claim.repost_url) || isLivestream || !isChannelPage);
|
|
|
|
if (placeholder || (!claim && isResolvingUri)) {
|
|
return (
|
|
<li
|
|
className={classnames('placeholder claim-preview--tile', {
|
|
'swipe-list__item claim-preview--horizontal-tile': swipeLayout,
|
|
})}
|
|
>
|
|
<div className="media__thumb">
|
|
<img src={PlaceholderTx} alt="Placeholder" />
|
|
</div>
|
|
<div className="placeholder__wrapper">
|
|
<div className="claim-tile__title" />
|
|
<div className="claim-tile__title_b" />
|
|
<div
|
|
className={classnames('claim-tile__info', {
|
|
contains_view_count: shouldShowViewCount,
|
|
})}
|
|
>
|
|
<div className="channel-thumbnail" />
|
|
<div className="claim-tile__about">
|
|
<div className="button__content" />
|
|
<div className="claim-tile__about--counts" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
);
|
|
}
|
|
|
|
let liveProperty = null;
|
|
if (isLivestream) {
|
|
if (isLivestreamActive === true && livestreamViewerCount) {
|
|
liveProperty = (claim) => (
|
|
<span className="livestream__viewer-count">
|
|
{livestreamViewerCount} <Icon icon={ICONS.EYE} />
|
|
</span>
|
|
);
|
|
} else {
|
|
liveProperty = (claim) => <>LIVE</>;
|
|
}
|
|
}
|
|
|
|
return (
|
|
<li
|
|
onClick={handleClick}
|
|
className={classnames('card claim-preview--tile', {
|
|
'claim-preview__wrapper--channel': isChannel,
|
|
'claim-preview__live': isLivestreamActive,
|
|
'swipe-list__item claim-preview--horizontal-tile': swipeLayout,
|
|
})}
|
|
>
|
|
<NavLink {...navLinkProps} role="none" tabIndex={-1} aria-hidden>
|
|
<FileThumbnail thumbnail={thumbnailUrl} allowGifs>
|
|
{!isChannel && (
|
|
<React.Fragment>
|
|
<div className="claim-preview__hover-actions">
|
|
{isPlayable && <FileWatchLaterLink focusable={false} uri={repostedContentUri} />}
|
|
</div>
|
|
{fypId && (
|
|
<div className="claim-preview__hover-actions">
|
|
{isStream && <FileHideRecommendation focusable={false} uri={repostedContentUri} />}
|
|
</div>
|
|
)}
|
|
{/* @if TARGET='app' */}
|
|
<div className="claim-preview__hover-actions">
|
|
{isStream && <FileDownloadLink focusable={false} uri={canonicalUrl} hideOpenButton />}
|
|
</div>
|
|
{/* @endif */}
|
|
<div className="claim-preview__file-property-overlay">
|
|
<PreviewOverlayProperties uri={uri} properties={liveProperty || properties} />
|
|
</div>
|
|
<ClaimPreviewProgress uri={uri} />
|
|
</React.Fragment>
|
|
)}
|
|
{isCollection && (
|
|
<React.Fragment>
|
|
<div className="claim-preview__collection-wrapper">
|
|
<CollectionPreviewOverlay collectionId={listId} uri={uri} />
|
|
</div>
|
|
</React.Fragment>
|
|
)}
|
|
</FileThumbnail>
|
|
</NavLink>
|
|
<div className="claim-tile__header">
|
|
<NavLink aria-label={ariaLabelData} {...navLinkProps}>
|
|
<h2 className="claim-tile__title">
|
|
<TruncatedText text={title || (claim && claim.name)} lines={isChannel ? 1 : 2} />
|
|
{isChannel && (
|
|
<div className="claim-tile__about">
|
|
<UriIndicator uri={uri} />
|
|
</div>
|
|
)}
|
|
</h2>
|
|
</NavLink>
|
|
<ClaimMenuList uri={uri} collectionId={listId} fypId={fypId} channelUri={channelUri} />
|
|
</div>
|
|
<div>
|
|
<div
|
|
className={classnames('claim-tile__info', {
|
|
contains_view_count: shouldShowViewCount,
|
|
})}
|
|
>
|
|
{isChannel ? (
|
|
// <div className="claim-tile__about--channel">
|
|
// <SubscribeButton uri={repostedChannelUri || uri} />
|
|
// </div>
|
|
<></>
|
|
) : (
|
|
<React.Fragment>
|
|
<UriIndicator focusable={false} uri={uri} link hideAnonymous>
|
|
<ChannelThumbnail uri={channelUri} xsmall checkMembership={false} />
|
|
</UriIndicator>
|
|
|
|
<div className="claim-tile__about">
|
|
<UriIndicator uri={uri} link />
|
|
<div className="claim-tile__about--counts">
|
|
<FileViewCountInline uri={uri} isLivestream={isLivestream} />
|
|
{isLivestream && <LivestreamDateTime uri={uri} />}
|
|
{!isLivestream && <DateTime timeAgo uri={uri} />}
|
|
</div>
|
|
</div>
|
|
</React.Fragment>
|
|
)}
|
|
</div>
|
|
{isRepost && (
|
|
<div className="claim-tile__repost-author">
|
|
<ClaimRepostAuthor uri={uri} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
</li>
|
|
);
|
|
}
|
|
|
|
export default withRouter(ClaimPreviewTile);
|