1package eu.siacs.conversations.ui.adapter;
2
3import android.content.Context;
4import android.content.SharedPreferences;
5import android.content.res.Resources;
6import android.graphics.Bitmap;
7import android.graphics.drawable.BitmapDrawable;
8import android.graphics.drawable.Drawable;
9import android.os.AsyncTask;
10import android.preference.PreferenceManager;
11import android.view.LayoutInflater;
12import android.view.View;
13import android.view.ViewGroup;
14import android.widget.ArrayAdapter;
15import android.widget.ImageView;
16import android.widget.TextView;
17
18import com.wefika.flowlayout.FlowLayout;
19
20import java.lang.ref.WeakReference;
21import java.util.List;
22import java.util.concurrent.RejectedExecutionException;
23
24import eu.siacs.conversations.R;
25import eu.siacs.conversations.entities.ListItem;
26import eu.siacs.conversations.ui.SettingsActivity;
27import eu.siacs.conversations.ui.XmppActivity;
28import eu.siacs.conversations.utils.UIHelper;
29
30public class ListItemAdapter extends ArrayAdapter<ListItem> {
31
32 protected XmppActivity activity;
33 protected boolean showDynamicTags = false;
34 private View.OnClickListener onTagTvClick = new View.OnClickListener() {
35 @Override
36 public void onClick(View view) {
37 if (view instanceof TextView && mOnTagClickedListener != null) {
38 TextView tv = (TextView) view;
39 final String tag = tv.getText().toString();
40 mOnTagClickedListener.onTagClicked(tag);
41 }
42 }
43 };
44 private OnTagClickedListener mOnTagClickedListener = null;
45
46 public ListItemAdapter(XmppActivity activity, List<ListItem> objects) {
47 super(activity, 0, objects);
48 this.activity = activity;
49 }
50
51 public void refreshSettings() {
52 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
53 this.showDynamicTags = preferences.getBoolean(SettingsActivity.SHOW_DYNAMIC_TAGS,false);
54 }
55
56 @Override
57 public View getView(int position, View view, ViewGroup parent) {
58 LayoutInflater inflater = (LayoutInflater) getContext()
59 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
60 ListItem item = getItem(position);
61 if (view == null) {
62 view = inflater.inflate(R.layout.contact, parent, false);
63 }
64 TextView tvName = (TextView) view.findViewById(R.id.contact_display_name);
65 TextView tvJid = (TextView) view.findViewById(R.id.contact_jid);
66 ImageView picture = (ImageView) view.findViewById(R.id.contact_photo);
67 FlowLayout tagLayout = (FlowLayout) view.findViewById(R.id.tags);
68
69 List<ListItem.Tag> tags = item.getTags(activity);
70 if (tags.size() == 0 || !this.showDynamicTags) {
71 tagLayout.setVisibility(View.GONE);
72 } else {
73 tagLayout.setVisibility(View.VISIBLE);
74 tagLayout.removeAllViewsInLayout();
75 for(ListItem.Tag tag : tags) {
76 TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag,tagLayout,false);
77 tv.setText(tag.getName());
78 tv.setBackgroundColor(tag.getColor());
79 tv.setOnClickListener(this.onTagTvClick);
80 tagLayout.addView(tv);
81 }
82 }
83 final String jid = item.getDisplayJid();
84 if (jid != null) {
85 tvJid.setVisibility(View.VISIBLE);
86 tvJid.setText(jid);
87 } else {
88 tvJid.setVisibility(View.GONE);
89 }
90 tvName.setText(item.getDisplayName());
91 loadAvatar(item,picture);
92 return view;
93 }
94
95 public void setOnTagClickedListener(OnTagClickedListener listener) {
96 this.mOnTagClickedListener = listener;
97 }
98
99 public interface OnTagClickedListener {
100 void onTagClicked(String tag);
101 }
102
103 class BitmapWorkerTask extends AsyncTask<ListItem, Void, Bitmap> {
104 private final WeakReference<ImageView> imageViewReference;
105 private ListItem item = null;
106
107 public BitmapWorkerTask(ImageView imageView) {
108 imageViewReference = new WeakReference<>(imageView);
109 }
110
111 @Override
112 protected Bitmap doInBackground(ListItem... params) {
113 return activity.avatarService().get(params[0], activity.getPixel(48), isCancelled());
114 }
115
116 @Override
117 protected void onPostExecute(Bitmap bitmap) {
118 if (bitmap != null && !isCancelled()) {
119 final ImageView imageView = imageViewReference.get();
120 if (imageView != null) {
121 imageView.setImageBitmap(bitmap);
122 imageView.setBackgroundColor(0x00000000);
123 }
124 }
125 }
126 }
127
128 public void loadAvatar(ListItem item, ImageView imageView) {
129 if (cancelPotentialWork(item, imageView)) {
130 final Bitmap bm = activity.avatarService().get(item,activity.getPixel(48),true);
131 if (bm != null) {
132 cancelPotentialWork(item, imageView);
133 imageView.setImageBitmap(bm);
134 imageView.setBackgroundColor(0x00000000);
135 } else {
136 imageView.setBackgroundColor(UIHelper.getColorForName(item.getDisplayName()));
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 static boolean cancelPotentialWork(ListItem item, ImageView imageView) {
150 final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
151
152 if (bitmapWorkerTask != null) {
153 final ListItem oldItem = bitmapWorkerTask.item;
154 if (oldItem == null || item != oldItem) {
155 bitmapWorkerTask.cancel(true);
156 } else {
157 return false;
158 }
159 }
160 return true;
161 }
162
163 private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
164 if (imageView != null) {
165 final Drawable drawable = imageView.getDrawable();
166 if (drawable instanceof AsyncDrawable) {
167 final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
168 return asyncDrawable.getBitmapWorkerTask();
169 }
170 }
171 return null;
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}