Skip to content

Commit f81505c

Browse files
committed
[change] extend ImageLoader.load params
Prepare code to add a custom handler for loading images with headers Removed the old `image.decode` change as it's covered by the minimal browser versions supported here
1 parent d4cb0d3 commit f81505c

File tree

1 file changed

+69
-19
lines changed
  • packages/react-native-web/src/modules/ImageLoader

1 file changed

+69
-19
lines changed

packages/react-native-web/src/modules/ImageLoader/index.js

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,15 @@ const requests = {};
7575

7676
const ImageLoader = {
7777
abort(requestId: number) {
78-
let image = requests[`${requestId}`];
79-
if (image) {
78+
const request = requests[requestId];
79+
if (request) {
80+
const { image, cleanup } = request;
81+
if (cleanup) cleanup();
82+
8083
image.onerror = null;
8184
image.onload = null;
82-
image = null;
83-
delete requests[`${requestId}`];
85+
image.src = '';
86+
delete requests[requestId];
8487
}
8588
},
8689
getSize(
@@ -93,7 +96,7 @@ const ImageLoader = {
9396
const requestId = ImageLoader.load(uri, callback, errorCallback);
9497

9598
function callback() {
96-
const image = requests[`${requestId}`];
99+
const { image } = requests[requestId] || {};
97100
if (image) {
98101
const { naturalHeight, naturalWidth } = image;
99102
if (naturalHeight && naturalWidth) {
@@ -118,24 +121,62 @@ const ImageLoader = {
118121
has(uri: string): boolean {
119122
return ImageUriCache.has(uri);
120123
},
121-
load(uri: string, onLoad: Function, onError: Function): number {
124+
load(
125+
source: ImageSource,
126+
onLoad: (ImageResult) => void,
127+
onError: Function
128+
): number {
122129
id += 1;
123130
const image = new window.Image();
124-
image.onerror = onError;
125-
image.onload = (e) => {
131+
132+
const handleLoad = (e) => {
126133
// avoid blocking the main thread
127-
const onDecode = () => onLoad({ nativeEvent: e });
128-
if (typeof image.decode === 'function') {
129-
// Safari currently throws exceptions when decoding svgs.
130-
// We want to catch that error and allow the load handler
131-
// to be forwarded to the onLoad handler in this case
132-
image.decode().then(onDecode, onDecode);
133-
} else {
134-
setTimeout(onDecode, 0);
135-
}
134+
const onDecode = () =>
135+
onLoad({
136+
nativeEvent: e,
137+
uri: image.src,
138+
width: image.naturalWidth,
139+
height: image.naturalHeight
140+
});
141+
142+
// Safari currently throws exceptions when decoding svgs.
143+
// We want to catch that error and allow the load handler
144+
// to be forwarded to the onLoad handler in this case
145+
image.decode().then(onDecode, onDecode);
136146
};
137-
image.src = uri;
138-
requests[`${id}`] = image;
147+
148+
image.onerror = onError;
149+
image.onload = handleLoad;
150+
requests[id] = { image };
151+
152+
// When headers are supplied we can't load the image through `image.src`, but we `fetch` it as an AJAX request
153+
if (source.headers) {
154+
const abortCtrl = new AbortController();
155+
const request = new Request(source.uri, {
156+
headers: source.headers,
157+
signal: abortCtrl.signal
158+
});
159+
request.headers.append('accept', 'image/*');
160+
161+
requests[id].cleanup = () => {
162+
abortCtrl.abort();
163+
URL.revokeObjectURL(image.src);
164+
};
165+
166+
fetch(request)
167+
.then((response) => response.blob())
168+
.then((blob) => {
169+
image.src = URL.createObjectURL(blob);
170+
})
171+
.catch((error) => {
172+
if (error.name !== 'AbortError') onError(error);
173+
});
174+
} else {
175+
// For simple request we load the image through `image.src` because it has wider support
176+
// like better cross-origin support and progressive loading
177+
image.src = source.uri;
178+
}
179+
139180
return id;
140181
},
141182
prefetch(uri: string): Promise<void> {
@@ -164,4 +205,13 @@ const ImageLoader = {
164205
}
165206
};
166207

208+
type ImageSource = { uri: string, headers?: Record<string, string> };
209+
210+
type ImageResult = {
211+
uri: string,
212+
width: number,
213+
height: number,
214+
nativeEvent: Event
215+
};
216+
167217
export default ImageLoader;

0 commit comments

Comments
 (0)