align FileActions with odysee style
This commit is contained in:
parent
0138eccb60
commit
a92a3305b1
14 changed files with 166 additions and 94 deletions
|
@ -1,7 +1,6 @@
|
|||
// @flow
|
||||
import { SIMPLE_SITE, SITE_NAME } from 'config';
|
||||
import * as PAGES from 'constants/pages';
|
||||
import * as CS from 'constants/claim_search';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
|
@ -80,32 +79,23 @@ function FileActions(props: Props) {
|
|||
|
||||
const lhsSection = (
|
||||
<>
|
||||
<ClaimSupportButton uri={uri} fileAction />
|
||||
<Button
|
||||
button="alt"
|
||||
className="button--file-action"
|
||||
icon={ICONS.REPOST}
|
||||
label={
|
||||
claim.meta.reposted > 1 ? __(`%repost_total% Reposts`, { repost_total: claim.meta.reposted }) : __('Repost')
|
||||
}
|
||||
requiresAuth={IS_WEB}
|
||||
onClick={handleRepostClick}
|
||||
/>
|
||||
<Button
|
||||
className="button--file-action"
|
||||
icon={ICONS.SHARE}
|
||||
label={__('Share')}
|
||||
onClick={() => openModal(MODALS.SOCIAL_SHARE, { uri, webShareable })}
|
||||
/>
|
||||
|
||||
<div className="button-group">
|
||||
<Button
|
||||
button="alt"
|
||||
icon={ICONS.REPOST}
|
||||
label={__('Repost')}
|
||||
requiresAuth={IS_WEB}
|
||||
onClick={handleRepostClick}
|
||||
/>
|
||||
{claim.meta.reposted > 0 && (
|
||||
<Button
|
||||
button="alt"
|
||||
label={claim.meta.reposted}
|
||||
requiresAuth={IS_WEB}
|
||||
navigate={`/$/${PAGES.DISCOVER}?${CS.REPOSTED_URI_KEY}=${encodeURIComponent(uri)}`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ClaimSupportButton uri={uri} />
|
||||
</>
|
||||
);
|
||||
|
||||
|
@ -115,7 +105,7 @@ function FileActions(props: Props) {
|
|||
|
||||
{claimIsMine && (
|
||||
<Button
|
||||
button="alt"
|
||||
className="button--file-action"
|
||||
icon={ICONS.EDIT}
|
||||
label={__('Edit')}
|
||||
navigate="/$/upload"
|
||||
|
@ -128,16 +118,16 @@ function FileActions(props: Props) {
|
|||
{showDelete && (
|
||||
<Button
|
||||
title={__('Remove from your library')}
|
||||
button="alt"
|
||||
className="button--file-action"
|
||||
icon={ICONS.DELETE}
|
||||
description={__('Delete')}
|
||||
onClick={() => openModal(MODALS.CONFIRM_FILE_REMOVE, { uri })}
|
||||
/>
|
||||
)}
|
||||
{!claimIsMine && !SIMPLE_SITE && (
|
||||
{!claimIsMine && (
|
||||
<Button
|
||||
title={__('Report content')}
|
||||
button="alt"
|
||||
className="button--file-action"
|
||||
icon={ICONS.REPORT}
|
||||
href={`https://lbry.com/dmca/${claimId}`}
|
||||
/>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// @flow
|
||||
import React, { PureComponent } from 'react';
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import MarkdownPreview from 'component/common/markdown-preview';
|
||||
import ClaimTags from 'component/claimTags';
|
||||
import Card from 'component/common/card';
|
||||
import Button from 'component/button';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
|
@ -12,35 +13,50 @@ type Props = {
|
|||
tags: any,
|
||||
};
|
||||
|
||||
class FileDescription extends PureComponent<Props> {
|
||||
render() {
|
||||
const { uri, claim, metadata, tags } = this.props;
|
||||
function FileDescription(props: Props) {
|
||||
const { uri, claim, metadata, tags } = props;
|
||||
const [expanded, setExpanded] = React.useState(false);
|
||||
const [hasOverflow, setHasOverflow] = React.useState(false);
|
||||
const [hasCalculatedOverflow, setHasCalculatedOverflow] = React.useState(false);
|
||||
const descriptionRef = React.useRef();
|
||||
|
||||
if (!claim || !metadata) {
|
||||
return <span className="empty">{__('Empty claim or metadata info.')}</span>;
|
||||
React.useEffect(() => {
|
||||
if (descriptionRef && descriptionRef.current) {
|
||||
const element = descriptionRef.current;
|
||||
const isOverflowing = element.scrollHeight > element.clientHeight;
|
||||
setHasOverflow(isOverflowing);
|
||||
setHasCalculatedOverflow(true);
|
||||
}
|
||||
}, [descriptionRef]);
|
||||
|
||||
const { description } = metadata;
|
||||
|
||||
if (!description && !(tags && tags.length)) return null;
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={__('Description')}
|
||||
defaultExpand
|
||||
actions={
|
||||
<>
|
||||
{description && (
|
||||
<div className="media__info-text">
|
||||
<MarkdownPreview className="markdown-preview--description" content={description} />
|
||||
</div>
|
||||
)}
|
||||
<ClaimTags uri={uri} type="large" />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
if (!claim || !metadata) {
|
||||
return <span className="empty">{__('Empty claim or metadata info.')}</span>;
|
||||
}
|
||||
|
||||
const { description } = metadata;
|
||||
|
||||
if (!description && !(tags && tags.length)) return null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
ref={descriptionRef}
|
||||
className={classnames({ 'media__info-text--contracted': !expanded, 'media__info-text--expanded': expanded })}
|
||||
>
|
||||
<MarkdownPreview className="markdown-preview--description" content={description} />
|
||||
<ClaimTags uri={uri} type="large" />
|
||||
</div>
|
||||
{hasCalculatedOverflow && hasOverflow && (
|
||||
<div className="media__info-expand">
|
||||
{expanded ? (
|
||||
<Button button="link" label={__('Less')} onClick={() => setExpanded(!expanded)} />
|
||||
) : (
|
||||
<Button button="link" label={__('More')} onClick={() => setExpanded(!expanded)} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FileDescription;
|
||||
|
|
|
@ -33,7 +33,7 @@ function FileDownloadLink(props: Props) {
|
|||
download,
|
||||
uri,
|
||||
claim,
|
||||
buttonType = 'alt',
|
||||
buttonType,
|
||||
showLabel = false,
|
||||
hideOpenButton = false,
|
||||
hideDownloadStatus = false,
|
||||
|
@ -107,6 +107,7 @@ function FileDownloadLink(props: Props) {
|
|||
return (
|
||||
<Button
|
||||
button={buttonType}
|
||||
className={buttonType ? undefined : 'button--file-action'}
|
||||
title={label}
|
||||
icon={ICONS.DOWNLOAD}
|
||||
label={showLabel ? label : null}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectClaimForUri, makeSelectPendingAmountByUri, makeSelectClaimIsMine } from 'lbry-redux';
|
||||
import { makeSelectClaimForUri, makeSelectPendingAmountByUri } from 'lbry-redux';
|
||||
import FileSubtitle from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
pendingAmount: makeSelectPendingAmountByUri(props.uri)(state),
|
||||
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||
});
|
||||
export default connect(select)(FileSubtitle);
|
||||
|
|
|
@ -1,41 +1,40 @@
|
|||
// @flow
|
||||
import { SIMPLE_SITE } from 'config';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
import DateTime from 'component/dateTime';
|
||||
import FileViewCount from 'component/fileViewCount';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
import HelpLink from 'component/common/help-link';
|
||||
import FileActions from 'component/fileActions';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
claim: StreamClaim,
|
||||
pendingAmount: string,
|
||||
claimIsMine: boolean,
|
||||
};
|
||||
|
||||
function FileSubtitle(props: Props) {
|
||||
const { uri, claim, pendingAmount, claimIsMine } = props;
|
||||
const claimId = claim && claim.claim_id;
|
||||
const { uri, claim, pendingAmount } = props;
|
||||
|
||||
return (
|
||||
<div className="media__subtitle--between">
|
||||
<DateTime uri={uri} show={DateTime.SHOW_DATE} />
|
||||
<span>
|
||||
{!SIMPLE_SITE && (
|
||||
<>
|
||||
<CreditAmount
|
||||
amount={parseFloat(claim.amount) + parseFloat(pendingAmount || claim.meta.support_amount)}
|
||||
precision={2}
|
||||
/>
|
||||
{' • ' /* this is bad, but it's quick! */}
|
||||
</>
|
||||
)}
|
||||
<div className="file__viewdate">
|
||||
<span>
|
||||
<DateTime uri={uri} show={DateTime.SHOW_DATE} />
|
||||
{!SIMPLE_SITE && (
|
||||
<>
|
||||
{' • ' /* this is bad, but it's quick! */}
|
||||
<CreditAmount
|
||||
amount={parseFloat(claim.amount) + parseFloat(pendingAmount || claim.meta.support_amount)}
|
||||
precision={2}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
|
||||
<FileViewCount uri={uri} />
|
||||
{claimId && !claimIsMine && SIMPLE_SITE && (
|
||||
<HelpLink description={__('Report content')} icon={ICONS.REPORT} href={`https://lbry.com/dmca/${claimId}`} />
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<FileActions uri={uri} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@ import FilePrice from 'component/filePrice';
|
|||
import ClaimInsufficientCredits from 'component/claimInsufficientCredits';
|
||||
import FileSubtitle from 'component/fileSubtitle';
|
||||
import FileAuthor from 'component/fileAuthor';
|
||||
import FileActions from 'component/fileActions';
|
||||
import Card from 'component/common/card';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import Icon from 'component/common/icon';
|
||||
import I18nMessage from 'component/i18nMessage';
|
||||
import Button from 'component/button';
|
||||
import * as PAGES from 'constants/pages';
|
||||
import FileDescription from 'component/fileDescription';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
|
@ -64,13 +64,9 @@ function FileTitle(props: Props) {
|
|||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div className="section">
|
||||
<FileActions uri={uri} />
|
||||
</div>
|
||||
<div className="section">
|
||||
<FileAuthor uri={uri} />
|
||||
</div>
|
||||
<div className="section">
|
||||
<FileAuthor uri={uri} />
|
||||
<FileDescription uri={uri} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ function FileViewCount(props: Props) {
|
|||
const formattedViewCount = Number(viewCount).toLocaleString();
|
||||
|
||||
return (
|
||||
<span>
|
||||
<span className="media__subtitle--centered">
|
||||
{viewCount !== 1 ? __('%view_count% views', { view_count: formattedViewCount }) : __('1 view')}
|
||||
<HelpLink href="https://lbry.com/faq/views" />
|
||||
</span>
|
||||
|
|
|
@ -9,8 +9,6 @@ import FileRenderInline from 'component/fileRenderInline';
|
|||
import FileRenderDownload from 'component/fileRenderDownload';
|
||||
import FileDetails from 'component/fileDetails';
|
||||
import FileValues from 'component/fileValues';
|
||||
import FileDescription from 'component/fileDescription';
|
||||
// import WaitUntilOnPage from 'component/common/wait-until-on-page';
|
||||
import RecommendedContent from 'component/recommendedContent';
|
||||
import CommentsList from 'component/commentsList';
|
||||
|
||||
|
@ -145,7 +143,6 @@ class FilePage extends React.Component<Props> {
|
|||
<Page className="file-page" filePage>
|
||||
<div className={classnames('section card-stack', `file-page__${renderMode}`)}>
|
||||
{this.renderFilePageLayout(uri, renderMode, costInfo ? costInfo.cost : null)}
|
||||
<FileDescription uri={uri} />
|
||||
<FileValues uri={uri} />
|
||||
<FileDetails uri={uri} />
|
||||
|
||||
|
|
|
@ -167,6 +167,33 @@
|
|||
}
|
||||
}
|
||||
|
||||
.button--file-action {
|
||||
@extend .button--alt;
|
||||
background-color: transparent;
|
||||
margin-right: var(--spacing-m);
|
||||
padding: 0 var(--spacing-xxs);
|
||||
|
||||
.icon {
|
||||
stroke: #777;
|
||||
}
|
||||
|
||||
.button__label {
|
||||
min-width: 10px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-button-alt-bg);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.button--disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
|
@ -173,13 +173,10 @@
|
|||
width: 100%;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-xsmall) {
|
||||
.claim-preview__text {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.claim-preview__actions {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
|
|
@ -497,3 +497,18 @@
|
|||
.autoplay-countdown__button--1 {
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
.file__viewdate {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: var(--spacing-s);
|
||||
|
||||
@media (min-width: $breakpoint-small) {
|
||||
flex-direction: column;
|
||||
margin-bottom: 0;
|
||||
|
||||
> :first-child {
|
||||
margin-bottom: var(--spacing-s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
color: var(--color-subtitle);
|
||||
margin-left: var(--spacing-xs);
|
||||
opacity: 0.7;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.icon--hidden {
|
||||
|
|
|
@ -69,11 +69,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
.media__subtitle--centered {
|
||||
@extend .media__subtitle;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.media__subtitle--between {
|
||||
@extend .media__subtitle;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
@media (min-width: $breakpoint-small) {
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.media__info-text {
|
||||
|
@ -88,12 +99,36 @@
|
|||
}
|
||||
}
|
||||
|
||||
.media__info-text--contracted {
|
||||
margin-top: var(--spacing-m);
|
||||
max-height: 5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.media__info-text--expanded {
|
||||
margin-top: var(--spacing-m);
|
||||
max-height: auto;
|
||||
}
|
||||
|
||||
.media__info-text--contracted,
|
||||
.media__info-text--expanded {
|
||||
max-width: 50rem;
|
||||
}
|
||||
|
||||
.media__info-expand {
|
||||
margin-top: var(--spacing-s);
|
||||
}
|
||||
|
||||
.media__actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
margin-top: 0;
|
||||
|
||||
> *:not(:last-child) {
|
||||
margin-right: var(--spacing-m);
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-small) {
|
||||
justify-content: flex-start;
|
||||
padding-top: var(--spacing-s);
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
}
|
||||
|
||||
.section__actions--no-margin {
|
||||
@extend .section__actions;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue