diff --git a/src/app/WardrobePage/OutfitControls.js b/src/app/WardrobePage/OutfitControls.js index 4326334..2d81b2c 100644 --- a/src/app/WardrobePage/OutfitControls.js +++ b/src/app/WardrobePage/OutfitControls.js @@ -607,7 +607,13 @@ function useDownloadableImage(visibleLayers) { // performance (can use cached SVG), and predictability (image will // look like what you see here). const imagePromises = visibleLayers.map((layer) => - loadImage(getBestImageUrlForLayer(layer, { hiResMode })) + loadImage({ + src: getBestImageUrlForLayer(layer, { + hiResMode, + crossOrigin: "anonymous", + }), + crossOrigin: "anonymous", + }) ); let images; diff --git a/src/app/components/OutfitMovieLayer.js b/src/app/components/OutfitMovieLayer.js index 61a2991..5ab45e8 100644 --- a/src/app/components/OutfitMovieLayer.js +++ b/src/app/components/OutfitMovieLayer.js @@ -290,7 +290,9 @@ export async function loadMovieLibrary(librarySrc) { library.properties.manifest.map(({ id, src }) => [ id, loadImage({ - src: safeImageUrl(librarySrcDir + "/" + src), + src: safeImageUrl(librarySrcDir + "/" + src, { + crossOrigin: "anonymous", + }), crossOrigin: "anonymous", }), ]) diff --git a/src/app/components/OutfitPreview.js b/src/app/components/OutfitPreview.js index 08af37d..ab12df8 100644 --- a/src/app/components/OutfitPreview.js +++ b/src/app/components/OutfitPreview.js @@ -262,16 +262,7 @@ export function OutfitLayers({ ) : ( tags are always allowed through CORS), but - // this means we make the same request that the Download - // button makes, so it can use the cached version of this - // image instead of requesting it again with crossOrigin! - crossOrigin={ - getBestImageUrlForLayer(layer, { hiResMode }) - .crossOrigin - } + src={getBestImageUrlForLayer(layer, { hiResMode })} alt="" objectFit="contain" maxWidth="100%" @@ -341,11 +332,14 @@ export function FullScreenCenter({ children, ...otherProps }) { ); } -export function getBestImageUrlForLayer(layer, { hiResMode = false } = {}) { +export function getBestImageUrlForLayer( + layer, + { hiResMode = false, crossOrigin = null } = {} +) { if (hiResMode && layer.svgUrl) { - return { src: safeImageUrl(layer.svgUrl), crossOrigin: "anonymous" }; + return safeImageUrl(layer.svgUrl, { crossOrigin }); } else { - return { src: safeImageUrl(layer.imageUrl), crossOrigin: "anonymous" }; + return safeImageUrl(layer.imageUrl, { crossOrigin }); } } @@ -392,12 +386,12 @@ export function usePreloadLayers(layers) { }) ); } else { - return loadImage(getBestImageUrlForLayer(layer, { hiResMode })).then( - (image) => ({ - type: "image", - image, - }) - ); + return loadImage({ + src: getBestImageUrlForLayer(layer, { hiResMode }), + }).then((image) => ({ + type: "image", + image, + })); } }); diff --git a/src/app/util.js b/src/app/util.js index c48fb1d..08466c8 100644 --- a/src/app/util.js +++ b/src/app/util.js @@ -115,7 +115,7 @@ export function useCommonStyles() { /** * safeImageUrl returns an HTTPS-safe image URL for Neopets assets! */ -export function safeImageUrl(urlString) { +export function safeImageUrl(urlString, { crossOrigin = null } = {}) { if (urlString == null) { return urlString; } @@ -141,12 +141,18 @@ export function safeImageUrl(urlString) { return "https://impress-2020.openneo.net/__error__URL-was-not-parseable__"; } + // Rewrite Neopets URLs to their HTTPS equivalents, or to our proxy if we + // need CORS headers. if (url.origin === "http://images.neopets.com") { url.protocol = "https:"; - url.host = "images.neopets-asset-proxy.openneo.net"; + if (crossOrigin) { + url.host = "images.neopets-asset-proxy.openneo.net"; + } } else if (url.origin === "http://pets.neopets.com") { url.protocol = "https:"; - url.host = "pets.neopets-asset-proxy.openneo.net"; + if (crossOrigin) { + url.host = "pets.neopets-asset-proxy.openneo.net"; + } } if (url.protocol !== "https:") {