Improve ~more~ comment viewing operation (#1798)
This commit is contained in:
parent
3233e3ab64
commit
7ecbb779af
6 changed files with 81 additions and 88 deletions
|
@ -26,7 +26,7 @@ import React, { useEffect, useState } from 'react';
|
||||||
import { parseURI } from 'util/lbryURI';
|
import { parseURI } from 'util/lbryURI';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Expandable from 'component/expandable';
|
import Expandable from 'component/common/expandable';
|
||||||
import MarkdownPreview from 'component/common/markdown-preview';
|
import MarkdownPreview from 'component/common/markdown-preview';
|
||||||
import CommentBadge from 'component/common/comment-badge';
|
import CommentBadge from 'component/common/comment-badge';
|
||||||
import ChannelThumbnail from 'component/channelThumbnail';
|
import ChannelThumbnail from 'component/channelThumbnail';
|
||||||
|
@ -88,8 +88,6 @@ type Props = {
|
||||||
threadDepthLevel?: number,
|
threadDepthLevel?: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
const LENGTH_TO_COLLAPSE = 300;
|
|
||||||
|
|
||||||
function CommentView(props: Props) {
|
function CommentView(props: Props) {
|
||||||
const {
|
const {
|
||||||
comment,
|
comment,
|
||||||
|
@ -176,7 +174,6 @@ function CommentView(props: Props) {
|
||||||
const contentChannelClaim = getChannelFromClaim(claim);
|
const contentChannelClaim = getChannelFromClaim(claim);
|
||||||
const commentByOwnerOfContent = contentChannelClaim && contentChannelClaim.permanent_url === authorUri;
|
const commentByOwnerOfContent = contentChannelClaim && contentChannelClaim.permanent_url === authorUri;
|
||||||
const stickerFromMessage = parseSticker(message);
|
const stickerFromMessage = parseSticker(message);
|
||||||
const isExpandable = editedMessage.length >= LENGTH_TO_COLLAPSE;
|
|
||||||
|
|
||||||
let channelOwnerOfContent;
|
let channelOwnerOfContent;
|
||||||
try {
|
try {
|
||||||
|
@ -388,8 +385,8 @@ function CommentView(props: Props) {
|
||||||
<div className="sticker__comment">
|
<div className="sticker__comment">
|
||||||
<OptimizedImage src={stickerFromMessage.url} waitLoad loading="lazy" />
|
<OptimizedImage src={stickerFromMessage.url} waitLoad loading="lazy" />
|
||||||
</div>
|
</div>
|
||||||
) : isExpandable ? (
|
) : (
|
||||||
<Expandable beginCollapsed>
|
<Expandable>
|
||||||
<MarkdownPreview
|
<MarkdownPreview
|
||||||
content={message}
|
content={message}
|
||||||
promptLinks
|
promptLinks
|
||||||
|
@ -398,14 +395,6 @@ function CommentView(props: Props) {
|
||||||
hasMembership={Boolean(commenterMembership)}
|
hasMembership={Boolean(commenterMembership)}
|
||||||
/>
|
/>
|
||||||
</Expandable>
|
</Expandable>
|
||||||
) : (
|
|
||||||
<MarkdownPreview
|
|
||||||
content={message}
|
|
||||||
promptLinks
|
|
||||||
parentCommentId={commentId}
|
|
||||||
stakedLevel={stakedLevel}
|
|
||||||
hasMembership={Boolean(commenterMembership)}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
70
ui/component/common/expandable.jsx
Normal file
70
ui/component/common/expandable.jsx
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// @flow
|
||||||
|
import React from 'react';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import Button from 'component/button';
|
||||||
|
import { useOnResize } from 'effects/use-on-resize';
|
||||||
|
|
||||||
|
const COLLAPSED_HEIGHT = 120;
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: React$Node | Array<React$Node>,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Expandable(props: Props) {
|
||||||
|
const { children } = props;
|
||||||
|
|
||||||
|
const ref = React.useRef();
|
||||||
|
|
||||||
|
const [expanded, setExpanded] = React.useState(false);
|
||||||
|
const [childRect, setRect] = React.useState();
|
||||||
|
|
||||||
|
const childOverflows = childRect && childRect.height > COLLAPSED_HEIGHT;
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
setExpanded(!expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the rect when children changes,
|
||||||
|
// this is needed when there is an image or claim embed
|
||||||
|
// to be loaded ! :D
|
||||||
|
React.useLayoutEffect(() => {
|
||||||
|
if (ref.current) {
|
||||||
|
const childElem = ref.current.children[0];
|
||||||
|
setRect(childElem.getBoundingClientRect());
|
||||||
|
}
|
||||||
|
}, [children]);
|
||||||
|
|
||||||
|
const expandableRef = React.useCallback((node) => {
|
||||||
|
if (node) {
|
||||||
|
const childElem = node.children[0];
|
||||||
|
setRect(childElem.getBoundingClientRect());
|
||||||
|
ref.current = node;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Update the childRect initially & when the window size changes.
|
||||||
|
useOnResize(() => expandableRef(ref.current));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={classnames('expandable', {
|
||||||
|
'expandable--open': expanded,
|
||||||
|
'expandable--closed-fade': !expanded && childOverflows,
|
||||||
|
})}
|
||||||
|
ref={expandableRef}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{childOverflows && (
|
||||||
|
<Button
|
||||||
|
button="link"
|
||||||
|
className="expandable__button"
|
||||||
|
label={expanded ? __('Less') : __('More')}
|
||||||
|
onClick={handleClick}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
import Expandable from './view';
|
|
||||||
|
|
||||||
export default Expandable;
|
|
|
@ -1,67 +0,0 @@
|
||||||
// @flow
|
|
||||||
import React, { useRef, useState } from 'react';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import Button from 'component/button';
|
|
||||||
import { useOnResize } from 'effects/use-on-resize';
|
|
||||||
|
|
||||||
const COLLAPSED_HEIGHT = 120;
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
children: React$Node | Array<React$Node>,
|
|
||||||
beginCollapsed?: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function Expandable(props: Props) {
|
|
||||||
const { children, beginCollapsed } = props;
|
|
||||||
|
|
||||||
const [expanded, setExpanded] = useState(false);
|
|
||||||
const [rect, setRect] = useState();
|
|
||||||
const ref = useRef();
|
|
||||||
|
|
||||||
// Update the rect initially & when the window size changes.
|
|
||||||
useOnResize(() => {
|
|
||||||
if (ref.current) {
|
|
||||||
setRect(ref.current.getBoundingClientRect());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the rect when children changes,
|
|
||||||
// not sure if this is needed but a situation could arise when the
|
|
||||||
// component re-renders with a different children prop,
|
|
||||||
// Can enable on a later date if needed.
|
|
||||||
// useLayoutEffect(() => {
|
|
||||||
// console.log('render, useLayoutEffect');
|
|
||||||
// if (ref.current) {
|
|
||||||
// setRect(ref.current.getBoundingClientRect());
|
|
||||||
// }
|
|
||||||
// }, [children]);
|
|
||||||
|
|
||||||
function handleClick() {
|
|
||||||
setExpanded(!expanded);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={ref}>
|
|
||||||
{(rect && rect.height > COLLAPSED_HEIGHT) || beginCollapsed ? (
|
|
||||||
<div ref={ref}>
|
|
||||||
<div
|
|
||||||
className={classnames({
|
|
||||||
'expandable--open': expanded,
|
|
||||||
'expandable--closed': !expanded,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
button="link"
|
|
||||||
className="expandable__button"
|
|
||||||
label={expanded ? __('Less') : __('More')}
|
|
||||||
onClick={handleClick}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div>{children}</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -14,5 +14,6 @@ export function useOnResize(cb) {
|
||||||
|
|
||||||
return () => window.removeEventListener('resize', handleResize);
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isWindowClient]);
|
}, [isWindowClient]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
$COLLAPSED_HEIGHT: 120px;
|
$COLLAPSED_HEIGHT: 120px;
|
||||||
|
|
||||||
|
.expandable {
|
||||||
|
max-height: 120px;
|
||||||
|
position: relative;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.expandable--closed,
|
.expandable--closed,
|
||||||
.expandable--open {
|
.expandable--open {
|
||||||
margin-bottom: var(--spacing-s);
|
margin-bottom: var(--spacing-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.expandable--closed {
|
.expandable--closed-fade {
|
||||||
max-height: calc(#{$COLLAPSED_HEIGHT} * 3 / 4);
|
|
||||||
overflow-y: hidden;
|
|
||||||
position: relative;
|
|
||||||
-webkit-mask-image: -webkit-gradient(linear, left 30%, left bottom, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
-webkit-mask-image: -webkit-gradient(linear, left 30%, left bottom, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue