2020-01-20 17:47:03 +01:00
|
|
|
// @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';
|
2020-01-29 16:26:39 +01:00
|
|
|
import FileProperties from 'component/fileProperties';
|
2020-01-25 20:42:39 +01:00
|
|
|
import FileDownloadLink from 'component/fileDownloadLink';
|
2020-01-31 17:43:14 +01:00
|
|
|
import ClaimRepostAuthor from 'component/claimRepostAuthor';
|
2020-01-25 20:42:39 +01:00
|
|
|
|
2020-01-20 17:47:03 +01:00
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
|
|
|
function ClaimPreviewTile(props: Props) {
|
|
|
|
const {
|
|
|
|
history,
|
|
|
|
uri,
|
|
|
|
isResolvingUri,
|
|
|
|
thumbnail,
|
|
|
|
title,
|
|
|
|
resolveUri,
|
|
|
|
claim,
|
|
|
|
placeholder,
|
|
|
|
blackListedOutpoints,
|
|
|
|
filteredOutpoints,
|
|
|
|
getFile,
|
|
|
|
streamingUrl,
|
2020-01-20 19:55:28 +01:00
|
|
|
blockedChannelUris,
|
2020-01-20 17:47:03 +01:00
|
|
|
} = props;
|
2020-01-31 17:43:14 +01:00
|
|
|
const isRepost = claim && claim.repost_channel_url;
|
2020-01-20 17:47:03 +01:00
|
|
|
const shouldFetch = claim === undefined;
|
|
|
|
const thumbnailUrl = useGetThumbnail(uri, claim, streamingUrl, getFile, placeholder) || thumbnail;
|
|
|
|
const claimsInChannel = (claim && claim.meta.claims_in_channel) || 0;
|
2020-02-03 20:26:30 +01:00
|
|
|
const canonicalUrl = claim && claim.canonical_url;
|
2020-02-05 00:54:49 +01:00
|
|
|
const navigateUrl = formatLbryUrlForWeb(canonicalUrl || uri || '/');
|
2020-02-03 19:02:49 +01:00
|
|
|
|
2020-01-27 16:00:33 +01:00
|
|
|
const navLinkProps = {
|
2020-02-05 00:32:36 +01:00
|
|
|
to: navigateUrl,
|
2020-01-27 16:00:33 +01:00
|
|
|
onClick: e => e.stopPropagation(),
|
|
|
|
};
|
2020-01-20 17:47:03 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-01-20 19:55:28 +01:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2020-01-20 17:47:03 +01:00
|
|
|
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', {
|
2020-01-31 17:43:14 +01:00
|
|
|
'claim-preview__wrapper--channel': isChannel,
|
2020-01-20 17:47:03 +01:00
|
|
|
})}
|
|
|
|
>
|
2020-01-27 16:00:33 +01:00
|
|
|
<NavLink {...navLinkProps}>
|
2020-01-29 17:38:46 +01:00
|
|
|
<FileThumbnail thumbnail={thumbnailUrl}>
|
|
|
|
{!isChannel && (
|
2020-01-29 19:58:43 +01:00
|
|
|
<React.Fragment>
|
|
|
|
{/* @if TARGET='app' */}
|
2020-02-05 17:42:46 +01:00
|
|
|
<div className="claim-preview__hover-actions">
|
2020-02-03 20:26:30 +01:00
|
|
|
<FileDownloadLink uri={canonicalUrl} hideOpenButton />
|
2020-01-29 19:58:43 +01:00
|
|
|
</div>
|
|
|
|
{/* @endif */}
|
|
|
|
<div className="claim-tile__file-properties">
|
|
|
|
<FileProperties uri={uri} small />
|
|
|
|
</div>
|
|
|
|
</React.Fragment>
|
2020-01-29 17:38:46 +01:00
|
|
|
)}
|
|
|
|
</FileThumbnail>
|
2020-01-20 17:47:03 +01:00
|
|
|
</NavLink>
|
2020-01-27 16:00:33 +01:00
|
|
|
<NavLink {...navLinkProps}>
|
2020-01-29 17:38:46 +01:00
|
|
|
<h2 className="claim-tile__title">
|
|
|
|
<TruncatedText text={title || (claim && claim.name)} lines={2} />
|
|
|
|
</h2>
|
2020-01-20 17:47:03 +01:00
|
|
|
</NavLink>
|
2020-01-31 17:43:14 +01:00
|
|
|
<div>
|
|
|
|
<div className="claim-tile__info">
|
|
|
|
{isChannel ? (
|
|
|
|
<div className="claim-tile__about--channel">
|
|
|
|
<SubscribeButton uri={uri} />
|
|
|
|
<span className="claim-tile__publishes">
|
|
|
|
{claimsInChannel === 1
|
|
|
|
? __('%claimsInChannel% publish', { claimsInChannel })
|
|
|
|
: __('%claimsInChannel% publishes', { claimsInChannel })}
|
|
|
|
</span>
|
2020-01-20 17:47:03 +01:00
|
|
|
</div>
|
2020-01-31 17:43:14 +01:00
|
|
|
) : (
|
|
|
|
<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>
|
2020-01-20 17:47:03 +01:00
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default withRouter(ClaimPreviewTile);
|