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