fix(post-form): convert twimg query-format links in the reply modal (#1168)

Share getPublishLinkOptions between the inline post form and the reply modal so the modal publishes twimg ?format= links in their .jpg/.png form (previously raw), and rewrite the link field on blur in both so the conversion is visible. Also gate the dev service worker's runtime asset cache to production so dev no longer serves stale /src modules.
This commit is contained in:
Tommaso Casaburi
2026-06-09 19:24:28 +07:00
committed by GitHub
parent ee5aa7845e
commit 2f938d59ae
6 changed files with 147 additions and 28 deletions
@@ -678,6 +678,41 @@ describe('ReplyModal', () => {
expect(testState.publishReplyMock).toHaveBeenCalledTimes(1);
});
it('publishes twimg query-format reply links with a path extension', async () => {
testState.openEmpty = true;
testState.selectedText = 'reply body';
await renderReplyModal('/mu/thread/post-1');
const linkInput = container.querySelectorAll<HTMLInputElement>('input[type="text"]')[2];
// The publish path normalizes the raw `?format=` link even without blurring the field.
await dispatchInput(linkInput, 'https://pbs.twimg.com/media/HKUAehoXUAAXkMb?format=jpg&name=4096x4096');
expect(linkInput.value).toBe('https://pbs.twimg.com/media/HKUAehoXUAAXkMb?format=jpg&name=4096x4096');
await clickButtonByText('post');
expect(testState.publishReplyMock).toHaveBeenCalledTimes(1);
expect(testState.publishReplyMock).toHaveBeenCalledWith(expect.objectContaining({ link: 'https://pbs.twimg.com/media/HKUAehoXUAAXkMb.jpg' }));
});
it('rewrites twimg query-format reply links to their path-extension form on blur', async () => {
testState.openEmpty = true;
testState.selectedText = 'reply body';
await renderReplyModal('/mu/thread/post-1');
const linkInput = container.querySelectorAll<HTMLInputElement>('input[type="text"]')[2];
await dispatchInput(linkInput, 'https://pbs.twimg.com/media/HKUAehoXUAAXkMb?format=jpg&name=4096x4096');
expect(linkInput.value).toBe('https://pbs.twimg.com/media/HKUAehoXUAAXkMb?format=jpg&name=4096x4096');
await act(async () => {
linkInput.dispatchEvent(new FocusEvent('focusout', { bubbles: true }));
});
expect(linkInput.value).toBe('https://pbs.twimg.com/media/HKUAehoXUAAXkMb.jpg');
});
it('moves YouTube links into reply content and publishes the thumbnail link on media-only boards', async () => {
const youtubeLink = 'https://youtu.be/reply123';
const thumbnailLink = 'https://img.youtube.com/vi/reply123/0.jpg';
+17 -2
View File
@@ -3,7 +3,8 @@ import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { setAccount, useAccount } from '@bitsocial/bitsocial-react-hooks';
import { getExpiringMediaLinkAlert, getPublishFileDisplayName } from '../../lib/utils/media-link-validation-utils';
import { getExpiringMediaLinkAlert, getPublishFileDisplayName, getPublishLinkOptions } from '../../lib/utils/media-link-validation-utils';
import { getTwimgMediaFilePublishUrl } from '../../lib/utils/media-utils';
import { getCommentFlagOptionsForDirectory, getCommentFlagPublishOptionsForDirectory } from '../../lib/comment-flag-selection';
import {
type DiceRoll,
@@ -185,7 +186,7 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
setError(null);
nonokoRedirectPathRef.current = hasNonokoOption(currentOptions) ? `/${postOptionsDirectoryCode || params.boardIdentifier || communityAddress}` : null;
publishReply({ content: publishContent, ...(appliedYouTubeConversion ? { link: currentUrl } : {}), ...flagPublishOptions });
publishReply({ content: publishContent, ...getPublishLinkOptions(currentUrl, appliedYouTubeConversion), ...flagPublishOptions });
};
useEffect(() => {
@@ -431,6 +432,19 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
}
};
// Mirror the inline post form: normalize twimg `?format=` links to their `.jpg`/`.png` form once
// the field loses focus, so the conversion that happens at publish time is visible in the input.
const handleLinkBlur = () => {
const currentValue = urlRef.current?.value ?? '';
const twimgPublishUrl = getTwimgMediaFilePublishUrl(currentValue);
if (twimgPublishUrl && twimgPublishUrl !== currentValue) {
if (urlRef.current) {
urlRef.current.value = twimgPublishUrl;
}
setLinkValue(twimgPublishUrl);
}
};
useEffect(() => {
const canInsertQuote = showReplyModal && quoteInsertRequestId !== 0 && !!textRef.current;
@@ -601,6 +615,7 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
onChange={(e) => {
handleLinkChange(e.target.value);
}}
onBlur={handleLinkBlur}
/>
</div>
{showOekakiControls && (