diff options
author | Harsh Shandilya <me@msfjarvis.dev> | 2020-10-01 20:46:21 +0530 |
---|---|---|
committer | Harsh Shandilya <me@msfjarvis.dev> | 2020-10-01 20:46:21 +0530 |
commit | 14b51d580899138bcebc539f45b7560bb1b82308 (patch) | |
tree | 7975e5884fb4f94e942e06660dc8dbbfe4efbe62 | |
parent | 944efee00eafe52bf0748a1375149569325a6b85 (diff) |
Add key selection step to onboarding flow
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
4 files changed, 156 insertions, 9 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/KeySelectionFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/KeySelectionFragment.kt new file mode 100644 index 00000000..66017379 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/KeySelectionFragment.kt @@ -0,0 +1,66 @@ +/* + * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ + +package com.zeapo.pwdstore.ui.onboarding.fragments + +import android.content.Intent +import android.os.Bundle +import android.view.View +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.edit +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import com.zeapo.pwdstore.R +import com.zeapo.pwdstore.crypto.GetKeyIdsActivity +import com.zeapo.pwdstore.databinding.FragmentKeySelectionBinding +import com.zeapo.pwdstore.utils.PasswordRepository +import com.zeapo.pwdstore.utils.PreferenceKeys +import com.zeapo.pwdstore.utils.commitChange +import com.zeapo.pwdstore.utils.finish +import com.zeapo.pwdstore.utils.sharedPrefs +import com.zeapo.pwdstore.utils.viewBinding +import java.io.File +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import me.msfjarvis.openpgpktx.util.OpenPgpApi + +class KeySelectionFragment : Fragment(R.layout.fragment_key_selection) { + + private val settings by lazy { requireActivity().applicationContext.sharedPrefs } + private val binding by viewBinding(FragmentKeySelectionBinding::bind) + + private val gpgKeySelectAction = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == AppCompatActivity.RESULT_OK) { + result.data?.getStringArrayExtra(OpenPgpApi.EXTRA_KEY_IDS)?.let { keyIds -> + lifecycleScope.launch { + withContext(Dispatchers.IO) { + val gpgIdentifierFile = File(PasswordRepository.getRepositoryDirectory(), ".gpg-id") + gpgIdentifierFile.writeText(keyIds.joinToString("\n")) + } + settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) } + requireActivity().commitChange(getString( + R.string.git_commit_gpg_id, + getString(R.string.app_name) + )) + } + } + } else { + throw IllegalStateException("Failed to initialize repository state.") + } + finish() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding.selectKey.setOnClickListener { gpgKeySelectAction.launch(Intent(requireContext(), GetKeyIdsActivity::class.java)) } + } + + companion object { + + fun newInstance() = KeySelectionFragment() + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/RepoLocationFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/RepoLocationFragment.kt index 9e8a8f9d..2253dea8 100644 --- a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/RepoLocationFragment.kt +++ b/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/RepoLocationFragment.kt @@ -14,6 +14,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.content.edit import androidx.fragment.app.Fragment import com.github.ajalt.timberkt.d +import com.github.ajalt.timberkt.e import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.runCatching import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -26,14 +27,14 @@ import com.zeapo.pwdstore.utils.finish import com.zeapo.pwdstore.utils.getString import com.zeapo.pwdstore.utils.isPermissionGranted import com.zeapo.pwdstore.utils.listFilesRecursively +import com.zeapo.pwdstore.utils.performTransactionWithBackStack import com.zeapo.pwdstore.utils.sharedPrefs import com.zeapo.pwdstore.utils.viewBinding import java.io.File class RepoLocationFragment : Fragment(R.layout.fragment_repo_location) { - private val firstRunActivity by lazy { requireActivity() } - private val settings by lazy { firstRunActivity.applicationContext.sharedPrefs } + private val settings by lazy { requireActivity().applicationContext.sharedPrefs } private val binding by viewBinding(FragmentRepoLocationBinding::bind) private val sortOrder: PasswordRepository.PasswordSortOrder get() = PasswordRepository.PasswordSortOrder.getSortOrder(settings) @@ -151,18 +152,14 @@ class RepoLocationFragment : Fragment(R.layout.fragment_repo_location) { if (!PasswordRepository.isInitialized) { PasswordRepository.initialize() } - if (File(localDir.absolutePath + "/.gpg-id").createNewFile()) { - settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) } - } else { - throw IllegalStateException("Failed to initialize repository state.") - } + parentFragmentManager.performTransactionWithBackStack(KeySelectionFragment.newInstance()) }.onFailure { e -> - e.printStackTrace() + e(e) if (!localDir.delete()) { d { "Failed to delete local repository: $localDir" } } + finish() } - finish() } private fun initializeRepositoryInfo() { diff --git a/app/src/main/res/layout/fragment_key_selection.xml b/app/src/main/res/layout/fragment_key_selection.xml new file mode 100644 index 00000000..9a391276 --- /dev/null +++ b/app/src/main/res/layout/fragment_key_selection.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. + ~ SPDX-License-Identifier: GPL-3.0-only + --> + +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/colorPrimary" + android:orientation="vertical"> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/app_icon" + android:layout_width="64dp" + android:layout_height="64dp" + android:layout_marginStart="32dp" + android:layout_marginTop="100dp" + android:contentDescription="@string/app_icon_hint" + android:src="@mipmap/ic_launcher" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/app_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_marginStart="16dp" + android:text="@string/app_name" + android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" + android:textColor="@color/color_control_normal" + android:textStyle="bold" + app:layout_constraintBottom_toBottomOf="@id/app_icon" + app:layout_constraintStart_toEndOf="@id/app_icon" + app:layout_constraintTop_toTopOf="@+id/app_icon" /> + + <TextView + android:id="@+id/gpg_key" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="48dp" + android:text="@string/select_gpg_key_title" + android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4" + android:textColor="@color/color_control_normal" + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0" + app:layout_constraintStart_toStartOf="@id/app_icon" + app:layout_constraintTop_toBottomOf="@id/app_icon" /> + + <TextView + android:id="@+id/gpg_key_text" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="48dp" + android:layout_marginEnd="16dp" + android:text="@string/select_gpg_key_message" + android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" + android:textColor="@color/color_control_normal" + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="@id/gpg_key" + app:layout_constraintTop_toBottomOf="@id/gpg_key" /> + + <com.google.android.material.button.MaterialButton + android:id="@+id/select_key" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="48dp" + android:layout_marginEnd="16dp" + android:maxWidth="300dp" + android:minWidth="100dp" + android:text="@string/gpg_key_select" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/gpg_key_text" /> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 57c32126..4ed3ee52 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -400,6 +400,9 @@ <string name="select_repo_type_text">Select if you want to create a local repo or clone a remote repo.</string> <string name="clone_remote_repo">Clone Remote Repo</string> <string name="create_local_repo">Create Local Repo</string> + <string name="select_gpg_key_title">Select\nGPG\nKey</string> + <string name="select_gpg_key_message">Select a GPG key to initialize your store with</string> + <string name="gpg_key_select">Select key</string> <!-- SSH port validation --> <string name="ssh_scheme_needed_title">Potentially incorrect URL</string> |