get recommended videos from search based on title #1845
22 changed files with 163 additions and 113 deletions
|
@ -9,9 +9,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
||||||
* Wallet Encryption/Decryption user flows ([#1785](https://github.com/lbryio/lbry-desktop/pull/1785))
|
* Wallet Encryption/Decryption user flows ([#1785](https://github.com/lbryio/lbry-desktop/pull/1785))
|
||||||
* Add FAQ to Publishing Area ([#1833](https://github.com/lbryio/lbry-desktop/pull/1833))
|
* Add FAQ to Publishing Area ([#1833](https://github.com/lbryio/lbry-desktop/pull/1833))
|
||||||
* Better preview for content ([#620](https://github.com/lbryio/lbry-desktop/pull/620))
|
* Better preview for content ([#620](https://github.com/lbryio/lbry-desktop/pull/620))
|
||||||
* Add new markdown and docx viewer ([#1826](https://github.com/lbryio/lbry-desktop/pull/1826))
|
* New markdown and docx viewer ([#1826](https://github.com/lbryio/lbry-desktop/pull/1826))
|
||||||
* Add new viewer for human-readable text files ([#1826](https://github.com/lbryio/lbry-desktop/pull/1826))
|
* New viewer for human-readable text files ([#1826](https://github.com/lbryio/lbry-desktop/pull/1826))
|
||||||
* Add csv and json viewer ([#1410](https://github.com/lbryio/lbry-desktop/pull/1410))
|
* CSV and JSON viewer ([#1410](https://github.com/lbryio/lbry-desktop/pull/1410))
|
||||||
|
* Recommended content on file viewer page ([#1845](https://github.com/lbryio/lbry-desktop/pull/1845))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Pass error message from spee.ch API during thumbnail upload ([#1840](https://github.com/lbryio/lbry-desktop/pull/1840))
|
* Pass error message from spee.ch API during thumbnail upload ([#1840](https://github.com/lbryio/lbry-desktop/pull/1840))
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"formik": "^0.10.4",
|
"formik": "^0.10.4",
|
||||||
"hast-util-sanitize": "^1.1.2",
|
"hast-util-sanitize": "^1.1.2",
|
||||||
"keytar": "^4.2.1",
|
"keytar": "^4.2.1",
|
||||||
"lbry-redux": "lbryio/lbry-redux#83fec2a8419cbf0f1fafdc98a50dab3051191ef5",
|
"lbry-redux": "lbryio/lbry-redux#8794a775bf71e7b8b7d1ac44392196bb58a0042a",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
"mammoth": "^1.4.6",
|
"mammoth": "^1.4.6",
|
||||||
"mime": "^2.3.1",
|
"mime": "^2.3.1",
|
||||||
|
|
|
@ -40,7 +40,6 @@ export class FormField extends React.PureComponent<Props> {
|
||||||
children,
|
children,
|
||||||
stretch,
|
stretch,
|
||||||
affixClass,
|
affixClass,
|
||||||
firstInList,
|
|
||||||
...inputProps
|
...inputProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -103,7 +102,6 @@ export class FormField extends React.PureComponent<Props> {
|
||||||
<div
|
<div
|
||||||
className={classnames('form-field__input', {
|
className={classnames('form-field__input', {
|
||||||
'form-field--auto-height': type === 'markdown',
|
'form-field--auto-height': type === 'markdown',
|
||||||
'form-field--first-item': firstInList,
|
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{prefix && (
|
{prefix && (
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class FormRow extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { centered, children, padded, verticallyCentered, stretch, alignRight } = this.props;
|
const { children, padded, verticallyCentered, stretch, alignRight } = this.props;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classnames('form-row', {
|
className={classnames('form-row', {
|
||||||
|
|
|
@ -94,20 +94,16 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
<CardMedia thumbnail={thumbnail} />
|
<CardMedia thumbnail={thumbnail} />
|
||||||
<div className="card__title-identity">
|
<div className="card__title-identity">
|
||||||
<div className="card__title--small card__title--file-card">
|
<div className="card__title--small card__title--file-card">
|
||||||
<TruncatedText lines={3}>{title}</TruncatedText>
|
<TruncatedText lines={2}>{title}</TruncatedText>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__subtitle">
|
<div className="card__subtitle">
|
||||||
{pending ? (
|
{pending ? <div>Pending...</div> : <UriIndicator uri={uri} link />}
|
||||||
<div>Pending...</div>
|
</div>
|
||||||
) : (
|
<div className="card__file-properties">
|
||||||
<React.Fragment>
|
{showPrice && <FilePrice hideFree uri={uri} />}
|
||||||
<UriIndicator uri={uri} link />
|
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
||||||
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
{fileInfo && <Icon icon={icons.LOCAL} />}
|
||||||
{fileInfo && <Icon icon={icons.LOCAL} />}
|
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{showPrice && <FilePrice uri={uri} />}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,6 +13,7 @@ type Props = {
|
||||||
filePage?: boolean,
|
filePage?: boolean,
|
||||||
inheritStyle?: boolean,
|
inheritStyle?: boolean,
|
||||||
showLBC?: boolean,
|
showLBC?: boolean,
|
||||||
|
hideFree?: boolean, // hide the file price if it's free
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilePrice extends React.PureComponent<Props> {
|
class FilePrice extends React.PureComponent<Props> {
|
||||||
|
@ -37,7 +38,11 @@ class FilePrice extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { costInfo, showFullPrice, filePage, inheritStyle, showLBC } = this.props;
|
const { costInfo, showFullPrice, filePage, inheritStyle, showLBC, hideFree } = this.props;
|
||||||
|
|
||||||
|
if (costInfo && !costInfo.cost && hideFree) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return costInfo ? (
|
return costInfo ? (
|
||||||
<CreditAmount
|
<CreditAmount
|
||||||
|
|
|
@ -116,18 +116,22 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
'card__title--x-small': small,
|
'card__title--x-small': small,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<TruncatedText lines={3}>{title || name}</TruncatedText>
|
<TruncatedText lines={small ? 2 : 3}>{title || name}</TruncatedText>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={classnames('card__subtitle', {
|
className={classnames('card__subtitle', {
|
||||||
'card__subtitle--x-small': small,
|
'card__subtitle--x-small': small,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{showUri ? uri : channel || __('Anonymous')}
|
<span className="file-tile__channel">
|
||||||
{isRewardContent && <Icon icon={icons.FEATURED} />}
|
{showUri ? uri : channel || __('Anonymous')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="card__file-properties">
|
||||||
|
<FilePrice hideFree uri={uri} />
|
||||||
|
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
||||||
{showLocal && isDownloaded && <Icon icon={icons.LOCAL} />}
|
{showLocal && isDownloaded && <Icon icon={icons.LOCAL} />}
|
||||||
</div>
|
</div>
|
||||||
<FilePrice uri={uri} />
|
|
||||||
{displayDescription && (
|
{displayDescription && (
|
||||||
<div className="card__subtext card__subtext--small">
|
<div className="card__subtext card__subtext--small">
|
||||||
<TruncatedText lines={3}>{description}</TruncatedText>
|
<TruncatedText lines={3}>{description}</TruncatedText>
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
import * as settings from 'constants/settings';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchClaimsByChannel } from 'redux/actions/content';
|
import { makeSelectClaimForUri, doSearch, makeSelectRecommendedContentForUri } from 'lbry-redux';
|
||||||
import { makeSelectClaimsInChannelForCurrentPage } from 'lbry-redux';
|
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
|
||||||
import RecommendedVideos from './view';
|
import RecommendedVideos from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
claimsInChannel: makeSelectClaimsInChannelForCurrentPage(props.channelUri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
autoplay: makeSelectClientSetting(settings.AUTOPLAY)(state),
|
recommendedContent: makeSelectRecommendedContentForUri(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
|
search: query => dispatch(doSearch(query, 20, undefined, true)),
|
||||||
setAutoplay: value => dispatch(doSetClientSetting(settings.AUTOPLAY, value)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -1,73 +1,72 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import FileTile from 'component/fileTile';
|
import FileTile from 'component/fileTile';
|
||||||
import { FormRow, FormField } from 'component/common/form';
|
|
||||||
import ToolTip from 'component/common/tooltip';
|
|
||||||
import type { Claim } from 'types/claim';
|
import type { Claim } from 'types/claim';
|
||||||
import { buildURI, parseURI } from 'lbry-redux';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
channelUri: ?string,
|
claim: ?Claim,
|
||||||
claimsInChannel: ?Array<Claim>,
|
recommendedContent: Array<string>,
|
||||||
autoplay: boolean,
|
search: string => void,
|
||||||
setAutoplay: boolean => void,
|
|
||||||
fetchClaims: (string, number) => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class RecommendedContent extends React.PureComponent<Props> {
|
export default class RecommendedContent extends React.PureComponent<Props, State> {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.didSearch = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { channelUri, fetchClaims, claimsInChannel } = this.props;
|
this.getRecommendedContent();
|
||||||
if (channelUri && !claimsInChannel) {
|
}
|
||||||
fetchClaims(channelUri, 1);
|
|
||||||
|
componentDidUpdate(prevProps: Props) {
|
||||||
|
const { claim, uri } = this.props;
|
||||||
|
|
||||||
|
if (uri !== prevProps.uri) {
|
||||||
|
this.didSearch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (claim && !this.didSearch) {
|
||||||
|
this.getRecommendedContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
getRecommendedContent() {
|
||||||
const { claimsInChannel, autoplay, uri, setAutoplay } = this.props;
|
const { claim, search } = this.props;
|
||||||
|
|
||||||
let recommendedContent;
|
if (claim && claim.value && claim.value.stream && claim.value.stream.metadata) {
|
||||||
if (claimsInChannel) {
|
const {
|
||||||
recommendedContent = claimsInChannel.filter(claim => {
|
value: {
|
||||||
const { name, claim_id: claimId, channel_name: channelName, value } = claim;
|
stream: {
|
||||||
const { isChannel } = parseURI(uri);
|
metadata: { title },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} = claim;
|
||||||
|
|
||||||
// The uri may include the channel name
|
search(title);
|
||||||
const recommendedUri =
|
this.didSearch = true;
|
||||||
isChannel && value && value.publisherSignature
|
|
||||||
? buildURI({
|
|
||||||
contentName: name,
|
|
||||||
claimName: channelName,
|
|
||||||
claimId: value.publisherSignature.certificateId,
|
|
||||||
})
|
|
||||||
: buildURI({ claimName: name, claimId });
|
|
||||||
|
|
||||||
return recommendedUri !== uri;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
didSearch: ?boolean;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { recommendedContent } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="card__list--recommended">
|
<section className="card__list--recommended">
|
||||||
<FormRow>
|
<span>Related</span>
|
||||||
<ToolTip onComponent body={__('Automatically download and play free content.')}>
|
|
||||||
<FormField
|
|
||||||
useToggle
|
|
||||||
firstInList
|
|
||||||
name="autoplay"
|
|
||||||
type="checkbox"
|
|
||||||
prefix={__('Autoplay')}
|
|
||||||
checked={autoplay}
|
|
||||||
onChange={e => setAutoplay(e.target.checked)}
|
|
||||||
/>
|
|
||||||
</ToolTip>
|
|
||||||
</FormRow>
|
|
||||||
{recommendedContent &&
|
{recommendedContent &&
|
||||||
recommendedContent.map(({ permanent_url: permanentUrl }) => (
|
recommendedContent.length &&
|
||||||
|
recommendedContent.map(recommendedUri => (
|
||||||
<FileTile
|
<FileTile
|
||||||
small
|
small
|
||||||
|
hideNoResult
|
||||||
displayDescription={false}
|
displayDescription={false}
|
||||||
key={permanentUrl}
|
key={recommendedUri}
|
||||||
uri={`lbry://${permanentUrl}`}
|
uri={recommendedUri}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -27,14 +27,14 @@ const ModalCreditIntro = (props: Props) => {
|
||||||
</p>
|
</p>
|
||||||
{currentBalance <= 0 && (
|
{currentBalance <= 0 && (
|
||||||
<p>
|
<p>
|
||||||
You currently have <CreditAmount noStyle amount={currentBalance} />, so the actions you
|
You currently have <CreditAmount inheritStyle amount={currentBalance} />, so the actions
|
||||||
can take are limited.
|
you can take are limited.
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{Boolean(totalRewardValue) && (
|
{Boolean(totalRewardValue) && (
|
||||||
<p>
|
<p>
|
||||||
There are a variety of ways to get credits, including more than{' '}
|
There are a variety of ways to get credits, including more than{' '}
|
||||||
<CreditAmount noStyle amount={totalRewardRounded} />{' '}
|
<CreditAmount inheritStyle amount={totalRewardRounded} />{' '}
|
||||||
{__('in free rewards for participating in the LBRY beta.')}
|
{__('in free rewards for participating in the LBRY beta.')}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import * as settings from 'constants/settings';
|
||||||
import { buildURI, normalizeURI, MODALS } from 'lbry-redux';
|
import { buildURI, normalizeURI, MODALS } from 'lbry-redux';
|
||||||
import FileViewer from 'component/fileViewer';
|
import FileViewer from 'component/fileViewer';
|
||||||
import Thumbnail from 'component/common/thumbnail';
|
import Thumbnail from 'component/common/thumbnail';
|
||||||
|
@ -20,6 +21,8 @@ import FileDownloadLink from 'component/fileDownloadLink';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import getMediaType from 'util/getMediaType';
|
import getMediaType from 'util/getMediaType';
|
||||||
import RecommendedContent from 'component/recommendedContent';
|
import RecommendedContent from 'component/recommendedContent';
|
||||||
|
import { FormField, FormRow } from 'component/common/form';
|
||||||
|
import ToolTip from 'component/common/tooltip';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: Claim,
|
claim: Claim,
|
||||||
|
@ -43,6 +46,8 @@ type Props = {
|
||||||
prepareEdit: ({}, string) => void,
|
prepareEdit: ({}, string) => void,
|
||||||
checkSubscription: ({ channelName: string, uri: string }) => void,
|
checkSubscription: ({ channelName: string, uri: string }) => void,
|
||||||
subscriptions: Array<Subscription>,
|
subscriptions: Array<Subscription>,
|
||||||
|
setClientSetting: (string, boolean | string) => void,
|
||||||
|
autoplay: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilePage extends React.Component<Props> {
|
class FilePage extends React.Component<Props> {
|
||||||
|
@ -59,6 +64,12 @@ class FilePage extends React.Component<Props> {
|
||||||
'application',
|
'application',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
(this: any).onAutoplayChange = this.onAutoplayChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { uri, fileInfo, fetchFileInfo, fetchCostInfo } = this.props;
|
const { uri, fileInfo, fetchFileInfo, fetchCostInfo } = this.props;
|
||||||
|
|
||||||
|
@ -79,6 +90,10 @@ class FilePage extends React.Component<Props> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onAutoplayChange(event: SyntheticInputEvent<*>) {
|
||||||
|
this.props.setClientSetting(settings.AUTOPLAY, event.target.checked);
|
||||||
|
}
|
||||||
|
|
||||||
checkSubscription = (props: Props) => {
|
checkSubscription = (props: Props) => {
|
||||||
if (props.subscriptions.find(sub => sub.channelName === props.claim.channel_name)) {
|
if (props.subscriptions.find(sub => sub.channelName === props.claim.channel_name)) {
|
||||||
props.checkSubscription({
|
props.checkSubscription({
|
||||||
|
@ -108,6 +123,7 @@ class FilePage extends React.Component<Props> {
|
||||||
navigate,
|
navigate,
|
||||||
costInfo,
|
costInfo,
|
||||||
fileInfo,
|
fileInfo,
|
||||||
|
autoplay,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// File info
|
// File info
|
||||||
|
@ -213,12 +229,23 @@ class FilePage extends React.Component<Props> {
|
||||||
<FileActions uri={uri} claimId={claim.claim_id} />
|
<FileActions uri={uri} claimId={claim.claim_id} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<FormRow padded>
|
||||||
|
<ToolTip direction="right" body={__('Automatically download and play free content.')}>
|
||||||
|
<FormField
|
||||||
|
name="autoplay"
|
||||||
|
type="checkbox"
|
||||||
|
postfix={__('Autoplay')}
|
||||||
|
checked={autoplay}
|
||||||
|
onChange={this.onAutoplayChange}
|
||||||
|
/>
|
||||||
|
</ToolTip>
|
||||||
|
</FormRow>
|
||||||
<div className="card__content--extra-padding">
|
<div className="card__content--extra-padding">
|
||||||
<FileDetails uri={uri} />
|
<FileDetails uri={uri} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<RecommendedContent uri={uri} channelUri={`lbry://${subscriptionUri}`} />
|
<RecommendedContent uri={uri} />
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,10 +257,8 @@ p {
|
||||||
}
|
}
|
||||||
|
|
||||||
.credit-amount {
|
.credit-amount {
|
||||||
font-family: 'metropolis-bold';
|
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding: $spacing-vertical * 1/6 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.credit-amount--large {
|
.credit-amount--large {
|
||||||
|
@ -269,12 +267,13 @@ p {
|
||||||
}
|
}
|
||||||
|
|
||||||
.credit-amount--file-page {
|
.credit-amount--file-page {
|
||||||
|
font-family: 'metropolis-bold';
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.credit-amount--free {
|
.credit-amount--free {
|
||||||
color: var(--color-secondary);
|
color: var(--color-credit-free);
|
||||||
|
|
||||||
&.credit-amount--file-page {
|
&.credit-amount--file-page {
|
||||||
color: var(--color-dark-blue);
|
color: var(--color-dark-blue);
|
||||||
|
@ -283,7 +282,7 @@ p {
|
||||||
}
|
}
|
||||||
|
|
||||||
.credit-amount--cost {
|
.credit-amount--cost {
|
||||||
color: var(--color-yellow);
|
color: var(--color-credit-price);
|
||||||
|
|
||||||
&.credit-amount--file-page {
|
&.credit-amount--file-page {
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
|
|
|
@ -9,7 +9,7 @@ $large-breakpoint: 1921px;
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* Widths & spacings */
|
/* Widths & spacings */
|
||||||
--side-nav-width: 190px;
|
--side-nav-width: 160px;
|
||||||
--side-nav-width-m: 240px;
|
--side-nav-width-m: 240px;
|
||||||
--side-nav-width-l: 320px;
|
--side-nav-width-l: 320px;
|
||||||
--font-size-subtext-multiple: 0.92;
|
--font-size-subtext-multiple: 0.92;
|
||||||
|
@ -49,6 +49,8 @@ $large-breakpoint: 1921px;
|
||||||
--color-bg-alt: var(--color-grey-light);
|
--color-bg-alt: var(--color-grey-light);
|
||||||
--color-placeholder: var(--color-grey);
|
--color-placeholder: var(--color-grey);
|
||||||
--color-search-placeholder: var(--color-placeholder);
|
--color-search-placeholder: var(--color-placeholder);
|
||||||
|
--color-credit-free: var(--color-dark-blue);
|
||||||
|
--color-credit-price: var(--card-text-color);
|
||||||
|
|
||||||
/* Shadows */
|
/* Shadows */
|
||||||
--box-shadow-layer: transparent; // 0 2px 4px rgba(0,0,0,0.25);
|
--box-shadow-layer: transparent; // 0 2px 4px rgba(0,0,0,0.25);
|
||||||
|
|
|
@ -111,11 +111,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__title--small {
|
.card__title--small {
|
||||||
font-size: 14px;
|
font-size: 12px;
|
||||||
line-height: 18px;
|
line-height: 12px;
|
||||||
|
|
||||||
@media only screen and (min-width: $large-breakpoint) {
|
@media only screen and (min-width: $medium-breakpoint) {
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
|
line-height: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +136,13 @@
|
||||||
|
|
||||||
.card__title--file-card {
|
.card__title--file-card {
|
||||||
padding-top: $spacing-vertical * 1/3;
|
padding-top: $spacing-vertical * 1/3;
|
||||||
|
// height is the same height that two lines of title fill
|
||||||
|
// doing this so content below the title is inline accross the row
|
||||||
|
height: 30px;
|
||||||
|
|
||||||
|
@media only screen and (min-width: $medium-breakpoint) {
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__subtitle {
|
.card__subtitle {
|
||||||
|
@ -142,12 +150,6 @@
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-family: 'metropolis-medium';
|
font-family: 'metropolis-medium';
|
||||||
color: var(--card-text-color);
|
color: var(--card-text-color);
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
margin: 0 0 0 $spacing-vertical * 1/3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__subtitle--x-small {
|
.card__subtitle--x-small {
|
||||||
|
@ -170,6 +172,18 @@
|
||||||
padding-top: $spacing-vertical * 2/3;
|
padding-top: $spacing-vertical * 2/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card__file-properties {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: $spacing-vertical * 1/3;
|
||||||
|
color: var(--card-text-color);
|
||||||
|
|
||||||
|
.icon + .icon,
|
||||||
|
.credit-amount + .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
|
||||||
.card {
|
.card {
|
||||||
.card-media__internal-links {
|
.card-media__internal-links {
|
||||||
|
|
|
@ -31,9 +31,15 @@
|
||||||
|
|
||||||
.card__subtitle {
|
.card__subtitle {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file-tile__channel {
|
||||||
|
padding-right: $spacing-width * 1/4;
|
||||||
|
}
|
||||||
|
|
||||||
.file-tile.file-tile--small {
|
.file-tile.file-tile--small {
|
||||||
padding-top: $spacing-vertical * 2/3;
|
padding-top: $spacing-vertical * 2/3;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.form-row--padded {
|
&.form-row--padded {
|
||||||
padding-top: $spacing-vertical * 2/3;
|
padding-top: $spacing-vertical * 1/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.form-row--vertically-centered {
|
&.form-row--vertically-centered {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.nav {
|
.nav {
|
||||||
width: var(--side-nav-width);
|
min-width: var(--side-nav-width);
|
||||||
background-color: var(--nav-bg-color);
|
background-color: var(--nav-bg-color);
|
||||||
padding: $spacing-width * 1/3;
|
padding: $spacing-width * 1/3;
|
||||||
color: var(--nav-color);
|
color: var(--nav-color);
|
||||||
|
@ -13,11 +13,11 @@
|
||||||
|
|
||||||
@media (min-width: $medium-breakpoint) {
|
@media (min-width: $medium-breakpoint) {
|
||||||
padding-left: $spacing-width;
|
padding-left: $spacing-width;
|
||||||
width: calc(var(--side-nav-width) * 1.2);
|
width: calc(var(--side-nav-width) * 1.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: $large-breakpoint) {
|
@media (min-width: $large-breakpoint) {
|
||||||
width: calc(var(--side-nav-width) * 1.4);
|
width: calc(var(--side-nav-width) * 1.6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-toggle-screenreader-only {
|
.react-toggle-screenreader-only {
|
||||||
|
@ -30,8 +31,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-toggle-track {
|
.react-toggle-track {
|
||||||
width: 50px;
|
width: 40px;
|
||||||
height: 24px;
|
height: 19px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
background-color: #4d4d4d;
|
background-color: #4d4d4d;
|
||||||
|
@ -61,7 +62,7 @@
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
left: 8px;
|
left: 6px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
-webkit-transition: opacity 0.25s ease;
|
-webkit-transition: opacity 0.25s ease;
|
||||||
-moz-transition: opacity 0.25s ease;
|
-moz-transition: opacity 0.25s ease;
|
||||||
|
@ -98,8 +99,8 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
left: 1px;
|
left: 1px;
|
||||||
width: 22px;
|
width: 17px;
|
||||||
height: 22px;
|
height: 17px;
|
||||||
border: 1px solid #4d4d4d;
|
border: 1px solid #4d4d4d;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
|
@ -108,6 +109,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-toggle--checked .react-toggle-thumb {
|
.react-toggle--checked .react-toggle-thumb {
|
||||||
left: 27px;
|
left: 22px;
|
||||||
border-color: var(--input-switch-color);
|
border-color: var(--input-switch-color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,8 +75,8 @@
|
||||||
|
|
||||||
.tooltip--right {
|
.tooltip--right {
|
||||||
.tooltip__body {
|
.tooltip__body {
|
||||||
margin-top: -5px;
|
margin-top: -30px;
|
||||||
margin-left: 10px;
|
margin-left: 110%;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
top: 17px;
|
top: 17px;
|
||||||
|
|
|
@ -34,6 +34,8 @@ export type Claim = {
|
||||||
publisherSignature: ?{
|
publisherSignature: ?{
|
||||||
certificateId: ?string,
|
certificateId: ?string,
|
||||||
},
|
},
|
||||||
stream: ?Metadata,
|
stream: {
|
||||||
|
metadata: ?Metadata,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
--color-bg: var(--color-blue-grey);
|
--color-bg: var(--color-blue-grey);
|
||||||
--color-bg-alt: #2D3D56;
|
--color-bg-alt: #2D3D56;
|
||||||
--color-placeholder: var(--color-bg-alt);
|
--color-placeholder: var(--color-bg-alt);
|
||||||
|
--color-credit-free: var(--color-secondary);
|
||||||
|
|
||||||
/* Text */
|
/* Text */
|
||||||
--text-color: var(--color-white);
|
--text-color: var(--color-white);
|
||||||
|
|
|
@ -5651,9 +5651,9 @@ lazy-val@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
|
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#b4fffe863df316bc73183567ab978221ee623b8c:
|
lbry-redux@lbryio/lbry-redux#03c3354c12f7834e6ed63705ff19487669be32b9:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/b4fffe863df316bc73183567ab978221ee623b8c"
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/03c3354c12f7834e6ed63705ff19487669be32b9"
|
||||||
dependencies:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
Loading…
Add table
Reference in a new issue