mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-03-21 13:19:22 +01:00
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:
parent
5944b4fe30
commit
7e84088d67
2 changed files with 74 additions and 29 deletions
10
src/app.css
10
src/app.css
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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…{' '}
|
Show more…{' '}
|
||||||
<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;
|
||||||
|
|
Loading…
Reference in a new issue