use LiveData in LinkedIdWizard and related Fragments

This commit is contained in:
Vincent Breitmoser 2018-06-24 12:41:13 +02:00
parent 2a5b93d9c5
commit 4fcc5253ae
15 changed files with 296 additions and 613 deletions

View file

@ -140,11 +140,6 @@ public class KeychainContract {
.appendPath(PATH_UNIFIED).build();
}
public static Uri buildUnifiedKeyRingUri(Uri uri) {
return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1))
.appendPath(PATH_UNIFIED).build();
}
public static Uri buildUnifiedKeyRingsFindByEmailUri(String email) {
return CONTENT_URI.buildUpon().appendPath(PATH_FIND)
.appendPath(PATH_BY_EMAIL).appendPath(email).build();

View file

@ -17,40 +17,41 @@
package org.sufficientlysecure.keychain.ui;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
import timber.log.Timber;
public class CertifyFingerprintActivity extends BaseActivity {
protected Uri mDataUri;
public static final String EXTRA_MASTER_KEY_ID = "master_key_id";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDataUri = getIntent().getData();
if (mDataUri == null) {
Timber.e("Data missing. Should be uri of key!");
Bundle extras = getIntent().getExtras();
if (extras == null || !extras.containsKey(EXTRA_MASTER_KEY_ID)) {
Timber.e("Missing required extra master_key_id!");
finish();
return;
}
setFullScreenDialogClose(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
setFullScreenDialogClose(v -> finish());
Timber.i("dataUri: " + mDataUri.toString());
long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
UnifiedKeyInfoViewModel viewModel = ViewModelProviders.of(this).get(UnifiedKeyInfoViewModel.class);
viewModel.setMasterKeyId(masterKeyId);
startFragment(savedInstanceState, mDataUri);
if (savedInstanceState == null) {
startFragment();
}
}
@Override
@ -58,24 +59,9 @@ public class CertifyFingerprintActivity extends BaseActivity {
setContentView(R.layout.certify_fingerprint_activity);
}
private void startFragment(Bundle savedInstanceState, Uri dataUri) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create an instance of the fragment
CertifyFingerprintFragment frag = CertifyFingerprintFragment.newInstance(dataUri);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
getSupportFragmentManager().beginTransaction()
.replace(R.id.certify_fingerprint_fragment, frag)
.commitAllowingStateLoss();
// do it immediately!
getSupportFragmentManager().executePendingTransactions();
private void startFragment() {
CertifyFingerprintFragment frag = CertifyFingerprintFragment.newInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.certify_fingerprint_fragment, frag).commit();
}
}

View file

@ -18,79 +18,42 @@
package org.sufficientlysecure.keychain.ui;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import timber.log.Timber;
public class CertifyFingerprintFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
public class CertifyFingerprintFragment extends Fragment {
static final int REQUEST_CERTIFY = 1;
public static final String ARG_DATA_URI = "uri";
private TextView vFingerprint;
private TextView mActionYes;
private TextView mFingerprint;
private TextView mIntro;
private TextView mHeader;
private UnifiedKeyInfoViewModel viewModel;
private static final int LOADER_ID_UNIFIED = 0;
private Uri mDataUri;
/**
* Creates new instance of this fragment
*/
public static CertifyFingerprintFragment newInstance(Uri dataUri) {
CertifyFingerprintFragment frag = new CertifyFingerprintFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_DATA_URI, dataUri);
frag.setArguments(args);
return frag;
public static CertifyFingerprintFragment newInstance() {
return new CertifyFingerprintFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.certify_fingerprint_fragment, viewGroup, false);
TextView actionNo = view.findViewById(R.id.certify_fingerprint_button_no);
mActionYes = view.findViewById(R.id.certify_fingerprint_button_yes);
vFingerprint = view.findViewById(R.id.certify_fingerprint_fingerprint);
mFingerprint = view.findViewById(R.id.certify_fingerprint_fingerprint);
mIntro = view.findViewById(R.id.certify_fingerprint_intro);
mHeader = view.findViewById(R.id.certify_fingerprint_fingerprint_header);
actionNo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().finish();
}
});
mActionYes.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
certify(mDataUri);
}
});
view.findViewById(R.id.certify_fingerprint_button_no).setOnClickListener(v -> requireActivity().finish());
view.findViewById(R.id.certify_fingerprint_button_yes).setOnClickListener(v -> startCertifyActivity());
return view;
}
@ -99,103 +62,35 @@ public class CertifyFingerprintFragment extends Fragment implements LoaderManage
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
if (dataUri == null) {
Timber.e("Data missing. Should be Uri of key!");
getActivity().finish();
viewModel = ViewModelProviders.of(requireActivity()).get(UnifiedKeyInfoViewModel.class);
viewModel.getUnifiedKeyInfoLiveData(requireContext()).observe(this, this::onLoadUnifiedKeyInfo);
}
private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
if (unifiedKeyInfo == null) {
return;
}
loadData(dataUri);
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(unifiedKeyInfo.fingerprint());
vFingerprint.setText(KeyFormattingUtils.formatFingerprint(fingerprint));
}
private void loadData(Uri dataUri) {
mDataUri = dataUri;
Timber.i("dataUri: " + mDataUri.toString());
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
}
static final String[] UNIFIED_PROJECTION = new String[]{
KeyRings._ID, KeyRings.FINGERPRINT,
};
static final int INDEX_UNIFIED_FINGERPRINT = 1;
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ID_UNIFIED: {
Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
}
default:
return null;
}
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
/* TODO better error handling? May cause problems when a key is deleted,
* because the notification triggers faster than the activity closes.
*/
// Avoid NullPointerExceptions...
if (data.getCount() == 0) {
return;
}
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
switch (loader.getId()) {
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT);
displayHexConfirm(fingerprintBlob);
break;
}
}
}
}
private void displayHexConfirm(byte[] fingerprintBlob) {
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintBlob);
mFingerprint.setText(KeyFormattingUtils.formatFingerprint(fingerprint));
}
/**
* This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
* We need to make sure we are no longer using it.
*/
public void onLoaderReset(Loader<Cursor> loader) {
}
private void certify(Uri dataUri) {
long keyId = 0;
try {
keyId = KeyRepository.create(getContext())
.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
} catch (PgpKeyNotFoundException e) {
Timber.e(e, "key not found!");
}
private void startCertifyActivity() {
Intent certifyIntent = new Intent(getActivity(), CertifyKeyActivity.class);
certifyIntent.putExtras(getActivity().getIntent());
certifyIntent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{keyId});
certifyIntent.putExtras(requireActivity().getIntent());
certifyIntent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[] { viewModel.getMasterKeyId() });
startActivityForResult(certifyIntent, REQUEST_CERTIFY);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// always just pass this one through
if (requestCode == REQUEST_CERTIFY) {
getActivity().setResult(resultCode, data);
getActivity().finish();
FragmentActivity activity = requireActivity();
activity.setResult(resultCode, data);
activity.finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}

View file

@ -17,8 +17,11 @@
package org.sufficientlysecure.keychain.ui;
import java.util.Date;
import java.util.HashMap;
import android.app.Activity;
import android.support.v7.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
@ -26,6 +29,7 @@ import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
@ -34,12 +38,11 @@ import android.widget.Spinner;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
import org.sufficientlysecure.keychain.operations.results.DeleteResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.RevokeResult;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.DeleteKeyringParcel;
import org.sufficientlysecure.keychain.service.RevokeKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
@ -48,9 +51,6 @@ import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
import timber.log.Timber;
import java.util.Date;
import java.util.HashMap;
public class DeleteKeyDialogActivity extends FragmentActivity {
public static final String EXTRA_DELETE_MASTER_KEY_IDS = "extra_delete_master_key_ids";
public static final String EXTRA_HAS_SECRET = "extra_has_secret";
@ -81,6 +81,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
log.add(OperationResult.LogType.MSG_DEL_ERROR_MULTI_SECRET, 0);
returnResult(new DeleteResult(OperationResult.RESULT_ERROR, log, 0,
mMasterKeyIds.length));
return;
}
if (mMasterKeyIds.length == 1 && mHasSecret) {

View file

@ -0,0 +1,40 @@
package org.sufficientlysecure.keychain.ui.keyview;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.ViewModel;
import android.content.Context;
import org.sufficientlysecure.keychain.livedata.GenericLiveData;
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
public class UnifiedKeyInfoViewModel extends ViewModel {
private Long masterKeyId;
private LiveData<UnifiedKeyInfo> unifiedKeyInfoLiveData;
public void setMasterKeyId(long masterKeyId) {
if (this.masterKeyId != null) {
throw new IllegalStateException("cannot change masterKeyId once set!");
}
this.masterKeyId = masterKeyId;
}
public long getMasterKeyId() {
return masterKeyId;
}
public 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, KeyRings.buildGenericKeyRingUri(masterKeyId),
() -> keyRepository.getUnifiedKeyInfo(masterKeyId));
}
return unifiedKeyInfoLiveData;
}
}

View file

@ -28,8 +28,6 @@ import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
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.Intent;
@ -70,7 +68,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
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.ImportKeyResult;
@ -269,7 +266,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
qrCodeLayout.setOnClickListener(v -> showQrCodeDialog());
ViewKeyViewModel viewModel = ViewModelProviders.of(this).get(ViewKeyViewModel.class);
UnifiedKeyInfoViewModel viewModel = ViewModelProviders.of(this).get(UnifiedKeyInfoViewModel.class);
viewModel.setMasterKeyId(getIntent().getLongExtra(EXTRA_MASTER_KEY_ID, 0L));
if (savedInstanceState == null && intent.hasExtra(EXTRA_DISPLAY_RESULT)) {
@ -296,30 +293,6 @@ 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, KeyRings.buildGenericKeyRingUri(masterKeyId),
() -> keyRepository.getUnifiedKeyInfo(masterKeyId));
}
return unifiedKeyInfoLiveData;
}
}
@Override
protected void initLayout() {
setContentView(R.layout.view_key_activity);
@ -467,7 +440,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
private void certifyFingerprint() {
Intent intent = new Intent(this, CertifyFingerprintActivity.class);
intent.setData(KeyRings.buildUnifiedKeyRingUri(unifiedKeyInfo.master_key_id()));
intent.putExtra(CertifyFingerprintActivity.EXTRA_MASTER_KEY_ID, unifiedKeyInfo.master_key_id());
startActivityForResult(intent, REQUEST_CERTIFY);
}

View file

@ -46,11 +46,9 @@ import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.provider.AutocryptPeerDao;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.IdentityClickListener;
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity.ViewKeyViewModel;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.AutocryptPeerInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo;
@ -119,7 +117,7 @@ public class ViewKeyFragment extends Fragment implements OnMenuItemClickListener
Context context = requireContext();
ViewKeyViewModel viewKeyViewModel = ViewModelProviders.of(requireActivity()).get(ViewKeyViewModel.class);
UnifiedKeyInfoViewModel viewKeyViewModel = ViewModelProviders.of(requireActivity()).get(UnifiedKeyInfoViewModel.class);
LiveData<UnifiedKeyInfo> unifiedKeyInfoLiveData = viewKeyViewModel.getUnifiedKeyInfoLiveData(requireContext());
unifiedKeyInfoLiveData.observe(this, this::onLoadUnifiedKeyInfo);
@ -277,7 +275,7 @@ public class ViewKeyFragment extends Fragment implements OnMenuItemClickListener
private void addLinkedIdentity() {
Intent intent = new Intent(requireContext(), LinkedIdWizard.class);
intent.setData(KeyRings.buildUnifiedKeyRingUri(unifiedKeyInfo.master_key_id()));
intent.putExtra(LinkedIdWizard.EXTRA_MASTER_KEY_ID, unifiedKeyInfo.master_key_id());
startActivity(intent);
}

View file

@ -17,6 +17,8 @@
package org.sufficientlysecure.keychain.ui.linked;
import android.arch.lifecycle.ViewModelProviders;
import android.graphics.PorterDuff;
import android.os.AsyncTask;
import android.os.Bundle;
@ -25,7 +27,6 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
@ -34,6 +35,7 @@ import android.widget.ViewAnimator;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.linked.LinkedAttribute;
import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
@ -41,68 +43,57 @@ import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
import org.sufficientlysecure.keychain.ui.util.Notify;
public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragment {
protected LinkedIdWizard mLinkedIdWizard;
private ImageView mVerifyImage;
private TextView mVerifyStatus;
private ViewAnimator mVerifyAnimator;
private long masterKeyId;
byte[] fingerprint;
// This is a resource, set AFTER it has been verified
LinkedTokenResource mVerifiedResource = null;
private ViewAnimator mVerifyButtonAnimator;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLinkedIdWizard = (LinkedIdWizard) getActivity();
}
protected abstract View newView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
@Override @NonNull
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
UnifiedKeyInfoViewModel viewModel = ViewModelProviders.of(requireActivity()).get(UnifiedKeyInfoViewModel.class);
viewModel.getUnifiedKeyInfoLiveData(requireContext()).observe(this, this::onLoadUnifiedKeyInfo);
}
private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
this.masterKeyId = unifiedKeyInfo.master_key_id();
this.fingerprint = unifiedKeyInfo.fingerprint();
}
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = newView(inflater, container, savedInstanceState);
View nextButton = view.findViewById(R.id.next_button);
if (nextButton != null) {
nextButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
cryptoOperation();
}
});
nextButton.setOnClickListener(v -> cryptoOperation());
}
view.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLinkedIdWizard.loadFragment(null, null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
}
});
view.findViewById(R.id.back_button).setOnClickListener(
v -> ((LinkedIdWizard) requireActivity()).loadFragment(null, LinkedIdWizard.FRAG_ACTION_TO_LEFT));
mVerifyAnimator = view.findViewById(R.id.verify_progress);
mVerifyImage = view.findViewById(R.id.verify_image);
mVerifyStatus = view.findViewById(R.id.verify_status);
mVerifyButtonAnimator = view.findViewById(R.id.verify_buttons);
view.findViewById(R.id.button_verify).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
proofVerify();
}
});
view.findViewById(R.id.button_verify).setOnClickListener(v -> proofVerify());
view.findViewById(R.id.button_retry).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
proofVerify();
}
});
view.findViewById(R.id.button_retry).setOnClickListener(v -> proofVerify());
setVerifyProgress(false, null);
mVerifyStatus.setText(R.string.linked_verify_pending);
@ -154,7 +145,7 @@ public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragmen
return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
}
LinkedVerifyResult result = resource.verify(getActivity(), mLinkedIdWizard.mFingerprint);
LinkedVerifyResult result = resource.verify(getActivity(), fingerprint);
// ux flow: this operation should take at last a second
timer = System.currentTimeMillis() -timer;
@ -211,7 +202,7 @@ public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragmen
@Override
public Parcelable createOperationInput() {
SaveKeyringParcel.Builder builder=
SaveKeyringParcel.buildChangeKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint);
SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, fingerprint);
WrappedUserAttribute ua = LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute();
builder.addUserAttribute(ua);
return builder.build();
@ -219,7 +210,7 @@ public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragmen
@Override
public void onCryptoOperationSuccess(OperationResult result) {
getActivity().finish();
requireActivity().finish();
}
@Override

View file

@ -33,13 +33,11 @@ import java.util.Random;
import android.app.Activity;
import android.app.Dialog;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@ -47,11 +45,9 @@ import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.app.FragmentActivity;
import android.util.Base64;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.WebView;
@ -69,10 +65,12 @@ import org.sufficientlysecure.keychain.BuildConfig;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.linked.LinkedAttribute;
import org.sufficientlysecure.keychain.linked.resources.GithubResource;
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
@ -109,7 +107,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
}
@Override @NonNull
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.linked_create_github_fragment, container, false);
mButtonContainer = view.findViewById(R.id.button_container);
@ -125,24 +123,15 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
mLinkedIdTitle = view.findViewById(R.id.linked_id_title);
mLinkedIdComment = view.findViewById(R.id.linked_id_comment);
view.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinkedIdWizard activity = (LinkedIdWizard) getActivity();
if (activity == null) {
return;
}
activity.loadFragment(null, null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
}
view.findViewById(R.id.back_button).setOnClickListener(v -> {
LinkedIdWizard activity = (LinkedIdWizard) requireActivity();
activity.loadFragment(null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
});
view.findViewById(R.id.button_send).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
step1GetOAuthCode();
// for animation testing
// onCryptoOperationSuccess(null);
}
view.findViewById(R.id.button_send).setOnClickListener(v -> {
step1GetOAuthCode();
// for animation testing
// onCryptoOperationSuccess(null);
});
return view;
@ -152,34 +141,29 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
LinkedIdWizard wizard = (LinkedIdWizard) getActivity();
mFingerprint = wizard.mFingerprint;
mMasterKeyId = wizard.mMasterKeyId;
UnifiedKeyInfoViewModel viewModel = ViewModelProviders.of(requireActivity()).get(UnifiedKeyInfoViewModel.class);
viewModel.getUnifiedKeyInfoLiveData(requireContext()).observe(this, this::onLoadUnifiedKeyInfo);
}
private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
this.mMasterKeyId = unifiedKeyInfo.master_key_id();
this.mFingerprint = unifiedKeyInfo.fingerprint();
}
private void step1GetOAuthCode() {
setState(State.AUTH_PROCESS);
mButtonContainer.setDisplayedChild(1);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
oAuthRequest("github.com/login/oauth/authorize", BuildConfig.GITHUB_CLIENT_ID, "gist");
}
}, 300);
new Handler().postDelayed(
() -> oAuthRequest("github.com/login/oauth/authorize", BuildConfig.GITHUB_CLIENT_ID, "gist"), 300);
}
private void showRetryForOAuth() {
mRetryButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
v.setOnClickListener(null);
step1GetOAuthCode();
}
mRetryButton.setOnClickListener(v -> {
v.setOnClickListener(null);
step1GetOAuthCode();
});
mButtonContainer.setDisplayedChild(3);
@ -402,14 +386,11 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
setState(State.LID_PROCESS);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
WrappedUserAttribute ua = LinkedAttribute.fromResource(resource).toUserAttribute();
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
mSkpBuilder.addUserAttribute(ua);
cryptoOperation();
}
new Handler().postDelayed(() -> {
WrappedUserAttribute ua = LinkedAttribute.fromResource(resource).toUserAttribute();
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
mSkpBuilder.addUserAttribute(ua);
cryptoOperation();
}, 250);
}
@ -429,31 +410,28 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
mButtonContainer.getInAnimation().setDuration(750);
mButtonContainer.setDisplayedChild(2);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
FragmentActivity activity = getActivity();
Intent intent = ViewKeyActivity.getViewKeyActivityIntent(requireActivity(), mMasterKeyId);
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
new Handler().postDelayed(() -> {
Activity activity = requireActivity();
Intent intent = ViewKeyActivity.getViewKeyActivityIntent(requireActivity(), mMasterKeyId);
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
intent.putExtra(ViewKeyActivity.EXTRA_LINKED_TRANSITION, true);
View linkedItem = mButtonContainer.getChildAt(2);
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
intent.putExtra(ViewKeyActivity.EXTRA_LINKED_TRANSITION, true);
View linkedItem = mButtonContainer.getChildAt(2);
Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(
activity, linkedItem, linkedItem.getTransitionName()).toBundle();
activity.startActivity(intent, options);
mFinishOnStop = true;
} else {
activity.startActivity(intent);
activity.finish();
}
Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(
activity, linkedItem, linkedItem.getTransitionName()).toBundle();
activity.startActivity(intent, options);
mFinishOnStop = true;
} else {
activity.startActivity(intent);
activity.finish();
}
}, 1000);
}
@Override
public void onSaveInstanceState(Bundle outState) {
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// cookies are automatically saved, we don't want that
@ -463,7 +441,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
@ -491,7 +469,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
super.onStop();
if (mFinishOnStop) {
Activity activity = getActivity();
Activity activity = requireActivity();
activity.setResult(Activity.RESULT_OK);
activity.finish();
}
@ -505,14 +483,11 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
@Override
public void onCryptoOperationCancelled() {
mRetryButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
v.setOnClickListener(null);
mButtonContainer.setDisplayedChild(1);
setState(State.LID_PROCESS);
cryptoOperation();
}
mRetryButton.setOnClickListener(v -> {
v.setOnClickListener(null);
mButtonContainer.setDisplayedChild(1);
setState(State.LID_PROCESS);
cryptoOperation();
});
mButtonContainer.setDisplayedChild(3);
setState(State.LID_ERROR);
@ -573,12 +548,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
auth_dialog.setTitle(R.string.linked_webview_title_github);
auth_dialog.setCancelable(true);
auth_dialog.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
step1GetOAuthToken();
}
});
auth_dialog.setOnDismissListener(dialog -> step1GetOAuthToken());
auth_dialog.show();
web.loadUrl("https://" + hostAndPath +

View file

@ -17,24 +17,22 @@
package org.sufficientlysecure.keychain.ui.linked;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
public class LinkedIdCreateHttpsStep1Fragment extends Fragment {
LinkedIdWizard mLinkedIdWizard;
EditText mEditUri;
public static LinkedIdCreateHttpsStep1Fragment newInstance() {
@ -47,44 +45,23 @@ public class LinkedIdCreateHttpsStep1Fragment extends Fragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mLinkedIdWizard = (LinkedIdWizard) getActivity();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.linked_create_https_fragment_step1, container, false);
view.findViewById(R.id.next_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String uri = "https://" + mEditUri.getText();
if (!checkUri(uri)) {
return;
}
String proofText = GenericHttpsResource.generateText(getActivity(),
mLinkedIdWizard.mFingerprint);
LinkedIdCreateHttpsStep2Fragment frag =
LinkedIdCreateHttpsStep2Fragment.newInstance(uri, proofText);
mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
view.findViewById(R.id.next_button).setOnClickListener(v -> {
String uri = "https://" + mEditUri.getText();
if (!checkUri(uri)) {
return;
}
LinkedIdCreateHttpsStep2Fragment frag = LinkedIdCreateHttpsStep2Fragment.newInstance(uri);
((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
});
view.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLinkedIdWizard.loadFragment(null, null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
}
});
view.findViewById(R.id.back_button).setOnClickListener(
v -> ((LinkedIdWizard) requireActivity()).loadFragment(null, LinkedIdWizard.FRAG_ACTION_TO_LEFT));
mEditUri = view.findViewById(R.id.linked_create_https_uri);

View file

@ -17,47 +17,46 @@
package org.sufficientlysecure.keychain.ui.linked;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.FileHelper;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragment {
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.FileHelper;
import timber.log.Timber;
public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragment {
private static final int REQUEST_CODE_OUTPUT = 0x00007007;
public static final String ARG_URI = "uri", ARG_TEXT = "text";
public static final String ARG_URI = "uri";
EditText mEditUri;
URI mResourceUri;
String mResourceString;
public static LinkedIdCreateHttpsStep2Fragment newInstance
(String uri, String proofText) {
public static LinkedIdCreateHttpsStep2Fragment newInstance(String uri) {
LinkedIdCreateHttpsStep2Fragment frag = new LinkedIdCreateHttpsStep2Fragment();
Bundle args = new Bundle();
args.putString(ARG_URI, uri);
args.putString(ARG_TEXT, proofText);
frag.setArguments(args);
return frag;
@ -75,47 +74,33 @@ public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragmen
try {
mResourceUri = new URI(getArguments().getString(ARG_URI));
} catch (URISyntaxException e) {
e.printStackTrace();
getActivity().finish();
Timber.e(e);
requireActivity().finish();
}
mResourceString = getArguments().getString(ARG_TEXT);
}
protected View newView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.linked_create_https_fragment_step2, container, false);
mResourceString = GenericHttpsResource.generateText(requireActivity(), fingerprint);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
protected View newView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.linked_create_https_fragment_step2, container, false);
}
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
if (view != null) {
view.findViewById(R.id.button_send).setOnClickListener(v -> proofSend());
view.findViewById(R.id.button_save).setOnClickListener(v -> proofSave());
view.findViewById(R.id.button_send).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
proofSend();
}
});
view.findViewById(R.id.button_save).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
proofSave();
}
});
mEditUri = view.findViewById(R.id.linked_create_https_uri);
mEditUri.setText(mResourceUri.toString());
}
mEditUri = view.findViewById(R.id.linked_create_https_uri);
mEditUri.setText(mResourceUri.toString());
return view;
}
private void proofSend () {
private void proofSend() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, mResourceString);
@ -123,7 +108,7 @@ public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragmen
startActivity(sendIntent);
}
private void proofSave () {
private void proofSave() {
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
Notify.create(getActivity(), "External storage not available!", Style.ERROR).show();
@ -138,8 +123,7 @@ public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragmen
private void saveFile(Uri uri) {
try {
PrintWriter out =
new PrintWriter(getActivity().getContentResolver().openOutputStream(uri));
PrintWriter out = new PrintWriter(requireActivity().getContentResolver().openOutputStream(uri));
out.print(mResourceString);
if (out.checkError()) {
Notify.create(getActivity(), "Error writing file!", Style.ERROR).show();

View file

@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui.linked;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@ -30,30 +31,14 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.util.Notify;
public class LinkedIdCreateTwitterStep1Fragment extends Fragment {
LinkedIdWizard mLinkedIdWizard;
EditText mEditHandle;
public static LinkedIdCreateTwitterStep1Fragment newInstance() {
LinkedIdCreateTwitterStep1Fragment frag = new LinkedIdCreateTwitterStep1Fragment();
Bundle args = new Bundle();
frag.setArguments(args);
return frag;
return new LinkedIdCreateTwitterStep1Fragment();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mLinkedIdWizard = (LinkedIdWizard) getActivity();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.linked_create_twitter_fragment_step1, container, false);
view.findViewById(R.id.next_button).setOnClickListener(new OnClickListener() {
@ -96,19 +81,15 @@ public class LinkedIdCreateTwitterStep1Fragment extends Fragment {
LinkedIdCreateTwitterStep2Fragment frag =
LinkedIdCreateTwitterStep2Fragment.newInstance(handle);
mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
}
}.execute();
}
});
view.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLinkedIdWizard.loadFragment(null, null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
}
});
view.findViewById(R.id.back_button).setOnClickListener(
v -> ((LinkedIdWizard) requireActivity()).loadFragment(null, LinkedIdWizard.FRAG_ACTION_TO_LEFT));
mEditHandle = view.findViewById(R.id.linked_create_twitter_handle);

View file

@ -17,20 +17,23 @@
package org.sufficientlysecure.keychain.ui.linked;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
import org.sufficientlysecure.keychain.linked.resources.TwitterResource;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
public class LinkedIdCreateTwitterStep2Fragment extends LinkedIdCreateFinalFragment {
@ -39,9 +42,7 @@ public class LinkedIdCreateTwitterStep2Fragment extends LinkedIdCreateFinalFragm
String mResourceHandle;
String mResourceString;
public static LinkedIdCreateTwitterStep2Fragment newInstance
(String handle) {
public static LinkedIdCreateTwitterStep2Fragment newInstance(String handle) {
LinkedIdCreateTwitterStep2Fragment frag = new LinkedIdCreateTwitterStep2Fragment();
Bundle args = new Bundle();
@ -52,39 +53,23 @@ public class LinkedIdCreateTwitterStep2Fragment extends LinkedIdCreateFinalFragm
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mResourceString =
TwitterResource.generate(mLinkedIdWizard.mFingerprint);
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mResourceString = TwitterResource.generate(fingerprint);
mResourceHandle = getArguments().getString(ARG_HANDLE);
}
@NonNull
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
if (view != null) {
view.findViewById(R.id.button_send).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
proofSend();
}
});
view.findViewById(R.id.button_send).setOnClickListener(v -> proofSend());
view.findViewById(R.id.button_share).setOnClickListener(v -> proofShare());
view.findViewById(R.id.button_share).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
proofShare();
}
});
((TextView) view.findViewById(R.id.linked_tweet_published)).setText(
Html.fromHtml(getString(R.string.linked_create_twitter_2_3, mResourceHandle))
);
}
Spanned tweetText = Html.fromHtml(getString(R.string.linked_create_twitter_2_3, mResourceHandle));
((TextView) view.findViewById(R.id.linked_tweet_published)).setText(tweetText);
return view;
}
@ -109,13 +94,12 @@ public class LinkedIdCreateTwitterStep2Fragment extends LinkedIdCreateFinalFragm
}
private void proofSend() {
Uri.Builder builder = Uri.parse("https://twitter.com/intent/tweet").buildUpon();
builder.appendQueryParameter("text", mResourceString);
Uri uri = builder.build();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
getActivity().startActivity(intent);
startActivity(intent);
}
}

View file

@ -17,7 +17,9 @@
package org.sufficientlysecure.keychain.ui.linked;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@ -25,81 +27,33 @@ import android.view.ViewGroup;
import org.sufficientlysecure.keychain.R;
public class LinkedIdSelectFragment extends Fragment {
LinkedIdWizard mLinkedIdWizard;
/**
* Creates new instance of this fragment
*/
public static LinkedIdSelectFragment newInstance() {
LinkedIdSelectFragment frag = new LinkedIdSelectFragment();
Bundle args = new Bundle();
frag.setArguments(args);
return frag;
return new LinkedIdSelectFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.linked_select_fragment, container, false);
view.findViewById(R.id.linked_create_https_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinkedIdCreateHttpsStep1Fragment frag =
LinkedIdCreateHttpsStep1Fragment.newInstance();
view.findViewById(R.id.linked_create_https_button).setOnClickListener(v -> {
LinkedIdCreateHttpsStep1Fragment frag = LinkedIdCreateHttpsStep1Fragment.newInstance();
((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
});
mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
}
});
view.findViewById(R.id.linked_create_twitter_button).setOnClickListener(v -> {
LinkedIdCreateTwitterStep1Fragment frag = LinkedIdCreateTwitterStep1Fragment.newInstance();
((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
});
/*
view.findViewById(R.id.linked_create_dns_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinkedIdCreateDnsStep1Fragment frag =
LinkedIdCreateDnsStep1Fragment.newInstance();
mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
}
});
*/
view.findViewById(R.id.linked_create_twitter_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinkedIdCreateTwitterStep1Fragment frag =
LinkedIdCreateTwitterStep1Fragment.newInstance();
mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
}
});
view.findViewById(R.id.linked_create_github_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinkedIdCreateGithubFragment frag =
LinkedIdCreateGithubFragment.newInstance();
mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
}
});
view.findViewById(R.id.linked_create_github_button).setOnClickListener(v -> {
LinkedIdCreateGithubFragment frag = LinkedIdCreateGithubFragment.newInstance();
((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
});
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mLinkedIdWizard = (LinkedIdWizard) getActivity();
}
}

View file

@ -18,64 +18,60 @@
package org.sufficientlysecure.keychain.ui.linked;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.NavUtils;
import android.support.v4.app.TaskStackBuilder;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
import timber.log.Timber;
public class LinkedIdWizard extends BaseActivity {
public static final String EXTRA_MASTER_KEY_ID = "master_key_id";
public static final int FRAG_ACTION_START = 0;
public static final int FRAG_ACTION_TO_RIGHT = 1;
public static final int FRAG_ACTION_TO_LEFT = 2;
long mMasterKeyId;
byte[] mFingerprint;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(getString(R.string.title_linked_id_create));
try {
Uri uri = getIntent().getData();
uri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(uri);
CachedPublicKeyRing ring = KeyRepository.create(this).getCachedPublicKeyRing(uri);
if (!ring.hasAnySecret()) {
Timber.e("Linked Identities can only be added to secret keys!");
finish();
return;
}
mMasterKeyId = ring.extractOrGetMasterKeyId();
mFingerprint = ring.getFingerprint();
} catch (PgpKeyNotFoundException e) {
Timber.e("Invalid uri given, key does not exist!");
Bundle extras = getIntent().getExtras();
if (extras == null || !extras.containsKey(EXTRA_MASTER_KEY_ID)) {
Timber.e("Missing required extra master_key_id!");
finish();
return;
}
long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
UnifiedKeyInfoViewModel viewModel = ViewModelProviders.of(this).get(UnifiedKeyInfoViewModel.class);
viewModel.setMasterKeyId(masterKeyId);
viewModel.getUnifiedKeyInfoLiveData(this).observe(this, this::onLoadUnifiedKeyInfo);
hideKeyboard();
// pass extras into fragment
LinkedIdSelectFragment frag = LinkedIdSelectFragment.newInstance();
loadFragment(null, frag, FRAG_ACTION_START);
if (savedInstanceState == null) {
LinkedIdSelectFragment frag = LinkedIdSelectFragment.newInstance();
loadFragment(frag, FRAG_ACTION_START);
}
}
private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
if (!unifiedKeyInfo.has_any_secret()) {
Timber.e("Linked Identities can only be added to secret keys!");
finish();
}
}
@Override
@ -83,16 +79,7 @@ public class LinkedIdWizard extends BaseActivity {
setContentView(R.layout.create_key_activity);
}
public void loadFragment(Bundle savedInstanceState, Fragment fragment, int action) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
hideKeyboard();
public void loadFragment(Fragment fragment, int action) {
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
@ -115,50 +102,17 @@ public class LinkedIdWizard extends BaseActivity {
break;
}
// do it immediately!
getSupportFragmentManager().executePendingTransactions();
}
private void hideKeyboard() {
InputMethodManager inputManager = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
// check if no view has focus
View v = getCurrentFocus();
if (v == null)
if (v == null || inputManager == null) {
return;
}
inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
@Override
public void onBackPressed() {
if (!getFragmentManager().popBackStackImmediate()) {
navigateBack();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
navigateBack();
return true;
}
return super.onOptionsItemSelected(item);
}
private void navigateBack() {
Intent upIntent = NavUtils.getParentActivityIntent(this);
upIntent.setData(KeyRings.buildGenericKeyRingUri(mMasterKeyId));
// This activity is NOT part of this app's task, so create a new task
// when navigating up, with a synthesized back stack.
TaskStackBuilder.create(this)
// Add all of this activity's parents to the back stack
.addNextIntentWithParentStack(upIntent)
// Navigate up to the closest parent
.startActivities();
}
}