lbry-desktop/ui/component/claimPreviewTile/view.jsx

220 lines
6.7 KiB
JavaScript

// @flow
import React from 'react';
import classnames from 'classnames';
import { NavLink, withRouter } from 'react-router-dom';
import FileThumbnail from 'component/fileThumbnail';
import UriIndicator from 'component/uriIndicator';
import TruncatedText from 'component/common/truncated-text';
import DateTime from 'component/dateTime';
import ChannelThumbnail from 'component/channelThumbnail';
import SubscribeButton from 'component/subscribeButton';
import useGetThumbnail from 'effects/use-get-thumbnail';
import { formatLbryUrlForWeb } from 'util/url';
import { parseURI } from 'lbry-redux';
import FileProperties from 'component/fileProperties';
import FileDownloadLink from 'component/fileDownloadLink';
import ClaimRepostAuthor from 'component/claimRepostAuthor';
type Props = {
uri: string,
claim: ?Claim,
resolveUri: string => void,
isResolvingUri: boolean,
history: { push: string => void },
thumbnail: string,
title: string,
placeholder: boolean,
blackListedOutpoints: Array<{
txid: string,
nout: number,
}>,
filteredOutpoints: Array<{
txid: string,
nout: number,
}>,
blockedChannelUris: Array<string>,
getFile: string => void,
placeholder: boolean,
streamingUrl: string,
isMature: boolean,
showMature: boolean,
};
function ClaimPreviewTile(props: Props) {
const {
history,
uri,
isResolvingUri,
thumbnail,
title,
resolveUri,
claim,
placeholder,
blackListedOutpoints,
filteredOutpoints,
getFile,
streamingUrl,
blockedChannelUris,
isMature,
showMature,
} = props;
const isRepost = claim && claim.repost_channel_url;
const shouldFetch = claim === undefined;
const thumbnailUrl = useGetThumbnail(uri, claim, streamingUrl, getFile, placeholder) || thumbnail;
const claimsInChannel = (claim && claim.meta.claims_in_channel) || 0;
const canonicalUrl = claim && claim.canonical_url;
const navigateUrl = formatLbryUrlForWeb(canonicalUrl || uri || '/');
const navLinkProps = {
to: navigateUrl,
onClick: e => e.stopPropagation(),
};
let isChannel;
let isValid = false;
if (uri) {
try {
({ isChannel } = parseURI(uri));
isValid = true;
} catch (e) {
isValid = false;
}
}
const signingChannel = claim && claim.signing_channel;
let channelThumbnail;
if (signingChannel) {
channelThumbnail =
// I should be able to just pass the the uri to <ChannelThumbnail /> but it wasn't working
// Come back to me
(signingChannel.value && signingChannel.value.thumbnail && signingChannel.value.thumbnail.url) || undefined;
}
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;
}
// 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 && blockedChannelUris.length && signingChannel) {
shouldHide = blockedChannelUris.some(blockedUri => blockedUri === signingChannel.permanent_url);
}
// block channel claims if we can't control for them in claim search
// e.g. fetchRecommendedSubscriptions
if (claim && isChannel && !shouldHide && blockedChannelUris.length) {
shouldHide = blockedChannelUris.some(blockedUri => blockedUri === claim.permanent_url);
}
if (shouldHide) {
return null;
}
if (placeholder || isResolvingUri) {
return (
<li className={classnames('claim-preview--tile', {})}>
<div className="placeholder media__thumb" />
<div className="placeholder__wrapper">
<div className="placeholder claim-tile__title" />
<div className="placeholder claim-tile__info" />
</div>
</li>
);
}
return (
<li
role="link"
onClick={handleClick}
className={classnames('card claim-preview--tile', {
'claim-preview__wrapper--channel': isChannel,
})}
>
<NavLink {...navLinkProps}>
<FileThumbnail thumbnail={thumbnailUrl}>
{!isChannel && (
<React.Fragment>
{/* @if TARGET='app' */}
<div className="claim-preview__hover-actions">
<FileDownloadLink uri={canonicalUrl} hideOpenButton />
</div>
{/* @endif */}
<div className="claim-tile__file-properties">
<FileProperties uri={uri} small />
</div>
</React.Fragment>
)}
</FileThumbnail>
</NavLink>
<NavLink {...navLinkProps}>
<h2 className="claim-tile__title">
<TruncatedText text={title || (claim && claim.name)} lines={2} />
</h2>
</NavLink>
<div>
<div className="claim-tile__info">
{isChannel ? (
<div className="claim-tile__about--channel">
<SubscribeButton uri={uri} shrinkOnMobile />
<span className="claim-tile__publishes">
{claimsInChannel === 1
? __('%claimsInChannel% publish', { claimsInChannel })
: __('%claimsInChannel% publishes', { claimsInChannel })}
</span>
</div>
) : (
<React.Fragment>
<UriIndicator uri={uri} link hideAnonymous>
<ChannelThumbnail thumbnailPreview={channelThumbnail} />
</UriIndicator>
<div className="claim-tile__about">
<UriIndicator uri={uri} link />
<DateTime timeAgo uri={uri} />
</div>
</React.Fragment>
)}
</div>
{isRepost && (
<div className="claim-tile__repost-author">
<ClaimRepostAuthor uri={uri} />
</div>
)}
</div>
</li>
);
}
export default withRouter(ClaimPreviewTile);