Allow user to generate new recovery code
diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt
index abd2d8f..15c1d5a 100644
--- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt
+++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt
@@ -1,8 +1,11 @@
package com.stevesoltys.seedvault.ui.recoverycode
+import android.app.Activity.RESULT_OK
+import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
+import android.view.View.GONE
import android.view.View.OnFocusChangeListener
import android.view.View.VISIBLE
import android.view.ViewGroup
@@ -12,9 +15,11 @@
import android.widget.TextView
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
+import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.appcompat.app.AlertDialog
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.Fragment
+import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputLayout
import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.isDebugBuild
@@ -32,6 +37,7 @@
private lateinit var introText: TextView
private lateinit var doneButton: Button
+ private lateinit var newCodeButton: Button
private lateinit var backView: TextView
private lateinit var wordLayout1: TextInputLayout
private lateinit var wordLayout2: TextInputLayout
@@ -61,6 +67,7 @@
introText = v.findViewById(R.id.introText)
doneButton = v.findViewById(R.id.doneButton)
+ newCodeButton = v.findViewById(R.id.newCodeButton)
backView = v.findViewById(R.id.backView)
wordLayout1 = v.findViewById(R.id.wordLayout1)
wordLayout2 = v.findViewById(R.id.wordLayout2)
@@ -103,6 +110,8 @@
editText.setAdapter(adapter)
}
doneButton.setOnClickListener { done() }
+ newCodeButton.visibility = if (forVerifyingNewCode) GONE else VISIBLE
+ newCodeButton.setOnClickListener { generateNewCode() }
viewModel.existingCodeChecked.observeEvent(viewLifecycleOwner,
LiveEventHandler { verified -> onExistingCodeChecked(verified) }
@@ -172,10 +181,38 @@
setPositiveButton(R.string.recovery_code_verification_try_again) { dialog, _ ->
dialog.dismiss()
}
+ setNegativeButton(R.string.recovery_code_verification_generate_new) { dialog, _ ->
+ dialog.dismiss()
+ }
}
}.show()
}
+ private val regenRequest = registerForActivityResult(StartActivityForResult()) {
+ if (it.resultCode == RESULT_OK) {
+ parentFragmentManager.popBackStack()
+ Snackbar.make(requireView(), R.string.recovery_code_recreated, Snackbar.LENGTH_LONG)
+ .show()
+ }
+ }
+
+ private fun generateNewCode() {
+ AlertDialog.Builder(requireContext())
+ .setIcon(R.drawable.ic_warning)
+ .setTitle(R.string.recovery_code_verification_new_dialog_title)
+ .setMessage(R.string.recovery_code_verification_new_dialog_message)
+ .setPositiveButton(R.string.recovery_code_verification_generate_new) { dialog, _ ->
+ dialog.dismiss()
+ // TODO try to delete backups
+ val i = Intent(requireContext(), RecoveryCodeActivity::class.java)
+ regenRequest.launch(i)
+ }
+ .setNegativeButton(android.R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .show()
+ }
+
@Suppress("MagicNumber")
private fun getWordLayout(i: Int) = when (i + 1) {
1 -> wordLayout1
diff --git a/app/src/main/res/layout/fragment_recovery_code_input.xml b/app/src/main/res/layout/fragment_recovery_code_input.xml
index 09e421e..911415e 100644
--- a/app/src/main/res/layout/fragment_recovery_code_input.xml
+++ b/app/src/main/res/layout/fragment_recovery_code_input.xml
@@ -67,7 +67,7 @@
android:layout_marginBottom="8dp"
android:text="@string/recovery_code_done_button"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/newCodeButton"
app:layout_constraintStart_toStartOf="parent" />
<TextView
@@ -86,6 +86,20 @@
app:layout_constraintVertical_bias="1.0"
tools:visibility="visible" />
+ <Button
+ android:id="@+id/newCodeButton"
+ style="@style/Widget.AppCompat.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginBottom="8dp"
+ android:text="@string/recovery_code_verification_generate_new"
+ android:visibility="gone"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/doneButton"
+ tools:visibility="visible" />
+
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f3ac414..7b6c773 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -76,6 +76,10 @@
<string name="recovery_code_verification_error_title">Incorrect Recovery Code</string>
<string name="recovery_code_verification_error_message">You have entered an invalid recovery code. Please try again!\n\nIf you have lost your code, tap on Generate New Code below.</string>
<string name="recovery_code_verification_try_again">Try Again</string>
+ <string name="recovery_code_verification_generate_new">Generate New Code</string>
+ <string name="recovery_code_verification_new_dialog_title">Wait one second…</string>
+ <string name="recovery_code_verification_new_dialog_message">Generating a new code will make your existing backups inaccessible. We\'ll try to delete them if possible.\n\nAre you sure you want to do this?</string>
+ <string name="recovery_code_recreated">New recovery code has been created successfully</string>
<!-- Notification -->
<string name="notification_channel_title">Backup notification</string>