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 activity.hideConversationsOverview();
249 }
250 });
251 mEditMessage.setOnEditorActionListener(mEditorActionListener);
252 mEditMessage.setOnEnterPressedListener(new OnEnterPressed() {
253
254 @Override
255 public void onEnterPressed() {
256 sendMessage();
257 }
258 });
259
260 mSendButton = (ImageButton) view.findViewById(R.id.textSendButton);
261 mSendButton.setOnClickListener(this.mSendButtonListener);
262
263 snackbar = (RelativeLayout) view.findViewById(R.id.snackbar);
264 snackbarMessage = (TextView) view.findViewById(R.id.snackbar_message);
265 snackbarAction = (TextView) view.findViewById(R.id.snackbar_action);
266
267 messagesView = (ListView) view.findViewById(R.id.messages_view);
268 messagesView.setOnScrollListener(mOnScrollListener);
269 messagesView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
270 messageListAdapter = new MessageAdapter(
271 (ConversationActivity) getActivity(), this.messageList);
272 messageListAdapter
273 .setOnContactPictureClicked(new OnContactPictureClicked() {
274
275 @Override
276 public void onContactPictureClicked(Message message) {
277 if (message.getStatus() <= Message.STATUS_RECEIVED) {
278 if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
279 if (message.getPresence() != null) {
280 highlightInConference(message.getPresence());
281 } else {
282 highlightInConference(message
283 .getCounterpart());
284 }
285 } else {
286 Contact contact = message.getConversation()
287 .getContact();
288 if (contact.showInRoster()) {
289 activity.switchToContactDetails(contact);
290 } else {
291 activity.showAddToRosterDialog(message
292 .getConversation());
293 }
294 }
295 }
296 }
297 });
298 messageListAdapter
299 .setOnContactPictureLongClicked(new OnContactPictureLongClicked() {
300
301 @Override
302 public void onContactPictureLongClicked(Message message) {
303 if (message.getStatus() <= Message.STATUS_RECEIVED) {
304 if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
305 if (message.getPresence() != null) {
306 privateMessageWith(message.getPresence());
307 } else {
308 privateMessageWith(message.getCounterpart());
309 }
310 }
311 }
312 }
313 });
314 messagesView.setAdapter(messageListAdapter);
315
316 return view;
317 }
318
319 protected void privateMessageWith(String counterpart) {
320 this.mEditMessage.setText("");
321 this.conversation.setNextPresence(counterpart);
322 updateChatMsgHint();
323 }
324
325 protected void highlightInConference(String nick) {
326 String oldString = mEditMessage.getText().toString().trim();
327 if (oldString.isEmpty() || mEditMessage.getSelectionStart() == 0) {
328 mEditMessage.getText().insert(0, nick + ": ");
329 } else {
330 if (mEditMessage.getText().charAt(
331 mEditMessage.getSelectionStart() - 1) != ' ') {
332 nick = " " + nick;
333 }
334 mEditMessage.getText().insert(mEditMessage.getSelectionStart(),
335 nick + " ");
336 }
337 }
338
339 @Override
340 public void onStart() {
341 super.onStart();
342 this.activity = (ConversationActivity) getActivity();
343 if (activity.xmppConnectionServiceBound) {
344 this.onBackendConnected();
345 }
346 }
347
348 @Override
349 public void onStop() {
350 super.onStop();
351 if (this.conversation != null) {
352 this.conversation.setNextMessage(mEditMessage.getText().toString());
353 }
354 }
355
356 public void onBackendConnected() {
357 this.activity = (ConversationActivity) getActivity();
358 this.conversation = activity.getSelectedConversation();
359 if (this.conversation == null) {
360 return;
361 }
362 String oldString = conversation.getNextMessage().trim();
363 if (this.pastedText == null) {
364 this.mEditMessage.setText(oldString);
365 } else {
366
367 if (oldString.isEmpty()) {
368 mEditMessage.setText(pastedText);
369 } else {
370 mEditMessage.setText(oldString + " " + pastedText);
371 }
372 pastedText = null;
373 }
374 int position = mEditMessage.length();
375 Editable etext = mEditMessage.getText();
376 Selection.setSelection(etext, position);
377 if (activity.isConversationsOverviewHideable()) {
378 if (!activity.shouldPaneBeOpen()) {
379 activity.hideConversationsOverview();
380 activity.openConversation(conversation);
381 }
382 }
383 if (this.conversation.getMode() == Conversation.MODE_MULTI) {
384 conversation.setNextPresence(null);
385 }
386 updateMessages();
387 }
388
389 private void decryptMessage(Message message) {
390 PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
391 if (engine != null) {
392 engine.decrypt(message, new UiCallback<Message>() {
393
394 @Override
395 public void userInputRequried(PendingIntent pi, Message message) {
396 askForPassphraseIntent = pi.getIntentSender();
397 showSnackbar(R.string.openpgp_messages_found,
398 R.string.decrypt, clickToDecryptListener);
399 }
400
401 @Override
402 public void success(Message message) {
403 activity.xmppConnectionService.databaseBackend
404 .updateMessage(message);
405 updateMessages();
406 }
407
408 @Override
409 public void error(int error, Message message) {
410 message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
411 // updateMessages();
412 }
413 });
414 }
415 }
416
417 public void updateMessages() {
418 if (getView() == null) {
419 return;
420 }
421 hideSnackbar();
422 final ConversationActivity activity = (ConversationActivity) getActivity();
423 if (this.conversation != null) {
424 final Contact contact = this.conversation.getContact();
425 if (this.conversation.isMuted()) {
426 showSnackbar(R.string.notifications_disabled, R.string.enable,
427 new OnClickListener() {
428
429 @Override
430 public void onClick(View v) {
431 conversation.setMutedTill(0);
432 updateMessages();
433 }
434 });
435 } else if (!contact.showInRoster()
436 && contact
437 .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
438 showSnackbar(R.string.contact_added_you, R.string.add_back,
439 new OnClickListener() {
440
441 @Override
442 public void onClick(View v) {
443 activity.xmppConnectionService
444 .createContact(contact);
445 activity.switchToContactDetails(contact);
446 }
447 });
448 }
449 for (Message message : this.conversation.getMessages()) {
450 if ((message.getEncryption() == Message.ENCRYPTION_PGP)
451 && ((message.getStatus() == Message.STATUS_RECEIVED) || (message
452 .getStatus() == Message.STATUS_SEND))) {
453 decryptMessage(message);
454 break;
455 }
456 }
457 this.messageList.clear();
458 if (this.conversation.getMessages().size() == 0) {
459 messagesLoaded = false;
460 } else {
461 this.messageList.addAll(this.conversation.getMessages());
462 messagesLoaded = true;
463 updateStatusMessages();
464 }
465 this.messageListAdapter.notifyDataSetChanged();
466 if (conversation.getMode() == Conversation.MODE_SINGLE) {
467 if (messageList.size() >= 1) {
468 makeFingerprintWarning(conversation.getLatestEncryption());
469 }
470 } else {
471 if (!conversation.getMucOptions().online()
472 && conversation.getAccount().getStatus() == Account.STATUS_ONLINE) {
473 int error = conversation.getMucOptions().getError();
474 switch (error) {
475 case MucOptions.ERROR_NICK_IN_USE:
476 showSnackbar(R.string.nick_in_use, R.string.edit,
477 clickToMuc);
478 break;
479 case MucOptions.ERROR_ROOM_NOT_FOUND:
480 showSnackbar(R.string.conference_not_found,
481 R.string.leave, leaveMuc);
482 break;
483 case MucOptions.ERROR_PASSWORD_REQUIRED:
484 showSnackbar(R.string.conference_requires_password,
485 R.string.enter_password, enterPassword);
486 break;
487 default:
488 break;
489 }
490 }
491 }
492 getActivity().invalidateOptionsMenu();
493 updateChatMsgHint();
494 if (!activity.shouldPaneBeOpen()) {
495 activity.xmppConnectionService.markRead(conversation,true);
496 activity.updateConversationList();
497 }
498 this.updateSendButton();
499 }
500 }
501
502 private void messageSent() {
503 int size = this.messageList.size();
504 if (size >= 1 && this.messagesView.getLastVisiblePosition() != size - 1) {
505 messagesView.setSelection(size - 1);
506 }
507 mEditMessage.setText("");
508 updateChatMsgHint();
509 }
510
511 public void updateSendButton() {
512 Conversation c = this.conversation;
513 if (activity.useSendButtonToIndicateStatus() && c != null
514 && c.getAccount().getStatus() == Account.STATUS_ONLINE) {
515 if (c.getMode() == Conversation.MODE_SINGLE) {
516 switch (c.getContact().getMostAvailableStatus()) {
517 case Presences.CHAT:
518 this.mSendButton
519 .setImageResource(R.drawable.ic_action_send_now_online);
520 break;
521 case Presences.ONLINE:
522 this.mSendButton
523 .setImageResource(R.drawable.ic_action_send_now_online);
524 break;
525 case Presences.AWAY:
526 this.mSendButton
527 .setImageResource(R.drawable.ic_action_send_now_away);
528 break;
529 case Presences.XA:
530 this.mSendButton
531 .setImageResource(R.drawable.ic_action_send_now_away);
532 break;
533 case Presences.DND:
534 this.mSendButton
535 .setImageResource(R.drawable.ic_action_send_now_dnd);
536 break;
537 default:
538 this.mSendButton
539 .setImageResource(R.drawable.ic_action_send_now_offline);
540 break;
541 }
542 } else if (c.getMode() == Conversation.MODE_MULTI) {
543 if (c.getMucOptions().online()) {
544 this.mSendButton
545 .setImageResource(R.drawable.ic_action_send_now_online);
546 } else {
547 this.mSendButton
548 .setImageResource(R.drawable.ic_action_send_now_offline);
549 }
550 } else {
551 this.mSendButton
552 .setImageResource(R.drawable.ic_action_send_now_offline);
553 }
554 } else {
555 this.mSendButton
556 .setImageResource(R.drawable.ic_action_send_now_offline);
557 }
558 }
559
560 protected void updateStatusMessages() {
561 if (conversation.getMode() == Conversation.MODE_SINGLE) {
562 for (int i = this.messageList.size() - 1; i >= 0; --i) {
563 if (this.messageList.get(i).getStatus() == Message.STATUS_RECEIVED) {
564 return;
565 } else {
566 if (this.messageList.get(i).getStatus() == Message.STATUS_SEND_DISPLAYED) {
567 this.messageList.add(i + 1,
568 Message.createStatusMessage(conversation));
569 return;
570 }
571 }
572 }
573 }
574 }
575
576 protected void makeFingerprintWarning(int latestEncryption) {
577 Set<String> knownFingerprints = conversation.getContact()
578 .getOtrFingerprints();
579 if ((latestEncryption == Message.ENCRYPTION_OTR)
580 && (conversation.hasValidOtrSession()
581 && (!conversation.isMuted())
582 && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
583 .contains(conversation.getOtrFingerprint())))) {
584 showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify,
585 new OnClickListener() {
586
587 @Override
588 public void onClick(View v) {
589 if (conversation.getOtrFingerprint() != null) {
590 AlertDialog dialog = UIHelper
591 .getVerifyFingerprintDialog(
592 (ConversationActivity) getActivity(),
593 conversation, snackbar);
594 dialog.show();
595 }
596 }
597 });
598 }
599 }
600
601 protected void showSnackbar(int message, int action,
602 OnClickListener clickListener) {
603 snackbar.setVisibility(View.VISIBLE);
604 snackbar.setOnClickListener(null);
605 snackbarMessage.setText(message);
606 snackbarMessage.setOnClickListener(null);
607 snackbarAction.setText(action);
608 snackbarAction.setOnClickListener(clickListener);
609 }
610
611 protected void hideSnackbar() {
612 snackbar.setVisibility(View.GONE);
613 }
614
615 protected void sendPlainTextMessage(Message message) {
616 ConversationActivity activity = (ConversationActivity) getActivity();
617 activity.xmppConnectionService.sendMessage(message);
618 messageSent();
619 }
620
621 protected void sendPgpMessage(final Message message) {
622 final ConversationActivity activity = (ConversationActivity) getActivity();
623 final XmppConnectionService xmppService = activity.xmppConnectionService;
624 final Contact contact = message.getConversation().getContact();
625 if (activity.hasPgp()) {
626 if (conversation.getMode() == Conversation.MODE_SINGLE) {
627 if (contact.getPgpKeyId() != 0) {
628 xmppService.getPgpEngine().hasKey(contact,
629 new UiCallback<Contact>() {
630
631 @Override
632 public void userInputRequried(PendingIntent pi,
633 Contact contact) {
634 activity.runIntent(
635 pi,
636 ConversationActivity.REQUEST_ENCRYPT_MESSAGE);
637 }
638
639 @Override
640 public void success(Contact contact) {
641 messageSent();
642 activity.encryptTextMessage(message);
643 }
644
645 @Override
646 public void error(int error, Contact contact) {
647
648 }
649 });
650
651 } else {
652 showNoPGPKeyDialog(false,
653 new DialogInterface.OnClickListener() {
654
655 @Override
656 public void onClick(DialogInterface dialog,
657 int which) {
658 conversation
659 .setNextEncryption(Message.ENCRYPTION_NONE);
660 xmppService.databaseBackend
661 .updateConversation(conversation);
662 message.setEncryption(Message.ENCRYPTION_NONE);
663 xmppService.sendMessage(message);
664 messageSent();
665 }
666 });
667 }
668 } else {
669 if (conversation.getMucOptions().pgpKeysInUse()) {
670 if (!conversation.getMucOptions().everybodyHasKeys()) {
671 Toast warning = Toast
672 .makeText(getActivity(),
673 R.string.missing_public_keys,
674 Toast.LENGTH_LONG);
675 warning.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
676 warning.show();
677 }
678 activity.encryptTextMessage(message);
679 messageSent();
680 } else {
681 showNoPGPKeyDialog(true,
682 new DialogInterface.OnClickListener() {
683
684 @Override
685 public void onClick(DialogInterface dialog,
686 int which) {
687 conversation
688 .setNextEncryption(Message.ENCRYPTION_NONE);
689 message.setEncryption(Message.ENCRYPTION_NONE);
690 xmppService.databaseBackend
691 .updateConversation(conversation);
692 xmppService.sendMessage(message);
693 messageSent();
694 }
695 });
696 }
697 }
698 } else {
699 activity.showInstallPgpDialog();
700 }
701 }
702
703 public void showNoPGPKeyDialog(boolean plural,
704 DialogInterface.OnClickListener listener) {
705 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
706 builder.setIconAttribute(android.R.attr.alertDialogIcon);
707 if (plural) {
708 builder.setTitle(getString(R.string.no_pgp_keys));
709 builder.setMessage(getText(R.string.contacts_have_no_pgp_keys));
710 } else {
711 builder.setTitle(getString(R.string.no_pgp_key));
712 builder.setMessage(getText(R.string.contact_has_no_pgp_key));
713 }
714 builder.setNegativeButton(getString(R.string.cancel), null);
715 builder.setPositiveButton(getString(R.string.send_unencrypted),
716 listener);
717 builder.create().show();
718 }
719
720 protected void sendOtrMessage(final Message message) {
721 final ConversationActivity activity = (ConversationActivity) getActivity();
722 final XmppConnectionService xmppService = activity.xmppConnectionService;
723 if (conversation.hasValidOtrSession()) {
724 activity.xmppConnectionService.sendMessage(message);
725 messageSent();
726 } else {
727 activity.selectPresence(message.getConversation(),
728 new OnPresenceSelected() {
729
730 @Override
731 public void onPresenceSelected() {
732 message.setPresence(conversation.getNextPresence());
733 xmppService.sendMessage(message);
734 messageSent();
735 }
736 });
737 }
738 }
739
740 public void setText(String text) {
741 this.pastedText = text;
742 }
743
744 public void clearInputField() {
745 this.mEditMessage.setText("");
746 }
747}