Handle case when too many sub-comments

For now, encourage clicking on status to see more replies instead of expanding the sub-comments
Feels "wasted" since the comments are already loaded but it's just too much scrolling

Also auto-open if the sub-comments are not a lot.
This commit is contained in:
Lim Chee Aun 2022-12-23 00:30:55 +08:00
parent 5944b4fe30
commit 7e84088d67
2 changed files with 74 additions and 29 deletions

View file

@ -197,6 +197,16 @@ a.mention span {
border-color: transparent transparent var(--comment-line-color) transparent; border-color: transparent transparent var(--comment-line-color) transparent;
transform: rotate(45deg); transform: rotate(45deg);
} }
.timeline.contextual > li .replies-link {
color: var(--text-insignificant-color);
margin-left: 16px;
margin-top: -12px;
padding-bottom: 12px;
font-size: 90%;
}
.timeline.contextual > li .replies-link * {
vertical-align: middle;
}
.timeline.contextual > li .replies { .timeline.contextual > li .replies {
margin-top: -12px; margin-top: -12px;
} }

View file

@ -12,11 +12,14 @@ import { useSnapshot } from 'valtio';
import Icon from '../components/icon'; import Icon from '../components/icon';
import Loader from '../components/loader'; import Loader from '../components/loader';
import Status from '../components/status'; import Status from '../components/status';
import htmlContentLength from '../utils/html-content-length';
import shortenNumber from '../utils/shorten-number'; import shortenNumber from '../utils/shorten-number';
import states from '../utils/states'; import states from '../utils/states';
import store from '../utils/store'; import store from '../utils/store';
import useTitle from '../utils/useTitle'; import useTitle from '../utils/useTitle';
const LIMIT = 40;
function StatusPage({ id }) { function StatusPage({ id }) {
const snapStates = useSnapshot(states); const snapStates = useSnapshot(states);
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
@ -215,13 +218,13 @@ function StatusPage({ id }) {
}); });
const closeLink = `#${prevRoute || '/'}`; const closeLink = `#${prevRoute || '/'}`;
const [limit, setLimit] = useState(40); const [limit, setLimit] = useState(LIMIT);
const showMore = useMemo(() => { const showMore = useMemo(() => {
// return number of statuses to show // return number of statuses to show
return statuses.length - limit; return statuses.length - limit;
}, [statuses.length, limit]); }, [statuses.length, limit]);
const hasManyStatuses = statuses.length > 40; const hasManyStatuses = statuses.length > LIMIT;
const hasDescendants = statuses.some((s) => s.descendant); const hasDescendants = statuses.some((s) => s.descendant);
return ( return (
@ -286,33 +289,24 @@ function StatusPage({ id }) {
withinContext withinContext
size={thread || ancestor ? 'm' : 's'} size={thread || ancestor ? 'm' : 's'}
/> />
{replies?.length > LIMIT && (
<div class="replies-link">
<Icon icon="comment" />{' '}
<span title={replies.length}>
{shortenNumber(replies.length)}
</span>
</div>
)}
</Link> </Link>
)} )}
{descendant && replies?.length > 0 && ( {descendant &&
<details class="replies" open={!hasManyStatuses}> replies?.length > 0 &&
<summary hidden={!hasManyStatuses}> replies?.length <= LIMIT && (
<span title={replies.length}> <SubComments
{shortenNumber(replies.length)} hasManyStatuses={hasManyStatuses}
</span>{' '} replies={replies}
repl{replies.length === 1 ? 'y' : 'ies'} />
</summary> )}
<ul>
{replies.map((replyID) => (
<li key={replyID}>
<Link
class="status-link"
href={`#/s/${replyID}`}
onClick={() => {
userInitiated.current = true;
}}
>
<Status statusID={replyID} withinContext size="s" />
</Link>
</li>
))}
</ul>
</details>
)}
{uiState === 'loading' && {uiState === 'loading' &&
isHero && isHero &&
!!heroStatus?.repliesCount && !!heroStatus?.repliesCount &&
@ -330,11 +324,13 @@ function StatusPage({ id }) {
type="button" type="button"
class="plain block" class="plain block"
disabled={uiState === 'loading'} disabled={uiState === 'loading'}
onClick={() => setLimit((l) => l + 40)} onClick={() => setLimit((l) => l + LIMIT)}
style={{ marginBlockEnd: '6em' }} style={{ marginBlockEnd: '6em' }}
> >
Show more&hellip;{' '} Show more&hellip;{' '}
<span class="tag">{showMore > 40 ? '40+' : showMore}</span> <span class="tag">
{showMore > LIMIT ? `${LIMIT}+` : showMore}
</span>
</button> </button>
</li> </li>
)} )}
@ -344,4 +340,43 @@ function StatusPage({ id }) {
); );
} }
function SubComments({ hasManyStatuses, replies }) {
// If less than or 2 replies and total number of characters of content from replies is less than 500
let isBrief = false;
if (replies.length <= 2) {
let totalLength = replies.reduce((acc, reply) => {
const { content } = reply;
const length = htmlContentLength(content);
return acc + length;
}, 0);
isBrief = totalLength < 500;
}
const open = isBrief || !hasManyStatuses;
return (
<details class="replies" open={open}>
<summary hidden={open}>
<span title={replies.length}>{shortenNumber(replies.length)}</span> repl
{replies.length === 1 ? 'y' : 'ies'}
</summary>
<ul>
{replies.map((replyID) => (
<li key={replyID}>
<Link
class="status-link"
href={`#/s/${replyID}`}
onClick={() => {
userInitiated.current = true;
}}
>
<Status statusID={replyID} withinContext size="s" />
</Link>
</li>
))}
</ul>
</details>
);
}
export default StatusPage; export default StatusPage;