diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/livedata/KeyInfoInteractor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/livedata/KeyInfoInteractor.java
deleted file mode 100644
index 173e58ac5..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/livedata/KeyInfoInteractor.java
+++ /dev/null
@@ -1,145 +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.livedata;
-
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.support.annotation.Nullable;
-
-import com.google.auto.value.AutoValue;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
-import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
-import org.sufficientlysecure.keychain.util.DatabaseUtil;
-
-
-public class KeyInfoInteractor {
- // These are the rows that we will retrieve.
- private String[] QUERY_PROJECTION = new String[]{
- KeyRings._ID,
- KeyRings.MASTER_KEY_ID,
- KeyRings.CREATION,
- KeyRings.HAS_ENCRYPT,
- KeyRings.HAS_AUTHENTICATE_SECRET,
- KeyRings.HAS_ANY_SECRET,
- KeyRings.VERIFIED,
- KeyRings.NAME,
- KeyRings.EMAIL,
- KeyRings.COMMENT,
- KeyRings.IS_EXPIRED,
- KeyRings.IS_REVOKED,
- };
- private static final int INDEX_MASTER_KEY_ID = 1;
- private static final int INDEX_CREATION = 2;
- private static final int INDEX_HAS_ENCRYPT = 3;
- private static final int INDEX_HAS_AUTHENTICATE = 4;
- private static final int INDEX_HAS_ANY_SECRET = 5;
- private static final int INDEX_VERIFIED = 6;
- private static final int INDEX_NAME = 7;
- private static final int INDEX_EMAIL = 8;
- private static final int INDEX_COMMENT = 9;
-
- private static final String QUERY_WHERE_ALL = Tables.KEYS + "." + KeyRings.IS_REVOKED +
- " = 0 AND " + KeyRings.IS_EXPIRED + " = 0";
- private static final String QUERY_WHERE_SECRET = Tables.KEYS + "." + KeyRings.IS_REVOKED +
- " = 0 AND " + KeyRings.IS_EXPIRED + " = 0" + " AND " + KeyRings.HAS_ANY_SECRET + " != 0";
- private static final String QUERY_ORDER = Tables.KEYS + "." + KeyRings.CREATION + " DESC";
-
- private final ContentResolver contentResolver;
-
-
- public KeyInfoInteractor(ContentResolver contentResolver) {
- this.contentResolver = contentResolver;
- }
-
- public List loadKeyInfo(KeySelector keySelector) {
- ArrayList keyInfos = new ArrayList<>();
- Cursor cursor;
-
- String selection = keySelector.isOnlySecret() ? QUERY_WHERE_SECRET : QUERY_WHERE_ALL;
- String additionalSelection = keySelector.getSelection();
-
- selection = DatabaseUtil.concatenateWhere(selection, additionalSelection);
- cursor = contentResolver.query(keySelector.getKeyRingUri(), QUERY_PROJECTION, selection, null, QUERY_ORDER);
-
- if (cursor == null) {
- return null;
- }
-
- while (cursor.moveToNext()) {
- KeyInfo keyInfo = KeyInfo.fromCursor(cursor);
- keyInfos.add(keyInfo);
- }
-
- return Collections.unmodifiableList(keyInfos);
- }
-
- @AutoValue
- public abstract static class KeyInfo {
- public abstract long getMasterKeyId();
- public abstract long getCreationDate();
- public abstract boolean getHasEncrypt();
- public abstract boolean getHasAuthenticate();
- public abstract boolean getHasAnySecret();
- public abstract boolean getIsVerified();
-
- @Nullable
- public abstract String getName();
- @Nullable
- public abstract String getEmail();
- @Nullable
- public abstract String getComment();
-
- static KeyInfo fromCursor(Cursor cursor) {
- long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);
- long creationDate = cursor.getLong(INDEX_CREATION) * 1000L;
- boolean hasEncrypt = cursor.getInt(INDEX_HAS_ENCRYPT) != 0;
- boolean hasAuthenticate = cursor.getInt(INDEX_HAS_AUTHENTICATE) != 0;
- boolean hasAnySecret = cursor.getInt(INDEX_HAS_ANY_SECRET) != 0;
- boolean isVerified = cursor.getInt(INDEX_VERIFIED) == 2;
-
- String name = cursor.getString(INDEX_NAME);
- String email = cursor.getString(INDEX_EMAIL);
- String comment = cursor.getString(INDEX_COMMENT);
-
- return new AutoValue_KeyInfoInteractor_KeyInfo(
- masterKeyId, creationDate, hasEncrypt, hasAuthenticate, hasAnySecret, isVerified, name, email, comment);
- }
- }
-
- @AutoValue
- public abstract static class KeySelector {
- public abstract Uri getKeyRingUri();
- @Nullable
- public abstract String getSelection();
- public abstract boolean isOnlySecret();
-
- public static KeySelector create(Uri keyRingUri, String selection) {
- return new AutoValue_KeyInfoInteractor_KeySelector(keyRingUri, selection, false);
- }
-
- public static KeySelector createOnlySecret(Uri keyRingUri, String selection) {
- return new AutoValue_KeyInfoInteractor_KeySelector(keyRingUri, selection, true);
- }
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/livedata/KeyInfoLiveData.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/livedata/KeyInfoLiveData.java
deleted file mode 100644
index 502ab2f20..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/livedata/KeyInfoLiveData.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.sufficientlysecure.keychain.livedata;
-
-
-import java.util.List;
-
-import android.content.ContentResolver;
-import android.content.Context;
-
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeyInfo;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeySelector;
-import org.sufficientlysecure.keychain.ui.keyview.loader.AsyncTaskLiveData;
-
-
-public class KeyInfoLiveData extends AsyncTaskLiveData> {
- private final KeyInfoInteractor keyInfoInteractor;
-
- private KeySelector keySelector;
-
- public KeyInfoLiveData(Context context, ContentResolver contentResolver) {
- super(context, null);
-
- this.keyInfoInteractor = new KeyInfoInteractor(contentResolver);
- }
-
- public void setKeySelector(KeySelector keySelector) {
- this.keySelector = keySelector;
-
- updateDataInBackground();
- }
-
- @Override
- protected List asyncLoadData() {
- if (keySelector == null) {
- return null;
- }
- return keyInfoInteractor.loadKeyInfo(keySelector);
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/model/SubKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/model/SubKey.java
index 0f5463810..b834bcdb2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/model/SubKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/model/SubKey.java
@@ -15,8 +15,8 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
public abstract class SubKey implements KeysModel {
public static final Factory FACTORY =
new Factory<>(AutoValue_SubKey::new, CustomColumnAdapters.SECRET_KEY_TYPE_ADAPTER);
- public static final SelectAllUnifiedKeyInfoMapper UNIFIED_KEY_INFO_MAPPER =
- FACTORY.selectAllUnifiedKeyInfoMapper(AutoValue_SubKey_UnifiedKeyInfo::new);
+ public static final UnifiedKeyViewMapper UNIFIED_KEY_INFO_MAPPER =
+ FACTORY.selectUnifiedKeyInfoByMasterKeyIdMapper(AutoValue_SubKey_UnifiedKeyInfo::new);
public static Mapper SUBKEY_MAPPER = new Mapper<>(FACTORY);
public static RowMapper SKT_MAPPER = FACTORY.selectSecretKeyTypeMapper();
@@ -25,7 +25,7 @@ public abstract class SubKey implements KeysModel {
}
@AutoValue
- public static abstract class UnifiedKeyInfo implements SelectAllUnifiedKeyInfoModel {
+ public static abstract class UnifiedKeyInfo implements KeysModel.UnifiedKeyViewModel {
private List autocryptPackageNames;
public boolean is_expired() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeyRepository.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeyRepository.java
index a88937e11..cab949179 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeyRepository.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeyRepository.java
@@ -264,11 +264,21 @@ public class KeyRepository extends AbstractDao {
}
}
+ public List getUnifiedKeyInfosByMailAddress(String mailAddress) {
+ SqlDelightQuery query = SubKey.FACTORY.selectUnifiedKeyInfoSearchMailAddress('%' + mailAddress + '%');
+ return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map);
+ }
+
public List getAllUnifiedKeyInfo() {
SqlDelightQuery query = SubKey.FACTORY.selectAllUnifiedKeyInfo();
return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map);
}
+ public List getAllUnifiedKeyInfoWithSecret() {
+ SqlDelightQuery query = SubKey.FACTORY.selectAllUnifiedKeyInfoWithSecret();
+ return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map);
+ }
+
public List getUserIds(long... masterKeyIds) {
SqlDelightQuery query = UserPacket.FACTORY.selectUserIdsByMasterKeyId(masterKeyIds);
return mapAllRows(query, UserPacket.USER_ID_MAPPER::map);
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 3eced678e..7085ec839 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -100,9 +100,7 @@ public class KeychainContract {
public static final String PATH_UNIFIED = "unified";
public static final String PATH_FIND = "find";
- public static final String PATH_BY_EMAIL = "email";
public static final String PATH_BY_SUBKEY = "subkey";
- public static final String PATH_BY_USER_ID = "user_id";
public static final String PATH_PUBLIC = "public";
public static final String PATH_USER_IDS = "user_ids";
@@ -140,16 +138,6 @@ public class KeychainContract {
.appendPath(PATH_UNIFIED).build();
}
- public static Uri buildUnifiedKeyRingsFindByEmailUri(String email) {
- return CONTENT_URI.buildUpon().appendPath(PATH_FIND)
- .appendPath(PATH_BY_EMAIL).appendPath(email).build();
- }
-
- public static Uri buildUnifiedKeyRingsFindByUserIdUri(String query) {
- return CONTENT_URI.buildUpon().appendPath(PATH_FIND)
- .appendPath(PATH_BY_USER_ID).appendPath(query).build();
- }
-
public static Uri buildUnifiedKeyRingsFindBySubkeyUri(long subkey) {
return CONTENT_URI.buildUpon().appendPath(PATH_FIND)
.appendPath(PATH_BY_SUBKEY).appendPath(Long.toString(subkey)).build();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 2363bffe9..62e643b7d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.KeyMetadataModel;
import org.sufficientlysecure.keychain.KeyRingsPublicModel;
import org.sufficientlysecure.keychain.KeySignaturesModel;
+import org.sufficientlysecure.keychain.KeysModel;
import org.sufficientlysecure.keychain.UserPacketsModel;
import org.sufficientlysecure.keychain.model.ApiApp;
import org.sufficientlysecure.keychain.model.Certification;
@@ -65,7 +66,7 @@ import timber.log.Timber;
*/
public class KeychainDatabase {
private static final String DATABASE_NAME = "openkeychain.db";
- private static final int DATABASE_VERSION = 28;
+ private static final int DATABASE_VERSION = 29;
private final SupportSQLiteOpenHelper supportSQLiteOpenHelper;
private Context context;
@@ -205,6 +206,7 @@ public class KeychainDatabase {
db.execSQL(CREATE_OVERRIDDEN_WARNINGS);
db.execSQL(AutocryptPeersModel.CREATE_TABLE);
db.execSQL(ApiAppsModel.CREATE_TABLE);
+ db.execSQL(KeysModel.UNIFIEDKEYVIEW);
db.execSQL("CREATE INDEX keys_by_rank ON keys (" + KeysColumns.RANK + ", " + KeysColumns.MASTER_KEY_ID + ");");
db.execSQL("CREATE INDEX uids_by_rank ON user_packets (" + UserPacketsColumns.RANK + ", "
@@ -429,16 +431,22 @@ public class KeychainDatabase {
}
}
- case 26: {
+ case 26:
migrateUpdatedKeysToKeyMetadataTable(db);
- }
- case 27: {
+ case 27:
renameApiAutocryptPeersTable(db);
- }
+
+ case 28:
+ recreateUnifiedKeyView(db);
}
}
+ private void recreateUnifiedKeyView(SupportSQLiteDatabase db) {
+ db.execSQL("DROP VIEW IF EXISTS " + KeysModel.UNIFIEDKEYVIEW_VIEW_NAME);
+ db.execSQL(KeysModel.UNIFIEDKEYVIEW);
+ }
+
private void migrateSecretKeysFromDbToLocalStorage(SupportSQLiteDatabase db) throws IOException {
LocalSecretKeyStorage localSecretKeyStorage = LocalSecretKeyStorage.getInstance(context);
Cursor cursor = db.query("SELECT master_key_id, key_ring_data FROM keyrings_secret");
@@ -456,7 +464,6 @@ public class KeychainDatabase {
private void migrateUpdatedKeysToKeyMetadataTable(SupportSQLiteDatabase db) {
try {
db.execSQL("ALTER TABLE updated_keys RENAME TO key_metadata;");
- db.execSQL("UPDATE key_metadata SET last_updated = last_updated * 1000;");
} catch (SQLException e) {
if (Constants.DEBUG) {
Timber.e(e, "Ignoring migration exception, this probably happened before");
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 1e4534125..ebc997f7a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -28,7 +28,6 @@ import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
-import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
@@ -62,9 +61,7 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
private static final int KEY_RING_PUBLIC = 203;
private static final int KEY_RING_CERTS = 205;
- private static final int KEY_RINGS_FIND_BY_EMAIL = 400;
private static final int KEY_RINGS_FIND_BY_SUBKEY = 401;
- private static final int KEY_RINGS_FIND_BY_USER_ID = 402;
private static final int KEY_SIGNATURES = 700;
@@ -94,19 +91,12 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
/*
* find by criteria other than master key id
*
- * key_rings/find/email/_
* key_rings/find/subkey/_
*
*/
- matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
- + KeychainContract.PATH_FIND + "/" + KeychainContract.PATH_BY_EMAIL + "/*",
- KEY_RINGS_FIND_BY_EMAIL);
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
+ KeychainContract.PATH_FIND + "/" + KeychainContract.PATH_BY_SUBKEY + "/*",
KEY_RINGS_FIND_BY_SUBKEY);
- matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
- + KeychainContract.PATH_FIND + "/" + KeychainContract.PATH_BY_USER_ID + "/*",
- KEY_RINGS_FIND_BY_USER_ID);
/*
* list key_ring specifics
@@ -185,9 +175,7 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
switch (match) {
case KEY_RING_UNIFIED:
case KEY_RINGS_UNIFIED:
- case KEY_RINGS_FIND_BY_EMAIL:
- case KEY_RINGS_FIND_BY_SUBKEY:
- case KEY_RINGS_FIND_BY_USER_ID: {
+ case KEY_RINGS_FIND_BY_SUBKEY: {
HashMap projectionMap = new HashMap<>();
projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id");
projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
@@ -351,42 +339,6 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
}
break;
}
- case KEY_RINGS_FIND_BY_EMAIL:
- case KEY_RINGS_FIND_BY_USER_ID: {
- String chunks[] = uri.getLastPathSegment().split(" *, *");
- boolean gotCondition = false;
- String emailWhere = "";
- // JAVA ♥
- for (int i = 0; i < chunks.length; ++i) {
- if (chunks[i].length() == 0) {
- continue;
- }
- if (i != 0) {
- emailWhere += " OR ";
- }
- if (match == KEY_RINGS_FIND_BY_EMAIL) {
- emailWhere += "tmp." + UserPackets.EMAIL + " LIKE "
- + DatabaseUtils.sqlEscapeString(chunks[i]);
- } else {
- emailWhere += "tmp." + UserPackets.USER_ID + " LIKE "
- + DatabaseUtils.sqlEscapeString("%" + chunks[i] + "%");
- }
- gotCondition = true;
- }
- if(gotCondition) {
- qb.appendWhere(" AND EXISTS ("
- + " SELECT 1 FROM " + Tables.USER_PACKETS + " AS tmp"
- + " WHERE tmp." + UserPackets.MASTER_KEY_ID
- + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID
- + " AND (" + emailWhere + ")"
- + ")");
- } else {
- // TODO better way to do this?
- Timber.e("Malformed find by email query!");
- qb.appendWhere(" AND 0");
- }
- break;
- }
}
if (TextUtils.isEmpty(sortOrder)) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPendingIntentFactory.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPendingIntentFactory.java
index 7de402e69..bf5a1c3a1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPendingIntentFactory.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPendingIntentFactory.java
@@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.remote;
+
import java.util.ArrayList;
import android.app.PendingIntent;
@@ -25,7 +26,6 @@ import android.content.Intent;
import android.os.Build;
import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.remote.ui.RemoteBackupActivity;
import org.sufficientlysecure.keychain.remote.ui.RemoteDisplayTransferCodeActivity;
import org.sufficientlysecure.keychain.remote.ui.RemoteErrorActivity;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SecurityProblemPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SecurityProblemPresenter.java
index 3b8741458..b7109b1cf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SecurityProblemPresenter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SecurityProblemPresenter.java
@@ -207,9 +207,9 @@ class SecurityProblemPresenter {
}
void onClickViewKey() {
- Intent viewKeyIntent = new Intent(context, ViewKeyActivity.class);
- viewKeyIntent.setData(KeyRings.buildGenericKeyRingUri(viewKeyMasterKeyId));
- context.startActivity(viewKeyIntent);
+ Intent intent = new Intent(context, ViewKeyActivity.class);
+ intent.putExtra(ViewKeyActivity.EXTRA_MASTER_KEY_ID, viewKeyMasterKeyId);
+ context.startActivity(intent);
}
void onClickOverride() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/KeyInfoLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/KeyInfoLoader.java
deleted file mode 100644
index 31c87ac58..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/KeyInfoLoader.java
+++ /dev/null
@@ -1,76 +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.remote.ui.dialog;
-
-
-import java.util.List;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.support.v4.content.AsyncTaskLoader;
-
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeyInfo;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeySelector;
-
-
-public class KeyInfoLoader extends AsyncTaskLoader> {
- private final KeySelector keySelector;
-
- private List cachedResult;
- private KeyInfoInteractor keyInfoInteractor;
-
- KeyInfoLoader(Context context, ContentResolver contentResolver, KeySelector keySelector) {
- super(context);
-
- this.keySelector = keySelector;
- this.keyInfoInteractor = new KeyInfoInteractor(contentResolver);
- }
-
- @Override
- public List loadInBackground() {
- return keyInfoInteractor.loadKeyInfo(keySelector);
- }
-
- @Override
- public void deliverResult(List keySubkeyStatus) {
- cachedResult = keySubkeyStatus;
-
- if (isStarted()) {
- super.deliverResult(keySubkeyStatus);
- }
- }
-
- @Override
- protected void onStartLoading() {
- if (cachedResult != null) {
- deliverResult(cachedResult);
- }
-
- if (takeContentChanged() || cachedResult == null) {
- forceLoad();
- }
- }
-
- @Override
- protected void onStopLoading() {
- super.onStopLoading();
-
- cachedResult = null;
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteDeduplicateActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteDeduplicateActivity.java
index adb079821..1b62788c8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteDeduplicateActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteDeduplicateActivity.java
@@ -23,6 +23,9 @@ import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
+import android.arch.lifecycle.LiveData;
+import android.arch.lifecycle.ViewModel;
+import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -42,7 +45,6 @@ import android.text.format.DateUtils;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
@@ -50,8 +52,10 @@ import android.widget.TextView;
import com.mikepenz.materialdrawer.util.KeyboardUtil;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.livedata.GenericLiveData;
+import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
+import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.remote.ui.RemoteSecurityTokenOperationActivity;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeyInfo;
import org.sufficientlysecure.keychain.remote.ui.dialog.RemoteDeduplicatePresenter.RemoteDeduplicateView;
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
@@ -63,8 +67,6 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
public static final String EXTRA_PACKAGE_NAME = "package_name";
public static final String EXTRA_DUPLICATE_EMAILS = "duplicate_emails";
- public static final int LOADER_ID_KEYS = 0;
-
private RemoteDeduplicatePresenter presenter;
@@ -73,7 +75,7 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- presenter = new RemoteDeduplicatePresenter(getBaseContext(), LOADER_ID_KEYS);
+ presenter = new RemoteDeduplicatePresenter(getBaseContext(), this);
KeyboardUtil.hideKeyboard(this);
@@ -92,8 +94,43 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
String duplicateAddress = dupAddresses.get(0);
String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
- presenter.setupFromIntentData(packageName, duplicateAddress);
- presenter.startLoaders(getSupportLoaderManager());
+ DeduplicateViewModel viewModel = ViewModelProviders.of(this).get(DeduplicateViewModel.class);
+ viewModel.setDuplicateAddress(duplicateAddress);
+ viewModel.setPackageName(packageName);
+
+ presenter.setupFromViewModel(viewModel);
+ }
+
+ public static class DeduplicateViewModel extends ViewModel {
+ private String duplicateAddress;
+ private LiveData> keyInfoLiveData;
+ private String packageName;
+
+ public LiveData> getKeyInfoLiveData(Context context) {
+ if (keyInfoLiveData == null) {
+ keyInfoLiveData = new GenericLiveData<>(context, null, () -> {
+ KeyRepository keyRepository = KeyRepository.create(context);
+ return keyRepository.getUnifiedKeyInfosByMailAddress(duplicateAddress);
+ });
+ }
+ return keyInfoLiveData;
+ }
+
+ public void setDuplicateAddress(String duplicateAddress) {
+ this.duplicateAddress = duplicateAddress;
+ }
+
+ public void setPackageName(String packageName) {
+ this.packageName = packageName;
+ }
+
+ public String getPackageName() {
+ return packageName;
+ }
+
+ public String getDuplicateAddress() {
+ return duplicateAddress;
+ }
}
public static class RemoteDeduplicateDialogFragment extends DialogFragment {
@@ -107,7 +144,7 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Activity activity = getActivity();
+ Activity activity = requireActivity();
ContextThemeWrapper theme = ThemeChanger.getDialogThemeWrapper(activity);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme);
@@ -135,7 +172,7 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- presenter = ((RemoteDeduplicateActivity) getActivity()).presenter;
+ presenter = ((RemoteDeduplicateActivity) requireActivity()).presenter;
presenter.setView(mvpView);
}
@@ -202,7 +239,7 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
}
@Override
- public void setKeyListData(List data) {
+ public void setKeyListData(List data) {
keyChoiceAdapter.setData(data);
}
@@ -219,34 +256,17 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
}
private void setupListenersForPresenter() {
- buttonSelect.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- presenter.onClickSelect();
- }
- });
-
- buttonCancel.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- presenter.onClickCancel();
- }
- });
-
+ buttonSelect.setOnClickListener(view -> presenter.onClickSelect());
+ buttonCancel.setOnClickListener(view -> presenter.onClickCancel());
keyChoiceList.addOnItemTouchListener(new RecyclerItemClickListener(getContext(),
- new RecyclerItemClickListener.OnItemClickListener() {
- @Override
- public void onItemClick(View view, int position) {
- presenter.onKeyItemClick(position);
- }
- }));
+ (view, position) -> presenter.onKeyItemClick(position)));
}
}
private static class KeyChoiceAdapter extends Adapter {
private final LayoutInflater layoutInflater;
private final Resources resources;
- private List data;
+ private List data;
private Drawable iconUnselected;
private Drawable iconSelected;
private Integer activeItem;
@@ -256,15 +276,16 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
this.resources = resources;
}
+ @NonNull
@Override
- public KeyChoiceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ public KeyChoiceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View keyChoiceItemView = layoutInflater.inflate(R.layout.duplicate_key_item, parent, false);
return new KeyChoiceViewHolder(keyChoiceItemView);
}
@Override
- public void onBindViewHolder(KeyChoiceViewHolder holder, int position) {
- KeyInfo keyInfo = data.get(position);
+ public void onBindViewHolder(@NonNull KeyChoiceViewHolder holder, int position) {
+ UnifiedKeyInfo keyInfo = data.get(position);
Drawable icon = (activeItem != null && position == activeItem) ? iconSelected : iconUnselected;
holder.bind(keyInfo, icon);
}
@@ -274,7 +295,7 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
return data != null ? data.size() : 0;
}
- public void setData(List data) {
+ public void setData(List data) {
this.data = data;
notifyDataSetChanged();
}
@@ -319,11 +340,11 @@ public class RemoteDeduplicateActivity extends FragmentActivity {
vIcon = itemView.findViewById(R.id.key_list_item_icon);
}
- void bind(KeyInfo keyInfo, Drawable selectionIcon) {
- vName.setText(keyInfo.getName());
+ void bind(UnifiedKeyInfo keyInfo, Drawable selectionIcon) {
+ vName.setText(keyInfo.name());
Context context = vCreation.getContext();
- String dateTime = DateUtils.formatDateTime(context, keyInfo.getCreationDate(),
+ String dateTime = DateUtils.formatDateTime(context, keyInfo.creation(),
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME |
DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH);
vCreation.setText(context.getString(R.string.label_key_created, dateTime));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteDeduplicatePresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteDeduplicatePresenter.java
index a3ecadbe1..fd8a7ebae 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteDeduplicatePresenter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteDeduplicatePresenter.java
@@ -20,62 +20,59 @@ package org.sufficientlysecure.keychain.remote.ui.dialog;
import java.util.List;
+import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.app.LoaderManager.LoaderCallbacks;
-import android.support.v4.content.Loader;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeyInfo;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeySelector;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.remote.AutocryptInteractor;
+import org.sufficientlysecure.keychain.remote.ui.dialog.RemoteDeduplicateActivity.DeduplicateViewModel;
import timber.log.Timber;
-class RemoteDeduplicatePresenter implements LoaderCallbacks> {
+class RemoteDeduplicatePresenter {
private final PackageManager packageManager;
private final Context context;
- private final int loaderId;
+ private final LifecycleOwner lifecycleOwner;
private AutocryptInteractor autocryptInteractor;
- private String duplicateAddress;
+ private DeduplicateViewModel viewModel;
private RemoteDeduplicateView view;
private Integer selectedItem;
- private List keyInfoData;
+ private List keyInfoData;
- RemoteDeduplicatePresenter(Context context, int loaderId) {
+ RemoteDeduplicatePresenter(Context context, LifecycleOwner lifecycleOwner) {
this.context = context;
+ this.lifecycleOwner = lifecycleOwner;
packageManager = context.getPackageManager();
-
- this.loaderId = loaderId;
}
public void setView(RemoteDeduplicateView view) {
this.view = view;
}
- void setupFromIntentData(String packageName, String duplicateAddress) {
+ void setupFromViewModel(DeduplicateViewModel viewModel) {
+ this.viewModel = viewModel;
+ this.autocryptInteractor = AutocryptInteractor.getInstance(context, viewModel.getPackageName());
+
try {
- setPackageInfo(packageName);
+ setPackageInfo(viewModel.getPackageName());
} catch (NameNotFoundException e) {
Timber.e("Unable to find info of calling app!");
view.finishAsCancelled();
return;
}
- this.autocryptInteractor = AutocryptInteractor.getInstance(context, packageName);
+ view.setAddressText(viewModel.getDuplicateAddress());
- this.duplicateAddress = duplicateAddress;
- view.setAddressText(duplicateAddress);
+ viewModel.getKeyInfoLiveData(context).observe(lifecycleOwner, this::onLoadKeyInfos);
}
private void setPackageInfo(String packageName) throws NameNotFoundException {
@@ -85,31 +82,11 @@ class RemoteDeduplicatePresenter implements LoaderCallbacks> {
view.setTitleClientIcon(appIcon);
}
- void startLoaders(LoaderManager loaderManager) {
- loaderManager.restartLoader(loaderId, null, this);
- }
-
- @Override
- public Loader> onCreateLoader(int id, Bundle args) {
- KeySelector keySelector = KeySelector.create(
- KeyRings.buildUnifiedKeyRingsFindByEmailUri(duplicateAddress), null);
-
- return new KeyInfoLoader(context, context.getContentResolver(), keySelector);
- }
-
- @Override
- public void onLoadFinished(Loader> loader, List data) {
+ private void onLoadKeyInfos(List data) {
this.keyInfoData = data;
view.setKeyListData(data);
}
- @Override
- public void onLoaderReset(Loader loader) {
- if (view != null) {
- view.setKeyListData(null);
- }
- }
-
void onClickSelect() {
if (keyInfoData == null) {
Timber.e("got click on select with no data…?");
@@ -120,8 +97,8 @@ class RemoteDeduplicatePresenter implements LoaderCallbacks> {
return;
}
- long masterKeyId = keyInfoData.get(selectedItem).getMasterKeyId();
- autocryptInteractor.updateKeyGossipFromDedup(duplicateAddress, masterKeyId);
+ long masterKeyId = keyInfoData.get(selectedItem).master_key_id();
+ autocryptInteractor.updateKeyGossipFromDedup(viewModel.getDuplicateAddress(), masterKeyId);
view.finish();
}
@@ -151,7 +128,7 @@ class RemoteDeduplicatePresenter implements LoaderCallbacks> {
void setAddressText(String text);
void setTitleClientIcon(Drawable drawable);
- void setKeyListData(List data);
+ void setKeyListData(List data);
void setActiveItem(Integer position);
void setEnableSelectButton(boolean enabled);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectAuthenticationKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectAuthenticationKeyActivity.java
index 9c722885a..eecb21837 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectAuthenticationKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectAuthenticationKeyActivity.java
@@ -23,6 +23,9 @@ import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
+import android.arch.lifecycle.LiveData;
+import android.arch.lifecycle.ViewModel;
+import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -42,7 +45,6 @@ import android.text.format.DateUtils;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
@@ -51,8 +53,10 @@ import android.widget.TextView;
import com.mikepenz.materialdrawer.util.KeyboardUtil;
import org.openintents.ssh.authentication.SshAuthenticationApi;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeyInfo;
+import org.sufficientlysecure.keychain.livedata.GenericLiveData;
+import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.provider.ApiAppDao;
+import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.remote.ui.RemoteSecurityTokenOperationActivity;
import org.sufficientlysecure.keychain.remote.ui.dialog.RemoteSelectAuthenticationKeyPresenter.RemoteSelectAuthenticationKeyView;
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
@@ -64,8 +68,6 @@ import org.sufficientlysecure.keychain.ui.util.recyclerview.RecyclerItemClickLis
public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
public static final String EXTRA_PACKAGE_NAME = "package_name";
- public static final int LOADER_ID_KEYS = 0;
-
private RemoteSelectAuthenticationKeyPresenter presenter;
private String packageName;
@@ -75,7 +77,7 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- presenter = new RemoteSelectAuthenticationKeyPresenter(getBaseContext(), LOADER_ID_KEYS);
+ presenter = new RemoteSelectAuthenticationKeyPresenter(getBaseContext(), this);
KeyboardUtil.hideKeyboard(this);
@@ -92,8 +94,33 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
Intent intent = getIntent();
packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
- presenter.setupFromIntentData(packageName);
- presenter.startLoaders(getSupportLoaderManager());
+ SelectAuthKeyViewModel viewModel = ViewModelProviders.of(this).get(SelectAuthKeyViewModel.class);
+ viewModel.setPackageName(packageName);
+
+ presenter.setupFromViewModel(viewModel);
+ }
+
+ public static class SelectAuthKeyViewModel extends ViewModel {
+ private LiveData> keyInfoLiveData;
+ private String packageName;
+
+ public LiveData> getKeyInfoLiveData(Context context) {
+ if (keyInfoLiveData == null) {
+ keyInfoLiveData = new GenericLiveData<>(context, null, () -> {
+ KeyRepository keyRepository = KeyRepository.create(context);
+ return keyRepository.getAllUnifiedKeyInfoWithSecret();
+ });
+ }
+ return keyInfoLiveData;
+ }
+
+ public void setPackageName(String packageName) {
+ this.packageName = packageName;
+ }
+
+ public String getPackageName() {
+ return packageName;
+ }
}
private void onKeySelected(long masterKeyId) {
@@ -121,7 +148,7 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Activity activity = getActivity();
+ Activity activity = requireActivity();
ContextThemeWrapper theme = ThemeChanger.getDialogThemeWrapper(activity);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme);
@@ -149,7 +176,7 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- presenter = ((RemoteSelectAuthenticationKeyActivity) getActivity()).presenter;
+ presenter = ((RemoteSelectAuthenticationKeyActivity) requireActivity()).presenter;
presenter.setView(mvpView);
}
@@ -207,7 +234,7 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
}
@Override
- public void setKeyListData(List data) {
+ public void setKeyListData(List data) {
keyChoiceAdapter.setData(data);
}
@@ -224,34 +251,17 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
}
private void setupListenersForPresenter() {
- buttonSelect.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- presenter.onClickSelect();
- }
- });
-
- buttonCancel.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- presenter.onClickCancel();
- }
- });
-
+ buttonSelect.setOnClickListener(view -> presenter.onClickSelect());
+ buttonCancel.setOnClickListener(view -> presenter.onClickCancel());
keyChoiceList.addOnItemTouchListener(new RecyclerItemClickListener(getContext(),
- new RecyclerItemClickListener.OnItemClickListener() {
- @Override
- public void onItemClick(View view, int position) {
- presenter.onKeyItemClick(position);
- }
- }));
+ (view, position) -> presenter.onKeyItemClick(position)));
}
}
private static class KeyChoiceAdapter extends Adapter {
private final LayoutInflater layoutInflater;
private final Resources resources;
- private List data;
+ private List data;
private Drawable iconUnselected;
private Drawable iconSelected;
private Integer activeItem;
@@ -261,15 +271,16 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
this.resources = resources;
}
+ @NonNull
@Override
- public KeyChoiceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ public KeyChoiceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View keyChoiceItemView = layoutInflater.inflate(R.layout.authentication_key_item, parent, false);
return new KeyChoiceViewHolder(keyChoiceItemView);
}
@Override
- public void onBindViewHolder(KeyChoiceViewHolder holder, int position) {
- KeyInfo keyInfo = data.get(position);
+ public void onBindViewHolder(@NonNull KeyChoiceViewHolder holder, int position) {
+ UnifiedKeyInfo keyInfo = data.get(position);
Drawable icon = (activeItem != null && position == activeItem) ? iconSelected : iconUnselected;
holder.bind(keyInfo, icon);
}
@@ -279,7 +290,7 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
return data != null ? data.size() : 0;
}
- public void setData(List data) {
+ public void setData(List data) {
this.data = data;
notifyDataSetChanged();
}
@@ -324,11 +335,11 @@ public class RemoteSelectAuthenticationKeyActivity extends FragmentActivity {
vIcon = itemView.findViewById(R.id.key_list_item_icon);
}
- void bind(KeyInfo keyInfo, Drawable selectionIcon) {
- vName.setText(keyInfo.getName());
+ void bind(UnifiedKeyInfo keyInfo, Drawable selectionIcon) {
+ vName.setText(keyInfo.name());
Context context = vCreation.getContext();
- String dateTime = DateUtils.formatDateTime(context, keyInfo.getCreationDate(),
+ String dateTime = DateUtils.formatDateTime(context, keyInfo.creation(),
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME |
DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH);
vCreation.setText(context.getString(R.string.label_key_created, dateTime));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectAuthenticationKeyPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectAuthenticationKeyPresenter.java
index c9e0f70b0..24f93520a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectAuthenticationKeyPresenter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectAuthenticationKeyPresenter.java
@@ -20,52 +20,49 @@ package org.sufficientlysecure.keychain.remote.ui.dialog;
import java.util.List;
+import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.app.LoaderManager.LoaderCallbacks;
-import android.support.v4.content.Loader;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeyInfo;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeySelector;
+import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
+import org.sufficientlysecure.keychain.remote.ui.dialog.RemoteSelectAuthenticationKeyActivity.SelectAuthKeyViewModel;
import timber.log.Timber;
-class RemoteSelectAuthenticationKeyPresenter implements LoaderCallbacks> {
+class RemoteSelectAuthenticationKeyPresenter {
private final PackageManager packageManager;
+ private final LifecycleOwner lifecycleOwner;
private final Context context;
- private final int loaderId;
private RemoteSelectAuthenticationKeyView view;
private Integer selectedItem;
- private List keyInfoData;
+ private List keyInfoData;
- RemoteSelectAuthenticationKeyPresenter(Context context, int loaderId) {
+ RemoteSelectAuthenticationKeyPresenter(Context context, LifecycleOwner lifecycleOwner) {
this.context = context;
+ this.lifecycleOwner = lifecycleOwner;
packageManager = context.getPackageManager();
-
- this.loaderId = loaderId;
}
public void setView(RemoteSelectAuthenticationKeyView view) {
this.view = view;
}
- void setupFromIntentData(String packageName) {
+ void setupFromViewModel(SelectAuthKeyViewModel viewModel) {
try {
- setPackageInfo(packageName);
+ setPackageInfo(viewModel.getPackageName());
} catch (NameNotFoundException e) {
Timber.e("Unable to find info of calling app!");
view.finishAsCancelled();
}
+
+ viewModel.getKeyInfoLiveData(context).observe(lifecycleOwner, this::onLoadKeyInfos);
}
private void setPackageInfo(String packageName) throws NameNotFoundException {
@@ -75,31 +72,11 @@ class RemoteSelectAuthenticationKeyPresenter implements LoaderCallbacks> onCreateLoader(int id, Bundle args) {
- String selection = KeyRings.HAS_AUTHENTICATE_SECRET + " != 0";
- KeySelector keySelector = KeySelector.create(
- KeyRings.buildUnifiedKeyRingsUri(), selection);
- return new KeyInfoLoader(context, context.getContentResolver(), keySelector);
- }
-
- @Override
- public void onLoadFinished(Loader> loader, List data) {
+ private void onLoadKeyInfos(List data) {
this.keyInfoData = data;
view.setKeyListData(data);
}
- @Override
- public void onLoaderReset(Loader loader) {
- if (view != null) {
- view.setKeyListData(null);
- }
- }
-
void onClickSelect() {
if (keyInfoData == null) {
Timber.e("got click on select with no data…?");
@@ -110,7 +87,7 @@ class RemoteSelectAuthenticationKeyPresenter implements LoaderCallbacks data);
+ void setKeyListData(List data);
void setActiveItem(Integer position);
void setEnableSelectButton(boolean enabled);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdKeyActivity.java
index fa9674e73..790a830d2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdKeyActivity.java
@@ -23,6 +23,8 @@ import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
+import android.arch.lifecycle.LiveData;
+import android.arch.lifecycle.ViewModel;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.DialogInterface;
@@ -58,8 +60,11 @@ import android.widget.Toast;
import com.mikepenz.materialdrawer.util.KeyboardUtil;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeyInfo;
+import org.sufficientlysecure.keychain.livedata.GenericLiveData;
+import org.sufficientlysecure.keychain.livedata.PgpKeyGenerationLiveData;
+import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
+import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.remote.ui.dialog.RemoteSelectIdentityKeyPresenter.RemoteSelectIdentityKeyView;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.ui.MainActivity;
@@ -89,13 +94,18 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- RemoteSelectIdViewModel viewModel =
- ViewModelProviders.of(this).get(RemoteSelectIdViewModel.class);
-
- presenter = new RemoteSelectIdentityKeyPresenter(getBaseContext(), viewModel, this);
+ presenter = new RemoteSelectIdentityKeyPresenter(getBaseContext(), this);
KeyboardUtil.hideKeyboard(this);
+ RemoteSelectIdViewModel viewModel = ViewModelProviders.of(this).get(RemoteSelectIdViewModel.class);
+
+ Intent intent = getIntent();
+ viewModel.rawUserId = intent.getStringExtra(EXTRA_USER_ID);
+ viewModel.packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
+ viewModel.packageSignature = intent.getByteArrayExtra(EXTRA_PACKAGE_SIGNATURE);
+ viewModel.clientHasAutocryptSetupMsg = intent.getBooleanExtra(EXTRA_SHOW_AUTOCRYPT_HINT, false);
+
if (savedInstanceState == null) {
RemoteSelectIdentityKeyDialogFragment frag = new RemoteSelectIdentityKeyDialogFragment();
frag.show(getSupportFragmentManager(), "requestKeyDialog");
@@ -106,13 +116,45 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
protected void onStart() {
super.onStart();
- Intent intent = getIntent();
- String userId = intent.getStringExtra(EXTRA_USER_ID);
- String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
- byte[] packageSignature = intent.getByteArrayExtra(EXTRA_PACKAGE_SIGNATURE);
- boolean showAutocryptHint = intent.getBooleanExtra(EXTRA_SHOW_AUTOCRYPT_HINT, false);
+ RemoteSelectIdViewModel viewModel = ViewModelProviders.of(this).get(RemoteSelectIdViewModel.class);
+ presenter.setupFromViewModel(viewModel);
+ }
+
+ public static class RemoteSelectIdViewModel extends ViewModel {
+ public String packageName;
+ public byte[] packageSignature;
+ public String rawUserId;
+ public boolean clientHasAutocryptSetupMsg;
+
+ public List filteredKeyInfo;
+
+ private LiveData> keyInfo;
+ private PgpKeyGenerationLiveData keyGenerationData;
+ private boolean listAllKeys;
+
+ public LiveData> getSecretUnifiedKeyInfo(Context context) {
+ if (keyInfo == null) {
+ KeyRepository keyRepository = KeyRepository.create(context);
+ keyInfo = new GenericLiveData<>(context, null, keyRepository::getAllUnifiedKeyInfoWithSecret);
+ }
+ return keyInfo;
+ }
+
+ public PgpKeyGenerationLiveData getKeyGenerationLiveData(Context context) {
+ if (keyGenerationData == null) {
+ keyGenerationData = new PgpKeyGenerationLiveData(context);
+ }
+ return keyGenerationData;
+ }
+
+ public boolean isListAllKeys() {
+ return listAllKeys;
+ }
+
+ public void setListAllKeys(boolean listAllKeys) {
+ this.listAllKeys = listAllKeys;
+ }
- presenter.setupFromIntentData(packageName, packageSignature, userId, showAutocryptHint);
}
public static class RemoteSelectIdentityKeyDialogFragment extends DialogFragment {
@@ -135,7 +177,7 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Activity activity = getActivity();
+ Activity activity = requireActivity();
ContextThemeWrapper theme = ThemeChanger.getDialogThemeWrapper(activity);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme);
@@ -177,7 +219,7 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- presenter = ((RemoteSelectIdKeyActivity) getActivity()).presenter;
+ presenter = ((RemoteSelectIdKeyActivity) requireActivity()).presenter;
presenter.setView(mvpView);
}
@@ -203,7 +245,7 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
@NonNull
private RemoteSelectIdentityKeyView createMvpView(final ViewGroup rootView, LayoutInflater layoutInflater) {
// final ImageView iconClientApp = rootView.findViewById(R.id.icon_client_app);
- final KeyChoiceAdapter keyChoiceAdapter = new KeyChoiceAdapter(layoutInflater, getResources());
+ final KeyChoiceAdapter keyChoiceAdapter = new KeyChoiceAdapter(layoutInflater);
final TextView titleText = rootView.findViewById(R.id.text_title_select_key);
final TextView addressText = rootView.findViewById(R.id.text_user_id);
final TextView autocryptHint = rootView.findViewById(R.id.key_import_autocrypt_hint);
@@ -309,7 +351,7 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
}
@Override
- public void setKeyListData(List data) {
+ public void setKeyListData(List data) {
keyChoiceAdapter.setData(data);
}
@@ -405,19 +447,18 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
private static class KeyChoiceAdapter extends Adapter {
private final LayoutInflater layoutInflater;
- private final Resources resources;
- private List data;
+ private List data;
private Drawable iconUnselected;
private Drawable iconSelected;
private Integer activeItem;
- KeyChoiceAdapter(LayoutInflater layoutInflater, Resources resources) {
+ KeyChoiceAdapter(LayoutInflater layoutInflater) {
this.layoutInflater = layoutInflater;
- this.resources = resources;
}
+ @NonNull
@Override
- public KeyChoiceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ public KeyChoiceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View keyChoiceItemView = layoutInflater.inflate(R.layout.api_select_identity_item, parent, false);
return new KeyChoiceViewHolder(keyChoiceItemView);
}
@@ -428,8 +469,8 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
}
@Override
- public void onBindViewHolder(KeyChoiceViewHolder holder, int position) {
- KeyInfo keyInfo = data.get(position);
+ public void onBindViewHolder(@NonNull KeyChoiceViewHolder holder, int position) {
+ UnifiedKeyInfo keyInfo = data.get(position);
boolean hasActiveItem = activeItem != null;
boolean isActiveItem = hasActiveItem && position == activeItem;
@@ -444,7 +485,7 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
return data != null ? data.size() : 0;
}
- public void setData(List data) {
+ public void setData(List data) {
this.data = data;
notifyDataSetChanged();
}
@@ -469,11 +510,11 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
vIcon = itemView.findViewById(R.id.key_list_item_icon);
}
- void bind(KeyInfo keyInfo, Drawable selectionIcon) {
+ void bind(UnifiedKeyInfo keyInfo, Drawable selectionIcon) {
Context context = vCreation.getContext();
- String email = keyInfo.getEmail();
- String name = keyInfo.getName();
+ String email = keyInfo.email();
+ String name = keyInfo.name();
if (email != null) {
vName.setText(context.getString(R.string.use_key, email));
} else if (name != null) {
@@ -482,7 +523,7 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity {
vName.setText(context.getString(R.string.use_key_no_name));
}
- String dateTime = DateUtils.formatDateTime(context, keyInfo.getCreationDate(),
+ String dateTime = DateUtils.formatDateTime(context, keyInfo.creation(),
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME |
DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH);
vCreation.setText(context.getString(R.string.label_key_created, dateTime));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdViewModel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdViewModel.java
deleted file mode 100644
index d287129fb..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdViewModel.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.sufficientlysecure.keychain.remote.ui.dialog;
-
-
-import android.arch.lifecycle.ViewModel;
-import android.content.Context;
-
-import org.sufficientlysecure.keychain.livedata.KeyInfoLiveData;
-import org.sufficientlysecure.keychain.livedata.PgpKeyGenerationLiveData;
-
-
-public class RemoteSelectIdViewModel extends ViewModel {
-
- private KeyInfoLiveData keyInfo;
- private PgpKeyGenerationLiveData keyGenerationData;
- private boolean listAllKeys;
-
- public KeyInfoLiveData getKeyInfo(Context context) {
- if (keyInfo == null) {
- keyInfo = new KeyInfoLiveData(context, context.getContentResolver());
- }
- return keyInfo;
- }
-
- public PgpKeyGenerationLiveData getKeyGenerationLiveData(Context context) {
- if (keyGenerationData == null) {
- keyGenerationData = new PgpKeyGenerationLiveData(context);
- }
- return keyGenerationData;
- }
-
- public boolean isListAllKeys() {
- return listAllKeys;
- }
-
- public void setListAllKeys(boolean listAllKeys) {
- this.listAllKeys = listAllKeys;
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdentityKeyPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdentityKeyPresenter.java
index b9856367e..460546e70 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdentityKeyPresenter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdentityKeyPresenter.java
@@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.remote.ui.dialog;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import android.arch.lifecycle.LifecycleOwner;
@@ -27,19 +28,18 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
+import android.text.TextUtils;
import org.openintents.openpgp.util.OpenPgpUtils;
import org.openintents.openpgp.util.OpenPgpUtils.UserId;
import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeyInfo;
-import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeySelector;
import org.sufficientlysecure.keychain.model.ApiApp;
+import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.provider.ApiAppDao;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.remote.ui.dialog.RemoteSelectIdKeyActivity.RemoteSelectIdViewModel;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import timber.log.Timber;
@@ -47,12 +47,12 @@ import timber.log.Timber;
class RemoteSelectIdentityKeyPresenter {
private final PackageManager packageManager;
+ private LifecycleOwner lifecycleOwner;
private final Context context;
- private final RemoteSelectIdViewModel viewModel;
-
private RemoteSelectIdentityKeyView view;
- private List keyInfoData;
+ private RemoteSelectIdViewModel viewModel;
+ private List keyInfoData;
private UserId userId;
private long selectedMasterKeyId;
@@ -61,41 +61,35 @@ class RemoteSelectIdentityKeyPresenter {
private ApiApp apiApp;
- RemoteSelectIdentityKeyPresenter(Context context, RemoteSelectIdViewModel viewModel, LifecycleOwner lifecycleOwner) {
+ RemoteSelectIdentityKeyPresenter(Context context, LifecycleOwner lifecycleOwner) {
this.context = context;
- this.viewModel = viewModel;
+ this.lifecycleOwner = lifecycleOwner;
this.apiAppDao = ApiAppDao.getInstance(context);
packageManager = context.getPackageManager();
-
- viewModel.getKeyGenerationLiveData(context).observe(lifecycleOwner, this::onChangeKeyGeneration);
- viewModel.getKeyInfo(context).observe(lifecycleOwner, this::onChangeKeyInfoData);
}
public void setView(RemoteSelectIdentityKeyView view) {
this.view = view;
}
- void setupFromIntentData(String packageName, byte[] packageSignature, String rawUserId, boolean clientHasAutocryptSetupMsg) {
+ void setupFromViewModel(RemoteSelectIdViewModel viewModel) {
+ this.viewModel = viewModel;
+
try {
- setPackageInfo(packageName, packageSignature);
+ setPackageInfo(viewModel.packageName, viewModel.packageSignature);
} catch (NameNotFoundException e) {
Timber.e(e, "Unable to find info of calling app!");
view.finishAsCancelled();
return;
}
- this.userId = OpenPgpUtils.splitUserId(rawUserId);
+ this.userId = OpenPgpUtils.splitUserId(viewModel.rawUserId);
view.setAddressText(userId.email);
- view.setShowAutocryptHint(clientHasAutocryptSetupMsg);
+ view.setShowAutocryptHint(viewModel.clientHasAutocryptSetupMsg);
- loadKeyInfo();
- }
-
- private void loadKeyInfo() {
- Uri listedKeyRingUri = viewModel.isListAllKeys() ?
- KeyRings.buildUnifiedKeyRingsUri() : KeyRings.buildUnifiedKeyRingsFindByUserIdUri(userId.email);
- viewModel.getKeyInfo(context).setKeySelector(KeySelector.createOnlySecret(listedKeyRingUri, null));
+ viewModel.getKeyGenerationLiveData(context).observe(lifecycleOwner, this::onChangeKeyGeneration);
+ viewModel.getSecretUnifiedKeyInfo(context).observe(lifecycleOwner, this::onChangeKeyInfoData);
}
private void setPackageInfo(String packageName, byte[] packageSignature) throws NameNotFoundException {
@@ -108,22 +102,41 @@ class RemoteSelectIdentityKeyPresenter {
view.setTitleClientIconAndName(appIcon, appLabel);
}
- private void onChangeKeyInfoData(List data) {
+ private void onChangeKeyInfoData(List data) {
+ if (data == null) {
+ return;
+ }
keyInfoData = data;
goToSelectLayout();
}
private void goToSelectLayout() {
- if (keyInfoData == null) {
+ List filteredKeyInfoData =
+ viewModel.isListAllKeys() || TextUtils.isEmpty(userId.email) ? keyInfoData : getFilteredKeyInfo();
+
+ if (filteredKeyInfoData == null) {
view.showLayoutEmpty();
- } else if (keyInfoData.isEmpty()) {
+ } else if (filteredKeyInfoData.isEmpty()) {
view.showLayoutSelectNoKeys();
} else {
- view.setKeyListData(keyInfoData);
+ view.setKeyListData(filteredKeyInfoData);
view.showLayoutSelectKeyList();
}
}
+ private List getFilteredKeyInfo() {
+ if (viewModel.filteredKeyInfo == null) {
+ viewModel.filteredKeyInfo = new ArrayList<>();
+ for (UnifiedKeyInfo unifiedKeyInfo : keyInfoData) {
+ String emailSearchList = unifiedKeyInfo.user_id_list();
+ if (emailSearchList == null || emailSearchList.contains(userId.email)) {
+ viewModel.filteredKeyInfo.add(unifiedKeyInfo);
+ }
+ }
+ }
+ return viewModel.filteredKeyInfo;
+ }
+
private void onChangeKeyGeneration(PgpEditKeyResult pgpEditKeyResult) {
if (pgpEditKeyResult == null) {
return;
@@ -171,7 +184,7 @@ class RemoteSelectIdentityKeyPresenter {
}
void onKeyItemClick(int position) {
- selectedMasterKeyId = keyInfoData.get(position).getMasterKeyId();
+ selectedMasterKeyId = keyInfoData.get(position).master_key_id();
view.highlightKey(position);
}
@@ -222,8 +235,7 @@ class RemoteSelectIdentityKeyPresenter {
public void onClickMenuListAllKeys() {
viewModel.setListAllKeys(!viewModel.isListAllKeys());
- loadKeyInfo();
- view.showLayoutSelectKeyList();
+ goToSelectLayout();
}
public void onClickGoToOpenKeychain() {
@@ -246,7 +258,7 @@ class RemoteSelectIdentityKeyPresenter {
void showLayoutGenerateOk();
void showLayoutGenerateSave();
- void setKeyListData(List data);
+ void setKeyListData(List data);
void highlightKey(int position);
diff --git a/OpenKeychain/src/main/sqldelight/org/sufficientlysecure/keychain/Keys.sq b/OpenKeychain/src/main/sqldelight/org/sufficientlysecure/keychain/Keys.sq
index 4653b3ded..bdb260e54 100644
--- a/OpenKeychain/src/main/sqldelight/org/sufficientlysecure/keychain/Keys.sq
+++ b/OpenKeychain/src/main/sqldelight/org/sufficientlysecure/keychain/Keys.sq
@@ -23,8 +23,9 @@ CREATE TABLE IF NOT EXISTS keys (
keyrings_public(master_key_id) ON DELETE CASCADE
);
-selectAllUnifiedKeyInfo:
-SELECT keys.master_key_id, keys.fingerprint, MIN(user_packets.rank), user_packets.name, user_packets.email, user_packets.comment, keys.creation, keys.expiry, keys.is_revoked, keys.is_secure, certs.verified,
+unifiedKeyView:
+CREATE VIEW unifiedKeyView AS
+ SELECT keys.master_key_id, keys.fingerprint, MIN(user_packets.rank), user_packets.name, user_packets.email, user_packets.comment, keys.creation, keys.expiry, keys.is_revoked, keys.is_secure, certs.verified,
(EXISTS (SELECT * FROM user_packets AS dups WHERE dups.master_key_id != keys.master_key_id AND dups.rank = 0 AND dups.name = user_packets.name COLLATE NOCASE AND dups.email = user_packets.email COLLATE NOCASE )) AS has_duplicate_int,
(EXISTS (SELECT * FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.has_secret != 0 )) AS has_any_secret_int,
(EXISTS (SELECT * FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.can_authenticate != 0 )) AS has_auth_key_int,
@@ -36,23 +37,25 @@ SELECT keys.master_key_id, keys.fingerprint, MIN(user_packets.rank), user_packet
LEFT JOIN certs ON ( keys.master_key_id = certs.master_key_id AND certs.verified = 1 )
LEFT JOIN autocrypt_peers AS aTI ON ( aTI.master_key_id = keys.master_key_id )
WHERE keys.rank = 0
- GROUP BY keys.master_key_id
- ORDER BY has_secret DESC, user_packets.name COLLATE NOCASE ASC;
+ GROUP BY keys.master_key_id;
+
+selectAllUnifiedKeyInfo:
+SELECT * FROM unifiedKeyView
+ ORDER BY has_any_secret_int DESC, name COLLATE NOCASE ASC, creation DESC;
selectUnifiedKeyInfoByMasterKeyId:
-SELECT keys.master_key_id, keys.fingerprint, MIN(user_packets.rank), user_packets.name, user_packets.email, user_packets.comment, keys.creation, keys.expiry, keys.is_revoked, keys.is_secure, certs.verified,
- (EXISTS (SELECT * FROM user_packets AS dups WHERE dups.master_key_id != keys.master_key_id AND dups.rank = 0 AND dups.name = user_packets.name COLLATE NOCASE AND dups.email = user_packets.email COLLATE NOCASE )) AS has_duplicate_int,
- (EXISTS (SELECT * FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.has_secret != 0 )) AS has_any_secret_int,
- (EXISTS (SELECT * FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.can_authenticate != 0 )) AS has_auth_key_int,
- (EXISTS (SELECT * FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.can_encrypt != 0 )) AS has_encrypt_key_int,
- GROUP_CONCAT(DISTINCT aTI.package_name) AS autocrypt_package_names_csv,
- GROUP_CONCAT(user_packets.user_id, '|||') AS user_id_list
- FROM keys
- INNER JOIN user_packets ON ( keys.master_key_id = user_packets.master_key_id AND user_packets.type IS NULL )
- LEFT JOIN certs ON ( keys.master_key_id = certs.master_key_id AND certs.verified = 1 )
- LEFT JOIN autocrypt_peers AS aTI ON ( aTI.master_key_id = keys.master_key_id )
- WHERE keys.rank = 0 AND keys.master_key_id = ?
- GROUP BY keys.master_key_id;
+SELECT * FROM unifiedKeyView
+ WHERE is_revoked = 0 AND master_key_id = ?;
+
+selectUnifiedKeyInfoSearchMailAddress:
+SELECT * FROM unifiedKeyView
+ WHERE email LIKE ?
+ ORDER BY creation DESC;
+
+selectAllUnifiedKeyInfoWithSecret:
+SELECT * FROM unifiedKeyView
+ WHERE has_any_secret_int = 1
+ ORDER BY creation DESC;
selectSubkeysByMasterKeyId:
SELECT *