From 8924254c257846d14c6f7813f8b8408e559f5d2d Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 2 Sep 2025 19:57:02 +0200 Subject: [PATCH] feat: Custom settings and privileged --- .../passkeys_privileged_apps_google.json} | 0 app/src/main/AndroidManifest.xml | 12 +- ...> passkeys_privileged_apps_community.json} | 0 .../keepass/activities/AboutActivity.kt | 3 +- .../activities/FileDatabaseSelectActivity.kt | 6 +- .../dialogs/SetOTPDialogFragment.kt | 12 +- .../activity/AutofillLauncherActivity.kt | 6 +- .../EntrySelectionLauncherActivity.kt | 4 +- .../autofill/KeeAutofillService.kt | 4 +- .../passkey/util/PasskeyHelper.kt | 67 +++++--- .../keepass/hardware/HardwareKeyActivity.kt | 2 +- .../hardware/HardwareKeyResponseHelper.kt | 144 ----------------- .../settings/NestedAppSettingsFragment.kt | 17 +- .../settings/PasskeysSettingsActivity.kt | 34 ++++ .../settings/PasskeysSettingsFragment.kt | 63 ++++++++ .../keepass/settings/PreferencesUtil.kt | 4 +- ...legedAppsPreferenceDialogFragmentCompat.kt | 73 +++++++++ .../adapter/ListSelectionItemAdapter.kt | 78 ++++++++++ .../com/kunzisoft/keepass/utils/AppUtil.kt | 147 ++++++++++++++++++ .../com/kunzisoft/keepass/utils/MenuUtil.kt | 5 +- .../com/kunzisoft/keepass/utils/UriUtil.kt | 59 ------- .../com/kunzisoft/keepass/utils/WebDomain.kt | 35 ----- .../kunzisoft/keepass/view/TextFieldView.kt | 3 +- .../main/res/layout/pref_dialog_list_item.xml | 35 +++++ app/src/main/res/values-ar/strings.xml | 2 +- app/src/main/res/values-az/strings.xml | 2 +- app/src/main/res/values-bg/strings.xml | 2 +- app/src/main/res/values-ca/strings.xml | 2 +- app/src/main/res/values-cs/strings.xml | 2 +- app/src/main/res/values-da/strings.xml | 2 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-el/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-et/strings.xml | 2 +- app/src/main/res/values-eu/strings.xml | 2 +- app/src/main/res/values-fi/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-gl/strings.xml | 2 +- app/src/main/res/values-hr/strings.xml | 2 +- app/src/main/res/values-hu/strings.xml | 2 +- app/src/main/res/values-in/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-iw/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 2 +- app/src/main/res/values-lt/strings.xml | 2 +- app/src/main/res/values-ml/strings.xml | 2 +- app/src/main/res/values-nb/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 2 +- app/src/main/res/values-pa/strings.xml | 2 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-pt-rPT/strings.xml | 2 +- app/src/main/res/values-pt/strings.xml | 2 +- app/src/main/res/values-ro/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-sk/strings.xml | 2 +- app/src/main/res/values-sq/strings.xml | 2 +- app/src/main/res/values-sv/strings.xml | 2 +- app/src/main/res/values-ta/strings.xml | 2 +- app/src/main/res/values-th/strings.xml | 2 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values-uk/strings.xml | 2 +- app/src/main/res/values-vi/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values/donottranslate.xml | 9 +- app/src/main/res/values/strings.xml | 11 +- .../main/res/xml/preferences_form_filling.xml | 19 ++- app/src/main/res/xml/preferences_passkeys.xml | 53 +++++++ .../com/kunzisoft/keepass/model/AppOrigin.kt | 8 + 71 files changed, 647 insertions(+), 350 deletions(-) rename app/src/{main/assets/fido2_privileged_google.json => free/assets/passkeys_privileged_apps_google.json} (100%) rename app/src/main/assets/{fido2_privileged_community.json => passkeys_privileged_apps_community.json} (100%) delete mode 100644 app/src/main/java/com/kunzisoft/keepass/hardware/HardwareKeyResponseHelper.kt create mode 100644 app/src/main/java/com/kunzisoft/keepass/settings/PasskeysSettingsActivity.kt create mode 100644 app/src/main/java/com/kunzisoft/keepass/settings/PasskeysSettingsFragment.kt create mode 100644 app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/PasskeysPrivilegedAppsPreferenceDialogFragmentCompat.kt create mode 100644 app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/adapter/ListSelectionItemAdapter.kt create mode 100644 app/src/main/java/com/kunzisoft/keepass/utils/AppUtil.kt delete mode 100644 app/src/main/java/com/kunzisoft/keepass/utils/WebDomain.kt create mode 100644 app/src/main/res/layout/pref_dialog_list_item.xml create mode 100644 app/src/main/res/xml/preferences_passkeys.xml diff --git a/app/src/main/assets/fido2_privileged_google.json b/app/src/free/assets/passkeys_privileged_apps_google.json similarity index 100% rename from app/src/main/assets/fido2_privileged_google.json rename to app/src/free/assets/passkeys_privileged_apps_google.json diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d9adc5a52..5a952e707 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -159,20 +159,22 @@ android:label="@string/about" /> - + + (KEY_SEARCH_INFO)?.let { searchInfo -> - WebDomain.getConcreteWebDomain( + AppUtil.getConcreteWebDomain( this, searchInfo.webDomain ) { concreteWebDomain -> @@ -109,7 +109,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() { KEY_REGISTER_INFO ) val searchInfo = SearchInfo(registerInfo?.searchInfo) - WebDomain.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain -> + AppUtil.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain -> searchInfo.webDomain = concreteWebDomain launchRegistration(database, searchInfo, registerInfo) } diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/EntrySelectionLauncherActivity.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/EntrySelectionLauncherActivity.kt index 2c1bdb4f5..e3b2f4dad 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/EntrySelectionLauncherActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/EntrySelectionLauncherActivity.kt @@ -33,8 +33,8 @@ import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.helper.SearchHelper import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.otp.OtpEntryFields +import com.kunzisoft.keepass.utils.AppUtil import com.kunzisoft.keepass.utils.KeyboardUtil.isKeyboardActivatedInSettings -import com.kunzisoft.keepass.utils.WebDomain import com.kunzisoft.keepass.utils.getParcelableCompat /** @@ -109,7 +109,7 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() { this.otpString = otpString } - WebDomain.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain -> + AppUtil.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain -> searchInfo.webDomain = concreteWebDomain launch(database, searchInfo) } diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/autofill/KeeAutofillService.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/autofill/KeeAutofillService.kt index 9d832e3e1..6c3a3aeea 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/autofill/KeeAutofillService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/autofill/KeeAutofillService.kt @@ -53,7 +53,7 @@ import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.settings.AutofillSettingsActivity import com.kunzisoft.keepass.settings.PreferencesUtil -import com.kunzisoft.keepass.utils.WebDomain +import com.kunzisoft.keepass.utils.AppUtil import org.joda.time.DateTime @@ -120,7 +120,7 @@ class KeeAutofillService : AutofillService() { webDomain = parseResult.webDomain webScheme = parseResult.webScheme } - WebDomain.getConcreteWebDomain(this, searchInfo.webDomain) { webDomainWithoutSubDomain -> + AppUtil.getConcreteWebDomain(this, searchInfo.webDomain) { webDomainWithoutSubDomain -> searchInfo.webDomain = webDomainWithoutSubDomain val inlineSuggestionsRequest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && autofillInlineSuggestionsEnabled) { diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/util/PasskeyHelper.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/util/PasskeyHelper.kt index 2590adc5b..5b5ccb657 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/util/PasskeyHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/util/PasskeyHelper.kt @@ -328,19 +328,54 @@ object PasskeyHelper { return request.credentialOptions[0] as GetPublicKeyCredentialOption } - private fun getOriginFromPrivilegedAllowList( + /** + * Get the origin from a privileged allow list, + * [fileName] is the name of the file in assets containing the origin list as JSON + */ + private fun getOriginFromPrivilegedAllowListFile( callingAppInfo: CallingAppInfo, assets: AssetManager, - fileName: String): String? { + fileName: String + ): String? { val privilegedAllowList = assets.open(fileName).bufferedReader().use { it.readText() } return callingAppInfo.getOrigin(privilegedAllowList)?.removeSuffix("/") } + /** + * Get the origin from the predefined privileged allow lists + */ + private fun getOriginFromPrivilegedAllowLists( + callingAppInfo: CallingAppInfo, + assets: AssetManager + ): String? { + return try { + // TODO add the manual privileged apps + // Check the community apps first + getOriginFromPrivilegedAllowListFile( + callingAppInfo = callingAppInfo, + assets = assets, + fileName = FILE_NAME_PRIVILEGED_APPS_COMMUNITY + ) + } catch (e: Exception) { + // Then the Google list if allowed + if (BuildConfig.CLOSED_STORE) { + // http://www.gstatic.com/gpm-passkeys-privileged-apps/apps.json + getOriginFromPrivilegedAllowListFile( + callingAppInfo = callingAppInfo, + assets = assets, + fileName = FILE_NAME_PRIVILEGED_APPS_GOOGLE + ) + } else { + throw e + } + } + } + /** * Utility method to retrieve the origin asynchronously, - * checks for the presence of the application in the privilege list of the fido2_privileged_google.json file, + * checks for the presence of the application in the privilege list of the passkeys_privileged_apps_google.json file, * call [onOriginRetrieved] if the origin is already calculated by the system and in the privileged list, return the clientDataHash * call [onOriginNotRetrieved] if the origin is not retrieved from the system, return a new Android Origin */ @@ -357,32 +392,15 @@ object PasskeyHelper { withContext(Dispatchers.IO) { // For trusted browsers like Chrome and Firefox - // Check the community apps first - val callOrigin = try { - getOriginFromPrivilegedAllowList( - callingAppInfo, - assets, - "fido2_privileged_community.json" - ) - } catch (e: Exception) { - // Then the Google list if allowed - if (BuildConfig.CLOSED_STORE) { - getOriginFromPrivilegedAllowList( - callingAppInfo, - assets, - "fido2_privileged_google.json" - ) - } else { - throw e - } - } + val callOrigin = getOriginFromPrivilegedAllowLists(callingAppInfo, assets) + // Build the default Android origin val androidOrigin = AndroidOrigin( packageName = callingAppInfo.packageName, fingerprint = callingAppInfo.signingInfo.getApplicationFingerprints() ) - // Check if the webDomain is validated for the + // Check if the webDomain is validated by the system withContext(Dispatchers.Main) { if (callOrigin != null && providedClientDataHash != null) { // Origin already defined by the system @@ -624,4 +642,7 @@ object PasskeyHelper { } private const val BACKUP_ELIGIBILITY = true + + private const val FILE_NAME_PRIVILEGED_APPS_COMMUNITY = "passkeys_privileged_apps_community.json" + private const val FILE_NAME_PRIVILEGED_APPS_GOOGLE = "passkeys_privileged_apps_google.json" } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/hardware/HardwareKeyActivity.kt b/app/src/main/java/com/kunzisoft/keepass/hardware/HardwareKeyActivity.kt index 77d802025..cd746d88c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/hardware/HardwareKeyActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/hardware/HardwareKeyActivity.kt @@ -14,7 +14,7 @@ import androidx.appcompat.app.AlertDialog import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.legacy.DatabaseModeActivity import com.kunzisoft.keepass.database.ContextualDatabase -import com.kunzisoft.keepass.utils.UriUtil.openExternalApp +import com.kunzisoft.keepass.utils.AppUtil.openExternalApp /** * Special activity to deal with hardware key drivers, diff --git a/app/src/main/java/com/kunzisoft/keepass/hardware/HardwareKeyResponseHelper.kt b/app/src/main/java/com/kunzisoft/keepass/hardware/HardwareKeyResponseHelper.kt deleted file mode 100644 index 5f00e2138..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/hardware/HardwareKeyResponseHelper.kt +++ /dev/null @@ -1,144 +0,0 @@ -package com.kunzisoft.keepass.hardware - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import android.util.Log -import androidx.activity.result.ActivityResult -import androidx.activity.result.ActivityResultCallback -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AlertDialog -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentActivity -import androidx.lifecycle.lifecycleScope -import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.utils.UriUtil.openExternalApp -import kotlinx.coroutines.launch - -class HardwareKeyResponseHelper { - - private var activity: FragmentActivity? = null - private var fragment: Fragment? = null - - private var getChallengeResponseResultLauncher: ActivityResultLauncher? = null - - constructor(context: FragmentActivity) { - this.activity = context - this.fragment = null - } - - constructor(context: Fragment) { - this.activity = context.activity - this.fragment = context - } - - fun buildHardwareKeyResponse(onChallengeResponded: (challengeResponse: ByteArray?, - extra: Bundle?) -> Unit) { - val resultCallback = ActivityResultCallback { result -> - if (result.resultCode == Activity.RESULT_OK) { - val challengeResponse: ByteArray? = result.data?.getByteArrayExtra(HARDWARE_KEY_RESPONSE_KEY) - Log.d(TAG, "Response form challenge") - onChallengeResponded.invoke(challengeResponse, - result.data?.getBundleExtra(EXTRA_BUNDLE_KEY)) - } else { - Log.e(TAG, "Response from challenge error") - onChallengeResponded.invoke(null, - result.data?.getBundleExtra(EXTRA_BUNDLE_KEY)) - } - } - - getChallengeResponseResultLauncher = if (fragment != null) { - fragment?.registerForActivityResult( - ActivityResultContracts.StartActivityForResult(), - resultCallback - ) - } else { - activity?.registerForActivityResult( - ActivityResultContracts.StartActivityForResult(), - resultCallback - ) - } - } - - fun launchChallengeForResponse(hardwareKey: HardwareKey, seed: ByteArray?) { - when (hardwareKey) { - /* - HardwareKey.FIDO2_SECRET -> { - // TODO FIDO2 under development - throw Exception("FIDO2 not implemented") - } - */ - HardwareKey.CHALLENGE_RESPONSE_YUBIKEY -> { - // Transform the seed before sending - var challenge: ByteArray? = null - if (seed != null) { - challenge = ByteArray(64) - seed.copyInto(challenge, 0, 0, 32) - challenge.fill(32, 32, 64) - } - // Send to the driver - getChallengeResponseResultLauncher!!.launch( - Intent(YUBIKEY_CHALLENGE_RESPONSE_INTENT).apply { - putExtra(HARDWARE_KEY_CHALLENGE_KEY, challenge) - } - ) - Log.d(TAG, "Challenge sent") - } - } - } - - companion object { - private val TAG = HardwareKeyResponseHelper::class.java.simpleName - - private const val YUBIKEY_CHALLENGE_RESPONSE_INTENT = "android.yubikey.intent.action.CHALLENGE_RESPONSE" - private const val HARDWARE_KEY_CHALLENGE_KEY = "challenge" - private const val HARDWARE_KEY_RESPONSE_KEY = "response" - private const val EXTRA_BUNDLE_KEY = "EXTRA_BUNDLE_KEY" - - fun isHardwareKeyAvailable( - activity: FragmentActivity, - hardwareKey: HardwareKey, - showDialog: Boolean = true - ): Boolean { - return when (hardwareKey) { - /* - HardwareKey.FIDO2_SECRET -> { - // TODO FIDO2 under development - if (showDialog) - UnderDevelopmentFeatureDialogFragment() - .show(activity.supportFragmentManager, "underDevFeatureDialog") - false - } - */ - HardwareKey.CHALLENGE_RESPONSE_YUBIKEY -> { - // Check available intent - val yubikeyDriverAvailable = - Intent(YUBIKEY_CHALLENGE_RESPONSE_INTENT) - .resolveActivity(activity.packageManager) != null - if (showDialog && !yubikeyDriverAvailable) - showHardwareKeyDriverNeeded(activity, hardwareKey) - yubikeyDriverAvailable - } - } - } - - private fun showHardwareKeyDriverNeeded( - activity: FragmentActivity, - hardwareKey: HardwareKey - ) { - activity.lifecycleScope.launch { - val builder = AlertDialog.Builder(activity) - builder - .setMessage( - activity.getString(R.string.error_driver_required, hardwareKey.toString()) - ) - .setPositiveButton(R.string.download) { _, _ -> - activity.openExternalApp(activity.getString(R.string.key_driver_app_id)) - } - .setNegativeButton(android.R.string.cancel) { _, _ -> } - builder.create().show() - } - } - } -} 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 e22a6d042..e12b9c2e3 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt @@ -21,7 +21,6 @@ package com.kunzisoft.keepass.settings import android.content.ActivityNotFoundException import android.content.Intent -import android.net.Uri import android.os.Build import android.os.Bundle import android.provider.Settings @@ -30,6 +29,7 @@ import android.view.autofill.AutofillManager import android.widget.Toast import androidx.annotation.RequiresApi import androidx.appcompat.app.AlertDialog +import androidx.core.net.toUri import androidx.fragment.app.DialogFragment import androidx.fragment.app.FragmentActivity import androidx.preference.ListPreference @@ -47,7 +47,7 @@ import com.kunzisoft.keepass.icons.IconPackChooser import com.kunzisoft.keepass.services.ClipboardEntryNotificationService import com.kunzisoft.keepass.settings.preference.IconPackListPreference import com.kunzisoft.keepass.settings.preferencedialogfragment.DurationDialogFragmentCompat -import com.kunzisoft.keepass.utils.UriUtil.isContributingUser +import com.kunzisoft.keepass.utils.AppUtil.isContributingUser import com.kunzisoft.keepass.utils.UriUtil.openUrl import com.kunzisoft.keepass.utils.UriUtil.releaseAllUnnecessaryPermissionUris @@ -119,7 +119,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { activity?.let { activity -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val autoFillEnablePreference: TwoStatePreference? = findPreference(getString(R.string.settings_autofill_enable_key)) + val autoFillEnablePreference: TwoStatePreference? = findPreference(getString(R.string.settings_credential_provider_enable_key)) activity.getSystemService(AutofillManager::class.java)?.let { autofillManager -> if (autofillManager.hasEnabledAutofillServices()) autoFillEnablePreference?.isChecked = autofillManager.hasEnabledAutofillServices() @@ -161,7 +161,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { val intent = Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE) intent.data = - Uri.parse("package:com.kunzisoft.keepass.autofill.KeeAutofillService") + "package:com.kunzisoft.keepass.autofill.KeeAutofillService".toUri() Log.d(javaClass.name, "Autofill enable service: intent=$intent") startActivity(intent) } else { @@ -171,7 +171,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { } } } else { - findPreference(getString(R.string.autofill_key))?.isVisible = false + findPreference(getString(R.string.credential_provider_key))?.isVisible = false } } @@ -202,6 +202,11 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { false } + findPreference(getString(R.string.settings_passkeys_key))?.setOnPreferenceClickListener { + startActivity(Intent(context, PasskeysSettingsActivity::class.java)) + false + } + findPreference(getString(R.string.clipboard_notifications_key))?.setOnPreferenceChangeListener { _, newValue -> if (!(newValue as Boolean)) { ClipboardEntryNotificationService.removeNotification(context) @@ -530,7 +535,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { super.onResume() activity?.let { activity -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - findPreference(getString(R.string.settings_autofill_enable_key))?.let { autoFillEnablePreference -> + findPreference(getString(R.string.settings_credential_provider_enable_key))?.let { autoFillEnablePreference -> val autofillManager = activity.getSystemService(AutofillManager::class.java) autoFillEnablePreference.isChecked = autofillManager != null && autofillManager.hasEnabledAutofillServices() diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/PasskeysSettingsActivity.kt b/app/src/main/java/com/kunzisoft/keepass/settings/PasskeysSettingsActivity.kt new file mode 100644 index 000000000..e7e05bfa1 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/settings/PasskeysSettingsActivity.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2025 Jeremy Jamet / Kunzisoft. + * + * This file is part of KeePassDX. + * + * KeePassDX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KeePassDX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KeePassDX. If not, see . + * + */ +package com.kunzisoft.keepass.settings + +import androidx.preference.PreferenceFragmentCompat +import com.kunzisoft.keepass.R + +class PasskeysSettingsActivity : ExternalSettingsActivity() { + + override fun retrieveTitle(): Int { + return R.string.passkeys_preference_title + } + + override fun retrievePreferenceFragment(): PreferenceFragmentCompat { + return PasskeysSettingsFragment() + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/PasskeysSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/PasskeysSettingsFragment.kt new file mode 100644 index 000000000..7c0dd89b2 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/settings/PasskeysSettingsFragment.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2025 Jeremy Jamet / Kunzisoft. + * + * This file is part of KeePassDX. + * + * KeePassDX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KeePassDX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KeePassDX. If not, see . + * + */ +package com.kunzisoft.keepass.settings + +import android.os.Build +import android.os.Bundle +import androidx.fragment.app.DialogFragment +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.settings.preferencedialogfragment.PasskeysPrivilegedAppsPreferenceDialogFragmentCompat + +class PasskeysSettingsFragment : PreferenceFragmentCompat() { + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + // Load the preferences from an XML resource + setPreferencesFromResource(R.xml.preferences_passkeys, rootKey) + } + + override fun onDisplayPreferenceDialog(preference: Preference) { + var otherDialogFragment = false + + var dialogFragment: DialogFragment? = null + + when (preference.key) { + getString(R.string.passkeys_privileged_apps_key) -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + dialogFragment = PasskeysPrivilegedAppsPreferenceDialogFragmentCompat.newInstance(preference.key) + } + } + else -> otherDialogFragment = true + } + + if (dialogFragment != null) { + dialogFragment.setTargetFragment(this, 0) + dialogFragment.show(parentFragmentManager, TAG_PASSKEYS_PREF_FRAGMENT) + } else if (otherDialogFragment) { + super.onDisplayPreferenceDialog(preference) + } + } + + companion object { + + private const val TAG_PASSKEYS_PREF_FRAGMENT = "TAG_PASSKEYS_PREF_FRAGMENT" + } +} 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 9bc6ae1c6..e88e7e069 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt @@ -35,8 +35,8 @@ import com.kunzisoft.keepass.database.search.SearchParameters import com.kunzisoft.keepass.education.Education import com.kunzisoft.keepass.password.PassphraseGenerator import com.kunzisoft.keepass.timeout.TimeoutHelper +import com.kunzisoft.keepass.utils.AppUtil.isContributingUser import com.kunzisoft.keepass.utils.KeyboardUtil.isKeyboardActivatedInSettings -import com.kunzisoft.keepass.utils.UriUtil.isContributingUser import java.util.Properties object PreferencesUtil { @@ -821,7 +821,7 @@ object PreferencesUtil { context.getString(R.string.clipboard_notifications_key) -> editor.putBoolean(name, value.toBoolean()) context.getString(R.string.clear_clipboard_notification_key) -> editor.putBoolean(name, value.toBoolean()) context.getString(R.string.clipboard_timeout_key) -> editor.putString(name, value.toLong().toString()) - context.getString(R.string.settings_autofill_enable_key) -> editor.putBoolean(name, value.toBoolean()) + context.getString(R.string.settings_credential_provider_enable_key) -> editor.putBoolean(name, value.toBoolean()) context.getString(R.string.keyboard_notification_entry_key) -> editor.putBoolean(name, value.toBoolean()) context.getString(R.string.keyboard_notification_entry_clear_close_key) -> editor.putBoolean(name, value.toBoolean()) context.getString(R.string.keyboard_entry_timeout_key) -> editor.putString(name, value.toLong().toString()) diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/PasskeysPrivilegedAppsPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/PasskeysPrivilegedAppsPreferenceDialogFragmentCompat.kt new file mode 100644 index 000000000..f331580a0 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/PasskeysPrivilegedAppsPreferenceDialogFragmentCompat.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2025 Jeremy Jamet / Kunzisoft. + * + * This file is part of KeePassDX. + * + * KeePassDX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KeePassDX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KeePassDX. If not, see . + * + */ +package com.kunzisoft.keepass.settings.preferencedialogfragment + +import android.os.Build +import android.os.Bundle +import android.view.View +import androidx.annotation.RequiresApi +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.model.AndroidOrigin +import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListSelectionItemAdapter +import com.kunzisoft.keepass.utils.AppUtil.getInstalledBrowsersWithSignatures + +@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) +class PasskeysPrivilegedAppsPreferenceDialogFragmentCompat + : InputPreferenceDialogFragmentCompat() { + private var mAdapter = ListSelectionItemAdapter() + private var mListBrowsers: List = mutableListOf() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mListBrowsers = getInstalledBrowsersWithSignatures(requireContext()) + // TODO filter with current privileged apps + } + + override fun onBindDialogView(view: View) { + super.onBindDialogView(view) + view.findViewById(R.id.pref_dialog_list).apply { + layoutManager = LinearLayoutManager(context) + adapter = mAdapter.apply { + setItems(mListBrowsers) + } + } + } + + override fun onDialogClosed(positiveResult: Boolean) { + if (positiveResult) { + // TODO Save selected item in JSON + mAdapter.selectedItem + } + } + + companion object { + + fun newInstance(key: String): PasskeysPrivilegedAppsPreferenceDialogFragmentCompat { + val fragment = PasskeysPrivilegedAppsPreferenceDialogFragmentCompat() + val bundle = Bundle(1) + bundle.putString(ARG_KEY, key) + fragment.arguments = bundle + + return fragment + } + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/adapter/ListSelectionItemAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/adapter/ListSelectionItemAdapter.kt new file mode 100644 index 000000000..d691df561 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/adapter/ListSelectionItemAdapter.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2025 Jeremy Jamet / Kunzisoft. + * + * This file is part of KeePassDX. + * + * KeePassDX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KeePassDX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KeePassDX. If not, see . + * + */ +package com.kunzisoft.keepass.settings.preferencedialogfragment.adapter + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.kunzisoft.keepass.R + +class ListSelectionItemAdapter() + : RecyclerView.Adapter() { + + private val itemList: MutableList = ArrayList() + var selectedItem: T? = null + private set + + var itemSelectedCallback: ItemSelectedCallback? = null + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SelectionViewHolder { + return SelectionViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.pref_dialog_list_item, parent, false)) + } + + @SuppressLint("SetTextI18n", "NotifyDataSetChanged") + override fun onBindViewHolder(holder: SelectionViewHolder, position: Int) { + val item = itemList[position] + + holder.container.apply { + isSelected = item == selectedItem + } + holder.textView.apply { + text = item.toString() + setOnClickListener { + selectedItem = if (item == selectedItem) null else item + itemSelectedCallback?.onItemSelected(item) + notifyDataSetChanged() + } + } + } + + override fun getItemCount(): Int { + return itemList.size + } + + fun setItems(items: List) { + this.itemList.clear() + this.itemList.addAll(items) + } + + interface ItemSelectedCallback { + fun onItemSelected(item: T) + } + + class SelectionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var textView: TextView = itemView.findViewById(R.id.pref_dialog_list_text) + var container: ViewGroup = itemView.findViewById(R.id.pref_dialog_list_container) + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/utils/AppUtil.kt b/app/src/main/java/com/kunzisoft/keepass/utils/AppUtil.kt new file mode 100644 index 000000000..138dacfba --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/utils/AppUtil.kt @@ -0,0 +1,147 @@ +package com.kunzisoft.keepass.utils + +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.content.pm.ResolveInfo +import android.os.Build +import android.util.Log +import androidx.annotation.RequiresApi +import androidx.core.net.toUri +import com.kunzisoft.encrypt.Signature.getApplicationFingerprints +import com.kunzisoft.keepass.BuildConfig +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.education.Education +import com.kunzisoft.keepass.model.AndroidOrigin +import com.kunzisoft.keepass.model.SearchInfo +import com.kunzisoft.keepass.settings.PreferencesUtil +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import mozilla.components.lib.publicsuffixlist.PublicSuffixList + +object AppUtil { + + fun Context.isExternalAppInstalled(packageName: String, showError: Boolean = true): Boolean { + try { + this.applicationContext.packageManager.getPackageInfoCompat( + packageName, + PackageManager.GET_ACTIVITIES + ) + Education.setEducationScreenReclickedPerformed(this) + return true + } catch (e: Exception) { + if (showError) + Log.e(AppUtil::class.simpleName, "App not accessible", e) + } + return false + } + + fun Context.openExternalApp(packageName: String, sourcesURL: String? = null) { + var launchIntent: Intent? = null + try { + launchIntent = this.packageManager.getLaunchIntentForPackage(packageName)?.apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + } catch (ignored: Exception) { } + try { + if (launchIntent == null) { + this.startActivity( + Intent(Intent.ACTION_VIEW) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .setData( + if (sourcesURL != null + && !BuildConfig.CLOSED_STORE + ) { + sourcesURL + } else { + this.getString( + if (BuildConfig.CLOSED_STORE) + R.string.play_store_url + else + R.string.f_droid_url, + packageName + ) + }.toUri() + ) + ) + } else { + this.startActivity(launchIntent) + } + } catch (e: Exception) { + Log.e(AppUtil::class.simpleName, "App cannot be open", e) + } + } + + fun Context.isContributingUser(): Boolean { + return (Education.isEducationScreenReclickedPerformed(this) + || isExternalAppInstalled(this.getString(R.string.keepro_app_id), false) + ) + } + + /** + * Get the concrete web domain AKA without sub domain if needed + */ + fun getConcreteWebDomain(context: Context, + webDomain: String?, + concreteWebDomain: (String?) -> Unit) { + CoroutineScope(Dispatchers.Main).launch { + if (webDomain != null) { + // Warning, web domain can contains IP, don't crop in this case + if (PreferencesUtil.searchSubdomains(context) + || Regex(SearchInfo.WEB_IP_REGEX).matches(webDomain)) { + concreteWebDomain.invoke(webDomain) + } else { + val publicSuffixList = PublicSuffixList(context) + concreteWebDomain.invoke(publicSuffixList + .getPublicSuffixPlusOne(webDomain).await()) + } + } else { + concreteWebDomain.invoke(null) + } + } + } + + @RequiresApi(Build.VERSION_CODES.P) + fun getInstalledBrowsersWithSignatures(context: Context): List { + val packageManager = context.packageManager + val browserList = mutableListOf() + + // Create a generic web intent + val intent = Intent(Intent.ACTION_VIEW) + intent.data = "http://www.example.com".toUri() // Dummy URL + + // Query for apps that can handle this intent + val resolveInfoList: List = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + packageManager.queryIntentActivities( + intent, + PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_ALL.toLong()) + ) + } else { + @Suppress("DEPRECATION") + packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL) + } + + val processedPackageNames = mutableSetOf() + + for (resolveInfo in resolveInfoList) { + val packageName = resolveInfo.activityInfo.packageName + if (packageName != null && !processedPackageNames.contains(packageName)) { + try { + val packageInfo = packageManager.getPackageInfo( + packageName, + PackageManager.GET_SIGNING_CERTIFICATES + ) + val signatureFingerprints = packageInfo.signingInfo.getApplicationFingerprints() + signatureFingerprints?.let { + browserList.add(AndroidOrigin(packageName, signatureFingerprints)) + processedPackageNames.add(packageName) + } + } catch (e: Exception) { + Log.e(AppUtil::class.simpleName, "Error processing package: $packageName", e) + } + } + } + return browserList.distinctBy { it.packageName } // Ensure uniqueness just in case + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/utils/MenuUtil.kt b/app/src/main/java/com/kunzisoft/keepass/utils/MenuUtil.kt index cf0cd289b..6df1c4561 100644 --- a/app/src/main/java/com/kunzisoft/keepass/utils/MenuUtil.kt +++ b/app/src/main/java/com/kunzisoft/keepass/utils/MenuUtil.kt @@ -28,7 +28,7 @@ import android.view.MenuItem import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.AboutActivity import com.kunzisoft.keepass.settings.SettingsActivity -import com.kunzisoft.keepass.utils.UriUtil.isContributingUser +import com.kunzisoft.keepass.utils.AppUtil.isContributingUser import com.kunzisoft.keepass.utils.UriUtil.openUrl object MenuUtil { @@ -40,9 +40,6 @@ object MenuUtil { menu.findItem(R.id.menu_contribute)?.isVisible = false } - /* - * @param checkLock Check the time lock before launch settings in LockingActivity - */ fun onDefaultMenuOptionsItemSelected(activity: Activity, item: MenuItem, timeoutEnable: Boolean = false) { 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 c53a29e7d..83a06d6ee 100644 --- a/app/src/main/java/com/kunzisoft/keepass/utils/UriUtil.kt +++ b/app/src/main/java/com/kunzisoft/keepass/utils/UriUtil.kt @@ -200,64 +200,5 @@ object UriUtil { this.openUrl(this.getString(resId)) } - fun Context.isContributingUser(): Boolean { - return (Education.isEducationScreenReclickedPerformed(this) - || isExternalAppInstalled(this.getString(R.string.keepro_app_id), false) - ) - } - - fun Context.isExternalAppInstalled(packageName: String, showError: Boolean = true): Boolean { - try { - this.applicationContext.packageManager.getPackageInfoCompat( - packageName, - PackageManager.GET_ACTIVITIES - ) - Education.setEducationScreenReclickedPerformed(this) - return true - } catch (e: Exception) { - if (showError) - Log.e(TAG, "App not accessible", e) - } - return false - } - - fun Context.openExternalApp(packageName: String, sourcesURL: String? = null) { - var launchIntent: Intent? = null - try { - launchIntent = this.packageManager.getLaunchIntentForPackage(packageName)?.apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - } - } catch (ignored: Exception) { } - try { - if (launchIntent == null) { - this.startActivity( - Intent(Intent.ACTION_VIEW) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .setData( - Uri.parse( - if (sourcesURL != null - && !BuildConfig.CLOSED_STORE - ) { - sourcesURL - } else { - this.getString( - if (BuildConfig.CLOSED_STORE) - R.string.play_store_url - else - R.string.f_droid_url, - packageName - ) - } - ) - ) - ) - } else { - this.startActivity(launchIntent) - } - } catch (e: Exception) { - Log.e(TAG, "App cannot be open", e) - } - } - private const val TAG = "UriUtil" } diff --git a/app/src/main/java/com/kunzisoft/keepass/utils/WebDomain.kt b/app/src/main/java/com/kunzisoft/keepass/utils/WebDomain.kt deleted file mode 100644 index 429405ee0..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/utils/WebDomain.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.kunzisoft.keepass.utils - -import android.content.Context -import com.kunzisoft.keepass.model.SearchInfo -import com.kunzisoft.keepass.settings.PreferencesUtil -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import mozilla.components.lib.publicsuffixlist.PublicSuffixList - -object WebDomain { - - /** - * Get the concrete web domain AKA without sub domain if needed - */ - fun getConcreteWebDomain(context: Context, - webDomain: String?, - concreteWebDomain: (String?) -> Unit) { - CoroutineScope(Dispatchers.Main).launch { - if (webDomain != null) { - // Warning, web domain can contains IP, don't crop in this case - if (PreferencesUtil.searchSubdomains(context) - || Regex(SearchInfo.WEB_IP_REGEX).matches(webDomain)) { - concreteWebDomain.invoke(webDomain) - } else { - val publicSuffixList = PublicSuffixList(context) - concreteWebDomain.invoke(publicSuffixList - .getPublicSuffixPlusOne(webDomain).await()) - } - } else { - concreteWebDomain.invoke(null) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TextFieldView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TextFieldView.kt index fb53a360a..89f45b5d4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TextFieldView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TextFieldView.kt @@ -20,7 +20,6 @@ package com.kunzisoft.keepass.view import android.content.Context -import android.os.Build import android.text.InputFilter import android.text.util.Linkify import android.util.AttributeSet @@ -37,7 +36,7 @@ import androidx.core.view.ViewCompat import androidx.core.view.isVisible import com.kunzisoft.keepass.R import com.kunzisoft.keepass.model.AppOriginEntryField.APPLICATION_ID_FIELD_NAME -import com.kunzisoft.keepass.utils.UriUtil.openExternalApp +import com.kunzisoft.keepass.utils.AppUtil.openExternalApp open class TextFieldView @JvmOverloads constructor(context: Context, diff --git a/app/src/main/res/layout/pref_dialog_list_item.xml b/app/src/main/res/layout/pref_dialog_list_item.xml new file mode 100644 index 000000000..9c985da2c --- /dev/null +++ b/app/src/main/res/layout/pref_dialog_list_item.xml @@ -0,0 +1,35 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 494875b23..ae794372f 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -167,7 +167,7 @@ عام الملء التلقائي سجل باستخدام KeePassDX - تعيين خدمة الملأ التلقائي الافتراضية + تعيين خدمة الملأ التلقائي الافتراضية حجم كلمة السر المولدة تعيين الحجم الافتراضي لكلمات السر المولدة محارف كلمة السر diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 6ee009306..54954133a 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -518,7 +518,7 @@ Cihaz kilid açma istəyini başlatmaq mümkün deyil. Digər tətbiqlərdə formları (anket) daha sürətli doldurmaq üçün avtomatik doldurma funksiyasını aktiv edin Şifrə seç .… - Standart avtomatik doldurma xidmətini təyin edin + Standart avtomatik doldurma xidmətini təyin edin Avtomatik doldurmanın parametrləri Yaradılan şifrə həcmi Yaradılan şifrələrin standart həcmini təyin edər diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 2091a718a..c05eb24f5 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -288,7 +288,7 @@ Само за четене Хранилището съдържа повтарящ се идентификатор. Биометричен ключ - Задаване на подразбирана услуга за автоматично попълване + Задаване на подразбирана услуга за автоматично попълване Дължина на създаваните пароли Заключване при „Назад“ Съдържание diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 3a9c202d5..6d02fdb10 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -410,7 +410,7 @@ Esperant la resposta de desafiament… Nom del banc Wi-Fi - Estableix el servei d\'emplenament automàtic predeterminat + Estableix el servei d\'emplenament automàtic predeterminat Compressió Targeta d\'identificació Clau física no suportada. diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index bf764789e..5d391ddb4 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -181,7 +181,7 @@ Samovyplnění KeePassDX samovyplnění formulářů Přihlásit se s KeePassDX - Nastavit výchozí službu samovyplnění + Nastavit výchozí službu samovyplnění Zapnout samovyplnění formulářů za účelem rychlého vyplnění v ostatních aplikacích Délka generovaného hesla Nastavení výchozí délky generovaných hesel diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 64fbac849..a75170aaf 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -180,7 +180,7 @@ Autoudfyld KeePassDX formularudfyldning Log ind med KeePassDX - Indstil standard autoudfyldningstjeneste + Indstil standard autoudfyldningstjeneste Aktiver autofyldning for hurtigt at udfylde formularer i andre apps Genereret adgangskodelængde Angiver standardlængden for genererede adgangskoder diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b98393928..706244c77 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -197,7 +197,7 @@ Automatisches Ausfüllen KeePassDX Auto-Formularausfüllung Mit KeePassDX anmelden - Standard-Autofill-Service festlegen + Standard-Autofill-Service festlegen Automatisches Ausfüllen aktivieren, um Formulare in anderen Apps schnell auszufüllen Eintrag auswählen … Zwischenablage diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index f585bfe61..adc838d22 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -169,7 +169,7 @@ Αυτόματη συμπλήρωση Μορφή KeePassDX αυτόματης συμπλήρωσης Συνδεθείτε με το KeePassDX - Ορίστε την προεπιλεγμένη υπηρεσία αυτόματης συμπλήρωσης + Ορίστε την προεπιλεγμένη υπηρεσία αυτόματης συμπλήρωσης Παραγόμενο μέγεθος κωδικού πρόσβασης Ορίστε το προεπιλεγμένο μέγεθος των παραγόμενων κωδικών πρόσβασης Χαρακτήρες Κωδικού Πρόσβασης diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 992ccb923..dd351eb32 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -172,7 +172,7 @@ Autocompletado Autocompletado de formularios de KeePassDX Iniciar sesión con KeePassDX - Establecer servicio de autocompletado por defecto + Establecer servicio de autocompletado por defecto Tamaño de la contraseña generada Establece el tamaño predeterminado de las contraseñas generadas Caracteres de contraseña diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index bc89cded7..56a97585a 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -474,7 +474,7 @@ KeePassDXi automaattäite teenus Täitmaks andmevorme teistes rakenduses, luba automaattäite teenus Vali kirje… - Vali vaikimisi kasutatav automaattäite teenus + Vali vaikimisi kasutatav automaattäite teenus Automaattäite teenuse seadistused Andmebaas on avatud Lõikelaud diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 2cad4c545..1b55116ff 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -575,7 +575,7 @@ Fitxategirako atzipena baliogabetu du fitxategi kudeatzaileak, itxi datu-basea eta berriro ireki ezazu bere lokalizaziotik. Gailuaren desblokeorako esteka Ezin izan da hasieratu gailuaren desblokeatze menua. - Lehenetsi betetze automatiko zerbitzua + Lehenetsi betetze automatiko zerbitzua Edukia Datu-basearen desblokeatze automatikoa Pantaila-argazki modua diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 5d3ebf87a..9e6177ce9 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -237,7 +237,7 @@ Pääavain muunnetaan käyttäen satunnaista suolattua avaimen johtamisfunktiota, jotta salausalgoritmin avain voidaan generoida. Salasanatietokannan salausalgoritmi, jota käytetään kaikelle datalle. Generoidun salasanan pituus - Aseta oletus automaattiselle täytölle + Aseta oletus automaattiselle täytölle Kirjaudu sisään KeePassDX:llä KeePassDX:n automaattinen täyttö Automaattinen täyttö diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 4d0aefe9c..1ba157de4 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -165,7 +165,7 @@ Remplissage automatique Remplissage automatique des formulaires KeePassDX Se connecter avec KeePassDX - Définir le service de remplissage automatique par défaut + Définir le service de remplissage automatique par défaut Activer le remplissage automatique pour remplir rapidement des formulaires dans d’autres applications Sélectionner une entrée… Taille du mot de passe généré diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 9802a2569..050b5958c 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -373,7 +373,7 @@ Biométrico Habilite o servizo para autocompletar rapidamente os formularios de outras aplicacións Notificacións do portapapeis - Estabelecer o servizo de autocompletado predefinido + Estabelecer o servizo de autocompletado predefinido Bloquear a base de datos cando o usuario faga click no botón de volver á pantalla principal Mostrar botón de bloqueo Mostrar notificacións do portapapeis ao visualizar unha entrada diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 5d537d245..375310bc0 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -178,7 +178,7 @@ Opće Automatsko ispunjavanje Automatsko ispunjavanje KeePassDX obrasca - Postavi standardnu uslugu automatskog ispunjavanja + Postavi standardnu uslugu automatskog ispunjavanja Znakovi lozinke Postavi dozvoljene znakove za generiranje lozinke Baza podataka otvorena diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index d51d2a978..d18ff373f 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -185,7 +185,7 @@ Automatikus kitöltés KeePassDX űrlapkitöltés Bejelentkezés a KeePassDX-szel - Alapértelmezett automatikus kitöltési szolgáltatás beállítása + Alapértelmezett automatikus kitöltési szolgáltatás beállítása Automatikus kitöltés engedélyezése az űrlapok gyors kitöltéséhez más alkalmazásokban Előállított jelszó mérete Beállítja az előállított jelszavak alapértelmezett méretét diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index e4f226d30..009d79cda 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -423,7 +423,7 @@ Ketik kata sandi, lalu klik tombol ini. Isi formulir KeePassDX otomatis Pengaturan isi otomatis - Setel layanan isi otomatis secara default + Setel layanan isi otomatis secara default Aktifkan pengisian otomatis untuk mengisi formulir dengan cepat di aplikasi lain Masuk dengan KeePassDX Isi otomatis diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 37ef2ad12..c1c474aa6 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -180,7 +180,7 @@ Autocompletamento Autocompletamento di KeePassDX Accedi con KeePassDX - Servizio predefinito di autocompletamento + Servizio predefinito di autocompletamento Attiva l\'autocompletamento per riempire velocemente i campi in altre app Dimensione password generata Imposta la dimensione predefinita delle password generate diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index aef987119..b25c54740 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -414,7 +414,7 @@ התחבר עם KeePassDX כללי הפעל מילוי אוטומטי כדי למלא במהירות טפסים ביישומים אחרים - הגדר שירות מילוי אוטומטי ברירת מחדל + הגדר שירות מילוי אוטומטי ברירת מחדל גודל סיסמה שנוצרה מגדיר גודל ברירת המחדל של הסיסמאות שנוצרו תווי סיסמה diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 768ea7262..7dc4018e6 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -276,7 +276,7 @@ KeePassDX フォーム自動入力 KeePassDX でログイン 自動入力を有効にして、他のアプリ内のフォームにすばやく入力します - デフォルトの自動入力サービスに設定 + デフォルトの自動入力サービスに設定 自動入力の設定 生成されるパスワードの長さ 生成されるパスワードの長さのデフォルト値を設定します diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 37e4720d3..7c2afffce 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -385,7 +385,7 @@ KeePassDX로 로그인 생성된 비밀번호 크기 자동 완성 설정 - 기본 자동완성 서비스 설정 + 기본 자동완성 서비스 설정 화면 꺼짐 시 잠금 기기 잠금 방식을 사용하여 데이터베이스를 더 쉽게 여세요 생체 인식 잠금 해제 diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 7ca277d4b..d4463caa8 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -361,7 +361,7 @@ Failo \"hash\" reikšmė nėra garantuota, nes \"Android\" gali keisti jo duomenis. Norėdami užtikrinti teisingą vientisumą, pakeiskite failo plėtinį į .bin. Biometriniai duomenys ar prietaiso įgaliojimai neįrašomi. Automatinio pildymo nustatymai - Nustatyti numatytąją automatinio pildymo paslaugą + Nustatyti numatytąją automatinio pildymo paslaugą Ekrano užraktas Biometrinis atrakinimas Rodyti UUID diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index 1a4cb99ac..2b5dddeb3 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -339,7 +339,7 @@ നിങ്ങളുടെ ഉപകരണത്തിന്റെ ക്ലിപ്പ്ബോർഡ് ഉപയോഗിച്ച് എൻട്രി ഫീൽഡുകൾ പകർത്തുക പാസ്‌വേഡ് പ്രതീകങ്ങൾ സൃഷ്ടിച്ച പാസ്‌വേഡുകളുടെ സ്ഥിരസ്ഥിതി വലുപ്പം സജ്ജമാക്കുക - സ്ഥിരസ്ഥിതി ഓട്ടോഫിൽ സേവനം സജ്ജമാക്കുക + സ്ഥിരസ്ഥിതി ഓട്ടോഫിൽ സേവനം സജ്ജമാക്കുക മറ്റ് അപ്ലിക്കേഷനുകളിൽ ഫോമുകൾ വേഗത്തിൽ പൂരിപ്പിക്കുന്നതിന് ഓട്ടോഫില്ലിംഗ് പ്രവർത്തനക്ഷമമാക്കുക കീസ്റ്റോർ ശരിയായി സമാരംഭിച്ചിട്ടില്ല. റീസൈക്കിൾ ബിൻ ചുവടെയുണ്ട് diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 24233be04..37b01496e 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -175,7 +175,7 @@ Autofyll KeePassDX autofyll-tjeneste Logg inn med KeePassDX - Sett forvalgt autofyll-tjeneste + Sett forvalgt autofyll-tjeneste Skru på tjenesten for å fylle ut skjema fra andre programmer Passordsstørrelse Sett forvalgt størrelse for generert passord diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b4e7cbb1f..5763a2b7b 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -187,7 +187,7 @@ Automatisch aanvullen KeePassDX dienst automatisch aanvullen Inloggen met KeePassDX - Dienst automatisch aanvullen + Dienst automatisch aanvullen Schakel de dienst in om formulieren in andere apps in te vullen Gegenereerde wachtwoordlengte Stel de standaardlengte van gegenereerde wachtwoorden in diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 6a2079916..724314917 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -266,7 +266,7 @@ ਲਾਕ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਨੂੰ ਦਬਾਓ ਜਦੋਂ ਸਕਰੀਨ ਬੰਦ ਹੋ ਜਾਵੇ ਤਾਂ ਡਾਟਾਬੇਸ ਨੂੰ ਲਾਕ ਕਰੋ ਕਲਿੱਪਬੋਰਡ ਨੋਟੀਫਿਕੇਸ਼ਨ - ਮੂਲ ਆਪੇ-ਭਰਨ ਸੇਵਾ ਵਜੋਂ ਸੈੱਟ ਕਰੋ + ਮੂਲ ਆਪੇ-ਭਰਨ ਸੇਵਾ ਵਜੋਂ ਸੈੱਟ ਕਰੋ ਕੋਈ ਬਾਇਓਮੈਟਰਿਕ ਜਾਂ ਡਿਵਾਈਸ ਸਨਦ ਦਾਖਲ ਨਹੀਂ ਕੀਤੀ ਹੈ। ਇਹ ਡਾਟਾ ਕਿਵੇਂ ਵੀ ਹਟਾਉਣਾ ਹੈ\? ਕਿਵੇਂ ਵੀ ਫ਼ਾਇਲ ਜੋੜਨੀ ਹੈ\? diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 0764caae3..5e26487d6 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -182,7 +182,7 @@ Wypełnij automatycznie Autouzupełnianie formularzy KeePassDX Zaloguj się za pomocą KeePassDX - Ustaw domyślną usługę autouzupełniania + Ustaw domyślną usługę autouzupełniania Włącz autouzupełnianie, aby móc szybko wypełniać formularze w innych aplikacjach Wygenerowany rozmiar hasła Ustawia domyślny rozmiar wygenerowanych haseł diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 92d234c07..4880478dd 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -180,7 +180,7 @@ Preenchimento automático Preenchimento automático do KeePassDX Entre com o KeePassDX - Definir serviço padrão de preenchimento automático + Definir serviço padrão de preenchimento automático Habilite o serviço para rapidamente preencher formulários em outros aplicativos Comprimento da senha gerada Define o tamanho padrão para senhas geradas diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 11ebb1a23..ba2fcb56f 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -179,7 +179,7 @@ Preenchimento automático Serviço de preenchimento automático do KeePassDX Iniciar sessão com KeePassDX - Definir como serviço de preenchimento automático predefinido + Definir como serviço de preenchimento automático predefinido Ative o serviço de preencher automático para preencher formulários noutras aplicações Tamanho da palavra-passe gerada Editar entrada diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 8016ca296..1e36fbc1d 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -91,7 +91,7 @@ Caracteres das palavras-passe Define o tamanho predefinido para as palavras-passe geradas Tamanho da palavra-passe gerada - Definir como serviço de preenchimento automático predefinido + Definir como serviço de preenchimento automático predefinido Iniciar sessão com KeePassDX Serviço de preenchimento automático do KeePassDX Preenchimento automático diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 623deb078..7b558df3c 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -240,7 +240,7 @@ Completarea automată cu KeePassDX Conectați-vă cu KeePassDX Activați completarea automată pentru a completa rapid formulare în alte aplicații - Setați serviciul implicit de autocompletare + Setați serviciul implicit de autocompletare Dimensiunea parolei generate Setează dimensiunea implicită a parolelor generate Caractere parolă diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 23b40a62f..18b1c019f 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -184,7 +184,7 @@ Служба автозаполнения KeePassDX Войти с помощью KeePassDX Включите службу для быстрого заполнения форм в других приложениях - Использовать службу автозаполнения + Использовать службу автозаполнения Длина создаваемого пароля Настройка длины создаваемых паролей по умолчанию Символы пароля diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 4decad49c..2ad2c9e40 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -595,7 +595,7 @@ Vlastnosti Vzhľad Povoľte automatické dopĺňanie na rýchle vyplnenie formulárov v iných aplikáciách - Nastavte predvolenú službu automatického dopĺňania + Nastavte predvolenú službu automatického dopĺňania Nastavte povolené znaky generátora hesiel Umožňuje vám skenovať biometrické údaje a otvoriť databázu Maximálny počet diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 6d56c71c0..0e38282f2 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -570,7 +570,7 @@ Përzgjidhni tema të çelëta ose të errëta Paketë ikonash të përdorura te aplikacioni Zërat e skaduar nuk shfaqen - Caktoni shërbim parazgjedhje vetëplotësimesh + Caktoni shërbim parazgjedhje vetëplotësimesh Aktivizoni vetëplotësimet, për të plotësuar shpejt formularë në aplikacione të tjerë Rregullime vetëplotësimi Cakton madhësinë parazgjedhje për fjalëkalimet e prodhuar diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 666254906..bf7358e52 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -189,7 +189,7 @@ Autofyll KeePassDX autofyll formulär Logga in med KeePassDX - Välj standardtjänst för autofyll + Välj standardtjänst för autofyll Längd på genererat lösenord Anger standardlängden för de genererade lösenorden Lösenordstecken diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 946f50536..8fab75106 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -73,7 +73,7 @@ பயோமெட்ரிக் பாதுகாப்பு புதுப்பிப்பு தேவை. கீச்டோர் சரியாக துவக்கப்படவில்லை. தோற்றம் - இயல்புநிலை ஆட்டோஃபில் சேவையை அமைக்கவும் + இயல்புநிலை ஆட்டோஃபில் சேவையை அமைக்கவும் ஆட்டோஃபில் அமைப்புகள் திரை பூட்டு உள்ளடக்கம் diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 9f2cdfbc8..fe3af812d 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -529,7 +529,7 @@ ประวัติ เลือกไฟล์ที่จะนําเข้าการตั้งค่าของแอป นำเข้าการตั้งค่าแอปแล้ว - ตั่งค่าเป็นบริการกรอกข้อมูลอัตโนมัติเรื่มต้น + ตั่งค่าเป็นบริการกรอกข้อมูลอัตโนมัติเรื่มต้น เกิดข้อผิดพลาดระหว่างการส่งออกการตั้งค่าของแอป ลักษณะ ไบโอเมตริก diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 28b5aa6b8..a72ca8fa2 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -176,7 +176,7 @@ Otomatik Doldurma KeePassDX formu otomatik doldurma KeePassDX ile giriş yap - Öntanımlı otomatik doldurma hizmetini ayarla + Öntanımlı otomatik doldurma hizmetini ayarla Diğer uygulamalardaki formları hızlı doldurmak için otomatik doldurmayı etkinleştirin Oluşturulan parola boyutu Oluşturulan parolaların öntanımlı boyutunu ayarlar diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 7e2dca9e4..cde78726a 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -394,7 +394,7 @@ Встановити типову довжину створюваних паролів Довжина створюваного пароля Налаштування автозаповнення - Встановити типовою службою автозаповнення + Встановити типовою службою автозаповнення Увімкнути автозаповнення для швидкого заповнення форм в інших застосунках Увійти за допомогою KeePassDX Автозаповнення форм KeePassDX diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 19f93744c..e02cfdb36 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -415,7 +415,7 @@ Đăng nhập bằng KeePassDX Bật tính năng tự động điền để nhanh chóng điền vào biểu mẫu trong các ứng dụng khác Chọn mục… - Đặt dịch vụ tự động điền mặc định + Đặt dịch vụ tự động điền mặc định Thiết đặt tự động điền Kích thước mật khẩu đã tạo Đặt kích thước mặc định của mật khẩu được tạo diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index d6d8858b9..f23dda7c1 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -206,7 +206,7 @@ 构建 %1$s 加密密码已保存 不可用 - 设为默认自动填充服务 + 设为默认自动填充服务 启用自动填充功能,以快速填写其他应用中的表单 密码生成长度 设置生成密码的默认长度 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 3ea1a9310..99116662b 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -501,7 +501,7 @@ 選擇條目 複製%1$s到剪貼簿 選擇模式 - 設置為預設的填充服務 + 設置為預設的填充服務 設定 下次強制更改主密鑰(一次) 下次強制更換 diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index f563e16ad..2581f11bf 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -126,11 +126,14 @@ false clip_timeout_key 20000 - autofill_key + credential_provider_key + settings_credential_provider_enable_key + false autofill_explanation_key - settings_autofill_enable_key - false settings_autofill_key + passkeys_explanation_key + settings_passkeys_key + passkeys_privileged_apps_key keyboard_notification_entry_key true keyboard_notification_entry_clear_close_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d52376bfc..4420503ab 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -417,12 +417,19 @@ Biometric Device credential General + Credential provider + Credential provider service + Passkeys + Configure Passkeys for fast and secure passwordless login + Passkeys settings + Privileged apps + Add a browser to the list of privileged apps + Select an app to add to the list of privileged apps Autofill KeePassDX form autofilling Sign in with KeePassDX - Enable autofilling to quickly fill out forms in other apps + Configure autofilling to quickly fill out forms in other apps Select entry… - Set default autofill service Autofill settings Generated password size Sets default size of the generated passwords diff --git a/app/src/main/res/xml/preferences_form_filling.xml b/app/src/main/res/xml/preferences_form_filling.xml index ae166bd50..3510b0655 100644 --- a/app/src/main/res/xml/preferences_form_filling.xml +++ b/app/src/main/res/xml/preferences_form_filling.xml @@ -34,16 +34,23 @@ + android:key="@string/credential_provider_key" + android:title="@string/credential_provider"> + + + - diff --git a/app/src/main/res/xml/preferences_passkeys.xml b/app/src/main/res/xml/preferences_passkeys.xml new file mode 100644 index 000000000..397a4afb2 --- /dev/null +++ b/app/src/main/res/xml/preferences_passkeys.xml @@ -0,0 +1,53 @@ + + + + + + + + + \ No newline at end of file diff --git a/database/src/main/java/com/kunzisoft/keepass/model/AppOrigin.kt b/database/src/main/java/com/kunzisoft/keepass/model/AppOrigin.kt index d4d75f501..31208a90d 100644 --- a/database/src/main/java/com/kunzisoft/keepass/model/AppOrigin.kt +++ b/database/src/main/java/com/kunzisoft/keepass/model/AppOrigin.kt @@ -119,6 +119,10 @@ data class AndroidOrigin( } return "android:apk-key-hash:${fingerprintToUrlSafeBase64(fingerprint)}" } + + override fun toString(): String { + return "$packageName (${fingerprint})" + } } @Parcelize @@ -134,6 +138,10 @@ data class WebOrigin( return "${origin}/.well-known/assetlinks.json" } + override fun toString(): String { + return origin + } + companion object { const val RELYING_PARTY_DEFAULT_PROTOCOL = "https" fun fromRelyingParty(relyingParty: String): WebOrigin = WebOrigin(