From 713f3076f4ee1b94f1a1a133fba32a396c0d1039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 10 Feb 2016 16:22:27 +0100 Subject: Backup format v2: redesigned backup code fragment with masked edit text --- .../keychain/pgp/PgpSignEncryptOperation.java | 2 +- .../keychain/ui/BackupCodeFragment.java | 203 ++++++++------------- 2 files changed, 81 insertions(+), 124 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index f1d4d1272..009876045 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -152,7 +152,7 @@ public class PgpSignEncryptOperation extends BaseOperation { } // add proprietary header to indicate that this is a key backup if (input.isAddBackupHeader()) { - armorOut.setHeader("BackupVersion", "1"); + armorOut.setHeader("BackupVersion", "2"); } out = armorOut; } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java index 2d2e43e3b..2cacaea90 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Vincent Breitmoser + * Copyright (C) 2016 Dominik Schürmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,7 +41,7 @@ import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager.OnBackStackChangedListener; import android.text.Editable; -import android.text.TextUtils; +import android.text.InputType; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.Menu; @@ -50,9 +51,12 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; +import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.TextView; +import com.github.pinball83.maskededittext.MaskedEditText; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.ExportResult; @@ -79,12 +83,20 @@ public class BackupCodeFragment extends CryptoOperationFragment=16 - textView.setBackgroundDrawable(null); - } - } + TextView codeDisplayText = (TextView) view.findViewById(R.id.backup_code_display); + setupAutomaticLinebreak(codeDisplayText); - setupEditTextFocusNext(mCodeEditText); - setupEditTextSuccessListener(mCodeEditText); + // set background to null in TextViews - this will retain padding from EditText style! + // noinspection deprecation, setBackground(Drawable) is API level >=16 + codeDisplayText.setBackgroundDrawable(null); + + codeDisplayText.setText(mBackupCode); mStatusAnimator = (ToolableViewAnimator) view.findViewById(R.id.status_animator); mTitleAnimator = (ToolableViewAnimator) view.findViewById(R.id.title_animator); @@ -331,76 +322,66 @@ public class BackupCodeFragment extends CryptoOperationFragment + * NOTE: I was not able to get this behaviour using XML! + * Looks like the order of these method calls matter, see http://stackoverflow.com/a/11171307 + */ + private void setupAutomaticLinebreak(TextView textview) { + textview.setSingleLine(true); + textview.setMaxLines(6); + textview.setHorizontallyScrolling(false); + } - backupCode.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { + private void setupEditTextSuccessListener(final MaskedEditText backupCode) { + backupCode.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } + } - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } - @Override - public void afterTextChanged(Editable s) { - if (s.length() > 6) { - throw new AssertionError("max length of each field is 6!"); - } - - boolean inInputState = mCurrentState == BackupCodeState.STATE_INPUT - || mCurrentState == BackupCodeState.STATE_INPUT_ERROR; - boolean partIsComplete = s.length() == 6; - if (!inInputState || !partIsComplete) { - return; - } - - checkIfCodeIsCorrect(); + @Override + public void afterTextChanged(Editable s) { + boolean inInputState = mCurrentState == BackupCodeState.STATE_INPUT + || mCurrentState == BackupCodeState.STATE_INPUT_ERROR; + boolean partIsComplete = (backupCode.getText().toString().indexOf(' ') == -1); + if (!inInputState || !partIsComplete) { + return; } - }); - } + checkIfCodeIsCorrect(backupCode); + } + }); } - private void checkIfCodeIsCorrect() { + private void checkIfCodeIsCorrect(EditText backupCode) { if (Constants.DEBUG && mDebugModeAcceptAnyCode) { switchState(BackupCodeState.STATE_OK, true); return; } - StringBuilder backupCodeInput = new StringBuilder(26); - for (EditText editText : mCodeEditText) { - if (editText.getText().length() < 6) { - return; - } - backupCodeInput.append(editText.getText()); - backupCodeInput.append('-'); - } - backupCodeInput.deleteCharAt(backupCodeInput.length() - 1); - - // if they don't match, do nothing - if (backupCodeInput.toString().equals(mBackupCode)) { + if (backupCode.toString().equals(mBackupCode)) { switchState(BackupCodeState.STATE_OK, true); return; } switchState(BackupCodeState.STATE_INPUT_ERROR, true); - } private static void animateFlashText( - final TextView[] textViews, int color1, int color2, boolean staySecondColor) { + final TextView textView, int color1, int color2, boolean staySecondColor) { ValueAnimator anim = ValueAnimator.ofObject(new ArgbEvaluator(), color1, color2); anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { - for (TextView textView : textViews) { - textView.setTextColor((Integer) animator.getAnimatedValue()); - } + textView.setTextColor((Integer) animator.getAnimatedValue()); } }); anim.setRepeatMode(ValueAnimator.REVERSE); @@ -411,34 +392,6 @@ public class BackupCodeFragment extends CryptoOperationFragment Date: Wed, 10 Feb 2016 17:15:16 +0100 Subject: Backup format v2: redesign restore dialog --- .../keychain/pgp/PgpDecryptVerifyOperation.java | 2 +- .../keychain/ui/PassphraseDialogActivity.java | 68 ++++++++-------------- 2 files changed, 24 insertions(+), 46 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java index b6f102593..c4755c7c5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java @@ -278,7 +278,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation + * Copyright (C) 2014-2016 Dominik Schürmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,6 +46,8 @@ import android.widget.TextView; import android.widget.Toast; import android.widget.ViewAnimator; +import com.github.pinball83.maskededittext.MaskedEditText; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; @@ -158,7 +160,7 @@ public class PassphraseDialogActivity extends FragmentActivity { public static class PassphraseDialogFragment extends DialogFragment implements TextView.OnEditorActionListener { private EditText mPassphraseEditText; private TextView mPassphraseText; - private EditText[] mBackupCodeEditText; + private MaskedEditText mBackupCodeEditText; private boolean mIsCancelled = false; private RequiredInputParcel mRequiredInput; @@ -185,12 +187,13 @@ public class PassphraseDialogActivity extends FragmentActivity { View view = inflater.inflate(R.layout.passphrase_dialog_backup_code, null); alert.setView(view); - mBackupCodeEditText = new EditText[4]; - mBackupCodeEditText[0] = (EditText) view.findViewById(R.id.backup_code_1); - mBackupCodeEditText[1] = (EditText) view.findViewById(R.id.backup_code_2); - mBackupCodeEditText[2] = (EditText) view.findViewById(R.id.backup_code_3); - mBackupCodeEditText[3] = (EditText) view.findViewById(R.id.backup_code_4); - setupEditTextFocusNext(mBackupCodeEditText); + mBackupCodeEditText = (MaskedEditText) view.findViewById(R.id.backup_code); + // NOTE: order of these method calls matter, see setupAutomaticLinebreak() + mBackupCodeEditText.setInputType( + InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS); + setupAutomaticLinebreak(mBackupCodeEditText); + mBackupCodeEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE); + mBackupCodeEditText.setOnEditorActionListener(this); AlertDialog dialog = alert.create(); dialog.setButton(DialogInterface.BUTTON_POSITIVE, @@ -324,32 +327,16 @@ public class PassphraseDialogActivity extends FragmentActivity { return dialog; } - private static void setupEditTextFocusNext(final EditText[] backupCodes) { - for (int i = 0; i < backupCodes.length - 1; i++) { - - final int next = i + 1; - - backupCodes[i].addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - boolean inserting = before < count; - boolean cursorAtEnd = (start + count) == 6; - - if (inserting && cursorAtEnd) { - backupCodes[next].requestFocus(); - } - } - - @Override - public void afterTextChanged(Editable s) { - } - }); - - } + /** + * Automatic line break with max 6 lines for smaller displays + *

+ * NOTE: I was not able to get this behaviour using XML! + * Looks like the order of these method calls matter, see http://stackoverflow.com/a/11171307 + */ + private void setupAutomaticLinebreak(TextView textview) { + textview.setSingleLine(true); + textview.setMaxLines(6); + textview.setHorizontallyScrolling(false); } @Override @@ -363,17 +350,8 @@ public class PassphraseDialogActivity extends FragmentActivity { public void onClick(View v) { if (mRequiredInput.mType == RequiredInputType.BACKUP_CODE) { - StringBuilder backupCodeInput = new StringBuilder(26); - for (EditText editText : mBackupCodeEditText) { - if (editText.getText().length() < 6) { - return; - } - backupCodeInput.append(editText.getText()); - backupCodeInput.append('-'); - } - backupCodeInput.deleteCharAt(backupCodeInput.length() - 1); - - Passphrase passphrase = new Passphrase(backupCodeInput.toString()); + Passphrase passphrase = + new Passphrase(mBackupCodeEditText.getText().toString()); finishCaching(passphrase); return; -- cgit v1.2.3 From 0feb4d074ce284bfed17e82a3cbc218209aff14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 10 Feb 2016 18:14:36 +0100 Subject: Use non-breaking spaces for backup code MaskedEditText --- .../org/sufficientlysecure/keychain/ui/BackupCodeFragment.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java index 2cacaea90..a9dfaa2c5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java @@ -170,7 +170,11 @@ public class BackupCodeFragment extends CryptoOperationFragment