diff options
Diffstat (limited to 'OpenKeychain/src')
6 files changed, 417 insertions, 292 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java index cc80f8910..8c1555232 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java @@ -20,7 +20,9 @@ package org.sufficientlysecure.keychain.ui; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; +import android.view.MenuItem; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.base.BaseActivity; @@ -39,8 +41,10 @@ public class BackupActivity extends BaseActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + if (savedInstanceState == null) { - BackupCodeDisplayFragment frag = BackupCodeDisplayFragment.newInstance(); + Fragment frag = BackupCodeEntryFragment.newInstance(); FragmentManager fragMan = getSupportFragmentManager(); fragMan.beginTransaction() @@ -50,4 +54,19 @@ public class BackupActivity extends BaseActivity { } } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + FragmentManager fragMan = getSupportFragmentManager(); + // pop from back stack, or if nothing was on there finish activity + if ( ! fragMan.popBackStackImmediate()) { + finish(); + } + return true; + } + return super.onOptionsItemSelected(item); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeDisplayFragment.java deleted file mode 100644 index 89fadd8b7..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeDisplayFragment.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.ui; - - -import java.security.SecureRandom; -import java.util.Random; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.R; - - -public class BackupCodeDisplayFragment extends Fragment { - - public static final String ARG_BACKUP_CODE = "backup_code"; - - private String mBackupCode; - - private TextView vBackupCode; - private Button vOkButton; - - public static BackupCodeDisplayFragment newInstance() { - BackupCodeDisplayFragment frag = new BackupCodeDisplayFragment(); - - Bundle args = new Bundle(); - args.putString(ARG_BACKUP_CODE, generateRandomCode()); - frag.setArguments(args); - - return frag; - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - } - - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.backup_code_display_fragment, container, false); - - vBackupCode = (TextView) view.findViewById(R.id.backup_code); - vOkButton = (Button) view.findViewById(R.id.button_ok); - - return view; - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - if (savedInstanceState == null) { - mBackupCode = getArguments().getString(ARG_BACKUP_CODE); - } else { - mBackupCode = savedInstanceState.getString(ARG_BACKUP_CODE); - } - - vBackupCode.setText(mBackupCode); - - vOkButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - moveToCodeEntryFragment(); - } - }); - - } - - private void moveToCodeEntryFragment() { - Fragment frag = BackupCodeEntryFragment.newInstance(mBackupCode); - getFragmentManager().beginTransaction() - .addToBackStack("backup_code_display") - .replace(R.id.content_frame, frag) - .commit(); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - outState.putString(ARG_BACKUP_CODE, mBackupCode); - } - - @NonNull - private static String generateRandomCode() { - - Random r = new SecureRandom(); - - // simple generation of a 20 character backup code - StringBuilder code = new StringBuilder(28); - for (int i = 0; i < 24; i++) { - if (i == 6 || i == 12 || i == 18) { - code.append('-'); - } - code.append((char) ('A' + r.nextInt(26))); - } - - return code.toString(); - - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java index 5dc16faba..7872fd80e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java @@ -19,28 +19,36 @@ package org.sufficientlysecure.keychain.ui; import java.io.File; +import java.security.SecureRandom; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.Locale; +import java.util.Random; import android.animation.ObjectAnimator; import android.app.Activity; import android.content.Context; +import android.graphics.Color; +import android.graphics.PorterDuff.Mode; +import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.os.Handler; import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; 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.TextWatcher; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.animation.LinearInterpolator; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import android.widget.TextView; import android.widget.ViewAnimator; import org.sufficientlysecure.keychain.Constants; @@ -48,24 +56,35 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.ExportHelper; -public class BackupCodeEntryFragment extends Fragment { +public class BackupCodeEntryFragment extends Fragment implements OnBackStackChangedListener { public static final String ARG_BACKUP_CODE = "backup_code"; + public static final String BACK_STACK_INPUT = "state_display"; private ExportHelper mExportHelper; private EditText[] mCodeEditText; - private ViewAnimator mStatusAnimator, mTitleAnimator; + private TextView[] mCodeDisplayText; + private ViewAnimator mStatusAnimator, mTitleAnimator, mCodeFieldsAnimator; + private int mBackStackLevel; - public static BackupCodeEntryFragment newInstance(String backupCode) { + public static BackupCodeEntryFragment newInstance() { BackupCodeEntryFragment frag = new BackupCodeEntryFragment(); Bundle args = new Bundle(); - args.putString(ARG_BACKUP_CODE, backupCode); + args.putString(ARG_BACKUP_CODE, generateRandomCode()); frag.setArguments(args); return frag; } + enum BackupCodeState { + STATE_UNINITIALIZED, STATE_DISPLAY, STATE_INPUT, STATE_INPUT_ERROR, STATE_OK + } + + StringBuilder mCurrentCodeInput = new StringBuilder("---------------------------"); + BackupCodeState mCurrentState = BackupCodeState.STATE_UNINITIALIZED; + String mBackupCode; + @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -79,7 +98,65 @@ public class BackupCodeEntryFragment extends Fragment { mExportHelper = null; } - String mBackupCode; + void switchState(BackupCodeState state) { + + switch (state) { + case STATE_DISPLAY: + mTitleAnimator.setDisplayedChild(0); + mStatusAnimator.setDisplayedChild(0); + mCodeFieldsAnimator.setDisplayedChild(0); + + break; + + case STATE_INPUT: + mTitleAnimator.setDisplayedChild(1); + mStatusAnimator.setDisplayedChild(1); + mCodeFieldsAnimator.setDisplayedChild(1); + + for (EditText editText : mCodeEditText) { + editText.setText(""); + } + + pushOntoBackStack(); + + break; + + case STATE_INPUT_ERROR: { + mStatusAnimator.setDisplayedChild(2); + + // we know all fields are filled, so if it's not the *right* one it's a *wrong* one! + @ColorInt int black = mCodeEditText[0].getCurrentTextColor(); + @ColorInt int red = getResources().getColor(R.color.android_red_dark); + for (EditText editText : mCodeEditText) { + animateFlashText(editText, black, red, false); + } + + break; + } + + case STATE_OK: { + mTitleAnimator.setDisplayedChild(2); + mStatusAnimator.setDisplayedChild(3); + + hideKeyboard(); + + @ColorInt int black = mCodeEditText[0].getCurrentTextColor(); + @ColorInt int green = getResources().getColor(R.color.android_green_dark); + for (EditText editText : mCodeEditText) { + editText.setEnabled(false); + animateFlashText(editText, black, green, true); + } + + popFromBackStackNoAction(); + + break; + } + + } + + mCurrentState = state; + + } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -93,16 +170,45 @@ public class BackupCodeEntryFragment extends Fragment { mCodeEditText[2] = (EditText) view.findViewById(R.id.backup_code_3); mCodeEditText[3] = (EditText) view.findViewById(R.id.backup_code_4); + mCodeDisplayText = new TextView[4]; + mCodeDisplayText[0] = (TextView) view.findViewById(R.id.backup_code_display_1); + mCodeDisplayText[1] = (TextView) view.findViewById(R.id.backup_code_display_2); + mCodeDisplayText[2] = (TextView) view.findViewById(R.id.backup_code_display_3); + mCodeDisplayText[3] = (TextView) view.findViewById(R.id.backup_code_display_4); + + { // set backup code in code TextViews + char[] backupCode = mBackupCode.toCharArray(); + for (int i = 0; i < mCodeDisplayText.length; i++) { + mCodeDisplayText[i].setText(backupCode, i * 7, 6); + } + } + + { // set background to null in TextViews - this will retain padding from EditText style! + for (TextView textView : mCodeDisplayText) { + // noinspection deprecation, setBackground(Drawable) is API level >=16 + textView.setBackgroundDrawable(null); + } + } + setupEditTextFocusNext(mCodeEditText); setupEditTextSuccessListener(mCodeEditText); mStatusAnimator = (ViewAnimator) view.findViewById(R.id.status_animator); mTitleAnimator = (ViewAnimator) view.findViewById(R.id.title_animator); + mCodeFieldsAnimator = (ViewAnimator) view.findViewById(R.id.code_animator); + + View backupInput = view.findViewById(R.id.button_backup_input); + backupInput.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + switchState(BackupCodeState.STATE_INPUT); + } + }); View backupSave = view.findViewById(R.id.button_backup_save); View backupShare = view.findViewById(R.id.button_backup_share); - backupSave.setOnClickListener(new View.OnClickListener() { + backupSave.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startBackup(true); @@ -112,7 +218,14 @@ public class BackupCodeEntryFragment extends Fragment { return view; } - StringBuilder mCurrentCodeInput = new StringBuilder("---------------------------"); + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + if (mCurrentState == BackupCodeState.STATE_UNINITIALIZED) { + switchState(BackupCodeState.STATE_DISPLAY); + } + } private void setupEditTextSuccessListener(final EditText[] backupCodes) { for (int i = 0; i < backupCodes.length; i++) { @@ -133,6 +246,13 @@ public class BackupCodeEntryFragment extends Fragment { 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; + if (!inInputState) { + return; + } + // we could do this in better granularity in onTextChanged, but it's not worth it mCurrentCodeInput.replace(index, index +s.length(), s.toString()); // if (s.length() == 6) { @@ -154,43 +274,16 @@ public class BackupCodeEntryFragment extends Fragment { // if they don't match, do nothing if (mCurrentCodeInput.toString().equals(mBackupCode)) { - codeInputSuccessful(); + switchState(BackupCodeState.STATE_OK); return; } if (mCurrentCodeInput.toString().startsWith("ABC")) { - codeInputSuccessful(); + switchState(BackupCodeState.STATE_OK); return; } - // we know all fields are filled, so if it's not the *right* one it's a *wrong* one! - @ColorInt int black = mCodeEditText[0].getCurrentTextColor(); - @ColorInt int red = getResources().getColor(R.color.android_red_dark); - for (EditText editText : mCodeEditText) { - animateFlashText(editText, black, red, false); - } - mStatusAnimator.setDisplayedChild(1); - - } - - boolean mSuccessful = false; - private void codeInputSuccessful() { - if (mSuccessful) { - return; - } - mSuccessful = true; - - hideKeyboard(); - - mTitleAnimator.setDisplayedChild(1); - mStatusAnimator.setDisplayedChild(2); - - @ColorInt int black = mCodeEditText[0].getCurrentTextColor(); - @ColorInt int green = getResources().getColor(R.color.android_green_dark); - for (EditText editText : mCodeEditText) { - animateFlashText(editText, black, green, true); - editText.setEnabled(false); - } + switchState(BackupCodeState.STATE_INPUT_ERROR); } @@ -239,6 +332,28 @@ public class BackupCodeEntryFragment extends Fragment { } } + private void pushOntoBackStack() { + FragmentManager fragMan = getFragmentManager(); + mBackStackLevel = fragMan.getBackStackEntryCount(); + fragMan.beginTransaction().addToBackStack(BACK_STACK_INPUT).commit(); + fragMan.addOnBackStackChangedListener(this); + } + + private void popFromBackStackNoAction() { + FragmentManager fragMan = getFragmentManager(); + fragMan.removeOnBackStackChangedListener(this); + fragMan.popBackStack(BACK_STACK_INPUT, FragmentManager.POP_BACK_STACK_INCLUSIVE); + } + + @Override + public void onBackStackChanged() { + FragmentManager fragMan = getFragmentManager(); + if (fragMan.getBackStackEntryCount() == mBackStackLevel) { + fragMan.removeOnBackStackChangedListener(this); + switchState(BackupCodeState.STATE_DISPLAY); + } + } + private void startBackup(boolean exportSecret) { File filename; String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date()); @@ -266,4 +381,23 @@ public class BackupCodeEntryFragment extends Fragment { inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); } + @NonNull + private static String generateRandomCode() { + + Random r = new SecureRandom(); + + // simple generation of a 20 character backup code + StringBuilder code = new StringBuilder(28); + for (int i = 0; i < 24; i++) { + if (i == 6 || i == 12 || i == 18) { + code.append('-'); + } + code.append((char) ('A' + r.nextInt(26))); + } + + return code.toString(); + + } + + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ToolableViewAnimator.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ToolableViewAnimator.java index 18e830139..bd611e6bb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ToolableViewAnimator.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ToolableViewAnimator.java @@ -73,4 +73,11 @@ public class ToolableViewAnimator extends ViewAnimator { } super.addView(child, index, params); } + + @Override + public void setDisplayedChild(int whichChild) { + if (whichChild != getDisplayedChild()) { + super.setDisplayedChild(whichChild); + } + } } diff --git a/OpenKeychain/src/main/res/layout/backup_code_display_fragment.xml b/OpenKeychain/src/main/res/layout/backup_code_display_fragment.xml deleted file mode 100644 index b7fc5150b..000000000 --- a/OpenKeychain/src/main/res/layout/backup_code_display_fragment.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:paddingTop="50dp"> - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:padding="10dp" - android:layout_gravity="center_horizontal" - android:gravity="center_horizontal" - android:text="Your key backup will be secured with this backup code:" - style="?android:textAppearanceMedium" - /> - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:layout_marginTop="20dp" - android:layout_marginBottom="20dp" - android:id="@+id/backup_code" - tools:text="ABCDEF-FGHIJK-KLMNOP-PQRSTU" - android:textStyle="bold" - android:typeface="monospace" - android:textSize="@dimen/abc_text_size_medium_material" /> - - <Button - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:layout_margin="10dp" - android:text="Ok, I wrote it down!" - android:id="@+id/button_ok" - style="?buttonStyle" - /> - -</LinearLayout> diff --git a/OpenKeychain/src/main/res/layout/backup_code_entry_fragment.xml b/OpenKeychain/src/main/res/layout/backup_code_entry_fragment.xml index d6ee84761..b4938d5e9 100644 --- a/OpenKeychain/src/main/res/layout/backup_code_entry_fragment.xml +++ b/OpenKeychain/src/main/res/layout/backup_code_entry_fragment.xml @@ -7,7 +7,6 @@ android:layout_height="match_parent" android:paddingTop="50dp"> - <org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator android:layout_height="wrap_content" android:layout_width="match_parent" @@ -15,7 +14,17 @@ android:id="@+id/title_animator" android:inAnimation="@anim/fade_in" android:outAnimation="@anim/fade_out" - custom:initialView="1"> + custom:initialView="0"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="10dp" + android:layout_gravity="center_horizontal" + android:gravity="center_horizontal" + android:text="The backup will be secured with a backup code. Write it down before you proceed!" + style="?android:textAppearanceMedium" + /> <TextView android:layout_width="wrap_content" @@ -39,100 +48,210 @@ </org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator> - <LinearLayout - android:layout_width="wrap_content" + <org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator android:layout_height="wrap_content" + android:layout_width="match_parent" android:layout_gravity="center_horizontal" - android:layout_marginTop="20dp" - android:layout_marginBottom="20dp" - > + android:id="@+id/code_animator" + android:inAnimation="@anim/fade_in" + android:outAnimation="@anim/fade_out" + android:layout_marginTop="15dp" + android:layout_marginBottom="15dp" + custom:initialView="0"> - <EditText + <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" - android:id="@+id/backup_code_1" - android:textStyle="bold" - android:typeface="monospace" - android:textSize="@dimen/abc_text_size_medium_material" - android:hint="ABCDEF" - android:singleLine="true" - android:inputType="textNoSuggestions|textCapCharacters" - android:maxLength="6" - /> + > - <TextView - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="center_vertical" - android:textStyle="bold" - android:typeface="monospace" - android:textSize="@dimen/abc_text_size_medium_material" - android:text="-" - /> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:id="@+id/backup_code_display_1" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + style="@android:style/Widget.EditText" + android:clickable="false" + android:focusable="false" + tools:text="ABCDEF" + /> - <EditText - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:id="@+id/backup_code_2" - android:textStyle="bold" - android:typeface="monospace" - android:textSize="@dimen/abc_text_size_medium_material" - android:hint="GHIJKL" - android:singleLine="true" - android:inputType="textNoSuggestions|textCapCharacters" - android:maxLength="6" - /> + <TextView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:text="-" + /> - <TextView - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="center_vertical" - android:textStyle="bold" - android:typeface="monospace" - android:textSize="@dimen/abc_text_size_medium_material" - android:text="-" - /> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:id="@+id/backup_code_display_2" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + style="@android:style/Widget.EditText" + android:clickable="false" + android:focusable="false" + tools:text="GHIJKL" + /> - <EditText - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:id="@+id/backup_code_3" - android:textStyle="bold" - android:typeface="monospace" - android:textSize="@dimen/abc_text_size_medium_material" - android:hint="MNOPQR" - android:singleLine="true" - android:inputType="textNoSuggestions|textCapCharacters" - android:maxLength="6" - /> - <TextView - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="center_vertical" - android:textStyle="bold" - android:typeface="monospace" - android:textSize="@dimen/abc_text_size_medium_material" - android:text="-" - /> + <TextView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:text="-" + /> - <EditText + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:id="@+id/backup_code_display_3" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + style="@android:style/Widget.EditText" + android:clickable="false" + android:focusable="false" + tools:text="MNOPQR" + /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:text="-" + /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:id="@+id/backup_code_display_4" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:singleLine="true" + style="@android:style/Widget.EditText" + android:clickable="false" + android:focusable="false" + tools:text="STUVWX" + /> + + </LinearLayout> + + <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" - android:id="@+id/backup_code_4" - android:textStyle="bold" - android:typeface="monospace" - android:textSize="@dimen/abc_text_size_medium_material" - android:hint="STUVWX" - android:singleLine="true" - android:inputType="textNoSuggestions|textCapCharacters" - android:maxLength="6" - /> + > + + <EditText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:id="@+id/backup_code_1" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:singleLine="true" + android:inputType="textNoSuggestions|textCapCharacters" + android:hint="ABCDEF" + android:textColorHint="@android:color/transparent" + android:maxLength="6" + /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:text="-" + /> + + <EditText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:id="@+id/backup_code_2" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:singleLine="true" + android:inputType="textNoSuggestions|textCapCharacters" + android:hint="ABCDEF" + android:textColorHint="@android:color/transparent" + android:maxLength="6" + /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:text="-" + /> + + <EditText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:id="@+id/backup_code_3" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:singleLine="true" + android:inputType="textNoSuggestions|textCapCharacters" + android:hint="ABCDEF" + android:textColorHint="@android:color/transparent" + android:maxLength="6" + /> + <TextView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:text="-" + /> - </LinearLayout> + <EditText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:id="@+id/backup_code_4" + android:textStyle="bold" + android:typeface="monospace" + android:textSize="@dimen/abc_text_size_medium_material" + android:singleLine="true" + android:inputType="textNoSuggestions|textCapCharacters" + android:hint="ABCDEF" + android:textColorHint="@android:color/transparent" + android:maxLength="6" + /> + + </LinearLayout> + + </org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator> <org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator android:layout_height="wrap_content" @@ -140,8 +259,21 @@ android:layout_gravity="center_horizontal" android:id="@+id/status_animator" android:inAnimation="@anim/fade_in_delayed" - android:outAnimation="@anim/fade_out_delayed" - custom:initialView="2"> + android:outAnimation="@anim/fade_out" + custom:initialView="0"> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_margin="10dp" + android:text="Ok, I wrote it down!" + android:drawableLeft="@drawable/ic_check_white_24dp" + android:drawablePadding="8dp" + android:padding="12dp" + android:id="@+id/button_backup_input" + style="?android:buttonBarButtonStyle" + /> <Space android:layout_width="wrap_content" @@ -170,7 +302,7 @@ android:layout_height="wrap_content" android:layout_margin="10dp" android:padding="12dp" - android:text="Share backup…" + android:text="Share backup" android:drawableLeft="@drawable/ic_share_grey_24dp" android:drawablePadding="8dp" android:id="@+id/button_backup_share" @@ -182,7 +314,7 @@ android:layout_height="wrap_content" android:layout_margin="10dp" android:padding="12dp" - android:text="Save backup…" + android:text="Save backup" android:drawableLeft="@drawable/ic_save_grey_24dp" android:drawablePadding="8dp" android:id="@+id/button_backup_save" |