1package eu.siacs.conversations.ui.adapter;
2
3import android.content.Context;
4import android.content.SharedPreferences;
5import android.content.res.Resources;
6import android.databinding.DataBindingUtil;
7import android.graphics.Bitmap;
8import android.graphics.drawable.BitmapDrawable;
9import android.graphics.drawable.Drawable;
10import android.os.AsyncTask;
11import android.preference.PreferenceManager;
12import android.view.LayoutInflater;
13import android.view.View;
14import android.view.ViewGroup;
15import android.widget.ArrayAdapter;
16import android.widget.ImageView;
17import android.widget.TextView;
18
19import com.wefika.flowlayout.FlowLayout;
20
21import java.lang.ref.WeakReference;
22import java.util.List;
23import java.util.concurrent.RejectedExecutionException;
24
25import eu.siacs.conversations.R;
26import eu.siacs.conversations.databinding.ContactBinding;
27import eu.siacs.conversations.entities.ListItem;
28import eu.siacs.conversations.ui.SettingsActivity;
29import eu.siacs.conversations.ui.XmppActivity;
30import eu.siacs.conversations.utils.EmojiWrapper;
31import eu.siacs.conversations.utils.UIHelper;
32
33public class ListItemAdapter extends ArrayAdapter<ListItem> {
34
35 protected XmppActivity activity;
36 protected boolean showDynamicTags = false;
37 private OnTagClickedListener mOnTagClickedListener = null;
38 private View.OnClickListener onTagTvClick = new View.OnClickListener() {
39 @Override
40 public void onClick(View view) {
41 if (view instanceof TextView && mOnTagClickedListener != null) {
42 TextView tv = (TextView) view;
43 final String tag = tv.getText().toString();
44 mOnTagClickedListener.onTagClicked(tag);
45 }
46 }
47 };
48
49 public ListItemAdapter(XmppActivity activity, List<ListItem> objects) {
50 super(activity, 0, objects);
51 this.activity = activity;
52 }
53
54 public static boolean cancelPotentialWork(ListItem item, ImageView imageView) {
55 final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
56
57 if (bitmapWorkerTask != null) {
58 final ListItem oldItem = bitmapWorkerTask.item;
59 if (oldItem == null || item != oldItem) {
60 bitmapWorkerTask.cancel(true);
61 } else {
62 return false;
63 }
64 }
65 return true;
66 }
67
68 private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
69 if (imageView != null) {
70 final Drawable drawable = imageView.getDrawable();
71 if (drawable instanceof AsyncDrawable) {
72 final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
73 return asyncDrawable.getBitmapWorkerTask();
74 }
75 }
76 return null;
77 }
78
79 public void refreshSettings() {
80 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
81 this.showDynamicTags = preferences.getBoolean(SettingsActivity.SHOW_DYNAMIC_TAGS, false);
82 }
83
84 @Override
85 public View getView(int position, View view, ViewGroup parent) {
86 LayoutInflater inflater = activity.getLayoutInflater();
87 ListItem item = getItem(position);
88 ViewHolder viewHolder;
89 if (view == null) {
90 ContactBinding binding = DataBindingUtil.inflate(inflater,R.layout.contact,parent,false);
91 viewHolder = ViewHolder.get(binding);
92 view = binding.getRoot();
93 } else {
94 viewHolder = (ViewHolder) view.getTag();
95 }
96
97 List<ListItem.Tag> tags = item.getTags(activity);
98 if (tags.size() == 0 || !this.showDynamicTags) {
99 viewHolder.tags.setVisibility(View.GONE);
100 } else {
101 viewHolder.tags.setVisibility(View.VISIBLE);
102 viewHolder.tags.removeAllViewsInLayout();
103 for (ListItem.Tag tag : tags) {
104 TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag, viewHolder.tags, false);
105 tv.setText(tag.getName());
106 tv.setBackgroundColor(tag.getColor());
107 tv.setOnClickListener(this.onTagTvClick);
108 viewHolder.tags.addView(tv);
109 }
110 }
111 final String jid = item.getDisplayJid();
112 if (jid != null) {
113 viewHolder.jid.setVisibility(View.VISIBLE);
114 viewHolder.jid.setText(jid);
115 } else {
116 viewHolder.jid.setVisibility(View.GONE);
117 }
118 viewHolder.name.setText(EmojiWrapper.transform(item.getDisplayName()));
119 loadAvatar(item, viewHolder.avatar);
120 return view;
121 }
122
123 public void setOnTagClickedListener(OnTagClickedListener listener) {
124 this.mOnTagClickedListener = listener;
125 }
126
127 public void loadAvatar(ListItem item, ImageView imageView) {
128 if (cancelPotentialWork(item, imageView)) {
129 final Bitmap bm = activity.avatarService().get(item, activity.getPixel(48), true);
130 if (bm != null) {
131 cancelPotentialWork(item, imageView);
132 imageView.setImageBitmap(bm);
133 imageView.setBackgroundColor(0x00000000);
134 } else {
135 String seed = item.getJid() != null ? item.getJid().toBareJid().toString() : item.getDisplayName();
136 imageView.setBackgroundColor(UIHelper.getColorForName(seed));
137 imageView.setImageDrawable(null);
138 final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
139 final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
140 imageView.setImageDrawable(asyncDrawable);
141 try {
142 task.execute(item);
143 } catch (final RejectedExecutionException ignored) {
144 }
145 }
146 }
147 }
148
149 public interface OnTagClickedListener {
150 void onTagClicked(String tag);
151 }
152
153 private static class ViewHolder {
154 private TextView name;
155 private TextView jid;
156 private ImageView avatar;
157 private FlowLayout tags;
158
159 private ViewHolder() {
160
161 }
162
163 public static ViewHolder get(ContactBinding binding) {
164 ViewHolder viewHolder = new ViewHolder();
165 viewHolder.name = binding.contactDisplayName;
166 viewHolder.jid = binding.contactJid;
167 viewHolder.avatar = binding.contactPhoto;
168 viewHolder.tags = binding.tags;
169 binding.getRoot().setTag(viewHolder);
170 return viewHolder;
171 }
172 }
173
174 static class AsyncDrawable extends BitmapDrawable {
175 private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
176
177 public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
178 super(res, bitmap);
179 bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
180 }
181
182 public BitmapWorkerTask getBitmapWorkerTask() {
183 return bitmapWorkerTaskReference.get();
184 }
185 }
186
187 class BitmapWorkerTask extends AsyncTask<ListItem, Void, Bitmap> {
188 private final WeakReference<ImageView> imageViewReference;
189 private ListItem item = null;
190
191 public BitmapWorkerTask(ImageView imageView) {
192 imageViewReference = new WeakReference<>(imageView);
193 }
194
195 @Override
196 protected Bitmap doInBackground(ListItem... params) {
197 this.item = params[0];
198 return activity.avatarService().get(this.item, activity.getPixel(48), isCancelled());
199 }
200
201 @Override
202 protected void onPostExecute(Bitmap bitmap) {
203 if (bitmap != null && !isCancelled()) {
204 final ImageView imageView = imageViewReference.get();
205 if (imageView != null) {
206 imageView.setImageBitmap(bitmap);
207 imageView.setBackgroundColor(0x00000000);
208 }
209 }
210 }
211 }
212
213}