Revamp onboarding logic (#1068)
This commit is contained in:
parent
b7f58cfb6e
commit
e731943437
15 changed files with 233 additions and 194 deletions
|
@ -55,6 +55,7 @@
|
|||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="WRAP_ON_TYPING" value="0" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/app_name" />
|
||||
|
||||
<activity
|
||||
android:name=".OnboardingActivity"
|
||||
android:configChanges="orientation|screenSize" />
|
||||
|
||||
<activity
|
||||
android:name=".LaunchActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
|
|
203
app/src/main/java/com/zeapo/pwdstore/OnboardingActivity.kt
Normal file
203
app/src/main/java/com/zeapo/pwdstore/OnboardingActivity.kt
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
package com.zeapo.pwdstore
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.edit
|
||||
import com.github.ajalt.timberkt.d
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.zeapo.pwdstore.databinding.ActivityOnboardingBinding
|
||||
import com.zeapo.pwdstore.git.BaseGitActivity
|
||||
import com.zeapo.pwdstore.git.GitServerConfigActivity
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository
|
||||
import com.zeapo.pwdstore.utils.PreferenceKeys
|
||||
import com.zeapo.pwdstore.utils.checkRuntimePermission
|
||||
import com.zeapo.pwdstore.utils.getString
|
||||
import com.zeapo.pwdstore.utils.listFilesRecursively
|
||||
import com.zeapo.pwdstore.utils.sharedPrefs
|
||||
import com.zeapo.pwdstore.utils.viewBinding
|
||||
import java.io.File
|
||||
|
||||
class OnboardingActivity : AppCompatActivity() {
|
||||
|
||||
private val binding by viewBinding(ActivityOnboardingBinding::inflate)
|
||||
private val settings by lazy { applicationContext.sharedPrefs }
|
||||
private val sortOrder: PasswordRepository.PasswordSortOrder
|
||||
get() = PasswordRepository.PasswordSortOrder.getSortOrder(settings)
|
||||
|
||||
private val cloneAction = registerForActivityResult(StartActivityForResult()) { result ->
|
||||
if (result.resultCode == RESULT_OK) {
|
||||
settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) }
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private val repositoryInitAction = registerForActivityResult(StartActivityForResult()) { result ->
|
||||
if (result.resultCode == RESULT_OK) {
|
||||
initializeRepositoryInfo()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private val externalDirectorySelectAction = registerForActivityResult(StartActivityForResult()) { result ->
|
||||
if (result.resultCode == RESULT_OK) {
|
||||
if (checkExternalDirectory()) {
|
||||
finish()
|
||||
} else {
|
||||
createRepository()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar?.hide()
|
||||
setContentView(binding.root)
|
||||
binding.settingsButton.setOnClickListener {
|
||||
startActivity(Intent(this, UserPreference::class.java))
|
||||
}
|
||||
binding.localDirectoryButton.setOnClickListener {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(resources.getString(R.string.location_dialog_title))
|
||||
.setMessage(resources.getString(R.string.location_dialog_create_text))
|
||||
.setPositiveButton(resources.getString(R.string.location_hidden)) { _, _ ->
|
||||
createRepoInHiddenDir()
|
||||
}
|
||||
.setNegativeButton(resources.getString(R.string.location_sdcard)) { _, _ ->
|
||||
createRepoFromExternalDir()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
binding.cloneFromServerButton.setOnClickListener {
|
||||
cloneToHiddenDir()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones a remote Git repository to the app's private directory
|
||||
*/
|
||||
private fun cloneToHiddenDir() {
|
||||
settings.edit { putBoolean(PreferenceKeys.GIT_EXTERNAL, false) }
|
||||
cloneAction.launch(Intent(this, GitServerConfigActivity::class.java).apply {
|
||||
putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_CLONE)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
finish()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (!checkRuntimePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
registerForActivityResult(RequestPermission()) { granted ->
|
||||
if (granted) {
|
||||
externalDirectorySelectAction.launch(Intent(this, UserPreference::class.java).apply {
|
||||
putExtra("operation", "git_external")
|
||||
})
|
||||
}
|
||||
}.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
} else {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(resources.getString(R.string.directory_selected_title))
|
||||
.setMessage(resources.getString(R.string.directory_selected_message, externalRepo))
|
||||
.setPositiveButton(resources.getString(R.string.use)) { _, _ ->
|
||||
if (!checkRuntimePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
registerForActivityResult(RequestPermission()) { granted ->
|
||||
if (granted) {
|
||||
initializeRepositoryInfo()
|
||||
}
|
||||
}.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
} else {
|
||||
initializeRepositoryInfo()
|
||||
}
|
||||
}
|
||||
.setNegativeButton(resources.getString(R.string.change)) { _, _ ->
|
||||
if (!checkRuntimePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
registerForActivityResult(RequestPermission()) { granted ->
|
||||
if (granted) {
|
||||
repositoryInitAction.launch(Intent(this, UserPreference::class.java).apply {
|
||||
putExtra("operation", "git_external")
|
||||
})
|
||||
}
|
||||
}.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
}
|
||||
.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()
|
||||
try {
|
||||
check(localDir.exists() || localDir.mkdir()) { "Failed to create directory!" }
|
||||
PasswordRepository.createRepository(localDir)
|
||||
if (!PasswordRepository.isInitialized) {
|
||||
PasswordRepository.initialize()
|
||||
}
|
||||
if (File(localDir.absolutePath + "/.gpg-id").createNewFile()) {
|
||||
settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) }
|
||||
} else {
|
||||
throw IllegalStateException("Failed to initialize repository state.")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
if (!localDir.delete()) {
|
||||
d { "Failed to delete local repository: $localDir" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeRepositoryInfo() {
|
||||
val externalRepo = settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false)
|
||||
val externalRepoPath = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO)
|
||||
if (externalRepo && !checkRuntimePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
return
|
||||
}
|
||||
if (externalRepo && externalRepoPath != null) {
|
||||
if (checkExternalDirectory()) return
|
||||
}
|
||||
createRepository()
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ import android.Manifest
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ShortcutInfo.Builder
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.graphics.drawable.Icon
|
||||
|
@ -26,7 +25,6 @@ import androidx.activity.viewModels
|
|||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.appcompat.widget.SearchView.OnQueryTextListener
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.edit
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.fragment.app.FragmentManager
|
||||
|
@ -54,16 +52,13 @@ import com.zeapo.pwdstore.git.config.GitSettings
|
|||
import com.zeapo.pwdstore.ui.dialogs.FolderCreationDialogFragment
|
||||
import com.zeapo.pwdstore.utils.PasswordItem
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.closeRepository
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.createRepository
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getPasswords
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepository
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.initialize
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.isInitialized
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.PasswordSortOrder.Companion.getSortOrder
|
||||
import com.zeapo.pwdstore.utils.PreferenceKeys
|
||||
import com.zeapo.pwdstore.utils.base64
|
||||
import com.zeapo.pwdstore.utils.checkRuntimePermission
|
||||
import com.zeapo.pwdstore.utils.commitChange
|
||||
import com.zeapo.pwdstore.utils.contains
|
||||
import com.zeapo.pwdstore.utils.getString
|
||||
|
@ -94,43 +89,9 @@ class PasswordStore : BaseGitActivity() {
|
|||
ViewModelProvider.AndroidViewModelFactory(application)
|
||||
}
|
||||
|
||||
private val cloneAction = registerForActivityResult(StartActivityForResult()) { result ->
|
||||
private val listRefreshAction = registerForActivityResult(StartActivityForResult()) { result ->
|
||||
if (result.resultCode == RESULT_OK) {
|
||||
settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) }
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
val externalRepoPath = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO)
|
||||
val dir = externalRepoPath?.let { File(it) }
|
||||
if (dir != null &&
|
||||
dir.exists() &&
|
||||
dir.isDirectory &&
|
||||
dir.listFilesRecursively().isNotEmpty() &&
|
||||
getPasswords(dir, getRepositoryDirectory(), sortOrder).isNotEmpty()) {
|
||||
closeRepository()
|
||||
checkLocalRepository()
|
||||
return@registerForActivityResult
|
||||
}
|
||||
}
|
||||
checkPermissionsAndCloneAction.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
}
|
||||
|
||||
private val checkPermissionsAndCloneAction = registerForActivityResult(RequestPermission()) { granted ->
|
||||
if (granted) {
|
||||
val intent = Intent(activity, GitServerConfigActivity::class.java)
|
||||
intent.putExtra(REQUEST_ARG_OP, REQUEST_CLONE)
|
||||
cloneAction.launch(intent)
|
||||
refreshPasswordList()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,9 +121,7 @@ class PasswordStore : BaseGitActivity() {
|
|||
// prevent attempt to create password list fragment
|
||||
var savedInstance = savedInstanceState
|
||||
if (savedInstanceState != null && (!settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false) ||
|
||||
ContextCompat.checkSelfPermission(
|
||||
activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED)) {
|
||||
!checkRuntimePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE))) {
|
||||
savedInstance = null
|
||||
}
|
||||
super.onCreate(savedInstance)
|
||||
|
@ -229,7 +188,7 @@ class PasswordStore : BaseGitActivity() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false)) {
|
||||
hasRequiredStoragePermissions(true)
|
||||
hasRequiredStoragePermissions()
|
||||
} else {
|
||||
checkLocalRepository()
|
||||
}
|
||||
|
@ -361,47 +320,6 @@ class PasswordStore : BaseGitActivity() {
|
|||
searchItem.collapseActionView()
|
||||
}
|
||||
|
||||
private fun createRepository() {
|
||||
if (!isInitialized) {
|
||||
initialize()
|
||||
}
|
||||
val localDir = getRepositoryDirectory()
|
||||
try {
|
||||
check(localDir.mkdir()) { "Failed to create directory!" }
|
||||
createRepository(localDir)
|
||||
if (File(localDir.absolutePath + "/.gpg-id").createNewFile()) {
|
||||
settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) }
|
||||
} else {
|
||||
throw IllegalStateException("Failed to initialize repository state.")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
if (!localDir.delete()) {
|
||||
d { "Failed to delete local repository" }
|
||||
}
|
||||
return
|
||||
}
|
||||
checkLocalRepository()
|
||||
}
|
||||
|
||||
private fun initializeRepositoryInfo() {
|
||||
val externalRepo = settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false)
|
||||
val externalRepoPath = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO)
|
||||
if (externalRepo && !hasRequiredStoragePermissions()) {
|
||||
return
|
||||
}
|
||||
if (externalRepo && externalRepoPath != null) {
|
||||
val dir = File(externalRepoPath)
|
||||
if (dir.exists() && dir.isDirectory &&
|
||||
getPasswords(dir, getRepositoryDirectory(), sortOrder).isNotEmpty()) {
|
||||
closeRepository()
|
||||
checkLocalRepository()
|
||||
return // if not empty, just show me the passwords!
|
||||
}
|
||||
}
|
||||
createRepository()
|
||||
}
|
||||
|
||||
private fun runGitOperation(operation: Int) = lifecycleScope.launch {
|
||||
launchGitOperation(operation).fold(
|
||||
success = { refreshPasswordList() },
|
||||
|
@ -413,10 +331,8 @@ class PasswordStore : BaseGitActivity() {
|
|||
* Validates if storage permission is granted, and requests for it if not. The return value
|
||||
* is true if the permission has been granted.
|
||||
*/
|
||||
private fun hasRequiredStoragePermissions(checkLocalRepo: Boolean = false): Boolean {
|
||||
val cloning = supportFragmentManager.findFragmentByTag("ToCloneOrNot") != null
|
||||
return if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED && !cloning) {
|
||||
private fun hasRequiredStoragePermissions(): Boolean {
|
||||
return if (!checkRuntimePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
Snackbar.make(
|
||||
findViewById(R.id.main_layout),
|
||||
getString(R.string.access_sdcard_text),
|
||||
|
@ -432,7 +348,6 @@ class PasswordStore : BaseGitActivity() {
|
|||
}
|
||||
false
|
||||
} else {
|
||||
if (checkLocalRepo)
|
||||
checkLocalRepository()
|
||||
true
|
||||
}
|
||||
|
@ -478,11 +393,7 @@ class PasswordStore : BaseGitActivity() {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
supportActionBar!!.hide()
|
||||
supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||
supportFragmentManager.commit {
|
||||
replace(R.id.main_layout, ToCloneOrNot(), "ToCloneOrNot")
|
||||
}
|
||||
startActivity(Intent(this, OnboardingActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -821,60 +732,6 @@ class PasswordStore : BaseGitActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
fun initRepository(operation: Int) {
|
||||
closeRepository()
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(resources.getString(R.string.location_dialog_title))
|
||||
.setMessage(resources.getString(R.string.location_dialog_text))
|
||||
.setPositiveButton(resources.getString(R.string.location_hidden)) { _, _ ->
|
||||
settings.edit { putBoolean(PreferenceKeys.GIT_EXTERNAL, false) }
|
||||
when (operation) {
|
||||
NEW_REPO_BUTTON -> initializeRepositoryInfo()
|
||||
CLONE_REPO_BUTTON -> {
|
||||
val intent = Intent(activity, GitServerConfigActivity::class.java)
|
||||
intent.putExtra(REQUEST_ARG_OP, REQUEST_CLONE)
|
||||
cloneAction.launch(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
.setNegativeButton(resources.getString(R.string.location_sdcard)) { _, _ ->
|
||||
settings.edit { putBoolean(PreferenceKeys.GIT_EXTERNAL, true) }
|
||||
val externalRepo = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO)
|
||||
if (externalRepo == null) {
|
||||
val intent = Intent(activity, UserPreference::class.java)
|
||||
intent.putExtra("operation", "git_external")
|
||||
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))
|
||||
.setMessage(resources.getString(R.string.directory_selected_message, externalRepo))
|
||||
.setPositiveButton(resources.getString(R.string.use)) { _, _ ->
|
||||
when (operation) {
|
||||
NEW_REPO_BUTTON -> initializeRepositoryInfo()
|
||||
CLONE_REPO_BUTTON -> {
|
||||
val intent = Intent(activity, GitServerConfigActivity::class.java)
|
||||
intent.putExtra(REQUEST_ARG_OP, REQUEST_CLONE)
|
||||
cloneAction.launch(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
.setNegativeButton(resources.getString(R.string.change)) { _, _ ->
|
||||
val intent = Intent(activity, UserPreference::class.java)
|
||||
intent.putExtra("operation", "git_external")
|
||||
when (operation) {
|
||||
NEW_REPO_BUTTON -> repositoryInitAction.launch(intent)
|
||||
CLONE_REPO_BUTTON -> directoryChangeAction.launch(intent)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
fun matchPasswordWithApp(item: PasswordItem) {
|
||||
val path = item.file
|
||||
.absolutePath
|
||||
|
@ -886,14 +743,9 @@ class PasswordStore : BaseGitActivity() {
|
|||
finish()
|
||||
}
|
||||
|
||||
private val sortOrder: PasswordRepository.PasswordSortOrder
|
||||
get() = getSortOrder(settings)
|
||||
|
||||
companion object {
|
||||
|
||||
const val REQUEST_ARG_PATH = "PATH"
|
||||
const val CLONE_REPO_BUTTON = 401
|
||||
const val NEW_REPO_BUTTON = 402
|
||||
private fun isPrintable(c: Char): Boolean {
|
||||
val block = UnicodeBlock.of(c)
|
||||
return (!Character.isISOControl(c) &&
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
package com.zeapo.pwdstore
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.zeapo.pwdstore.databinding.FragmentToCloneOrNotBinding
|
||||
import com.zeapo.pwdstore.utils.viewBinding
|
||||
|
||||
class ToCloneOrNot : Fragment(R.layout.fragment_to_clone_or_not) {
|
||||
|
||||
private val binding by viewBinding(FragmentToCloneOrNotBinding::bind)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.settingsButton.setOnClickListener { startActivity(Intent(requireContext(), UserPreference::class.java)) }
|
||||
binding.localDirectoryButton.setOnClickListener { (requireActivity() as PasswordStore).initRepository(PasswordStore.NEW_REPO_BUTTON) }
|
||||
binding.cloneFromServerButton.setOnClickListener { (requireActivity() as PasswordStore).initRepository(PasswordStore.CLONE_REPO_BUTTON) }
|
||||
}
|
||||
}
|
|
@ -124,7 +124,10 @@ class GitServerConfigActivity : BaseGitActivity() {
|
|||
}
|
||||
snackbar.dismiss()
|
||||
launchGitOperation(REQUEST_CLONE).fold(
|
||||
success = ::finishOnSuccessHandler,
|
||||
success = {
|
||||
setResult(RESULT_OK)
|
||||
finish()
|
||||
},
|
||||
failure = ::finishAfterPromptOnErrorHandler,
|
||||
)
|
||||
}
|
||||
|
@ -159,7 +162,10 @@ class GitServerConfigActivity : BaseGitActivity() {
|
|||
}
|
||||
lifecycleScope.launch {
|
||||
launchGitOperation(REQUEST_CLONE).fold(
|
||||
success = ::finishOnSuccessHandler,
|
||||
success = {
|
||||
setResult(RESULT_OK)
|
||||
finish()
|
||||
},
|
||||
failure = ::finishAfterPromptOnErrorHandler,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.app.KeyguardManager
|
|||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.util.Base64
|
||||
import android.util.TypedValue
|
||||
|
@ -17,6 +18,7 @@ import android.view.inputmethod.InputMethodManager
|
|||
import androidx.annotation.IdRes
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.preference.PreferenceManager
|
||||
|
@ -131,6 +133,10 @@ suspend fun FragmentActivity.commitChange(
|
|||
}.execute()
|
||||
}
|
||||
|
||||
fun FragmentActivity.checkRuntimePermission(permission: String): Boolean {
|
||||
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension function for [AlertDialog] that requests focus for the
|
||||
* view whose id is [id]. Solution based on a StackOverflow
|
||||
|
|
|
@ -20,7 +20,6 @@ import org.eclipse.jgit.transport.URIish
|
|||
|
||||
open class PasswordRepository protected constructor() {
|
||||
|
||||
@Suppress("Unused")
|
||||
enum class PasswordSortOrder(val comparator: Comparator<PasswordItem>) {
|
||||
|
||||
FOLDER_FIRST(Comparator { p1: PasswordItem, p2: PasswordItem ->
|
||||
|
@ -93,10 +92,7 @@ open class PasswordRepository protected constructor() {
|
|||
@JvmStatic
|
||||
fun isGitRepo(): Boolean {
|
||||
if (repository != null) {
|
||||
// Check if remote exists
|
||||
return repository!!.config.getSubsections("remote").isNotEmpty() &&
|
||||
repository!!.objectDatabase.exists() &&
|
||||
repository!!.allRefs.isNotEmpty()
|
||||
return repository!!.objectDatabase.exists()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
<string name="clone">Klonovat ze serveru</string>
|
||||
<string name="initialize">Použít místní adresář</string>
|
||||
<string name="location_dialog_title">Umístění úložiště</string>
|
||||
<string name="location_dialog_text">Zvolte kde vytvořit, nebo kam klonovat vaše úložiště hesel.</string>
|
||||
<string name="location_sdcard">SD-Karta</string>
|
||||
<string name="location_hidden">Skryté (Preferováno)</string>
|
||||
<string name="external_repository_dialog_title">Vyberte kam ukládat hesla</string>
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
<string name="clone">Clonar desde servidor</string>
|
||||
<string name="initialize">Usar directorio local</string>
|
||||
<string name="location_dialog_title">Ubicación del repositorio</string>
|
||||
<string name="location_dialog_text">Selecciona dónde crear o clonar tu repositorio de contraseñas.</string>
|
||||
<string name="location_sdcard">Tarjeta SD</string>
|
||||
<string name="location_hidden">Oculto (Recomendado)</string>
|
||||
<string name="external_repository_dialog_title">Selecciona dónde almacenar tus contraseñas</string>
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
<string name="clone">Cloner depuis le serveur</string>
|
||||
<string name="initialize">Utiliser un répertoire local</string>
|
||||
<string name="location_dialog_title">Location du répertoire</string>
|
||||
<string name="location_dialog_text">Sélectionnez l\'emplacement de création ou de clonage de votre répertoire de mots de passe.</string>
|
||||
<string name="location_sdcard">Carte SD</string>
|
||||
<string name="location_hidden">Caché (Préféré)</string>
|
||||
<string name="external_repository_dialog_title">Choisissez où sauvegarder les mots de passe</string>
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
<string name="clone">Clonar do servidor</string>
|
||||
<string name="initialize">Usar diretório local</string>
|
||||
<string name="location_dialog_title">Local do repositório</string>
|
||||
<string name="location_dialog_text">Selecione onde criar ou clonar o repositório da sua senha.</string>
|
||||
<string name="location_sdcard">Cartão SD</string>
|
||||
<string name="location_hidden">Oculto (preferencial)</string>
|
||||
<string name="external_repository_dialog_title">Escolha onde armazenar as senhas</string>
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
<string name="clone">Клонировать с сервера</string>
|
||||
<string name="initialize">Использовать локальную директорию</string>
|
||||
<string name="location_dialog_title">Расположение репозитория</string>
|
||||
<string name="location_dialog_text">Укажите где создать/клонироввать ваш репозиторий с паролями.</string>
|
||||
<string name="location_sdcard">SD-Карта</string>
|
||||
<string name="location_hidden">Скрытый (Предпочтительно)</string>
|
||||
<string name="external_repository_dialog_title">Выберете где хранить пароли</string>
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
<string name="clone">Clone from server</string>
|
||||
<string name="initialize">Use local directory</string>
|
||||
<string name="location_dialog_title">Repository location</string>
|
||||
<string name="location_dialog_text">Select where to create or clone your password repository.</string>
|
||||
<string name="location_dialog_create_text">Select where to create your password repository</string>
|
||||
<string name="location_sdcard">SD-Card</string>
|
||||
<string name="location_hidden">Hidden (Preferred)</string>
|
||||
<string name="external_repository_dialog_title">Choose where to store the passwords</string>
|
||||
|
|
Loading…
Reference in a new issue