ConversationFragment.java

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