import { memo, useMemo } from 'react';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Comment, useCommunities } from '@bitsocialnet/bitsocial-react-hooks';
import styles from '../home.module.css';
import usePopularPosts from '../../../hooks/use-popular-posts';
import { useFeedStateString } from '../../../hooks/use-state-string';
import usePopularThreadsOptionsStore from '../../../stores/use-popular-threads-options-store';
import { getCommentMediaInfo } from '../../../lib/utils/media-utils';
import { CatalogPostMedia } from '../../../components/catalog-row';
import LoadingEllipsis from '../../../components/loading-ellipsis';
import BoxModal from '../box-modal';
import { DirectoryCommunity, findDirectoryByAddress } from '../../../hooks/use-directories';
import { useCommunityIdentifiers } from '../../../hooks/use-community-identifiers';
import { getBoardPath } from '../../../lib/utils/route-utils';
import { removeMarkdown } from '../../../lib/utils/post-utils';
interface PopularThreadProps {
post: Comment;
boardTitle: string;
boardPath: string;
}
const ContentPreview = ({ content, maxLength = 99 }: { content: string; maxLength?: number }) => {
const plainText = removeMarkdown(content).trim().replaceAll(' ', '').replace(/\n\n/g, '\n').replaceAll('\n\n', '');
const truncatedText = plainText.length > maxLength ? `${plainText.substring(0, maxLength).trim()}...` : plainText;
return truncatedText;
};
const PopularThreadCard = memo(
({ post, boardTitle, boardPath }: PopularThreadProps) => {
const { cid, content, link, linkHeight, linkWidth, thumbnailUrl, title } = post || {};
const commentMediaInfo = getCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight);
return (
{boardTitle}
{title && (
<>
{title.trim()}
{content && ': '}
>
)}
{content && }
);
},
(prevProps, nextProps) => prevProps.post?.cid === nextProps.post?.cid && prevProps.boardTitle === nextProps.boardTitle && prevProps.boardPath === nextProps.boardPath,
);
const PopularThreadsBox = ({ directories, directoryAddresses }: { directories: DirectoryCommunity[]; directoryAddresses: string[] }) => {
const { t } = useTranslation();
const { showWorksafeContentOnly, showNsfwContentOnly } = usePopularThreadsOptionsStore();
const getCommentCommunityAddress = (post: Comment) => post.communityAddress || post.subplebbitAddress;
const directoryCommunities = useCommunityIdentifiers(directoryAddresses);
const { communities } = useCommunities({ communities: directoryCommunities });
const { filteredBoardAddresses, filteredCommunities } = useMemo(() => {
const filteredEntries = directoryAddresses.flatMap((address, index) => {
const directoryEntry = findDirectoryByAddress(directories, address);
if (showWorksafeContentOnly && directoryEntry?.nsfw) {
return [];
}
if (showNsfwContentOnly && !directoryEntry?.nsfw) {
return [];
}
return [{ address, community: communities[index] }];
});
return {
filteredBoardAddresses: filteredEntries.map((entry) => entry.address),
filteredCommunities: filteredEntries.map((entry) => entry.community),
};
}, [directories, directoryAddresses, showNsfwContentOnly, showWorksafeContentOnly, communities]);
const { popularPosts, isLoading } = usePopularPosts(filteredCommunities, filteredBoardAddresses);
const loadingStateString = useFeedStateString(filteredBoardAddresses) || t('loading');
return (
{t('popular_threads')}
{isLoading ? (
) : (
popularPosts.map((post: Comment) => {
const communityAddress = getCommentCommunityAddress(post);
const directoryEntry = findDirectoryByAddress(directories, communityAddress);
const boardTitle = directoryEntry?.title?.replace(/^\/[^/]+\/\s*-\s*/, '') || '';
const boardPath = communityAddress ? getBoardPath(communityAddress, directories) : '';
return
;
})
)}
);
};
export default PopularThreadsBox;