chore(architecture): finish refactor audit

Merge the architecture audit refactors and follow-up UX fixes: remove release notes from generated LLM context, keep author edit controls delete-only, stabilize board refresh rendering, and address review feedback for role loading, refresh holds, moderation actions, and P2P stats polling.
This commit is contained in:
Tommaso Casaburi
2026-06-23 18:48:47 +07:00
committed by GitHub
parent da92b2fb0a
commit 371de88e22
54 changed files with 2690 additions and 3661 deletions
@@ -0,0 +1,143 @@
import { useCallback, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Comment, usePublishCommentModeration } from '@bitsocial/bitsocial-react-hooks';
import { approvePendingCommentModeration, rejectPendingCommentModeration } from '../lib/utils/pending-approval-moderation';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
import { formatErrorForDisplay } from '../lib/utils/error-utils';
import useChallengesStore from '../stores/use-challenges-store';
export type PendingModerationStatus = 'approved' | 'rejected' | 'failed' | null;
export interface UsePendingCommentModerationActionsOptions {
// The comment the moderation challenge is published against. Forwarded to the
// challenge store so the challenge UI can reference the target comment.
comment: Comment | undefined;
commentCid: string | undefined;
communityAddress: string | undefined;
// When false, the underlying publishers are disabled by withholding the
// community address (mirrors the mobile post page gating its actions).
enabled?: boolean;
// Run after a successful approve/reject publish, inside the same try block as
// the publish call so a throw here is logged exactly like the publish path.
onApproveSuccess?: () => void | Promise<void>;
onRejectSuccess?: () => void | Promise<void>;
}
export interface PendingCommentModerationActions {
handleApprove: () => Promise<void>;
handleReject: () => Promise<void>;
isPublishing: boolean;
// Action-derived status only ('approved'/'rejected' on success, 'failed' on
// error). Callers that also have a baseline (e.g. an already-moderated mod
// queue comment) combine that baseline with this value themselves.
status: PendingModerationStatus;
error: unknown;
errorMessage: string | undefined;
}
// Shared approve/reject state machine for pending-approval comment moderation.
// Extracted from the duplicated copies in desktop posts, mobile posts, and the
// mod queue so the riskiest moderation flow lives behind one tested boundary.
export const usePendingCommentModerationActions = ({
comment,
commentCid,
communityAddress,
enabled = true,
onApproveSuccess,
onRejectSuccess,
}: UsePendingCommentModerationActionsOptions): PendingCommentModerationActions => {
const { t } = useTranslation();
const effectiveCommunityAddress = enabled ? communityAddress : undefined;
const {
publishCommentModeration: approve,
state: approveState,
error: approveError,
} = usePublishCommentModeration({
commentCid,
communityAddress: effectiveCommunityAddress,
commentModeration: approvePendingCommentModeration,
onChallenge: async (...args: any) => {
useChallengesStore.getState().addChallenge([...args, comment]);
},
onChallengeVerification: async (challengeVerification, challengedComment) => {
alertChallengeVerificationFailed(challengeVerification, challengedComment);
},
onError: (error: Error & { details?: unknown }) => {
console.error('Approve failed:', error, error.details);
},
});
const {
publishCommentModeration: reject,
state: rejectState,
error: rejectError,
} = usePublishCommentModeration({
commentCid,
communityAddress: effectiveCommunityAddress,
commentModeration: rejectPendingCommentModeration,
onChallenge: async (...args: any) => {
useChallengesStore.getState().addChallenge([...args, comment]);
},
onChallengeVerification: async (challengeVerification, challengedComment) => {
alertChallengeVerificationFailed(challengeVerification, challengedComment);
},
onError: (error: Error & { details?: unknown }) => {
console.error('Reject failed:', error, error.details);
},
});
const [initiatedAction, setInitiatedAction] = useState<'approve' | 'reject' | null>(null);
const pendingActionRef = useRef<'approve' | 'reject' | null>(null);
const handleApprove = useCallback(async () => {
if (pendingActionRef.current) return;
if (!window.confirm(t('double_confirm'))) {
return;
}
pendingActionRef.current = 'approve';
setInitiatedAction('approve');
try {
await approve();
await onApproveSuccess?.();
} catch (e) {
console.error(e);
} finally {
pendingActionRef.current = null;
}
}, [approve, onApproveSuccess, t]);
const handleReject = useCallback(async () => {
if (pendingActionRef.current) return;
if (!window.confirm(t('double_confirm'))) {
return;
}
pendingActionRef.current = 'reject';
setInitiatedAction('reject');
try {
await reject();
await onRejectSuccess?.();
} catch (e) {
console.error(e);
} finally {
pendingActionRef.current = null;
}
}, [reject, onRejectSuccess, t]);
const isApproving = initiatedAction === 'approve' && approveState !== 'succeeded' && approveState !== 'failed';
const isRejecting = initiatedAction === 'reject' && rejectState !== 'succeeded' && rejectState !== 'failed';
const isPublishing = isApproving || isRejecting;
const approveSucceeded = initiatedAction === 'approve' && approveState === 'succeeded';
const rejectSucceeded = initiatedAction === 'reject' && rejectState === 'succeeded';
const approveFailed = initiatedAction === 'approve' && approveState === 'failed';
const rejectFailed = initiatedAction === 'reject' && rejectState === 'failed';
const status: PendingModerationStatus = approveSucceeded ? 'approved' : rejectSucceeded ? 'rejected' : approveFailed || rejectFailed ? 'failed' : null;
const error = approveFailed ? approveError : rejectFailed ? rejectError : undefined;
const errorMessage = formatErrorForDisplay(error);
return { handleApprove, handleReject, isPublishing, status, error, errorMessage };
};
export default usePendingCommentModerationActions;