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