diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fa6cc5fb6..937d51372 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,10 +8,15 @@ android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> - - - - + + + + - Snackbar.make(coordinatorLayout!!, - resultMessage, - Snackbar.LENGTH_LONG).asError().show() - } - } + coordinatorLayout?.showActionError(result) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt index 3472f2a70..d4a255950 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt @@ -52,6 +52,7 @@ import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_TASK +import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.utils.* import com.kunzisoft.keepass.view.asError import kotlinx.android.synthetic.main.activity_file_selection.* @@ -274,12 +275,28 @@ class FileDatabaseSelectActivity : StylishActivity(), updateExternalStorageWarning() // Construct adapter with listeners - mFileDatabaseHistoryAction?.getAllFileDatabaseHistories { databaseFileHistoryList -> - databaseFileHistoryList?.let { - mAdapterDatabaseHistory?.addDatabaseFileHistoryList(it) - updateFileListVisibility() - mAdapterDatabaseHistory?.notifyDataSetChanged() + if (PreferencesUtil.showRecentFiles(this)) { + mFileDatabaseHistoryAction?.getAllFileDatabaseHistories { databaseFileHistoryList -> + databaseFileHistoryList?.let { historyList -> + val hideBrokenLocations = PreferencesUtil.hideBrokenLocations(this@FileDatabaseSelectActivity) + mAdapterDatabaseHistory?.addDatabaseFileHistoryList( + // Show only uri accessible + historyList.filter { + if (hideBrokenLocations) { + UriUtil.parse(it.databaseUri)?.let { historyUri -> + UriUtil.isUriAccessible(contentResolver, historyUri) + } ?: false + } else + true + }) + mAdapterDatabaseHistory?.notifyDataSetChanged() + updateFileListVisibility() + } } + } else { + mAdapterDatabaseHistory?.clearDatabaseFileHistoryList() + mAdapterDatabaseHistory?.notifyDataSetChanged() + updateFileListVisibility() } // Register progress task diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index c60874e50..72c939bc0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -76,6 +76,7 @@ import com.kunzisoft.keepass.utils.MenuUtil import com.kunzisoft.keepass.view.AddNodeButtonView import com.kunzisoft.keepass.view.ToolbarAction import com.kunzisoft.keepass.view.asError +import com.kunzisoft.keepass.view.showActionError class GroupActivity : LockingActivity(), GroupEditDialogFragment.EditGroupListener, @@ -251,15 +252,7 @@ class GroupActivity : LockingActivity(), } } - if (!result.isSuccess) { - coordinatorLayout?.let { coordinatorLayout -> - result.exception?.errorId?.let { errorId -> - Snackbar.make(coordinatorLayout, errorId, Snackbar.LENGTH_LONG).asError().show() - } ?: result.message?.let { message -> - Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_LONG).asError().show() - } - } - } + coordinatorLayout?.showActionError(result) finishNodeAction() diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index fd1e71f29..c75cba034 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -24,7 +24,6 @@ import android.app.assist.AssistStructure import android.app.backup.BackupManager import android.content.Intent import android.content.SharedPreferences -import android.content.pm.PackageManager import android.net.Uri import android.os.Build import android.os.Bundle @@ -33,16 +32,15 @@ import android.preference.PreferenceManager import android.text.Editable import android.text.TextWatcher import android.util.Log -import android.view.KeyEvent -import android.view.Menu -import android.view.MenuItem -import android.view.View +import android.view.* import android.view.inputmethod.EditorInfo.IME_ACTION_DONE -import android.widget.* +import android.widget.Button +import android.widget.CompoundButton +import android.widget.EditText +import android.widget.TextView import androidx.annotation.RequiresApi import androidx.appcompat.widget.Toolbar import androidx.biometric.BiometricManager -import androidx.core.app.ActivityCompat import com.google.android.material.snackbar.Snackbar import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog @@ -74,11 +72,10 @@ import com.kunzisoft.keepass.view.asError import kotlinx.android.synthetic.main.activity_password.* import java.io.FileNotFoundException -class PasswordActivity : StylishActivity() { +open class PasswordActivity : StylishActivity() { // Views private var toolbar: Toolbar? = null - private var containerView: View? = null private var filenameView: TextView? = null private var passwordView: EditText? = null @@ -88,18 +85,28 @@ class PasswordActivity : StylishActivity() { private var checkboxKeyFileView: CompoundButton? = null private var checkboxDefaultDatabaseView: CompoundButton? = null private var advancedUnlockInfoView: AdvancedUnlockInfoView? = null + private var infoContainerView: ViewGroup? = null private var enableButtonOnCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null private var mDatabaseFileUri: Uri? = null private var mDatabaseKeyFileUri: Uri? = null - private var prefs: SharedPreferences? = null + private var mSharedPreferences: SharedPreferences? = null private var mRememberKeyFile: Boolean = false private var mOpenFileHelper: OpenFileHelper? = null - private var mPermissionAsked = false private var readOnly: Boolean = false + private var mForceReadOnly: Boolean = false + set(value) { + infoContainerView?.visibility = if (value) { + readOnly = true + View.VISIBLE + } else { + View.GONE + } + field = value + } private var mProgressDialogThread: ProgressDialogThread? = null @@ -108,9 +115,9 @@ class PasswordActivity : StylishActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - prefs = PreferenceManager.getDefaultSharedPreferences(this) + mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) - mRememberKeyFile = PreferencesUtil.rememberKeyFiles(this) + mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this) setContentView(R.layout.activity_password) @@ -121,7 +128,7 @@ class PasswordActivity : StylishActivity() { supportActionBar?.setDisplayShowHomeEnabled(true) containerView = findViewById(R.id.container) - confirmButtonView = findViewById(R.id.pass_ok) + confirmButtonView = findViewById(R.id.activity_password_open_button) filenameView = findViewById(R.id.filename) passwordView = findViewById(R.id.password) keyFileView = findViewById(R.id.pass_keyfile) @@ -129,8 +136,8 @@ class PasswordActivity : StylishActivity() { checkboxKeyFileView = findViewById(R.id.keyfile_checkox) checkboxDefaultDatabaseView = findViewById(R.id.default_database) advancedUnlockInfoView = findViewById(R.id.biometric_info) + infoContainerView = findViewById(R.id.activity_password_info_container) - mPermissionAsked = savedInstanceState?.getBoolean(KEY_PERMISSION_ASKED) ?: mPermissionAsked readOnly = ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrPreference(this, savedInstanceState) val browseView = findViewById(R.id.open_database_button) @@ -180,6 +187,7 @@ class PasswordActivity : StylishActivity() { removePassword() if (result.isSuccess) { + setEmptyViews() launchGroupActivity() } else { var resultError = "" @@ -281,7 +289,6 @@ class PasswordActivity : StylishActivity() { } override fun onSaveInstanceState(outState: Bundle) { - outState.putBoolean(KEY_PERMISSION_ASKED, mPermissionAsked) ReadOnlyHelper.onSaveInstanceState(outState, readOnly) super.onSaveInstanceState(outState) } @@ -302,6 +309,8 @@ class PasswordActivity : StylishActivity() { keyFileUri = intent.getParcelableExtra(KEY_KEYFILE) } + mForceReadOnly = UriUtil.isUriNotWritable(contentResolver, databaseUri) + // Post init uri with KeyFile if needed if (mRememberKeyFile && (keyFileUri == null || keyFileUri.toString().isEmpty())) { // Retrieve KeyFile in a thread @@ -340,7 +349,7 @@ class PasswordActivity : StylishActivity() { newDefaultFileName = databaseFileUri ?: newDefaultFileName } - prefs?.edit()?.apply { + mSharedPreferences?.edit()?.apply { newDefaultFileName?.let { putString(KEY_DEFAULT_DATABASE_PATH, newDefaultFileName.toString()) } ?: kotlin.run { @@ -355,7 +364,7 @@ class PasswordActivity : StylishActivity() { confirmButtonView?.setOnClickListener { verifyCheckboxesAndLoadDatabase() } // Retrieve settings for default database - val defaultFilename = prefs?.getString(KEY_DEFAULT_DATABASE_PATH, "") + val defaultFilename = mSharedPreferences?.getString(KEY_DEFAULT_DATABASE_PATH, "") if (databaseFileUri != null && databaseFileUri.path != null && databaseFileUri.path!!.isNotEmpty() && databaseFileUri == UriUtil.parse(defaultFilename)) { @@ -551,7 +560,12 @@ class PasswordActivity : StylishActivity() { val inflater = menuInflater // Read menu inflater.inflate(R.menu.open_file, menu) - changeOpenFileReadIcon(menu.findItem(R.id.menu_open_file_read_mode_key)) + + if (mForceReadOnly) { + menu.removeItem(R.id.menu_open_file_read_mode_key) + } else { + changeOpenFileReadIcon(menu.findItem(R.id.menu_open_file_read_mode_key)) + } MenuUtil.defaultMenuInflater(inflater, menu) @@ -562,45 +576,14 @@ class PasswordActivity : StylishActivity() { super.onCreateOptionsMenu(menu) - launchEducation(menu) { - launchCheckPermission() - } + launchEducation(menu) return true } - // Check permission - private fun launchCheckPermission() { - val writePermission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE - val permissions = arrayOf(writePermission) - if (Build.VERSION.SDK_INT >= 23 - && !readOnly - && !mPermissionAsked) { - mPermissionAsked = true - // Check self permission to show or not the dialog - if (toolbar != null - && ActivityCompat.checkSelfPermission(this, writePermission) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, permissions, WRITE_EXTERNAL_STORAGE_REQUEST) - } - } - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - - when (requestCode) { - WRITE_EXTERNAL_STORAGE_REQUEST -> { - if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) { - if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) - Toast.makeText(this, R.string.read_only_warning, Toast.LENGTH_LONG).show() - } - } - } - } - // To fix multiple view education private var performedEductionInProgress = false - private fun launchEducation(menu: Menu, onEducationFinished: ()-> Unit) { + private fun launchEducation(menu: Menu, onEducationFinished: (()-> Unit)? = null) { if (!performedEductionInProgress) { performedEductionInProgress = true // Show education views @@ -610,7 +593,7 @@ class PasswordActivity : StylishActivity() { private fun performedNextEducation(passwordActivityEducation: PasswordActivityEducation, menu: Menu, - onEducationFinished: ()-> Unit) { + onEducationFinished: (()-> Unit)? = null) { val educationToolbar = toolbar val unlockEducationPerformed = educationToolbar != null && passwordActivityEducation.checkAndPerformedUnlockEducation( @@ -650,7 +633,7 @@ class PasswordActivity : StylishActivity() { }) if (!biometricEducationPerformed) { - onEducationFinished.invoke() + onEducationFinished?.invoke() } } } @@ -727,10 +710,6 @@ class PasswordActivity : StylishActivity() { private const val KEY_PASSWORD = "password" private const val KEY_LAUNCH_IMMEDIATELY = "launchImmediately" - private const val KEY_PERMISSION_ASKED = "KEY_PERMISSION_ASKED" - - private const val WRITE_EXTERNAL_STORAGE_REQUEST = 647 - private fun buildAndLaunchIntent(activity: Activity, databaseFile: Uri, keyFile: Uri?, intentBuildLauncher: (Intent) -> Unit) { val intent = Intent(activity, PasswordActivity::class.java) diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/FileDatabaseHistoryAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/FileDatabaseHistoryAdapter.kt index 5907a6b15..3d01189b4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/FileDatabaseHistoryAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/FileDatabaseHistoryAdapter.kt @@ -20,6 +20,8 @@ package com.kunzisoft.keepass.adapters import android.content.Context +import android.graphics.Color +import android.graphics.PorterDuff import androidx.annotation.ColorInt import androidx.recyclerview.widget.RecyclerView import android.util.TypedValue @@ -82,15 +84,26 @@ class FileDatabaseHistoryAdapter(private val context: Context) // File path holder.filePath.text = UriUtil.decode(fileDatabaseInfo.fileUri?.toString()) - holder.filePreciseInfoContainer.visibility = if (fileDatabaseInfo.found()) { - // Modification - holder.fileModification.text = fileDatabaseInfo.getModificationString() - // Size - holder.fileSize.text = fileDatabaseInfo.getSizeString() + if (fileDatabaseInfo.dataAccessible()) { + holder.fileInformation.clearColorFilter() + } else { + holder.fileInformation.setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY) + } - View.VISIBLE - } else - View.GONE + // Modification + if (fileDatabaseInfo.lastModificationAccessible()) { + holder.fileModification.text = fileDatabaseInfo.getModificationString() + holder.fileModification.visibility = View.VISIBLE + } else { + holder.fileModification.visibility = View.GONE + } + // Size + if (fileDatabaseInfo.sizeAccessible()) { + holder.fileSize.text = fileDatabaseInfo.getSizeString() + holder.fileSize.visibility = View.VISIBLE + } else { + holder.fileSize.visibility = View.GONE + } // Click on information val isExpanded = position == mExpandedPosition @@ -142,6 +155,10 @@ class FileDatabaseHistoryAdapter(private val context: Context) return listDatabaseFiles.size } + fun clearDatabaseFileHistoryList() { + listDatabaseFiles.clear() + } + fun addDatabaseFileHistoryList(listFileDatabaseHistoryToAdd: List) { listDatabaseFiles.clear() listDatabaseFiles.addAll(listFileDatabaseHistoryToAdd) @@ -178,7 +195,6 @@ class FileDatabaseHistoryAdapter(private val context: Context) var fileModifyButton: ImageView = itemView.findViewById(R.id.file_modify_button) var fileDeleteButton: ImageView = itemView.findViewById(R.id.file_delete_button) var filePath: TextView = itemView.findViewById(R.id.file_path) - var filePreciseInfoContainer: ViewGroup = itemView.findViewById(R.id.file_precise_info_container) var fileModification: TextView = itemView.findViewById(R.id.file_modification) var fileSize: TextView = itemView.findViewById(R.id.file_size) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/CreateDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/CreateDatabaseRunnable.kt index dc0285883..9ac60a887 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/CreateDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/CreateDatabaseRunnable.kt @@ -24,6 +24,7 @@ import android.net.Uri import android.util.Log import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction import com.kunzisoft.keepass.database.element.Database +import com.kunzisoft.keepass.settings.PreferencesUtil class CreateDatabaseRunnable(context: Context, private val mDatabase: Database, @@ -57,8 +58,11 @@ class CreateDatabaseRunnable(context: Context, if (result.isSuccess) { // Add database to recent files - FileDatabaseHistoryAction.getInstance(context.applicationContext) - .addOrUpdateDatabaseUri(mDatabaseUri, mKeyFile) + if (PreferencesUtil.rememberDatabaseLocations(context)) { + FileDatabaseHistoryAction.getInstance(context.applicationContext) + .addOrUpdateDatabaseUri(mDatabaseUri, + if (PreferencesUtil.rememberKeyFileLocations(context)) mKeyFile else null) + } } else { Log.e("CreateDatabaseRunnable", "Unable to create the database") } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt index 00d5fff24..d584f1bbb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt @@ -74,14 +74,10 @@ class LoadDatabaseRunnable(private val context: Context, override fun onFinishRun() { if (result.isSuccess) { // Save keyFile in app database - val rememberKeyFile = PreferencesUtil.rememberKeyFiles(context) - if (rememberKeyFile) { - var keyUri = mKey - if (!rememberKeyFile) { - keyUri = null - } + if (PreferencesUtil.rememberDatabaseLocations(context)) { FileDatabaseHistoryAction.getInstance(context) - .addOrUpdateDatabaseUri(mUri, keyUri) + .addOrUpdateDatabaseUri(mUri, + if (PreferencesUtil.rememberKeyFileLocations(context)) mKey else null) } // Register the biometric diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt index 067b026c2..31facc9e1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt @@ -75,16 +75,16 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { activity?.let { activity -> allowCopyPassword() - findPreference(getString(R.string.keyfile_key))?.setOnPreferenceChangeListener { _, newValue -> + findPreference(getString(R.string.remember_database_locations_key))?.setOnPreferenceChangeListener { _, newValue -> if (!(newValue as Boolean)) { - FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAllKeyFiles() + FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAll() } true } - findPreference(getString(R.string.recentfile_key))?.setOnPreferenceChangeListener { _, newValue -> + findPreference(getString(R.string.remember_keyfile_locations_key))?.setOnPreferenceChangeListener { _, newValue -> if (!(newValue as Boolean)) { - FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAll() + FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAllKeyFiles() } true } diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt b/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt index f8cb09b1f..c86b90c55 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt @@ -28,10 +28,28 @@ import java.util.* object PreferencesUtil { - fun rememberKeyFiles(context: Context): Boolean { + fun rememberDatabaseLocations(context: Context): Boolean { val prefs = PreferenceManager.getDefaultSharedPreferences(context) - return prefs.getBoolean(context.getString(R.string.keyfile_key), - context.resources.getBoolean(R.bool.keyfile_default)) + return prefs.getBoolean(context.getString(R.string.remember_database_locations_key), + context.resources.getBoolean(R.bool.remember_database_locations_default)) + } + + fun showRecentFiles(context: Context): Boolean { + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + return prefs.getBoolean(context.getString(R.string.show_recent_files_key), + context.resources.getBoolean(R.bool.show_recent_files_default)) + } + + fun hideBrokenLocations(context: Context): Boolean { + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + return prefs.getBoolean(context.getString(R.string.hide_broken_locations_key), + context.resources.getBoolean(R.bool.hide_broken_locations_default)) + } + + fun rememberKeyFileLocations(context: Context): Boolean { + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + return prefs.getBoolean(context.getString(R.string.remember_keyfile_locations_key), + context.resources.getBoolean(R.bool.remember_keyfile_locations_default)) } fun omitBackup(context: Context): Boolean { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt b/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt index 81e8ad6c7..f2099c35a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt @@ -27,6 +27,7 @@ import android.net.Uri import android.os.Bundle import android.view.MenuItem import androidx.appcompat.widget.Toolbar +import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.fragment.app.Fragment import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment @@ -35,6 +36,7 @@ import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper import com.kunzisoft.keepass.activities.lock.LockingActivity import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.timeout.TimeoutHelper +import com.kunzisoft.keepass.view.showActionError open class SettingsActivity : LockingActivity(), @@ -43,6 +45,7 @@ open class SettingsActivity private var backupManager: BackupManager? = null + private var coordinatorLayout: CoordinatorLayout? = null private var toolbar: Toolbar? = null companion object { @@ -74,6 +77,8 @@ open class SettingsActivity super.onCreate(savedInstanceState) setContentView(R.layout.activity_toolbar) + + coordinatorLayout = findViewById(R.id.toolbar_coordinator) toolbar = findViewById(R.id.toolbar) toolbar?.setTitle(R.string.settings) setSupportActionBar(toolbar) @@ -92,6 +97,8 @@ open class SettingsActivity (supportFragmentManager .findFragmentByTag(TAG_NESTED) as NestedSettingsFragment?) ?.onProgressDialogThreadResult(actionTask, result) + + coordinatorLayout?.showActionError(result) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/timeout/ClipboardHelper.kt b/app/src/main/java/com/kunzisoft/keepass/timeout/ClipboardHelper.kt index 83707f92c..a9b8ab7f2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/timeout/ClipboardHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/timeout/ClipboardHelper.kt @@ -98,10 +98,14 @@ class ClipboardHelper(private val context: Context) { @Throws(ClipboardException::class) fun cleanClipboard(label: String = "") { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - getClipboardManager()?.clearPrimaryClip() - } else { - copyToClipboard(label, "") + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + getClipboardManager()?.clearPrimaryClip() + } else { + copyToClipboard(label, "") + } + } catch (e: Exception) { + throw ClipboardException(e) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/utils/FileInfo.kt b/app/src/main/java/com/kunzisoft/keepass/utils/FileInfo.kt index 4041f0422..d7a4a2b72 100644 --- a/app/src/main/java/com/kunzisoft/keepass/utils/FileInfo.kt +++ b/app/src/main/java/com/kunzisoft/keepass/utils/FileInfo.kt @@ -22,8 +22,6 @@ package com.kunzisoft.keepass.utils import android.content.Context import android.net.Uri import android.text.format.Formatter -import androidx.documentfile.provider.DocumentFile -import java.io.File import java.io.Serializable import java.text.DateFormat import java.util.* @@ -34,7 +32,7 @@ open class FileInfo : Serializable { var fileUri: Uri? var filePath: String? = null var fileName: String? = "" - var lastModification = Date() + var lastModification = Date(0L) var size: Long = 0L constructor(context: Context, fileUri: Uri) { @@ -51,22 +49,11 @@ open class FileInfo : Serializable { fun init() { this.filePath = fileUri?.path - if (EXTERNAL_STORAGE_AUTHORITY == fileUri?.authority) { - fileUri?.let { fileUri -> - DocumentFile.fromSingleUri(context, fileUri)?.let { file -> - size = file.length() - fileName = file.name - lastModification = Date(file.lastModified()) - } - } - } else { - filePath?.let { - File(it).let { file -> - size = file.length() - fileName = file.name - lastModification = Date(file.lastModified()) - } - } + + UriUtil.getFileData(context, fileUri)?.let { file -> + size = file.length() + fileName = file.name + lastModification = Date(file.lastModified()) } if (fileName == null || fileName!!.isEmpty()) { @@ -74,10 +61,18 @@ open class FileInfo : Serializable { } } - fun found(): Boolean { + fun lastModificationAccessible(): Boolean { + return lastModification.after(Date(0L)) + } + + fun sizeAccessible(): Boolean { return size != 0L } + fun dataAccessible(): Boolean { + return UriUtil.isUriAccessible(context.contentResolver, fileUri) + } + fun getModificationString(): String { return DateFormat.getDateTimeInstance() .format(lastModification) @@ -86,9 +81,4 @@ open class FileInfo : Serializable { fun getSizeString(): String { return Formatter.formatFileSize(context, size) } - - companion object { - - private const val EXTERNAL_STORAGE_AUTHORITY = "com.android.externalstorage.documents" - } } diff --git a/app/src/main/java/com/kunzisoft/keepass/utils/UriUtil.kt b/app/src/main/java/com/kunzisoft/keepass/utils/UriUtil.kt index 3ded3cb6c..2e22e25e8 100644 --- a/app/src/main/java/com/kunzisoft/keepass/utils/UriUtil.kt +++ b/app/src/main/java/com/kunzisoft/keepass/utils/UriUtil.kt @@ -24,29 +24,87 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Build +import android.util.Log import android.widget.Toast +import androidx.documentfile.provider.DocumentFile import com.kunzisoft.keepass.R +import java.io.File import java.io.FileInputStream import java.io.FileNotFoundException import java.io.InputStream +import java.util.* object UriUtil { - @Throws(FileNotFoundException::class) - fun getUriInputStream(contentResolver: ContentResolver, uri: Uri?): InputStream? { - if (uri == null) - return null - val scheme = uri.scheme - return if (scheme == null || scheme.isEmpty() || scheme == "file") { - FileInputStream(uri.path!!) - } else if (scheme == "content") { - contentResolver.openInputStream(uri) - } else { - null + fun isUriAccessible(contentResolver: ContentResolver, fileUri: Uri?): Boolean { + if (fileUri == null) + return false + return try { + //https://developer.android.com/reference/android/content/res/AssetFileDescriptor + contentResolver.openAssetFileDescriptor(fileUri, "r")?.close() + true + } catch (e: Exception) { + Log.e(UriUtil.javaClass.name, "Unable to access uri $fileUri : ${e.message}") + false } } + fun isUriNotWritable(contentResolver: ContentResolver, fileUri: Uri?): Boolean { + if (fileUri == null) + return true + return try { + contentResolver.openAssetFileDescriptor(fileUri, "wa")?.close() + false + } catch (e: Exception) { + Log.e(UriUtil.javaClass.name, "Unable to access uri $fileUri : ${e.message}") + true + } + } + + fun getFileData(context: Context, fileUri: Uri?): DocumentFile? { + if (fileUri == null) + return null + return when { + isFileScheme(fileUri) -> { + fileUri.path?.let { + File(it).let { file -> + return DocumentFile.fromFile(file) + } + } + } + isContentScheme(fileUri) -> DocumentFile.fromSingleUri(context, fileUri) + else -> null + } + } + + @Throws(FileNotFoundException::class) + fun getUriInputStream(contentResolver: ContentResolver, fileUri: Uri?): InputStream? { + if (fileUri == null) + return null + return when { + isFileScheme(fileUri) -> fileUri.path?.let { FileInputStream(it) } + isContentScheme(fileUri) -> contentResolver.openInputStream(fileUri) + else -> null + } + } + + private fun isFileScheme(fileUri: Uri): Boolean { + val scheme = fileUri.scheme + if (scheme == null || scheme.isEmpty() || scheme.toLowerCase(Locale.ENGLISH) == "file") { + return true + } + return false + } + + private fun isContentScheme(fileUri: Uri): Boolean { + val scheme = fileUri.scheme + if (scheme != null && scheme.toLowerCase(Locale.ENGLISH) == "content") { + return true + } + return false + } + fun parse(stringUri: String?): Uri? { return if (stringUri?.isNotEmpty() == true) { Uri.parse(stringUri) diff --git a/app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt b/app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt index 1daec2536..17fe14f4a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt @@ -29,8 +29,10 @@ import android.view.View import android.view.animation.AccelerateDecelerateInterpolator import android.widget.TextView import androidx.appcompat.widget.Toolbar +import androidx.coordinatorlayout.widget.CoordinatorLayout import com.google.android.material.snackbar.Snackbar import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.tasks.ActionRunnable /** * Replace font by monospace, must be called after seText() @@ -99,4 +101,14 @@ fun Toolbar.expand(animate: Boolean = true) { play(slideAnimator) interpolator = AccelerateDecelerateInterpolator() }.start() +} + +fun CoordinatorLayout.showActionError(result: ActionRunnable.Result) { + if (!result.isSuccess) { + result.exception?.errorId?.let { errorId -> + Snackbar.make(this, errorId, Snackbar.LENGTH_LONG).asError().show() + } ?: result.message?.let { message -> + Snackbar.make(this, message, Snackbar.LENGTH_LONG).asError().show() + } + } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_password.xml b/app/src/main/res/layout/activity_password.xml index 622fe82e7..c45eef25a 100644 --- a/app/src/main/res/layout/activity_password.xml +++ b/app/src/main/res/layout/activity_password.xml @@ -32,7 +32,7 @@ android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@+id/pass_ok"> + app:layout_constraintBottom_toTopOf="@+id/activity_password_info_container"> + android:scrollbarStyle="insideOverlay" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> + + + + . --> - - - - - + + android:layout_height="match_parent"> - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_file_row.xml b/app/src/main/res/layout/item_file_row.xml index 34c612734..d5ac85cc3 100644 --- a/app/src/main/res/layout/item_file_row.xml +++ b/app/src/main/res/layout/item_file_row.xml @@ -186,7 +186,7 @@ إنشاء قاعدة بيانات جديدة … الحماية للقراءة فقط - تذكر أسماء الملفات المستخدمة مؤخرا حذف الجذر استخدام الذاكرة @@ -172,11 +171,8 @@ لا تبحثفي مدخلات النسخ الاحتياطي قيد العمل… KeePassDX يحتاج صلاحية الكتابة من اجل تعديل قاعدة البيانات. - تذكر موقع ملف المفتاح قاعدة البيانات - حفظ الملف المفتاحي خوارزمية تشفير جميع البيانات. قاعدة بيانات غير مدعومة. - اسمح بالكتابة على بطاقة الذاكرة لحفظ التغيرات. اربط بطاقة الذاكرة لإنشاء او تحميل قاعدة بيانات. بناء %1$s تم حفظ كلمة السر المشفرة diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 3b2ed4e38..f1f5ab346 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -113,8 +113,6 @@ Omet els grups \'Còpia de seguretat\' i paperera dels resultats de cerca Creant nova base de dades… Treballant… - Recorda la localització d\'arxius clau - Guarda arxiu clau Elimina Rijndael (AES) Arrel diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index c3a11e3ab..98226e7e0 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -123,10 +123,6 @@ Zpracování… Ochrana Ke změně v databázi potřebuje KeePassDX oprávnění pro zápis. - Historie nedávných souborů - Pamatovat si nedávno otevřené soubory - Pamatovat si umístění souborů s klíči - Uložit soubor s klíčem Odstranit Rijndael (AES) Kořen @@ -144,7 +140,6 @@ Nepodporovaná verze databáze. Velká písmena Verze %1$s - Povolte oprávnění k zápisu na SD kartu, aby bylo možné uložit změny v databázi. Připojte SD kartu, aby bylo možné vytvořit a otevřít databázi. Databázi odemknete zadáním hesla a/nebo souboru s klíčem. \n diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index f4885f3a7..30e73d9dc 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -122,10 +122,6 @@ Arbejder… Beskyttelse KeePassDX behøver skrivetilladelse for at ændre i databasen. - Seneste filhistorik - Husk de seneste filnavne - Husker placeringen af databasernøglefiler - Gem nøglefil Fjern Rijndael (AES) Rod @@ -142,7 +138,6 @@ Understregning Database-versionen er ikke understøttet. Store bogstaver - Giv SD-kort skrive adgang for at gemme databasen ændringer. Monter SD-kortet for at oprette eller indlæse en database. Version %1$s Angiv en adgangskode og/eller en nøglefil til at låse databasen op. diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 02ea6227a..86c045960 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -127,10 +127,6 @@ Sicherheit Schreibgeschützt KeePassDX benötigt Schreibrechte, um etwas an der Datenbank zu ändern. - Zuletzt verwendete Datenbanken - Zuletzt verwendete Datenbanken merken - Erinnert sich an den Speicherort der Schlüsseldateien der Datenbanken - Schlüsselquelle merken Löschen Rijndael (AES) Start @@ -149,7 +145,6 @@ Großbuchstaben Warnung Passwortzeichen in der Datenbank vermeiden, die kein Text-Encoding-Format besitzen (nicht erkannte Zeichen werden in denselben Buchstaben umgewandelt). - Schreibzugriff auf die SD-Karte gewähren, um Datenbankänderungen speichern zu können. Die SD-Karte einbinden, um eine Datenbank erstellen oder laden zu können. Version %1$s Geben Sie das Passwort und/oder die Schlüsseldatei ein, um Ihre Datenbank zu entsperren. diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index c5a30e303..3b4f29368 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -122,10 +122,6 @@ Επεξεργασία… Προστασία Το KeePassDX χρειάζεται άδεια εγγραφής για να αλλάξει οτιδήποτε στη βάση δεδομένων σας. - Πρόσφατο ιστορικό αρχείων - Απομνημόνευση πρόσφατων ονομάτων αρχείων - Απομνημόνευση της τοποθεσίας αρχείων-κλειδιών των βάσεων δεδομένων - Αποθήκευση αρχείου-κλειδιού Αφαίρεση Rijndael (AES) Ριζικός Κατάλογος @@ -190,7 +186,6 @@ Προσπέλαση Προειδοποίηση Αποφύγετε τους χαρακτήρες κωδικού πρόσβασης έξω από τη μορφή κωδικοποίησης κειμένου στο αρχείο βάσης δεδομένων (οι μη αναγνωρισμένοι χαρακτήρες μετατρέπονται στο ίδιο γράμμα). - Δώστε πρόσβαση εγγραφής στην κάρτα SD για να αποθηκεύσετε τις αλλαγές της βάσης δεδομένων. Θέλετε πραγματικά να μην έχετε κανέναν κωδικό προστασίας ξεκλειδώματος; Είστε βέβαιοι ότι δεν θέλετε να χρησιμοποιήσετε κάποιο κλειδί κρυπτογράφησης; Ο Κρυπτογραφημένος κωδικός έχει αποθηκευτεί diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 4aeceeac4..aad777742 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -106,15 +106,11 @@ Nunca Sin resultado de búsqueda Instale un navegador web para abrir este URL. - Historial de archivos recientes - Recordar nombres de archivos recientes Bases de datos recientes No buscar en las entradas de respaldo Omite los grupos «Respaldo» y «Papelera de reciclaje» de los resultados de búsqueda Creando nueva base de datos… Trabajando… - Recuerda la ubicación de los archivos de clave de bases de datos - Guardando archivo de clave Quitar Rijndael (AES) Raíz @@ -314,7 +310,6 @@ Modificable Compilación %1$s Si la supresión automática del portapapeles falla, borran el historial manualmente. - Otorgue permiso de escritura a la tarjeta SD para guardar los cambios en la base de datos. ATENCIÓN: todas las aplicaciones comparten el portapapeles. Si copia datos confidenciales, otros programas podrían recuperarlos. No permitir claves maestras Activar el botón «Abrir» si no se selecciona ninguna credencial diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 7aee88588..ec7b9a50c 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -122,10 +122,6 @@ Datubase berria sortzen… Lanean… Babesa - Duela gutxiko fitxategien historia - Gogoratu duela gutxi erabili diren fitxategien izenak - Gogoratu gako fitxategien kokapenak - Gako fitxategia gorde Ezabatu Rijndael (AES) Root diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 15e8b4a76..0b95273cb 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -121,10 +121,6 @@ Luodaan uutta tietokantaa… Työskennellään… Suojaus - Viimeisten tiedostojen lista - Muista viimeksi käytettyjen tiedostojen nimet - Muista avaintiedostojen sijainti - Tallenna avaintiedosto Poista Rijndael (AES) Juuri diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9d7481d1e..f1c8e02ab 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -132,10 +132,6 @@ Protection Protégé en écriture Selon votre gestionnaire de fichiers, KeePassDX peut ne pas être autorisé à écrire dans votre stockage. - Historique de fichiers récents - Mémorise les noms des fichiers récents - Mémorise l’emplacement des fichiers clé des bases de données - Enregistrer le fichier clé Supprimer Racine Algorithme de chiffrement de la base de données utilisé pour toutes les données. @@ -167,7 +163,6 @@ Majuscules Alerte Éviter les caractères en dehors du format de codage de caractères du fichier de base de données (les caractères non reconnus sont convertis en une même lettre). - Accorder l’accès en écriture à la mémoire pour enregistrer les modifications de la base de données. Monter la carte mémoire pour créer ou charger une base de données. Ne voulez-vous vraiment aucune protection de déverrouillage par mot de passe \? Êtes-vous sûr de ne vouloir utiliser aucune clé de chiffrement \? diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 7b219b5da..afade3eb4 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -123,10 +123,6 @@ Védelem Írásvédett A KeePassDX-nek írási engedélyre van szüksége, hogy bármit is módosíthasson az adatbázisban. - Előző fájlok előzményei - Az előző fájlnevek megjegyzése - Megjegyzi az adatbázis-kulcsfájlok helyét - Kulcsfájl mentése Eltávolítás Rijndael (AES) Gyökérkönyvár @@ -212,7 +208,6 @@ Létrehozás Módosítás Hozzáférés - SD kártya írási jogosultság megadása az adatbázis-változások mentéséhez. Biztos, hogy nem akar jelszavas feloldási védelmet\? Biztos, hogy nem akar semmilyen titkosítási kulcsot használni\? Összeállítás: %1$s diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 6b04c912c..a3fd72d1c 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -123,10 +123,6 @@ Protezione Sola lettura KeePassDX richiede l\'autorizzazione di scrittura per poter modificare il tuo database. - Cronologia file recenti - Ricorda i file recenti - Ricorda la posizione dei file chiave dei database - Salva il file chiave Elimina Root Livello cifratura @@ -143,7 +139,6 @@ Maiuscole Attenzione Evita password con caratteri al di fuori del formato di codifica del testo nel file di database (i caratteri non riconosciuti vengono convertiti nella stessa lettera). - Permetti l\'accesso in scrittura alla scheda SD per salvare le modifiche al database. Monta la scheda SD per creare o caricare un database. Versione %1$s La scansione di impronte è supportata ma non impostata. diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 837f7e2a1..8cfc5413a 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -119,10 +119,6 @@ עובד… הגנה ל-KeePassDX אין הרשאות כתיבה למסד הנתונים הזה, ולכן הוא יפתח לקריאה בלבד. - היסטוריית קובץ אחרונה - שמור קבצים שהיו בשימוש לאחרונה - זכור מיקום קבצי מפתח - שמור קובץ מפתח הסר סיבובי הצפנה מספר סיבובי הצפנה גבוה יותר מספר הגה טובה יותר נגד התקפות, אבל יכול להעלות בהרבה את זמן הטעינה והשמירה. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 675ab7350..098064671 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -109,8 +109,6 @@ \"バックアップ\"と\"ごみ箱\"を検索対象から除外します データベースファイルを作成中… 実行中… - 前回使用したキーファイルを次回も表示します - キーファイルを記憶 消去 Rijndael (AES) Root @@ -181,8 +179,6 @@ 保護 書き込み保護 KeePassDX は、データベースを変更するために書き込みアクセス許可が必要です。 - 最近使用したファイルの履歴 - 最近使用したファイル名を記憶します すべてのデータで使用するデータベース暗号化アルゴリズム。 並び順 昇順 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index f4cd4241b..cafb5257d 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -145,10 +145,6 @@ 보호 쓰기 보호됨 KeePassDX는 데이터베이스를 수정하기 위해 쓰기 권한이 필요합니다. - 최근 파일 기록 - 최근 파일 이름 기억하기 - 데이터베이스 키 파일 위치 기억하기 - 키 파일 저장 삭제 루트 데이터베이스 암호화 알고리즘이 모든 데이터에 적용됩니다. diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index a7bb667c7..aa1cb15d2 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -58,10 +58,6 @@ Įspėjimas Įveskite duomenų bazės failą Įveskite teigiamą skaičių ilgio lauke - Naujausių failų istorija - Atsiminti paskutinius naudotus failų pavadinimus - Saugoti rakto failą - Atsimena rakto failų vietą Pašalinti Šaknis Tik skaitymui diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index f40d6a106..7f01bbf3b 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -101,10 +101,6 @@ Izveido jaunu datu bāzi… Darbojas… Aizsardzība - Nesen atvērtie - Glabāt atvērto failu nosaukumus - Atcerēties šo atslēgas faila vietu - Saglabāt atslēgas failu Noņemt Rijndael (AES) Root diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 178ffc274..51d3e1e25 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -144,10 +144,6 @@ Beskyttelse Skrivebeskyttet KeePassDX har ikke skrivetilgang til din databaseplassering, så den vil bli åpnet skrivebeskyttet. - Nylig filhistorikk - Husk nylig brukte filnavn - Husk nøkkelfilers plassering - Lagre nøkkelfil Fjern Rot Algoritme for å kryptere hele databasen. (Passord, brukernavn, merknader og all data i databasen er kryptert med valgt algoritme). @@ -179,7 +175,6 @@ Store bokstaver Advarsel Unngå passordtegn utenfor tekstkodingsformat i databasefil (ukjente tegn blir konvertert til samme bokstav). - SD-kortet ditt er i øyeblikket skrivebeskyttet. Det kan hende du ikke kan lagre endringer i databasen din. SD-kortet ditt er ikke montert på enheten din. Du vil ikke kunne laste inne eller opprette din database. Ønsker du virkelig å bruke en tom streng som ditt passord? Er du sikker på at du ønsker å bruke en krypteringsnøkkel? diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 38bfaa7d7..4f91d3856 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -111,8 +111,6 @@ Hiermee worden groepen \"Back-up\" en \"Prullenbak\" uit de zoekresultaten weggelaten Bezig met creëren van nieuwe databank… Bezig met verwerken… - Locatie van databank-sleutelbestanden onthouden - Sleutelbestand opslaan Verwijderen Rijndael (AES) Hoofdmap @@ -128,7 +126,6 @@ Onderstrepen Niet-ondersteunde databankversie. Hoofdletters - Machtig schrijftoegang om de databankwijzigingen op ge slaan. Koppel de SD-kaart aan om een databank te creëren of laden. Versie %1$s Geef het wachtwoord en/of sleutelbestand op om je databank te ontgrendelen. @@ -185,8 +182,8 @@ Beveiliging Alleen-lezen KeePassDX moet worden gemachtigd om je databank te kunnen aanpassen. - Recente bestandgeschiedenis - Recent gebruikte bestandsnamen onthouden + Recente bestandgeschiedenis + Recent gebruikte bestandsnamen onthouden Het algoritme dat moet worden gebruikt om de gehele databank te versleutelen. Om de sleutel voor het algoritme te kunnen genereren, wordt de hoofdsleutel getransformeerd middels een willekeurige afleidingsfunctie. Geheugengebruik diff --git a/app/src/main/res/values-nn/strings.xml b/app/src/main/res/values-nn/strings.xml index 9e0372953..5d01de553 100644 --- a/app/src/main/res/values-nn/strings.xml +++ b/app/src/main/res/values-nn/strings.xml @@ -110,8 +110,6 @@ Søkjeresultatet inneheld ikkje oppføringar frå \'Backup\' eller søppelbøtta Lager ny database … Arbeider … - Hugsar staden til nøkkelfilene - Lagra nøkkelfila Ta vekk Rijndael (AES) Rot diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 01245c1e8..d770e20b6 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -108,10 +108,6 @@ Pomija grupy „Kopia zapasowa” i „Kosz” w wynikach wyszukiwania Tworzenie nowej bazy danych… Pracuję… - Najnowsza historia plików - Zapamiętaj najnowsze nazwy plików - Zapamiętuje lokalizację plików kluczy baz danych - Zapisz plik klucza Usuń Rijndael (AES) Root @@ -127,7 +123,6 @@ Podkreślenie Nieobsługiwana wersja bazy danych. Wielkie litery - Przydziel dostęp do zapisu na karcie SD, aby zapisać zmiany w bazie danych. Zamontuj kartę SD, aby utworzyć lub załadować bazę danych. prowadź hasło i/lub plik klucza, aby odblokować bazę danych. \n diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 63e7dc803..983dea3e1 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -109,8 +109,6 @@ Omite os grupos \"Backup\" e \"Lixeira\" dos resultados da busca Criando novo banco de dados… Trabalhando… - Lembra o local dos arquivos-chave dos bancos de dados - Salvar arquivo de chave Remover Rijndael (AES) Raiz @@ -177,8 +175,8 @@ Proteção Apenas leitura KeePassDX precisa de permissões de escrita para poder mudar qualquer coisa no seu banco. - Histórico de arquivos recentes - Lembrar nomes recentes de arquivos + Histórico de arquivos recentes + Lembrar nomes recentes de arquivos Algoritmo de encriptação usado para todos os dados. Para gerar uma chave para o algoritmo de encriptação, a chave mestre é transformada usando uma função de derivação de chave. Uso de memória @@ -321,7 +319,6 @@ Pacote de ícones Pacote de ícones usado no aplicativo Editar entrada - Conceda acesso de escrita ao cartão SD para salvar alterações do banco. Falha ao carregar o banco. Não pôde carregar a chave. Tente diminuir o \"Uso de Memória\" do KDF. Mostrar nomes de usuário diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index be8ebc0a5..0b3f9f044 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -124,10 +124,6 @@ Proteção Apenas leitura KeePassDX precisa de permissões de escrita para poder mudar qualquer coisa no seu banco. - Histórico de ficheiros recentes - Lembrar nomes recentes de ficheiros - Lembra o local dos ficheiros-chave dos bancos de dados - Guardar ficheiro chave Remover Rijndael (AES) Raiz @@ -221,7 +217,6 @@ Deslize para o lado para limpar agora a área de transferência Não pôde ser habilitado o serviço de preenchimento automático. Algoritmo de encriptação usado para todos os dados. - Conceda acesso de escrita ao cartão SD para salvar alterações do banco. Define o tamanho padrão para palavras-passe geradas Caracteres da palavra-passe Definir os caracteres padrão do gerador de palavra-passe diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 00c9f4c48..75b79355e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -123,10 +123,6 @@ Защита Только чтение KeePassDX необходимо разрешение на запись, чтобы иметь возможность изменить что-либо в вашей базе. - Базы паролей - Хранить имена недавно открытых баз - Хранить пути к файлам ключей - Файлы ключей Убрать из списка Rijndael (AES) База @@ -145,7 +141,6 @@ ЗАГЛАВНЫЕ Внимание Избегайте использования в пароле символов вне кодировки текста в файле базы, так как эти символы будут преобразованы в одинаковый символ. - Предоставьте доступ к хранилищу на запись для сохранения изменений в базе. Подключите хранилище для создания или загрузки базы. Версия %1$s Биометрия поддерживается, но не настроена. diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 2098b18bc..c55817e06 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -109,8 +109,6 @@ Vynechať skupinu \'Backup\' a Recycle Bin z výsledkov hľadania Vytváram novú databázu… Pracujem… - Zapamätať si umiestnenie keyfile - Uložiť keyfile Odstrániť Rijndael (AES) Root diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index d7d73bec9..b11fb95ad 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -121,8 +121,6 @@ Skapar ny databas… Arbetar… Skydd - Kommer ihåg sökvägar till databasers nyckelfiler - Spara nyckelfil Ta bort Rijndael (AES) Root @@ -192,8 +190,6 @@ Formulär-ifyllning Skrivskyddad KeePass DX behöver skrivbehörighet för att ändra något i din databas. - Senaste filhistorik - Kom ihåg senaste filnamn Krypteringsalgoritm som används för all data i databasen. För att generera nyckeln till krypteringsalgoritmen kommer huvudnyckeln transformeras med en slumpmässigt saltad nyckelderivatsfunktion. Minnesanvändning @@ -211,7 +207,6 @@ Åtkomst Varning Undvik lösenordstecken utöver textkodningsformatet i databasfilen (okända tecken konverteras till samma bokstav). - Ge tillåtelse att skriva till SD-kortet för att spara ändringar i databasen. Är du säker på att du verkligen inte vill skydda dina lösenord från att låsas upp\? Är du säker på att du inte vill använda en krypteringsnyckel\? Krypterat lösenord sparat diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 49d0d77ac..1e6dd0ebf 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -144,10 +144,6 @@ Koruma Yazma korumalı Veritabanınızdaki herhangi bir şeyi değiştirmek için KeePassDX\'in yazma iznine ihtiyacı var. - Son dosya geçmişi - Son dosya adlarını hatırla - Veritabanı anahtar dosyaların yerini hatırlar - Anahtar dosya kaydet Kaldır Kök Tüm veriler için veritabanı şifreleme algoritması kullanılmıştır. @@ -180,7 +176,6 @@ Büyük harf Uyarı Veritabanı dosyasındaki metin kodlama formatının dışındaki parola karakterlerinden kaçının (tanınmayan karakterler benzer harfe dönüştürülür). - Veritabanı değişikliklerini kaydetmek için bellek yazma erişimi verin. Bir veritabanı oluşturmak veya yüklemek için hafıza kartını takın. Gerçekten parolasız açma koruması mı istiyorsunuz\? Herhangi bir şifreleme anahtarı kullanmak istemediğinize emin misiniz\? diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 78ed3eae0..aee10cdbc 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -110,8 +110,6 @@ Пропустити групу \'Резервна копія\' та Кошик серед результатів пошуку Створення нової бази даних… Працює… - Запам’ятати розташування файла ключа - Збережіть файл ключа Вилучити Rijndael (AES) Корінь diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index ba40e9286..efd63fc1e 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -106,8 +106,6 @@ 最近使用过的数据库 正在创建新数据库… 正在处理… - 记住密钥文件的位置 - 保存密钥文件 移除 Rijndael (AES) Root @@ -123,7 +121,6 @@ 下划线 不支持的数据库版本。 大写 - 请授予 SD 卡写入权限以保存数据库。 请挂载SD卡以创建或加载数据库。 输入密码和/或一个密钥文件来解锁你的数据库。 \n @@ -184,8 +181,8 @@ 保护 只读 KeePassDX 需要写入权限以修改数据库。 - 最近文件历史 - 记住最近使用的文件名 + 最近文件历史 + 记住最近使用的文件名 加密所有数据时采用的算法。 将转换主密钥以生成加密数据库所需的密钥,转换方式为随机加盐算法。 内存使用量 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index d4e5287ce..0bbfaeb4a 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -106,8 +106,6 @@ 最近打開的資料庫: 創建新資料庫中… 工作中… - 記住密鑰檔的位置 - 保存密鑰檔 移除 Rijndael加密(AES) Root @@ -206,8 +204,6 @@ 欄位值 找不到檔案。嘗試從檔案瀏覽器重新打開它。 從搜尋結果中省略\"備份\"和\"回收站\"組 - 最近的檔案歷史記錄 - 記住最近的檔案名 用於所有資料的資料庫加密演算法。 記憶體使用情況 密钥推導函數要使用的記憶體量(以二进制字节为单位)。 diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 9fef12e93..59c422441 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -83,10 +83,14 @@ true allow_copy_password_key false - recentfile - true - keyfile - true + remember_database_locations_key + true + show_recent_files_key + true + hide_broken_locations_key + true + remember_keyfile_locations_key + true advanced_unlock_explanation_key biometric_unlock_enable_key false diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 715309950..fe7815e98 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -203,10 +203,14 @@ The database contains duplicate UUIDs. By validating this dialog, KeePassDX will fix the problem (by generating new UUIDs for duplicates) and continue. Selection mode - Recent file history - Remember recent filenames - Remembers the location of databases keyfiles - Save keyfile + Save location of databases + Remember the location of databases + Show recent files + Show locations of recent databases + Hide broken database links + Hide broken links in the list of recent databases + Save location of keyfiles + Remember the location of databases keyfiles Root Database encryption algorithm used for all data. To generate the key for the encryption algorithm, the master key is transformed using a randomly salted key derivation function. @@ -240,7 +244,7 @@ Upper-case Warning Avoid password characters outside of text encoding format in database file (unrecognized chars are converted to the same letter). - Grant memory write access to save database changes. + Grant file write access to save database changes Mount the memory card to create or load a database. Do you really want no password unlocking protection? Are you sure you do not want to use any encryption key? diff --git a/app/src/main/res/xml/preferences_application.xml b/app/src/main/res/xml/preferences_application.xml index 59c8ef1ec..1c779f2df 100644 --- a/app/src/main/res/xml/preferences_application.xml +++ b/app/src/main/res/xml/preferences_application.xml @@ -121,16 +121,28 @@ android:title="@string/database_history"> + android:key="@string/remember_database_locations_key" + android:title="@string/remember_database_locations_title" + android:summary="@string/remember_database_locations_summary" + android:defaultValue="@bool/remember_database_locations_default"/> + android:key="@string/show_recent_files_key" + android:title="@string/show_recent_files_title" + android:summary="@string/show_recent_files_summary" + android:dependency="@string/remember_database_locations_key" + android:defaultValue="@bool/show_recent_files_default"/> + +