mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
Merge branch 'master' of github.com:bitsocialnet/5chan
# Conflicts: # public/translations/ar/default.json # public/translations/bn/default.json # public/translations/cs/default.json # public/translations/da/default.json # public/translations/de/default.json # public/translations/el/default.json # public/translations/en/default.json # public/translations/es/default.json # public/translations/fa/default.json # public/translations/fi/default.json # public/translations/fil/default.json # public/translations/fr/default.json # public/translations/he/default.json # public/translations/hi/default.json # public/translations/hu/default.json # public/translations/id/default.json # public/translations/it/default.json # public/translations/ja/default.json # public/translations/ko/default.json # public/translations/mr/default.json # public/translations/nl/default.json # public/translations/no/default.json # public/translations/pl/default.json # public/translations/pt/default.json # public/translations/ro/default.json # public/translations/ru/default.json # public/translations/sq/default.json # public/translations/sv/default.json # public/translations/te/default.json # public/translations/th/default.json # public/translations/tr/default.json # public/translations/uk/default.json # public/translations/ur/default.json # public/translations/vi/default.json # public/translations/zh/default.json
This commit is contained in:
@@ -18,7 +18,7 @@ const testState = vi.hoisted(() => ({
|
||||
features: {},
|
||||
title: '/mu/ - Music',
|
||||
},
|
||||
} as Record<string, { address: string; features?: Record<string, unknown>; title?: string }>,
|
||||
} as Record<string, { address: string; directoryCode?: string; features?: Record<string, unknown>; title?: string }>,
|
||||
handleUploadMock: vi.fn(),
|
||||
isMobile: false,
|
||||
isResolvingExternalQuotes: false,
|
||||
@@ -323,6 +323,12 @@ describe('ReplyModal', () => {
|
||||
features: {},
|
||||
title: '/mu/ - Music',
|
||||
},
|
||||
'politically-incorrect.bso': {
|
||||
address: 'politically-incorrect.bso',
|
||||
directoryCode: 'pol',
|
||||
features: { hasFlags: true },
|
||||
title: '/pol/ - Politically Incorrect',
|
||||
},
|
||||
'random-nsfw.bso': {
|
||||
address: 'random-nsfw.bso',
|
||||
features: {},
|
||||
@@ -425,6 +431,52 @@ describe('ReplyModal', () => {
|
||||
expect(testState.setPublishReplyOptionsMock).toHaveBeenCalledWith({ displayName: 'Alice' });
|
||||
});
|
||||
|
||||
it('shows a flag selector on flag boards and publishes the default geographic request', async () => {
|
||||
await renderReplyModal('/pol/thread/post-1', 'politically-incorrect.bso');
|
||||
|
||||
const flagSelect = container.querySelector<HTMLSelectElement>('select[aria-label="flag"]');
|
||||
|
||||
expect(flagSelect).toBeTruthy();
|
||||
expect(flagSelect?.value).toBe('country:auto');
|
||||
expect(
|
||||
Array.from(flagSelect?.options || [])
|
||||
.slice(0, 3)
|
||||
.map((option) => option.textContent),
|
||||
).toEqual(['Geographic Location', 'Anarcho-Capitalist', 'Anarchist']);
|
||||
|
||||
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 selected political flags from the reply modal', async () => {
|
||||
await renderReplyModal('/pol/thread/post-1', 'politically-incorrect.bso');
|
||||
|
||||
const flagSelect = container.querySelector<HTMLSelectElement>('select[aria-label="flag"]');
|
||||
await dispatchInput(container.querySelector<HTMLTextAreaElement>('textarea') as HTMLTextAreaElement, 'reply body');
|
||||
await act(async () => {
|
||||
if (flagSelect) {
|
||||
flagSelect.value = 'pol:AC';
|
||||
flagSelect.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
});
|
||||
await clickButtonByText('post');
|
||||
|
||||
expect(testState.publishReplyMock).toHaveBeenCalledWith({
|
||||
content: 'reply body',
|
||||
challengeRequest: {
|
||||
challengeAnswers: ['bitsocial-flags:5chan:flag:pol:AC'],
|
||||
},
|
||||
flairs: [{ type: 'pol', code: 'AC', text: 'flag:pol:AC' }],
|
||||
});
|
||||
});
|
||||
|
||||
it('uses the shared loading ellipsis while a reply upload is running', async () => {
|
||||
testState.isUploading = true;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
background-image: var(--close-button-background-image);
|
||||
}
|
||||
|
||||
.container input[type="text"], .container textarea {
|
||||
.container input[type="text"], .container textarea, .container select {
|
||||
border: var(--reply-modal-field-input-border, revert);
|
||||
font-family: var(--post-form-field-font-family, revert);
|
||||
appearance: var(--post-form-field-input-appearance, revert);
|
||||
@@ -53,7 +53,7 @@
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.container input[type="text"]:focus, .container textarea:focus {
|
||||
.container input[type="text"]:focus, .container textarea:focus, .container select:focus {
|
||||
border: var(--reply-modal-field-input-border-focus, revert);
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.container input[type="text"], .container textarea {
|
||||
.container input[type="text"], .container textarea, .container select {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import type { TFunction } from 'i18next';
|
||||
import { setAccount, useAccount } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { getExpiringMediaLinkAlert } from '../../lib/utils/media-link-validation-utils';
|
||||
import { getCommentFlagOptionsForDirectory, getCommentFlagPublishOptionsFromSelection } from '../../lib/comment-flag-selection';
|
||||
import {
|
||||
type DiceRoll,
|
||||
type FortuneEntry,
|
||||
@@ -64,6 +65,7 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
|
||||
const postOptionsDirectoryCode = getPostOptionsDirectoryCode(directoryEntry, location.pathname);
|
||||
const requirePostLinkIsMediaFeature = directoryEntry?.features?.requirePostLinkIsMedia;
|
||||
const requirePostLinkIsMedia = requirePostLinkIsMediaFeature === true || (requirePostLinkIsMediaFeature === undefined && (isInAllView || isInSubscriptionsView));
|
||||
const flagOptions = getCommentFlagOptionsForDirectory(directoryEntry);
|
||||
const { isResolvingExternalQuotes, publishReply, publishReplyError, publishReplyStateMessage, resetPublishReplyOptions, replyIndex, setPublishReplyOptions } =
|
||||
usePublishReply({
|
||||
cid: parentCid,
|
||||
@@ -89,6 +91,7 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
|
||||
});
|
||||
const urlRef = 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);
|
||||
@@ -166,9 +169,11 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
|
||||
return;
|
||||
}
|
||||
|
||||
const flagPublishOptions = getCommentFlagPublishOptionsFromSelection(flagRef.current?.value);
|
||||
|
||||
setError(null);
|
||||
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? `/${postOptionsDirectoryCode || params.boardIdentifier || communityAddress}` : null;
|
||||
publishReply({ content: publishContent });
|
||||
publishReply({ content: publishContent, ...flagPublishOptions });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -515,6 +520,17 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{flagOptions.length > 0 && (
|
||||
<div>
|
||||
<select key={flagOptions.map((option) => option.value).join('|')} aria-label={t('flag')} ref={flagRef} defaultValue={flagOptions[0]?.value}>
|
||||
{flagOptions.map((option) => (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.link}>
|
||||
<input
|
||||
type='text'
|
||||
|
||||
Reference in New Issue
Block a user