1package eu.siacs.conversations.ui.util;
2
3import android.content.Context;
4import android.content.res.Resources;
5import android.graphics.Bitmap;
6import android.graphics.drawable.BitmapDrawable;
7import android.graphics.drawable.Drawable;
8import android.os.AsyncTask;
9import android.widget.ImageView;
10
11import androidx.annotation.DimenRes;
12
13import java.lang.ref.WeakReference;
14import java.util.concurrent.RejectedExecutionException;
15
16import eu.siacs.conversations.R;
17import eu.siacs.conversations.entities.Account;
18import eu.siacs.conversations.services.AvatarService;
19import eu.siacs.conversations.ui.XmppActivity;
20
21public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Bitmap> {
22 private final WeakReference<ImageView> imageViewReference;
23 private AvatarService.Avatarable avatarable = null;
24 private @DimenRes
25 final int size;
26
27 public AvatarWorkerTask(ImageView imageView, @DimenRes int size) {
28 imageViewReference = new WeakReference<>(imageView);
29 this.size = size;
30 }
31
32 @Override
33 protected Bitmap doInBackground(AvatarService.Avatarable... params) {
34 this.avatarable = params[0];
35 final XmppActivity activity = XmppActivity.find(imageViewReference);
36 if (activity == null) {
37 return null;
38 }
39 return activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), isCancelled());
40 }
41
42 @Override
43 protected void onPostExecute(Bitmap bitmap) {
44 if (bitmap != null && !isCancelled()) {
45 final ImageView imageView = imageViewReference.get();
46 if (imageView != null) {
47 imageView.setImageBitmap(bitmap);
48 imageView.setBackgroundColor(0x00000000);
49 }
50 }
51 }
52
53 public static boolean cancelPotentialWork(AvatarService.Avatarable avatarable, ImageView imageView) {
54 final AvatarWorkerTask workerTask = getBitmapWorkerTask(imageView);
55
56 if (workerTask != null) {
57 final AvatarService.Avatarable old= workerTask.avatarable;
58 if (old == null || avatarable != old) {
59 workerTask.cancel(true);
60 } else {
61 return false;
62 }
63 }
64 return true;
65 }
66
67 public static AvatarWorkerTask getBitmapWorkerTask(ImageView imageView) {
68 if (imageView != null) {
69 final Drawable drawable = imageView.getDrawable();
70 if (drawable instanceof AsyncDrawable) {
71 final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
72 return asyncDrawable.getAvatarWorkerTask();
73 }
74 }
75 return null;
76 }
77
78 public static void loadAvatar(final AvatarService.Avatarable avatarable, final ImageView imageView, final @DimenRes int size) {
79 if (cancelPotentialWork(avatarable, imageView)) {
80 final XmppActivity activity = XmppActivity.find(imageView);
81 if (activity == null) {
82 return;
83 }
84 final Bitmap bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true);
85 setContentDescription(avatarable, imageView);
86 if (bm != null) {
87 cancelPotentialWork(avatarable, imageView);
88 imageView.setImageBitmap(bm);
89 imageView.setBackgroundColor(0x00000000);
90 } else {
91 imageView.setBackgroundColor(avatarable.getAvatarBackgroundColor());
92 imageView.setImageDrawable(null);
93 final AvatarWorkerTask task = new AvatarWorkerTask(imageView, size);
94 final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
95 imageView.setImageDrawable(asyncDrawable);
96 try {
97 task.execute(avatarable);
98 } catch (final RejectedExecutionException ignored) {
99 }
100 }
101 }
102 }
103
104 private static void setContentDescription(final AvatarService.Avatarable avatarable, final ImageView imageView) {
105 final Context context = imageView.getContext();
106 if (avatarable instanceof Account) {
107 imageView.setContentDescription(context.getString(R.string.your_avatar));
108 } else {
109 imageView.setContentDescription(context.getString(R.string.avatar_for_x, avatarable.getAvatarName()));
110 }
111 }
112
113 static class AsyncDrawable extends BitmapDrawable {
114 private final WeakReference<AvatarWorkerTask> avatarWorkerTaskReference;
115
116 AsyncDrawable(Resources res, Bitmap bitmap, AvatarWorkerTask workerTask) {
117 super(res, bitmap);
118 avatarWorkerTaskReference = new WeakReference<>(workerTask);
119 }
120
121 AvatarWorkerTask getAvatarWorkerTask() {
122 return avatarWorkerTaskReference.get();
123 }
124 }
125}