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