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

Commit 3d3a15c4 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Don't use avater as stream photo placeholder

Bug 5230226

Change-Id: I084676f2322c4071b938f3925471f3128cb6f10d
parent fad0b4b3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -74,4 +74,6 @@
    <!--  Color of the vertical stripe that goes on the left of a block quote inside a stream item -->
    <color name="stream_item_stripe_color">#CCCCCC</color>

    <!-- Color of image view placeholder. -->
    <color name="image_placeholder">#DDDDDD</color>
</resources>
+77 −15
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.Handler.Callback;
@@ -67,6 +69,35 @@ public abstract class ContactPhotoManager {
        return R.drawable.ic_contact_picture_holo_light;
    }

    public static abstract class DefaultImageProvider {
        public abstract void applyDefaultImage(ImageView view, boolean hires, boolean darkTheme);
    }

    private static class AvatarDefaultImageProvider extends DefaultImageProvider {
        @Override
        public void applyDefaultImage(ImageView view, boolean hires, boolean darkTheme) {
            view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
        }
    }

    private static class BlankDefaultImageProvider extends DefaultImageProvider {
        private static Drawable sDrawable;

        @Override
        public void applyDefaultImage(ImageView view, boolean hires, boolean darkTheme) {
            if (sDrawable == null) {
                Context context = view.getContext();
                sDrawable = new ColorDrawable(context.getResources().getColor(
                        R.color.image_placeholder));
            }
            view.setImageDrawable(sDrawable);
        }
    }

    public static final DefaultImageProvider DEFAULT_AVATER = new AvatarDefaultImageProvider();

    public static final DefaultImageProvider DEFAULT_BLANK = new BlankDefaultImageProvider();

    /**
     * Requests the singleton instance of {@link AccountTypeManager} with data bound from
     * the available authenticators. This method can safely be called from the UI thread.
@@ -91,14 +122,32 @@ public abstract class ContactPhotoManager {
     * it is displayed immediately.  Otherwise a request is sent to load the photo
     * from the database.
     */
    public abstract void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme);
    public abstract void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme,
            DefaultImageProvider defaultProvider);

    /**
     * Calls {@link #loadPhoto(ImageView, long, boolean, boolean, DefaultImageProvider)} with
     * {@link #DEFAULT_AVATER}.
     */
    public final void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme) {
        loadPhoto(view, photoId, hires, darkTheme, DEFAULT_AVATER);
    }

    /**
     * Load photo into the supplied image view.  If the photo is already cached,
     * it is displayed immediately.  Otherwise a request is sent to load the photo
     * from the location specified by the URI.
     */
    public abstract void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme);
    public abstract void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme,
            DefaultImageProvider defaultProvider);

    /**
     * Calls {@link #loadPhoto(ImageView, Uri, boolean, boolean, DefaultImageProvider)} with
     * {@link #DEFAULT_AVATER}.
     */
    public final void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme) {
        loadPhoto(view, photoUri, hires, darkTheme, DEFAULT_AVATER);
    }

    /**
     * Remove photo from the supplied image view. This also cancels current pending load request
@@ -236,24 +285,28 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback {
    }

    @Override
    public void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme) {
    public void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme,
            DefaultImageProvider defaultProvider) {
        if (photoId == 0) {
            // No photo is needed
            view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
            defaultProvider.applyDefaultImage(view, hires, darkTheme);
            mPendingRequests.remove(view);
        } else {
            loadPhotoByIdOrUri(view, Request.createFromId(photoId, hires, darkTheme));
            loadPhotoByIdOrUri(view, Request.createFromId(photoId, hires, darkTheme,
                    defaultProvider));
        }
    }

    @Override
    public void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme) {
    public void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme,
            DefaultImageProvider defaultProvider) {
        if (photoUri == null) {
            // No photo is needed
            view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
            defaultProvider.applyDefaultImage(view, hires, darkTheme);
            mPendingRequests.remove(view);
        } else {
            loadPhotoByIdOrUri(view, Request.createFromUri(photoUri, hires, darkTheme));
            loadPhotoByIdOrUri(view, Request.createFromUri(photoUri, hires, darkTheme,
                    defaultProvider));
        }
    }

@@ -292,12 +345,12 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback {
        BitmapHolder holder = mBitmapHolderCache.get(request.getKey());
        if (holder == null) {
            // The bitmap has not been loaded - should display the placeholder image.
            view.setImageResource(getDefaultAvatarResId(request.isHires(), request.isDarkTheme()));
            request.applyDefaultImage(view);
            return false;
        }

        if (holder.bytes == null) {
            view.setImageResource(getDefaultAvatarResId(request.isHires(), request.isDarkTheme()));
            request.applyDefaultImage(view);
            return holder.fresh;
        }

@@ -791,20 +844,25 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback {
        private final Uri mUri;
        private final boolean mDarkTheme;
        private final boolean mHires;
        private final DefaultImageProvider mDefaultProvider;

        private Request(long id, Uri uri, boolean hires, boolean darkTheme) {
        private Request(long id, Uri uri, boolean hires, boolean darkTheme,
                DefaultImageProvider defaultProvider) {
            mId = id;
            mUri = uri;
            mDarkTheme = darkTheme;
            mHires = hires;
            mDefaultProvider = defaultProvider;
        }

        public static Request createFromId(long id, boolean hires, boolean darkTheme) {
            return new Request(id, null /* no URI */, hires, darkTheme);
        public static Request createFromId(long id, boolean hires, boolean darkTheme,
                DefaultImageProvider defaultProvider) {
            return new Request(id, null /* no URI */, hires, darkTheme, defaultProvider);
        }

        public static Request createFromUri(Uri uri, boolean hires, boolean darkTheme) {
            return new Request(0 /* no ID */, uri, hires, darkTheme);
        public static Request createFromUri(Uri uri, boolean hires, boolean darkTheme,
                DefaultImageProvider defaultProvider) {
            return new Request(0 /* no ID */, uri, hires, darkTheme, defaultProvider);
        }

        public boolean isDarkTheme() {
@@ -841,5 +899,9 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback {
        public Object getKey() {
            return mUri == null ? mId : mUri;
        }

        public void applyDefaultImage(ImageView view) {
            mDefaultProvider.applyDefaultImage(view, mHires, mDarkTheme);
        }
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -249,7 +249,8 @@ public class ContactDetailDisplayUtils {
        setDataOrHideIfNone(snippet, statusView);
        if (photoUri != null) {
            ContactPhotoManager.getInstance(context).loadPhoto(
                    statusPhotoView, Uri.parse(photoUri), true, false);
                    statusPhotoView, Uri.parse(photoUri), true, false,
                    ContactPhotoManager.DEFAULT_BLANK);
            statusPhotoView.setVisibility(View.VISIBLE);
        } else {
            statusPhotoView.setVisibility(View.GONE);
@@ -339,7 +340,7 @@ public class ContactDetailDisplayUtils {
            pushLayerView.setEnabled(false);
        }
        contactPhotoManager.loadPhoto(imageView, Uri.parse(streamItemPhoto.getPhotoUri()), true,
                false);
                false, ContactPhotoManager.DEFAULT_BLANK);
    }

    @VisibleForTesting
+6 −4
Original line number Diff line number Diff line
@@ -27,13 +27,15 @@ import android.widget.ImageView;
 */
public class MockContactPhotoManager extends ContactPhotoManager {
    @Override
    public void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme) {
        view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
    public void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme,
            DefaultImageProvider defaultProvider) {
        defaultProvider.applyDefaultImage(view, hires, darkTheme);
    }

    @Override
    public void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme) {
        view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
    public void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme,
            DefaultImageProvider defaultProvider) {
        defaultProvider.applyDefaultImage(view, hires, darkTheme);
    }

    @Override