From cfa8ab2e40b7fc67781aeded5fcc3ef7ae6720cb Mon Sep 17 00:00:00 2001 From: Josh Knapp Date: Sun, 1 Nov 2026 10:52:56 -0800 Subject: [PATCH] Sitesmith modal: load assets once; clearer oversize-image message Co-Authored-By: Claude Sonnet 5.5 --- craft/src/panels/sitesmith/SitesmithModal.tsx | 3 +++ craft/src/utils/sitesmith-attachments.ts | 2 +- craft/src/utils/sitesmith-design.test.ts | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/craft/src/panels/sitesmith/SitesmithModal.tsx b/craft/src/panels/sitesmith/SitesmithModal.tsx index 550135b..e021220 100644 --- a/craft/src/panels/sitesmith/SitesmithModal.tsx +++ b/craft/src/panels/sitesmith/SitesmithModal.tsx @@ -142,7 +142,10 @@ export const SitesmithModal: React.FC = ({ onClose, target }) => { const useAssetsFlag = !(assetsLoaded && assets.length > 0 && includedAssets.size === 0); const assetFilter = assetsLoaded && excluded.size > 0 && includedAssets.size > 0 ? [...includedAssets] : undefined; + const assetsRequested = useRef(false); const loadAssets = async () => { + if (assetsRequested.current) return; + assetsRequested.current = true; const r = await ss.listAssets(); if (r.ok) { setAssets(r.assets ?? []); setAssetsError(null); } else setAssetsError(r.message); setAssetsLoaded(true); diff --git a/craft/src/utils/sitesmith-attachments.ts b/craft/src/utils/sitesmith-attachments.ts index 460d419..e2e361b 100644 --- a/craft/src/utils/sitesmith-attachments.ts +++ b/craft/src/utils/sitesmith-attachments.ts @@ -26,7 +26,7 @@ export function formatBytes(n: number): string { export async function validateAttachment(file: File, maxBytes = DEFAULT_MAX_UPLOAD_BYTES): Promise { const label = file.name ? `"${file.name.slice(0, 60)}"` : 'That file'; if (file.size === 0) return `${label} is empty.`; - if (file.size > maxBytes) return `${label} is ${formatBytes(file.size)}; the limit is ${formatBytes(maxBytes)}. Use a smaller image.`; + if (file.size > maxBytes) return `${label} is ${formatBytes(file.size)}, which is over the ${formatBytes(maxBytes)} limit. Use a smaller image.`; const t = await sniffImageType(file); if (!t) return `${label} is not a JPEG, PNG, WebP or GIF image (SVG, PDF and other formats are not accepted).`; return null; diff --git a/craft/src/utils/sitesmith-design.test.ts b/craft/src/utils/sitesmith-design.test.ts index db8481e..320cdd2 100644 --- a/craft/src/utils/sitesmith-design.test.ts +++ b/craft/src/utils/sitesmith-design.test.ts @@ -46,7 +46,7 @@ describe('attachments validation', () => { test('rejects wrong type, empty, and oversize with plain messages', async () => { expect(await validateAttachment(file([60, 115, 118, 103, 62, 0, 0, 0], 'logo.png'))).toMatch(/not a JPEG, PNG, WebP or GIF/); expect(await validateAttachment(file([], 'e.png'))).toMatch(/empty/); - expect(await validateAttachment(file(PNG, 'big.png', 9 * 1024 * 1024))).toMatch(/9\.0 MB; the limit is 8\.0 MB/); + expect(await validateAttachment(file(PNG, 'big.png', 9 * 1024 * 1024))).toMatch(/9\.0 MB, which is over the 8\.0 MB limit/); expect(await validateAttachment(file(PNG, 'ok.png'))).toBeNull(); expect(formatBytes(2048)).toBe('2 KB'); });