From 50248bd570f1de019b18a467e5181c4d14a772f6 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 2 Nov 2015 21:29:53 +0100 Subject: extended: init tabs with loader info --- .../keychain/ui/ViewKeyAdvActivity.java | 20 +++++++++++--------- .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 5 +++-- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java index 94a171f14..e676b441f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -78,9 +78,6 @@ public class ViewKeyAdvActivity extends BaseActivity implements mViewPager = (ViewPager) findViewById(R.id.pager); mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tab_layout); - Intent intent = getIntent(); - int switchToTab = intent.getIntExtra(EXTRA_SELECTED_TAB, TAB_SHARE); - mDataUri = getIntent().getData(); if (mDataUri == null) { Log.e(Constants.TAG, "Data missing. Should be uri of key!"); @@ -101,10 +98,6 @@ public class ViewKeyAdvActivity extends BaseActivity implements // or start new ones. getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); - initTabs(mDataUri); - - // switch to tab selected by extra - mViewPager.setCurrentItem(switchToTab); } @Override @@ -112,17 +105,18 @@ public class ViewKeyAdvActivity extends BaseActivity implements setContentView(R.layout.view_key_adv_activity); } - private void initTabs(Uri dataUri) { + private void initTabs(Uri dataUri, boolean hasSecret) { PagerTabStripAdapter adapter = new PagerTabStripAdapter(this); mViewPager.setAdapter(adapter); Bundle shareBundle = new Bundle(); - shareBundle.putParcelable(ViewKeyAdvUserIdsFragment.ARG_DATA_URI, dataUri); + shareBundle.putParcelable(ViewKeyAdvShareFragment.ARG_DATA_URI, dataUri); adapter.addTab(ViewKeyAdvShareFragment.class, shareBundle, getString(R.string.key_view_tab_share)); Bundle userIdsBundle = new Bundle(); userIdsBundle.putParcelable(ViewKeyAdvUserIdsFragment.ARG_DATA_URI, dataUri); + userIdsBundle.putBoolean(ViewKeyAdvUserIdsFragment.ARG_HAS_SECRET, hasSecret); adapter.addTab(ViewKeyAdvUserIdsFragment.class, userIdsBundle, getString(R.string.section_user_ids)); @@ -138,6 +132,12 @@ public class ViewKeyAdvActivity extends BaseActivity implements // update layout after operations mSlidingTabLayout.setViewPager(mViewPager); + + // switch to tab selected by extra + Intent intent = getIntent(); + int switchToTab = intent.getIntExtra(EXTRA_SELECTED_TAB, TAB_SHARE); + mViewPager.setCurrentItem(switchToTab); + } // These are the rows that we will retrieve. @@ -216,6 +216,8 @@ public class ViewKeyAdvActivity extends BaseActivity implements mStatusBar.setBackgroundColor(ViewKeyActivity.getStatusBarBackgroundColor(color)); mSlidingTabLayout.setBackgroundColor(color); + initTabs(mDataUri, isSecret); + break; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index ad437f924..386a26ae2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -43,15 +43,16 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { public static final String ARG_DATA_URI = "uri"; + public static final String ARG_HAS_SECRET = "has_secret"; private ListView mUserIds; - private static final int LOADER_ID_UNIFIED = 0; - private static final int LOADER_ID_USER_IDS = 1; + private static final int LOADER_ID_USER_IDS = 0; private UserIdsAdapter mUserIdsAdapter; private Uri mDataUri; + private boolean mHasSecret; @Override public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { -- cgit v1.2.3 From 5b6bc24a0c87162609d1c2b60ac8c13144641680 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 2 Nov 2015 21:30:41 +0100 Subject: extend-uid: add option icon for edit action mode --- .../keychain/ui/ViewKeyAdvActivity.java | 4 + .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 127 +++++++++++++-------- .../keychain/ui/adapter/UserIdsAdapter.java | 18 ++- .../keychain/ui/adapter/UserIdsAddedAdapter.java | 2 +- 4 files changed, 92 insertions(+), 59 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java index e676b441f..dc66e52ed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -26,6 +26,10 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.view.ViewPager; +import android.support.v7.view.ActionMode; +import android.support.v7.view.ActionMode.Callback; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.widget.Toast; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index 386a26ae2..2afb7d216 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -21,10 +21,16 @@ package org.sufficientlysecure.keychain.ui; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.view.ActionMode; +import android.view.ActionMode.Callback; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -33,8 +39,8 @@ import android.widget.ListView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -95,54 +101,44 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements getActivity().finish(); return; } + boolean hasSecret = getArguments().getBoolean(ARG_HAS_SECRET); - loadData(dataUri); + loadData(dataUri, hasSecret); } - private void loadData(Uri dataUri) { + private void loadData(Uri dataUri, boolean hasSecret) { mDataUri = dataUri; + mHasSecret = hasSecret; - Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); + Log.i(Constants.TAG, "mDataUri: " + mDataUri); mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0); mUserIds.setAdapter(mUserIdsAdapter); + setHasOptionsMenu(hasSecret); + // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. - getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); } - static final String[] UNIFIED_PROJECTION = new String[]{ - KeyRings._ID, KeyRings.MASTER_KEY_ID, - KeyRings.HAS_ANY_SECRET, KeyRings.IS_REVOKED, KeyRings.IS_EXPIRED, KeyRings.HAS_ENCRYPT - }; - static final int INDEX_UNIFIED_MASTER_KEY_ID = 1; - static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2; - static final int INDEX_UNIFIED_IS_REVOKED = 3; - static final int INDEX_UNIFIED_IS_EXPIRED = 4; - static final int INDEX_UNIFIED_HAS_ENCRYPT = 5; - public Loader onCreateLoader(int id, Bundle args) { setContentShown(false); - switch (id) { - case LOADER_ID_UNIFIED: { - Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri); - return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null); - } - case LOADER_ID_USER_IDS: { - Uri baseUri = UserPackets.buildUserIdsUri(mDataUri); - return new CursorLoader(getActivity(), baseUri, - UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null); - } - - default: - return null; + if (id != LOADER_ID_USER_IDS) { + return null; } + + Uri baseUri = UserPackets.buildUserIdsUri(mDataUri); + return new CursorLoader(getActivity(), baseUri, + UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null); } public void onLoadFinished(Loader loader, Cursor data) { + if (loader.getId() != LOADER_ID_USER_IDS) { + return; + } + /* TODO better error handling? May cause problems when a key is deleted, * because the notification triggers faster than the activity closes. */ @@ -150,23 +146,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements if (data.getCount() == 0) { return; } - // Swap the new cursor in. (The framework will take care of closing the - // old cursor once we return.) - switch (loader.getId()) { - case LOADER_ID_UNIFIED: { - if (data.moveToFirst()) { - - break; - } - } - - case LOADER_ID_USER_IDS: { - mUserIdsAdapter.swapCursor(data); - break; - } - - } + mUserIdsAdapter.swapCursor(data); setContentShown(true); } @@ -175,11 +156,61 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements * We need to make sure we are no longer using it. */ public void onLoaderReset(Loader loader) { - switch (loader.getId()) { - case LOADER_ID_USER_IDS: - mUserIdsAdapter.swapCursor(null); - break; + if (loader.getId() != LOADER_ID_USER_IDS) { + return; } + mUserIdsAdapter.swapCursor(null); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.edit_user_id, menu); + MenuItem vEditUserIds = menu.findItem(R.id.menu_edit_user_ids); + vEditUserIds.setVisible(mHasSecret); } + public void enterEditMode() { + FragmentActivity activity = getActivity(); + activity.startActionMode(new Callback() { + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mUserIdsAdapter.setEditMode(new SaveKeyringParcel(0L, new byte[0])); + getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); + + mode.setTitle("Edit User Ids"); + mode.getMenuInflater().inflate(R.menu.action_edit_uids, menu); + + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + mode.finish(); + return true; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + mUserIdsAdapter.setEditMode(null); + getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); + } + }); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_edit_user_ids: + enterEditMode(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index 0f4312dad..d5a9f551d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -29,6 +29,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import android.widget.ViewAnimator; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; @@ -66,7 +67,7 @@ public class UserIdsAdapter extends UserAttributesAdapter { TextView vAddress = (TextView) view.findViewById(R.id.user_id_item_address); TextView vComment = (TextView) view.findViewById(R.id.user_id_item_comment); ImageView vVerified = (ImageView) view.findViewById(R.id.user_id_item_certified); - View vVerifiedLayout = view.findViewById(R.id.user_id_item_certified_layout); + ViewAnimator vVerifiedLayout = (ViewAnimator) view.findViewById(R.id.user_id_icon_animator); ImageView vEditImage = (ImageView) view.findViewById(R.id.user_id_item_edit_image); ImageView vDeleteButton = (ImageView) view.findViewById(R.id.user_id_item_delete_button); vDeleteButton.setVisibility(View.GONE); // not used @@ -114,16 +115,9 @@ public class UserIdsAdapter extends UserAttributesAdapter { } } - vEditImage.setVisibility(View.VISIBLE); - vVerifiedLayout.setVisibility(View.GONE); + vVerifiedLayout.setDisplayedChild(2); } else { - vEditImage.setVisibility(View.GONE); - - if (mShowStatusImages) { - vVerifiedLayout.setVisibility(View.VISIBLE); - } else { - vVerifiedLayout.setVisibility(View.GONE); - } + vVerifiedLayout.setDisplayedChild(mShowStatusImages ? 1 : 0); } if (isRevoked) { @@ -177,6 +171,10 @@ public class UserIdsAdapter extends UserAttributesAdapter { return isRevokedPending; } + public void setEditMode(SaveKeyringParcel saveKeyringParcel) { + mSaveKeyringParcel = saveKeyringParcel; + } + @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { return mInflater.inflate(R.layout.view_key_adv_user_id_item, null); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java index c7197b46d..b1892b27e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java @@ -72,7 +72,7 @@ public class UserIdsAddedAdapter extends ArrayAdapter { holder.vDelete.setVisibility(View.VISIBLE); // always visible // not used: - View certifiedLayout = convertView.findViewById(R.id.user_id_item_certified_layout); + View certifiedLayout = convertView.findViewById(R.id.user_id_icon_animator); ImageView editImage = (ImageView) convertView.findViewById(R.id.user_id_item_edit_image); certifiedLayout.setVisibility(View.GONE); editImage.setVisibility(View.GONE); -- cgit v1.2.3 From a041acab65b916e3727ec679edc0f5583847a96c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 2 Nov 2015 21:59:31 +0100 Subject: extend-uid: allow changes to user ids in edit mode --- .../keychain/ui/EditKeyFragment.java | 3 +- .../keychain/ui/ViewKeyAdvActivity.java | 6 +- .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 70 +++++++++++++++++++++- .../keychain/ui/adapter/UserAttributesAdapter.java | 1 + .../keychain/ui/adapter/UserIdsAdapter.java | 17 ++++-- .../ui/adapter/UserIdsSelectableAdapter.java | 4 +- 6 files changed, 85 insertions(+), 16 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 07b0a12d3..fa0edec48 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -223,7 +223,8 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment parent, View view, int position, long id) { - showUserIdInfo(position); + showOrEditUserIdInfo(position); } }); return root; } + private void showOrEditUserIdInfo(final int position) { + if (mEditModeSaveKeyringParcel != null) { + editUserId(position); + } else { + showUserIdInfo(position); + } + } + + private void editUserId(final int position) { + final String userId = mUserIdsAdapter.getUserId(position); + final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); + final boolean isRevokedPending = mUserIdsAdapter.getIsRevokedPending(position); + + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + switch (message.what) { + case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID: + // toggle + if (mEditModeSaveKeyringParcel.mChangePrimaryUserId != null + && mEditModeSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { + mEditModeSaveKeyringParcel.mChangePrimaryUserId = null; + } else { + mEditModeSaveKeyringParcel.mChangePrimaryUserId = userId; + } + break; + case EditUserIdDialogFragment.MESSAGE_REVOKE: + // toggle + if (mEditModeSaveKeyringParcel.mRevokeUserIds.contains(userId)) { + mEditModeSaveKeyringParcel.mRevokeUserIds.remove(userId); + } else { + mEditModeSaveKeyringParcel.mRevokeUserIds.add(userId); + // not possible to revoke and change to primary user id + if (mEditModeSaveKeyringParcel.mChangePrimaryUserId != null + && mEditModeSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { + mEditModeSaveKeyringParcel.mChangePrimaryUserId = null; + } + } + break; + } + getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); + } + }; + + // Create a new Messenger for the communication back + final Messenger messenger = new Messenger(returnHandler); + + DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { + public void run() { + EditUserIdDialogFragment dialogFragment = + EditUserIdDialogFragment.newInstance(messenger, isRevoked, isRevokedPending); + dialogFragment.show(getActivity().getSupportFragmentManager(), "editUserIdDialog"); + } + }); + } + private void showUserIdInfo(final int position) { + final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); final int isVerified = mUserIdsAdapter.getIsVerified(position); @@ -175,10 +237,11 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements activity.startActionMode(new Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { - mUserIdsAdapter.setEditMode(new SaveKeyringParcel(0L, new byte[0])); + mEditModeSaveKeyringParcel = new SaveKeyringParcel(0L, new byte[0]); + mUserIdsAdapter.setEditMode(mEditModeSaveKeyringParcel); getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); - mode.setTitle("Edit User Ids"); + mode.setTitle(R.string.title_edit_identities); mode.getMenuInflater().inflate(R.menu.action_edit_uids, menu); return true; @@ -197,6 +260,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements @Override public void onDestroyActionMode(ActionMode mode) { + mEditModeSaveKeyringParcel = null; mUserIdsAdapter.setEditMode(null); getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java index e0abaf4b0..31f8513fa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java @@ -1,5 +1,6 @@ package org.sufficientlysecure.keychain.ui.adapter; + import android.content.Context; import android.database.Cursor; import android.support.v4.widget.CursorAdapter; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index d5a9f551d..7dee90b4e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -23,6 +23,7 @@ import android.content.Context; import android.database.Cursor; import android.graphics.Typeface; import android.net.Uri; +import android.support.annotation.Nullable; import android.support.v4.content.CursorLoader; import android.view.LayoutInflater; import android.view.View; @@ -53,10 +54,6 @@ public class UserIdsAdapter extends UserAttributesAdapter { mShowStatusImages = showStatusImages; } - public UserIdsAdapter(Context context, Cursor c, int flags, SaveKeyringParcel saveKeyringParcel) { - this(context, c, flags, true, saveKeyringParcel); - } - public UserIdsAdapter(Context context, Cursor c, int flags) { this(context, c, flags, true, null); } @@ -171,7 +168,17 @@ public class UserIdsAdapter extends UserAttributesAdapter { return isRevokedPending; } - public void setEditMode(SaveKeyringParcel saveKeyringParcel) { + /** Set this adapter into edit mode. This mode displays additional info for + * each item from a supplied SaveKeyringParcel reference. + * + * Note that it is up to the caller to reload the underlying cursor after + * updating the SaveKeyringParcel! + * + * @see SaveKeyringParcel + * + * @param saveKeyringParcel The parcel to get info from, or null to leave edit mode. + */ + public void setEditMode(@Nullable SaveKeyringParcel saveKeyringParcel) { mSaveKeyringParcel = saveKeyringParcel; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsSelectableAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsSelectableAdapter.java index 947d911c3..3cc2e2044 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsSelectableAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsSelectableAdapter.java @@ -18,8 +18,8 @@ public class UserIdsSelectableAdapter extends UserIdsAdapter implements AdapterV private final ArrayList mCheckStates; - public UserIdsSelectableAdapter(Context context, Cursor c, int flags, SaveKeyringParcel saveKeyringParcel) { - super(context, c, flags, saveKeyringParcel); + public UserIdsSelectableAdapter(Context context, Cursor c, int flags) { + super(context, c, flags); mCheckStates = new ArrayList(); } -- cgit v1.2.3 From 4ec51fcd9fc1a0871436cdb3d44428d6af23afac Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 2 Nov 2015 22:14:21 +0100 Subject: extend-uid: button and list to add user ids --- .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 51 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index fdaf188ca..6186e1440 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ui; + import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -45,7 +46,10 @@ import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; +import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -55,11 +59,14 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements public static final String ARG_DATA_URI = "uri"; public static final String ARG_HAS_SECRET = "has_secret"; - private ListView mUserIds; - private static final int LOADER_ID_USER_IDS = 0; + private ListView mUserIds; + private ListView mUserIdsAddedList; + private View mUserIdsAddedLayout; + private UserIdsAdapter mUserIdsAdapter; + private UserIdsAddedAdapter mUserIdsAddedAdapter; private Uri mDataUri; private boolean mHasSecret; @@ -71,6 +78,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements View view = inflater.inflate(R.layout.view_key_adv_main_fragment, getContainer()); mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); + mUserIdsAddedList = (ListView) view.findViewById(R.id.view_key_user_ids_added); + mUserIdsAddedLayout = view.findViewById(R.id.view_key_user_ids_add_layout); mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -79,6 +88,13 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements } }); + view.findViewById(R.id.view_key_action_add_user_id).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + addUserId(); + } + }); + return root; } @@ -153,6 +169,29 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements }); } + private void addUserId() { + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) { + Bundle data = message.getData(); + + // add new user id + mUserIdsAddedAdapter.add(data + .getString(AddUserIdDialogFragment.MESSAGE_DATA_USER_ID)); + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + + // pre-fill out primary name + AddUserIdDialogFragment addUserIdDialog = AddUserIdDialogFragment.newInstance(messenger, ""); + + addUserIdDialog.show(getActivity().getSupportFragmentManager(), "addUserIdDialog"); + } + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -237,7 +276,14 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements activity.startActionMode(new Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mEditModeSaveKeyringParcel = new SaveKeyringParcel(0L, new byte[0]); + + mUserIdsAddedAdapter = + new UserIdsAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddUserIds, false); + mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); + mUserIdsAddedLayout.setVisibility(View.VISIBLE); + mUserIdsAdapter.setEditMode(mEditModeSaveKeyringParcel); getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); @@ -262,6 +308,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements public void onDestroyActionMode(ActionMode mode) { mEditModeSaveKeyringParcel = null; mUserIdsAdapter.setEditMode(null); + mUserIdsAddedLayout.setVisibility(View.GONE); getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); } }); -- cgit v1.2.3 From 312c245de10ef39a45cfdd832634017a4a1bb79f Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 2 Nov 2015 23:05:20 +0100 Subject: extended-share: move qr code resizing into onLayoutChangeListener (+performance, -recreation crash) --- .../keychain/ui/ViewKeyAdvShareFragment.java | 47 ++++++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java index c5e575e32..ce2f2def8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java @@ -44,6 +44,7 @@ import android.support.v4.content.Loader; import android.support.v7.widget.CardView; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.widget.ImageButton; @@ -85,6 +86,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements private byte[] mFingerprint; private String mUserId; + private Bitmap mQrCodeBitmapCache; @Override public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { @@ -96,6 +98,34 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements mFingerprintView = (TextView) view.findViewById(R.id.view_key_fingerprint); mQrCode = (ImageView) view.findViewById(R.id.view_key_qr_code); + + // We cache the QR code bitmap in its smallest possible size, then scale + // it manually for the correct size whenever the layout of the ImageView + // changes. The fingerprint qr code loader which runs in the background + // just calls requestLayout when it is finished, this way the loader and + // background task are disconnected from any layouting the ImageView may + // undergo. Please note how these six lines are perfectly right-aligned. + mQrCode.addOnLayoutChangeListener(new OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, + int oldRight, + int oldBottom) { + // bitmap scaling is expensive, avoid doing it if we already have the correct size! + int mCurrentWidth = 0, mCurrentHeight = 0; + if (mQrCodeBitmapCache != null) { + if (mCurrentWidth == mQrCode.getWidth() && mCurrentHeight == mQrCode.getHeight()) { + return; + } + mCurrentWidth = mQrCode.getWidth(); + mCurrentHeight = mQrCode.getHeight(); + // scale the image up to our actual size. we do this in code rather + // than let the ImageView do this because we don't require filtering. + Bitmap scaled = Bitmap.createScaledBitmap(mQrCodeBitmapCache, + mCurrentWidth, mCurrentHeight, false); + mQrCode.setImageBitmap(scaled); + } + } + }); mQrCodeLayout = (CardView) view.findViewById(R.id.view_key_qr_code_layout); mQrCodeLayout.setOnClickListener(new View.OnClickListener() { @Override @@ -379,6 +409,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements */ public void onLoaderReset(Loader loader) { mFingerprint = null; + mQrCodeBitmapCache = null; } /** @@ -390,6 +421,10 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements final String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintBlob); mFingerprintView.setText(KeyFormattingUtils.colorizeFingerprint(fingerprint)); + if (mQrCodeBitmapCache != null) { + return; + } + AsyncTask loadTask = new AsyncTask() { protected Bitmap doInBackground(Void... unused) { @@ -402,15 +437,11 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements } protected void onPostExecute(Bitmap qrCode) { - // only change view, if fragment is attached to activity - if (ViewKeyAdvShareFragment.this.isAdded()) { + // cache for later, and if we are attached request re-layout + mQrCodeBitmapCache = qrCode; - // scale the image up to our actual size. we do this in code rather - // than let the ImageView do this because we don't require filtering. - Bitmap scaled = Bitmap.createScaledBitmap(qrCode, - mQrCode.getHeight(), mQrCode.getHeight(), - false); - mQrCode.setImageBitmap(scaled); + if (ViewKeyAdvShareFragment.this.isAdded()) { + mQrCode.requestLayout(); // simple fade-in animation AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f); -- cgit v1.2.3 From 54cc08c2917e2872cb79e56410b7c305dcebfef6 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 2 Nov 2015 23:06:35 +0100 Subject: extended: leave ActionMode on page change --- .../keychain/ui/ViewKeyAdvActivity.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java index a27bb3ad3..3db6bf4ae 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -27,6 +27,8 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.SimpleOnPageChangeListener; +import android.view.ActionMode; import android.view.View; import android.widget.Toast; @@ -239,4 +241,23 @@ public class ViewKeyAdvActivity extends BaseActivity implements super.onActivityResult(requestCode, resultCode, data); } } + + @Override + public void onActionModeStarted(final ActionMode mode) { + super.onActionModeStarted(mode); + // Leave whatever action mode we are in when we change the page + mSlidingTabLayout.setOnPageChangeListener(new SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + super.onPageSelected(position); + mode.finish(); + } + }); + } + + @Override + public void onActionModeFinished(ActionMode mode) { + super.onActionModeFinished(mode); + mSlidingTabLayout.setOnPageChangeListener(null); + } } -- cgit v1.2.3 From fd119bda00bac1cfe6dbcafa2736c65e3624c083 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 3 Nov 2015 00:30:12 +0100 Subject: extend-uid: use FAB instead of extra list item --- .../keychain/ui/ViewKeyAdvActivity.java | 2 ++ .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java index 3db6bf4ae..01dc10d28 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -29,6 +29,7 @@ import android.support.v4.content.Loader; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.SimpleOnPageChangeListener; import android.view.ActionMode; +import android.view.Menu; import android.view.View; import android.widget.Toast; @@ -260,4 +261,5 @@ public class ViewKeyAdvActivity extends BaseActivity implements super.onActionModeFinished(mode); mSlidingTabLayout.setOnPageChangeListener(null); } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index 6186e1440..e98970754 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -39,6 +39,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListView; +import android.widget.ViewAnimator; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -64,6 +65,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements private ListView mUserIds; private ListView mUserIdsAddedList; private View mUserIdsAddedLayout; + private ViewAnimator mUserIdAddFabLayout; private UserIdsAdapter mUserIdsAdapter; private UserIdsAddedAdapter mUserIdsAddedAdapter; @@ -88,7 +90,19 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements } }); - view.findViewById(R.id.view_key_action_add_user_id).setOnClickListener(new View.OnClickListener() { + View footer = new View(getActivity()); + int spacing = (int) android.util.TypedValue.applyDimension( + android.util.TypedValue.COMPLEX_UNIT_DIP, 72, getResources().getDisplayMetrics() + ); + android.widget.AbsListView.LayoutParams params = new android.widget.AbsListView.LayoutParams( + android.widget.AbsListView.LayoutParams.MATCH_PARENT, + spacing + ); + footer.setLayoutParams(params); + mUserIdsAddedList.addFooterView(footer, null, false); + + mUserIdAddFabLayout = (ViewAnimator) view.findViewById(R.id.view_key_user_id_fab_layout); + view.findViewById(R.id.view_key_user_id_fab).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { addUserId(); @@ -271,7 +285,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements vEditUserIds.setVisible(mHasSecret); } - public void enterEditMode() { + private void enterEditMode() { FragmentActivity activity = getActivity(); activity.startActionMode(new Callback() { @Override @@ -283,6 +297,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements new UserIdsAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddUserIds, false); mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); mUserIdsAddedLayout.setVisibility(View.VISIBLE); + mUserIdAddFabLayout.setDisplayedChild(1); mUserIdsAdapter.setEditMode(mEditModeSaveKeyringParcel); getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); @@ -309,6 +324,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements mEditModeSaveKeyringParcel = null; mUserIdsAdapter.setEditMode(null); mUserIdsAddedLayout.setVisibility(View.GONE); + mUserIdAddFabLayout.setDisplayedChild(0); getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); } }); -- cgit v1.2.3 From 00e97586b06e5e61f6639b75423f9ec3edba47a0 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 14 Nov 2015 03:24:07 +0100 Subject: inline subkey editing (wip commit) --- .../keychain/ui/EditKeyFragment.java | 3 +- .../keychain/ui/ViewKeyAdvSubkeysFragment.java | 272 ++++++++++++++++++++- .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 4 +- .../keychain/ui/adapter/SubkeysAdapter.java | 29 ++- 4 files changed, 294 insertions(+), 14 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index fa0edec48..969a84f14 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -231,7 +231,8 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment { public static final String ARG_DATA_URI = "data_uri"; + public static final int LOADER_ID_SUBKEYS = 0; private ListView mSubkeysList; + private ListView mSubkeysAddedList; + private View mSubkeysAddedLayout; + private ViewAnimator mSubkeyAddFabLayout; + private SubkeysAdapter mSubkeysAdapter; + private SubkeysAddedAdapter mSubkeysAddedAdapter; private Uri mDataUriSubkeys; + private boolean mHasSecret; + private SaveKeyringParcel mEditModeSaveKeyringParcel; + /** * Creates new instance of this fragment */ @@ -64,6 +93,36 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements mSubkeysList = (ListView) view.findViewById(R.id.keys); + mSubkeysList = (ListView) view.findViewById(R.id.view_key_user_ids); + mSubkeysAddedList = (ListView) view.findViewById(R.id.view_key_user_ids_added); + mSubkeysAddedLayout = view.findViewById(R.id.view_key_user_ids_add_layout); + + mSubkeysList.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + editSubkey(position); + } + }); + + View footer = new View(getActivity()); + int spacing = (int) android.util.TypedValue.applyDimension( + android.util.TypedValue.COMPLEX_UNIT_DIP, 72, getResources().getDisplayMetrics() + ); + android.widget.AbsListView.LayoutParams params = new android.widget.AbsListView.LayoutParams( + android.widget.AbsListView.LayoutParams.MATCH_PARENT, + spacing + ); + footer.setLayoutParams(params); + mSubkeysAddedList.addFooterView(footer, null, false); + + mSubkeyAddFabLayout = (ViewAnimator) view.findViewById(R.id.view_key_subkey_fab_layout); + view.findViewById(R.id.view_key_subkey_fab).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + addSubkey(); + } + }); + return root; } @@ -90,7 +149,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. - getLoaderManager().initLoader(0, null, this); + getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, this); } public Loader onCreateLoader(int id, Bundle args) { @@ -122,4 +181,215 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements mSubkeysAdapter.swapCursor(null); } + private void enterEditMode() { + FragmentActivity activity = getActivity(); + activity.startActionMode(new Callback() { + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + + mEditModeSaveKeyringParcel = new SaveKeyringParcel(0L, new byte[0]); + + mSubkeysAddedAdapter = + new SubkeysAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddSubKeys, false); + mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter); + mSubkeysAddedLayout.setVisibility(View.VISIBLE); + mSubkeyAddFabLayout.setDisplayedChild(1); + + mSubkeysAdapter.setEditMode(mEditModeSaveKeyringParcel); + getLoaderManager().restartLoader(LOADER_ID_SUBKEYS, null, ViewKeyAdvSubkeysFragment.this); + + mode.setTitle(R.string.title_edit_subkeys); + mode.getMenuInflater().inflate(R.menu.action_edit_uids, menu); + + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + mode.finish(); + return true; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + mEditModeSaveKeyringParcel = null; + mSubkeysAdapter.setEditMode(null); + mSubkeysAddedLayout.setVisibility(View.GONE); + mSubkeyAddFabLayout.setDisplayedChild(0); + getLoaderManager().restartLoader(0, null, ViewKeyAdvSubkeysFragment.this); + } + }); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_edit_subkeys: + enterEditMode(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private void addSubkey() { + boolean willBeMasterKey; + if (mSubkeysAdapter != null) { + willBeMasterKey = mSubkeysAdapter.getCount() == 0 && mSubkeysAddedAdapter.getCount() == 0; + } else { + willBeMasterKey = mSubkeysAddedAdapter.getCount() == 0; + } + + AddSubkeyDialogFragment addSubkeyDialogFragment = + AddSubkeyDialogFragment.newInstance(willBeMasterKey); + addSubkeyDialogFragment + .setOnAlgorithmSelectedListener( + new AddSubkeyDialogFragment.OnAlgorithmSelectedListener() { + @Override + public void onAlgorithmSelected(SaveKeyringParcel.SubkeyAdd newSubkey) { + mSubkeysAddedAdapter.add(newSubkey); + } + } + ); + addSubkeyDialogFragment.show(getActivity().getSupportFragmentManager(), "addSubkeyDialog"); + } + + private void editSubkey(final int position) { + final long keyId = mSubkeysAdapter.getKeyId(position); + + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + switch (message.what) { + case EditSubkeyDialogFragment.MESSAGE_CHANGE_EXPIRY: + editSubkeyExpiry(position); + break; + case EditSubkeyDialogFragment.MESSAGE_REVOKE: + // toggle + if (mEditModeSaveKeyringParcel.mRevokeSubKeys.contains(keyId)) { + mEditModeSaveKeyringParcel.mRevokeSubKeys.remove(keyId); + } else { + mEditModeSaveKeyringParcel.mRevokeSubKeys.add(keyId); + } + break; + case EditSubkeyDialogFragment.MESSAGE_STRIP: { + SecretKeyType secretKeyType = mSubkeysAdapter.getSecretKeyType(position); + if (secretKeyType == SecretKeyType.GNU_DUMMY) { + // Key is already stripped; this is a no-op. + break; + } + + SubkeyChange change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId); + if (change == null) { + mEditModeSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false)); + break; + } + // toggle + change.mDummyStrip = !change.mDummyStrip; + if (change.mDummyStrip && change.mMoveKeyToCard) { + // User had chosen to divert key, but now wants to strip it instead. + change.mMoveKeyToCard = false; + } + break; + } + case EditSubkeyDialogFragment.MESSAGE_MOVE_KEY_TO_CARD: { + // TODO: enable later when Admin PIN handling is resolved + Notify.create(getActivity(), + "This feature will be available in an upcoming OpenKeychain version.", + Notify.Style.WARN).show(); + break; + +// Activity activity = EditKeyFragment.this.getActivity(); +// SecretKeyType secretKeyType = mSubkeysAdapter.getSecretKeyType(position); +// if (secretKeyType == SecretKeyType.DIVERT_TO_CARD || +// secretKeyType == SecretKeyType.GNU_DUMMY) { +// Notify.create(activity, R.string.edit_key_error_bad_nfc_stripped, Notify.Style.ERROR) +// .show((ViewGroup) activity.findViewById(R.id.import_snackbar)); +// break; +// } +// int algorithm = mSubkeysAdapter.getAlgorithm(position); +// // these are the PGP constants for RSA_GENERAL, RSA_ENCRYPT and RSA_SIGN +// if (algorithm != 1 && algorithm != 2 && algorithm != 3) { +// Notify.create(activity, R.string.edit_key_error_bad_nfc_algo, Notify.Style.ERROR) +// .show((ViewGroup) activity.findViewById(R.id.import_snackbar)); +// break; +// } +// if (mSubkeysAdapter.getKeySize(position) != 2048) { +// Notify.create(activity, R.string.edit_key_error_bad_nfc_size, Notify.Style.ERROR) +// .show((ViewGroup) activity.findViewById(R.id.import_snackbar)); +// break; +// } +// +// +// SubkeyChange change; +// change = mSaveKeyringParcel.getSubkeyChange(keyId); +// if (change == null) { +// mSaveKeyringParcel.mChangeSubKeys.add( +// new SubkeyChange(keyId, false, true) +// ); +// break; +// } +// // toggle +// change.mMoveKeyToCard = !change.mMoveKeyToCard; +// if (change.mMoveKeyToCard && change.mDummyStrip) { +// // User had chosen to strip key, but now wants to divert it. +// change.mDummyStrip = false; +// } +// break; + } + } + getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad(); + } + }; + + // Create a new Messenger for the communication back + final Messenger messenger = new Messenger(returnHandler); + + DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { + public void run() { + EditSubkeyDialogFragment dialogFragment = + EditSubkeyDialogFragment.newInstance(messenger); + + dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyDialog"); + } + }); + } + + private void editSubkeyExpiry(final int position) { + final long keyId = mSubkeysAdapter.getKeyId(position); + final Long creationDate = mSubkeysAdapter.getCreationDate(position); + final Long expiryDate = mSubkeysAdapter.getExpiryDate(position); + + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + switch (message.what) { + case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY: + mEditModeSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = + (Long) message.getData().getSerializable( + EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY); + break; + } + getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad(); + } + }; + + // Create a new Messenger for the communication back + final Messenger messenger = new Messenger(returnHandler); + + DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { + public void run() { + EditSubkeyExpiryDialogFragment dialogFragment = + EditSubkeyExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate); + + dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyExpiryDialog"); + } + }); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index e98970754..c8e892276 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -101,8 +101,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements footer.setLayoutParams(params); mUserIdsAddedList.addFooterView(footer, null, false); - mUserIdAddFabLayout = (ViewAnimator) view.findViewById(R.id.view_key_user_id_fab_layout); - view.findViewById(R.id.view_key_user_id_fab).setOnClickListener(new View.OnClickListener() { + mUserIdAddFabLayout = (ViewAnimator) view.findViewById(R.id.view_key_subkey_fab_layout); + view.findViewById(R.id.view_key_subkey_fab).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { addUserId(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index 24f5f04a1..84608f2dc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -22,6 +22,7 @@ import android.content.res.ColorStateList; import android.database.Cursor; import android.graphics.PorterDuff; import android.graphics.Typeface; +import android.support.annotation.Nullable; import android.support.v4.widget.CursorAdapter; import android.text.Spannable; import android.text.SpannableString; @@ -49,7 +50,7 @@ public class SubkeysAdapter extends CursorAdapter { private LayoutInflater mInflater; private SaveKeyringParcel mSaveKeyringParcel; - private boolean hasAnySecret; + private boolean mHasAnySecret; private ColorStateList mDefaultTextColor; public static final String[] SUBKEYS_PROJECTION = new String[]{ @@ -85,16 +86,10 @@ public class SubkeysAdapter extends CursorAdapter { private static final int INDEX_EXPIRY = 13; private static final int INDEX_FINGERPRINT = 14; - public SubkeysAdapter(Context context, Cursor c, int flags, - SaveKeyringParcel saveKeyringParcel) { + public SubkeysAdapter(Context context, Cursor c, int flags) { super(context, c, flags); mInflater = LayoutInflater.from(context); - mSaveKeyringParcel = saveKeyringParcel; - } - - public SubkeysAdapter(Context context, Cursor c, int flags) { - this(context, c, flags, null); } public long getKeyId(int position) { @@ -133,12 +128,12 @@ public class SubkeysAdapter extends CursorAdapter { @Override public Cursor swapCursor(Cursor newCursor) { - hasAnySecret = false; + mHasAnySecret = false; if (newCursor != null && newCursor.moveToFirst()) { do { SecretKeyType hasSecret = SecretKeyType.fromNum(newCursor.getInt(INDEX_HAS_SECRET)); if (hasSecret.isUsable()) { - hasAnySecret = true; + mHasAnySecret = true; break; } } while (newCursor.moveToNext()); @@ -354,4 +349,18 @@ public class SubkeysAdapter extends CursorAdapter { } } + /** Set this adapter into edit mode. This mode displays additional info for + * each item from a supplied SaveKeyringParcel reference. + * + * Note that it is up to the caller to reload the underlying cursor after + * updating the SaveKeyringParcel! + * + * @see SaveKeyringParcel + * + * @param saveKeyringParcel The parcel to get info from, or null to leave edit mode. + */ + public void setEditMode(@Nullable SaveKeyringParcel saveKeyringParcel) { + mSaveKeyringParcel = saveKeyringParcel; + } + } -- cgit v1.2.3 From 69220cb4c0466112426e7d10f865da834b464d90 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 15 Nov 2015 20:19:24 +0100 Subject: inline subkey editing, fixed --- .../keychain/ui/ViewKeyAdvActivity.java | 1 + .../keychain/ui/ViewKeyAdvSubkeysFragment.java | 25 ++++++++++++++++------ .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 4 ++-- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java index 01dc10d28..86cabaf96 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -125,6 +125,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements Bundle keysBundle = new Bundle(); keysBundle.putParcelable(ViewKeyAdvSubkeysFragment.ARG_DATA_URI, dataUri); + keysBundle.putBoolean(ViewKeyAdvSubkeysFragment.ARG_HAS_SECRET, hasSecret); adapter.addTab(ViewKeyAdvSubkeysFragment.class, keysBundle, getString(R.string.key_view_tab_keys)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java index ce68bfab1..048dd4f77 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java @@ -47,7 +47,6 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter; -import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment; @@ -58,6 +57,8 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { public static final String ARG_DATA_URI = "data_uri"; + public static final String ARG_HAS_SECRET = "has_secret"; + public static final int LOADER_ID_SUBKEYS = 0; private ListView mSubkeysList; @@ -76,11 +77,12 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements /** * Creates new instance of this fragment */ - public static ViewKeyAdvSubkeysFragment newInstance(Uri dataUri) { + public static ViewKeyAdvSubkeysFragment newInstance(Uri dataUri, boolean hasSecret) { ViewKeyAdvSubkeysFragment frag = new ViewKeyAdvSubkeysFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_DATA_URI, dataUri); + args.putBoolean(ARG_HAS_SECRET, hasSecret); frag.setArguments(args); return frag; @@ -91,11 +93,9 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements View root = super.onCreateView(inflater, superContainer, savedInstanceState); View view = inflater.inflate(R.layout.view_key_adv_subkeys_fragment, getContainer()); - mSubkeysList = (ListView) view.findViewById(R.id.keys); - - mSubkeysList = (ListView) view.findViewById(R.id.view_key_user_ids); - mSubkeysAddedList = (ListView) view.findViewById(R.id.view_key_user_ids_added); - mSubkeysAddedLayout = view.findViewById(R.id.view_key_user_ids_add_layout); + mSubkeysList = (ListView) view.findViewById(R.id.view_key_subkeys); + mSubkeysAddedList = (ListView) view.findViewById(R.id.view_key_subkeys_added); + mSubkeysAddedLayout = view.findViewById(R.id.view_key_subkeys_add_layout); mSubkeysList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -136,6 +136,9 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements getActivity().finish(); return; } + mHasSecret = getArguments().getBoolean(ARG_HAS_SECRET); + + setHasOptionsMenu(true); loadData(dataUri); } @@ -226,6 +229,14 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements }); } + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.edit_subkeys, menu); + final MenuItem vEditSubkeys = menu.findItem(R.id.menu_edit_subkeys); + vEditSubkeys.setVisible(mHasSecret); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index c8e892276..49c0184c7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -218,6 +218,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements } boolean hasSecret = getArguments().getBoolean(ARG_HAS_SECRET); + setHasOptionsMenu(true); + loadData(dataUri, hasSecret); } @@ -230,8 +232,6 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0); mUserIds.setAdapter(mUserIdsAdapter); - setHasOptionsMenu(hasSecret); - // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); -- cgit v1.2.3 From aca0cd340bda38cc15547aa5a116c679782ff740 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 15 Nov 2015 23:24:20 +0100 Subject: inline-edit: move action mode menu handling int activity --- .../keychain/ui/ViewKeyAdvActivity.java | 118 ++++++++++++++++++--- .../keychain/ui/ViewKeyAdvSubkeysFragment.java | 43 ++++---- .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 36 +++---- 3 files changed, 135 insertions(+), 62 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java index 86cabaf96..fe4135cd8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -18,19 +18,26 @@ package org.sufficientlysecure.keychain.ui; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; -import android.support.v4.app.LoaderManager; +import android.support.v4.app.Fragment; +import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.view.ViewPager; -import android.support.v4.view.ViewPager.SimpleOnPageChangeListener; +import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.ActionMode; +import android.view.LayoutInflater; import android.view.Menu; +import android.view.MenuItem; import android.view.View; +import android.view.ViewPropertyAnimator; +import android.view.animation.OvershootInterpolator; import android.widget.Toast; import com.astuetz.PagerSlidingTabStrip; @@ -47,7 +54,7 @@ import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.Log; public class ViewKeyAdvActivity extends BaseActivity implements - LoaderManager.LoaderCallbacks { + LoaderCallbacks, OnPageChangeListener { ProviderHelper mProviderHelper; @@ -64,6 +71,11 @@ public class ViewKeyAdvActivity extends BaseActivity implements private PagerSlidingTabStrip mSlidingTabLayout; private static final int LOADER_ID_UNIFIED = 0; + private ActionMode mActionMode; + private boolean mHasSecret; + private PagerTabStripAdapter mTabAdapter; + private boolean mActionIconShown; + private boolean[] mTabsWithActionMode; @Override protected void onCreate(Bundle savedInstanceState) { @@ -109,33 +121,44 @@ public class ViewKeyAdvActivity extends BaseActivity implements } private void initTabs(Uri dataUri, boolean hasSecret) { - PagerTabStripAdapter adapter = new PagerTabStripAdapter(this); - mViewPager.setAdapter(adapter); + + mHasSecret = hasSecret; + + mTabAdapter = new PagerTabStripAdapter(this); + mViewPager.setAdapter(mTabAdapter); + + // keep track which of these are action mode enabled! + mTabsWithActionMode = new boolean[4]; Bundle shareBundle = new Bundle(); shareBundle.putParcelable(ViewKeyAdvShareFragment.ARG_DATA_URI, dataUri); - adapter.addTab(ViewKeyAdvShareFragment.class, + mTabAdapter.addTab(ViewKeyAdvShareFragment.class, shareBundle, getString(R.string.key_view_tab_share)); + mTabsWithActionMode[0] = false; Bundle userIdsBundle = new Bundle(); userIdsBundle.putParcelable(ViewKeyAdvUserIdsFragment.ARG_DATA_URI, dataUri); userIdsBundle.putBoolean(ViewKeyAdvUserIdsFragment.ARG_HAS_SECRET, hasSecret); - adapter.addTab(ViewKeyAdvUserIdsFragment.class, + mTabAdapter.addTab(ViewKeyAdvUserIdsFragment.class, userIdsBundle, getString(R.string.section_user_ids)); + mTabsWithActionMode[1] = true; Bundle keysBundle = new Bundle(); keysBundle.putParcelable(ViewKeyAdvSubkeysFragment.ARG_DATA_URI, dataUri); keysBundle.putBoolean(ViewKeyAdvSubkeysFragment.ARG_HAS_SECRET, hasSecret); - adapter.addTab(ViewKeyAdvSubkeysFragment.class, + mTabAdapter.addTab(ViewKeyAdvSubkeysFragment.class, keysBundle, getString(R.string.key_view_tab_keys)); + mTabsWithActionMode[2] = true; Bundle certsBundle = new Bundle(); certsBundle.putParcelable(ViewKeyAdvCertsFragment.ARG_DATA_URI, dataUri); - adapter.addTab(ViewKeyAdvCertsFragment.class, + mTabAdapter.addTab(ViewKeyAdvCertsFragment.class, certsBundle, getString(R.string.key_view_tab_certs)); + mTabsWithActionMode[3] = false; // update layout after operations mSlidingTabLayout.setViewPager(mViewPager); + mSlidingTabLayout.setOnPageChangeListener(this); // switch to tab selected by extra Intent intent = getIntent(); @@ -245,22 +268,83 @@ public class ViewKeyAdvActivity extends BaseActivity implements } @Override - public void onActionModeStarted(final ActionMode mode) { - super.onActionModeStarted(mode); - // Leave whatever action mode we are in when we change the page - mSlidingTabLayout.setOnPageChangeListener(new SimpleOnPageChangeListener() { + public boolean onCreateOptionsMenu(Menu menu) { + + if (!mHasSecret) { + return false; + } + + // always add the item, switch its visibility depending on fragment + getMenuInflater().inflate(R.menu.action_mode_edit, menu); + final MenuItem vActionModeItem = menu.findItem(R.id.menu_action_mode_edit); + + boolean isCurrentActionFragment = mTabsWithActionMode[mViewPager.getCurrentItem()]; + + // if the state is as it should be, never mind + if (isCurrentActionFragment == mActionIconShown) { + return isCurrentActionFragment; + } + + // show or hide accordingly + mActionIconShown = isCurrentActionFragment; + vActionModeItem.setEnabled(isCurrentActionFragment); + animateMenuItem(vActionModeItem, isCurrentActionFragment); + + return true; + } + + private void animateMenuItem(final MenuItem vEditSubkeys, final boolean animateShow) { + + View actionView = LayoutInflater.from(this).inflate(R.layout.edit_icon, null); + vEditSubkeys.setActionView(actionView); + actionView.setTranslationX(animateShow ? 150 : 0); + + ViewPropertyAnimator animator = actionView.animate(); + animator.translationX(animateShow ? 0 : 150); + animator.setDuration(300); + animator.setInterpolator(new OvershootInterpolator(1.5f)); + animator.setListener(new AnimatorListenerAdapter() { @Override - public void onPageSelected(int position) { - super.onPageSelected(position); - mode.finish(); + public void onAnimationEnd(Animator animation) { + if (!animateShow) { + vEditSubkeys.setVisible(false); + } + vEditSubkeys.setActionView(null); } }); + animator.start(); + + } + + @Override + public void onActionModeStarted(final ActionMode mode) { + super.onActionModeStarted(mode); + mActionMode = mode; } @Override public void onActionModeFinished(ActionMode mode) { super.onActionModeFinished(mode); - mSlidingTabLayout.setOnPageChangeListener(null); + mActionMode = null; + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if (mActionMode != null) { + mActionMode.finish(); + mActionMode = null; + } + invalidateOptionsMenu(); + } + + @Override + public void onPageScrollStateChanged(int state) { + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java index 048dd4f77..b93eccb92 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java @@ -17,6 +17,7 @@ package org.sufficientlysecure.keychain.ui; + import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -28,7 +29,6 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.view.ActionMode; -import android.view.ActionMode.Callback; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -123,6 +123,8 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements } }); + setHasOptionsMenu(true); + return root; } @@ -138,8 +140,6 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements } mHasSecret = getArguments().getBoolean(ARG_HAS_SECRET); - setHasOptionsMenu(true); - loadData(dataUri); } @@ -184,9 +184,23 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements mSubkeysAdapter.swapCursor(null); } - private void enterEditMode() { + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_action_mode_edit: + enterEditMode(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public void enterEditMode() { FragmentActivity activity = getActivity(); - activity.startActionMode(new Callback() { + if (activity == null) { + return; + } + activity.startActionMode(new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { @@ -229,25 +243,6 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements }); } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.edit_subkeys, menu); - final MenuItem vEditSubkeys = menu.findItem(R.id.menu_edit_subkeys); - vEditSubkeys.setVisible(mHasSecret); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_edit_subkeys: - enterEditMode(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - private void addSubkey() { boolean willBeMasterKey; if (mSubkeysAdapter != null) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index 49c0184c7..1e38a823a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -30,10 +30,8 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.view.ActionMode; -import android.view.ActionMode.Callback; import android.view.LayoutInflater; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -109,6 +107,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements } }); + setHasOptionsMenu(true); + return root; } @@ -218,8 +218,6 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements } boolean hasSecret = getArguments().getBoolean(ARG_HAS_SECRET); - setHasOptionsMenu(true); - loadData(dataUri, hasSecret); } @@ -278,16 +276,22 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.edit_user_id, menu); - MenuItem vEditUserIds = menu.findItem(R.id.menu_edit_user_ids); - vEditUserIds.setVisible(mHasSecret); + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_action_mode_edit: + enterEditMode(); + return true; + default: + return super.onOptionsItemSelected(item); + } } - private void enterEditMode() { + public void enterEditMode() { FragmentActivity activity = getActivity(); - activity.startActionMode(new Callback() { + if (activity == null) { + return; + } + activity.startActionMode(new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { @@ -330,14 +334,4 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements }); } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_edit_user_ids: - enterEditMode(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } } -- cgit v1.2.3 From 1dea4ef19f594f3562e31f104abc77958f6edb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 27 Dec 2015 15:45:08 +0100 Subject: Pass trough masterKeyId and fingerprint to advanced key edit fragments --- .../keychain/ui/ViewKeyAdvActivity.java | 14 +++++++++++--- .../keychain/ui/ViewKeyAdvSubkeysFragment.java | 22 +++++++--------------- .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 16 +++++++++++----- 3 files changed, 29 insertions(+), 23 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java index fe4135cd8..c2f63fa4e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -120,7 +120,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements setContentView(R.layout.view_key_adv_activity); } - private void initTabs(Uri dataUri, boolean hasSecret) { + private void initTabs(Uri dataUri, boolean hasSecret, long masterKeyId, byte[] fingerprint) { mHasSecret = hasSecret; @@ -139,6 +139,8 @@ public class ViewKeyAdvActivity extends BaseActivity implements Bundle userIdsBundle = new Bundle(); userIdsBundle.putParcelable(ViewKeyAdvUserIdsFragment.ARG_DATA_URI, dataUri); userIdsBundle.putBoolean(ViewKeyAdvUserIdsFragment.ARG_HAS_SECRET, hasSecret); + userIdsBundle.putLong(ViewKeyAdvUserIdsFragment.ARG_MASTER_KEY_ID, masterKeyId); + userIdsBundle.putByteArray(ViewKeyAdvUserIdsFragment.ARG_FINGERPRINT, fingerprint); mTabAdapter.addTab(ViewKeyAdvUserIdsFragment.class, userIdsBundle, getString(R.string.section_user_ids)); mTabsWithActionMode[1] = true; @@ -146,6 +148,8 @@ public class ViewKeyAdvActivity extends BaseActivity implements Bundle keysBundle = new Bundle(); keysBundle.putParcelable(ViewKeyAdvSubkeysFragment.ARG_DATA_URI, dataUri); keysBundle.putBoolean(ViewKeyAdvSubkeysFragment.ARG_HAS_SECRET, hasSecret); + keysBundle.putLong(ViewKeyAdvSubkeysFragment.ARG_MASTER_KEY_ID, masterKeyId); + keysBundle.putByteArray(ViewKeyAdvSubkeysFragment.ARG_FINGERPRINT, fingerprint); mTabAdapter.addTab(ViewKeyAdvSubkeysFragment.class, keysBundle, getString(R.string.key_view_tab_keys)); mTabsWithActionMode[2] = true; @@ -175,7 +179,8 @@ public class ViewKeyAdvActivity extends BaseActivity implements KeychainContract.KeyRings.IS_REVOKED, KeychainContract.KeyRings.IS_EXPIRED, KeychainContract.KeyRings.VERIFIED, - KeychainContract.KeyRings.HAS_ANY_SECRET + KeychainContract.KeyRings.HAS_ANY_SECRET, + KeychainContract.KeyRings.FINGERPRINT, }; static final int INDEX_MASTER_KEY_ID = 1; @@ -184,6 +189,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements static final int INDEX_IS_EXPIRED = 4; static final int INDEX_VERIFIED = 5; static final int INDEX_HAS_ANY_SECRET = 6; + static final int INDEX_FINGERPRINT = 7; @Override public Loader onCreateLoader(int id, Bundle args) { @@ -217,6 +223,8 @@ public class ViewKeyAdvActivity extends BaseActivity implements setTitle(R.string.user_id_no_name); } + byte[] fingerprint = data.getBlob(INDEX_FINGERPRINT); + // get key id from MASTER_KEY_ID long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID); getSupportActionBar().setSubtitle(KeyFormattingUtils.beautifyKeyIdWithPrefix(this, masterKeyId)); @@ -243,7 +251,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements mStatusBar.setBackgroundColor(ViewKeyActivity.getStatusBarBackgroundColor(color)); mSlidingTabLayout.setBackgroundColor(color); - initTabs(mDataUri, isSecret); + initTabs(mDataUri, isSecret, masterKeyId, fingerprint); break; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java index b93eccb92..923a1e61c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java @@ -58,6 +58,8 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements public static final String ARG_DATA_URI = "data_uri"; public static final String ARG_HAS_SECRET = "has_secret"; + public static final String ARG_MASTER_KEY_ID = "master_key_id"; + public static final String ARG_FINGERPRINT = "fingerprint"; public static final int LOADER_ID_SUBKEYS = 0; @@ -71,23 +73,11 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements private Uri mDataUriSubkeys; + private long mMasterKeyId; + private byte[] mFingerprint; private boolean mHasSecret; private SaveKeyringParcel mEditModeSaveKeyringParcel; - /** - * Creates new instance of this fragment - */ - public static ViewKeyAdvSubkeysFragment newInstance(Uri dataUri, boolean hasSecret) { - ViewKeyAdvSubkeysFragment frag = new ViewKeyAdvSubkeysFragment(); - - Bundle args = new Bundle(); - args.putParcelable(ARG_DATA_URI, dataUri); - args.putBoolean(ARG_HAS_SECRET, hasSecret); - - frag.setArguments(args); - return frag; - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { View root = super.onCreateView(inflater, superContainer, savedInstanceState); @@ -139,6 +129,8 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements return; } mHasSecret = getArguments().getBoolean(ARG_HAS_SECRET); + mMasterKeyId = getArguments().getLong(ARG_MASTER_KEY_ID); + mFingerprint = getArguments().getByteArray(ARG_FINGERPRINT); loadData(dataUri); } @@ -204,7 +196,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { - mEditModeSaveKeyringParcel = new SaveKeyringParcel(0L, new byte[0]); + mEditModeSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint); mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddSubKeys, false); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index 1e38a823a..a44d4da5e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -57,6 +57,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements public static final String ARG_DATA_URI = "uri"; public static final String ARG_HAS_SECRET = "has_secret"; + public static final String ARG_MASTER_KEY_ID = "master_key_id"; + public static final String ARG_FINGERPRINT = "fingerprint"; private static final int LOADER_ID_USER_IDS = 0; @@ -69,6 +71,9 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements private UserIdsAddedAdapter mUserIdsAddedAdapter; private Uri mDataUri; + + private long mMasterKeyId; + private byte[] mFingerprint; private boolean mHasSecret; private SaveKeyringParcel mEditModeSaveKeyringParcel; @@ -216,14 +221,15 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements getActivity().finish(); return; } - boolean hasSecret = getArguments().getBoolean(ARG_HAS_SECRET); + mHasSecret = getArguments().getBoolean(ARG_HAS_SECRET); + mMasterKeyId = getArguments().getLong(ARG_MASTER_KEY_ID); + mFingerprint = getArguments().getByteArray(ARG_FINGERPRINT); - loadData(dataUri, hasSecret); + loadData(dataUri); } - private void loadData(Uri dataUri, boolean hasSecret) { + private void loadData(Uri dataUri) { mDataUri = dataUri; - mHasSecret = hasSecret; Log.i(Constants.TAG, "mDataUri: " + mDataUri); @@ -295,7 +301,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { - mEditModeSaveKeyringParcel = new SaveKeyringParcel(0L, new byte[0]); + mEditModeSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint); mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddUserIds, false); -- cgit v1.2.3 From 9887e8b42ad2e6fddb1f3be4c0c315724c4d5c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 28 Dec 2015 15:38:16 +0100 Subject: Advanced screen: edited key saved --- .../keychain/ui/ViewKeyAdvSubkeysFragment.java | 51 +++++++++++++++++++++- .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 50 ++++++++++++++++++++- 2 files changed, 99 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java index 923a1e61c..5a0b1b393 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ui; +import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -41,12 +42,14 @@ import android.widget.ViewAnimator; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.operations.results.EditKeyResult; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment; @@ -71,6 +74,8 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements private SubkeysAdapter mSubkeysAdapter; private SubkeysAddedAdapter mSubkeysAddedAdapter; + private CryptoOperationHelper mEditKeyHelper; + private Uri mDataUriSubkeys; private long mMasterKeyId; @@ -135,6 +140,15 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements loadData(dataUri); } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (mEditKeyHelper != null) { + mEditKeyHelper.handleActivityResult(requestCode, resultCode, data); + } + + super.onActivityResult(requestCode, resultCode, data); + } + private void loadData(Uri dataUri) { mDataUriSubkeys = KeychainContract.Keys.buildKeysUri(dataUri); @@ -220,7 +234,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - mode.finish(); + editKey(mode); return true; } @@ -390,4 +404,39 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements }); } + + private void editKey(final ActionMode mode) { + CryptoOperationHelper.Callback editKeyCallback + = new CryptoOperationHelper.Callback() { + + @Override + public SaveKeyringParcel createOperationInput() { + return mEditModeSaveKeyringParcel; + } + + @Override + public void onCryptoOperationSuccess(EditKeyResult result) { + mode.finish(); + result.createNotify(getActivity()).show(); + } + + @Override + public void onCryptoOperationCancelled() { + + } + + @Override + public void onCryptoOperationError(EditKeyResult result) { + + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + mEditKeyHelper = new CryptoOperationHelper<>(1, this, editKeyCallback, R.string.progress_saving); + mEditKeyHelper.cryptoOperation(); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index a44d4da5e..176eb6ca0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui; +import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -42,10 +43,12 @@ import android.widget.ViewAnimator; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.operations.results.EditKeyResult; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; @@ -70,6 +73,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements private UserIdsAdapter mUserIdsAdapter; private UserIdsAddedAdapter mUserIdsAddedAdapter; + private CryptoOperationHelper mEditKeyHelper; + private Uri mDataUri; private long mMasterKeyId; @@ -228,6 +233,15 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements loadData(dataUri); } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (mEditKeyHelper != null) { + mEditKeyHelper.handleActivityResult(requestCode, resultCode, data); + } + + super.onActivityResult(requestCode, resultCode, data); + } + private void loadData(Uri dataUri) { mDataUri = dataUri; @@ -325,7 +339,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - mode.finish(); + editKey(mode); return true; } @@ -340,4 +354,38 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements }); } + private void editKey(final ActionMode mode) { + CryptoOperationHelper.Callback editKeyCallback + = new CryptoOperationHelper.Callback() { + + @Override + public SaveKeyringParcel createOperationInput() { + return mEditModeSaveKeyringParcel; + } + + @Override + public void onCryptoOperationSuccess(EditKeyResult result) { + mode.finish(); + result.createNotify(getActivity()).show(); + } + + @Override + public void onCryptoOperationCancelled() { + + } + + @Override + public void onCryptoOperationError(EditKeyResult result) { + + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + mEditKeyHelper = new CryptoOperationHelper<>(1, this, editKeyCallback, R.string.progress_saving); + mEditKeyHelper.cryptoOperation(); + } + } -- cgit v1.2.3 From ea3b25846946e96e124cd5635e710f8ece77eceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 28 Dec 2015 15:41:36 +0100 Subject: use correct white add icon --- .../org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index 176eb6ca0..3e165a77e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -85,7 +85,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements @Override public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { View root = super.onCreateView(inflater, superContainer, savedInstanceState); - View view = inflater.inflate(R.layout.view_key_adv_main_fragment, getContainer()); + View view = inflater.inflate(R.layout.view_key_adv_user_ids_fragment, getContainer()); mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); mUserIdsAddedList = (ListView) view.findViewById(R.id.view_key_user_ids_added); -- cgit v1.2.3 From 621f8c2c70183bdb44c4adb6f6a507a192af58a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 29 Dec 2015 19:57:01 +0100 Subject: Load key data in tabs independently from advanced activity. This decouples the fragments from the activity and allows to init the tabs before loading key data in the advanced activity. Fixes switching to the first tab when key has been edited. --- .../keychain/ui/ViewKeyAdvActivity.java | 22 ++---- .../keychain/ui/ViewKeyAdvSubkeysFragment.java | 78 +++++++++++++++------ .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 80 +++++++++++++++------- 3 files changed, 118 insertions(+), 62 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java index c2f63fa4e..b10e5f8d4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -25,7 +25,6 @@ import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; -import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; @@ -41,6 +40,7 @@ import android.view.animation.OvershootInterpolator; import android.widget.Toast; import com.astuetz.PagerSlidingTabStrip; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.OperationResult; @@ -113,6 +113,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements // or start new ones. getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); + initTabs(mDataUri); } @Override @@ -120,10 +121,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements setContentView(R.layout.view_key_adv_activity); } - private void initTabs(Uri dataUri, boolean hasSecret, long masterKeyId, byte[] fingerprint) { - - mHasSecret = hasSecret; - + private void initTabs(Uri dataUri) { mTabAdapter = new PagerTabStripAdapter(this); mViewPager.setAdapter(mTabAdapter); @@ -138,18 +136,12 @@ public class ViewKeyAdvActivity extends BaseActivity implements Bundle userIdsBundle = new Bundle(); userIdsBundle.putParcelable(ViewKeyAdvUserIdsFragment.ARG_DATA_URI, dataUri); - userIdsBundle.putBoolean(ViewKeyAdvUserIdsFragment.ARG_HAS_SECRET, hasSecret); - userIdsBundle.putLong(ViewKeyAdvUserIdsFragment.ARG_MASTER_KEY_ID, masterKeyId); - userIdsBundle.putByteArray(ViewKeyAdvUserIdsFragment.ARG_FINGERPRINT, fingerprint); mTabAdapter.addTab(ViewKeyAdvUserIdsFragment.class, userIdsBundle, getString(R.string.section_user_ids)); mTabsWithActionMode[1] = true; Bundle keysBundle = new Bundle(); keysBundle.putParcelable(ViewKeyAdvSubkeysFragment.ARG_DATA_URI, dataUri); - keysBundle.putBoolean(ViewKeyAdvSubkeysFragment.ARG_HAS_SECRET, hasSecret); - keysBundle.putLong(ViewKeyAdvSubkeysFragment.ARG_MASTER_KEY_ID, masterKeyId); - keysBundle.putByteArray(ViewKeyAdvSubkeysFragment.ARG_FINGERPRINT, fingerprint); mTabAdapter.addTab(ViewKeyAdvSubkeysFragment.class, keysBundle, getString(R.string.key_view_tab_keys)); mTabsWithActionMode[2] = true; @@ -229,7 +221,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID); getSupportActionBar().setSubtitle(KeyFormattingUtils.beautifyKeyIdWithPrefix(this, masterKeyId)); - boolean isSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; + mHasSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0; boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0; boolean isVerified = data.getInt(INDEX_VERIFIED) > 0; @@ -238,7 +230,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements int color; if (isRevoked || isExpired) { color = getResources().getColor(R.color.key_flag_red); - } else if (isSecret) { + } else if (mHasSecret) { color = getResources().getColor(R.color.android_green_light); } else { if (isVerified) { @@ -251,8 +243,6 @@ public class ViewKeyAdvActivity extends BaseActivity implements mStatusBar.setBackgroundColor(ViewKeyActivity.getStatusBarBackgroundColor(color)); mSlidingTabLayout.setBackgroundColor(color); - initTabs(mDataUri, isSecret, masterKeyId, fingerprint); - break; } } @@ -284,7 +274,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements // always add the item, switch its visibility depending on fragment getMenuInflater().inflate(R.menu.action_mode_edit, menu); - final MenuItem vActionModeItem = menu.findItem(R.id.menu_action_mode_edit); + final MenuItem vActionModeItem = menu.findItem(R.id.menu_action_mode_edit); boolean isCurrentActionFragment = mTabsWithActionMode[mViewPager.getCurrentItem()]; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java index 5a0b1b393..4308983ce 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java @@ -60,11 +60,9 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { public static final String ARG_DATA_URI = "data_uri"; - public static final String ARG_HAS_SECRET = "has_secret"; - public static final String ARG_MASTER_KEY_ID = "master_key_id"; - public static final String ARG_FINGERPRINT = "fingerprint"; - public static final int LOADER_ID_SUBKEYS = 0; + private static final int LOADER_ID_UNIFIED = 0; + private static final int LOADER_ID_SUBKEYS = 1; private ListView mSubkeysList; private ListView mSubkeysAddedList; @@ -76,7 +74,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements private CryptoOperationHelper mEditKeyHelper; - private Uri mDataUriSubkeys; + private Uri mDataUri; private long mMasterKeyId; private byte[] mFingerprint; @@ -133,9 +131,6 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements getActivity().finish(); return; } - mHasSecret = getArguments().getBoolean(ARG_HAS_SECRET); - mMasterKeyId = getArguments().getLong(ARG_MASTER_KEY_ID); - mFingerprint = getArguments().getByteArray(ARG_FINGERPRINT); loadData(dataUri); } @@ -150,7 +145,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements } private void loadData(Uri dataUri) { - mDataUriSubkeys = KeychainContract.Keys.buildKeysUri(dataUri); + mDataUri = dataUri; // Create an empty adapter we will use to display the loaded data. mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0); @@ -158,14 +153,42 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. + getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, this); } + // These are the rows that we will retrieve. + static final String[] PROJECTION = new String[]{ + KeychainContract.KeyRings._ID, + KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.HAS_ANY_SECRET, + KeychainContract.KeyRings.FINGERPRINT, + }; + + static final int INDEX_MASTER_KEY_ID = 1; + static final int INDEX_HAS_ANY_SECRET = 2; + static final int INDEX_FINGERPRINT = 3; + + @Override public Loader onCreateLoader(int id, Bundle args) { - setContentShown(false); + switch (id) { + case LOADER_ID_UNIFIED: { + Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri); + return new CursorLoader(getActivity(), baseUri, + PROJECTION, null, null, null); + } + + case LOADER_ID_SUBKEYS: { + setContentShown(false); - return new CursorLoader(getActivity(), mDataUriSubkeys, - SubkeysAdapter.SUBKEYS_PROJECTION, null, null, null); + Uri subkeysUri = KeychainContract.Keys.buildKeysUri(mDataUri); + return new CursorLoader(getActivity(), subkeysUri, + SubkeysAdapter.SUBKEYS_PROJECTION, null, null, null); + } + + default: + return null; + } } public void onLoadFinished(Loader loader, Cursor data) { @@ -174,12 +197,26 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements return; } - // Swap the new cursor in. (The framework will take care of closing the - // old cursor once we return.) - mSubkeysAdapter.swapCursor(data); + switch (loader.getId()) { + case LOADER_ID_UNIFIED: { + data.moveToFirst(); + + mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID); + mHasSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; + mFingerprint = data.getBlob(INDEX_FINGERPRINT); + break; + } + case LOADER_ID_SUBKEYS: { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mSubkeysAdapter.swapCursor(data); + + // TODO: maybe show not before both are loaded! + setContentShown(true); + break; + } + } - // TODO: maybe show not before both are loaded! - setContentShown(true); } /** @@ -244,7 +281,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements mSubkeysAdapter.setEditMode(null); mSubkeysAddedLayout.setVisibility(View.GONE); mSubkeyAddFabLayout.setDisplayedChild(0); - getLoaderManager().restartLoader(0, null, ViewKeyAdvSubkeysFragment.this); + getLoaderManager().restartLoader(LOADER_ID_SUBKEYS, null, ViewKeyAdvSubkeysFragment.this); } }); } @@ -422,12 +459,13 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements @Override public void onCryptoOperationCancelled() { - + mode.finish(); } @Override public void onCryptoOperationError(EditKeyResult result) { - + mode.finish(); + result.createNotify(getActivity()).show(); } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index 3e165a77e..ae1dd51d0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -44,6 +44,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.operations.results.EditKeyResult; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; @@ -59,11 +60,9 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { public static final String ARG_DATA_URI = "uri"; - public static final String ARG_HAS_SECRET = "has_secret"; - public static final String ARG_MASTER_KEY_ID = "master_key_id"; - public static final String ARG_FINGERPRINT = "fingerprint"; - private static final int LOADER_ID_USER_IDS = 0; + private static final int LOADER_ID_UNIFIED = 0; + private static final int LOADER_ID_USER_IDS = 1; private ListView mUserIds; private ListView mUserIdsAddedList; @@ -226,9 +225,6 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements getActivity().finish(); return; } - mHasSecret = getArguments().getBoolean(ARG_HAS_SECRET); - mMasterKeyId = getArguments().getLong(ARG_MASTER_KEY_ID); - mFingerprint = getArguments().getByteArray(ARG_FINGERPRINT); loadData(dataUri); } @@ -252,36 +248,67 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. + getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); } + // These are the rows that we will retrieve. + static final String[] PROJECTION = new String[]{ + KeychainContract.KeyRings._ID, + KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.HAS_ANY_SECRET, + KeychainContract.KeyRings.FINGERPRINT, + }; + + static final int INDEX_MASTER_KEY_ID = 1; + static final int INDEX_HAS_ANY_SECRET = 2; + static final int INDEX_FINGERPRINT = 3; + public Loader onCreateLoader(int id, Bundle args) { - setContentShown(false); + switch (id) { + case LOADER_ID_UNIFIED: { + Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri); + return new CursorLoader(getActivity(), baseUri, + PROJECTION, null, null, null); + } - if (id != LOADER_ID_USER_IDS) { - return null; - } + case LOADER_ID_USER_IDS: { + setContentShown(false); - Uri baseUri = UserPackets.buildUserIdsUri(mDataUri); - return new CursorLoader(getActivity(), baseUri, - UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null); - } + Uri userIdUri = UserPackets.buildUserIdsUri(mDataUri); + return new CursorLoader(getActivity(), userIdUri, + UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null); + } - public void onLoadFinished(Loader loader, Cursor data) { - if (loader.getId() != LOADER_ID_USER_IDS) { - return; + default: + return null; } + } - /* TODO better error handling? May cause problems when a key is deleted, - * because the notification triggers faster than the activity closes. - */ - // Avoid NullPointerExceptions... + public void onLoadFinished(Loader loader, Cursor data) { + // Avoid NullPointerExceptions, if we get an empty result set. if (data.getCount() == 0) { return; } - mUserIdsAdapter.swapCursor(data); - setContentShown(true); + switch (loader.getId()) { + case LOADER_ID_UNIFIED: { + data.moveToFirst(); + + mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID); + mHasSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; + mFingerprint = data.getBlob(INDEX_FINGERPRINT); + break; + } + case LOADER_ID_USER_IDS: { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mUserIdsAdapter.swapCursor(data); + + setContentShown(true); + break; + } + } } /** @@ -371,12 +398,13 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements @Override public void onCryptoOperationCancelled() { - + mode.finish(); } @Override public void onCryptoOperationError(EditKeyResult result) { - + mode.finish(); + result.createNotify(getActivity()).show(); } @Override -- cgit v1.2.3 From 3f705117080def34b7793f6935e6ec7b6109d741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 29 Dec 2015 21:21:11 +0100 Subject: Add edit action to user id card, left align card actions per material design guidelines --- .../org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 7 +++---- .../keychain/ui/ViewKeyAdvSubkeysFragment.java | 2 +- .../org/sufficientlysecure/keychain/ui/ViewKeyFragment.java | 11 ++++++++++- .../keychain/ui/util/ContentDescriptionHint.java | 9 ++++----- 4 files changed, 18 insertions(+), 11 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 35e00ff21..1eb16b3c3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -391,11 +391,11 @@ public class ViewKeyActivity extends BaseNfcActivity implements return true; } case R.id.menu_key_view_certify_fingerprint: { - certifyFingeprint(mDataUri, false); + certifyFingerprint(mDataUri, false); return true; } case R.id.menu_key_view_certify_fingerprint_word: { - certifyFingeprint(mDataUri, true); + certifyFingerprint(mDataUri, true); return true; } } @@ -423,14 +423,13 @@ public class ViewKeyActivity extends BaseNfcActivity implements return true; } - private void scanQrCode() { Intent scanQrCode = new Intent(this, ImportKeysProxyActivity.class); scanQrCode.setAction(ImportKeysProxyActivity.ACTION_SCAN_WITH_RESULT); startActivityForResult(scanQrCode, REQUEST_QR_FINGERPRINT); } - private void certifyFingeprint(Uri dataUri, boolean enableWordConfirm) { + private void certifyFingerprint(Uri dataUri, boolean enableWordConfirm) { Intent intent = new Intent(this, CertifyFingerprintActivity.class); intent.setData(dataUri); intent.putExtra(CertifyFingerprintActivity.EXTRA_ENABLE_WORD_CONFIRM, enableWordConfirm); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java index 4308983ce..14477723e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java @@ -200,7 +200,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements switch (loader.getId()) { case LOADER_ID_UNIFIED: { data.moveToFirst(); - + mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID); mHasSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; mFingerprint = data.getBlob(INDEX_FINGERPRINT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java index f75012731..b8edb9b1c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -162,7 +162,7 @@ public class ViewKeyFragment extends LoaderFragment implements try { frag = mLinkedIdsAdapter.getLinkedIdFragment(mDataUri, position, mFingerprint); } catch (IOException e) { - e.printStackTrace(); + Log.e(Constants.TAG, "IOException", e); return; } @@ -429,8 +429,17 @@ public class ViewKeyFragment extends LoaderFragment implements } case LOADER_ID_USER_IDS: { + LinearLayout editButtonsLayout = + (LinearLayout) getActivity().findViewById(R.id.view_key_card_user_ids_buttons); + if (mIsSecret) { + editButtonsLayout.setVisibility(View.VISIBLE); + } else { + editButtonsLayout.setVisibility(View.GONE); + } + setContentShown(true, false); mUserIdsAdapter.swapCursor(data); + break; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ContentDescriptionHint.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ContentDescriptionHint.java index 8e45a20e9..758e63eb1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ContentDescriptionHint.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ContentDescriptionHint.java @@ -1,8 +1,3 @@ -package org.sufficientlysecure.keychain.ui.util; - -/** - * Created by rohan on 20/9/15. - */ /* * Copyright 2012 Google Inc. * @@ -19,14 +14,18 @@ package org.sufficientlysecure.keychain.ui.util; * limitations under the License. */ +package org.sufficientlysecure.keychain.ui.util; + import android.content.Context; import android.graphics.Rect; import android.text.TextUtils; import android.view.Gravity; import android.view.View; import android.widget.Toast; + public class ContentDescriptionHint { private static final int ESTIMATED_TOAST_HEIGHT_DIPS = 48; + public static void setup(View view) { view.setOnLongClickListener(new View.OnLongClickListener() { @Override -- cgit v1.2.3 From 269330f04f6b4a438a2e3ae3f5e714be50443fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 30 Dec 2015 16:47:42 +0100 Subject: Add activity to edit user ids only --- .../keychain/ui/EditIdentitiesActivity.java | 70 ++++ .../keychain/ui/EditIdentitiesFragment.java | 359 +++++++++++++++++++++ .../keychain/ui/ViewKeyActivity.java | 13 - .../keychain/ui/ViewKeyFragment.java | 27 +- 4 files changed, 449 insertions(+), 20 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesActivity.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesActivity.java new file mode 100644 index 000000000..6f65e9cef --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesActivity.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2014-2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.net.Uri; +import android.os.Bundle; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.base.BaseActivity; +import org.sufficientlysecure.keychain.util.Log; + +public class EditIdentitiesActivity extends BaseActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Uri dataUri = getIntent().getData(); + if (dataUri == null) { + Log.e(Constants.TAG, "Either a key Uri or EXTRA_SAVE_KEYRING_PARCEL is required!"); + finish(); + return; + } + + loadFragment(savedInstanceState, dataUri); + } + + @Override + protected void initLayout() { + setContentView(R.layout.edit_identities_activity); + } + + private void loadFragment(Bundle savedInstanceState, Uri dataUri) { + // However, if we're being restored from a previous state, + // then we don't need to do anything and should return or else + // we could end up with overlapping fragments. + if (savedInstanceState != null) { + return; + } + + // Create an instance of the fragment + EditIdentitiesFragment mEditIdentitiesFragment; + mEditIdentitiesFragment = EditIdentitiesFragment.newInstance(dataUri); + + // Add the fragment to the 'fragment_container' FrameLayout + // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! + getSupportFragmentManager().beginTransaction() + .replace(R.id.edit_key_fragment_container, mEditIdentitiesFragment) + .commitAllowingStateLoss(); + // do it immediately! + getSupportFragmentManager().executePendingTransactions(); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java new file mode 100644 index 000000000..ebc0c9158 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2014-2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ListView; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; +import org.sufficientlysecure.keychain.operations.results.SingletonResult; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; +import org.sufficientlysecure.keychain.ui.base.QueueingCryptoOperationFragment; +import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; +import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.Date; + +public class EditIdentitiesFragment extends QueueingCryptoOperationFragment + implements LoaderManager.LoaderCallbacks { + + public static final String ARG_DATA_URI = "uri"; + + private ListView mUserIdsList; + private ListView mUserIdsAddedList; + private View mAddUserId; + + private static final int LOADER_ID_USER_IDS = 0; + + private UserIdsAdapter mUserIdsAdapter; + private UserIdsAddedAdapter mUserIdsAddedAdapter; + + private Uri mDataUri; + + private SaveKeyringParcel mSaveKeyringParcel; + + private String mPrimaryUserId; + + /** + * Creates new instance of this fragment + */ + public static EditIdentitiesFragment newInstance(Uri dataUri) { + EditIdentitiesFragment frag = new EditIdentitiesFragment(); + + Bundle args = new Bundle(); + args.putParcelable(ARG_DATA_URI, dataUri); + + frag.setArguments(args); + + return frag; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.edit_identities_fragment, null); + + mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids); + mUserIdsAddedList = (ListView) view.findViewById(R.id.edit_key_user_ids_added); + mAddUserId = view.findViewById(R.id.edit_key_action_add_user_id); + + return view; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + ((EditIdentitiesActivity) getActivity()).setFullScreenDialogDoneClose( + R.string.btn_save, + new OnClickListener() { + @Override + public void onClick(View v) { + // if we are working on an Uri, save directly + if (mDataUri == null) { + returnKeyringParcel(); + } else { + cryptoOperation(new CryptoInputParcel(new Date())); + } + } + }, new OnClickListener() { + @Override + public void onClick(View v) { + getActivity().setResult(Activity.RESULT_CANCELED); + getActivity().finish(); + } + }); + + Uri dataUri = getArguments().getParcelable(ARG_DATA_URI); + if (dataUri == null) { + Log.e(Constants.TAG, "Either a key Uri is required!"); + getActivity().finish(); + return; + } + + initView(); + loadData(dataUri); + } + + private void loadData(Uri dataUri) { + mDataUri = dataUri; + + Log.i(Constants.TAG, "mDataUri: " + mDataUri); + + // load the secret key ring. we do verify here that the passphrase is correct, so cached won't do + try { + Uri secretUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri); + CachedPublicKeyRing keyRing = + new ProviderHelper(getActivity()).getCachedPublicKeyRing(secretUri); + long masterKeyId = keyRing.getMasterKeyId(); + + // check if this is a master secret key we can work with + switch (keyRing.getSecretKeyType(masterKeyId)) { + case GNU_DUMMY: + finishWithError(LogType.MSG_EK_ERROR_DUMMY); + return; + } + + mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint()); + mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback(); + + } catch (PgpKeyNotFoundException | NotFoundException e) { + finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND); + return; + } + + // Prepare the loaders. Either re-connect with an existing ones, + // or start new ones. + getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditIdentitiesFragment.this); + + mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0); + mUserIdsAdapter.setEditMode(mSaveKeyringParcel); + mUserIdsList.setAdapter(mUserIdsAdapter); + + // TODO: SaveParcel from savedInstance?! + mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, false); + mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); + } + + private void initView() { + mAddUserId.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + addUserId(); + } + }); + + mUserIdsList.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + editUserId(position); + } + }); + } + + public Loader onCreateLoader(int id, Bundle args) { + + switch (id) { + case LOADER_ID_USER_IDS: { + Uri baseUri = UserPackets.buildUserIdsUri(mDataUri); + return new CursorLoader(getActivity(), baseUri, + UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null); + } + + default: + return null; + } + } + + public void onLoadFinished(Loader loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + switch (loader.getId()) { + case LOADER_ID_USER_IDS: { + mUserIdsAdapter.swapCursor(data); + break; + } + } + } + + /** + * This is called when the last Cursor provided to onLoadFinished() above is about to be closed. + * We need to make sure we are no longer using it. + */ + public void onLoaderReset(Loader loader) { + switch (loader.getId()) { + case LOADER_ID_USER_IDS: { + mUserIdsAdapter.swapCursor(null); + break; + } + } + } + + private void editUserId(final int position) { + final String userId = mUserIdsAdapter.getUserId(position); + final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); + final boolean isRevokedPending = mUserIdsAdapter.getIsRevokedPending(position); + + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + switch (message.what) { + case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID: + // toggle + if (mSaveKeyringParcel.mChangePrimaryUserId != null + && mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { + mSaveKeyringParcel.mChangePrimaryUserId = null; + } else { + mSaveKeyringParcel.mChangePrimaryUserId = userId; + } + break; + case EditUserIdDialogFragment.MESSAGE_REVOKE: + // toggle + if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) { + mSaveKeyringParcel.mRevokeUserIds.remove(userId); + } else { + mSaveKeyringParcel.mRevokeUserIds.add(userId); + // not possible to revoke and change to primary user id + if (mSaveKeyringParcel.mChangePrimaryUserId != null + && mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { + mSaveKeyringParcel.mChangePrimaryUserId = null; + } + } + break; + } + getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); + } + }; + + // Create a new Messenger for the communication back + final Messenger messenger = new Messenger(returnHandler); + + DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { + public void run() { + EditUserIdDialogFragment dialogFragment = + EditUserIdDialogFragment.newInstance(messenger, isRevoked, isRevokedPending); + dialogFragment.show(getActivity().getSupportFragmentManager(), "editUserIdDialog"); + } + }); + } + + private void addUserId() { + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) { + Bundle data = message.getData(); + + // add new user id + mUserIdsAddedAdapter.add(data + .getString(AddUserIdDialogFragment.MESSAGE_DATA_USER_ID)); + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + + // pre-fill out primary name + String predefinedName = KeyRing.splitUserId(mPrimaryUserId).name; + AddUserIdDialogFragment addUserIdDialog = AddUserIdDialogFragment.newInstance(messenger, + predefinedName); + + addUserIdDialog.show(getActivity().getSupportFragmentManager(), "addUserIdDialog"); + } + + + protected void returnKeyringParcel() { + if (mSaveKeyringParcel.mAddUserIds.size() == 0) { + Notify.create(getActivity(), R.string.edit_key_error_add_identity, Notify.Style.ERROR).show(); + return; + } + + // use first user id as primary + mSaveKeyringParcel.mChangePrimaryUserId = mSaveKeyringParcel.mAddUserIds.get(0); + + Intent returnIntent = new Intent(); + returnIntent.putExtra(EditKeyActivity.EXTRA_SAVE_KEYRING_PARCEL, mSaveKeyringParcel); + getActivity().setResult(Activity.RESULT_OK, returnIntent); + getActivity().finish(); + } + + /** + * Closes this activity, returning a result parcel with a single error log entry. + */ + void finishWithError(LogType reason) { + // Prepare an intent with an EXTRA_RESULT + Intent intent = new Intent(); + intent.putExtra(OperationResult.EXTRA_RESULT, + new SingletonResult(SingletonResult.RESULT_ERROR, reason)); + + // Finish with result + getActivity().setResult(EditKeyActivity.RESULT_OK, intent); + getActivity().finish(); + } + + @Override + public SaveKeyringParcel createOperationInput() { + return mSaveKeyringParcel; + } + + @Override + public void onQueuedOperationSuccess(OperationResult result) { + + // null-protected from Queueing*Fragment + Activity activity = getActivity(); + + // if good -> finish, return result to showkey and display there! + Intent intent = new Intent(); + intent.putExtra(OperationResult.EXTRA_RESULT, result); + activity.setResult(EditKeyActivity.RESULT_OK, intent); + activity.finish(); + + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 1eb16b3c3..d2b58804e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -386,10 +386,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements finish(); return true; } - case R.id.menu_key_view_edit: { - editKey(mDataUri); - return true; - } case R.id.menu_key_view_certify_fingerprint: { certifyFingerprint(mDataUri, false); return true; @@ -404,9 +400,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements @Override public boolean onPrepareOptionsMenu(Menu menu) { - MenuItem editKey = menu.findItem(R.id.menu_key_view_edit); - editKey.setVisible(mIsSecret); - MenuItem backupKey = menu.findItem(R.id.menu_key_view_backup); backupKey.setVisible(mIsSecret); @@ -691,12 +684,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements } } - private void editKey(Uri dataUri) { - Intent editIntent = new Intent(this, EditKeyActivity.class); - editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri)); - startActivityForResult(editIntent, 0); - } - private void startSafeSlinger(Uri dataUri) { long keyId = 0; try { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java index b8edb9b1c..888cc32b8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -51,6 +51,7 @@ import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnPreDrawListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; +import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; @@ -76,6 +77,7 @@ public class ViewKeyFragment extends LoaderFragment implements public static final String ARG_POSTPONE_TYPE = "postpone_type"; private ListView mUserIds; + private Button mUserIdsEditButton; //private ListView mLinkedSystemContact; enum PostponeType { @@ -131,10 +133,20 @@ public class ViewKeyFragment extends LoaderFragment implements mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); mLinkedIdsCard = (CardView) view.findViewById(R.id.card_linked_ids); - mLinkedIds = (ListView) view.findViewById(R.id.view_key_linked_ids); - mLinkedIdsExpander = (TextView) view.findViewById(R.id.view_key_linked_ids_expander); + mUserIdsEditButton = (Button) view.findViewById(R.id.view_key_card_user_ids_edit); + mSystemContactCard = (CardView) view.findViewById(R.id.linked_system_contact_card); + mSystemContactLayout = (LinearLayout) view.findViewById(R.id.system_contact_layout); + mSystemContactName = (TextView) view.findViewById(R.id.system_contact_name); + mSystemContactPicture = (ImageView) view.findViewById(R.id.system_contact_picture); + + mUserIdsEditButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + editIdentities(mDataUri); + } + }); mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -149,14 +161,15 @@ public class ViewKeyFragment extends LoaderFragment implements } }); - mSystemContactCard = (CardView) view.findViewById(R.id.linked_system_contact_card); - mSystemContactLayout = (LinearLayout) view.findViewById(R.id.system_contact_layout); - mSystemContactName = (TextView) view.findViewById(R.id.system_contact_name); - mSystemContactPicture = (ImageView) view.findViewById(R.id.system_contact_picture); - return root; } + private void editIdentities(Uri dataUri) { + Intent editIntent = new Intent(getActivity(), EditIdentitiesActivity.class); + editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri)); + startActivityForResult(editIntent, 0); + } + private void showLinkedId(final int position) { final LinkedIdViewFragment frag; try { -- cgit v1.2.3 From 373a3fc3f52bd95fc6b5a57f666d438bdc3c0964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 31 Dec 2015 14:13:43 +0100 Subject: Edit identities design --- .../keychain/ui/EditIdentitiesFragment.java | 36 +++++----------------- .../keychain/ui/EditKeyFragment.java | 6 ++-- .../keychain/ui/ViewKeyAdvUserIdsFragment.java | 3 +- .../keychain/ui/ViewKeyFragment.java | 12 ++++++++ .../ui/dialog/AddUserIdDialogFragment.java | 12 +++++++- 5 files changed, 35 insertions(+), 34 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java index ebc0c9158..31153d7af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java @@ -56,7 +56,6 @@ import org.sufficientlysecure.keychain.ui.base.QueueingCryptoOperationFragment; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; -import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; import java.util.Date; @@ -99,9 +98,9 @@ public class EditIdentitiesFragment extends QueueingCryptoOperationFragment finish, return result to showkey and display there! Intent intent = new Intent(); intent.putExtra(OperationResult.EXTRA_RESULT, result); - activity.setResult(EditKeyActivity.RESULT_OK, intent); + activity.setResult(Activity.RESULT_OK, intent); activity.finish(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 969a84f14..1c72cdf41 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -556,7 +556,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment finish, return result to showkey and display there! Intent intent = new Intent(); intent.putExtra(OperationResult.EXTRA_RESULT, result); - activity.setResult(EditKeyActivity.RESULT_OK, intent); + activity.setResult(Activity.RESULT_OK, intent); activity.finish(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java index ae1dd51d0..69ccab162 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java @@ -210,7 +210,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements Messenger messenger = new Messenger(returnHandler); // pre-fill out primary name - AddUserIdDialogFragment addUserIdDialog = AddUserIdDialogFragment.newInstance(messenger, ""); + AddUserIdDialogFragment addUserIdDialog = + AddUserIdDialogFragment.newInstance(messenger, "", true); addUserIdDialog.show(getActivity().getSupportFragmentManager(), "addUserIdDialog"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java index 888cc32b8..b23287144 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -60,6 +60,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; @@ -311,6 +312,17 @@ public class ViewKeyFragment extends LoaderFragment implements loadData(dataUri); } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + // if a result has been returned, display a notify + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { + OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); + result.createNotify(getActivity()).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + } + // These are the rows that we will retrieve. static final String[] UNIFIED_PROJECTION = new String[]{ KeychainContract.KeyRings._ID, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java index bc82feb70..4500ccd24 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java @@ -48,6 +48,7 @@ import org.sufficientlysecure.keychain.util.Log; public class AddUserIdDialogFragment extends DialogFragment implements OnEditorActionListener { private static final String ARG_MESSENGER = "messenger"; private static final String ARG_NAME = "name"; + private static final String ARG_ALLOW_COMMENT = "allow_comment"; public static final int MESSAGE_OKAY = 1; public static final int MESSAGE_CANCEL = 2; @@ -59,12 +60,14 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA private EmailEditText mEmail; private EditText mComment; - public static AddUserIdDialogFragment newInstance(Messenger messenger, String predefinedName) { + public static AddUserIdDialogFragment newInstance(Messenger messenger, String predefinedName, + boolean allowComment) { AddUserIdDialogFragment frag = new AddUserIdDialogFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_MESSENGER, messenger); args.putString(ARG_NAME, predefinedName); + args.putBoolean(ARG_ALLOW_COMMENT, allowComment); frag.setArguments(args); return frag; @@ -78,6 +81,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA final Activity activity = getActivity(); mMessenger = getArguments().getParcelable(ARG_MESSENGER); String predefinedName = getArguments().getString(ARG_NAME); + boolean allowComment = getArguments().getBoolean(ARG_ALLOW_COMMENT); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); @@ -91,6 +95,12 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA mEmail = (EmailEditText) view.findViewById(R.id.add_user_id_address); mComment = (EditText) view.findViewById(R.id.add_user_id_comment); + if (allowComment) { + mComment.setVisibility(View.VISIBLE); + } else { + mComment.setVisibility(View.GONE); + } + mName.setText(predefinedName); alert.setPositiveButton(android.R.string.ok, new OnClickListener() { -- cgit v1.2.3 From 122705c24e04541fbdd015a4e00ef59d0c746fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 31 Dec 2015 15:24:56 +0100 Subject: Improve linked identity handling --- .../keychain/ui/ViewKeyActivity.java | 22 +--- .../keychain/ui/ViewKeyFragment.java | 129 +++++++++++++-------- 2 files changed, 85 insertions(+), 66 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index d2b58804e..2c0f4afcc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -379,13 +379,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements } return true; } - case R.id.menu_key_view_add_linked_identity: { - Intent intent = new Intent(this, LinkedIdWizard.class); - intent.setData(mDataUri); - startActivity(intent); - finish(); - return true; - } case R.id.menu_key_view_certify_fingerprint: { certifyFingerprint(mDataUri, false); return true; @@ -403,10 +396,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements MenuItem backupKey = menu.findItem(R.id.menu_key_view_backup); backupKey.setVisible(mIsSecret); - MenuItem addLinked = menu.findItem(R.id.menu_key_view_add_linked_identity); - addLinked.setVisible(mIsSecret - && Preferences.getPreferences(this).getExperimentalEnableLinkedIdentities()); - MenuItem certifyFingerprint = menu.findItem(R.id.menu_key_view_certify_fingerprint); certifyFingerprint.setVisible(!mIsSecret && !mIsVerified && !mIsExpired && !mIsRevoked); MenuItem certifyFingerprintWord = menu.findItem(R.id.menu_key_view_certify_fingerprint_word); @@ -432,7 +421,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements private void certifyImmediate() { Intent intent = new Intent(this, CertifyKeyActivity.class); - intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[] { mMasterKeyId }); + intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{mMasterKeyId}); startActivityForResult(intent, REQUEST_CERTIFY); } @@ -794,14 +783,15 @@ public class ViewKeyActivity extends BaseNfcActivity implements /* TODO better error handling? May cause problems when a key is deleted, * because the notification triggers faster than the activity closes. */ - // Avoid NullPointerExceptions... - if (data.getCount() == 0) { - return; - } + // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) switch (loader.getId()) { case LOADER_ID_UNIFIED: { + // Avoid NullPointerExceptions... + if (data.getCount() == 0) { + return; + } if (data.moveToFirst()) { // get name, email, and comment from USER_ID diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java index b23287144..89dd90ff7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -24,7 +24,6 @@ import java.util.List; import android.Manifest; import android.annotation.TargetApi; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -47,7 +46,6 @@ import android.transition.TransitionInflater; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnPreDrawListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; @@ -67,6 +65,7 @@ import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment; import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment.OnIdentityLoadedListener; +import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard; import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; @@ -78,8 +77,6 @@ public class ViewKeyFragment extends LoaderFragment implements public static final String ARG_POSTPONE_TYPE = "postpone_type"; private ListView mUserIds; - private Button mUserIdsEditButton; - //private ListView mLinkedSystemContact; enum PostponeType { NONE, LINKED; @@ -89,8 +86,8 @@ public class ViewKeyFragment extends LoaderFragment implements private static final int LOADER_ID_UNIFIED = 0; private static final int LOADER_ID_USER_IDS = 1; - private static final int LOADER_ID_LINKED_CONTACT = 2; - private static final int LOADER_ID_LINKED_IDS = 3; + private static final int LOADER_ID_LINKED_IDS = 2; + private static final int LOADER_ID_LINKED_CONTACT = 3; private static final String LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID = "loader_linked_contact_master_key_id"; @@ -110,6 +107,7 @@ public class ViewKeyFragment extends LoaderFragment implements private ListView mLinkedIds; private CardView mLinkedIdsCard; + private TextView mLinkedIdsEmpty; private byte[] mFingerprint; private TextView mLinkedIdsExpander; @@ -133,22 +131,31 @@ public class ViewKeyFragment extends LoaderFragment implements View view = inflater.inflate(R.layout.view_key_fragment, getContainer()); mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); + Button userIdsEditButton = (Button) view.findViewById(R.id.view_key_card_user_ids_edit); mLinkedIdsCard = (CardView) view.findViewById(R.id.card_linked_ids); mLinkedIds = (ListView) view.findViewById(R.id.view_key_linked_ids); mLinkedIdsExpander = (TextView) view.findViewById(R.id.view_key_linked_ids_expander); - mUserIdsEditButton = (Button) view.findViewById(R.id.view_key_card_user_ids_edit); + mLinkedIdsEmpty = (TextView) view.findViewById(R.id.view_key_linked_ids_empty); + Button linkedIdsAddButton = (Button) view.findViewById(R.id.view_key_card_linked_ids_add); mSystemContactCard = (CardView) view.findViewById(R.id.linked_system_contact_card); mSystemContactLayout = (LinearLayout) view.findViewById(R.id.system_contact_layout); mSystemContactName = (TextView) view.findViewById(R.id.system_contact_name); mSystemContactPicture = (ImageView) view.findViewById(R.id.system_contact_picture); - mUserIdsEditButton.setOnClickListener(new View.OnClickListener() { + userIdsEditButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { editIdentities(mDataUri); } }); + linkedIdsAddButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + addLinkedIdentity(mDataUri); + } + }); + mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { @@ -171,6 +178,13 @@ public class ViewKeyFragment extends LoaderFragment implements startActivityForResult(editIntent, 0); } + private void addLinkedIdentity(Uri dataUri) { + Intent intent = new Intent(getActivity(), LinkedIdWizard.class); + intent.setData(dataUri); + startActivity(intent); + getActivity().finish(); + } + private void showLinkedId(final int position) { final LinkedIdViewFragment frag; try { @@ -182,7 +196,7 @@ public class ViewKeyFragment extends LoaderFragment implements if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Transition trans = TransitionInflater.from(getActivity()) - .inflateTransition(R.transition.linked_id_card_trans); + .inflateTransition(R.transition.linked_id_card_trans); // setSharedElementReturnTransition(trans); setExitTransition(new Fade()); frag.setSharedElementEnterTransition(trans); @@ -235,7 +249,7 @@ public class ViewKeyFragment extends LoaderFragment implements */ private void loadLinkedSystemContact(final long contactId) { // contact doesn't exist, stop - if(contactId == -1) return; + if (contactId == -1) return; final Context context = mSystemContactName.getContext(); ContactHelper contactHelper = new ContactHelper(context); @@ -323,7 +337,6 @@ public class ViewKeyFragment extends LoaderFragment implements } } - // These are the rows that we will retrieve. static final String[] UNIFIED_PROJECTION = new String[]{ KeychainContract.KeyRings._ID, KeychainContract.KeyRings.MASTER_KEY_ID, @@ -350,7 +363,7 @@ public class ViewKeyFragment extends LoaderFragment implements @SuppressWarnings("unused") static final int INDEX_HAS_ENCRYPT = 8; - private static final String[] RAWCONTACT_PROJECTION = { + private static final String[] RAW_CONTACT_PROJECTION = { ContactsContract.RawContacts.CONTACT_ID }; @@ -384,29 +397,28 @@ public class ViewKeyFragment extends LoaderFragment implements return LinkedIdsAdapter.createLoader(getActivity(), mDataUri); } - //we need a separate loader for linked contact to ensure refreshing on verification case LOADER_ID_LINKED_CONTACT: { - //passed in args to explicitly specify their need + // we need a separate loader for linked contact + // to ensure refreshing on verification + + // passed in args to explicitly specify their need long masterKeyId = args.getLong(LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID); boolean isSecret = args.getBoolean(LOADER_EXTRA_LINKED_CONTACT_IS_SECRET); - Uri baseUri; - if (isSecret) - baseUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI; - else - baseUri = ContactsContract.RawContacts.CONTENT_URI; + Uri baseUri = isSecret ? ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI : + ContactsContract.RawContacts.CONTENT_URI; return new CursorLoader( getActivity(), baseUri, - RAWCONTACT_PROJECTION, + RAW_CONTACT_PROJECTION, ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=? AND " + ContactsContract.RawContacts.DELETED + "=?", - new String[]{//"0" for "not deleted" + new String[]{ Constants.ACCOUNT_TYPE, Long.toString(masterKeyId), - "0" + "0" // "0" for "not deleted" }, null); } @@ -421,47 +433,29 @@ public class ViewKeyFragment extends LoaderFragment implements /* TODO better error handling? May cause problems when a key is deleted, * because the notification triggers faster than the activity closes. */ - // Avoid NullPointerExceptions... - if (data == null || data.getCount() == 0) { + if (data == null) { return; } // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) switch (loader.getId()) { case LOADER_ID_UNIFIED: { - if (data.moveToFirst()) { + if (data.getCount() == 1 && data.moveToFirst()) { mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; mFingerprint = data.getBlob(INDEX_FINGERPRINT); long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID); - // load user ids after we know if it's a secret key - mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null); - mUserIds.setAdapter(mUserIdsAdapter); - getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); - - if (Preferences.getPreferences(getActivity()).getExperimentalEnableLinkedIdentities()) { - mLinkedIdsAdapter = - new LinkedIdsAdapter(getActivity(), null, 0, mIsSecret, mLinkedIdsExpander); - mLinkedIds.setAdapter(mLinkedIdsAdapter); - getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this); - } - + // init other things after we know if it's a secret key + initUserIds(mIsSecret); + initLinkedIds(mIsSecret); initLinkedContactLoader(masterKeyId, mIsSecret); - - break; + initCardButtonsVisibility(mIsSecret); } + break; } case LOADER_ID_USER_IDS: { - LinearLayout editButtonsLayout = - (LinearLayout) getActivity().findViewById(R.id.view_key_card_user_ids_buttons); - if (mIsSecret) { - editButtonsLayout.setVisibility(View.VISIBLE); - } else { - editButtonsLayout.setVisibility(View.GONE); - } - setContentShown(true, false); mUserIdsAdapter.swapCursor(data); @@ -470,7 +464,15 @@ public class ViewKeyFragment extends LoaderFragment implements case LOADER_ID_LINKED_IDS: { mLinkedIdsAdapter.swapCursor(data); - mLinkedIdsCard.setVisibility(mLinkedIdsAdapter.getCount() > 0 ? View.VISIBLE : View.GONE); + + if (mIsSecret) { + mLinkedIdsCard.setVisibility(View.VISIBLE); + mLinkedIdsEmpty.setVisibility(mLinkedIdsAdapter.getCount() > 0 ? View.GONE : View.VISIBLE); + } else { + mLinkedIdsCard.setVisibility(mLinkedIdsAdapter.getCount() > 0 ? View.VISIBLE : View.GONE); + mLinkedIdsEmpty.setVisibility(View.GONE); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mPostponeType == PostponeType.LINKED) { mLinkedIdsCard.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() { @TargetApi(VERSION_CODES.LOLLIPOP) @@ -486,13 +488,27 @@ public class ViewKeyFragment extends LoaderFragment implements } case LOADER_ID_LINKED_CONTACT: { - if (data.moveToFirst()) {// if we have a linked contact + if (data.moveToFirst()) { // if we have a linked contact long contactId = data.getLong(INDEX_CONTACT_ID); loadLinkedSystemContact(contactId); } break; } + } + } + + private void initUserIds(boolean isSecret) { + mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !isSecret, null); + mUserIds.setAdapter(mUserIdsAdapter); + getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); + } + private void initLinkedIds(boolean isSecret) { + if (Preferences.getPreferences(getActivity()).getExperimentalEnableLinkedIdentities()) { + mLinkedIdsAdapter = + new LinkedIdsAdapter(getActivity(), null, 0, isSecret, mLinkedIdsExpander); + mLinkedIds.setAdapter(mLinkedIdsAdapter); + getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this); } } @@ -512,6 +528,20 @@ public class ViewKeyFragment extends LoaderFragment implements getLoaderManager().initLoader(LOADER_ID_LINKED_CONTACT, linkedContactData, this); } + private void initCardButtonsVisibility(boolean isSecret) { + LinearLayout buttonsUserIdsLayout = + (LinearLayout) getActivity().findViewById(R.id.view_key_card_user_ids_buttons); + LinearLayout buttonsLinkedIdsLayout = + (LinearLayout) getActivity().findViewById(R.id.view_key_card_linked_ids_buttons); + if (isSecret) { + buttonsUserIdsLayout.setVisibility(View.VISIBLE); + buttonsLinkedIdsLayout.setVisibility(View.VISIBLE); + } else { + buttonsUserIdsLayout.setVisibility(View.GONE); + buttonsLinkedIdsLayout.setVisibility(View.GONE); + } + } + /** * This is called when the last Cursor provided to onLoadFinished() above is about to be closed. * We need to make sure we are no longer using it. @@ -524,7 +554,6 @@ public class ViewKeyFragment extends LoaderFragment implements break; } case LOADER_ID_LINKED_IDS: { - mLinkedIdsCard.setVisibility(View.GONE); mLinkedIdsAdapter.swapCursor(null); break; } -- cgit v1.2.3 From bfa28fcb5e023ac82df2665f7616bd9305daa589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 31 Dec 2015 15:49:50 +0100 Subject: Upload to keyserver after editing identities --- .../keychain/ui/EditIdentitiesFragment.java | 160 ++++++++++++++++++--- 1 file changed, 142 insertions(+), 18 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java index 31153d7af..cfd3f3cea 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditIdentitiesFragment.java @@ -25,6 +25,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Messenger; +import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; @@ -33,14 +34,17 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; +import android.widget.CheckBox; import android.widget.ListView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.operations.results.EditKeyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.SingletonResult; +import org.sufficientlysecure.keychain.operations.results.UploadResult; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; @@ -49,22 +53,22 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; -import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.UploadKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; -import org.sufficientlysecure.keychain.ui.base.QueueingCryptoOperationFragment; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Preferences; -import java.util.Date; - -public class EditIdentitiesFragment extends QueueingCryptoOperationFragment +public class EditIdentitiesFragment extends Fragment implements LoaderManager.LoaderCallbacks { public static final String ARG_DATA_URI = "uri"; + private CheckBox mUploadKeyCheckbox; private ListView mUserIdsList; private ListView mUserIdsAddedList; private View mAddUserId; @@ -78,6 +82,9 @@ public class EditIdentitiesFragment extends QueueingCryptoOperationFragment mEditOpHelper; + private CryptoOperationHelper mUploadOpHelper; + private String mPrimaryUserId; /** @@ -98,10 +105,16 @@ public class EditIdentitiesFragment extends QueueingCryptoOperationFragment editKeyCallback + = new CryptoOperationHelper.Callback() { + @Override + public SaveKeyringParcel createOperationInput() { + return mSaveKeyringParcel; + } + + @Override + public void onCryptoOperationSuccess(EditKeyResult result) { + + if (result.mMasterKeyId != null && mUploadKeyCheckbox.isChecked()) { + // result will be displayed after upload + uploadKey(result); + return; + } + + finishWithResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + + } + + @Override + public void onCryptoOperationError(EditKeyResult result) { + displayResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + mEditOpHelper = new CryptoOperationHelper<>(1, this, editKeyCallback, R.string.progress_building_key); + mEditOpHelper.cryptoOperation(); + } + + + private void uploadKey(final EditKeyResult editKeyResult) { + Activity activity = getActivity(); + // if the activity is gone at this point, there is nothing we can do! + if (activity == null) { + return; + } + + // set data uri as path to keyring + final long masterKeyId = editKeyResult.mMasterKeyId; + // upload to favorite keyserver + final String keyserver = Preferences.getPreferences(activity).getPreferredKeyserver(); + + CryptoOperationHelper.Callback callback + = new CryptoOperationHelper.Callback() { + + @Override + public UploadKeyringParcel createOperationInput() { + return new UploadKeyringParcel(keyserver, masterKeyId); + } + + @Override + public void onCryptoOperationSuccess(UploadResult result) { + handleResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + + } + + @Override + public void onCryptoOperationError(UploadResult result) { + displayResult(result); + } + + public void handleResult(UploadResult result) { + editKeyResult.getLog().add(result, 0); + finishWithResult(editKeyResult); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + mUploadOpHelper = new CryptoOperationHelper<>(3, this, callback, R.string.progress_uploading); + mUploadOpHelper.cryptoOperation(); + } + /** * Closes this activity, returning a result parcel with a single error log entry. */ @@ -315,23 +438,24 @@ public class EditIdentitiesFragment extends QueueingCryptoOperationFragment finish, return result to showkey and display there! - Intent intent = new Intent(); - intent.putExtra(OperationResult.EXTRA_RESULT, result); - activity.setResult(Activity.RESULT_OK, intent); + Intent data = new Intent(); + data.putExtra(OperationResult.EXTRA_RESULT, result); + activity.setResult(Activity.RESULT_OK, data); activity.finish(); - } } -- cgit v1.2.3 From 6fb96ce7903623f2e3b1c38c765e8a501dbcc0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 31 Dec 2015 16:29:55 +0100 Subject: Add change password menu item to view key --- .../keychain/ui/ViewKeyActivity.java | 105 ++++++++++++++++++--- 1 file changed, 94 insertions(+), 11 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 2c0f4afcc..1db273e48 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -36,6 +36,8 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.Message; +import android.os.Messenger; import android.provider.ContactsContract; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; @@ -64,6 +66,7 @@ import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; +import org.sufficientlysecure.keychain.operations.results.EditKeyResult; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; @@ -75,10 +78,11 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.service.ImportKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.ViewKeyFragment.PostponeType; import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; -import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard; +import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.util.FormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; @@ -90,6 +94,7 @@ import org.sufficientlysecure.keychain.ui.util.QrCodeUtils; import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.NfcHelper; +import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Preferences; @@ -116,7 +121,9 @@ public class ViewKeyActivity extends BaseNfcActivity implements // For CryptoOperationHelper.Callback private String mKeyserver; private ArrayList mKeyList; - private CryptoOperationHelper mOperationHelper; + private CryptoOperationHelper mImportOpHelper; + private CryptoOperationHelper mEditOpHelper; + private SaveKeyringParcel mSaveKeyringParcel; private TextView mStatusText; private ImageView mStatusImage; @@ -151,8 +158,10 @@ public class ViewKeyActivity extends BaseNfcActivity implements private boolean mIsRefreshing; private Animation mRotate, mRotateSpin; private View mRefresh; - private String mFingerprint; + private long mMasterKeyId; + private byte[] mFingerprint; + private String mFingerprintString; private byte[] mNfcFingerprints; private String mNfcUserId; @@ -164,7 +173,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements super.onCreate(savedInstanceState); mProviderHelper = new ProviderHelper(this); - mOperationHelper = new CryptoOperationHelper<>(1, this, this, null); + mImportOpHelper = new CryptoOperationHelper<>(1, this, this, null); setTitle(null); @@ -357,6 +366,10 @@ public class ViewKeyActivity extends BaseNfcActivity implements startActivity(homeIntent); return true; } + case R.id.menu_key_change_password: { + changePassword(); + return true; + } case R.id.menu_key_view_backup: { startPassphraseActivity(REQUEST_BACKUP); return true; @@ -395,6 +408,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements public boolean onPrepareOptionsMenu(Menu menu) { MenuItem backupKey = menu.findItem(R.id.menu_key_view_backup); backupKey.setVisible(mIsSecret); + MenuItem changePassword = menu.findItem(R.id.menu_key_change_password); + changePassword.setVisible(mIsSecret); MenuItem certifyFingerprint = menu.findItem(R.id.menu_key_view_certify_fingerprint); certifyFingerprint.setVisible(!mIsSecret && !mIsVerified && !mIsExpired && !mIsRevoked); @@ -405,6 +420,70 @@ public class ViewKeyActivity extends BaseNfcActivity implements return true; } + private void changePassword() { + mSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint); + + CryptoOperationHelper.Callback editKeyCallback + = new CryptoOperationHelper.Callback() { + @Override + public SaveKeyringParcel createOperationInput() { + return mSaveKeyringParcel; + } + + @Override + public void onCryptoOperationSuccess(EditKeyResult result) { + displayResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + + } + + @Override + public void onCryptoOperationError(EditKeyResult result) { + displayResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + mEditOpHelper = new CryptoOperationHelper<>(2, this, editKeyCallback, R.string.progress_building_key); + + // Message is received after passphrase is cached + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) { + Bundle data = message.getData(); + + // use new passphrase! + mSaveKeyringParcel.mNewUnlock = new SaveKeyringParcel.ChangeUnlockParcel( + (Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE), + null + ); + + mEditOpHelper.cryptoOperation(); + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + + SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance( + messenger, R.string.title_change_passphrase); + + setPassphraseDialog.show(getSupportFragmentManager(), "setPassphraseDialog"); + } + + private void displayResult(OperationResult result) { + result.createNotify(this).show(); + } + private void scanQrCode() { Intent scanQrCode = new Intent(this, ImportKeysProxyActivity.class); scanQrCode.setAction(ImportKeysProxyActivity.ACTION_SCAN_WITH_RESULT); @@ -496,9 +575,12 @@ public class ViewKeyActivity extends BaseNfcActivity implements @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (mOperationHelper.handleActivityResult(requestCode, resultCode, data)) { + if (mImportOpHelper.handleActivityResult(requestCode, resultCode, data)) { return; } + if (mEditOpHelper != null) { + mEditOpHelper.handleActivityResult(requestCode, resultCode, data); + } switch (requestCode) { case REQUEST_QR_FINGERPRINT: { @@ -519,7 +601,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements Notify.create(this, R.string.error_scan_fp, Notify.LENGTH_LONG, Style.ERROR).show(); return; } - if (mFingerprint.equalsIgnoreCase(fp)) { + if (mFingerprintString.equalsIgnoreCase(fp)) { certifyImmediate(); } else { Notify.create(this, R.string.error_scan_match, Notify.LENGTH_LONG, Style.ERROR).show(); @@ -584,7 +666,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements byte[] candidateFp = ring.getFingerprint(); // if the master key of that key matches this one, just show the yubikey dialog - if (KeyFormattingUtils.convertFingerprintToHex(candidateFp).equals(mFingerprint)) { + if (KeyFormattingUtils.convertFingerprintToHex(candidateFp).equals(mFingerprintString)) { showYubiKeyFragment(mNfcFingerprints, mNfcUserId, mNfcAid); return; } @@ -803,7 +885,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements } mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID); - mFingerprint = KeyFormattingUtils.convertFingerprintToHex(data.getBlob(INDEX_FINGERPRINT)); + mFingerprint = data.getBlob(INDEX_FINGERPRINT); + mFingerprintString = KeyFormattingUtils.convertFingerprintToHex(mFingerprint); // if it wasn't shown yet, display yubikey fragment if (mShowYubikeyAfterCreation && getIntent().hasExtra(EXTRA_NFC_AID)) { @@ -880,8 +963,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements mStatusImage.setVisibility(View.GONE); color = getResources().getColor(R.color.key_flag_green); // reload qr code only if the fingerprint changed - if (!mFingerprint.equals(mQrCodeLoaded)) { - loadQrCode(mFingerprint); + if (!mFingerprintString.equals(mQrCodeLoaded)) { + loadQrCode(mFingerprintString); } photoTask.execute(mMasterKeyId); mQrCodeLayout.setVisibility(View.VISIBLE); @@ -1021,7 +1104,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements mKeyserver = Preferences.getPreferences(this).getPreferredKeyserver(); - mOperationHelper.cryptoOperation(); + mImportOpHelper.cryptoOperation(); } @Override -- cgit v1.2.3