1package eu.siacs.conversations.ui;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.List;
6import java.util.Set;
7
8import net.java.otr4j.session.SessionStatus;
9import eu.siacs.conversations.R;
10import eu.siacs.conversations.crypto.PgpEngine;
11import eu.siacs.conversations.entities.Contact;
12import eu.siacs.conversations.entities.Conversation;
13import eu.siacs.conversations.entities.Message;
14import eu.siacs.conversations.entities.MucOptions;
15import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
16import eu.siacs.conversations.services.ImageProvider;
17import eu.siacs.conversations.services.XmppConnectionService;
18import eu.siacs.conversations.utils.UIHelper;
19import eu.siacs.conversations.xmpp.jingle.JingleConnection;
20import android.app.AlertDialog;
21import android.app.Fragment;
22import android.app.PendingIntent;
23import android.content.Context;
24import android.content.DialogInterface;
25import android.content.Intent;
26import android.content.IntentSender;
27import android.content.SharedPreferences;
28import android.content.IntentSender.SendIntentException;
29import android.graphics.Bitmap;
30import android.graphics.Typeface;
31import android.os.Bundle;
32import android.preference.PreferenceManager;
33import android.text.Editable;
34import android.text.Selection;
35import android.util.DisplayMetrics;
36import android.util.Log;
37import android.view.LayoutInflater;
38import android.view.View;
39import android.view.View.OnClickListener;
40import android.view.ViewGroup;
41import android.widget.ArrayAdapter;
42import android.widget.Button;
43import android.widget.EditText;
44import android.widget.LinearLayout;
45import android.widget.ListView;
46import android.widget.ImageButton;
47import android.widget.ImageView;
48import android.widget.TextView;
49import android.widget.Toast;
50
51public class ConversationFragment extends Fragment {
52
53 protected Conversation conversation;
54 protected ListView messagesView;
55 protected LayoutInflater inflater;
56 protected List<Message> messageList = new ArrayList<Message>();
57 protected ArrayAdapter<Message> messageListAdapter;
58 protected Contact contact;
59 protected BitmapCache mBitmapCache = new BitmapCache();
60
61 protected String queuedPqpMessage = null;
62
63 private EditText chatMsg;
64 private String pastedText = null;
65
66 protected Bitmap selfBitmap;
67
68 private boolean useSubject = true;
69
70 private IntentSender askForPassphraseIntent = null;
71
72 private OnClickListener sendMsgListener = new OnClickListener() {
73
74 @Override
75 public void onClick(View v) {
76 if (chatMsg.getText().length() < 1)
77 return;
78 Message message = new Message(conversation, chatMsg.getText()
79 .toString(), conversation.getNextEncryption());
80 if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) {
81 sendOtrMessage(message);
82 } else if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
83 sendPgpMessage(message);
84 } else {
85 sendPlainTextMessage(message);
86 }
87 }
88 };
89 protected OnClickListener clickToDecryptListener = new OnClickListener() {
90
91 @Override
92 public void onClick(View v) {
93 if (askForPassphraseIntent != null) {
94 try {
95 getActivity().startIntentSenderForResult(
96 askForPassphraseIntent,
97 ConversationActivity.REQUEST_DECRYPT_PGP, null, 0,
98 0, 0);
99 } catch (SendIntentException e) {
100 Log.d("xmppService", "couldnt fire intent");
101 }
102 }
103 }
104 };
105
106 private LinearLayout pgpInfo;
107 private LinearLayout mucError;
108 private TextView mucErrorText;
109 private OnClickListener clickToMuc = new OnClickListener() {
110
111 @Override
112 public void onClick(View v) {
113 Intent intent = new Intent(getActivity(), MucDetailsActivity.class);
114 intent.setAction(MucDetailsActivity.ACTION_VIEW_MUC);
115 intent.putExtra("uuid", conversation.getUuid());
116 startActivity(intent);
117 }
118 };
119 private ConversationActivity activity;
120
121 public void hidePgpPassphraseBox() {
122 pgpInfo.setVisibility(View.GONE);
123 }
124
125 public void updateChatMsgHint() {
126 if (conversation.getMode() == Conversation.MODE_MULTI) {
127 chatMsg.setHint(getString(R.string.send_message_to_conference));
128 } else {
129 switch (conversation.getNextEncryption()) {
130 case Message.ENCRYPTION_NONE:
131 chatMsg.setHint(getString(R.string.send_plain_text_message));
132 break;
133 case Message.ENCRYPTION_OTR:
134 chatMsg.setHint(getString(R.string.send_otr_message));
135 break;
136 case Message.ENCRYPTION_PGP:
137 chatMsg.setHint(getString(R.string.send_pgp_message));
138 break;
139 default:
140 break;
141 }
142 }
143 }
144
145 @Override
146 public View onCreateView(final LayoutInflater inflater,
147 ViewGroup container, Bundle savedInstanceState) {
148
149 final DisplayMetrics metrics = getResources().getDisplayMetrics();
150
151 this.inflater = inflater;
152
153 final View view = inflater.inflate(R.layout.fragment_conversation,
154 container, false);
155 chatMsg = (EditText) view.findViewById(R.id.textinput);
156
157 ImageButton sendButton = (ImageButton) view
158 .findViewById(R.id.textSendButton);
159 sendButton.setOnClickListener(this.sendMsgListener);
160
161 pgpInfo = (LinearLayout) view.findViewById(R.id.pgp_keyentry);
162 pgpInfo.setOnClickListener(clickToDecryptListener);
163 mucError = (LinearLayout) view.findViewById(R.id.muc_error);
164 mucError.setOnClickListener(clickToMuc);
165 mucErrorText = (TextView) view.findViewById(R.id.muc_error_msg);
166
167 messagesView = (ListView) view.findViewById(R.id.messages_view);
168
169 messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
170 .getApplicationContext(), R.layout.message_sent,
171 this.messageList) {
172
173 private static final int SENT = 0;
174 private static final int RECIEVED = 1;
175
176 @Override
177 public int getViewTypeCount() {
178 return 2;
179 }
180
181 @Override
182 public int getItemViewType(int position) {
183 if (getItem(position).getStatus() <= Message.STATUS_RECIEVED) {
184 return RECIEVED;
185 } else {
186 return SENT;
187 }
188 }
189
190 private void displayStatus(ViewHolder viewHolder, Message message) {
191 String filesize = null;
192 String info = null;
193 boolean error = false;
194 if (message.getType() == Message.TYPE_IMAGE) {
195 String[] fileParams = message.getBody().split(",");
196 try {
197 long size = Long.parseLong(fileParams[0]);
198 filesize = size / 1024 + " KB";
199 } catch (NumberFormatException e) {
200 filesize = "0 KB";
201 }
202 }
203 switch (message.getStatus()) {
204 case Message.STATUS_UNSEND:
205 info = getString(R.string.sending);
206 break;
207 case Message.STATUS_OFFERED:
208 info = getString(R.string.offering);
209 break;
210 case Message.STATUS_SEND_FAILED:
211 info = getString(R.string.send_failed);
212 error = true;
213 break;
214 case Message.STATUS_SEND_REJECTED:
215 info = getString(R.string.send_rejected);
216 error = true;
217 break;
218 default:
219 if ((message.getConversation().getMode() == Conversation.MODE_MULTI)
220 && (message.getStatus() <= Message.STATUS_RECIEVED)) {
221 info = message.getCounterpart();
222 }
223 break;
224 }
225 if (error) {
226 viewHolder.time.setTextColor(0xFFe92727);
227 } else {
228 viewHolder.time.setTextColor(0xFF8e8e8e);
229 }
230 if (message.getEncryption() == Message.ENCRYPTION_NONE) {
231 viewHolder.indicator.setVisibility(View.GONE);
232 } else {
233 viewHolder.indicator.setVisibility(View.VISIBLE);
234 }
235
236 String formatedTime = UIHelper.readableTimeDifference(message
237 .getTimeSent());
238 if (message.getStatus() <= Message.STATUS_RECIEVED) {
239 if ((filesize != null) && (info != null)) {
240 viewHolder.time.setText(filesize + " \u00B7 " + info);
241 } else if ((filesize == null) && (info != null)) {
242 viewHolder.time.setText(formatedTime + " \u00B7 "
243 + info);
244 } else if ((filesize != null) && (info == null)) {
245 viewHolder.time.setText(formatedTime + " \u00B7 "
246 + filesize);
247 } else {
248 viewHolder.time.setText(formatedTime);
249 }
250 } else {
251 if ((filesize != null) && (info != null)) {
252 viewHolder.time.setText(filesize + " \u00B7 " + info);
253 } else if ((filesize == null) && (info != null)) {
254 viewHolder.time.setText(info + " \u00B7 "
255 + formatedTime);
256 } else if ((filesize != null) && (info == null)) {
257 viewHolder.time.setText(filesize + " \u00B7 "
258 + formatedTime);
259 } else {
260 viewHolder.time.setText(formatedTime);
261 }
262 }
263 }
264
265 private void displayInfoMessage(ViewHolder viewHolder, int r) {
266 if (viewHolder.download_button!=null) {
267 viewHolder.download_button.setVisibility(View.GONE);
268 }
269 viewHolder.image.setVisibility(View.GONE);
270 viewHolder.messageBody.setVisibility(View.VISIBLE);
271 viewHolder.messageBody.setText(getString(r));
272 viewHolder.messageBody.setTextColor(0xff33B5E5);
273 viewHolder.messageBody.setTypeface(null, Typeface.ITALIC);
274 }
275
276 private void displayDecryptionFailed(ViewHolder viewHolder) {
277 viewHolder.download_button.setVisibility(View.GONE);
278 viewHolder.image.setVisibility(View.GONE);
279 viewHolder.messageBody.setVisibility(View.VISIBLE);
280 viewHolder.messageBody
281 .setText(getString(R.string.decryption_failed));
282 viewHolder.messageBody.setTextColor(0xFFe92727);
283 viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
284 }
285
286 private void displayTextMessage(ViewHolder viewHolder, String text) {
287 if (viewHolder.download_button != null) {
288 viewHolder.download_button.setVisibility(View.GONE);
289 }
290 viewHolder.image.setVisibility(View.GONE);
291 viewHolder.messageBody.setVisibility(View.VISIBLE);
292 if (text != null) {
293 viewHolder.messageBody.setText(text.trim());
294 } else {
295 viewHolder.messageBody.setText("");
296 }
297 viewHolder.messageBody.setTextColor(0xff333333);
298 viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
299 }
300
301 private void displayImageMessage(ViewHolder viewHolder,
302 final Message message) {
303 if (viewHolder.download_button != null) {
304 viewHolder.download_button.setVisibility(View.GONE);
305 }
306 viewHolder.messageBody.setVisibility(View.GONE);
307 viewHolder.image.setVisibility(View.VISIBLE);
308 String[] fileParams = message.getBody().split(",");
309 if (fileParams.length == 3) {
310 double target = metrics.density * 288;
311 int w = Integer.parseInt(fileParams[1]);
312 int h = Integer.parseInt(fileParams[2]);
313 int scalledW;
314 int scalledH;
315 if (w <= h) {
316 scalledW = (int) (w / ((double) h / target));
317 scalledH = (int) target;
318 } else {
319 scalledW = (int) target;
320 scalledH = (int) (h / ((double) w / target));
321 }
322 viewHolder.image
323 .setLayoutParams(new LinearLayout.LayoutParams(
324 scalledW, scalledH));
325 }
326 activity.loadBitmap(message, viewHolder.image);
327 viewHolder.image.setOnClickListener(new OnClickListener() {
328
329 @Override
330 public void onClick(View v) {
331 Intent intent = new Intent(Intent.ACTION_VIEW);
332 intent.setDataAndType(ImageProvider.getContentUri(message), "image/*");
333 startActivity(intent);
334 }
335 });
336 }
337
338 @Override
339 public View getView(int position, View view, ViewGroup parent) {
340 final Message item = getItem(position);
341 int type = getItemViewType(position);
342 ViewHolder viewHolder;
343 if (view == null) {
344 viewHolder = new ViewHolder();
345 switch (type) {
346 case SENT:
347 view = (View) inflater.inflate(R.layout.message_sent,
348 null);
349 viewHolder.contact_picture = (ImageView) view
350 .findViewById(R.id.message_photo);
351 viewHolder.contact_picture.setImageBitmap(selfBitmap);
352 break;
353 case RECIEVED:
354 view = (View) inflater.inflate(
355 R.layout.message_recieved, null);
356 viewHolder.contact_picture = (ImageView) view
357 .findViewById(R.id.message_photo);
358
359 viewHolder.download_button = (Button) view
360 .findViewById(R.id.download_button);
361
362 if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
363
364 viewHolder.contact_picture
365 .setImageBitmap(mBitmapCache.get(
366 item.getConversation().getName(
367 useSubject), item
368 .getConversation()
369 .getContact(),
370 getActivity()
371 .getApplicationContext()));
372
373 }
374 break;
375 default:
376 viewHolder = null;
377 break;
378 }
379 viewHolder.indicator = (ImageView) view
380 .findViewById(R.id.security_indicator);
381 viewHolder.image = (ImageView) view
382 .findViewById(R.id.message_image);
383 viewHolder.messageBody = (TextView) view
384 .findViewById(R.id.message_body);
385 viewHolder.time = (TextView) view
386 .findViewById(R.id.message_time);
387 view.setTag(viewHolder);
388 } else {
389 viewHolder = (ViewHolder) view.getTag();
390 }
391
392 if (type == RECIEVED) {
393 if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
394 if (item.getCounterpart() != null) {
395 viewHolder.contact_picture
396 .setImageBitmap(mBitmapCache.get(item
397 .getCounterpart(), null,
398 getActivity()
399 .getApplicationContext()));
400 } else {
401 viewHolder.contact_picture
402 .setImageBitmap(mBitmapCache.get(
403 item.getConversation().getName(
404 useSubject), null,
405 getActivity()
406 .getApplicationContext()));
407 }
408 }
409 }
410
411 if (item.getType() == Message.TYPE_IMAGE) {
412 if (item.getStatus() == Message.STATUS_RECIEVING) {
413 displayInfoMessage(viewHolder, R.string.receiving_image);
414 } else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) {
415 viewHolder.image.setVisibility(View.GONE);
416 viewHolder.messageBody.setVisibility(View.GONE);
417 viewHolder.download_button.setVisibility(View.VISIBLE);
418 viewHolder.download_button
419 .setOnClickListener(new OnClickListener() {
420
421 @Override
422 public void onClick(View v) {
423 JingleConnection connection = item
424 .getJingleConnection();
425 if (connection != null) {
426 connection.accept();
427 } else {
428 Log.d("xmppService",
429 "attached jingle connection was null");
430 }
431 }
432 });
433 } else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED)
434 || (item.getEncryption() == Message.ENCRYPTION_NONE)) {
435 displayImageMessage(viewHolder, item);
436 } else if (item.getEncryption() == Message.ENCRYPTION_PGP) {
437 displayInfoMessage(viewHolder,
438 R.string.encrypted_message);
439 } else {
440 displayDecryptionFailed(viewHolder);
441 }
442 } else {
443 if (item.getEncryption() == Message.ENCRYPTION_PGP) {
444 displayInfoMessage(viewHolder,
445 R.string.encrypted_message);
446 } else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
447 displayDecryptionFailed(viewHolder);
448 } else {
449 displayTextMessage(viewHolder, item.getBody());
450 }
451 }
452
453 displayStatus(viewHolder, item);
454
455 return view;
456 }
457 };
458 messagesView.setAdapter(messageListAdapter);
459
460 return view;
461 }
462
463 protected Bitmap findSelfPicture() {
464 SharedPreferences sharedPref = PreferenceManager
465 .getDefaultSharedPreferences(getActivity()
466 .getApplicationContext());
467 boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
468 "show_phone_selfcontact_picture", true);
469
470 return UIHelper.getSelfContactPicture(conversation.getAccount(), 48,
471 showPhoneSelfContactPicture, getActivity());
472 }
473
474 @Override
475 public void onStart() {
476 super.onStart();
477 this.activity = (ConversationActivity) getActivity();
478 SharedPreferences preferences = PreferenceManager
479 .getDefaultSharedPreferences(activity);
480 this.useSubject = preferences.getBoolean("use_subject_in_muc", true);
481 if (activity.xmppConnectionServiceBound) {
482 this.onBackendConnected();
483 }
484 }
485
486 @Override
487 public void onStop() {
488 super.onStop();
489 if (this.conversation!=null) {
490 this.conversation.setNextMessage(chatMsg.getText().toString());
491 }
492 }
493
494 public void onBackendConnected() {
495 this.conversation = activity.getSelectedConversation();
496 if (this.conversation == null) {
497 return;
498 }
499 if (this.pastedText == null) {
500 this.chatMsg.setText(conversation.getNextMessage());
501 } else {
502 chatMsg.setText(conversation.getNextMessage() + " " + pastedText);
503 pastedText = null;
504 }
505 int position = chatMsg.length();
506 Editable etext = chatMsg.getText();
507 Selection.setSelection(etext, position);
508 this.selfBitmap = findSelfPicture();
509 updateMessages();
510 if (activity.getSlidingPaneLayout().isSlideable()) {
511 if (!activity.shouldPaneBeOpen()) {
512 activity.getSlidingPaneLayout().closePane();
513 activity.getActionBar().setDisplayHomeAsUpEnabled(true);
514 activity.getActionBar().setTitle(
515 conversation.getName(useSubject));
516 activity.invalidateOptionsMenu();
517
518 }
519 }
520 if (conversation.getMode() == Conversation.MODE_MULTI) {
521 activity.xmppConnectionService
522 .setOnRenameListener(new OnRenameListener() {
523
524 @Override
525 public void onRename(final boolean success) {
526 activity.xmppConnectionService
527 .updateConversation(conversation);
528 getActivity().runOnUiThread(new Runnable() {
529
530 @Override
531 public void run() {
532 if (success) {
533 Toast.makeText(
534 getActivity(),
535 getString(R.string.your_nick_has_been_changed),
536 Toast.LENGTH_SHORT).show();
537 } else {
538 Toast.makeText(
539 getActivity(),
540 getString(R.string.nick_in_use),
541 Toast.LENGTH_SHORT).show();
542 }
543 }
544 });
545 }
546 });
547 }
548 }
549
550 private void decryptMessage(final Message message) {
551 PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
552 if (engine != null) {
553 engine.decrypt(message, new UiCallback() {
554
555 @Override
556 public void userInputRequried(PendingIntent pi) {
557 askForPassphraseIntent = pi.getIntentSender();
558 pgpInfo.setVisibility(View.VISIBLE);
559 }
560
561 @Override
562 public void success() {
563 activity.xmppConnectionService.databaseBackend
564 .updateMessage(message);
565 updateMessages();
566 }
567
568 @Override
569 public void error(int error) {
570 message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
571 // updateMessages();
572 }
573 });
574 } else {
575 pgpInfo.setVisibility(View.VISIBLE);
576 }
577 }
578
579 public void updateMessages() {
580 if (getView()==null) {
581 return;
582 }
583 ConversationActivity activity = (ConversationActivity) getActivity();
584 if (this.conversation != null) {
585 for (Message message : this.conversation.getMessages()) {
586 if ((message.getEncryption() == Message.ENCRYPTION_PGP)
587 && (message.getStatus() == Message.STATUS_RECIEVED)) {
588 decryptMessage(message);
589 break;
590 }
591 }
592 this.messageList.clear();
593 this.messageList.addAll(this.conversation.getMessages());
594 this.messageListAdapter.notifyDataSetChanged();
595 if (conversation.getMode() == Conversation.MODE_SINGLE) {
596 if (messageList.size() >= 1) {
597 makeFingerprintWarning(conversation.getLatestEncryption());
598 }
599 } else {
600 if (conversation.getMucOptions().getError() != 0) {
601 mucError.setVisibility(View.VISIBLE);
602 if (conversation.getMucOptions().getError() == MucOptions.ERROR_NICK_IN_USE) {
603 mucErrorText.setText(getString(R.string.nick_in_use));
604 }
605 } else {
606 mucError.setVisibility(View.GONE);
607 }
608 }
609 getActivity().invalidateOptionsMenu();
610 updateChatMsgHint();
611 int size = this.messageList.size();
612 if (size >= 1)
613 messagesView.setSelection(size - 1);
614 if (!activity.shouldPaneBeOpen()) {
615 conversation.markRead();
616 // TODO update notifications
617 UIHelper.updateNotification(getActivity(),
618 activity.getConversationList(), null, false);
619 activity.updateConversationList();
620 }
621 }
622 }
623
624 protected void makeFingerprintWarning(int latestEncryption) {
625 final LinearLayout fingerprintWarning = (LinearLayout) getView()
626 .findViewById(R.id.new_fingerprint);
627 if (conversation.getContact() != null) {
628 Set<String> knownFingerprints = conversation.getContact()
629 .getOtrFingerprints();
630 if ((latestEncryption == Message.ENCRYPTION_OTR)
631 && (conversation.hasValidOtrSession()
632 && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
633 .contains(conversation.getOtrFingerprint())))) {
634 fingerprintWarning.setVisibility(View.VISIBLE);
635 TextView fingerprint = (TextView) getView().findViewById(
636 R.id.otr_fingerprint);
637 fingerprint.setText(conversation.getOtrFingerprint());
638 fingerprintWarning.setOnClickListener(new OnClickListener() {
639
640 @Override
641 public void onClick(View v) {
642 AlertDialog dialog = UIHelper
643 .getVerifyFingerprintDialog(
644 (ConversationActivity) getActivity(),
645 conversation, fingerprintWarning);
646 dialog.show();
647 }
648 });
649 } else {
650 fingerprintWarning.setVisibility(View.GONE);
651 }
652 } else {
653 fingerprintWarning.setVisibility(View.GONE);
654 }
655 }
656
657 protected void sendPlainTextMessage(Message message) {
658 ConversationActivity activity = (ConversationActivity) getActivity();
659 activity.xmppConnectionService.sendMessage(message, null);
660 chatMsg.setText("");
661 }
662
663 protected void sendPgpMessage(final Message message) {
664 activity.pendingMessage = message;
665 final ConversationActivity activity = (ConversationActivity) getActivity();
666 final XmppConnectionService xmppService = activity.xmppConnectionService;
667 final Contact contact = message.getConversation().getContact();
668 if (activity.hasPgp()) {
669 if (contact.getPgpKeyId() != 0) {
670 xmppService.getPgpEngine().hasKey(contact,
671 new UiCallback() {
672
673 @Override
674 public void userInputRequried(PendingIntent pi) {
675 activity.runIntent(
676 pi,
677 ConversationActivity.REQUEST_ENCRYPT_MESSAGE);
678 }
679
680 @Override
681 public void success() {
682 activity.encryptTextMessage();
683 }
684
685 @Override
686 public void error(int error) {
687
688 }
689 });
690
691 } else {
692 showNoPGPKeyDialog(new DialogInterface.OnClickListener() {
693
694 @Override
695 public void onClick(DialogInterface dialog,
696 int which) {
697 conversation
698 .setNextEncryption(Message.ENCRYPTION_NONE);
699 message.setEncryption(Message.ENCRYPTION_NONE);
700 xmppService.sendMessage(message, null);
701 chatMsg.setText("");
702 }
703 });
704 }
705 }
706 }
707
708 public void showNoPGPKeyDialog(DialogInterface.OnClickListener listener) {
709 AlertDialog.Builder builder = new AlertDialog.Builder(
710 getActivity());
711 builder.setTitle(getString(R.string.no_pgp_key));
712 builder.setIconAttribute(android.R.attr.alertDialogIcon);
713 builder.setMessage(getText(R.string.contact_has_no_pgp_key));
714 builder.setNegativeButton(getString(R.string.cancel), null);
715 builder.setPositiveButton(getString(R.string.send_unencrypted),listener);
716 builder.create().show();
717 }
718
719 protected void sendOtrMessage(final Message message) {
720 ConversationActivity activity = (ConversationActivity) getActivity();
721 final XmppConnectionService xmppService = activity.xmppConnectionService;
722 if (conversation.hasValidOtrSession()) {
723 activity.xmppConnectionService.sendMessage(message, null);
724 chatMsg.setText("");
725 } else {
726 activity.selectPresence(message.getConversation(),
727 new OnPresenceSelected() {
728
729 @Override
730 public void onPresenceSelected(boolean success,
731 String presence) {
732 if (success) {
733 xmppService.sendMessage(message, presence);
734 chatMsg.setText("");
735 }
736 }
737
738 @Override
739 public void onSendPlainTextInstead() {
740 message.setEncryption(Message.ENCRYPTION_NONE);
741 xmppService.sendMessage(message, null);
742 chatMsg.setText("");
743 }
744 }, "otr");
745 }
746 }
747
748 private static class ViewHolder {
749
750 protected Button download_button;
751 protected ImageView image;
752 protected ImageView indicator;
753 protected TextView time;
754 protected TextView messageBody;
755 protected ImageView contact_picture;
756
757 }
758
759 private class BitmapCache {
760 private HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
761 private Bitmap error = null;
762
763 public Bitmap get(String name, Contact contact, Context context) {
764 if (bitmaps.containsKey(name)) {
765 return bitmaps.get(name);
766 } else {
767 Bitmap bm;
768 if (contact != null) {
769 bm = UIHelper
770 .getContactPicture(contact, 48, context, false);
771 } else {
772 bm = UIHelper.getContactPicture(name, 48, context, false);
773 }
774 bitmaps.put(name, bm);
775 return bm;
776 }
777 }
778 }
779
780 public void setText(String text) {
781 this.pastedText = text;
782 }
783
784 public void clearInputField() {
785 this.chatMsg.setText("");
786 }
787}