mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
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:
@@ -771,6 +771,39 @@ describe('PostForm', () => {
|
||||
expect(testState.publishedPostOptions?.link).toBe(publishLink);
|
||||
});
|
||||
|
||||
it('rewrites known twimg query-format links to their path-extension form when the link field loses focus', async () => {
|
||||
await renderPostForm('/all');
|
||||
await clickByText(container, 'start_new_thread');
|
||||
|
||||
const table = container.querySelector('table') as HTMLTableElement;
|
||||
const select = table.querySelector('select') as HTMLSelectElement;
|
||||
const linkInput = table.querySelectorAll<HTMLInputElement>('input[type="text"]')[3];
|
||||
|
||||
await dispatchChange(select, 'music-posting.eth');
|
||||
|
||||
const blurLinkInput = async () => {
|
||||
await act(async () => {
|
||||
linkInput.dispatchEvent(new FocusEvent('focusout', { bubbles: true }));
|
||||
});
|
||||
};
|
||||
|
||||
// A twimg `?format=jpg` link becomes its `.jpg` form once the field loses focus.
|
||||
await dispatchInput(linkInput, 'https://pbs.twimg.com/media/HJxnhNKWMAAhqFU?format=jpg&name=medium');
|
||||
expect(linkInput.value).toBe('https://pbs.twimg.com/media/HJxnhNKWMAAhqFU?format=jpg&name=medium');
|
||||
await blurLinkInput();
|
||||
expect(linkInput.value).toBe('https://pbs.twimg.com/media/HJxnhNKWMAAhqFU.jpg');
|
||||
|
||||
// The detected format is preserved (png stays png).
|
||||
await dispatchInput(linkInput, 'https://pbs.twimg.com/media/ZZZ9?format=png&name=orig');
|
||||
await blurLinkInput();
|
||||
expect(linkInput.value).toBe('https://pbs.twimg.com/media/ZZZ9.png');
|
||||
|
||||
// Non-twimg links are left untouched.
|
||||
await dispatchInput(linkInput, 'https://example.com/photo?format=jpg&name=large');
|
||||
await blurLinkInput();
|
||||
expect(linkInput.value).toBe('https://example.com/photo?format=jpg&name=large');
|
||||
});
|
||||
|
||||
it('shows Oekaki draw controls only on the /i/ board form', async () => {
|
||||
testState.directories.push({
|
||||
address: 'oekaki-posting.bso',
|
||||
|
||||
@@ -6,7 +6,13 @@ import { Comment, setAccount, useAccount, useEditedComment } from '@bitsocial/bi
|
||||
import getShortAddress from '../../lib/get-short-address';
|
||||
import useCommunitiesPagesStore from '@bitsocial/bitsocial-react-hooks/dist/stores/communities-pages';
|
||||
import { getDisplayMediaInfoType, getLinkMediaInfo, getTwimgMediaFilePublishUrl } from '../../lib/utils/media-utils';
|
||||
import { getExpiringMediaLinkAlert, getPublishFileDisplayName, isPublishFileMediaLink, isPublishFileMediaType } from '../../lib/utils/media-link-validation-utils';
|
||||
import {
|
||||
getExpiringMediaLinkAlert,
|
||||
getPublishFileDisplayName,
|
||||
getPublishLinkOptions,
|
||||
isPublishFileMediaLink,
|
||||
isPublishFileMediaType,
|
||||
} from '../../lib/utils/media-link-validation-utils';
|
||||
import {
|
||||
type DiceRoll,
|
||||
type FortuneEntry,
|
||||
@@ -67,15 +73,6 @@ const getPostFormFileDisplayLabel = (url: string, uploadedFileName: string | nul
|
||||
return truncateWithEllipsisInMiddle(raw, POST_FORM_FILE_DISPLAY_MAX_LENGTH);
|
||||
};
|
||||
|
||||
const getPublishLinkOptions = (link: string, includeCurrentLink: boolean): Partial<Pick<Comment, 'link'>> => {
|
||||
const twimgPublishUrl = getTwimgMediaFilePublishUrl(link);
|
||||
if (twimgPublishUrl) {
|
||||
return { link: twimgPublishUrl };
|
||||
}
|
||||
|
||||
return includeCurrentLink && link ? { link } : {};
|
||||
};
|
||||
|
||||
export const LinkTypePreviewer = ({ link, requireFile = false }: { link: string; requireFile?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const mediaInfo = getLinkMediaInfo(link);
|
||||
@@ -161,6 +158,7 @@ interface PostFormFieldsProps {
|
||||
handleContentChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
||||
handleContentValueChange: (content: string, options?: string) => void;
|
||||
handleLinkChange: (link: string) => void;
|
||||
handleLinkBlur: () => void;
|
||||
handleOptionsChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
disableLinkInput: boolean;
|
||||
setPublishPostOptions: (opts: Record<string, unknown>) => void;
|
||||
@@ -213,6 +211,7 @@ const PostFormFields = ({
|
||||
handleContentChange,
|
||||
handleContentValueChange,
|
||||
handleLinkChange,
|
||||
handleLinkBlur,
|
||||
handleOptionsChange,
|
||||
disableLinkInput,
|
||||
setPublishPostOptions,
|
||||
@@ -376,6 +375,7 @@ const PostFormFields = ({
|
||||
onChange={(e) => {
|
||||
handleLinkChange(e.target.value);
|
||||
}}
|
||||
onBlur={handleLinkBlur}
|
||||
/>
|
||||
<span className={styles.linkType}> {url && <LinkTypePreviewer link={url} requireFile={requirePostLinkIsMedia} />}</span>
|
||||
</td>
|
||||
@@ -826,6 +826,20 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
|
||||
}
|
||||
};
|
||||
|
||||
// Normalize pbs.twimg.com `?format=` media links to their `.jpg`/`.png` form once the field
|
||||
// loses focus, so the conversion that happens at publish time is visible in the input. Done on
|
||||
// blur (not per keystroke) to avoid rewriting the URL while it is still being typed or pasted.
|
||||
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(() => {
|
||||
if (typeof replyIndex === 'number') {
|
||||
const nonokoRedirectPath = nonokoRedirectPathRef.current;
|
||||
@@ -895,6 +909,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
|
||||
handleContentChange={handleContentChange}
|
||||
handleContentValueChange={handleContentValueChange}
|
||||
handleLinkChange={handleLinkChange}
|
||||
handleLinkBlur={handleLinkBlur}
|
||||
handleOptionsChange={handleOptionsChange}
|
||||
disableLinkInput={isUploading || youtubeThumbnailConversionCountdown !== null}
|
||||
setPublishPostOptions={setPublishPostOptions}
|
||||
|
||||
Reference in New Issue
Block a user