diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx
index 6c9b6493..77860263 100644
--- a/src/components/post-desktop/post-desktop.tsx
+++ b/src/components/post-desktop/post-desktop.tsx
@@ -1,7 +1,7 @@
import { useEffect, useRef, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { Link, useLocation, useParams } from 'react-router-dom';
-import { Comment, useAccount, useAuthorAvatar, useComment, useEditedComment } from '@plebbit/plebbit-react-hooks';
+import { Comment, useAccount, useAccountComments, useAuthorAvatar, useComment, useEditedComment } from '@plebbit/plebbit-react-hooks';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import styles from '../../views/post/post.module.css';
import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '../../lib/utils/media-utils';
@@ -383,6 +383,9 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
const visiblelinksCount = useCountLinksInReplies(post, 5);
const totalLinksCount = useCountLinksInReplies(post);
const replyCount = replies?.length;
+ const { accountComments } = useAccountComments();
+ const isPostInAccountComments = accountComments?.find((comment) => comment.cid === cid);
+
const repliesCount = pinned ? replyCount : replyCount - 5;
const linksCount = pinned ? totalLinksCount : totalLinksCount - visiblelinksCount;
const { showOmittedReplies, setShowOmittedReplies } = useShowOmittedReplies();
@@ -439,7 +442,7 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
)}
)}
- {post?.replyCount === undefined && !isInPendingPostView && (
+ {post?.replyCount === undefined && !isPostInAccountComments && !isInPendingPostView && (
diff --git a/src/hooks/use-catalog-feed-rows.ts b/src/hooks/use-catalog-feed-rows.ts
new file mode 100644
index 00000000..e2119e80
--- /dev/null
+++ b/src/hooks/use-catalog-feed-rows.ts
@@ -0,0 +1,113 @@
+import { useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useParams, useLocation } from 'react-router-dom';
+import { useAccountComments, Subplebbit } from '@plebbit/plebbit-react-hooks';
+import { isAllView } from '../lib/utils/view-utils';
+import { useMultisubMetadata } from './use-default-subplebbits';
+import useCatalogFiltersStore from '../stores/use-catalog-filters-store';
+import _ from 'lodash';
+import { getCommentMediaInfo, getHasThumbnail } from '../lib/utils/media-utils';
+
+const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolean, subplebbit: Subplebbit) => {
+ const { t } = useTranslation();
+ const { address, createdAt, description, rules, shortAddress, suggested, title } = subplebbit || {};
+ const { avatarUrl } = suggested || {};
+ const { showTextOnlyThreads } = useCatalogFiltersStore();
+
+ const location = useLocation();
+ const isInAllView = isAllView(location.pathname, useParams());
+ const multisub = useMultisubMetadata();
+
+ const { accountComments } = useAccountComments();
+
+ const feedWithFakePostsOnTop = useMemo(() => {
+ if (!isFeedLoaded) {
+ return []; // prevent rules and description from appearing while feed is loading
+ }
+
+ if (!description && !rules && !isInAllView) {
+ return feed;
+ }
+
+ 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) => {
+ const { cid, deleted, link, postCid, removed, subplebbitAddress } = comment || {};
+ const commentMediaInfo = getCommentMediaInfo(comment);
+ const isMediaShowed = getHasThumbnail(commentMediaInfo, link);
+
+ if (
+ !deleted &&
+ !removed &&
+ (!showTextOnlyThreads || (showTextOnlyThreads && !isMediaShowed)) &&
+ cid &&
+ cid === postCid &&
+ subplebbitAddress === address &&
+ !_feed.some((feedItem) => feedItem.cid === cid)
+ ) {
+ _feed.unshift({
+ ...comment,
+ isAccountComment: true,
+ });
+ }
+ });
+
+ if ((description && description.length > 0 && (showTextOnlyThreads || (!showTextOnlyThreads && suggested?.avatarUrl))) || isInAllView) {
+ _feed.unshift({
+ isDescription: true,
+ subplebbitAddress: address,
+ timestamp: createdAt,
+ author: { displayName: `## ${t('board_mods')}` },
+ content: isInAllView ? multisub?.description : description,
+ link: avatarUrl,
+ title: t('welcome_to_board', { board: isInAllView ? multisub?.title : title || `p/${shortAddress}`, interpolation: { escapeValue: false } }),
+ pinned: true,
+ locked: true,
+ });
+ }
+
+ if (rules && rules.length > 0 && showTextOnlyThreads) {
+ _feed.unshift({
+ isRules: true,
+ subplebbitAddress: address,
+ timestamp: createdAt,
+ author: { displayName: `## ${t('board_mods')}` },
+ content: rules.map((rule: string, index: number) => `${index + 1}. ${rule}`).join('\n'),
+ title: _.capitalize(t('rules')),
+ pinned: true,
+ locked: true,
+ });
+ }
+
+ return _feed;
+ }, [
+ accountComments,
+ feed,
+ description,
+ rules,
+ address,
+ isFeedLoaded,
+ createdAt,
+ title,
+ shortAddress,
+ avatarUrl,
+ t,
+ isInAllView,
+ multisub,
+ showTextOnlyThreads,
+ suggested?.avatarUrl,
+ ]);
+
+ const rows = useMemo(() => {
+ const rows = [];
+ for (let i = 0; i < feedWithFakePostsOnTop.length; i += columnCount) {
+ rows.push(feedWithFakePostsOnTop.slice(i, i + columnCount));
+ }
+ return rows;
+ }, [feedWithFakePostsOnTop, columnCount]);
+
+ return rows;
+};
+
+export default useCatalogFeedRows;
diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx
index eb1a87ad..90ef5d96 100644
--- a/src/views/board/board.tsx
+++ b/src/views/board/board.tsx
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useRef } from 'react';
import { useLocation, useParams } from 'react-router-dom';
-import { useAccount, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
+import { useAccount, useAccountComments, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { useTranslation } from 'react-i18next';
import styles from './board.module.css';
@@ -20,6 +20,20 @@ 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 } = comment || {};
+ return !deleted && !removed && cid && cid === postCid && comment?.subplebbitAddress === subplebbitAddress && !_feed.some((post) => post.cid === cid);
+ });
+
+ return filteredComments.map((comment) => );
+};
+
const Board = () => {
const { t } = useTranslation();
const location = useLocation();
@@ -161,6 +175,7 @@ const Board = () => {
title={title}
/>
)}
+ {subplebbitAddress && }
>
)}
{
- const { t } = useTranslation();
- const { address, createdAt, description, rules, shortAddress, suggested, title } = subplebbit || {};
- const { avatarUrl } = suggested || {};
- const { showTextOnlyThreads } = useCatalogFiltersStore();
-
- const location = useLocation();
- const isInAllView = isAllView(location.pathname, useParams());
- const multisub = useMultisubMetadata();
-
- const feedWithDescriptionAndRules = useMemo(() => {
- if (!isFeedLoaded) {
- return []; // prevent rules and description from appearing while feed is loading
- }
-
- if (!description && !rules && !isInAllView) {
- return feed;
- }
-
- const _feed = [...feed];
- if ((description && description.length > 0 && (showTextOnlyThreads || (!showTextOnlyThreads && suggested?.avatarUrl))) || isInAllView) {
- _feed.unshift({
- isDescription: true,
- subplebbitAddress: address,
- timestamp: createdAt,
- author: { displayName: `## ${t('board_mods')}` },
- content: isInAllView ? multisub?.description : description,
- link: avatarUrl,
- title: t('welcome_to_board', { board: isInAllView ? multisub?.title : title || `p/${shortAddress}`, interpolation: { escapeValue: false } }),
- pinned: true,
- locked: true,
- });
- }
- if (rules && rules.length > 0 && showTextOnlyThreads) {
- _feed.unshift({
- isRules: true,
- subplebbitAddress: address,
- timestamp: createdAt,
- author: { displayName: `## ${t('board_mods')}` },
- content: rules.map((rule: string, index: number) => `${index + 1}. ${rule}`).join('\n'),
- title: _.capitalize(t('rules')),
- pinned: true,
- locked: true,
- });
- }
- return _feed;
- }, [feed, description, rules, address, isFeedLoaded, createdAt, title, shortAddress, avatarUrl, t, isInAllView, multisub, showTextOnlyThreads, suggested?.avatarUrl]);
-
- const rows = useMemo(() => {
- const rows = [];
- for (let i = 0; i < feedWithDescriptionAndRules.length; i += columnCount) {
- rows.push(feedWithDescriptionAndRules.slice(i, i + columnCount));
- }
- return rows;
- }, [feedWithDescriptionAndRules, columnCount]);
-
- return rows;
-};
-
const catalogFilter = (comment: Comment) => {
const commentMediaInfo = getCommentMediaInfo(comment);
const hasThumbnail = getHasThumbnail(commentMediaInfo, comment?.link);
@@ -212,7 +152,7 @@ const Catalog = () => {
const isFeedLoaded = feed.length > 0 || state === 'failed';
- const rows = useFeedRows(columnCount, feed, isFeedLoaded, subplebbit);
+ const rows = useCatalogFeedRows(columnCount, feed, isFeedLoaded, subplebbit);
// save the last Virtuoso state to restore it when navigating back
const virtuosoRef = useRef(null);