Backup format v2: redesign restore dialog

This commit is contained in:
Dominik Schürmann
2016-02-10 17:15:16 +01:00
parent 713f3076f4
commit a2ea509f06
3 changed files with 34 additions and 134 deletions

View File

@@ -278,7 +278,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
ArmorHeaders armorHeaders = parseArmorHeaders(in, log, indent); ArmorHeaders armorHeaders = parseArmorHeaders(in, log, indent);
String charset = armorHeaders.charset; String charset = armorHeaders.charset;
boolean useBackupCode = false; boolean useBackupCode = false;
if (armorHeaders.backupVersion != null && armorHeaders.backupVersion == 1) { if (armorHeaders.backupVersion != null && armorHeaders.backupVersion == 2) {
useBackupCode = true; useBackupCode = true;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2014-2016 Dominik Schürmann <dominik@dominikschuermann.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * 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.Toast;
import android.widget.ViewAnimator; import android.widget.ViewAnimator;
import com.github.pinball83.maskededittext.MaskedEditText;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
@@ -158,7 +160,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
public static class PassphraseDialogFragment extends DialogFragment implements TextView.OnEditorActionListener { public static class PassphraseDialogFragment extends DialogFragment implements TextView.OnEditorActionListener {
private EditText mPassphraseEditText; private EditText mPassphraseEditText;
private TextView mPassphraseText; private TextView mPassphraseText;
private EditText[] mBackupCodeEditText; private MaskedEditText mBackupCodeEditText;
private boolean mIsCancelled = false; private boolean mIsCancelled = false;
private RequiredInputParcel mRequiredInput; private RequiredInputParcel mRequiredInput;
@@ -185,12 +187,13 @@ public class PassphraseDialogActivity extends FragmentActivity {
View view = inflater.inflate(R.layout.passphrase_dialog_backup_code, null); View view = inflater.inflate(R.layout.passphrase_dialog_backup_code, null);
alert.setView(view); alert.setView(view);
mBackupCodeEditText = new EditText[4]; mBackupCodeEditText = (MaskedEditText) view.findViewById(R.id.backup_code);
mBackupCodeEditText[0] = (EditText) view.findViewById(R.id.backup_code_1); // NOTE: order of these method calls matter, see setupAutomaticLinebreak()
mBackupCodeEditText[1] = (EditText) view.findViewById(R.id.backup_code_2); mBackupCodeEditText.setInputType(
mBackupCodeEditText[2] = (EditText) view.findViewById(R.id.backup_code_3); InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
mBackupCodeEditText[3] = (EditText) view.findViewById(R.id.backup_code_4); setupAutomaticLinebreak(mBackupCodeEditText);
setupEditTextFocusNext(mBackupCodeEditText); mBackupCodeEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
mBackupCodeEditText.setOnEditorActionListener(this);
AlertDialog dialog = alert.create(); AlertDialog dialog = alert.create();
dialog.setButton(DialogInterface.BUTTON_POSITIVE, dialog.setButton(DialogInterface.BUTTON_POSITIVE,
@@ -324,32 +327,16 @@ public class PassphraseDialogActivity extends FragmentActivity {
return dialog; return dialog;
} }
private static void setupEditTextFocusNext(final EditText[] backupCodes) { /**
for (int i = 0; i < backupCodes.length - 1; i++) { * Automatic line break with max 6 lines for smaller displays
* <p/>
final int next = i + 1; * 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
backupCodes[i].addTextChangedListener(new TextWatcher() { */
@Override private void setupAutomaticLinebreak(TextView textview) {
public void beforeTextChanged(CharSequence s, int start, int count, int after) { textview.setSingleLine(true);
} textview.setMaxLines(6);
textview.setHorizontallyScrolling(false);
@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) {
}
});
}
} }
@Override @Override
@@ -363,17 +350,8 @@ public class PassphraseDialogActivity extends FragmentActivity {
public void onClick(View v) { public void onClick(View v) {
if (mRequiredInput.mType == RequiredInputType.BACKUP_CODE) { if (mRequiredInput.mType == RequiredInputType.BACKUP_CODE) {
StringBuilder backupCodeInput = new StringBuilder(26); Passphrase passphrase =
for (EditText editText : mBackupCodeEditText) { new Passphrase(mBackupCodeEditText.getText().toString());
if (editText.getText().length() < 6) {
return;
}
backupCodeInput.append(editText.getText());
backupCodeInput.append('-');
}
backupCodeInput.deleteCharAt(backupCodeInput.length() - 1);
Passphrase passphrase = new Passphrase(backupCodeInput.toString());
finishCaching(passphrase); finishCaching(passphrase);
return; return;

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -27,99 +28,20 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"> android:layout_marginTop="8dp">
<!-- <com.github.pinball83.maskededittext.MaskedEditText
The most reliable way to correctly size these I found was to put a transparent hint on them. android:id="@+id/backup_code"
Theoretically, this should be what the android:ems attribute is for - didn't work for me.
-->
<EditText
android:id="@+id/backup_code_1"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:hint="ABCDEF" android:layout_marginLeft="16dp"
android:inputType="textNoSuggestions|textCapCharacters" android:layout_marginRight="16dp"
android:maxLength="6" android:textSize="18dp"
android:singleLine="true"
android:textColorHint="@android:color/transparent"
android:textSize="14dp"
android:textStyle="bold" android:textStyle="bold"
android:typeface="monospace" android:typeface="monospace"
tools:ignore="HardcodedText,SpUsage" /> app:mask="****-****-****-****-****-****"
app:maskIconColor="@color/colorPrimary"
<TextView app:notMaskedSymbol="*"
android:layout_width="wrap_content" tools:ignore="SpUsage" />
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="-"
android:textSize="14dp"
android:textStyle="bold"
android:typeface="monospace"
tools:ignore="HardcodedText,SpUsage" />
<EditText
android:id="@+id/backup_code_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:hint="ABCDEF"
android:inputType="textNoSuggestions|textCapCharacters"
android:maxLength="6"
android:singleLine="true"
android:textColorHint="@android:color/transparent"
android:textSize="14dp"
android:textStyle="bold"
android:typeface="monospace"
tools:ignore="HardcodedText,SpUsage" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="-"
android:textSize="14dp"
android:textStyle="bold"
android:typeface="monospace"
tools:ignore="HardcodedText,SpUsage" />
<EditText
android:id="@+id/backup_code_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:hint="ABCDEF"
android:inputType="textNoSuggestions|textCapCharacters"
android:maxLength="6"
android:singleLine="true"
android:textColorHint="@android:color/transparent"
android:textSize="14dp"
android:textStyle="bold"
android:typeface="monospace"
tools:ignore="HardcodedText,SpUsage" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="-"
android:textSize="14dp"
android:textStyle="bold"
android:typeface="monospace"
tools:ignore="HardcodedText,SpUsage" />
<EditText
android:id="@+id/backup_code_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:hint="ABCDEF"
android:inputType="textNoSuggestions|textCapCharacters"
android:maxLength="6"
android:singleLine="true"
android:textColorHint="@android:color/transparent"
android:textSize="14dp"
android:textStyle="bold"
android:typeface="monospace"
tools:ignore="HardcodedText,SpUsage" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>