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