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 private void displayStatus(ViewHolder viewHolder, Message message) {
196 String filesize = null;
197 String info = null;
198 boolean error = false;
199 if (message.getType() == Message.TYPE_IMAGE) {
200 String[] fileParams = message.getBody().split(",");
201 long size = Long.parseLong(fileParams[0]);
202 filesize = size / 1024 + " KB";
203 }
204 switch (message.getStatus()) {
205 case Message.STATUS_UNSEND:
206 info = getString(R.string.sending);
207 break;
208 case Message.STATUS_OFFERED:
209 info = getString(R.string.offering);
210 break;
211 case Message.STATUS_SEND_FAILED:
212 info = getString(R.string.send_failed);
213 error = true;
214 break;
215 case Message.STATUS_SEND_REJECTED:
216 info = getString(R.string.send_rejected);
217 error = true;
218 break;
219 default:
220 if ((message.getConversation().getMode() == Conversation.MODE_MULTI)
221 && (message.getStatus() <= Message.STATUS_RECIEVED)) {
222 info = message.getCounterpart();
223 }
224 break;
225 }
226 if (error) {
227 viewHolder.time.setTextColor(0xFFe92727);
228 } else {
229 viewHolder.time.setTextColor(0xFF8e8e8e);
230 }
231 if (message.getEncryption() == Message.ENCRYPTION_NONE) {
232 viewHolder.indicator.setVisibility(View.GONE);
233 } else {
234 viewHolder.indicator.setVisibility(View.VISIBLE);
235 }
236
237 String formatedTime = UIHelper.readableTimeDifference(message
238 .getTimeSent());
239 if (message.getStatus() <= Message.STATUS_RECIEVED) {
240 if ((filesize != null) && (info != null)) {
241 viewHolder.time.setText(filesize + " \u00B7 " + info);
242 } else if ((filesize == null) && (info != null)) {
243 viewHolder.time.setText(formatedTime + " \u00B7 "
244 + info);
245 } else if ((filesize != null) && (info == null)) {
246 viewHolder.time.setText(formatedTime + " \u00B7 "
247 + filesize);
248 } else {
249 viewHolder.time.setText(formatedTime);
250 }
251 } else {
252 if ((filesize != null) && (info != null)) {
253 viewHolder.time.setText(filesize + " \u00B7 " + info);
254 } else if ((filesize == null) && (info != null)) {
255 viewHolder.time.setText(info + " \u00B7 "
256 + formatedTime);
257 } else if ((filesize != null) && (info == null)) {
258 viewHolder.time.setText(filesize + " \u00B7 "
259 + formatedTime);
260 } else {
261 viewHolder.time.setText(formatedTime);
262 }
263 }
264 }
265
266 private void displayInfoMessage(ViewHolder viewHolder, int r) {
267 viewHolder.download_button.setVisibility(View.GONE);
268 viewHolder.image.setVisibility(View.GONE);
269 viewHolder.messageBody.setVisibility(View.VISIBLE);
270 viewHolder.messageBody.setText(getString(r));
271 viewHolder.messageBody.setTextColor(0xff33B5E5);
272 viewHolder.messageBody.setTypeface(null, Typeface.ITALIC);
273 }
274
275 private void displayDecryptionFailed(ViewHolder viewHolder) {
276 viewHolder.download_button.setVisibility(View.GONE);
277 viewHolder.image.setVisibility(View.GONE);
278 viewHolder.messageBody.setVisibility(View.VISIBLE);
279 viewHolder.messageBody
280 .setText(getString(R.string.decryption_failed));
281 viewHolder.messageBody.setTextColor(0xFFe92727);
282 viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
283 }
284
285 private void displayTextMessage(ViewHolder viewHolder, String text) {
286 if (viewHolder.download_button != null) {
287 viewHolder.download_button.setVisibility(View.GONE);
288 }
289 viewHolder.image.setVisibility(View.GONE);
290 viewHolder.messageBody.setVisibility(View.VISIBLE);
291 if (text != null) {
292 viewHolder.messageBody.setText(text.trim());
293 } else {
294 viewHolder.messageBody.setText("");
295 }
296 viewHolder.messageBody.setTextColor(0xff333333);
297 viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
298 }
299
300 private void displayImageMessage(ViewHolder viewHolder,
301 final Message message) {
302 if (viewHolder.download_button != null) {
303 viewHolder.download_button.setVisibility(View.GONE);
304 }
305 viewHolder.messageBody.setVisibility(View.GONE);
306 viewHolder.image.setVisibility(View.VISIBLE);
307 String[] fileParams = message.getBody().split(",");
308 if (fileParams.length == 3) {
309 double target = metrics.density * 288;
310 int w = Integer.parseInt(fileParams[1]);
311 int h = Integer.parseInt(fileParams[2]);
312 int scalledW;
313 int scalledH;
314 if (w <= h) {
315 scalledW = (int) (w / ((double) h / target));
316 scalledH = (int) target;
317 } else {
318 scalledW = (int) target;
319 scalledH = (int) (h / ((double) w / target));
320 }
321 viewHolder.image
322 .setLayoutParams(new LinearLayout.LayoutParams(
323 scalledW, scalledH));
324 }
325 activity.loadBitmap(message, viewHolder.image);
326 viewHolder.image.setOnClickListener(new OnClickListener() {
327
328 @Override
329 public void onClick(View v) {
330 Uri uri = Uri
331 .parse("content://eu.siacs.conversations.images/"
332 + message.getConversationUuid()
333 + "/"
334 + message.getUuid());
335 Log.d("xmppService",
336 "staring intent with uri:" + uri.toString());
337 Intent intent = new Intent(Intent.ACTION_VIEW);
338 intent.setDataAndType(uri, "image/*");
339 startActivity(intent);
340 }
341 });
342 }
343
344 @Override
345 public View getView(int position, View view, ViewGroup parent) {
346 final Message item = getItem(position);
347 int type = getItemViewType(position);
348 ViewHolder viewHolder;
349 if (view == null) {
350 viewHolder = new ViewHolder();
351 switch (type) {
352 case SENT:
353 view = (View) inflater.inflate(R.layout.message_sent,
354 null);
355 viewHolder.contact_picture = (ImageView) view
356 .findViewById(R.id.message_photo);
357 viewHolder.contact_picture.setImageBitmap(selfBitmap);
358 break;
359 case RECIEVED:
360 view = (View) inflater.inflate(
361 R.layout.message_recieved, null);
362 viewHolder.contact_picture = (ImageView) view
363 .findViewById(R.id.message_photo);
364
365 viewHolder.download_button = (Button) view
366 .findViewById(R.id.download_button);
367
368 if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
369
370 viewHolder.contact_picture
371 .setImageBitmap(mBitmapCache.get(
372 item.getConversation().getName(
373 useSubject), item
374 .getConversation()
375 .getContact(),
376 getActivity()
377 .getApplicationContext()));
378
379 }
380 break;
381 default:
382 viewHolder = null;
383 break;
384 }
385 viewHolder.indicator = (ImageView) view
386 .findViewById(R.id.security_indicator);
387 viewHolder.image = (ImageView) view
388 .findViewById(R.id.message_image);
389 viewHolder.messageBody = (TextView) view
390 .findViewById(R.id.message_body);
391 viewHolder.time = (TextView) view
392 .findViewById(R.id.message_time);
393 view.setTag(viewHolder);
394 } else {
395 viewHolder = (ViewHolder) view.getTag();
396 }
397
398 if (type == RECIEVED) {
399 if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
400 if (item.getCounterpart() != null) {
401 viewHolder.contact_picture
402 .setImageBitmap(mBitmapCache.get(item
403 .getCounterpart(), null,
404 getActivity()
405 .getApplicationContext()));
406 } else {
407 viewHolder.contact_picture
408 .setImageBitmap(mBitmapCache.get(
409 item.getConversation().getName(
410 useSubject), null,
411 getActivity()
412 .getApplicationContext()));
413 }
414 }
415 }
416
417 if (item.getType() == Message.TYPE_IMAGE) {
418 if (item.getStatus() == Message.STATUS_RECIEVING) {
419 displayInfoMessage(viewHolder, R.string.receiving_image);
420 } else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) {
421 viewHolder.image.setVisibility(View.GONE);
422 viewHolder.messageBody.setVisibility(View.GONE);
423 viewHolder.download_button.setVisibility(View.VISIBLE);
424 viewHolder.download_button
425 .setOnClickListener(new OnClickListener() {
426
427 @Override
428 public void onClick(View v) {
429 JingleConnection connection = item
430 .getJingleConnection();
431 if (connection != null) {
432 connection.accept();
433 } else {
434 Log.d("xmppService",
435 "attached jingle connection was null");
436 }
437 }
438 });
439 } else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED)
440 || (item.getEncryption() == Message.ENCRYPTION_NONE)) {
441 displayImageMessage(viewHolder, item);
442 } else if (item.getEncryption() == Message.ENCRYPTION_PGP) {
443 displayInfoMessage(viewHolder,
444 R.string.encrypted_message);
445 } else {
446 displayDecryptionFailed(viewHolder);
447 }
448 } else {
449 if (item.getEncryption() == Message.ENCRYPTION_PGP) {
450 displayInfoMessage(viewHolder,
451 R.string.encrypted_message);
452 } else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
453 displayDecryptionFailed(viewHolder);
454 } else {
455 displayTextMessage(viewHolder, item.getBody());
456 }
457 }
458
459 displayStatus(viewHolder, item);
460
461 return view;
462 }
463 };
464 messagesView.setAdapter(messageListAdapter);
465
466 return view;
467 }
468
469 protected Bitmap findSelfPicture() {
470 SharedPreferences sharedPref = PreferenceManager
471 .getDefaultSharedPreferences(getActivity()
472 .getApplicationContext());
473 boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
474 "show_phone_selfcontact_picture", true);
475
476 return UIHelper.getSelfContactPicture(conversation.getAccount(), 48,
477 showPhoneSelfContactPicture, getActivity());
478 }
479
480 @Override
481 public void onStart() {
482 super.onStart();
483 this.activity = (ConversationActivity) getActivity();
484 SharedPreferences preferences = PreferenceManager
485 .getDefaultSharedPreferences(activity);
486 this.useSubject = preferences.getBoolean("use_subject_in_muc", true);
487 if (activity.xmppConnectionServiceBound) {
488 this.onBackendConnected();
489 }
490 }
491
492 @Override
493 public void onStop() {
494 super.onStop();
495 this.conversation.setNextMessage(chatMsg.getText().toString());
496 }
497
498 public void onBackendConnected() {
499 this.conversation = activity.getSelectedConversation();
500 if (this.conversation == null) {
501 return;
502 }
503 if (this.pastedText == null) {
504 this.chatMsg.setText(conversation.getNextMessage());
505 } else {
506 chatMsg.setText(conversation.getNextMessage() + " " + pastedText);
507 pastedText = null;
508 }
509 int position = chatMsg.length();
510 Editable etext = chatMsg.getText();
511 Selection.setSelection(etext, position);
512 this.selfBitmap = findSelfPicture();
513 updateMessages();
514 if (activity.getSlidingPaneLayout().isSlideable()) {
515 if (!activity.shouldPaneBeOpen()) {
516 activity.getSlidingPaneLayout().closePane();
517 activity.getActionBar().setDisplayHomeAsUpEnabled(true);
518 activity.getActionBar().setTitle(
519 conversation.getName(useSubject));
520 activity.invalidateOptionsMenu();
521
522 }
523 }
524 if (conversation.getMode() == Conversation.MODE_MULTI) {
525 activity.xmppConnectionService
526 .setOnRenameListener(new OnRenameListener() {
527
528 @Override
529 public void onRename(final boolean success) {
530 activity.xmppConnectionService
531 .updateConversation(conversation);
532 getActivity().runOnUiThread(new Runnable() {
533
534 @Override
535 public void run() {
536 if (success) {
537 Toast.makeText(
538 getActivity(),
539 getString(R.string.your_nick_has_been_changed),
540 Toast.LENGTH_SHORT).show();
541 } else {
542 Toast.makeText(
543 getActivity(),
544 getString(R.string.nick_in_use),
545 Toast.LENGTH_SHORT).show();
546 }
547 }
548 });
549 }
550 });
551 }
552 }
553
554 private void decryptMessage(final Message message) {
555 PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
556 if (engine != null) {
557 engine.decrypt(message, new OnPgpEngineResult() {
558
559 @Override
560 public void userInputRequried(PendingIntent pi) {
561 askForPassphraseIntent = pi.getIntentSender();
562 pgpInfo.setVisibility(View.VISIBLE);
563 }
564
565 @Override
566 public void success() {
567 activity.xmppConnectionService.databaseBackend
568 .updateMessage(message);
569 updateMessages();
570 }
571
572 @Override
573 public void error(OpenPgpError openPgpError) {
574 Log.d("xmppService",
575 "decryption error" + openPgpError.getMessage());
576 message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
577 // updateMessages();
578 }
579 });
580 } else {
581 pgpInfo.setVisibility(View.VISIBLE);
582 }
583 }
584
585 public void updateMessages() {
586 ConversationActivity activity = (ConversationActivity) getActivity();
587 if (this.conversation != null) {
588 for (Message message : this.conversation.getMessages()) {
589 if ((message.getEncryption() == Message.ENCRYPTION_PGP)
590 && (message.getStatus() == Message.STATUS_RECIEVED)) {
591 decryptMessage(message);
592 break;
593 }
594 }
595 this.messageList.clear();
596 this.messageList.addAll(this.conversation.getMessages());
597 this.messageListAdapter.notifyDataSetChanged();
598 if (conversation.getMode() == Conversation.MODE_SINGLE) {
599 if (messageList.size() >= 1) {
600 makeFingerprintWarning(conversation.getLatestEncryption());
601 }
602 } else {
603 if (conversation.getMucOptions().getError() != 0) {
604 mucError.setVisibility(View.VISIBLE);
605 if (conversation.getMucOptions().getError() == MucOptions.ERROR_NICK_IN_USE) {
606 mucErrorText.setText(getString(R.string.nick_in_use));
607 }
608 } else {
609 mucError.setVisibility(View.GONE);
610 }
611 }
612 getActivity().invalidateOptionsMenu();
613 updateChatMsgHint();
614 int size = this.messageList.size();
615 if (size >= 1)
616 messagesView.setSelection(size - 1);
617 if (!activity.shouldPaneBeOpen()) {
618 conversation.markRead();
619 // TODO update notifications
620 UIHelper.updateNotification(getActivity(),
621 activity.getConversationList(), null, false);
622 activity.updateConversationList();
623 }
624 }
625 }
626
627 protected void makeFingerprintWarning(int latestEncryption) {
628 final LinearLayout fingerprintWarning = (LinearLayout) getView()
629 .findViewById(R.id.new_fingerprint);
630 if (conversation.getContact() != null) {
631 Set<String> knownFingerprints = conversation.getContact()
632 .getOtrFingerprints();
633 if ((latestEncryption == Message.ENCRYPTION_OTR)
634 && (conversation.hasValidOtrSession()
635 && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
636 .contains(conversation.getOtrFingerprint())))) {
637 fingerprintWarning.setVisibility(View.VISIBLE);
638 TextView fingerprint = (TextView) getView().findViewById(
639 R.id.otr_fingerprint);
640 fingerprint.setText(conversation.getOtrFingerprint());
641 fingerprintWarning.setOnClickListener(new OnClickListener() {
642
643 @Override
644 public void onClick(View v) {
645 AlertDialog dialog = UIHelper
646 .getVerifyFingerprintDialog(
647 (ConversationActivity) getActivity(),
648 conversation, fingerprintWarning);
649 dialog.show();
650 }
651 });
652 } else {
653 fingerprintWarning.setVisibility(View.GONE);
654 }
655 } else {
656 fingerprintWarning.setVisibility(View.GONE);
657 }
658 }
659
660 protected void sendPlainTextMessage(Message message) {
661 ConversationActivity activity = (ConversationActivity) getActivity();
662 activity.xmppConnectionService.sendMessage(message, null);
663 chatMsg.setText("");
664 }
665
666 protected void sendPgpMessage(final Message message) {
667 final ConversationActivity activity = (ConversationActivity) getActivity();
668 final XmppConnectionService xmppService = activity.xmppConnectionService;
669 final Contact contact = message.getConversation().getContact();
670 final Account account = message.getConversation().getAccount();
671 if (activity.hasPgp()) {
672 if (contact.getPgpKeyId() != 0) {
673 xmppService.getPgpEngine().hasKey(contact,
674 new OnPgpEngineResult() {
675
676 @Override
677 public void userInputRequried(PendingIntent pi) {
678 activity.runIntent(
679 pi,
680 ConversationActivity.REQUEST_SEND_MESSAGE);
681 }
682
683 @Override
684 public void success() {
685 xmppService.getPgpEngine().encrypt(account,
686 message, new OnPgpEngineResult() {
687
688 @Override
689 public void userInputRequried(
690 PendingIntent pi) {
691 activity.runIntent(
692 pi,
693 ConversationActivity.REQUEST_SEND_MESSAGE);
694 }
695
696 @Override
697 public void success() {
698 xmppService.sendMessage(
699 message, null);
700 chatMsg.setText("");
701 }
702
703 @Override
704 public void error(
705 OpenPgpError openPgpError) {
706 // TODO Auto-generated method
707 // stub
708
709 }
710 });
711 }
712
713 @Override
714 public void error(OpenPgpError openPgpError) {
715 Log.d("xmppService", "openpgp error"
716 + openPgpError.getMessage());
717 }
718 });
719
720 } else {
721 AlertDialog.Builder builder = new AlertDialog.Builder(
722 getActivity());
723 builder.setTitle("No openPGP key found");
724 builder.setIconAttribute(android.R.attr.alertDialogIcon);
725 builder.setMessage("There is no openPGP key associated with this contact");
726 builder.setNegativeButton("Cancel", null);
727 builder.setPositiveButton("Send plain text",
728 new DialogInterface.OnClickListener() {
729
730 @Override
731 public void onClick(DialogInterface dialog,
732 int which) {
733 conversation
734 .setNextEncryption(Message.ENCRYPTION_NONE);
735 message.setEncryption(Message.ENCRYPTION_NONE);
736 xmppService.sendMessage(message, null);
737 chatMsg.setText("");
738 }
739 });
740 builder.create().show();
741 }
742 }
743 }
744
745 protected void sendOtrMessage(final Message message) {
746 ConversationActivity activity = (ConversationActivity) getActivity();
747 final XmppConnectionService xmppService = activity.xmppConnectionService;
748 if (conversation.hasValidOtrSession()) {
749 activity.xmppConnectionService.sendMessage(message, null);
750 chatMsg.setText("");
751 } else {
752 activity.selectPresence(message.getConversation(),
753 new OnPresenceSelected() {
754
755 @Override
756 public void onPresenceSelected(boolean success,
757 String presence) {
758 if (success) {
759 xmppService.sendMessage(message, presence);
760 chatMsg.setText("");
761 }
762 }
763
764 @Override
765 public void onSendPlainTextInstead() {
766 message.setEncryption(Message.ENCRYPTION_NONE);
767 xmppService.sendMessage(message, null);
768 chatMsg.setText("");
769 }
770 }, "otr");
771 }
772 }
773
774 private static class ViewHolder {
775
776 protected Button download_button;
777 protected ImageView image;
778 protected ImageView indicator;
779 protected TextView time;
780 protected TextView messageBody;
781 protected ImageView contact_picture;
782
783 }
784
785 private class BitmapCache {
786 private HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
787 private Bitmap error = null;
788
789 public Bitmap get(String name, Contact contact, Context context) {
790 if (bitmaps.containsKey(name)) {
791 return bitmaps.get(name);
792 } else {
793 Bitmap bm;
794 if (contact != null) {
795 bm = UIHelper
796 .getContactPicture(contact, 48, context, false);
797 } else {
798 bm = UIHelper.getContactPicture(name, 48, context, false);
799 }
800 bitmaps.put(name, bm);
801 return bm;
802 }
803 }
804 }
805
806 public void setText(String text) {
807 this.pastedText = text;
808 }
809}