show newly published account comments after pinned threads

This commit is contained in:
Tom (plebeius.eth)
2024-08-04 15:40:09 +02:00
parent 4103fabb12
commit a992912e10
2 changed files with 111 additions and 95 deletions
+19 -10
View File
@@ -31,29 +31,38 @@ const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolea
const _feed = [...feed];
// show account comments instantly in the feed instead of waiting for the next feed update, then hide them when they are in the feed
accountComments.forEach((comment) => {
// show account comments instantly in the feed once published (cid defined), instead of waiting for the feed to update
const filteredComments = accountComments.filter((comment) => {
const { cid, deleted, link, postCid, removed, state, subplebbitAddress } = comment || {};
const commentMediaInfo = getCommentMediaInfo(comment);
const isMediaShowed = getHasThumbnail(commentMediaInfo, link);
if (
return (
!deleted &&
!removed &&
state === 'succeeded' &&
(!showTextOnlyThreads || (showTextOnlyThreads && !isMediaShowed)) &&
(showTextOnlyThreads || (!showTextOnlyThreads && isMediaShowed)) &&
cid &&
cid === postCid &&
subplebbitAddress === address &&
!_feed.some((feedItem) => feedItem.cid === cid)
) {
_feed.unshift({
...comment,
isAccountComment: true,
});
}
);
});
// show newest account comment at the top of the feed but after pinned posts
const lastPinnedIndex = _feed.map((post) => post.pinned).lastIndexOf(true);
if (filteredComments.length > 0) {
_feed.splice(
lastPinnedIndex + 1,
0,
...filteredComments.map((comment) => ({
...comment,
isAccountComment: true,
})),
);
}
// add subplebbit description and rules as fake posts at the top of the feed
if ((description && description.length > 0 && (showTextOnlyThreads || (!showTextOnlyThreads && suggested?.avatarUrl))) || isInAllView) {
_feed.unshift({
isDescription: true,
+92 -85
View File
@@ -20,28 +20,6 @@ import SubplebbitRules from '../../components/subplebbit-rules';
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
// show account comments instantly in the feed instead of waiting for the next feed update, then hide them when they are in the feed
const AccountCommentsNotYetInFeed = ({ subplebbitAddress, feed }: { subplebbitAddress: string; feed: any }) => {
const { accountComments } = useAccountComments();
const _feed = [...feed];
const filteredComments = accountComments.filter((comment) => {
const { cid, deleted, postCid, removed, state } = comment || {};
return (
!deleted &&
!removed &&
state === 'succeeded' &&
cid &&
cid === postCid &&
comment?.subplebbitAddress === subplebbitAddress &&
!_feed.some((post) => post.cid === cid)
);
});
return filteredComments.map((comment) => <Post key={comment.cid} post={comment} />);
};
const Board = () => {
const { t } = useTranslation();
const location = useLocation();
@@ -67,22 +45,60 @@ const Board = () => {
const { sortType } = useSortingStore();
const { timeFilterSeconds } = useTimeFilter();
const feedOptions: any = {
subplebbitAddresses,
sortType,
postsPerPage: isInAllView || isInSubscriptionsView ? 5 : 25,
};
if (isInAllView || isInSubscriptionsView) {
feedOptions.newerThan = timeFilterSeconds;
}
const feedOptions: any = useMemo(
() => ({
subplebbitAddresses,
sortType,
postsPerPage: isInAllView || isInSubscriptionsView ? 5 : 25,
...(isInAllView || isInSubscriptionsView ? { newerThan: timeFilterSeconds } : {}),
}),
[subplebbitAddresses, sortType, timeFilterSeconds, isInAllView, isInSubscriptionsView],
);
const { feed, hasMore, loadMore, reset } = useFeed(feedOptions);
const { accountComments } = useAccountComments();
const resetTriggeredRef = useRef(false);
const setResetFunction = useFeedResetStore((state) => state.setResetFunction);
useEffect(() => {
setResetFunction(reset);
}, [reset, setResetFunction]);
}, [reset, setResetFunction, feed]);
// show account comments instantly in the feed once published (cid defined), instead of waiting for the feed to update
const filteredComments = useMemo(
() =>
accountComments.filter((comment) => {
const { cid, deleted, postCid, removed, state } = comment || {};
return (
!deleted &&
!removed &&
state === 'succeeded' &&
cid &&
cid === postCid &&
comment?.subplebbitAddress === subplebbitAddress &&
!feed.some((post) => post.cid === cid)
);
}),
[accountComments, subplebbitAddress, feed],
);
// show newest account comment at the top of the feed but after pinned posts
const combinedFeed = useMemo(() => {
const newFeed = [...feed];
const lastPinnedIndex = newFeed.map((post) => post.pinned).lastIndexOf(true);
if (filteredComments.length > 0) {
newFeed.splice(lastPinnedIndex + 1, 0, ...filteredComments);
}
return newFeed;
}, [feed, filteredComments]);
useEffect(() => {
if (filteredComments.length > 0 && !resetTriggeredRef.current) {
reset();
resetTriggeredRef.current = true;
}
}, [filteredComments, reset]);
const subplebbit = useSubplebbit({ subplebbitAddress });
const { createdAt, description, error, rules, shortAddress, state, suggested } = subplebbit || {};
@@ -90,6 +106,7 @@ const Board = () => {
const { activeCid, closeModal, openReplyModal, showReplyModal, scrollY } = useReplyModal();
const { blocked, unblock } = useBlock({ address: subplebbitAddress });
const loadingStateString = useFeedStateString(subplebbitAddresses) || t('loading');
const loadingString = (
<div className={styles.stateString}>
@@ -97,6 +114,10 @@ const Board = () => {
<span className='red'>{state}</span>
) : isInSubscriptionsView && subscriptions?.length === 0 ? (
t('not_subscribed_to_any_board')
) : blocked ? (
'you have blocked this board'
) : !hasMore && feed.length === 0 ? (
t('no_posts')
) : (
<LoadingEllipsis string={loadingStateString} />
)}
@@ -109,40 +130,8 @@ const Board = () => {
</div>
);
const { blocked, unblock } = useBlock({ address: subplebbitAddress });
const Footer = () => {
let footerContent;
if (feed.length === 0) {
if (blocked) {
footerContent = 'you have blocked this board';
} else {
footerContent = t('no_posts');
}
}
if (hasMore || subplebbitAddresses.length === 0) {
footerContent = loadingString;
}
return (
<div className={styles.footer}>
{footerContent}
{blocked && (
<>
&nbsp;&nbsp;[
<span
className={styles.button}
onClick={() => {
unblock();
reset();
}}
>
Unblock
</span>
]
</>
)}
</div>
);
return <div className={styles.footer}>{loadingString}</div>;
};
// save the last Virtuoso state to restore it when navigating back
@@ -170,7 +159,7 @@ const Board = () => {
<div className={styles.content}>
{location.pathname.endsWith('/settings') && <SettingsModal />}
{showReplyModal && activeCid && <ReplyModal closeModal={closeModal} parentCid={activeCid} scrollY={scrollY} />}
{feed.length > 0 && (
{feed.length !== 0 ? (
<>
{rules && rules.length > 0 && <SubplebbitRules subplebbitAddress={subplebbitAddress} createdAt={createdAt} rules={rules} />}
{((description && description.length > 0) || isInAllView) && (
@@ -183,26 +172,44 @@ const Board = () => {
title={title}
/>
)}
{subplebbitAddress && <AccountCommentsNotYetInFeed subplebbitAddress={subplebbitAddress} feed={feed} />}
</>
)}
<Virtuoso
increaseViewportBy={{ bottom: 1200, top: 1200 }}
totalCount={feed?.length || 0}
data={feed}
itemContent={(index, post) => {
const { deleted, locked, removed } = post || {};
const isThreadClosed = deleted || locked || removed;
<Virtuoso
increaseViewportBy={{ bottom: 1200, top: 1200 }}
totalCount={combinedFeed.length}
data={combinedFeed}
itemContent={(index, post) => {
const { deleted, locked, removed } = post || {};
const isThreadClosed = deleted || locked || removed;
return <Post index={index} post={post} openReplyModal={isThreadClosed ? () => alert(t('thread_closed_alert')) : openReplyModal} />;
}}
useWindowScroll={true}
components={{ Footer }}
endReached={loadMore}
ref={virtuosoRef}
restoreStateFrom={lastVirtuosoState}
initialScrollTop={lastVirtuosoState?.scrollTop}
/>
return <Post index={index} post={post} openReplyModal={isThreadClosed ? () => alert(t('thread_closed_alert')) : openReplyModal} />;
}}
useWindowScroll={true}
components={{ Footer }}
endReached={loadMore}
ref={virtuosoRef}
restoreStateFrom={lastVirtuosoState}
initialScrollTop={lastVirtuosoState?.scrollTop}
/>
</>
) : (
<div className={styles.footer}>
{loadingString}
{blocked && (
<>
&nbsp;&nbsp;[
<span
className={styles.button}
onClick={() => {
unblock();
reset();
}}
>
Unblock
</span>
]
</>
)}
</div>
)}
</div>
);
};