From 83600087e15021acd07cc867071b4538cf61844f Mon Sep 17 00:00:00 2001 From: Jacoco <63549689+Jacocococo@users.noreply.github.com> Date: Sun, 28 May 2023 14:44:23 +0200 Subject: [PATCH] Fix images being stretched on Pleroma (#522) Closes sk22#488 * Update image bounds after load when metadata is null * Fix broken image layout in some scenarios * Transition when image dimensions update * Replace blurhash with accent color on Pleroma * fall back to solid color regardless of server * use fragment's context instead of passing it down --------- Co-authored-by: sk --- .../fragments/BaseStatusListFragment.java | 8 ++++++ .../android/ui/BetterItemAnimator.java | 13 +++++++-- .../MediaGridStatusDisplayItem.java | 28 +++++++++++++++++-- .../ui/displayitems/StatusDisplayItem.java | 10 +++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java index 29e39e38d..71a0009a5 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java @@ -551,6 +551,14 @@ public abstract class BaseStatusListFragment exten } } + public void onImageUpdated(MediaGridStatusDisplayItem.Holder holder, int index) { + holder.rebind(); + MediaGridStatusDisplayItem.Holder mediaGrid = findHolderOfType(holder.getItemID(), MediaGridStatusDisplayItem.Holder.class); + if(mediaGrid!=null){ + adapter.notifyItemChanged(mediaGrid.getAbsoluteAdapterPosition()); + } + } + public void onGapClick(GapStatusDisplayItem.Holder item){} public void onWarningClick(WarningFilteredStatusDisplayItem.Holder warning){ diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/BetterItemAnimator.java b/mastodon/src/main/java/org/joinmastodon/android/ui/BetterItemAnimator.java index cbdf7d8a3..0bd6afa1f 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/BetterItemAnimator.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/BetterItemAnimator.java @@ -18,13 +18,15 @@ package org.joinmastodon.android.ui; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; -import android.animation.ValueAnimator; import android.view.View; import android.view.ViewPropertyAnimator; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; + +import org.joinmastodon.android.ui.displayitems.MediaGridStatusDisplayItem; + import me.grishka.appkit.utils.CubicBezierInterpolator; import java.util.ArrayList; @@ -358,7 +360,14 @@ public class BetterItemAnimator extends SimpleItemAnimator{ mChangeAnimations.add(changeInfo.oldHolder); oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); - oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() { + float alpha = 0; + if (holder instanceof MediaGridStatusDisplayItem.Holder mediaItemHolder) { + if (mediaItemHolder.isSizeUpdating()) { + alpha = 1; // Image will flicker out and then in if alpha is 0 + mediaItemHolder.sizeUpdated(); + } + } + oldViewAnim.alpha(alpha).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animator) { dispatchChangeStarting(changeInfo.oldHolder, true); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/MediaGridStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/MediaGridStatusDisplayItem.java index 0c5683b3a..18a21af39 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/MediaGridStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/MediaGridStatusDisplayItem.java @@ -7,6 +7,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.view.View; @@ -17,7 +18,6 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; -import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.R; import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.model.Attachment; @@ -40,7 +40,7 @@ import me.grishka.appkit.utils.CubicBezierInterpolator; public class MediaGridStatusDisplayItem extends StatusDisplayItem{ private static final String TAG="MediaGridDisplayItem"; - private final PhotoLayoutHelper.TiledLayoutResult tiledLayout; + private PhotoLayoutHelper.TiledLayoutResult tiledLayout; private final TypedObjectPool viewPool; private final List attachments; private final ArrayList requests=new ArrayList<>(); @@ -98,6 +98,8 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{ private int altTextIndex=-1; private Animator altTextAnimator; + private boolean sizeUpdating = false; + public Holder(Activity activity, ViewGroup parent){ super(new FrameLayoutThatOnlyMeasuresFirstChild(activity)); wrapper=(FrameLayout)itemView; @@ -126,6 +128,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{ } layout.removeAllViews(); controllers.clear(); + int i=0; for(Attachment att:item.attachments){ MediaAttachmentViewController c=item.viewPool.obtain(switch(att.type){ @@ -158,6 +161,19 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{ @Override public void setImage(int index, Drawable drawable){ + Rect bounds=drawable.getBounds(); + drawable.setBounds(bounds.left, bounds.top, bounds.left+drawable.getIntrinsicWidth(), bounds.top+drawable.getIntrinsicHeight()); + if(item.attachments.get(index).meta==null){ + Attachment.Metadata metadata = new Attachment.Metadata(); + metadata.width=drawable.getIntrinsicWidth(); + metadata.height=drawable.getIntrinsicHeight(); + item.attachments.get(index).meta=metadata; + + item.tiledLayout=PhotoLayoutHelper.processThumbs(item.attachments); + sizeUpdating = true; + item.parentFragment.onImageUpdated(this, index); + } + controllers.get(index).setImage(drawable); } @@ -314,5 +330,13 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{ layout.setClipChildren(clip); wrapper.setClipChildren(clip); } + + public boolean isSizeUpdating() { + return sizeUpdating; + } + + public void sizeUpdated() { + sizeUpdating = false; + } } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java index 6932173bc..99de1e3b7 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java @@ -2,6 +2,7 @@ package org.joinmastodon.android.ui.displayitems; import android.app.Activity; import android.content.Context; +import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -9,6 +10,7 @@ import android.view.ViewGroup; import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.R; +import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.HashtagTimelineFragment; @@ -20,12 +22,14 @@ import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.DisplayItemsParent; import org.joinmastodon.android.model.Filter; +import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Poll; import org.joinmastodon.android.model.ScheduledStatus; import org.joinmastodon.android.model.Status; import org.joinmastodon.android.ui.PhotoLayoutHelper; import org.joinmastodon.android.ui.text.HtmlParser; +import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.utils.StatusFilterPredicate; import org.parceler.Parcels; @@ -173,6 +177,12 @@ public abstract class StatusDisplayItem{ .filter(att->att.type.isImage() && !att.type.equals(Attachment.Type.UNKNOWN)) .collect(Collectors.toList()); if(!imageAttachments.isEmpty()){ + int color = UiUtils.getThemeColor(fragment.getContext(), R.attr.colorAccentLightest); + for (Attachment att : imageAttachments) { + if (att.blurhashPlaceholder == null) { + att.blurhashPlaceholder = new ColorDrawable(color); + } + } PhotoLayoutHelper.TiledLayoutResult layout=PhotoLayoutHelper.processThumbs(imageAttachments); items.add(new MediaGridStatusDisplayItem(parentID, fragment, layout, imageAttachments, statusForContent)); }