add content placeholder and time info on file{card,tile}
This commit is contained in:
parent
df65db0dfc
commit
3c87c47632
14 changed files with 181 additions and 79 deletions
|
@ -1,6 +1,15 @@
|
||||||
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
class DateTime extends React.PureComponent {
|
type Props = {
|
||||||
|
date?: number,
|
||||||
|
timeAgo?: boolean,
|
||||||
|
formatOptions: {},
|
||||||
|
show?: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
class DateTime extends React.PureComponent<Props> {
|
||||||
static SHOW_DATE = 'date';
|
static SHOW_DATE = 'date';
|
||||||
static SHOW_TIME = 'time';
|
static SHOW_TIME = 'time';
|
||||||
static SHOW_BOTH = 'both';
|
static SHOW_BOTH = 'both';
|
||||||
|
@ -29,18 +38,22 @@ class DateTime extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { date, formatOptions } = this.props;
|
const { date, formatOptions, timeAgo } = this.props;
|
||||||
const show = this.props.show || DateTime.SHOW_BOTH;
|
const show = this.props.show || DateTime.SHOW_BOTH;
|
||||||
const locale = app.i18n.getLocale();
|
const locale = app.i18n.getLocale();
|
||||||
|
|
||||||
|
if (timeAgo) {
|
||||||
|
return date ? <span>{moment(date).from(moment())}</span> : <span />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{date &&
|
{date &&
|
||||||
(show == DateTime.SHOW_BOTH || show === DateTime.SHOW_DATE) &&
|
(show === DateTime.SHOW_BOTH || show === DateTime.SHOW_DATE) &&
|
||||||
date.toLocaleDateString([locale, 'en-US'], formatOptions)}
|
date.toLocaleDateString([locale, 'en-US'], formatOptions)}
|
||||||
{show == DateTime.SHOW_BOTH && ' '}
|
{show === DateTime.SHOW_BOTH && ' '}
|
||||||
{date &&
|
{date &&
|
||||||
(show == DateTime.SHOW_BOTH || show === DateTime.SHOW_TIME) &&
|
(show === DateTime.SHOW_BOTH || show === DateTime.SHOW_TIME) &&
|
||||||
date.toLocaleTimeString()}
|
date.toLocaleTimeString()}
|
||||||
{!date && '...'}
|
{!date && '...'}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -14,6 +14,8 @@ import {
|
||||||
} from 'redux/selectors/content';
|
} from 'redux/selectors/content';
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { selectPendingPublish } from 'redux/selectors/publish';
|
import { selectPendingPublish } from 'redux/selectors/publish';
|
||||||
|
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
||||||
|
import { doClearContentHistoryUri } from 'redux/actions/content';
|
||||||
import FileCard from './view';
|
import FileCard from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
|
@ -36,6 +38,7 @@ const select = (state, props) => {
|
||||||
...fileCardInfo,
|
...fileCardInfo,
|
||||||
pending: !!pendingPublish,
|
pending: !!pendingPublish,
|
||||||
position: makeSelectContentPositionForUri(props.uri)(state),
|
position: makeSelectContentPositionForUri(props.uri)(state),
|
||||||
|
subscribed: makeSelectIsSubscribed(props.uri)(state),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import * as icons from 'constants/icons';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import FilePrice from 'component/filePrice';
|
import FilePrice from 'component/filePrice';
|
||||||
import { openCopyLinkMenu } from 'util/contextMenu';
|
import { openCopyLinkMenu } from 'util/contextMenu';
|
||||||
|
import DateTime from 'component/dateTime';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -24,15 +25,11 @@ type Props = {
|
||||||
/* eslint-disable react/no-unused-prop-types */
|
/* eslint-disable react/no-unused-prop-types */
|
||||||
resolveUri: string => void,
|
resolveUri: string => void,
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
showPrice: boolean,
|
|
||||||
/* eslint-enable react/no-unused-prop-types */
|
/* eslint-enable react/no-unused-prop-types */
|
||||||
|
subscribed: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileCard extends React.PureComponent<Props> {
|
class FileCard extends React.PureComponent<Props> {
|
||||||
static defaultProps = {
|
|
||||||
showPrice: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.resolve(this.props);
|
this.resolve(this.props);
|
||||||
}
|
}
|
||||||
|
@ -59,9 +56,20 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
obscureNsfw,
|
obscureNsfw,
|
||||||
claimIsMine,
|
claimIsMine,
|
||||||
pending,
|
pending,
|
||||||
showPrice,
|
subscribed,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
if (!claim) {
|
||||||
|
return (
|
||||||
|
<div className="card card--small">
|
||||||
|
<div className="card--placeholder card__media" />
|
||||||
|
<div className="card--placeholder placeholder__title" />
|
||||||
|
<div className="card--placeholder placeholder__channel" />
|
||||||
|
<div className="card--placeholder placeholder__date" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const shouldHide = !claimIsMine && !pending && obscureNsfw && metadata && metadata.nsfw;
|
const shouldHide = !claimIsMine && !pending && obscureNsfw && metadata && metadata.nsfw;
|
||||||
if (shouldHide) {
|
if (shouldHide) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -70,7 +78,8 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
const uri = !pending ? normalizeURI(this.props.uri) : this.props.uri;
|
const uri = !pending ? normalizeURI(this.props.uri) : this.props.uri;
|
||||||
const title = metadata && metadata.title ? metadata.title : uri;
|
const title = metadata && metadata.title ? metadata.title : uri;
|
||||||
const thumbnail = metadata && metadata.thumbnail ? metadata.thumbnail : null;
|
const thumbnail = metadata && metadata.thumbnail ? metadata.thumbnail : null;
|
||||||
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
|
const { height } = claim;
|
||||||
const handleContextMenu = event => {
|
const handleContextMenu = event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
@ -97,10 +106,15 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
<div className="card__subtitle">
|
<div className="card__subtitle">
|
||||||
{pending ? <div>Pending...</div> : <UriIndicator uri={uri} link />}
|
{pending ? <div>Pending...</div> : <UriIndicator uri={uri} link />}
|
||||||
</div>
|
</div>
|
||||||
<div className="card__file-properties">
|
<div className="card__subtitle card--space-between">
|
||||||
{showPrice && <FilePrice hideFree uri={uri} />}
|
<DateTime timeAgo block={height} />
|
||||||
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
|
||||||
{fileInfo && <Icon icon={icons.LOCAL} />}
|
<div className="card__file-properties">
|
||||||
|
<FilePrice hideFree uri={uri} />
|
||||||
|
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
||||||
|
{subscribed && <Icon icon={icons.HEART} />}
|
||||||
|
{fileInfo && <Icon icon={icons.LOCAL} />}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doClearPublish, doUpdatePublishForm } from 'redux/actions/publish';
|
import { doClearPublish, doUpdatePublishForm } from 'redux/actions/publish';
|
||||||
import { selectRewardContentClaimIds } from 'redux/selectors/content';
|
import { selectRewardContentClaimIds } from 'redux/selectors/content';
|
||||||
|
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
||||||
import FileTile from './view';
|
import FileTile from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
@ -21,6 +22,7 @@ const select = (state, props) => ({
|
||||||
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
|
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
|
||||||
obscureNsfw: !selectShowNsfw(state),
|
obscureNsfw: !selectShowNsfw(state),
|
||||||
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||||
|
subscribed: makeSelectIsSubscribed(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -10,9 +10,9 @@ import Button from 'component/button';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import FilePrice from 'component/filePrice';
|
import FilePrice from 'component/filePrice';
|
||||||
import UriIndicator from 'component/uriIndicator';
|
import UriIndicator from 'component/uriIndicator';
|
||||||
|
import DateTime from 'component/dateTime';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
showUri: boolean,
|
|
||||||
showLocal: boolean,
|
showLocal: boolean,
|
||||||
obscureNsfw: boolean,
|
obscureNsfw: boolean,
|
||||||
claimIsMine: boolean,
|
claimIsMine: boolean,
|
||||||
|
@ -30,11 +30,11 @@ type Props = {
|
||||||
displayHiddenMessage?: boolean,
|
displayHiddenMessage?: boolean,
|
||||||
displayDescription?: boolean,
|
displayDescription?: boolean,
|
||||||
size: string,
|
size: string,
|
||||||
|
subscribed: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileTile extends React.PureComponent<Props> {
|
class FileTile extends React.PureComponent<Props> {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
showUri: false,
|
|
||||||
showLocal: false,
|
showLocal: false,
|
||||||
displayDescription: true,
|
displayDescription: true,
|
||||||
size: 'regular',
|
size: 'regular',
|
||||||
|
@ -57,7 +57,6 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
isResolvingUri,
|
isResolvingUri,
|
||||||
navigate,
|
navigate,
|
||||||
rewardedContentClaimIds,
|
rewardedContentClaimIds,
|
||||||
showUri,
|
|
||||||
obscureNsfw,
|
obscureNsfw,
|
||||||
claimIsMine,
|
claimIsMine,
|
||||||
showLocal,
|
showLocal,
|
||||||
|
@ -68,8 +67,27 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
displayHiddenMessage,
|
displayHiddenMessage,
|
||||||
displayDescription,
|
displayDescription,
|
||||||
size,
|
size,
|
||||||
|
subscribed,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
if (!claim && isResolvingUri) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classnames('file-tile', {
|
||||||
|
'file-tile--small': size === 'small',
|
||||||
|
'file-tile--large': size === 'large',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<div className="card--placeholder card__media" />
|
||||||
|
<div className="file-tile__info">
|
||||||
|
<div className="card--placeholder placeholder__title--tile" />
|
||||||
|
<div className="card--placeholder placeholder__channel" />
|
||||||
|
<div className="card--placeholder placeholder__date" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const shouldHide = !claimIsMine && obscureNsfw && metadata && metadata.nsfw;
|
const shouldHide = !claimIsMine && obscureNsfw && metadata && metadata.nsfw;
|
||||||
if (shouldHide) {
|
if (shouldHide) {
|
||||||
return displayHiddenMessage ? (
|
return displayHiddenMessage ? (
|
||||||
|
@ -90,9 +108,10 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
const onClick = () => navigate('/show', { uri });
|
const onClick = () => navigate('/show', { uri });
|
||||||
|
|
||||||
|
let height;
|
||||||
let name;
|
let name;
|
||||||
if (claim) {
|
if (isClaimed) {
|
||||||
({ name } = claim);
|
({ name, height } = claim);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !name && hideNoResult ? null : (
|
return !name && hideNoResult ? null : (
|
||||||
|
@ -108,43 +127,42 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
>
|
>
|
||||||
<CardMedia title={title || name} thumbnail={thumbnail} />
|
<CardMedia title={title || name} thumbnail={thumbnail} />
|
||||||
<div className="file-tile__info">
|
<div className="file-tile__info">
|
||||||
{isResolvingUri && <div className="file-tile__title">{__('Loading...')}</div>}
|
<div className="file-tile__title">
|
||||||
{!isResolvingUri && (
|
<TruncatedText text={title || name} lines={size === 'small' ? 2 : 3} />
|
||||||
|
</div>
|
||||||
|
<div className="card__subtitle">
|
||||||
|
<UriIndicator uri={uri} link />
|
||||||
|
</div>
|
||||||
|
<div className="card__subtitle card--space-between">
|
||||||
|
<DateTime timeAgo block={height} />
|
||||||
|
<div className="card__file-properties">
|
||||||
|
<FilePrice hideFree uri={uri} />
|
||||||
|
{subscribed && <Icon icon={icons.HEART} />}
|
||||||
|
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
||||||
|
{showLocal && isDownloaded && <Icon icon={icons.LOCAL} />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{displayDescription && (
|
||||||
|
<div className="card__subtext">
|
||||||
|
<TruncatedText text={description} lines={size === 'large' ? 4 : 3} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!name && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="file-tile__title">
|
{__('This location is unused.')}{' '}
|
||||||
<TruncatedText text={title || name} lines={size === 'small' ? 2 : 3} />
|
<Button
|
||||||
</div>
|
button="link"
|
||||||
<div className="card__subtitle">
|
label={__('Put something here!')}
|
||||||
{showUri ? uri : <UriIndicator uri={uri} link />}
|
onClick={e => {
|
||||||
</div>
|
// avoid navigating to /show from clicking on the section
|
||||||
<div className="card__file-properties">
|
e.stopPropagation();
|
||||||
<FilePrice hideFree uri={uri} />
|
// strip prefix from the Uri and use that as navigation parameter
|
||||||
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
const nameFromUri = uri.replace(/lbry:\/\//g, '').replace(/-/g, ' ');
|
||||||
{showLocal && isDownloaded && <Icon icon={icons.LOCAL} />}
|
clearPublish(); // to remove any existing publish data
|
||||||
</div>
|
updatePublishForm({ name: nameFromUri }); // to populate the name
|
||||||
{displayDescription && (
|
navigate('/publish');
|
||||||
<div className="card__subtext">
|
}}
|
||||||
<TruncatedText text={description} lines={size === 'large' ? 4 : 3} />
|
/>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!name && (
|
|
||||||
<React.Fragment>
|
|
||||||
{__('This location is unused.')}{' '}
|
|
||||||
<Button
|
|
||||||
button="link"
|
|
||||||
label={__('Put something here!')}
|
|
||||||
onClick={e => {
|
|
||||||
// avoid navigating to /show from clicking on the section
|
|
||||||
e.stopPropagation();
|
|
||||||
// strip prefix from the Uri and use that as navigation parameter
|
|
||||||
const nameFromUri = uri.replace(/lbry:\/\//g, '').replace(/-/g, ' ');
|
|
||||||
clearPublish(); // to remove any existing publish data
|
|
||||||
updatePublishForm({ name: nameFromUri }); // to populate the name
|
|
||||||
navigate('/publish');
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import FileTile from 'component/fileTile';
|
import FileTile from 'component/fileTile';
|
||||||
import type { Claim } from 'types/claim';
|
import type { Claim } from 'types/claim';
|
||||||
import Spinner from 'component/spinner';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -58,6 +57,7 @@ export default class RecommendedContent extends React.PureComponent<Props> {
|
||||||
<FileTile
|
<FileTile
|
||||||
size="small"
|
size="small"
|
||||||
hideNoResult
|
hideNoResult
|
||||||
|
showLocal
|
||||||
displayDescription={false}
|
displayDescription={false}
|
||||||
key={recommendedUri}
|
key={recommendedUri}
|
||||||
uri={recommendedUri}
|
uri={recommendedUri}
|
||||||
|
@ -66,7 +66,6 @@ export default class RecommendedContent extends React.PureComponent<Props> {
|
||||||
{recommendedContent &&
|
{recommendedContent &&
|
||||||
!recommendedContent.length &&
|
!recommendedContent.length &&
|
||||||
!isSearching && <div className="card__subtitle">No related content found</div>}
|
!isSearching && <div className="card__subtitle">No related content found</div>}
|
||||||
{isSearching && <Spinner type="small" />}
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ const select = state => {
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
||||||
clearHistoryUri: uri => dispatch(doClearContentHistoryUri(uri)),
|
clearHistoryUri: uri => dispatch(doClearContentHistoryUri(uri)),
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -43,9 +43,13 @@ type Props = {
|
||||||
fetchFileInfo: string => void,
|
fetchFileInfo: string => void,
|
||||||
fetchCostInfo: string => void,
|
fetchCostInfo: string => void,
|
||||||
prepareEdit: ({}, string) => void,
|
prepareEdit: ({}, string) => void,
|
||||||
|
setViewed: string => void,
|
||||||
|
autoplay: boolean,
|
||||||
|
setClientSetting: (string, string | boolean | number) => void,
|
||||||
|
/* eslint-disable react/no-unused-prop-types */
|
||||||
checkSubscription: (uri: string) => void,
|
checkSubscription: (uri: string) => void,
|
||||||
subscriptions: Array<Subscription>,
|
subscriptions: Array<Subscription>,
|
||||||
setViewed: string => void,
|
/* eslint-enable react/no-unused-prop-types */
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilePage extends React.Component<Props> {
|
class FilePage extends React.Component<Props> {
|
||||||
|
@ -183,7 +187,7 @@ class FilePage extends React.Component<Props> {
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<div className="card__title__space-between">
|
<div className="card--space-between">
|
||||||
<h1>{title}</h1>
|
<h1>{title}</h1>
|
||||||
<div className="card__title-identity-icons">
|
<div className="card__title-identity-icons">
|
||||||
{isRewardContent && (
|
{isRewardContent && (
|
||||||
|
@ -220,14 +224,12 @@ class FilePage extends React.Component<Props> {
|
||||||
onClick={() => openModal({ id: MODALS.SEND_TIP }, { uri })}
|
onClick={() => openModal({ id: MODALS.SEND_TIP }, { uri })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{speechShareable && (
|
<Button
|
||||||
<Button
|
button="alt"
|
||||||
button="alt"
|
icon={icons.GLOBE}
|
||||||
icon={icons.GLOBE}
|
label={__('Share')}
|
||||||
label={__('Share')}
|
onClick={() => openModal({ id: MODALS.SOCIAL_SHARE }, { uri, speechShareable })}
|
||||||
onClick={() => openModal({ id: MODALS.SOCIAL_SHARE }, { uri })}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="card__actions">
|
<div className="card__actions">
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {
|
||||||
selectAllClaimsByChannel,
|
selectAllClaimsByChannel,
|
||||||
selectClaimsById,
|
selectClaimsById,
|
||||||
selectAllFetchingChannelClaims,
|
selectAllFetchingChannelClaims,
|
||||||
|
makeSelectClaimForUri,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
|
|
||||||
// get the entire subscriptions state
|
// get the entire subscriptions state
|
||||||
|
@ -71,3 +72,13 @@ export const selectSubscriptionsBeingFetched = createSelector(
|
||||||
return fetchingSubscriptionMap;
|
return fetchingSubscriptionMap;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const makeSelectIsSubscribed = uri =>
|
||||||
|
createSelector(selectSubscriptions, makeSelectClaimForUri(uri), (subscriptions, claim) => {
|
||||||
|
if (!claim || !claim.channel_name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channelUri = `${claim.channel_name}#${claim.value.publisherSignature.certificateId}`;
|
||||||
|
return subscriptions.some(sub => sub.uri === channelUri);
|
||||||
|
});
|
||||||
|
|
|
@ -32,3 +32,4 @@
|
||||||
@import 'component/_item-list.scss';
|
@import 'component/_item-list.scss';
|
||||||
@import 'component/_time.scss';
|
@import 'component/_time.scss';
|
||||||
@import 'component/_icon.scss';
|
@import 'component/_icon.scss';
|
||||||
|
@import 'component/_placeholder.scss';
|
||||||
|
|
|
@ -88,20 +88,16 @@
|
||||||
// FileCard is slightly different where the title is only slightly bigger than the subtitle
|
// FileCard is slightly different where the title is only slightly bigger than the subtitle
|
||||||
// Slightly bigger than 2 lines for consistent channel placement
|
// Slightly bigger than 2 lines for consistent channel placement
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
height: 4em;
|
height: 3.3em;
|
||||||
|
|
||||||
@media only screen and (min-width: $large-breakpoint) {
|
@media only screen and (min-width: $large-breakpoint) {
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__title__space-between {
|
.card--space-between {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.icon {
|
|
||||||
margin: 0 $spacing-vertical * 1/3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__title-identity-icons {
|
.card__title-identity-icons {
|
||||||
|
@ -114,6 +110,7 @@
|
||||||
color: var(--card-text-color);
|
color: var(--card-text-color);
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
|
padding-top: $spacing-vertical * 1/3;
|
||||||
|
|
||||||
@media (min-width: $large-breakpoint) {
|
@media (min-width: $large-breakpoint) {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
|
@ -142,8 +139,11 @@
|
||||||
.card__file-properties {
|
.card__file-properties {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-top: $spacing-vertical * 1/3;
|
|
||||||
color: var(--card-text-color);
|
color: var(--card-text-color);
|
||||||
|
|
||||||
|
.icon + .icon {
|
||||||
|
margin-left: $spacing-vertical * 1/3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// .card-media__internal__links should always be inside a card
|
// .card-media__internal__links should always be inside a card
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-tile__title {
|
.file-tile__title {
|
||||||
|
font-size: 1.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-tile--small {
|
.file-tile--small {
|
||||||
|
@ -65,6 +66,7 @@
|
||||||
|
|
||||||
.file-tile__info {
|
.file-tile__info {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-left: $spacing-vertical * 2/3;
|
margin-left: $spacing-vertical * 2/3;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
|
|
38
src/renderer/scss/component/_placeholder.scss
Normal file
38
src/renderer/scss/component/_placeholder.scss
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card--placeholder {
|
||||||
|
animation: pulse 2s infinite ease-in-out;
|
||||||
|
background: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Individual items we need a placeholder for
|
||||||
|
// FileCard
|
||||||
|
.placeholder__title {
|
||||||
|
margin-top: $spacing-vertical * 1/3;
|
||||||
|
height: 3em;
|
||||||
|
}
|
||||||
|
.placeholder__channel {
|
||||||
|
margin-top: $spacing-vertical * 1/3;
|
||||||
|
height: 1em;
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
.placeholder__date {
|
||||||
|
height: 1em;
|
||||||
|
margin-top: $spacing-vertical * 1/3;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileTile
|
||||||
|
.placeholder__title--tile {
|
||||||
|
height: 3em;
|
||||||
|
}
|
|
@ -5662,9 +5662,9 @@ lbry-redux@lbryio/lbry-redux:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#c079b108c3bc4ba2b4fb85fb112b52cfc040c301:
|
lbry-redux@lbryio/lbry-redux#4ee6c376e5f2c3e3e96d199a56970e2621a84af1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/c079b108c3bc4ba2b4fb85fb112b52cfc040c301"
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/4ee6c376e5f2c3e3e96d199a56970e2621a84af1"
|
||||||
dependencies:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
Loading…
Reference in a new issue