Skip to content

Commit bef6667

Browse files
authored
Merge pull request #3 from ArekChr/feat/merge_patches_from_expensify
feat: migrate patches
2 parents 2712377 + a9b2a50 commit bef6667

File tree

8 files changed

+152
-14
lines changed

8 files changed

+152
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.dylanvann.fastimage;
2+
3+
import android.graphics.BitmapFactory;
4+
5+
import androidx.annotation.NonNull;
6+
import androidx.annotation.Nullable;
7+
import androidx.exifinterface.media.ExifInterface;
8+
9+
import com.bumptech.glide.load.Options;
10+
import com.bumptech.glide.load.ResourceDecoder;
11+
import com.bumptech.glide.load.engine.Resource;
12+
import com.bumptech.glide.load.resource.SimpleResource;
13+
14+
import java.io.IOException;
15+
import java.io.InputStream;
16+
17+
public class BitmapSizeDecoder implements ResourceDecoder<InputStream, BitmapFactory.Options> {
18+
19+
@Override
20+
public boolean handles(@NonNull InputStream source, @NonNull Options options) throws IOException {
21+
return true;
22+
}
23+
24+
@Nullable
25+
@Override
26+
public Resource<BitmapFactory.Options> decode(@NonNull InputStream source, int width, int height, @NonNull Options options) throws IOException {
27+
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
28+
bitmapOptions.inJustDecodeBounds = true;
29+
BitmapFactory.decodeStream(source, null, bitmapOptions);
30+
31+
// BitmapFactory#decodeStream leaves stream's position where ever it was after reading the encoded data
32+
// https://developer.android.com/reference/android/graphics/BitmapFactory#decodeStream(java.io.InputStream)
33+
// so we need to rewind the stream to be able to read image header with exif values
34+
source.reset();
35+
36+
int orientation = new ExifInterface(source).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
37+
if (orientation == ExifInterface.ORIENTATION_ROTATE_90 || orientation == ExifInterface.ORIENTATION_ROTATE_270) {
38+
int tmpWidth = bitmapOptions.outWidth;
39+
bitmapOptions.outWidth = bitmapOptions.outHeight;
40+
bitmapOptions.outHeight = tmpWidth;
41+
}
42+
return new SimpleResource(bitmapOptions);
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.dylanvann.fastimage;
2+
3+
import android.graphics.BitmapFactory;
4+
5+
import androidx.annotation.NonNull;
6+
import androidx.annotation.Nullable;
7+
8+
import com.bumptech.glide.load.Options;
9+
import com.bumptech.glide.load.engine.Resource;
10+
import com.bumptech.glide.load.resource.SimpleResource;
11+
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
12+
13+
public class BitmapSizeTranscoder implements ResourceTranscoder<BitmapFactory.Options, Size> {
14+
@Nullable
15+
@Override
16+
public Resource<Size> transcode(@NonNull Resource<BitmapFactory.Options> toTranscode, @NonNull Options options) {
17+
BitmapFactory.Options bitmap = toTranscode.get();
18+
Size size = new Size();
19+
size.width = bitmap.outWidth;
20+
size.height = bitmap.outHeight;
21+
return new SimpleResource(size);
22+
}
23+
}

android/src/main/java/com/dylanvann/fastimage/FastImageOkHttpProgressGlideModule.java

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.content.Context;
44
import androidx.annotation.NonNull;
5+
import android.graphics.BitmapFactory;
56

67
import com.bumptech.glide.Glide;
78
import com.bumptech.glide.Registry;
@@ -47,6 +48,9 @@ public void registerComponents(
4748
.build();
4849
OkHttpUrlLoader.Factory factory = new OkHttpUrlLoader.Factory(client);
4950
registry.replace(GlideUrl.class, InputStream.class, factory);
51+
// Decoder + Transcoder pair for InputStream -> Size
52+
registry.prepend(InputStream.class, BitmapFactory.Options.class, new BitmapSizeDecoder());
53+
registry.register(BitmapFactory.Options.class, Size.class, new BitmapSizeTranscoder());
5054
}
5155

5256
private static Interceptor createInterceptor(final ResponseProgressListener listener) {

android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java

-8
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@ public class FastImageRequestListener implements RequestListener<Drawable> {
2222
this.key = key;
2323
}
2424

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;
30-
}
31-
3225
@Override
3326
public boolean onLoadFailed(@androidx.annotation.Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
3427
FastImageOkHttpProgressGlideModule.forget(key);
@@ -53,7 +46,6 @@ public boolean onResourceReady(Drawable resource, Object model, Target<Drawable>
5346
ThemedReactContext context = (ThemedReactContext) view.getContext();
5447
RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
5548
int viewId = view.getId();
56-
eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_EVENT, mapFromResource(resource));
5749
eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
5850
return false;
5951
}

android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java

+56-3
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,32 @@
22

33
import static com.dylanvann.fastimage.FastImageRequestListener.REACT_ON_ERROR_EVENT;
44

5+
import androidx.annotation.NonNull;
56
import android.annotation.SuppressLint;
67
import android.content.Context;
78
import android.graphics.drawable.Drawable;
89

910
import androidx.annotation.Nullable;
1011
import androidx.appcompat.widget.AppCompatImageView;
1112

13+
import com.bumptech.glide.Glide;
1214
import com.bumptech.glide.RequestBuilder;
1315
import com.bumptech.glide.RequestManager;
16+
import com.bumptech.glide.load.DataSource;
17+
import com.bumptech.glide.load.engine.GlideException;
1418
import com.bumptech.glide.load.model.GlideUrl;
1519
import com.bumptech.glide.request.Request;
20+
import com.bumptech.glide.request.RequestListener;
21+
import com.bumptech.glide.request.target.SimpleTarget;
22+
import com.bumptech.glide.request.target.Target;
23+
import com.bumptech.glide.request.transition.Transition;
1624
import com.facebook.react.bridge.ReadableMap;
1725
import com.facebook.react.bridge.WritableMap;
1826
import com.facebook.react.bridge.WritableNativeMap;
1927
import com.facebook.react.uimanager.ThemedReactContext;
2028
import com.facebook.react.uimanager.events.RCTEventEmitter;
2129

30+
import java.io.File;
2231
import java.util.ArrayList;
2332
import java.util.Collections;
2433
import java.util.List;
@@ -130,9 +139,34 @@ public void onAfterUpdate(
130139
RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
131140
int viewId = this.getId();
132141

133-
eventEmitter.receiveEvent(viewId,
134-
FastImageViewManager.REACT_ON_LOAD_START_EVENT,
135-
new WritableNativeMap());
142+
// Request the URL from cache to see if it exists there and if so pass the cache
143+
// path as an argument in the onLoadStart event
144+
requestManager
145+
.asFile()
146+
.load(glideUrl)
147+
.onlyRetrieveFromCache(true)
148+
.listener(new RequestListener<File>() {
149+
@Override
150+
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
151+
WritableNativeMap result = new WritableNativeMap();
152+
result.putNull("cachePath");
153+
eventEmitter.receiveEvent(viewId,
154+
FastImageViewManager.REACT_ON_LOAD_START_EVENT,
155+
result);
156+
return false;
157+
}
158+
159+
@Override
160+
public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
161+
WritableNativeMap result = new WritableNativeMap();
162+
result.putString("cachePath", resource.getAbsolutePath());
163+
eventEmitter.receiveEvent(viewId,
164+
FastImageViewManager.REACT_ON_LOAD_START_EVENT,
165+
result);
166+
return false;
167+
}
168+
})
169+
.submit();
136170
}
137171

138172
if (requestManager != null) {
@@ -158,6 +192,25 @@ public void onAfterUpdate(
158192
builder.listener(new FastImageRequestListener(key));
159193

160194
builder.into(this);
195+
196+
// Used specifically to handle the `onLoad` event for the image
197+
RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
198+
int viewId = this.getId();
199+
requestManager
200+
.as(Size.class)
201+
.load(imageSource == null ? null : imageSource.getSourceForLoad())
202+
.into(new SimpleTarget<Size>() {
203+
@Override
204+
public void onResourceReady(@NonNull Size resource, @Nullable Transition<? super Size> transition) {
205+
WritableMap resourceData = new WritableNativeMap();
206+
resourceData.putInt("width", resource.width);
207+
resourceData.putInt("height", resource.height);
208+
eventEmitter.receiveEvent(viewId,
209+
"onFastImageLoad",
210+
resourceData
211+
);
212+
}
213+
});
161214
}
162215
}
163216

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.dylanvann.fastimage;
2+
3+
public class Size {
4+
int width;
5+
int height;
6+
}

ios/FastImage/FFFastImageView.m

+12-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ - (void) setOnFastImageError: (RCTDirectEventBlock)onFastImageError {
5454
- (void) setOnFastImageLoadStart: (RCTDirectEventBlock)onFastImageLoadStart {
5555
if (_source && !self.hasSentOnLoadStart) {
5656
_onFastImageLoadStart = onFastImageLoadStart;
57-
onFastImageLoadStart(@{});
5857
self.hasSentOnLoadStart = YES;
5958
} else {
6059
_onFastImageLoadStart = onFastImageLoadStart;
@@ -188,7 +187,18 @@ - (void) reloadImage {
188187
}
189188

190189
if (self.onFastImageLoadStart) {
191-
self.onFastImageLoadStart(@{});
190+
NSString* cachePath = [[SDImageCache sharedImageCache] cachePathForKey:url];
191+
BOOL isCached = [[SDImageCache sharedImageCache] diskImageDataExistsWithKey:url];
192+
if (isCached) {
193+
self.onFastImageLoadStart(@{
194+
@"cachePath": cachePath
195+
});
196+
}
197+
else {
198+
self.onFastImageLoadStart(@{
199+
@"cachePath": [NSNull null]
200+
});
201+
}
192202
self.hasSentOnLoadStart = YES;
193203
} else {
194204
self.hasSentOnLoadStart = NO;

src/index.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ export type Source = {
5252
cache?: Cache
5353
}
5454

55+
export interface OnLoadStartEvent {
56+
nativeEvent: {
57+
cachePath: string | null;
58+
};
59+
}
60+
5561
export interface OnLoadEvent {
5662
nativeEvent: {
5763
width: number
@@ -86,7 +92,7 @@ export interface FastImageProps extends AccessibilityProps, ViewProps {
8692
resizeMode?: ResizeMode
8793
fallback?: boolean
8894

89-
onLoadStart?(): void
95+
onLoadStart?(event: OnLoadStartEvent): void
9096

9197
onProgress?(event: OnProgressEvent): void
9298

0 commit comments

Comments
 (0)