lbry-desktop/ui/component/postViewer/view.jsx
infinite-persistence 032e17cecd
Improve CLS on Posts
## Issue
6068 Fix "Cumulative Layout Shift" for Core Web Vitals

In Posts, the Comments section appears first while we fetch the MD file. When the MD is fetched, Comments get pushed to the bottom (or shifted up for short posts), hence the red CLS scores.

## Approach
There are too many layers between `<FilePage>` and `<DocumentViewer>` to pass the `loading` state around to hide the Comments section, so just make Comments fade in after a 2s delay.

## Changes
- Posts: Add 2s fade-in delay to Comments.
- Posts: remove the gray placeholder. This improves the score a bit more, and reduces flicker as well. There's already a spinner from `FileRenderInline` to tell the user to be patient.
- Posts: add a minimum 30vh height so that short posts don't get collapsed too much, causing the `FileDetails` and Comments to shift. Small shifts are fine as long as CLS is below 0.1.
2021-07-22 10:38:01 +08:00

117 lines
3.5 KiB
JavaScript

// @flow
import * as React from 'react';
import * as ICONS from 'constants/icons';
import * as MODALS from 'constants/modal_types';
import { formatCredits } from 'lbry-redux';
import FileDetails from 'component/fileDetails';
import ClaimAuthor from 'component/claimAuthor';
import FileTitle from 'component/fileTitle';
import FileActions from 'component/fileActions';
import FileRenderInitiator from 'component/fileRenderInitiator';
import FileRenderInline from 'component/fileRenderInline';
import FileValues from 'component/fileValues';
import FileViewCount from 'component/fileViewCount';
import ClaimTags from 'component/claimTags';
import DateTime from 'component/dateTime';
import Button from 'component/button';
import LbcSymbol from 'component/common/lbc-symbol';
import classnames from 'classnames';
const EXPAND = {
NONE: 'none',
CREDIT_DETAILS: 'credit_details',
FILE_DETAILS: 'file_details',
};
type Props = {
uri: string,
claim: ?StreamClaim,
claimIsMine: boolean,
doOpenModal: (id: string, {}) => void,
};
function PostViewer(props: Props) {
const { uri, claim, claimIsMine, doOpenModal } = props;
const [expand, setExpand] = React.useState(EXPAND.NONE);
if (!claim) {
return null;
}
const amount = parseFloat(claim.amount) + parseFloat(claim.meta.support_amount);
const formattedAmount = formatCredits(amount, 2, true);
const hasSupport = claim && claim.meta && claim.meta.support_amount && Number(claim.meta.support_amount) > 0;
function handleExpand(newExpand) {
if (expand === newExpand) {
setExpand(EXPAND.NONE);
} else {
setExpand(newExpand);
}
}
return (
<div className="post">
<FileTitle uri={uri} className="post__title">
<span className="post__date">
<DateTime uri={uri} show={DateTime.SHOW_DATE} />
</span>
</FileTitle>
<div
className={classnames('post__info', {
'post__info--expanded': expand !== EXPAND.NONE,
})}
>
<div className="post__info--grouped">
<Button
button="link"
className="dim"
icon={ICONS.INFO}
aria-label={__('View claim details')}
onClick={() => handleExpand(EXPAND.FILE_DETAILS)}
/>
<Button button="link" className="dim" onClick={() => handleExpand(EXPAND.CREDIT_DETAILS)}>
<LbcSymbol postfix={expand === EXPAND.CREDIT_DETAILS ? __('Hide') : formattedAmount} />
</Button>
{claimIsMine && hasSupport && (
<Button
button="link"
className="expandable__button"
icon={ICONS.UNLOCK}
aria-label={__('Unlock tips')}
onClick={() => {
doOpenModal(MODALS.LIQUIDATE_SUPPORTS, { uri });
}}
/>
)}
</div>
<FileViewCount uri={uri} />
</div>
{expand === EXPAND.CREDIT_DETAILS && (
<div className="section post__info--credit-details">
<FileValues uri={uri} />
</div>
)}
{expand === EXPAND.FILE_DETAILS && (
<div className="section post__info--credit-details">
<ClaimTags uri={uri} type="large" />
<FileDetails uri={uri} />
</div>
)}
<ClaimAuthor uri={uri} />
<div className="file-render--post-container">
<FileRenderInitiator uri={uri} />
<FileRenderInline uri={uri} />
</div>
<FileActions uri={uri} />
</div>
);
}
export default PostViewer;