diff options
Diffstat (limited to 'src/main/java/eu/siacs/conversations/ui')
12 files changed, 400 insertions, 152 deletions
diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index e4bfd6ff..8c4f6eaf 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -237,6 +237,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers MenuItem menuItemDeleteBookmark = menu.findItem(R.id.action_delete_bookmark); MenuItem menuItemAdvancedMode = menu.findItem(R.id.action_advanced_mode); menuItemAdvancedMode.setChecked(mAdvancedMode); + if (mConversation == null) { + return true; + } Account account = mConversation.getAccount(); if (account.hasBookmarkFor(mConversation.getJid().toBareJid())) { menuItemSaveBookmark.setVisible(false); diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index 40a4587c..f7156d7a 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -256,16 +256,19 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd MenuItem unblock = menu.findItem(R.id.action_unblock); MenuItem edit = menu.findItem(R.id.action_edit_contact); MenuItem delete = menu.findItem(R.id.action_delete_contact); + if (contact == null) { + return true; + } final XmppConnection connection = contact.getAccount().getXmppConnection(); if (connection != null && connection.getFeatures().blocking()) { if (this.contact.isBlocked()) { - menu.findItem(R.id.action_block).setVisible(false); + block.setVisible(false); } else { - menu.findItem(R.id.action_unblock).setVisible(false); + unblock.setVisible(false); } } else { - menu.findItem(R.id.action_unblock).setVisible(false); - menu.findItem(R.id.action_block).setVisible(false); + unblock.setVisible(false); + block.setVisible(false); } if (!contact.showInRoster()) { edit.setVisible(false); @@ -275,6 +278,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd } private void populateView() { + invalidateOptionsMenu(); setTitle(contact.getDisplayName()); if (contact.showInRoster()) { send.setVisibility(View.VISIBLE); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 82afda07..aec755fc 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -5,6 +5,7 @@ import android.app.ActionBar; import android.app.AlertDialog; import android.app.FragmentTransaction; import android.app.PendingIntent; +import android.content.ClipData; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; @@ -22,14 +23,15 @@ import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.CheckBox; -import android.widget.ListView; import android.widget.PopupMenu; import android.widget.PopupMenu.OnMenuItemClickListener; import android.widget.Toast; import net.java.otr4j.session.SessionStatus; +import de.timroes.android.listview.EnhancedListView; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import eu.siacs.conversations.R; @@ -69,15 +71,16 @@ public class ConversationActivity extends XmppActivity private String mOpenConverstaion = null; private boolean mPanelOpen = true; - private Uri mPendingImageUri = null; - private Uri mPendingFileUri = null; + final private List<Uri> mPendingImageUris = new ArrayList<>(); + final private List<Uri> mPendingFileUris = new ArrayList<>(); private Uri mPendingGeoUri = null; private View mContentView; private List<Conversation> conversationList = new ArrayList<>(); + private Conversation swipedConversation = null; private Conversation mSelectedConversation = null; - private ListView listView; + private EnhancedListView listView; private ConversationFragment mConversationFragment; private ArrayAdapter<Conversation> listAdapter; @@ -140,13 +143,14 @@ public class ConversationActivity extends XmppActivity @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (savedInstanceState != null) {mOpenConverstaion = savedInstanceState.getString( - STATE_OPEN_CONVERSATION, null); - mPanelOpen = savedInstanceState.getBoolean(STATE_PANEL_OPEN, true); - String pending = savedInstanceState.getString(STATE_PENDING_URI, null); - if (pending != null) { - mPendingImageUri = Uri.parse(pending); - } + if (savedInstanceState != null) { + mOpenConverstaion = savedInstanceState.getString(STATE_OPEN_CONVERSATION, null); + mPanelOpen = savedInstanceState.getBoolean(STATE_PANEL_OPEN, true); + String pending = savedInstanceState.getString(STATE_PENDING_URI, null); + if (pending != null) { + mPendingImageUris.clear(); + mPendingImageUris.add(Uri.parse(pending)); + } } setContentView(R.layout.fragment_conversations_overview); @@ -156,7 +160,7 @@ public class ConversationActivity extends XmppActivity transaction.replace(R.id.selected_conversation, this.mConversationFragment, "conversation"); transaction.commit(); - listView = (ListView) findViewById(R.id.list); + listView = (EnhancedListView) findViewById(R.id.list); this.listAdapter = new ConversationAdapter(this, conversationList); listView.setAdapter(this.listAdapter); @@ -178,6 +182,73 @@ public class ConversationActivity extends XmppActivity openConversation(); } }); + + listView.setDismissCallback(new EnhancedListView.OnDismissCallback() { + + @Override + public EnhancedListView.Undoable onDismiss(final EnhancedListView enhancedListView, final int position) { + + final int index = listView.getFirstVisiblePosition(); + View v = listView.getChildAt(0); + final int top = (v == null) ? 0 : (v.getTop() - listView.getPaddingTop()); + + swipedConversation = listAdapter.getItem(position); + listAdapter.remove(swipedConversation); + swipedConversation.markRead(); + xmppConnectionService.getNotificationService().clear(swipedConversation); + + final boolean formerlySelected = (getSelectedConversation() == swipedConversation); + if (position == 0 && listAdapter.getCount() == 0) { + endConversation(swipedConversation, false, true); + return null; + } else if (formerlySelected) { + setSelectedConversation(listAdapter.getItem(0)); + ConversationActivity.this.mConversationFragment + .reInit(getSelectedConversation()); + } + + return new EnhancedListView.Undoable() { + + @Override + public void undo() { + listAdapter.insert(swipedConversation, position); + if (formerlySelected) { + setSelectedConversation(swipedConversation); + ConversationActivity.this.mConversationFragment + .reInit(getSelectedConversation()); + } + swipedConversation = null; + listView.setSelectionFromTop(index + (listView.getChildCount() < position ? 1 : 0), top); + } + + @Override + public void discard() { + if (!swipedConversation.isRead() + && swipedConversation.getMode() == Conversation.MODE_SINGLE) { + swipedConversation = null; + return; + } + endConversation(swipedConversation, false, false); + swipedConversation = null; + } + + @Override + public String getTitle() { + if (swipedConversation.getMode() == Conversation.MODE_MULTI) { + return getResources().getString(R.string.title_undo_swipe_out_muc); + } else { + return getResources().getString(R.string.title_undo_swipe_out_conversation); + } + } + }; + } + }); + listView.enableSwipeToDismiss(); + listView.setSwipingLayout(R.id.swipeable_item); + listView.setUndoStyle(EnhancedListView.UndoStyle.SINGLE_POPUP); + listView.setUndoHideDelay(5000); + listView.setRequireTouchBeforeDismiss(false); + mContentView = findViewById(R.id.content_view_spl); if (mContentView == null) { mContentView = findViewById(R.id.content_view_ll); @@ -204,6 +275,7 @@ public class ConversationActivity extends XmppActivity @Override public void onPanelClosed(View arg0) { + listView.discardUndo(); openConversation(); } @@ -303,7 +375,7 @@ public class ConversationActivity extends XmppActivity if (this.getSelectedConversation().getLatestMessage() .getEncryption() != Message.ENCRYPTION_NONE) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - menuSecure.setIcon(R.drawable.ic_lock_outline_white_48dp); + menuSecure.setIcon(R.drawable.ic_lock_white_24dp); } else { menuSecure.setIcon(R.drawable.ic_action_secure); } @@ -340,13 +412,18 @@ public class ConversationActivity extends XmppActivity switch (attachmentChoice) { case ATTACHMENT_CHOICE_CHOOSE_IMAGE: intent.setAction(Intent.ACTION_GET_CONTENT); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true); + } intent.setType("image/*"); chooser = true; break; case ATTACHMENT_CHOICE_TAKE_PHOTO: - mPendingImageUri = xmppConnectionService.getFileBackend().getTakePhotoUri(); + Uri uri = xmppConnectionService.getFileBackend().getTakePhotoUri(); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); - intent.putExtra(MediaStore.EXTRA_OUTPUT, mPendingImageUri); + intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + mPendingImageUris.clear(); + mPendingImageUris.add(uri); break; case ATTACHMENT_CHOICE_CHOOSE_FILE: chooser = true; @@ -485,13 +562,21 @@ public class ConversationActivity extends XmppActivity } public void endConversation(Conversation conversation) { - showConversationsOverview(); + endConversation(conversation, true, true); + } + + public void endConversation(Conversation conversation, boolean showOverview, boolean reinit) { + if (showOverview) { + showConversationsOverview(); + } xmppConnectionService.archiveConversation(conversation); - if (conversationList.size() > 0) { - setSelectedConversation(conversationList.get(0)); - this.mConversationFragment.reInit(getSelectedConversation()); - } else { - setSelectedConversation(null); + if (reinit) { + if (conversationList.size() > 0) { + setSelectedConversation(conversationList.get(0)); + this.mConversationFragment.reInit(getSelectedConversation()); + } else { + setSelectedConversation(null); + } } } @@ -744,6 +829,7 @@ public class ConversationActivity extends XmppActivity @Override public void onPause() { + listView.discardUndo(); super.onPause(); this.mActivityPaused = true; if (this.xmppConnectionServiceBound) { @@ -779,8 +865,8 @@ public class ConversationActivity extends XmppActivity } savedInstanceState.putBoolean(STATE_PANEL_OPEN, isConversationsOverviewVisable()); - if (this.mPendingImageUri != null) { - savedInstanceState.putString(STATE_PENDING_URI, this.mPendingImageUri.toString()); + if (this.mPendingImageUris.size() >= 1) { + savedInstanceState.putString(STATE_PENDING_URI, this.mPendingImageUris.get(0).toString()); } super.onSaveInstanceState(savedInstanceState); } @@ -819,21 +905,23 @@ public class ConversationActivity extends XmppActivity this.mConversationFragment.reInit(getSelectedConversation()); } else { showConversationsOverview(); - mPendingImageUri = null; - mPendingFileUri = null; + mPendingImageUris.clear(); + mPendingFileUris.clear(); mPendingGeoUri = null; setSelectedConversation(conversationList.get(0)); this.mConversationFragment.reInit(getSelectedConversation()); } - if (mPendingImageUri != null) { - attachImageToConversation(getSelectedConversation(),mPendingImageUri); - mPendingImageUri = null; - } else if (mPendingFileUri != null) { - attachFileToConversation(getSelectedConversation(),mPendingFileUri); - mPendingFileUri = null; - } else if (mPendingGeoUri != null) { - attachLocationToConversation(getSelectedConversation(),mPendingGeoUri); + for(Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) { + attachImageToConversation(getSelectedConversation(),i.next()); + } + + for(Iterator<Uri> i = mPendingFileUris.iterator(); i.hasNext(); i.remove()) { + attachFileToConversation(getSelectedConversation(),i.next()); + } + + if (mPendingGeoUri != null) { + attachLocationToConversation(getSelectedConversation(), mPendingGeoUri); mPendingGeoUri = null; } ExceptionHelper.checkForCrash(this, this.xmppConnectionService); @@ -841,10 +929,10 @@ public class ConversationActivity extends XmppActivity } private void handleViewConversationIntent(final Intent intent) { - final String uuid = (String) intent.getExtras().get(CONVERSATION); - final String downloadUuid = (String) intent.getExtras().get(MESSAGE); - final String text = intent.getExtras().getString(TEXT, ""); - final String nick = intent.getExtras().getString(NICK, null); + final String uuid = intent.getStringExtra(CONVERSATION); + final String downloadUuid = intent.getStringExtra(MESSAGE); + final String text = intent.getStringExtra(TEXT); + final String nick = intent.getStringExtra(NICK); if (selectConversationByUuid(uuid)) { this.mConversationFragment.reInit(getSelectedConversation()); if (nick != null) { @@ -885,6 +973,21 @@ public class ConversationActivity extends XmppActivity xmppConnectionService.getNotificationService().setOpenConversation(null); } + @SuppressLint("NewApi") + private static List<Uri> extractUriFromIntent(final Intent intent) { + List<Uri> uris = new ArrayList<>(); + Uri uri = intent.getData(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && uri == null) { + ClipData clipData = intent.getClipData(); + for(int i = 0; i < clipData.getItemCount(); ++i) { + uris.add(clipData.getItemAt(i).getUri()); + } + } else { + uris.add(uri); + } + return uris; + } + @Override protected void onActivityResult(int requestCode, int resultCode, final Intent data) { @@ -894,25 +997,34 @@ public class ConversationActivity extends XmppActivity mConversationFragment.hideSnackbar(); mConversationFragment.updateMessages(); } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_IMAGE) { - mPendingImageUri = data.getData(); + mPendingImageUris.clear(); + mPendingImageUris.addAll(extractUriFromIntent(data)); if (xmppConnectionServiceBound) { - attachImageToConversation(getSelectedConversation(),mPendingImageUri); - mPendingImageUri = null; + for(Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) { + attachImageToConversation(getSelectedConversation(),i.next()); + } } } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_FILE || requestCode == ATTACHMENT_CHOICE_RECORD_VOICE) { - mPendingFileUri = data.getData(); + mPendingFileUris.clear(); + mPendingFileUris.addAll(extractUriFromIntent(data)); if (xmppConnectionServiceBound) { - attachFileToConversation(getSelectedConversation(),mPendingFileUri); - mPendingFileUri = null; + for(Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) { + attachFileToConversation(getSelectedConversation(), i.next()); + } } - } else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO && mPendingImageUri != null) { - if (xmppConnectionServiceBound) { - attachImageToConversation(getSelectedConversation(),mPendingImageUri); - mPendingImageUri = null; + } else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) { + if (mPendingImageUris.size() == 1) { + Uri uri = mPendingImageUris.get(0); + if (xmppConnectionServiceBound) { + attachImageToConversation(getSelectedConversation(), uri); + mPendingImageUris.clear(); + } + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(uri); + sendBroadcast(intent); + } else { + mPendingImageUris.clear(); } - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(mPendingImageUri); - sendBroadcast(intent); } else if (requestCode == ATTACHMENT_CHOICE_LOCATION) { double latitude = data.getDoubleExtra("latitude",0); double longitude = data.getDoubleExtra("longitude",0); @@ -923,9 +1035,8 @@ public class ConversationActivity extends XmppActivity } } } else { - if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) { - mPendingImageUri = null; - } + mPendingImageUris.clear(); + mPendingFileUris.clear(); } } @@ -1013,6 +1124,13 @@ public class ConversationActivity extends XmppActivity public void updateConversationList() { xmppConnectionService .populateWithOrderedConversations(conversationList); + if (swipedConversation != null) { + if (swipedConversation.isRead()) { + conversationList.remove(swipedConversation); + } else { + listView.discardUndo(); + } + } listAdapter.notifyDataSetChanged(); } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index d5f20e41..5b1e9b4d 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -8,7 +8,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; import android.content.IntentSender.SendIntentException; -import android.net.Uri; import android.os.Bundle; import android.text.InputType; import android.view.ContextMenu; @@ -268,7 +267,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa if (conversation.getNextCounterpart() != null) { message.setCounterpart(conversation.getNextCounterpart()); message.setType(Message.TYPE_PRIVATE); - conversation.setNextCounterpart(null); } } if (conversation.getNextEncryption(activity.forceEncryption()) == Message.ENCRYPTION_OTR) { @@ -316,8 +314,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa @Override public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - final View view = inflater.inflate(R.layout.fragment_conversation, - container, false); + final View view = inflater.inflate(R.layout.fragment_conversation,container, false); + view.setOnClickListener(null); mEditMessage = (EditMessage) view.findViewById(R.id.textinput); setupIme(); mEditMessage.setOnClickListener(new OnClickListener() { @@ -720,21 +718,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa final ConversationActivity activity = (ConversationActivity) getActivity(); if (this.conversation != null) { updateSnackBar(this.conversation); - final Contact contact = this.conversation.getContact(); - if (this.conversation.isBlocked()) { - - } else if (!contact.showInRoster() - && contact - .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { - - } else if (conversation.getMode() == Conversation.MODE_SINGLE) { - makeFingerprintWarning(); - } else if (!conversation.getMucOptions().online() - && conversation.getAccount().getStatus() == Account.State.ONLINE) { - - } else if (this.conversation.isMuted()) { - - } conversation.populateWithMessages(ConversationFragment.this.messageList); for (final Message message : this.messageList) { if (message.getEncryption() == Message.ENCRYPTION_PGP @@ -781,6 +764,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } catch (final NoSuchElementException ignored) { } + askForPassphraseIntent = null; activity.xmppConnectionService.updateMessage(message); } @@ -880,10 +864,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } } - protected void makeFingerprintWarning() { - - } - protected void showSnackbar(final int message, final int action, final OnClickListener clickListener) { snackbar.setVisibility(View.VISIBLE); @@ -1020,6 +1000,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } public void appendText(String text) { + if (text == null) { + return; + } String previous = this.mEditMessage.getText().toString(); if (previous.length() != 0 && !previous.endsWith(" ")) { text = " " + text; diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 27dfc492..7aa7b1c2 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -67,7 +67,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate @Override public void onClick(final View v) { - if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED) { + if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED && !accountInfoEdited()) { mAccount.setOption(Account.OPTION_DISABLED, false); xmppConnectionService.updateAccount(mAccount); return; @@ -237,7 +237,11 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } protected void updateSaveButton() { - if (mAccount != null && (mAccount.getStatus() == Account.State.CONNECTING || mFetchingAvatar)) { + if (accountInfoEdited() && jidToEdit != null) { + this.mSaveButton.setText(R.string.save); + this.mSaveButton.setEnabled(true); + this.mSaveButton.setTextColor(getPrimaryTextColor()); + } else if (mAccount != null && (mAccount.getStatus() == Account.State.CONNECTING || mFetchingAvatar)) { this.mSaveButton.setEnabled(false); this.mSaveButton.setTextColor(getSecondaryTextColor()); this.mSaveButton.setText(R.string.account_status_connecting); @@ -265,9 +269,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } protected boolean accountInfoEdited() { - return (!this.mAccount.getJid().toBareJid().toString().equals( - this.mAccountJid.getText().toString())) - || (!this.mAccount.getPassword().equals( + return this.mAccount != null && (!this.mAccount.getJid().toBareJid().toString().equals( + this.mAccountJid.getText().toString()) + || !this.mAccount.getPassword().equals( this.mPassword.getText().toString())); } @@ -464,7 +468,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } else { this.mServerInfoSm.setText(R.string.server_info_unavailable); } - if (features.pubsub()) { + if (features.pep()) { this.mServerInfoPep.setText(R.string.server_info_available); } else { this.mServerInfoPep.setText(R.string.server_info_unavailable); diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java index b2d5ddfd..56dbc55e 100644 --- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -168,6 +168,14 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda } } + public void onClickTglAccountState(Account account, boolean enable) { + if (enable) { + enableAccount(account); + } else { + disableAccount(account); + } + } + private void publishAvatar(Account account) { Intent intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class); diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index 3f72b723..e8ab8dae 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -163,8 +163,7 @@ public class PublishProfilePictureActivity extends XmppActivity { if (jid != null) { this.account = xmppConnectionService.findAccountByJid(jid); if (this.account.getXmppConnection() != null) { - this.support = this.account.getXmppConnection() - .getFeatures().pubsub(); + this.support = this.account.getXmppConnection().getFeatures().pep(); } if (this.avatarUri == null) { if (this.account.getAvatar() != null diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index 39e215f2..eb5d9b2e 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -1,17 +1,29 @@ package eu.siacs.conversations.ui; +import java.security.KeyStoreException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Locale; +import de.duenndns.ssl.MemorizingTrustManager; + +import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.xmpp.XmppConnection; +import android.app.AlertDialog; +import android.app.Fragment; +import android.app.FragmentManager; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Build; import android.os.Bundle; import android.preference.ListPreference; +import android.preference.Preference; import android.preference.PreferenceManager; +import android.widget.Toast; public class SettingsActivity extends XmppActivity implements OnSharedPreferenceChangeListener { @@ -20,9 +32,12 @@ public class SettingsActivity extends XmppActivity implements @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mSettingsFragment = new SettingsFragment(); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, mSettingsFragment).commit(); + FragmentManager fm = getFragmentManager(); + mSettingsFragment = (SettingsFragment) fm.findFragmentById(android.R.id.content); + if (mSettingsFragment == null || !mSettingsFragment.getClass().equals(SettingsFragment.class)) { + mSettingsFragment = new SettingsFragment(); + fm.beginTransaction().replace(android.R.id.content, mSettingsFragment).commit(); + } } @Override @@ -33,19 +48,78 @@ public class SettingsActivity extends XmppActivity implements @Override public void onStart() { super.onStart(); - PreferenceManager.getDefaultSharedPreferences(this) - .registerOnSharedPreferenceChangeListener(this); - ListPreference resources = (ListPreference) mSettingsFragment - .findPreference("resource"); + PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); + ListPreference resources = (ListPreference) mSettingsFragment.findPreference("resource"); if (resources != null) { - ArrayList<CharSequence> entries = new ArrayList<CharSequence>( - Arrays.asList(resources.getEntries())); - entries.add(0, Build.MODEL); - resources.setEntries(entries.toArray(new CharSequence[entries - .size()])); - resources.setEntryValues(entries.toArray(new CharSequence[entries - .size()])); + ArrayList<CharSequence> entries = new ArrayList<>(Arrays.asList(resources.getEntries())); + if (!entries.contains(Build.MODEL)) { + entries.add(0, Build.MODEL); + resources.setEntries(entries.toArray(new CharSequence[entries.size()])); + resources.setEntryValues(entries.toArray(new CharSequence[entries.size()])); + } } + + final Preference removeCertsPreference = mSettingsFragment.findPreference("remove_trusted_certificates"); + removeCertsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + final MemorizingTrustManager mtm = xmppConnectionService.getMemorizingTrustManager(); + final ArrayList<String> aliases = Collections.list(mtm.getCertificates()); + if (aliases.size() == 0) { + displayToast(getString(R.string.toast_no_trusted_certs)); + return true; + } + final ArrayList selectedItems = new ArrayList<Integer>(); + final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(SettingsActivity.this); + dialogBuilder.setTitle(getResources().getString(R.string.dialog_manage_certs_title)); + dialogBuilder.setMultiChoiceItems(aliases.toArray(new CharSequence[aliases.size()]), null, + new DialogInterface.OnMultiChoiceClickListener() { + @Override + public void onClick(DialogInterface dialog, int indexSelected, + boolean isChecked) { + if (isChecked) { + selectedItems.add(indexSelected); + } else if (selectedItems.contains(indexSelected)) { + selectedItems.remove(Integer.valueOf(indexSelected)); + } + if (selectedItems.size() > 0) + ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true); + else { + ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false); + } + } + }); + + dialogBuilder.setPositiveButton( + getResources().getString(R.string.dialog_manage_certs_positivebutton), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + int count = selectedItems.size(); + if (count > 0) { + for (int i = 0; i < count; i++) { + try { + Integer item = Integer.valueOf(selectedItems.get(i).toString()); + String alias = aliases.get(item); + mtm.deleteCertificate(alias); + } catch (KeyStoreException e) { + e.printStackTrace(); + displayToast("Error: " + e.getLocalizedMessage()); + } + } + if (xmppConnectionServiceBound) { + reconnectAccounts(); + } + displayToast(getResources().getQuantityString(R.plurals.toast_delete_certificates, count, count)); + } + } + }); + dialogBuilder.setNegativeButton(getResources().getString(R.string.dialog_manage_certs_negativebutton), null); + AlertDialog removeCertsDialog = dialogBuilder.create(); + removeCertsDialog.show(); + removeCertsDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); + return true; + } + }); } @Override @@ -63,9 +137,14 @@ public class SettingsActivity extends XmppActivity implements .toLowerCase(Locale.US); if (xmppConnectionServiceBound) { for (Account account : xmppConnectionService.getAccounts()) { - account.setResource(resource); - if (!account.isOptionSet(Account.OPTION_DISABLED)) { - xmppConnectionService.reconnectAccountInBackground(account); + if (account.setResource(resource)) { + if (!account.isOptionSet(Account.OPTION_DISABLED)) { + XmppConnection connection = account.getXmppConnection(); + if (connection != null) { + connection.resetStreamId(); + } + xmppConnectionService.reconnectAccountInBackground(account); + } } } } @@ -79,6 +158,27 @@ public class SettingsActivity extends XmppActivity implements } } } + } else if (name.equals("dont_trust_system_cas")) { + xmppConnectionService.updateMemorizingTrustmanager(); + reconnectAccounts(); + } + + } + + private void displayToast(final String msg) { + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(SettingsActivity.this, msg, Toast.LENGTH_LONG).show(); + } + }); + } + + private void reconnectAccounts() { + for (Account account : xmppConnectionService.getAccounts()) { + if (!account.isOptionSet(Account.OPTION_DISABLED)) { + xmppConnectionService.reconnectAccountInBackground(account); + } } } diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java index 6be238dc..200a577e 100644 --- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java @@ -18,6 +18,7 @@ import java.net.URLConnection; import java.net.URLDecoder; import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import eu.siacs.conversations.Config; @@ -32,7 +33,7 @@ import eu.siacs.conversations.xmpp.jid.Jid; public class ShareWithActivity extends XmppActivity { private class Share { - public Uri uri; + public List<Uri> uris = new ArrayList<>(); public boolean image; public String account; public String contact; @@ -104,7 +105,7 @@ public class ShareWithActivity extends XmppActivity { int position, long arg3) { Conversation conversation = mConversations.get(position); if (conversation.getMode() == Conversation.MODE_SINGLE - || share.uri == null) { + || share.uris.size() == 0) { share(mConversations.get(position)); } } @@ -133,18 +134,32 @@ public class ShareWithActivity extends XmppActivity { @Override public void onStart() { - final String type = getIntent().getType(); - final Uri uri = getIntent().getParcelableExtra(Intent.EXTRA_STREAM); - if (type != null && uri != null && !type.equalsIgnoreCase("text/plain")) { - this.share.uri = uri; - this.share.image = type.startsWith("image/") || isImage(uri); - } else { - this.share.text = getIntent().getStringExtra(Intent.EXTRA_TEXT); + super.onStart(); + Intent intent = getIntent(); + if (intent == null) { + return; + } + final String type = intent.getType(); + if (Intent.ACTION_SEND.equals(intent.getAction())) { + final Uri uri = getIntent().getParcelableExtra(Intent.EXTRA_STREAM); + if (type != null && uri != null && !type.equalsIgnoreCase("text/plain")) { + this.share.uris.add(uri); + this.share.image = type.startsWith("image/") || isImage(uri); + } else { + this.share.text = getIntent().getStringExtra(Intent.EXTRA_TEXT); + } + } else if (Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction())) { + this.share.image = type != null && type.startsWith("image/"); + if (!this.share.image) { + return; + } + + this.share.uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); } if (xmppConnectionServiceBound) { - xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uri == null); + xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.image); } - super.onStart(); + } protected boolean isImage(Uri uri) { @@ -164,7 +179,7 @@ public class ShareWithActivity extends XmppActivity { return; } xmppConnectionService.populateWithOrderedConversations(mConversations, - this.share != null && this.share.uri == null); + this.share != null && this.share.uris.size() == 0); } private void share() { @@ -188,7 +203,7 @@ public class ShareWithActivity extends XmppActivity { } private void share(final Conversation conversation) { - if (share.uri != null) { + if (share.uris.size() != 0) { selectPresence(conversation, new OnPresenceSelected() { @Override public void onPresenceSelected() { @@ -196,22 +211,23 @@ public class ShareWithActivity extends XmppActivity { Toast.makeText(getApplicationContext(), getText(R.string.preparing_image), Toast.LENGTH_LONG).show(); - ShareWithActivity.this.xmppConnectionService - .attachImageToConversation(conversation, share.uri, - attachFileCallback); + for (Iterator<Uri> i = share.uris.iterator(); i.hasNext(); i.remove()) { + ShareWithActivity.this.xmppConnectionService + .attachImageToConversation(conversation, i.next(), + attachFileCallback); + } } else { Toast.makeText(getApplicationContext(), getText(R.string.preparing_file), Toast.LENGTH_LONG).show(); ShareWithActivity.this.xmppConnectionService - .attachFileToConversation(conversation, share.uri, - attachFileCallback); + .attachFileToConversation(conversation, share.uris.get(0), + attachFileCallback); } switchToConversation(conversation, null, true); finish(); } }); - } else { switchToConversation(conversation, this.share.text, true); finish(); diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 7eaec10c..392e57a7 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -90,6 +90,7 @@ public abstract class XmppActivity extends Activity { protected int mPrimaryTextColor; protected int mSecondaryTextColor; + protected int mPrimaryBackgroundColor; protected int mSecondaryBackgroundColor; protected int mColorRed; protected int mColorOrange; @@ -331,6 +332,7 @@ public abstract class XmppActivity extends Activity { mColorOrange = getResources().getColor(R.color.orange); mColorGreen = getResources().getColor(R.color.green); mPrimaryColor = getResources().getColor(R.color.primary); + mPrimaryBackgroundColor = getResources().getColor(R.color.primarybackground); mSecondaryBackgroundColor = getResources().getColor(R.color.secondarybackground); this.mTheme = findTheme(); setTheme(this.mTheme); @@ -740,7 +742,11 @@ public abstract class XmppActivity extends Activity { public int getOnlineColor() { return this.mColorGreen; } - + + public int getPrimaryBackgroundColor() { + return this.mPrimaryBackgroundColor; + } + public int getSecondaryBackgroundColor() { return this.mSecondaryBackgroundColor; } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java index 29730914..95c0524d 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java @@ -5,13 +5,16 @@ import java.util.List; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.ui.XmppActivity; +import eu.siacs.conversations.ui.ManageAccountActivity; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; +import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Switch; public class AccountAdapter extends ArrayAdapter<Account> { @@ -24,7 +27,7 @@ public class AccountAdapter extends ArrayAdapter<Account> { @Override public View getView(int position, View view, ViewGroup parent) { - Account account = getItem(position); + final Account account = getItem(position); if (view == null) { LayoutInflater inflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -34,21 +37,32 @@ public class AccountAdapter extends ArrayAdapter<Account> { jid.setText(account.getJid().toBareJid().toString()); TextView statusView = (TextView) view.findViewById(R.id.account_status); ImageView imageView = (ImageView) view.findViewById(R.id.account_image); - imageView.setImageBitmap(activity.avatarService().get(account, - activity.getPixel(48))); - statusView.setText(getContext().getString(account.getStatus().getReadableId())); - switch (account.getStatus()) { - case ONLINE: - statusView.setTextColor(activity.getOnlineColor()); - break; - case DISABLED: - case CONNECTING: - statusView.setTextColor(activity.getSecondaryTextColor()); - break; - default: - statusView.setTextColor(activity.getWarningTextColor()); - break; - } + imageView.setImageBitmap(activity.avatarService().get(account, activity.getPixel(48))); + statusView.setText(getContext().getString(account.getStatus().getReadableId())); + switch (account.getStatus()) { + case ONLINE: + statusView.setTextColor(activity.getOnlineColor()); + break; + case DISABLED: + case CONNECTING: + statusView.setTextColor(activity.getSecondaryTextColor()); + break; + default: + statusView.setTextColor(activity.getWarningTextColor()); + break; + } + final Switch tglAccountState = (Switch) view.findViewById(R.id.tgl_account_status); + final boolean isDisabled = (account.getStatus() == Account.State.DISABLED) ? true : false; + tglAccountState.setOnCheckedChangeListener(null); + tglAccountState.setChecked(!isDisabled); + tglAccountState.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + if (b == isDisabled && activity instanceof ManageAccountActivity) { + ((ManageAccountActivity) activity).onClickTglAccountState(account,b); + } + } + }); return view; } } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index a48f6ae4..d5b7e4c0 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -46,17 +46,10 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> { } Conversation conversation = getItem(position); if (this.activity instanceof ConversationActivity) { - ConversationActivity activity = (ConversationActivity) this.activity; - if (!activity.isConversationsOverviewHideable()) { - if (conversation == activity.getSelectedConversation()) { - view.setBackgroundColor(activity - .getSecondaryBackgroundColor()); - } else { - view.setBackgroundColor(Color.TRANSPARENT); - } - } else { - view.setBackgroundColor(Color.TRANSPARENT); - } + View swipeableItem = view.findViewById(R.id.swipeable_item); + ConversationActivity a = (ConversationActivity) this.activity; + int c = !a.isConversationsOverviewHideable() && conversation == a.getSelectedConversation() ? a.getSecondaryBackgroundColor() : a.getPrimaryBackgroundColor(); + swipeableItem.setBackgroundColor(c); } TextView convName = (TextView) view.findViewById(R.id.conversation_name); if (conversation.getMode() == Conversation.MODE_SINGLE || activity.useSubjectToIdentifyConference()) { |