1package eu.siacs.conversations.ui;
2
3import java.util.ArrayList;
4import java.util.List;
5import java.util.Set;
6import java.util.concurrent.ConcurrentLinkedQueue;
7
8import net.java.otr4j.session.SessionStatus;
9import eu.siacs.conversations.R;
10import eu.siacs.conversations.crypto.PgpEngine;
11import eu.siacs.conversations.entities.Account;
12import eu.siacs.conversations.entities.Contact;
13import eu.siacs.conversations.entities.Conversation;
14import eu.siacs.conversations.entities.Message;
15import eu.siacs.conversations.entities.MucOptions;
16import eu.siacs.conversations.entities.Presences;
17import eu.siacs.conversations.services.XmppConnectionService;
18import eu.siacs.conversations.ui.EditMessage.OnEnterPressed;
19import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected;
20import eu.siacs.conversations.ui.XmppActivity.OnValueEdited;
21import eu.siacs.conversations.ui.adapter.MessageAdapter;
22import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked;
23import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked;
24import eu.siacs.conversations.utils.UIHelper;
25import android.app.AlertDialog;
26import android.app.Fragment;
27import android.app.PendingIntent;
28import android.content.Context;
29import android.content.DialogInterface;
30import android.content.Intent;
31import android.content.IntentSender;
32import android.content.IntentSender.SendIntentException;
33import android.os.Bundle;
34import android.text.Editable;
35import android.text.Selection;
36import android.view.Gravity;
37import android.view.KeyEvent;
38import android.view.LayoutInflater;
39import android.view.View;
40import android.view.View.OnClickListener;
41import android.view.ViewGroup;
42import android.view.inputmethod.EditorInfo;
43import android.view.inputmethod.InputMethodManager;
44import android.widget.AbsListView.OnScrollListener;
45import android.widget.TextView.OnEditorActionListener;
46import android.widget.AbsListView;
47
48import android.widget.ListView;
49import android.widget.ImageButton;
50import android.widget.RelativeLayout;
51import android.widget.TextView;
52import android.widget.Toast;
53
54public class ConversationFragment extends Fragment {
55
56 protected Conversation conversation;
57 protected ListView messagesView;
58 protected LayoutInflater inflater;
59 protected List<Message> messageList = new ArrayList<Message>();
60 protected MessageAdapter messageListAdapter;
61 protected Contact contact;
62
63 protected String queuedPqpMessage = null;
64
65 private EditMessage mEditMessage;
66 private ImageButton mSendButton;
67 private String pastedText = null;
68 private RelativeLayout snackbar;
69 private TextView snackbarMessage;
70 private TextView snackbarAction;
71
72 private boolean messagesLoaded = false;
73
74 private IntentSender askForPassphraseIntent = null;
75
76
77 private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<Message>();
78 private boolean mDecryptJobRunning = false;
79
80 private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() {
81
82 @Override
83 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
84 if (actionId == EditorInfo.IME_ACTION_SEND) {
85 InputMethodManager imm = (InputMethodManager) v.getContext()
86 .getSystemService(Context.INPUT_METHOD_SERVICE);
87 imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
88 sendMessage();
89 return true;
90 } else {
91 return false;
92 }
93 }
94 };
95
96 private OnClickListener mSendButtonListener = new OnClickListener() {
97
98 @Override
99 public void onClick(View v) {
100 sendMessage();
101 }
102 };
103 protected OnClickListener clickToDecryptListener = new OnClickListener() {
104
105 @Override
106 public void onClick(View v) {
107 if (activity.hasPgp() && askForPassphraseIntent != null) {
108 try {
109 getActivity().startIntentSenderForResult(
110 askForPassphraseIntent,
111 ConversationActivity.REQUEST_DECRYPT_PGP, null, 0,
112 0, 0);
113 } catch (SendIntentException e) {
114 //
115 }
116 }
117 }
118 };
119
120 private OnClickListener clickToMuc = new OnClickListener() {
121
122 @Override
123 public void onClick(View v) {
124 Intent intent = new Intent(getActivity(),
125 ConferenceDetailsActivity.class);
126 intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC);
127 intent.putExtra("uuid", conversation.getUuid());
128 startActivity(intent);
129 }
130 };
131
132 private OnClickListener leaveMuc = new OnClickListener() {
133
134 @Override
135 public void onClick(View v) {
136 activity.endConversation(conversation);
137 }
138 };
139
140 private OnClickListener joinMuc = new OnClickListener() {
141
142 @Override
143 public void onClick(View v) {
144 activity.xmppConnectionService.joinMuc(conversation);
145 }
146 };
147
148 private OnClickListener enterPassword = new OnClickListener() {
149
150 @Override
151 public void onClick(View v) {
152 MucOptions muc = conversation.getMucOptions();
153 String password = muc.getPassword();
154 if (password == null) {
155 password = "";
156 }
157 activity.quickPasswordEdit(password, new OnValueEdited() {
158
159 @Override
160 public void onValueEdited(String value) {
161 activity.xmppConnectionService.providePasswordForMuc(
162 conversation, value);
163 }
164 });
165 }
166 };
167
168 private OnScrollListener mOnScrollListener = new OnScrollListener() {
169
170 @Override
171 public void onScrollStateChanged(AbsListView view, int scrollState) {
172 // TODO Auto-generated method stub
173
174 }
175
176 @Override
177 public void onScroll(AbsListView view, int firstVisibleItem,
178 int visibleItemCount, int totalItemCount) {
179 if (firstVisibleItem == 0 && messagesLoaded) {
180 long timestamp = messageList.get(0).getTimeSent();
181 messagesLoaded = false;
182 int size = activity.xmppConnectionService.loadMoreMessages(
183 conversation, timestamp);
184 messageList.clear();
185 messageList.addAll(conversation.getMessages());
186 updateStatusMessages();
187 messageListAdapter.notifyDataSetChanged();
188 if (size != 0) {
189 messagesLoaded = true;
190 }
191 messagesView.setSelectionFromTop(size + 1, 0);
192 }
193 }
194 };
195
196 private ConversationActivity activity;
197
198 private void sendMessage() {
199 if (this.conversation == null) {
200 return;
201 }
202 if (mEditMessage.getText().length() < 1) {
203 if (this.conversation.getMode() == Conversation.MODE_MULTI) {
204 conversation.setNextPresence(null);
205 updateChatMsgHint();
206 }
207 return;
208 }
209 Message message = new Message(conversation, mEditMessage.getText()
210 .toString(), conversation.getNextEncryption(activity
211 .forceEncryption()));
212 if (conversation.getMode() == Conversation.MODE_MULTI) {
213 if (conversation.getNextPresence() != null) {
214 message.setPresence(conversation.getNextPresence());
215 message.setType(Message.TYPE_PRIVATE);
216 conversation.setNextPresence(null);
217 }
218 }
219 if (conversation.getNextEncryption(activity.forceEncryption()) == Message.ENCRYPTION_OTR) {
220 sendOtrMessage(message);
221 } else if (conversation.getNextEncryption(activity.forceEncryption()) == Message.ENCRYPTION_PGP) {
222 sendPgpMessage(message);
223 } else {
224 sendPlainTextMessage(message);
225 }
226 }
227
228 public void updateChatMsgHint() {
229 if (conversation.getMode() == Conversation.MODE_MULTI
230 && conversation.getNextPresence() != null) {
231 this.mEditMessage.setHint(getString(
232 R.string.send_private_message_to,
233 conversation.getNextPresence()));
234 } else {
235 switch (conversation.getNextEncryption(activity.forceEncryption())) {
236 case Message.ENCRYPTION_NONE:
237 mEditMessage
238 .setHint(getString(R.string.send_plain_text_message));
239 break;
240 case Message.ENCRYPTION_OTR:
241 mEditMessage.setHint(getString(R.string.send_otr_message));
242 break;
243 case Message.ENCRYPTION_PGP:
244 mEditMessage.setHint(getString(R.string.send_pgp_message));
245 break;
246 default:
247 break;
248 }
249 }
250 }
251
252 @Override
253 public View onCreateView(final LayoutInflater inflater,
254 ViewGroup container, Bundle savedInstanceState) {
255 final View view = inflater.inflate(R.layout.fragment_conversation,
256 container, false);
257 mEditMessage = (EditMessage) view.findViewById(R.id.textinput);
258 mEditMessage.setOnClickListener(new OnClickListener() {
259
260 @Override
261 public void onClick(View v) {
262 activity.hideConversationsOverview();
263 }
264 });
265 mEditMessage.setOnEditorActionListener(mEditorActionListener);
266 mEditMessage.setOnEnterPressedListener(new OnEnterPressed() {
267
268 @Override
269 public void onEnterPressed() {
270 sendMessage();
271 }
272 });
273
274 mSendButton = (ImageButton) view.findViewById(R.id.textSendButton);
275 mSendButton.setOnClickListener(this.mSendButtonListener);
276
277 snackbar = (RelativeLayout) view.findViewById(R.id.snackbar);
278 snackbarMessage = (TextView) view.findViewById(R.id.snackbar_message);
279 snackbarAction = (TextView) view.findViewById(R.id.snackbar_action);
280
281 messagesView = (ListView) view.findViewById(R.id.messages_view);
282 messagesView.setOnScrollListener(mOnScrollListener);
283 messagesView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
284 messageListAdapter = new MessageAdapter(
285 (ConversationActivity) getActivity(), this.messageList);
286 messageListAdapter
287 .setOnContactPictureClicked(new OnContactPictureClicked() {
288
289 @Override
290 public void onContactPictureClicked(Message message) {
291 if (message.getStatus() <= Message.STATUS_RECEIVED) {
292 if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
293 if (message.getPresence() != null) {
294 highlightInConference(message.getPresence());
295 } else {
296 highlightInConference(message
297 .getCounterpart());
298 }
299 } else {
300 Contact contact = message.getConversation()
301 .getContact();
302 if (contact.showInRoster()) {
303 activity.switchToContactDetails(contact);
304 } else {
305 activity.showAddToRosterDialog(message
306 .getConversation());
307 }
308 }
309 }
310 }
311 });
312 messageListAdapter
313 .setOnContactPictureLongClicked(new OnContactPictureLongClicked() {
314
315 @Override
316 public void onContactPictureLongClicked(Message message) {
317 if (message.getStatus() <= Message.STATUS_RECEIVED) {
318 if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
319 if (message.getPresence() != null) {
320 privateMessageWith(message.getPresence());
321 } else {
322 privateMessageWith(message.getCounterpart());
323 }
324 }
325 }
326 }
327 });
328 messagesView.setAdapter(messageListAdapter);
329
330 return view;
331 }
332
333 protected void privateMessageWith(String counterpart) {
334 this.mEditMessage.setText("");
335 this.conversation.setNextPresence(counterpart);
336 updateChatMsgHint();
337 }
338
339 protected void highlightInConference(String nick) {
340 String oldString = mEditMessage.getText().toString().trim();
341 if (oldString.isEmpty() || mEditMessage.getSelectionStart() == 0) {
342 mEditMessage.getText().insert(0, nick + ": ");
343 } else {
344 if (mEditMessage.getText().charAt(
345 mEditMessage.getSelectionStart() - 1) != ' ') {
346 nick = " " + nick;
347 }
348 mEditMessage.getText().insert(mEditMessage.getSelectionStart(),
349 nick + " ");
350 }
351 }
352
353 @Override
354 public void onStart() {
355 super.onStart();
356 this.activity = (ConversationActivity) getActivity();
357 if (activity.xmppConnectionServiceBound) {
358 this.onBackendConnected();
359 }
360 }
361
362 @Override
363 public void onStop() {
364 mDecryptJobRunning = false;
365 super.onStop();
366 if (this.conversation != null) {
367 this.conversation.setNextMessage(mEditMessage.getText().toString());
368 }
369 }
370
371 public void onBackendConnected() {
372 this.activity = (ConversationActivity) getActivity();
373 this.conversation = activity.getSelectedConversation();
374 if (this.conversation == null) {
375 return;
376 }
377 String oldString = conversation.getNextMessage().trim();
378 if (this.pastedText == null) {
379 this.mEditMessage.setText(oldString);
380 } else {
381
382 if (oldString.isEmpty()) {
383 mEditMessage.setText(pastedText);
384 } else {
385 mEditMessage.setText(oldString + " " + pastedText);
386 }
387 pastedText = null;
388 }
389 int position = mEditMessage.length();
390 Editable etext = mEditMessage.getText();
391 Selection.setSelection(etext, position);
392 if (activity.isConversationsOverviewHideable()) {
393 if (!activity.shouldPaneBeOpen()) {
394 activity.hideConversationsOverview();
395 activity.openConversation(conversation);
396 }
397 }
398 if (this.conversation.getMode() == Conversation.MODE_MULTI) {
399 conversation.setNextPresence(null);
400 }
401 updateMessages();
402 }
403
404 public void updateMessages() {
405 if (getView() == null) {
406 return;
407 }
408 hideSnackbar();
409 final ConversationActivity activity = (ConversationActivity) getActivity();
410 if (this.conversation != null) {
411 final Contact contact = this.conversation.getContact();
412 if (this.conversation.isMuted()) {
413 showSnackbar(R.string.notifications_disabled, R.string.enable,
414 new OnClickListener() {
415
416 @Override
417 public void onClick(View v) {
418 conversation.setMutedTill(0);
419 activity.xmppConnectionService.databaseBackend
420 .updateConversation(conversation);
421 updateMessages();
422 }
423 });
424 } else if (!contact.showInRoster()
425 && contact
426 .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
427 showSnackbar(R.string.contact_added_you, R.string.add_back,
428 new OnClickListener() {
429
430 @Override
431 public void onClick(View v) {
432 activity.xmppConnectionService
433 .createContact(contact);
434 activity.switchToContactDetails(contact);
435 }
436 });
437 }
438 for (Message message : this.conversation.getMessages()) {
439 if ((message.getEncryption() == Message.ENCRYPTION_PGP)
440 && ((message.getStatus() == Message.STATUS_RECEIVED) || (message
441 .getStatus() == Message.STATUS_SEND))) {
442 if (!mEncryptedMessages.contains(message)) {
443 mEncryptedMessages.add(message);
444 }
445 }
446 }
447 decryptNext();
448 this.messageList.clear();
449 if (this.conversation.getMessages().size() == 0) {
450 messagesLoaded = false;
451 } else {
452 this.messageList.addAll(this.conversation.getMessages());
453 messagesLoaded = true;
454 updateStatusMessages();
455 }
456 this.messageListAdapter.notifyDataSetChanged();
457 if (conversation.getMode() == Conversation.MODE_SINGLE) {
458 if (messageList.size() >= 1) {
459 makeFingerprintWarning(conversation.getLatestEncryption());
460 }
461 } else {
462 if (!conversation.getMucOptions().online()
463 && conversation.getAccount().getStatus() == Account.STATUS_ONLINE) {
464 int error = conversation.getMucOptions().getError();
465 switch (error) {
466 case MucOptions.ERROR_NICK_IN_USE:
467 showSnackbar(R.string.nick_in_use, R.string.edit,
468 clickToMuc);
469 break;
470 case MucOptions.ERROR_ROOM_NOT_FOUND:
471 showSnackbar(R.string.conference_not_found,
472 R.string.leave, leaveMuc);
473 break;
474 case MucOptions.ERROR_PASSWORD_REQUIRED:
475 showSnackbar(R.string.conference_requires_password,
476 R.string.enter_password, enterPassword);
477 break;
478 case MucOptions.ERROR_BANNED:
479 showSnackbar(R.string.conference_banned,
480 R.string.leave, leaveMuc);
481 break;
482 case MucOptions.ERROR_MEMBERS_ONLY:
483 showSnackbar(R.string.conference_members_only,
484 R.string.leave, leaveMuc);
485 break;
486 case MucOptions.KICKED_FROM_ROOM:
487 showSnackbar(R.string.conference_kicked, R.string.join,
488 joinMuc);
489 break;
490 default:
491 break;
492 }
493 }
494 }
495 getActivity().invalidateOptionsMenu();
496 updateChatMsgHint();
497 if (!activity.shouldPaneBeOpen()) {
498 activity.xmppConnectionService.markRead(conversation, true);
499 activity.updateConversationList();
500 }
501 this.updateSendButton();
502 }
503 }
504
505 private void decryptNext() {
506 Message next = this.mEncryptedMessages.peek();
507 PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
508
509 if (next!=null && engine != null && !mDecryptJobRunning) {
510 mDecryptJobRunning = true;
511 engine.decrypt(next, new UiCallback<Message>() {
512
513 @Override
514 public void userInputRequried(PendingIntent pi, Message message) {
515 mDecryptJobRunning = false;
516 askForPassphraseIntent = pi.getIntentSender();
517 showSnackbar(R.string.openpgp_messages_found,
518 R.string.decrypt, clickToDecryptListener);
519 }
520
521 @Override
522 public void success(Message message) {
523 mDecryptJobRunning = false;
524 mEncryptedMessages.remove();
525 activity.xmppConnectionService.updateMessage(message);
526 }
527
528 @Override
529 public void error(int error, Message message) {
530 message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
531 mDecryptJobRunning = false;
532 mEncryptedMessages.remove();
533 activity.updateConversationList();
534 activity.xmppConnectionService.updateConversationUi();
535 }
536 });
537 }
538 }
539
540 private void messageSent() {
541 int size = this.messageList.size();
542 messagesView.setSelection(size - 1);
543 mEditMessage.setText("");
544 updateChatMsgHint();
545 }
546
547 public void updateSendButton() {
548 Conversation c = this.conversation;
549 if (activity.useSendButtonToIndicateStatus() && c != null
550 && c.getAccount().getStatus() == Account.STATUS_ONLINE) {
551 if (c.getMode() == Conversation.MODE_SINGLE) {
552 switch (c.getContact().getMostAvailableStatus()) {
553 case Presences.CHAT:
554 this.mSendButton
555 .setImageResource(R.drawable.ic_action_send_now_online);
556 break;
557 case Presences.ONLINE:
558 this.mSendButton
559 .setImageResource(R.drawable.ic_action_send_now_online);
560 break;
561 case Presences.AWAY:
562 this.mSendButton
563 .setImageResource(R.drawable.ic_action_send_now_away);
564 break;
565 case Presences.XA:
566 this.mSendButton
567 .setImageResource(R.drawable.ic_action_send_now_away);
568 break;
569 case Presences.DND:
570 this.mSendButton
571 .setImageResource(R.drawable.ic_action_send_now_dnd);
572 break;
573 default:
574 this.mSendButton
575 .setImageResource(R.drawable.ic_action_send_now_offline);
576 break;
577 }
578 } else if (c.getMode() == Conversation.MODE_MULTI) {
579 if (c.getMucOptions().online()) {
580 this.mSendButton
581 .setImageResource(R.drawable.ic_action_send_now_online);
582 } else {
583 this.mSendButton
584 .setImageResource(R.drawable.ic_action_send_now_offline);
585 }
586 } else {
587 this.mSendButton
588 .setImageResource(R.drawable.ic_action_send_now_offline);
589 }
590 } else {
591 this.mSendButton
592 .setImageResource(R.drawable.ic_action_send_now_offline);
593 }
594 }
595
596 protected void updateStatusMessages() {
597 if (conversation.getMode() == Conversation.MODE_SINGLE) {
598 for (int i = this.messageList.size() - 1; i >= 0; --i) {
599 if (this.messageList.get(i).getStatus() == Message.STATUS_RECEIVED) {
600 return;
601 } else {
602 if (this.messageList.get(i).getStatus() == Message.STATUS_SEND_DISPLAYED) {
603 this.messageList.add(i + 1,
604 Message.createStatusMessage(conversation));
605 return;
606 }
607 }
608 }
609 }
610 }
611
612 protected void makeFingerprintWarning(int latestEncryption) {
613 Set<String> knownFingerprints = conversation.getContact()
614 .getOtrFingerprints();
615 if ((latestEncryption == Message.ENCRYPTION_OTR)
616 && (conversation.hasValidOtrSession()
617 && (!conversation.isMuted())
618 && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
619 .contains(conversation.getOtrFingerprint())))) {
620 showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify,
621 new OnClickListener() {
622
623 @Override
624 public void onClick(View v) {
625 if (conversation.getOtrFingerprint() != null) {
626 AlertDialog dialog = UIHelper
627 .getVerifyFingerprintDialog(
628 (ConversationActivity) getActivity(),
629 conversation, snackbar);
630 dialog.show();
631 }
632 }
633 });
634 }
635 }
636
637 protected void showSnackbar(int message, int action,
638 OnClickListener clickListener) {
639 snackbar.setVisibility(View.VISIBLE);
640 snackbar.setOnClickListener(null);
641 snackbarMessage.setText(message);
642 snackbarMessage.setOnClickListener(null);
643 snackbarAction.setText(action);
644 snackbarAction.setOnClickListener(clickListener);
645 }
646
647 protected void hideSnackbar() {
648 snackbar.setVisibility(View.GONE);
649 }
650
651 protected void sendPlainTextMessage(Message message) {
652 ConversationActivity activity = (ConversationActivity) getActivity();
653 activity.xmppConnectionService.sendMessage(message);
654 messageSent();
655 }
656
657 protected void sendPgpMessage(final Message message) {
658 final ConversationActivity activity = (ConversationActivity) getActivity();
659 final XmppConnectionService xmppService = activity.xmppConnectionService;
660 final Contact contact = message.getConversation().getContact();
661 if (activity.hasPgp()) {
662 if (conversation.getMode() == Conversation.MODE_SINGLE) {
663 if (contact.getPgpKeyId() != 0) {
664 xmppService.getPgpEngine().hasKey(contact,
665 new UiCallback<Contact>() {
666
667 @Override
668 public void userInputRequried(PendingIntent pi,
669 Contact contact) {
670 activity.runIntent(
671 pi,
672 ConversationActivity.REQUEST_ENCRYPT_MESSAGE);
673 }
674
675 @Override
676 public void success(Contact contact) {
677 messageSent();
678 activity.encryptTextMessage(message);
679 }
680
681 @Override
682 public void error(int error, Contact contact) {
683
684 }
685 });
686
687 } else {
688 showNoPGPKeyDialog(false,
689 new DialogInterface.OnClickListener() {
690
691 @Override
692 public void onClick(DialogInterface dialog,
693 int which) {
694 conversation
695 .setNextEncryption(Message.ENCRYPTION_NONE);
696 xmppService.databaseBackend
697 .updateConversation(conversation);
698 message.setEncryption(Message.ENCRYPTION_NONE);
699 xmppService.sendMessage(message);
700 messageSent();
701 }
702 });
703 }
704 } else {
705 if (conversation.getMucOptions().pgpKeysInUse()) {
706 if (!conversation.getMucOptions().everybodyHasKeys()) {
707 Toast warning = Toast
708 .makeText(getActivity(),
709 R.string.missing_public_keys,
710 Toast.LENGTH_LONG);
711 warning.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
712 warning.show();
713 }
714 activity.encryptTextMessage(message);
715 messageSent();
716 } else {
717 showNoPGPKeyDialog(true,
718 new DialogInterface.OnClickListener() {
719
720 @Override
721 public void onClick(DialogInterface dialog,
722 int which) {
723 conversation
724 .setNextEncryption(Message.ENCRYPTION_NONE);
725 message.setEncryption(Message.ENCRYPTION_NONE);
726 xmppService.databaseBackend
727 .updateConversation(conversation);
728 xmppService.sendMessage(message);
729 messageSent();
730 }
731 });
732 }
733 }
734 } else {
735 activity.showInstallPgpDialog();
736 }
737 }
738
739 public void showNoPGPKeyDialog(boolean plural,
740 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 final ConversationActivity activity = (ConversationActivity) getActivity();
758 final XmppConnectionService xmppService = activity.xmppConnectionService;
759 if (conversation.hasValidOtrSession()) {
760 activity.xmppConnectionService.sendMessage(message);
761 messageSent();
762 } else {
763 activity.selectPresence(message.getConversation(),
764 new OnPresenceSelected() {
765
766 @Override
767 public void onPresenceSelected() {
768 message.setPresence(conversation.getNextPresence());
769 xmppService.sendMessage(message);
770 messageSent();
771 }
772 });
773 }
774 }
775
776 public void setText(String text) {
777 this.pastedText = text;
778 }
779
780 public void clearInputField() {
781 this.mEditMessage.setText("");
782 }
783}