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