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 (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 if (conversation.getMode() == Conversation.MODE_MULTI) {
128 chatMsg.setHint(getString(R.string.send_message_to_conference));
129 } else {
130 switch (conversation.getNextEncryption()) {
131 case Message.ENCRYPTION_NONE:
132 chatMsg.setHint(getString(R.string.send_plain_text_message));
133 break;
134 case Message.ENCRYPTION_OTR:
135 chatMsg.setHint(getString(R.string.send_otr_message));
136 break;
137 case Message.ENCRYPTION_PGP:
138 chatMsg.setHint(getString(R.string.send_pgp_message));
139 break;
140 default:
141 break;
142 }
143 }
144 }
145
146 @Override
147 public View onCreateView(final LayoutInflater inflater,
148 ViewGroup container, Bundle savedInstanceState) {
149
150 final DisplayMetrics metrics = getResources().getDisplayMetrics();
151
152 this.inflater = inflater;
153
154 final View view = inflater.inflate(R.layout.fragment_conversation,
155 container, false);
156 chatMsg = (EditText) view.findViewById(R.id.textinput);
157
158 ImageButton sendButton = (ImageButton) view
159 .findViewById(R.id.textSendButton);
160 sendButton.setOnClickListener(this.sendMsgListener);
161
162 pgpInfo = (LinearLayout) view.findViewById(R.id.pgp_keyentry);
163 pgpInfo.setOnClickListener(clickToDecryptListener);
164 mucError = (LinearLayout) view.findViewById(R.id.muc_error);
165 mucError.setOnClickListener(clickToMuc);
166 mucErrorText = (TextView) view.findViewById(R.id.muc_error_msg);
167
168 messagesView = (ListView) view.findViewById(R.id.messages_view);
169
170 messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
171 .getApplicationContext(), R.layout.message_sent,
172 this.messageList) {
173
174 private static final int SENT = 0;
175 private static final int RECIEVED = 1;
176
177 @Override
178 public int getViewTypeCount() {
179 return 2;
180 }
181
182 @Override
183 public int getItemViewType(int position) {
184 if (getItem(position).getStatus() <= Message.STATUS_RECIEVED) {
185 return RECIEVED;
186 } else {
187 return SENT;
188 }
189 }
190
191 private void displayStatus(ViewHolder viewHolder, Message message) {
192 String filesize = null;
193 String info = null;
194 boolean error = false;
195 if (message.getType() == Message.TYPE_IMAGE) {
196 String[] fileParams = message.getBody().split(",");
197 try {
198 long size = Long.parseLong(fileParams[0]);
199 filesize = size / 1024 + " KB";
200 } catch (NumberFormatException e) {
201 filesize = "0 KB";
202 }
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(getContext(), 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 if (viewHolder.download_button != null) {
268 viewHolder.download_button.setVisibility(View.GONE);
269 }
270 viewHolder.image.setVisibility(View.GONE);
271 viewHolder.messageBody.setVisibility(View.VISIBLE);
272 viewHolder.messageBody.setText(getString(r));
273 viewHolder.messageBody.setTextColor(0xff33B5E5);
274 viewHolder.messageBody.setTypeface(null, Typeface.ITALIC);
275 }
276
277 private void displayDecryptionFailed(ViewHolder viewHolder) {
278 viewHolder.download_button.setVisibility(View.GONE);
279 viewHolder.image.setVisibility(View.GONE);
280 viewHolder.messageBody.setVisibility(View.VISIBLE);
281 viewHolder.messageBody
282 .setText(getString(R.string.decryption_failed));
283 viewHolder.messageBody.setTextColor(0xFFe92727);
284 viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
285 }
286
287 private void displayTextMessage(ViewHolder viewHolder, String text) {
288 if (viewHolder.download_button != null) {
289 viewHolder.download_button.setVisibility(View.GONE);
290 }
291 viewHolder.image.setVisibility(View.GONE);
292 viewHolder.messageBody.setVisibility(View.VISIBLE);
293 if (text != null) {
294 viewHolder.messageBody.setText(text.trim());
295 } else {
296 viewHolder.messageBody.setText("");
297 }
298 viewHolder.messageBody.setTextColor(0xff333333);
299 viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
300 }
301
302 private void displayImageMessage(ViewHolder viewHolder,
303 final Message message) {
304 if (viewHolder.download_button != null) {
305 viewHolder.download_button.setVisibility(View.GONE);
306 }
307 viewHolder.messageBody.setVisibility(View.GONE);
308 viewHolder.image.setVisibility(View.VISIBLE);
309 String[] fileParams = message.getBody().split(",");
310 if (fileParams.length == 3) {
311 double target = metrics.density * 288;
312 int w = Integer.parseInt(fileParams[1]);
313 int h = Integer.parseInt(fileParams[2]);
314 int scalledW;
315 int scalledH;
316 if (w <= h) {
317 scalledW = (int) (w / ((double) h / target));
318 scalledH = (int) target;
319 } else {
320 scalledW = (int) target;
321 scalledH = (int) (h / ((double) w / target));
322 }
323 viewHolder.image
324 .setLayoutParams(new LinearLayout.LayoutParams(
325 scalledW, scalledH));
326 }
327 activity.loadBitmap(message, viewHolder.image);
328 viewHolder.image.setOnClickListener(new OnClickListener() {
329
330 @Override
331 public void onClick(View v) {
332 Intent intent = new Intent(Intent.ACTION_VIEW);
333 intent.setDataAndType(
334 ImageProvider.getContentUri(message), "image/*");
335 startActivity(intent);
336 }
337 });
338 }
339
340 @Override
341 public View getView(int position, View view, ViewGroup parent) {
342 final Message item = getItem(position);
343 int type = getItemViewType(position);
344 ViewHolder viewHolder;
345 if (view == null) {
346 viewHolder = new ViewHolder();
347 switch (type) {
348 case SENT:
349 view = (View) inflater.inflate(R.layout.message_sent,
350 null);
351 viewHolder.contact_picture = (ImageView) view
352 .findViewById(R.id.message_photo);
353 viewHolder.contact_picture.setImageBitmap(selfBitmap);
354 break;
355 case RECIEVED:
356 view = (View) inflater.inflate(
357 R.layout.message_recieved, null);
358 viewHolder.contact_picture = (ImageView) view
359 .findViewById(R.id.message_photo);
360
361 viewHolder.download_button = (Button) view
362 .findViewById(R.id.download_button);
363
364 if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
365
366 viewHolder.contact_picture
367 .setImageBitmap(mBitmapCache.get(
368 item.getConversation().getName(
369 useSubject), item
370 .getConversation()
371 .getContact(),
372 getActivity()
373 .getApplicationContext()));
374
375 }
376 break;
377 default:
378 viewHolder = null;
379 break;
380 }
381 viewHolder.indicator = (ImageView) view
382 .findViewById(R.id.security_indicator);
383 viewHolder.image = (ImageView) view
384 .findViewById(R.id.message_image);
385 viewHolder.messageBody = (TextView) view
386 .findViewById(R.id.message_body);
387 viewHolder.time = (TextView) view
388 .findViewById(R.id.message_time);
389 view.setTag(viewHolder);
390 } else {
391 viewHolder = (ViewHolder) view.getTag();
392 }
393
394 if (type == RECIEVED) {
395 if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
396 viewHolder.contact_picture.setImageBitmap(mBitmapCache
397 .get(item.getCounterpart(), null, getActivity()
398 .getApplicationContext()));
399 viewHolder.contact_picture
400 .setOnClickListener(new OnClickListener() {
401
402 @Override
403 public void onClick(View v) {
404 highlightInConference(item.getCounterpart());
405 }
406 });
407 }
408 }
409
410 if (item.getType() == Message.TYPE_IMAGE) {
411 if (item.getStatus() == Message.STATUS_RECIEVING) {
412 displayInfoMessage(viewHolder, R.string.receiving_image);
413 } else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) {
414 viewHolder.image.setVisibility(View.GONE);
415 viewHolder.messageBody.setVisibility(View.GONE);
416 viewHolder.download_button.setVisibility(View.VISIBLE);
417 viewHolder.download_button
418 .setOnClickListener(new OnClickListener() {
419
420 @Override
421 public void onClick(View v) {
422 JingleConnection connection = item
423 .getJingleConnection();
424 if (connection != null) {
425 connection.accept();
426 } else {
427 Log.d("xmppService",
428 "attached jingle connection was null");
429 }
430 }
431 });
432 } else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED)
433 || (item.getEncryption() == Message.ENCRYPTION_NONE)) {
434 displayImageMessage(viewHolder, item);
435 } else if (item.getEncryption() == Message.ENCRYPTION_PGP) {
436 displayInfoMessage(viewHolder,
437 R.string.encrypted_message);
438 } else {
439 displayDecryptionFailed(viewHolder);
440 }
441 } else {
442 if (item.getEncryption() == Message.ENCRYPTION_PGP) {
443 displayInfoMessage(viewHolder,
444 R.string.encrypted_message);
445 } else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
446 displayDecryptionFailed(viewHolder);
447 } else {
448 displayTextMessage(viewHolder, item.getBody());
449 }
450 }
451
452 displayStatus(viewHolder, item);
453
454 return view;
455 }
456 };
457 messagesView.setAdapter(messageListAdapter);
458
459 return view;
460 }
461
462 protected void highlightInConference(String nick) {
463 String oldString = chatMsg.getText().toString().trim();
464 if (oldString.isEmpty()) {
465 chatMsg.setText(nick+": ");
466 } else {
467 chatMsg.setText(oldString+" "+nick+" ");
468 }
469 int position = chatMsg.length();
470 Editable etext = chatMsg.getText();
471 Selection.setSelection(etext, position);
472 }
473
474 protected Bitmap findSelfPicture() {
475 SharedPreferences sharedPref = PreferenceManager
476 .getDefaultSharedPreferences(getActivity()
477 .getApplicationContext());
478 boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
479 "show_phone_selfcontact_picture", true);
480
481 return UIHelper.getSelfContactPicture(conversation.getAccount(), 48,
482 showPhoneSelfContactPicture, getActivity());
483 }
484
485 @Override
486 public void onStart() {
487 super.onStart();
488 this.activity = (ConversationActivity) getActivity();
489 SharedPreferences preferences = PreferenceManager
490 .getDefaultSharedPreferences(activity);
491 this.useSubject = preferences.getBoolean("use_subject_in_muc", true);
492 if (activity.xmppConnectionServiceBound) {
493 this.onBackendConnected();
494 }
495 }
496
497 @Override
498 public void onStop() {
499 super.onStop();
500 if (this.conversation != null) {
501 this.conversation.setNextMessage(chatMsg.getText().toString());
502 }
503 }
504
505 public void onBackendConnected() {
506 this.conversation = activity.getSelectedConversation();
507 if (this.conversation == null) {
508 return;
509 }
510 String oldString = conversation.getNextMessage().trim();
511 if (this.pastedText == null) {
512 this.chatMsg.setText(oldString);
513 } else {
514
515 if (oldString.isEmpty()) {
516 chatMsg.setText(pastedText);
517 } else {
518 chatMsg.setText(oldString + " " + pastedText);
519 }
520 pastedText = null;
521 }
522 int position = chatMsg.length();
523 Editable etext = chatMsg.getText();
524 Selection.setSelection(etext, position);
525 this.selfBitmap = findSelfPicture();
526 updateMessages();
527 if (activity.getSlidingPaneLayout().isSlideable()) {
528 if (!activity.shouldPaneBeOpen()) {
529 activity.getSlidingPaneLayout().closePane();
530 activity.getActionBar().setDisplayHomeAsUpEnabled(true);
531 activity.getActionBar().setHomeButtonEnabled(true);
532 activity.getActionBar().setTitle(
533 conversation.getName(useSubject));
534 activity.invalidateOptionsMenu();
535
536 }
537 }
538 if (conversation.getMode() == Conversation.MODE_MULTI) {
539 activity.xmppConnectionService
540 .setOnRenameListener(new OnRenameListener() {
541
542 @Override
543 public void onRename(final boolean success) {
544 activity.xmppConnectionService
545 .updateConversation(conversation);
546 getActivity().runOnUiThread(new Runnable() {
547
548 @Override
549 public void run() {
550 if (success) {
551 Toast.makeText(
552 getActivity(),
553 getString(R.string.your_nick_has_been_changed),
554 Toast.LENGTH_SHORT).show();
555 } else {
556 Toast.makeText(
557 getActivity(),
558 getString(R.string.nick_in_use),
559 Toast.LENGTH_SHORT).show();
560 }
561 }
562 });
563 }
564 });
565 }
566 }
567
568 private void decryptMessage(final Message message) {
569 PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
570 if (engine != null) {
571 engine.decrypt(message, new UiCallback() {
572
573 @Override
574 public void userInputRequried(PendingIntent pi) {
575 askForPassphraseIntent = pi.getIntentSender();
576 pgpInfo.setVisibility(View.VISIBLE);
577 }
578
579 @Override
580 public void success() {
581 activity.xmppConnectionService.databaseBackend
582 .updateMessage(message);
583 updateMessages();
584 }
585
586 @Override
587 public void error(int error) {
588 message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
589 // updateMessages();
590 }
591 });
592 } else {
593 pgpInfo.setVisibility(View.VISIBLE);
594 }
595 }
596
597 public void updateMessages() {
598 if (getView() == null) {
599 return;
600 }
601 ConversationActivity activity = (ConversationActivity) getActivity();
602 if (this.conversation != null) {
603 for (Message message : this.conversation.getMessages()) {
604 if ((message.getEncryption() == Message.ENCRYPTION_PGP)
605 && ((message.getStatus() == Message.STATUS_RECIEVED) || (message
606 .getStatus() == Message.STATUS_SEND))) {
607 decryptMessage(message);
608 break;
609 }
610 }
611 this.messageList.clear();
612 this.messageList.addAll(this.conversation.getMessages());
613 this.messageListAdapter.notifyDataSetChanged();
614 if (conversation.getMode() == Conversation.MODE_SINGLE) {
615 if (messageList.size() >= 1) {
616 makeFingerprintWarning(conversation.getLatestEncryption());
617 }
618 } else {
619 if (conversation.getMucOptions().getError() != 0) {
620 mucError.setVisibility(View.VISIBLE);
621 if (conversation.getMucOptions().getError() == MucOptions.ERROR_NICK_IN_USE) {
622 mucErrorText.setText(getString(R.string.nick_in_use));
623 }
624 } else {
625 mucError.setVisibility(View.GONE);
626 }
627 }
628 getActivity().invalidateOptionsMenu();
629 updateChatMsgHint();
630 int size = this.messageList.size();
631 if (size >= 1)
632 messagesView.setSelection(size - 1);
633 if (!activity.shouldPaneBeOpen()) {
634 conversation.markRead();
635 // TODO update notifications
636 UIHelper.updateNotification(getActivity(),
637 activity.getConversationList(), null, false);
638 activity.updateConversationList();
639 }
640 }
641 }
642
643 protected void makeFingerprintWarning(int latestEncryption) {
644 final LinearLayout fingerprintWarning = (LinearLayout) getView()
645 .findViewById(R.id.new_fingerprint);
646 Set<String> knownFingerprints = conversation.getContact()
647 .getOtrFingerprints();
648 if ((latestEncryption == Message.ENCRYPTION_OTR)
649 && (conversation.hasValidOtrSession()
650 && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
651 .contains(conversation.getOtrFingerprint())))) {
652 fingerprintWarning.setVisibility(View.VISIBLE);
653 TextView fingerprint = (TextView) getView().findViewById(
654 R.id.otr_fingerprint);
655 fingerprint.setText(conversation.getOtrFingerprint());
656 fingerprintWarning.setOnClickListener(new OnClickListener() {
657
658 @Override
659 public void onClick(View v) {
660 AlertDialog dialog = UIHelper.getVerifyFingerprintDialog(
661 (ConversationActivity) getActivity(), conversation,
662 fingerprintWarning);
663 dialog.show();
664 }
665 });
666 } else {
667 fingerprintWarning.setVisibility(View.GONE);
668 }
669 }
670
671 protected void sendPlainTextMessage(Message message) {
672 ConversationActivity activity = (ConversationActivity) getActivity();
673 activity.xmppConnectionService.sendMessage(message, null);
674 chatMsg.setText("");
675 }
676
677 protected void sendPgpMessage(final Message message) {
678 activity.pendingMessage = message;
679 final ConversationActivity activity = (ConversationActivity) getActivity();
680 final XmppConnectionService xmppService = activity.xmppConnectionService;
681 final Contact contact = message.getConversation().getContact();
682 if (activity.hasPgp()) {
683 if (conversation.getMode() == Conversation.MODE_SINGLE) {
684 if (contact.getPgpKeyId() != 0) {
685 xmppService.getPgpEngine().hasKey(contact, new UiCallback() {
686
687 @Override
688 public void userInputRequried(PendingIntent pi) {
689 activity.runIntent(pi,
690 ConversationActivity.REQUEST_ENCRYPT_MESSAGE);
691 }
692
693 @Override
694 public void success() {
695 activity.encryptTextMessage();
696 }
697
698 @Override
699 public void error(int error) {
700
701 }
702 });
703
704 } else {
705 showNoPGPKeyDialog(false,new DialogInterface.OnClickListener() {
706
707 @Override
708 public void onClick(DialogInterface dialog, int which) {
709 conversation.setNextEncryption(Message.ENCRYPTION_NONE);
710 message.setEncryption(Message.ENCRYPTION_NONE);
711 xmppService.sendMessage(message, null);
712 chatMsg.setText("");
713 }
714 });
715 }
716 } else {
717 if (conversation.getMucOptions().pgpKeysInUse()) {
718 if (!conversation.getMucOptions().everybodyHasKeys()) {
719 Toast warning = Toast.makeText(getActivity(), R.string.missing_public_keys, Toast.LENGTH_LONG);
720 warning.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
721 warning.show();
722 }
723 activity.encryptTextMessage();
724 } else {
725 showNoPGPKeyDialog(true,new DialogInterface.OnClickListener() {
726
727 @Override
728 public void onClick(DialogInterface dialog, int which) {
729 conversation.setNextEncryption(Message.ENCRYPTION_NONE);
730 message.setEncryption(Message.ENCRYPTION_NONE);
731 xmppService.sendMessage(message, null);
732 chatMsg.setText("");
733 }
734 });
735 }
736 }
737 }
738 }
739
740 public void showNoPGPKeyDialog(boolean plural, DialogInterface.OnClickListener listener) {
741 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
742 builder.setIconAttribute(android.R.attr.alertDialogIcon);
743 if (plural) {
744 builder.setTitle(getString(R.string.no_pgp_keys));
745 builder.setMessage(getText(R.string.contacts_have_no_pgp_keys));
746 } else {
747 builder.setTitle(getString(R.string.no_pgp_key));
748 builder.setMessage(getText(R.string.contact_has_no_pgp_key));
749 }
750 builder.setNegativeButton(getString(R.string.cancel), null);
751 builder.setPositiveButton(getString(R.string.send_unencrypted),
752 listener);
753 builder.create().show();
754 }
755
756 protected void sendOtrMessage(final Message message) {
757 ConversationActivity activity = (ConversationActivity) getActivity();
758 final XmppConnectionService xmppService = activity.xmppConnectionService;
759 if (conversation.hasValidOtrSession()) {
760 activity.xmppConnectionService.sendMessage(message, null);
761 chatMsg.setText("");
762 } else {
763 activity.selectPresence(message.getConversation(),
764 new OnPresenceSelected() {
765
766 @Override
767 public void onPresenceSelected(boolean success,
768 String presence) {
769 if (success) {
770 xmppService.sendMessage(message, presence);
771 chatMsg.setText("");
772 }
773 }
774
775 @Override
776 public void onSendPlainTextInstead() {
777 message.setEncryption(Message.ENCRYPTION_NONE);
778 xmppService.sendMessage(message, null);
779 chatMsg.setText("");
780 }
781 }, "otr");
782 }
783 }
784
785 private static class ViewHolder {
786
787 protected Button download_button;
788 protected ImageView image;
789 protected ImageView indicator;
790 protected TextView time;
791 protected TextView messageBody;
792 protected ImageView contact_picture;
793
794 }
795
796 private class BitmapCache {
797 private HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
798
799 public Bitmap get(String name, Contact contact, Context context) {
800 if (bitmaps.containsKey(name)) {
801 return bitmaps.get(name);
802 } else {
803 Bitmap bm;
804 if (contact != null) {
805 bm = UIHelper
806 .getContactPicture(contact, 48, context, false);
807 } else {
808 bm = UIHelper.getContactPicture(name, 48, context, false);
809 }
810 bitmaps.put(name, bm);
811 return bm;
812 }
813 }
814 }
815
816 public void setText(String text) {
817 this.pastedText = text;
818 }
819
820 public void clearInputField() {
821 this.chatMsg.setText("");
822 }
823}