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