diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/AbstractDao.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/AbstractDao.java index 9ad28f8d8..0fbb25ba0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/AbstractDao.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/AbstractDao.java @@ -33,8 +33,10 @@ class AbstractDao { List mapAllRows(SupportSQLiteQuery query, Mapper mapper) { ArrayList result = new ArrayList<>(); try (Cursor cursor = getReadableDb().query(query)) { - T item = mapper.map(cursor); - result.add(item); + while (cursor.moveToNext()) { + T item = mapper.map(cursor); + result.add(item); + } } return result; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 696d6e1d4..4d3db4a13 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -229,18 +229,6 @@ public class KeychainContract { public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() .appendPath(BASE_KEY_RINGS).build(); - /** - * Use if multiple items get returned - */ - public static final String CONTENT_TYPE - = "vnd.android.cursor.dir/vnd.org.sufficientlysecure.keychain.provider.user_ids"; - - /** - * Use if a single item is returned - */ - public static final String CONTENT_ITEM_TYPE - = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.user_ids"; - public static Uri buildUserIdsUri() { return CONTENT_URI.buildUpon().appendPath(PATH_USER_IDS).build(); } @@ -248,10 +236,6 @@ public class KeychainContract { public static Uri buildUserIdsUri(long masterKeyId) { return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).appendPath(PATH_USER_IDS).build(); } - - public static Uri buildUserIdsUri(Uri uri) { - return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_USER_IDS).build(); - } } public static class Certs implements CertsColumns, BaseColumns { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 40398f741..d5481f5ea 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -177,9 +177,6 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe case KEY_RING_KEYS: return Keys.CONTENT_TYPE; - case KEY_RING_USER_IDS: - return UserPackets.CONTENT_TYPE; - case KEY_SIGNATURES: return KeySignatures.CONTENT_TYPE; @@ -466,8 +463,7 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe break; } - case KEY_RINGS_USER_IDS: - case KEY_RING_USER_IDS: { + case KEY_RINGS_USER_IDS: { HashMap projectionMap = new HashMap<>(); projectionMap.put(UserPackets._ID, Tables.USER_PACKETS + ".oid AS _id"); projectionMap.put(UserPackets.MASTER_KEY_ID, Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID); @@ -497,13 +493,6 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL"); - // If we are searching for a particular keyring's ids, add where - if (match == KEY_RING_USER_IDS) { - qb.appendWhere(" AND "); - qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(1)); - } - if (TextUtils.isEmpty(sortOrder)) { sortOrder = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " ASC" + "," + Tables.USER_PACKETS + "." + UserPackets.RANK + " ASC"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 7e5995a80..90184bc00 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -17,7 +17,7 @@ package org.sufficientlysecure.keychain.ui; -import android.net.Uri; + import android.os.Bundle; import org.sufficientlysecure.keychain.R; @@ -27,24 +27,20 @@ import timber.log.Timber; public class EditKeyActivity extends BaseActivity { - public static final String EXTRA_SAVE_KEYRING_PARCEL = "save_keyring_parcel"; - private EditKeyFragment mEditKeyFragment; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Uri dataUri = getIntent().getData(); SaveKeyringParcel saveKeyringParcel = getIntent().getParcelableExtra(EXTRA_SAVE_KEYRING_PARCEL); - if (dataUri == null && saveKeyringParcel == null) { + if (saveKeyringParcel == null) { Timber.e("Either a key Uri or EXTRA_SAVE_KEYRING_PARCEL is required!"); finish(); return; } - loadFragment(savedInstanceState, dataUri, saveKeyringParcel); + loadFragment(savedInstanceState, saveKeyringParcel); } @Override @@ -52,7 +48,7 @@ public class EditKeyActivity extends BaseActivity { setContentView(R.layout.edit_key_activity); } - private void loadFragment(Bundle savedInstanceState, Uri dataUri, SaveKeyringParcel saveKeyringParcel) { + private void loadFragment(Bundle savedInstanceState, SaveKeyringParcel saveKeyringParcel) { // 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. @@ -61,16 +57,12 @@ public class EditKeyActivity extends BaseActivity { } // Create an instance of the fragment - if (dataUri != null) { - mEditKeyFragment = EditKeyFragment.newInstance(dataUri); - } else { - mEditKeyFragment = EditKeyFragment.newInstance(saveKeyringParcel); - } + EditKeyFragment editKeyFragment = EditKeyFragment.newInstance(saveKeyringParcel); // 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, mEditKeyFragment) + .replace(R.id.edit_key_fragment_container, editKeyFragment) .commitAllowingStateLoss(); // do it immediately! getSupportFragmentManager().executePendingTransactions(); 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 10c62dda3..0bbabeab6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -18,103 +18,49 @@ package org.sufficientlysecure.keychain.ui; -import java.util.Date; - 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.support.annotation.NonNull; +import android.support.v4.app.Fragment; 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.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.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; -import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; -import org.sufficientlysecure.keychain.provider.KeyRepository; -import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.service.ChangeUnlockParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange; -import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; -import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter; -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.AddSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.util.Notify; import timber.log.Timber; -public class EditKeyFragment extends QueueingCryptoOperationFragment - implements LoaderManager.LoaderCallbacks { +public class EditKeyFragment extends Fragment { + private static final String ARG_SAVE_KEYRING_PARCEL = "save_keyring_parcel"; - public static final String ARG_DATA_URI = "uri"; - public static final String ARG_SAVE_KEYRING_PARCEL = "save_keyring_parcel"; - - private ListView mUserIdsList; - private ListView mSubkeysList; private ListView mUserIdsAddedList; private ListView mSubkeysAddedList; private View mChangePassphrase; private View mAddUserId; private View mAddSubkey; - private static final int LOADER_ID_USER_IDS = 0; - private static final int LOADER_ID_SUBKEYS = 1; - - // cursor adapter - private UserIdsAdapter mUserIdsAdapter; - private SubkeysAdapter mSubkeysAdapter; - // array adapter private UserIdsAddedAdapter mUserIdsAddedAdapter; private SubkeysAddedAdapter mSubkeysAddedAdapter; - private Uri mDataUri; - private SaveKeyringParcel.Builder mSkpBuilder; private String mPrimaryUserId; - /** - * Creates new instance of this fragment - */ - public static EditKeyFragment newInstance(Uri dataUri) { - EditKeyFragment frag = new EditKeyFragment(); - - Bundle args = new Bundle(); - args.putParcelable(ARG_DATA_URI, dataUri); - - frag.setArguments(args); - - return frag; - } - public static EditKeyFragment newInstance(SaveKeyringParcel saveKeyringParcel) { EditKeyFragment frag = new EditKeyFragment(); @@ -127,11 +73,9 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment { + // if we are working on an Uri, save directly + returnKeyringParcel(); + }, + v -> { + getActivity().setResult(Activity.RESULT_CANCELED); + getActivity().finish(); }); - Uri dataUri = getArguments().getParcelable(ARG_DATA_URI); SaveKeyringParcel saveKeyringParcel = getArguments().getParcelable(ARG_SAVE_KEYRING_PARCEL); - if (dataUri == null && saveKeyringParcel == null) { + if (saveKeyringParcel == null) { Timber.e("Either a key Uri or ARG_SAVE_KEYRING_PARCEL is required!"); getActivity().finish(); return; } initView(); - if (dataUri != null) { - loadData(dataUri); - } else { - loadSaveKeyringParcel(saveKeyringParcel); - } + loadSaveKeyringParcel(saveKeyringParcel); } private void loadSaveKeyringParcel(SaveKeyringParcel saveKeyringParcel) { @@ -191,146 +121,13 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment parent, View view, int position, long id) { - editSubkey(position); - } - }); - - 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); - } - - case LOADER_ID_SUBKEYS: { - Uri baseUri = KeychainContract.Keys.buildKeysUri(mDataUri); - return new CursorLoader(getActivity(), baseUri, - SubkeysAdapter.SUBKEYS_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; - - case LOADER_ID_SUBKEYS: - mSubkeysAdapter.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; - case LOADER_ID_SUBKEYS: - mSubkeysAdapter.swapCursor(null); - break; - } + mChangePassphrase.setOnClickListener(v -> changePassphrase()); + mAddUserId.setOnClickListener(v -> addUserId()); + mAddSubkey.setOnClickListener(v -> addSubkey()); } private void changePassphrase() { -// Intent passIntent = new Intent(getActivity(), PassphraseWizardActivity.class); -// passIntent.setAction(PassphraseWizardActivity.CREATE_METHOD); -// startActivityForResult(passIntent, 12); - // Message is received after passphrase is cached Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { @@ -354,138 +151,6 @@ 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(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 6e51ee7a0..9ce7058c8 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,9 @@ package org.sufficientlysecure.keychain.ui; +import java.util.List; + +import android.arch.lifecycle.LiveData; import android.content.Intent; import android.database.Cursor; import android.net.Uri; @@ -41,10 +44,14 @@ import android.widget.ViewAnimator; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.livedata.GenericLiveData; +import org.sufficientlysecure.keychain.model.UserPacket.UserId; import org.sufficientlysecure.keychain.operations.results.EditKeyResult; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeyRepository; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; -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; @@ -63,7 +70,6 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements public static final String ARG_DATA_URI = "uri"; private static final int LOADER_ID_UNIFIED = 0; - private static final int LOADER_ID_USER_IDS = 1; private ListView mUserIds; private ListView mUserIdsAddedList; @@ -162,7 +168,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements } break; } - getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); + mUserIdsAdapter.notifyDataSetChanged(); } }; @@ -244,13 +250,30 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements Timber.i("dataUri: " + mDataUri); - mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0); + mUserIdsAdapter = new UserIdsAdapter(getActivity(), false); mUserIds.setAdapter(mUserIdsAdapter); // 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); + + KeyRepository keyRepository = KeyRepository.create(getContext()); + try { + Uri uri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri); + CachedPublicKeyRing keyRing = keyRepository.getCachedPublicKeyRing(uri); + long masterKeyId = keyRing.getMasterKeyId(); + + LiveData> userIdLiveData = + new GenericLiveData<>(getContext(), null, () -> keyRepository.getUserIds(masterKeyId)); + userIdLiveData.observe(this, this::onUserIdsLoaded); + } catch (PgpKeyNotFoundException e) { + e.printStackTrace(); + } + } + + private void onUserIdsLoaded(List userIds) { + mUserIdsAdapter.setData(userIds); + setContentShown(true); } // These are the rows that we will retrieve. @@ -273,14 +296,6 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements PROJECTION, null, null, null); } - case LOADER_ID_USER_IDS: { - setContentShown(false); - - Uri userIdUri = UserPackets.buildUserIdsUri(mDataUri); - return new CursorLoader(getActivity(), userIdUri, - UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null); - } - default: return null; } @@ -301,14 +316,6 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements 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; - } } } @@ -317,10 +324,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements * We need to make sure we are no longer using it. */ public void onLoaderReset(Loader loader) { - if (loader.getId() != LOADER_ID_USER_IDS) { - return; - } - mUserIdsAdapter.swapCursor(null); + } @Override @@ -352,7 +356,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements mUserIdAddFabLayout.setDisplayedChild(1); mUserIdsAdapter.setEditMode(mSkpBuilder); - getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); + mUserIdsAdapter.notifyDataSetChanged(); mode.setTitle(R.string.title_edit_identities); mode.getMenuInflater().inflate(R.menu.action_edit_uids, menu); @@ -377,7 +381,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements mUserIdsAdapter.setEditMode(null); mUserIdsAddedLayout.setVisibility(View.GONE); mUserIdAddFabLayout.setDisplayedChild(0); - getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); + mUserIdsAdapter.notifyDataSetChanged(); } }); } 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 deleted file mode 100644 index ac9fbd636..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2017 Schürmann & Breitmoser GbR - * - * 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.adapter; - -import android.content.Context; -import android.database.Cursor; -import android.support.v4.widget.CursorAdapter; -import android.view.View; - -import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; - -public abstract class UserAttributesAdapter extends CursorAdapter { - public static final String[] USER_PACKETS_PROJECTION = new String[]{ - UserPackets._ID, - UserPackets.TYPE, - UserPackets.USER_ID, - UserPackets.ATTRIBUTE_DATA, - UserPackets.RANK, - UserPackets.VERIFIED, - UserPackets.IS_PRIMARY, - UserPackets.IS_REVOKED, - UserPackets.NAME, - UserPackets.EMAIL, - UserPackets.COMMENT, - }; - public static final int INDEX_ID = 0; - public static final int INDEX_TYPE = 1; - public static final int INDEX_USER_ID = 2; - public static final int INDEX_ATTRIBUTE_DATA = 3; - public static final int INDEX_RANK = 4; - public static final int INDEX_VERIFIED = 5; - public static final int INDEX_IS_PRIMARY = 6; - public static final int INDEX_IS_REVOKED = 7; - public static final int INDEX_NAME = 8; - public static final int INDEX_EMAIL = 9; - public static final int INDEX_COMMENT = 10; - - public UserAttributesAdapter(Context context, Cursor c, int flags) { - super(context, c, flags); - } - - @Override - public abstract void bindView(View view, Context context, Cursor cursor); - - public String getUserId(int position) { - mCursor.moveToPosition(position); - return mCursor.getString(INDEX_USER_ID); - } - - public boolean getIsRevoked(int position) { - mCursor.moveToPosition(position); - return mCursor.getInt(INDEX_IS_REVOKED) > 0; - } - - public int getIsVerified(int position) { - mCursor.moveToPosition(position); - return mCursor.getInt(INDEX_VERIFIED); - } - -} 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 8550a5eca..892226b88 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 @@ -18,41 +18,73 @@ package org.sufficientlysecure.keychain.ui.adapter; +import java.util.List; + import android.content.Context; -import android.database.Cursor; import android.graphics.Typeface; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import android.widget.ViewAnimator; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.model.UserPacket.UserId; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; -public class UserIdsAdapter extends UserAttributesAdapter { - protected LayoutInflater mInflater; +// TODO move to RecyclerView +public class UserIdsAdapter extends BaseAdapter { + private Context context; + private List data; private SaveKeyringParcel.Builder mSkpBuilder; private boolean mShowStatusImages; + private LayoutInflater layoutInflater; - public UserIdsAdapter(Context context, Cursor c, int flags, boolean showStatusImages) { - super(context, c, flags); - mInflater = LayoutInflater.from(context); + public UserIdsAdapter(Context context, boolean showStatusImages) { + super(); + this.context = context; + this.layoutInflater = LayoutInflater.from(context); mShowStatusImages = showStatusImages; } - public UserIdsAdapter(Context context, Cursor c, int flags) { - this(context, c, flags, true); + @Override + public int getCount() { + return data != null ? data.size() : 0; } @Override - public void bindView(View view, Context context, Cursor cursor) { + public UserId getItem(int position) { + return data.get(position); + } + + @Override + public long getItemId(int position) { + return data.get(position).master_key_id(); + } + + public void setData(List data) { + this.data = data; + notifyDataSetChanged(); + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + View view; + if (convertView != null) { + view = convertView; + } else { + view = layoutInflater.inflate(R.layout.view_key_adv_user_id_item, parent, false); + } + TextView vName = view.findViewById(R.id.user_id_item_name); TextView vAddress = view.findViewById(R.id.user_id_item_address); TextView vComment = view.findViewById(R.id.user_id_item_comment); @@ -62,37 +94,35 @@ public class UserIdsAdapter extends UserAttributesAdapter { ImageView vDeleteButton = view.findViewById(R.id.user_id_item_delete_button); vDeleteButton.setVisibility(View.GONE); // not used - String userId = cursor.getString(INDEX_USER_ID); - String name = cursor.getString(INDEX_NAME); - String email = cursor.getString(INDEX_EMAIL); - String comment = cursor.getString(INDEX_COMMENT); - if (name != null) { - vName.setText(name); + UserId userId = getItem(position); + + if (userId.name() != null) { + vName.setText(userId.name()); } else { vName.setText(R.string.user_id_no_name); } - if (email != null) { - vAddress.setText(email); + if (userId.email() != null) { + vAddress.setText(userId.email()); vAddress.setVisibility(View.VISIBLE); } else { vAddress.setVisibility(View.GONE); } - if (comment != null) { - vComment.setText(comment); + if (userId.comment() != null) { + vComment.setText(userId.comment()); vComment.setVisibility(View.VISIBLE); } else { vComment.setVisibility(View.GONE); } - boolean isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0; - boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; + boolean isPrimary = userId.is_primary(); + boolean isRevoked = userId.is_revoked(); // for edit key if (mSkpBuilder != null) { String changePrimaryUserId = mSkpBuilder.getChangePrimaryUserId(); boolean changeAnyPrimaryUserId = (changePrimaryUserId != null); - boolean changeThisPrimaryUserId = (changeAnyPrimaryUserId && changePrimaryUserId.equals(userId)); - boolean revokeThisUserId = (mSkpBuilder.getMutableRevokeUserIds().contains(userId)); + boolean changeThisPrimaryUserId = (changeAnyPrimaryUserId && changePrimaryUserId.equals(userId.user_id())); + boolean revokeThisUserId = (mSkpBuilder.getMutableRevokeUserIds().contains(userId.user_id())); // only if primary user id will be changed // (this is not triggered if the user id is currently the primary one) @@ -114,7 +144,7 @@ public class UserIdsAdapter extends UserAttributesAdapter { if (isRevoked) { // set revocation icon (can this even be primary?) - KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.REVOKED, R.color.key_flag_gray); + KeyFormattingUtils.setStatusImage(context, vVerified, null, State.REVOKED, R.color.key_flag_gray); // disable revoked user ids vName.setEnabled(false); @@ -133,24 +163,25 @@ public class UserIdsAdapter extends UserAttributesAdapter { vAddress.setTypeface(null, Typeface.NORMAL); } - int isVerified = cursor.getInt(INDEX_VERIFIED); + int isVerified = getIsVerified(position); switch (isVerified) { case Certs.VERIFIED_SECRET: - KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR); + KeyFormattingUtils.setStatusImage(context, vVerified, null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR); break; case Certs.VERIFIED_SELF: - KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR); + KeyFormattingUtils.setStatusImage(context, vVerified, null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR); break; default: - KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR); + KeyFormattingUtils.setStatusImage(context, vVerified, null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR); break; } } + + return view; } public boolean getIsRevokedPending(int position) { - mCursor.moveToPosition(position); - String userId = mCursor.getString(INDEX_USER_ID); + String userId = getUserId(position); boolean isRevokedPending = false; if (mSkpBuilder != null) { @@ -177,8 +208,15 @@ public class UserIdsAdapter extends UserAttributesAdapter { mSkpBuilder = saveKeyringParcel; } - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - return mInflater.inflate(R.layout.view_key_adv_user_id_item, null); + public String getUserId(int position) { + return data.get(position).user_id(); + } + + public boolean getIsRevoked(int position) { + return data.get(position).is_revoked(); + } + + public int getIsVerified(int position) { + return data.get(position).verified(); } } diff --git a/OpenKeychain/src/main/res/layout/edit_key_fragment.xml b/OpenKeychain/src/main/res/layout/edit_key_fragment.xml index 84686b2ad..10bb4566f 100644 --- a/OpenKeychain/src/main/res/layout/edit_key_fragment.xml +++ b/OpenKeychain/src/main/res/layout/edit_key_fragment.xml @@ -40,16 +40,6 @@ android:text="@string/section_user_ids" android:layout_weight="1" /> - - - - - - - -