Improve comments rendering

- Don't render summary/details if not needed
- Delay-render collapsed summary/details
This commit is contained in:
Lim Chee Aun 2024-10-31 18:48:13 +08:00
parent cbfd4ef333
commit 2f53fd332f
2 changed files with 132 additions and 111 deletions

8
src/locales/en.po generated
View file

@ -186,7 +186,7 @@ msgstr ""
#: src/pages/catchup.jsx:1445 #: src/pages/catchup.jsx:1445
#: src/pages/catchup.jsx:2056 #: src/pages/catchup.jsx:2056
#: src/pages/status.jsx:921 #: src/pages/status.jsx:921
#: src/pages/status.jsx:1523 #: src/pages/status.jsx:1543
msgid "Replies" msgid "Replies"
msgstr "" msgstr ""
@ -3636,15 +3636,15 @@ msgstr ""
msgid "Unable to load post" msgid "Unable to load post"
msgstr "" msgstr ""
#: src/pages/status.jsx:1455 #: src/pages/status.jsx:1473
msgid "{0, plural, one {# reply} other {<0>{1}</0> replies}}" msgid "{0, plural, one {# reply} other {<0>{1}</0> replies}}"
msgstr "" msgstr ""
#: src/pages/status.jsx:1473 #: src/pages/status.jsx:1491
msgid "{totalComments, plural, one {# comment} other {<0>{0}</0> comments}}" msgid "{totalComments, plural, one {# comment} other {<0>{0}</0> comments}}"
msgstr "" msgstr ""
#: src/pages/status.jsx:1495 #: src/pages/status.jsx:1513
msgid "View post with its replies" msgid "View post with its replies"
msgstr "" msgstr ""

View file

@ -1423,130 +1423,151 @@ function SubComments({
}; };
}, []); }, []);
// If not open, delay render replies
const [renderReplies, setRenderReplies] = useState(openBefore || open);
useEffect(() => {
let timer;
if (!openBefore && !open) {
timer = setTimeout(() => setRenderReplies(true), 100);
}
return () => clearTimeout(timer);
}, [openBefore, open]);
const Container = open ? 'div' : 'details';
const isDetails = Container === 'details';
return ( return (
<details <Container
ref={detailsRef} ref={detailsRef}
class="replies" class="replies"
open={openBefore || open} open={isDetails ? openBefore || open : undefined}
onToggle={(e) => { onToggle={
const { open } = e.target; isDetails
// use first reply as ID ? (e) => {
cachedRepliesToggle[replies[0].id] = open; const { open } = e.target;
}} // use first reply as ID
cachedRepliesToggle[replies[0].id] = open;
}
: undefined
}
style={{ style={{
'--comments-level': level, '--comments-level': level,
}} }}
data-comments-level={level} data-comments-level={level}
data-comments-level-overflow={level > 4} data-comments-level-overflow={level > 4}
> >
<summary class="replies-summary" hidden={open}> {!open && (
<span class="avatars"> <summary class="replies-summary" hidden={open}>
{accounts.map((a) => ( <span class="avatars">
<Avatar {accounts.map((a) => (
key={a.id} <Avatar
url={a.avatarStatic} key={a.id}
title={`${a.displayName} @${a.username}`} url={a.avatarStatic}
squircle={a?.bot} title={`${a.displayName} @${a.username}`}
/> squircle={a?.bot}
))} />
</span> ))}
<span class="replies-counts"> </span>
<b> <span class="replies-counts">
<Plural <b>
value={replies.length} <Plural
one="# reply" value={replies.length}
other={ one="# reply"
<Trans> other={
<span title={replies.length}> <Trans>
{shortenNumber(replies.length)} <span title={replies.length}>
</span>{' '} {shortenNumber(replies.length)}
replies </span>{' '}
</Trans> replies
} </Trans>
/> }
</b> />
{!sameCount && totalComments > 1 && ( </b>
<> {!sameCount && totalComments > 1 && (
{' '} <>
&middot;{' '} {' '}
<span> &middot;{' '}
<Plural <span>
value={totalComments} <Plural
one="# comment" value={totalComments}
other={ one="# comment"
<Trans> other={
<span title={totalComments}> <Trans>
{shortenNumber(totalComments)} <span title={totalComments}>
</span>{' '} {shortenNumber(totalComments)}
comments </span>{' '}
</Trans> comments
} </Trans>
/> }
</span> />
</> </span>
</>
)}
</span>
<Icon icon="chevron-down" class="replies-summary-chevron" />
{!!parentLink && (
<Link
class="replies-parent-link"
to={parentLink.to}
onClick={parentLink.onClick}
title={t`View post with its replies`}
>
&raquo;
</Link>
)} )}
</span> </summary>
<Icon icon="chevron-down" class="replies-summary-chevron" /> )}
{!!parentLink && ( {renderReplies && (
<Link <ul>
class="replies-parent-link" {replies.map((r) => (
to={parentLink.to} <li key={r.id}>
onClick={parentLink.onClick} {/* <Link
title={t`View post with its replies`}
>
&raquo;
</Link>
)}
</summary>
<ul>
{replies.map((r) => (
<li key={r.id}>
{/* <Link
class="status-link" class="status-link"
to={instance ? `/${instance}/s/${r.id}` : `/s/${r.id}`} to={instance ? `/${instance}/s/${r.id}` : `/s/${r.id}`}
onClick={() => { onClick={() => {
resetScrollPosition(r.id); resetScrollPosition(r.id);
}} }}
> */} > */}
<div class="status-focus" tabIndex={0}> <div class="status-focus" tabIndex={0}>
<Status <Status
statusID={r.id} statusID={r.id}
instance={instance} instance={instance}
withinContext withinContext
size="s" size="s"
enableTranslate enableTranslate
onMediaClick={handleMediaClick} onMediaClick={handleMediaClick}
showActionsBar showActionsBar
/> />
{!r.replies?.length && r.repliesCount > 0 && ( {!r.replies?.length && r.repliesCount > 0 && (
<div class="replies-link"> <div class="replies-link">
<Icon icon="comment2" alt={t`Replies`} />{' '} <Icon icon="comment2" alt={t`Replies`} />{' '}
<span title={r.repliesCount}> <span title={r.repliesCount}>
{shortenNumber(r.repliesCount)} {shortenNumber(r.repliesCount)}
</span> </span>
</div> </div>
)}
</div>
{/* </Link> */}
{r.replies?.length && (
<SubComments
instance={instance}
replies={r.replies}
level={r.level}
accWeight={!open ? r.weight : totalWeight}
openAll={openAll}
parentLink={{
to: instance ? `/${instance}/s/${r.id}` : `/s/${r.id}`,
onClick: () => {
resetScrollPosition(r.id);
},
}}
/>
)} )}
</div> </li>
{/* </Link> */} ))}
{r.replies?.length && ( </ul>
<SubComments )}
instance={instance} </Container>
replies={r.replies}
level={r.level}
accWeight={!open ? r.weight : totalWeight}
openAll={openAll}
parentLink={{
to: instance ? `/${instance}/s/${r.id}` : `/s/${r.id}`,
onClick: () => {
resetScrollPosition(r.id);
},
}}
/>
)}
</li>
))}
</ul>
</details>
); );
} }