use LiveData to load data in ViewKeyActivity
This commit is contained in:
@@ -58,5 +58,9 @@ public abstract class SubKey implements KeysModel {
|
|||||||
public boolean has_auth_key() {
|
public boolean has_auth_key() {
|
||||||
return has_auth_key_int() != 0;
|
return has_auth_key_int() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean has_encrypt_key() {
|
||||||
|
return has_encrypt_key_int() != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,11 @@ import android.animation.ObjectAnimator;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityOptions;
|
import android.app.ActivityOptions;
|
||||||
|
import android.arch.lifecycle.LiveData;
|
||||||
|
import android.arch.lifecycle.ViewModel;
|
||||||
|
import android.arch.lifecycle.ViewModelProviders;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -49,9 +51,6 @@ import android.support.design.widget.CoordinatorLayout;
|
|||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.LoaderManager;
|
|
||||||
import android.support.v4.content.CursorLoader;
|
|
||||||
import android.support.v4.content.Loader;
|
|
||||||
import android.support.v7.widget.CardView;
|
import android.support.v7.widget.CardView;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -71,14 +70,14 @@ import org.sufficientlysecure.keychain.Constants;
|
|||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
||||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||||
|
import org.sufficientlysecure.keychain.livedata.GenericLiveData;
|
||||||
|
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||||
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
|
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
|
||||||
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection;
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection;
|
||||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||||
@@ -113,7 +112,6 @@ import timber.log.Timber;
|
|||||||
|
|
||||||
|
|
||||||
public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor>,
|
|
||||||
CryptoOperationHelper.Callback<ImportKeyringParcel, ImportKeyResult> {
|
CryptoOperationHelper.Callback<ImportKeyringParcel, ImportKeyResult> {
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@IntDef({REQUEST_QR_FINGERPRINT, REQUEST_BACKUP, REQUEST_CERTIFY, REQUEST_DELETE})
|
@IntDef({REQUEST_QR_FINGERPRINT, REQUEST_BACKUP, REQUEST_CERTIFY, REQUEST_DELETE})
|
||||||
@@ -151,23 +149,13 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
|
|
||||||
private byte[] qrCodeLoaded;
|
private byte[] qrCodeLoaded;
|
||||||
|
|
||||||
private static final int LOADER_ID_UNIFIED = 0;
|
private UnifiedKeyInfo unifiedKeyInfo;
|
||||||
|
|
||||||
private boolean isSecret = false;
|
|
||||||
private boolean hasEncrypt = false;
|
|
||||||
private boolean isVerified = false;
|
|
||||||
private boolean isRevoked = false;
|
|
||||||
private boolean isSecure = true;
|
|
||||||
private boolean isExpired = false;
|
|
||||||
|
|
||||||
private MenuItem refreshItem;
|
private MenuItem refreshItem;
|
||||||
private boolean isRefreshing;
|
private boolean isRefreshing;
|
||||||
private Animation rotate, rotateSpin;
|
private Animation rotate, rotateSpin;
|
||||||
private View refreshView;
|
private View refreshView;
|
||||||
|
|
||||||
private long masterKeyId;
|
|
||||||
private byte[] fingerprint;
|
|
||||||
|
|
||||||
public static Intent getViewKeyActivityIntent(@NonNull Context context, long masterKeyId) {
|
public static Intent getViewKeyActivityIntent(@NonNull Context context, long masterKeyId) {
|
||||||
Intent viewIntent = new Intent(context, ViewKeyActivity.class);
|
Intent viewIntent = new Intent(context, ViewKeyActivity.class);
|
||||||
viewIntent.putExtra(ViewKeyActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
|
viewIntent.putExtra(ViewKeyActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
|
||||||
@@ -250,6 +238,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
});
|
});
|
||||||
refreshView = getLayoutInflater().inflate(R.layout.indeterminate_progress, null);
|
refreshView = getLayoutInflater().inflate(R.layout.indeterminate_progress, null);
|
||||||
|
|
||||||
|
long masterKeyId;
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
Uri dataUri = intent.getData();
|
Uri dataUri = intent.getData();
|
||||||
if (intent.hasExtra(EXTRA_MASTER_KEY_ID)) {
|
if (intent.hasExtra(EXTRA_MASTER_KEY_ID)) {
|
||||||
@@ -271,7 +260,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
actionEncryptText.setOnClickListener(v -> encrypt(true));
|
actionEncryptText.setOnClickListener(v -> encrypt(true));
|
||||||
|
|
||||||
floatingActionButton.setOnClickListener(v -> {
|
floatingActionButton.setOnClickListener(v -> {
|
||||||
if (isSecret) {
|
if (unifiedKeyInfo.has_any_secret()) {
|
||||||
startSafeSlinger();
|
startSafeSlinger();
|
||||||
} else {
|
} else {
|
||||||
scanQrCode();
|
scanQrCode();
|
||||||
@@ -280,9 +269,8 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
|
|
||||||
qrCodeLayout.setOnClickListener(v -> showQrCodeDialog());
|
qrCodeLayout.setOnClickListener(v -> showQrCodeDialog());
|
||||||
|
|
||||||
// Prepare the loaders. Either re-connect with an existing ones,
|
ViewKeyViewModel viewModel = ViewModelProviders.of(this).get(ViewKeyViewModel.class);
|
||||||
// or start new ones.
|
viewModel.setMasterKeyId(getIntent().getLongExtra(EXTRA_MASTER_KEY_ID, 0L));
|
||||||
getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
|
|
||||||
|
|
||||||
if (savedInstanceState == null && intent.hasExtra(EXTRA_DISPLAY_RESULT)) {
|
if (savedInstanceState == null && intent.hasExtra(EXTRA_DISPLAY_RESULT)) {
|
||||||
OperationResult result = intent.getParcelableExtra(EXTRA_DISPLAY_RESULT);
|
OperationResult result = intent.getParcelableExtra(EXTRA_DISPLAY_RESULT);
|
||||||
@@ -294,8 +282,13 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FragmentManager manager = getSupportFragmentManager();
|
||||||
|
|
||||||
|
ViewKeyFragment frag = ViewKeyFragment.newInstance();
|
||||||
|
manager.beginTransaction().replace(R.id.view_key_fragment, frag, "view_key_fragment").commit();
|
||||||
|
|
||||||
if (Preferences.getPreferences(this).getExperimentalEnableKeybase()) {
|
if (Preferences.getPreferences(this).getExperimentalEnableKeybase()) {
|
||||||
FragmentManager manager = getSupportFragmentManager();
|
manager = getSupportFragmentManager();
|
||||||
final ViewKeyKeybaseFragment keybaseFrag = ViewKeyKeybaseFragment.newInstance(masterKeyId);
|
final ViewKeyKeybaseFragment keybaseFrag = ViewKeyKeybaseFragment.newInstance(masterKeyId);
|
||||||
manager.beginTransaction()
|
manager.beginTransaction()
|
||||||
.replace(R.id.view_key_keybase_fragment, keybaseFrag)
|
.replace(R.id.view_key_keybase_fragment, keybaseFrag)
|
||||||
@@ -303,6 +296,30 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ViewKeyViewModel extends ViewModel {
|
||||||
|
private Long masterKeyId;
|
||||||
|
private LiveData<UnifiedKeyInfo> unifiedKeyInfoLiveData;
|
||||||
|
|
||||||
|
void setMasterKeyId(long masterKeyId) {
|
||||||
|
if (this.masterKeyId != null) {
|
||||||
|
throw new IllegalStateException("cannot change masterKeyId once set!");
|
||||||
|
}
|
||||||
|
this.masterKeyId = masterKeyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<UnifiedKeyInfo> getUnifiedKeyInfoLiveData(Context context) {
|
||||||
|
if (masterKeyId == null) {
|
||||||
|
throw new IllegalStateException("masterKeyId must be set to retrieve this!");
|
||||||
|
}
|
||||||
|
if (unifiedKeyInfoLiveData == null) {
|
||||||
|
KeyRepository keyRepository = KeyRepository.create(context);
|
||||||
|
unifiedKeyInfoLiveData = new GenericLiveData<>(context, null,
|
||||||
|
() -> keyRepository.getUnifiedKeyInfo(masterKeyId));
|
||||||
|
}
|
||||||
|
return unifiedKeyInfoLiveData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initLayout() {
|
protected void initLayout() {
|
||||||
setContentView(R.layout.view_key_activity);
|
setContentView(R.layout.view_key_activity);
|
||||||
@@ -346,7 +363,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
}
|
}
|
||||||
case R.id.menu_key_view_advanced: {
|
case R.id.menu_key_view_advanced: {
|
||||||
Intent advancedIntent = new Intent(this, ViewKeyAdvActivity.class);
|
Intent advancedIntent = new Intent(this, ViewKeyAdvActivity.class);
|
||||||
advancedIntent.putExtra(ViewKeyAdvActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
|
advancedIntent.putExtra(ViewKeyAdvActivity.EXTRA_MASTER_KEY_ID, unifiedKeyInfo.master_key_id());
|
||||||
startActivity(advancedIntent);
|
startActivity(advancedIntent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -365,13 +382,15 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
MenuItem backupKey = menu.findItem(R.id.menu_key_view_backup);
|
MenuItem backupKey = menu.findItem(R.id.menu_key_view_backup);
|
||||||
backupKey.setVisible(isSecret);
|
backupKey.setVisible(unifiedKeyInfo.has_any_secret());
|
||||||
menu.findItem(R.id.menu_key_view_skt).setVisible(isSecret);
|
menu.findItem(R.id.menu_key_view_skt).setVisible(unifiedKeyInfo.has_any_secret());
|
||||||
MenuItem changePassword = menu.findItem(R.id.menu_key_change_password);
|
MenuItem changePassword = menu.findItem(R.id.menu_key_change_password);
|
||||||
changePassword.setVisible(isSecret);
|
changePassword.setVisible(unifiedKeyInfo.has_any_secret());
|
||||||
|
|
||||||
MenuItem certifyFingerprint = menu.findItem(R.id.menu_key_view_certify_fingerprint);
|
MenuItem certifyFingerprint = menu.findItem(R.id.menu_key_view_certify_fingerprint);
|
||||||
certifyFingerprint.setVisible(!isSecret && !isVerified && !isExpired && !isRevoked);
|
certifyFingerprint.setVisible(
|
||||||
|
!unifiedKeyInfo.has_any_secret() && !unifiedKeyInfo.is_verified() && !unifiedKeyInfo.is_expired() &&
|
||||||
|
!unifiedKeyInfo.is_revoked());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -387,6 +406,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
@Override
|
@Override
|
||||||
public void onCryptoOperationSuccess(EditKeyResult result) {
|
public void onCryptoOperationSuccess(EditKeyResult result) {
|
||||||
displayResult(result);
|
displayResult(result);
|
||||||
|
long masterKeyId = unifiedKeyInfo.master_key_id();
|
||||||
PassphraseCacheService.clearCachedPassphrase(getApplicationContext(), masterKeyId, masterKeyId);
|
PassphraseCacheService.clearCachedPassphrase(getApplicationContext(), masterKeyId, masterKeyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +437,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
|
|
||||||
// use new passphrase!
|
// use new passphrase!
|
||||||
changeUnlockParcel = ChangeUnlockParcel.createChangeUnlockParcel(
|
changeUnlockParcel = ChangeUnlockParcel.createChangeUnlockParcel(
|
||||||
masterKeyId, fingerprint,
|
unifiedKeyInfo.master_key_id(), unifiedKeyInfo.fingerprint(),
|
||||||
data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)
|
data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -447,14 +467,14 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
|
|
||||||
private void certifyFingerprint() {
|
private void certifyFingerprint() {
|
||||||
Intent intent = new Intent(this, CertifyFingerprintActivity.class);
|
Intent intent = new Intent(this, CertifyFingerprintActivity.class);
|
||||||
intent.setData(KeyRings.buildUnifiedKeyRingUri(masterKeyId));
|
intent.setData(KeyRings.buildUnifiedKeyRingUri(unifiedKeyInfo.master_key_id()));
|
||||||
|
|
||||||
startActivityForResult(intent, REQUEST_CERTIFY);
|
startActivityForResult(intent, REQUEST_CERTIFY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void certifyImmediate() {
|
private void certifyImmediate() {
|
||||||
Intent intent = new Intent(this, CertifyKeyActivity.class);
|
Intent intent = new Intent(this, CertifyKeyActivity.class);
|
||||||
intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[] { masterKeyId });
|
intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[] { unifiedKeyInfo.master_key_id() });
|
||||||
|
|
||||||
startActivityForResult(intent, REQUEST_CERTIFY);
|
startActivityForResult(intent, REQUEST_CERTIFY);
|
||||||
}
|
}
|
||||||
@@ -471,7 +491,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
opts = options.toBundle();
|
opts = options.toBundle();
|
||||||
}
|
}
|
||||||
|
|
||||||
qrCodeIntent.setData(KeyRings.buildUnifiedKeyRingUri(masterKeyId));
|
qrCodeIntent.setData(KeyRings.buildUnifiedKeyRingUri(unifiedKeyInfo.master_key_id()));
|
||||||
ActivityCompat.startActivity(this, qrCodeIntent, opts);
|
ActivityCompat.startActivity(this, qrCodeIntent, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,6 +499,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
|
|
||||||
if (keyHasPassphrase()) {
|
if (keyHasPassphrase()) {
|
||||||
Intent intent = new Intent(this, PassphraseDialogActivity.class);
|
Intent intent = new Intent(this, PassphraseDialogActivity.class);
|
||||||
|
long masterKeyId = unifiedKeyInfo.master_key_id();
|
||||||
RequiredInputParcel requiredInput =
|
RequiredInputParcel requiredInput =
|
||||||
RequiredInputParcel.createRequiredDecryptPassphrase(masterKeyId, masterKeyId);
|
RequiredInputParcel.createRequiredDecryptPassphrase(masterKeyId, masterKeyId);
|
||||||
requiredInput.mSkipCaching = true;
|
requiredInput.mSkipCaching = true;
|
||||||
@@ -491,6 +512,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
|
|
||||||
private boolean keyHasPassphrase() {
|
private boolean keyHasPassphrase() {
|
||||||
try {
|
try {
|
||||||
|
long masterKeyId = unifiedKeyInfo.master_key_id();
|
||||||
SecretKeyType secretKeyType =
|
SecretKeyType secretKeyType =
|
||||||
keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretKeyType(masterKeyId);
|
keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretKeyType(masterKeyId);
|
||||||
switch (secretKeyType) {
|
switch (secretKeyType) {
|
||||||
@@ -510,7 +532,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
|
|
||||||
private void startBackupActivity() {
|
private void startBackupActivity() {
|
||||||
Intent intent = new Intent(this, BackupActivity.class);
|
Intent intent = new Intent(this, BackupActivity.class);
|
||||||
intent.putExtra(BackupActivity.EXTRA_MASTER_KEY_IDS, new long[]{ masterKeyId });
|
intent.putExtra(BackupActivity.EXTRA_MASTER_KEY_IDS, new long[] { unifiedKeyInfo.master_key_id() });
|
||||||
intent.putExtra(BackupActivity.EXTRA_SECRET, true);
|
intent.putExtra(BackupActivity.EXTRA_SECRET, true);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
@@ -519,9 +541,9 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
Intent deleteIntent = new Intent(this, DeleteKeyDialogActivity.class);
|
Intent deleteIntent = new Intent(this, DeleteKeyDialogActivity.class);
|
||||||
|
|
||||||
deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS,
|
deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS,
|
||||||
new long[]{ masterKeyId });
|
new long[]{ unifiedKeyInfo.master_key_id() });
|
||||||
deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_HAS_SECRET, isSecret);
|
deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_HAS_SECRET, unifiedKeyInfo.has_any_secret());
|
||||||
if (isSecret) {
|
if (unifiedKeyInfo.has_any_secret()) {
|
||||||
// for upload in case key is secret
|
// for upload in case key is secret
|
||||||
deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_KEYSERVER,
|
deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_KEYSERVER,
|
||||||
Preferences.getPreferences(this).getPreferredKeyserver());
|
Preferences.getPreferences(this).getPreferredKeyserver());
|
||||||
@@ -559,7 +581,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
Notify.create(this, R.string.error_scan_fp, Notify.LENGTH_LONG, Style.ERROR).show();
|
Notify.create(this, R.string.error_scan_fp, Notify.LENGTH_LONG, Style.ERROR).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Arrays.equals(this.fingerprint, fingerprint)) {
|
if (Arrays.equals(unifiedKeyInfo.fingerprint(), fingerprint)) {
|
||||||
certifyImmediate();
|
certifyImmediate();
|
||||||
} else {
|
} else {
|
||||||
Notify.create(this, R.string.error_scan_match, Notify.LENGTH_LONG, Style.ERROR).show();
|
Notify.create(this, R.string.error_scan_match, Notify.LENGTH_LONG, Style.ERROR).show();
|
||||||
@@ -598,35 +620,13 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showMainFragment() {
|
|
||||||
new Handler().post(() -> {
|
|
||||||
FragmentManager manager = getSupportFragmentManager();
|
|
||||||
|
|
||||||
// unless we must refresh
|
|
||||||
ViewKeyFragment frag = (ViewKeyFragment) manager.findFragmentByTag("view_key_fragment");
|
|
||||||
// if everything is valid, just drop it
|
|
||||||
if (frag != null && frag.isValidForData(isSecret)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the main fragment doesn't exist, or is not of the correct type, (re)create it
|
|
||||||
frag = ViewKeyFragment.newInstance(masterKeyId, isSecret);
|
|
||||||
// get rid of possible backstack, this fragment is always at the bottom
|
|
||||||
manager.popBackStack("security_token", FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
|
||||||
manager.beginTransaction()
|
|
||||||
.replace(R.id.view_key_fragment, frag, "view_key_fragment")
|
|
||||||
// if this gets lost, it doesn't really matter since the loader will reinstate it onResume
|
|
||||||
.commitAllowingStateLoss();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void encrypt(boolean text) {
|
private void encrypt(boolean text) {
|
||||||
// If there is no encryption key, don't bother.
|
// If there is no encryption key, don't bother.
|
||||||
if (!hasEncrypt) {
|
if (!unifiedKeyInfo.has_encrypt_key()) {
|
||||||
Notify.create(this, R.string.error_no_encrypt_subkey, Notify.Style.ERROR).show();
|
Notify.create(this, R.string.error_no_encrypt_subkey, Notify.Style.ERROR).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
long[] encryptionKeyIds = new long[] { masterKeyId };
|
long[] encryptionKeyIds = new long[] { unifiedKeyInfo.master_key_id() };
|
||||||
Intent intent;
|
Intent intent;
|
||||||
if (text) {
|
if (text) {
|
||||||
intent = new Intent(this, EncryptTextActivity.class);
|
intent = new Intent(this, EncryptTextActivity.class);
|
||||||
@@ -643,7 +643,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
|
|
||||||
private void startSafeSlinger() {
|
private void startSafeSlinger() {
|
||||||
Intent safeSlingerIntent = new Intent(this, SafeSlingerActivity.class);
|
Intent safeSlingerIntent = new Intent(this, SafeSlingerActivity.class);
|
||||||
safeSlingerIntent.putExtra(SafeSlingerActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
|
safeSlingerIntent.putExtra(SafeSlingerActivity.EXTRA_MASTER_KEY_ID, unifiedKeyInfo.master_key_id());
|
||||||
startActivityForResult(safeSlingerIntent, 0);
|
startActivityForResult(safeSlingerIntent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,50 +682,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
loadTask.execute();
|
loadTask.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// These are the rows that we will retrieve.
|
|
||||||
static final String[] PROJECTION = new String[]{
|
|
||||||
KeychainContract.KeyRings._ID,
|
|
||||||
KeychainContract.KeyRings.MASTER_KEY_ID,
|
|
||||||
KeychainContract.KeyRings.USER_ID,
|
|
||||||
KeychainContract.KeyRings.IS_REVOKED,
|
|
||||||
KeychainContract.KeyRings.IS_EXPIRED,
|
|
||||||
KeychainContract.KeyRings.IS_SECURE,
|
|
||||||
KeychainContract.KeyRings.VERIFIED,
|
|
||||||
KeychainContract.KeyRings.HAS_ANY_SECRET,
|
|
||||||
KeychainContract.KeyRings.FINGERPRINT,
|
|
||||||
KeychainContract.KeyRings.HAS_ENCRYPT,
|
|
||||||
KeyRings.NAME,
|
|
||||||
KeyRings.EMAIL,
|
|
||||||
KeyRings.COMMENT
|
|
||||||
};
|
|
||||||
|
|
||||||
static final int INDEX_MASTER_KEY_ID = 1;
|
|
||||||
static final int INDEX_USER_ID = 2;
|
|
||||||
static final int INDEX_IS_REVOKED = 3;
|
|
||||||
static final int INDEX_IS_EXPIRED = 4;
|
|
||||||
static final int INDEX_IS_SECURE = 5;
|
|
||||||
static final int INDEX_VERIFIED = 6;
|
|
||||||
static final int INDEX_HAS_ANY_SECRET = 7;
|
|
||||||
static final int INDEX_FINGERPRINT = 8;
|
|
||||||
static final int INDEX_HAS_ENCRYPT = 9;
|
|
||||||
static final int INDEX_NAME = 10;
|
|
||||||
static final int INDEX_EMAIL = 11;
|
|
||||||
static final int INDEX_COMMENT = 12;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
|
||||||
switch (id) {
|
|
||||||
case LOADER_ID_UNIFIED: {
|
|
||||||
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(masterKeyId);
|
|
||||||
return new CursorLoader(this, baseUri, PROJECTION, null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int mPreviousColor = 0;
|
int mPreviousColor = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -747,127 +703,104 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
return (0xff << 24) | (r << 16) | (g << 8) | b;
|
return (0xff << 24) | (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
|
||||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
if (unifiedKeyInfo == null) {
|
||||||
/* TODO better error handling? May cause problems when a key is deleted,
|
return;
|
||||||
* because the notification triggers faster than the activity closes.
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// Swap the new cursor in. (The framework will take care of closing the
|
this.unifiedKeyInfo = unifiedKeyInfo;
|
||||||
// old cursor once we return.)
|
|
||||||
switch (loader.getId()) {
|
|
||||||
case LOADER_ID_UNIFIED: {
|
|
||||||
// Avoid NullPointerExceptions...
|
|
||||||
if (data.getCount() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.moveToFirst()) {
|
String name = unifiedKeyInfo.name();
|
||||||
// get name, email, and comment from USER_ID
|
collapsingToolbarLayout.setTitle(name != null ? name : getString(R.string.user_id_no_name));
|
||||||
|
|
||||||
String name = data.getString(INDEX_NAME);
|
// if the refresh animation isn't playing
|
||||||
|
if (!rotate.hasStarted() && !rotateSpin.hasStarted()) {
|
||||||
|
// re-create options menu based on isSecret, isVerified
|
||||||
|
supportInvalidateOptionsMenu();
|
||||||
|
// this is done at the end of the animation otherwise
|
||||||
|
}
|
||||||
|
|
||||||
collapsingToolbarLayout.setTitle(name != null ? name : getString(R.string.user_id_no_name));
|
AsyncTask<Long, Void, Bitmap> photoTask =
|
||||||
|
new AsyncTask<Long, Void, Bitmap>() {
|
||||||
masterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
|
protected Bitmap doInBackground(Long... mMasterKeyId) {
|
||||||
fingerprint = data.getBlob(INDEX_FINGERPRINT);
|
return new ContactHelper(ViewKeyActivity.this)
|
||||||
isSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
|
.loadPhotoByMasterKeyId(mMasterKeyId[0], true);
|
||||||
hasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0;
|
|
||||||
isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
|
|
||||||
isExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
|
|
||||||
isSecure = data.getInt(INDEX_IS_SECURE) == 1;
|
|
||||||
isVerified = data.getInt(INDEX_VERIFIED) > 0;
|
|
||||||
|
|
||||||
// queue showing of the main fragment
|
|
||||||
showMainFragment();
|
|
||||||
|
|
||||||
// if the refresh animation isn't playing
|
|
||||||
if (!rotate.hasStarted() && !rotateSpin.hasStarted()) {
|
|
||||||
// re-create options menu based on isSecret, isVerified
|
|
||||||
supportInvalidateOptionsMenu();
|
|
||||||
// this is done at the end of the animation otherwise
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncTask<Long, Void, Bitmap> photoTask =
|
protected void onPostExecute(Bitmap photo) {
|
||||||
new AsyncTask<Long, Void, Bitmap>() {
|
if (photo == null) {
|
||||||
protected Bitmap doInBackground(Long... mMasterKeyId) {
|
return;
|
||||||
return new ContactHelper(ViewKeyActivity.this)
|
|
||||||
.loadPhotoByMasterKeyId(mMasterKeyId[0], true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onPostExecute(Bitmap photo) {
|
|
||||||
if (photo == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
photoView.setImageBitmap(photo);
|
|
||||||
photoView.setColorFilter(getResources().getColor(R.color.toolbar_photo_tint), PorterDuff.Mode.SRC_ATOP);
|
|
||||||
photoLayout.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
boolean showStatusText = isSecure && !isExpired && !isRevoked;
|
|
||||||
if (showStatusText) {
|
|
||||||
statusText.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
if (isSecret) {
|
|
||||||
statusText.setText(R.string.view_key_my_key);
|
|
||||||
} else if (isVerified) {
|
|
||||||
statusText.setText(R.string.view_key_verified);
|
|
||||||
} else {
|
|
||||||
statusText.setText(R.string.view_key_unverified);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
statusText.setVisibility(View.GONE);
|
photoView.setImageBitmap(photo);
|
||||||
|
photoView.setColorFilter(getResources().getColor(R.color.toolbar_photo_tint),
|
||||||
|
PorterDuff.Mode.SRC_ATOP);
|
||||||
|
photoLayout.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Note: order is important
|
boolean showStatusText = unifiedKeyInfo.is_secure() && !unifiedKeyInfo.is_expired() && !unifiedKeyInfo.is_revoked();
|
||||||
int color;
|
if (showStatusText) {
|
||||||
if (isRevoked) {
|
statusText.setVisibility(View.VISIBLE);
|
||||||
statusImage.setVisibility(View.VISIBLE);
|
|
||||||
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
|
||||||
State.REVOKED, R.color.icons, true);
|
|
||||||
// noinspection deprecation, fix requires api level 23
|
|
||||||
color = getResources().getColor(R.color.key_flag_red);
|
|
||||||
|
|
||||||
actionEncryptFile.setVisibility(View.INVISIBLE);
|
if (unifiedKeyInfo.has_any_secret()) {
|
||||||
actionEncryptText.setVisibility(View.INVISIBLE);
|
statusText.setText(R.string.view_key_my_key);
|
||||||
hideFab();
|
} else if (unifiedKeyInfo.is_verified()) {
|
||||||
qrCodeLayout.setVisibility(View.GONE);
|
statusText.setText(R.string.view_key_verified);
|
||||||
} else if (!isSecure) {
|
} else {
|
||||||
statusImage.setVisibility(View.VISIBLE);
|
statusText.setText(R.string.view_key_unverified);
|
||||||
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
}
|
||||||
State.INSECURE, R.color.icons, true);
|
} else {
|
||||||
// noinspection deprecation, fix requires api level 23
|
statusText.setVisibility(View.GONE);
|
||||||
color = getResources().getColor(R.color.key_flag_red);
|
}
|
||||||
|
|
||||||
actionEncryptFile.setVisibility(View.INVISIBLE);
|
// Note: order is important
|
||||||
actionEncryptText.setVisibility(View.INVISIBLE);
|
int color;
|
||||||
hideFab();
|
if (unifiedKeyInfo.is_revoked()) {
|
||||||
qrCodeLayout.setVisibility(View.GONE);
|
statusImage.setVisibility(View.VISIBLE);
|
||||||
} else if (isExpired) {
|
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
||||||
statusImage.setVisibility(View.VISIBLE);
|
State.REVOKED, R.color.icons, true);
|
||||||
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
// noinspection deprecation, fix requires api level 23
|
||||||
State.EXPIRED, R.color.icons, true);
|
color = getResources().getColor(R.color.key_flag_red);
|
||||||
// noinspection deprecation, fix requires api level 23
|
|
||||||
color = getResources().getColor(R.color.key_flag_red);
|
|
||||||
|
|
||||||
actionEncryptFile.setVisibility(View.INVISIBLE);
|
actionEncryptFile.setVisibility(View.INVISIBLE);
|
||||||
actionEncryptText.setVisibility(View.INVISIBLE);
|
actionEncryptText.setVisibility(View.INVISIBLE);
|
||||||
hideFab();
|
hideFab();
|
||||||
qrCodeLayout.setVisibility(View.GONE);
|
qrCodeLayout.setVisibility(View.GONE);
|
||||||
} else if (isSecret) {
|
} else if (!unifiedKeyInfo.is_secure()) {
|
||||||
statusImage.setVisibility(View.GONE);
|
statusImage.setVisibility(View.VISIBLE);
|
||||||
// noinspection deprecation, fix requires api level 23
|
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
||||||
color = getResources().getColor(R.color.key_flag_green);
|
State.INSECURE, R.color.icons, true);
|
||||||
// reload qr code only if the fingerprint changed
|
// noinspection deprecation, fix requires api level 23
|
||||||
if (!Arrays.equals(fingerprint, qrCodeLoaded)) {
|
color = getResources().getColor(R.color.key_flag_red);
|
||||||
loadQrCode(fingerprint);
|
|
||||||
}
|
|
||||||
photoTask.execute(masterKeyId);
|
|
||||||
qrCodeLayout.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
// and place leftOf qr code
|
actionEncryptFile.setVisibility(View.INVISIBLE);
|
||||||
|
actionEncryptText.setVisibility(View.INVISIBLE);
|
||||||
|
hideFab();
|
||||||
|
qrCodeLayout.setVisibility(View.GONE);
|
||||||
|
} else if (unifiedKeyInfo.is_expired()) {
|
||||||
|
statusImage.setVisibility(View.VISIBLE);
|
||||||
|
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
||||||
|
State.EXPIRED, R.color.icons, true);
|
||||||
|
// noinspection deprecation, fix requires api level 23
|
||||||
|
color = getResources().getColor(R.color.key_flag_red);
|
||||||
|
|
||||||
|
actionEncryptFile.setVisibility(View.INVISIBLE);
|
||||||
|
actionEncryptText.setVisibility(View.INVISIBLE);
|
||||||
|
hideFab();
|
||||||
|
qrCodeLayout.setVisibility(View.GONE);
|
||||||
|
} else if (unifiedKeyInfo.has_any_secret()) {
|
||||||
|
statusImage.setVisibility(View.GONE);
|
||||||
|
// noinspection deprecation, fix requires api level 23
|
||||||
|
color = getResources().getColor(R.color.key_flag_green);
|
||||||
|
// reload qr code only if the fingerprint changed
|
||||||
|
if (!Arrays.equals(unifiedKeyInfo.fingerprint(), qrCodeLoaded)) {
|
||||||
|
loadQrCode(unifiedKeyInfo.fingerprint());
|
||||||
|
}
|
||||||
|
photoTask.execute(unifiedKeyInfo.master_key_id());
|
||||||
|
qrCodeLayout.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
// and place leftOf qr code
|
||||||
// RelativeLayout.LayoutParams nameParams = (RelativeLayout.LayoutParams)
|
// RelativeLayout.LayoutParams nameParams = (RelativeLayout.LayoutParams)
|
||||||
// mName.getLayoutParams();
|
// mName.getLayoutParams();
|
||||||
// // remove right margin
|
// // remove right margin
|
||||||
@@ -878,72 +811,67 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
// nameParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout);
|
// nameParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout);
|
||||||
// mName.setLayoutParams(nameParams);
|
// mName.setLayoutParams(nameParams);
|
||||||
|
|
||||||
RelativeLayout.LayoutParams statusParams = (RelativeLayout.LayoutParams)
|
RelativeLayout.LayoutParams statusParams = (RelativeLayout.LayoutParams)
|
||||||
statusText.getLayoutParams();
|
statusText.getLayoutParams();
|
||||||
statusParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0);
|
statusParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0);
|
||||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||||
statusParams.setMarginEnd(0);
|
statusParams.setMarginEnd(0);
|
||||||
}
|
}
|
||||||
statusParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout);
|
statusParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout);
|
||||||
statusText.setLayoutParams(statusParams);
|
statusText.setLayoutParams(statusParams);
|
||||||
|
|
||||||
actionEncryptFile.setVisibility(View.VISIBLE);
|
actionEncryptFile.setVisibility(View.VISIBLE);
|
||||||
actionEncryptText.setVisibility(View.VISIBLE);
|
actionEncryptText.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
showFab();
|
showFab();
|
||||||
// noinspection deprecation (no getDrawable with theme at current minApi level 15!)
|
// noinspection deprecation (no getDrawable with theme at current minApi level 15!)
|
||||||
floatingActionButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_repeat_white_24dp));
|
floatingActionButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_repeat_white_24dp));
|
||||||
} else {
|
} else {
|
||||||
actionEncryptFile.setVisibility(View.VISIBLE);
|
actionEncryptFile.setVisibility(View.VISIBLE);
|
||||||
actionEncryptText.setVisibility(View.VISIBLE);
|
actionEncryptText.setVisibility(View.VISIBLE);
|
||||||
qrCodeLayout.setVisibility(View.GONE);
|
qrCodeLayout.setVisibility(View.GONE);
|
||||||
|
|
||||||
if (isVerified) {
|
if (unifiedKeyInfo.is_verified()) {
|
||||||
statusText.setText(R.string.view_key_verified);
|
statusText.setText(R.string.view_key_verified);
|
||||||
statusImage.setVisibility(View.VISIBLE);
|
statusImage.setVisibility(View.VISIBLE);
|
||||||
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
||||||
State.VERIFIED, R.color.icons, true);
|
State.VERIFIED, R.color.icons, true);
|
||||||
// noinspection deprecation, fix requires api level 23
|
// noinspection deprecation, fix requires api level 23
|
||||||
color = getResources().getColor(R.color.key_flag_green);
|
color = getResources().getColor(R.color.key_flag_green);
|
||||||
photoTask.execute(masterKeyId);
|
photoTask.execute(unifiedKeyInfo.master_key_id());
|
||||||
|
|
||||||
hideFab();
|
hideFab();
|
||||||
} else {
|
} else {
|
||||||
statusText.setText(R.string.view_key_unverified);
|
statusText.setText(R.string.view_key_unverified);
|
||||||
statusImage.setVisibility(View.VISIBLE);
|
statusImage.setVisibility(View.VISIBLE);
|
||||||
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
KeyFormattingUtils.setStatusImage(this, statusImage, statusText,
|
||||||
State.UNVERIFIED, R.color.icons, true);
|
State.UNVERIFIED, R.color.icons, true);
|
||||||
// noinspection deprecation, fix requires api level 23
|
// noinspection deprecation, fix requires api level 23
|
||||||
color = getResources().getColor(R.color.key_flag_orange);
|
color = getResources().getColor(R.color.key_flag_orange);
|
||||||
|
|
||||||
showFab();
|
showFab();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPreviousColor == 0 || mPreviousColor == color) {
|
|
||||||
appBarLayout.setBackgroundColor(color);
|
|
||||||
collapsingToolbarLayout.setContentScrimColor(color);
|
|
||||||
collapsingToolbarLayout.setStatusBarScrimColor(getStatusBarBackgroundColor(color));
|
|
||||||
mPreviousColor = color;
|
|
||||||
} else {
|
|
||||||
ObjectAnimator colorFade =
|
|
||||||
ObjectAnimator.ofObject(appBarLayout, "backgroundColor",
|
|
||||||
new ArgbEvaluator(), mPreviousColor, color);
|
|
||||||
collapsingToolbarLayout.setContentScrimColor(color);
|
|
||||||
collapsingToolbarLayout.setStatusBarScrimColor(getStatusBarBackgroundColor(color));
|
|
||||||
|
|
||||||
colorFade.setDuration(1200);
|
|
||||||
colorFade.start();
|
|
||||||
mPreviousColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
//noinspection deprecation
|
|
||||||
statusImage.setAlpha(80);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mPreviousColor == 0 || mPreviousColor == color) {
|
||||||
|
appBarLayout.setBackgroundColor(color);
|
||||||
|
collapsingToolbarLayout.setContentScrimColor(color);
|
||||||
|
collapsingToolbarLayout.setStatusBarScrimColor(getStatusBarBackgroundColor(color));
|
||||||
|
mPreviousColor = color;
|
||||||
|
} else {
|
||||||
|
ObjectAnimator colorFade =
|
||||||
|
ObjectAnimator.ofObject(appBarLayout, "backgroundColor",
|
||||||
|
new ArgbEvaluator(), mPreviousColor, color);
|
||||||
|
collapsingToolbarLayout.setContentScrimColor(color);
|
||||||
|
collapsingToolbarLayout.setStatusBarScrimColor(getStatusBarBackgroundColor(color));
|
||||||
|
|
||||||
|
colorFade.setDuration(1200);
|
||||||
|
colorFade.start();
|
||||||
|
mPreviousColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection deprecation
|
||||||
|
statusImage.setAlpha(80);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -968,16 +896,11 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
floatingActionButton.setVisibility(View.GONE);
|
floatingActionButton.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoaderReset(Loader<Cursor> loader) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// CryptoOperationHelper.Callback functions
|
// CryptoOperationHelper.Callback functions
|
||||||
|
|
||||||
|
|
||||||
private void updateFromKeyserver() {
|
private void updateFromKeyserver() {
|
||||||
if (fingerprint == null) {
|
if (unifiedKeyInfo == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -993,7 +916,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
public ImportKeyringParcel createOperationInput() {
|
public ImportKeyringParcel createOperationInput() {
|
||||||
HkpKeyserverAddress preferredKeyserver = Preferences.getPreferences(this).getPreferredKeyserver();
|
HkpKeyserverAddress preferredKeyserver = Preferences.getPreferences(this).getPreferredKeyserver();
|
||||||
|
|
||||||
ParcelableKeyRing keyEntry = ParcelableKeyRing.createFromReference(fingerprint, null, null, null);
|
ParcelableKeyRing keyEntry = ParcelableKeyRing.createFromReference(unifiedKeyInfo.fingerprint(), null, null, null);
|
||||||
|
|
||||||
return ImportKeyringParcel.createImportKeyringParcel(Collections.singletonList(keyEntry), preferredKeyserver);
|
return ImportKeyringParcel.createImportKeyringParcel(Collections.singletonList(keyEntry), preferredKeyserver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ import android.arch.lifecycle.ViewModelProviders;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v7.widget.PopupMenu;
|
import android.support.v7.widget.PopupMenu;
|
||||||
import android.support.v7.widget.PopupMenu.OnDismissListener;
|
|
||||||
import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
|
import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -40,8 +40,9 @@ import android.view.ViewGroup;
|
|||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
|
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
|
||||||
import org.sufficientlysecure.keychain.model.KeyMetadata;
|
import org.sufficientlysecure.keychain.model.KeyMetadata;
|
||||||
|
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
import org.sufficientlysecure.keychain.ui.base.LoaderFragment;
|
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity.ViewKeyViewModel;
|
||||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo;
|
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo;
|
||||||
import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeySubkeyStatus;
|
import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeySubkeyStatus;
|
||||||
import org.sufficientlysecure.keychain.ui.keyview.loader.SystemContactDao.SystemContactInfo;
|
import org.sufficientlysecure.keychain.ui.keyview.loader.SystemContactDao.SystemContactInfo;
|
||||||
@@ -56,12 +57,7 @@ import org.sufficientlysecure.keychain.ui.keyview.view.KeyserverStatusView;
|
|||||||
import org.sufficientlysecure.keychain.ui.keyview.view.SystemContactCardView;
|
import org.sufficientlysecure.keychain.ui.keyview.view.SystemContactCardView;
|
||||||
|
|
||||||
|
|
||||||
public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView, OnMenuItemClickListener {
|
public class ViewKeyFragment extends Fragment implements ViewKeyMvpView, OnMenuItemClickListener {
|
||||||
public static final String ARG_MASTER_KEY_ID = "master_key_id";
|
|
||||||
public static final String ARG_IS_SECRET = "is_secret";
|
|
||||||
|
|
||||||
boolean mIsSecret = false;
|
|
||||||
|
|
||||||
private IdentitiesCardView identitiesCardView;
|
private IdentitiesCardView identitiesCardView;
|
||||||
private IdentitiesPresenter identitiesPresenter;
|
private IdentitiesPresenter identitiesPresenter;
|
||||||
|
|
||||||
@@ -76,32 +72,20 @@ public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView, O
|
|||||||
|
|
||||||
private Integer displayedContextMenuPosition;
|
private Integer displayedContextMenuPosition;
|
||||||
|
|
||||||
/**
|
public static ViewKeyFragment newInstance() {
|
||||||
* Creates new instance of this fragment
|
return new ViewKeyFragment();
|
||||||
*/
|
|
||||||
public static ViewKeyFragment newInstance(long masterKeyId, boolean isSecret) {
|
|
||||||
ViewKeyFragment frag = new ViewKeyFragment();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putLong(ARG_MASTER_KEY_ID, masterKeyId);
|
|
||||||
args.putBoolean(ARG_IS_SECRET, isSecret);
|
|
||||||
|
|
||||||
frag.setArguments(args);
|
|
||||||
|
|
||||||
return frag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
|
||||||
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
|
View view = inflater.inflate(R.layout.view_key_fragment, viewGroup, false);
|
||||||
View view = inflater.inflate(R.layout.view_key_fragment, getContainer());
|
|
||||||
|
|
||||||
identitiesCardView = view.findViewById(R.id.card_identities);
|
identitiesCardView = view.findViewById(R.id.card_identities);
|
||||||
|
|
||||||
systemContactCard = view.findViewById(R.id.linked_system_contact_card);
|
systemContactCard = view.findViewById(R.id.linked_system_contact_card);
|
||||||
keyStatusHealth = view.findViewById(R.id.key_status_health);
|
keyStatusHealth = view.findViewById(R.id.key_status_health);
|
||||||
keyStatusKeyserver = view.findViewById(R.id.key_status_keyserver);
|
keyStatusKeyserver = view.findViewById(R.id.key_status_keyserver);
|
||||||
|
|
||||||
return root;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class KeyFragmentViewModel extends ViewModel {
|
public static class KeyFragmentViewModel extends ViewModel {
|
||||||
@@ -143,39 +127,36 @@ public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView, O
|
|||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
long masterKeyId = getArguments().getLong(ARG_MASTER_KEY_ID);
|
ViewKeyViewModel viewKeyViewModel = ViewModelProviders.of(requireActivity()).get(ViewKeyViewModel.class);
|
||||||
mIsSecret = getArguments().getBoolean(ARG_IS_SECRET);
|
viewKeyViewModel.getUnifiedKeyInfoLiveData(requireContext()).observe(this, this::onLoadUnifiedKeyInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
|
||||||
KeyFragmentViewModel model = ViewModelProviders.of(this).get(KeyFragmentViewModel.class);
|
KeyFragmentViewModel model = ViewModelProviders.of(this).get(KeyFragmentViewModel.class);
|
||||||
|
|
||||||
identitiesPresenter = new IdentitiesPresenter(
|
identitiesPresenter = new IdentitiesPresenter(
|
||||||
getContext(), identitiesCardView, this, masterKeyId, mIsSecret);
|
getContext(), identitiesCardView, this, unifiedKeyInfo.master_key_id(), unifiedKeyInfo.has_any_secret());
|
||||||
model.getIdentityInfo(identitiesPresenter).observe(this, identitiesPresenter);
|
model.getIdentityInfo(identitiesPresenter).observe(this, identitiesPresenter);
|
||||||
|
|
||||||
systemContactPresenter = new SystemContactPresenter(
|
systemContactPresenter = new SystemContactPresenter(
|
||||||
getContext(), systemContactCard, masterKeyId, mIsSecret);
|
getContext(), systemContactCard, unifiedKeyInfo.master_key_id(), unifiedKeyInfo.has_any_secret());
|
||||||
model.getSystemContactInfo(systemContactPresenter).observe(this, systemContactPresenter);
|
model.getSystemContactInfo(systemContactPresenter).observe(this, systemContactPresenter);
|
||||||
|
|
||||||
keyHealthPresenter = new KeyHealthPresenter(getContext(), keyStatusHealth, masterKeyId);
|
keyHealthPresenter = new KeyHealthPresenter(getContext(), keyStatusHealth, unifiedKeyInfo.master_key_id());
|
||||||
model.getSubkeyStatus(keyHealthPresenter).observe(this, keyHealthPresenter);
|
model.getSubkeyStatus(keyHealthPresenter).observe(this, keyHealthPresenter);
|
||||||
|
|
||||||
keyserverStatusPresenter = new KeyserverStatusPresenter(
|
keyserverStatusPresenter = new KeyserverStatusPresenter(
|
||||||
getContext(), keyStatusKeyserver, masterKeyId, mIsSecret);
|
getContext(), keyStatusKeyserver, unifiedKeyInfo.master_key_id(), unifiedKeyInfo.has_any_secret());
|
||||||
model.getKeyserverStatus(keyserverStatusPresenter).observe(this, keyserverStatusPresenter);
|
model.getKeyserverStatus(keyserverStatusPresenter).observe(this, keyserverStatusPresenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void switchToFragment(final Fragment frag, final String backStackName) {
|
public void switchToFragment(final Fragment frag, final String backStackName) {
|
||||||
new Handler().post(new Runnable() {
|
new Handler().post(() -> requireFragmentManager().beginTransaction()
|
||||||
@Override
|
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
|
||||||
public void run() {
|
.replace(R.id.view_key_fragment, frag)
|
||||||
getFragmentManager().beginTransaction()
|
.addToBackStack(backStackName)
|
||||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
|
.commit());
|
||||||
.replace(R.id.view_key_fragment, frag)
|
|
||||||
.addToBackStack(backStackName)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -189,10 +170,6 @@ public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView, O
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValidForData(boolean isSecret) {
|
|
||||||
return isSecret == mIsSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startActivityAndShowResultSnackbar(Intent intent) {
|
public void startActivityAndShowResultSnackbar(Intent intent) {
|
||||||
startActivityForResult(intent, 0);
|
startActivityForResult(intent, 0);
|
||||||
@@ -200,26 +177,18 @@ public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView, O
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showDialogFragment(final DialogFragment dialogFragment, final String tag) {
|
public void showDialogFragment(final DialogFragment dialogFragment, final String tag) {
|
||||||
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
|
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(
|
||||||
public void run() {
|
() -> dialogFragment.show(requireFragmentManager(), tag));
|
||||||
dialogFragment.show(getActivity().getSupportFragmentManager(), tag);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showContextMenu(int position, View anchor) {
|
public void showContextMenu(int position, View anchor) {
|
||||||
displayedContextMenuPosition = position;
|
displayedContextMenuPosition = position;
|
||||||
|
|
||||||
PopupMenu menu = new PopupMenu(getContext(), anchor);
|
PopupMenu menu = new PopupMenu(requireContext(), anchor);
|
||||||
menu.inflate(R.menu.identity_context_menu);
|
menu.inflate(R.menu.identity_context_menu);
|
||||||
menu.setOnMenuItemClickListener(this);
|
menu.setOnMenuItemClickListener(this);
|
||||||
menu.setOnDismissListener(new OnDismissListener() {
|
menu.setOnDismissListener(popupMenu -> displayedContextMenuPosition = null);
|
||||||
@Override
|
|
||||||
public void onDismiss(PopupMenu popupMenu) {
|
|
||||||
displayedContextMenuPosition = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.show();
|
menu.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ public class IdentitiesPresenter implements Observer<List<IdentityInfo>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(@Nullable List<IdentityInfo> identityInfos) {
|
public void onChanged(@Nullable List<IdentityInfo> identityInfos) {
|
||||||
viewKeyMvpView.setContentShown(true, false);
|
|
||||||
identitiesAdapter.setData(identityInfos);
|
identitiesAdapter.setData(identityInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ package org.sufficientlysecure.keychain.ui.keyview.presenter;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.arch.lifecycle.LiveData;
|
import android.arch.lifecycle.LiveData;
|
||||||
import android.arch.lifecycle.Observer;
|
import android.arch.lifecycle.Observer;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ public interface ViewKeyMvpView {
|
|||||||
void startActivity(Intent intent);
|
void startActivity(Intent intent);
|
||||||
void startActivityAndShowResultSnackbar(Intent intent);
|
void startActivityAndShowResultSnackbar(Intent intent);
|
||||||
void showDialogFragment(DialogFragment dialogFragment, final String tag);
|
void showDialogFragment(DialogFragment dialogFragment, final String tag);
|
||||||
void setContentShown(boolean show, boolean animate);
|
|
||||||
|
|
||||||
void showContextMenu(int position, View anchor);
|
void showContextMenu(int position, View anchor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ SELECT keys.master_key_id, keys.fingerprint, MIN(user_packets.rank), user_packet
|
|||||||
(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 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.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_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(DISTINCT aTI.package_name) AS autocrypt_package_names_csv,
|
||||||
GROUP_CONCAT(user_packets.user_id, '|||') AS user_id_list
|
GROUP_CONCAT(user_packets.user_id, '|||') AS user_id_list
|
||||||
FROM keys
|
FROM keys
|
||||||
@@ -43,6 +44,7 @@ SELECT keys.master_key_id, keys.fingerprint, MIN(user_packets.rank), user_packet
|
|||||||
(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 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.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_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(DISTINCT aTI.package_name) AS autocrypt_package_names_csv,
|
||||||
GROUP_CONCAT(user_packets.user_id, '|||') AS user_id_list
|
GROUP_CONCAT(user_packets.user_id, '|||') AS user_id_list
|
||||||
FROM keys
|
FROM keys
|
||||||
|
|||||||
Reference in New Issue
Block a user