Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5676546c authored by Oli Lan's avatar Oli Lan
Browse files

Add a delay between the photo picker and the crop UI.

This adds a short delay before showing the crop UI after the photo
picker, to allow the photo picker exit animation to complete.

An interaction between the picker exit animation and the crop entry
animation causes visual jank without this delay.

Bug: 224477967
Test: install and exercise UI
Change-Id: Iaae0703617c1a6eb2f0337e7642059d1788be058
parent af4514e5
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -78,6 +78,11 @@ class AvatarPhotoController {
    static final int REQUEST_CODE_TAKE_PHOTO = 1002;
    static final int REQUEST_CODE_CROP_PHOTO = 1003;

    /**
     * Delay to allow the photo picker exit animation to complete before the crop activity opens.
     */
    private static final long DELAY_BEFORE_CROP_MILLIS = 150;

    private static final String IMAGES_DIR = "multi_user";
    private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg";
    private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
@@ -131,13 +136,15 @@ class AvatarPhotoController {
                mAvatarUi.returnUriResult(pictureUri);
                return true;
            case REQUEST_CODE_TAKE_PHOTO:
            case REQUEST_CODE_CHOOSE_PHOTO:
                if (mTakePictureUri.equals(pictureUri)) {
                    cropPhoto(pictureUri);
                } else {
                    copyAndCropPhoto(pictureUri);
                    copyAndCropPhoto(pictureUri, false);
                }
                return true;
            case REQUEST_CODE_CHOOSE_PHOTO:
                copyAndCropPhoto(pictureUri, true);
                return true;
        }
        return false;
    }
@@ -154,7 +161,7 @@ class AvatarPhotoController {
        mAvatarUi.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
    }

    private void copyAndCropPhoto(final Uri pictureUri) {
    private void copyAndCropPhoto(final Uri pictureUri, boolean delayBeforeCrop) {
        try {
            ThreadUtils.postOnBackgroundThread(() -> {
                final ContentResolver cr = mContextInjector.getContentResolver();
@@ -165,11 +172,17 @@ class AvatarPhotoController {
                    Log.w(TAG, "Failed to copy photo", e);
                    return;
                }
                ThreadUtils.postOnMainThread(() -> {
                Runnable cropRunnable = () -> {
                    if (!mAvatarUi.isFinishing()) {
                        cropPhoto(mPreCropPictureUri);
                    }
                });
                };
                if (delayBeforeCrop) {
                    ThreadUtils.postOnMainThreadDelayed(cropRunnable, DELAY_BEFORE_CROP_MILLIS);
                } else {
                    ThreadUtils.postOnMainThread(cropRunnable);
                }

            }).get();
        } catch (InterruptedException | ExecutionException e) {
            Log.e(TAG, "Error performing copy-and-crop", e);
+7 −0
Original line number Diff line number Diff line
@@ -84,6 +84,13 @@ public class ThreadUtils {
        getUiThreadHandler().post(runnable);
    }

    /**
     * Posts the runnable on the main thread with a delay.
     */
    public static void postOnMainThreadDelayed(Runnable runnable, long delayMillis) {
        getUiThreadHandler().postDelayed(runnable, delayMillis);
    }

    private static synchronized ExecutorService getThreadExecutor() {
        if (sThreadExecutor == null) {
            sThreadExecutor = Executors.newFixedThreadPool(