feat(thread-stats): show board page number in post stats via cache-first lookup

This commit is contained in:
plebeius
2026-02-24 18:15:50 +08:00
parent bec6bf4d51
commit 0ddb22f5fa
38 changed files with 239 additions and 35 deletions
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "إظهار لوحة الإعلانات", "show_blotter": "إظهار لوحة الإعلانات",
"top": "أعلى", "top": "أعلى",
"reply_count": "عدد الردود", "reply_count": "عدد الردود",
"pagination.pageCurrent": "الصفحة {{page}} (الحالية)" "pagination.pageCurrent": "الصفحة {{page}} (الحالية)",
"pagination.pageLabel": "صفحة"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "ঘোষণা দেখান", "show_blotter": "ঘোষণা দেখান",
"top": "শীর্ষ", "top": "শীর্ষ",
"reply_count": "উত্তরসংখ্যা", "reply_count": "উত্তরসংখ্যা",
"pagination.pageCurrent": "পৃষ্ঠা {{page}} (বর্তমান)" "pagination.pageCurrent": "পৃষ্ঠা {{page}} (বর্তমান)",
"pagination.pageLabel": "পৃষ্ঠা"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Zobrazit Oznámení", "show_blotter": "Zobrazit Oznámení",
"top": "Nahoru", "top": "Nahoru",
"reply_count": "Počet odpovědí", "reply_count": "Počet odpovědí",
"pagination.pageCurrent": "Stránka {{page}} (aktuální)" "pagination.pageCurrent": "Stránka {{page}} (aktuální)",
"pagination.pageLabel": "Stránka"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Vis Meddelelser", "show_blotter": "Vis Meddelelser",
"top": "Top", "top": "Top",
"reply_count": "Antal svar", "reply_count": "Antal svar",
"pagination.pageCurrent": "Side {{page}} (nuværende)" "pagination.pageCurrent": "Side {{page}} (nuværende)",
"pagination.pageLabel": "Side"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Ankündigungen anzeigen", "show_blotter": "Ankündigungen anzeigen",
"top": "Oben", "top": "Oben",
"reply_count": "Anzahl Antworten", "reply_count": "Anzahl Antworten",
"pagination.pageCurrent": "Seite {{page}} (aktuell)" "pagination.pageCurrent": "Seite {{page}} (aktuell)",
"pagination.pageLabel": "Seite"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Εμφάνιση Ανακοινώσεων", "show_blotter": "Εμφάνιση Ανακοινώσεων",
"top": "Πάνω", "top": "Πάνω",
"reply_count": "Αριθμός απαντήσεων", "reply_count": "Αριθμός απαντήσεων",
"pagination.pageCurrent": "Σελίδα {{page}} (τρέχουσα)" "pagination.pageCurrent": "Σελίδα {{page}} (τρέχουσα)",
"pagination.pageLabel": "Σελίδα"
} }
+2 -1
View File
@@ -282,5 +282,6 @@
"message": "Message", "message": "Message",
"show_all": "Show All", "show_all": "Show All",
"show_blotter": "Show Blotter", "show_blotter": "Show Blotter",
"reply_count": "Reply count" "reply_count": "Reply count",
"pagination.pageLabel": "Page"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Mostrar Anuncios", "show_blotter": "Mostrar Anuncios",
"top": "Arriba", "top": "Arriba",
"reply_count": "Número de respuestas", "reply_count": "Número de respuestas",
"pagination.pageCurrent": "Página {{page}} (actual)" "pagination.pageCurrent": "Página {{page}} (actual)",
"pagination.pageLabel": "Página"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "نمایش اعلانات", "show_blotter": "نمایش اعلانات",
"top": "بالا", "top": "بالا",
"reply_count": "تعداد پاسخ‌ها", "reply_count": "تعداد پاسخ‌ها",
"pagination.pageCurrent": "صفحه {{page}} (فعلی)" "pagination.pageCurrent": "صفحه {{page}} (فعلی)",
"pagination.pageLabel": "صفحه"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Näytä ilmoitukset", "show_blotter": "Näytä ilmoitukset",
"top": "Ylös", "top": "Ylös",
"reply_count": "Vastausten määrä", "reply_count": "Vastausten määrä",
"pagination.pageCurrent": "Sivu {{page}} (nykyinen)" "pagination.pageCurrent": "Sivu {{page}} (nykyinen)",
"pagination.pageLabel": "Sivu"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Ipakita ang Mga anunsyo", "show_blotter": "Ipakita ang Mga anunsyo",
"top": "Itaas", "top": "Itaas",
"reply_count": "Bilang ng mga tugon", "reply_count": "Bilang ng mga tugon",
"pagination.pageCurrent": "Pahina {{page}} (kasalukuyan)" "pagination.pageCurrent": "Pahina {{page}} (kasalukuyan)",
"pagination.pageLabel": "Pahina"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Afficher les annonces", "show_blotter": "Afficher les annonces",
"top": "Haut", "top": "Haut",
"reply_count": "Nombre de réponses", "reply_count": "Nombre de réponses",
"pagination.pageCurrent": "Page {{page}} (actuelle)" "pagination.pageCurrent": "Page {{page}} (actuelle)",
"pagination.pageLabel": "Page"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "הצג הודעות", "show_blotter": "הצג הודעות",
"top": "למעלה", "top": "למעלה",
"reply_count": "מספר תגובות", "reply_count": "מספר תגובות",
"pagination.pageCurrent": "עמוד {{page}} (נוכחי)" "pagination.pageCurrent": "עמוד {{page}} (נוכחי)",
"pagination.pageLabel": "עמוד"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "सूचनाएं दिखाएं", "show_blotter": "सूचनाएं दिखाएं",
"top": "शीर्ष", "top": "शीर्ष",
"reply_count": "जवाबों की संख्या", "reply_count": "जवाबों की संख्या",
"pagination.pageCurrent": "पृष्ठ {{page}} (वर्तमान)" "pagination.pageCurrent": "पृष्ठ {{page}} (वर्तमान)",
"pagination.pageLabel": "पृष्ठ"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Közlemények megjelenítése", "show_blotter": "Közlemények megjelenítése",
"top": "Felül", "top": "Felül",
"reply_count": "Válaszok száma", "reply_count": "Válaszok száma",
"pagination.pageCurrent": "{{page}}. oldal (jelenlegi)" "pagination.pageCurrent": "{{page}}. oldal (jelenlegi)",
"pagination.pageLabel": "Oldal"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Tampilkan Pengumuman", "show_blotter": "Tampilkan Pengumuman",
"top": "Atas", "top": "Atas",
"reply_count": "Jumlah balasan", "reply_count": "Jumlah balasan",
"pagination.pageCurrent": "Halaman {{page}} (saat ini)" "pagination.pageCurrent": "Halaman {{page}} (saat ini)",
"pagination.pageLabel": "Halaman"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Mostra annunci", "show_blotter": "Mostra annunci",
"top": "In alto", "top": "In alto",
"reply_count": "Numero di risposte", "reply_count": "Numero di risposte",
"pagination.pageCurrent": "Pagina {{page}} (corrente)" "pagination.pageCurrent": "Pagina {{page}} (corrente)",
"pagination.pageLabel": "Pagina"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "お知らせを表示", "show_blotter": "お知らせを表示",
"top": "上", "top": "上",
"reply_count": "返信数", "reply_count": "返信数",
"pagination.pageCurrent": "{{page}}ページ(現在)" "pagination.pageCurrent": "{{page}}ページ(現在)",
"pagination.pageLabel": "ページ"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "공지 표시", "show_blotter": "공지 표시",
"top": "맨 위", "top": "맨 위",
"reply_count": "답글 수", "reply_count": "답글 수",
"pagination.pageCurrent": "{{page}}페이지 (현재)" "pagination.pageCurrent": "{{page}}페이지 (현재)",
"pagination.pageLabel": "페이지"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "जाहिराती दाखवा", "show_blotter": "जाहिराती दाखवा",
"top": "वर", "top": "वर",
"reply_count": "प्रत्युत्तरांची संख्या", "reply_count": "प्रत्युत्तरांची संख्या",
"pagination.pageCurrent": "पृष्ठ {{page}} (वर्तमान)" "pagination.pageCurrent": "पृष्ठ {{page}} (वर्तमान)",
"pagination.pageLabel": "पृष्ठ"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Mededelingen tonen", "show_blotter": "Mededelingen tonen",
"top": "Boven", "top": "Boven",
"reply_count": "Aantal reacties", "reply_count": "Aantal reacties",
"pagination.pageCurrent": "Pagina {{page}} (huidige)" "pagination.pageCurrent": "Pagina {{page}} (huidige)",
"pagination.pageLabel": "Pagina"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Vis Kunngjøringer", "show_blotter": "Vis Kunngjøringer",
"top": "Topp", "top": "Topp",
"reply_count": "Antall svar", "reply_count": "Antall svar",
"pagination.pageCurrent": "Side {{page}} (nåværende)" "pagination.pageCurrent": "Side {{page}} (nåværende)",
"pagination.pageLabel": "Side"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Pokaż Ogłoszenia", "show_blotter": "Pokaż Ogłoszenia",
"top": "Góra", "top": "Góra",
"reply_count": "Liczba odpowiedzi", "reply_count": "Liczba odpowiedzi",
"pagination.pageCurrent": "Strona {{page}} (bieżąca)" "pagination.pageCurrent": "Strona {{page}} (bieżąca)",
"pagination.pageLabel": "Strona"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Mostrar Anúncios", "show_blotter": "Mostrar Anúncios",
"top": "Topo", "top": "Topo",
"reply_count": "Número de respostas", "reply_count": "Número de respostas",
"pagination.pageCurrent": "Página {{page}} (atual)" "pagination.pageCurrent": "Página {{page}} (atual)",
"pagination.pageLabel": "Página"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Afișează Blotter", "show_blotter": "Afișează Blotter",
"top": "Sus", "top": "Sus",
"reply_count": "Număr de răspunsuri", "reply_count": "Număr de răspunsuri",
"pagination.pageCurrent": "Pagina {{page}} (curentă)" "pagination.pageCurrent": "Pagina {{page}} (curentă)",
"pagination.pageLabel": "Pagină"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Показать объявления", "show_blotter": "Показать объявления",
"top": "Вверх", "top": "Вверх",
"reply_count": "Количество ответов", "reply_count": "Количество ответов",
"pagination.pageCurrent": "Страница {{page}} (текущая)" "pagination.pageCurrent": "Страница {{page}} (текущая)",
"pagination.pageLabel": "Страница"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Shfaq Njoftimet", "show_blotter": "Shfaq Njoftimet",
"top": "Lart", "top": "Lart",
"reply_count": "Numri i përgjigjeve", "reply_count": "Numri i përgjigjeve",
"pagination.pageCurrent": "Faqja {{page}} (aktuale)" "pagination.pageCurrent": "Faqja {{page}} (aktuale)",
"pagination.pageLabel": "Faqe"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Visa Meddelanden", "show_blotter": "Visa Meddelanden",
"top": "Topp", "top": "Topp",
"reply_count": "Antal svar", "reply_count": "Antal svar",
"pagination.pageCurrent": "Sida {{page}} (nuvarande)" "pagination.pageCurrent": "Sida {{page}} (nuvarande)",
"pagination.pageLabel": "Sida"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "ప్రకటనలు చూపించు", "show_blotter": "ప్రకటనలు చూపించు",
"top": "పై", "top": "పై",
"reply_count": "సమాధానాల సంఖ్య", "reply_count": "సమాధానాల సంఖ్య",
"pagination.pageCurrent": "పేజీ {{page}} (ప్రస్తుత)" "pagination.pageCurrent": "పేజీ {{page}} (ప్రస్తుత)",
"pagination.pageLabel": "పేజీ"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "แสดงประกาศ", "show_blotter": "แสดงประกาศ",
"top": "บน", "top": "บน",
"reply_count": "จำนวนการตอบกลับ", "reply_count": "จำนวนการตอบกลับ",
"pagination.pageCurrent": "หน้า {{page}} (ปัจจุบัน)" "pagination.pageCurrent": "หน้า {{page}} (ปัจจุบัน)",
"pagination.pageLabel": "หน้า"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Duyuruları Göster", "show_blotter": "Duyuruları Göster",
"top": "Üst", "top": "Üst",
"reply_count": "Yanıt sayısı", "reply_count": "Yanıt sayısı",
"pagination.pageCurrent": "Sayfa {{page}} (mevcut)" "pagination.pageCurrent": "Sayfa {{page}} (mevcut)",
"pagination.pageLabel": "Sayfa"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Показати оголошення", "show_blotter": "Показати оголошення",
"top": "Вгору", "top": "Вгору",
"reply_count": "Кількість відповідей", "reply_count": "Кількість відповідей",
"pagination.pageCurrent": "Сторінка {{page}} (поточна)" "pagination.pageCurrent": "Сторінка {{page}} (поточна)",
"pagination.pageLabel": "Сторінка"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "اعلانات دکھائیں", "show_blotter": "اعلانات دکھائیں",
"top": "اوپر", "top": "اوپر",
"reply_count": "جوابوں کی تعداد", "reply_count": "جوابوں کی تعداد",
"pagination.pageCurrent": "صفحہ {{page}} (موجودہ)" "pagination.pageCurrent": "صفحہ {{page}} (موجودہ)",
"pagination.pageLabel": "صفحہ"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "Hiển thị Thông báo", "show_blotter": "Hiển thị Thông báo",
"top": "Trên", "top": "Trên",
"reply_count": "Số lượng phản hồi", "reply_count": "Số lượng phản hồi",
"pagination.pageCurrent": "Trang {{page}} (hiện tại)" "pagination.pageCurrent": "Trang {{page}} (hiện tại)",
"pagination.pageLabel": "Trang"
} }
+2 -1
View File
@@ -281,5 +281,6 @@
"show_blotter": "显示公告", "show_blotter": "显示公告",
"top": "顶部", "top": "顶部",
"reply_count": "回复数", "reply_count": "回复数",
"pagination.pageCurrent": "第{{page}}页(当前)" "pagination.pageCurrent": "第{{page}}页(当前)",
"pagination.pageLabel": "页"
} }
@@ -2,6 +2,7 @@ import { useTranslation } from 'react-i18next';
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'; import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
import { useAccountComment, useComment, useSubscribe } from '@plebbit/plebbit-react-hooks'; import { useAccountComment, useComment, useSubscribe } from '@plebbit/plebbit-react-hooks';
import { isAllView, isCatalogView, isModView, isModQueueView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; import { isAllView, isCatalogView, isModView, isModQueueView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
import { usePostPageNumber } from '../../hooks/use-post-page-number';
import { useDirectories } from '../../hooks/use-directories'; import { useDirectories } from '../../hooks/use-directories';
import { getBoardPath, isDirectoryBoard } from '../../lib/utils/route-utils'; import { getBoardPath, isDirectoryBoard } from '../../lib/utils/route-utils';
import { useResolvedSubplebbitAddress } from '../../hooks/use-resolved-subplebbit-address'; import { useResolvedSubplebbitAddress } from '../../hooks/use-resolved-subplebbit-address';
@@ -457,7 +458,11 @@ export const MobileBoardButtons = () => {
export const PostPageStats = () => { export const PostPageStats = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const params = useParams(); const params = useParams();
const location = useLocation();
const commentCid = params?.commentCid as string | undefined; const commentCid = params?.commentCid as string | undefined;
const resolvedAddress = useResolvedSubplebbitAddress();
const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any });
const subplebbitAddress = resolvedAddress || accountComment?.subplebbitAddress;
const comment = useComment({ commentCid }); const comment = useComment({ commentCid });
const postCid = comment?.parentCid ?? commentCid; const postCid = comment?.parentCid ?? commentCid;
@@ -466,6 +471,13 @@ export const PostPageStats = () => {
const { closed, pinned, replyCount } = post || {}; const { closed, pinned, replyCount } = post || {};
const linkCount = useCountLinksInReplies(post); const linkCount = useCountLinksInReplies(post);
const isThreadView = isPostPageView(location.pathname, params);
const pageNumber = usePostPageNumber({
subplebbitAddress,
postCid,
enabled: isThreadView,
});
const displayReplyCount = replyCount !== undefined ? replyCount.toString() : '?'; const displayReplyCount = replyCount !== undefined ? replyCount.toString() : '?';
const replyCountTooltip = replyCount !== undefined ? capitalize(t('replies')) : t('loading'); const replyCountTooltip = replyCount !== undefined ? capitalize(t('replies')) : t('loading');
@@ -474,6 +486,12 @@ export const PostPageStats = () => {
{pinned && `${capitalize(t('sticky'))} / `} {pinned && `${capitalize(t('sticky'))} / `}
{closed && `${capitalize(t('closed'))} / `} {closed && `${capitalize(t('closed'))} / `}
<Tooltip content={replyCountTooltip}>{displayReplyCount}</Tooltip> / <Tooltip content={capitalize(t('links'))}>{linkCount?.toString()}</Tooltip> <Tooltip content={replyCountTooltip}>{displayReplyCount}</Tooltip> / <Tooltip content={capitalize(t('links'))}>{linkCount?.toString()}</Tooltip>
{isThreadView && (
<>
{' '}
/ <Tooltip content={pageNumber != null ? t('pagination.pageLabel') : t('loading')}>{pageNumber?.toString() ?? '?'}</Tooltip>
</>
)}
</span> </span>
); );
}; };
+55
View File
@@ -0,0 +1,55 @@
import { useMemo } from 'react';
import { useFeed } from '@plebbit/plebbit-react-hooks';
import useFeedsStore from '@plebbit/plebbit-react-hooks/dist/stores/feeds';
import { useDirectoryByAddress } from './use-directories';
import { useBoardFeedPageSize } from './use-board-feed-page-size';
import { findPostPageInFeed, findPostPageInLoadedBoardFeeds, type FeedsOptionsLike, type LoadedFeedsLike } from '../lib/utils/post-page-resolution';
export interface UsePostPageNumberOptions {
subplebbitAddress: string | undefined;
postCid: string | undefined;
/** When false, page segment is excluded (e.g. pending-post view). When true, resolve and show page. */
enabled?: boolean;
}
/**
* Resolve the board pagination page (1-based) for a post in a thread view.
* Uses cache-first lookup from feeds store, then preloads via useFeed if miss.
* Preload depth is capped to board pagination window (10 pages via paginationFeedPostsPerPage).
*
* @returns 1-based page number, or undefined when unresolved (render as "?")
*/
export function usePostPageNumber({ subplebbitAddress, postCid, enabled = true }: UsePostPageNumberOptions): number | undefined {
const community = useDirectoryByAddress(subplebbitAddress);
const { guiPostsPerPage, paginationFeedPostsPerPage } = useBoardFeedPageSize(community);
const canResolve = Boolean(enabled && subplebbitAddress && postCid && guiPostsPerPage > 0);
// Cache-first: selector returns only computed page to minimize rerenders
const cachedPage = useFeedsStore((state) => {
if (!canResolve) return undefined;
return findPostPageInLoadedBoardFeeds(state.feedsOptions as FeedsOptionsLike, state.loadedFeeds as LoadedFeedsLike, subplebbitAddress!, postCid!, guiPostsPerPage);
});
// Preload when cache miss and enabled (10 GUI pages)
const preloadOptions = useMemo(
() =>
canResolve
? {
subplebbitAddresses: [subplebbitAddress!],
sortType: 'active' as const,
postsPerPage: paginationFeedPostsPerPage,
}
: undefined,
[canResolve, subplebbitAddress, paginationFeedPostsPerPage],
);
const { feed: preloadFeed } = useFeed(preloadOptions);
const preloadedPage = useMemo(() => {
if (!canResolve || !preloadFeed?.length) return undefined;
return findPostPageInFeed(preloadFeed, postCid!, guiPostsPerPage);
}, [canResolve, postCid, preloadFeed, guiPostsPerPage]);
return cachedPage ?? preloadedPage;
}
+96
View File
@@ -0,0 +1,96 @@
/**
* Post page resolution utilities.
* Page semantics are board pagination pages (not catalog ordering, not fetch-chunk index).
*/
/** Minimal Comment shape with cid */
export interface CommentWithCid {
cid?: string;
[key: string]: unknown;
}
/** Minimal FeedOptions shape for board-feed filtering */
export interface FeedOptionsLike {
subplebbitAddresses: string[];
sortType: string;
postsPerPage?: number;
filter?: unknown;
newerThan?: number;
modQueue?: unknown;
accountComments?: unknown;
}
/** FeedsOptions-like map */
export type FeedsOptionsLike = Record<string, FeedOptionsLike>;
/** Loaded feeds map: feedName -> Comment[] */
export type LoadedFeedsLike = Record<string, CommentWithCid[]>;
/**
* Find the board pagination page (1-based) containing postCid in a feed.
* Pure index math: page = floor(index / guiPostsPerPage) + 1.
*
* @param feed - Array of comments (posts) in feed order
* @param postCid - CID of the post (OP) to locate
* @param guiPostsPerPage - Posts per GUI page
* @returns 1-based page number, or undefined if post not found
*/
export function findPostPageInFeed(feed: CommentWithCid[], postCid: string, guiPostsPerPage: number): number | undefined {
if (!postCid || guiPostsPerPage <= 0) return undefined;
const index = feed.findIndex((c) => c.cid === postCid);
if (index < 0) return undefined;
return Math.floor(index / guiPostsPerPage) + 1;
}
/**
* Strict board-feed filter criteria.
* A feed is a "board feed" iff:
* - sortType === 'active'
* - single-sub feed (subplebbitAddresses.length === 1)
* - no filter, no newerThan, no modQueue, no accountComments
*/
export function isBoardFeedOptions(opts: FeedOptionsLike, subplebbitAddress: string): boolean {
return (
opts.sortType === 'active' &&
opts.subplebbitAddresses?.length === 1 &&
opts.subplebbitAddresses[0] === subplebbitAddress &&
!opts.filter &&
opts.newerThan == null &&
!opts.modQueue &&
!opts.accountComments
);
}
/**
* Find the board pagination page for postCid by searching loaded board feeds.
* Only considers feeds matching strict board-feed criteria.
*
* @param feedsOptions - Feeds store feedsOptions
* @param loadedFeeds - Feeds store loadedFeeds
* @param subplebbitAddress - Board subplebbit address
* @param postCid - CID of the post (OP) to locate
* @param guiPostsPerPage - Posts per GUI page
* @returns 1-based page number, or undefined if not found in any matching feed
*/
export function findPostPageInLoadedBoardFeeds(
feedsOptions: FeedsOptionsLike,
loadedFeeds: LoadedFeedsLike,
subplebbitAddress: string,
postCid: string,
guiPostsPerPage: number,
): number | undefined {
if (!subplebbitAddress || !postCid || guiPostsPerPage <= 0) return undefined;
for (const feedName of Object.keys(feedsOptions)) {
const opts = feedsOptions[feedName];
if (!opts || !isBoardFeedOptions(opts, subplebbitAddress)) continue;
const feed = loadedFeeds[feedName];
if (!feed || !Array.isArray(feed)) continue;
const page = findPostPageInFeed(feed, postCid, guiPostsPerPage);
if (page !== undefined) return page;
}
return undefined;
}