basic display of reposts in app
This commit is contained in:
parent
e94bf5d33e
commit
77e26eb440
10 changed files with 192 additions and 90 deletions
|
@ -130,7 +130,7 @@
|
|||
"imagesloaded": "^4.1.4",
|
||||
"json-loader": "^0.5.4",
|
||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||
"lbry-redux": "lbryio/lbry-redux#71e85536dbe397df98a47a3c4b4311760b2e7419",
|
||||
"lbry-redux": "lbryio/lbry-redux#bfbaa0dbdd2c1b2b340c0760d0d97c99f3cefb02",
|
||||
"lbryinc": "lbryio/lbryinc#6a59102c52673502569d2c43bd4ee58c315fb2e4",
|
||||
"lint-staged": "^7.0.2",
|
||||
"localforage": "^1.7.1",
|
||||
|
|
|
@ -17,6 +17,7 @@ import BlockButton from 'component/blockButton';
|
|||
import useGetThumbnail from 'effects/use-get-thumbnail';
|
||||
import ClaimPreviewTitle from 'component/claimPreviewTitle';
|
||||
import ClaimPreviewSubtitle from 'component/claimPreviewSubtitle';
|
||||
import ClaimRepostAuthor from 'component/claimRepostAuthor';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
|
@ -177,11 +178,19 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
|
||||
if (placeholder === 'loading' || (isResolvingUri && !claim)) {
|
||||
return (
|
||||
<li className={classnames('claim-preview', { 'claim-preview--large': type === 'large' })} disabled>
|
||||
<div className="placeholder media__thumb" />
|
||||
<div className="placeholder__wrapper">
|
||||
<div className="placeholder claim-preview__title" />
|
||||
<div className="placeholder media__subtitle" />
|
||||
<li
|
||||
disabled
|
||||
className={classnames('claim-preview__wrapper', {
|
||||
'claim-preview__wrapper--channel': isChannel && type !== 'inline',
|
||||
'claim-preview__wrapper--inline': type === 'inline',
|
||||
})}
|
||||
>
|
||||
<div className={classnames('claim-preview', { 'claim-preview--large': type === 'large' })}>
|
||||
<div className="placeholder media__thumb" />
|
||||
<div className="placeholder__wrapper">
|
||||
<div className="placeholder claim-preview__title" />
|
||||
<div className="placeholder media__subtitle" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
|
@ -197,50 +206,61 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
role="link"
|
||||
onClick={pending || type === 'inline' ? undefined : handleOnClick}
|
||||
onContextMenu={handleContextMenu}
|
||||
className={classnames('claim-preview', {
|
||||
'claim-preview--small': type === 'small' || type === 'tooltip',
|
||||
'claim-preview--large': type === 'large',
|
||||
'claim-preview--inline': type === 'inline',
|
||||
'claim-preview--tooltip': type === 'tooltip',
|
||||
'claim-preview--channel': isChannel,
|
||||
'claim-preview--visited': !isChannel && !claimIsMine && hasVisitedUri,
|
||||
'claim-preview--pending': pending,
|
||||
className={classnames('claim-preview__wrapper', {
|
||||
'claim-preview__wrapper--channel': isChannel && type !== 'inline',
|
||||
'claim-preview__wrapper--inline': type === 'inline',
|
||||
'claim-preview__wrapper--small': type === 'small',
|
||||
})}
|
||||
>
|
||||
{isChannel && claim ? (
|
||||
<UriIndicator uri={uri} link>
|
||||
<ChannelThumbnail uri={uri} obscure={channelIsBlocked} />
|
||||
</UriIndicator>
|
||||
) : (
|
||||
<FileThumbnail thumbnail={thumbnailUrl} />
|
||||
)}
|
||||
<div className="claim-preview__text">
|
||||
<div className="claim-preview-metadata">
|
||||
<div className="claim-preview-info">
|
||||
<ClaimPreviewTitle uri={uri} />
|
||||
{!isChannel && <FileProperties uri={uri} />}
|
||||
</div>
|
||||
{type !== 'large' && type !== 'inline' && <ClaimRepostAuthor uri={uri} />}
|
||||
|
||||
<ClaimPreviewSubtitle uri={uri} type={type} />
|
||||
</div>
|
||||
<div className="claim-preview__actions">
|
||||
{!pending && (
|
||||
<React.Fragment>
|
||||
{hideActions ? null : actions !== undefined ? (
|
||||
actions
|
||||
) : (
|
||||
<div className="card__actions--inline">
|
||||
{isChannel && !channelIsBlocked && !claimIsMine && (
|
||||
<SubscribeButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />
|
||||
)}
|
||||
{!hideBlock && isChannel && !isSubscribed && !claimIsMine && (
|
||||
<BlockButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
{properties !== undefined ? properties : <ClaimTags uri={uri} type={type} />}
|
||||
<div
|
||||
className={classnames('claim-preview', {
|
||||
'claim-preview--small': type === 'small' || type === 'tooltip',
|
||||
'claim-preview--large': type === 'large',
|
||||
'claim-preview--inline': type === 'inline',
|
||||
'claim-preview--tooltip': type === 'tooltip',
|
||||
'claim-preview--channel': isChannel,
|
||||
'claim-preview--visited': !isChannel && !claimIsMine && hasVisitedUri,
|
||||
'claim-preview--pending': pending,
|
||||
})}
|
||||
>
|
||||
{isChannel && claim ? (
|
||||
<UriIndicator uri={uri} link>
|
||||
<ChannelThumbnail uri={uri} obscure={channelIsBlocked} />
|
||||
</UriIndicator>
|
||||
) : (
|
||||
<FileThumbnail thumbnail={thumbnailUrl} />
|
||||
)}
|
||||
|
||||
<div className="claim-preview__text">
|
||||
<div className="claim-preview-metadata">
|
||||
<div className="claim-preview-info">
|
||||
<ClaimPreviewTitle uri={uri} />
|
||||
{!isChannel && <FileProperties uri={uri} />}
|
||||
</div>
|
||||
|
||||
<ClaimPreviewSubtitle uri={uri} type={type} />
|
||||
</div>
|
||||
<div className="claim-preview__actions">
|
||||
{!pending && (
|
||||
<React.Fragment>
|
||||
{hideActions ? null : actions !== undefined ? (
|
||||
actions
|
||||
) : (
|
||||
<div className="card__actions--inline">
|
||||
{isChannel && !channelIsBlocked && !claimIsMine && (
|
||||
<SubscribeButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />
|
||||
)}
|
||||
{!hideBlock && isChannel && !isSubscribed && !claimIsMine && (
|
||||
<BlockButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
{properties !== undefined ? properties : <ClaimTags uri={uri} type={type} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -12,8 +12,8 @@ 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,
|
||||
|
@ -54,6 +54,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
streamingUrl,
|
||||
blockedChannelUris,
|
||||
} = 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;
|
||||
|
@ -146,7 +147,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
role="link"
|
||||
onClick={handleClick}
|
||||
className={classnames('card claim-preview--tile', {
|
||||
'claim-preview--channel': isChannel,
|
||||
'claim-preview__wrapper--channel': isChannel,
|
||||
})}
|
||||
>
|
||||
<NavLink {...navLinkProps}>
|
||||
|
@ -170,27 +171,34 @@ function ClaimPreviewTile(props: Props) {
|
|||
<TruncatedText text={title || (claim && claim.name)} lines={2} />
|
||||
</h2>
|
||||
</NavLink>
|
||||
<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>
|
||||
</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>
|
||||
<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>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<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>
|
||||
|
|
9
ui/component/claimRepostAuthor/index.js
Normal file
9
ui/component/claimRepostAuthor/index.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectClaimForUri } from 'lbry-redux';
|
||||
import ClaimRepostAuthor from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
});
|
||||
|
||||
export default connect(select)(ClaimRepostAuthor);
|
31
ui/component/claimRepostAuthor/view.jsx
Normal file
31
ui/component/claimRepostAuthor/view.jsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
// @flow
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
import I18nMessage from 'component/i18nMessage';
|
||||
import UriIndicator from 'component/uriIndicator';
|
||||
import Icon from 'component/common/icon';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
claim: ?Claim,
|
||||
};
|
||||
|
||||
function ClaimRepostAuthor(props: Props) {
|
||||
const { claim } = props;
|
||||
const repostChannelUrl = claim && claim.repost_channel_url;
|
||||
|
||||
if (!repostChannelUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="claim-preview__repost-author">
|
||||
<Icon icon={ICONS.REPOST} size={10} />
|
||||
<I18nMessage tokens={{ repost_channel_link: <UriIndicator link uri={repostChannelUrl} /> }}>
|
||||
%repost_channel_link% reposted
|
||||
</I18nMessage>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ClaimRepostAuthor;
|
|
@ -392,4 +392,12 @@ export const icons = {
|
|||
<polyline points="7 3 7 8 15 8" />
|
||||
</g>
|
||||
),
|
||||
[ICONS.REPOST]: buildIcon(
|
||||
<g>
|
||||
<polyline points="17 1 21 5 17 9" />
|
||||
<path d="M3 11V9a4 4 0 0 1 4-4h14" />
|
||||
<polyline points="7 23 3 19 7 15" />
|
||||
<path d="M21 13v2a4 4 0 0 1-4 4H3" />
|
||||
</g>
|
||||
),
|
||||
};
|
||||
|
|
|
@ -86,3 +86,4 @@ export const AUDIO = 'HeadPhones';
|
|||
export const VIDEO = 'Video';
|
||||
export const TEXT = 'FileText';
|
||||
export const DOWNLOADABLE = 'Downloadable';
|
||||
export const REPOST = 'Repeat';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.claim-list {
|
||||
.claim-preview {
|
||||
.claim-preview__wrapper {
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
}
|
||||
|
@ -60,12 +60,28 @@
|
|||
}
|
||||
}
|
||||
|
||||
.claim-preview__wrapper {
|
||||
padding: var(--spacing-medium);
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.claim-preview__wrapper--channel {
|
||||
background-color: var(--color-card-background-highlighted);
|
||||
}
|
||||
|
||||
.claim-preview__wrapper--inline {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.claim-preview__wrapper--small {
|
||||
padding: var(--spacing-small);
|
||||
}
|
||||
|
||||
.claim-preview {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
padding: var(--spacing-medium);
|
||||
|
||||
&:not(.claim-preview--inline):not(.claim-preview--pending):not(.claim-preview--inactive) {
|
||||
cursor: pointer;
|
||||
|
@ -112,8 +128,6 @@
|
|||
}
|
||||
|
||||
.claim-preview--small {
|
||||
padding: var(--spacing-small);
|
||||
|
||||
.media__thumb {
|
||||
width: 8rem;
|
||||
}
|
||||
|
@ -124,18 +138,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
.claim-preview--channel:not(.claim-preview--inline) {
|
||||
background-color: var(--color-card-background-highlighted);
|
||||
}
|
||||
|
||||
.claim-preview--pending {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.claim-preview--inline {
|
||||
padding: 0;
|
||||
border-bottom: none;
|
||||
|
||||
.channel-thumbnail {
|
||||
width: var(--channel-thumbnail-width--small);
|
||||
height: var(--channel-thumbnail-width--small);
|
||||
|
@ -413,3 +420,20 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.claim-preview__repost-author {
|
||||
transform: translateY(calc(var(--spacing-small) * -1));
|
||||
font-size: var(--font-xsmall);
|
||||
color: var(--color-text-subtitle);
|
||||
line-height: 1;
|
||||
|
||||
.icon {
|
||||
margin-right: var(--spacing-miniscule);
|
||||
margin-bottom: -1px; // Offset it slightly because it doesn't look aligned next to all lowercase text + the @ from a channel
|
||||
}
|
||||
}
|
||||
|
||||
.claim-tile__repost-author {
|
||||
margin: var(--spacing-small);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
.file-properties--large {
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: var(--spacing-large);
|
||||
margin-left: 0;
|
||||
|
||||
& > * {
|
||||
margin-top: var(--spacing-small);
|
||||
|
|
20
yarn.lock
20
yarn.lock
|
@ -1073,10 +1073,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz#eef87a431300f6148c39a7f75f8cfeb218b2547e"
|
||||
integrity sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==
|
||||
|
||||
"@octokit/plugin-rest-endpoint-methods@2.1.3":
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.1.3.tgz#a316af20ac9465af3fcbd0da3e4b764d94703ed2"
|
||||
integrity sha512-YtP757n6UIyVhd4YJ0aerx7CuO4+VJJ5BYlvD2aPnUPhCoNbINSxVS1p7UEBRzMOrPfEGDYEcs/tjADB1NOCyg==
|
||||
"@octokit/plugin-rest-endpoint-methods@^2.1.0":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.1.2.tgz#c9b72657a1dca049aa8f51cca7d12faa85ccefc1"
|
||||
integrity sha512-PS77CqifhDqYONWAxLh+BKGlmuhdEX39JVEVQoWWDvkh5B+2bcg9eaxMEFUEJtfuqdAw33sdGrrlGtqtl+9lqg==
|
||||
dependencies:
|
||||
"@octokit/types" "^2.0.1"
|
||||
deprecation "^2.3.1"
|
||||
|
@ -1120,14 +1120,14 @@
|
|||
url-template "^2.0.8"
|
||||
|
||||
"@octokit/rest@^16.40.0":
|
||||
version "16.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.41.0.tgz#28950d7bb854da3bf36bd317c95526ffbcb7b982"
|
||||
integrity sha512-qdXSdoI7RI+u04KR5FEv2UAo8kuCLH1l48mLCQu3gpMoCapmIXL0dGDjzhAbuQHRxkGz2zuvCKhskdMhy66Nww==
|
||||
version "16.40.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.40.2.tgz#f32ecb96d4cfadd3ab8fbfeb91a6018368d03956"
|
||||
integrity sha512-6JYp+VQOPGYBPbpVA+rat0VWMLACjbWz4iwpbpcTeXQj8SlxZRErUcRk7hvUNK5swyf2GHAwKG6Kpl3xdYxVrA==
|
||||
dependencies:
|
||||
"@octokit/auth-token" "^2.4.0"
|
||||
"@octokit/plugin-paginate-rest" "^1.1.1"
|
||||
"@octokit/plugin-request-log" "^1.0.0"
|
||||
"@octokit/plugin-rest-endpoint-methods" "2.1.3"
|
||||
"@octokit/plugin-rest-endpoint-methods" "^2.1.0"
|
||||
"@octokit/request" "^5.2.0"
|
||||
"@octokit/request-error" "^1.0.2"
|
||||
atob-lite "^2.0.0"
|
||||
|
@ -7277,9 +7277,9 @@ lazy-val@^1.0.4:
|
|||
yargs "^13.2.2"
|
||||
zstd-codec "^0.1.1"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#71e85536dbe397df98a47a3c4b4311760b2e7419:
|
||||
lbry-redux@lbryio/lbry-redux#bfbaa0dbdd2c1b2b340c0760d0d97c99f3cefb02:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/71e85536dbe397df98a47a3c4b4311760b2e7419"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/bfbaa0dbdd2c1b2b340c0760d0d97c99f3cefb02"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
|
|
Loading…
Reference in a new issue