fix(codebase audit): preserve cleanup without regressions

Fix codebase audit regressions while preserving UI/UX behavior and adding review-driven hardening.
This commit is contained in:
Tommaso Casaburi
2026-04-24 15:48:07 +07:00
committed by GitHub
parent 5df994b2c7
commit 5dc5408a15
70 changed files with 1478 additions and 518 deletions
+40 -39
View File
@@ -34,6 +34,7 @@ import LoadingEllipsis from '../loading-ellipsis';
import PostMenuDesktop from './post-menu-desktop';
import ReplyQuotePreview from '../reply-quote-preview';
import Tooltip from '../tooltip';
import TimeAgoTooltip from '../time-ago-tooltip';
import { PostProps } from '../../views/post/post';
import { create } from 'zustand';
import capitalize from 'lodash/capitalize';
@@ -244,8 +245,8 @@ const PostInfo = ({
const location = useLocation();
const isInPostPageView = isPostPageView(location.pathname, params);
const isInModQueueView = isModQueueView(location.pathname);
const { getAlertThresholdSeconds } = useModQueueStore();
const currentTime = useCurrentTime();
const getAlertThresholdSeconds = useModQueueStore((state) => state.getAlertThresholdSeconds);
const currentTime = useCurrentTime(isInModQueueView ? 60 : false);
const account = useAccount();
const accountAddress = account?.author?.address;
@@ -282,22 +283,26 @@ const PostInfo = ({
return Math.max(postsByAuthorInThread?.get(shortAddress) ?? 0, 1);
})();
const { hidden } = useHide(post);
const { hidden } = useHide({ cid: cid || '' });
const { openReplyModal } = useReplyModalStore();
const onReplyModalClick = () => {
deleted
? isReply
? alert(t('this_reply_was_deleted'))
: alert(t('this_thread_was_deleted'))
: removed || purged
? isReply
? alert(t('this_reply_was_removed'))
: alert(t('this_thread_was_removed'))
: archived && !isReply
? alert(t('thread_archived'))
: openReplyModal && openReplyModal(cid, post?.number, postCid, threadNumber, communityAddress);
if (deleted) {
alert(t(isReply ? 'this_reply_was_deleted' : 'this_thread_was_deleted'));
return;
}
if (removed || purged) {
alert(t(isReply ? 'this_reply_was_removed' : 'this_thread_was_removed'));
return;
}
if (archived && !isReply) {
alert(t('thread_archived'));
return;
}
if (cid && postCid && communityAddress && openReplyModal) {
openReplyModal(cid, post?.number, postCid, threadNumber, communityAddress);
}
};
const threadRoute = cid ? (boardPath ? `/${boardPath}/thread/${cid}` : `/thread/${cid}`) : undefined;
@@ -329,7 +334,7 @@ const PostInfo = ({
return (
<div className={styles.postInfo} data-post-info-cid={cid}>
{isHidden ? parentCid && <span className={styles.hiddenReplyEditMenuSpacer} /> : <EditMenu post={post} />}
{isHidden ? parentCid && <span className={styles.hiddenReplyEditMenuSpacer} /> : post ? <EditMenu post={post} /> : null}
<span className={(hidden || ((removed || deleted || purged) && !reason)) && parentCid ? styles.postDesktopHidden : ''}>
{title &&
(title.length <= 75 ? (
@@ -410,15 +415,15 @@ const PostInfo = ({
<span className={styles.dateTime}>
{isInModQueueView && isOverThreshold ? (
<>
<Tooltip content={getFormattedTimeAgo(timestamp)}>
<TimeAgoTooltip timestamp={timestamp}>
<span>{getFormattedDate(timestamp)}</span>
</Tooltip>{' '}
</TimeAgoTooltip>{' '}
(<span className={styles.alert}>{getFormattedTimeAgo(timestamp)}</span>)
</>
) : (
<Tooltip content={getFormattedTimeAgo(timestamp)}>
<TimeAgoTooltip timestamp={timestamp}>
<span>{getFormattedDate(timestamp)}</span>
</Tooltip>
</TimeAgoTooltip>
)}{' '}
</span>
<span className={styles.postNum}>
@@ -529,7 +534,7 @@ const PostInfo = ({
{shouldShowPendingApprovalButtons && communityAddress && cid && <PendingModerationActions cid={cid} communityAddress={communityAddress} post={post} />}
</span>
{!(removed || deleted || purged) && !isModQueue && <PostMenuDesktop postMenu={postMenuProps} />}
{cid && parentCid && <ReplyBacklinks post={post} quotedByMap={quotedByMap} directRepliesByParentCid={directRepliesByParentCid} />}
{post && cid && parentCid && <ReplyBacklinks post={post} quotedByMap={quotedByMap} directRepliesByParentCid={directRepliesByParentCid} />}
{cid && !parentCid && <OpBacklinks cid={cid} quotedByMap={quotedByMap} />}
</span>
</div>
@@ -589,13 +594,13 @@ const OpBacklinks = ({ cid, quotedByMap }: { cid: string; quotedByMap?: Map<stri
interface PostMediaProps {
commentMediaInfo: CommentMediaInfo | undefined;
hasThumbnail: boolean;
spoiler: boolean;
deleted: boolean;
spoiler?: boolean;
deleted?: boolean;
purged: boolean;
removed: boolean;
linkHeight: number;
linkWidth: number;
parentCid: string;
removed?: boolean;
linkHeight?: number;
linkWidth?: number;
parentCid?: string;
communityAddress?: string;
isInAllView: boolean;
isInSubscriptionsView: boolean;
@@ -659,7 +664,8 @@ const PostMedia = ({
if (spoiler) return capitalize(t('spoiler'));
if (requirePostLinkIsMedia && url) {
try {
const filename = new URL(url).pathname.split('/').pop();
const pathParts = new URL(url).pathname.split('/');
const filename = pathParts[pathParts.length - 1];
if (filename && /\.\w+$/.test(filename)) return truncateWithEllipsisInMiddle(filename);
} catch {}
}
@@ -809,7 +815,7 @@ const Reply = ({
isInModView={isInModView}
/>
)}
{!hidden && (!(removed || deleted || purged) || ((removed || deleted) && reason) || purged) && (
{post && !hidden && (!(removed || deleted || purged) || ((removed || deleted) && reason) || purged) && (
<CommentContent comment={post} prependContent={failedPublishNotice} />
)}
</div>
@@ -836,8 +842,7 @@ const PostDesktop = ({
}: PostProps) => {
const { t } = useTranslation();
const resolvedPost = withResolvedCommentCommunityAddress(post);
const { author, cid, content, deleted, link, linkHeight, linkWidth, pinned, postCid, removed, spoiler, state, communityAddress, thumbnailUrl, parentCid } =
resolvedPost || {};
const { author, cid, content, deleted, link, linkHeight, linkWidth, postCid, removed, spoiler, state, communityAddress, thumbnailUrl, parentCid } = resolvedPost || {};
const purged = resolvedPost?.commentModeration?.purged;
const params = useParams();
const location = useLocation();
@@ -876,9 +881,7 @@ const PostDesktop = ({
repliesPerPage: BOARD_REPLIES_PREVIEW_FETCH_SIZE,
accountComments: { newerThan: Infinity, append: true },
});
const cachedPreviewReplies = (cachedPreviewRepliesResult as { updatedReplies?: Comment[] }).updatedReplies?.length
? (cachedPreviewRepliesResult as { updatedReplies?: Comment[] }).updatedReplies!
: cachedPreviewRepliesResult.replies || [];
const cachedPreviewReplies = cachedPreviewRepliesResult.updatedReplies?.length ? cachedPreviewRepliesResult.updatedReplies : cachedPreviewRepliesResult.replies || [];
const hasEnoughCachedPreview = hasEnoughPreviewReplies({
replyCount: resolvedPost?.replyCount,
loadedCount: cachedPreviewReplies.length,
@@ -899,14 +902,12 @@ const PostDesktop = ({
accountComments: { newerThan: Infinity, append: true },
});
const livePreviewReplies = (previewRepliesResult as { updatedReplies?: Comment[] }).updatedReplies?.length
? (previewRepliesResult as { updatedReplies?: Comment[] }).updatedReplies!
: previewRepliesResult.replies || [];
const livePreviewReplies = previewRepliesResult.updatedReplies?.length ? previewRepliesResult.updatedReplies : previewRepliesResult.replies || [];
const previewReplies = hasReplyPaginationOverride ? replyPaginationOverride.replies : hasEnoughCachedPreview ? cachedPreviewReplies : livePreviewReplies;
const fullReplies = hasReplyPaginationOverride
? replyPaginationOverride.replies
: (fullRepliesResult as { updatedReplies?: Comment[] }).updatedReplies?.length
? (fullRepliesResult as { updatedReplies?: Comment[] }).updatedReplies!
: fullRepliesResult.updatedReplies?.length
? fullRepliesResult.updatedReplies
: fullRepliesResult.replies || [];
const hasMore = replyPaginationOverride?.hasMore ?? fullRepliesResult.hasMore;
@@ -1191,7 +1192,7 @@ const PostDesktop = ({
directRepliesByParentCid={directRepliesByParentCid}
/>
{!isHidden && !content && !(deleted || removed || purged) && <div className={styles.spacer} />}
{!isHidden && <CommentContent comment={resolvedPost} prependContent={failedPublishNotice} />}
{resolvedPost && !isHidden && <CommentContent comment={resolvedPost} prependContent={failedPublishNotice} />}
</div>
{!isHidden && !isInPendingPostView && showReplies && repliesCount > 0 && !isInPostPageView && (
<span className={styles.summary}>
@@ -215,9 +215,9 @@ describe('PostMenuDesktop', () => {
const hrefs = Array.from(document.body.querySelectorAll('a')).map((link) => link.getAttribute('href'));
expect(hrefs).toEqual(
expect.arrayContaining([
'https://lens.google.com/uploadbyurl?url=https://cdn.example/image.png',
'https://www.yandex.com/images/search?url=https://cdn.example/image.png&rpt=imageview',
'https://saucenao.com/search.php?url=https://cdn.example/image.png',
'https://lens.google.com/uploadbyurl?url=https%3A%2F%2Fcdn.example%2Fimage.png',
'https://www.yandex.com/images/search?img_url=https%3A%2F%2Fcdn.example%2Fimage.png&rpt=imageview',
'https://saucenao.com/search.php?url=https%3A%2F%2Fcdn.example%2Fimage.png',
]),
);
});
@@ -9,7 +9,7 @@ import { copyShareLinkToClipboard, isValidURL, type ShareLinkType } from '../../
import { copyToClipboard } from '../../../lib/utils/clipboard-utils';
import { getBoardPath } from '../../../lib/utils/route-utils';
import { useDirectories } from '../../../hooks/use-directories';
import { isAllView, isCatalogView, isPostPageView, isSubscriptionsView } from '../../../lib/utils/view-utils';
import { isCatalogView, isPostPageView } from '../../../lib/utils/view-utils';
import useHide from '../../../hooks/use-hide';
import capitalize from 'lodash/capitalize';
import { PostMenuProps } from '../../../lib/utils/post-menu-props';
@@ -119,6 +119,7 @@ const CopyUserIdButton = ({ address, onClose }: { address: string; onClose: () =
const ImageSearchButton = ({ url, onClose }: { url: string; onClose: () => void }) => {
const { t } = useTranslation();
const [isImageSearchMenuOpen, setIsImageSearchMenuOpen] = useState(false);
const encodedUrl = encodeURIComponent(url);
const { refs, floatingStyles } = useFloating({
placement: 'right-start',
@@ -144,13 +145,13 @@ const ImageSearchButton = ({ url, onClose }: { url: string; onClose: () => void
{capitalize(t('image_search'))} »
{isImageSearchMenuOpen && (
<div ref={refs.setFloating} style={floatingStyles} className={styles.dropdownMenu}>
<a href={`https://lens.google.com/uploadbyurl?url=${url}`} target='_blank' rel='noreferrer'>
<a href={`https://lens.google.com/uploadbyurl?url=${encodedUrl}`} target='_blank' rel='noopener noreferrer'>
<div className={styles.postMenuItem}>Google</div>
</a>
<a href={`https://www.yandex.com/images/search?url=${url}&rpt=imageview`} target='_blank' rel='noreferrer'>
<a href={`https://www.yandex.com/images/search?img_url=${encodedUrl}&rpt=imageview`} target='_blank' rel='noopener noreferrer'>
<div className={styles.postMenuItem}>Yandex</div>
</a>
<a href={`https://saucenao.com/search.php?url=${url}`} target='_blank' rel='noreferrer'>
<a href={`https://saucenao.com/search.php?url=${encodedUrl}`} target='_blank' rel='noopener noreferrer'>
<div className={styles.postMenuItem}>SauceNAO</div>
</a>
</div>
@@ -174,10 +175,8 @@ const PostMenuDesktop = ({ postMenu }: PostMenuDesktopProps) => {
const location = useLocation();
const params = useParams();
const isInAllView = isAllView(location.pathname);
const isInCatalogView = isCatalogView(location.pathname, params);
const isInPostPageView = isPostPageView(location.pathname, params);
const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams());
const { refs, floatingStyles, context } = useFloating({
placement: 'bottom-start',
@@ -249,13 +248,21 @@ const PostMenuDesktop = ({ postMenu }: PostMenuDesktopProps) => {
role='button'
tabIndex={0}
onClick={() => {
hidden ? unhide() : hide();
if (hidden) {
unhide();
} else {
hide();
}
handleClose();
}}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
hidden ? unhide() : hide();
if (hidden) {
unhide();
} else {
hide();
}
handleClose();
}
}}