-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[HOLD for payment 2023-02-20] [$2000] Android - Attachment- User seen frame when attaching picture #14448
Comments
reviewing now |
Using browserstack I believe I could create (hard to take photo though on the app) |
Job added to Upwork: https://www.upwork.com/jobs/~01ddb836bc6b1f8022 |
Current assignee @dylanexpensify is eligible for the External assigner, not assigning anyone new. |
Triggered auto assignment to Contributor-plus team member for initial proposal review - @thesahindia ( |
Triggered auto assignment to @mountiny ( |
RCA:the issue comes from wrong image size calculation in App/src/components/ThumbnailImage.js Line 55 in 142fbba
Vertical images doesn't get rotated on Android phones - they are still horizontal images with exif orientation flag set. So RNImage.getSize returns width > height for vertical images and doesn't know anything about rotation Proposal:We could:
|
Proposal RCA This issue comes from
FastImageViewWithUrl.java requestManager
.as(Size.class)
.apply(new RequestOptions()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.DATA))
.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
);
}
}); BitmapSizeDecoder.java public Resource<BitmapFactory.Options> decode(@NonNull File source, int width, int height, @NonNull Options options) throws IOException {
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(source.getAbsolutePath(), bitmapOptions);
int orientation = Integer.parseInt(new ExifInterface(source.getAbsolutePath()).getAttribute(ExifInterface.TAG_ORIENTATION));
if (orientation == ExifInterface.ORIENTATION_ROTATE_90 || orientation == ExifInterface.ORIENTATION_ROTATE_270) {
int outHeight = bitmapOptions.outHeight;
int outWidth = bitmapOptions.outWidth;
bitmapOptions.outHeight = outWidth;
bitmapOptions.outWidth = outHeight;
}
return new SimpleResource(bitmapOptions);
} If you want to verify the solution, you can just apply the following diff to Click mediff --git a/patches/react-native-fast-image+8.6.3.patch b/patches/react-native-fast-image+8.6.3.patch
index fc7e59c17c..b07bbc1d74 100644
--- a/patches/react-native-fast-image+8.6.3.patch
+++ b/patches/react-native-fast-image+8.6.3.patch
@@ -1,12 +1,13 @@
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..03ad017
+index 0000000..5614e4f
--- /dev/null
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/BitmapSizeDecoder.java
-@@ -0,0 +1,31 @@
+@@ -0,0 +1,39 @@
+package com.dylanvann.fastimage;
+
+import android.graphics.BitmapFactory;
++import android.media.ExifInterface;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
@@ -16,22 +17,29 @@ index 0000000..03ad017
+import com.bumptech.glide.load.engine.Resource;
+import com.bumptech.glide.load.resource.SimpleResource;
+
++import java.io.File;
+import java.io.IOException;
-+import java.io.InputStream;
+
-+public class BitmapSizeDecoder implements ResourceDecoder<InputStream, BitmapFactory.Options> {
++public class BitmapSizeDecoder implements ResourceDecoder<File, BitmapFactory.Options> {
+
+ @Override
-+ public boolean handles(@NonNull InputStream source, @NonNull Options options) throws IOException {
++ public boolean handles(@NonNull File 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 {
++ public Resource<BitmapFactory.Options> decode(@NonNull File 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.decodeFile(source.getAbsolutePath(), bitmapOptions);
++ int orientation = Integer.parseInt(new ExifInterface(source.getAbsolutePath()).getAttribute(ExifInterface.TAG_ORIENTATION));
++ if (orientation == ExifInterface.ORIENTATION_ROTATE_90 || orientation == ExifInterface.ORIENTATION_ROTATE_270) {
++ int outHeight = bitmapOptions.outHeight;
++ int outWidth = bitmapOptions.outWidth;
++ bitmapOptions.outHeight = outWidth;
++ bitmapOptions.outWidth = outHeight;
++ }
+ return new SimpleResource(bitmapOptions);
+ }
+}
@@ -67,7 +75,7 @@ index 0000000..7d208d1
+}
\ 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
+index 811292a..dcfb413 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;
@@ -78,12 +86,20 @@ index 811292a..f60b87c 100644
import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
-@@ -47,6 +48,9 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
+@@ -11,6 +12,7 @@ import com.bumptech.glide.load.model.GlideUrl;
+ import com.bumptech.glide.module.LibraryGlideModule;
+ import com.facebook.react.modules.network.OkHttpClientProvider;
+
++import java.io.File;
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.util.HashMap;
+@@ -47,6 +49,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.prepend(File.class, BitmapFactory.Options.class, new BitmapSizeDecoder());
+ registry.register(BitmapFactory.Options.class, Size.class, new BitmapSizeTranscoder());
}
@@ -115,7 +131,7 @@ index dbeb813..bf8f21c 100644
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
+index 34fcf89..8f6e741 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;
@@ -126,7 +142,7 @@ index 34fcf89..1339f5c 100644
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
-@@ -9,16 +10,24 @@ import android.graphics.drawable.Drawable;
+@@ -9,16 +10,26 @@ import android.graphics.drawable.Drawable;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
@@ -134,10 +150,12 @@ index 34fcf89..1339f5c 100644
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.RequestManager;
+import com.bumptech.glide.load.DataSource;
++import com.bumptech.glide.load.engine.DiskCacheStrategy;
+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.RequestOptions;
+import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.target.Target;
+import com.bumptech.glide.request.transition.Transition;
@@ -151,7 +169,7 @@ index 34fcf89..1339f5c 100644
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-@@ -124,9 +133,34 @@ class FastImageViewWithUrl extends AppCompatImageView {
+@@ -124,9 +135,34 @@ class FastImageViewWithUrl extends AppCompatImageView {
RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
int viewId = this.getId();
@@ -189,7 +207,7 @@ index 34fcf89..1339f5c 100644
}
if (requestManager != null) {
-@@ -148,6 +182,25 @@ class FastImageViewWithUrl extends AppCompatImageView {
+@@ -148,6 +184,28 @@ class FastImageViewWithUrl extends AppCompatImageView {
builder.listener(new FastImageRequestListener(key));
builder.into(this);
@@ -199,7 +217,10 @@ index 34fcf89..1339f5c 100644
+ int viewId = this.getId();
+ requestManager
+ .as(Size.class)
-+ .load(imageSource == null ? null : imageSource.getSourceForLoad())
++ .apply(new RequestOptions()
++ .skipMemoryCache(true)
++ .diskCacheStrategy(DiskCacheStrategy.DATA))
++ .load(imageSource == null ? null : imageSource.getUri())
+ .into(new SimpleTarget<Size>() {
+ @Override
+ public void onResourceReady(@NonNull Size resource, @Nullable Transition<? super Size> transition) { |
What's the point of using File instead of input stream? ExifInterface works with InputStream as well: https://android.googlesource.com/platform/frameworks/base/+/master/media/java/android/media/ExifInterface.java#1590 |
Hey @alexxxwork , thanks for looking into it. It's mainly because the File constructor API has wider sdk version support than the newer InputStream constructor. You can check the API level and the |
Not overdue, waiting to review proposals cc @thesahindia |
I am not familiar with the code here, so I think we should assign a new C+. |
I can review proposals today |
📣 @0xmiroslav You have been assigned to this job by @mountiny! |
If XML is used, then one or two lines in the View is sufficient: |
working on this today! |
@alexxxwork test steps look great, thank you! |
posted rt proposal. @mountiny mind reviewing? https://expensify.slack.com/archives/C01SKUP7QR0/p1677069041526679 |
Alright, we're good here on RT steps |
@0xmiroslav can you apply to the job please? |
@dylanexpensify thank you. Does this issue eligible 50% bonus for merging whithin 3 business days?
|
Yes it will! |
I'll add the bonus during the payout 😄 |
Payment sent, contract closed @alexxxwork - thanks for your help! |
|
@0xmiroslav ah, I missed that comment. Can you confirm if we agreed internally on that course of action? |
Ok, so it seems $2K (inclusive of bonus) to @alexxxwork then? And $1K to @eh2077? |
yes, @mountiny can you please confirm? |
Yep, agreed, lets do that! |
@dylanexpensify oh, sorry. Didn't get it that this agreement already included time bonus. Should we rollback upwork transaction now? |
@alexxxwork no worries, this is on me! I'm going to request a refund from you of $1K! Thanks for confirming @mountiny ! |
@alexxxwork sent refund request! |
@dylanexpensify accepted 🙌 |
Hi @dylanexpensify, I have applied it, thanks! |
@eh2077 offer sent! |
all payments now done! thanks everyone! |
@dylanexpensify accepted the offer, thanks! |
payment already sent @eh2077 ! 🙌 |
If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!
Action Performed:
Expected Result:
Picture should be displayed in full size
Actual Result:
User seen frame when attaching picture
Workaround:
Unknown
Platforms:
Which of our officially supported platforms is this issue occurring on?
Version Number: 1.2.57.2
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos: Any additional supporting documentation
Screen_Recording_20230120_154219_New.Expensify.mp4
Expensify/Expensify Issue URL:
Issue reported by: Applause - Internal Team
Slack conversation:
View all open jobs on GitHub
Upwork Automation - Do Not Edit
The text was updated successfully, but these errors were encountered: