MediaPreviewAdapter.java

  1package eu.siacs.conversations.ui.adapter;
  2
  3import android.app.Activity;
  4import android.content.res.Resources;
  5import android.databinding.DataBindingUtil;
  6import android.graphics.Bitmap;
  7import android.graphics.drawable.BitmapDrawable;
  8import android.graphics.drawable.Drawable;
  9import android.net.Uri;
 10import android.os.AsyncTask;
 11import android.support.annotation.NonNull;
 12import android.support.v7.widget.RecyclerView;
 13import android.view.LayoutInflater;
 14import android.view.View;
 15import android.view.ViewGroup;
 16import android.widget.ImageView;
 17
 18import java.lang.ref.WeakReference;
 19import java.util.ArrayList;
 20import java.util.List;
 21import java.util.concurrent.RejectedExecutionException;
 22
 23import eu.siacs.conversations.R;
 24import eu.siacs.conversations.databinding.MediaPreviewBinding;
 25import eu.siacs.conversations.entities.Conversation;
 26import eu.siacs.conversations.ui.ConversationFragment;
 27import eu.siacs.conversations.ui.XmppActivity;
 28import eu.siacs.conversations.ui.util.Attachment;
 29import eu.siacs.conversations.utils.UIHelper;
 30
 31public class MediaPreviewAdapter extends RecyclerView.Adapter<MediaPreviewAdapter.MediaPreviewViewHolder> {
 32
 33    private final List<Attachment> mediaPreviews = new ArrayList<>();
 34
 35    private final ConversationFragment conversationFragment;
 36
 37    public MediaPreviewAdapter(ConversationFragment fragment) {
 38        this.conversationFragment = fragment;
 39    }
 40
 41    @NonNull
 42    @Override
 43    public MediaPreviewViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
 44        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
 45        MediaPreviewBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.media_preview, parent, false);
 46        return new MediaPreviewViewHolder(binding);
 47    }
 48
 49    @Override
 50    public void onBindViewHolder(@NonNull MediaPreviewViewHolder holder, int position) {
 51        final Attachment attachment = mediaPreviews.get(position);
 52        loadPreview(attachment, holder.binding.mediaPreview);
 53        holder.binding.deleteButton.setOnClickListener(v -> {
 54            int pos = mediaPreviews.indexOf(attachment);
 55            mediaPreviews.remove(pos);
 56            notifyItemRemoved(pos);
 57            conversationFragment.toggleInputMethod();
 58        });
 59    }
 60
 61    public void addMediaPreviews(List<Attachment> attachments) {
 62        this.mediaPreviews.addAll(attachments);
 63        notifyDataSetChanged();
 64    }
 65
 66    private void loadPreview(Attachment attachment, ImageView imageView) {
 67        if (cancelPotentialWork(attachment, imageView)) {
 68            XmppActivity activity = (XmppActivity) conversationFragment.getActivity();
 69            final Bitmap bm = activity.xmppConnectionService.getFileBackend().getPreviewForUri(attachment,Math.round(activity.getResources().getDimension(R.dimen.media_preview_size)),true);
 70            if (bm != null) {
 71                cancelPotentialWork(attachment, imageView);
 72                imageView.setImageBitmap(bm);
 73                imageView.setBackgroundColor(0x00000000);
 74            } else {
 75                imageView.setImageDrawable(null);
 76                final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
 77                final AsyncDrawable asyncDrawable = new AsyncDrawable(conversationFragment.getActivity().getResources(), null, task);
 78                imageView.setImageDrawable(asyncDrawable);
 79                try {
 80                    task.execute(attachment);
 81                } catch (final RejectedExecutionException ignored) {
 82                }
 83            }
 84        }
 85    }
 86
 87    private static boolean cancelPotentialWork(Attachment attachment, ImageView imageView) {
 88        final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
 89
 90        if (bitmapWorkerTask != null) {
 91            final Attachment oldAttachment = bitmapWorkerTask.attachment;
 92            if (oldAttachment == null || !oldAttachment.equals(attachment)) {
 93                bitmapWorkerTask.cancel(true);
 94            } else {
 95                return false;
 96            }
 97        }
 98        return true;
 99    }
100
101    private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
102        if (imageView != null) {
103            final Drawable drawable = imageView.getDrawable();
104            if (drawable instanceof AsyncDrawable) {
105                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
106                return asyncDrawable.getBitmapWorkerTask();
107            }
108        }
109        return null;
110    }
111
112    @Override
113    public int getItemCount() {
114        return mediaPreviews.size();
115    }
116
117    public boolean hasAttachments() {
118        return mediaPreviews.size() > 0;
119    }
120
121    public List<Attachment> getAttachments() {
122        return mediaPreviews;
123    }
124
125    class MediaPreviewViewHolder extends RecyclerView.ViewHolder {
126
127        private final MediaPreviewBinding binding;
128
129        MediaPreviewViewHolder(MediaPreviewBinding binding) {
130            super(binding.getRoot());
131            this.binding = binding;
132        }
133    }
134
135    static class AsyncDrawable extends BitmapDrawable {
136        private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
137
138        AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
139            super(res, bitmap);
140            bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
141        }
142
143        BitmapWorkerTask getBitmapWorkerTask() {
144            return bitmapWorkerTaskReference.get();
145        }
146    }
147
148    class BitmapWorkerTask extends AsyncTask<Attachment, Void, Bitmap> {
149        private final WeakReference<ImageView> imageViewReference;
150        private Attachment attachment = null;
151
152        BitmapWorkerTask(ImageView imageView) {
153            imageViewReference = new WeakReference<>(imageView);
154        }
155
156        @Override
157        protected Bitmap doInBackground(Attachment... params) {
158            Activity activity = conversationFragment.getActivity();
159            if (activity instanceof XmppActivity) {
160                final XmppActivity xmppActivity = (XmppActivity) activity;
161                this.attachment = params[0];
162                return xmppActivity.xmppConnectionService.getFileBackend().getPreviewForUri(this.attachment, Math.round(xmppActivity.getResources().getDimension(R.dimen.media_preview_size)), false);
163            } else {
164                return null;
165            }
166        }
167
168        @Override
169        protected void onPostExecute(Bitmap bitmap) {
170            if (bitmap != null && !isCancelled()) {
171                final ImageView imageView = imageViewReference.get();
172                if (imageView != null) {
173                    imageView.setImageBitmap(bitmap);
174                    imageView.setBackgroundColor(0x00000000);
175                }
176            }
177        }
178    }
179}