1package eu.siacs.conversations.ui.adapter;
2
3import android.content.Intent;
4import android.content.pm.PackageManager;
5import android.content.pm.ResolveInfo;
6import android.graphics.Color;
7import android.graphics.Typeface;
8import android.net.Uri;
9import android.text.Spannable;
10import android.text.SpannableString;
11import android.text.Spanned;
12import android.text.style.ForegroundColorSpan;
13import android.text.style.RelativeSizeSpan;
14import android.text.style.StyleSpan;
15import android.util.DisplayMetrics;
16import android.view.View;
17import android.view.View.OnClickListener;
18import android.view.View.OnLongClickListener;
19import android.view.ViewGroup;
20import android.widget.ArrayAdapter;
21import android.widget.Button;
22import android.widget.ImageView;
23import android.widget.LinearLayout;
24import android.widget.TextView;
25import android.widget.Toast;
26
27import java.util.List;
28
29import eu.siacs.conversations.R;
30import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore;
31import eu.siacs.conversations.entities.Account;
32import eu.siacs.conversations.entities.Contact;
33import eu.siacs.conversations.entities.Conversation;
34import eu.siacs.conversations.entities.DownloadableFile;
35import eu.siacs.conversations.entities.Message;
36import eu.siacs.conversations.entities.Message.FileParams;
37import eu.siacs.conversations.entities.Transferable;
38import eu.siacs.conversations.ui.ConversationActivity;
39import eu.siacs.conversations.utils.GeoHelper;
40import eu.siacs.conversations.utils.UIHelper;
41
42public class MessageAdapter extends ArrayAdapter<Message> {
43
44 private static final int SENT = 0;
45 private static final int RECEIVED = 1;
46 private static final int STATUS = 2;
47
48 private ConversationActivity activity;
49
50 private DisplayMetrics metrics;
51
52 private OnContactPictureClicked mOnContactPictureClickedListener;
53 private OnContactPictureLongClicked mOnContactPictureLongClickedListener;
54
55 private OnLongClickListener openContextMenu = new OnLongClickListener() {
56
57 @Override
58 public boolean onLongClick(View v) {
59 v.showContextMenu();
60 return true;
61 }
62 };
63
64 public MessageAdapter(ConversationActivity activity, List<Message> messages) {
65 super(activity, 0, messages);
66 this.activity = activity;
67 metrics = getContext().getResources().getDisplayMetrics();
68 }
69
70 public void setOnContactPictureClicked(OnContactPictureClicked listener) {
71 this.mOnContactPictureClickedListener = listener;
72 }
73
74 public void setOnContactPictureLongClicked(
75 OnContactPictureLongClicked listener) {
76 this.mOnContactPictureLongClickedListener = listener;
77 }
78
79 @Override
80 public int getViewTypeCount() {
81 return 3;
82 }
83
84 public int getItemViewType(Message message) {
85 if (message.getType() == Message.TYPE_STATUS) {
86 return STATUS;
87 } else if (message.getStatus() <= Message.STATUS_RECEIVED) {
88 return RECEIVED;
89 }
90
91 return SENT;
92 }
93
94 @Override
95 public int getItemViewType(int position) {
96 return this.getItemViewType(getItem(position));
97 }
98
99 private int getMessageTextColor(int type, boolean primary) {
100 if (type == SENT) {
101 return activity.getResources().getColor(primary ? R.color.black87 : R.color.black54);
102 } else {
103 return activity.getResources().getColor(primary ? R.color.white : R.color.white70);
104 }
105 }
106
107 private void displayStatus(ViewHolder viewHolder, Message message, int type) {
108 String filesize = null;
109 String info = null;
110 boolean error = false;
111 if (viewHolder.indicatorReceived != null) {
112 viewHolder.indicatorReceived.setVisibility(View.GONE);
113 }
114 boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI
115 && message.getMergedStatus() <= Message.STATUS_RECEIVED;
116 if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getTransferable() != null) {
117 FileParams params = message.getFileParams();
118 if (params.size > (1.5 * 1024 * 1024)) {
119 filesize = params.size / (1024 * 1024)+ " MiB";
120 } else if (params.size > 0) {
121 filesize = params.size / 1024 + " KiB";
122 }
123 if (message.getTransferable() != null && message.getTransferable().getStatus() == Transferable.STATUS_FAILED) {
124 error = true;
125 }
126 }
127 switch (message.getMergedStatus()) {
128 case Message.STATUS_WAITING:
129 info = getContext().getString(R.string.waiting);
130 break;
131 case Message.STATUS_UNSEND:
132 Transferable d = message.getTransferable();
133 if (d!=null) {
134 info = getContext().getString(R.string.sending_file,d.getProgress());
135 } else {
136 info = getContext().getString(R.string.sending);
137 }
138 break;
139 case Message.STATUS_OFFERED:
140 info = getContext().getString(R.string.offering);
141 break;
142 case Message.STATUS_SEND_RECEIVED:
143 if (activity.indicateReceived()) {
144 viewHolder.indicatorReceived.setVisibility(View.VISIBLE);
145 }
146 break;
147 case Message.STATUS_SEND_DISPLAYED:
148 if (activity.indicateReceived()) {
149 viewHolder.indicatorReceived.setVisibility(View.VISIBLE);
150 }
151 break;
152 case Message.STATUS_SEND_FAILED:
153 info = getContext().getString(R.string.send_failed);
154 error = true;
155 break;
156 default:
157 if (multiReceived) {
158 info = UIHelper.getMessageDisplayName(message);
159 }
160 break;
161 }
162 if (error && type == SENT) {
163 viewHolder.time.setTextColor(activity.getWarningTextColor());
164 } else {
165 viewHolder.time.setTextColor(this.getMessageTextColor(type,false));
166 }
167 if (message.getEncryption() == Message.ENCRYPTION_NONE) {
168 viewHolder.indicator.setVisibility(View.GONE);
169 } else {
170 viewHolder.indicator.setVisibility(View.VISIBLE);
171 if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
172 SQLiteAxolotlStore.Trust trust = message.getConversation()
173 .getAccount().getAxolotlService().getFingerprintTrust(
174 message.getAxolotlFingerprint());
175
176 if(trust == null || trust != SQLiteAxolotlStore.Trust.TRUSTED) {
177 viewHolder.indicator.setColorFilter(activity.getWarningTextColor());
178 viewHolder.indicator.setAlpha(1.0f);
179 } else {
180 viewHolder.indicator.clearColorFilter();
181 if (type == SENT) {
182 viewHolder.indicator.setAlpha(0.57f);
183 } else {
184 viewHolder.indicator.setAlpha(0.7f);
185 }
186 }
187 } else {
188 viewHolder.indicator.clearColorFilter();
189 if (type == SENT) {
190 viewHolder.indicator.setAlpha(0.57f);
191 } else {
192 viewHolder.indicator.setAlpha(0.7f);
193 }
194 }
195 }
196
197 String formatedTime = UIHelper.readableTimeDifferenceFull(getContext(),
198 message.getMergedTimeSent());
199 if (message.getStatus() <= Message.STATUS_RECEIVED) {
200 if ((filesize != null) && (info != null)) {
201 viewHolder.time.setText(formatedTime + " \u00B7 " + filesize +" \u00B7 " + info);
202 } else if ((filesize == null) && (info != null)) {
203 viewHolder.time.setText(formatedTime + " \u00B7 " + info);
204 } else if ((filesize != null) && (info == null)) {
205 viewHolder.time.setText(formatedTime + " \u00B7 " + filesize);
206 } else {
207 viewHolder.time.setText(formatedTime);
208 }
209 } else {
210 if ((filesize != null) && (info != null)) {
211 viewHolder.time.setText(filesize + " \u00B7 " + info);
212 } else if ((filesize == null) && (info != null)) {
213 if (error) {
214 viewHolder.time.setText(info + " \u00B7 " + formatedTime);
215 } else {
216 viewHolder.time.setText(info);
217 }
218 } else if ((filesize != null) && (info == null)) {
219 viewHolder.time.setText(filesize + " \u00B7 " + formatedTime);
220 } else {
221 viewHolder.time.setText(formatedTime);
222 }
223 }
224 }
225
226 private void displayInfoMessage(ViewHolder viewHolder, String text, int type) {
227 if (viewHolder.download_button != null) {
228 viewHolder.download_button.setVisibility(View.GONE);
229 }
230 viewHolder.image.setVisibility(View.GONE);
231 viewHolder.messageBody.setVisibility(View.VISIBLE);
232 viewHolder.messageBody.setText(text);
233 viewHolder.messageBody.setTextColor(getMessageTextColor(type,false));
234 viewHolder.messageBody.setTypeface(null, Typeface.ITALIC);
235 viewHolder.messageBody.setTextIsSelectable(false);
236 }
237
238 private void displayDecryptionFailed(ViewHolder viewHolder, int type) {
239 if (viewHolder.download_button != null) {
240 viewHolder.download_button.setVisibility(View.GONE);
241 }
242 viewHolder.image.setVisibility(View.GONE);
243 viewHolder.messageBody.setVisibility(View.VISIBLE);
244 viewHolder.messageBody.setText(getContext().getString(
245 R.string.decryption_failed));
246 viewHolder.messageBody.setTextColor(getMessageTextColor(type,false));
247 viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
248 viewHolder.messageBody.setTextIsSelectable(false);
249 }
250
251 private void displayHeartMessage(final ViewHolder viewHolder, final String body) {
252 if (viewHolder.download_button != null) {
253 viewHolder.download_button.setVisibility(View.GONE);
254 }
255 viewHolder.image.setVisibility(View.GONE);
256 viewHolder.messageBody.setVisibility(View.VISIBLE);
257 viewHolder.messageBody.setIncludeFontPadding(false);
258 Spannable span = new SpannableString(body);
259 span.setSpan(new RelativeSizeSpan(4.0f), 0, body.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
260 span.setSpan(new ForegroundColorSpan(activity.getWarningTextColor()), 0, body.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
261 viewHolder.messageBody.setText(span);
262 }
263
264 private void displayTextMessage(final ViewHolder viewHolder, final Message message, int type) {
265 if (viewHolder.download_button != null) {
266 viewHolder.download_button.setVisibility(View.GONE);
267 }
268 viewHolder.image.setVisibility(View.GONE);
269 viewHolder.messageBody.setVisibility(View.VISIBLE);
270 viewHolder.messageBody.setIncludeFontPadding(true);
271 if (message.getBody() != null) {
272 final String nick = UIHelper.getMessageDisplayName(message);
273 final String body = message.getMergedBody().replaceAll("^" + Message.ME_COMMAND,nick + " ");
274 final SpannableString formattedBody = new SpannableString(body);
275 int i = body.indexOf(Message.MERGE_SEPARATOR);
276 while(i >= 0) {
277 final int end = i + Message.MERGE_SEPARATOR.length();
278 formattedBody.setSpan(new RelativeSizeSpan(0.3f),i,end,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
279 i = body.indexOf(Message.MERGE_SEPARATOR,end);
280 }
281 if (message.getType() != Message.TYPE_PRIVATE) {
282 if (message.hasMeCommand()) {
283 final Spannable span = new SpannableString(formattedBody);
284 span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(),
285 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
286 viewHolder.messageBody.setText(span);
287 } else {
288 viewHolder.messageBody.setText(formattedBody);
289 }
290 } else {
291 String privateMarker;
292 if (message.getStatus() <= Message.STATUS_RECEIVED) {
293 privateMarker = activity
294 .getString(R.string.private_message);
295 } else {
296 final String to;
297 if (message.getCounterpart() != null) {
298 to = message.getCounterpart().getResourcepart();
299 } else {
300 to = "";
301 }
302 privateMarker = activity.getString(R.string.private_message_to, to);
303 }
304 final Spannable span = new SpannableString(privateMarker + " "
305 + formattedBody);
306 span.setSpan(new ForegroundColorSpan(activity
307 .getSecondaryTextColor()), 0, privateMarker
308 .length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
309 span.setSpan(new StyleSpan(Typeface.BOLD), 0,
310 privateMarker.length(),
311 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
312 if (message.hasMeCommand()) {
313 span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), privateMarker.length() + 1,
314 privateMarker.length() + 1 + nick.length(),
315 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
316 }
317 viewHolder.messageBody.setText(span);
318 }
319 } else {
320 viewHolder.messageBody.setText("");
321 }
322 viewHolder.messageBody.setTextColor(this.getMessageTextColor(type,true));
323 viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
324 viewHolder.messageBody.setTextIsSelectable(true);
325 }
326
327 private void displayDownloadableMessage(ViewHolder viewHolder,
328 final Message message, String text) {
329 viewHolder.image.setVisibility(View.GONE);
330 viewHolder.messageBody.setVisibility(View.GONE);
331 viewHolder.download_button.setVisibility(View.VISIBLE);
332 viewHolder.download_button.setText(text);
333 viewHolder.download_button.setOnClickListener(new OnClickListener() {
334
335 @Override
336 public void onClick(View v) {
337 startDownloadable(message);
338 }
339 });
340 viewHolder.download_button.setOnLongClickListener(openContextMenu);
341 }
342
343 private void displayOpenableMessage(ViewHolder viewHolder,final Message message) {
344 viewHolder.image.setVisibility(View.GONE);
345 viewHolder.messageBody.setVisibility(View.GONE);
346 viewHolder.download_button.setVisibility(View.VISIBLE);
347 viewHolder.download_button.setText(activity.getString(R.string.open_x_file, UIHelper.getFileDescriptionString(activity, message)));
348 viewHolder.download_button.setOnClickListener(new OnClickListener() {
349
350 @Override
351 public void onClick(View v) {
352 openDownloadable(message);
353 }
354 });
355 viewHolder.download_button.setOnLongClickListener(openContextMenu);
356 }
357
358 private void displayLocationMessage(ViewHolder viewHolder, final Message message) {
359 viewHolder.image.setVisibility(View.GONE);
360 viewHolder.messageBody.setVisibility(View.GONE);
361 viewHolder.download_button.setVisibility(View.VISIBLE);
362 viewHolder.download_button.setText(R.string.show_location);
363 viewHolder.download_button.setOnClickListener(new OnClickListener() {
364
365 @Override
366 public void onClick(View v) {
367 showLocation(message);
368 }
369 });
370 viewHolder.download_button.setOnLongClickListener(openContextMenu);
371 }
372
373 private void displayImageMessage(ViewHolder viewHolder,
374 final Message message) {
375 if (viewHolder.download_button != null) {
376 viewHolder.download_button.setVisibility(View.GONE);
377 }
378 viewHolder.messageBody.setVisibility(View.GONE);
379 viewHolder.image.setVisibility(View.VISIBLE);
380 FileParams params = message.getFileParams();
381 double target = metrics.density * 288;
382 int scalledW;
383 int scalledH;
384 if (params.width <= params.height) {
385 scalledW = (int) (params.width / ((double) params.height / target));
386 scalledH = (int) target;
387 } else {
388 scalledW = (int) target;
389 scalledH = (int) (params.height / ((double) params.width / target));
390 }
391 LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(scalledW, scalledH);
392 layoutParams.setMargins(0, (int)(metrics.density * 4), 0, (int)(metrics.density * 4));
393 viewHolder.image.setLayoutParams(layoutParams);
394 activity.loadBitmap(message, viewHolder.image);
395 viewHolder.image.setOnClickListener(new OnClickListener() {
396
397 @Override
398 public void onClick(View v) {
399 Intent intent = new Intent(Intent.ACTION_VIEW);
400 intent.setDataAndType(activity.xmppConnectionService
401 .getFileBackend().getJingleFileUri(message), "image/*");
402 getContext().startActivity(intent);
403 }
404 });
405 viewHolder.image.setOnLongClickListener(openContextMenu);
406 }
407
408 @Override
409 public View getView(int position, View view, ViewGroup parent) {
410 final Message message = getItem(position);
411 final Conversation conversation = message.getConversation();
412 final Account account = conversation.getAccount();
413 final int type = getItemViewType(position);
414 ViewHolder viewHolder;
415 if (view == null) {
416 viewHolder = new ViewHolder();
417 switch (type) {
418 case SENT:
419 view = activity.getLayoutInflater().inflate(
420 R.layout.message_sent, parent, false);
421 viewHolder.message_box = (LinearLayout) view
422 .findViewById(R.id.message_box);
423 viewHolder.contact_picture = (ImageView) view
424 .findViewById(R.id.message_photo);
425 viewHolder.download_button = (Button) view
426 .findViewById(R.id.download_button);
427 viewHolder.indicator = (ImageView) view
428 .findViewById(R.id.security_indicator);
429 viewHolder.image = (ImageView) view
430 .findViewById(R.id.message_image);
431 viewHolder.messageBody = (TextView) view
432 .findViewById(R.id.message_body);
433 viewHolder.time = (TextView) view
434 .findViewById(R.id.message_time);
435 viewHolder.indicatorReceived = (ImageView) view
436 .findViewById(R.id.indicator_received);
437 break;
438 case RECEIVED:
439 view = activity.getLayoutInflater().inflate(
440 R.layout.message_received, parent, false);
441 viewHolder.message_box = (LinearLayout) view
442 .findViewById(R.id.message_box);
443 viewHolder.contact_picture = (ImageView) view
444 .findViewById(R.id.message_photo);
445 viewHolder.download_button = (Button) view
446 .findViewById(R.id.download_button);
447 viewHolder.indicator = (ImageView) view
448 .findViewById(R.id.security_indicator);
449 viewHolder.image = (ImageView) view
450 .findViewById(R.id.message_image);
451 viewHolder.messageBody = (TextView) view
452 .findViewById(R.id.message_body);
453 viewHolder.time = (TextView) view
454 .findViewById(R.id.message_time);
455 viewHolder.indicatorReceived = (ImageView) view
456 .findViewById(R.id.indicator_received);
457 break;
458 case STATUS:
459 view = activity.getLayoutInflater().inflate(R.layout.message_status, parent, false);
460 viewHolder.contact_picture = (ImageView) view.findViewById(R.id.message_photo);
461 viewHolder.status_message = (TextView) view.findViewById(R.id.status_message);
462 break;
463 default:
464 viewHolder = null;
465 break;
466 }
467 view.setTag(viewHolder);
468 } else {
469 viewHolder = (ViewHolder) view.getTag();
470 if (viewHolder == null) {
471 return view;
472 }
473 }
474
475 if (type == STATUS) {
476 if (conversation.getMode() == Conversation.MODE_SINGLE) {
477 viewHolder.contact_picture.setImageBitmap(activity
478 .avatarService().get(conversation.getContact(),
479 activity.getPixel(32)));
480 viewHolder.contact_picture.setAlpha(0.5f);
481 viewHolder.status_message.setText(message.getBody());
482 }
483 return view;
484 } else if (type == RECEIVED) {
485 Contact contact = message.getContact();
486 if (contact != null) {
487 viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(contact, activity.getPixel(48)));
488 } else if (conversation.getMode() == Conversation.MODE_MULTI) {
489 viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(
490 UIHelper.getMessageDisplayName(message),
491 activity.getPixel(48)));
492 }
493 } else if (type == SENT) {
494 viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(account, activity.getPixel(48)));
495 }
496
497 viewHolder.contact_picture
498 .setOnClickListener(new OnClickListener() {
499
500 @Override
501 public void onClick(View v) {
502 if (MessageAdapter.this.mOnContactPictureClickedListener != null) {
503 MessageAdapter.this.mOnContactPictureClickedListener
504 .onContactPictureClicked(message);
505 }
506
507 }
508 });
509 viewHolder.contact_picture
510 .setOnLongClickListener(new OnLongClickListener() {
511
512 @Override
513 public boolean onLongClick(View v) {
514 if (MessageAdapter.this.mOnContactPictureLongClickedListener != null) {
515 MessageAdapter.this.mOnContactPictureLongClickedListener
516 .onContactPictureLongClicked(message);
517 return true;
518 } else {
519 return false;
520 }
521 }
522 });
523
524 final Transferable transferable = message.getTransferable();
525 if (transferable != null && transferable.getStatus() != Transferable.STATUS_UPLOADING) {
526 if (transferable.getStatus() == Transferable.STATUS_OFFER) {
527 displayDownloadableMessage(viewHolder,message,activity.getString(R.string.download_x_file, UIHelper.getFileDescriptionString(activity, message)));
528 } else if (transferable.getStatus() == Transferable.STATUS_OFFER_CHECK_FILESIZE) {
529 displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message)));
530 } else {
531 displayInfoMessage(viewHolder, UIHelper.getMessagePreview(activity, message).first,type);
532 }
533 } else if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) {
534 displayImageMessage(viewHolder, message);
535 } else if (message.getType() == Message.TYPE_FILE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) {
536 if (message.getFileParams().width > 0) {
537 displayImageMessage(viewHolder,message);
538 } else {
539 displayOpenableMessage(viewHolder, message);
540 }
541 } else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
542 if (activity.hasPgp()) {
543 displayInfoMessage(viewHolder,activity.getString(R.string.encrypted_message),type);
544 } else {
545 displayInfoMessage(viewHolder,activity.getString(R.string.install_openkeychain),type);
546 if (viewHolder != null) {
547 viewHolder.message_box
548 .setOnClickListener(new OnClickListener() {
549
550 @Override
551 public void onClick(View v) {
552 activity.showInstallPgpDialog();
553 }
554 });
555 }
556 }
557 } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
558 displayDecryptionFailed(viewHolder,type);
559 } else {
560 if (GeoHelper.isGeoUri(message.getBody())) {
561 displayLocationMessage(viewHolder,message);
562 } else if (message.bodyIsHeart()) {
563 displayHeartMessage(viewHolder, message.getBody().trim());
564 } else if (message.treatAsDownloadable() == Message.Decision.MUST) {
565 displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message)));
566 } else {
567 displayTextMessage(viewHolder, message, type);
568 }
569 }
570
571 if (type == RECEIVED) {
572 boolean wasEncrypted = false;
573 for (Message iterator = message.prev(); iterator != null; iterator = iterator.prev()){
574 if (iterator.getEncryption() != Message.ENCRYPTION_NONE) {
575 wasEncrypted = true;
576 break;
577 }
578 if (!iterator.isCarbon() && iterator.getType() == SENT) {
579 break;
580 }
581 }
582 boolean willBeEncrypted = conversation.getNextEncryption(false) != Message.ENCRYPTION_NONE;
583 for (Message iterator = message.next(); iterator != null; iterator = iterator.next()){
584 if (iterator.getEncryption() != Message.ENCRYPTION_NONE) {
585 willBeEncrypted = true;
586 break;
587 }
588 if (!iterator.isCarbon() && iterator.getType() == SENT) {
589 break;
590 }
591 }
592
593 if ( willBeEncrypted && wasEncrypted
594 && message.getEncryption() == Message.ENCRYPTION_NONE) {
595 viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_warning);
596 } else {
597 viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received);
598 }
599 }
600
601 displayStatus(viewHolder, message, type);
602
603 return view;
604 }
605
606 public void startDownloadable(Message message) {
607 Transferable transferable = message.getTransferable();
608 if (transferable != null) {
609 if (!transferable.start()) {
610 Toast.makeText(activity, R.string.not_connected_try_again,
611 Toast.LENGTH_SHORT).show();
612 }
613 } else if (message.treatAsDownloadable() != Message.Decision.NEVER) {
614 activity.xmppConnectionService.getHttpConnectionManager().createNewDownloadConnection(message,true);
615 }
616 }
617
618 public void openDownloadable(Message message) {
619 DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message);
620 if (!file.exists()) {
621 Toast.makeText(activity,R.string.file_deleted,Toast.LENGTH_SHORT).show();
622 return;
623 }
624 Intent openIntent = new Intent(Intent.ACTION_VIEW);
625 openIntent.setDataAndType(Uri.fromFile(file), file.getMimeType());
626 PackageManager manager = activity.getPackageManager();
627 List<ResolveInfo> infos = manager.queryIntentActivities(openIntent, 0);
628 if (infos.size() > 0) {
629 getContext().startActivity(openIntent);
630 } else {
631 Toast.makeText(activity,R.string.no_application_found_to_open_file,Toast.LENGTH_SHORT).show();
632 }
633 }
634
635 public void showLocation(Message message) {
636 for(Intent intent : GeoHelper.createGeoIntentsFromMessage(message)) {
637 if (intent.resolveActivity(getContext().getPackageManager()) != null) {
638 getContext().startActivity(intent);
639 return;
640 }
641 }
642 Toast.makeText(activity,R.string.no_application_found_to_display_location,Toast.LENGTH_SHORT).show();
643 }
644
645 public interface OnContactPictureClicked {
646 public void onContactPictureClicked(Message message);
647 }
648
649 public interface OnContactPictureLongClicked {
650 public void onContactPictureLongClicked(Message message);
651 }
652
653 private static class ViewHolder {
654
655 protected LinearLayout message_box;
656 protected Button download_button;
657 protected ImageView image;
658 protected ImageView indicator;
659 protected ImageView indicatorReceived;
660 protected TextView time;
661 protected TextView messageBody;
662 protected ImageView contact_picture;
663 protected TextView status_message;
664 }
665}