mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'release/2.7'
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
KeePassDX(2.7)
|
||||
* Add blocklists for autofill
|
||||
* Add autofill compatibility mode (usefull for Browser not compatible)
|
||||
* Upgrade autofill recognition algorithm
|
||||
* Setting to search through web subdomains
|
||||
* Refactoring selection mode
|
||||
|
||||
KeePassDX(2.6)
|
||||
* Share a web domain to automatically search for an entry
|
||||
* Default group icon for a new entry
|
||||
|
||||
@@ -11,8 +11,8 @@ android {
|
||||
applicationId "com.kunzisoft.keepass"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 29
|
||||
versionCode = 34
|
||||
versionName = "2.6"
|
||||
versionCode = 35
|
||||
versionName = "2.7"
|
||||
multiDexEnabled true
|
||||
|
||||
testApplicationId = "com.kunzisoft.keepass.tests"
|
||||
@@ -69,7 +69,7 @@ android {
|
||||
buildConfigField "String", "BUILD_VERSION", "\"free\""
|
||||
buildConfigField "boolean", "FULL_VERSION", "false"
|
||||
buildConfigField "boolean", "CLOSED_STORE", "true"
|
||||
buildConfigField "String[]", "STYLES_DISABLED", "{\"KeepassDXStyle_Dark\",\"KeepassDXStyle_Blue\",\"KeepassDXStyle_Red\",\"KeepassDXStyle_Purple\"}"
|
||||
buildConfigField "String[]", "STYLES_DISABLED", "{}"
|
||||
buildConfigField "String[]", "ICON_PACKS_DISABLED", "{}"
|
||||
manifestPlaceholders = [ googleAndroidBackupAPIKey:"AEdPqrEAAAAIbRfbV8fHLItXo8OcHwrO0sSNblqhPwkc0DPTqg" ]
|
||||
}
|
||||
|
||||
@@ -26,25 +26,43 @@ import android.content.Intent
|
||||
import android.content.IntentSender
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.autofill.KeeAutofillService
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
class AutofillLauncherActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// Pass extra for Autofill (EXTRA_ASSIST_STRUCTURE)
|
||||
val assistStructure = AutofillHelper.retrieveAssistStructure(intent)
|
||||
if (assistStructure != null) {
|
||||
|
||||
// Build search param
|
||||
val searchInfo = SearchInfo().apply {
|
||||
applicationId = intent.getStringExtra(KEY_SEARCH_APPLICATION_ID)
|
||||
webDomain = intent.getStringExtra(KEY_SEARCH_DOMAIN)
|
||||
}
|
||||
|
||||
// Pass extra for Autofill (EXTRA_ASSIST_STRUCTURE)
|
||||
val assistStructure = AutofillHelper.retrieveAssistStructure(intent)
|
||||
|
||||
if (assistStructure == null) {
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
finish()
|
||||
} else if (!KeeAutofillService.searchAllowedFor(searchInfo.applicationId,
|
||||
PreferencesUtil.applicationIdBlocklist(this))
|
||||
|| !KeeAutofillService.searchAllowedFor(searchInfo.webDomain,
|
||||
PreferencesUtil.webDomainBlocklist(this))) {
|
||||
// If item not allowed, show a toast
|
||||
Toast.makeText(this.applicationContext, R.string.autofill_block_restart, Toast.LENGTH_LONG).show()
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
finish()
|
||||
} else {
|
||||
// If database is open
|
||||
SearchHelper.checkAutoSearchInfo(this,
|
||||
Database.getInstance(),
|
||||
@@ -57,17 +75,17 @@ class AutofillLauncherActivity : AppCompatActivity() {
|
||||
{
|
||||
// Show the database UI to select the entry
|
||||
GroupActivity.launchForAutofillResult(this,
|
||||
assistStructure)
|
||||
assistStructure,
|
||||
false,
|
||||
searchInfo)
|
||||
},
|
||||
{
|
||||
// If database not open
|
||||
FileDatabaseSelectActivity.launchForAutofillResult(this,
|
||||
assistStructure, searchInfo)
|
||||
assistStructure,
|
||||
searchInfo)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
finish()
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.education.EntryEditActivityEducation
|
||||
import com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService
|
||||
@@ -166,13 +167,18 @@ class EntryEditActivity : LockingActivity(),
|
||||
mNewEntry = mDatabase?.createEntry()
|
||||
}
|
||||
mParent = mDatabase?.getGroupById(it)
|
||||
// Add the default icon from parent
|
||||
mParent?.icon?.let { parentIcon ->
|
||||
// Add the default icon from parent if not a folder
|
||||
val parentIcon = mParent?.icon
|
||||
if (parentIcon != null
|
||||
&& parentIcon.iconId != IconImage.UNKNOWN_ID
|
||||
&& parentIcon.iconId != IconImageStandard.FOLDER) {
|
||||
temporarilySaveAndShowSelectedIcon(parentIcon)
|
||||
} ?: mDatabase?.drawFactory?.let { iconFactory ->
|
||||
} else {
|
||||
mDatabase?.drawFactory?.let { iconFactory ->
|
||||
entryEditContentsView?.setDefaultIcon(iconFactory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the new entry after an orientation change
|
||||
if (savedInstanceState != null
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
@@ -49,22 +48,21 @@ class EntrySelectionLauncherActivity : AppCompatActivity() {
|
||||
if ("text/plain" == intent.type) {
|
||||
// Retrieve web domain
|
||||
intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
|
||||
sharedWebDomain = Uri.parse(it).authority
|
||||
sharedWebDomain = Uri.parse(it).host
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
// Setting to integrate Magikeyboard
|
||||
val searchShareForMagikeyboard = PreferencesUtil.isKeyboardSearchShareEnable(this)
|
||||
|
||||
// Build search param
|
||||
val searchInfo = SearchInfo().apply {
|
||||
webDomain = sharedWebDomain
|
||||
}
|
||||
|
||||
// Setting to integrate Magikeyboard
|
||||
val searchShareForMagikeyboard = PreferencesUtil.isKeyboardSearchShareEnable(this)
|
||||
|
||||
// If database is open
|
||||
SearchHelper.checkAutoSearchInfo(this,
|
||||
Database.getInstance(),
|
||||
@@ -75,29 +73,41 @@ class EntrySelectionLauncherActivity : AppCompatActivity() {
|
||||
if (items.size == 1) {
|
||||
// Automatically populate keyboard
|
||||
val entryPopulate = items[0]
|
||||
populateKeyboardAndMoveAppToBackground(this, entryPopulate, intent)
|
||||
populateKeyboardAndMoveAppToBackground(this,
|
||||
entryPopulate,
|
||||
intent)
|
||||
} else {
|
||||
// Select the one we want
|
||||
GroupActivity.launchForEntrySelectionResult(this, searchInfo)
|
||||
GroupActivity.launchForEntrySelectionResult(this,
|
||||
true,
|
||||
searchInfo)
|
||||
}
|
||||
} else {
|
||||
GroupActivity.launch(this, searchInfo)
|
||||
GroupActivity.launch(this,
|
||||
true,
|
||||
searchInfo)
|
||||
}
|
||||
},
|
||||
{
|
||||
// Show the database UI to select the entry
|
||||
if (searchShareForMagikeyboard) {
|
||||
GroupActivity.launchForEntrySelectionResult(this)
|
||||
GroupActivity.launchForEntrySelectionResult(this,
|
||||
false,
|
||||
searchInfo)
|
||||
} else {
|
||||
GroupActivity.launch(this)
|
||||
GroupActivity.launch(this,
|
||||
false,
|
||||
searchInfo)
|
||||
}
|
||||
},
|
||||
{
|
||||
// If database not open
|
||||
if (searchShareForMagikeyboard) {
|
||||
FileDatabaseSelectActivity.launchForEntrySelectionResult(this, searchInfo)
|
||||
FileDatabaseSelectActivity.launchForEntrySelectionResult(this,
|
||||
searchInfo)
|
||||
} else {
|
||||
FileDatabaseSelectActivity.launch(this, searchInfo)
|
||||
FileDatabaseSelectActivity.launch(this,
|
||||
searchInfo)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper.KEY_SEARCH_INFO
|
||||
import com.kunzisoft.keepass.activities.helpers.OpenFileHelper
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||
import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
@@ -59,13 +59,14 @@ import com.kunzisoft.keepass.view.asError
|
||||
import kotlinx.android.synthetic.main.activity_file_selection.*
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
class FileDatabaseSelectActivity : StylishActivity(),
|
||||
class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
AssignMasterKeyDialogFragment.AssignPasswordDialogListener {
|
||||
|
||||
// Views
|
||||
private var coordinatorLayout: CoordinatorLayout? = null
|
||||
private var fileManagerExplanationButton: View? = null
|
||||
private var createButtonView: View? = null
|
||||
private var databaseButtonsContainerView: View? = null
|
||||
private var createDatabaseButtonView: View? = null
|
||||
private var openDatabaseButtonView: View? = null
|
||||
|
||||
// Adapter to manage database history list
|
||||
@@ -96,19 +97,13 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
UriUtil.gotoUrl(this, R.string.file_manager_explanation_url)
|
||||
}
|
||||
|
||||
// Create button
|
||||
createButtonView = findViewById(R.id.create_database_button)
|
||||
if (allowCreateDocumentByStorageAccessFramework(packageManager)) {
|
||||
// There is an activity which can handle this intent.
|
||||
createButtonView?.visibility = View.VISIBLE
|
||||
}
|
||||
else{
|
||||
// No Activity found that can handle this intent.
|
||||
createButtonView?.visibility = View.GONE
|
||||
}
|
||||
databaseButtonsContainerView = findViewById(R.id.database_buttons_container)
|
||||
|
||||
createButtonView?.setOnClickListener { createNewFile() }
|
||||
// Create database button
|
||||
createDatabaseButtonView = findViewById(R.id.create_database_button)
|
||||
createDatabaseButtonView?.setOnClickListener { createNewFile() }
|
||||
|
||||
// Open database button
|
||||
mOpenFileHelper = OpenFileHelper(this)
|
||||
openDatabaseButtonView = findViewById(R.id.open_keyfile_button)
|
||||
openDatabaseButtonView?.apply {
|
||||
@@ -157,7 +152,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
UriUtil.parse(databasePath)?.let { databaseFileUri ->
|
||||
launchPasswordActivityWithPath(databaseFileUri)
|
||||
} ?: run {
|
||||
Log.i(TAG, "Unable to launch Password Activity")
|
||||
Log.i(TAG, "No default database to prepare")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,11 +236,13 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
EntrySelectionHelper.doEntrySelectionAction(intent,
|
||||
{
|
||||
GroupActivity.launch(this@FileDatabaseSelectActivity,
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
},
|
||||
{
|
||||
GroupActivity.launchForEntrySelectionResult(this@FileDatabaseSelectActivity,
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
// Do not keep history
|
||||
@@ -255,6 +252,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
GroupActivity.launchForAutofillResult(this@FileDatabaseSelectActivity,
|
||||
assistStructure,
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
}
|
||||
@@ -269,13 +267,27 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
// Show open and create button or special mode
|
||||
if (mSelectionMode) {
|
||||
// Disable buttons if in selection mode or request for autofill
|
||||
databaseButtonsContainerView?.visibility = View.GONE
|
||||
} else {
|
||||
if (allowCreateDocumentByStorageAccessFramework(packageManager)) {
|
||||
// There is an activity which can handle this intent.
|
||||
createDatabaseButtonView?.visibility = View.VISIBLE
|
||||
} else{
|
||||
// No Activity found that can handle this intent.
|
||||
createDatabaseButtonView?.visibility = View.GONE
|
||||
}
|
||||
databaseButtonsContainerView?.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
val database = Database.getInstance()
|
||||
if (database.loaded) {
|
||||
launchGroupActivity(database.isReadOnly)
|
||||
}
|
||||
|
||||
super.onResume()
|
||||
|
||||
} else {
|
||||
// Construct adapter with listeners
|
||||
if (PreferencesUtil.showRecentFiles(this)) {
|
||||
mFileDatabaseHistoryAction?.getAllFileDatabaseHistories { databaseFileHistoryList ->
|
||||
@@ -301,6 +313,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
// Register progress task
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
// Unregister progress task
|
||||
@@ -378,7 +391,10 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
super.onCreateOptionsMenu(menu)
|
||||
|
||||
if (!mSelectionMode) {
|
||||
MenuUtil.defaultMenuInflater(menuInflater, menu)
|
||||
}
|
||||
|
||||
Handler().post { performedNextEducation(FileDatabaseSelectActivityEducation(this)) }
|
||||
|
||||
@@ -387,11 +403,11 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
|
||||
private fun performedNextEducation(fileDatabaseSelectActivityEducation: FileDatabaseSelectActivityEducation) {
|
||||
// If no recent files
|
||||
val createDatabaseEducationPerformed = createButtonView != null && createButtonView!!.visibility == View.VISIBLE
|
||||
val createDatabaseEducationPerformed = createDatabaseButtonView != null && createDatabaseButtonView!!.visibility == View.VISIBLE
|
||||
&& mAdapterDatabaseHistory != null
|
||||
&& mAdapterDatabaseHistory!!.itemCount > 0
|
||||
&& fileDatabaseSelectActivityEducation.checkAndPerformedCreateDatabaseEducation(
|
||||
createButtonView!!,
|
||||
createDatabaseButtonView!!,
|
||||
{
|
||||
createNewFile()
|
||||
},
|
||||
|
||||
@@ -63,6 +63,7 @@ import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.education.GroupActivityEducation
|
||||
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.model.getSearchString
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_GROUP_TASK
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_DELETE_NODES_TASK
|
||||
@@ -74,10 +75,7 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.MenuUtil
|
||||
import com.kunzisoft.keepass.view.AddNodeButtonView
|
||||
import com.kunzisoft.keepass.view.ToolbarAction
|
||||
import com.kunzisoft.keepass.view.asError
|
||||
import com.kunzisoft.keepass.view.showActionError
|
||||
import com.kunzisoft.keepass.view.*
|
||||
|
||||
class GroupActivity : LockingActivity(),
|
||||
GroupEditDialogFragment.EditGroupListener,
|
||||
@@ -96,7 +94,6 @@ class GroupActivity : LockingActivity(),
|
||||
private var toolbarAction: ToolbarAction? = null
|
||||
private var iconView: ImageView? = null
|
||||
private var numberChildrenView: TextView? = null
|
||||
private var modeTitleView: TextView? = null
|
||||
private var addNodeButtonView: AddNodeButtonView? = null
|
||||
private var groupNameView: TextView? = null
|
||||
|
||||
@@ -106,6 +103,9 @@ class GroupActivity : LockingActivity(),
|
||||
private var mCurrentGroupIsASearch: Boolean = false
|
||||
private var mRequestStartupSearch = true
|
||||
|
||||
// To manage history in selection mode
|
||||
private var mSelectionModeCountBackStack = 0
|
||||
|
||||
// Nodes
|
||||
private var mRootGroup: Group? = null
|
||||
private var mCurrentGroup: Group? = null
|
||||
@@ -135,7 +135,6 @@ class GroupActivity : LockingActivity(),
|
||||
searchTitleView = findViewById(R.id.search_title)
|
||||
groupNameView = findViewById(R.id.group_name)
|
||||
toolbarAction = findViewById(R.id.toolbar_action)
|
||||
modeTitleView = findViewById(R.id.mode_title_view)
|
||||
lockView = findViewById(R.id.lock_button)
|
||||
|
||||
lockView?.setOnClickListener {
|
||||
@@ -285,7 +284,7 @@ class GroupActivity : LockingActivity(),
|
||||
|
||||
intent?.let { intentNotNull ->
|
||||
// To transform KEY_SEARCH_INFO in ACTION_SEARCH
|
||||
manageSearchInfoIntent(intent)
|
||||
manageSearchInfoIntent(intentNotNull)
|
||||
Log.d(TAG, "setNewIntent: $intentNotNull")
|
||||
setIntent(intentNotNull)
|
||||
mCurrentGroupIsASearch = if (Intent.ACTION_SEARCH == intentNotNull.action) {
|
||||
@@ -305,11 +304,10 @@ class GroupActivity : LockingActivity(),
|
||||
private fun manageSearchInfoIntent(intent: Intent): Boolean {
|
||||
// To relaunch the activity as ACTION_SEARCH
|
||||
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
|
||||
if (searchInfo != null) {
|
||||
val autoSearch = intent.getBooleanExtra(AUTO_SEARCH_KEY, false)
|
||||
if (searchInfo != null && autoSearch) {
|
||||
intent.action = Intent.ACTION_SEARCH
|
||||
val searchQuery = searchInfo.webDomain ?: searchInfo.applicationId
|
||||
intent.removeExtra(KEY_SEARCH_INFO)
|
||||
intent.putExtra(SearchManager.QUERY, searchQuery)
|
||||
intent.putExtra(SearchManager.QUERY, searchInfo.getSearchString(this))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -354,6 +352,9 @@ class GroupActivity : LockingActivity(),
|
||||
fragmentTransaction.addToBackStack(fragmentTag)
|
||||
fragmentTransaction.commit()
|
||||
|
||||
if (mSelectionMode)
|
||||
mSelectionModeCountBackStack++
|
||||
|
||||
// Update last access time.
|
||||
group?.touch(modified = false, touchParents = false)
|
||||
|
||||
@@ -460,13 +461,6 @@ class GroupActivity : LockingActivity(),
|
||||
// Assign number of children
|
||||
refreshNumberOfChildren()
|
||||
|
||||
// Show selection mode message if needed
|
||||
if (mSelectionMode) {
|
||||
modeTitleView?.visibility = View.VISIBLE
|
||||
} else {
|
||||
modeTitleView?.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Show button if allowed
|
||||
addNodeButtonView?.apply {
|
||||
|
||||
@@ -484,6 +478,20 @@ class GroupActivity : LockingActivity(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancelSpecialMode() {
|
||||
// To remove the navigation history and
|
||||
EntrySelectionHelper.removeEntrySelectionModeFromIntent(intent)
|
||||
val fragmentManager = supportFragmentManager
|
||||
if (mSelectionModeCountBackStack > 0) {
|
||||
for (selectionMode in 0 .. mSelectionModeCountBackStack) {
|
||||
fragmentManager.popBackStack()
|
||||
}
|
||||
}
|
||||
// Reinit the counter for navigation history
|
||||
mSelectionModeCountBackStack = 0
|
||||
backToTheAppCaller()
|
||||
}
|
||||
|
||||
private fun refreshNumberOfChildren() {
|
||||
numberChildrenView?.apply {
|
||||
if (PreferencesUtil.showNumberEntries(context)) {
|
||||
@@ -702,8 +710,7 @@ class GroupActivity : LockingActivity(),
|
||||
menu.findItem(R.id.menu_save_database)?.isVisible = false
|
||||
}
|
||||
if (!mSelectionMode) {
|
||||
inflater.inflate(R.menu.default_menu, menu)
|
||||
MenuUtil.contributionMenuInflater(inflater, menu)
|
||||
MenuUtil.defaultMenuInflater(inflater, menu)
|
||||
}
|
||||
|
||||
// Menu for recycle bin
|
||||
@@ -912,19 +919,16 @@ class GroupActivity : LockingActivity(),
|
||||
}
|
||||
|
||||
override fun startActivity(intent: Intent) {
|
||||
|
||||
// Get the intent, verify the action and get the query
|
||||
if (Intent.ACTION_SEARCH == intent.action) {
|
||||
// manually launch the real search activity
|
||||
val searchIntent = Intent(applicationContext, GroupActivity::class.java).apply {
|
||||
// Add bundle of current intent
|
||||
putExtras(this@GroupActivity.intent)
|
||||
// manually launch the same search activity
|
||||
val searchIntent = getIntent().apply {
|
||||
// add query to the Intent Extras
|
||||
action = Intent.ACTION_SEARCH
|
||||
putExtra(SearchManager.QUERY, intent.getStringExtra(SearchManager.QUERY))
|
||||
}
|
||||
|
||||
super.startActivity(searchIntent)
|
||||
setIntent(searchIntent)
|
||||
onNewIntent(searchIntent)
|
||||
} else {
|
||||
super.startActivity(intent)
|
||||
}
|
||||
@@ -971,26 +975,38 @@ class GroupActivity : LockingActivity(),
|
||||
assignGroupViewElements()
|
||||
}
|
||||
|
||||
private fun backToTheAppCaller() {
|
||||
if (mAutofillSelection) {
|
||||
// To get the app caller, only for autofill
|
||||
super.onBackPressed()
|
||||
} else {
|
||||
// To move the app in background
|
||||
moveTaskToBack(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (mListNodesFragment?.nodeActionSelectionMode == true) {
|
||||
finishNodeAction()
|
||||
} else {
|
||||
// Normal way when we are not in root
|
||||
if (mRootGroup != null && mRootGroup != mCurrentGroup)
|
||||
if (mRootGroup != null && mRootGroup != mCurrentGroup) {
|
||||
super.onBackPressed()
|
||||
// Else lock if needed
|
||||
rebuildListNodes()
|
||||
}
|
||||
// Else in root, lock if needed
|
||||
else {
|
||||
intent.removeExtra(AUTO_SEARCH_KEY)
|
||||
intent.removeExtra(KEY_SEARCH_INFO)
|
||||
if (PreferencesUtil.isLockDatabaseWhenBackButtonOnRootClicked(this)) {
|
||||
lockAndExit()
|
||||
super.onBackPressed()
|
||||
} else {
|
||||
// To restore standard mode
|
||||
EntrySelectionHelper.removeEntrySelectionModeFromIntent(intent)
|
||||
moveTaskToBack(true)
|
||||
backToTheAppCaller()
|
||||
}
|
||||
}
|
||||
|
||||
rebuildListNodes()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1003,6 +1019,7 @@ class GroupActivity : LockingActivity(),
|
||||
private const val LIST_NODES_FRAGMENT_TAG = "LIST_NODES_FRAGMENT_TAG"
|
||||
private const val SEARCH_FRAGMENT_TAG = "SEARCH_FRAGMENT_TAG"
|
||||
private const val OLD_GROUP_TO_UPDATE_KEY = "OLD_GROUP_TO_UPDATE_KEY"
|
||||
private const val AUTO_SEARCH_KEY = "AUTO_SEARCH_KEY"
|
||||
|
||||
private fun buildIntent(context: Context,
|
||||
group: Group?,
|
||||
@@ -1040,12 +1057,14 @@ class GroupActivity : LockingActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launch(context: Context,
|
||||
autoSearch: Boolean = false,
|
||||
searchInfo: SearchInfo? = null,
|
||||
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
|
||||
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
|
||||
searchInfo?.let {
|
||||
intent.putExtra(KEY_SEARCH_INFO, it)
|
||||
}
|
||||
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
@@ -1056,9 +1075,11 @@ class GroupActivity : LockingActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launchForEntrySelectionResult(context: Context,
|
||||
autoSearch: Boolean = false,
|
||||
searchInfo: SearchInfo? = null,
|
||||
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
|
||||
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
|
||||
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
|
||||
EntrySelectionHelper.startActivityForEntrySelectionResult(context, intent, searchInfo)
|
||||
}
|
||||
}
|
||||
@@ -1071,9 +1092,11 @@ class GroupActivity : LockingActivity(),
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
fun launchForAutofillResult(activity: Activity,
|
||||
assistStructure: AssistStructure,
|
||||
autoSearch: Boolean = false,
|
||||
searchInfo: SearchInfo? = null,
|
||||
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(activity)) {
|
||||
checkTimeAndBuildIntent(activity, null, readOnly) { intent ->
|
||||
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
|
||||
AutofillHelper.startActivityForAutofillResult(activity, intent, assistStructure, searchInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper.KEY_SEARCH_
|
||||
import com.kunzisoft.keepass.activities.helpers.OpenFileHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
import com.kunzisoft.keepass.activities.lock.LockingActivity
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
@@ -73,11 +73,10 @@ import com.kunzisoft.keepass.view.asError
|
||||
import kotlinx.android.synthetic.main.activity_password.*
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
open class PasswordActivity : StylishActivity() {
|
||||
open class PasswordActivity : SpecialModeActivity() {
|
||||
|
||||
// Views
|
||||
private var toolbar: Toolbar? = null
|
||||
private var containerView: View? = null
|
||||
private var filenameView: TextView? = null
|
||||
private var passwordView: EditText? = null
|
||||
private var keyFileSelectionView: KeyFileSelectionView? = null
|
||||
@@ -124,7 +123,6 @@ open class PasswordActivity : StylishActivity() {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
|
||||
containerView = findViewById(R.id.container)
|
||||
confirmButtonView = findViewById(R.id.activity_password_open_button)
|
||||
filenameView = findViewById(R.id.filename)
|
||||
passwordView = findViewById(R.id.password)
|
||||
@@ -265,9 +263,10 @@ open class PasswordActivity : StylishActivity() {
|
||||
EntrySelectionHelper.doEntrySelectionAction(intent,
|
||||
{
|
||||
GroupActivity.launch(this@PasswordActivity,
|
||||
true,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
// Remove the search info from intent
|
||||
// Finish activity if no search info
|
||||
if (searchInfo != null) {
|
||||
finish()
|
||||
}
|
||||
@@ -284,13 +283,16 @@ open class PasswordActivity : StylishActivity() {
|
||||
intent)
|
||||
} else {
|
||||
// Select the one we want
|
||||
GroupActivity.launchForEntrySelectionResult(this, searchInfo)
|
||||
GroupActivity.launchForEntrySelectionResult(this,
|
||||
true,
|
||||
searchInfo)
|
||||
}
|
||||
},
|
||||
{
|
||||
// Here no search info found
|
||||
// Here no search info found, disable auto search
|
||||
GroupActivity.launchForEntrySelectionResult(this@PasswordActivity,
|
||||
null,
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
},
|
||||
{
|
||||
@@ -311,10 +313,11 @@ open class PasswordActivity : StylishActivity() {
|
||||
finish()
|
||||
},
|
||||
{
|
||||
// Here no search info found
|
||||
// Here no search info found, disable auto search
|
||||
GroupActivity.launchForAutofillResult(this@PasswordActivity,
|
||||
assistStructure,
|
||||
null,
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
},
|
||||
{
|
||||
@@ -337,6 +340,7 @@ open class PasswordActivity : StylishActivity() {
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
if (Database.getInstance().loaded) {
|
||||
launchGroupActivity()
|
||||
@@ -349,9 +353,6 @@ open class PasswordActivity : StylishActivity() {
|
||||
clearCredentialsViews()
|
||||
}
|
||||
|
||||
// For check shutdown
|
||||
super.onResume()
|
||||
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
|
||||
// Don't allow auto open prompt if lock become when UI visible
|
||||
@@ -624,14 +625,15 @@ open class PasswordActivity : StylishActivity() {
|
||||
val inflater = menuInflater
|
||||
// Read menu
|
||||
inflater.inflate(R.menu.open_file, menu)
|
||||
|
||||
if (mForceReadOnly) {
|
||||
if (mSelectionMode || mForceReadOnly) {
|
||||
menu.removeItem(R.id.menu_open_file_read_mode_key)
|
||||
} else {
|
||||
changeOpenFileReadIcon(menu.findItem(R.id.menu_open_file_read_mode_key))
|
||||
}
|
||||
|
||||
if (!mSelectionMode) {
|
||||
MenuUtil.defaultMenuInflater(inflater, menu)
|
||||
}
|
||||
|
||||
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// biometric menu
|
||||
@@ -779,10 +781,13 @@ open class PasswordActivity : StylishActivity() {
|
||||
if (!keyFileResult) {
|
||||
// this block if not a key file response
|
||||
when (resultCode) {
|
||||
LockingActivity.RESULT_EXIT_LOCK, Activity.RESULT_CANCELED -> {
|
||||
LockingActivity.RESULT_EXIT_LOCK -> {
|
||||
clearCredentialsViews()
|
||||
Database.getInstance().closeAndClear(applicationContext.filesDir)
|
||||
}
|
||||
Activity.RESULT_CANCELED -> {
|
||||
clearCredentialsViews()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@ import android.widget.BaseAdapter
|
||||
import android.widget.GridView
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.widget.ImageViewCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
|
||||
import com.kunzisoft.keepass.icons.IconPack
|
||||
import com.kunzisoft.keepass.icons.IconPackChooser
|
||||
@@ -132,7 +132,7 @@ class IconPickerDialogFragment : DialogFragment() {
|
||||
return bundle.getParcelable(KEY_ICON_STANDARD)
|
||||
}
|
||||
|
||||
fun launch(activity: StylishActivity) {
|
||||
fun launch(activity: AppCompatActivity) {
|
||||
// Create an instance of the dialog fragment and show it
|
||||
val dialog = IconPickerDialogFragment()
|
||||
dialog.show(activity.supportFragmentManager, "IconPickerDialogFragment")
|
||||
|
||||
@@ -24,16 +24,15 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.*
|
||||
|
||||
abstract class LockingActivity : StylishActivity() {
|
||||
abstract class LockingActivity : SpecialModeActivity() {
|
||||
|
||||
protected var mTimeoutEnable: Boolean = true
|
||||
|
||||
@@ -49,7 +48,6 @@ abstract class LockingActivity : StylishActivity() {
|
||||
mReadOnlyToSave = value
|
||||
}
|
||||
private var mReadOnlyToSave: Boolean = false
|
||||
protected var mSelectionMode: Boolean = false
|
||||
protected var mAutoSaveEnable: Boolean = true
|
||||
|
||||
var mProgressDialogThread: ProgressDialogThread? = null
|
||||
@@ -100,7 +98,6 @@ abstract class LockingActivity : StylishActivity() {
|
||||
|
||||
// To refresh when back to normal workflow from selection workflow
|
||||
mReadOnlyToSave = ReadOnlyHelper.retrieveReadOnlyFromIntent(intent)
|
||||
mSelectionMode = EntrySelectionHelper.retrieveEntrySelectionModeFromIntent(intent)
|
||||
mAutoSaveEnable = PreferencesUtil.isAutoSaveDatabaseEnabled(this)
|
||||
|
||||
invalidateOptionsMenu()
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.kunzisoft.keepass.activities.selection
|
||||
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.view.SpecialModeView
|
||||
|
||||
/**
|
||||
* Activity to manage special mode (ie: selection mode)
|
||||
*/
|
||||
abstract class SpecialModeActivity : StylishActivity() {
|
||||
|
||||
protected var mSelectionMode: Boolean = false
|
||||
|
||||
protected var mAutofillSelection: Boolean = false
|
||||
|
||||
private var specialModeView: SpecialModeView? = null
|
||||
|
||||
open fun onCancelSpecialMode() {
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
mSelectionMode = EntrySelectionHelper.retrieveEntrySelectionModeFromIntent(intent)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
mAutofillSelection = AutofillHelper.retrieveAssistStructure(intent) != null
|
||||
}
|
||||
|
||||
val searchInfo: SearchInfo? = intent.getParcelableExtra(EntrySelectionHelper.KEY_SEARCH_INFO)
|
||||
|
||||
// To show the selection mode
|
||||
specialModeView = findViewById(R.id.special_mode_view)
|
||||
specialModeView?.apply {
|
||||
// Populate title
|
||||
val typeModeId = if (mAutofillSelection)
|
||||
R.string.autofill
|
||||
else
|
||||
R.string.magic_keyboard_title
|
||||
title = "${resources.getString(R.string.selection_mode)} (${getString(typeModeId)})"
|
||||
// Populate subtitle
|
||||
subtitle = searchInfo?.getName(resources)
|
||||
|
||||
// Show the toolbar or not
|
||||
visible = mSelectionMode
|
||||
|
||||
// Add back listener
|
||||
onCancelButtonClickListener = View.OnClickListener {
|
||||
onCancelSpecialMode()
|
||||
}
|
||||
|
||||
// Create menu
|
||||
menu.clear()
|
||||
if (mAutofillSelection) {
|
||||
menuInflater.inflate(R.menu.autofill, menu)
|
||||
setOnMenuItemClickListener { menuItem ->
|
||||
when (menuItem.itemId) {
|
||||
R.id.menu_block_autofill -> {
|
||||
blockAutofill(searchInfo)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun blockAutofill(searchInfo: SearchInfo?) {
|
||||
val webDomain = searchInfo?.webDomain
|
||||
val applicationId = searchInfo?.applicationId
|
||||
if (webDomain != null) {
|
||||
PreferencesUtil.addWebDomainToBlocklist(this,
|
||||
webDomain)
|
||||
} else if (applicationId != null) {
|
||||
PreferencesUtil.addApplicationIdToBlocklist(this,
|
||||
applicationId)
|
||||
}
|
||||
onCancelSpecialMode()
|
||||
Toast.makeText(this.applicationContext,
|
||||
R.string.autofill_block_restart,
|
||||
Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
@@ -119,6 +119,9 @@ object AutofillHelper {
|
||||
* Build the Autofill response for many entry
|
||||
*/
|
||||
fun buildResponse(activity: Activity, entriesInfo: List<EntryInfo>) {
|
||||
if (entriesInfo.isEmpty()) {
|
||||
activity.setResult(Activity.RESULT_CANCELED)
|
||||
} else {
|
||||
var setResultOk = false
|
||||
activity.intent?.extras?.let { extras ->
|
||||
if (extras.containsKey(ASSIST_STRUCTURE)) {
|
||||
@@ -145,6 +148,7 @@ object AutofillHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to start an activity with an Autofill for result
|
||||
|
||||
@@ -30,10 +30,21 @@ import com.kunzisoft.keepass.activities.AutofillLauncherActivity
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
class KeeAutofillService : AutofillService() {
|
||||
|
||||
var applicationIdBlocklist: Set<String>? = null
|
||||
var webDomainBlocklist: Set<String>? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
applicationIdBlocklist = PreferencesUtil.applicationIdBlocklist(this)
|
||||
webDomainBlocklist = PreferencesUtil.webDomainBlocklist(this)
|
||||
}
|
||||
|
||||
override fun onFillRequest(request: FillRequest,
|
||||
cancellationSignal: CancellationSignal,
|
||||
callback: FillCallback) {
|
||||
@@ -45,6 +56,9 @@ class KeeAutofillService : AutofillService() {
|
||||
// Check user's settings for authenticating Responses and Datasets.
|
||||
StructureParser(latestStructure).parse()?.let { parseResult ->
|
||||
|
||||
// Build search info only if applicationId or webDomain are not blocked
|
||||
if (searchAllowedFor(parseResult.applicationId, applicationIdBlocklist)
|
||||
&& searchAllowedFor(parseResult.domain, webDomainBlocklist)) {
|
||||
val searchInfo = SearchInfo().apply {
|
||||
applicationId = parseResult.applicationId
|
||||
webDomain = parseResult.domain
|
||||
@@ -73,6 +87,7 @@ class KeeAutofillService : AutofillService() {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showUIForEntrySelection(parseResult: StructureParser.Result,
|
||||
searchInfo: SearchInfo,
|
||||
@@ -116,5 +131,18 @@ class KeeAutofillService : AutofillService() {
|
||||
|
||||
companion object {
|
||||
private val TAG = KeeAutofillService::class.java.name
|
||||
|
||||
fun searchAllowedFor(element: String?, blockList: Set<String>?): Boolean {
|
||||
element?.let { elementNotNull ->
|
||||
if (blockList?.any { appIdBlocked ->
|
||||
elementNotNull.contains(appIdBlocked)
|
||||
} == true
|
||||
) {
|
||||
Log.d(TAG, "Autofill not allowed for $elementNotNull")
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,44 +163,78 @@ internal class StructureParser(private val structure: AssistStructure) {
|
||||
return false
|
||||
}
|
||||
|
||||
private fun inputIsVariationType(inputType: Int, vararg type: Int): Boolean {
|
||||
type.forEach {
|
||||
if (inputType and InputType.TYPE_MASK_VARIATION == it)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun showHexInputType(inputType: Int): String {
|
||||
return "0x${"%08x".format(inputType)}"
|
||||
}
|
||||
|
||||
private fun parseNodeByAndroidInput(node: AssistStructure.ViewNode): Boolean {
|
||||
val autofillId = node.autofillId
|
||||
val inputType = node.inputType
|
||||
if (inputType and InputType.TYPE_CLASS_TEXT != 0) {
|
||||
when (inputType and InputType.TYPE_MASK_CLASS) {
|
||||
InputType.TYPE_CLASS_TEXT -> {
|
||||
when {
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS != 0 -> {
|
||||
inputIsVariationType(inputType,
|
||||
InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS,
|
||||
InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS) -> {
|
||||
result?.usernameId = autofillId
|
||||
Log.d(TAG, "Autofill username android type: $inputType")
|
||||
Log.d(TAG, "Autofill username android text type: ${showHexInputType(inputType)}")
|
||||
}
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_NORMAL != 0 ||
|
||||
inputType and InputType.TYPE_NUMBER_VARIATION_NORMAL != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_PERSON_NAME != 0 -> {
|
||||
inputIsVariationType(inputType,
|
||||
InputType.TYPE_TEXT_VARIATION_NORMAL,
|
||||
InputType.TYPE_TEXT_VARIATION_PERSON_NAME,
|
||||
InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) -> {
|
||||
usernameCandidate = autofillId
|
||||
Log.d(TAG, "Autofill username candidate android type: $inputType")
|
||||
Log.d(TAG, "Autofill username candidate android text type: ${showHexInputType(inputType)}")
|
||||
}
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_PASSWORD != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD != 0 ||
|
||||
inputType and InputType.TYPE_NUMBER_VARIATION_PASSWORD != 0 -> {
|
||||
inputIsVariationType(inputType,
|
||||
InputType.TYPE_TEXT_VARIATION_PASSWORD,
|
||||
InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD,
|
||||
InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD) -> {
|
||||
result?.passwordId = autofillId
|
||||
Log.d(TAG, "Autofill password android type: $inputType")
|
||||
// Username not needed in this case
|
||||
Log.d(TAG, "Autofill password android text type: ${showHexInputType(inputType)}")
|
||||
usernameNeeded = false
|
||||
return true
|
||||
}
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_FILTER != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_PHONETIC != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_URI != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != 0 ||
|
||||
inputType and InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD != 0 -> {
|
||||
inputIsVariationType(inputType,
|
||||
InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT,
|
||||
InputType.TYPE_TEXT_VARIATION_FILTER,
|
||||
InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE,
|
||||
InputType.TYPE_TEXT_VARIATION_PHONETIC,
|
||||
InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS,
|
||||
InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE,
|
||||
InputType.TYPE_TEXT_VARIATION_URI) -> {
|
||||
// Type not used
|
||||
}
|
||||
else -> {
|
||||
Log.d(TAG, "Autofill unknown android type: $inputType")
|
||||
Log.d(TAG, "Autofill unknown android text type: ${showHexInputType(inputType)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
InputType.TYPE_CLASS_NUMBER -> {
|
||||
when {
|
||||
inputIsVariationType(inputType,
|
||||
InputType.TYPE_NUMBER_VARIATION_NORMAL) -> {
|
||||
usernameCandidate = autofillId
|
||||
Log.d(TAG, "Autofill usernale candidate android number type: ${showHexInputType(inputType)}")
|
||||
}
|
||||
inputIsVariationType(inputType,
|
||||
InputType.TYPE_NUMBER_VARIATION_PASSWORD) -> {
|
||||
result?.passwordId = autofillId
|
||||
Log.d(TAG, "Autofill password android number type: ${showHexInputType(inputType)}")
|
||||
usernameNeeded = false
|
||||
return true
|
||||
}
|
||||
else -> {
|
||||
Log.d(TAG, "Autofill unknown android number type: ${showHexInputType(inputType)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,14 +404,9 @@ class Database {
|
||||
return mSearchHelper?.createVirtualGroupWithSearchResult(this, searchQuery, SearchParameters(), max)
|
||||
}
|
||||
|
||||
fun createVirtualGroupFromSearch(searchInfo: SearchInfo,
|
||||
fun createVirtualGroupFromSearchInfo(searchInfoString: String,
|
||||
max: Int = Integer.MAX_VALUE): Group? {
|
||||
val query = (if (searchInfo.webDomain != null)
|
||||
searchInfo.webDomain
|
||||
else
|
||||
searchInfo.applicationId)
|
||||
?: return null
|
||||
return mSearchHelper?.createVirtualGroupWithSearchResult(this, query, SearchParameters().apply {
|
||||
return mSearchHelper?.createVirtualGroupWithSearchResult(this, searchInfoString, SearchParameters().apply {
|
||||
searchInTitles = false
|
||||
searchInUserNames = false
|
||||
searchInPasswords = false
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.kunzisoft.keepass.database.search.iterator.EntrySearchStringIteratorK
|
||||
import com.kunzisoft.keepass.database.search.iterator.EntrySearchStringIteratorKDBX
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.model.getSearchString
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
|
||||
@@ -48,9 +49,13 @@ class SearchHelper(private val isOmitBackup: Boolean) {
|
||||
if (database.loaded && TimeoutHelper.checkTime(context)) {
|
||||
var searchWithoutUI = false
|
||||
if (PreferencesUtil.isAutofillAutoSearchEnable(context)
|
||||
&& searchInfo != null) {
|
||||
&& searchInfo != null
|
||||
&& !searchInfo.containsOnlyNullValues()) {
|
||||
// If search provide results
|
||||
database.createVirtualGroupFromSearch(searchInfo, SearchHelper.MAX_SEARCH_ENTRY)?.let { searchGroup ->
|
||||
database.createVirtualGroupFromSearchInfo(
|
||||
searchInfo.getSearchString(context),
|
||||
MAX_SEARCH_ENTRY
|
||||
)?.let { searchGroup ->
|
||||
if (searchGroup.getNumberOfChildEntries() > 0) {
|
||||
searchWithoutUI = true
|
||||
onItemsFound.invoke(
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
package com.kunzisoft.keepass.model
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.ObjectNameResource
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
|
||||
class SearchInfo : Parcelable {
|
||||
class SearchInfo : ObjectNameResource, Parcelable {
|
||||
|
||||
var applicationId: String? = null
|
||||
set(value) {
|
||||
field = when {
|
||||
value == null -> null
|
||||
Regex(APPLICATION_ID_REGEX).matches(value) -> value
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
var webDomain: String? = null
|
||||
set(value) {
|
||||
field = when {
|
||||
value == null -> null
|
||||
Regex(WEB_DOMAIN_REGEX).matches(value) -> value
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
constructor()
|
||||
|
||||
@@ -26,7 +45,40 @@ class SearchInfo : Parcelable {
|
||||
parcel.writeString(webDomain ?: "")
|
||||
}
|
||||
|
||||
override fun getName(resources: Resources): String {
|
||||
return toString()
|
||||
}
|
||||
|
||||
fun containsOnlyNullValues(): Boolean {
|
||||
return applicationId == null && webDomain == null
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as SearchInfo
|
||||
|
||||
if (applicationId != other.applicationId) return false
|
||||
if (webDomain != other.webDomain) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = applicationId?.hashCode() ?: 0
|
||||
result = 31 * result + (webDomain?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return webDomain ?: applicationId ?: ""
|
||||
}
|
||||
|
||||
companion object {
|
||||
// https://gist.github.com/rishabhmhjn/8663966
|
||||
const val APPLICATION_ID_REGEX = "^(?:[a-zA-Z]+(?:\\d*[a-zA-Z_]*)*)(?:\\.[a-zA-Z]+(?:\\d*[a-zA-Z_]*)*)+\$"
|
||||
const val WEB_DOMAIN_REGEX = "^(?!://)([a-zA-Z0-9-_]+\\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+\\.[a-zA-Z]{2,11}?\$"
|
||||
|
||||
@JvmField
|
||||
val CREATOR: Parcelable.Creator<SearchInfo> = object : Parcelable.Creator<SearchInfo> {
|
||||
@@ -40,3 +92,14 @@ class SearchInfo : Parcelable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun SearchInfo.getSearchString(context: Context): String {
|
||||
return run {
|
||||
if (!PreferencesUtil.searchSubdomains(context))
|
||||
UriUtil.getWebDomainWithoutSubDomain(webDomain)
|
||||
else
|
||||
webDomain
|
||||
}
|
||||
?: applicationId
|
||||
?: ""
|
||||
}
|
||||
@@ -151,6 +151,7 @@ class KeyboardEntryNotificationService : LockNotificationService() {
|
||||
|
||||
fun launchNotificationIfAllowed(context: Context, entry: EntryInfo, toast: Boolean) {
|
||||
|
||||
val containsURLToCopy = entry.url.isNotEmpty()
|
||||
val containsUsernameToCopy = entry.username.isNotEmpty()
|
||||
val containsPasswordToCopy = entry.password.isNotEmpty()
|
||||
val containsExtraFieldToCopy = entry.customFields.isNotEmpty()
|
||||
@@ -158,7 +159,7 @@ class KeyboardEntryNotificationService : LockNotificationService() {
|
||||
var startService = false
|
||||
val intent = Intent(context, KeyboardEntryNotificationService::class.java)
|
||||
|
||||
if (containsUsernameToCopy || containsPasswordToCopy || containsExtraFieldToCopy) {
|
||||
if (containsURLToCopy || containsUsernameToCopy || containsPasswordToCopy || containsExtraFieldToCopy) {
|
||||
if (toast) {
|
||||
Toast.makeText(context,
|
||||
context.getString(R.string.keyboard_notification_entry_content_title, entry.title),
|
||||
|
||||
@@ -23,9 +23,9 @@ import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||
|
||||
class AutofillSettingsActivity : StylishActivity() {
|
||||
class AutofillSettingsActivity : SpecialModeActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -20,9 +20,12 @@
|
||||
package com.kunzisoft.keepass.settings
|
||||
|
||||
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.AutofillBlocklistAppIdPreferenceDialogFragmentCompat
|
||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.AutofillBlocklistWebDomainPreferenceDialogFragmentCompat
|
||||
|
||||
class AutofillSettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
@@ -30,4 +33,34 @@ class AutofillSettingsFragment : PreferenceFragmentCompat() {
|
||||
// Load the preferences from an XML resource
|
||||
setPreferencesFromResource(R.xml.preferences_autofill, rootKey)
|
||||
}
|
||||
|
||||
override fun onDisplayPreferenceDialog(preference: Preference?) {
|
||||
var otherDialogFragment = false
|
||||
|
||||
var dialogFragment: DialogFragment? = null
|
||||
|
||||
when (preference?.key) {
|
||||
getString(R.string.autofill_application_id_blocklist_key) -> {
|
||||
dialogFragment = AutofillBlocklistAppIdPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||
}
|
||||
getString(R.string.autofill_web_domain_blocklist_key) -> {
|
||||
dialogFragment = AutofillBlocklistWebDomainPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||
}
|
||||
else -> otherDialogFragment = true
|
||||
}
|
||||
|
||||
if (dialogFragment != null) {
|
||||
dialogFragment.setTargetFragment(this, 0)
|
||||
dialogFragment.show(parentFragmentManager, TAG_AUTOFILL_PREF_FRAGMENT)
|
||||
}
|
||||
// Could not be handled here. Try with the super method.
|
||||
else if (otherDialogFragment) {
|
||||
super.onDisplayPreferenceDialog(preference)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val TAG_AUTOFILL_PREF_FRAGMENT = "TAG_AUTOFILL_PREF_FRAGMENT"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ import androidx.appcompat.widget.Toolbar
|
||||
import android.view.MenuItem
|
||||
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||
|
||||
class MagikeyboardSettingsActivity : StylishActivity() {
|
||||
class MagikeyboardSettingsActivity : SpecialModeActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
package com.kunzisoft.keepass.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.net.Uri
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.SortNodeEnum
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
@@ -97,6 +99,12 @@ object PreferencesUtil {
|
||||
context.resources.getBoolean(R.bool.auto_focus_search_default))
|
||||
}
|
||||
|
||||
fun searchSubdomains(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.subdomain_search_key),
|
||||
context.resources.getBoolean(R.bool.subdomain_search_default))
|
||||
}
|
||||
|
||||
fun showUsernamesListEntries(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.list_entries_show_username_key),
|
||||
@@ -366,4 +374,46 @@ object PreferencesUtil {
|
||||
return prefs.getBoolean(context.getString(R.string.autofill_auto_search_key),
|
||||
context.resources.getBoolean(R.bool.autofill_auto_search_default))
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the default Blocklist for application ID, including the current app
|
||||
*/
|
||||
fun getDefaultApplicationIdBlocklist(resources: Resources?): Set<String> {
|
||||
return resources?.getStringArray(R.array.autofill_application_id_blocklist_default)
|
||||
?.toMutableSet()?.apply {
|
||||
add(BuildConfig.APPLICATION_ID)
|
||||
} ?: emptySet()
|
||||
}
|
||||
|
||||
fun applicationIdBlocklist(context: Context): Set<String> {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getStringSet(context.getString(R.string.autofill_application_id_blocklist_key),
|
||||
getDefaultApplicationIdBlocklist(context.resources))
|
||||
?: emptySet()
|
||||
}
|
||||
|
||||
fun webDomainBlocklist(context: Context): Set<String> {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getStringSet(context.getString(R.string.autofill_web_domain_blocklist_key),
|
||||
context.resources.getStringArray(R.array.autofill_web_domain_blocklist_default).toMutableSet())
|
||||
?: emptySet()
|
||||
}
|
||||
|
||||
fun addApplicationIdToBlocklist(context: Context, applicationId: String) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val setItems: MutableSet<String> = applicationIdBlocklist(context).toMutableSet()
|
||||
setItems.add(applicationId)
|
||||
prefs.edit()
|
||||
.putStringSet(context.getString(R.string.autofill_application_id_blocklist_key), setItems)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun addWebDomainToBlocklist(context: Context, webDomain: String) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val setItems: MutableSet<String> = webDomainBlocklist(context).toMutableSet()
|
||||
setItems.add(webDomain)
|
||||
prefs.edit()
|
||||
.putStringSet(context.getString(R.string.autofill_web_domain_blocklist_key), setItems)
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.settings.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.preference.DialogPreference
|
||||
import com.kunzisoft.keepass.R
|
||||
|
||||
open class InputListPreference @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = R.attr.dialogPreferenceStyle,
|
||||
defStyleRes: Int = defStyleAttr)
|
||||
: DialogPreference(context, attrs, defStyleAttr, defStyleRes) {
|
||||
|
||||
override fun getDialogLayoutResource(): Int {
|
||||
return R.layout.pref_dialog_input_list
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2020 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
|
||||
class AutofillBlocklistAppIdPreferenceDialogFragmentCompat
|
||||
: AutofillBlocklistPreferenceDialogFragmentCompat() {
|
||||
|
||||
override fun buildSearchInfoFromString(searchInfoString: String): SearchInfo? {
|
||||
val newSearchInfo = searchInfoString
|
||||
// remove chars not allowed in application ID
|
||||
.replace(Regex("[^a-zA-Z0-9_.]+"), "")
|
||||
return SearchInfo().apply { this.applicationId = newSearchInfo }
|
||||
}
|
||||
|
||||
override fun getDefaultValues(): Set<String> {
|
||||
return PreferencesUtil.getDefaultApplicationIdBlocklist(this.resources)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(key: String): AutofillBlocklistAppIdPreferenceDialogFragmentCompat {
|
||||
val fragment = AutofillBlocklistAppIdPreferenceDialogFragmentCompat()
|
||||
val bundle = Bundle(1)
|
||||
bundle.putString(ARG_KEY, key)
|
||||
fragment.arguments = bundle
|
||||
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2020 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.AutofillBlocklistAdapter
|
||||
import java.util.*
|
||||
import kotlin.Comparator
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
abstract class AutofillBlocklistPreferenceDialogFragmentCompat
|
||||
: InputPreferenceDialogFragmentCompat(),
|
||||
AutofillBlocklistAdapter.ItemDeletedCallback<SearchInfo> {
|
||||
|
||||
private var persistedItems = TreeSet<SearchInfo>(
|
||||
Comparator { o1, o2 -> o1.toString().compareTo(o2.toString()) })
|
||||
|
||||
private var filterAdapter: AutofillBlocklistAdapter<SearchInfo>? = null
|
||||
|
||||
abstract fun buildSearchInfoFromString(searchInfoString: String): SearchInfo?
|
||||
|
||||
abstract fun getDefaultValues(): Set<String>
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// To get items for saved instance state
|
||||
savedInstanceState?.getParcelableArray(ITEMS_KEY)?.let {
|
||||
it.forEach { itemSaved ->
|
||||
(itemSaved as SearchInfo?)?.let { item ->
|
||||
persistedItems.add(item)
|
||||
}
|
||||
}
|
||||
} ?: run {
|
||||
// Or from preference
|
||||
preference.getPersistedStringSet(getDefaultValues()).forEach { searchInfoString ->
|
||||
addSearchInfo(searchInfoString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindDialogView(view: View) {
|
||||
super.onBindDialogView(view)
|
||||
|
||||
setOnInputTextEditorActionListener(TextView.OnEditorActionListener { _, actionId, _ ->
|
||||
when (actionId) {
|
||||
EditorInfo.IME_ACTION_DONE -> {
|
||||
if (inputText.isEmpty()) {
|
||||
onDialogClosed(true)
|
||||
dialog?.dismiss()
|
||||
true
|
||||
} else {
|
||||
addItemFromInputText()
|
||||
false
|
||||
}
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
})
|
||||
|
||||
val addItemButton = view.findViewById<View>(R.id.add_item_button)
|
||||
addItemButton?.setOnClickListener {
|
||||
addItemFromInputText()
|
||||
}
|
||||
|
||||
val recyclerView = view.findViewById<RecyclerView>(R.id.pref_dialog_list)
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
|
||||
activity?.let { activity ->
|
||||
filterAdapter = AutofillBlocklistAdapter(activity)
|
||||
filterAdapter?.setItemDeletedCallback(this)
|
||||
recyclerView.adapter = filterAdapter
|
||||
filterAdapter?.replaceItems(persistedItems.toList())
|
||||
}
|
||||
}
|
||||
|
||||
private fun addSearchInfo(searchInfoString: String): Boolean {
|
||||
val itemToAdd = buildSearchInfoFromString(searchInfoString)
|
||||
return if (itemToAdd != null && !itemToAdd.containsOnlyNullValues()) {
|
||||
persistedItems.add(itemToAdd)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun addItemFromInputText() {
|
||||
if (addSearchInfo(inputText)) {
|
||||
inputText = ""
|
||||
} else {
|
||||
setInputTextError(getString(R.string.error_string_type))
|
||||
}
|
||||
filterAdapter?.replaceItems(persistedItems.toList())
|
||||
}
|
||||
|
||||
override fun onItemDeleted(item: SearchInfo) {
|
||||
persistedItems.remove(item)
|
||||
filterAdapter?.replaceItems(persistedItems.toList())
|
||||
}
|
||||
|
||||
private fun getStringItems(): Set<String> {
|
||||
val setItems = HashSet<String>()
|
||||
persistedItems.forEach {
|
||||
it.getName(resources).let { item ->
|
||||
setItems.add(item)
|
||||
}
|
||||
}
|
||||
return setItems
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putParcelableArray(ITEMS_KEY, persistedItems.toTypedArray())
|
||||
}
|
||||
|
||||
override fun onDialogClosed(positiveResult: Boolean) {
|
||||
if (positiveResult) {
|
||||
preference.persistStringSet(getStringItems())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ITEMS_KEY = "ITEMS_KEY"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2020 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
|
||||
class AutofillBlocklistWebDomainPreferenceDialogFragmentCompat
|
||||
: AutofillBlocklistPreferenceDialogFragmentCompat() {
|
||||
|
||||
override fun buildSearchInfoFromString(searchInfoString: String): SearchInfo? {
|
||||
val newSearchInfo = searchInfoString
|
||||
// remove prefix https://
|
||||
.replace(Regex("^.*://"), "")
|
||||
// Remove suffix /login...
|
||||
.replace(Regex("/.*$"), "")
|
||||
return SearchInfo().apply { webDomain = newSearchInfo }
|
||||
}
|
||||
|
||||
override fun getDefaultValues(): Set<String> {
|
||||
return context?.resources
|
||||
?.getStringArray(R.array.autofill_web_domain_blocklist_default)
|
||||
?.toMutableSet()
|
||||
?: emptySet()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(key: String): AutofillBlocklistWebDomainPreferenceDialogFragmentCompat {
|
||||
val fragment = AutofillBlocklistWebDomainPreferenceDialogFragmentCompat()
|
||||
val bundle = Bundle(1)
|
||||
bundle.putString(ARG_KEY, key)
|
||||
fragment.arguments = bundle
|
||||
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,12 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.PreferenceDialogFragmentCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
|
||||
@@ -34,6 +36,8 @@ abstract class InputPreferenceDialogFragmentCompat : PreferenceDialogFragmentCom
|
||||
private var textExplanationView: TextView? = null
|
||||
private var switchElementView: CompoundButton? = null
|
||||
|
||||
private var mOnInputTextEditorActionListener: TextView.OnEditorActionListener? = null
|
||||
|
||||
var inputText: String
|
||||
get() = this.inputTextView?.text?.toString() ?: ""
|
||||
set(inputText) {
|
||||
@@ -43,6 +47,14 @@ abstract class InputPreferenceDialogFragmentCompat : PreferenceDialogFragmentCom
|
||||
}
|
||||
}
|
||||
|
||||
fun setInputTextError(error: CharSequence) {
|
||||
this.inputTextView?.error = error
|
||||
}
|
||||
|
||||
fun setOnInputTextEditorActionListener(onEditorActionListener: TextView.OnEditorActionListener) {
|
||||
this.mOnInputTextEditorActionListener = onEditorActionListener
|
||||
}
|
||||
|
||||
var explanationText: String?
|
||||
get() = textExplanationView?.text?.toString() ?: ""
|
||||
set(explanationText) {
|
||||
@@ -63,7 +75,8 @@ abstract class InputPreferenceDialogFragmentCompat : PreferenceDialogFragmentCom
|
||||
inputTextView = view.findViewById(R.id.input_text)
|
||||
inputTextView?.apply {
|
||||
imeOptions = EditorInfo.IME_ACTION_DONE
|
||||
setOnEditorActionListener { _, actionId, _ ->
|
||||
setOnEditorActionListener { v, actionId, event ->
|
||||
if (mOnInputTextEditorActionListener == null) {
|
||||
when (actionId) {
|
||||
EditorInfo.IME_ACTION_DONE -> {
|
||||
onDialogClosed(true)
|
||||
@@ -74,6 +87,10 @@ abstract class InputPreferenceDialogFragmentCompat : PreferenceDialogFragmentCom
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mOnInputTextEditorActionListener?.onEditorAction(v, actionId, event)
|
||||
?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
textExplanationView = view.findViewById(R.id.explanation_text)
|
||||
@@ -82,6 +99,20 @@ abstract class InputPreferenceDialogFragmentCompat : PreferenceDialogFragmentCom
|
||||
switchElementView?.visibility = View.GONE
|
||||
}
|
||||
|
||||
protected fun hideKeyboard(): Boolean {
|
||||
context?.let {
|
||||
ContextCompat.getSystemService(it, InputMethodManager::class.java)?.let { inputManager ->
|
||||
activity?.currentFocus?.let { focus ->
|
||||
val windowToken = focus.windowToken
|
||||
if (windowToken != null) {
|
||||
return inputManager.hideSoftInputFromWindow(windowToken, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun setInoutText(@StringRes inputTextId: Int) {
|
||||
inputText = getString(inputTextId)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2020 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.settings.preferencedialogfragment.adapter
|
||||
|
||||
import android.content.Context
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.utils.ObjectNameResource
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class AutofillBlocklistAdapter<T : ObjectNameResource>(private val context: Context)
|
||||
: RecyclerView.Adapter<AutofillBlocklistAdapter.BlocklistItemViewHolder>() {
|
||||
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
|
||||
val items: MutableList<T> = ArrayList()
|
||||
|
||||
private var itemDeletedCallback: ItemDeletedCallback<T>? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlocklistItemViewHolder {
|
||||
val view = inflater.inflate(R.layout.pref_dialog_list_removable_item, parent, false)
|
||||
return BlocklistItemViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BlocklistItemViewHolder, position: Int) {
|
||||
val item = this.items[position]
|
||||
holder.textItem.text = item.getName(context.resources)
|
||||
holder.deleteButton.setOnClickListener(OnItemDeleteClickListener(item))
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
fun replaceItems(items: List<T>) {
|
||||
this.items.clear()
|
||||
this.items.addAll(items)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private inner class OnItemDeleteClickListener(private val itemClicked: T) : View.OnClickListener {
|
||||
|
||||
override fun onClick(view: View) {
|
||||
itemDeletedCallback?.onItemDeleted(itemClicked)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
fun setItemDeletedCallback(itemDeletedCallback: ItemDeletedCallback<T>) {
|
||||
this.itemDeletedCallback = itemDeletedCallback
|
||||
}
|
||||
|
||||
interface ItemDeletedCallback<T> {
|
||||
fun onItemDeleted(item: T)
|
||||
}
|
||||
|
||||
class BlocklistItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
var textItem: TextView = itemView.findViewById(R.id.pref_dialog_list_text)
|
||||
var deleteButton: ImageView = itemView.findViewById(R.id.pref_dialog_list_delete_button)
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,19 @@ object UriUtil {
|
||||
null
|
||||
}
|
||||
|
||||
fun getWebDomainWithoutSubDomain(webDomain: String?): String? {
|
||||
webDomain?.split(".")?.let { domainArray ->
|
||||
if (domainArray.isEmpty()) {
|
||||
return ""
|
||||
}
|
||||
if (domainArray.size == 1) {
|
||||
return domainArray[0];
|
||||
}
|
||||
return domainArray[domainArray.size - 2] + "." + domainArray[domainArray.size - 1]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun decode(uri: String?): String {
|
||||
return Uri.decode(uri) ?: ""
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2020 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.kunzisoft.keepass.R
|
||||
|
||||
class SpecialModeView @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = androidx.appcompat.R.attr.toolbarStyle)
|
||||
: Toolbar(context, attrs, defStyle) {
|
||||
|
||||
init {
|
||||
setNavigationIcon(R.drawable.ic_close_white_24dp)
|
||||
title = resources.getString(R.string.selection_mode)
|
||||
}
|
||||
|
||||
var onCancelButtonClickListener: OnClickListener? = null
|
||||
set(value) {
|
||||
if (value != null)
|
||||
setNavigationOnClickListener(value)
|
||||
}
|
||||
|
||||
var visible: Boolean = false
|
||||
set(value) {
|
||||
visibility = if (value) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
field = value
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Replace font by monospace, must be called after seText()
|
||||
@@ -93,14 +92,17 @@ fun Toolbar.collapse(animate: Boolean = true) {
|
||||
}
|
||||
|
||||
fun Toolbar.expand(animate: Boolean = true) {
|
||||
visibility = View.VISIBLE
|
||||
val actionBarHeight = layoutParams.height
|
||||
layoutParams.height = 0
|
||||
val slideAnimator = ValueAnimator
|
||||
.ofInt(0, actionBarHeight)
|
||||
if (animate)
|
||||
slideAnimator.duration = 300L
|
||||
slideAnimator.addUpdateListener { animation ->
|
||||
layoutParams.height = animation.animatedValue as Int
|
||||
if (layoutParams.height >= 1) {
|
||||
visibility = View.VISIBLE
|
||||
}
|
||||
requestLayout()
|
||||
}
|
||||
AnimatorSet().apply {
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<corners
|
||||
android:radius="0dp" />
|
||||
<padding
|
||||
android:left="0dp"
|
||||
android:right="0dp"
|
||||
android:left="8dp"
|
||||
android:right="8dp"
|
||||
android:top="12dp"
|
||||
android:bottom="12dp"/>
|
||||
<solid android:color="?attr/colorAccent"/>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<corners
|
||||
android:radius="0dp" />
|
||||
<padding
|
||||
android:left="0dp"
|
||||
android:right="0dp"
|
||||
android:left="8dp"
|
||||
android:right="8dp"
|
||||
android:top="12dp"
|
||||
android:bottom="12dp"/>
|
||||
<solid android:color="@color/orange_light"/>
|
||||
@@ -17,8 +17,8 @@
|
||||
<corners
|
||||
android:radius="0dp" />
|
||||
<padding
|
||||
android:left="0dp"
|
||||
android:right="0dp"
|
||||
android:left="8dp"
|
||||
android:right="8dp"
|
||||
android:top="12dp"
|
||||
android:bottom="12dp"/>
|
||||
<solid android:color="@color/orange"/>
|
||||
|
||||
9
app/src/main/res/drawable/ic_block_white_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_block_white_24dp.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
|
||||
</vector>
|
||||
@@ -26,13 +26,22 @@
|
||||
android:importantForAutofill="noExcludeDescendants"
|
||||
tools:targetApi="o">
|
||||
|
||||
<com.kunzisoft.keepass.view.SpecialModeView
|
||||
android:id="@+id/special_mode_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="?attr/specialToolbarAppearance"
|
||||
app:titleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.Title"
|
||||
app:subtitleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.SubTitle"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/activity_file_selection_coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/background_repeat"
|
||||
android:backgroundTint="?android:attr/textColor"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/special_mode_view"
|
||||
app:layout_constraintBottom_toTopOf="@+id/file_selection_buttons_container">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
@@ -156,11 +165,18 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/database_buttons_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_gravity="top"
|
||||
app:layout_constraintBottom_toTopOf="@+id/open_keyfile_button"
|
||||
android:background="?attr/colorPrimaryDark"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/open_keyfile_button"
|
||||
@@ -191,11 +207,6 @@
|
||||
android:paddingEnd="24dp"
|
||||
android:text="@string/create_keepass_file"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_gravity="top"
|
||||
android:background="?attr/colorPrimaryDark"/>
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -17,18 +17,28 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<RelativeLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.kunzisoft.keepass.view.SpecialModeView
|
||||
android:id="@+id/special_mode_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="?attr/specialToolbarAppearance"
|
||||
app:titleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.Title"
|
||||
app:subtitleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.SubTitle"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/group_coordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_above="@+id/toolbar_action">
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/special_mode_view"
|
||||
app:layout_constraintBottom_toTopOf="@+id/toolbar_action">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar"
|
||||
@@ -124,15 +134,6 @@
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:layout_below="@+id/toolbar">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mode_title_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:background="?attr/colorAccent"
|
||||
android:textColor="?attr/textColorInverse"
|
||||
android:text="@string/selection_mode"/>
|
||||
<FrameLayout
|
||||
android:id="@+id/nodes_list_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
@@ -159,10 +160,10 @@
|
||||
android:id="@+id/toolbar_action"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:elevation="4dp"
|
||||
android:theme="?attr/toolbarBottomAppearance"
|
||||
android:theme="?attr/actionToolbarAppearance"
|
||||
android:background="?attr/colorAccent"
|
||||
tools:targetApi="lollipop" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -21,17 +21,24 @@
|
||||
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/container"
|
||||
android:importantForAutofill="noExcludeDescendants"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:targetApi="o">
|
||||
|
||||
<com.kunzisoft.keepass.view.SpecialModeView
|
||||
android:id="@+id/special_mode_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="?attr/specialToolbarAppearance"
|
||||
app:titleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.Title"
|
||||
app:subtitleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.SubTitle"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/activity_password_coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/special_mode_view"
|
||||
app:layout_constraintBottom_toTopOf="@+id/activity_password_info_container">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
@@ -155,7 +162,8 @@
|
||||
android:hint="@string/password"
|
||||
android:inputType="textPassword"
|
||||
android:importantForAccessibility="no"
|
||||
android:importantForAutofill="no"
|
||||
android:importantForAutofill="yes"
|
||||
android:autofillHints="password|"
|
||||
android:imeOptions="actionDone"
|
||||
android:maxLines="1"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
@@ -213,7 +221,7 @@
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingRight="24dp"
|
||||
style="@style/KeepassDXStyle.TextAppearance.TinyText"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Tiny"
|
||||
android:text="@string/warning_database_link_revoked"
|
||||
android:textColor="?attr/textColorInverse"
|
||||
android:background="?attr/colorAccent"
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:importantForAutofill="noExcludeDescendants"
|
||||
tools:targetApi="o">
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_view_master_password"
|
||||
@@ -63,7 +62,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword"
|
||||
android:importantForAccessibility="no"
|
||||
android:importantForAutofill="no"
|
||||
android:importantForAutofill="yes"
|
||||
android:autofillHints="newPassword"
|
||||
android:maxLines="1"
|
||||
android:hint="@string/hint_pass"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
@@ -81,7 +81,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword"
|
||||
android:importantForAccessibility="no"
|
||||
android:importantForAutofill="no"
|
||||
android:importantForAutofill="yes"
|
||||
android:autofillHints="newPassword"
|
||||
android:maxLines="1"
|
||||
android:hint="@string/hint_conf_pass"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
android:id="@+id/item_attachment_compression"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/KeepassDXStyle.TextAppearance.TinyText"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Tiny"
|
||||
android:firstBaselineToTopHeight="0dp"
|
||||
android:includeFontPadding="false"
|
||||
android:paddingStart="8dp"
|
||||
|
||||
88
app/src/main/res/layout/pref_dialog_input_list.xml
Normal file
88
app/src/main/res/layout/pref_dialog_input_list.xml
Normal file
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2020 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 <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<LinearLayout
|
||||
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/edit"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAutofill="noExcludeDescendants"
|
||||
tools:targetApi="o">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/explanation_text"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="8dp"
|
||||
style="@style/KeepassDXStyle.TextAppearance.SmallTitle"/>
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/switch_element"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="24dp"
|
||||
android:text="@string/enable"
|
||||
android:background="@drawable/background_button_small"
|
||||
android:textColor="?attr/textColorInverse"
|
||||
android:minHeight="48dp"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/add_item_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:orientation="horizontal">
|
||||
<EditText
|
||||
android:id="@+id/input_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/add_item_button"
|
||||
app:layout_constraintBottom_toBottomOf="@id/add_item_button"
|
||||
android:inputType="textUri"
|
||||
android:hint="@string/content_description_add_item"/>
|
||||
<ImageButton
|
||||
android:id="@+id/add_item_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:contentDescription="@string/content_description_add_item"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:src="@drawable/ic_add_white_24dp" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/pref_dialog_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/default_margin"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingRight="24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
43
app/src/main/res/layout/pref_dialog_list_removable_item.xml
Normal file
43
app/src/main/res/layout/pref_dialog_list_removable_item.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2019 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 <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/pref_dialog_list_container"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/pref_dialog_list_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintTop_toTopOf="@+id/pref_dialog_list_delete_button"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/pref_dialog_list_delete_button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/pref_dialog_list_delete_button"/>
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/pref_dialog_list_delete_button"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:src="@drawable/ic_content_delete_white_24dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
27
app/src/main/res/menu/autofill.xml
Normal file
27
app/src/main/res/menu/autofill.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2020 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 <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item android:id="@+id/menu_block_autofill"
|
||||
android:icon="@drawable/ic_block_white_24dp"
|
||||
android:title="@string/autofill_block"
|
||||
android:orderInCategory="1"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
||||
@@ -117,13 +117,14 @@
|
||||
<string name="app_timeout">مهلة التطبيق</string>
|
||||
<string name="app_timeout_summary">مدة الانتظار قبل إقفال قاعدة البيانات</string>
|
||||
<string name="file_manager_install_description">تصفَّح الملفات بتثبيت مدير الملفات OpenIntents</string>
|
||||
<string name="clipboard_error">بعض هواتف سامسونغ لا تسمح للتطبيقات باستعمال الحافظة.</string>
|
||||
<string name="clipboard_error">بعض الأجهزة لا تسمح للتطبيقات باستعمال الحافظة.</string>
|
||||
<string name="clipboard_timeout">مهلة الحافظة</string>
|
||||
<string name="clipboard_timeout_summary">مدة التخزين في الحافظة</string>
|
||||
<string name="select_to_copy">اختر لنسخ %1$s إلى الحافظة</string>
|
||||
<string name="retrieving_db_key">يجلب مفتاح قاعدة البيانات…</string>
|
||||
<string name="default_checkbox">استخدامها كقاعدة بيانات افتراضية</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d د كونزيسوفت تأتي مع الضمان لا على الإطلاق؛ هذا هو البرمجيات الحرة، وكنت أهلا إعادة توزيعه تحت شروط إصدار الترخيص 3 أو في وقت لاحق.</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d كونزيسوفت <strong>مفتوح المصدر</strong> و <strong>بدون اعلانات</strong>.
|
||||
\n يوزع كما هو، بدون ضمان, تحت ترخيص <strong>GPLv3</strong></string>
|
||||
<string name="entry_accessed">نُفذ إليه</string>
|
||||
<string name="entry_expires">تنتهي صلاحيته في</string>
|
||||
<string name="entry_keyfile">ملف المفتاح</string>
|
||||
@@ -276,4 +277,12 @@
|
||||
<string name="content_description_keyboard_close_fields">أغلق الحقول</string>
|
||||
<string name="error_create_database_file">لا يمكن انشاء قاعدة بيانات بكلمة السر وملف المفتاح الحاليين.</string>
|
||||
<string name="menu_advanced_unlock_settings">إلغاء القفل المتقدم</string>
|
||||
<string name="entry_attachments">مرفقات</string>
|
||||
<string name="entry_history">السجل</string>
|
||||
<string name="entry_add_attachment">أضف مرفقا</string>
|
||||
<string name="discard">إلغاء</string>
|
||||
<string name="discard_changes">تجاهل التغييرات؟</string>
|
||||
<string name="validate">تأكيد</string>
|
||||
<string name="security">الأمان</string>
|
||||
<string name="master_key">المفتاح الرئيسي</string>
|
||||
</resources>
|
||||
@@ -17,9 +17,8 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
Catalan translation by Oriol Garrote
|
||||
-->
|
||||
<resources>
|
||||
<string name="feedback">Comentaris:</string>
|
||||
--><resources>
|
||||
<string name="feedback">Comentaris</string>
|
||||
<string name="homepage">Pàgina inici:</string>
|
||||
<string name="about_description">KeePassDX és una implementació per a Android de KeePass password manager</string>
|
||||
<string name="accept">Accepta</string>
|
||||
|
||||
@@ -344,7 +344,7 @@
|
||||
<string name="keyboard_selection_entry_title">Výběr položky</string>
|
||||
<string name="keyboard_selection_entry_summary">Při prohlížení záznamu ukázat na Magikeyboard pole položek</string>
|
||||
<string name="delete_entered_password_title">Smazat heslo</string>
|
||||
<string name="delete_entered_password_summary">Smaže heslo zadané po pokusu o připojení</string>
|
||||
<string name="delete_entered_password_summary">Smaže heslo zadané po pokusu o připojení k databázi</string>
|
||||
<string name="content_description_open_file">Otevři soubor</string>
|
||||
<string name="content_description_node_children">Potomci uzlu</string>
|
||||
<string name="content_description_add_node">Přidej uzel</string>
|
||||
@@ -476,4 +476,6 @@
|
||||
<string name="autofill_preference_title">Nastavení samovyplnění</string>
|
||||
<string name="warning_database_link_revoked">Přístup k souboru zrušenému správcem souborů</string>
|
||||
<string name="error_label_exists">Tento štítek již existuje.</string>
|
||||
<string name="keyboard_search_share_summary">Automaticky vyhledat sdílené informace pro naplnění klávesnice</string>
|
||||
<string name="keyboard_search_share_title">Prohledat sdílené info</string>
|
||||
</resources>
|
||||
@@ -193,11 +193,11 @@
|
||||
<string name="warning_empty_password">Bekræft brug af ingen adgangskode til beskyttelse mod oplåsning\?</string>
|
||||
<string name="warning_no_encryption_key">Fortsæt uden krypteringsnøgle\?</string>
|
||||
<string name="configure_biometric">Biometrisk prompt understøttes, men er ikke konfigureret.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Åbn den biometriske prompt for at låse databasen op</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Åbn biometriske forespørgsel for at låse databasen op</string>
|
||||
<string name="encrypted_value_stored">Krypteret adgangskode er gemt</string>
|
||||
<string name="biometric_invalid_key">Kan ikke læse den biometriske nøgle. Slet den og gentag den biometriske genkendelsesprocedure.</string>
|
||||
<string name="biometric_not_recognized">Kunne ikke genkende fingeraftryk</string>
|
||||
<string name="biometric_scanning_error">Problem med fingeraftryk: %1$s</string>
|
||||
<string name="biometric_not_recognized">Kunne ikke genkende biometrisk</string>
|
||||
<string name="biometric_scanning_error">Biometrisk fejl: %1$s</string>
|
||||
<string name="open_biometric_prompt_store_credential">Åbn den biometriske prompt for at gemme legitimationsoplysninger</string>
|
||||
<string name="no_credentials_stored">Databasen har endnu ikke en adgangskode.</string>
|
||||
<string name="database_history">Historik</string>
|
||||
@@ -220,11 +220,11 @@
|
||||
<string name="lock_database_screen_off_title">Skærmlås</string>
|
||||
<string name="lock_database_screen_off_summary">Lås databasen, når skærmen er slukket</string>
|
||||
<string name="advanced_unlock">Fingeraftryk</string>
|
||||
<string name="biometric_unlock_enable_title">Fingeraftryksscanning</string>
|
||||
<string name="biometric_unlock_enable_summary">Lader dig scanne din biometrisk for at åbne databasen</string>
|
||||
<string name="biometric_unlock_enable_title">Biometrisk oplåsning</string>
|
||||
<string name="biometric_unlock_enable_summary">Giver mulighed for at scanne biometriske for at åbne databasen</string>
|
||||
<string name="biometric_delete_all_key_title">Slet krypteringsnøgler</string>
|
||||
<string name="biometric_delete_all_key_summary">Slet alle krypteringsnøgler, der er relateret til fingeraftryk</string>
|
||||
<string name="biometric_delete_all_key_warning">Slet alle nøgler, der er relateret til fingeraftryksgenkendelse\?</string>
|
||||
<string name="biometric_delete_all_key_summary">Slet alle krypteringsnøgler, der er relateret til biometrisk genkendelse</string>
|
||||
<string name="biometric_delete_all_key_warning">Slet alle krypteringsnøgler, der er relateret til biometrisk genkendelse\?</string>
|
||||
<string name="unavailable_feature_text">Funktionen kunne ikke startes.</string>
|
||||
<string name="unavailable_feature_version">Android-version %1$s opfylder ikke minimum versionskrav %2$s.</string>
|
||||
<string name="unavailable_feature_hardware">Kunne ikke finde den tilsvarende hardware.</string>
|
||||
@@ -269,8 +269,8 @@
|
||||
\nGrupper (~mapper) organiserer poster i databasen.</string>
|
||||
<string name="education_search_title">Søg i poster</string>
|
||||
<string name="education_search_summary">Indtast titel, brugernavn eller indhold af andre felter for at hente adgangskoder.</string>
|
||||
<string name="education_biometric_title">Database oplåsning med fingeraftryk</string>
|
||||
<string name="education_biometric_summary">Link adgangskoden til det scannede fingeraftryk for hurtigt at låse databasen op.</string>
|
||||
<string name="education_biometric_title">Oplåsning af database ved hjælp af biometrisk</string>
|
||||
<string name="education_biometric_summary">Knyt adgangskoden til det scannede biometri for hurtigt at låse databasen op.</string>
|
||||
<string name="education_entry_edit_title">Rediger posten</string>
|
||||
<string name="education_entry_edit_summary">Rediger post med brugerdefinerede felter. Pool data kan refereres mellem forskellige indtastningsfelter.</string>
|
||||
<string name="education_generate_password_title">Opret en stærk adgangskode</string>
|
||||
@@ -343,7 +343,7 @@
|
||||
<string name="keyboard_selection_entry_title">Valg af indtastning</string>
|
||||
<string name="keyboard_selection_entry_summary">Vis indtastningsfelter i Magikeyboard, når der vises en post</string>
|
||||
<string name="delete_entered_password_title">Slet adgangskode</string>
|
||||
<string name="delete_entered_password_summary">Sletter adgangskoden som er indtastet efter et forbindelsesforsøg</string>
|
||||
<string name="delete_entered_password_summary">Sletter adgangskoden der er angivet efter et forsøg på at oprette forbindelse til en database</string>
|
||||
<string name="content_description_open_file">Åbn fil</string>
|
||||
<string name="content_description_node_children">Undernode</string>
|
||||
<string name="content_description_add_node">Tilføj knude</string>
|
||||
@@ -374,7 +374,7 @@
|
||||
<string name="biometric_prompt_extract_credential_message">Uddrag databasens legitimationsoplysninger med biometriske data</string>
|
||||
<string name="biometric">Biometrisk</string>
|
||||
<string name="biometric_auto_open_prompt_title">Åbn automatisk biometrisk prompt</string>
|
||||
<string name="biometric_auto_open_prompt_summary">Spørg automatisk efter biometrisk, hvis databasen er konfigureret til at bruge den</string>
|
||||
<string name="biometric_auto_open_prompt_summary">Spørg automatisk efter biometri, hvis databasen er konfigureret til at bruge den</string>
|
||||
<string name="enable">Aktiver</string>
|
||||
<string name="disable">Deaktiver</string>
|
||||
<string name="master_key">Hovednøgle</string>
|
||||
@@ -428,7 +428,7 @@
|
||||
<string name="command_execution">Udfører kommandoen…</string>
|
||||
<string name="warning_permanently_delete_nodes">Slet markerede noder permanent\?</string>
|
||||
<string name="keystore_not_accessible">Nøglelageret er ikke korrekt initialiseret.</string>
|
||||
<string name="credential_before_click_biometric_button">Skriv adgangskoden, før der klikkes på den biometriske knap.</string>
|
||||
<string name="credential_before_click_biometric_button">Indtast adgangskoden, og klik derefter på knappen \"Biometrisk\".</string>
|
||||
<string name="recycle_bin_group_title">Papirkurvsgruppe</string>
|
||||
<string name="enable_auto_save_database_title">Gem automatisk database</string>
|
||||
<string name="enable_auto_save_database_summary">Gem databasen efter hver en vigtig handling (i tilstanden \"Modificerbar\")</string>
|
||||
@@ -475,4 +475,6 @@
|
||||
<string name="autofill_preference_title">Indstillinger for automatisk udfyldning</string>
|
||||
<string name="warning_database_link_revoked">Adgang til filen tilbagekaldt af filadministratoren</string>
|
||||
<string name="error_label_exists">Etiketten findes allerede.</string>
|
||||
<string name="keyboard_search_share_summary">Søg automatisk efter delte oplysninger for at udfylde tastaturet</string>
|
||||
<string name="keyboard_search_share_title">Søg i delte oplysninger</string>
|
||||
</resources>
|
||||
@@ -357,7 +357,7 @@
|
||||
<string name="keyboard_selection_entry_title">Eintragsauswahl</string>
|
||||
<string name="keyboard_selection_entry_summary">Eingabefelder beim Betrachten eines Eintrags im Magikeyboard anzeigen</string>
|
||||
<string name="delete_entered_password_title">Passwort löschen</string>
|
||||
<string name="delete_entered_password_summary">Löscht das eingegebene Passwort nach einem Verbindungsversuch</string>
|
||||
<string name="delete_entered_password_summary">Löscht das eingegebene Passwort nach einem Verbindungsversuch zu einer Datenbank</string>
|
||||
<string name="content_description_open_file">Datei öffnen</string>
|
||||
<string name="content_description_add_entry">Eintrag hinzufügen</string>
|
||||
<string name="content_description_add_group">Gruppe hinzufügen</string>
|
||||
@@ -486,4 +486,6 @@
|
||||
<string name="autofill_preference_title">Autofill-Einstellungen</string>
|
||||
<string name="warning_database_link_revoked">Zugriff auf die Datei durch den Dateimanager widerrufen</string>
|
||||
<string name="error_label_exists">Diese Bezeichnung existiert bereits.</string>
|
||||
<string name="keyboard_search_share_summary">Automatische Suche nach gemeinsam genutzten Informationen zur Belegung der Tastatur</string>
|
||||
<string name="keyboard_search_share_title">Gemeinsame Infos durchsuchen</string>
|
||||
</resources>
|
||||
@@ -17,9 +17,8 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
Basque translation by David García-Abad
|
||||
-->
|
||||
<resources>
|
||||
<string name="feedback">Feedback:</string>
|
||||
--><resources>
|
||||
<string name="feedback">Feedback</string>
|
||||
<string name="homepage">Hasiera orria</string>
|
||||
<string name="about_description">Keepass pasahitza kudeatzailearen Androiderako inplementazioa</string>
|
||||
<string name="accept">Onartu</string>
|
||||
@@ -134,9 +133,7 @@
|
||||
<string name="unsupported_db_version">Euskarririk gabeko datubase bertsioa.</string>
|
||||
<string name="uppercase">Maiuskulak</string>
|
||||
<string name="version_label">Bertsioa %1$s</string>
|
||||
|
||||
<string name="education_unlock_summary">Sartu pasahitz eta / edo gako fitxategi bat zure datubasea desblokeatzeko.</string>
|
||||
|
||||
<string-array name="timeout_options">
|
||||
<item>5 segundu</item>
|
||||
<item>10 segundu</item>
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
--><resources>
|
||||
<string name="feedback">Palaute:</string>
|
||||
<string name="homepage">Kotisivu:</string>
|
||||
<string name="feedback">Palaute</string>
|
||||
<string name="homepage">Kotisivu</string>
|
||||
<string name="about_description">KeePass-salasanahallintaohjelman Android toteutus</string>
|
||||
<string name="accept">Hyväksy</string>
|
||||
<string name="add_entry">Lisää uusi salasanatietue</string>
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources>
|
||||
<string name="feedback">Comentarios:</string>
|
||||
<string name="homepage">Páxina inicial:</string>
|
||||
--><resources>
|
||||
<string name="feedback">Comentarios</string>
|
||||
<string name="homepage">Páxina inicial</string>
|
||||
<string name="about_description">KeePassDX é unha implementación para Android do xestor de contrasinais KeePass.</string>
|
||||
<string name="accept">Aceptar</string>
|
||||
<string name="add_entry">Engadir entrada</string>
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources>
|
||||
--><resources>
|
||||
<string name="about_description">Android implementacija KeePass upravitelja lozinki</string>
|
||||
<string name="accept">Prihvati</string>
|
||||
<string name="add_entry">Dodaj unos</string>
|
||||
@@ -273,7 +272,7 @@
|
||||
<string name="progress_title">Obrada…</string>
|
||||
<string name="read_only">Zaštićeno od pisanja</string>
|
||||
<string name="read_only_warning">Zavisno o vašem upravitelju datotekama, KeePassDX možda neće moći zapisivati u vašu pohranu.</string>
|
||||
<string name="contains_duplicate_uuid_procedure">Potvrdom ovog dialoga, KeePassDX će riješiti problem (generiranjem novih UUID-ova za duplikate) i nastaviti.</string>
|
||||
<string name="contains_duplicate_uuid_procedure">Riješi problem generiranjem novih UUID-ova za duplikate\?</string>
|
||||
<string name="root">Korijen</string>
|
||||
<string name="memory_usage_explanation">Količina memorije (u bajtovima) koju će koristiti funkcija izvedbe ključa.</string>
|
||||
<string name="do_not_kill_app">Ne zatvarajte aplikaciju…</string>
|
||||
@@ -341,4 +340,15 @@
|
||||
<string name="education_create_database_summary">Kreirajte svoju prvu datoteku za upravljanje lozinkama.</string>
|
||||
<string name="education_select_database_title">Otvaranje postojeće baze podataka</string>
|
||||
<string name="education_select_database_summary">Otvorite vašu prijašnju bazu podataka iz vašeg upravitelja datotekama kako bi je nastavili koristiti.</string>
|
||||
<string name="remember_database_locations_title">Zapamti lokaciju baze podataka</string>
|
||||
<string name="auto_focus_search_title">Brzo pretraživanje</string>
|
||||
<string name="error_create_database">Nije moguće kreirati datoteku baze podataka.</string>
|
||||
<string name="error_rounds_too_large">Prevelik broj \"transformacijskih rundi\". Postavljeno na 2147483648.</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft je <strong>open source</strong> te <strong>bez reklama</strong>.
|
||||
\nDostupan kakav je, pod <strong>GPLv3</strong> licencom, bez ikakvog jamstva.</string>
|
||||
<string name="entry_add_attachment">Dodaj privitak</string>
|
||||
<string name="discard">Odbaci</string>
|
||||
<string name="discard_changes">Odbaci promjene\?</string>
|
||||
<string name="contact">Kontakt</string>
|
||||
<string name="homepage">Početna stranica</string>
|
||||
</resources>
|
||||
@@ -16,13 +16,12 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources>
|
||||
--><resources>
|
||||
<string name="about_description">KeePassDX yra KeePass slaptažodžių tvarkyklės realizacija Android platformai</string>
|
||||
<string name="clipboard_cleared">Iškarpinė išvalyta.</string>
|
||||
<string name="invalid_credentials">Neteisingas slaptažodis arba rakto failas.</string>
|
||||
<string name="feedback">Atsiliepimai:</string>
|
||||
<string name="homepage">Pagrindinis puslapis:</string>
|
||||
<string name="feedback">Atsiliepimai</string>
|
||||
<string name="homepage">Pagrindinis puslapis</string>
|
||||
<string name="accept">Priimti</string>
|
||||
<string name="add_entry">Pridėti įrašą</string>
|
||||
<string name="add_group">Pridėti grupę</string>
|
||||
@@ -107,7 +106,5 @@
|
||||
<string name="hide_password_summary">Slėpti slaptažodžius pagal nutylėjimą</string>
|
||||
<string name="invalid_algorithm">Neteisingas algoritmas.</string>
|
||||
<string name="error_invalid_path">Neteisingas kelias.</string>
|
||||
|
||||
<string name="education_unlock_summary">Įveskite slaptažodį rba raktą, tam kad atidarytumėte duomenų bazę.</string>
|
||||
|
||||
</resources>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources>
|
||||
<string name="feedback">Atsauksmes:</string>
|
||||
<string name="homepage">Mājaslapa:</string>
|
||||
--><resources>
|
||||
<string name="feedback">Atsauksmes</string>
|
||||
<string name="homepage">Mājaslapa</string>
|
||||
<string name="about_description">KeePassDX ir KeePass paroļu menedžera Android implementācija</string>
|
||||
<string name="accept">Pieņemt</string>
|
||||
<string name="add_entry">Jauns ieraksts</string>
|
||||
@@ -131,9 +130,7 @@
|
||||
<string name="unsupported_db_version">Neatbalstīta datu bāzes versija.</string>
|
||||
<string name="uppercase">Lielie burti</string>
|
||||
<string name="version_label">Versija %1$s</string>
|
||||
|
||||
<string name="education_unlock_summary">Ievadiet paroli/atslēgas failu, lai atbloķētu savu datu bāzi.</string>
|
||||
|
||||
<string-array name="timeout_options">
|
||||
<item>5 sekundes</item>
|
||||
<item>10 sekundes</item>
|
||||
@@ -150,9 +147,9 @@
|
||||
<item>Vidējs</item>
|
||||
<item>Liels</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">Labot ierakstu</string>
|
||||
<string name="edit_entry">Labot ierakstu</string>
|
||||
<string name="encryption">Šifrēšana</string>
|
||||
<string name="extended_ASCII">Paplašinātais ASCII</string>
|
||||
<string name="allow">Atļaut</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft nāk bez jebkādas garantijas. Šī ir bezmaksas programmatūra un jūs to varat izplatīt apstākļos, kas aprakstīti GPL 3 versijā vai jaunākā.</string>
|
||||
</resources>
|
||||
</resources>
|
||||
@@ -222,7 +222,7 @@
|
||||
<string name="monospace_font_fields_enable_summary">Endre skriften brukt i felter for bedre tegngjengivelse</string>
|
||||
<string name="allow_copy_password_title">Kopi av passord</string>
|
||||
<string name="allow_copy_password_summary">Tillat kopiering av adgangspassordet og beskyttede felter til utklippstavlen</string>
|
||||
<string name="allow_copy_password_warning">ADVARSEL: Utklippstavlen deles av alle programmer. Hvis sensitiv data kopieres, kan annen programvare gjenopprette den.</string>
|
||||
<string name="allow_copy_password_warning">Advarsel: Utklippstavlen deles av alle programmer. Hvis sensitiv data kopieres, kan annen programvare gjenopprette den.</string>
|
||||
<string name="database_name_title">Databasenavn</string>
|
||||
<string name="database_description_title">Databasebeskrivelse</string>
|
||||
<string name="database_version_title">Databaseversjon</string>
|
||||
@@ -255,7 +255,7 @@
|
||||
<string name="education_biometric_summary">Lenk passordet og fingeravtrykket ditt for å låse opp databasen din enkelt.</string>
|
||||
<string name="education_entry_edit_title">Rediger oppføringen</string>
|
||||
<string name="education_entry_edit_summary">Rediger din oppføring med egendefinerte felter, referanser til pooldata kan legges til mellom felter av forskjellige oppføringer.</string>
|
||||
<string name="education_generate_password_title">Opprett et sterkt passord.</string>
|
||||
<string name="education_generate_password_title">Opprett et sterkt passord</string>
|
||||
<string name="education_generate_password_summary">Generer et sterkt passord å tilknytte oppføringen din, definer det i henhold til kriteriene i skjemaet, og ikke glem å gjøre passordet sikkert.</string>
|
||||
<string name="education_entry_new_field_title">Legg til egendefinerte felter</string>
|
||||
<string name="education_entry_new_field_summary">Du ønsker å registrere et grunnleggende felt som ikke allerede finnes, fyll inn et nytt et du også kan beskytte visuelt.</string>
|
||||
@@ -281,7 +281,7 @@
|
||||
<string name="html_text_ad_free">Ulikt mange passordbehandlingsprogrammer, er dette <strong>reklamefri</strong>, <strong>copyleftbasert fri programvare</strong> og samler ikke inn personlig data på tjenerne sine, selv i sin gratisversjon.</string>
|
||||
<string name="html_text_buy_pro">Ved kjøp av pro-versjonen, vil du få tilgang til denne <strong>visuelle funksjonen</strong> og du vil spesielt hjelpe <strong> realiseringen av gemenskapsprosjekter.</strong>
|
||||
</string>
|
||||
<string name="html_text_feature_generosity">Denne <strong>visuelle funksjonen</strong> er tilgjengelig takket være din generøsitet.</string>
|
||||
<string name="html_text_feature_generosity">Denne <strong>visuelle stilen</strong> er tilgjengelig takket være din generøsitet.</string>
|
||||
<string name="html_text_donation">For å beholde vår frihet og alltid være aktive, stoler vi på dine <strong>bidrag.</strong>
|
||||
</string>
|
||||
<string name="html_text_dev_feature">Denne funksjonen er <strong>under utvikling</strong> og krever <strong>bidrag</strong> for å bli tilgjengelig snart.</string>
|
||||
@@ -296,7 +296,7 @@
|
||||
<string name="encryption_rijndael">Rijndael (AES)</string>
|
||||
<string name="encryption_twofish">Twofish</string>
|
||||
<string name="encryption_chacha20">ChaCha20</string>
|
||||
<string name="kdf_AES">AES KDF</string>
|
||||
<string name="kdf_AES">AES</string>
|
||||
<string name="kdf_Argon2">Argon2</string>
|
||||
<string name="style_choose_title">Velg en drakt</string>
|
||||
<string name="style_choose_summary">Tilpass programdrakten ved å endre fargene</string>
|
||||
@@ -319,8 +319,8 @@
|
||||
<string name="keyboard_appearance_category">Utseende</string>
|
||||
<string name="keyboard_theme_title">Tastaturdrakt</string>
|
||||
<string name="keyboard_keys_category">Taster</string>
|
||||
<string name="keyboard_key_vibrate_title">Vibrer ved tastetrykk</string>
|
||||
<string name="keyboard_key_sound_title">Lyd ved tastetrykk</string>
|
||||
<string name="keyboard_key_vibrate_title">Vibrasjonstastetrykk</string>
|
||||
<string name="keyboard_key_sound_title">Hørbare tastetrykk</string>
|
||||
<string name="selection_mode">Valgmodus</string>
|
||||
<string name="do_not_kill_app">Ikke drep programmet…</string>
|
||||
<string name="lock_database_back_root_title">Tilbakelås</string>
|
||||
@@ -331,7 +331,7 @@
|
||||
<string name="keyboard_selection_entry_title">Oppføringsvalg</string>
|
||||
<string name="keyboard_selection_entry_summary">Vis inndatafelter i Magikeyboard når en oppføring vises</string>
|
||||
<string name="delete_entered_password_title">Slett passord</string>
|
||||
<string name="delete_entered_password_summary">Sletter passord innskrevet etter et tilkoblingsforsøk</string>
|
||||
<string name="delete_entered_password_summary">Sletter passord innskrevet etter et tilkoblingsforsøk til en database</string>
|
||||
<string name="content_description_open_file">Åpne fil</string>
|
||||
<string name="content_description_add_node">Legg til node</string>
|
||||
<string name="content_description_add_entry">Legg til oppføring</string>
|
||||
@@ -428,4 +428,9 @@
|
||||
<string name="lock_database_show_button_title">Vis låseknapp</string>
|
||||
<string name="error_label_exists">Denne etiketten finnes allerede.</string>
|
||||
<string name="validate">Bekreft</string>
|
||||
<string name="biometric_prompt_extract_credential_title">Åpne database med biometrisk gjenkjenning</string>
|
||||
<string name="warning_database_link_revoked">Tilgang til filen nektes av filbehandleren</string>
|
||||
<string name="warning_database_read_only">Innvilg skrivetilgang for å lagre databaseendringer</string>
|
||||
<string name="hide_broken_locations_summary">Skjul ødelagte lenker i listen over nylige databaser</string>
|
||||
<string name="hide_broken_locations_title">Skjul ødelagte databaselenker</string>
|
||||
</resources>
|
||||
@@ -21,7 +21,7 @@
|
||||
--><resources>
|
||||
<string name="feedback">Reacties</string>
|
||||
<string name="homepage">Website</string>
|
||||
<string name="about_description">Android-implementatie van de KeePass-wachtwoordbeheerder</string>
|
||||
<string name="about_description">Android-implementatie van KeePass-wachtwoordbeheer</string>
|
||||
<string name="accept">Accepteren</string>
|
||||
<string name="add_entry">Item toevoegen</string>
|
||||
<string name="add_group">Groep toevoegen</string>
|
||||
@@ -31,7 +31,7 @@
|
||||
<string name="application">App</string>
|
||||
<string name="menu_app_settings">App-instellingen</string>
|
||||
<string name="brackets">Haakjes</string>
|
||||
<string name="file_manager_install_description">Een bestandsbeheerder die de Intent-actie ACTION_CREATE_DOCUMENT en ACTION_OPEN_DOCUMENT accepteert, is nodig om databasebestanden te maken, te openen en op te slaan.</string>
|
||||
<string name="file_manager_install_description">Bestandsbeheer dat de Intent-actie ACTION_CREATE_DOCUMENT en ACTION_OPEN_DOCUMENT accepteert, is nodig om databasebestanden aan te maken, te openen en op te slaan.</string>
|
||||
<string name="clipboard_cleared">Klembord gewist</string>
|
||||
<string name="clipboard_timeout">Klembordtime-out</string>
|
||||
<string name="clipboard_timeout_summary">Tijd van opslag op het klembord</string>
|
||||
@@ -48,7 +48,7 @@
|
||||
<string name="entry_cancel">Annuleren</string>
|
||||
<string name="entry_notes">Opmerkingen</string>
|
||||
<string name="entry_confpassword">Wachtwoord bevestigen</string>
|
||||
<string name="entry_created">Gecreëerd op</string>
|
||||
<string name="entry_created">Aangemaakt</string>
|
||||
<string name="entry_expires">Verloopt op</string>
|
||||
<string name="entry_keyfile">Sleutelbestand</string>
|
||||
<string name="entry_modified">Bewerkt op</string>
|
||||
@@ -59,7 +59,7 @@
|
||||
<string name="entry_user_name">Gebruikersnaam</string>
|
||||
<string name="error_arc4">De Arcfour stream-versleuteling wordt niet ondersteund.</string>
|
||||
<string name="error_can_not_handle_uri">KeePassDX kan deze URI niet verwerken.</string>
|
||||
<string name="error_file_not_create">Kan bestand niet creëren:</string>
|
||||
<string name="error_file_not_create">Bestand is niet aangemaakt:</string>
|
||||
<string name="error_invalid_db">Kan database niet uitlezen.</string>
|
||||
<string name="error_invalid_path">Zorg ervoor dat het pad juist is.</string>
|
||||
<string name="error_no_name">Voer een naam in.</string>
|
||||
@@ -81,12 +81,12 @@
|
||||
<string name="invalid_credentials">Kan referenties niet lezen.</string>
|
||||
<string name="invalid_db_sig">Databaseformaat kan niet worden herkend.</string>
|
||||
<string name="length">Lengte</string>
|
||||
<string name="list_size_title">Lengte van itemlijst</string>
|
||||
<string name="list_size_summary">Tekstgrootte van itemlijst</string>
|
||||
<string name="list_size_title">Lengte van lijst met items</string>
|
||||
<string name="list_size_summary">Tekstgrootte in de lijst</string>
|
||||
<string name="loading_database">Database laden…</string>
|
||||
<string name="lowercase">Kleine letters</string>
|
||||
<string name="hide_password_title">Wachtwoord verbergen</string>
|
||||
<string name="hide_password_summary">Wachtwoorden standaard afschermen (***)</string>
|
||||
<string name="hide_password_title">Wachtwoorden verbergen</string>
|
||||
<string name="hide_password_summary">Wachtwoorden standaard verbergen (***)</string>
|
||||
<string name="about">Over</string>
|
||||
<string name="menu_change_key_settings">Hoofdsleutel wijzigen</string>
|
||||
<string name="settings">Instellingen</string>
|
||||
@@ -124,7 +124,7 @@
|
||||
<string name="unsupported_db_version">Niet-ondersteunde databaseversie.</string>
|
||||
<string name="uppercase">Hoofdletters</string>
|
||||
<string name="version_label">Versie %1$s</string>
|
||||
<string name="education_unlock_summary">Geef het wachtwoord en/of sleutelbestand op om je database te ontgrendelen.
|
||||
<string name="education_unlock_summary">Voer het wachtwoord en/of sleutelbestand in om je database te ontgrendelen.
|
||||
\n
|
||||
\nMaak na elke aanpassing een kopie van je .kdbx-bestand op een veilige locatie.</string>
|
||||
<string-array name="timeout_options">
|
||||
@@ -160,25 +160,25 @@
|
||||
<string name="error_move_folder_in_itself">Een groep kan niet naar zichzelf worden verplaatst.</string>
|
||||
<string name="field_name">Veldnaam</string>
|
||||
<string name="field_value">Veldwaarde</string>
|
||||
<string name="file_not_found_content">Bestand niet gevonden. Probeer opnieuw te openen via je bestandsbeheerder.</string>
|
||||
<string name="file_not_found_content">Bestand niet gevonden. Probeer opnieuw te openen via bestandsbeheer.</string>
|
||||
<string name="invalid_algorithm">Ongeldig algoritme.</string>
|
||||
<string name="keyfile_is_empty">Het sleutelbestand is leeg.</string>
|
||||
<string name="list_entries_show_username_title">Gebruikersnamen tonen</string>
|
||||
<string name="list_entries_show_username_summary">Gebruikersnamen tonen in itemlijsten</string>
|
||||
<string name="list_entries_show_username_summary">Gebruikersnamen tonen in lijsten</string>
|
||||
<string name="copy_field">Kopie van %1$s</string>
|
||||
<string name="menu_form_filling_settings">Formulierinvulling</string>
|
||||
<string name="menu_copy">Kopiëren</string>
|
||||
<string name="menu_move">Verplaatsen</string>
|
||||
<string name="menu_paste">Plakken</string>
|
||||
<string name="menu_cancel">Annuleren</string>
|
||||
<string name="menu_biometric_remove_key">Opgeslagen vingerafdruk verwijderen</string>
|
||||
<string name="menu_biometric_remove_key">Opgeslagen biometrische gegevens verwijderen</string>
|
||||
<string name="menu_file_selection_read_only">Alleen-lezen</string>
|
||||
<string name="menu_open_file_read_and_write">Lezen en schrijven</string>
|
||||
<string name="protection">Beveiliging</string>
|
||||
<string name="read_only">Alleen-lezen</string>
|
||||
<string name="read_only_warning">KeePassDX moet worden gemachtigd om je databank te kunnen aanpassen.</string>
|
||||
<string name="show_recent_files_title">Recente bestandgeschiedenis</string>
|
||||
<string name="show_recent_files_summary">Recent gebruikte bestandsnamen onthouden</string>
|
||||
<string name="show_recent_files_title">Bestandsgeschiedenis</string>
|
||||
<string name="show_recent_files_summary">Toon locaties van recente databases</string>
|
||||
<string name="encryption_explanation">Database-encryptie-algoritme dat voor alle gegevens wordt gebruikt.</string>
|
||||
<string name="kdf_explanation">Om de sleutel voor het algoritme te kunnen genereren, wordt de hoofdsleutel getransformeerd middels een willekeurige afleidingsfunctie.</string>
|
||||
<string name="memory_usage">Geheugengebruik</string>
|
||||
@@ -199,13 +199,13 @@
|
||||
<string name="warning_password_encoding">Vermijd wachtwoordtekens buiten het tekstcoderingsformaat in het databasebestand (niet-herkende tekens worden geconverteerd naar dezelfde letter).</string>
|
||||
<string name="warning_empty_password">Doorgaan zonder beveiliging voor wachtwoordontgrendeling\?</string>
|
||||
<string name="warning_no_encryption_key">Doorgaan zonder coderingssleutel\?</string>
|
||||
<string name="configure_biometric">Vingerafdruk wordt ondersteund, maar is niet ingesteld.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Open de biometrische prompt om de database te ontgrendelen</string>
|
||||
<string name="configure_biometric">Biometrische herkenning is ondersteund, maar niet ingesteld.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Biometrische herkenning gebruiken om de database te ontgrendelen</string>
|
||||
<string name="encrypted_value_stored">Versleuteld wachtwoord is opgeslagen</string>
|
||||
<string name="biometric_invalid_key">Kan de biometrische sleutel niet lezen. Verwijder deze en herhaal de procedure voor biometrische herkenning.</string>
|
||||
<string name="biometric_not_recognized">Vingerafdruk niet herkend</string>
|
||||
<string name="biometric_scanning_error">Vingerafdrukprobleem: %1$s</string>
|
||||
<string name="open_biometric_prompt_store_credential">Vingerafdruk gebruiken om dit wachtwoord op te slaan</string>
|
||||
<string name="biometric_invalid_key">Kan de biometrische gegevens niet lezen. Verwijder deze en herhaal de procedure voor biometrische herkenning.</string>
|
||||
<string name="biometric_not_recognized">Biometrie niet herkend</string>
|
||||
<string name="biometric_scanning_error">Probleem met biometrie: %1$s</string>
|
||||
<string name="open_biometric_prompt_store_credential">Biometrische herkenning gebruiken om wachtwoorden op te slaan</string>
|
||||
<string name="no_credentials_stored">Deze databank heeft nog geen wachtwoord.</string>
|
||||
<string name="database_history">Geschiedenis</string>
|
||||
<string name="menu_appearance_settings">Uiterlijk</string>
|
||||
@@ -213,12 +213,12 @@
|
||||
<string name="autofill">Auto-aanvullen</string>
|
||||
<string name="autofill_service_name">KeePassDX auto-aanvullendienst</string>
|
||||
<string name="autofill_sign_in_prompt">Inloggen met KeePassDX</string>
|
||||
<string name="set_autofill_service_title">Standaard aanvuldienst instellen</string>
|
||||
<string name="set_autofill_service_title">Dienst voor automatisch aanvullen</string>
|
||||
<string name="autofill_explanation_summary">Schakel de dienst in om formulieren in andere apps snel in te vullen</string>
|
||||
<string name="password_size_title">Gegenereerde wachtwoordlengte</string>
|
||||
<string name="password_size_summary">Standaardlengte van gegenereerd wachtwoord instellen</string>
|
||||
<string name="list_password_generator_options_title">Wachtwoordtekens</string>
|
||||
<string name="list_password_generator_options_summary">Standaard wachtwoordtekens instellen</string>
|
||||
<string name="list_password_generator_options_summary">Toegestane wachtwoordtekens instellen</string>
|
||||
<string name="clipboard">Klembord</string>
|
||||
<string name="clipboard_notifications_title">Klembordmeldingen</string>
|
||||
<string name="clipboard_notifications_summary">Schakel klembordmeldingen in om velden te kopiëren bij het bekijken van een item</string>
|
||||
@@ -226,11 +226,11 @@
|
||||
<string name="lock">Vergrendelen</string>
|
||||
<string name="lock_database_screen_off_title">Schermvergrendeling</string>
|
||||
<string name="lock_database_screen_off_summary">Database vergrendelen wanneer het scherm is uitgeschakeld</string>
|
||||
<string name="advanced_unlock">Vingerafdruk</string>
|
||||
<string name="biometric_unlock_enable_title">Vingerafdrukherkenning</string>
|
||||
<string name="biometric_unlock_enable_summary">Laat u uw biometrische gegevens scannen om de database te openen</string>
|
||||
<string name="biometric_delete_all_key_title">Sleutels voor versleuteling verwijderen</string>
|
||||
<string name="biometric_delete_all_key_summary">Alle aan vingerafdrukherkenning gerelateerde sleutels wilt verwijderen</string>
|
||||
<string name="advanced_unlock">Geavanceerd ontgrendelen</string>
|
||||
<string name="biometric_unlock_enable_title">Ontgrendelen met biometrie</string>
|
||||
<string name="biometric_unlock_enable_summary">Gebruik biometrische herkenning om de database te openen</string>
|
||||
<string name="biometric_delete_all_key_title">Coderingssleutels verwijderen</string>
|
||||
<string name="biometric_delete_all_key_summary">Alle sleutels voor biometrische herkenning verwijderen</string>
|
||||
<string name="biometric_delete_all_key_warning">Alle coderingssleutels voor biometrische herkenning verwijderen\?</string>
|
||||
<string name="unavailable_feature_text">Kan deze functie niet starten.</string>
|
||||
<string name="unavailable_feature_version">Je Android-versie, %1$s, voldoet niet aan de minimumvereiste %2$s.</string>
|
||||
@@ -257,15 +257,15 @@
|
||||
<string name="keyboard">Toetsenbord</string>
|
||||
<string name="magic_keyboard_title">Magikeyboard</string>
|
||||
<string name="magic_keyboard_explanation_summary">Aangepast toetsenbord met je wachtwoorden en alle identiteitsvelden activeren</string>
|
||||
<string name="allow_no_password_title">Geen hoofdwachtwoord toestaan</string>
|
||||
<string name="allow_no_password_title">Geen hoofdwachtwoord</string>
|
||||
<string name="allow_no_password_summary">Schakel de knop \"Openen\" in als er geen referenties zijn geselecteerd</string>
|
||||
<string name="enable_read_only_title">Alleen-lezen</string>
|
||||
<string name="enable_read_only_summary">Open de database standaard alleen-lezen</string>
|
||||
<string name="enable_education_screens_title">Educatieve hints</string>
|
||||
<string name="enable_education_screens_title">Informatieve tips</string>
|
||||
<string name="enable_education_screens_summary">Markeer elementen om te leren hoe de app werkt</string>
|
||||
<string name="reset_education_screens_title">Educatieve hints opnieuw instellen</string>
|
||||
<string name="reset_education_screens_summary">Educatieve informatie opnieuw weergeven</string>
|
||||
<string name="reset_education_screens_text">Educatieve hints opnieuw ingesteld</string>
|
||||
<string name="reset_education_screens_title">Informatieve tips opnieuw instellen</string>
|
||||
<string name="reset_education_screens_summary">Informatieve tips opnieuw weergeven</string>
|
||||
<string name="reset_education_screens_text">Informatieve tips opnieuw ingesteld</string>
|
||||
<string name="education_create_database_title">Maak je databasebestand aan</string>
|
||||
<string name="education_create_database_summary">Maak je eerste wachtwoordbeheerbestand aan.</string>
|
||||
<string name="education_select_database_title">Open een bestaande database</string>
|
||||
@@ -276,8 +276,8 @@
|
||||
\nGroepen (~mappen) organiseren de items in je database.</string>
|
||||
<string name="education_search_title">Doorzoek al je items</string>
|
||||
<string name="education_search_summary">Doorzoek items op titel, gebruikersnaam of andere velden om wachtwoorden te vinden.</string>
|
||||
<string name="education_biometric_title">Ontgrendel de database met biometrie</string>
|
||||
<string name="education_biometric_summary">Koppel je wachtwoord en vingerafdruk om de database snel te ontgrendelen.</string>
|
||||
<string name="education_biometric_title">Database-ontgrendeling met biometrie</string>
|
||||
<string name="education_biometric_summary">Koppel je wachtwoord aan je biometrie om de database snel te ontgrendelen.</string>
|
||||
<string name="education_entry_edit_title">Item bewerken</string>
|
||||
<string name="education_entry_edit_summary">Bewerk het item met aangepaste velden. Referenties kunnen worden toegevoegd tussen velden van verschillende items.</string>
|
||||
<string name="education_generate_password_title">Genereer een sterk wachtwoord</string>
|
||||
@@ -289,7 +289,6 @@
|
||||
<string name="education_read_only_summary">Wijzig de opstartmodus van de sessie.
|
||||
\n
|
||||
\nIn alleen-lezenmodus kunnen geen onbedoelde wijzigingen worden gemaakt.
|
||||
\n
|
||||
\nIn schrijfmodus kun je elementen toevoegen, verwijderen of aanpassen.</string>
|
||||
<string name="education_field_copy_title">Veld kopiëren toestaan</string>
|
||||
<string name="education_field_copy_summary">Kopieer een veld en plak de inhoud waar je maar wilt.
|
||||
@@ -304,8 +303,7 @@
|
||||
<string name="html_text_ad_free">In tegenstelling tot veel apps voor wachtwoordbeheer, is deze <strong> reclamevrij</strong>, <strong> vrije software </strong> en verzamelt het geen persoonlijke gegevens op haar servers, ongeacht welke versie je gebruikt.</string>
|
||||
<string name="html_text_buy_pro">Door de pro-versie te kopen krijg je toegang tot dit <strong>visuele thema</strong> en draag je bij aan het <strong>realiseren van gemeenschapsprojecten.</strong></string>
|
||||
<string name="html_text_feature_generosity">Dit <strong>visuele thema</strong> is beschikbaar gemaakt dankzij jouw vrijgevigheid.</string>
|
||||
<string name="html_text_donation">Om altijd vrij en actief te blijven, zijn we afhankelijk van jouw <strong>bijdrage.</strong>
|
||||
</string>
|
||||
<string name="html_text_donation">Om altijd vrij en actief te blijven, rekenen we op jouw <strong>bijdrage.</strong></string>
|
||||
<string name="html_text_dev_feature">Deze functie <strong>wordt momenteel ontwikkeld</strong> en kan alleen beschikbaar komen middels jouw <strong>bijdrage</strong>.</string>
|
||||
<string name="html_text_dev_feature_buy_pro">Door de <strong>pro</strong>-versie te kopen,</string>
|
||||
<string name="html_text_dev_feature_contibute">Door <strong>bij te dragen</strong>,</string>
|
||||
@@ -322,7 +320,7 @@
|
||||
<string name="style_choose_summary">Thema gebruikt in de app</string>
|
||||
<string name="icon_pack_choose_title">Icoonverzameling</string>
|
||||
<string name="icon_pack_choose_summary">Iconenverzameling gebruikt in de app</string>
|
||||
<string name="build_label">Bouw %1$s</string>
|
||||
<string name="build_label">Build %1$s</string>
|
||||
<string name="keyboard_name">Magikeyboard</string>
|
||||
<string name="keyboard_label">Magikeyboard (KeePassDX)</string>
|
||||
<string name="keyboard_setting_label">Instellingen Magikeyboard</string>
|
||||
@@ -343,7 +341,7 @@
|
||||
<string name="keyboard_key_sound_title">Geluid bij toetsaanslag</string>
|
||||
<string name="selection_mode">Selectiemodus</string>
|
||||
<string name="do_not_kill_app">App niet afsluiten…</string>
|
||||
<string name="lock_database_back_root_title">Druk op \'Terug\' om te vergrendelen</string>
|
||||
<string name="lock_database_back_root_title">Druk \'Terug\' om te vergrendelen</string>
|
||||
<string name="lock_database_back_root_summary">Vergrendel de database wanneer de gebruiker op de knop Terug in het hoofdscherm klikt</string>
|
||||
<string name="clear_clipboard_notification_title">Wissen bij afsluiten</string>
|
||||
<string name="clear_clipboard_notification_summary">Vergrendel de database wanneer u de melding sluit</string>
|
||||
@@ -351,7 +349,7 @@
|
||||
<string name="keyboard_selection_entry_title">Itemselectie</string>
|
||||
<string name="keyboard_selection_entry_summary">Invoervelden in Magikeyboard tonen bij het bekijken van een item</string>
|
||||
<string name="delete_entered_password_title">Wachtwoord wissen</string>
|
||||
<string name="delete_entered_password_summary">Wist het ingevoerde wachtwoord na een verbindingspoging</string>
|
||||
<string name="delete_entered_password_summary">Wis het ingevoerde wachtwoord na een poging met een database te verbinden</string>
|
||||
<string name="content_description_open_file">Bestand openen</string>
|
||||
<string name="content_description_node_children">Onderliggende items</string>
|
||||
<string name="content_description_add_node">Knooppunt toevoegen</string>
|
||||
@@ -369,20 +367,20 @@
|
||||
<string name="entry_UUID">UUID</string>
|
||||
<string name="error_move_entry_here">Je kan hier geen item plaatsen.</string>
|
||||
<string name="error_copy_entry_here">Je kan hier geen item kopiëren.</string>
|
||||
<string name="list_groups_show_number_entries_title">Het aantal items tonen</string>
|
||||
<string name="list_groups_show_number_entries_title">Toon het aantal items</string>
|
||||
<string name="list_groups_show_number_entries_summary">Toon het aantal items in een groep</string>
|
||||
<string name="content_description_background">Achtergrond</string>
|
||||
<string name="content_description_update_from_list">Update</string>
|
||||
<string name="content_description_keyboard_close_fields">Velden sluiten</string>
|
||||
<string name="error_create_database_file">Kan geen database maken met dit wachtwoord en dit sleutelbestand.</string>
|
||||
<string name="error_create_database_file">Kan geen database aanmaken met dit wachtwoord en sleutelbestand.</string>
|
||||
<string name="menu_advanced_unlock_settings">Geavanceerd ontgrendelen</string>
|
||||
<string name="biometric_prompt_store_credential_title">Biometrische herkenning opslaan</string>
|
||||
<string name="biometric_prompt_store_credential_message">Waarschuwing: Je moet nog steeds je hoofdwachtwoord onthouden als je biometrische herkenning gebruikt.</string>
|
||||
<string name="biometric_prompt_extract_credential_title">Database met biometrische herkenning openen</string>
|
||||
<string name="biometric_prompt_extract_credential_message">Database-referenties uitpakken met biometrische gegevens</string>
|
||||
<string name="biometric">Biometrisch</string>
|
||||
<string name="biometric_auto_open_prompt_title">Automatisch biometrische prompt openen</string>
|
||||
<string name="biometric_auto_open_prompt_summary">Vraag automatisch om biometrie als een database hiervoor is ingesteld</string>
|
||||
<string name="biometric_prompt_extract_credential_title">Database openen met biometrische herkenning</string>
|
||||
<string name="biometric_prompt_extract_credential_message">Database-referenties uitpakken met biometrische herkenning</string>
|
||||
<string name="biometric">Biometrie</string>
|
||||
<string name="biometric_auto_open_prompt_title">Automatisch om biometrie vragen</string>
|
||||
<string name="biometric_auto_open_prompt_summary">Automatisch om biometrie vragen als een database hiervoor is ingesteld</string>
|
||||
<string name="enable">Inschakelen</string>
|
||||
<string name="disable">Uitschakelen</string>
|
||||
<string name="master_key">Hoofdsleutel</string>
|
||||
@@ -423,33 +421,33 @@
|
||||
<string name="settings_database_force_changing_master_key_title">Vernieuwing afdwingen</string>
|
||||
<string name="settings_database_force_changing_master_key_summary">De hoofdsleutel verplicht wijzigen (dagen)</string>
|
||||
<string name="settings_database_force_changing_master_key_next_time_title">Volgende keer verplicht vernieuwen</string>
|
||||
<string name="settings_database_force_changing_master_key_next_time_summary">Het hoofdwachtwoord de volgende keer vernieuwen (eenmalig)</string>
|
||||
<string name="settings_database_force_changing_master_key_next_time_summary">Het hoofdwachtwoord de volgende keer (eenmalig) vernieuwen</string>
|
||||
<string name="database_default_username_title">Standaard gebruikersnaam</string>
|
||||
<string name="database_custom_color_title">Aangepaste databasekleur</string>
|
||||
<string name="compression">Compressie</string>
|
||||
<string name="compression_none">Geen</string>
|
||||
<string name="compression_gzip">gzip</string>
|
||||
<string name="device_keyboard_setting_title">Toetsenbordinstellingen voor apparaat</string>
|
||||
<string name="enable_auto_save_database_summary">Sla de database op na elke belangrijke actie (in \"Modificeerbare\" modus)</string>
|
||||
<string name="device_keyboard_setting_title">Toetsenbordinstellingen</string>
|
||||
<string name="enable_auto_save_database_summary">Sla de database op na elke belangrijke actie (in \"Schrijf\" modus)</string>
|
||||
<string name="education_setup_OTP_title">Instellingen OTP</string>
|
||||
<string name="remember_keyfile_locations_title">Locatie van sleutelbestanden opslaan</string>
|
||||
<string name="remember_database_locations_title">Locatie van de databases opslaan</string>
|
||||
<string name="hide_expired_entries_summary">Verlopen items zijn verborgen</string>
|
||||
<string name="hide_expired_entries_title">Verlopen items verbergen</string>
|
||||
<string name="remember_database_locations_title">Databaselocatie opslaan</string>
|
||||
<string name="hide_expired_entries_summary">Verlopen items worden verborgen</string>
|
||||
<string name="hide_expired_entries_title">Verberg verlopen items</string>
|
||||
<string name="download_complete">Klaar! Tik om het bestand te openen.</string>
|
||||
<string name="download_finalization">Voltooien…</string>
|
||||
<string name="download_progression">Voortgang: %1$d%%</string>
|
||||
<string name="download_initialization">Initialiseren…</string>
|
||||
<string name="download_attachment">Download %1$s</string>
|
||||
<string name="education_setup_OTP_summary">Stel eenmalig wachtwoordbeheer (HOTP / TOTP) in om een token te genereren dat is aangevraagd voor tweefactorauthenticatie (2FA).</string>
|
||||
<string name="enable_auto_save_database_title">Database automatisch opslaan</string>
|
||||
<string name="enable_auto_save_database_title">Automatisch opslaan</string>
|
||||
<string name="autofill_auto_search_summary">Automatisch zoekresultaten voorstellen vanuit het webdomein of de toepassings-ID</string>
|
||||
<string name="autofill_auto_search_title">Automatisch zoeken</string>
|
||||
<string name="recycle_bin_group_title">Prullenbak</string>
|
||||
<string name="lock_database_show_button_summary">Geeft de vergrendelknop weer in de gebruikersinterface</string>
|
||||
<string name="lock_database_show_button_title">Vergrendelknop weergeven</string>
|
||||
<string name="autofill_preference_title">Instellingen voor automatisch invullen</string>
|
||||
<string name="credential_before_click_biometric_button">Typ het wachtwoord in en klik vervolgens op de knop \"Biometrisch\".</string>
|
||||
<string name="autofill_preference_title">Instellingen voor automatisch aanvullen</string>
|
||||
<string name="credential_before_click_biometric_button">Voer het wachtwoord in en klik vervolgens op de knop \"Biometrie\".</string>
|
||||
<string name="keystore_not_accessible">De sleutelopslag is niet correct geïnitialiseerd.</string>
|
||||
<string name="warning_permanently_delete_nodes">Geselecteerde knooppunten definitief verwijderen\?</string>
|
||||
<string name="warning_database_link_revoked">Toegang tot het bestand ingetrokken door bestandsbeheer</string>
|
||||
@@ -466,14 +464,16 @@
|
||||
<string name="menu_empty_recycle_bin">Prullenbak legen</string>
|
||||
<string name="menu_save_database">Database opslaan</string>
|
||||
<string name="error_save_database">Kan database niet opslaan.</string>
|
||||
<string name="error_create_database">Kan databasebestand niet aanmaken.</string>
|
||||
<string name="error_create_database">Databasebestand is niet aangemaakt.</string>
|
||||
<string name="error_label_exists">Dit label bestaat al.</string>
|
||||
<string name="entry_attachments">Bijlagen</string>
|
||||
<string name="html_about_contribution">Om <strong>onze vrijheid te behouden</strong>, <strong>bugs te verhelpen</strong>, <strong>functies toe te voegen</strong> en <strong>altijd actief te blijven</strong>, kunnen wij niet zonder uw <strong>bijdrage</strong>.</string>
|
||||
<string name="html_about_contribution">Om <strong>onze vrijheid te behouden</strong>, <strong>bugs te verhelpen</strong>, <strong>functies toe te voegen</strong> en <strong>altijd actief te blijven</strong>, rekenen wij op jouw <strong>bijdrage</strong>.</string>
|
||||
<string name="entry_add_attachment">Bijlage toevoegen</string>
|
||||
<string name="discard">Weggooien</string>
|
||||
<string name="discard_changes">Veranderingen ongedaan maken\?</string>
|
||||
<string name="validate">Valideren</string>
|
||||
<string name="contribution">Bijdragen</string>
|
||||
<string name="contact">Contact</string>
|
||||
<string name="keyboard_search_share_summary">Zoek automatisch naar gedeelde informatie om het toetsenbord te vullen</string>
|
||||
<string name="keyboard_search_share_title">Gedeelde informatie zoeken</string>
|
||||
</resources>
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources>
|
||||
<string name="feedback">Tilbakemelding:</string>
|
||||
<string name="homepage">Heimeside:</string>
|
||||
--><resources>
|
||||
<string name="feedback">Tilbakemelding</string>
|
||||
<string name="homepage">Heimeside</string>
|
||||
<string name="about_description">KeePassDX er ei android-utgåve av KeePass passordstyrar.</string>
|
||||
<string name="accept">Godta</string>
|
||||
<string name="add_entry">Legg til post</string>
|
||||
@@ -122,9 +121,7 @@
|
||||
<string name="unsupported_db_version">Kan ikkje bruka databaseutgåva.</string>
|
||||
<string name="uppercase">Store bokstavar</string>
|
||||
<string name="version_label">Utgåve %1$s</string>
|
||||
|
||||
<string name="education_unlock_summary">Skriv inn passordet og/eller nøkkelfil for å låsa opp databasen.</string>
|
||||
|
||||
<string-array name="timeout_options">
|
||||
<item>5 sekund</item>
|
||||
<item>10 sekund</item>
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
<string name="sort_db">Porządek naturalny</string>
|
||||
<string name="special">Znaki specjalne</string>
|
||||
<string name="search">Szukaj</string>
|
||||
<string name="encryption_twofish">Dwie ryby</string>
|
||||
<string name="encryption_twofish">Algorytm szyfrujący Twofish</string>
|
||||
<string name="underline">Podkreślenie</string>
|
||||
<string name="unsupported_db_version">Nieobsługiwana wersja bazy danych.</string>
|
||||
<string name="uppercase">Wielkie litery</string>
|
||||
@@ -344,7 +344,7 @@
|
||||
<string name="keyboard_selection_entry_title">Wybór wpisu</string>
|
||||
<string name="keyboard_selection_entry_summary">Pokaż pola wprowadzania w Magikeyboard podczas przeglądania wpisu</string>
|
||||
<string name="delete_entered_password_title">Usuń hasło</string>
|
||||
<string name="delete_entered_password_summary">Usuwa hasło wprowadzone po próbie połączenia</string>
|
||||
<string name="delete_entered_password_summary">Usuwa hasło wprowadzone po próbie połączenia z bazą danych</string>
|
||||
<string name="content_description_open_file">Otwórz plik</string>
|
||||
<string name="content_description_add_entry">Dodaj wpis</string>
|
||||
<string name="content_description_add_group">Dodaj grupę</string>
|
||||
@@ -474,4 +474,6 @@
|
||||
<string name="autofill_preference_title">Ustawienia autouzupełniania</string>
|
||||
<string name="warning_database_link_revoked">Dostęp do pliku anulowany przez menedżera plików</string>
|
||||
<string name="error_label_exists">Ta etykieta już istnieje.</string>
|
||||
<string name="keyboard_search_share_summary">Automatyczne wyszukiwanie udostępnionych informacji w celu zapełnienia klawiatury</string>
|
||||
<string name="keyboard_search_share_title">Wyszukaj udostępnione informacje</string>
|
||||
</resources>
|
||||
@@ -192,7 +192,7 @@
|
||||
<string name="warning_empty_password">Continuar sem proteção de desbloqueio de senha\?</string>
|
||||
<string name="warning_no_encryption_key">Continuar sem chave de criptografia\?</string>
|
||||
<string name="configure_biometric">Impressão digital é suportada, mas não está configurada.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Escaneamento de impressão digital</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Escaneamento de impressão digital para abrir o bando de dados</string>
|
||||
<string name="encrypted_value_stored">Senha encriptada armazenada</string>
|
||||
<string name="biometric_invalid_key">Não pôde ler chave de impressão digital. Por favor, apague-a e repita o procedimento de reconhecimento biométrico.</string>
|
||||
<string name="biometric_not_recognized">Não pôde reconhecer impressão digital</string>
|
||||
@@ -347,7 +347,7 @@
|
||||
<string name="keyboard_selection_entry_title">Seleção de entrada</string>
|
||||
<string name="keyboard_selection_entry_summary">Mostrar campos de entrada no Magikeyboard quando estiver visualizando uma Entrada</string>
|
||||
<string name="delete_entered_password_title">Deletar senha</string>
|
||||
<string name="delete_entered_password_summary">Deleta a senha inserida após uma tentativa de conexão</string>
|
||||
<string name="delete_entered_password_summary">Deleta a senha inserida após uma tentativa de conexão com o banco de dados</string>
|
||||
<string name="content_description_open_file">Abrir arquivo</string>
|
||||
<string name="content_description_add_node">Inserir nó</string>
|
||||
<string name="content_description_add_entry">Adicionar entrada</string>
|
||||
@@ -474,4 +474,6 @@
|
||||
<string name="discard_changes">Descartar alterações\?</string>
|
||||
<string name="validate">Validação</string>
|
||||
<string name="contribution">Contribuição</string>
|
||||
<string name="keyboard_search_share_summary">Procurar automaticamente por informação compartilhada para popular o teclado</string>
|
||||
<string name="keyboard_search_share_title">Procurar informação compartilhada</string>
|
||||
</resources>
|
||||
@@ -344,7 +344,7 @@
|
||||
<string name="keyboard_selection_entry_title">Выбор записи</string>
|
||||
<string name="keyboard_selection_entry_summary">Показывать поля ввода в Magikeyboard при просмотре записи</string>
|
||||
<string name="delete_entered_password_title">Удалять пароль</string>
|
||||
<string name="delete_entered_password_summary">Забывать введённый пароль</string>
|
||||
<string name="delete_entered_password_summary">Забывать введённый пароль после попытки входа в базу</string>
|
||||
<string name="content_description_open_file">Открыть файл</string>
|
||||
<string name="content_description_node_children">Дочерний узел</string>
|
||||
<string name="content_description_add_node">Добавить узел</string>
|
||||
@@ -474,4 +474,6 @@
|
||||
<string name="warning_database_link_revoked">Доступ к файлу отменён файловым менеджером</string>
|
||||
<string name="autofill_auto_search_title">Автопоиск</string>
|
||||
<string name="autofill_preference_title">Настройки автозаполнения</string>
|
||||
<string name="keyboard_search_share_summary">Выполнять автоматический поиск общедоступной информации для подстановки в клавиатуру</string>
|
||||
<string name="keyboard_search_share_title">Поиск доступной информации</string>
|
||||
</resources>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources>
|
||||
<string name="feedback">అభిప్రాయం:</string>
|
||||
<string name="homepage">హోమ్ పేజీ:</string>
|
||||
--><resources>
|
||||
<string name="feedback">అభిప్రాయం</string>
|
||||
<string name="homepage">హోమ్ పేజీ</string>
|
||||
<string name="about_description">KeePassDX అనేది KeePass పాస్వర్డ్ మేనేజర్ యొక్క యాండ్రాయిడ్ అమలు.</string>
|
||||
<string name="accept">ఆమోదించు</string>
|
||||
<string name="add_entry">"ఎంట్రీని జత చెయ్యండి "</string>
|
||||
|
||||
@@ -346,7 +346,7 @@
|
||||
<string name="keyboard_selection_entry_title">Giriş seçimi</string>
|
||||
<string name="keyboard_selection_entry_summary">Bir girişi görüntülerken Magikeyboard\'da giriş alanlarını göster</string>
|
||||
<string name="delete_entered_password_title">Parolayı sil</string>
|
||||
<string name="delete_entered_password_summary">Bir bağlantı denemesinden sonra girilen parolayı siler</string>
|
||||
<string name="delete_entered_password_summary">Veri tabanına bağlantı denemesinden sonra girilen parolayı siler</string>
|
||||
<string name="content_description_node_children">Alt düğüm</string>
|
||||
<string name="content_description_repeat_toggle_password_visibility">Parola görünürlüğünü değiştirmeyi tekrarla</string>
|
||||
<string name="content_description_background">Arka plan</string>
|
||||
@@ -458,4 +458,6 @@
|
||||
<string name="autofill_preference_title">Otomatik doldurma ayarları</string>
|
||||
<string name="warning_database_link_revoked">Dosyaya erişim dosya yöneticisi tarafından iptal edildi</string>
|
||||
<string name="error_label_exists">Bu etiket zaten var.</string>
|
||||
<string name="keyboard_search_share_summary">Klavyeyi doldurmak için paylaşılan bilgileri otomatik olarak ara</string>
|
||||
<string name="keyboard_search_share_title">Paylaşılan bilgileri ara</string>
|
||||
</resources>
|
||||
@@ -18,7 +18,7 @@
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
--><resources>
|
||||
<string name="feedback">Відгук</string>
|
||||
<string name="homepage">Домашня сторінка</string>
|
||||
<string name="homepage">Домівка</string>
|
||||
<string name="about_description">KeePassDX є Android-версією менеджера паролів KeePass</string>
|
||||
<string name="accept">Прийняти</string>
|
||||
<string name="add_entry">Додати запис</string>
|
||||
@@ -141,7 +141,7 @@
|
||||
<item>Середній</item>
|
||||
<item>Великий</item>
|
||||
</string-array>
|
||||
<string name="contribution">Допомога проєкту</string>
|
||||
<string name="contribution">Допомогти проєкту</string>
|
||||
<string name="contact">Контакти</string>
|
||||
<string name="content_description_password_length">Довжина пароля</string>
|
||||
<string name="content_description_open_file">Відкрити файл</string>
|
||||
@@ -149,7 +149,7 @@
|
||||
<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="configure_biometric">Розблокування біометричними даними підтримується, але не налаштоване.</string>
|
||||
<string name="content_description_add_group">Додати групу</string>
|
||||
<string name="content_description_update_from_list">Оновити</string>
|
||||
<string name="keyboard">Клавіатура</string>
|
||||
@@ -344,7 +344,7 @@
|
||||
<string name="enable_auto_save_database_title">Автозбереження бази даних</string>
|
||||
<string name="enable_read_only_summary">Типово відкривати базу даних лише для читання</string>
|
||||
<string name="enable_read_only_title">Захист від запису</string>
|
||||
<string name="delete_entered_password_summary">Видаляти пароль, введений після спроби з\'єднання</string>
|
||||
<string name="delete_entered_password_summary">Видаляти пароль, введений після спроби з\'єднання з базою даних</string>
|
||||
<string name="delete_entered_password_title">Видалити пароль</string>
|
||||
<string name="allow_no_password_summary">Увімкнути кнопку \"Відкрити\", якщо не вибрано головний пароль</string>
|
||||
<string name="allow_no_password_title">Дозволити без головного ключа</string>
|
||||
@@ -421,7 +421,7 @@
|
||||
<string name="clipboard_warning">Якщо не вдалось очистити буфер обміну автоматично, видаліть його історію вручну.</string>
|
||||
<string name="clipboard_notifications_summary">Увімкнути сповіщення буфера обміну для копіювання полів під час перегляду запису</string>
|
||||
<string name="clipboard_notifications_title">Сповіщення буфера обміну</string>
|
||||
<string name="clipboard_explanation_summary">Копіювати облікові дані за допомогою буфера обміну вашого пристрою</string>
|
||||
<string name="clipboard_explanation_summary">Копіювати облікові дані за допомогою буфера обміну пристрою</string>
|
||||
<string name="clipboard">Буфер обміну</string>
|
||||
<string name="database_opened">Базу даних відкрито</string>
|
||||
<string name="list_password_generator_options_summary">Встановіть дозволені символи для створення пароля</string>
|
||||
@@ -445,8 +445,8 @@
|
||||
<string name="biometric_prompt_extract_credential_message">Витяг облікових даних бази даних за допомогою біометричного ключа</string>
|
||||
<string name="biometric_prompt_extract_credential_title">Відкрити базу даних біометричним ключем</string>
|
||||
<string name="biometric_prompt_store_credential_title">Зберегти біометричний ключ</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Скористатися біометричним ключем для розблокування базу даних</string>
|
||||
<string name="open_biometric_prompt_store_credential">Скористатися біометричним ключем, щоби зберегти дані</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Розблокувати базу даних біометричним ключем</string>
|
||||
<string name="open_biometric_prompt_store_credential">Скористатися біометричним ключем щоби зберегти дані</string>
|
||||
<string name="keystore_not_accessible">Сховище ключів не ініціалізовано належним чином.</string>
|
||||
<string name="build_label">Збірка %1$s</string>
|
||||
<string name="warning_permanently_delete_nodes">Видалити вибрані вузли остаточно\?</string>
|
||||
@@ -474,4 +474,6 @@
|
||||
<string name="parallelism">Паралельність</string>
|
||||
<string name="memory_usage">Використання пам\'яті</string>
|
||||
<string name="encryption_explanation">Алгоритм шифрування бази даних, застосований для всіх даних.</string>
|
||||
<string name="keyboard_search_share_summary">Автоматичний пошук загальнодоступної інформації для заповнення клавіатури</string>
|
||||
<string name="keyboard_search_share_title">Пошук доступної інформації</string>
|
||||
</resources>
|
||||
@@ -347,7 +347,7 @@
|
||||
<string name="keyboard_selection_entry_title">条目选择</string>
|
||||
<string name="keyboard_selection_entry_summary">在查看条目时,在专用键盘中显示输入字段</string>
|
||||
<string name="delete_entered_password_title">删除密码</string>
|
||||
<string name="delete_entered_password_summary">密码错误后删除已输入的密码</string>
|
||||
<string name="delete_entered_password_summary">在连接数据库尝试后删除输入的密码</string>
|
||||
<string name="content_description_open_file">打开文件</string>
|
||||
<string name="content_description_node_children">子节点</string>
|
||||
<string name="content_description_add_node">增加节点</string>
|
||||
@@ -474,4 +474,6 @@
|
||||
<string name="autofill_preference_title">自动填充设置</string>
|
||||
<string name="warning_database_link_revoked">访问文件管理器撤消访问权限的文件</string>
|
||||
<string name="error_label_exists">该标签已经存在。</string>
|
||||
<string name="keyboard_search_share_summary">自动搜索共享信息以填充键盘</string>
|
||||
<string name="keyboard_search_share_title">搜索分享的信息</string>
|
||||
</resources>
|
||||
@@ -19,7 +19,8 @@
|
||||
-->
|
||||
<resources>
|
||||
<attr name="toolbarAppearance" format="reference" />
|
||||
<attr name="toolbarBottomAppearance" format="reference" />
|
||||
<attr name="specialToolbarAppearance" format="reference" />
|
||||
<attr name="actionToolbarAppearance" format="reference" />
|
||||
<attr name="toolbarPopupAppearance" format="reference" />
|
||||
|
||||
<attr name="colorAccentLight" format="reference|color" />
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
<color name="blue_dark">#1976D2</color>
|
||||
<color name="blue_darker">#1565C0</color>
|
||||
|
||||
<color name="cyan_lighter">#33b5e5</color>
|
||||
<color name="cyan">#2c7a96</color>
|
||||
|
||||
<color name="red_lighter">#ef9a9a</color>
|
||||
<color name="red_light">#f44336</color>
|
||||
<color name="red">#e53935</color>
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
<bool name="omit_backup_search_default" translatable="false">true</bool>
|
||||
<string name="auto_focus_search_key" translatable="false">auto_focus_search_key</string>
|
||||
<bool name="auto_focus_search_default" translatable="false">false</bool>
|
||||
<string name="subdomain_search_key" translatable="false">subdomain_search_key</string>
|
||||
<bool name="subdomain_search_default" translatable="false">false</bool>
|
||||
<string name="app_timeout_key" translatable="false">app_timeout_key</string>
|
||||
<string name="lock_database_screen_off_key" translatable="false">lock_database_screen_off_key</string>
|
||||
<bool name="lock_database_screen_off_default" translatable="false">true</bool>
|
||||
@@ -132,6 +134,12 @@
|
||||
<bool name="keyboard_key_sound_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>
|
||||
<string-array name="autofill_application_id_blocklist_default">
|
||||
</string-array>
|
||||
<string name="autofill_web_domain_blocklist_key" translatable="false">autofill_web_domain_blocklist_key</string>
|
||||
<string-array name="autofill_web_domain_blocklist_default">
|
||||
</string-array>
|
||||
|
||||
<!-- Advanced Unlock Settings -->
|
||||
<string name="settings_advanced_unlock_key" translatable="false">settings_advanced_unlock_key</string>
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<string name="content_description_add_node">Add node</string>
|
||||
<string name="content_description_add_entry">Add entry</string>
|
||||
<string name="content_description_add_group">Add group</string>
|
||||
<string name="content_description_add_item">Add item</string>
|
||||
<string name="content_description_file_information">File information</string>
|
||||
<string name="content_description_password_checkbox">Password checkbox</string>
|
||||
<string name="content_description_keyfile_checkbox">Keyfile checkbox</string>
|
||||
@@ -131,6 +132,7 @@
|
||||
<string name="error_otp_counter">Counter must be between %1$d and %2$d.</string>
|
||||
<string name="error_otp_period">Period must be between %1$d and %2$d seconds.</string>
|
||||
<string name="error_otp_digits">Token must contain %1$d to %2$d digits.</string>
|
||||
<string name="error_string_type">This text does not match the requested item.</string>
|
||||
<string name="field_name">Field name</string>
|
||||
<string name="field_value">Field value</string>
|
||||
<string name="file_not_found_content">Could not find file. Try reopening it from your file browser.</string>
|
||||
@@ -200,6 +202,8 @@
|
||||
<string name="omit_backup_search_summary">Omits \"Backup\" and \"Recycle bin\" groups from search results</string>
|
||||
<string name="auto_focus_search_title">Quick search</string>
|
||||
<string name="auto_focus_search_summary">Request a search when opening a database</string>
|
||||
<string name="subdomain_search_title">Subdomain search</string>
|
||||
<string name="subdomain_search_summary">Search web domains with subdomains constraints</string>
|
||||
<string name="progress_create">Creating new database…</string>
|
||||
<string name="progress_title">Working…</string>
|
||||
<string name="protection">Protection</string>
|
||||
@@ -230,6 +234,7 @@
|
||||
<string name="do_not_kill_app">Do not kill the app…</string>
|
||||
<string name="space">Space</string>
|
||||
<string name="search_label">Search</string>
|
||||
<string name="filter">Filter</string>
|
||||
<string name="sort_menu">Sort</string>
|
||||
<string name="sort_ascending">Lowest first ↓</string>
|
||||
<string name="sort_groups_before">Groups before</string>
|
||||
@@ -378,7 +383,13 @@
|
||||
<string name="keyboard_key_vibrate_title">Vibratory keypresses</string>
|
||||
<string name="keyboard_key_sound_title">Audible keypresses</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_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>
|
||||
<string name="autofill_application_id_blocklist_summary">Blocklist that prevents auto filling of apps</string>
|
||||
<string name="autofill_web_domain_blocklist_title">Web domain blocklist</string>
|
||||
<string name="autofill_web_domain_blocklist_summary">Blocklist that prevents auto filling of web domains</string>
|
||||
<string name="autofill_block">Block autofill</string>
|
||||
<string name="autofill_block_restart">Restart the app containing the form to activate the blocking.</string>
|
||||
<string name="allow_no_password_title">Allow no master key</string>
|
||||
<string name="allow_no_password_summary">Enable the \"Open\" button if no credentials are selected</string>
|
||||
<string name="delete_entered_password_title">Delete password</string>
|
||||
|
||||
@@ -30,12 +30,13 @@
|
||||
<item name="android:textColorHintInverse">@color/green_light</item>
|
||||
<item name="android:windowBackground">@color/background_dark</item>
|
||||
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Black</item>
|
||||
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Black</item>
|
||||
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Black</item>
|
||||
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Black</item>
|
||||
<item name="android:alertDialogTheme">@style/KeepassDXStyle.Black.Dialog</item>
|
||||
<item name="alertDialogTheme">@style/KeepassDXStyle.Black.Dialog</item>
|
||||
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Dark</item>
|
||||
</style>
|
||||
<!-- Toolbar Style Black Green -->
|
||||
<!-- Toolbar Style Black -->
|
||||
<style name="KeepassDXStyle.Toolbar.Black" parent="KeepassDXStyle.Black">
|
||||
<item name="colorControlNormal">@color/colorTextInverse</item>
|
||||
<item name="android:textColorPrimary">@color/colorTextInverse</item>
|
||||
@@ -44,6 +45,11 @@
|
||||
<item name="android:textColorHint">@color/green_lighter</item>
|
||||
<item name="android:tint">@color/colorTextInverse</item>
|
||||
</style>
|
||||
<!-- Special Toolbar Black -->
|
||||
<style name="KeepassDXStyle.Toolbar.Special.Black" parent="KeepassDXStyle.Toolbar.Black">
|
||||
<item name="android:background">@color/black</item>
|
||||
<item name="background">@color/black</item>
|
||||
</style>
|
||||
<!-- Contextual Action Bar Dark -->
|
||||
<style name="KeepassDXStyle.ActionMode.Black" parent="@style/Widget.AppCompat.ActionMode">
|
||||
<item name="background">@color/dark</item>
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
<item name="android:textColorHintInverse">@color/blue_lighter</item>
|
||||
<item name="android:windowBackground">@color/background_light</item>
|
||||
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Blue</item>
|
||||
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Bottom.Blue</item>
|
||||
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Blue</item>
|
||||
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Action.Blue</item>
|
||||
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Blue</item>
|
||||
</style>
|
||||
<!-- Toolbar Style Blue -->
|
||||
@@ -42,7 +43,14 @@
|
||||
<item name="android:textColorHint">@color/blue_lighter</item>
|
||||
<item name="android:tint">@color/colorTextInverse</item>
|
||||
</style>
|
||||
<style name="KeepassDXStyle.Toolbar.Bottom.Blue" parent="KeepassDXStyle.Toolbar.Blue">
|
||||
<!-- Special Toolbar Blue -->
|
||||
<style name="KeepassDXStyle.Toolbar.Special.Blue" parent="KeepassDXStyle.Toolbar.Blue">
|
||||
<item name="actionMenuTextColor">@color/colorTextInverse</item>
|
||||
<item name="android:background">@color/blue_dark</item>
|
||||
<item name="background">@color/blue_dark</item>
|
||||
</style>
|
||||
<!-- Action Toolbar Blue -->
|
||||
<style name="KeepassDXStyle.Toolbar.Action.Blue" parent="KeepassDXStyle.Toolbar.Blue">
|
||||
<item name="actionMenuTextColor">@color/colorTextInverse</item>
|
||||
</style>
|
||||
<!-- Contextual Action Bar Blue -->
|
||||
|
||||
@@ -22,14 +22,15 @@
|
||||
<style name="KeepassDXStyle.Dark" parent="KeepassDXStyle.Night.v21" >
|
||||
<item name="colorPrimary">#212121</item>
|
||||
<item name="colorPrimaryDark">@color/dark</item>
|
||||
<item name="colorAccent">#2c7a96</item>
|
||||
<item name="colorAccentLight">#33b5e5</item>
|
||||
<item name="colorControlActivated">#33b5e5</item>
|
||||
<item name="android:textColorPrimary">#33b5e5</item>
|
||||
<item name="android:textColorHintInverse">#33b5e5</item>
|
||||
<item name="colorAccent">@color/cyan</item>
|
||||
<item name="colorAccentLight">@color/cyan_lighter</item>
|
||||
<item name="colorControlActivated">@color/cyan_lighter</item>
|
||||
<item name="android:textColorPrimary">@color/cyan_lighter</item>
|
||||
<item name="android:textColorHintInverse">@color/cyan_lighter</item>
|
||||
<item name="android:windowBackground">@color/background_dark</item>
|
||||
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Dark</item>
|
||||
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Dark</item>
|
||||
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Dark</item>
|
||||
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Dark</item>
|
||||
<item name="android:alertDialogTheme">@style/KeepassDXStyle.Dark.Dialog</item>
|
||||
<item name="alertDialogTheme">@style/KeepassDXStyle.Dark.Dialog</item>
|
||||
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Dark</item>
|
||||
@@ -41,6 +42,11 @@
|
||||
<item name="android:textColorSecondary">@color/colorTextSecondary</item>
|
||||
<item name="android:tint">@color/colorTextInverse</item>
|
||||
</style>
|
||||
<!-- Special Toolbar Dark -->
|
||||
<style name="KeepassDXStyle.Toolbar.Special.Dark" parent="KeepassDXStyle.Toolbar.Dark">
|
||||
<item name="android:background">@color/dark</item>
|
||||
<item name="background">@color/dark</item>
|
||||
</style>
|
||||
<!-- Contextual Action Bar Dark -->
|
||||
<style name="KeepassDXStyle.ActionMode.Dark" parent="@style/Widget.AppCompat.ActionMode">
|
||||
<item name="background">@color/dark</item>
|
||||
@@ -48,6 +54,6 @@
|
||||
<!-- Dialog -->
|
||||
<style name="KeepassDXStyle.Dark.Dialog" parent="KeepassDXStyle.Night.Dialog">
|
||||
<item name="colorAccent">#fefefe</item>
|
||||
<item name="android:textColorPrimary">#33b5e5</item>
|
||||
<item name="android:textColorPrimary">@color/cyan_lighter</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -29,7 +29,8 @@
|
||||
<item name="android:textColorHintInverse">@color/purple_lighter</item>
|
||||
<item name="android:windowBackground">@color/background_purple</item>
|
||||
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Purple</item>
|
||||
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Bottom.Purple</item>
|
||||
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Purple</item>
|
||||
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Action.Purple</item>
|
||||
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Purple</item>
|
||||
</style>
|
||||
<!-- Toolbar Style Purple -->
|
||||
@@ -42,7 +43,13 @@
|
||||
<item name="android:textColorHint">@color/purple_lighter</item>
|
||||
<item name="android:tint">@color/colorTextInverse</item>
|
||||
</style>
|
||||
<style name="KeepassDXStyle.Toolbar.Bottom.Purple" parent="KeepassDXStyle.Toolbar.Purple">
|
||||
<!-- Special Toolbar Purple -->
|
||||
<style name="KeepassDXStyle.Toolbar.Special.Purple" parent="KeepassDXStyle.Toolbar.Purple">
|
||||
<item name="android:background">@color/purple_dark</item>
|
||||
<item name="background">@color/purple_dark</item>
|
||||
</style>
|
||||
<!-- Action Toolbar Purple -->
|
||||
<style name="KeepassDXStyle.Toolbar.Action.Purple" parent="KeepassDXStyle.Toolbar.Purple">
|
||||
<item name="actionMenuTextColor">@color/colorTextInverse</item>
|
||||
</style>
|
||||
<!-- Contextual Action Bar Purple -->
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
<item name="android:textColorHintInverse">@color/red_lighter</item>
|
||||
<item name="android:windowBackground">@color/background_night</item>
|
||||
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Red</item>
|
||||
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Red</item>
|
||||
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Red</item>
|
||||
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Red</item>
|
||||
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Red</item>
|
||||
</style>
|
||||
<!-- Toolbar Style Red -->
|
||||
@@ -42,6 +43,11 @@
|
||||
<item name="android:textColorHint">@color/red_lighter</item>
|
||||
<item name="android:tint">@color/colorTextInverse</item>
|
||||
</style>
|
||||
<!-- Special Toolbar Red -->
|
||||
<style name="KeepassDXStyle.Toolbar.Special.Red" parent="KeepassDXStyle.Toolbar.Red">
|
||||
<item name="android:background">@color/red_dark</item>
|
||||
<item name="background">@color/red_dark</item>
|
||||
</style>
|
||||
<!-- Contextual Action Bar Red -->
|
||||
<style name="KeepassDXStyle.ActionMode.Red" parent="@style/Widget.AppCompat.ActionMode">
|
||||
<item name="background">@color/orange</item>
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
<!-- Toolbar -->
|
||||
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Light</item>
|
||||
<item name="toolbarPopupAppearance">@style/KeepassDXStyle.Light.Toolbar.Popup</item>
|
||||
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Night</item>
|
||||
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Light</item>
|
||||
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Light</item>
|
||||
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode</item>
|
||||
<!-- CollapsingToolbarLayout -->
|
||||
<item name="expandedTitleTextAppearance">@style/KeepassDXStyle.Expanded.Title</item>
|
||||
@@ -126,7 +127,8 @@
|
||||
<!-- Toolbar -->
|
||||
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Night</item>
|
||||
<item name="toolbarPopupAppearance">@style/KeepassDXStyle.Night.Toolbar.Popup</item>
|
||||
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Night</item>
|
||||
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Night</item>
|
||||
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Night</item>
|
||||
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode</item>
|
||||
<!-- CollapsingToolbarLayout -->
|
||||
<item name="expandedTitleTextAppearance">@style/KeepassDXStyle.Expanded.Title</item>
|
||||
@@ -175,8 +177,21 @@
|
||||
<item name="android:tint">@color/colorTextInverse</item>
|
||||
</style>
|
||||
|
||||
<!-- Special Toolbar Light Style -->
|
||||
<style name="KeepassDXStyle.Toolbar.Special.Light" parent="KeepassDXStyle.Toolbar.Light">
|
||||
<item name="android:background">@color/green_dark</item>
|
||||
<item name="background">@color/green_dark</item>
|
||||
</style>
|
||||
|
||||
<!-- Special Toolbar Night Style -->
|
||||
<style name="KeepassDXStyle.Toolbar.Special.Night" parent="KeepassDXStyle.Toolbar.Night">
|
||||
<item name="android:background">@color/green_dark</item>
|
||||
<item name="background">@color/green_dark</item>
|
||||
</style>
|
||||
|
||||
<!-- Contextual Action Bar -->
|
||||
<style name="KeepassDXStyle.ActionMode" parent="@style/Widget.AppCompat.ActionMode">
|
||||
<item name="android:background">@color/orange</item>
|
||||
<item name="background">@color/orange</item>
|
||||
</style>
|
||||
|
||||
@@ -257,7 +272,7 @@
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
<item name="android:textSize">20sp</item>
|
||||
</style>
|
||||
<style name="KeepassDXStyle.TextAppearance.TinyText" parent="KeepassDXStyle.TextAppearance">
|
||||
<style name="KeepassDXStyle.TextAppearance.Tiny" parent="KeepassDXStyle.TextAppearance">
|
||||
<item name="android:textSize">12sp</item>
|
||||
</style>
|
||||
<style name="KeepassDXStyle.TextAppearance.WarningTextStyle" parent="KeepassDXStyle.TextAppearance">
|
||||
@@ -291,6 +306,14 @@
|
||||
<item name="android:tint">@color/group_subtitle_color</item>
|
||||
</style>
|
||||
|
||||
<!-- Special Toolbar text titlé -->
|
||||
<style name="KeepassDXStyle.TextAppearance.Toolbar.Special.Title" parent="KeepassDXStyle.TextAppearance.Small">
|
||||
<item name="android:textColor">?attr/colorAccent</item>
|
||||
</style>
|
||||
<style name="KeepassDXStyle.TextAppearance.Toolbar.Special.SubTitle" parent="KeepassDXStyle.TextAppearance.Tiny">
|
||||
<item name="android:textColor">@color/colorTextInverse</item>
|
||||
</style>
|
||||
|
||||
<!-- Button Style -->
|
||||
<style name="KeepassDXStyle.v21.Button" parent="Base.TextAppearance.AppCompat.Button">
|
||||
<item name="android:gravity">center</item>
|
||||
|
||||
@@ -1,22 +1,180 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
-->
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2020 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Attributes for the Autofill service that tell the framework what will act as the Autofill service's
|
||||
Settings Activity. This is pointed to in the service's meta-data in the application's manifest.
|
||||
-->
|
||||
<autofill-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:settingsActivity="com.kunzisoft.keepass.settings.AutofillSettingsActivity" />
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:targetApi="p"
|
||||
android:settingsActivity="com.kunzisoft.keepass.settings.AutofillSettingsActivity" >
|
||||
<compatibility-package
|
||||
android:name="com.amazon.cloud9"
|
||||
android:maxLongVersionCode="10000000000" />
|
||||
<compatibility-package
|
||||
android:name="com.android.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.android.chrome"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.avast.android.secure.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.avg.android.secure.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.brave.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.brave.browser_beta"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.brave.browser_default"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.brave.browser_dev"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.brave.browser_nightly"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.chrome.beta"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.chrome.canary"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.chrome.dev"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.ecosia.android"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.google.android.apps.chrome"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.google.android.apps.chrome_dev"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.kiwibrowser.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.microsoft.emmx"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.naver.whale"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.opera.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.opera.browser.beta"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.opera.mini.native"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.opera.mini.native.beta"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.opera.touch"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.qwant.liberty"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.sec.android.app.sbrowser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.sec.android.app.sbrowser.beta"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.stoutner.privacybrowser.free"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.stoutner.privacybrowser.standard"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.vivaldi.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.vivaldi.browser.snapshot"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.vivaldi.browser.sopranos"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.yandex.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="mark.via.gp"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.adblockplus.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.adblockplus.browser.beta"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.bromite.bromite"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.bromite.chromium"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.chromium.chrome"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.codeaurora.swe.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.gnu.icecat"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.fenix"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.fenix.nightly"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.fennec_aurora"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.fennec_fdroid"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.firefox"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.firefox_beta"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.reference.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.rocket"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.torproject.torbrowser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.torproject.torbrowser_alpha"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
</autofill-service>
|
||||
@@ -59,7 +59,11 @@
|
||||
android:title="@string/auto_focus_search_title"
|
||||
android:summary="@string/auto_focus_search_summary"
|
||||
android:defaultValue="@bool/auto_focus_search_default"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="@string/subdomain_search_key"
|
||||
android:title="@string/subdomain_search_title"
|
||||
android:summary="@string/subdomain_search_summary"
|
||||
android:defaultValue="@bool/subdomain_search_default"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 Jeremy Jamet / Kunzisoft.
|
||||
Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||
|
||||
This file is part of KeePassDX.
|
||||
|
||||
@@ -26,4 +26,15 @@
|
||||
android:summary="@string/autofill_auto_search_summary"
|
||||
android:defaultValue="@bool/autofill_auto_search_default"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/filter">
|
||||
<com.kunzisoft.keepass.settings.preference.InputListPreference
|
||||
android:key="@string/autofill_application_id_blocklist_key"
|
||||
android:title="@string/autofill_application_id_blocklist_title"
|
||||
android:summary="@string/autofill_application_id_blocklist_summary"/>
|
||||
<com.kunzisoft.keepass.settings.preference.InputListPreference
|
||||
android:key="@string/autofill_web_domain_blocklist_key"
|
||||
android:title="@string/autofill_web_domain_blocklist_title"
|
||||
android:summary="@string/autofill_web_domain_blocklist_summary"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
6
fastlane/metadata/android/en-US/changelogs/35.txt
Normal file
6
fastlane/metadata/android/en-US/changelogs/35.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
* Add blocklists for autofill
|
||||
* Add autofill compatibility mode (usefull for Browser not compatible)
|
||||
* Upgrade autofill recognition algorithm
|
||||
* Setting to search through web subdomains
|
||||
* Refactoring selection mode
|
||||
|
||||
5
fastlane/metadata/android/fr-FR/changelogs/35.txt
Normal file
5
fastlane/metadata/android/fr-FR/changelogs/35.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
* Ajout des listes de blocage pour le remplissage automatique
|
||||
* Ajout du mode de compatibilité pour le remplissage automatique (utile pour les navigateurs non compatibles)
|
||||
* Mise à jour de l'algorithme de reconnaissance du remplissage automatique
|
||||
* Paramètre pour rechercher à travers les sous-domaines web
|
||||
* Refactorisation du mode sélection
|
||||
Reference in New Issue
Block a user