react-native-fast-image 8.6.32 → 8.6.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -176,7 +176,7 @@ e.g. `onProgress={e => console.log(e.nativeEvent.loaded / e.nativeEvent.total)}`
176
176
 
177
177
  ### `onLoad?: (event) => void`
178
178
 
179
- Called on a successful image fetch. Called with the width and height of the loaded image.
179
+ Called on a successful image fetch. Called with the width and height of the image itself, not of the view (on iOS, in points: an `@2x` asset reports half its pixel size).
180
180
 
181
181
  e.g. `onLoad={e => console.log(e.nativeEvent.width, e.nativeEvent.height)}`
182
182
 
@@ -0,0 +1,45 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import com.facebook.react.bridge.WritableMap;
4
+ import com.facebook.react.uimanager.events.Event;
5
+ import com.facebook.react.uimanager.events.RCTEventEmitter;
6
+
7
+ // An event for a FastImage view, sent with the EventDispatcher (see
8
+ // FastImageEvents) instead of the RCTEventEmitter JS module, which the New
9
+ // Architecture warns about on every event.
10
+ class FastImageEvent extends Event<FastImageEvent> {
11
+ private final String name;
12
+ private final WritableMap data;
13
+
14
+ // Event(viewTag) works back to React Native 0.60. Without a surface id,
15
+ // Fabric finds the view by its tag.
16
+ @SuppressWarnings("deprecation")
17
+ FastImageEvent(int viewTag, String name, WritableMap data) {
18
+ super(viewTag);
19
+ this.name = name;
20
+ this.data = data;
21
+ }
22
+
23
+ @Override
24
+ public String getEventName() {
25
+ return name;
26
+ }
27
+
28
+ // Every event reaches JS, e.g. each progress update, as before.
29
+ @Override
30
+ public boolean canCoalesce() {
31
+ return false;
32
+ }
33
+
34
+ // Overrides Event.getEventData on React Native 0.65+ (not on older ones,
35
+ // hence no @Override).
36
+ protected WritableMap getEventData() {
37
+ return data;
38
+ }
39
+
40
+ @Override
41
+ @SuppressWarnings("deprecation")
42
+ public void dispatch(RCTEventEmitter rctEventEmitter) {
43
+ rctEventEmitter.receiveEvent(getViewTag(), name, data);
44
+ }
45
+ }
@@ -0,0 +1,60 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import android.view.View;
4
+
5
+ import androidx.annotation.Nullable;
6
+
7
+ import com.facebook.react.bridge.Arguments;
8
+ import com.facebook.react.bridge.ReactContext;
9
+ import com.facebook.react.bridge.WritableMap;
10
+ import com.facebook.react.uimanager.UIManagerModule;
11
+ import com.facebook.react.uimanager.events.EventDispatcher;
12
+
13
+ import java.lang.reflect.Method;
14
+
15
+ // Sends FastImage view events through React Native's EventDispatcher.
16
+ final class FastImageEvents {
17
+ // UIManagerHelper.getEventDispatcherForReactTag (React Native 0.63+, also
18
+ // bridgeless). Looked up by reflection so older versions still compile.
19
+ @Nullable
20
+ private static final Method GET_EVENT_DISPATCHER = findGetEventDispatcher();
21
+
22
+ private FastImageEvents() {
23
+ }
24
+
25
+ static void send(View view, String name) {
26
+ send(view, name, Arguments.createMap());
27
+ }
28
+
29
+ static void send(View view, String name, WritableMap data) {
30
+ ReactContext context = FastImageViewManager.getReactContext(view.getContext());
31
+ if (context == null) return;
32
+ EventDispatcher dispatcher = eventDispatcher(context, view.getId());
33
+ if (dispatcher != null) {
34
+ dispatcher.dispatchEvent(new FastImageEvent(view.getId(), name, data));
35
+ }
36
+ }
37
+
38
+ @Nullable
39
+ private static EventDispatcher eventDispatcher(ReactContext context, int viewTag) {
40
+ if (GET_EVENT_DISPATCHER != null) {
41
+ try {
42
+ return (EventDispatcher) GET_EVENT_DISPATCHER.invoke(null, context, viewTag);
43
+ } catch (Exception ignored) {
44
+ // Fall back to the UIManagerModule's.
45
+ }
46
+ }
47
+ UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
48
+ return uiManager == null ? null : uiManager.getEventDispatcher();
49
+ }
50
+
51
+ @Nullable
52
+ private static Method findGetEventDispatcher() {
53
+ try {
54
+ return Class.forName("com.facebook.react.uimanager.UIManagerHelper")
55
+ .getMethod("getEventDispatcherForReactTag", ReactContext.class, int.class);
56
+ } catch (Exception e) {
57
+ return null;
58
+ }
59
+ }
60
+ }
@@ -4,29 +4,24 @@ import android.graphics.drawable.Drawable;
4
4
 
5
5
  import com.bumptech.glide.load.DataSource;
6
6
  import com.bumptech.glide.load.engine.GlideException;
7
+ import com.bumptech.glide.load.model.GlideUrl;
8
+ import com.bumptech.glide.request.Request;
7
9
  import com.bumptech.glide.request.RequestListener;
8
10
  import com.bumptech.glide.request.target.ImageViewTarget;
9
11
  import com.bumptech.glide.request.target.Target;
10
12
  import com.facebook.react.bridge.WritableMap;
11
13
  import com.facebook.react.bridge.WritableNativeMap;
12
- import com.facebook.react.bridge.ReactContext;
13
- import com.facebook.react.uimanager.events.RCTEventEmitter;
14
14
 
15
15
  public class FastImageRequestListener implements RequestListener<Drawable> {
16
16
  static final String REACT_ON_ERROR_EVENT = "onFastImageError";
17
17
  static final String REACT_ON_LOAD_EVENT = "onFastImageLoad";
18
18
  static final String REACT_ON_LOAD_END_EVENT = "onFastImageLoadEnd";
19
19
  private final String key;
20
+ private final FastImageSource source;
20
21
 
21
- FastImageRequestListener(String key) {
22
+ FastImageRequestListener(String key, FastImageSource source) {
22
23
  this.key = key;
23
- }
24
-
25
- private static WritableMap mapFromResource(Drawable resource) {
26
- WritableMap resourceData = new WritableNativeMap();
27
- resourceData.putInt("width", resource.getIntrinsicWidth());
28
- resourceData.putInt("height", resource.getIntrinsicHeight());
29
- return resourceData;
24
+ this.source = source;
30
25
  }
31
26
 
32
27
  @Override
@@ -36,31 +31,41 @@ public class FastImageRequestListener implements RequestListener<Drawable> {
36
31
  return false;
37
32
  }
38
33
  FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView();
39
- ReactContext context = FastImageViewManager.getReactContext(view.getContext());
40
- if (context == null) {
41
- return false;
42
- }
43
- RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
44
- int viewId = view.getId();
45
- eventEmitter.receiveEvent(viewId, REACT_ON_ERROR_EVENT, new WritableNativeMap());
46
- eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
34
+ FastImageEvents.send(view, REACT_ON_ERROR_EVENT);
35
+ FastImageEvents.send(view, REACT_ON_LOAD_END_EVENT);
47
36
  return false;
48
37
  }
49
38
 
50
39
  @Override
51
- public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
40
+ public boolean onResourceReady(Drawable resource, Object model, final Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
52
41
  if (!(target instanceof ImageViewTarget)) {
53
42
  return false;
54
43
  }
55
- FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView();
56
- ReactContext context = FastImageViewManager.getReactContext(view.getContext());
57
- if (context == null) {
44
+ final FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView();
45
+ boolean local = !(model instanceof GlideUrl);
46
+ int[] size = FastImageSourceSize.get(resource, model, local,
47
+ dataSource == DataSource.RESOURCE_DISK_CACHE);
48
+ if (size != null) {
49
+ sendLoad(view, size);
58
50
  return false;
59
51
  }
60
- RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
61
- int viewId = view.getId();
62
- eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_EVENT, mapFromResource(resource));
63
- eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
52
+ // A local image whose size isn't known: read it from the image first,
53
+ // unless the view starts another load meanwhile.
54
+ final Request request = target.getRequest();
55
+ FastImageSourceSize.readLocal(view.getContext(), source, resource, model, new FastImageSourceSize.Callback() {
56
+ @Override
57
+ public void onSize(int[] size) {
58
+ if (target.getRequest() == request) sendLoad(view, size);
59
+ }
60
+ });
64
61
  return false;
65
62
  }
63
+
64
+ private static void sendLoad(FastImageViewWithUrl view, int[] size) {
65
+ WritableMap event = new WritableNativeMap();
66
+ event.putInt("width", size[0]);
67
+ event.putInt("height", size[1]);
68
+ FastImageEvents.send(view, REACT_ON_LOAD_EVENT, event);
69
+ FastImageEvents.send(view, REACT_ON_LOAD_END_EVENT);
70
+ }
66
71
  }
@@ -0,0 +1,237 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import android.content.Context;
4
+ import android.graphics.BitmapFactory;
5
+ import android.graphics.drawable.Drawable;
6
+ import android.net.Uri;
7
+ import android.os.Handler;
8
+ import android.os.Looper;
9
+ import android.util.Base64;
10
+ import android.util.LruCache;
11
+ import android.widget.ImageView;
12
+
13
+ import androidx.annotation.Nullable;
14
+
15
+ import com.bumptech.glide.Glide;
16
+ import com.bumptech.glide.load.ImageHeaderParserUtils;
17
+ import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy;
18
+ import com.bumptech.glide.load.resource.gif.GifDrawable;
19
+ import com.bumptech.glide.request.RequestOptions;
20
+
21
+ import java.io.ByteArrayInputStream;
22
+ import java.io.IOException;
23
+ import java.io.InputStream;
24
+ import java.nio.ByteBuffer;
25
+ import java.util.concurrent.Executor;
26
+ import java.util.concurrent.Executors;
27
+
28
+ // Works out an image's own size for onLoad, as iOS reports it (#608). Glide
29
+ // decodes images to fit the view, so the loaded drawable is usually smaller
30
+ // than the image.
31
+ final class FastImageSourceSize {
32
+ // Sizes of recently decoded images, for loads from the memory cache, which
33
+ // don't decode.
34
+ private static final LruCache<String, int[]> SIZES = new LruCache<>(500);
35
+ private static final Executor EXECUTOR = Executors.newSingleThreadExecutor();
36
+ private static final Handler MAIN = new Handler(Looper.getMainLooper());
37
+
38
+ private FastImageSourceSize() {
39
+ }
40
+
41
+ // Wraps the downsample strategy Glide would use, to record the image's
42
+ // size (after EXIF rotation) when Glide decodes it. Views loading the same
43
+ // image at the same size share one decode, which uses the first view's
44
+ // options, so the size is recorded by image rather than by request.
45
+ static final class Capture extends DownsampleStrategy {
46
+ private final DownsampleStrategy strategy;
47
+ private final String key;
48
+ private boolean recorded;
49
+
50
+ Capture(DownsampleStrategy strategy, String key) {
51
+ this.strategy = strategy;
52
+ this.key = key;
53
+ }
54
+
55
+ @Override
56
+ public float getScaleFactor(int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
57
+ // Called again with the sampled size; the first call has the image's.
58
+ if (!recorded) {
59
+ recorded = true;
60
+ SIZES.put(key, new int[]{sourceWidth, sourceHeight});
61
+ }
62
+ return strategy.getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight);
63
+ }
64
+
65
+ @Override
66
+ public SampleSizeRounding getSampleSizeRounding(int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
67
+ return strategy.getSampleSizeRounding(sourceWidth, sourceHeight, requestedWidth, requestedHeight);
68
+ }
69
+
70
+ // Glide's memory cache keys include the strategy, so match the wrapped
71
+ // one to keep sharing cached images between views.
72
+ @Override
73
+ public boolean equals(Object o) {
74
+ return o instanceof Capture && ((Capture) o).strategy.equals(strategy);
75
+ }
76
+
77
+ @Override
78
+ public int hashCode() {
79
+ return strategy.hashCode();
80
+ }
81
+ }
82
+
83
+ // What RequestBuilder.into(ImageView) applies for the view's scale type
84
+ // (it leaves a transformation that's already set alone), with the
85
+ // downsample strategy it implies wrapped by capture.
86
+ static RequestOptions scaleTypeOptions(@Nullable ImageView.ScaleType scaleType, Capture capture) {
87
+ RequestOptions options = new RequestOptions();
88
+ if (scaleType != null) {
89
+ switch (scaleType) {
90
+ case CENTER_CROP:
91
+ options = options.optionalCenterCrop();
92
+ break;
93
+ case CENTER_INSIDE:
94
+ case FIT_XY:
95
+ options = options.optionalCenterInside();
96
+ break;
97
+ case FIT_CENTER:
98
+ case FIT_START:
99
+ case FIT_END:
100
+ options = options.optionalFitCenter();
101
+ break;
102
+ default:
103
+ break;
104
+ }
105
+ }
106
+ return options.downsample(capture);
107
+ }
108
+
109
+ static Capture capture(@Nullable ImageView.ScaleType scaleType, Object model) {
110
+ return new Capture(strategy(scaleType), String.valueOf(model));
111
+ }
112
+
113
+ private static DownsampleStrategy strategy(@Nullable ImageView.ScaleType scaleType) {
114
+ if (scaleType == null) return DownsampleStrategy.DEFAULT;
115
+ switch (scaleType) {
116
+ case CENTER_CROP:
117
+ return DownsampleStrategy.CENTER_OUTSIDE;
118
+ case CENTER_INSIDE:
119
+ case FIT_XY:
120
+ return DownsampleStrategy.CENTER_INSIDE;
121
+ case FIT_CENTER:
122
+ case FIT_START:
123
+ case FIT_END:
124
+ return DownsampleStrategy.FIT_CENTER;
125
+ default:
126
+ return DownsampleStrategy.DEFAULT;
127
+ }
128
+ }
129
+
130
+ // The image's size, or null when it has to be read from a local image's
131
+ // header first (see readLocal).
132
+ @Nullable
133
+ static int[] get(Drawable resource, Object model, boolean local, boolean fromResourceCache) {
134
+ String key = String.valueOf(model);
135
+ if (resource instanceof GifDrawable) {
136
+ // Glide decodes GIFs itself (sampled to fit the view), without the
137
+ // downsample strategy; their header has the size.
138
+ int[] size = gifSize((GifDrawable) resource);
139
+ if (size != null) return size;
140
+ } else if (fromResourceCache) {
141
+ // Glide caches local images already resized for the view, and the
142
+ // decode from there recorded the resized size.
143
+ SIZES.remove(key);
144
+ return null;
145
+ } else {
146
+ int[] size = SIZES.get(key);
147
+ if (size != null) return size;
148
+ if (local) return null;
149
+ }
150
+ return new int[]{resource.getIntrinsicWidth(), resource.getIntrinsicHeight()};
151
+ }
152
+
153
+ @Nullable
154
+ private static int[] gifSize(GifDrawable gif) {
155
+ ByteBuffer buffer = gif.getBuffer();
156
+ if (buffer == null || buffer.limit() < 10) return null;
157
+ // The logical screen width and height (little-endian) follow the
158
+ // 6-byte signature.
159
+ int width = (buffer.get(6) & 0xff) | (buffer.get(7) & 0xff) << 8;
160
+ int height = (buffer.get(8) & 0xff) | (buffer.get(9) & 0xff) << 8;
161
+ return new int[]{width, height};
162
+ }
163
+
164
+ interface Callback {
165
+ void onSize(int[] size);
166
+ }
167
+
168
+ // Reads a local image's size from its header, off the main thread.
169
+ static void readLocal(Context context, final FastImageSource source, final Drawable resource, final Object model, final Callback callback) {
170
+ final Context appContext = context.getApplicationContext();
171
+ EXECUTOR.execute(new Runnable() {
172
+ @Override
173
+ public void run() {
174
+ int[] size = readBounds(appContext, source);
175
+ if (size != null) {
176
+ SIZES.put(String.valueOf(model), size);
177
+ } else {
178
+ size = new int[]{resource.getIntrinsicWidth(), resource.getIntrinsicHeight()};
179
+ }
180
+ final int[] result = size;
181
+ MAIN.post(new Runnable() {
182
+ @Override
183
+ public void run() {
184
+ callback.onSize(result);
185
+ }
186
+ });
187
+ }
188
+ });
189
+ }
190
+
191
+ @Nullable
192
+ private static int[] readBounds(Context context, FastImageSource source) {
193
+ try {
194
+ BitmapFactory.Options options = new BitmapFactory.Options();
195
+ options.inJustDecodeBounds = true;
196
+ InputStream stream = open(context, source);
197
+ try {
198
+ BitmapFactory.decodeStream(stream, null, options);
199
+ } finally {
200
+ stream.close();
201
+ }
202
+ if (options.outWidth <= 0 || options.outHeight <= 0) return null;
203
+ int orientation;
204
+ stream = open(context, source);
205
+ try {
206
+ Glide glide = Glide.get(context);
207
+ orientation = ImageHeaderParserUtils.getOrientation(
208
+ glide.getRegistry().getImageHeaderParsers(), stream, glide.getArrayPool());
209
+ } finally {
210
+ stream.close();
211
+ }
212
+ // EXIF orientations 5 to 8 rotate by 90 or 270 degrees.
213
+ boolean rotated = orientation >= 5 && orientation <= 8;
214
+ return rotated
215
+ ? new int[]{options.outHeight, options.outWidth}
216
+ : new int[]{options.outWidth, options.outHeight};
217
+ } catch (IOException | RuntimeException e) {
218
+ return null;
219
+ }
220
+ }
221
+
222
+ private static InputStream open(Context context, FastImageSource source) throws IOException {
223
+ if (source.isBase64Resource()) {
224
+ String data = source.getSource();
225
+ byte[] bytes = Base64.decode(data.substring(data.indexOf(',') + 1), Base64.DEFAULT);
226
+ return new ByteArrayInputStream(bytes);
227
+ }
228
+ Uri uri = source.getUri();
229
+ String path = uri.getPath();
230
+ if ("file".equals(uri.getScheme()) && path != null && path.startsWith("/android_asset/")) {
231
+ return context.getAssets().open(path.substring("/android_asset/".length()));
232
+ }
233
+ InputStream stream = context.getContentResolver().openInputStream(uri);
234
+ if (stream == null) throw new IOException("Can't open " + uri);
235
+ return stream;
236
+ }
237
+ }
@@ -23,7 +23,6 @@ import com.facebook.react.uimanager.SimpleViewManager;
23
23
  import com.facebook.react.bridge.ReactContext;
24
24
  import com.facebook.react.uimanager.ThemedReactContext;
25
25
  import com.facebook.react.uimanager.annotations.ReactProp;
26
- import com.facebook.react.uimanager.events.RCTEventEmitter;
27
26
  import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
28
27
 
29
28
  import java.util.List;
@@ -121,11 +120,7 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple
121
120
  WritableMap event = new WritableNativeMap();
122
121
  event.putInt("loaded", (int) bytesRead);
123
122
  event.putInt("total", (int) expectedLength);
124
- ReactContext context = getReactContext(view.getContext());
125
- if (context == null) continue;
126
- RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
127
- int viewId = view.getId();
128
- eventEmitter.receiveEvent(viewId, REACT_ON_PROGRESS_EVENT, event);
123
+ FastImageEvents.send(view, REACT_ON_PROGRESS_EVENT, event);
129
124
  }
130
125
  }
131
126
  }
@@ -18,8 +18,6 @@ import com.bumptech.glide.request.Request;
18
18
  import com.facebook.react.bridge.ReadableMap;
19
19
  import com.facebook.react.bridge.WritableMap;
20
20
  import com.facebook.react.bridge.WritableNativeMap;
21
- import com.facebook.react.bridge.ReactContext;
22
- import com.facebook.react.uimanager.events.RCTEventEmitter;
23
21
 
24
22
  import java.util.ArrayList;
25
23
  import java.util.Collections;
@@ -97,15 +95,10 @@ class FastImageViewWithUrl extends AppCompatImageView {
97
95
  // resolved: fire onError and onLoadEnd and show defaultSource, as on iOS
98
96
  // (#1028, #945).
99
97
  if (mSource != null && (imageSource == null || imageSource.getUri().toString().length() == 0)) {
100
- ReactContext context = FastImageViewManager.getReactContext(getContext());
101
- if (context != null) {
102
- RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
103
- int viewId = getId();
104
- WritableMap event = new WritableNativeMap();
105
- event.putString("message", "Invalid source prop:" + mSource);
106
- eventEmitter.receiveEvent(viewId, REACT_ON_ERROR_EVENT, event);
107
- eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
108
- }
98
+ WritableMap event = new WritableNativeMap();
99
+ event.putString("message", "Invalid source prop:" + mSource);
100
+ FastImageEvents.send(this, REACT_ON_ERROR_EVENT, event);
101
+ FastImageEvents.send(this, REACT_ON_LOAD_END_EVENT);
109
102
 
110
103
  // Cancel existing requests.
111
104
  clearView(requestManager);
@@ -140,18 +133,15 @@ class FastImageViewWithUrl extends AppCompatImageView {
140
133
  }
141
134
  }
142
135
 
143
- ReactContext reactContext = FastImageViewManager.getReactContext(getContext());
144
- if (imageSource != null && reactContext != null) {
136
+ if (imageSource != null) {
145
137
  // This is an orphan even without a load/loadend when only loading a placeholder
146
- RCTEventEmitter eventEmitter = reactContext.getJSModule(RCTEventEmitter.class);
147
- int viewId = this.getId();
148
-
149
- eventEmitter.receiveEvent(viewId,
150
- FastImageViewManager.REACT_ON_LOAD_START_EVENT,
151
- new WritableNativeMap());
138
+ FastImageEvents.send(this, FastImageViewManager.REACT_ON_LOAD_START_EVENT);
152
139
  }
153
140
 
154
141
  if (requestManager != null) {
142
+ // Records the image's own size when Glide decodes it, for onLoad.
143
+ Object model = imageSource == null ? null : imageSource.getSourceForLoad();
144
+ FastImageSourceSize.Capture capture = FastImageSourceSize.capture(getScaleType(), model);
155
145
  RequestBuilder<Drawable> builder =
156
146
  requestManager
157
147
  // This will make this work for remote and local images. e.g.
@@ -160,14 +150,17 @@ class FastImageViewWithUrl extends AppCompatImageView {
160
150
  // - res:/
161
151
  // - android.resource://
162
152
  // - data:image/png;base64
163
- .load(imageSource == null ? null : imageSource.getSourceForLoad())
153
+ .load(model)
164
154
  .apply(FastImageViewConverter
165
155
  .getOptions(getContext(), imageSource, mSource)
166
156
  .placeholder(mDefaultSource) // show until loaded
167
- .fallback(mDefaultSource)); // null will not be treated as error
157
+ .fallback(mDefaultSource)) // null will not be treated as error
158
+ // What into() would apply for the scale type, with
159
+ // the size capture.
160
+ .apply(FastImageSourceSize.scaleTypeOptions(getScaleType(), capture));
168
161
 
169
162
  if (key != null)
170
- builder.listener(new FastImageRequestListener(key));
163
+ builder.listener(new FastImageRequestListener(key, imageSource));
171
164
 
172
165
  builder.into(this);
173
166
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-fast-image",
3
- "version": "8.6.32",
3
+ "version": "8.6.34",
4
4
  "description": "🚩 FastImage, performant React Native image component.",
5
5
  "keywords": [
6
6
  "cache",
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "https://github.com/DylanVann/react-native-fast-image.git"
18
+ "url": "git+https://github.com/DylanVann/react-native-fast-image.git"
19
19
  },
20
20
  "license": "(MIT AND Apache-2.0)",
21
21
  "author": "Dylan Vann <dylan@dylanvann.com> (https://dylanvann.com)",