mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'develop' of github.com:Kunzisoft/KeePassDX into develop
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
KeePassDX(2.8)
|
||||
* Fix TOTP period (> 60s)
|
||||
* Fix searching in recycle bin
|
||||
* Settings to back to the previous keyboard during database credentials and after form filling
|
||||
* Improve action tasks
|
||||
* Improve recognition to reset app timeout
|
||||
* Fix minor issues
|
||||
|
||||
KeePassDX(2.7)
|
||||
* Add blocklists for autofill
|
||||
|
||||
@@ -102,6 +102,9 @@ dependencies {
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'androidx.biometric:biometric:1.0.1'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
|
||||
// TODO #538 implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
|
||||
// To upgrade with style
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
// Database
|
||||
|
||||
@@ -89,7 +89,7 @@ class EntryActivity : LockingActivity() {
|
||||
private var mAttachmentsToDownload: HashMap<Int, EntryAttachment> = HashMap()
|
||||
|
||||
private var clipboardHelper: ClipboardHelper? = null
|
||||
private var firstLaunchOfActivity: Boolean = false
|
||||
private var mFirstLaunchOfActivity: Boolean = false
|
||||
|
||||
private var iconColor: Int = 0
|
||||
|
||||
@@ -130,9 +130,12 @@ class EntryActivity : LockingActivity() {
|
||||
lockAndExit()
|
||||
}
|
||||
|
||||
// Focus view to reinitialize timeout
|
||||
resetAppTimeoutWhenViewFocusedOrChanged(coordinatorLayout)
|
||||
|
||||
// Init the clipboard helper
|
||||
clipboardHelper = ClipboardHelper(this)
|
||||
firstLaunchOfActivity = true
|
||||
mFirstLaunchOfActivity = savedInstanceState?.getBoolean(KEY_FIRST_LAUNCH_ACTIVITY) ?: true
|
||||
|
||||
// Init attachment service binder manager
|
||||
mAttachmentFileBinderManager = AttachmentFileBinderManager(this)
|
||||
@@ -196,7 +199,7 @@ class EntryActivity : LockingActivity() {
|
||||
val entryInfo = entry.getEntryInfo(Database.getInstance())
|
||||
|
||||
// Manage entry copy to start notification if allowed
|
||||
if (firstLaunchOfActivity) {
|
||||
if (mFirstLaunchOfActivity) {
|
||||
// Manage entry to launch copying notification if allowed
|
||||
ClipboardEntryNotificationService.launchNotificationIfAllowed(this, entryInfo)
|
||||
// Manage entry to populate Magikeyboard and launch keyboard notification if allowed
|
||||
@@ -215,7 +218,7 @@ class EntryActivity : LockingActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
firstLaunchOfActivity = false
|
||||
mFirstLaunchOfActivity = false
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
@@ -542,6 +545,11 @@ class EntryActivity : LockingActivity() {
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
|
||||
outState.putBoolean(KEY_FIRST_LAUNCH_ACTIVITY, mFirstLaunchOfActivity)
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
// Transit data in previous Activity after an update
|
||||
@@ -555,6 +563,8 @@ class EntryActivity : LockingActivity() {
|
||||
companion object {
|
||||
private val TAG = EntryActivity::class.java.name
|
||||
|
||||
private const val KEY_FIRST_LAUNCH_ACTIVITY = "KEY_FIRST_LAUNCH_ACTIVITY"
|
||||
|
||||
const val KEY_ENTRY = "KEY_ENTRY"
|
||||
const val KEY_ENTRY_HISTORY_POSITION = "KEY_ENTRY_HISTORY_POSITION"
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
private var scrollView: NestedScrollView? = null
|
||||
private var entryEditContentsView: EntryEditContentsView? = null
|
||||
private var entryEditAddToolBar: ActionMenuView? = null
|
||||
private var saveView: View? = null
|
||||
private var validateButton: View? = null
|
||||
private var lockView: View? = null
|
||||
|
||||
// Education
|
||||
@@ -121,7 +121,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
}
|
||||
|
||||
// Focus view to reinitialize timeout
|
||||
resetAppTimeoutWhenViewFocusedOrChanged(entryEditContentsView)
|
||||
resetAppTimeoutWhenViewFocusedOrChanged(coordinatorLayout)
|
||||
|
||||
stopService(Intent(this, ClipboardEntryNotificationService::class.java))
|
||||
stopService(Intent(this, KeyboardEntryNotificationService::class.java))
|
||||
@@ -237,8 +237,8 @@ class EntryEditActivity : LockingActivity(),
|
||||
}
|
||||
|
||||
// Save button
|
||||
saveView = findViewById(R.id.entry_edit_validate)
|
||||
saveView?.setOnClickListener { saveEntry() }
|
||||
validateButton = findViewById(R.id.entry_edit_validate)
|
||||
validateButton?.setOnClickListener { saveEntry() }
|
||||
|
||||
// Verify the education views
|
||||
entryEditActivityEducation = EntryEditActivityEducation(this)
|
||||
|
||||
@@ -65,7 +65,6 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
// Views
|
||||
private var coordinatorLayout: CoordinatorLayout? = null
|
||||
private var fileManagerExplanationButton: View? = null
|
||||
private var databaseButtonsContainerView: View? = null
|
||||
private var createDatabaseButtonView: View? = null
|
||||
private var openDatabaseButtonView: View? = null
|
||||
|
||||
@@ -97,8 +96,6 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
UriUtil.gotoUrl(this, R.string.file_manager_explanation_url)
|
||||
}
|
||||
|
||||
databaseButtonsContainerView = findViewById(R.id.database_buttons_container)
|
||||
|
||||
// Create database button
|
||||
createDatabaseButtonView = findViewById(R.id.create_database_button)
|
||||
createDatabaseButtonView?.setOnClickListener { createNewFile() }
|
||||
@@ -271,8 +268,8 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
|
||||
// Show open and create button or special mode
|
||||
if (mSelectionMode) {
|
||||
// Disable buttons if in selection mode or request for autofill
|
||||
databaseButtonsContainerView?.visibility = View.GONE
|
||||
// Disable create button if in selection mode or request for autofill
|
||||
createDatabaseButtonView?.visibility = View.GONE
|
||||
} else {
|
||||
if (allowCreateDocumentByStorageAccessFramework(packageManager)) {
|
||||
// There is an activity which can handle this intent.
|
||||
@@ -281,7 +278,6 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
// No Activity found that can handle this intent.
|
||||
createDatabaseButtonView?.visibility = View.GONE
|
||||
}
|
||||
databaseButtonsContainerView?.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
val database = Database.getInstance()
|
||||
@@ -403,11 +399,12 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
|
||||
private fun performedNextEducation(fileDatabaseSelectActivityEducation: FileDatabaseSelectActivityEducation) {
|
||||
// If no recent files
|
||||
val createDatabaseEducationPerformed = createDatabaseButtonView != null && createDatabaseButtonView!!.visibility == View.VISIBLE
|
||||
val createDatabaseEducationPerformed =
|
||||
createDatabaseButtonView != null && createDatabaseButtonView!!.visibility == View.VISIBLE
|
||||
&& mAdapterDatabaseHistory != null
|
||||
&& mAdapterDatabaseHistory!!.itemCount > 0
|
||||
&& fileDatabaseSelectActivityEducation.checkAndPerformedCreateDatabaseEducation(
|
||||
createDatabaseButtonView!!,
|
||||
createDatabaseButtonView!!,
|
||||
{
|
||||
createNewFile()
|
||||
},
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.RequiresApi
|
||||
@@ -90,6 +91,7 @@ class GroupActivity : LockingActivity(),
|
||||
SortDialogFragment.SortSelectionListener {
|
||||
|
||||
// Views
|
||||
private var rootContainerView: ViewGroup? = null
|
||||
private var coordinatorLayout: CoordinatorLayout? = null
|
||||
private var lockView: View? = null
|
||||
private var toolbar: Toolbar? = null
|
||||
@@ -130,6 +132,7 @@ class GroupActivity : LockingActivity(),
|
||||
setContentView(layoutInflater.inflate(R.layout.activity_group, null))
|
||||
|
||||
// Initialize views
|
||||
rootContainerView = findViewById(R.id.activity_group_container_view)
|
||||
coordinatorLayout = findViewById(R.id.group_coordinator)
|
||||
iconView = findViewById(R.id.group_icon)
|
||||
numberChildrenView = findViewById(R.id.group_numbers)
|
||||
@@ -153,7 +156,7 @@ class GroupActivity : LockingActivity(),
|
||||
taTextColor.recycle()
|
||||
|
||||
// Focus view to reinitialize timeout
|
||||
resetAppTimeoutWhenViewFocusedOrChanged(addNodeButtonView)
|
||||
resetAppTimeoutWhenViewFocusedOrChanged(rootContainerView)
|
||||
|
||||
// Retrieve elements after an orientation change
|
||||
if (savedInstanceState != null) {
|
||||
|
||||
@@ -64,9 +64,7 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.MASTER_PASSWORD_KEY
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.READ_ONLY_KEY
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.FileDatabaseInfo
|
||||
import com.kunzisoft.keepass.utils.MenuUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.*
|
||||
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
|
||||
import com.kunzisoft.keepass.view.KeyFileSelectionView
|
||||
import com.kunzisoft.keepass.view.asError
|
||||
@@ -355,6 +353,11 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
|
||||
// Back to previous keyboard is setting activated
|
||||
if (PreferencesUtil.isKeyboardPreviousDatabaseCredentialsEnable(this)) {
|
||||
sendBroadcast(Intent(BACK_PREVIOUS_KEYBOARD_ACTION))
|
||||
}
|
||||
|
||||
// Don't allow auto open prompt if lock become when UI visible
|
||||
mAllowAutoOpenBiometricPrompt = if (LockingActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK == true)
|
||||
false
|
||||
|
||||
@@ -89,13 +89,13 @@ class OpenFileHelper {
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
private fun openActivityWithActionOpenDocument() {
|
||||
val intentOpenDocument = Intent(APP_ACTION_OPEN_DOCUMENT).apply {
|
||||
val intentOpenDocument = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/*"
|
||||
flags = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
||||
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
}
|
||||
if (fragment != null)
|
||||
fragment?.startActivityForResult(intentOpenDocument, OPEN_DOC)
|
||||
@@ -108,10 +108,10 @@ class OpenFileHelper {
|
||||
val intentGetContent = Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/*"
|
||||
flags = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
||||
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
}
|
||||
if (fragment != null)
|
||||
fragment?.startActivityForResult(intentGetContent, GET_CONTENT)
|
||||
@@ -226,12 +226,6 @@ class OpenFileHelper {
|
||||
|
||||
private const val TAG = "OpenFileHelper"
|
||||
|
||||
private var APP_ACTION_OPEN_DOCUMENT: String = try {
|
||||
Intent::class.java.getField("ACTION_OPEN_DOCUMENT").get(null) as String
|
||||
} catch (e: Exception) {
|
||||
"android.intent.action.OPEN_DOCUMENT"
|
||||
}
|
||||
|
||||
const val OPEN_INTENTS_FILE_BROWSE = "org.openintents.action.PICK_FILE"
|
||||
|
||||
private const val GET_CONTENT = 25745
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.activities.lock
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
@@ -71,6 +72,7 @@ abstract class LockingActivity : SpecialModeActivity() {
|
||||
LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = LOCKING_ACTIVITY_UI_VISIBLE
|
||||
// Add onActivityForResult response
|
||||
setResult(RESULT_EXIT_LOCK)
|
||||
closeOptionsMenu()
|
||||
finish()
|
||||
}
|
||||
registerLockReceiver(mLockReceiver)
|
||||
@@ -151,11 +153,21 @@ abstract class LockingActivity : SpecialModeActivity() {
|
||||
/**
|
||||
* To reset the app timeout when a view is focused or changed
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
protected fun resetAppTimeoutWhenViewFocusedOrChanged(vararg views: View?) {
|
||||
views.forEach {
|
||||
it?.setOnTouchListener { _, event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
// Log.d(TAG, "View touched, try to reset app timeout")
|
||||
TimeoutHelper.checkTimeAndLockIfTimeoutOrResetTimeout(this)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
it?.setOnFocusChangeListener { _, hasFocus ->
|
||||
if (hasFocus) {
|
||||
Log.d(TAG, "View focused, reset app timeout")
|
||||
// Log.d(TAG, "View focused, try to reset app timeout")
|
||||
TimeoutHelper.checkTimeAndLockIfTimeoutOrResetTimeout(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,12 +52,19 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
|
||||
private var biometricUnlockDatabaseHelper: BiometricUnlockDatabaseHelper? = null
|
||||
private var biometricMode: Mode = Mode.UNAVAILABLE
|
||||
|
||||
/**
|
||||
* Manage setting to auto open biometric prompt
|
||||
*/
|
||||
private var biometricPromptAutoOpenPreference = PreferencesUtil.isBiometricPromptAutoOpenEnable(context)
|
||||
var isBiometricPromptAutoOpenEnable: Boolean = true
|
||||
get() {
|
||||
return field && biometricPromptAutoOpenPreference
|
||||
}
|
||||
|
||||
// Variable to check if the prompt can be open (if the right activity is currently shown)
|
||||
// checkBiometricAvailability() allows open biometric prompt and onDestroy() removes the authorization
|
||||
private var allowOpenBiometricPrompt = false
|
||||
|
||||
private var cipherDatabaseAction = CipherDatabaseAction.getInstance(context.applicationContext)
|
||||
|
||||
init {
|
||||
@@ -77,6 +84,7 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
|
||||
// biometric not supported (by API level or hardware) so keep option hidden
|
||||
// or manually disable
|
||||
val biometricCanAuthenticate = BiometricManager.from(context).canAuthenticate()
|
||||
allowOpenBiometricPrompt = true
|
||||
|
||||
if (!PreferencesUtil.isBiometricUnlockEnable(context)
|
||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|
||||
@@ -210,7 +218,8 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
|
||||
cryptoObject: BiometricPrompt.CryptoObject,
|
||||
promptInfo: BiometricPrompt.PromptInfo) {
|
||||
context.runOnUiThread {
|
||||
biometricPrompt?.authenticate(promptInfo, cryptoObject)
|
||||
if (allowOpenBiometricPrompt)
|
||||
biometricPrompt?.authenticate(promptInfo, cryptoObject)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,6 +286,7 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
|
||||
|
||||
fun destroy() {
|
||||
// Close the biometric prompt
|
||||
allowOpenBiometricPrompt = false
|
||||
biometricUnlockDatabaseHelper?.closeBiometricPrompt()
|
||||
// Restore the checked listener
|
||||
checkboxPasswordView?.setOnCheckedChangeListener(onCheckedPasswordChangeListener)
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
||||
import com.kunzisoft.keepass.database.exception.LoadDatabaseException
|
||||
import com.kunzisoft.keepass.notifications.DatabaseOpenNotificationService
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
@@ -86,9 +85,6 @@ class LoadDatabaseRunnable(private val context: Context,
|
||||
|
||||
// Register the current time to init the lock timer
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
|
||||
// Start the opening notification
|
||||
DatabaseOpenNotificationService.start(context)
|
||||
} else {
|
||||
mDatabase.closeAndClear(cacheDirectory)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.kunzisoft.keepass.activities.lock.LockingActivity
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
||||
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
@@ -37,7 +36,6 @@ import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.database.element.security.EncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.notifications.DatabaseOpenNotificationService
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK
|
||||
@@ -68,7 +66,6 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.PROGRESS_TASK_DIALOG_TAG
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
|
||||
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||
import java.util.*
|
||||
@@ -90,9 +87,6 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
|
||||
private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener {
|
||||
override fun onStartAction(titleId: Int?, messageId: Int?, warningId: Int?) {
|
||||
TimeoutHelper.temporarilyDisableTimeout()
|
||||
// Stop the opening notification
|
||||
DatabaseOpenNotificationService.stop(activity)
|
||||
startDialog(titleId, messageId, warningId)
|
||||
}
|
||||
|
||||
@@ -102,21 +96,8 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
|
||||
override fun onStopAction(actionTask: String, result: ActionRunnable.Result) {
|
||||
onActionFinish?.invoke(actionTask, result)
|
||||
|
||||
// Remove the progress task
|
||||
stopDialog()
|
||||
TimeoutHelper.releaseTemporarilyDisableTimeout()
|
||||
|
||||
val inTime = if (activity is LockingActivity) {
|
||||
TimeoutHelper.checkTimeAndLockIfTimeout(activity)
|
||||
} else {
|
||||
TimeoutHelper.checkTime(activity)
|
||||
}
|
||||
// Start the opening notification if in time
|
||||
// (databaseOpenService is open manually in Action Open Task)
|
||||
if (actionTask != ACTION_DATABASE_LOAD_TASK && inTime) {
|
||||
DatabaseOpenNotificationService.start(activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,9 @@ class MagikIME : InputMethodService(), KeyboardView.OnKeyboardActionListener {
|
||||
removeEntryInfo()
|
||||
assignKeyboardView()
|
||||
}
|
||||
lockReceiver?.backToPreviousKeyboardAction = {
|
||||
switchToPreviousKeyboard()
|
||||
}
|
||||
|
||||
registerLockReceiver(lockReceiver, true)
|
||||
}
|
||||
@@ -262,8 +265,12 @@ class MagikIME : InputMethodService(), KeyboardView.OnKeyboardActionListener {
|
||||
}
|
||||
|
||||
private fun actionGoAutomatically() {
|
||||
if (PreferencesUtil.isAutoGoActionEnable(this))
|
||||
if (PreferencesUtil.isAutoGoActionEnable(this)) {
|
||||
currentInputConnection.performEditorAction(EditorInfo.IME_ACTION_GO)
|
||||
if (PreferencesUtil.isKeyboardPreviousFillInEnable(this)) {
|
||||
switchToPreviousKeyboard()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPress(primaryCode: Int) {
|
||||
|
||||
@@ -153,9 +153,6 @@ class ClipboardEntryNotificationService : LockNotificationService() {
|
||||
val nextField = nextFields[0]
|
||||
builder.setContentText(getString(R.string.select_to_copy, nextField.label))
|
||||
builder.setContentIntent(getCopyPendingIntent(nextField, nextFields))
|
||||
// Else tell to swipe for a clean
|
||||
} else {
|
||||
builder.setContentText(getString(R.string.clipboard_swipe_clean))
|
||||
}
|
||||
|
||||
val cleanIntent = Intent(this, ClipboardEntryNotificationService::class.java)
|
||||
|
||||
@@ -21,7 +21,6 @@ package com.kunzisoft.keepass.notifications
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.AsyncTask
|
||||
import android.os.Binder
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
@@ -40,19 +39,23 @@ import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
|
||||
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdater {
|
||||
|
||||
override val notificationId: Int = 575
|
||||
|
||||
private var actionRunnableAsyncTask: ActionRunnableAsyncTask? = null
|
||||
private val mainScope = CoroutineScope(Dispatchers.Main)
|
||||
|
||||
private var mActionTaskBinder = ActionTaskBinder()
|
||||
private var mActionTaskListeners = LinkedList<ActionTaskListener>()
|
||||
private var mAllowFinishAction = AtomicBoolean()
|
||||
|
||||
private var mTitleId: Int? = null
|
||||
private var mMessageId: Int? = null
|
||||
@@ -64,10 +67,14 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
||||
|
||||
fun addActionTaskListener(actionTaskListener: ActionTaskListener) {
|
||||
mActionTaskListeners.add(actionTaskListener)
|
||||
mAllowFinishAction.set(true)
|
||||
}
|
||||
|
||||
fun removeActionTaskListener(actionTaskListener: ActionTaskListener) {
|
||||
mActionTaskListeners.remove(actionTaskListener)
|
||||
if (mActionTaskListeners.size == 0) {
|
||||
mAllowFinishAction.set(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,34 +166,79 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
||||
newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, titleId))
|
||||
|
||||
// Build and launch the action
|
||||
actionRunnableAsyncTask = ActionRunnableAsyncTask(this,
|
||||
{
|
||||
sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply {
|
||||
putExtra(DATABASE_TASK_TITLE_KEY, titleId)
|
||||
putExtra(DATABASE_TASK_MESSAGE_KEY, messageId)
|
||||
putExtra(DATABASE_TASK_WARNING_KEY, warningId)
|
||||
})
|
||||
mainScope.launch {
|
||||
executeAction(this@DatabaseTaskNotificationService,
|
||||
{
|
||||
sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply {
|
||||
putExtra(DATABASE_TASK_TITLE_KEY, titleId)
|
||||
putExtra(DATABASE_TASK_MESSAGE_KEY, messageId)
|
||||
putExtra(DATABASE_TASK_WARNING_KEY, warningId)
|
||||
})
|
||||
|
||||
mActionTaskListeners.forEach { actionTaskListener ->
|
||||
actionTaskListener.onStartAction(titleId, messageId, warningId)
|
||||
}
|
||||
mActionTaskListeners.forEach { actionTaskListener ->
|
||||
actionTaskListener.onStartAction(titleId, messageId, warningId)
|
||||
}
|
||||
|
||||
}, { result ->
|
||||
mActionTaskListeners.forEach { actionTaskListener ->
|
||||
actionTaskListener.onStopAction(intentAction!!, result)
|
||||
}
|
||||
},
|
||||
{
|
||||
actionRunnableNotNull
|
||||
},
|
||||
{ result ->
|
||||
mActionTaskListeners.forEach { actionTaskListener ->
|
||||
actionTaskListener.onStopAction(intentAction!!, result)
|
||||
}
|
||||
|
||||
sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION))
|
||||
sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION))
|
||||
|
||||
stopSelf()
|
||||
}
|
||||
)
|
||||
actionRunnableAsyncTask?.execute({ actionRunnableNotNull })
|
||||
stopSelf()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return START_REDELIVER_INTENT
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute action with a coroutine
|
||||
*/
|
||||
private suspend fun executeAction(progressTaskUpdater: ProgressTaskUpdater,
|
||||
onPreExecute: () -> Unit,
|
||||
onExecute: (ProgressTaskUpdater?) -> ActionRunnable?,
|
||||
onPostExecute: (result: ActionRunnable.Result) -> Unit) {
|
||||
mAllowFinishAction.set(false)
|
||||
|
||||
// Stop the opening notification
|
||||
DatabaseOpenNotificationService.stop(this)
|
||||
TimeoutHelper.temporarilyDisableTimeout()
|
||||
onPreExecute.invoke()
|
||||
withContext(Dispatchers.IO) {
|
||||
onExecute.invoke(progressTaskUpdater)?.apply {
|
||||
val asyncResult: Deferred<ActionRunnable.Result> = async {
|
||||
val startTime = System.currentTimeMillis()
|
||||
var timeIsUp = false
|
||||
// Run the actionRunnable
|
||||
run()
|
||||
// Wait onBind or 4 seconds max
|
||||
while (!mAllowFinishAction.get() && !timeIsUp) {
|
||||
delay(100)
|
||||
if (startTime + 4000 < System.currentTimeMillis())
|
||||
timeIsUp = true
|
||||
}
|
||||
result
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
onPostExecute.invoke(asyncResult.await())
|
||||
TimeoutHelper.releaseTemporarilyDisableTimeout()
|
||||
// Start the opening notification
|
||||
if (TimeoutHelper.checkTimeAndLockIfTimeout(this@DatabaseTaskNotificationService)) {
|
||||
DatabaseOpenNotificationService.start(this@DatabaseTaskNotificationService)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun newNotification(title: Int) {
|
||||
|
||||
val builder = buildNewNotification()
|
||||
@@ -567,33 +619,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
||||
}
|
||||
}
|
||||
|
||||
private class ActionRunnableAsyncTask(private val progressTaskUpdater: ProgressTaskUpdater,
|
||||
private val onPreExecute: () -> Unit,
|
||||
private val onPostExecute: (result: ActionRunnable.Result) -> Unit)
|
||||
: AsyncTask<((ProgressTaskUpdater?) -> ActionRunnable), Void, ActionRunnable.Result>() {
|
||||
|
||||
override fun onPreExecute() {
|
||||
super.onPreExecute()
|
||||
onPreExecute.invoke()
|
||||
}
|
||||
|
||||
override fun doInBackground(vararg actionRunnables: ((ProgressTaskUpdater?)-> ActionRunnable)?): ActionRunnable.Result {
|
||||
var resultTask = ActionRunnable.Result(false)
|
||||
actionRunnables.forEach {
|
||||
it?.invoke(progressTaskUpdater)?.apply {
|
||||
run()
|
||||
resultTask = result
|
||||
}
|
||||
}
|
||||
return resultTask
|
||||
}
|
||||
|
||||
override fun onPostExecute(result: ActionRunnable.Result) {
|
||||
super.onPostExecute(result)
|
||||
onPostExecute.invoke(result)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val TAG = DatabaseTaskNotificationService::class.java.name
|
||||
|
||||
@@ -369,6 +369,18 @@ object PreferencesUtil {
|
||||
context.resources.getBoolean(R.bool.keyboard_key_sound_default))
|
||||
}
|
||||
|
||||
fun isKeyboardPreviousDatabaseCredentialsEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_previous_database_credentials_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_database_credentials_default))
|
||||
}
|
||||
|
||||
fun isKeyboardPreviousFillInEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_previous_fill_in_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_fill_in_default))
|
||||
}
|
||||
|
||||
fun isAutofillAutoSearchEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.autofill_auto_search_key),
|
||||
|
||||
@@ -92,6 +92,9 @@ open class SettingsActivity
|
||||
lockAndExit()
|
||||
}
|
||||
|
||||
// Focus view to reinitialize timeout
|
||||
resetAppTimeoutWhenViewFocusedOrChanged(coordinatorLayout)
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager.beginTransaction()
|
||||
.add(R.id.fragment_container, retrieveMainFragment())
|
||||
|
||||
@@ -38,6 +38,7 @@ object TimeoutHelper {
|
||||
|
||||
private const val TAG = "TimeoutHelper"
|
||||
|
||||
private var lastAppTimeoutRecord: Long? = null
|
||||
var temporarilyDisableTimeout = false
|
||||
private set
|
||||
|
||||
@@ -84,9 +85,15 @@ object TimeoutHelper {
|
||||
* Record the current time, to check it later with checkTime and start a new lock timer
|
||||
*/
|
||||
fun recordTime(context: Context) {
|
||||
// Record timeout time in case timeout service is killed
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
startLockTimer(context)
|
||||
// To prevent spam registration, record after at least 2 seconds
|
||||
if (lastAppTimeoutRecord == null
|
||||
|| lastAppTimeoutRecord!! + 2000 <= System.currentTimeMillis()) {
|
||||
Log.d(TAG, "Record app timeout")
|
||||
// Record timeout time in case timeout service is killed
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
startLockTimer(context)
|
||||
lastAppTimeoutRecord = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,10 +42,12 @@ const val DATABASE_STOP_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_STOP_TASK_
|
||||
|
||||
const val LOCK_ACTION = "com.kunzisoft.keepass.LOCK"
|
||||
const val REMOVE_ENTRY_MAGIKEYBOARD_ACTION = "com.kunzisoft.keepass.REMOVE_ENTRY_MAGIKEYBOARD"
|
||||
const val BACK_PREVIOUS_KEYBOARD_ACTION = "com.kunzisoft.keepass.BACK_PREVIOUS_KEYBOARD"
|
||||
|
||||
class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
|
||||
var mLockPendingIntent: PendingIntent? = null
|
||||
var backToPreviousKeyboardAction: (() -> Unit)? = null
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
// If allowed, lock and exit
|
||||
@@ -76,7 +78,12 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
}
|
||||
}
|
||||
LOCK_ACTION,
|
||||
REMOVE_ENTRY_MAGIKEYBOARD_ACTION -> lockAction.invoke()
|
||||
REMOVE_ENTRY_MAGIKEYBOARD_ACTION -> {
|
||||
lockAction.invoke()
|
||||
}
|
||||
BACK_PREVIOUS_KEYBOARD_ACTION -> {
|
||||
backToPreviousKeyboardAction?.invoke()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -93,14 +100,16 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
fun Context.registerLockReceiver(lockReceiver: LockReceiver?,
|
||||
registerRemoveEntryMagikeyboard: Boolean = false) {
|
||||
registerKeyboardAction: Boolean = false) {
|
||||
lockReceiver?.let {
|
||||
registerReceiver(it, IntentFilter().apply {
|
||||
addAction(Intent.ACTION_SCREEN_OFF)
|
||||
addAction(Intent.ACTION_SCREEN_ON)
|
||||
addAction(LOCK_ACTION)
|
||||
if (registerRemoveEntryMagikeyboard)
|
||||
if (registerKeyboardAction) {
|
||||
addAction(REMOVE_ENTRY_MAGIKEYBOARD_ACTION)
|
||||
addAction(BACK_PREVIOUS_KEYBOARD_ACTION)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/activity_group_container_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
<string name="clipboard_cleared">مُسِحت الحافظة</string>
|
||||
<string name="clipboard_error_title">خطأ في الحافظة</string>
|
||||
<string name="clipboard_error_clear">تعذَّر مسح الحافظة</string>
|
||||
<string name="clipboard_swipe_clean">اسحب لمسح الحافظة فورًا</string>
|
||||
<string name="database">قاعدة البيانات</string>
|
||||
<string name="decrypting_db">يفك تعمية محتوى قاعدة البيانات…</string>
|
||||
<string name="digits">أرقام</string>
|
||||
|
||||
@@ -295,7 +295,6 @@
|
||||
<string name="content_description_add_node">Afegeix node</string>
|
||||
<string name="content_description_open_file">Obre fitxer</string>
|
||||
<string name="content_description_background">Fons</string>
|
||||
<string name="clipboard_swipe_clean">Llisqueu per a netejear el porta-retalls ara</string>
|
||||
<string name="clipboard_error_clear">No ha estat possible netejar el porta-retalls</string>
|
||||
<string name="clipboard_error">Alguns dispositius no permeten que les aplicacions facin servir el porta-retalls.</string>
|
||||
<string name="clipboard_error_title">Error del porta-retalls</string>
|
||||
|
||||
@@ -156,7 +156,6 @@
|
||||
<string name="key_derivation_function">Funkce pro tvorbu klíče</string>
|
||||
<string name="extended_ASCII">Rozšířené ASCII</string>
|
||||
<string name="allow">Umožnit</string>
|
||||
<string name="clipboard_swipe_clean">Schránku vymažete přejetím</string>
|
||||
<string name="error_load_database">Databázi se nedaří načíst.</string>
|
||||
<string name="error_load_database_KDF_memory">Klíč se nedaří načíst, zkuste snížit množství paměti, využívané funkcí pro tvorbu klíče.</string>
|
||||
<string name="error_autofill_enable_service">Službu automatického vyplňování se nedaří zapnout.</string>
|
||||
|
||||
@@ -155,7 +155,6 @@
|
||||
<string name="key_derivation_function">Nøgleafledningsfunktion</string>
|
||||
<string name="extended_ASCII">Udvidet ASCII</string>
|
||||
<string name="allow">Tillad</string>
|
||||
<string name="clipboard_swipe_clean">Stryg for at at rydde udklipsholder nu</string>
|
||||
<string name="error_load_database">Databasen kunne ikke indlæses.</string>
|
||||
<string name="error_load_database_KDF_memory">Kunne ikke indlæse nøglen. Prøv at reducere KDF \"hukommelsesforbrug\".</string>
|
||||
<string name="error_autofill_enable_service">Kunne ikke aktivere autofyld tjenesten.</string>
|
||||
|
||||
@@ -198,7 +198,6 @@
|
||||
<string name="key_derivation_function">Schlüsselableitungsfunktion</string>
|
||||
<string name="extended_ASCII">Erweiterte ASCII</string>
|
||||
<string name="allow">Erlauben</string>
|
||||
<string name="clipboard_swipe_clean">Wischen, um Zwischenablage jetzt zu leeren</string>
|
||||
<string name="error_autofill_enable_service">Autofill-Dienst kann nicht aktiviert werden.</string>
|
||||
<string name="copy_field">Kopie von %1$s</string>
|
||||
<string name="menu_form_filling_settings">Formularausfüllung</string>
|
||||
|
||||
@@ -157,7 +157,6 @@
|
||||
<string name="key_derivation_function">Λειτουργία εξαγωγής κλειδιών</string>
|
||||
<string name="extended_ASCII">Extended ASCII</string>
|
||||
<string name="allow">Δέχομαι</string>
|
||||
<string name="clipboard_swipe_clean">Σύρετε για να διαγράψετε το πρόχειρο τώρα</string>
|
||||
<string name="error_autofill_enable_service">Δεν ήταν δυνατή η ενεργοποίηση της υπηρεσίας αυτόματης συμπλήρωσης.</string>
|
||||
<string name="file_not_found_content">Δεν ήταν δυνατή η εύρεση αρχείου. Δοκιμάστε να το ανοίξετε ξανά από το πρόγραμμα περιήγησης αρχείων σας.</string>
|
||||
<string name="copy_field">Αντιγραφή του %1$s</string>
|
||||
|
||||
@@ -148,7 +148,6 @@
|
||||
<string name="clipboard_error_title">Error del portapapeles</string>
|
||||
<string name="clipboard_error">Algunos dispositivos Android tienen un error en la implementación del portapapeles que provoca fallos al copiar desde las aplicaciones.</string>
|
||||
<string name="clipboard_error_clear">Falló la limpieza del portapapeles</string>
|
||||
<string name="clipboard_swipe_clean">Deslizar ahora para limpiar el portapapeles</string>
|
||||
<string name="error_string_key">Cada cadena debe tener un nombre de campo.</string>
|
||||
<string name="error_autofill_enable_service">No se pudo activar el servicio de compleción automática.</string>
|
||||
<string name="field_name">Nombre del campo</string>
|
||||
|
||||
@@ -149,7 +149,6 @@
|
||||
<item>Keskikokoinen</item>
|
||||
<item>Suuri</item>
|
||||
</string-array>
|
||||
<string name="clipboard_swipe_clean">Pyyhkäise tyhjentääksesi leikepöydän</string>
|
||||
<string name="allow">Salli</string>
|
||||
<string name="extended_ASCII">Laajennettu ASCII</string>
|
||||
<string name="key_derivation_function">Avaimen derivointifunktio</string>
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
<string name="clipboard_error">Certains appareils ne permettent pas aux applications d’utiliser le presse-papier.</string>
|
||||
<string name="clipboard_error_clear">Impossible de vider le presse-papier</string>
|
||||
<string name="clipboard_timeout">Expiration du presse-papier</string>
|
||||
<string name="clipboard_timeout_summary">Durée de stockage dans le presse-papier</string>
|
||||
<string name="clipboard_swipe_clean">Glisser pour vider le presse-papier maintenant</string>
|
||||
<string name="clipboard_timeout_summary">Durée de stockage dans le presse-papier (si supporté par votre appareil)</string>
|
||||
<string name="select_to_copy">Copier %1$s dans le presse-papier</string>
|
||||
<string name="retrieving_db_key">Récupération de la clé de la base de données…</string>
|
||||
<string name="database">Base de données</string>
|
||||
@@ -210,7 +209,7 @@
|
||||
<string name="monospace_font_fields_enable_summary">Change la fonte utilisée dans les champs pour une meilleure visibilité des caractères</string>
|
||||
<string name="allow_copy_password_title">Faire confiance au presse-papier</string>
|
||||
<string name="allow_copy_password_summary">Autorise la copie du mot de passe de l’entrée et des champs protégés dans le presse-papier</string>
|
||||
<string name="allow_copy_password_warning">Attention : Le presse-papiers est partagé par toutes les applications. Si des données sensibles sont copiées, d’autres logiciels peuvent les récupérer.</string>
|
||||
<string name="allow_copy_password_warning">Attention : Le presse-papier est partagé par toutes les applications. Si des données sensibles sont copiées, d’autres logiciels peuvent les récupérer.</string>
|
||||
<string name="database_name_title">Nom de la base de données</string>
|
||||
<string name="database_description_title">Description de la base de données</string>
|
||||
<string name="database_version_title">Version de la base de données</string>
|
||||
@@ -219,7 +218,7 @@
|
||||
<string name="other">Autres</string>
|
||||
<string name="keyboard">Clavier</string>
|
||||
<string name="magic_keyboard_title">Magiclavier</string>
|
||||
<string name="magic_keyboard_explanation_summary">Active un clavier personnalisé pour remplir vos mots de passe et tous les champs d’identité</string>
|
||||
<string name="magic_keyboard_explanation_summary">Activer un clavier personnalisé pour remplir vos mots de passe et tous les champs d’identité</string>
|
||||
<string name="enable_education_screens_title">Conseils pédagogiques</string>
|
||||
<string name="enable_education_screens_summary">Met en surbrillance les éléments pour apprendre le fonctionnement de l’application</string>
|
||||
<string name="reset_education_screens_title">Réinitialiser les conseils pédagogiques</string>
|
||||
@@ -349,7 +348,7 @@
|
||||
<string name="lock_database_back_root_title">Appuyer sur « Retour » pour verrouiller</string>
|
||||
<string name="lock_database_back_root_summary">Verrouille la base de données lorsque l’utilisateur clique sur le bouton retour de l’écran racine</string>
|
||||
<string name="clear_clipboard_notification_title">Suppression à la fermeture</string>
|
||||
<string name="clear_clipboard_notification_summary">Verrouille la base de données lors de la fermeture de la notification</string>
|
||||
<string name="clear_clipboard_notification_summary">Verrouille la base de données lorsque la durée du presse-papier expire ou que la notification est fermée après avoir commencé à l’utiliser</string>
|
||||
<string name="recycle_bin">Corbeille</string>
|
||||
<string name="keyboard_selection_entry_title">Sélection de l’entrée</string>
|
||||
<string name="keyboard_selection_entry_summary">Affiche les champs de saisie dans le Magiclavier lors de l’affichage d’une entrée</string>
|
||||
@@ -413,7 +412,7 @@
|
||||
<string name="contains_duplicate_uuid">La base de données contient des doublons d’UUID.</string>
|
||||
<string name="contains_duplicate_uuid_procedure">Résoudre le problème en générant de nouveaux UUID pour les doublons et continuer \?</string>
|
||||
<string name="database_opened">Base de données ouverte</string>
|
||||
<string name="clipboard_explanation_summary">Copie les champs d’une entrée à l’aide du presse-papier de votre appareil</string>
|
||||
<string name="clipboard_explanation_summary">Copier les champs d’une entrée à l’aide du presse-papier de votre appareil</string>
|
||||
<string name="advanced_unlock_explanation_summary">Utilise le déverrouillage avancé pour ouvrir plus facilement une base de données</string>
|
||||
<string name="database_data_compression_title">Compression de données</string>
|
||||
<string name="database_data_compression_summary">La compression des données réduit la taille de la base de données.</string>
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
<string name="clipboard_error_clear">Fallou a limpeza do portapapeis</string>
|
||||
<string name="clipboard_timeout">Tempo límite para o portapapeis</string>
|
||||
<string name="clipboard_timeout_summary">Tempo antes de limpar o portapapeis após copiar usuario ou contrasinal</string>
|
||||
<string name="clipboard_swipe_clean">Deslice para limpar agora o portapapeis</string>
|
||||
<string name="edit_entry">Editar entrada</string>
|
||||
<string name="select_to_copy">Seleccione para copiar %1$s para o portapapeis</string>
|
||||
<string name="retrieving_db_key">A criar a chave da base de dados…</string>
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
<string name="clipboard_error_clear">क्लिपबोर्ड को साफ़ नहीं किया जा सका</string>
|
||||
<string name="clipboard_timeout">क्लिपबोर्ड टाइमआउट</string>
|
||||
<string name="clipboard_timeout_summary">क्लिपबोर्ड में भंडारण की अवधि</string>
|
||||
<string name="clipboard_swipe_clean">अब क्लिपबोर्ड को साफ करने के लिए स्वाइप करें</string>
|
||||
<string name="select_to_copy">क्लिपबोर्ड पर %1$s को कॉपी करने के लिए चयन करें</string>
|
||||
<string name="retrieving_db_key">डेटाबेस कुंजी पुनर्प्राप्त कर रहा है…</string>
|
||||
<string name="database">डेटाबेस</string>
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
<string name="clipboard_error">Neki uređaji neće dopustiti aplikacijama korištenje međuspremnika.</string>
|
||||
<string name="clipboard_error_clear">Nije moguće isprazniti međuspremnik</string>
|
||||
<string name="clipboard_timeout_summary">Trajanje pohrane u međuspremniku</string>
|
||||
<string name="clipboard_swipe_clean">Prijeđite prstom da biste odmah ispraznili međuspremnik</string>
|
||||
<string name="content_description_background">Pozadina</string>
|
||||
<string name="content_description_open_file">Otvori datoteku</string>
|
||||
<string name="content_description_add_node">Dodaj čvor</string>
|
||||
|
||||
@@ -312,7 +312,6 @@
|
||||
<string name="education_sort_title">Elemek rendezése</string>
|
||||
<string name="education_sort_summary">Válasszon, hogy az elemek és csoportok hogyan legyenek rendezve.</string>
|
||||
<string name="education_donation_title">Közreműködés</string>
|
||||
<string name="clipboard_swipe_clean">Seprés a vágólap azonnali törléséhez</string>
|
||||
<string name="education_entry_edit_summary">Szerkessze a bejegyzése egyéni mezőit. Az adatok hivatkozhatóak a különböző mezők között.</string>
|
||||
<string name="education_donation_summary">Segítsen a stabilitás és a biztonság növelésében, és az új funkciók hozzáadásában.</string>
|
||||
<string name="html_text_ad_free">Számos más jelszókezelő alkalmazással ellentétben, ez egy <strong>reklámmentes</strong>, <strong>copyleft licencelésű szabad szoftver</strong>, amely nem gyűjt személyes adatokat a kiszolgálókon, bármelyik verziót is használja.</string>
|
||||
|
||||
@@ -168,7 +168,6 @@
|
||||
<string name="encryption">Cifratura</string>
|
||||
<string name="key_derivation_function">Funzione di derivazione chiave</string>
|
||||
<string name="extended_ASCII">ASCII esteso</string>
|
||||
<string name="clipboard_swipe_clean">Scorri per pulire gli appunti ora</string>
|
||||
<string name="error_nokeyfile">Seleziona un file chiave.</string>
|
||||
<string name="error_autofill_enable_service">Attivazione del servizio di auto-completamento fallita.</string>
|
||||
<string name="error_move_folder_in_itself">Non puoi spostare un gruppo in se stesso.</string>
|
||||
|
||||
@@ -149,7 +149,6 @@
|
||||
<string name="edit_entry">ערוך רשומה</string>
|
||||
<string name="encryption">הצפנה</string>
|
||||
<string name="allow">אפשר</string>
|
||||
<string name="clipboard_swipe_clean">החלק לניקוי לוח העתקה עכשיו</string>
|
||||
<string name="entry_url">כתובת URL</string>
|
||||
<string name="error_load_database">לא ניתן לטעון את בסיס הנתונים</string>
|
||||
</resources>
|
||||
@@ -147,7 +147,6 @@
|
||||
<string name="clipboard_error_title">クリップボードエラー</string>
|
||||
<string name="clipboard_error">一部の端末ではアプリからクリップボードを使用できません。</string>
|
||||
<string name="clipboard_error_clear">クリップボードをクリアできません</string>
|
||||
<string name="clipboard_swipe_clean">スワイプすると今すぐクリップボードをクリアします</string>
|
||||
<string name="entry_not_found">エントリデータが見つかりませんでした。</string>
|
||||
<string name="error_load_database">データベースを読み込みできませんでした。</string>
|
||||
<string name="error_load_database_KDF_memory">鍵を読み込みできませんでした。KDF の \"メモリ使用量\" を下げてみてください。</string>
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
<string name="clipboard_error_clear">클립보드를 비울 수 없음</string>
|
||||
<string name="clipboard_timeout">클립보드 시간 초과</string>
|
||||
<string name="clipboard_timeout_summary">클립보드 저장이 유지될 시간</string>
|
||||
<string name="clipboard_swipe_clean">클립보드를 지우기 위해 스와이프</string>
|
||||
<string name="select_to_copy">%1$s 을(를) 클립보드에 복사하려면 선택하십시오.</string>
|
||||
<string name="retrieving_db_key">데이터베이스 키를 검색하는 중…</string>
|
||||
<string name="database">데이터베이스</string>
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
<string name="clipboard_error_clear">Kunne ikke tømme utklippstavle</string>
|
||||
<string name="clipboard_timeout">Tidsavbrudd for utklippstavle</string>
|
||||
<string name="clipboard_timeout_summary">Tid før utklippstavlen tømmes etter kopiering av brukernavn og passord</string>
|
||||
<string name="clipboard_swipe_clean">Dra for å tømme utklippstavlen nå</string>
|
||||
<string name="select_to_copy">Velg for å kopier %1$s til utklippstavlen</string>
|
||||
<string name="retrieving_db_key">Oppretter databasenøkkel…</string>
|
||||
<string name="database">Database</string>
|
||||
|
||||
@@ -151,7 +151,6 @@
|
||||
<string name="clipboard_error_title">Klembordfout</string>
|
||||
<string name="clipboard_error">Sommige apparaten staan niet toe dat apps het klembord gebruiken.</string>
|
||||
<string name="clipboard_error_clear">Wissen van klembord mislukt</string>
|
||||
<string name="clipboard_swipe_clean">Veeg om klembord nu te wissen</string>
|
||||
<string name="entry_not_found">Geen iteminhoud gevonden.</string>
|
||||
<string name="error_load_database">Je database kan niet worden geladen.</string>
|
||||
<string name="error_load_database_KDF_memory">De sleutel kan niet worden geladen. Probeer om het \"geheugengebruik\" van KDF te verminderen.</string>
|
||||
|
||||
@@ -146,7 +146,6 @@
|
||||
<string name="clipboard_error_title">Błąd schowka</string>
|
||||
<string name="clipboard_error">Niektóre urządzenia nie pozwalają aplikacjom korzystać ze schowka.</string>
|
||||
<string name="clipboard_error_clear">Nie można wyczyścić schowka</string>
|
||||
<string name="clipboard_swipe_clean">Przesuń, by wyczyścić schowek</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft jest <strong>open source</strong> i <strong>bez reklam</strong>.
|
||||
\nJest on dostarczany w stanie, zgodnie z licencją <strong>GPLv3</strong> bez żadnych gwarancji.</string>
|
||||
<string name="entry_not_found">Nie znaleziono danych wejściowych.</string>
|
||||
|
||||
@@ -147,7 +147,6 @@
|
||||
<string name="clipboard_error_title">Erro na área de transferência</string>
|
||||
<string name="clipboard_error">Alguns dispositivos não permitem que aplicativos usem a área de transferência.</string>
|
||||
<string name="clipboard_error_clear">Não foi possível limpar a área de transferência</string>
|
||||
<string name="clipboard_swipe_clean">Deslize para limpar a área de transferência agora</string>
|
||||
<string name="entry_not_found">Não pôde encontrar dado de entrada.</string>
|
||||
<string name="error_string_key">Um nome do campo é necessário para cada string.</string>
|
||||
<string name="error_autofill_enable_service">Não pôde ser habilitado o serviço de preenchimento automático.</string>
|
||||
|
||||
@@ -208,7 +208,6 @@
|
||||
<string name="edit_entry">Editar entrada</string>
|
||||
<string name="encryption">Encriptação</string>
|
||||
<string name="key_derivation_function">Função de derivação de chave</string>
|
||||
<string name="clipboard_swipe_clean">Deslize para o lado para limpar agora a área de transferência</string>
|
||||
<string name="error_autofill_enable_service">Não pôde ser habilitado o serviço de preenchimento automático.</string>
|
||||
<string name="encryption_explanation">Algoritmo de encriptação usado para todos os dados.</string>
|
||||
<string name="password_size_summary">Define o tamanho padrão para palavras-passe geradas</string>
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
<string name="clipboard_error_clear">Nu s-a putut curata memoria carnetelului</string>
|
||||
<string name="clipboard_timeout">Timp expirat de citire a carnetelului</string>
|
||||
<string name="clipboard_timeout_summary">Durata de memorare din carnetel</string>
|
||||
<string name="clipboard_swipe_clean">Schimba ca sa cureti carnetelul acum</string>
|
||||
<string name="content_description_background">In spate</string>
|
||||
<string name="content_description_open_file">Deschide fisier</string>
|
||||
<string name="content_description_node_children">Copil nod</string>
|
||||
|
||||
@@ -184,7 +184,6 @@
|
||||
<string name="sort_last_access_time">Время последнего доступа</string>
|
||||
<string name="edit_entry">Изменить</string>
|
||||
<string name="allow">Разрешить</string>
|
||||
<string name="clipboard_swipe_clean">Смахните для очистки буфера обмена</string>
|
||||
<string name="error_load_database">Невозможно загрузить базу.</string>
|
||||
<string name="error_load_database_KDF_memory">Невозможно загрузить ключ. Попробуйте уменьшить размер памяти, используемой функцией формирования ключа (KDF).</string>
|
||||
<string name="error_move_folder_in_itself">Нельзя переместить группу в саму себя.</string>
|
||||
|
||||
@@ -147,7 +147,6 @@
|
||||
<string name="clipboard_error_title">Chyba schránky</string>
|
||||
<string name="clipboard_error">Niektoré zariadenia nedovolia aplikáciám používať schránku.</string>
|
||||
<string name="clipboard_error_clear">Nepodarilo sa vymazať schránku</string>
|
||||
<string name="clipboard_swipe_clean">Schránku vymažete potiahnutím prsta cez políčko</string>
|
||||
<string name="entry_not_found">Nenašli sa údaje záznamu</string>
|
||||
<string name="contact">Kontakt</string>
|
||||
<string name="content_description_open_file">Otvoriť súbor</string>
|
||||
|
||||
@@ -156,7 +156,6 @@
|
||||
<string name="key_derivation_function">Nyckelhärledningsfunktion</string>
|
||||
<string name="extended_ASCII">Utökad ASCII</string>
|
||||
<string name="allow">Tillåt</string>
|
||||
<string name="clipboard_swipe_clean">Svep för att rensa urklipp nu</string>
|
||||
<string name="content_description_open_file">Öppna fil</string>
|
||||
<string name="content_description_add_node">Lägg till nod</string>
|
||||
<string name="content_description_add_entry">Ny post</string>
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
<string name="error_invalid_db">Veritabanı okunamadı.</string>
|
||||
<string name="error_invalid_path">Yolun doğru olduğundan emin olun.</string>
|
||||
<string name="error_no_name">Bir isim girin.</string>
|
||||
<string name="clipboard_swipe_clean">Şimdi panoyu temizlemek için kaydırın</string>
|
||||
<string name="select_to_copy">%1$s dosyasını panoya kopyalamak için seçin</string>
|
||||
<string name="retrieving_db_key">Veritabanı anahtarı alınıyor…</string>
|
||||
<string name="decrypting_db">Veritabanı içeriği deşifre ediliyor…</string>
|
||||
|
||||
@@ -147,7 +147,6 @@
|
||||
<string name="content_description_open_file">Відкрити файл</string>
|
||||
<string name="extended_ASCII">Розширений ASCII</string>
|
||||
<string name="edit_entry">Змінити запис</string>
|
||||
<string name="clipboard_swipe_clean">Проведіть пальцем, щоб очистити буфер обміну зараз</string>
|
||||
<string name="clear_clipboard_notification_summary">Блокувати базу даних під час закриття сповіщення</string>
|
||||
<string name="configure_biometric">Розблокування біометричними даними підтримується, але не налаштоване.</string>
|
||||
<string name="content_description_add_group">Додати групу</string>
|
||||
|
||||
@@ -143,7 +143,6 @@
|
||||
<string name="clipboard_error_title">剪切板错误</string>
|
||||
<string name="clipboard_error">一些设备不允许程序使用剪切板。</string>
|
||||
<string name="clipboard_error_clear">无法清空剪切板</string>
|
||||
<string name="clipboard_swipe_clean">滑动以清空剪切板</string>
|
||||
<string name="encryption_chacha20">ChaCha20</string>
|
||||
<string name="kdf_AES">AES</string>
|
||||
<string name="kdf_Argon2">Argon2</string>
|
||||
|
||||
@@ -140,7 +140,6 @@
|
||||
<string name="clipboard_error_title">剪貼簿錯誤</string>
|
||||
<string name="clipboard_error">部份設備不容許其他程式使用剪貼簿。</string>
|
||||
<string name="clipboard_error_clear">無法清除剪貼簿</string>
|
||||
<string name="clipboard_swipe_clean">滑动即可清除剪贴板</string>
|
||||
<string name="error_autofill_enable_service">無法啟用自動填入服務。</string>
|
||||
<string name="error_move_folder_in_itself">無法移動一個群組至自己本身。</string>
|
||||
<string name="invalid_algorithm">無效的演算法。</string>
|
||||
|
||||
@@ -132,6 +132,10 @@
|
||||
<bool name="keyboard_key_vibrate_default" translatable="false">true</bool>
|
||||
<string name="keyboard_key_sound_key" translatable="false">keyboard_key_sound_key</string>
|
||||
<bool name="keyboard_key_sound_default" translatable="false">false</bool>
|
||||
<string name="keyboard_previous_database_credentials_key" translatable="false">keyboard_previous_database_credentials_key</string>
|
||||
<bool name="keyboard_previous_database_credentials_default" translatable="false">false</bool>
|
||||
<string name="keyboard_previous_fill_in_key" translatable="false">keyboard_previous_fill_in_key</string>
|
||||
<bool name="keyboard_previous_fill_in_default" translatable="false">false</bool>
|
||||
<string name="autofill_auto_search_key" translatable="false">autofill_auto_search_key</string>
|
||||
<bool name="autofill_auto_search_default" translatable="false">true</bool>
|
||||
<string name="autofill_application_id_blocklist_key" translatable="false">autofill_application_id_blocklist_key</string>
|
||||
|
||||
@@ -44,8 +44,7 @@
|
||||
<string name="clipboard_error">Some devices won\'t let apps use the clipboard.</string>
|
||||
<string name="clipboard_error_clear">Could not clear clipboard</string>
|
||||
<string name="clipboard_timeout">Clipboard timeout</string>
|
||||
<string name="clipboard_timeout_summary">Duration of storage in the clipboard</string>
|
||||
<string name="clipboard_swipe_clean">Swipe to clear clipboard now</string>
|
||||
<string name="clipboard_timeout_summary">Duration of storage in the clipboard (if supported by your device)</string>
|
||||
<string name="content_description_background">Background</string>
|
||||
<string name="content_description_open_file">Open file</string>
|
||||
<string name="content_description_node_children">Node children</string>
|
||||
@@ -341,7 +340,7 @@
|
||||
<string name="enable">Enable</string>
|
||||
<string name="disable">Disable</string>
|
||||
<string name="clear_clipboard_notification_title">Clear at closing</string>
|
||||
<string name="clear_clipboard_notification_summary">Lock the database when closing the notification</string>
|
||||
<string name="clear_clipboard_notification_summary">Lock the database when the clipboard duration expires or the notification is closed after you start using it</string>
|
||||
<string name="database_name_title">Database name</string>
|
||||
<string name="database_description_title">Database description</string>
|
||||
<string name="database_default_username_title">Default username</string>
|
||||
@@ -382,6 +381,11 @@
|
||||
<string name="keyboard_auto_go_action_summary">\"Go\" key action after pressing a \"Field\" key</string>
|
||||
<string name="keyboard_key_vibrate_title">Vibratory keypresses</string>
|
||||
<string name="keyboard_key_sound_title">Audible keypresses</string>
|
||||
<string name="keyboard_change">Keyboard change</string>
|
||||
<string name="keyboard_previous_database_credentials_title">Previous keyboard during database credentials</string>
|
||||
<string name="keyboard_previous_database_credentials_summary">Automatically back to the previous keyboard if the database credentials screen is shown</string>
|
||||
<string name="keyboard_previous_fill_in_title">Previous keyboard after form filling</string>
|
||||
<string name="keyboard_previous_fill_in_summary">Automatically back to the previous keyboard if the form is filling and "Go" key action is auto activated</string>
|
||||
<string name="autofill_auto_search_title">Auto search</string>
|
||||
<string name="autofill_auto_search_summary">Automatically suggest search results from the web domain or application ID</string>
|
||||
<string name="autofill_application_id_blocklist_title">Application blocklist</string>
|
||||
|
||||
@@ -67,4 +67,18 @@
|
||||
android:defaultValue="@bool/keyboard_key_sound_default"
|
||||
android:title="@string/keyboard_key_sound_title" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/keyboard_change">
|
||||
<SwitchPreference
|
||||
android:key="@string/keyboard_previous_database_credentials_key"
|
||||
android:title="@string/keyboard_previous_database_credentials_title"
|
||||
android:summary="@string/keyboard_previous_database_credentials_summary"
|
||||
android:defaultValue="@bool/keyboard_previous_database_credentials_default"/>
|
||||
<SwitchPreference
|
||||
android:key="@string/keyboard_previous_fill_in_key"
|
||||
android:title="@string/keyboard_previous_fill_in_title"
|
||||
android:summary="@string/keyboard_previous_fill_in_summary"
|
||||
android:defaultValue="@bool/keyboard_previous_fill_in_default"
|
||||
android:dependency="@string/keyboard_auto_go_action_key"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
@@ -1,3 +1,7 @@
|
||||
* Fix TOTP period (> 60s)
|
||||
* Fix searching in recycle bin
|
||||
* Settings to back to the previous keyboard during database credentials and after form filling
|
||||
* Improving action tasks
|
||||
* Improve recognition to reset app timeout
|
||||
* Fix minor issues
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
* Correction de la période pour le TOTP (> 60s)
|
||||
* Correction de la recherche dans la corbeille
|
||||
|
||||
* Paramètres pour revenir automatiquement au clavier précédent durant l'identification de la base et après le remplissage de formulaire
|
||||
* Amélioration des tâches d'action
|
||||
* Amélioration de la reconnaissance pour le temps écoulé
|
||||
* Correction de problèmes mineurs
|
||||
|
||||
Reference in New Issue
Block a user