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