mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-02-02 14:16:39 +01:00
Smarter logic for auto-collapsing
This logic is getting similar to HackerWeb's
This commit is contained in:
parent
54849b60a9
commit
4c188ab59b
1 changed files with 52 additions and 41 deletions
|
@ -42,7 +42,6 @@ import useTitle from '../utils/useTitle';
|
|||
import getInstanceStatusURL from './../utils/get-instance-status-url';
|
||||
|
||||
const LIMIT = 40;
|
||||
const THREAD_LIMIT = 20;
|
||||
|
||||
let cachedRepliesToggle = {};
|
||||
let cachedStatusesMap = {};
|
||||
|
@ -293,6 +292,7 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
|||
account: _r.account,
|
||||
repliesCount: _r.repliesCount,
|
||||
content: _r.content,
|
||||
weight: calcStatusWeight(_r),
|
||||
replies: expandReplies(_r.__replies),
|
||||
}));
|
||||
}
|
||||
|
@ -304,13 +304,19 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
|||
isThread: ancestorsIsThread,
|
||||
accountID: s.account.id,
|
||||
repliesCount: s.repliesCount,
|
||||
weight: calcStatusWeight(s),
|
||||
})),
|
||||
{ id, accountID: heroStatus.account.id },
|
||||
{
|
||||
id,
|
||||
accountID: heroStatus.account.id,
|
||||
weight: calcStatusWeight(heroStatus),
|
||||
},
|
||||
...nestedDescendants.map((s) => ({
|
||||
id: s.id,
|
||||
accountID: s.account.id,
|
||||
descendant: true,
|
||||
thread: s.account.id === heroStatus.account.id,
|
||||
weight: calcStatusWeight(s),
|
||||
replies: expandReplies(s.__replies),
|
||||
})),
|
||||
];
|
||||
|
@ -412,6 +418,7 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
|||
states.reloadStatusPage = 0;
|
||||
cachedStatusesMap = {};
|
||||
cachedRepliesToggle = {};
|
||||
statusWeightCache.clear();
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
@ -458,7 +465,6 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
|||
return statuses.length - limit;
|
||||
}, [statuses.length, limit]);
|
||||
|
||||
const hasManyStatuses = statuses.length > THREAD_LIMIT;
|
||||
const hasDescendants = statuses.some((s) => s.descendant);
|
||||
const ancestors = statuses.filter((s) => s.ancestor);
|
||||
|
||||
|
@ -589,6 +595,12 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
|||
});
|
||||
}, []);
|
||||
|
||||
const totalWeight = useMemo(() => {
|
||||
return statuses.reduce((acc, status) => {
|
||||
return acc + status.weight;
|
||||
}, 0);
|
||||
}, [id, statuses?.length]);
|
||||
|
||||
return (
|
||||
<div
|
||||
tabIndex="-1"
|
||||
|
@ -778,6 +790,7 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
|||
thread,
|
||||
replies,
|
||||
repliesCount,
|
||||
weight,
|
||||
} = status;
|
||||
const isHero = statusID === id;
|
||||
return (
|
||||
|
@ -898,10 +911,10 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
|||
{descendant && replies?.length > 0 && (
|
||||
<SubComments
|
||||
instance={instance}
|
||||
hasManyStatuses={hasManyStatuses}
|
||||
replies={replies}
|
||||
hasParentThread={thread}
|
||||
level={1}
|
||||
accWeight={totalWeight}
|
||||
/>
|
||||
)}
|
||||
{uiState === 'loading' &&
|
||||
|
@ -980,33 +993,8 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
|||
);
|
||||
}
|
||||
|
||||
function SubComments({
|
||||
hasManyStatuses,
|
||||
replies,
|
||||
instance,
|
||||
hasParentThread,
|
||||
level,
|
||||
previousOpen,
|
||||
}) {
|
||||
function SubComments({ replies, instance, hasParentThread, level, accWeight }) {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
// Set isBrief = true:
|
||||
// - if less than or 2 replies
|
||||
// - if replies have no sub-replies
|
||||
// - if total number of characters of content from replies is less than 500
|
||||
let isBrief = false;
|
||||
if (replies.length <= 2) {
|
||||
const containsSubReplies = replies.some(
|
||||
(r) => r.repliesCount > 0 || r.replies?.length > 0,
|
||||
);
|
||||
if (!containsSubReplies) {
|
||||
let totalLength = replies.reduce((acc, reply) => {
|
||||
const { content } = reply;
|
||||
const length = htmlContentLength(content);
|
||||
return acc + length;
|
||||
}, 0);
|
||||
isBrief = totalLength < 500;
|
||||
}
|
||||
}
|
||||
|
||||
// Total comments count, including sub-replies
|
||||
const diveDeep = (replies) => {
|
||||
|
@ -1026,16 +1014,12 @@ function SubComments({
|
|||
.slice(0, 3);
|
||||
|
||||
let open = false;
|
||||
// const open =
|
||||
// !previousOpen &&
|
||||
// (!hasParentThread || totalComments === 1) &&
|
||||
// (isBrief || !hasManyStatuses);
|
||||
if (hasParentThread) {
|
||||
open = totalComments === 1;
|
||||
} else {
|
||||
open = isBrief;
|
||||
if (accWeight < 5) {
|
||||
open = true;
|
||||
} else if (!hasParentThread && totalComments === 1) {
|
||||
const shortReply = calcStatusWeight(replies[0]) < 2;
|
||||
if (shortReply) open = true;
|
||||
}
|
||||
if (!previousOpen && !open) open = true;
|
||||
const openBefore = cachedRepliesToggle[replies[0].id];
|
||||
|
||||
const handleMediaClick = useCallback((e, i, media, status) => {
|
||||
|
@ -1060,6 +1044,12 @@ function SubComments({
|
|||
};
|
||||
}, []);
|
||||
|
||||
const totalWeight = useMemo(() => {
|
||||
return replies?.reduce((acc, reply) => {
|
||||
return acc + reply?.weight;
|
||||
}, 0);
|
||||
}, [replies?.length]);
|
||||
|
||||
return (
|
||||
<details
|
||||
ref={detailsRef}
|
||||
|
@ -1134,10 +1124,9 @@ function SubComments({
|
|||
{r.replies?.length && (
|
||||
<SubComments
|
||||
instance={instance}
|
||||
hasManyStatuses={hasManyStatuses}
|
||||
replies={r.replies}
|
||||
level={level + 1}
|
||||
previousOpen={open}
|
||||
accWeight={!open ? totalWeight : accWeight + totalWeight}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
|
@ -1147,4 +1136,26 @@ function SubComments({
|
|||
);
|
||||
}
|
||||
|
||||
const MEDIA_VIRTUAL_LENGTH = 140;
|
||||
const POLL_VIRTUAL_LENGTH = 35;
|
||||
const CARD_VIRTUAL_LENGTH = 70;
|
||||
const WEIGHT_SEGMENT = 140;
|
||||
const statusWeightCache = new Map();
|
||||
function calcStatusWeight(status) {
|
||||
const cachedWeight = statusWeightCache.get(status.id);
|
||||
if (cachedWeight) return cachedWeight;
|
||||
const { spoilerText, content, mediaAttachments, poll, card } = status;
|
||||
const length = htmlContentLength(spoilerText + content);
|
||||
const mediaLength = mediaAttachments?.length ? MEDIA_VIRTUAL_LENGTH : 0;
|
||||
const pollLength = (poll?.options?.length || 0) * POLL_VIRTUAL_LENGTH;
|
||||
const cardLength =
|
||||
card && (mediaAttachments?.length || poll?.options?.length)
|
||||
? 0
|
||||
: CARD_VIRTUAL_LENGTH;
|
||||
const totalLength = length + mediaLength + pollLength + cardLength;
|
||||
const weight = totalLength / WEIGHT_SEGMENT;
|
||||
statusWeightCache.set(status.id, weight);
|
||||
return weight;
|
||||
}
|
||||
|
||||
export default memo(StatusPage);
|
||||
|
|
Loading…
Reference in a new issue