summaryrefslogtreecommitdiff
path: root/app/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java')
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt70
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt145
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt5
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/UserPreference.kt241
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt1
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt1
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt1
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt1
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt1
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt38
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt25
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillSaveActivity.kt86
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt3
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/BreakOutOfDetached.kt4
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt4
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt17
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt9
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt4
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt4
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt4
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt4
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java10
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/ui/dialogs/ItemCreationBottomSheet.kt16
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt10
24 files changed, 350 insertions, 354 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt
index e91df9c6..ff022fab 100644
--- a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt
@@ -14,9 +14,11 @@ import android.view.MenuItem
import android.view.View
import android.view.animation.Animation
import android.view.animation.AnimationUtils
+import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.appcompat.view.ActionMode
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
+import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.observe
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
@@ -47,17 +49,26 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
private val model: SearchableRepositoryViewModel by activityViewModels()
private val binding by viewBinding(PasswordRecyclerViewBinding::bind)
+ private val swipeResult = registerForActivityResult(StartActivityForResult()) {
+ binding.swipeRefresher.isRefreshing = false
+ requireStore().refreshPasswordList()
+ }
- private fun requireStore() = requireActivity() as PasswordStore
+ val currentDir: File
+ get() = model.currentDir.value!!
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
settings = PreferenceManager.getDefaultSharedPreferences(requireContext())
initializePasswordList()
binding.fab.setOnClickListener {
- ItemCreationBottomSheet().apply {
- setTargetFragment(this@PasswordFragment, 1000)
- }.show(parentFragmentManager, "BOTTOM_SHEET")
+ ItemCreationBottomSheet().show(childFragmentManager, "BOTTOM_SHEET")
+ }
+ childFragmentManager.setFragmentResultListener(ITEM_CREATION_REQUEST_KEY, viewLifecycleOwner) { _, bundle ->
+ when (bundle.getString(ACTION_KEY)) {
+ ACTION_FOLDER -> requireStore().createFolder()
+ ACTION_PASSWORD -> requireStore().createPassword()
+ }
}
}
@@ -73,7 +84,7 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
.setAction(R.string.clone_button) {
val intent = Intent(context, GitServerConfigActivity::class.java)
intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_CLONE)
- startActivityForResult(intent, BaseGitActivity.REQUEST_CLONE)
+ swipeResult.launch(intent)
}
.show()
binding.swipeRefresher.isRefreshing = false
@@ -87,7 +98,7 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
}
val intent = Intent(context, GitOperationActivity::class.java)
intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, operationId)
- startActivityForResult(intent, operationId)
+ swipeResult.launch(intent)
}
}
@@ -129,22 +140,26 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
// and not on folder navigations since the latter leads to too many removal animations.
(recyclerView.itemAnimator as OnOffItemAnimator).isEnabled = result.isFiltered
recyclerAdapter.submitList(result.passwordItems) {
- if (result.isFiltered) {
- // When the result is filtered, we always scroll to the top since that is where
- // the best fuzzy match appears.
- recyclerView.scrollToPosition(0)
- } else if (scrollTarget != null) {
- scrollTarget?.let {
- recyclerView.scrollToPosition(recyclerAdapter.getPositionForFile(it))
+ when {
+ result.isFiltered -> {
+ // When the result is filtered, we always scroll to the top since that is where
+ // the best fuzzy match appears.
+ recyclerView.scrollToPosition(0)
}
- scrollTarget == null
- } else {
- // When the result is not filtered and there is a saved scroll position for it,
- // we try to restore it.
- recyclerViewStateToRestore?.let {
- recyclerView.layoutManager!!.onRestoreInstanceState(it)
+ scrollTarget != null -> {
+ scrollTarget?.let {
+ recyclerView.scrollToPosition(recyclerAdapter.getPositionForFile(it))
+ }
+ scrollTarget = null
+ }
+ else -> {
+ // When the result is not filtered and there is a saved scroll position for it,
+ // we try to restore it.
+ recyclerViewStateToRestore?.let {
+ recyclerView.layoutManager!!.onRestoreInstanceState(it)
+ }
+ recyclerViewStateToRestore = null
}
- recyclerViewStateToRestore = null
}
}
}
@@ -244,9 +259,7 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
}
}
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- binding.swipeRefresher.isRefreshing = false
- }
+ private fun requireStore() = requireActivity() as PasswordStore
/**
* Returns true if the back press was handled by the [Fragment].
@@ -262,16 +275,17 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
return true
}
- val currentDir: File
- get() = model.currentDir.value!!
-
fun dismissActionMode() {
actionMode?.finish()
}
- fun createFolder() = requireStore().createFolder()
+ companion object {
+ const val ITEM_CREATION_REQUEST_KEY = "creation_key"
+ const val ACTION_KEY = "action"
+ const val ACTION_FOLDER = "folder"
+ const val ACTION_PASSWORD = "password"
+ }
- fun createPassword() = requireStore().createPassword()
fun navigateTo(file: File) {
requireStore().clearSearch()
diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
index 54fc7c97..e157965f 100644
--- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
@@ -6,7 +6,6 @@ package com.zeapo.pwdstore
import android.Manifest
import android.annotation.SuppressLint
-import android.app.Activity
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
@@ -93,6 +92,46 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
ViewModelProvider.AndroidViewModelFactory(application)
}
+ private val cloneAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) }
+ }
+ }
+
+ private val listRefreshAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ refreshPasswordList()
+ }
+ }
+
+ private val repositoryInitAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ initializeRepositoryInfo()
+ }
+ }
+
+ private val directoryChangeAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ if (settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false) &&
+ settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO, null) != null) {
+ val externalRepoPath = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO, null)
+ val dir = externalRepoPath?.let { File(it) }
+ if (dir != null &&
+ dir.exists() &&
+ dir.isDirectory &&
+ dir.listFilesRecursively().isNotEmpty() &&
+ getPasswords(dir, getRepositoryDirectory(this), sortOrder).isNotEmpty()) {
+ closeRepository()
+ checkLocalRepository()
+ return@registerForActivityResult
+ }
+ }
+ val intent = Intent(activity, GitOperationActivity::class.java)
+ intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_CLONE)
+ cloneAction.launch(intent)
+ }
+ }
+
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
// open search view on search key, or Ctr+F
if ((keyCode == KeyEvent.KEYCODE_SEARCH || keyCode == KeyEvent.KEYCODE_F && event.isCtrlPressed) &&
@@ -295,7 +334,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
}
intent = Intent(this, GitOperationActivity::class.java)
intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_PUSH)
- startActivityForResult(intent, BaseGitActivity.REQUEST_PUSH)
+ startActivity(intent)
return true
}
R.id.git_pull -> {
@@ -305,7 +344,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
}
intent = Intent(this, GitOperationActivity::class.java)
intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_PULL)
- startActivityForResult(intent, BaseGitActivity.REQUEST_PULL)
+ listRefreshAction.launch(intent)
return true
}
R.id.git_sync -> {
@@ -315,7 +354,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
}
intent = Intent(this, GitOperationActivity::class.java)
intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_SYNC)
- startActivityForResult(intent, BaseGitActivity.REQUEST_SYNC)
+ listRefreshAction.launch(intent)
return true
}
R.id.refresh -> {
@@ -383,7 +422,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
.setMessage(resources.getString(R.string.key_dialog_text))
.setPositiveButton(resources.getString(R.string.dialog_positive)) { _, _ ->
val intent = Intent(activity, UserPreference::class.java)
- startActivityForResult(intent, BaseGitActivity.REQUEST_INIT)
+ repositoryInitAction.launch(intent)
}
.setNegativeButton(resources.getString(R.string.dialog_negative), null)
.show()
@@ -426,7 +465,11 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
if (repo == null) {
val intent = Intent(activity, UserPreference::class.java)
intent.putExtra("operation", "git_external")
- startActivityForResult(intent, HOME)
+ registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ checkLocalRepository()
+ }
+ }.launch(intent)
} else {
checkLocalRepository(getRepositoryDirectory(applicationContext))
}
@@ -526,7 +569,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
shortcutManager!!.addDynamicShortcuts(listOf(shortcut))
}
}
- startActivityForResult(decryptIntent, REQUEST_CODE_DECRYPT_AND_VERIFY)
+ startActivity(decryptIntent)
}
private fun validateState(): Boolean {
@@ -558,7 +601,12 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
val intent = Intent(this, PasswordCreationActivity::class.java)
intent.putExtra("FILE_PATH", currentDir.absolutePath)
intent.putExtra("REPO_PATH", getRepositoryDirectory(applicationContext).absolutePath)
- startActivityForResult(intent, REQUEST_CODE_ENCRYPT)
+ registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ commitChange(resources.getString(R.string.git_commit_add_text, result.data?.extras?.getString("LONG_NAME")))
+ refreshPasswordList()
+ }
+ }.launch(intent)
}
fun createFolder() {
@@ -574,6 +622,11 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
else
size += it.file.listFilesRecursively().size
}
+ if (size == 0) {
+ selectedItems.map { item -> item.file.deleteRecursively() }
+ refreshPasswordList()
+ return
+ }
MaterialAlertDialogBuilder(this)
.setMessage(resources.getQuantityString(R.plurals.delete_dialog_text, size, size))
.setPositiveButton(resources.getString(R.string.dialog_yes)) { _, _ ->
@@ -585,6 +638,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
filesToDelete.add(item.file)
}
selectedItems.map { item -> item.file.deleteRecursively() }
+ refreshPasswordList()
AutofillMatcher.updateMatches(applicationContext, delete = filesToDelete)
commitChange(resources.getString(R.string.git_commit_remove_text,
selectedItems.joinToString(separator = ", ") { item ->
@@ -756,61 +810,6 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
private val currentDir: File
get() = plist?.currentDir ?: getRepositoryDirectory(applicationContext)
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (resultCode == Activity.RESULT_OK) {
- when (requestCode) {
- // if we get here with a RESULT_OK then it's probably OK :)
- BaseGitActivity.REQUEST_CLONE -> settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) }
- // if went from decrypt->edit and user saved changes, we need to commitChange
- REQUEST_CODE_DECRYPT_AND_VERIFY -> {
- if (data != null && data.getBooleanExtra("needCommit", false)) {
- if (data.getStringExtra("OPERATION") == "EDIT") {
- commitChange(resources.getString(R.string.git_commit_edit_text,
- data.extras!!.getString("LONG_NAME")))
- }
- }
- }
- REQUEST_CODE_ENCRYPT -> {
- commitChange(resources.getString(R.string.git_commit_add_text,
- data!!.extras!!.getString(PasswordCreationActivity.RETURN_EXTRA_LONG_NAME)))
- refreshPasswordList(File(data.extras!!.getString(PasswordCreationActivity.RETURN_EXTRA_CREATED_FILE)!!))
- }
- BaseGitActivity.REQUEST_INIT, NEW_REPO_BUTTON -> initializeRepositoryInfo()
- BaseGitActivity.REQUEST_SYNC, BaseGitActivity.REQUEST_PULL -> refreshPasswordList()
- HOME -> checkLocalRepository()
- // duplicate code
- CLONE_REPO_BUTTON -> {
- if (settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false) &&
- settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO, null) != null) {
- val externalRepoPath = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO, null)
- val dir = externalRepoPath?.let { File(it) }
- if (dir != null &&
- dir.exists() &&
- dir.isDirectory &&
- dir.listFilesRecursively().isNotEmpty() &&
- getPasswords(dir, getRepositoryDirectory(this), sortOrder).isNotEmpty()) {
- closeRepository()
- checkLocalRepository()
- return // if not empty, just show me the passwords!
- }
- }
- val intent = Intent(activity, GitOperationActivity::class.java)
- intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_CLONE)
- startActivityForResult(intent, BaseGitActivity.REQUEST_CLONE)
- }
- else -> {
- d { "Unexpected request code: $requestCode" }
- // FIXME: The sync operation returns with a requestCode of 65535 instead of the
- // expected 105. It is completely unclear why, but the issue might be resolved
- // by switching to ActivityResultContracts. For now, we run the post-sync code
- // also when encountering an unexpected request code.
- refreshPasswordList()
- }
- }
- }
- super.onActivityResult(requestCode, resultCode, data)
- }
-
private suspend fun moveFile(source: File, destinationFile: File) {
val sourceDestinationMap = if (source.isDirectory) {
destinationFile.mkdirs()
@@ -848,7 +847,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
CLONE_REPO_BUTTON -> {
val intent = Intent(activity, GitServerConfigActivity::class.java)
intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_CLONE)
- startActivityForResult(intent, BaseGitActivity.REQUEST_CLONE)
+ cloneAction.launch(intent)
}
}
}
@@ -858,7 +857,10 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
if (externalRepo == null) {
val intent = Intent(activity, UserPreference::class.java)
intent.putExtra("operation", "git_external")
- startActivityForResult(intent, operation)
+ when (operation) {
+ NEW_REPO_BUTTON -> repositoryInitAction.launch(intent)
+ CLONE_REPO_BUTTON -> directoryChangeAction.launch(intent)
+ }
} else {
MaterialAlertDialogBuilder(activity)
.setTitle(resources.getString(R.string.directory_selected_title))
@@ -869,14 +871,17 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
CLONE_REPO_BUTTON -> {
val intent = Intent(activity, GitServerConfigActivity::class.java)
intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_CLONE)
- startActivityForResult(intent, BaseGitActivity.REQUEST_CLONE)
+ cloneAction.launch(intent)
}
}
}
.setNegativeButton(resources.getString(R.string.change)) { _, _ ->
val intent = Intent(activity, UserPreference::class.java)
intent.putExtra("operation", "git_external")
- startActivityForResult(intent, operation)
+ when (operation) {
+ NEW_REPO_BUTTON -> repositoryInitAction.launch(intent)
+ CLONE_REPO_BUTTON -> directoryChangeAction.launch(intent)
+ }
}
.show()
}
@@ -891,7 +896,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
.replace(".gpg", "")
val data = Intent()
data.putExtra("path", path)
- setResult(Activity.RESULT_OK, data)
+ setResult(RESULT_OK, data)
finish()
}
@@ -899,13 +904,9 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
get() = getSortOrder(settings)
companion object {
- const val REQUEST_CODE_ENCRYPT = 9911
- const val REQUEST_CODE_DECRYPT_AND_VERIFY = 9913
const val REQUEST_ARG_PATH = "PATH"
- private val TAG = PasswordStore::class.java.name
const val CLONE_REPO_BUTTON = 401
const val NEW_REPO_BUTTON = 402
- private const val HOME = 403
private const val REQUEST_EXTERNAL_STORAGE = 50
private fun isPrintable(c: Char): Boolean {
val block = UnicodeBlock.of(c)
diff --git a/app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt b/app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt
index 568f86f3..848977f0 100644
--- a/app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt
@@ -4,7 +4,6 @@
*/
package com.zeapo.pwdstore
-import android.app.Activity
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
@@ -43,7 +42,7 @@ class SelectFolderActivity : AppCompatActivity(R.layout.select_folder_layout) {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
- setResult(Activity.RESULT_CANCELED)
+ setResult(RESULT_CANCELED)
finish()
return true
}
@@ -54,7 +53,7 @@ class SelectFolderActivity : AppCompatActivity(R.layout.select_folder_layout) {
private fun selectFolder() {
intent.putExtra("SELECTED_FOLDER_PATH", passwordList.currentDir.absolutePath)
- setResult(Activity.RESULT_OK, intent)
+ setResult(RESULT_OK, intent)
finish()
}
}
diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
index 03e314f6..ea3bac38 100644
--- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
@@ -6,7 +6,6 @@ package com.zeapo.pwdstore
import android.accessibilityservice.AccessibilityServiceInfo
import android.annotation.SuppressLint
-import android.app.Activity
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.ShortcutManager
@@ -21,7 +20,8 @@ import android.text.TextUtils
import android.view.MenuItem
import android.view.accessibility.AccessibilityManager
import android.widget.Toast
-import androidx.activity.result.contract.ActivityResultContracts
+import androidx.activity.result.ActivityResult
+import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatTextView
import androidx.biometric.BiometricManager
@@ -167,7 +167,7 @@ class UserPreference : AppCompatActivity() {
false
} else {
val intent = Intent(callingActivity, GetKeyIdsActivity::class.java)
- val keySelectResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+ val keySelectResult = registerForActivityResult(StartActivityForResult()) {
updateKeyIDsSummary(pref)
}
keySelectResult.launch(intent)
@@ -490,7 +490,7 @@ class UserPreference : AppCompatActivity() {
override fun onBackPressed() {
super.onBackPressed()
- setResult(Activity.RESULT_OK)
+ setResult(RESULT_OK)
finish()
}
@@ -511,13 +511,40 @@ class UserPreference : AppCompatActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
+ @Suppress("Deprecation") // for Environment.getExternalStorageDirectory()
fun selectExternalGitRepository() {
MaterialAlertDialogBuilder(this)
.setTitle(this.resources.getString(R.string.external_repository_dialog_title))
.setMessage(this.resources.getString(R.string.external_repository_dialog_text))
.setPositiveButton(R.string.dialog_ok) { _, _ ->
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
- startActivityForResult(Intent.createChooser(i, "Choose Directory"), SELECT_GIT_DIRECTORY)
+ registerForActivityResult(StartActivityForResult()) { result ->
+ if (!validateResult(result)) return@registerForActivityResult
+ val uri = result.data?.data
+
+ tag(TAG).d { "Selected repository URI is $uri" }
+ // TODO: This is fragile. Workaround until PasswordItem is backed by DocumentFile
+ val docId = DocumentsContract.getTreeDocumentId(uri)
+ val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ val path = if (split.size > 1) split[1] else split[0]
+ val repoPath = "${Environment.getExternalStorageDirectory()}/$path"
+ val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
+
+ tag(TAG).d { "Selected repository path is $repoPath" }
+
+ if (Environment.getExternalStorageDirectory().path == repoPath) {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(getString(R.string.sdcard_root_warning_title))
+ .setMessage(getString(R.string.sdcard_root_warning_message))
+ .setPositiveButton("Remove everything") { _, _ ->
+ prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, uri?.path) }
+ }
+ .setNegativeButton(R.string.dialog_cancel, null)
+ .show()
+ }
+ prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, repoPath) }
+
+ }.launch(Intent.createChooser(i, "Choose Directory"))
}
.setNegativeButton(R.string.dialog_cancel, null)
.show()
@@ -529,7 +556,7 @@ class UserPreference : AppCompatActivity() {
// as you specify a parent activity in AndroidManifest.xml.
return when (item.itemId) {
android.R.id.home -> {
- setResult(Activity.RESULT_OK)
+ setResult(RESULT_OK)
finish()
true
}
@@ -538,22 +565,74 @@ class UserPreference : AppCompatActivity() {
}
/**
+ * Given a [ActivityResult], validates that the result is usable.
+ */
+ private fun validateResult(result: ActivityResult): Boolean {
+ if (result.resultCode != RESULT_OK) {
+ return false
+ }
+ if (result.data == null) {
+ setResult(RESULT_CANCELED)
+ return false
+ }
+ return true
+ }
+
+ /**
* Opens a file explorer to import the private key
*/
private fun getSshKey() {
- val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
+ registerForActivityResult(StartActivityForResult()) { result ->
+ if (!validateResult(result)) return@registerForActivityResult
+ try {
+ val uri: Uri = result.data?.data ?: throw IOException("Unable to open file")
+
+ copySshKey(uri)
+
+ Toast.makeText(
+ this,
+ this.resources.getString(R.string.ssh_key_success_dialog_title),
+ Toast.LENGTH_LONG
+ ).show()
+ val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
+
+ prefs.edit { putBoolean(PreferenceKeys.USE_GENERATED_KEY, false) }
+ getEncryptedPrefs("git_operation").edit { remove(PreferenceKeys.SSH_KEY_LOCAL_PASSPHRASE) }
+
+ // Delete the public key from generation
+ File("""$filesDir/.ssh_key.pub""").delete()
+ setResult(RESULT_OK)
+
+ finish()
+ } catch (e: Exception) {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(resources.getString(R.string.ssh_key_error_dialog_title))
+ .setMessage(e.message)
+ .setPositiveButton(resources.getString(R.string.dialog_ok), null)
+ .show()
+ }
+ }.launch(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
- }
- startActivityForResult(intent, IMPORT_SSH_KEY)
+ })
}
/**
* Exports the passwords
*/
private fun exportPasswords() {
- val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
- startActivityForResult(Intent.createChooser(i, "Choose Directory"), EXPORT_PASSWORDS)
+ registerForActivityResult(StartActivityForResult()) { result ->
+ if (!validateResult(result)) return@registerForActivityResult
+ val uri = result.data?.data
+
+ if (uri != null) {
+ val targetDirectory = DocumentFile.fromTreeUri(applicationContext, uri)
+
+ if (targetDirectory != null) {
+ exportPasswords(targetDirectory)
+ }
+ }
+ }.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE))
}
/**
@@ -563,7 +642,7 @@ class UserPreference : AppCompatActivity() {
val intent = Intent(applicationContext, SshKeyGenActivity::class.java)
startActivity(intent)
if (!fromPreferences) {
- setResult(Activity.RESULT_OK)
+ setResult(RESULT_OK)
finish()
}
}
@@ -572,11 +651,33 @@ class UserPreference : AppCompatActivity() {
* Pick custom xkpwd dictionary from sdcard
*/
private fun storeCustomDictionaryPath() {
- val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
+ registerForActivityResult(StartActivityForResult()) { result ->
+ if (!validateResult(result)) return@registerForActivityResult
+ val uri: Uri = result.data?.data ?: throw IOException("Unable to open file")
+
+ Toast.makeText(
+ this,
+ this.resources.getString(R.string.xkpwgen_custom_dict_imported, uri.path),
+ Toast.LENGTH_SHORT
+ ).show()
+ val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
+
+ prefs.edit { putString(PreferenceKeys.PREF_KEY_CUSTOM_DICT, uri.toString()) }
+
+ val customDictPref = prefsFragment.findPreference<Preference>(PreferenceKeys.PREF_KEY_CUSTOM_DICT)
+ setCustomDictSummary(customDictPref, uri)
+ // copy user selected file to internal storage
+ val inputStream = contentResolver.openInputStream(uri)
+ val customDictFile = File(filesDir.toString(), XkpwdDictionary.XKPWD_CUSTOM_DICT_FILE).outputStream()
+ inputStream?.copyTo(customDictFile, 1024)
+ inputStream?.close()
+ customDictFile.close()
+
+ setResult(RESULT_OK)
+ }.launch(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
- }
- startActivityForResult(intent, SET_CUSTOM_XKPWD_DICT)
+ })
}
@Throws(IllegalArgumentException::class, IOException::class)
@@ -631,111 +732,6 @@ class UserPreference : AppCompatActivity() {
return autofillManager?.hasEnabledAutofillServices() == true
}
- override fun onActivityResult(
- requestCode: Int,
- resultCode: Int,
- data: Intent?
- ) {
- if (resultCode == Activity.RESULT_OK) {
- if (data == null) {
- setResult(Activity.RESULT_CANCELED)
- return
- }
-
- when (requestCode) {
- IMPORT_SSH_KEY -> {
- try {
- val uri: Uri = data.data ?: throw IOException("Unable to open file")
-
- copySshKey(uri)
-
- Toast.makeText(
- this,
- this.resources.getString(R.string.ssh_key_success_dialog_title),
- Toast.LENGTH_LONG
- ).show()
- val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
-
- prefs.edit { putBoolean(PreferenceKeys.USE_GENERATED_KEY, false) }
- getEncryptedPrefs("git_operation").edit { remove(PreferenceKeys.SSH_KEY_LOCAL_PASSPHRASE) }
-
- // Delete the public key from generation
- File("""$filesDir/.ssh_key.pub""").delete()
- setResult(Activity.RESULT_OK)
-
- finish()
- } catch (e: Exception) {
- MaterialAlertDialogBuilder(this)
- .setTitle(resources.getString(R.string.ssh_key_error_dialog_title))
- .setMessage(e.message)
- .setPositiveButton(resources.getString(R.string.dialog_ok), null)
- .show()
- }
- }
- SELECT_GIT_DIRECTORY -> {
- val uri = data.data
-
- tag(TAG).d { "Selected repository URI is $uri" }
- // TODO: This is fragile. Workaround until PasswordItem is backed by DocumentFile
- val docId = DocumentsContract.getTreeDocumentId(uri)
- val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
- val path = if (split.size > 1) split[1] else split[0]
- val repoPath = "${Environment.getExternalStorageDirectory()}/$path"
- val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
-
- tag(TAG).d { "Selected repository path is $repoPath" }
-
- if (Environment.getExternalStorageDirectory().path == repoPath) {
- MaterialAlertDialogBuilder(this)
- .setTitle(getString(R.string.sdcard_root_warning_title))
- .setMessage(getString(R.string.sdcard_root_warning_message))
- .setPositiveButton("Remove everything") { _, _ ->
- prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, uri?.path) }
- }
- .setNegativeButton(R.string.dialog_cancel, null)
- .show()
- }
- prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, repoPath) }
- }
- EXPORT_PASSWORDS -> {
- val uri = data.data
-
- if (uri != null) {
- val targetDirectory = DocumentFile.fromTreeUri(applicationContext, uri)
-
- if (targetDirectory != null) {
- exportPasswords(targetDirectory)
- }
- }
- }
- SET_CUSTOM_XKPWD_DICT -> {
- val uri: Uri = data.data ?: throw IOException("Unable to open file")
-
- Toast.makeText(
- this,
- this.resources.getString(R.string.xkpwgen_custom_dict_imported, uri.path),
- Toast.LENGTH_SHORT
- ).show()
- val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
-
- prefs.edit { putString(PreferenceKeys.PREF_KEY_CUSTOM_DICT, uri.toString()) }
-
- val customDictPref = prefsFragment.findPreference<Preference>(PreferenceKeys.PREF_KEY_CUSTOM_DICT)
- setCustomDictSummary(customDictPref, uri)
- // copy user selected file to internal storage
- val inputStream = contentResolver.openInputStream(uri)
- val customDictFile = File(filesDir.toString(), XkpwdDictionary.XKPWD_CUSTOM_DICT_FILE).outputStream()
- inputStream?.copyTo(customDictFile, 1024)
- inputStream?.close()
- customDictFile.close()
-
- setResult(Activity.RESULT_OK)
- }
- }
- }
- super.onActivityResult(requestCode, resultCode, data)
- }
-
/**
* Exports passwords to the given directory.
*
@@ -808,11 +804,6 @@ class UserPreference : AppCompatActivity() {
}
companion object {
- private const val IMPORT_SSH_KEY = 1
- private const val SELECT_GIT_DIRECTORY = 2
- private const val EXPORT_PASSWORDS = 3
- private const val EDIT_GIT_CONFIG = 4
- private const val SET_CUSTOM_XKPWD_DICT = 5
private const val TAG = "UserPreference"
/**
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt
index 87881968..a64cdced 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt
@@ -2,6 +2,7 @@
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
+@file:Suppress("Deprecation")
package com.zeapo.pwdstore.autofill
import android.app.PendingIntent
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt
index 2410d53e..269e6624 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt
@@ -2,6 +2,7 @@
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
+@file:Suppress("Deprecation")
package com.zeapo.pwdstore.autofill
import android.annotation.SuppressLint
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt
index 860d8459..e8bf5537 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt
@@ -2,6 +2,7 @@
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
+@file:Suppress("Deprecation")
package com.zeapo.pwdstore.autofill
import android.content.Context
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt
index 811ff7af..5752b055 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt
@@ -2,6 +2,7 @@
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
+@file:Suppress("Deprecation")
package com.zeapo.pwdstore.autofill
import android.content.Context
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt
index 177233a8..bfb1c5d0 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt
@@ -2,6 +2,7 @@
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
+@file:Suppress("Deprecation")
package com.zeapo.pwdstore.autofill
import android.accessibilityservice.AccessibilityService
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt
index d7d8daaf..c5e47544 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt
@@ -4,7 +4,6 @@
*/
package com.zeapo.pwdstore.autofill.oreo.ui
-import android.app.Activity
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
@@ -13,7 +12,10 @@ import android.os.Build
import android.os.Bundle
import android.view.autofill.AutofillManager
import android.widget.Toast
+import androidx.activity.result.IntentSenderRequest
+import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult
import androidx.annotation.RequiresApi
+import androidx.appcompat.app.AppCompatActivity
import com.github.ajalt.timberkt.d
import com.github.ajalt.timberkt.e
import com.zeapo.pwdstore.autofill.oreo.AutofillAction
@@ -44,13 +46,12 @@ import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
@RequiresApi(Build.VERSION_CODES.O)
-class AutofillDecryptActivity : Activity(), CoroutineScope {
+class AutofillDecryptActivity : AppCompatActivity(), CoroutineScope {
companion object {
private const val EXTRA_FILE_PATH = "com.zeapo.pwdstore.autofill.oreo.EXTRA_FILE_PATH"
private const val EXTRA_SEARCH_ACTION =
"com.zeapo.pwdstore.autofill.oreo.EXTRA_SEARCH_ACTION"
- private const val REQUEST_CODE_CONTINUE_AFTER_USER_INTERACTION = 1
private const val OPENPGP_PROVIDER = "org.sufficientlysecure.keychain"
private var decryptFileRequestCode = 1
@@ -194,14 +195,17 @@ class AutofillDecryptActivity : Activity(), CoroutineScope {
val intentToResume = withContext(Dispatchers.Main) {
suspendCoroutine<Intent> { cont ->
continueAfterUserInteraction = cont
- startIntentSenderForResult(
- pendingIntent.intentSender,
- REQUEST_CODE_CONTINUE_AFTER_USER_INTERACTION,
- null,
- 0,
- 0,
- 0
- )
+ registerForActivityResult(StartIntentSenderForResult()) { result ->
+ if (continueAfterUserInteraction != null) {
+ val data = result.data
+ if (resultCode == RESULT_OK && data != null) {
+ continueAfterUserInteraction?.resume(data)
+ } else {
+ continueAfterUserInteraction?.resumeWithException(Exception("OpenPgpApi ACTION_DECRYPT_VERIFY failed to continue after user interaction"))
+ }
+ continueAfterUserInteraction = null
+ }
+ }.launch(IntentSenderRequest.Builder(pendingIntent.intentSender).build())
}
}
decryptCredential(file, intentToResume)
@@ -230,16 +234,4 @@ class AutofillDecryptActivity : Activity(), CoroutineScope {
}
}
}
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- if (requestCode == REQUEST_CODE_CONTINUE_AFTER_USER_INTERACTION && continueAfterUserInteraction != null) {
- if (resultCode == RESULT_OK && data != null) {
- continueAfterUserInteraction?.resume(data)
- } else {
- continueAfterUserInteraction?.resumeWithException(Exception("OpenPgpApi ACTION_DECRYPT_VERIFY failed to continue after user interaction"))
- }
- continueAfterUserInteraction = null
- }
- }
}
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
index 1a969b51..7467b9c9 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
@@ -14,6 +14,7 @@ import android.os.Bundle
import android.view.View
import android.view.autofill.AutofillManager
import android.widget.TextView
+import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.bold
@@ -44,7 +45,6 @@ class AutofillFilterView : AppCompatActivity() {
companion object {
private const val HEIGHT_PERCENTAGE = 0.9
private const val WIDTH_PERCENTAGE = 0.75
- private const val DECRYPT_FILL_REQUEST_CODE = 1
private const val EXTRA_FORM_ORIGIN_WEB =
"com.zeapo.pwdstore.autofill.oreo.ui.EXTRA_FORM_ORIGIN_WEB"
@@ -197,20 +197,15 @@ class AutofillFilterView : AppCompatActivity() {
item.file
)
// intent?.extras? is checked to be non-null in onCreate
- startActivityForResult(
- AutofillDecryptActivity.makeDecryptFileIntent(
- item.file,
- intent!!.extras!!,
- this
- ), DECRYPT_FILL_REQUEST_CODE
- )
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- if (requestCode == DECRYPT_FILL_REQUEST_CODE) {
- if (resultCode == RESULT_OK) setResult(RESULT_OK, data)
+ registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ setResult(RESULT_OK, result.data)
+ }
finish()
- }
+ }.launch(AutofillDecryptActivity.makeDecryptFileIntent(
+ item.file,
+ intent!!.extras!!,
+ this
+ ))
}
}
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillSaveActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillSaveActivity.kt
index b5bd9e38..87359333 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillSaveActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillSaveActivity.kt
@@ -4,7 +4,6 @@
*/
package com.zeapo.pwdstore.autofill.oreo.ui
-import android.app.Activity
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
@@ -12,10 +11,11 @@ import android.content.IntentSender
import android.os.Build
import android.os.Bundle
import android.view.autofill.AutofillManager
+import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.annotation.RequiresApi
+import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import com.github.ajalt.timberkt.e
-import com.zeapo.pwdstore.PasswordStore
import com.zeapo.pwdstore.R
import com.zeapo.pwdstore.autofill.oreo.AutofillAction
import com.zeapo.pwdstore.autofill.oreo.AutofillMatcher
@@ -29,7 +29,7 @@ import com.zeapo.pwdstore.utils.commitChange
import java.io.File
@RequiresApi(Build.VERSION_CODES.O)
-class AutofillSaveActivity : Activity() {
+class AutofillSaveActivity : AppCompatActivity() {
companion object {
private const val EXTRA_FOLDER_NAME =
@@ -109,50 +109,46 @@ class AutofillSaveActivity : Activity() {
)
)
}
- startActivityForResult(saveIntent, PasswordStore.REQUEST_CODE_ENCRYPT)
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- if (requestCode == PasswordStore.REQUEST_CODE_ENCRYPT && resultCode == RESULT_OK && data != null) {
- val createdPath = data.getStringExtra("CREATED_FILE")!!
- formOrigin?.let {
- AutofillMatcher.addMatchFor(this, it, File(createdPath))
- }
- val longName = data.getStringExtra("LONG_NAME")!!
- val password = data.getStringExtra("PASSWORD")
- val result = if (password != null) {
- // Password was generated and should be filled into a form.
- val username = data.getStringExtra("USERNAME")
- val clientState =
- intent?.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE) ?: run {
- e { "AutofillDecryptActivity started without EXTRA_CLIENT_STATE" }
- finish()
- return
+ registerForActivityResult(StartActivityForResult()) { result ->
+ val data = result.data
+ if (result.resultCode == RESULT_OK && data != null) {
+ val createdPath = data.getStringExtra("CREATED_FILE")!!
+ formOrigin?.let {
+ AutofillMatcher.addMatchFor(this, it, File(createdPath))
+ }
+ val longName = data.getStringExtra("LONG_NAME")!!
+ val password = data.getStringExtra("PASSWORD")
+ val resultIntent = if (password != null) {
+ // Password was generated and should be filled into a form.
+ val username = data.getStringExtra("USERNAME")
+ val clientState =
+ intent?.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE) ?: run {
+ e { "AutofillDecryptActivity started without EXTRA_CLIENT_STATE" }
+ finish()
+ return@registerForActivityResult
+ }
+ val credentials = Credentials(username, password, null)
+ val fillInDataset = FillableForm.makeFillInDataset(
+ this,
+ credentials,
+ clientState,
+ AutofillAction.Generate
+ )
+ Intent().apply {
+ putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, fillInDataset)
}
- val credentials = Credentials(username, password, null)
- val fillInDataset = FillableForm.makeFillInDataset(
- this,
- credentials,
- clientState,
- AutofillAction.Generate
- )
- Intent().apply {
- putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, fillInDataset)
+ } else {
+ // Password was extracted from a form, there is nothing to fill.
+ Intent()
}
- } else {
- // Password was extracted from a form, there is nothing to fill.
- Intent()
+ // PasswordCreationActivity delegates committing the added file to PasswordStore. Since
+ // PasswordStore is not involved in an AutofillScenario, we have to commit the file ourselves.
+ commitChange(
+ getString(R.string.git_commit_add_text, longName),
+ finishWithResultOnEnd = resultIntent
+ )
+ // GitAsyncTask will finish the activity for us.
}
- // PasswordCreationActivity delegates committing the added file to PasswordStore. Since
- // PasswordStore is not involved in an AutofillScenario, we have to commit the file ourselves.
- commitChange(
- getString(R.string.git_commit_add_text, longName),
- finishWithResultOnEnd = result
- )
- // GitAsyncTask will finish the activity for us.
- } else {
- finish()
- }
+ }.launch(saveIntent)
}
}
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt b/app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt
index ae2bbc07..341bd3fd 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt
@@ -4,7 +4,6 @@
*/
package com.zeapo.pwdstore.git
-import android.app.Activity
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
@@ -167,7 +166,7 @@ abstract class BaseGitActivity : AppCompatActivity() {
*/
fun launchGitOperation(operation: Int) {
if (url == null) {
- setResult(Activity.RESULT_CANCELED)
+ setResult(RESULT_CANCELED)
finish()
return
}
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/BreakOutOfDetached.kt b/app/src/main/java/com/zeapo/pwdstore/git/BreakOutOfDetached.kt
index 8533187f..6a3fdfd5 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/BreakOutOfDetached.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/BreakOutOfDetached.kt
@@ -4,7 +4,7 @@
*/
package com.zeapo.pwdstore.git
-import android.app.Activity
+import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.zeapo.pwdstore.R
import org.eclipse.jgit.api.Git
@@ -13,7 +13,7 @@ import org.eclipse.jgit.api.PushCommand
import org.eclipse.jgit.api.RebaseCommand
import java.io.File
-class BreakOutOfDetached(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) {
+class BreakOutOfDetached(fileDir: File, callingActivity: AppCompatActivity) : GitOperation(fileDir, callingActivity) {
private lateinit var commands: List<GitCommand<out Any>>
/**
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt
index 0e89af0f..2af86303 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt
@@ -4,8 +4,8 @@
*/
package com.zeapo.pwdstore.git
-import android.app.Activity
import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.zeapo.pwdstore.R
import org.eclipse.jgit.api.CloneCommand
@@ -18,7 +18,7 @@ import java.io.File
* @param fileDir the git working tree directory
* @param callingActivity the calling activity
*/
-class CloneOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) {
+class CloneOperation(fileDir: File, callingActivity: AppCompatActivity) : GitOperation(fileDir, callingActivity) {
/**
* Sets the command using the repository uri
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt b/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt
index 84e08dfc..66d953e9 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt
@@ -4,11 +4,11 @@
*/
package com.zeapo.pwdstore.git
-import android.app.Activity
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.os.AsyncTask
+import androidx.appcompat.app.AppCompatActivity
import com.github.ajalt.timberkt.e
import com.zeapo.pwdstore.R
import com.zeapo.pwdstore.git.config.SshjSessionFactory
@@ -28,14 +28,14 @@ import java.lang.ref.WeakReference
class GitAsyncTask(
- activity: Activity,
+ activity: AppCompatActivity,
private val operation: GitOperation,
private val finishWithResultOnEnd: Intent?,
private val silentlyExecute: Boolean = false
) : AsyncTask<GitCommand<*>, Int, GitAsyncTask.Result>() {
- private val activityWeakReference: WeakReference<Activity> = WeakReference(activity)
- private val activity: Activity?
+ private val activityWeakReference: WeakReference<AppCompatActivity> = WeakReference(activity)
+ private val activity: AppCompatActivity?
get() = activityWeakReference.get()
private val context: Context = activity.applicationContext
private val dialog = ProgressDialog(activity)
@@ -86,7 +86,8 @@ class GitAsyncTask(
RemoteRefUpdate.Status.REJECTED_NODELETE,
RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED,
RemoteRefUpdate.Status.NON_EXISTING,
- RemoteRefUpdate.Status.NOT_ATTEMPTED ->
+ RemoteRefUpdate.Status.NOT_ATTEMPTED
+ ->
(activity!!.getString(R.string.git_push_generic_error) + rru.status.name)
RemoteRefUpdate.Status.REJECTED_OTHER_REASON -> {
if
@@ -149,21 +150,21 @@ class GitAsyncTask(
// Currently, this is only executed when the user cancels a password prompt
// during authentication.
if (finishWithResultOnEnd != null) {
- activity?.setResult(Activity.RESULT_CANCELED)
+ activity?.setResult(AppCompatActivity.RESULT_CANCELED)
activity?.finish()
}
} else {
e(result.err)
operation.onError(rootCauseException(result.err))
if (finishWithResultOnEnd != null) {
- activity?.setResult(Activity.RESULT_CANCELED)
+ activity?.setResult(AppCompatActivity.RESULT_CANCELED)
}
}
}
is Result.Ok -> {
operation.onSuccess()
if (finishWithResultOnEnd != null) {
- activity?.setResult(Activity.RESULT_OK, finishWithResultOnEnd)
+ activity?.setResult(AppCompatActivity.RESULT_OK, finishWithResultOnEnd)
activity?.finish()
}
}
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt
index 48c28920..c9037e0a 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt
@@ -5,10 +5,10 @@
package com.zeapo.pwdstore.git
import android.annotation.SuppressLint
-import android.app.Activity
import android.content.Intent
import android.view.LayoutInflater
import androidx.annotation.StringRes
+import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.preference.PreferenceManager
@@ -40,7 +40,10 @@ import kotlin.coroutines.resume
import com.google.android.material.R as materialR
-private class GitOperationCredentialFinder(val callingActivity: Activity, val connectionMode: ConnectionMode) : InteractivePasswordFinder() {
+private class GitOperationCredentialFinder(
+ val callingActivity: AppCompatActivity,
+ val connectionMode: ConnectionMode
+) : InteractivePasswordFinder() {
override fun askForPassword(cont: Continuation<String?>, isRetry: Boolean) {
val gitOperationPrefs = callingActivity.getEncryptedPrefs("git_operation")
@@ -118,7 +121,7 @@ private class GitOperationCredentialFinder(val callingActivity: Activity, val co
* @param gitDir the git working tree directory
* @param callingActivity the calling activity
*/
-abstract class GitOperation(gitDir: File, internal val callingActivity: Activity) {
+abstract class GitOperation(gitDir: File, internal val callingActivity: AppCompatActivity) {
protected val repository: Repository? = PasswordRepository.getRepository(gitDir)
internal var provider: CredentialsProvider? = null
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt
index c543f885..436c81bb 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt
@@ -4,8 +4,8 @@
*/
package com.zeapo.pwdstore.git
-import android.app.Activity
import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.zeapo.pwdstore.R
import org.eclipse.jgit.api.Git
@@ -18,7 +18,7 @@ import java.io.File
* @param fileDir the git working tree directory
* @param callingActivity the calling activity
*/
-class PullOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) {
+class PullOperation(fileDir: File, callingActivity: AppCompatActivity) : GitOperation(fileDir, callingActivity) {
/**
* Sets the command
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt
index fc58705f..7a936e73 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt
@@ -4,8 +4,8 @@
*/
package com.zeapo.pwdstore.git
-import android.app.Activity
import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.zeapo.pwdstore.R
import org.eclipse.jgit.api.Git
@@ -18,7 +18,7 @@ import java.io.File
* @param fileDir the git working tree directory
* @param callingActivity the calling activity
*/
-class PushOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) {
+class PushOperation(fileDir: File, callingActivity: AppCompatActivity) : GitOperation(fileDir, callingActivity) {
/**
* Sets the command
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt
index be9e929f..fbd747b3 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt
@@ -4,8 +4,8 @@
*/
package com.zeapo.pwdstore.git
-import android.app.Activity
import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.zeapo.pwdstore.R
import org.eclipse.jgit.api.AddCommand
@@ -20,7 +20,7 @@ import java.io.File
* @param fileDir the git working tree directory
* @param callingActivity the calling activity
*/
-class ResetToRemoteOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) {
+class ResetToRemoteOperation(fileDir: File, callingActivity: AppCompatActivity) : GitOperation(fileDir, callingActivity) {
private var addCommand: AddCommand? = null
private var fetchCommand: FetchCommand? = null
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt
index 3af6f08d..6d99828e 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt
@@ -4,8 +4,8 @@
*/
package com.zeapo.pwdstore.git
-import android.app.Activity
import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.zeapo.pwdstore.R
import org.eclipse.jgit.api.AddCommand
@@ -22,7 +22,7 @@ import java.io.File
* @param fileDir the git working tree directory
* @param callingActivity the calling activity
*/
-class SyncOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) {
+class SyncOperation(fileDir: File, callingActivity: AppCompatActivity) : GitOperation(fileDir, callingActivity) {
private var addCommand: AddCommand? = null
private var statusCommand: StatusCommand? = null
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java b/app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java
index 5a51d28a..aa62fdae 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java
+++ b/app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java
@@ -4,13 +4,13 @@
*/
package com.zeapo.pwdstore.git.config;
-import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
@@ -245,7 +245,7 @@ public class SshApiSessionFactory extends JschConfigSessionFactory {
// back
// though onActivityResult
callingActivity.onActivityResult(
- requestCode, Activity.RESULT_OK, null);
+ requestCode, AppCompatActivity.RESULT_OK, null);
}
@Override
@@ -289,7 +289,7 @@ public class SshApiSessionFactory extends JschConfigSessionFactory {
private final String description;
private final String alg;
private final byte[] publicKey;
- private final Activity callingActivity;
+ private final AppCompatActivity callingActivity;
private final SshAuthenticationApi api;
private CountDownLatch latch;
private byte[] signature;
@@ -299,7 +299,7 @@ public class SshApiSessionFactory extends JschConfigSessionFactory {
String description,
byte[] publicKey,
String alg,
- Activity callingActivity,
+ AppCompatActivity callingActivity,
SshAuthenticationApi api) {
this.keyId = keyId;
this.description = description;
@@ -310,7 +310,7 @@ public class SshApiSessionFactory extends JschConfigSessionFactory {
}
@Override
- public boolean setPassphrase(byte[] passphrase) throws JSchException {
+ public boolean setPassphrase(byte[] passphrase) {
// We are not encrypted with a passphrase
return true;
}
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
index 55a767d8..94379bbf 100644
--- a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/ItemCreationBottomSheet.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/ItemCreationBottomSheet.kt
@@ -11,11 +11,15 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.FrameLayout
-import androidx.fragment.app.Fragment
+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
+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
@@ -50,11 +54,11 @@ class ItemCreationBottomSheet : BottomSheetDialogFragment() {
addBottomSheetCallback(bottomSheetCallback)
}
dialog.findViewById<View>(R.id.create_folder)?.setOnClickListener {
- (requireTargetFragment() as PasswordFragment).createFolder()
+ setFragmentResult(ITEM_CREATION_REQUEST_KEY, bundleOf(ACTION_KEY to ACTION_FOLDER))
dismiss()
}
dialog.findViewById<View>(R.id.create_password)?.setOnClickListener {
- (requireTargetFragment() as PasswordFragment).createPassword()
+ setFragmentResult(ITEM_CREATION_REQUEST_KEY, bundleOf(ACTION_KEY to ACTION_PASSWORD))
dismiss()
}
}
@@ -69,8 +73,4 @@ class ItemCreationBottomSheet : BottomSheetDialogFragment() {
super.dismiss()
behavior?.removeBottomSheetCallback(bottomSheetCallback)
}
-
- private fun requireTargetFragment(): Fragment = requireNotNull(targetFragment) {
- "A target fragment must be set for $this"
- }
}
diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
index 6ba03743..ad460550 100644
--- a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
@@ -4,7 +4,6 @@
*/
package com.zeapo.pwdstore.utils
-import android.app.Activity
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
@@ -18,6 +17,7 @@ import androidx.annotation.IdRes
import androidx.annotation.MainThread
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.getSystemService
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
@@ -49,7 +49,7 @@ fun CharArray.clear() {
val Context.clipboard get() = getSystemService<ClipboardManager>()
-fun Activity.snackbar(
+fun AppCompatActivity.snackbar(
view: View = findViewById(android.R.id.content),
message: String,
length: Int = Snackbar.LENGTH_SHORT
@@ -96,10 +96,10 @@ fun Context.getEncryptedPrefs(fileName: String): SharedPreferences {
}
@MainThread
-fun Activity.commitChange(message: String, finishWithResultOnEnd: Intent? = null) {
+fun AppCompatActivity.commitChange(message: String, finishWithResultOnEnd: Intent? = null) {
if (!PasswordRepository.isGitRepo()) {
if (finishWithResultOnEnd != null) {
- setResult(Activity.RESULT_OK, finishWithResultOnEnd)
+ setResult(AppCompatActivity.RESULT_OK, finishWithResultOnEnd)
finish()
}
return
@@ -141,6 +141,6 @@ val Context.autofillManager: AutofillManager?
@RequiresApi(Build.VERSION_CODES.O)
get() = getSystemService()
-fun Activity.isInsideRepository(file: File): Boolean {
+fun AppCompatActivity.isInsideRepository(file: File): Boolean {
return file.canonicalPath.contains(getRepositoryDirectory(this).canonicalPath)
}