Major update for v1 and tests
This commit is contained in:
52
src/utils/imageLoading.js
Normal file
52
src/utils/imageLoading.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Image-loading helpers used by photo upload and slot assignment.
|
||||
*
|
||||
* Before this module: `useTemplate.assignImageToSlot` and `UploadTab.getImageSize`
|
||||
* each had their own inline `new Image() + onload + onerror` Promise wrapper,
|
||||
* and `App.handlePhotoEditComplete` had a third variant using callbacks
|
||||
* instead of a Promise. The three wrappers had subtly different error
|
||||
* handling — one rejected with a generic message, another logged to the
|
||||
* console, the third silently swallowed errors and used a fallback path.
|
||||
*
|
||||
* Centralizing here gives every caller the same behavior: a clean Promise
|
||||
* that resolves to dimensions or rejects with a descriptive Error. The
|
||||
* App.jsx photo-edit flow still uses the lower-level callback form because
|
||||
* its onload handler runs synchronously before its setEditingElement call
|
||||
* (timing matters for the Filerobot modal teardown sequence) — but the
|
||||
* other two consumers go through `loadImageDimensions`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Load an image and resolve to its natural pixel dimensions.
|
||||
*
|
||||
* Resolves with `{ width, height }` from `naturalWidth`/`naturalHeight`,
|
||||
* falling back to `width`/`height` for the rare case where naturalWidth is 0
|
||||
* (some Safari versions report this for SVG sources without intrinsic size).
|
||||
*
|
||||
* Rejects with a descriptive Error if the image fails to load. Callers
|
||||
* should `await` and use try/catch — not `.then(undefined, () => fallback)`,
|
||||
* which would silently mask bugs.
|
||||
*
|
||||
* @param {string} src - data:, blob:, or remote URL
|
||||
* @returns {Promise<{ width: number, height: number }>}
|
||||
*/
|
||||
export function loadImageDimensions(src) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new window.Image();
|
||||
img.onload = () => resolve({
|
||||
width: img.naturalWidth || img.width,
|
||||
height: img.naturalHeight || img.height,
|
||||
});
|
||||
img.onerror = () => reject(new Error(`Failed to load image: ${truncate(src, 80)}`));
|
||||
img.src = src;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate a URL for use in error messages. Long data: URLs in stack traces
|
||||
* blow up log readers; the first 80 chars are enough to identify the type.
|
||||
*/
|
||||
function truncate(s, n) {
|
||||
if (typeof s !== 'string') return String(s);
|
||||
return s.length > n ? `${s.slice(0, n)}…` : s;
|
||||
}
|
||||
Reference in New Issue
Block a user