From 5e66d99c852ea67a88b650c03b0e8d55e83eccde Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Sat, 5 Dec 2020 06:07:18 +0530 Subject: Refactor package structure (#1233) * idea: default test runner to Gradle * Kick off package structure revamp * Reparent all classes under dev.msfjarvis.aps Signed-off-by: Harsh Shandilya --- .../com/zeapo/pwdstore/ui/OnOffItemAnimator.kt | 71 -------- .../ui/adapters/PasswordItemRecyclerAdapter.kt | 82 --------- .../zeapo/pwdstore/ui/dialogs/BasicBottomSheet.kt | 161 ----------------- .../ui/dialogs/FolderCreationDialogFragment.kt | 106 ------------ .../pwdstore/ui/dialogs/ItemCreationBottomSheet.kt | 77 --------- .../ui/dialogs/PasswordGeneratorDialogFragment.kt | 101 ----------- .../dialogs/XkPasswordGeneratorDialogFragment.kt | 131 -------------- .../ui/onboarding/activity/OnboardingActivity.kt | 26 --- .../ui/onboarding/fragments/CloneFragment.kt | 59 ------- .../onboarding/fragments/KeySelectionFragment.kt | 66 ------- .../onboarding/fragments/RepoLocationFragment.kt | 192 --------------------- .../ui/onboarding/fragments/WelcomeFragment.kt | 30 ---- .../pwdstore/ui/proxy/ProxySelectorActivity.kt | 75 -------- 13 files changed, 1177 deletions(-) delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/OnOffItemAnimator.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/adapters/PasswordItemRecyclerAdapter.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/dialogs/BasicBottomSheet.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/dialogs/ItemCreationBottomSheet.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/dialogs/PasswordGeneratorDialogFragment.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/dialogs/XkPasswordGeneratorDialogFragment.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/onboarding/activity/OnboardingActivity.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/CloneFragment.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/KeySelectionFragment.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/RepoLocationFragment.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/WelcomeFragment.kt delete mode 100644 app/src/main/java/com/zeapo/pwdstore/ui/proxy/ProxySelectorActivity.kt (limited to 'app/src/main/java/com/zeapo/pwdstore/ui') diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/OnOffItemAnimator.kt b/app/src/main/java/com/zeapo/pwdstore/ui/OnOffItemAnimator.kt deleted file mode 100644 index e394e656..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/OnOffItemAnimator.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.ui - -import androidx.recyclerview.widget.DefaultItemAnimator -import androidx.recyclerview.widget.RecyclerView - -class OnOffItemAnimator : DefaultItemAnimator() { - - var isEnabled: Boolean = true - set(value) { - // Defer update until no animation is running anymore. - isRunning { field = value } - } - - private fun dontAnimate(viewHolder: RecyclerView.ViewHolder): Boolean { - dispatchAnimationFinished(viewHolder) - return false - } - - override fun animateAppearance( - viewHolder: RecyclerView.ViewHolder, - preLayoutInfo: ItemHolderInfo?, - postLayoutInfo: ItemHolderInfo - ): Boolean { - return if (isEnabled) { - super.animateAppearance(viewHolder, preLayoutInfo, postLayoutInfo) - } else { - dontAnimate(viewHolder) - } - } - - override fun animateChange( - oldHolder: RecyclerView.ViewHolder, - newHolder: RecyclerView.ViewHolder, - preInfo: ItemHolderInfo, - postInfo: ItemHolderInfo - ): Boolean { - return if (isEnabled) { - super.animateChange(oldHolder, newHolder, preInfo, postInfo) - } else { - dontAnimate(oldHolder) - } - } - - override fun animateDisappearance( - viewHolder: RecyclerView.ViewHolder, - preLayoutInfo: ItemHolderInfo, - postLayoutInfo: ItemHolderInfo? - ): Boolean { - return if (isEnabled) { - super.animateDisappearance(viewHolder, preLayoutInfo, postLayoutInfo) - } else { - dontAnimate(viewHolder) - } - } - - override fun animatePersistence( - viewHolder: RecyclerView.ViewHolder, - preInfo: ItemHolderInfo, - postInfo: ItemHolderInfo - ): Boolean { - return if (isEnabled) { - super.animatePersistence(viewHolder, preInfo, postInfo) - } else { - dontAnimate(viewHolder) - } - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/adapters/PasswordItemRecyclerAdapter.kt b/app/src/main/java/com/zeapo/pwdstore/ui/adapters/PasswordItemRecyclerAdapter.kt deleted file mode 100644 index 38315876..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/adapters/PasswordItemRecyclerAdapter.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.ui.adapters - -import android.text.SpannableString -import android.text.style.RelativeSizeSpan -import android.view.MotionEvent -import android.view.View -import androidx.appcompat.widget.AppCompatImageView -import androidx.appcompat.widget.AppCompatTextView -import androidx.recyclerview.selection.ItemDetailsLookup -import androidx.recyclerview.selection.Selection -import androidx.recyclerview.widget.RecyclerView -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.SearchableRepositoryAdapter -import com.zeapo.pwdstore.stableId -import com.zeapo.pwdstore.utils.PasswordItem - -open class PasswordItemRecyclerAdapter : - SearchableRepositoryAdapter( - R.layout.password_row_layout, - ::PasswordItemViewHolder, - PasswordItemViewHolder::bind - ) { - - fun makeSelectable(recyclerView: RecyclerView) { - makeSelectable(recyclerView, ::PasswordItemDetailsLookup) - } - - override fun onItemClicked(listener: (holder: PasswordItemViewHolder, item: PasswordItem) -> Unit): PasswordItemRecyclerAdapter { - return super.onItemClicked(listener) as PasswordItemRecyclerAdapter - } - - override fun onSelectionChanged(listener: (selection: Selection) -> Unit): PasswordItemRecyclerAdapter { - return super.onSelectionChanged(listener) as PasswordItemRecyclerAdapter - } - - class PasswordItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - - private val name: AppCompatTextView = itemView.findViewById(R.id.label) - private val childCount: AppCompatTextView = itemView.findViewById(R.id.child_count) - private val folderIndicator: AppCompatImageView = - itemView.findViewById(R.id.folder_indicator) - lateinit var itemDetails: ItemDetailsLookup.ItemDetails - - fun bind(item: PasswordItem) { - val parentPath = item.fullPathToParent.replace("(^/)|(/$)".toRegex(), "") - val source = if (parentPath.isNotEmpty()) { - "$parentPath\n$item" - } else { - "$item" - } - val spannable = SpannableString(source) - spannable.setSpan(RelativeSizeSpan(0.7f), 0, parentPath.length, 0) - name.text = spannable - if (item.type == PasswordItem.TYPE_CATEGORY) { - folderIndicator.visibility = View.VISIBLE - val count = item.file.listFiles { path -> path.isDirectory || path.extension == "gpg" }?.size ?: 0 - childCount.visibility = if (count > 0) View.VISIBLE else View.GONE - childCount.text = "$count" - } else { - childCount.visibility = View.GONE - folderIndicator.visibility = View.GONE - } - itemDetails = object : ItemDetailsLookup.ItemDetails() { - override fun getPosition() = absoluteAdapterPosition - override fun getSelectionKey() = item.stableId - } - } - } - - class PasswordItemDetailsLookup(private val recyclerView: RecyclerView) : - ItemDetailsLookup() { - - override fun getItemDetails(event: MotionEvent): ItemDetails? { - val view = recyclerView.findChildViewUnder(event.x, event.y) ?: return null - return (recyclerView.getChildViewHolder(view) as PasswordItemViewHolder).itemDetails - } - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/BasicBottomSheet.kt b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/BasicBottomSheet.kt deleted file mode 100644 index 6f028009..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/BasicBottomSheet.kt +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package com.zeapo.pwdstore.ui.dialogs - -import android.content.Context -import android.graphics.drawable.GradientDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.ViewTreeObserver -import android.widget.FrameLayout -import androidx.annotation.StringRes -import androidx.core.view.isVisible -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.databinding.BasicBottomSheetBinding -import com.zeapo.pwdstore.utils.resolveAttribute -import com.zeapo.pwdstore.utils.viewBinding - -/** - * [BottomSheetDialogFragment] that exposes a simple [androidx.appcompat.app.AlertDialog] like - * API through [Builder] to create a similar UI, just at the bottom of the screen. - */ -class BasicBottomSheet private constructor( - val title: String?, - val message: String, - val positiveButtonLabel: String?, - val negativeButtonLabel: String?, - val positiveButtonClickListener: View.OnClickListener?, - val negativeButtonClickListener: View.OnClickListener?, -) : BottomSheetDialogFragment() { - - private val binding by viewBinding(BasicBottomSheetBinding::bind) - - private var behavior: BottomSheetBehavior? = null - private val bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() { - override fun onSlide(bottomSheet: View, slideOffset: Float) { - } - - override fun onStateChanged(bottomSheet: View, newState: Int) { - if (newState == BottomSheetBehavior.STATE_COLLAPSED) { - dismiss() - } - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - if (savedInstanceState != null) dismiss() - return layoutInflater.inflate(R.layout.basic_bottom_sheet, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { - override fun onGlobalLayout() { - view.viewTreeObserver.removeOnGlobalLayoutListener(this) - val dialog = dialog as BottomSheetDialog? ?: return - behavior = dialog.behavior - behavior?.apply { - state = BottomSheetBehavior.STATE_EXPANDED - peekHeight = 0 - addBottomSheetCallback(bottomSheetCallback) - } - if (!title.isNullOrEmpty()) { - binding.bottomSheetTitle.isVisible = true - binding.bottomSheetTitle.text = title - } - binding.bottomSheetMessage.text = message - if (positiveButtonClickListener != null) { - positiveButtonLabel?.let { buttonLbl -> - binding.bottomSheetOkButton.text = buttonLbl - } - binding.bottomSheetOkButton.isVisible = true - binding.bottomSheetOkButton.setOnClickListener { - positiveButtonClickListener.onClick(it) - dismiss() - } - } - if (negativeButtonClickListener != null) { - binding.bottomSheetCancelButton.isVisible = true - negativeButtonLabel?.let { buttonLbl -> - binding.bottomSheetCancelButton.text = buttonLbl - } - binding.bottomSheetCancelButton.setOnClickListener { - negativeButtonClickListener.onClick(it) - dismiss() - } - } - } - }) - val gradientDrawable = GradientDrawable().apply { - setColor(requireContext().resolveAttribute(android.R.attr.windowBackground)) - } - view.background = gradientDrawable - } - - override fun dismiss() { - super.dismiss() - behavior?.removeBottomSheetCallback(bottomSheetCallback) - } - - class Builder(val context: Context) { - - private var title: String? = null - private var message: String? = null - private var positiveButtonLabel: String? = null - private var negativeButtonLabel: String? = null - private var positiveButtonClickListener: View.OnClickListener? = null - private var negativeButtonClickListener: View.OnClickListener? = null - - fun setTitleRes(@StringRes titleRes: Int): Builder { - this.title = context.resources.getString(titleRes) - return this - } - - fun setTitle(title: String): Builder { - this.title = title - return this - } - - fun setMessageRes(@StringRes messageRes: Int): Builder { - this.message = context.resources.getString(messageRes) - return this - } - - fun setMessage(message: String): Builder { - this.message = message - return this - } - - fun setPositiveButtonClickListener(buttonLabel: String? = null, listener: View.OnClickListener): Builder { - this.positiveButtonClickListener = listener - this.positiveButtonLabel = buttonLabel - return this - } - - fun setNegativeButtonClickListener(buttonLabel: String? = null, listener: View.OnClickListener): Builder { - this.negativeButtonClickListener = listener - this.negativeButtonLabel = buttonLabel - return this - } - - fun build(): BasicBottomSheet { - require(message != null) { "Message needs to be set" } - return BasicBottomSheet( - title, - message!!, - positiveButtonLabel, - negativeButtonLabel, - positiveButtonClickListener, - negativeButtonClickListener - ) - } - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt deleted file mode 100644 index d5dd9b43..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.ui.dialogs - -import android.app.Dialog -import android.content.Intent -import android.os.Bundle -import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.core.os.bundleOf -import androidx.fragment.app.DialogFragment -import androidx.lifecycle.lifecycleScope -import com.google.android.material.checkbox.MaterialCheckBox -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.textfield.TextInputEditText -import com.google.android.material.textfield.TextInputLayout -import com.zeapo.pwdstore.PasswordStore -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.crypto.BasePgpActivity -import com.zeapo.pwdstore.crypto.GetKeyIdsActivity -import com.zeapo.pwdstore.utils.PasswordRepository -import com.zeapo.pwdstore.utils.commitChange -import com.zeapo.pwdstore.utils.requestInputFocusOnView -import java.io.File -import kotlinx.coroutines.launch -import me.msfjarvis.openpgpktx.util.OpenPgpApi - -class FolderCreationDialogFragment : DialogFragment() { - - private lateinit var newFolder: File - - private val keySelectAction = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == AppCompatActivity.RESULT_OK) { - result.data?.getStringArrayExtra(OpenPgpApi.EXTRA_KEY_IDS)?.let { keyIds -> - val gpgIdentifierFile = File(newFolder, ".gpg-id") - gpgIdentifierFile.writeText(keyIds.joinToString("\n")) - val repo = PasswordRepository.getRepository(null) - if (repo != null) { - lifecycleScope.launch { - val repoPath = PasswordRepository.getRepositoryDirectory().absolutePath - requireActivity().commitChange( - getString( - R.string.git_commit_gpg_id, - BasePgpActivity.getLongName(gpgIdentifierFile.parentFile!!.absolutePath, repoPath, gpgIdentifierFile.name) - ), - ) - dismiss() - } - } - } - } - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val alertDialogBuilder = MaterialAlertDialogBuilder(requireContext()) - alertDialogBuilder.setTitle(R.string.title_create_folder) - alertDialogBuilder.setView(R.layout.folder_dialog_fragment) - alertDialogBuilder.setPositiveButton(getString(R.string.button_create), null) - alertDialogBuilder.setNegativeButton(getString(android.R.string.cancel)) { _, _ -> - dismiss() - } - val dialog = alertDialogBuilder.create() - dialog.requestInputFocusOnView(R.id.folder_name_text) - dialog.setOnShowListener { - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { - createDirectory(requireArguments().getString(CURRENT_DIR_EXTRA)!!) - } - } - return dialog - } - - private fun createDirectory(currentDir: String) { - val dialog = requireDialog() - val folderNameView = dialog.findViewById(R.id.folder_name_text) - val folderNameViewContainer = dialog.findViewById(R.id.folder_name_container) - newFolder = File("$currentDir/${folderNameView.text}") - folderNameViewContainer.error = when { - newFolder.isFile -> getString(R.string.folder_creation_err_file_exists) - newFolder.isDirectory -> getString(R.string.folder_creation_err_folder_exists) - else -> null - } - if (folderNameViewContainer.error != null) return - newFolder.mkdirs() - (requireActivity() as PasswordStore).refreshPasswordList(newFolder) - if (dialog.findViewById(R.id.set_gpg_key).isChecked) { - keySelectAction.launch(Intent(requireContext(), GetKeyIdsActivity::class.java)) - return - } else { - dismiss() - } - } - - companion object { - - private const val CURRENT_DIR_EXTRA = "CURRENT_DIRECTORY" - fun newInstance(startingDirectory: String): FolderCreationDialogFragment { - val extras = bundleOf(CURRENT_DIR_EXTRA to startingDirectory) - val fragment = FolderCreationDialogFragment() - fragment.arguments = extras - return fragment - } - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/ItemCreationBottomSheet.kt b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/ItemCreationBottomSheet.kt deleted file mode 100644 index 5acc8091..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/ItemCreationBottomSheet.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.ui.dialogs - -import android.graphics.drawable.GradientDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.ViewTreeObserver -import android.widget.FrameLayout -import androidx.core.os.bundleOf -import androidx.fragment.app.setFragmentResult -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import com.zeapo.pwdstore.PasswordFragment.Companion.ACTION_FOLDER -import com.zeapo.pwdstore.PasswordFragment.Companion.ACTION_KEY -import com.zeapo.pwdstore.PasswordFragment.Companion.ACTION_PASSWORD -import com.zeapo.pwdstore.PasswordFragment.Companion.ITEM_CREATION_REQUEST_KEY -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.utils.resolveAttribute - -class ItemCreationBottomSheet : BottomSheetDialogFragment() { - - private var behavior: BottomSheetBehavior? = null - private val bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() { - override fun onSlide(bottomSheet: View, slideOffset: Float) { - } - - override fun onStateChanged(bottomSheet: View, newState: Int) { - if (newState == BottomSheetBehavior.STATE_COLLAPSED) { - dismiss() - } - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - if (savedInstanceState != null) dismiss() - return inflater.inflate(R.layout.item_create_sheet, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { - override fun onGlobalLayout() { - view.viewTreeObserver.removeOnGlobalLayoutListener(this) - val dialog = dialog as BottomSheetDialog? ?: return - behavior = dialog.behavior - behavior?.apply { - state = BottomSheetBehavior.STATE_EXPANDED - peekHeight = 0 - addBottomSheetCallback(bottomSheetCallback) - } - dialog.findViewById(R.id.create_folder)?.setOnClickListener { - setFragmentResult(ITEM_CREATION_REQUEST_KEY, bundleOf(ACTION_KEY to ACTION_FOLDER)) - dismiss() - } - dialog.findViewById(R.id.create_password)?.setOnClickListener { - setFragmentResult(ITEM_CREATION_REQUEST_KEY, bundleOf(ACTION_KEY to ACTION_PASSWORD)) - dismiss() - } - } - }) - val gradientDrawable = GradientDrawable().apply { - setColor(requireContext().resolveAttribute(android.R.attr.windowBackground)) - } - view.background = gradientDrawable - } - - override fun dismiss() { - super.dismiss() - behavior?.removeBottomSheetCallback(bottomSheetCallback) - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/PasswordGeneratorDialogFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/PasswordGeneratorDialogFragment.kt deleted file mode 100644 index 7aa66a03..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/PasswordGeneratorDialogFragment.kt +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.ui.dialogs - -import android.annotation.SuppressLint -import android.app.AlertDialog -import android.app.Dialog -import android.content.Context -import android.graphics.Typeface -import android.os.Bundle -import android.widget.CheckBox -import android.widget.EditText -import android.widget.Toast -import androidx.annotation.IdRes -import androidx.appcompat.widget.AppCompatEditText -import androidx.appcompat.widget.AppCompatTextView -import androidx.fragment.app.DialogFragment -import com.github.michaelbull.result.getOrElse -import com.github.michaelbull.result.runCatching -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.pwgen.PasswordGenerator -import com.zeapo.pwdstore.pwgen.PasswordGenerator.generate -import com.zeapo.pwdstore.pwgen.PasswordGenerator.setPrefs -import com.zeapo.pwdstore.pwgen.PasswordOption -import com.zeapo.pwdstore.utils.PreferenceKeys - -class PasswordGeneratorDialogFragment : DialogFragment() { - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val callingActivity = requireActivity() - val inflater = callingActivity.layoutInflater - - @SuppressLint("InflateParams") - val view = inflater.inflate(R.layout.fragment_pwgen, null) - val monoTypeface = Typeface.createFromAsset(callingActivity.assets, "fonts/sourcecodepro.ttf") - val prefs = requireActivity().applicationContext - .getSharedPreferences("PasswordGenerator", Context.MODE_PRIVATE) - - view.findViewById(R.id.numerals)?.isChecked = !prefs.getBoolean(PasswordOption.NoDigits.key, false) - view.findViewById(R.id.symbols)?.isChecked = prefs.getBoolean(PasswordOption.AtLeastOneSymbol.key, false) - view.findViewById(R.id.uppercase)?.isChecked = !prefs.getBoolean(PasswordOption.NoUppercaseLetters.key, false) - view.findViewById(R.id.lowercase)?.isChecked = !prefs.getBoolean(PasswordOption.NoLowercaseLetters.key, false) - view.findViewById(R.id.ambiguous)?.isChecked = !prefs.getBoolean(PasswordOption.NoAmbiguousCharacters.key, false) - view.findViewById(R.id.pronounceable)?.isChecked = !prefs.getBoolean(PasswordOption.FullyRandom.key, true) - - val textView: AppCompatEditText = view.findViewById(R.id.lengthNumber) - textView.setText(prefs.getInt(PreferenceKeys.LENGTH, 20).toString()) - val passwordText: AppCompatTextView = view.findViewById(R.id.passwordText) - passwordText.typeface = monoTypeface - return MaterialAlertDialogBuilder(requireContext()).run { - setTitle(R.string.pwgen_title) - setView(view) - setPositiveButton(R.string.dialog_ok) { _, _ -> - val edit = callingActivity.findViewById(R.id.password) - edit.setText(passwordText.text) - } - setNeutralButton(R.string.dialog_cancel) { _, _ -> } - setNegativeButton(R.string.pwgen_generate, null) - create() - }.apply { - setOnShowListener { - generate(passwordText) - getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener { - generate(passwordText) - } - } - } - } - - private fun generate(passwordField: AppCompatTextView) { - setPreferences() - passwordField.text = runCatching { - generate(requireContext().applicationContext) - }.getOrElse { e -> - Toast.makeText(requireActivity(), e.message, Toast.LENGTH_SHORT).show() - "" - } - } - - private fun isChecked(@IdRes id: Int): Boolean { - return requireDialog().findViewById(id).isChecked - } - - private fun setPreferences() { - val preferences = listOfNotNull( - PasswordOption.NoDigits.takeIf { !isChecked(R.id.numerals) }, - PasswordOption.AtLeastOneSymbol.takeIf { isChecked(R.id.symbols) }, - PasswordOption.NoUppercaseLetters.takeIf { !isChecked(R.id.uppercase) }, - PasswordOption.NoAmbiguousCharacters.takeIf { !isChecked(R.id.ambiguous) }, - PasswordOption.FullyRandom.takeIf { !isChecked(R.id.pronounceable) }, - PasswordOption.NoLowercaseLetters.takeIf { !isChecked(R.id.lowercase) } - ) - val lengthText = requireDialog().findViewById(R.id.lengthNumber).text.toString() - val length = lengthText.toIntOrNull()?.takeIf { it >= 0 } - ?: PasswordGenerator.DEFAULT_LENGTH - setPrefs(requireActivity().applicationContext, preferences, length) - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/XkPasswordGeneratorDialogFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/XkPasswordGeneratorDialogFragment.kt deleted file mode 100644 index 274330bb..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/XkPasswordGeneratorDialogFragment.kt +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.ui.dialogs - -import android.app.Dialog -import android.content.Context -import android.content.SharedPreferences -import android.graphics.Typeface -import android.os.Bundle -import android.widget.EditText -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.widget.AppCompatTextView -import androidx.core.content.edit -import androidx.fragment.app.DialogFragment -import com.github.ajalt.timberkt.Timber.tag -import com.github.michaelbull.result.fold -import com.github.michaelbull.result.getOr -import com.github.michaelbull.result.runCatching -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.databinding.FragmentXkpwgenBinding -import com.zeapo.pwdstore.pwgenxkpwd.CapsType -import com.zeapo.pwdstore.pwgenxkpwd.PasswordBuilder -import com.zeapo.pwdstore.utils.getString - -/** A placeholder fragment containing a simple view. */ -class XkPasswordGeneratorDialogFragment : DialogFragment() { - - private lateinit var prefs: SharedPreferences - private lateinit var binding: FragmentXkpwgenBinding - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val builder = MaterialAlertDialogBuilder(requireContext()) - val callingActivity = requireActivity() - val inflater = callingActivity.layoutInflater - binding = FragmentXkpwgenBinding.inflate(inflater) - - val monoTypeface = Typeface.createFromAsset(callingActivity.assets, "fonts/sourcecodepro.ttf") - - builder.setView(binding.root) - - prefs = callingActivity.getSharedPreferences("PasswordGenerator", Context.MODE_PRIVATE) - - val previousStoredCapStyle: String = runCatching { - prefs.getString(PREF_KEY_CAPITALS_STYLE)!! - }.getOr(DEFAULT_CAPS_STYLE) - - val lastCapitalsStyleIndex: Int = runCatching { - CapsType.valueOf(previousStoredCapStyle).ordinal - }.getOr(DEFAULT_CAPS_INDEX) - binding.xkCapType.setSelection(lastCapitalsStyleIndex) - binding.xkNumWords.setText(prefs.getString(PREF_KEY_NUM_WORDS, DEFAULT_NUMBER_OF_WORDS)) - - binding.xkSeparator.setText(prefs.getString(PREF_KEY_SEPARATOR, DEFAULT_WORD_SEPARATOR)) - binding.xkNumberSymbolMask.setText(prefs.getString(PREF_KEY_EXTRA_SYMBOLS_MASK, DEFAULT_EXTRA_SYMBOLS_MASK)) - - binding.xkPasswordText.typeface = monoTypeface - - builder.setPositiveButton(resources.getString(R.string.dialog_ok)) { _, _ -> - setPreferences() - val edit = callingActivity.findViewById(R.id.password) - edit.setText(binding.xkPasswordText.text) - } - - // flip neutral and negative buttons - builder.setNeutralButton(resources.getString(R.string.dialog_cancel)) { _, _ -> } - builder.setNegativeButton(resources.getString(R.string.pwgen_generate), null) - - val dialog = builder.setTitle(this.resources.getString(R.string.xkpwgen_title)).create() - - dialog.setOnShowListener { - setPreferences() - makeAndSetPassword(binding.xkPasswordText) - - dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener { - setPreferences() - makeAndSetPassword(binding.xkPasswordText) - } - } - return dialog - } - - private fun makeAndSetPassword(passwordText: AppCompatTextView) { - PasswordBuilder(requireContext()) - .setNumberOfWords(Integer.valueOf(binding.xkNumWords.text.toString())) - .setMinimumWordLength(DEFAULT_MIN_WORD_LENGTH) - .setMaximumWordLength(DEFAULT_MAX_WORD_LENGTH) - .setSeparator(binding.xkSeparator.text.toString()) - .appendNumbers(binding.xkNumberSymbolMask.text!!.count { c -> c == EXTRA_CHAR_PLACEHOLDER_DIGIT }) - .appendSymbols(binding.xkNumberSymbolMask.text!!.count { c -> c == EXTRA_CHAR_PLACEHOLDER_SYMBOL }) - .setCapitalization(CapsType.valueOf(binding.xkCapType.selectedItem.toString())).create() - .fold( - success = { passwordText.text = it }, - failure = { e -> - Toast.makeText(requireActivity(), e.message, Toast.LENGTH_SHORT).show() - tag("xkpw").e(e, "failure generating xkpasswd") - passwordText.text = FALLBACK_ERROR_PASS - }, - ) - } - - private fun setPreferences() { - prefs.edit { - putString(PREF_KEY_CAPITALS_STYLE, binding.xkCapType.selectedItem.toString()) - putString(PREF_KEY_NUM_WORDS, binding.xkNumWords.text.toString()) - putString(PREF_KEY_SEPARATOR, binding.xkSeparator.text.toString()) - putString(PREF_KEY_EXTRA_SYMBOLS_MASK, binding.xkNumberSymbolMask.text.toString()) - } - } - - companion object { - - const val PREF_KEY_CAPITALS_STYLE = "pref_key_capitals_style" - const val PREF_KEY_NUM_WORDS = "pref_key_num_words" - const val PREF_KEY_SEPARATOR = "pref_key_separator" - const val PREF_KEY_EXTRA_SYMBOLS_MASK = "pref_key_xkpwgen_extra_symbols_mask" - val DEFAULT_CAPS_STYLE = CapsType.Sentence.name - val DEFAULT_CAPS_INDEX = CapsType.Sentence.ordinal - const val DEFAULT_NUMBER_OF_WORDS = "3" - const val DEFAULT_WORD_SEPARATOR = "." - const val DEFAULT_EXTRA_SYMBOLS_MASK = "ds" - const val DEFAULT_MIN_WORD_LENGTH = 3 - const val DEFAULT_MAX_WORD_LENGTH = 9 - const val FALLBACK_ERROR_PASS = "42" - const val EXTRA_CHAR_PLACEHOLDER_DIGIT = 'd' - const val EXTRA_CHAR_PLACEHOLDER_SYMBOL = 's' - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/activity/OnboardingActivity.kt b/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/activity/OnboardingActivity.kt deleted file mode 100644 index b81efb4c..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/activity/OnboardingActivity.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright © 2019-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package com.zeapo.pwdstore.ui.onboarding.activity - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.zeapo.pwdstore.R - -class OnboardingActivity : AppCompatActivity(R.layout.activity_onboarding) { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - supportActionBar?.hide() - } - - override fun onBackPressed() { - if (supportFragmentManager.backStackEntryCount == 0) { - finishAffinity() - } else { - super.onBackPressed() - } - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/CloneFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/CloneFragment.kt deleted file mode 100644 index acd0151c..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/CloneFragment.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright © 2019-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.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 com.zeapo.pwdstore.R -import com.zeapo.pwdstore.databinding.FragmentCloneBinding -import com.zeapo.pwdstore.git.GitServerConfigActivity -import com.zeapo.pwdstore.utils.PreferenceKeys -import com.zeapo.pwdstore.utils.finish -import com.zeapo.pwdstore.utils.performTransactionWithBackStack -import com.zeapo.pwdstore.utils.sharedPrefs -import com.zeapo.pwdstore.utils.viewBinding - -class CloneFragment : Fragment(R.layout.fragment_clone) { - - private val binding by viewBinding(FragmentCloneBinding::bind) - - private val settings by lazy(LazyThreadSafetyMode.NONE) { requireActivity().applicationContext.sharedPrefs } - - private val cloneAction = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == AppCompatActivity.RESULT_OK) { - settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) } - finish() - } - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding.cloneRemote.setOnClickListener { - cloneToHiddenDir() - } - binding.createLocal.setOnClickListener { - parentFragmentManager.performTransactionWithBackStack(RepoLocationFragment.newInstance()) - } - } - - /** - * Clones a remote Git repository to the app's private directory - */ - private fun cloneToHiddenDir() { - settings.edit { putBoolean(PreferenceKeys.GIT_EXTERNAL, false) } - cloneAction.launch(GitServerConfigActivity.createCloneIntent(requireContext())) - } - - companion object { - - fun newInstance(): CloneFragment = CloneFragment() - } -} 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 deleted file mode 100644 index 3dc03954..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/KeySelectionFragment.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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(LazyThreadSafetyMode.NONE) { 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 deleted file mode 100644 index bea0ce3e..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/RepoLocationFragment.kt +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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.Manifest -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 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 -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.UserPreference -import com.zeapo.pwdstore.databinding.FragmentRepoLocationBinding -import com.zeapo.pwdstore.utils.PasswordRepository -import com.zeapo.pwdstore.utils.PasswordSortOrder -import com.zeapo.pwdstore.utils.PreferenceKeys -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 settings by lazy(LazyThreadSafetyMode.NONE) { requireActivity().applicationContext.sharedPrefs } - private val binding by viewBinding(FragmentRepoLocationBinding::bind) - private val sortOrder: PasswordSortOrder - get() = PasswordSortOrder.getSortOrder(settings) - - private val repositoryInitAction = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == AppCompatActivity.RESULT_OK) { - initializeRepositoryInfo() - } - } - - private val externalDirectorySelectAction = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == AppCompatActivity.RESULT_OK) { - if (checkExternalDirectory()) { - finish() - } else { - createRepository() - } - } - } - - private val externalDirPermGrantedAction = createPermGrantedAction { - externalDirectorySelectAction.launch(UserPreference.createDirectorySelectionIntent(requireContext())) - } - - private val repositoryUsePermGrantedAction = createPermGrantedAction { - initializeRepositoryInfo() - } - - private val repositoryChangePermGrantedAction = createPermGrantedAction { - repositoryInitAction.launch(UserPreference.createDirectorySelectionIntent(requireContext())) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding.hidden.setOnClickListener { - createRepoInHiddenDir() - } - - binding.sdcard.setOnClickListener { - createRepoFromExternalDir() - } - } - - /** - * Initializes an empty repository in the app's private directory - */ - private fun createRepoInHiddenDir() { - settings.edit { - putBoolean(PreferenceKeys.GIT_EXTERNAL, false) - remove(PreferenceKeys.GIT_EXTERNAL_REPO) - } - initializeRepositoryInfo() - } - - /** - * Initializes an empty repository in a selected directory if one does not already exist - */ - private fun createRepoFromExternalDir() { - settings.edit { putBoolean(PreferenceKeys.GIT_EXTERNAL, true) } - val externalRepo = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO) - if (externalRepo == null) { - if (!isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - externalDirPermGrantedAction.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) - } else { - // Unlikely we have storage permissions without user ever selecting a directory, - // but let's not assume. - externalDirectorySelectAction.launch(UserPreference.createDirectorySelectionIntent(requireContext())) - } - } else { - MaterialAlertDialogBuilder(requireActivity()) - .setTitle(resources.getString(R.string.directory_selected_title)) - .setMessage(resources.getString(R.string.directory_selected_message, externalRepo)) - .setPositiveButton(resources.getString(R.string.use)) { _, _ -> - if (!isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - repositoryUsePermGrantedAction.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) - } else { - initializeRepositoryInfo() - } - } - .setNegativeButton(resources.getString(R.string.change)) { _, _ -> - if (!isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - repositoryChangePermGrantedAction.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) - } else { - repositoryInitAction.launch(UserPreference.createDirectorySelectionIntent(requireContext())) - } - } - .show() - } - } - - private fun checkExternalDirectory(): Boolean { - if (settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false) && - settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO) != null) { - val externalRepoPath = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO) - val dir = externalRepoPath?.let { File(it) } - if (dir != null && // The directory could be opened - dir.exists() && // The directory exists - dir.isDirectory && // The directory, is really a directory - dir.listFilesRecursively().isNotEmpty() && // The directory contains files - // The directory contains a non-zero number of password files - PasswordRepository.getPasswords(dir, PasswordRepository.getRepositoryDirectory(), sortOrder).isNotEmpty() - ) { - PasswordRepository.closeRepository() - return true - } - } - return false - } - - private fun createRepository() { - val localDir = PasswordRepository.getRepositoryDirectory() - runCatching { - check(localDir.exists() || localDir.mkdir()) { "Failed to create directory!" } - PasswordRepository.createRepository(localDir) - if (!PasswordRepository.isInitialized) { - PasswordRepository.initialize() - } - parentFragmentManager.performTransactionWithBackStack(KeySelectionFragment.newInstance()) - }.onFailure { e -> - e(e) - if (!localDir.delete()) { - d { "Failed to delete local repository: $localDir" } - } - finish() - } - } - - private fun initializeRepositoryInfo() { - val externalRepo = settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false) - val externalRepoPath = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO) - if (externalRepo && !isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - return - } - if (externalRepo && externalRepoPath != null) { - if (checkExternalDirectory()) { - finish() - return - } - } - createRepository() - } - - private fun createPermGrantedAction(block: () -> Unit) = - registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> - if (granted) { - block.invoke() - } - } - - companion object { - - fun newInstance(): RepoLocationFragment = RepoLocationFragment() - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/WelcomeFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/WelcomeFragment.kt deleted file mode 100644 index 2ebab29f..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/onboarding/fragments/WelcomeFragment.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2019-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.annotation.Keep -import androidx.fragment.app.Fragment -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.UserPreference -import com.zeapo.pwdstore.databinding.FragmentWelcomeBinding -import com.zeapo.pwdstore.utils.performTransactionWithBackStack -import com.zeapo.pwdstore.utils.viewBinding - -@Keep -@Suppress("unused") -class WelcomeFragment : Fragment(R.layout.fragment_welcome) { - - private val binding by viewBinding(FragmentWelcomeBinding::bind) - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding.letsGo.setOnClickListener { parentFragmentManager.performTransactionWithBackStack(CloneFragment.newInstance()) } - binding.settingsButton.setOnClickListener { startActivity(Intent(requireContext(), UserPreference::class.java)) } - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/proxy/ProxySelectorActivity.kt b/app/src/main/java/com/zeapo/pwdstore/ui/proxy/ProxySelectorActivity.kt deleted file mode 100644 index 29c4d53a..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/ui/proxy/ProxySelectorActivity.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package com.zeapo.pwdstore.ui.proxy - -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.util.Patterns -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.edit -import androidx.core.os.postDelayed -import androidx.core.widget.doOnTextChanged -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.databinding.ActivityProxySelectorBinding -import com.zeapo.pwdstore.git.config.GitSettings -import com.zeapo.pwdstore.utils.PreferenceKeys -import com.zeapo.pwdstore.utils.ProxyUtils -import com.zeapo.pwdstore.utils.getEncryptedProxyPrefs -import com.zeapo.pwdstore.utils.getString -import com.zeapo.pwdstore.utils.viewBinding - -private val IP_ADDRESS_REGEX = Patterns.IP_ADDRESS.toRegex() -private val WEB_ADDRESS_REGEX = Patterns.WEB_URL.toRegex() - -class ProxySelectorActivity : AppCompatActivity() { - - private val binding by viewBinding(ActivityProxySelectorBinding::inflate) - private val proxyPrefs by lazy(LazyThreadSafetyMode.NONE) { applicationContext.getEncryptedProxyPrefs() } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(binding.root) - with(binding) { - proxyHost.setText(proxyPrefs.getString(PreferenceKeys.PROXY_HOST)) - proxyUser.setText(proxyPrefs.getString(PreferenceKeys.PROXY_USERNAME)) - proxyPrefs.getInt(PreferenceKeys.PROXY_PORT, -1).takeIf { it != -1 }?.let { - proxyPort.setText("$it") - } - proxyPassword.setText(proxyPrefs.getString(PreferenceKeys.PROXY_PASSWORD)) - save.setOnClickListener { saveSettings() } - proxyHost.doOnTextChanged { text, _, _, _ -> - if (text != null) { - proxyHost.error = if (text.matches(IP_ADDRESS_REGEX) || text.matches(WEB_ADDRESS_REGEX)) { - null - } else { - getString(R.string.invalid_proxy_url) - } - } - } - } - - } - - private fun saveSettings() { - proxyPrefs.edit { - binding.proxyHost.text?.toString()?.takeIf { it.isNotEmpty() }.let { - GitSettings.proxyHost = it - } - binding.proxyUser.text?.toString()?.takeIf { it.isNotEmpty() }.let { - GitSettings.proxyUsername = it - } - binding.proxyPort.text?.toString()?.takeIf { it.isNotEmpty() }?.let { - GitSettings.proxyPort = it.toInt() - } - binding.proxyPassword.text?.toString()?.takeIf { it.isNotEmpty() }.let { - GitSettings.proxyPassword = it - } - } - ProxyUtils.setDefaultProxy() - Handler(Looper.getMainLooper()).postDelayed(500) { finish() } - } -} -- cgit v1.2.3