1package eu.siacs.conversations.ui;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import eu.siacs.conversations.R;
7import eu.siacs.conversations.entities.Contact;
8import eu.siacs.conversations.entities.Conversation;
9import eu.siacs.conversations.entities.Message;
10import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
11import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate;
12import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
13import eu.siacs.conversations.ui.adapter.ConversationAdapter;
14import eu.siacs.conversations.utils.ExceptionHelper;
15import eu.siacs.conversations.utils.UIHelper;
16import android.net.Uri;
17import android.os.Bundle;
18import android.os.SystemClock;
19import android.provider.MediaStore;
20import android.app.ActionBar;
21import android.app.AlertDialog;
22import android.app.FragmentTransaction;
23import android.app.PendingIntent;
24import android.content.DialogInterface;
25import android.content.DialogInterface.OnClickListener;
26import android.content.IntentSender.SendIntentException;
27import android.content.Intent;
28import android.support.v4.widget.SlidingPaneLayout;
29import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
30import android.view.KeyEvent;
31import android.view.Menu;
32import android.view.MenuItem;
33import android.view.View;
34import android.widget.AdapterView;
35import android.widget.AdapterView.OnItemClickListener;
36import android.widget.ArrayAdapter;
37import android.widget.CheckBox;
38import android.widget.ListView;
39import android.widget.PopupMenu;
40import android.widget.PopupMenu.OnMenuItemClickListener;
41import android.widget.Toast;
42
43public class ConversationActivity extends XmppActivity implements
44 OnAccountUpdate, OnConversationUpdate, OnRosterUpdate {
45
46 public static final String VIEW_CONVERSATION = "viewConversation";
47 public static final String CONVERSATION = "conversationUuid";
48 public static final String TEXT = "text";
49 public static final String PRESENCE = "eu.siacs.conversations.presence";
50
51 public static final int REQUEST_SEND_MESSAGE = 0x0201;
52 public static final int REQUEST_DECRYPT_PGP = 0x0202;
53 private static final int REQUEST_ATTACH_FILE_DIALOG = 0x0203;
54 private static final int REQUEST_IMAGE_CAPTURE = 0x0204;
55 private static final int REQUEST_RECORD_AUDIO = 0x0205;
56 private static final int REQUEST_SEND_PGP_IMAGE = 0x0206;
57 public static final int REQUEST_ENCRYPT_MESSAGE = 0x0207;
58
59 private static final int ATTACHMENT_CHOICE_CHOOSE_IMAGE = 0x0301;
60 private static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x0302;
61 private static final int ATTACHMENT_CHOICE_RECORD_VOICE = 0x0303;
62
63 protected SlidingPaneLayout spl;
64
65 private List<Conversation> conversationList = new ArrayList<Conversation>();
66 private Conversation selectedConversation = null;
67 private ListView listView;
68
69 private boolean paneShouldBeOpen = true;
70 private ArrayAdapter<Conversation> listAdapter;
71
72 protected ConversationActivity activity = this;
73 private Toast prepareImageToast;
74
75 private Uri pendingImageUri = null;
76
77 public List<Conversation> getConversationList() {
78 return this.conversationList;
79 }
80
81 public Conversation getSelectedConversation() {
82 return this.selectedConversation;
83 }
84
85 public void setSelectedConversation(Conversation conversation) {
86 this.selectedConversation = conversation;
87 }
88
89 public ListView getConversationListView() {
90 return this.listView;
91 }
92
93 public SlidingPaneLayout getSlidingPaneLayout() {
94 return this.spl;
95 }
96
97 public boolean shouldPaneBeOpen() {
98 return paneShouldBeOpen;
99 }
100
101 @Override
102 protected void onCreate(Bundle savedInstanceState) {
103 super.onCreate(savedInstanceState);
104
105 setContentView(R.layout.fragment_conversations_overview);
106
107 listView = (ListView) findViewById(R.id.list);
108
109 getActionBar().setDisplayHomeAsUpEnabled(false);
110 getActionBar().setHomeButtonEnabled(false);
111
112 this.listAdapter = new ConversationAdapter(this, conversationList);
113 listView.setAdapter(this.listAdapter);
114
115 listView.setOnItemClickListener(new OnItemClickListener() {
116
117 @Override
118 public void onItemClick(AdapterView<?> arg0, View clickedView,
119 int position, long arg3) {
120 paneShouldBeOpen = false;
121 if (getSelectedConversation() != conversationList.get(position)) {
122 setSelectedConversation(conversationList.get(position));
123 swapConversationFragment();
124 } else {
125 spl.closePane();
126 }
127 }
128 });
129 spl = (SlidingPaneLayout) findViewById(R.id.slidingpanelayout);
130 spl.setParallaxDistance(150);
131 spl.setShadowResource(R.drawable.es_slidingpane_shadow);
132 spl.setSliderFadeColor(0);
133 spl.setPanelSlideListener(new PanelSlideListener() {
134
135 @Override
136 public void onPanelOpened(View arg0) {
137 paneShouldBeOpen = true;
138 ActionBar ab = getActionBar();
139 if (ab != null) {
140 ab.setDisplayHomeAsUpEnabled(false);
141 ab.setHomeButtonEnabled(false);
142 ab.setTitle(R.string.app_name);
143 }
144 invalidateOptionsMenu();
145 hideKeyboard();
146 }
147
148 @Override
149 public void onPanelClosed(View arg0) {
150 paneShouldBeOpen = false;
151 if ((conversationList.size() > 0)
152 && (getSelectedConversation() != null)) {
153 ActionBar ab = getActionBar();
154 if (ab != null) {
155 ab.setDisplayHomeAsUpEnabled(true);
156 ab.setHomeButtonEnabled(true);
157 ab.setTitle(getSelectedConversation().getName());
158 }
159 invalidateOptionsMenu();
160 if (!getSelectedConversation().isRead()) {
161 xmppConnectionService
162 .markRead(getSelectedConversation());
163 UIHelper.updateNotification(getApplicationContext(),
164 getConversationList(), null, false);
165 listView.invalidateViews();
166 }
167 }
168 }
169
170 @Override
171 public void onPanelSlide(View arg0, float arg1) {
172 // TODO Auto-generated method stub
173
174 }
175 });
176 }
177
178 @Override
179 public boolean onCreateOptionsMenu(Menu menu) {
180 getMenuInflater().inflate(R.menu.conversations, menu);
181 MenuItem menuSecure = (MenuItem) menu.findItem(R.id.action_security);
182 MenuItem menuArchive = (MenuItem) menu.findItem(R.id.action_archive);
183 MenuItem menuMucDetails = (MenuItem) menu
184 .findItem(R.id.action_muc_details);
185 MenuItem menuContactDetails = (MenuItem) menu
186 .findItem(R.id.action_contact_details);
187 MenuItem menuAttach = (MenuItem) menu.findItem(R.id.action_attach_file);
188 MenuItem menuClearHistory = (MenuItem) menu
189 .findItem(R.id.action_clear_history);
190 MenuItem menuAdd = (MenuItem) menu.findItem(R.id.action_add);
191 MenuItem menuInviteContact = (MenuItem) menu
192 .findItem(R.id.action_invite);
193 MenuItem menuMute = (MenuItem) menu.findItem(R.id.action_mute);
194
195 if ((spl.isOpen() && (spl.isSlideable()))) {
196 menuArchive.setVisible(false);
197 menuMucDetails.setVisible(false);
198 menuContactDetails.setVisible(false);
199 menuSecure.setVisible(false);
200 menuInviteContact.setVisible(false);
201 menuAttach.setVisible(false);
202 menuClearHistory.setVisible(false);
203 menuMute.setVisible(false);
204 } else {
205 menuAdd.setVisible(!spl.isSlideable());
206 if (this.getSelectedConversation() != null) {
207 if (this.getSelectedConversation().getLatestMessage()
208 .getEncryption() != Message.ENCRYPTION_NONE) {
209 menuSecure.setIcon(R.drawable.ic_action_secure);
210 }
211 if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) {
212 menuContactDetails.setVisible(false);
213 menuAttach.setVisible(false);
214 } else {
215 menuMucDetails.setVisible(false);
216 menuInviteContact.setVisible(false);
217 }
218 }
219 }
220 return true;
221 }
222
223 private void selectPresenceToAttachFile(final int attachmentChoice) {
224 selectPresence(getSelectedConversation(), new OnPresenceSelected() {
225
226 @Override
227 public void onPresenceSelected() {
228 if (attachmentChoice == ATTACHMENT_CHOICE_TAKE_PHOTO) {
229 pendingImageUri = xmppConnectionService.getFileBackend()
230 .getTakePhotoUri();
231 Intent takePictureIntent = new Intent(
232 MediaStore.ACTION_IMAGE_CAPTURE);
233 takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
234 pendingImageUri);
235 if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
236 startActivityForResult(takePictureIntent,
237 REQUEST_IMAGE_CAPTURE);
238 }
239 } else if (attachmentChoice == ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
240 Intent attachFileIntent = new Intent();
241 attachFileIntent.setType("image/*");
242 attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
243 Intent chooser = Intent.createChooser(attachFileIntent,
244 getString(R.string.attach_file));
245 startActivityForResult(chooser, REQUEST_ATTACH_FILE_DIALOG);
246 } else if (attachmentChoice == ATTACHMENT_CHOICE_RECORD_VOICE) {
247 Intent intent = new Intent(
248 MediaStore.Audio.Media.RECORD_SOUND_ACTION);
249 startActivityForResult(intent, REQUEST_RECORD_AUDIO);
250 }
251 }
252 });
253 }
254
255 private void attachFile(final int attachmentChoice) {
256 final Conversation conversation = getSelectedConversation();
257 if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) {
258 if (hasPgp()) {
259 if (conversation.getContact().getPgpKeyId() != 0) {
260 xmppConnectionService.getPgpEngine().hasKey(
261 conversation.getContact(),
262 new UiCallback<Contact>() {
263
264 @Override
265 public void userInputRequried(PendingIntent pi,
266 Contact contact) {
267 ConversationActivity.this.runIntent(pi,
268 attachmentChoice);
269 }
270
271 @Override
272 public void success(Contact contact) {
273 selectPresenceToAttachFile(attachmentChoice);
274 }
275
276 @Override
277 public void error(int error, Contact contact) {
278 displayErrorDialog(error);
279 }
280 });
281 } else {
282 final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
283 .findFragmentByTag("conversation");
284 if (fragment != null) {
285 fragment.showNoPGPKeyDialog(false,
286 new OnClickListener() {
287
288 @Override
289 public void onClick(DialogInterface dialog,
290 int which) {
291 conversation
292 .setNextEncryption(Message.ENCRYPTION_NONE);
293 selectPresenceToAttachFile(attachmentChoice);
294 }
295 });
296 }
297 }
298 } else {
299 showInstallPgpDialog();
300 }
301 } else if (getSelectedConversation().getNextEncryption(
302 forceEncryption()) == Message.ENCRYPTION_NONE) {
303 selectPresenceToAttachFile(attachmentChoice);
304 } else {
305 selectPresenceToAttachFile(attachmentChoice);
306 }
307 }
308
309 @Override
310 public boolean onOptionsItemSelected(MenuItem item) {
311 switch (item.getItemId()) {
312 case android.R.id.home:
313 spl.openPane();
314 return true;
315 case R.id.action_attach_file:
316 View menuAttachFile = findViewById(R.id.action_attach_file);
317 if (menuAttachFile == null) {
318 break;
319 }
320 PopupMenu attachFilePopup = new PopupMenu(this, menuAttachFile);
321 attachFilePopup.inflate(R.menu.attachment_choices);
322 attachFilePopup
323 .setOnMenuItemClickListener(new OnMenuItemClickListener() {
324
325 @Override
326 public boolean onMenuItemClick(MenuItem item) {
327 switch (item.getItemId()) {
328 case R.id.attach_choose_picture:
329 attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE);
330 break;
331 case R.id.attach_take_picture:
332 attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO);
333 break;
334 case R.id.attach_record_voice:
335 attachFile(ATTACHMENT_CHOICE_RECORD_VOICE);
336 break;
337 }
338 return false;
339 }
340 });
341 attachFilePopup.show();
342 break;
343 case R.id.action_add:
344 startActivity(new Intent(this, StartConversationActivity.class));
345 break;
346 case R.id.action_archive:
347 this.endConversation(getSelectedConversation());
348 break;
349 case R.id.action_contact_details:
350 Contact contact = this.getSelectedConversation().getContact();
351 if (contact.showInRoster()) {
352 switchToContactDetails(contact);
353 } else {
354 showAddToRosterDialog(getSelectedConversation());
355 }
356 break;
357 case R.id.action_muc_details:
358 Intent intent = new Intent(this, ConferenceDetailsActivity.class);
359 intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC);
360 intent.putExtra("uuid", getSelectedConversation().getUuid());
361 startActivity(intent);
362 break;
363 case R.id.action_invite:
364 inviteToConversation(getSelectedConversation());
365 break;
366 case R.id.action_security:
367 final Conversation conversation = getSelectedConversation();
368 View menuItemView = findViewById(R.id.action_security);
369 if (menuItemView == null) {
370 break;
371 }
372 PopupMenu popup = new PopupMenu(this, menuItemView);
373 final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
374 .findFragmentByTag("conversation");
375 if (fragment != null) {
376 popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
377
378 @Override
379 public boolean onMenuItemClick(MenuItem item) {
380 switch (item.getItemId()) {
381 case R.id.encryption_choice_none:
382 conversation
383 .setNextEncryption(Message.ENCRYPTION_NONE);
384 item.setChecked(true);
385 break;
386 case R.id.encryption_choice_otr:
387 conversation
388 .setNextEncryption(Message.ENCRYPTION_OTR);
389 item.setChecked(true);
390 break;
391 case R.id.encryption_choice_pgp:
392 if (hasPgp()) {
393 if (conversation.getAccount().getKeys()
394 .has("pgp_signature")) {
395 conversation
396 .setNextEncryption(Message.ENCRYPTION_PGP);
397 item.setChecked(true);
398 } else {
399 announcePgp(conversation.getAccount(),
400 conversation);
401 }
402 } else {
403 showInstallPgpDialog();
404 }
405 break;
406 default:
407 conversation
408 .setNextEncryption(Message.ENCRYPTION_NONE);
409 break;
410 }
411 fragment.updateChatMsgHint();
412 return true;
413 }
414 });
415 popup.inflate(R.menu.encryption_choices);
416 MenuItem otr = popup.getMenu().findItem(
417 R.id.encryption_choice_otr);
418 MenuItem none = popup.getMenu().findItem(
419 R.id.encryption_choice_none);
420 if (conversation.getMode() == Conversation.MODE_MULTI) {
421 otr.setEnabled(false);
422 } else {
423 if (forceEncryption()) {
424 none.setVisible(false);
425 }
426 }
427 switch (conversation.getNextEncryption(forceEncryption())) {
428 case Message.ENCRYPTION_NONE:
429 none.setChecked(true);
430 break;
431 case Message.ENCRYPTION_OTR:
432 otr.setChecked(true);
433 break;
434 case Message.ENCRYPTION_PGP:
435 popup.getMenu().findItem(R.id.encryption_choice_pgp)
436 .setChecked(true);
437 break;
438 default:
439 popup.getMenu().findItem(R.id.encryption_choice_none)
440 .setChecked(true);
441 break;
442 }
443 popup.show();
444 }
445
446 break;
447 case R.id.action_clear_history:
448 clearHistoryDialog(getSelectedConversation());
449 break;
450 case R.id.action_mute:
451 muteConversationDialog(getSelectedConversation());
452 break;
453 default:
454 break;
455 }
456 return super.onOptionsItemSelected(item);
457 }
458
459 public void endConversation(Conversation conversation) {
460 conversation.setStatus(Conversation.STATUS_ARCHIVED);
461 paneShouldBeOpen = true;
462 spl.openPane();
463 xmppConnectionService.archiveConversation(conversation);
464 if (conversationList.size() > 0) {
465 setSelectedConversation(conversationList.get(0));
466 } else {
467 setSelectedConversation(null);
468 }
469 }
470
471 protected void clearHistoryDialog(final Conversation conversation) {
472 AlertDialog.Builder builder = new AlertDialog.Builder(this);
473 builder.setTitle(getString(R.string.clear_conversation_history));
474 View dialogView = getLayoutInflater().inflate(
475 R.layout.dialog_clear_history, null);
476 final CheckBox endConversationCheckBox = (CheckBox) dialogView
477 .findViewById(R.id.end_conversation_checkbox);
478 builder.setView(dialogView);
479 builder.setNegativeButton(getString(R.string.cancel), null);
480 builder.setPositiveButton(getString(R.string.delete_messages),
481 new OnClickListener() {
482
483 @Override
484 public void onClick(DialogInterface dialog, int which) {
485 activity.xmppConnectionService
486 .clearConversationHistory(conversation);
487 if (endConversationCheckBox.isChecked()) {
488 endConversation(conversation);
489 }
490 }
491 });
492 builder.create().show();
493 }
494
495 protected void muteConversationDialog(final Conversation conversation) {
496 AlertDialog.Builder builder = new AlertDialog.Builder(this);
497 builder.setTitle(R.string.disable_notifications_for_this_conversation);
498 final int[] durations = getResources().getIntArray(
499 R.array.mute_options_durations);
500 builder.setItems(R.array.mute_options_descriptions,
501 new OnClickListener() {
502
503 @Override
504 public void onClick(DialogInterface dialog, int which) {
505 long till;
506 if (durations[which] == -1) {
507 till = Long.MAX_VALUE;
508 } else {
509 till = SystemClock.elapsedRealtime()
510 + (durations[which] * 1000);
511 }
512 conversation.setMutedTill(till);
513 ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
514 .findFragmentByTag("conversation");
515 if (selectedFragment != null) {
516 selectedFragment.updateMessages();
517 }
518 }
519 });
520 builder.create().show();
521 }
522
523 protected ConversationFragment swapConversationFragment() {
524 ConversationFragment selectedFragment = new ConversationFragment();
525 if (!isFinishing()) {
526
527 FragmentTransaction transaction = getFragmentManager()
528 .beginTransaction();
529 transaction.replace(R.id.selected_conversation, selectedFragment,
530 "conversation");
531
532 transaction.commitAllowingStateLoss();
533 }
534 return selectedFragment;
535 }
536
537 @Override
538 public boolean onKeyDown(int keyCode, KeyEvent event) {
539 if (keyCode == KeyEvent.KEYCODE_BACK) {
540 if (!spl.isOpen()) {
541 spl.openPane();
542 return false;
543 }
544 }
545 return super.onKeyDown(keyCode, event);
546 }
547
548 @Override
549 protected void onNewIntent(Intent intent) {
550 if (xmppConnectionServiceBound) {
551 if ((Intent.ACTION_VIEW.equals(intent.getAction()) && (VIEW_CONVERSATION
552 .equals(intent.getType())))) {
553 String convToView = (String) intent.getExtras().get(
554 CONVERSATION);
555 updateConversationList();
556 for (int i = 0; i < conversationList.size(); ++i) {
557 if (conversationList.get(i).getUuid().equals(convToView)) {
558 setSelectedConversation(conversationList.get(i));
559 break;
560 }
561 }
562 paneShouldBeOpen = false;
563 String text = intent.getExtras().getString(TEXT, null);
564 swapConversationFragment().setText(text);
565 }
566 } else {
567 handledViewIntent = false;
568 setIntent(intent);
569 }
570 }
571
572 @Override
573 public void onStart() {
574 super.onStart();
575 if (this.xmppConnectionServiceBound) {
576 this.onBackendConnected();
577 }
578 if (conversationList.size() >= 1) {
579 this.onConversationUpdate();
580 }
581 }
582
583 @Override
584 protected void onStop() {
585 if (xmppConnectionServiceBound) {
586 xmppConnectionService.removeOnConversationListChangedListener();
587 xmppConnectionService.removeOnAccountListChangedListener();
588 xmppConnectionService.removeOnRosterUpdateListener();
589 }
590 super.onStop();
591 }
592
593 @Override
594 void onBackendConnected() {
595 this.registerListener();
596 if (conversationList.size() == 0) {
597 updateConversationList();
598 }
599
600 if (getSelectedConversation() != null && pendingImageUri != null) {
601 attachImageToConversation(getSelectedConversation(),
602 pendingImageUri);
603 pendingImageUri = null;
604 } else {
605 pendingImageUri = null;
606 }
607
608 if ((getIntent().getAction() != null)
609 && (getIntent().getAction().equals(Intent.ACTION_VIEW) && (!handledViewIntent))) {
610 if (getIntent().getType().equals(
611 ConversationActivity.VIEW_CONVERSATION)) {
612 handledViewIntent = true;
613
614 String convToView = (String) getIntent().getExtras().get(
615 CONVERSATION);
616
617 for (int i = 0; i < conversationList.size(); ++i) {
618 if (conversationList.get(i).getUuid().equals(convToView)) {
619 setSelectedConversation(conversationList.get(i));
620 }
621 }
622 paneShouldBeOpen = false;
623 String text = getIntent().getExtras().getString(TEXT, null);
624 swapConversationFragment().setText(text);
625 }
626 } else {
627 if (xmppConnectionService.getAccounts().size() == 0) {
628 startActivity(new Intent(this, EditAccountActivity.class));
629 } else if (conversationList.size() <= 0) {
630 // add no history
631 startActivity(new Intent(this, StartConversationActivity.class));
632 finish();
633 } else {
634 spl.openPane();
635 // find currently loaded fragment
636 ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
637 .findFragmentByTag("conversation");
638 if (selectedFragment != null) {
639 selectedFragment.onBackendConnected();
640 } else {
641 setSelectedConversation(conversationList.get(0));
642 swapConversationFragment();
643 }
644 ExceptionHelper.checkForCrash(this, this.xmppConnectionService);
645 }
646 }
647 }
648
649 public void registerListener() {
650 if (xmppConnectionServiceBound) {
651 xmppConnectionService.setOnConversationListChangedListener(this);
652 xmppConnectionService.setOnAccountListChangedListener(this);
653 xmppConnectionService.setOnRosterUpdateListener(this);
654 }
655 }
656
657 @Override
658 protected void onActivityResult(int requestCode, int resultCode,
659 final Intent data) {
660 super.onActivityResult(requestCode, resultCode, data);
661 if (resultCode == RESULT_OK) {
662 if (requestCode == REQUEST_DECRYPT_PGP) {
663 ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
664 .findFragmentByTag("conversation");
665 if (selectedFragment != null) {
666 selectedFragment.hideSnackbar();
667 }
668 } else if (requestCode == REQUEST_ATTACH_FILE_DIALOG) {
669 pendingImageUri = data.getData();
670 if (xmppConnectionServiceBound) {
671 attachImageToConversation(getSelectedConversation(),
672 pendingImageUri);
673 pendingImageUri = null;
674 }
675 } else if (requestCode == REQUEST_SEND_PGP_IMAGE) {
676
677 } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
678 attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE);
679 } else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) {
680 attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO);
681 } else if (requestCode == REQUEST_ANNOUNCE_PGP) {
682 announcePgp(getSelectedConversation().getAccount(),
683 getSelectedConversation());
684 } else if (requestCode == REQUEST_ENCRYPT_MESSAGE) {
685 // encryptTextMessage();
686 } else if (requestCode == REQUEST_IMAGE_CAPTURE) {
687 if (xmppConnectionServiceBound) {
688 attachImageToConversation(getSelectedConversation(),
689 pendingImageUri);
690 pendingImageUri = null;
691 }
692 Intent intent = new Intent(
693 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
694 intent.setData(pendingImageUri);
695 sendBroadcast(intent);
696 } else if (requestCode == REQUEST_RECORD_AUDIO) {
697 attachAudioToConversation(getSelectedConversation(),
698 data.getData());
699 }
700 }
701 }
702
703 private void attachAudioToConversation(Conversation conversation, Uri uri) {
704
705 }
706
707 private void attachImageToConversation(Conversation conversation, Uri uri) {
708 prepareImageToast = Toast.makeText(getApplicationContext(),
709 getText(R.string.preparing_image), Toast.LENGTH_LONG);
710 prepareImageToast.show();
711 xmppConnectionService.attachImageToConversation(conversation, uri,
712 new UiCallback<Message>() {
713
714 @Override
715 public void userInputRequried(PendingIntent pi,
716 Message object) {
717 hidePrepareImageToast();
718 ConversationActivity.this.runIntent(pi,
719 ConversationActivity.REQUEST_SEND_PGP_IMAGE);
720 }
721
722 @Override
723 public void success(Message message) {
724 xmppConnectionService.sendMessage(message);
725 }
726
727 @Override
728 public void error(int error, Message message) {
729 hidePrepareImageToast();
730 displayErrorDialog(error);
731 }
732 });
733 }
734
735 private void hidePrepareImageToast() {
736 if (prepareImageToast != null) {
737 runOnUiThread(new Runnable() {
738
739 @Override
740 public void run() {
741 prepareImageToast.cancel();
742 }
743 });
744 }
745 }
746
747 public void updateConversationList() {
748 xmppConnectionService
749 .populateWithOrderedConversations(conversationList);
750 listAdapter.notifyDataSetChanged();
751 }
752
753 public void runIntent(PendingIntent pi, int requestCode) {
754 try {
755 this.startIntentSenderForResult(pi.getIntentSender(), requestCode,
756 null, 0, 0, 0);
757 } catch (SendIntentException e1) {
758 }
759 }
760
761 public void encryptTextMessage(Message message) {
762 xmppConnectionService.getPgpEngine().encrypt(message,
763 new UiCallback<Message>() {
764
765 @Override
766 public void userInputRequried(PendingIntent pi,
767 Message message) {
768 activity.runIntent(pi,
769 ConversationActivity.REQUEST_SEND_MESSAGE);
770 }
771
772 @Override
773 public void success(Message message) {
774 message.setEncryption(Message.ENCRYPTION_DECRYPTED);
775 xmppConnectionService.sendMessage(message);
776 }
777
778 @Override
779 public void error(int error, Message message) {
780
781 }
782 });
783 }
784
785 public boolean forceEncryption() {
786 return getPreferences().getBoolean("force_encryption", false);
787 }
788
789 public boolean useSendButtonToIndicateStatus() {
790 return getPreferences().getBoolean("send_button_status", false);
791 }
792
793 @Override
794 public void onAccountUpdate() {
795 final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
796 .findFragmentByTag("conversation");
797 if (fragment != null) {
798 runOnUiThread(new Runnable() {
799
800 @Override
801 public void run() {
802 fragment.updateMessages();
803 }
804 });
805 }
806 }
807
808 @Override
809 public void onConversationUpdate() {
810 runOnUiThread(new Runnable() {
811
812 @Override
813 public void run() {
814 updateConversationList();
815 if (paneShouldBeOpen) {
816 if (conversationList.size() >= 1) {
817 swapConversationFragment();
818 } else {
819 startActivity(new Intent(getApplicationContext(),
820 StartConversationActivity.class));
821 finish();
822 }
823 }
824 ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
825 .findFragmentByTag("conversation");
826 if (selectedFragment != null) {
827 selectedFragment.updateMessages();
828 }
829 }
830 });
831 }
832
833 @Override
834 public void onRosterUpdate() {
835 final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
836 .findFragmentByTag("conversation");
837 if (fragment != null) {
838 runOnUiThread(new Runnable() {
839
840 @Override
841 public void run() {
842 fragment.updateMessages();
843 }
844 });
845 }
846 }
847}