ListItemAdapter.java

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