1package eu.siacs.conversations.ui.adapter;
2
3import android.content.Context;
4import android.content.res.Resources;
5import android.graphics.Bitmap;
6import android.graphics.Typeface;
7import android.graphics.drawable.BitmapDrawable;
8import android.graphics.drawable.Drawable;
9import android.os.AsyncTask;
10import android.util.Pair;
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 java.lang.ref.WeakReference;
19import java.util.List;
20import java.util.concurrent.RejectedExecutionException;
21
22import eu.siacs.conversations.R;
23import eu.siacs.conversations.entities.Conversation;
24import eu.siacs.conversations.entities.Message;
25import eu.siacs.conversations.entities.Transferable;
26import eu.siacs.conversations.ui.ConversationActivity;
27import eu.siacs.conversations.ui.XmppActivity;
28import eu.siacs.conversations.utils.UIHelper;
29
30public class ConversationAdapter extends ArrayAdapter<Conversation> {
31
32 private XmppActivity activity;
33
34 public ConversationAdapter(XmppActivity activity,
35 List<Conversation> conversations) {
36 super(activity, 0, conversations);
37 this.activity = activity;
38 }
39
40 @Override
41 public View getView(int position, View view, ViewGroup parent) {
42 if (view == null) {
43 LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
44 view = inflater.inflate(R.layout.conversation_list_row,parent, false);
45 }
46 Conversation conversation = getItem(position);
47 if (this.activity instanceof ConversationActivity) {
48 View swipeableItem = view.findViewById(R.id.swipeable_item);
49 ConversationActivity a = (ConversationActivity) this.activity;
50 int c = a.highlightSelectedConversations() && conversation == a.getSelectedConversation() ? a.getSecondaryBackgroundColor() : a.getPrimaryBackgroundColor();
51 swipeableItem.setBackgroundColor(c);
52 }
53 TextView convName = (TextView) view.findViewById(R.id.conversation_name);
54 if (conversation.getMode() == Conversation.MODE_SINGLE || activity.useSubjectToIdentifyConference()) {
55 convName.setText(conversation.getName());
56 } else {
57 convName.setText(conversation.getJid().toBareJid().toString());
58 }
59 TextView mLastMessage = (TextView) view.findViewById(R.id.conversation_lastmsg);
60 TextView mTimestamp = (TextView) view.findViewById(R.id.conversation_lastupdate);
61 ImageView imagePreview = (ImageView) view.findViewById(R.id.conversation_lastimage);
62
63 Message message = conversation.getLatestMessage();
64
65 if (!conversation.isRead()) {
66 convName.setTypeface(null, Typeface.BOLD);
67 } else {
68 convName.setTypeface(null, Typeface.NORMAL);
69 }
70
71 if (message.getFileParams().width > 0
72 && (message.getTransferable() == null
73 || message.getTransferable().getStatus() != Transferable.STATUS_DELETED)) {
74 mLastMessage.setVisibility(View.GONE);
75 imagePreview.setVisibility(View.VISIBLE);
76 activity.loadBitmap(message, imagePreview);
77 } else {
78 Pair<String,Boolean> preview = UIHelper.getMessagePreview(activity,message);
79 mLastMessage.setVisibility(View.VISIBLE);
80 imagePreview.setVisibility(View.GONE);
81 mLastMessage.setText(preview.first);
82 if (preview.second) {
83 if (conversation.isRead()) {
84 mLastMessage.setTypeface(null, Typeface.ITALIC);
85 } else {
86 mLastMessage.setTypeface(null,Typeface.BOLD_ITALIC);
87 }
88 } else {
89 if (conversation.isRead()) {
90 mLastMessage.setTypeface(null,Typeface.NORMAL);
91 } else {
92 mLastMessage.setTypeface(null,Typeface.BOLD);
93 }
94 }
95 }
96
97 mTimestamp.setText(UIHelper.readableTimeDifference(activity,conversation.getLatestMessage().getTimeSent()));
98 ImageView profilePicture = (ImageView) view.findViewById(R.id.conversation_image);
99 loadAvatar(conversation,profilePicture);
100
101 return view;
102 }
103
104 class BitmapWorkerTask extends AsyncTask<Conversation, Void, Bitmap> {
105 private final WeakReference<ImageView> imageViewReference;
106 private Conversation conversation = null;
107
108 public BitmapWorkerTask(ImageView imageView) {
109 imageViewReference = new WeakReference<>(imageView);
110 }
111
112 @Override
113 protected Bitmap doInBackground(Conversation... params) {
114 return activity.avatarService().get(params[0], activity.getPixel(56));
115 }
116
117 @Override
118 protected void onPostExecute(Bitmap bitmap) {
119 if (bitmap != null) {
120 final ImageView imageView = imageViewReference.get();
121 if (imageView != null) {
122 imageView.setImageBitmap(bitmap);
123 imageView.setBackgroundColor(0x00000000);
124 }
125 }
126 }
127 }
128
129 public void loadAvatar(Conversation conversation, ImageView imageView) {
130 if (cancelPotentialWork(conversation, imageView)) {
131 final Bitmap bm = activity.avatarService().get(conversation, activity.getPixel(56), true);
132 if (bm != null) {
133 imageView.setImageBitmap(bm);
134 imageView.setBackgroundColor(0x00000000);
135 } else {
136 imageView.setBackgroundColor(UIHelper.getColorForName(conversation.getName()));
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(conversation);
143 } catch (final RejectedExecutionException ignored) {
144 }
145 }
146 }
147 }
148
149 public static boolean cancelPotentialWork(Conversation conversation, ImageView imageView) {
150 final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
151
152 if (bitmapWorkerTask != null) {
153 final Conversation oldConversation = bitmapWorkerTask.conversation;
154 if (oldConversation == null || conversation != oldConversation) {
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}