Show an overlay on image attachments that failed to load
This commit is contained in:
parent
f5961c8077
commit
eda1526830
|
@ -700,6 +700,10 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||||
anim.start();
|
anim.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void retryFailedImages(){
|
||||||
|
imgLoader.retryFailedRequests();
|
||||||
|
}
|
||||||
|
|
||||||
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
|
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
|
||||||
|
|
||||||
public DisplayItemsAdapter(){
|
public DisplayItemsAdapter(){
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
import android.graphics.drawable.LayerDrawable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -110,6 +111,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
||||||
private static final ColorDrawable drawableForWhenThereIsNoBlurhash=new ColorDrawable(0xffffffff);
|
private static final ColorDrawable drawableForWhenThereIsNoBlurhash=new ColorDrawable(0xffffffff);
|
||||||
private final TextView hideSensitiveButton;
|
private final TextView hideSensitiveButton;
|
||||||
private final TextView sensitiveText;
|
private final TextView sensitiveText;
|
||||||
|
private boolean thereAreFailedImages;
|
||||||
|
|
||||||
public Holder(Activity activity, ViewGroup parent){
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
super(new FrameLayoutThatOnlyMeasuresFirstChild(activity));
|
super(new FrameLayoutThatOnlyMeasuresFirstChild(activity));
|
||||||
|
@ -143,6 +145,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(MediaGridStatusDisplayItem item){
|
public void onBind(MediaGridStatusDisplayItem item){
|
||||||
|
thereAreFailedImages=false;
|
||||||
wrapper.setPadding(0, 0, 0, item.inset ? 0 : V.dp(8));
|
wrapper.setPadding(0, 0, 0, item.inset ? 0 : V.dp(8));
|
||||||
|
|
||||||
layout.setTiledLayout(item.tiledLayout);
|
layout.setTiledLayout(item.tiledLayout);
|
||||||
|
@ -220,9 +223,23 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
||||||
controllers.get(index).clearImage();
|
controllers.get(index).clearImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onImageLoadingFailed(int index, Throwable error){
|
||||||
|
controllers.get(index).showFailedOverlay();
|
||||||
|
thereAreFailedImages=true;
|
||||||
|
}
|
||||||
|
|
||||||
private void onViewClick(View v){
|
private void onViewClick(View v){
|
||||||
int index=(Integer)v.getTag();
|
int index=(Integer)v.getTag();
|
||||||
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, index, this);
|
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, index, this);
|
||||||
|
if(thereAreFailedImages){
|
||||||
|
for(MediaAttachmentViewController controller:controllers){
|
||||||
|
if(controller.isFailedOverlayShown()){
|
||||||
|
controller.clearImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item.parentFragment.retryFailedImages();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAltTextClick(View v){
|
private void onAltTextClick(View v){
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.view.ViewGroup;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.fragments.StatusListFragment;
|
|
||||||
import org.joinmastodon.android.fragments.ThreadFragment;
|
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.model.Attachment;
|
import org.joinmastodon.android.model.Attachment;
|
||||||
|
@ -35,7 +34,7 @@ import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
|
|
||||||
public abstract class StatusDisplayItem{
|
public abstract class StatusDisplayItem{
|
||||||
public final String parentID;
|
public final String parentID;
|
||||||
public final BaseStatusListFragment parentFragment;
|
public final BaseStatusListFragment<?> parentFragment;
|
||||||
public boolean inset;
|
public boolean inset;
|
||||||
public int index;
|
public int index;
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ public abstract class StatusDisplayItem{
|
||||||
public static final int FLAG_MEDIA_FORCE_HIDDEN=1 << 3;
|
public static final int FLAG_MEDIA_FORCE_HIDDEN=1 << 3;
|
||||||
public static final int FLAG_NO_HEADER=1 << 4;
|
public static final int FLAG_NO_HEADER=1 << 4;
|
||||||
|
|
||||||
public StatusDisplayItem(String parentID, BaseStatusListFragment parentFragment){
|
public StatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment){
|
||||||
this.parentID=parentID;
|
this.parentID=parentID;
|
||||||
this.parentFragment=parentFragment;
|
this.parentFragment=parentFragment;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ import org.joinmastodon.android.ui.displayitems.MediaGridStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.drawables.BlurhashCrossfadeDrawable;
|
import org.joinmastodon.android.ui.drawables.BlurhashCrossfadeDrawable;
|
||||||
import org.joinmastodon.android.ui.drawables.PlayIconDrawable;
|
import org.joinmastodon.android.ui.drawables.PlayIconDrawable;
|
||||||
|
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
public class MediaAttachmentViewController{
|
public class MediaAttachmentViewController{
|
||||||
public final View view;
|
public final View view;
|
||||||
public final MediaGridStatusDisplayItem.GridItemType type;
|
public final MediaGridStatusDisplayItem.GridItemType type;
|
||||||
|
@ -23,6 +25,8 @@ public class MediaAttachmentViewController{
|
||||||
public final View altButton;
|
public final View altButton;
|
||||||
public final TextView duration;
|
public final TextView duration;
|
||||||
public final View playButton;
|
public final View playButton;
|
||||||
|
public final View failedOverlay;
|
||||||
|
public final View failedText;
|
||||||
private BlurhashCrossfadeDrawable crossfadeDrawable=new BlurhashCrossfadeDrawable();
|
private BlurhashCrossfadeDrawable crossfadeDrawable=new BlurhashCrossfadeDrawable();
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private boolean didClear;
|
private boolean didClear;
|
||||||
|
@ -39,6 +43,8 @@ public class MediaAttachmentViewController{
|
||||||
altButton=view.findViewById(R.id.alt_button);
|
altButton=view.findViewById(R.id.alt_button);
|
||||||
duration=view.findViewById(R.id.duration);
|
duration=view.findViewById(R.id.duration);
|
||||||
playButton=view.findViewById(R.id.play_button);
|
playButton=view.findViewById(R.id.play_button);
|
||||||
|
failedOverlay=view.findViewById(R.id.failed_overlay);
|
||||||
|
failedText=view.findViewById(R.id.failed_text);
|
||||||
this.type=type;
|
this.type=type;
|
||||||
this.context=context;
|
this.context=context;
|
||||||
if(playButton!=null){
|
if(playButton!=null){
|
||||||
|
@ -65,6 +71,11 @@ public class MediaAttachmentViewController{
|
||||||
duration.setText(UiUtils.formatMediaDuration((int)attachment.getDuration()));
|
duration.setText(UiUtils.formatMediaDuration((int)attachment.getDuration()));
|
||||||
}
|
}
|
||||||
didClear=false;
|
didClear=false;
|
||||||
|
if(failedOverlay!=null){
|
||||||
|
V.cancelVisibilityAnimation(failedOverlay);
|
||||||
|
failedOverlay.setVisibility(View.GONE);
|
||||||
|
failedText.setVisibility(status.mediaAttachments.size()>1 ? View.GONE : View.VISIBLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImage(Drawable drawable){
|
public void setImage(Drawable drawable){
|
||||||
|
@ -76,11 +87,27 @@ public class MediaAttachmentViewController{
|
||||||
photo.setImageDrawable(null);
|
photo.setImageDrawable(null);
|
||||||
photo.setImageDrawable(crossfadeDrawable);
|
photo.setImageDrawable(crossfadeDrawable);
|
||||||
}
|
}
|
||||||
|
if(failedOverlay!=null && failedOverlay.getVisibility()!=View.GONE){
|
||||||
|
V.setVisibilityAnimated(failedOverlay, View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearImage(){
|
public void clearImage(){
|
||||||
crossfadeDrawable.setCrossfadeAlpha(1f);
|
crossfadeDrawable.setCrossfadeAlpha(1f);
|
||||||
crossfadeDrawable.setImageDrawable(null);
|
crossfadeDrawable.setImageDrawable(null);
|
||||||
didClear=true;
|
didClear=true;
|
||||||
|
if(failedOverlay!=null && failedOverlay.getVisibility()!=View.GONE){
|
||||||
|
V.setVisibilityAnimated(failedOverlay, View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showFailedOverlay(){
|
||||||
|
if(failedOverlay!=null){
|
||||||
|
V.setVisibilityAnimated(failedOverlay, View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFailedOverlayShown(){
|
||||||
|
return failedOverlay!=null && failedOverlay.getVisibility()!=View.GONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="64dp"
|
||||||
|
android:height="64dp"
|
||||||
|
android:viewportWidth="64"
|
||||||
|
android:viewportHeight="64">
|
||||||
|
<path
|
||||||
|
android:pathData="M28,11L25,15L31,23L25,31L31,39L25,47L28,51H5V11H28Z"
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:fillAlpha="0.4" />
|
||||||
|
<path
|
||||||
|
android:pathData="M2.2,53.8C3,54.6 3.933,55 5,55L31,55L28,51H5V11H28L31,7H5C3.933,7 3,7.4 2.2,8.2C1.4,9 1,9.933 1,11V51C1,52.067 1.4,53 2.2,53.8ZM28.397,35.529L22.733,42.867L16.533,34.4L8.733,44.533H26.85L31,39L28.397,35.529Z"
|
||||||
|
android:fillColor="#000000" />
|
||||||
|
<path
|
||||||
|
android:pathData="M43.449,11.897L39.571,15.052L43.457,24.266L35.7,30.577L39.586,39.791L31.829,46.102L33.772,50.709L50.268,54.821L59.944,16.01L43.449,11.897Z"
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:fillAlpha="0.4" />
|
||||||
|
<path
|
||||||
|
android:pathData="M47.328,8.742L43.449,11.897L59.944,16.01L50.268,54.821L33.772,50.709L35.716,55.316L49.3,58.703C50.335,58.961 51.337,58.798 52.307,58.216C53.277,57.633 53.891,56.824 54.149,55.789L63.826,16.977C64.084,15.942 63.921,14.94 63.339,13.97C62.756,13 61.947,12.387 60.912,12.128L47.328,8.742ZM34.221,44.156L48.274,47.66L41.926,32.611L37.9,35.794L39.586,39.791L34.221,44.156Z"
|
||||||
|
android:fillColor="#000000" />
|
||||||
|
</vector>
|
|
@ -15,4 +15,34 @@
|
||||||
<include layout="@layout/alt_text_badge"
|
<include layout="@layout/alt_text_badge"
|
||||||
android:id="@+id/alt_button"/>
|
android:id="@+id/alt_button"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/failed_overlay"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="#33000000"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:background="@drawable/broken_media"
|
||||||
|
android:backgroundTint="#fff"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/failed_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:minHeight="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="#fff"
|
||||||
|
android:textAppearance="@style/m3_label_medium"
|
||||||
|
android:text="@string/cant_load_image"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -777,4 +777,5 @@
|
||||||
<string name="donation_server_error">We are sorry, an error occurred and we have not been able to process your donation.\n\nPlease retry in a few minutes.</string>
|
<string name="donation_server_error">We are sorry, an error occurred and we have not been able to process your donation.\n\nPlease retry in a few minutes.</string>
|
||||||
<string name="settings_donate">Donate to Mastodon</string>
|
<string name="settings_donate">Donate to Mastodon</string>
|
||||||
<string name="settings_manage_donations">Manage donations</string>
|
<string name="settings_manage_donations">Manage donations</string>
|
||||||
|
<string name="cant_load_image">Couldn’t load image</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue