feat(archive): implement comment.archived and add archive page (#1074)

* feat(archive): implement comment.archived and add archive page

Add isCommentArchived() utility, /board/:boardIdentifier/archive route,
archive view with filtered feed, and UI integration (board buttons, edit
menu, catalog row, post). Archived indicator on catalog and posts.

* fix(archive): address review feedback from Bugbot and CodeRabbit

Add missing i18n keys (archived, thread_archived, view, loading_archive),
add /archive/settings route, replace hardcoded English in archive.tsx, and
fix mobile test state.
This commit is contained in:
Tommaso Casaburi
2026-03-13 16:06:36 +08:00
committed by GitHub
parent d7703953fb
commit aedee9fb83
65 changed files with 1384 additions and 62 deletions
+6 -3
View File
@@ -16,6 +16,7 @@ import usePublishPost from '../../hooks/use-publish-post';
import usePublishReply from '../../hooks/use-publish-reply';
import { useFileUpload } from '../../hooks/use-file-upload';
import { getShowUploadControls, isWebRuntime } from '../../lib/media-hosting/show-upload-controls';
import { isCommentArchived } from '../../lib/utils/comment-moderation-utils';
import useMediaHostingStore from '../../stores/use-media-hosting-store';
import BoardOfflineAlert from '../board-offline-alert/board-offline-alert';
import styles from './post-form.module.css';
@@ -525,7 +526,9 @@ const PostForm = () => {
}
const { deleted, locked, removed, postCid } = comment || {};
const isThreadClosed = deleted || locked || removed;
const archived = isCommentArchived(comment);
const isThreadClosed = deleted || locked || removed || archived;
const threadStateKey = archived ? 'thread_archived' : 'thread_closed';
const [showForm, setShowForm] = useState(false);
@@ -543,7 +546,7 @@ const PostForm = () => {
<div className={styles.modQueueTitle}>{t('moderation_queue')}</div>
) : isThreadClosed ? (
<div className={styles.closed}>
{t('thread_closed')}
{t(threadStateKey)}
<br />
{t('may_not_reply')}
</div>
@@ -567,7 +570,7 @@ const PostForm = () => {
<div className={styles.modQueueTitle}>{t('moderation_queue')}</div>
) : isThreadClosed ? (
<div className={styles.closed}>
{t('thread_closed')}
{t(threadStateKey)}
<br />
{t('may_not_reply')}
</div>