Skip to content

Commit

Permalink
Merge pull request #19021 from Expensify/revert-16532-fix/large_image…
Browse files Browse the repository at this point in the history
…s_android

Revert "Fix/large images android"

(cherry picked from commit 5fab2de)
  • Loading branch information
mountiny authored and OSBotify committed May 18, 2023
1 parent 94f82d2 commit 1d8db57
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 10 deletions.
4 changes: 2 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<!-- android:hardwareAccelerated is essential for Android performance: https://developer.android.com/topic/performance/hardware-accel -->
<application
android:supportsRtl="false"
android:largeHeap="true"
android:hardwareAccelerated="false"
android:hardwareAccelerated="true"
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
Expand Down
8 changes: 2 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"react-native-dev-menu": "^4.1.1",
"react-native-device-info": "^10.3.0",
"react-native-document-picker": "^8.0.0",
"react-native-fast-image": "git+https://github.com/Expensify/react-native-fast-image.git#afedf204bfc253d18f08fdcc5356a2bb82f6a87c",
"react-native-fast-image": "^8.6.3",
"react-native-gesture-handler": "2.9.0",
"react-native-google-places-autocomplete": "git+https://github.com/Expensify/react-native-google-places-autocomplete.git#6f436a06a3018cb49750bb110b89df75f6a865d5",
"react-native-haptic-feedback": "^1.13.0",
Expand Down
300 changes: 300 additions & 0 deletions patches/react-native-fast-image+8.6.3.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
diff --git a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/BitmapSizeDecoder.java b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/BitmapSizeDecoder.java
new file mode 100644
index 0000000..2bd58b8
--- /dev/null
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/BitmapSizeDecoder.java
@@ -0,0 +1,44 @@
+package com.dylanvann.fastimage;
+
+import android.graphics.BitmapFactory;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.exifinterface.media.ExifInterface;
+
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.ResourceDecoder;
+import com.bumptech.glide.load.engine.Resource;
+import com.bumptech.glide.load.resource.SimpleResource;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BitmapSizeDecoder implements ResourceDecoder<InputStream, BitmapFactory.Options> {
+
+ @Override
+ public boolean handles(@NonNull InputStream source, @NonNull Options options) throws IOException {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public Resource<BitmapFactory.Options> decode(@NonNull InputStream source, int width, int height, @NonNull Options options) throws IOException {
+ BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
+ bitmapOptions.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(source, null, bitmapOptions);
+
+ // BitmapFactory#decodeStream leaves stream's position where ever it was after reading the encoded data
+ // https://developer.android.com/reference/android/graphics/BitmapFactory#decodeStream(java.io.InputStream)
+ // so we need to rewind the stream to be able to read image header with exif values
+ source.reset();
+
+ int orientation = new ExifInterface(source).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
+ if (orientation == ExifInterface.ORIENTATION_ROTATE_90 || orientation == ExifInterface.ORIENTATION_ROTATE_270) {
+ int tmpWidth = bitmapOptions.outWidth;
+ bitmapOptions.outWidth = bitmapOptions.outHeight;
+ bitmapOptions.outHeight = tmpWidth;
+ }
+ return new SimpleResource(bitmapOptions);
+ }
+}
\ No newline at end of file
diff --git a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/BitmapSizeTranscoder.java b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/BitmapSizeTranscoder.java
new file mode 100644
index 0000000..7d208d1
--- /dev/null
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/BitmapSizeTranscoder.java
@@ -0,0 +1,23 @@
+package com.dylanvann.fastimage;
+
+import android.graphics.BitmapFactory;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.engine.Resource;
+import com.bumptech.glide.load.resource.SimpleResource;
+import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
+
+public class BitmapSizeTranscoder implements ResourceTranscoder<BitmapFactory.Options, Size> {
+ @Nullable
+ @Override
+ public Resource<Size> transcode(@NonNull Resource<BitmapFactory.Options> toTranscode, @NonNull Options options) {
+ BitmapFactory.Options bitmap = toTranscode.get();
+ Size size = new Size();
+ size.width = bitmap.outWidth;
+ size.height = bitmap.outHeight;
+ return new SimpleResource(size);
+ }
+}
\ No newline at end of file
diff --git a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageOkHttpProgressGlideModule.java b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageOkHttpProgressGlideModule.java
index 811292a..f60b87c 100644
--- a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageOkHttpProgressGlideModule.java
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageOkHttpProgressGlideModule.java
@@ -2,6 +2,7 @@ package com.dylanvann.fastimage;

import android.content.Context;
import androidx.annotation.NonNull;
+import android.graphics.BitmapFactory;

import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
@@ -47,6 +48,9 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
.build();
OkHttpUrlLoader.Factory factory = new OkHttpUrlLoader.Factory(client);
registry.replace(GlideUrl.class, InputStream.class, factory);
+ // Decoder + Transcoder pair for InputStream -> Size
+ registry.prepend(InputStream.class, BitmapFactory.Options.class, new BitmapSizeDecoder());
+ registry.register(BitmapFactory.Options.class, Size.class, new BitmapSizeTranscoder());
}

private static Interceptor createInterceptor(final ResponseProgressListener listener) {
diff --git a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java
index dbeb813..bf8f21c 100644
--- a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java
@@ -22,13 +22,6 @@ public class FastImageRequestListener implements RequestListener<Drawable> {
this.key = key;
}

- private static WritableMap mapFromResource(Drawable resource) {
- WritableMap resourceData = new WritableNativeMap();
- resourceData.putInt("width", resource.getIntrinsicWidth());
- resourceData.putInt("height", resource.getIntrinsicHeight());
- return resourceData;
- }
-
@Override
public boolean onLoadFailed(@androidx.annotation.Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
FastImageOkHttpProgressGlideModule.forget(key);
@@ -53,7 +46,6 @@ public class FastImageRequestListener implements RequestListener<Drawable> {
ThemedReactContext context = (ThemedReactContext) view.getContext();
RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
int viewId = view.getId();
- eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_EVENT, mapFromResource(resource));
eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
return false;
}
diff --git a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java
index 34fcf89..1339f5c 100644
--- a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java
@@ -2,6 +2,7 @@ package com.dylanvann.fastimage;

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

+import androidx.annotation.NonNull;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -9,16 +10,24 @@ import android.graphics.drawable.Drawable;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;

+import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.RequestManager;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.request.Request;
+import com.bumptech.glide.request.RequestListener;
+import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.target.Target;
+import com.bumptech.glide.request.transition.Transition;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.events.RCTEventEmitter;

+import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -124,9 +133,34 @@ class FastImageViewWithUrl extends AppCompatImageView {
RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
int viewId = this.getId();

- eventEmitter.receiveEvent(viewId,
- FastImageViewManager.REACT_ON_LOAD_START_EVENT,
- new WritableNativeMap());
+ // Request the URL from cache to see if it exists there and if so pass the cache
+ // path as an argument in the onLoadStart event
+ requestManager
+ .asFile()
+ .load(glideUrl)
+ .onlyRetrieveFromCache(true)
+ .listener(new RequestListener<File>() {
+ @Override
+ public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
+ WritableNativeMap result = new WritableNativeMap();
+ result.putNull("cachePath");
+ eventEmitter.receiveEvent(viewId,
+ FastImageViewManager.REACT_ON_LOAD_START_EVENT,
+ result);
+ return false;
+ }
+
+ @Override
+ public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
+ WritableNativeMap result = new WritableNativeMap();
+ result.putString("cachePath", resource.getAbsolutePath());
+ eventEmitter.receiveEvent(viewId,
+ FastImageViewManager.REACT_ON_LOAD_START_EVENT,
+ result);
+ return false;
+ }
+ })
+ .submit();
}

if (requestManager != null) {
@@ -148,6 +182,25 @@ class FastImageViewWithUrl extends AppCompatImageView {
builder.listener(new FastImageRequestListener(key));

builder.into(this);
+
+ // Used specifically to handle the `onLoad` event for the image
+ RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
+ int viewId = this.getId();
+ requestManager
+ .as(Size.class)
+ .load(imageSource == null ? null : imageSource.getSourceForLoad())
+ .into(new SimpleTarget<Size>() {
+ @Override
+ public void onResourceReady(@NonNull Size resource, @Nullable Transition<? super Size> transition) {
+ WritableMap resourceData = new WritableNativeMap();
+ resourceData.putInt("width", resource.width);
+ resourceData.putInt("height", resource.height);
+ eventEmitter.receiveEvent(viewId,
+ "onFastImageLoad",
+ resourceData
+ );
+ }
+ });
}
}

diff --git a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/Size.java b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/Size.java
new file mode 100644
index 0000000..2fe8a47
--- /dev/null
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/Size.java
@@ -0,0 +1,6 @@
+package com.dylanvann.fastimage;
+
+public class Size {
+ int width;
+ int height;
+}
\ No newline at end of file
diff --git a/node_modules/react-native-fast-image/dist/index.d.ts b/node_modules/react-native-fast-image/dist/index.d.ts
index 5abb7c9..a2672c6 100644
--- a/node_modules/react-native-fast-image/dist/index.d.ts
+++ b/node_modules/react-native-fast-image/dist/index.d.ts
@@ -27,6 +27,11 @@ export declare type Source = {
priority?: Priority;
cache?: Cache;
};
+export interface OnLoadStartEvent {
+ nativeEvent: {
+ cachePath: string | null;
+ };
+}
export interface OnLoadEvent {
nativeEvent: {
width: number;
@@ -57,7 +62,7 @@ export interface FastImageProps extends AccessibilityProps, ViewProps {
defaultSource?: ImageRequireSource;
resizeMode?: ResizeMode;
fallback?: boolean;
- onLoadStart?(): void;
+ onLoadStart?(event: OnLoadStartEvent): void;
onProgress?(event: OnProgressEvent): void;
onLoad?(event: OnLoadEvent): void;
onError?(): void;
diff --git a/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.m b/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.m
index f710081..391ef92 100644
--- a/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.m
+++ b/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.m
@@ -54,7 +54,6 @@ - (void) setOnFastImageError: (RCTDirectEventBlock)onFastImageError {
- (void) setOnFastImageLoadStart: (RCTDirectEventBlock)onFastImageLoadStart {
if (_source && !self.hasSentOnLoadStart) {
_onFastImageLoadStart = onFastImageLoadStart;
- onFastImageLoadStart(@{});
self.hasSentOnLoadStart = YES;
} else {
_onFastImageLoadStart = onFastImageLoadStart;
@@ -188,7 +187,18 @@ - (void) reloadImage {
}

if (self.onFastImageLoadStart) {
- self.onFastImageLoadStart(@{});
+ NSString* cachePath = [[SDImageCache sharedImageCache] cachePathForKey:url];
+ BOOL isCached = [[SDImageCache sharedImageCache] diskImageDataExistsWithKey:url];
+ if (isCached) {
+ self.onFastImageLoadStart(@{
+ @"cachePath": cachePath
+ });
+ }
+ else {
+ self.onFastImageLoadStart(@{
+ @"cachePath": [NSNull null]
+ });
+ }
self.hasSentOnLoadStart = YES;
} else {
self.hasSentOnLoadStart = NO;
1 change: 0 additions & 1 deletion src/components/ImageView/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ class ImageView extends PureComponent {
// due to ImageZoom
shouldShowLoadingIndicator ? styles.opacity0 : styles.opacity1,
]}
disableTransformation
source={{uri: this.props.url}}
isAuthTokenRequired={this.props.isAuthTokenRequired}
resizeMode={Image.resizeMode.contain}
Expand Down

0 comments on commit 1d8db57

Please sign in to comment.