mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(flags): move reply flag below link and auto-geo on /bant/
Hide the flag selector on /bant/ while still publishing geographic location, and place the reply modal flag field after the link field.
This commit is contained in:
@@ -24,7 +24,7 @@ import { getPublishURLFilename, isValidPublishURL, isValidURL } from '../../lib/
|
|||||||
import { hasModQueueAccessRole } from '../../lib/utils/mod-access';
|
import { hasModQueueAccessRole } from '../../lib/utils/mod-access';
|
||||||
import { getBoardPath } from '../../lib/utils/route-utils';
|
import { getBoardPath } from '../../lib/utils/route-utils';
|
||||||
import { isAllView, isCatalogView, isModQueueView, isModView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
import { isAllView, isCatalogView, isModQueueView, isModView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
||||||
import { getCommentFlagOptionsForDirectory, getCommentFlagPublishOptionsFromSelection, type CommentFlagSelectOption } from '../../lib/comment-flag-selection';
|
import { getCommentFlagOptionsForDirectory, getCommentFlagPublishOptionsForDirectory, type CommentFlagSelectOption } from '../../lib/comment-flag-selection';
|
||||||
import { useAccountCommunityAddresses } from '../../hooks/use-account-community-addresses';
|
import { useAccountCommunityAddresses } from '../../hooks/use-account-community-addresses';
|
||||||
import { useDirectories, useDirectoryByAddress } from '../../hooks/use-directories';
|
import { useDirectories, useDirectoryByAddress } from '../../hooks/use-directories';
|
||||||
import { useCommunityField } from '../../hooks/use-stable-community';
|
import { useCommunityField } from '../../hooks/use-stable-community';
|
||||||
@@ -576,7 +576,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const flagPublishOptions = getCommentFlagPublishOptionsFromSelection(flagRef.current?.value);
|
const flagPublishOptions = getCommentFlagPublishOptionsForDirectory(directoryEntry, flagRef.current?.value);
|
||||||
|
|
||||||
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? getBoardIndexPath() : null;
|
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? getBoardIndexPath() : null;
|
||||||
publishPost({ content: publishContent, ...flagPublishOptions });
|
publishPost({ content: publishContent, ...flagPublishOptions });
|
||||||
@@ -688,7 +688,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const flagPublishOptions = getCommentFlagPublishOptionsFromSelection(flagRef.current?.value);
|
const flagPublishOptions = getCommentFlagPublishOptionsForDirectory(directoryEntry, flagRef.current?.value);
|
||||||
|
|
||||||
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? getBoardIndexPath() : null;
|
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? getBoardIndexPath() : null;
|
||||||
publishReply({ content: publishContent, ...flagPublishOptions });
|
publishReply({ content: publishContent, ...flagPublishOptions });
|
||||||
|
|||||||
@@ -329,6 +329,12 @@ describe('ReplyModal', () => {
|
|||||||
features: { hasFlags: true },
|
features: { hasFlags: true },
|
||||||
title: '/pol/ - Politically Incorrect',
|
title: '/pol/ - Politically Incorrect',
|
||||||
},
|
},
|
||||||
|
'international-nsfw.bso': {
|
||||||
|
address: 'international-nsfw.bso',
|
||||||
|
directoryCode: 'bant',
|
||||||
|
features: { hasFlags: true },
|
||||||
|
title: '/bant/ - International/Random',
|
||||||
|
},
|
||||||
'random-nsfw.bso': {
|
'random-nsfw.bso': {
|
||||||
address: 'random-nsfw.bso',
|
address: 'random-nsfw.bso',
|
||||||
features: {},
|
features: {},
|
||||||
@@ -443,6 +449,24 @@ describe('ReplyModal', () => {
|
|||||||
.slice(0, 3)
|
.slice(0, 3)
|
||||||
.map((option) => option.textContent),
|
.map((option) => option.textContent),
|
||||||
).toEqual(['Geographic Location', 'Anarcho-Capitalist', 'Anarchist']);
|
).toEqual(['Geographic Location', 'Anarcho-Capitalist', 'Anarchist']);
|
||||||
|
const linkInput = container.querySelectorAll<HTMLInputElement>('input[type="text"]')[2];
|
||||||
|
expect(Boolean(linkInput!.compareDocumentPosition(flagSelect!) & Node.DOCUMENT_POSITION_FOLLOWING)).toBe(true);
|
||||||
|
|
||||||
|
await clickButtonByText('post');
|
||||||
|
|
||||||
|
expect(testState.publishReplyMock).toHaveBeenCalledWith({
|
||||||
|
content: '>>42\nselected text',
|
||||||
|
challengeRequest: {
|
||||||
|
challengeAnswers: ['bitsocial-flags:5chan:flag:country:auto'],
|
||||||
|
},
|
||||||
|
flairs: [{ type: 'country', code: 'auto', text: 'flag:country:auto' }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('publishes geographic location on /bant/ without showing a flag selector', async () => {
|
||||||
|
await renderReplyModal('/bant/thread/post-1', 'international-nsfw.bso');
|
||||||
|
|
||||||
|
expect(container.querySelector<HTMLSelectElement>('select[aria-label="flag"]')).toBeNull();
|
||||||
|
|
||||||
await clickButtonByText('post');
|
await clickButtonByText('post');
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { setAccount, useAccount } from '@bitsocial/bitsocial-react-hooks';
|
import { setAccount, useAccount } from '@bitsocial/bitsocial-react-hooks';
|
||||||
import { getExpiringMediaLinkAlert } from '../../lib/utils/media-link-validation-utils';
|
import { getExpiringMediaLinkAlert } from '../../lib/utils/media-link-validation-utils';
|
||||||
import { getCommentFlagOptionsForDirectory, getCommentFlagPublishOptionsFromSelection } from '../../lib/comment-flag-selection';
|
import { getCommentFlagOptionsForDirectory, getCommentFlagPublishOptionsForDirectory } from '../../lib/comment-flag-selection';
|
||||||
import {
|
import {
|
||||||
type DiceRoll,
|
type DiceRoll,
|
||||||
type FortuneEntry,
|
type FortuneEntry,
|
||||||
@@ -169,7 +169,7 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const flagPublishOptions = getCommentFlagPublishOptionsFromSelection(flagRef.current?.value);
|
const flagPublishOptions = getCommentFlagPublishOptionsForDirectory(directoryEntry, flagRef.current?.value);
|
||||||
|
|
||||||
setError(null);
|
setError(null);
|
||||||
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? `/${postOptionsDirectoryCode || params.boardIdentifier || communityAddress}` : null;
|
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? `/${postOptionsDirectoryCode || params.boardIdentifier || communityAddress}` : null;
|
||||||
@@ -520,6 +520,19 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={styles.link}>
|
||||||
|
<input
|
||||||
|
type='text'
|
||||||
|
ref={urlRef}
|
||||||
|
aria-label={requirePostLinkIsMedia ? t('link_to_file') : t('link')}
|
||||||
|
placeholder={requirePostLinkIsMedia ? FILE_LINK_PLACEHOLDER : capitalize(t('link'))}
|
||||||
|
disabled={isUploading}
|
||||||
|
onChange={(e) => {
|
||||||
|
setUrl(e.target.value);
|
||||||
|
setPublishReplyOptions({ link: e.target.value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{flagOptions.length > 0 && (
|
{flagOptions.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<select
|
<select
|
||||||
@@ -538,19 +551,6 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={styles.link}>
|
|
||||||
<input
|
|
||||||
type='text'
|
|
||||||
ref={urlRef}
|
|
||||||
aria-label={requirePostLinkIsMedia ? t('link_to_file') : t('link')}
|
|
||||||
placeholder={requirePostLinkIsMedia ? FILE_LINK_PLACEHOLDER : capitalize(t('link'))}
|
|
||||||
disabled={isUploading}
|
|
||||||
onChange={(e) => {
|
|
||||||
setUrl(e.target.value);
|
|
||||||
setPublishReplyOptions({ link: e.target.value });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
{showUploadControls && (
|
{showUploadControls && (
|
||||||
<span className={styles.uploadContainer}>
|
<span className={styles.uploadContainer}>
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { getCommentFlagOptionsForDirectory, getCommentFlagPublishOptionsFromSelection, getCommentFlagRequestFromSelection } from '../comment-flag-selection';
|
import {
|
||||||
|
getCommentFlagOptionsForDirectory,
|
||||||
|
getCommentFlagPublishOptionsForDirectory,
|
||||||
|
getCommentFlagPublishOptionsFromSelection,
|
||||||
|
getCommentFlagRequestFromSelection,
|
||||||
|
} from '../comment-flag-selection';
|
||||||
|
|
||||||
describe('comment-flag-selection', () => {
|
describe('comment-flag-selection', () => {
|
||||||
it('does not expose options for boards without flags', () => {
|
it('does not expose options for boards without flags', () => {
|
||||||
@@ -16,6 +21,29 @@ describe('comment-flag-selection', () => {
|
|||||||
).toEqual([{ label: 'Geographic Location', value: 'country:auto' }]);
|
).toEqual([{ label: 'Geographic Location', value: 'country:auto' }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not expose a flag selector on /bant/ but still publishes geographic location', () => {
|
||||||
|
expect(
|
||||||
|
getCommentFlagOptionsForDirectory({
|
||||||
|
directoryCode: 'bant',
|
||||||
|
features: { hasFlags: true },
|
||||||
|
title: '/bant/ - International/Random',
|
||||||
|
}),
|
||||||
|
).toEqual([]);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
getCommentFlagPublishOptionsForDirectory({
|
||||||
|
directoryCode: 'bant',
|
||||||
|
features: { hasFlags: true },
|
||||||
|
title: '/bant/ - International/Random',
|
||||||
|
}),
|
||||||
|
).toEqual({
|
||||||
|
challengeRequest: {
|
||||||
|
challengeAnswers: ['bitsocial-flags:5chan:flag:country:auto'],
|
||||||
|
},
|
||||||
|
flairs: [{ type: 'country', code: 'auto', text: 'flag:country:auto' }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('matches the 4chan /pol/ flag order', () => {
|
it('matches the 4chan /pol/ flag order', () => {
|
||||||
const options = getCommentFlagOptionsForDirectory({
|
const options = getCommentFlagOptionsForDirectory({
|
||||||
directoryCode: 'pol',
|
directoryCode: 'pol',
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ const NO_FLAG_OPTION: CommentFlagSelectOption = {
|
|||||||
label: 'None',
|
label: 'None',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Boards that always publish geographic location without showing a flag selector. */
|
||||||
|
const AUTO_GEOGRAPHIC_FLAG_DIRECTORY_CODES = new Set(['bant']);
|
||||||
|
|
||||||
const getDirectoryCode = (directory: Pick<DirectoryCommunity, 'directoryCode' | 'title'> | undefined): string | undefined => {
|
const getDirectoryCode = (directory: Pick<DirectoryCommunity, 'directoryCode' | 'title'> | undefined): string | undefined => {
|
||||||
const directoryCode = directory?.directoryCode?.trim().toLowerCase();
|
const directoryCode = directory?.directoryCode?.trim().toLowerCase();
|
||||||
return directoryCode || directory?.title?.match(/^\/([^/]+)\//)?.[1]?.toLowerCase();
|
return directoryCode || directory?.title?.match(/^\/([^/]+)\//)?.[1]?.toLowerCase();
|
||||||
@@ -52,6 +55,10 @@ export const getCommentFlagOptionsForDirectory = (directory: Pick<DirectoryCommu
|
|||||||
}
|
}
|
||||||
|
|
||||||
const directoryCode = getDirectoryCode(directory);
|
const directoryCode = getDirectoryCode(directory);
|
||||||
|
if (directoryCode && AUTO_GEOGRAPHIC_FLAG_DIRECTORY_CODES.has(directoryCode)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
if (directoryCode === 'mlp') {
|
if (directoryCode === 'mlp') {
|
||||||
return [NO_FLAG_OPTION, ...getBoardFlagOptions('pony')];
|
return [NO_FLAG_OPTION, ...getBoardFlagOptions('pony')];
|
||||||
}
|
}
|
||||||
@@ -63,6 +70,33 @@ export const getCommentFlagOptionsForDirectory = (directory: Pick<DirectoryCommu
|
|||||||
return [GEOGRAPHIC_LOCATION_OPTION];
|
return [GEOGRAPHIC_LOCATION_OPTION];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCommentFlagPublishOptionsForDirectory = (
|
||||||
|
directory: Pick<DirectoryCommunity, 'directoryCode' | 'features' | 'title'> | undefined,
|
||||||
|
selectedValue?: string,
|
||||||
|
): CommentFlagPublishOptions => {
|
||||||
|
if (directory?.features?.hasFlags !== true) {
|
||||||
|
return {
|
||||||
|
challengeRequest: undefined,
|
||||||
|
flairs: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const directoryCode = getDirectoryCode(directory);
|
||||||
|
if (directoryCode && AUTO_GEOGRAPHIC_FLAG_DIRECTORY_CODES.has(directoryCode)) {
|
||||||
|
return getCommentFlagPublishOptionsFromSelection(GEOGRAPHIC_LOCATION_FLAG_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const flagOptions = getCommentFlagOptionsForDirectory(directory);
|
||||||
|
if (flagOptions.length === 0) {
|
||||||
|
return {
|
||||||
|
challengeRequest: undefined,
|
||||||
|
flairs: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return getCommentFlagPublishOptionsFromSelection(selectedValue ?? flagOptions[0]?.value);
|
||||||
|
};
|
||||||
|
|
||||||
export const getCommentFlagRequestFromSelection = (value: string | undefined): CommentFlagRequest | undefined => {
|
export const getCommentFlagRequestFromSelection = (value: string | undefined): CommentFlagRequest | undefined => {
|
||||||
if (!value || value === NO_FLAG_VALUE) {
|
if (!value || value === NO_FLAG_VALUE) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
Reference in New Issue
Block a user