feat(flags): add comment flags (#1140)

* feat(flags): add comment flags

* fix(flags): address review feedback

* fix(flags): clear stale flag publish data
This commit is contained in:
Tommaso Casaburi
2026-05-24 23:14:36 +07:00
committed by GitHub
parent 804c14fc35
commit f74b33f43b
66 changed files with 1293 additions and 74 deletions
+38 -2
View File
@@ -23,6 +23,7 @@ import { getPublishURLFilename, isValidPublishURL, isValidURL } from '../../lib/
import { hasModQueueAccessRole } from '../../lib/utils/mod-access';
import { getBoardPath } from '../../lib/utils/route-utils';
import { isAllView, isCatalogView, isModQueueView, isModView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
import { getCommentFlagOptionsForDirectory, getCommentFlagPublishOptionsFromSelection, type CommentFlagSelectOption } from '../../lib/comment-flag-selection';
import { useAccountCommunityAddresses } from '../../hooks/use-account-community-addresses';
import { useDirectories, useDirectoryByAddress } from '../../hooks/use-directories';
import { useCommunityField } from '../../hooks/use-stable-community';
@@ -124,6 +125,7 @@ interface PostFormFieldsProps {
postCid: string;
subjectRef: React.Ref<HTMLInputElement>;
optionsRef: React.RefObject<HTMLInputElement>;
flagRef: React.RefObject<HTMLSelectElement>;
textRef: React.RefObject<HTMLTextAreaElement>;
urlRef: React.Ref<HTMLInputElement>;
url: string;
@@ -148,6 +150,7 @@ interface PostFormFieldsProps {
communityAddress: string | undefined;
rulesPath: string;
requirePostLinkIsMedia: boolean;
flagOptions: CommentFlagSelectOption[];
showBbcodeToolbar: boolean;
onBbcodePreviewToggle: () => void;
onPublishReply: () => void;
@@ -166,6 +169,7 @@ const PostFormFields = ({
postCid,
subjectRef,
optionsRef,
flagRef,
textRef,
urlRef,
url,
@@ -190,6 +194,7 @@ const PostFormFields = ({
communityAddress,
rulesPath,
requirePostLinkIsMedia,
flagOptions,
showBbcodeToolbar,
onBbcodePreviewToggle,
onPublishReply,
@@ -292,6 +297,26 @@ const PostFormFields = ({
{lengthError && <div className={styles.error}>{lengthError}</div>}
</td>
</tr>
{flagOptions.length > 0 && (
<tr>
<td>{t('flag')}</td>
<td>
<select
key={flagOptions.map((option) => option.value).join('|')}
aria-label={t('flag')}
className={styles.flagSelect}
ref={flagRef}
defaultValue={flagOptions[0]?.value}
>
{flagOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</td>
</tr>
)}
<tr>
<td>{requirePostLinkIsMedia ? t('link_to_file') : t('link')}</td>
<td className={styles.linkField}>
@@ -420,6 +445,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
const urlRef = useRef<HTMLInputElement>(null);
const subjectRef = useRef<HTMLInputElement>(null);
const optionsRef = useRef<HTMLInputElement>(null);
const flagRef = useRef<HTMLSelectElement>(null);
const fortuneEntryRef = useRef<FortuneEntry | null>(null);
const diceRollRef = useRef<DiceRoll | null>(null);
const nonokoRedirectPathRef = useRef<string | null>(null);
@@ -438,6 +464,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
const postOptionsDirectoryCode = getPostOptionsDirectoryCode(directoryEntry, location.pathname);
const requirePostLinkIsMediaFeature = directoryEntry?.features?.requirePostLinkIsMedia;
const requirePostLinkIsMedia = requirePostLinkIsMediaFeature === true || (requirePostLinkIsMediaFeature === undefined && (isInAllView || isInSubscriptionsView));
const flagOptions = getCommentFlagOptionsForDirectory(directoryEntry);
const accountCommunityAddresses = useAccountCommunityAddresses();
const accountAddress = account?.author?.address;
@@ -483,6 +510,9 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
if (optionsRef.current) {
optionsRef.current.value = '';
}
if (flagRef.current) {
flagRef.current.value = flagRef.current.options[0]?.value ?? '';
}
checkContentLength.cancel();
checkPostOptions.cancel();
fortuneEntryRef.current = null;
@@ -542,8 +572,10 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
return;
}
const flagPublishOptions = getCommentFlagPublishOptionsFromSelection(flagRef.current?.value);
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? getBoardIndexPath() : null;
publishPost({ content: publishContent });
publishPost({ content: publishContent, ...flagPublishOptions });
};
// redirect to pending page when pending comment is created
@@ -652,8 +684,10 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
return;
}
const flagPublishOptions = getCommentFlagPublishOptionsFromSelection(flagRef.current?.value);
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? getBoardIndexPath() : null;
publishReply({ content: publishContent });
publishReply({ content: publishContent, ...flagPublishOptions });
};
useEffect(() => {
@@ -712,6 +746,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
postCid={postCid}
subjectRef={subjectRef}
optionsRef={optionsRef}
flagRef={flagRef}
textRef={textRef}
urlRef={urlRef}
url={url}
@@ -736,6 +771,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
communityAddress={communityAddress}
rulesPath={rulesPath}
requirePostLinkIsMedia={requirePostLinkIsMedia}
flagOptions={flagOptions}
showBbcodeToolbar={showBbcodeToolbar}
onBbcodePreviewToggle={handleBbcodePreviewToggle}
onPublishReply={onPublishReply}