mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Compare commits
167 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dae19bbccf | ||
|
|
c81f83887e | ||
|
|
04e555dde9 | ||
|
|
be94518e31 | ||
|
|
66bec1e08c | ||
|
|
f61ce10716 | ||
|
|
b1b92b2995 | ||
|
|
bd9f2c4757 | ||
|
|
a3ead2153e | ||
|
|
e12f008b92 | ||
|
|
d064ece0ff | ||
|
|
379fbf68b1 | ||
|
|
83783c1a88 | ||
|
|
c7e46205b3 | ||
|
|
0c61f0ded2 | ||
|
|
49e2ec0498 | ||
|
|
fb0a74c101 | ||
|
|
245a7ddfe9 | ||
|
|
ca8874c2e1 | ||
|
|
dbcd7c8e03 | ||
|
|
9cce63659e | ||
|
|
be0bbab0c8 | ||
|
|
7b6d3698c4 | ||
|
|
56daca8b4f | ||
|
|
ed382d102e | ||
|
|
745de2502e | ||
|
|
503a4b1374 | ||
|
|
0b71b2d659 | ||
|
|
2ad244df94 | ||
|
|
d0da4f03a6 | ||
|
|
ab0cd4152a | ||
|
|
93d04bfe60 | ||
|
|
b1ccb40bd3 | ||
|
|
d177001ea8 | ||
|
|
2f921897c7 | ||
|
|
1a0f7146ce | ||
|
|
dff2386594 | ||
|
|
55cc782cc6 | ||
|
|
6903099873 | ||
|
|
6e2d84be33 | ||
|
|
9e542d0bbe | ||
|
|
ade9af9ecd | ||
|
|
59f11a1b26 | ||
|
|
cc1d6e2b47 | ||
|
|
2655b1b3d1 | ||
|
|
053dd28f8c | ||
|
|
65e4cf83d8 | ||
|
|
419099318c | ||
|
|
972edd3a30 | ||
|
|
cc4125e766 | ||
|
|
da40cc9830 | ||
|
|
29d7e2dcfe | ||
|
|
3d906fd582 | ||
|
|
0cad43c18b | ||
|
|
c66b686a63 | ||
|
|
e2a1e3f327 | ||
|
|
2b5cf75a53 | ||
|
|
1c350ac87b | ||
|
|
ef6539909c | ||
|
|
47d7c6fe65 | ||
|
|
c94c5fbc95 | ||
|
|
63a833d114 | ||
|
|
72162128e2 | ||
|
|
a8f712c335 | ||
|
|
ea8888a685 | ||
|
|
2aecf69b67 | ||
|
|
1a4c24dd86 | ||
|
|
6cf2b45051 | ||
|
|
38dd2bdf6e | ||
|
|
8784f1da70 | ||
|
|
b9208ea94e | ||
|
|
dfb648b480 | ||
|
|
f7af4f06ea | ||
|
|
d98f9eb62c | ||
|
|
fef1335f51 | ||
|
|
59f14cbdd4 | ||
|
|
e8645c543f | ||
|
|
b92f6177e3 | ||
|
|
2888829a4f | ||
|
|
3d392ead19 | ||
|
|
a79b2bfa79 | ||
|
|
15e1e2f02e | ||
|
|
9e652803d0 | ||
|
|
7795fceb72 | ||
|
|
9f01f26ea6 | ||
|
|
abbc9a1d7a | ||
|
|
2c15befb8e | ||
|
|
ba8ea84c4e | ||
|
|
97912046da | ||
|
|
43e99c23e3 | ||
|
|
ffe14d75fc | ||
|
|
872ef66641 | ||
|
|
6363862ec2 | ||
|
|
775a112e83 | ||
|
|
7168904290 | ||
|
|
4213209b08 | ||
|
|
5dce91b7f6 | ||
|
|
6d7fb9f87c | ||
|
|
cc6c9dd8d1 | ||
|
|
21ebec52f3 | ||
|
|
11023ab225 | ||
|
|
fe97b15905 | ||
|
|
de8738aa03 | ||
|
|
568bbf9126 | ||
|
|
a2481652da | ||
|
|
33e3d3272d | ||
|
|
b909651c29 | ||
|
|
16794c5252 | ||
|
|
49ad270d88 | ||
|
|
df9b6cb7e8 | ||
|
|
c6c4551928 | ||
|
|
de84353eb0 | ||
|
|
6f05b80f34 | ||
|
|
797dc706e2 | ||
|
|
bdb615bcf9 | ||
|
|
1b98717b0e | ||
|
|
7bd1aedada | ||
|
|
34bf8f9d1f | ||
|
|
b07f70e9fe | ||
|
|
e635788955 | ||
|
|
bdb1cef3e5 | ||
|
|
e5a32e65c0 | ||
|
|
5fc77922b4 | ||
|
|
ce8add2895 | ||
|
|
88e1e5b770 | ||
|
|
76ecbd3497 | ||
|
|
e33c9b932f | ||
|
|
038f6caa04 | ||
|
|
36f5249d71 | ||
|
|
570702a5bd | ||
|
|
5d03c9c644 | ||
|
|
83906def4a | ||
|
|
33e0f25fb1 | ||
|
|
2080de4139 | ||
|
|
decaca889c | ||
|
|
794a39032f | ||
|
|
cc3cf17060 | ||
|
|
b07da4bfa8 | ||
|
|
4f52a4ee79 | ||
|
|
cf77b999a3 | ||
|
|
c9f062bdd9 | ||
|
|
12669f7ea0 | ||
|
|
03451d2a6e | ||
|
|
b5d7595f87 | ||
|
|
0d3d760a43 | ||
|
|
1cfc86e5ce | ||
|
|
938343323d | ||
|
|
37112715c0 | ||
|
|
bc80c10193 | ||
|
|
d989f48226 | ||
|
|
45bcbb3a3d | ||
|
|
f4a74e0254 | ||
|
|
ace83cf68d | ||
|
|
209b9b9a6f | ||
|
|
0d9dd6a33e | ||
|
|
e4137a031e | ||
|
|
41e9ea7e4f | ||
|
|
1a8b88973d | ||
|
|
3109e251b9 | ||
|
|
452ab280f1 | ||
|
|
34ecfbb846 | ||
|
|
11fb97d275 | ||
|
|
4bb30d075b | ||
|
|
f38af55c05 | ||
|
|
8a007376cc | ||
|
|
940a1dfc78 | ||
|
|
cbd64d1602 |
16
CHANGELOG
16
CHANGELOG
@@ -1,3 +1,19 @@
|
||||
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
|
||||
* Better autofill recognition
|
||||
* Fix entry not visually deleted in search
|
||||
* Fix hanged loading dialog
|
||||
* Fix auto open biometric prompt if comes from background
|
||||
* Minor fixes
|
||||
|
||||
KeePassDX(2.5)
|
||||
* First stable version of KeePassDX
|
||||
* Fork completely rewritten from the KeePassDroid project
|
||||
|
||||
@@ -11,8 +11,8 @@ android {
|
||||
applicationId "com.kunzisoft.keepass"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 29
|
||||
versionCode = 33
|
||||
versionName = "2.5"
|
||||
versionCode = 35
|
||||
versionName = "2.7"
|
||||
multiDexEnabled true
|
||||
|
||||
testApplicationId = "com.kunzisoft.keepass.tests"
|
||||
@@ -42,9 +42,6 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
}
|
||||
|
||||
flavorDimensions "version"
|
||||
productFlavors {
|
||||
libre {
|
||||
@@ -72,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" ]
|
||||
}
|
||||
@@ -88,42 +85,44 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
def room_version = "2.2.5"
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'androidx.biometric:biometric:1.0.1'
|
||||
implementation "androidx.core:core-ktx:1.2.0"
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
// To upgrade with style
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
// Database
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
// Crypto
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.65.01'
|
||||
// Time
|
||||
implementation 'joda-time:joda-time:2.9.9'
|
||||
implementation 'joda-time:joda-time:2.10.6'
|
||||
// Color
|
||||
implementation 'com.github.Kunzisoft:AndroidClearChroma:2.3'
|
||||
// Education
|
||||
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.0'
|
||||
// Apache Commons Collections
|
||||
implementation 'commons-collections:commons-collections:3.2.1'
|
||||
implementation 'org.apache.commons:commons-io:1.3.2'
|
||||
implementation 'commons-collections:commons-collections:3.2.2'
|
||||
// Apache Commons Codec
|
||||
implementation 'commons-codec:commons-codec:1.11'
|
||||
implementation 'commons-codec:commons-codec:1.14'
|
||||
// Icon pack
|
||||
implementation project(path: ':icon-pack-classic')
|
||||
implementation project(path: ':icon-pack-material')
|
||||
|
||||
// Tests
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'junit:junit:4.13'
|
||||
}
|
||||
|
||||
@@ -131,16 +131,30 @@
|
||||
android:name="com.kunzisoft.keepass.activities.AboutActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:label="@string/about" />
|
||||
<activity android:name="com.kunzisoft.keepass.settings.SettingsActivity" />
|
||||
<activity android:name="com.kunzisoft.keepass.autofill.AutofillLauncherActivity"
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.settings.SettingsActivity" />
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.activities.AutofillLauncherActivity"
|
||||
android:theme="@style/Theme.Transparent"
|
||||
android:configChanges="keyboardHidden" />
|
||||
<activity android:name="com.kunzisoft.keepass.settings.SettingsAdvancedUnlockActivity" />
|
||||
<activity android:name="com.kunzisoft.keepass.settings.AutofillSettingsActivity" />
|
||||
<activity android:name="com.kunzisoft.keepass.magikeyboard.KeyboardLauncherActivity"
|
||||
android:label="@string/keyboard_name"
|
||||
android:exported="true">
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.settings.SettingsAdvancedUnlockActivity" />
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.settings.AutofillSettingsActivity" />
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.activities.EntrySelectionLauncherActivity"
|
||||
android:theme="@style/Theme.Transparent">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.kunzisoft.keepass.settings.MagikeyboardSettingsActivity"
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.activities.MagikeyboardLauncherActivity"
|
||||
android:theme="@style/Theme.Transparent" />
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.settings.MagikeyboardSettingsActivity"
|
||||
android:label="@string/keyboard_setting_label">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
Binary file not shown.
@@ -17,7 +17,7 @@
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.autofill
|
||||
package com.kunzisoft.keepass.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.PendingIntent
|
||||
@@ -26,27 +26,45 @@ 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.activities.FileDatabaseSelectActivity
|
||||
import com.kunzisoft.keepass.activities.GroupActivity
|
||||
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
|
||||
AutofillHelper.checkAutoSearchInfo(this,
|
||||
SearchHelper.checkAutoSearchInfo(this,
|
||||
Database.getInstance(),
|
||||
searchInfo,
|
||||
{ items ->
|
||||
@@ -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,11 +167,18 @@ class EntryEditActivity : LockingActivity(),
|
||||
mNewEntry = mDatabase?.createEntry()
|
||||
}
|
||||
mParent = mDatabase?.getGroupById(it)
|
||||
// Add the default icon
|
||||
// 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)
|
||||
} else {
|
||||
mDatabase?.drawFactory?.let { iconFactory ->
|
||||
entryEditContentsView?.setDefaultIcon(iconFactory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the new entry after an orientation change
|
||||
if (savedInstanceState != null
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikIME
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
|
||||
/**
|
||||
* Activity to search or select entry in database,
|
||||
* Commonly used with Magikeyboard
|
||||
*/
|
||||
class EntrySelectionLauncherActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
var sharedWebDomain: String? = null
|
||||
|
||||
when (intent?.action) {
|
||||
Intent.ACTION_SEND -> {
|
||||
if ("text/plain" == intent.type) {
|
||||
// Retrieve web domain
|
||||
intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
|
||||
sharedWebDomain = Uri.parse(it).host
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
// Setting to integrate Magikeyboard
|
||||
val searchShareForMagikeyboard = PreferencesUtil.isKeyboardSearchShareEnable(this)
|
||||
|
||||
// Build search param
|
||||
val searchInfo = SearchInfo().apply {
|
||||
webDomain = sharedWebDomain
|
||||
}
|
||||
|
||||
// If database is open
|
||||
SearchHelper.checkAutoSearchInfo(this,
|
||||
Database.getInstance(),
|
||||
searchInfo,
|
||||
{ items ->
|
||||
// Items found
|
||||
if (searchShareForMagikeyboard) {
|
||||
if (items.size == 1) {
|
||||
// Automatically populate keyboard
|
||||
val entryPopulate = items[0]
|
||||
populateKeyboardAndMoveAppToBackground(this,
|
||||
entryPopulate,
|
||||
intent)
|
||||
} else {
|
||||
// Select the one we want
|
||||
GroupActivity.launchForEntrySelectionResult(this,
|
||||
true,
|
||||
searchInfo)
|
||||
}
|
||||
} else {
|
||||
GroupActivity.launch(this,
|
||||
true,
|
||||
searchInfo)
|
||||
}
|
||||
},
|
||||
{
|
||||
// Show the database UI to select the entry
|
||||
if (searchShareForMagikeyboard) {
|
||||
GroupActivity.launchForEntrySelectionResult(this,
|
||||
false,
|
||||
searchInfo)
|
||||
} else {
|
||||
GroupActivity.launch(this,
|
||||
false,
|
||||
searchInfo)
|
||||
}
|
||||
},
|
||||
{
|
||||
// If database not open
|
||||
if (searchShareForMagikeyboard) {
|
||||
FileDatabaseSelectActivity.launchForEntrySelectionResult(this,
|
||||
searchInfo)
|
||||
} else {
|
||||
FileDatabaseSelectActivity.launch(this,
|
||||
searchInfo)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
finish()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
}
|
||||
|
||||
fun populateKeyboardAndMoveAppToBackground(activity: Activity,
|
||||
entry: EntryInfo,
|
||||
intent: Intent,
|
||||
toast: Boolean = true) {
|
||||
// Populate Magikeyboard with entry
|
||||
MagikIME.addEntryAndLaunchNotificationIfAllowed(activity, entry, toast)
|
||||
// Consume the selection mode
|
||||
EntrySelectionHelper.removeEntrySelectionModeFromIntent(intent)
|
||||
activity.moveTaskToBack(true)
|
||||
}
|
||||
@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.activities
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.assist.AssistStructure
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
@@ -41,12 +42,12 @@ import com.google.android.material.snackbar.Snackbar
|
||||
import com.kunzisoft.keepass.R
|
||||
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
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper.KEY_SEARCH_INFO
|
||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation
|
||||
@@ -58,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
|
||||
@@ -95,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 {
|
||||
@@ -156,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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,23 +192,30 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
}
|
||||
|
||||
private fun launchPasswordActivity(databaseUri: Uri, keyFile: Uri?) {
|
||||
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
|
||||
EntrySelectionHelper.doEntrySelectionAction(intent,
|
||||
{
|
||||
try {
|
||||
PasswordActivity.launch(this@FileDatabaseSelectActivity,
|
||||
databaseUri, keyFile)
|
||||
databaseUri, keyFile,
|
||||
searchInfo)
|
||||
} catch (e: FileNotFoundException) {
|
||||
fileNoFoundAction(e)
|
||||
}
|
||||
// Remove the search info from intent
|
||||
if (searchInfo != null) {
|
||||
finish()
|
||||
}
|
||||
},
|
||||
{
|
||||
try {
|
||||
PasswordActivity.launchForKeyboardResult(this@FileDatabaseSelectActivity,
|
||||
databaseUri, keyFile)
|
||||
finish()
|
||||
databaseUri, keyFile,
|
||||
searchInfo)
|
||||
} catch (e: FileNotFoundException) {
|
||||
fileNoFoundAction(e)
|
||||
}
|
||||
finish()
|
||||
},
|
||||
{ assistStructure ->
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
@@ -220,23 +223,27 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
PasswordActivity.launchForAutofillResult(this@FileDatabaseSelectActivity,
|
||||
databaseUri, keyFile,
|
||||
assistStructure,
|
||||
intent.getParcelableExtra(KEY_SEARCH_INFO))
|
||||
searchInfo)
|
||||
} catch (e: FileNotFoundException) {
|
||||
fileNoFoundAction(e)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun launchGroupActivity(readOnly: Boolean) {
|
||||
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
|
||||
EntrySelectionHelper.doEntrySelectionAction(intent,
|
||||
{
|
||||
GroupActivity.launch(this@FileDatabaseSelectActivity,
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
},
|
||||
{
|
||||
GroupActivity.launchForKeyboardSelection(this@FileDatabaseSelectActivity,
|
||||
GroupActivity.launchForEntrySelectionResult(this@FileDatabaseSelectActivity,
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
// Do not keep history
|
||||
finish()
|
||||
@@ -245,7 +252,8 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
GroupActivity.launchForAutofillResult(this@FileDatabaseSelectActivity,
|
||||
assistStructure,
|
||||
intent.getParcelableExtra(KEY_SEARCH_INFO),
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
}
|
||||
})
|
||||
@@ -259,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 ->
|
||||
@@ -291,6 +313,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
// Register progress task
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
// Unregister progress task
|
||||
@@ -368,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)) }
|
||||
|
||||
@@ -377,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()
|
||||
},
|
||||
@@ -416,18 +442,30 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
|
||||
/*
|
||||
* -------------------------
|
||||
* No Standard Launch, pass by PasswordActivity
|
||||
* Launch only to standard search, else pass by PasswordActivity
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
fun launch(context: Context,
|
||||
searchInfo: SearchInfo? = null) {
|
||||
val intent = Intent(context, FileDatabaseSelectActivity::class.java)
|
||||
searchInfo?.let {
|
||||
intent.putExtra(KEY_SEARCH_INFO, it)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------
|
||||
* Keyboard Launch
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
fun launchForKeyboardSelection(activity: Activity) {
|
||||
EntrySelectionHelper.startActivityForEntrySelection(activity, Intent(activity, FileDatabaseSelectActivity::class.java))
|
||||
fun launchForEntrySelectionResult(activity: Activity,
|
||||
searchInfo: SearchInfo? = null) {
|
||||
EntrySelectionHelper.startActivityForEntrySelectionResult(activity,
|
||||
Intent(activity, FileDatabaseSelectActivity::class.java),
|
||||
searchInfo)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -439,7 +477,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
fun launchForAutofillResult(activity: Activity,
|
||||
assistStructure: AssistStructure,
|
||||
searchInfo: SearchInfo?) {
|
||||
searchInfo: SearchInfo? = null) {
|
||||
AutofillHelper.startActivityForAutofillResult(activity,
|
||||
Intent(activity, FileDatabaseSelectActivity::class.java),
|
||||
assistStructure,
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.SortDialogFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper.KEY_SEARCH_INFO
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
import com.kunzisoft.keepass.activities.lock.LockingActivity
|
||||
import com.kunzisoft.keepass.adapters.SearchEntryCursorAdapter
|
||||
@@ -61,8 +62,8 @@ import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.education.GroupActivityEducation
|
||||
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikIME
|
||||
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 {
|
||||
@@ -145,6 +144,11 @@ class GroupActivity : LockingActivity(),
|
||||
toolbar?.title = ""
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
// Retrieve the textColor to tint the icon
|
||||
val taTextColor = theme.obtainStyledAttributes(intArrayOf(R.attr.textColorInverse))
|
||||
mIconColor = taTextColor.getColor(0, Color.WHITE)
|
||||
taTextColor.recycle()
|
||||
|
||||
// Focus view to reinitialize timeout
|
||||
resetAppTimeoutWhenViewFocusedOrChanged(addNodeButtonView)
|
||||
|
||||
@@ -171,14 +175,6 @@ class GroupActivity : LockingActivity(),
|
||||
return
|
||||
}
|
||||
|
||||
// Update last access time.
|
||||
mCurrentGroup?.touch(modified = false, touchParents = false)
|
||||
|
||||
// Retrieve the textColor to tint the icon
|
||||
val taTextColor = theme.obtainStyledAttributes(intArrayOf(R.attr.textColorInverse))
|
||||
mIconColor = taTextColor.getColor(0, Color.WHITE)
|
||||
taTextColor.recycle()
|
||||
|
||||
var fragmentTag = LIST_NODES_FRAGMENT_TAG
|
||||
if (mCurrentGroupIsASearch)
|
||||
fragmentTag = SEARCH_FRAGMENT_TAG
|
||||
@@ -195,6 +191,14 @@ class GroupActivity : LockingActivity(),
|
||||
fragmentTag)
|
||||
.commit()
|
||||
|
||||
// Update last access time.
|
||||
mCurrentGroup?.touch(modified = false, touchParents = false)
|
||||
|
||||
// To relaunch the activity with ACTION_SEARCH
|
||||
if (manageSearchInfoIntent(intent)) {
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
// Add listeners to the add buttons
|
||||
addNodeButtonView?.setAddGroupClickListener(View.OnClickListener {
|
||||
GroupEditDialogFragment.build()
|
||||
@@ -223,6 +227,8 @@ class GroupActivity : LockingActivity(),
|
||||
newNodes = getListNodesFromBundle(database, newNodesBundle)
|
||||
}
|
||||
|
||||
refreshSearchGroup()
|
||||
|
||||
when (actionTask) {
|
||||
ACTION_DATABASE_UPDATE_GROUP_TASK -> {
|
||||
if (result.isSuccess) {
|
||||
@@ -277,11 +283,14 @@ class GroupActivity : LockingActivity(),
|
||||
super.onNewIntent(intent)
|
||||
|
||||
intent?.let { intentNotNull ->
|
||||
// To transform KEY_SEARCH_INFO in ACTION_SEARCH
|
||||
manageSearchInfoIntent(intentNotNull)
|
||||
Log.d(TAG, "setNewIntent: $intentNotNull")
|
||||
setIntent(intentNotNull)
|
||||
mCurrentGroupIsASearch = if (Intent.ACTION_SEARCH == intentNotNull.action) {
|
||||
// only one instance of search in backstack
|
||||
openSearchGroup(retrieveCurrentGroup(intentNotNull, null))
|
||||
deletePreviousSearchGroup()
|
||||
openGroup(retrieveCurrentGroup(intentNotNull, null), true)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -289,8 +298,24 @@ class GroupActivity : LockingActivity(),
|
||||
}
|
||||
}
|
||||
|
||||
private fun openSearchGroup(group: Group?) {
|
||||
/**
|
||||
* Transform the KEY_SEARCH_INFO in ACTION_SEARCH, return true if KEY_SEARCH_INFO was present
|
||||
*/
|
||||
private fun manageSearchInfoIntent(intent: Intent): Boolean {
|
||||
// To relaunch the activity as ACTION_SEARCH
|
||||
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
|
||||
val autoSearch = intent.getBooleanExtra(AUTO_SEARCH_KEY, false)
|
||||
if (searchInfo != null && autoSearch) {
|
||||
intent.action = Intent.ACTION_SEARCH
|
||||
intent.putExtra(SearchManager.QUERY, searchInfo.getSearchString(this))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun deletePreviousSearchGroup() {
|
||||
// Delete the previous search fragment
|
||||
try {
|
||||
val searchFragment = supportFragmentManager.findFragmentByTag(SEARCH_FRAGMENT_TAG)
|
||||
if (searchFragment != null) {
|
||||
if (supportFragmentManager
|
||||
@@ -298,11 +323,9 @@ class GroupActivity : LockingActivity(),
|
||||
FragmentManager.POP_BACK_STACK_INCLUSIVE))
|
||||
supportFragmentManager.beginTransaction().remove(searchFragment).commit()
|
||||
}
|
||||
openGroup(group, true)
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "unable to remove previous search fragment", exception)
|
||||
}
|
||||
|
||||
private fun openChildGroup(group: Group) {
|
||||
openGroup(group, false)
|
||||
}
|
||||
|
||||
private fun openGroup(group: Group?, isASearch: Boolean) {
|
||||
@@ -329,6 +352,12 @@ class GroupActivity : LockingActivity(),
|
||||
fragmentTransaction.addToBackStack(fragmentTag)
|
||||
fragmentTransaction.commit()
|
||||
|
||||
if (mSelectionMode)
|
||||
mSelectionModeCountBackStack++
|
||||
|
||||
// Update last access time.
|
||||
group?.touch(modified = false, touchParents = false)
|
||||
|
||||
mListNodesFragment = newListNodeFragment
|
||||
mCurrentGroup = group
|
||||
assignGroupViewElements()
|
||||
@@ -346,6 +375,12 @@ class GroupActivity : LockingActivity(),
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
private fun refreshSearchGroup() {
|
||||
deletePreviousSearchGroup()
|
||||
if (mCurrentGroupIsASearch)
|
||||
openGroup(retrieveCurrentGroup(intent, null), true)
|
||||
}
|
||||
|
||||
private fun retrieveCurrentGroup(intent: Intent, savedInstanceState: Bundle?): Group? {
|
||||
|
||||
// Force read only if the database is like that
|
||||
@@ -426,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 {
|
||||
|
||||
@@ -450,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)) {
|
||||
@@ -468,7 +510,8 @@ class GroupActivity : LockingActivity(),
|
||||
override fun onNodeClick(node: Node) {
|
||||
when (node.type) {
|
||||
Type.GROUP -> try {
|
||||
openChildGroup(node as Group)
|
||||
// Open child group
|
||||
openGroup(node as Group, false)
|
||||
} catch (e: ClassCastException) {
|
||||
Log.e(TAG, "Node can't be cast in Group")
|
||||
}
|
||||
@@ -480,14 +523,13 @@ class GroupActivity : LockingActivity(),
|
||||
EntryActivity.launch(this@GroupActivity, entryVersioned, mReadOnly)
|
||||
},
|
||||
{
|
||||
rebuildListNodes()
|
||||
// Populate Magikeyboard with entry
|
||||
mDatabase?.let { database ->
|
||||
MagikIME.addEntryAndLaunchNotificationIfAllowed(this@GroupActivity,
|
||||
entryVersioned.getEntryInfo(database))
|
||||
populateKeyboardAndMoveAppToBackground(this@GroupActivity,
|
||||
entryVersioned.getEntryInfo(database),
|
||||
intent)
|
||||
}
|
||||
// Consume the selection mode
|
||||
EntrySelectionHelper.removeEntrySelectionModeFromIntent(intent)
|
||||
moveTaskToBack(true)
|
||||
},
|
||||
{
|
||||
// Build response with the entry selected
|
||||
@@ -616,6 +658,7 @@ class GroupActivity : LockingActivity(),
|
||||
if (database != null
|
||||
&& database.isRecycleBinEnabled
|
||||
&& database.recycleBin != mCurrentGroup) {
|
||||
|
||||
mProgressDialogThread?.startDatabaseDeleteNodes(
|
||||
nodes,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
@@ -667,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
|
||||
@@ -877,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)
|
||||
}
|
||||
@@ -921,12 +960,29 @@ class GroupActivity : LockingActivity(),
|
||||
mListNodesFragment?.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
private fun removeSearchInIntent(intent: Intent) {
|
||||
if (Intent.ACTION_SEARCH == intent.action) {
|
||||
private fun rebuildListNodes() {
|
||||
mListNodesFragment = supportFragmentManager.findFragmentByTag(LIST_NODES_FRAGMENT_TAG) as ListNodesFragment?
|
||||
// to refresh fragment
|
||||
mListNodesFragment?.rebuildList()
|
||||
mCurrentGroup = mListNodesFragment?.mainGroup
|
||||
// Remove search in intent
|
||||
deletePreviousSearchGroup()
|
||||
mCurrentGroupIsASearch = false
|
||||
if (Intent.ACTION_SEARCH == intent.action) {
|
||||
intent.action = Intent.ACTION_DEFAULT
|
||||
intent.removeExtra(SearchManager.QUERY)
|
||||
}
|
||||
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() {
|
||||
@@ -934,24 +990,23 @@ class GroupActivity : LockingActivity(),
|
||||
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 {
|
||||
moveTaskToBack(true)
|
||||
// To restore standard mode
|
||||
EntrySelectionHelper.removeEntrySelectionModeFromIntent(intent)
|
||||
backToTheAppCaller()
|
||||
}
|
||||
}
|
||||
|
||||
mListNodesFragment = supportFragmentManager.findFragmentByTag(LIST_NODES_FRAGMENT_TAG) as ListNodesFragment?
|
||||
// to refresh fragment
|
||||
mListNodesFragment?.rebuildList()
|
||||
mCurrentGroup = mListNodesFragment?.mainGroup
|
||||
removeSearchInIntent(intent)
|
||||
assignGroupViewElements()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,42 +1019,35 @@ 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?,
|
||||
searchInfo: SearchInfo?,
|
||||
readOnly: Boolean,
|
||||
intentBuildLauncher: (Intent) -> Unit) {
|
||||
val intent = Intent(context, GroupActivity::class.java)
|
||||
if (group != null) {
|
||||
intent.putExtra(GROUP_ID_KEY, group.nodeId)
|
||||
}
|
||||
if (searchInfo != null) {
|
||||
intent.action = Intent.ACTION_SEARCH
|
||||
val searchQuery = searchInfo.webDomain ?: searchInfo.applicationId
|
||||
intent.putExtra(SearchManager.QUERY, searchQuery)
|
||||
}
|
||||
ReadOnlyHelper.putReadOnlyInIntent(intent, readOnly)
|
||||
intentBuildLauncher.invoke(intent)
|
||||
}
|
||||
|
||||
private fun checkTimeAndBuildIntent(activity: Activity,
|
||||
group: Group?,
|
||||
searchInfo: SearchInfo?,
|
||||
readOnly: Boolean,
|
||||
intentBuildLauncher: (Intent) -> Unit) {
|
||||
if (TimeoutHelper.checkTimeAndLockIfTimeout(activity)) {
|
||||
buildIntent(activity, group, searchInfo, readOnly, intentBuildLauncher)
|
||||
buildIntent(activity, group, readOnly, intentBuildLauncher)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkTimeAndBuildIntent(context: Context,
|
||||
group: Group?,
|
||||
searchInfo: SearchInfo?,
|
||||
readOnly: Boolean,
|
||||
intentBuildLauncher: (Intent) -> Unit) {
|
||||
if (TimeoutHelper.checkTime(context)) {
|
||||
buildIntent(context, group, searchInfo, readOnly, intentBuildLauncher)
|
||||
buildIntent(context, group, readOnly, intentBuildLauncher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1009,8 +1057,14 @@ class GroupActivity : LockingActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launch(context: Context,
|
||||
autoSearch: Boolean = false,
|
||||
searchInfo: SearchInfo? = null,
|
||||
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
|
||||
checkTimeAndBuildIntent(context, null, null, readOnly) { intent ->
|
||||
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
|
||||
searchInfo?.let {
|
||||
intent.putExtra(KEY_SEARCH_INFO, it)
|
||||
}
|
||||
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
@@ -1020,11 +1074,13 @@ class GroupActivity : LockingActivity(),
|
||||
* Keyboard Launch
|
||||
* -------------------------
|
||||
*/
|
||||
// TODO implement pre search to directly open the direct group #280
|
||||
fun launchForKeyboardSelection(context: Context,
|
||||
fun launchForEntrySelectionResult(context: Context,
|
||||
autoSearch: Boolean = false,
|
||||
searchInfo: SearchInfo? = null,
|
||||
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
|
||||
checkTimeAndBuildIntent(context, null, null, readOnly) { intent ->
|
||||
EntrySelectionHelper.startActivityForEntrySelection(context, intent)
|
||||
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
|
||||
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
|
||||
EntrySelectionHelper.startActivityForEntrySelectionResult(context, intent, searchInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1036,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, searchInfo, readOnly) { intent ->
|
||||
checkTimeAndBuildIntent(activity, null, readOnly) { intent ->
|
||||
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
|
||||
AutofillHelper.startActivityForAutofillResult(activity, intent, assistStructure, searchInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
* Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
@@ -17,24 +17,31 @@
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.magikeyboard
|
||||
package com.kunzisoft.keepass.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.kunzisoft.keepass.activities.FileDatabaseSelectActivity
|
||||
import com.kunzisoft.keepass.activities.GroupActivity
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
|
||||
class KeyboardLauncherActivity : AppCompatActivity() {
|
||||
/**
|
||||
* Activity to select entry in database and populate it in Magikeyboard
|
||||
*/
|
||||
class MagikeyboardLauncherActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (Database.getInstance().loaded && TimeoutHelper.checkTime(this))
|
||||
GroupActivity.launchForKeyboardSelection(this)
|
||||
else {
|
||||
SearchHelper.checkAutoSearchInfo(this,
|
||||
Database.getInstance(),
|
||||
null,
|
||||
{},
|
||||
{
|
||||
GroupActivity.launchForEntrySelectionResult(this)
|
||||
},
|
||||
{
|
||||
// Pass extra to get entry
|
||||
FileDatabaseSelectActivity.launchForKeyboardSelection(this)
|
||||
FileDatabaseSelectActivity.launchForEntrySelectionResult(this)
|
||||
}
|
||||
)
|
||||
finish()
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
@@ -42,18 +42,19 @@ import com.google.android.material.snackbar.Snackbar
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog
|
||||
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.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
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper.KEY_SEARCH_INFO
|
||||
import com.kunzisoft.keepass.biometric.AdvancedUnlockedManager
|
||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.education.PasswordActivityEducation
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
|
||||
@@ -72,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
|
||||
@@ -110,6 +110,7 @@ open class PasswordActivity : StylishActivity() {
|
||||
private var mProgressDialogThread: ProgressDialogThread? = null
|
||||
|
||||
private var advancedUnlockedManager: AdvancedUnlockedManager? = null
|
||||
private var mAllowAutoOpenBiometricPrompt: Boolean = true
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -122,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)
|
||||
@@ -166,6 +166,10 @@ open class PasswordActivity : StylishActivity() {
|
||||
mDatabaseKeyFileUri = UriUtil.parse(savedInstanceState.getString(KEY_KEYFILE))
|
||||
}
|
||||
|
||||
if (savedInstanceState?.containsKey(ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT) == true) {
|
||||
mAllowAutoOpenBiometricPrompt = savedInstanceState.getBoolean(ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT)
|
||||
}
|
||||
|
||||
mProgressDialogThread = ProgressDialogThread(this).apply {
|
||||
onActionFinish = { actionTask, result ->
|
||||
when (actionTask) {
|
||||
@@ -255,21 +259,52 @@ open class PasswordActivity : StylishActivity() {
|
||||
}
|
||||
|
||||
private fun launchGroupActivity() {
|
||||
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
|
||||
EntrySelectionHelper.doEntrySelectionAction(intent,
|
||||
{
|
||||
GroupActivity.launch(this@PasswordActivity,
|
||||
true,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
// Finish activity if no search info
|
||||
if (searchInfo != null) {
|
||||
finish()
|
||||
}
|
||||
},
|
||||
{
|
||||
SearchHelper.checkAutoSearchInfo(this,
|
||||
Database.getInstance(),
|
||||
searchInfo,
|
||||
{ items ->
|
||||
// Response is build
|
||||
if (items.size == 1) {
|
||||
populateKeyboardAndMoveAppToBackground(this@PasswordActivity,
|
||||
items[0],
|
||||
intent)
|
||||
} else {
|
||||
// Select the one we want
|
||||
GroupActivity.launchForEntrySelectionResult(this,
|
||||
true,
|
||||
searchInfo)
|
||||
}
|
||||
},
|
||||
{
|
||||
// Here no search info found, disable auto search
|
||||
GroupActivity.launchForEntrySelectionResult(this@PasswordActivity,
|
||||
false,
|
||||
searchInfo,
|
||||
readOnly)
|
||||
},
|
||||
{
|
||||
GroupActivity.launchForKeyboardSelection(this@PasswordActivity,
|
||||
readOnly)
|
||||
// Simply close if database not opened, normally not happened
|
||||
}
|
||||
)
|
||||
// Do not keep history
|
||||
finish()
|
||||
},
|
||||
{ assistStructure ->
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
|
||||
AutofillHelper.checkAutoSearchInfo(this,
|
||||
SearchHelper.checkAutoSearchInfo(this,
|
||||
Database.getInstance(),
|
||||
searchInfo,
|
||||
{ items ->
|
||||
@@ -278,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)
|
||||
},
|
||||
{
|
||||
@@ -304,10 +340,11 @@ open class PasswordActivity : StylishActivity() {
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
if (Database.getInstance().loaded)
|
||||
if (Database.getInstance().loaded) {
|
||||
launchGroupActivity()
|
||||
|
||||
} else {
|
||||
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
|
||||
|
||||
// If the database isn't accessible make sure to clear the password field, if it
|
||||
@@ -316,23 +353,18 @@ open class PasswordActivity : StylishActivity() {
|
||||
clearCredentialsViews()
|
||||
}
|
||||
|
||||
// For check shutdown
|
||||
super.onResume()
|
||||
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
|
||||
// Don't allow auto open prompt if lock become when UI visible
|
||||
mAllowAutoOpenBiometricPrompt = if (LockingActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK == true)
|
||||
false
|
||||
else
|
||||
mAllowAutoOpenBiometricPrompt
|
||||
|
||||
initUriFromIntent()
|
||||
|
||||
checkPermission()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putBoolean(KEY_PERMISSION_ASKED, mPermissionAsked)
|
||||
mDatabaseKeyFileUri?.let {
|
||||
outState.putString(KEY_KEYFILE, it.toString())
|
||||
}
|
||||
ReadOnlyHelper.onSaveInstanceState(outState, readOnly)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
private fun initUriFromIntent() {
|
||||
@@ -438,6 +470,7 @@ open class PasswordActivity : StylishActivity() {
|
||||
}
|
||||
})
|
||||
}
|
||||
advancedUnlockedManager?.isBiometricPromptAutoOpenEnable = mAllowAutoOpenBiometricPrompt
|
||||
advancedUnlockedManager?.checkBiometricAvailability()
|
||||
biometricInitialize = true
|
||||
} else {
|
||||
@@ -499,14 +532,26 @@ open class PasswordActivity : StylishActivity() {
|
||||
override fun onPause() {
|
||||
mProgressDialogThread?.unregisterProgressTask()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
advancedUnlockedManager?.destroy()
|
||||
advancedUnlockedManager = null
|
||||
}
|
||||
|
||||
// Reinit locking activity UI variable
|
||||
LockingActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = null
|
||||
mAllowAutoOpenBiometricPrompt = true
|
||||
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
advancedUnlockedManager?.destroy()
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putBoolean(KEY_PERMISSION_ASKED, mPermissionAsked)
|
||||
mDatabaseKeyFileUri?.let {
|
||||
outState.putString(KEY_KEYFILE, it.toString())
|
||||
}
|
||||
super.onDestroy()
|
||||
ReadOnlyHelper.onSaveInstanceState(outState, readOnly)
|
||||
outState.putBoolean(ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT, false)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
private fun verifyCheckboxesAndLoadDatabase(cipherDatabaseEntity: CipherDatabaseEntity? = null) {
|
||||
@@ -580,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
|
||||
@@ -715,6 +761,8 @@ open class PasswordActivity : StylishActivity() {
|
||||
data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
mAllowAutoOpenBiometricPrompt = false
|
||||
|
||||
// To get entry in result
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data)
|
||||
@@ -733,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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -754,6 +805,8 @@ open class PasswordActivity : StylishActivity() {
|
||||
private const val KEY_PERMISSION_ASKED = "KEY_PERMISSION_ASKED"
|
||||
private const val WRITE_EXTERNAL_STORAGE_REQUEST = 647
|
||||
|
||||
private const val ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT = "ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT"
|
||||
|
||||
private fun buildAndLaunchIntent(activity: Activity, databaseFile: Uri, keyFile: Uri?,
|
||||
intentBuildLauncher: (Intent) -> Unit) {
|
||||
val intent = Intent(activity, PasswordActivity::class.java)
|
||||
@@ -773,8 +826,12 @@ open class PasswordActivity : StylishActivity() {
|
||||
fun launch(
|
||||
activity: Activity,
|
||||
databaseFile: Uri,
|
||||
keyFile: Uri?) {
|
||||
keyFile: Uri?,
|
||||
searchInfo: SearchInfo?) {
|
||||
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
|
||||
searchInfo?.let {
|
||||
intent.putExtra(KEY_SEARCH_INFO, it)
|
||||
}
|
||||
activity.startActivity(intent)
|
||||
}
|
||||
}
|
||||
@@ -789,9 +846,13 @@ open class PasswordActivity : StylishActivity() {
|
||||
fun launchForKeyboardResult(
|
||||
activity: Activity,
|
||||
databaseFile: Uri,
|
||||
keyFile: Uri?) {
|
||||
keyFile: Uri?,
|
||||
searchInfo: SearchInfo?) {
|
||||
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
|
||||
EntrySelectionHelper.startActivityForEntrySelection(activity, intent)
|
||||
EntrySelectionHelper.startActivityForEntrySelectionResult(
|
||||
activity,
|
||||
intent,
|
||||
searchInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -818,7 +879,7 @@ open class PasswordActivity : StylishActivity() {
|
||||
searchInfo)
|
||||
}
|
||||
} else {
|
||||
launch(activity, databaseFile, keyFile)
|
||||
launch(activity, databaseFile, keyFile, searchInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,15 +24,22 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
|
||||
object EntrySelectionHelper {
|
||||
|
||||
private const val EXTRA_ENTRY_SELECTION_MODE = "com.kunzisoft.keepass.extra.ENTRY_SELECTION_MODE"
|
||||
private const val DEFAULT_ENTRY_SELECTION_MODE = false
|
||||
// Key to retrieve search in intent
|
||||
const val KEY_SEARCH_INFO = "KEY_SEARCH_INFO"
|
||||
|
||||
fun startActivityForEntrySelection(context: Context, intent: Intent) {
|
||||
fun startActivityForEntrySelectionResult(context: Context,
|
||||
intent: Intent,
|
||||
searchInfo: SearchInfo?) {
|
||||
addEntrySelectionModeExtraInIntent(intent)
|
||||
// only to avoid visible flickering when redirecting
|
||||
searchInfo?.let {
|
||||
intent.putExtra(KEY_SEARCH_INFO, it)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,26 +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() {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val TAG = "LockingActivity"
|
||||
|
||||
const val RESULT_EXIT_LOCK = 1450
|
||||
|
||||
const val TIMEOUT_ENABLE_KEY = "TIMEOUT_ENABLE_KEY"
|
||||
const val TIMEOUT_ENABLE_KEY_DEFAULT = true
|
||||
}
|
||||
abstract class LockingActivity : SpecialModeActivity() {
|
||||
|
||||
protected var mTimeoutEnable: Boolean = true
|
||||
|
||||
@@ -51,11 +40,14 @@ abstract class LockingActivity : StylishActivity() {
|
||||
private var mExitLock: Boolean = false
|
||||
|
||||
// Force readOnly if Entry Selection mode
|
||||
protected var mReadOnly: Boolean = false
|
||||
protected var mReadOnly: Boolean
|
||||
get() {
|
||||
return field || mSelectionMode
|
||||
return mReadOnlyToSave || mSelectionMode
|
||||
}
|
||||
protected var mSelectionMode: Boolean = false
|
||||
set(value) {
|
||||
mReadOnlyToSave = value
|
||||
}
|
||||
private var mReadOnlyToSave: Boolean = false
|
||||
protected var mAutoSaveEnable: Boolean = true
|
||||
|
||||
var mProgressDialogThread: ProgressDialogThread? = null
|
||||
@@ -75,6 +67,8 @@ abstract class LockingActivity : StylishActivity() {
|
||||
if (mTimeoutEnable) {
|
||||
mLockReceiver = LockReceiver {
|
||||
closeDatabase()
|
||||
if (LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK == null)
|
||||
LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = LOCKING_ACTIVITY_UI_VISIBLE
|
||||
// Add onActivityForResult response
|
||||
setResult(RESULT_EXIT_LOCK)
|
||||
finish()
|
||||
@@ -83,7 +77,6 @@ abstract class LockingActivity : StylishActivity() {
|
||||
}
|
||||
|
||||
mExitLock = false
|
||||
mReadOnly = ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrIntent(savedInstanceState, intent)
|
||||
|
||||
mProgressDialogThread = ProgressDialogThread(this)
|
||||
}
|
||||
@@ -104,7 +97,7 @@ abstract class LockingActivity : StylishActivity() {
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
|
||||
// To refresh when back to normal workflow from selection workflow
|
||||
mSelectionMode = EntrySelectionHelper.retrieveEntrySelectionModeFromIntent(intent)
|
||||
mReadOnlyToSave = ReadOnlyHelper.retrieveReadOnlyFromIntent(intent)
|
||||
mAutoSaveEnable = PreferencesUtil.isAutoSaveDatabaseEnabled(this)
|
||||
|
||||
invalidateOptionsMenu()
|
||||
@@ -124,15 +117,18 @@ abstract class LockingActivity : StylishActivity() {
|
||||
if (!mExitLock)
|
||||
TimeoutHelper.recordTime(this)
|
||||
}
|
||||
|
||||
LOCKING_ACTIVITY_UI_VISIBLE = true
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
ReadOnlyHelper.onSaveInstanceState(outState, mReadOnly)
|
||||
outState.putBoolean(TIMEOUT_ENABLE_KEY, mTimeoutEnable)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
LOCKING_ACTIVITY_UI_VISIBLE = false
|
||||
|
||||
mProgressDialogThread?.unregisterProgressTask()
|
||||
|
||||
super.onPause()
|
||||
@@ -180,4 +176,17 @@ abstract class LockingActivity : StylishActivity() {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val TAG = "LockingActivity"
|
||||
|
||||
const val RESULT_EXIT_LOCK = 1450
|
||||
|
||||
const val TIMEOUT_ENABLE_KEY = "TIMEOUT_ENABLE_KEY"
|
||||
const val TIMEOUT_ENABLE_KEY_DEFAULT = true
|
||||
|
||||
private var LOCKING_ACTIVITY_UI_VISIBLE = false
|
||||
var LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK: Boolean? = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.SortedList
|
||||
import androidx.recyclerview.widget.SortedListAdapterCallback
|
||||
@@ -73,7 +74,11 @@ class NodeAdapter (private val context: Context)
|
||||
|
||||
private val mDatabase: Database
|
||||
|
||||
@ColorInt
|
||||
private val contentSelectionColor: Int
|
||||
@ColorInt
|
||||
private val iconGroupColor: Int
|
||||
@ColorInt
|
||||
private val iconEntryColor: Int
|
||||
|
||||
/**
|
||||
@@ -97,6 +102,10 @@ class NodeAdapter (private val context: Context)
|
||||
// Database
|
||||
this.mDatabase = Database.getInstance()
|
||||
|
||||
// Color of content selection
|
||||
val taContentSelectionColor = context.theme.obtainStyledAttributes(intArrayOf(R.attr.textColorInverse))
|
||||
this.contentSelectionColor = taContentSelectionColor.getColor(0, Color.WHITE)
|
||||
taContentSelectionColor.recycle()
|
||||
// Retrieve the color to tint the icon
|
||||
val taTextColorPrimary = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColorPrimary))
|
||||
this.iconGroupColor = taTextColorPrimary.getColor(0, Color.BLACK)
|
||||
@@ -280,11 +289,18 @@ class NodeAdapter (private val context: Context)
|
||||
|
||||
override fun onBindViewHolder(holder: NodeViewHolder, position: Int) {
|
||||
val subNode = nodeSortedList.get(position)
|
||||
|
||||
// Node selection
|
||||
holder.container.isSelected = actionNodesList.contains(subNode)
|
||||
|
||||
// Assign image
|
||||
val iconColor = when (subNode.type) {
|
||||
val iconColor = if (holder.container.isSelected)
|
||||
contentSelectionColor
|
||||
else when (subNode.type) {
|
||||
Type.GROUP -> iconGroupColor
|
||||
Type.ENTRY -> iconEntryColor
|
||||
}
|
||||
holder.imageIdentifier?.setColorFilter(iconColor)
|
||||
holder.icon.apply {
|
||||
assignDatabaseIcon(mDatabase.drawFactory, subNode.icon, iconColor)
|
||||
// Relative size of the icon
|
||||
@@ -347,8 +363,6 @@ class NodeAdapter (private val context: Context)
|
||||
holder.container.setOnLongClickListener {
|
||||
nodeClickCallback?.onNodeLongClick(subNode) ?: false
|
||||
}
|
||||
|
||||
holder.container.isSelected = actionNodesList.contains(subNode)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
@@ -372,6 +386,7 @@ class NodeAdapter (private val context: Context)
|
||||
|
||||
class NodeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
var container: View = itemView.findViewById(R.id.node_container)
|
||||
var imageIdentifier: ImageView? = itemView.findViewById(R.id.node_image_identifier)
|
||||
var icon: ImageView = itemView.findViewById(R.id.node_icon)
|
||||
var text: TextView = itemView.findViewById(R.id.node_text)
|
||||
var subText: TextView = itemView.findViewById(R.id.node_subtext)
|
||||
|
||||
@@ -34,14 +34,12 @@ import androidx.annotation.RequiresApi
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper.KEY_SEARCH_INFO
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
@@ -50,7 +48,6 @@ object AutofillHelper {
|
||||
private const val AUTOFILL_RESPONSE_REQUEST_CODE = 8165
|
||||
|
||||
private const val ASSIST_STRUCTURE = AutofillManager.EXTRA_ASSIST_STRUCTURE
|
||||
const val KEY_SEARCH_INFO = "KEY_SEARCH_INFO"
|
||||
|
||||
fun retrieveAssistStructure(intent: Intent?): AssistStructure? {
|
||||
intent?.let {
|
||||
@@ -122,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)) {
|
||||
@@ -148,35 +148,6 @@ object AutofillHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to perform actions if item is found or not after an auto search in [database]
|
||||
*/
|
||||
fun checkAutoSearchInfo(context: Context,
|
||||
database: Database,
|
||||
searchInfo: SearchInfo?,
|
||||
onItemsFound: (items: List<EntryInfo>) -> Unit,
|
||||
onItemNotFound: () -> Unit,
|
||||
onDatabaseClosed: () -> Unit) {
|
||||
if (database.loaded && TimeoutHelper.checkTime(context)) {
|
||||
var searchWithoutUI = false
|
||||
if (PreferencesUtil.isAutofillAutoSearchEnable(context)
|
||||
&& searchInfo != null) {
|
||||
// If search provide results
|
||||
database.createVirtualGroupFromSearch(searchInfo, SearchHelper.MAX_SEARCH_ENTRY)?.let { searchGroup ->
|
||||
if (searchGroup.getNumberOfChildEntries() > 0) {
|
||||
searchWithoutUI = true
|
||||
onItemsFound.invoke(
|
||||
searchGroup.getChildEntriesInfo(database))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!searchWithoutUI) {
|
||||
onItemNotFound.invoke()
|
||||
}
|
||||
} else {
|
||||
onDatabaseClosed.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,12 +26,25 @@ import android.util.Log
|
||||
import android.widget.RemoteViews
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.kunzisoft.keepass.R
|
||||
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) {
|
||||
@@ -43,12 +56,15 @@ 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
|
||||
}
|
||||
|
||||
AutofillHelper.checkAutoSearchInfo(this,
|
||||
SearchHelper.checkAutoSearchInfo(this,
|
||||
Database.getInstance(),
|
||||
searchInfo,
|
||||
{ items ->
|
||||
@@ -71,6 +87,7 @@ class KeeAutofillService : AutofillService() {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showUIForEntrySelection(parseResult: StructureParser.Result,
|
||||
searchInfo: SearchInfo,
|
||||
@@ -114,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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +102,12 @@ internal class StructureParser(private val structure: AssistStructure) {
|
||||
when {
|
||||
it.equals(View.AUTOFILL_HINT_USERNAME, true)
|
||||
|| it.equals(View.AUTOFILL_HINT_EMAIL_ADDRESS, true)
|
||||
|| it.equals(View.AUTOFILL_HINT_PHONE, true)
|
||||
|| it.equals("email", true)
|
||||
|| it.equals("usernameOrEmail", true)-> {
|
||||
|| it.equals(View.AUTOFILL_HINT_PHONE, true)
|
||||
|| it.contains("OrUsername", true)
|
||||
|| it.contains("OrEmailAddress", true)
|
||||
|| it.contains("OrEmail", true)
|
||||
|| it.contains("OrPhone", true)-> {
|
||||
result?.usernameId = autofillId
|
||||
Log.d(TAG, "Autofill username hint")
|
||||
}
|
||||
@@ -112,7 +115,7 @@ internal class StructureParser(private val structure: AssistStructure) {
|
||||
|| it.contains("password", true) -> {
|
||||
result?.passwordId = autofillId
|
||||
Log.d(TAG, "Autofill password hint")
|
||||
// Username not needed in this specific case
|
||||
// Username not needed in this case
|
||||
usernameNeeded = false
|
||||
return true
|
||||
}
|
||||
@@ -160,42 +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")
|
||||
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)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,11 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
|
||||
private var biometricUnlockDatabaseHelper: BiometricUnlockDatabaseHelper? = null
|
||||
private var biometricMode: Mode = Mode.UNAVAILABLE
|
||||
|
||||
private var isBiometricPromptAutoOpenEnable = PreferencesUtil.isBiometricPromptAutoOpenEnable(context)
|
||||
private var biometricPromptAutoOpenPreference = PreferencesUtil.isBiometricPromptAutoOpenEnable(context)
|
||||
var isBiometricPromptAutoOpenEnable: Boolean = true
|
||||
get() {
|
||||
return field && biometricPromptAutoOpenPreference
|
||||
}
|
||||
|
||||
private var cipherDatabaseAction = CipherDatabaseAction.getInstance(context.applicationContext)
|
||||
|
||||
@@ -272,6 +276,8 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// Close the biometric prompt
|
||||
biometricUnlockDatabaseHelper?.closeBiometricPrompt()
|
||||
// Restore the checked listener
|
||||
checkboxPasswordView?.setOnCheckedChangeListener(onCheckedPasswordChangeListener)
|
||||
}
|
||||
|
||||
@@ -271,6 +271,10 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
|
||||
}
|
||||
}
|
||||
|
||||
fun closeBiometricPrompt() {
|
||||
biometricPrompt?.cancelAuthentication()
|
||||
}
|
||||
|
||||
interface BiometricUnlockErrorCallback {
|
||||
fun onInvalidKeyException(e: Exception)
|
||||
fun onBiometricException(e: Exception)
|
||||
|
||||
@@ -41,17 +41,6 @@ object CipherFactory {
|
||||
Security.addProvider(BouncyCastleProvider())
|
||||
}
|
||||
|
||||
@Throws(NoSuchAlgorithmException::class, NoSuchPaddingException::class)
|
||||
@JvmOverloads
|
||||
fun getInstance(transformation: String, androidOverride: Boolean = false): Cipher {
|
||||
// Return the native AES if it is possible
|
||||
return if (!deviceBlacklisted() && !androidOverride && hasNativeImplementation(transformation) && NativeLib.loaded()) {
|
||||
Cipher.getInstance(transformation, AESProvider())
|
||||
} else {
|
||||
Cipher.getInstance(transformation)
|
||||
}
|
||||
}
|
||||
|
||||
fun deviceBlacklisted(): Boolean {
|
||||
if (!blacklistInit) {
|
||||
blacklistInit = true
|
||||
@@ -65,6 +54,16 @@ object CipherFactory {
|
||||
return transformation == "AES/CBC/PKCS5Padding"
|
||||
}
|
||||
|
||||
@Throws(NoSuchAlgorithmException::class, NoSuchPaddingException::class)
|
||||
fun getInstance(transformation: String, androidOverride: Boolean = false): Cipher {
|
||||
// Return the native AES if it is possible
|
||||
return if (!deviceBlacklisted() && !androidOverride && hasNativeImplementation(transformation) && NativeLib.loaded()) {
|
||||
Cipher.getInstance(transformation, AESProvider())
|
||||
} else {
|
||||
Cipher.getInstance(transformation)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate appropriate cipher based on KeePass 2.x UUID's
|
||||
*/
|
||||
|
||||
@@ -74,12 +74,10 @@ object CryptoUtil {
|
||||
return ret
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun hashSha256(data: ByteArray, offset: Int = 0, count: Int = data.size): ByteArray {
|
||||
return hashGen("SHA-256", data, offset, count)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun hashSha512(data: ByteArray, offset: Int = 0, count: Int = data.size): ByteArray {
|
||||
return hashGen("SHA-512", data, offset, count)
|
||||
}
|
||||
|
||||
@@ -93,11 +93,11 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
TimeoutHelper.temporarilyDisableTimeout()
|
||||
// Stop the opening notification
|
||||
DatabaseOpenNotificationService.stop(activity)
|
||||
startOrUpdateDialog(titleId, messageId, warningId)
|
||||
startDialog(titleId, messageId, warningId)
|
||||
}
|
||||
|
||||
override fun onUpdateAction(titleId: Int?, messageId: Int?, warningId: Int?) {
|
||||
startOrUpdateDialog(titleId, messageId, warningId)
|
||||
updateDialog(titleId, messageId, warningId)
|
||||
}
|
||||
|
||||
override fun onStopAction(actionTask: String, result: ActionRunnable.Result) {
|
||||
@@ -120,7 +120,9 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun startOrUpdateDialog(titleId: Int?, messageId: Int?, warningId: Int?) {
|
||||
private fun startDialog(titleId: Int? = null,
|
||||
messageId: Int? = null,
|
||||
warningId: Int? = null) {
|
||||
if (progressTaskDialogFragment == null) {
|
||||
progressTaskDialogFragment = activity.supportFragmentManager
|
||||
.findFragmentByTag(PROGRESS_TASK_DIALOG_TAG) as ProgressTaskDialogFragment?
|
||||
@@ -129,6 +131,10 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
progressTaskDialogFragment = ProgressTaskDialogFragment()
|
||||
progressTaskDialogFragment?.show(activity.supportFragmentManager, PROGRESS_TASK_DIALOG_TAG)
|
||||
}
|
||||
updateDialog(titleId, messageId, warningId)
|
||||
}
|
||||
|
||||
private fun updateDialog(titleId: Int?, messageId: Int?, warningId: Int?) {
|
||||
progressTaskDialogFragment?.apply {
|
||||
titleId?.let {
|
||||
updateTitle(it)
|
||||
@@ -194,6 +200,8 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
bindService()
|
||||
}
|
||||
DATABASE_STOP_TASK_ACTION -> {
|
||||
// Remove the progress task
|
||||
stopDialog()
|
||||
unBindService()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ import com.kunzisoft.keepass.stream.readBytes4ToUInt
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.SingletonHolder
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import org.apache.commons.io.FileUtils
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
@@ -405,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
|
||||
@@ -492,7 +486,9 @@ class Database {
|
||||
mDatabaseKDBX?.clearCache()
|
||||
// In all cases, delete all the files in the temp dir
|
||||
try {
|
||||
FileUtils.cleanDirectory(filesDirectory)
|
||||
filesDirectory?.let { directory ->
|
||||
cleanDirectory(directory)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to clear the directory cache.", e)
|
||||
}
|
||||
@@ -503,6 +499,17 @@ class Database {
|
||||
this.loaded = false
|
||||
}
|
||||
|
||||
private fun cleanDirectory(directory: File) {
|
||||
directory.listFiles()?.let { files ->
|
||||
for (file in files) {
|
||||
if (file.isDirectory) {
|
||||
cleanDirectory(file)
|
||||
}
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun validatePasswordEncoding(password: String?, containsKeyFile: Boolean): Boolean {
|
||||
return mDatabaseKDB?.validatePasswordEncoding(password, containsKeyFile)
|
||||
?: mDatabaseKDBX?.validatePasswordEncoding(password, containsKeyFile)
|
||||
|
||||
@@ -41,7 +41,6 @@ class DeletedObject {
|
||||
|
||||
constructor()
|
||||
|
||||
@JvmOverloads
|
||||
constructor(uuid: UUID, deletionTime: Date = Date()) {
|
||||
this.uuid = uuid
|
||||
this.mDeletionTime = deletionTime
|
||||
|
||||
@@ -20,15 +20,14 @@
|
||||
package com.kunzisoft.keepass.database.element.database
|
||||
|
||||
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
|
||||
import com.kunzisoft.keepass.database.element.security.EncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.database.element.entry.EntryVersioned
|
||||
import com.kunzisoft.keepass.database.element.group.GroupVersioned
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageFactory
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.database.element.security.EncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
||||
import com.kunzisoft.keepass.database.exception.KeyFileEmptyDatabaseException
|
||||
import org.apache.commons.io.IOUtils
|
||||
import java.io.*
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
@@ -127,7 +126,7 @@ abstract class DatabaseVersioned<
|
||||
protected fun getFileKey(keyInputStream: InputStream): ByteArray {
|
||||
|
||||
val keyByteArrayOutputStream = ByteArrayOutputStream()
|
||||
IOUtils.copy(keyInputStream, keyByteArrayOutputStream)
|
||||
keyInputStream.copyTo(keyByteArrayOutputStream)
|
||||
val keyData = keyByteArrayOutputStream.toByteArray()
|
||||
|
||||
val keyByteArrayInputStream = ByteArrayInputStream(keyData)
|
||||
|
||||
@@ -31,7 +31,6 @@ class NodeIdInt : NodeId<Int> {
|
||||
|
||||
constructor(source: NodeIdInt) : this(source.id)
|
||||
|
||||
@JvmOverloads
|
||||
constructor(groupId: Int = Random().nextInt()) : super() {
|
||||
this.id = groupId
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ class NodeIdUUID : NodeId<UUID> {
|
||||
|
||||
constructor(source: NodeIdUUID) : this(source.id)
|
||||
|
||||
@JvmOverloads
|
||||
constructor(uuid: UUID = UUID.randomUUID()) : super() {
|
||||
this.id = uuid
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ class ProtectedString : Parcelable {
|
||||
this.stringValue = toCopy.stringValue
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
constructor(enableProtection: Boolean = false, string: String = "") {
|
||||
this.isProtected = enableProtection
|
||||
this.stringValue = string
|
||||
|
||||
@@ -19,17 +19,57 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.search
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.action.node.NodeHandler
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.search.iterator.EntrySearchStringIteratorKDB
|
||||
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
|
||||
|
||||
class SearchHelper(private val isOmitBackup: Boolean) {
|
||||
|
||||
companion object {
|
||||
const val MAX_SEARCH_ENTRY = 6
|
||||
|
||||
/**
|
||||
* Utility method to perform actions if item is found or not after an auto search in [database]
|
||||
*/
|
||||
fun checkAutoSearchInfo(context: Context,
|
||||
database: Database,
|
||||
searchInfo: SearchInfo?,
|
||||
onItemsFound: (items: List<EntryInfo>) -> Unit,
|
||||
onItemNotFound: () -> Unit,
|
||||
onDatabaseClosed: () -> Unit) {
|
||||
if (database.loaded && TimeoutHelper.checkTime(context)) {
|
||||
var searchWithoutUI = false
|
||||
if (PreferencesUtil.isAutofillAutoSearchEnable(context)
|
||||
&& searchInfo != null
|
||||
&& !searchInfo.containsOnlyNullValues()) {
|
||||
// If search provide results
|
||||
database.createVirtualGroupFromSearchInfo(
|
||||
searchInfo.getSearchString(context),
|
||||
MAX_SEARCH_ENTRY
|
||||
)?.let { searchGroup ->
|
||||
if (searchGroup.getNumberOfChildEntries() > 0) {
|
||||
searchWithoutUI = true
|
||||
onItemsFound.invoke(
|
||||
searchGroup.getChildEntriesInfo(database))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!searchWithoutUI) {
|
||||
onItemNotFound.invoke()
|
||||
}
|
||||
} else {
|
||||
onDatabaseClosed.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var incrementEntry = 0
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.widget.FrameLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.MagikeyboardLauncherActivity
|
||||
import com.kunzisoft.keepass.adapters.FieldsAdapter
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
@@ -211,7 +212,7 @@ class MagikIME : InputMethodService(), KeyboardView.OnKeyboardActionListener {
|
||||
// Stop current service and reinit entry
|
||||
stopService(Intent(this, KeyboardEntryNotificationService::class.java))
|
||||
removeEntryInfo()
|
||||
val intent = Intent(this, KeyboardLauncherActivity::class.java)
|
||||
val intent = Intent(this, MagikeyboardLauncherActivity::class.java)
|
||||
// New task needed because don't launch from an Activity context
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
@@ -248,7 +249,9 @@ class MagikIME : InputMethodService(), KeyboardView.OnKeyboardActionListener {
|
||||
}
|
||||
popupCustomKeys?.showAtLocation(keyboardView, Gravity.END or Gravity.TOP, 0, 0)
|
||||
}
|
||||
Keyboard.KEYCODE_DELETE -> inputConnection.deleteSurroundingText(1, 0)
|
||||
Keyboard.KEYCODE_DELETE -> {
|
||||
inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
|
||||
}
|
||||
Keyboard.KEYCODE_DONE -> inputConnection.performEditorAction(EditorInfo.IME_ACTION_GO)
|
||||
}
|
||||
}
|
||||
@@ -321,11 +324,11 @@ class MagikIME : InputMethodService(), KeyboardView.OnKeyboardActionListener {
|
||||
context.sendBroadcast(Intent(REMOVE_ENTRY_MAGIKEYBOARD_ACTION))
|
||||
}
|
||||
|
||||
fun addEntryAndLaunchNotificationIfAllowed(context: Context, entry: EntryInfo) {
|
||||
fun addEntryAndLaunchNotificationIfAllowed(context: Context, entry: EntryInfo, toast: Boolean = false) {
|
||||
// Add a new entry
|
||||
entryInfoKey = entry
|
||||
// Launch notification if allowed
|
||||
KeyboardEntryNotificationService.launchNotificationIfAllowed(context, entry)
|
||||
KeyboardEntryNotificationService.launchNotificationIfAllowed(context, entry, toast)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
?: ""
|
||||
}
|
||||
@@ -81,6 +81,7 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
|
||||
val downloadFileUri: Uri? = if (intent?.hasExtra(DOWNLOAD_FILE_URI_KEY) == true) {
|
||||
intent.getParcelableExtra(DOWNLOAD_FILE_URI_KEY)
|
||||
|
||||
@@ -55,6 +55,8 @@ class ClipboardEntryNotificationService : LockNotificationService() {
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
|
||||
// Get entry info from intent
|
||||
mEntryInfo = intent?.getParcelableExtra(EXTRA_ENTRY_INFO)
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ class DatabaseOpenNotificationService: LockNotificationService() {
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
|
||||
when(intent?.action) {
|
||||
ACTION_CLOSE_DATABASE -> {
|
||||
|
||||
@@ -39,7 +39,6 @@ import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
|
||||
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdater {
|
||||
@@ -61,8 +60,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
||||
|
||||
fun addActionTaskListener(actionTaskListener: ActionTaskListener) {
|
||||
mActionTaskListeners.add(actionTaskListener)
|
||||
// To prevent task dialog to be unbound before the display
|
||||
actionRunnableAsyncTask?.allowFinishTask?.set(true)
|
||||
}
|
||||
|
||||
fun removeActionTaskListener(actionTaskListener: ActionTaskListener) {
|
||||
@@ -78,7 +75,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
||||
|
||||
fun checkAction() {
|
||||
mActionTaskListeners.forEach { actionTaskListener ->
|
||||
actionTaskListener.onUpdateAction(mTitleId, mMessageId, mWarningId)
|
||||
actionTaskListener.onStartAction(mTitleId, mMessageId, mWarningId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +84,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
|
||||
if (intent == null) return START_REDELIVER_INTENT
|
||||
|
||||
@@ -571,8 +569,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
||||
private val onPostExecute: (result: ActionRunnable.Result) -> Unit)
|
||||
: AsyncTask<((ProgressTaskUpdater?) -> ActionRunnable), Void, ActionRunnable.Result>() {
|
||||
|
||||
var allowFinishTask = AtomicBoolean(false)
|
||||
|
||||
override fun onPreExecute() {
|
||||
super.onPreExecute()
|
||||
onPreExecute.invoke()
|
||||
@@ -586,10 +582,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
||||
resultTask = result
|
||||
}
|
||||
}
|
||||
// Additional wait if the dialog take time to show
|
||||
while(!allowFinishTask.get()) {
|
||||
Thread.sleep(250)
|
||||
}
|
||||
return resultTask
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikIME
|
||||
@@ -49,6 +50,8 @@ class KeyboardEntryNotificationService : LockNotificationService() {
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
|
||||
//Get settings
|
||||
notificationTimeoutMilliSecs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getString(getString(R.string.keyboard_entry_timeout_key),
|
||||
@@ -146,8 +149,9 @@ class KeyboardEntryNotificationService : LockNotificationService() {
|
||||
|
||||
const val ACTION_CLEAN_KEYBOARD_ENTRY = "ACTION_CLEAN_KEYBOARD_ENTRY"
|
||||
|
||||
fun launchNotificationIfAllowed(context: Context, entry: EntryInfo) {
|
||||
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()
|
||||
@@ -155,14 +159,22 @@ class KeyboardEntryNotificationService : LockNotificationService() {
|
||||
var startService = false
|
||||
val intent = Intent(context, KeyboardEntryNotificationService::class.java)
|
||||
|
||||
if (containsURLToCopy || containsUsernameToCopy || containsPasswordToCopy || containsExtraFieldToCopy) {
|
||||
if (toast) {
|
||||
Toast.makeText(context,
|
||||
context.getString(R.string.keyboard_notification_entry_content_title, entry.title),
|
||||
Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
// Show the notification if allowed in Preferences
|
||||
if (PreferencesUtil.isKeyboardNotificationEntryEnable(context)) {
|
||||
if (containsUsernameToCopy || containsPasswordToCopy || containsExtraFieldToCopy) {
|
||||
startService = true
|
||||
context.startService(intent.apply {
|
||||
putExtra(ENTRY_INFO_KEY, entry)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
MagikIME.removeEntry(context)
|
||||
}
|
||||
|
||||
if (!startService)
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.kunzisoft.keepass.utils.unregisterLockReceiver
|
||||
|
||||
abstract class LockNotificationService : NotificationService() {
|
||||
|
||||
private var onStart: Boolean = false
|
||||
private var mLockReceiver: LockReceiver? = null
|
||||
|
||||
protected open fun actionOnLock() {
|
||||
@@ -38,11 +39,17 @@ abstract class LockNotificationService : NotificationService() {
|
||||
|
||||
// Register a lock receiver to stop notification service when lock on keyboard is performed
|
||||
mLockReceiver = LockReceiver {
|
||||
if (onStart)
|
||||
actionOnLock()
|
||||
}
|
||||
registerLockReceiver(mLockReceiver)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
onStart = true
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
protected fun stopTask(task: Thread?) {
|
||||
if (task != null && task.isAlive)
|
||||
task.interrupt()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -62,7 +62,6 @@ abstract class NestedSettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
private const val TAG_KEY = "NESTED_KEY"
|
||||
|
||||
@JvmOverloads
|
||||
fun newInstance(key: Screen, databaseReadOnly: Boolean = ReadOnlyHelper.READ_ONLY_DEFAULT)
|
||||
: NestedSettingsFragment {
|
||||
val fragment: NestedSettingsFragment = when (key) {
|
||||
|
||||
@@ -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),
|
||||
@@ -337,6 +345,12 @@ object PreferencesUtil {
|
||||
context.resources.getBoolean(R.bool.keyboard_notification_entry_default))
|
||||
}
|
||||
|
||||
fun isKeyboardSearchShareEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_search_share_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_search_share_default))
|
||||
}
|
||||
|
||||
fun isAutoGoActionEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_auto_go_action_key),
|
||||
@@ -360,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)
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,6 @@ object MenuUtil {
|
||||
/*
|
||||
* @param checkLock Check the time lock before launch settings in LockingActivity
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun onDefaultMenuOptionsItemSelected(activity: Activity,
|
||||
item: MenuItem,
|
||||
readOnly: Boolean = READ_ONLY_DEFAULT,
|
||||
|
||||
@@ -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) ?: ""
|
||||
}
|
||||
|
||||
@@ -309,15 +309,17 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
enableActionButton: Boolean,
|
||||
onActionClickListener: OnClickListener?) {
|
||||
|
||||
val entryCustomField = EntryCustomField(context, attrs, defStyle)
|
||||
entryCustomField.apply {
|
||||
val entryCustomField: EntryCustomField? = EntryCustomField(context, attrs, defStyle)
|
||||
entryCustomField?.apply {
|
||||
setLabel(title)
|
||||
setValue(value.toString(), value.isProtected)
|
||||
enableActionButton(enableActionButton)
|
||||
assignActionButtonClickListener(onActionClickListener)
|
||||
applyFontVisibility(fontInVisibility)
|
||||
}
|
||||
extrasView.addView(entryCustomField)
|
||||
entryCustomField?.let {
|
||||
extrasView.addView(it)
|
||||
}
|
||||
extrasContainerView.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
|
||||
open class EntryCustomField @JvmOverloads constructor(context: Context,
|
||||
class EntryCustomField @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0)
|
||||
: LinearLayout(context, attrs, defStyle) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
5
app/src/main/res/color/entry_subtitle_color.xml
Normal file
5
app/src/main/res/color/entry_subtitle_color.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_selected="true" android:color="@color/colorTextInverse"/>
|
||||
<item android:color="?android:attr/textColorSecondary"/>
|
||||
</selector>
|
||||
5
app/src/main/res/color/entry_title_color.xml
Normal file
5
app/src/main/res/color/entry_title_color.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_selected="true" android:color="@color/colorTextInverse"/>
|
||||
<item android:color="?android:attr/textColor"/>
|
||||
</selector>
|
||||
5
app/src/main/res/color/group_subtitle_color.xml
Normal file
5
app/src/main/res/color/group_subtitle_color.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_selected="true" android:color="@color/colorTextInverse"/>
|
||||
<item android:color="?android:attr/textColorSecondary"/>
|
||||
</selector>
|
||||
5
app/src/main/res/color/group_title_color.xml
Normal file
5
app/src/main/res/color/group_title_color.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_selected="true" android:color="@color/colorTextInverse"/>
|
||||
<item android:color="?android:attr/textColorPrimary"/>
|
||||
</selector>
|
||||
@@ -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="?attr/colorPrimary"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:backgroundTint="?android:attr/textColor"
|
||||
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"
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
tools:text="Node Title"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Default" /> <!-- style override -->
|
||||
style="@style/KeepassDXStyle.TextAppearance.Entry.Title" />
|
||||
<TextView
|
||||
android:id="@+id/node_subtext"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -76,7 +76,7 @@
|
||||
tools:text="Node SubTitle"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Secondary" /> <!-- style override -->
|
||||
style="@style/KeepassDXStyle.TextAppearance.Entry.SubTitle" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -35,11 +35,10 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:background="?android:attr/selectableItemBackground" >
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/group_arrow"
|
||||
android:id="@+id/node_image_identifier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_arrow_right_white_24dp"
|
||||
android:tint="?android:attr/textColorPrimary"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_centerVertical="true"
|
||||
@@ -58,8 +57,8 @@
|
||||
android:src="@drawable/ic_blank_32dp"
|
||||
android:scaleType="fitXY"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toRightOf="@+id/group_arrow"
|
||||
android:layout_toEndOf="@+id/group_arrow" />
|
||||
android:layout_toRightOf="@+id/node_image_identifier"
|
||||
android:layout_toEndOf="@+id/node_image_identifier" />
|
||||
<TextView
|
||||
android:id="@+id/node_child_numbers"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -90,7 +89,7 @@
|
||||
tools:text="Node Title"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Title" /> <!-- style override -->
|
||||
style="@style/KeepassDXStyle.TextAppearance.Group.Title" />
|
||||
<TextView
|
||||
android:id="@+id/node_subtext"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -100,7 +99,7 @@
|
||||
android:layout_marginTop="-4dp"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Secondary" /> <!-- style override -->
|
||||
style="@style/KeepassDXStyle.TextAppearance.Group.SubTitle" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
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>
|
||||
@@ -16,15 +16,13 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
--><resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
<string name="homepage">الصفحة الرئيسية</string>
|
||||
<string name="accept">قبول</string>
|
||||
<string name="add_group">إضافة مجموعة</string>
|
||||
<string name="encryption">التعمية</string>
|
||||
<string name="encryption_algorithm">خوارزمية التعمية</string>
|
||||
<string name="application">التطبيق</string>
|
||||
<string name="beta_dontask">لا تظهر مرة أخرى</string>
|
||||
<string name="brackets">أقواس</string>
|
||||
<string name="extended_ASCII">تمديد ASCII</string>
|
||||
<string name="allow">السماح</string>
|
||||
@@ -117,15 +115,16 @@
|
||||
<string name="edit_entry">تحرير مدخلة</string>
|
||||
<string name="key_derivation_function">وظيفة اشتقاق المفتاح</string>
|
||||
<string name="app_timeout">مهلة التطبيق</string>
|
||||
<string name="app_timeout_summary">مدة الانتظار قبل إقفال التطبيق</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>
|
||||
@@ -278,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>
|
||||
22
app/src/main/res/values-bn-rBD/strings.xml
Normal file
22
app/src/main/res/values-bn-rBD/strings.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="homepage">মূলপাতা</string>
|
||||
<string name="feedback">প্রতিক্রিয়া</string>
|
||||
<string name="contribution">অবদান</string>
|
||||
<string name="contact">যোগাযোগ</string>
|
||||
<string name="extended_ASCII">বর্ধিত ASCII</string>
|
||||
<string name="brackets">ব্র্যাকেট</string>
|
||||
<string name="application">অ্যাপ</string>
|
||||
<string name="app_timeout_summary">ডাটাবেস লক করার আগে অব্যবহৃত সময়</string>
|
||||
<string name="app_timeout">অ্যাপের সময় পার হয়ে গিয়েছিলো</string>
|
||||
<string name="key_derivation_function">কি পাওয়ার ফাংশন</string>
|
||||
<string name="encryption_algorithm">এনক্রিপশন অ্যালগরিদম</string>
|
||||
<string name="encryption">এনক্রিপশন</string>
|
||||
<string name="security">নিরাপত্তা</string>
|
||||
<string name="master_key">প্রধান চাবি</string>
|
||||
<string name="add_group">গ্রুপ যোগ করুন</string>
|
||||
<string name="edit_entry">এন্টরি সম্পাদনা করুন</string>
|
||||
<string name="add_entry">এন্টরি যোগ করুন</string>
|
||||
<string name="accept">গ্রহণ</string>
|
||||
<string name="about_description">কিপাস পাসওয়ার্ড ম্যানেজারের অ্যান্ড্রয়েড বাস্তবায়ন</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>
|
||||
@@ -77,7 +76,7 @@
|
||||
<string name="hint_length">Longitud</string>
|
||||
<string name="hint_pass">Contrasenya</string>
|
||||
<string name="password">Contrasenya</string>
|
||||
<string name="invalid_credentials">No s\'han pogut llegir les credencials. Si torna a passar, el fitxer de la vostra base de dades podria estar malmès.</string>
|
||||
<string name="invalid_credentials">No s\'han pogut llegir les credencials.</string>
|
||||
<string name="invalid_db_sig">No s\'ha pogut reconèixer el format de la base de dades.</string>
|
||||
<string name="length">Longitud</string>
|
||||
<string name="list_size_title">Mida de la llista de grups</string>
|
||||
@@ -147,7 +146,6 @@
|
||||
<string name="edit_entry">Edita l\'entrada</string>
|
||||
<string name="contribution">Contribució</string>
|
||||
<string name="contact">Contacte</string>
|
||||
<string name="beta_dontask">No tornis a mostrar</string>
|
||||
<string name="extended_ASCII">ASCII ampliat</string>
|
||||
<string name="sort_username">Nom d\'usuari</string>
|
||||
<string name="sort_title">Títol</string>
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
<string name="app_timeout_summary">Doba nečinnosti než se aplikace zamkne</string>
|
||||
<string name="application">Aplikace</string>
|
||||
<string name="menu_app_settings">Nastavení aplikace</string>
|
||||
<string name="beta_dontask">Znovu neukázat</string>
|
||||
<string name="brackets">Závorky</string>
|
||||
<string name="file_manager_install_description">K založení, otevření a uložení databázových souborů je potřebný správce souborů, který akceptuje akci intentu ACTION_CREATE_DOCUMENT a ACTION_OPEN_DOCUMENT.</string>
|
||||
<string name="clipboard_cleared">Schránka vyčištěna</string>
|
||||
@@ -82,7 +81,7 @@
|
||||
<string name="hint_length">Délka</string>
|
||||
<string name="hint_pass">Heslo</string>
|
||||
<string name="password">Heslo</string>
|
||||
<string name="invalid_credentials">Nebylo možno načíst autentizační údaje. Pokud se chyba opakuje, databázový soubor může být poškozen.</string>
|
||||
<string name="invalid_credentials">Nebylo možno načíst autentizační údaje.</string>
|
||||
<string name="invalid_algorithm">Nesprávný algoritmus.</string>
|
||||
<string name="invalid_db_sig">Nedaří se rozpoznat formát databáze.</string>
|
||||
<string name="keyfile_is_empty">Soubor s klíčem je prázdný.</string>
|
||||
@@ -195,7 +194,7 @@
|
||||
<string name="warning_empty_password">Pokračovat bez ochrany odemknutím heslem\?</string>
|
||||
<string name="warning_no_encryption_key">Pokračovat bez šifrovacího klíče\?</string>
|
||||
<string name="configure_biometric">Biometrická pobídka je zařízením podporována, ale není nastavena.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Otevři biometrickou pobídku k otevření databáze</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Otevřít biometrickou pobídku k otevření databáze</string>
|
||||
<string name="encrypted_value_stored">Šifrované heslo uloženo</string>
|
||||
<string name="biometric_invalid_key">Nelze načíst biometrický klíč. Prosím, smažte jej a opakujte proceduru biometrického rozpoznání.</string>
|
||||
<string name="biometric_not_recognized">Biometrický prvek nerozpoznán</string>
|
||||
@@ -345,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>
|
||||
@@ -477,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>
|
||||
@@ -28,7 +28,6 @@
|
||||
<string name="app_timeout_summary">Inaktiv tid, før databasen låses</string>
|
||||
<string name="application">Program</string>
|
||||
<string name="menu_app_settings">Indstillinger</string>
|
||||
<string name="beta_dontask">Vis ikke igen</string>
|
||||
<string name="brackets">Parenteser</string>
|
||||
<string name="file_manager_install_description">En filhåndtering, der accepterer intensionshandlingen ACTION_CREATE_DOCUMENT og ACTION_OPEN_DOCUMENT, er nødvendig for at oprette, åbne og gemme databasefiler.</string>
|
||||
<string name="clipboard_cleared">Udklipsholder ryddet</string>
|
||||
@@ -81,7 +80,7 @@
|
||||
<string name="hint_length">Længde</string>
|
||||
<string name="hint_pass">Adgangskode</string>
|
||||
<string name="password">Adgangskode</string>
|
||||
<string name="invalid_credentials">Legitimationsoplysningerne kunne ikke læses. Hvis det sker igen, kan databasefilen være beskadiget.</string>
|
||||
<string name="invalid_credentials">Legitimationsoplysningerne kunne ikke læses.</string>
|
||||
<string name="invalid_algorithm">Forkert algoritme.</string>
|
||||
<string name="invalid_db_sig">Kunne ikke genkende databaseformat.</string>
|
||||
<string name="keyfile_is_empty">Nøglefilen er tom.</string>
|
||||
@@ -194,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>
|
||||
@@ -221,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>
|
||||
@@ -270,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>
|
||||
@@ -344,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>
|
||||
@@ -375,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>
|
||||
@@ -429,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>
|
||||
@@ -476,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>
|
||||
@@ -34,7 +34,6 @@
|
||||
<string name="app_timeout_summary">Inaktivität vor dem Sperren der Datenbank</string>
|
||||
<string name="application">App</string>
|
||||
<string name="menu_app_settings">App-Einstellungen</string>
|
||||
<string name="beta_dontask">Nicht mehr anzeigen</string>
|
||||
<string name="brackets">Klammern</string>
|
||||
<string name="file_manager_install_description">Zum Erstellen, Öffnen und Speichern von Datenbankdateien wird ein Dateimanager benötigt, der die beabsichtigte Aktion ACTION_CREATE_DOCUMENT und ACTION_OPEN_DOCUMENT akzeptiert.</string>
|
||||
<string name="clipboard_cleared">Zwischenablage geleert</string>
|
||||
@@ -91,7 +90,7 @@
|
||||
<string name="hint_length">Länge</string>
|
||||
<string name="hint_pass">Passwort</string>
|
||||
<string name="password">Passwort</string>
|
||||
<string name="invalid_credentials">Die Anmeldeinformationen konnten nicht gelesen werden. Wenn dies erneut auftritt, kann Ihre Datenbankdatei beschädigt sein.</string>
|
||||
<string name="invalid_credentials">Die Anmeldeinformationen konnten nicht gelesen werden.</string>
|
||||
<string name="invalid_algorithm">Falscher Algorithmus.</string>
|
||||
<string name="invalid_db_sig">Datenbankformat nicht erkannt.</string>
|
||||
<string name="keyfile_is_empty">Die Schlüsseldatei ist leer.</string>
|
||||
@@ -187,7 +186,7 @@
|
||||
<string name="list_password_generator_options_summary">Erlaubte Zeichen für Passwortgenerator festlegen</string>
|
||||
<string name="list_password_generator_options_title">Passwortzeichen</string>
|
||||
<string name="configure_biometric">Die biometrische Abfrage wird unterstützt, ist aber nicht eingerichtet.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Biometrische Abfrage öffnen, um die Datenbank zu entsperren.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Biometrie-Abfrage öffnen, um die Datenbank zu entsperrenœ</string>
|
||||
<string name="encrypted_value_stored">Verschlüsseltes Passwort wurde gespeichert</string>
|
||||
<string name="biometric_invalid_key">Der biometrische Schlüssel kann nicht gelesen werden. Bitte löschen Sie ihn und wiederholen Sie den biometrischen Erkennungsprozess.</string>
|
||||
<string name="biometric_scanning_error">Biometrischer Fehler: %1$s</string>
|
||||
@@ -358,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>
|
||||
@@ -390,7 +389,7 @@
|
||||
<string name="biometric">Biometrisch</string>
|
||||
<string name="enable">Aktivieren</string>
|
||||
<string name="disable">Deaktivieren</string>
|
||||
<string name="biometric_prompt_store_credential_message">Achtung: Wenn du die biometrische Erkennung verwendest, musst du dir das Master-Passwort trotzdem merken.</string>
|
||||
<string name="biometric_prompt_store_credential_message">Achtung: Wenn Sie die biometrische Erkennung verwenden, müssen Sie sich trotzdem Ihr Master-Passwort merken.</string>
|
||||
<string name="biometric_prompt_extract_credential_message">Datenbank-Anmeldeinformationen aus biometrischen Daten extrahieren</string>
|
||||
<string name="biometric_auto_open_prompt_title">Biometrische Abfrage automatisch öffnen</string>
|
||||
<string name="biometric_auto_open_prompt_summary">Automatisch nach Biometrie fragen, wenn die Datenbank dafür eingerichtet ist</string>
|
||||
@@ -487,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>
|
||||
@@ -28,7 +28,6 @@
|
||||
<string name="app_timeout_summary">Χρόνος αδράνειας πριν από το κλείδωμα της βάσης δεδομένων</string>
|
||||
<string name="application">Εφαρμογή</string>
|
||||
<string name="menu_app_settings">Ρυθμίσεις εφαρμογής</string>
|
||||
<string name="beta_dontask">Να μην εμφανιστεί ξανά</string>
|
||||
<string name="brackets">Αγκύλες</string>
|
||||
<string name="file_manager_install_description">Ένας διαχειριστής αρχείων που δέχεται τις ενέργειες δράσης ACTION_CREATE_DOCUMENT και ACTION_OPEN_DOCUMENT είναι απαραίτητος για τη δημιουργία, το άνοιγμα και την αποθήκευση αρχείων βάσης δεδομένων.</string>
|
||||
<string name="clipboard_cleared">Το πρόχειρο καθαρίστηκε</string>
|
||||
@@ -43,7 +42,7 @@
|
||||
<string name="decrypting_db">Αποκρυπτογράφηση περιεχομένου βάσης δεδομένων …</string>
|
||||
<string name="default_checkbox">Χρήση ως προεπιλεγμένης βάσης δεδομένων</string>
|
||||
<string name="digits">Ψηφία</string>
|
||||
<string name="html_about_licence">Το KeePassDX © %1$d Kunzisoft είναι <strong>ανοιχτού κώδικα</strong>" και "<strong>χωρίς διαφημίσεις</strong>.
|
||||
<string name="html_about_licence">Το KeePassDX © %1$d Kunzisoft είναι <strong>ανοιχτού κώδικα</strong> και <strong>χωρίς διαφημίσεις</strong>.
|
||||
\nΠαρέχεται ως έχει, με άδεια <strong>GPLv3</strong>, χωρίς καμία εγγύηση.</string>
|
||||
<string name="select_database_file">Ανοίξτε την υπάρχουσα βάση δεδομένων</string>
|
||||
<string name="entry_accessed">Πρόσβαση</string>
|
||||
@@ -84,7 +83,7 @@
|
||||
<string name="hint_length">Μήκος</string>
|
||||
<string name="hint_pass">Κωδικός</string>
|
||||
<string name="password">Κωδικός Πρόσβασης</string>
|
||||
<string name="invalid_credentials">Δεν ήταν δυνατή η ανάγνωση διαπιστευτηρίων. Εάν αυτό επαναληφθεί, το αρχείο της βάσης δεδομένων ενδέχεται να είναι κατεστραμμένο.</string>
|
||||
<string name="invalid_credentials">Δεν ήταν δυνατή η ανάγνωση διαπιστευτηρίων.</string>
|
||||
<string name="invalid_algorithm">Λάθος αλγόριθμος.</string>
|
||||
<string name="invalid_db_sig">Δεν ήταν δυνατή η αναγνώριση της μορφής της βάσης δεδομένων.</string>
|
||||
<string name="keyfile_is_empty">Το αρχείο-κλειδί είναι κενό.</string>
|
||||
|
||||
@@ -143,7 +143,6 @@
|
||||
</string-array>
|
||||
<string name="encryption">Cifrado</string>
|
||||
<string name="key_derivation_function">Función de derivación de clave</string>
|
||||
<string name="beta_dontask">No mostrar nuevamente</string>
|
||||
<string name="extended_ASCII">ASCII extendido</string>
|
||||
<string name="allow">Permitir</string>
|
||||
<string name="clipboard_error_title">Error del portapapeles</string>
|
||||
|
||||
@@ -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>
|
||||
@@ -30,7 +29,6 @@
|
||||
<string name="app_timeout_summary">Denbora datubasea blokeatu baino lehenago aplikazioa erabili gabe dagoenean</string>
|
||||
<string name="application">Aplikazioa</string>
|
||||
<string name="menu_app_settings">Aplikazioaren ezarpenak</string>
|
||||
<string name="beta_dontask">Ez erakutsi berriro</string>
|
||||
<string name="brackets">Brackets</string>
|
||||
<string name="file_manager_install_description">Fitxategietan nabigatzeak Open Intents Fitxategi Kudeatzailea behar du. Klik egin azpian instalatzeko. Fitxategien kudeatzailaren arazo batzuk direla eta, izan daiteke nabigazioak ondo ez funtzionatzea lehenengo aldian.</string>
|
||||
<string name="clipboard_cleared">Arbela ezabatuta.</string>
|
||||
@@ -135,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>
|
||||
|
||||
@@ -16,32 +16,30 @@
|
||||
|
||||
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="about_description">KeePassDX on KeePass-salasanahallintaohjelman Android-versio</string>
|
||||
--><resources>
|
||||
<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>
|
||||
<string name="add_group">Lisää ryhmä</string>
|
||||
<string name="encryption_algorithm">Algoritmi</string>
|
||||
<string name="app_timeout">Ohjelman aikakatkaisu</string>
|
||||
<string name="app_timeout_summary">Aika, jonka jälkeen KeePass lukitaan jos se on ollut toimeton.</string>
|
||||
<string name="application">Ohjelma</string>
|
||||
<string name="encryption_algorithm">Salausalgoritmi</string>
|
||||
<string name="app_timeout">Sovelluksen aikakatkaisu</string>
|
||||
<string name="app_timeout_summary">Joutoaika ennen tietokannan lukkiutumista</string>
|
||||
<string name="application">Sovellus</string>
|
||||
<string name="menu_app_settings">Ohjelman asetukset</string>
|
||||
<string name="beta_dontask">Älä näytä enää uudelleen</string>
|
||||
<string name="brackets">Hakasulkeet</string>
|
||||
<string name="file_manager_install_description">Tiedostojen selaus vaatii Open Intents File Manager -tiedostonhallintaohjelman, klikkaa alla olevaa linkkiä asentaaksesi sen. Joidenkin ominaisuuksien takia se ei ehkä toimi oikein ensimmäisellä käynnistyksellä.</string>
|
||||
<string name="file_manager_install_description">Tietokantojen avaamista, luomista ja tallentamista varten tarvitaan tiedostonhallintaohjelma, joka tukee ACTION_CREATE_DOCUMENT ja ACTION_OPEN_DOCUMENT Intent-toimintoja.</string>
|
||||
<string name="clipboard_cleared">Leikepöytä tyhjennetty.</string>
|
||||
<string name="clipboard_error_title">Leikepöytävirhe</string>
|
||||
<string name="clipboard_error">Joissakin Android-puhelimissa on virhe leikepöydän toteutuksessa, mikä aiheuttaa kopioinnin epäonnistumisen. Lisätietoa:</string>
|
||||
<string name="clipboard_error_clear">Leikepöydän tyhjennys epäonnistui</string>
|
||||
<string name="clipboard_error">Jotkin laitteet eivät anna sovellusten käyttää leikepöytää.</string>
|
||||
<string name="clipboard_error_clear">Leikepöytää ei voitu tyhjentää</string>
|
||||
<string name="clipboard_timeout">Leikepöydän aikakatkaisu</string>
|
||||
<string name="clipboard_timeout_summary">Aika, jonka jälkeen leikepöytä tyhjennetään käyttäjätunnuksen tai salasanan kopioinnin jälkeen</string>
|
||||
<string name="clipboard_timeout_summary">Leikepöydälle tallennuksen kesto</string>
|
||||
<string name="select_to_copy">Valitse kopioidaksesi %1$s</string>
|
||||
<string name="retrieving_db_key">Luodaan tietokanta-avainta…</string>
|
||||
<string name="retrieving_db_key">Luodaan tietokanta-avainta…</string>
|
||||
<string name="database">Tietokanta</string>
|
||||
<string name="decrypting_db">Puretaan tietokannan salausta…</string>
|
||||
<string name="decrypting_db">Puretaan tietokannan salausta…</string>
|
||||
<string name="default_checkbox">Käytä tätä oletustietokantana</string>
|
||||
<string name="digits">Numerot</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft comes with absolutely no warranty. This is free software, and you are welcome to redistribute it under the conditions of the GPL version 3 or later.</string>
|
||||
@@ -91,7 +89,7 @@
|
||||
<string name="length">Pituus</string>
|
||||
<string name="list_size_title">Ryhmälistan pituus</string>
|
||||
<string name="list_size_summary">Tekstin koko ryhmälistauksessa</string>
|
||||
<string name="loading_database">Ladataan salasanatietokantaa…</string>
|
||||
<string name="loading_database">Ladataan salasanatietokantaa…</string>
|
||||
<string name="lowercase">pienet kirjaimet</string>
|
||||
<string name="hide_password_title">Piilota salasaan</string>
|
||||
<string name="hide_password_summary">Piilota salasanat oletuksena</string>
|
||||
@@ -114,15 +112,15 @@
|
||||
<string name="no_url_handler">Tälle URL:lle ei ole käsittelijää.</string>
|
||||
<string name="omit_backup_search_title">Älä etsi varmuuskopioista eikä roskakorista</string>
|
||||
<string name="omit_backup_search_summary">Poista \'Varmuuskopiot\' ja roskakori hakutuloksista</string>
|
||||
<string name="progress_create">Luodaan uutta tietokantaa…</string>
|
||||
<string name="progress_title">Työskennellään…</string>
|
||||
<string name="progress_create">Luodaan uutta tietokantaa…</string>
|
||||
<string name="progress_title">Työskennellään…</string>
|
||||
<string name="protection">Suojaus</string>
|
||||
<string name="content_description_remove_from_list">Poista</string>
|
||||
<string name="encryption_rijndael">Rijndael (AES)</string>
|
||||
<string name="root">Juuri</string>
|
||||
<string name="rounds">Salauskierroksia</string>
|
||||
<string name="rounds_explanation">Suurempi kierrosten määrä parantaa suojausta raa\'alla voimalla tehdyiltä murtoyrityksiltä, mutta voi todella hidastaa lataamista ja tallentamista.</string>
|
||||
<string name="saving_database">Tallennetaan tietokantaa…</string>
|
||||
<string name="saving_database">Tallennetaan tietokantaa…</string>
|
||||
<string name="space">Tila</string>
|
||||
<string name="search_label">Etsi</string>
|
||||
<string name="sort_db">Tietokannan lajittelujärjestys</string>
|
||||
@@ -134,9 +132,7 @@
|
||||
<string name="unsupported_db_version">Ei-tuettu salasanatietokannan versio.</string>
|
||||
<string name="uppercase">Isot kirjaimet</string>
|
||||
<string name="version_label">Versio %1$s</string>
|
||||
|
||||
<string name="education_unlock_summary">Syötä salasana ja/tai avaintiedosto avataksesi tietokantasi.</string>
|
||||
|
||||
<string-array name="timeout_options">
|
||||
<item>5 sekuntia</item>
|
||||
<item>10 sekuntia</item>
|
||||
@@ -153,4 +149,15 @@
|
||||
<item>Keskikokoinen</item>
|
||||
<item>Suuri</item>
|
||||
</string-array>
|
||||
<string name="clipboard_swipe_clean">Pyyhkäise tyhjentääksesi leikepöydän</string>
|
||||
<string name="allow">Salli</string>
|
||||
<string name="extended_ASCII">Laajennettu ASCII</string>
|
||||
<string name="key_derivation_function">Avaimen derivointifunktio</string>
|
||||
<string name="master_key">Pääavain</string>
|
||||
<string name="contribution">Avustus</string>
|
||||
<string name="contact">Ota yhteyttä</string>
|
||||
<string name="content_description_open_file">Avaa tiedosto</string>
|
||||
<string name="encryption">Salaus</string>
|
||||
<string name="security">Turvallisuus</string>
|
||||
<string name="edit_entry">Muokkaa merkintää</string>
|
||||
</resources>
|
||||
@@ -31,7 +31,6 @@
|
||||
<string name="application">Application</string>
|
||||
<string name="menu_app_settings">Paramètres de l’application</string>
|
||||
<string name="menu_form_filling_settings">Remplissage de formulaire</string>
|
||||
<string name="beta_dontask">Ne plus afficher</string>
|
||||
<string name="brackets">Parenthèses (ou autres)</string>
|
||||
<string name="extended_ASCII">ASCII étendu</string>
|
||||
<string name="file_manager_install_description">Un gestionnaire de fichiers qui accepte l\'action d\'intention ACTION_CREATE_DOCUMENT et ACTION_OPEN_DOCUMENT est nécessaire pour créer, ouvrir et enregistrer des fichiers de base de données.</string>
|
||||
@@ -91,7 +90,7 @@
|
||||
<string name="hint_length">Longueur</string>
|
||||
<string name="hint_pass">Mot de passe</string>
|
||||
<string name="password">Mot de passe</string>
|
||||
<string name="invalid_credentials">Impossible de lire les identifiants. Si cela se reproduit, votre fichier de base de données est peut-être corrompu.</string>
|
||||
<string name="invalid_credentials">Impossible de lire les identifiants.</string>
|
||||
<string name="invalid_algorithm">Algorithme invalide.</string>
|
||||
<string name="invalid_db_sig">Impossible de reconnaître le format de la base de données.</string>
|
||||
<string name="keyfile_is_empty">Le fichier clé est vide.</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>
|
||||
@@ -30,7 +29,6 @@
|
||||
<string name="app_timeout">Tempo de espera da aplicación</string>
|
||||
<string name="app_timeout_summary">Tempo antes de bloquear a base de datos cando a aplicación está inactiva.</string>
|
||||
<string name="application">Aplicación</string>
|
||||
<string name="beta_dontask">Non amosar de novo</string>
|
||||
<string name="brackets">Parénteses</string>
|
||||
<string name="extended_ASCII">ASCII extendido</string>
|
||||
<string name="allow">Permitir</string>
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
<string name="app_timeout">ऐप का समय समाप्त</string>
|
||||
<string name="app_timeout_summary">ऐप लॉक होने से पहले निष्क्रियता</string>
|
||||
<string name="application">ऐप</string>
|
||||
<string name="beta_dontask">फिर मत दिखाना</string>
|
||||
<string name="brackets">कोष्ठक</string>
|
||||
<string name="extended_ASCII">विस्तारित ASCII</string>
|
||||
<string name="allow">अनुमति दें</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>
|
||||
@@ -30,7 +29,6 @@
|
||||
<string name="key_derivation_function">Funkcija izvedbe ključa</string>
|
||||
<string name="app_timeout_summary">Vrijeme neaktivnosti prije zaključavanja baze podataka</string>
|
||||
<string name="application">Aplikacija</string>
|
||||
<string name="beta_dontask">Ne prikazuj ponovno</string>
|
||||
<string name="brackets">Zagrade</string>
|
||||
<string name="extended_ASCII">Prošireni ASCII kod</string>
|
||||
<string name="file_manager_install_description">Za stvaranje, otvaranje i pohranu datoteka baze podataka potreban je upravitelj datoteka koji prihvaća zahtjeve ACTION_CREATE_DOCUMENT i ACTION_OPEN_DOCUMENT.</string>
|
||||
@@ -260,7 +258,7 @@
|
||||
<string name="error_save_database">Nije moguće spremiti bazu podataka.</string>
|
||||
<string name="error_otp_period">Razdoblje mora biti između %1$d i %2$d sekundi.</string>
|
||||
<string name="file_not_found_content">Nije moguće pronaći datoteku. Probajte je ponovno otvoriti iz vašeg upravitelja datotekama.</string>
|
||||
<string name="invalid_credentials">Akreditacija se ne može pročitati. Ako se ovo ponavlja, vaša datoteka baze podataka je možda oštećena.</string>
|
||||
<string name="invalid_credentials">Akreditacija se ne može pročitati.</string>
|
||||
<string name="list_size_title">Veličina članova liste</string>
|
||||
<string name="list_size_summary">Veličina teksta članova liste</string>
|
||||
<string name="lowercase">Mala slova</string>
|
||||
@@ -274,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>
|
||||
@@ -342,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>
|
||||
@@ -28,7 +28,6 @@
|
||||
<string name="app_timeout_summary">Tétlenség az adatbázis feloldása előtt</string>
|
||||
<string name="application">Alkalmazás</string>
|
||||
<string name="menu_app_settings">Alkalmazásbeállítások</string>
|
||||
<string name="beta_dontask">Ne mutassa újra</string>
|
||||
<string name="brackets">Zárójelek</string>
|
||||
<string name="file_manager_install_description">Egy fájlkezelő, amely fogadja az ACTION_CREATE_DOCUMENT és ACTION_OPEN_DOCUMENT Intenteket, melyek az adatbázisfájlok létrehozásához, megnyitásához és mentéséhez szükségesek.</string>
|
||||
<string name="clipboard_cleared">Vágólap törölve</string>
|
||||
@@ -84,7 +83,7 @@
|
||||
<string name="hint_length">Hossz</string>
|
||||
<string name="hint_pass">Jelszó</string>
|
||||
<string name="password">Jelszó</string>
|
||||
<string name="invalid_credentials">A hitelesítő adatok nem olvashatók. Ha ez újra megtörténik, akkor az adatbázisfájl sérült lehet.</string>
|
||||
<string name="invalid_credentials">A hitelesítő adatok nem olvashatók.</string>
|
||||
<string name="invalid_algorithm">Hibás algoritmus.</string>
|
||||
<string name="invalid_db_sig">Az adatbázis formátuma nem ismerhető fel.</string>
|
||||
<string name="keyfile_is_empty">A kulcsfájl üres.</string>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<string name="hint_length">Lunghezza</string>
|
||||
<string name="password">Password</string>
|
||||
<string name="hint_pass">Password</string>
|
||||
<string name="invalid_credentials">Non è possibile leggere le credenziali. Se questo dovesse riaccadere, il file del databese potrebbe essere corrotto.</string>
|
||||
<string name="invalid_credentials">Non è possibile leggere le credenziali.</string>
|
||||
<string name="invalid_algorithm">Algoritmo errato.</string>
|
||||
<string name="invalid_db_sig">Formato database non riconosciuto.</string>
|
||||
<string name="keyfile_is_empty">Il file chiave è vuoto.</string>
|
||||
@@ -138,7 +138,7 @@
|
||||
<string name="warning_password_encoding">Evita password con caratteri al di fuori del formato di codifica del testo nel file di database (i caratteri non riconosciuti vengono convertiti nella stessa lettera).</string>
|
||||
<string name="version_label">Versione %1$s</string>
|
||||
<string name="configure_biometric">La scansione di impronte è supportata ma non impostata.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Scansione impronte</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Usa la scansione impronte per sbloccare la banca dati</string>
|
||||
<string name="encrypted_value_stored">Password criptata salvata</string>
|
||||
<string name="biometric_invalid_key">Impossibile leggere la chiave biometrica. Eliminala e ripeti la procedura di riconoscimento.</string>
|
||||
<string name="biometric_scanning_error">Problema impronta: %1$s</string>
|
||||
@@ -163,7 +163,6 @@
|
||||
<item>Medio</item>
|
||||
<item>Grande</item>
|
||||
</string-array>
|
||||
<string name="beta_dontask">Non mostrare di nuovo</string>
|
||||
<string name="allow">Consenti</string>
|
||||
<string name="copy_field">Copia di %1$s</string>
|
||||
<string name="encryption">Cifratura</string>
|
||||
@@ -252,7 +251,7 @@
|
||||
<string name="allow_no_password_summary">Abilita il pulsante «Apri» se le credenziali non sono selezionate</string>
|
||||
<string name="enable_read_only_title">Protetto da scrittura</string>
|
||||
<string name="enable_read_only_summary">Apri il database in sola lettura in modo predefinito</string>
|
||||
<string name="enable_education_screens_title">Schermate educative</string>
|
||||
<string name="enable_education_screens_title">Suggerimenti educativi</string>
|
||||
<string name="enable_education_screens_summary">Evidenzia gli elementi per imparare come funziona l\'app</string>
|
||||
<string name="reset_education_screens_title">Ripristina le schermate educative</string>
|
||||
<string name="reset_education_screens_summary">Mostra di nuovo tutti gli elementi educativi</string>
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
<string name="app_timeout_summary">זמן לפני נעילת מסד הנתונים כאשר היישום לא פעיל.</string>
|
||||
<string name="application">יישום</string>
|
||||
<string name="menu_app_settings">הגדרות יישום</string>
|
||||
<string name="beta_dontask">אל תציג שוב</string>
|
||||
<string name="brackets">סוגריים</string>
|
||||
<string name="file_manager_install_description">סייר הקבצים דורש את סייר הקבצים Open Intents, לחץ למטע כדי להתקין. בגלל מספר בעיות בסייר, ייתכן ויהיו בעיות בהפעלה הראשונה.</string>
|
||||
<string name="clipboard_cleared">לוח ההעתקה נוקה.</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="feedback">フィードバック</string>
|
||||
<string name="homepage">ホームページ</string>
|
||||
<string name="about_description">KeePass パスワードマネージャーの Android 実装</string>
|
||||
@@ -26,22 +25,23 @@
|
||||
<string name="add_group">グループを追加</string>
|
||||
<string name="encryption_algorithm">暗号化アルゴリズム</string>
|
||||
<string name="app_timeout">アプリ タイムアウト</string>
|
||||
<string name="app_timeout_summary">KeePassがこの時間非アクティブだった場合、データベースをロックします。</string>
|
||||
<string name="application">アプリケーション</string>
|
||||
<string name="menu_app_settings">アプリケーション設定</string>
|
||||
<string name="app_timeout_summary">データベースをロックするまでの休止時間</string>
|
||||
<string name="application">アプリ</string>
|
||||
<string name="menu_app_settings">アプリの設定</string>
|
||||
<string name="brackets">カッコ</string>
|
||||
<string name="file_manager_install_description">ファイルを検索するには OI File Manager が必要です。</string>
|
||||
<string name="file_manager_install_description">ACTION_CREATE_DOCUMENT と ACTION_OPEN_DOCUMENT のインテントアクションを受け付けるファイルマネージャーがデータベースファイルの作成、オープン、保存に必要です。</string>
|
||||
<string name="clipboard_cleared">クリップボードを消去しました。</string>
|
||||
<string name="clipboard_timeout">クリップボード タイムアウト</string>
|
||||
<string name="clipboard_timeout_summary">コピーした情報をクリップボードから消去する時間</string>
|
||||
<string name="clipboard_timeout_summary">クリップボードでの保存時間</string>
|
||||
<string name="select_to_copy">ここをタップすると%1$sをクリップボードにコピーします</string>
|
||||
<string name="retrieving_db_key">データベース認証中…</string>
|
||||
<string name="database">データベース</string>
|
||||
<string name="decrypting_db">データベースを解析中…</string>
|
||||
<string name="default_checkbox">このデータベースを次回以降も利用する</string>
|
||||
<string name="decrypting_db">データベースを復号中…</string>
|
||||
<string name="default_checkbox">デフォルトのデータベースとして使う</string>
|
||||
<string name="digits">数字</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft によって作られたフリーソフトウェアであり、無保証です。GPLバージョン3以上の条件下でこれを再頒布することができます。</string>
|
||||
<string name="select_database_file">データベースファイル</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft は <strong>オープンソース</strong> であり <strong>広告はありません</strong>。
|
||||
\n現状のまま、<strong>GPLv3</strong> ライセンスのもとで、何らの保証もなく提供されます。</string>
|
||||
<string name="select_database_file">既存のデータベースを開く</string>
|
||||
<string name="entry_accessed">最終アクセス日</string>
|
||||
<string name="entry_cancel">キャンセル</string>
|
||||
<string name="entry_notes">備考</string>
|
||||
@@ -55,28 +55,28 @@
|
||||
<string name="entry_title">タイトル</string>
|
||||
<string name="entry_url">URL</string>
|
||||
<string name="entry_user_name">ユーザー名</string>
|
||||
<string name="error_arc4">Arcfour stream cipherには対応していません。</string>
|
||||
<string name="error_can_not_handle_uri">KeePassDXはこのuriを処理できません。</string>
|
||||
<string name="error_arc4">Arcfourストリーム暗号には対応していません。</string>
|
||||
<string name="error_can_not_handle_uri">KeePassDXはこのURIを処理できません。</string>
|
||||
<string name="error_file_not_create">ファイルを作成できません。</string>
|
||||
<string name="error_invalid_db">無効なデータベースです。</string>
|
||||
<string name="error_invalid_path">パスが無効です。</string>
|
||||
<string name="error_no_name">タイトルは必須入力です。</string>
|
||||
<string name="error_nokeyfile">パスワードかキーファイルが必要です。</string>
|
||||
<string name="error_out_of_memory">データベース解析中にメモリ不足になりました。</string>
|
||||
<string name="error_invalid_db">データベースを読み込めません。</string>
|
||||
<string name="error_invalid_path">パスが正しいことを確認してください。</string>
|
||||
<string name="error_no_name">名前を入力してください。</string>
|
||||
<string name="error_nokeyfile">キーファイルを選択してください。</string>
|
||||
<string name="error_out_of_memory">データベース全体を読み込むメモリがありません。</string>
|
||||
<string name="error_pass_gen_type">少なくとも1つ以上のパスワード生成タイプを選択する必要があります。</string>
|
||||
<string name="error_pass_match">パスワードが一致しません</string>
|
||||
<string name="error_pass_match">パスワードが一致しません。</string>
|
||||
<string name="error_rounds_too_large">値が大きすぎます。 2147483648にセットしました。</string>
|
||||
<string name="error_wrong_length">\"長さ\"欄には正の整数を入力してください。</string>
|
||||
<string name="file_browser">ファイルブラウザ</string>
|
||||
<string name="file_browser">ファイルマネージャー</string>
|
||||
<string name="generate_password">パスワードを生成する</string>
|
||||
<string name="hint_conf_pass">パスワードをもう一度入力</string>
|
||||
<string name="hint_generated_password">生成されたパスワードが表示されます</string>
|
||||
<string name="hint_generated_password">生成されたパスワード</string>
|
||||
<string name="hint_group_name">グループ名</string>
|
||||
<string name="hint_keyfile">キーファイル</string>
|
||||
<string name="hint_length">長さ</string>
|
||||
<string name="password">パスワード</string>
|
||||
<string name="hint_pass">パスワード</string>
|
||||
<string name="invalid_credentials">パスワード/キーファイルが違います。</string>
|
||||
<string name="invalid_credentials">認証情報が読めません。</string>
|
||||
<string name="invalid_db_sig">データベースフォーマットが認識できません。</string>
|
||||
<string name="length">生成するパスワードの長さ</string>
|
||||
<string name="list_size_title">グループ一覧サイズ</string>
|
||||
@@ -142,11 +142,10 @@
|
||||
<string name="edit_entry">エントリーを編集</string>
|
||||
<string name="encryption">暗号化</string>
|
||||
<string name="key_derivation_function">鍵導出関数</string>
|
||||
<string name="beta_dontask">今後、表示しない</string>
|
||||
<string name="extended_ASCII">拡張 ASCII</string>
|
||||
<string name="allow">許可</string>
|
||||
<string name="clipboard_error_title">クリップボードエラー</string>
|
||||
<string name="clipboard_error">一部の Samsung Android 携帯電話はアプリからクリップボードが使用できません。</string>
|
||||
<string name="clipboard_error">一部の端末ではアプリからクリップボードを使用できません。</string>
|
||||
<string name="clipboard_error_clear">クリップボードをクリアできません</string>
|
||||
<string name="clipboard_swipe_clean">スワイプすると今すぐクリップボードをクリアします</string>
|
||||
<string name="entry_not_found">エントリデータが見つかりませんでした。</string>
|
||||
@@ -214,4 +213,28 @@
|
||||
<string name="menu_empty_recycle_bin">ゴミ箱を空にする</string>
|
||||
<string name="command_execution">コマンド実行中…</string>
|
||||
<string name="warning_permanently_delete_nodes">削除するとこのエントリーは復活できませんがよろしいですか?</string>
|
||||
<string name="auto_focus_search_summary">データベースを開くとき検索を要求する</string>
|
||||
<string name="auto_focus_search_title">クイックサーチ</string>
|
||||
<string name="menu_delete_entry_history">履歴を削除する</string>
|
||||
<string name="menu_restore_entry_history">履歴を復元する</string>
|
||||
<string name="list_groups_show_number_entries_summary">グループ内のエントリーの数を表示</string>
|
||||
<string name="list_groups_show_number_entries_title">エントリーの数を表示</string>
|
||||
<string name="error_otp_digits">トークンは %1$d 桁 から %2$d 桁である必要があります。</string>
|
||||
<string name="error_create_database_file">このパスワードとキーファイルでデータベースを作成できません。</string>
|
||||
<string name="error_create_database">データベースファイルを作成できません。</string>
|
||||
<string name="error_label_exists">このラベルはすでに存在します。</string>
|
||||
<string name="error_disallow_no_credentials">少なくとも一つの認証情報がセットされる必要があります。</string>
|
||||
<string name="error_invalid_OTP">無効な OTP 秘密鍵。</string>
|
||||
<string name="otp_digits">桁</string>
|
||||
<string name="entry_setup_otp">ワンタイムパスワードを設定する</string>
|
||||
<string name="entry_attachments">添付</string>
|
||||
<string name="entry_UUID">UUID</string>
|
||||
<string name="html_about_contribution"><strong>自由を維持し</strong><strong>バグを修正し</strong>と<strong>機能を追加し</strong> and <strong>活発に開発し続ける</strong>ためには、あなたの<strong>貢献</strong>が頼りです。</string>
|
||||
<string name="content_description_keyfile_checkbox">キーファイルのチェックボックス</string>
|
||||
<string name="content_description_password_checkbox">パスワードのチェックボックス</string>
|
||||
<string name="content_description_add_node">ノードの追加</string>
|
||||
<string name="content_description_node_children">ノードの子要素</string>
|
||||
<string name="content_description_background">バックグラウンド</string>
|
||||
<string name="security">セキュリティ</string>
|
||||
<string name="contribution">貢献</string>
|
||||
</resources>
|
||||
@@ -31,7 +31,6 @@
|
||||
<string name="app_timeout">앱 자동 종료 시간</string>
|
||||
<string name="app_timeout_summary">앱이 잠기기 전에 비활성화됨</string>
|
||||
<string name="application">앱</string>
|
||||
<string name="beta_dontask">다시 보이지 않음</string>
|
||||
<string name="brackets">브라켓</string>
|
||||
<string name="extended_ASCII">확장 ASCII</string>
|
||||
<string name="file_manager_install_description">OpenIntents File Manager를 설치하여 파일 찾아보기</string>
|
||||
|
||||
@@ -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>
|
||||
@@ -30,7 +29,6 @@
|
||||
<string name="app_timeout_summary">Laikas, per kurį yra užrakinama duomenų bazė po neveiklumo programėlėje.</string>
|
||||
<string name="application">Programėlė</string>
|
||||
<string name="menu_app_settings">Programėlės nustatymai</string>
|
||||
<string name="beta_dontask">Daugiau neberodyti</string>
|
||||
<string name="brackets">Skliaustai</string>
|
||||
<string name="database">Duomenų bazė</string>
|
||||
<string name="digits">Skaitmenys</string>
|
||||
@@ -108,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>
|
||||
@@ -29,7 +28,6 @@
|
||||
<string name="app_timeout_summary">Bloķēšanas taimauts, kad programma nav aktīva.</string>
|
||||
<string name="application">Programma</string>
|
||||
<string name="menu_app_settings">Programmas iestatījumi</string>
|
||||
<string name="beta_dontask">Turpmāk nerādīt</string>
|
||||
<string name="brackets">Iekavas</string>
|
||||
<string name="file_manager_install_description">Failu pārlūkošanai nepieciešams pārlūks.</string>
|
||||
<string name="clipboard_cleared">Starpliktuve notīrīta</string>
|
||||
@@ -132,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>
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
<string name="app_timeout">Programtidsavbrudd</string>
|
||||
<string name="app_timeout_summary">Inaktivitet før programmet låses</string>
|
||||
<string name="application">Program</string>
|
||||
<string name="beta_dontask">Ikke vis igjen</string>
|
||||
<string name="brackets">Parenteser</string>
|
||||
<string name="extended_ASCII">Utvidet ASCII</string>
|
||||
<string name="file_manager_install_description">Utforsk filer ved å installere OpenIntents-filbehandleren</string>
|
||||
@@ -223,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>
|
||||
@@ -256,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>
|
||||
@@ -282,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>
|
||||
@@ -297,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>
|
||||
@@ -320,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>
|
||||
@@ -332,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 +427,10 @@
|
||||
<string name="lock_database_show_button_summary">Viser låseknappen i brukergrensesnittet</string>
|
||||
<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>
|
||||
@@ -18,37 +18,37 @@
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Dutch translation by Erik Devriendt, corrected by Erik Jan Meijer
|
||||
-->
|
||||
<resources>
|
||||
--><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>
|
||||
<string name="encryption_algorithm">Algoritme</string>
|
||||
<string name="app_timeout">App-time-out</string>
|
||||
<string name="app_timeout_summary">Tijd tot vergrendelen bij inactiviteit</string>
|
||||
<string name="app_timeout_summary">Tijd tot vergrendeling bij inactiviteit</string>
|
||||
<string name="application">App</string>
|
||||
<string name="menu_app_settings">App-instellingen</string>
|
||||
<string name="brackets">Haakjes</string>
|
||||
<string name="file_manager_install_description">Zoek een bestand op door het installeren van de OpenIntents File Manager</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>
|
||||
<string name="select_to_copy">Selecteer om %1$s naar klembord te kopiëren</string>
|
||||
<string name="retrieving_db_key">Bezig met creëren van databanksleutel…</string>
|
||||
<string name="database">Databank</string>
|
||||
<string name="decrypting_db">Bezig met ontsleutelen van databankinhoud…</string>
|
||||
<string name="default_checkbox">Gebruiken als standaarddatabank</string>
|
||||
<string name="retrieving_db_key">Databasesleutel ophalen…</string>
|
||||
<string name="database">Database</string>
|
||||
<string name="decrypting_db">Database-inhoud decoderen …</string>
|
||||
<string name="default_checkbox">Gebruiken als standaarddatabase</string>
|
||||
<string name="digits">Getallen</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft biedt geen enkele garantie. Dit is vrije software, dus je mag deze software verspreiden onder de voorwaarden van de GPL versie 3 of recenter.</string>
|
||||
<string name="select_database_file">Bestaande databank openen</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft is <strong>open source</strong> en <strong>zonder reclame</strong>.
|
||||
\nHet wordt geleverd zoals het is, onder <strong>GPLv3</strong> -licentie, zonder enige garantie.</string>
|
||||
<string name="select_database_file">Bestaande database openen</string>
|
||||
<string name="entry_accessed">Laatst geopend</string>
|
||||
<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,43 +59,43 @@
|
||||
<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_invalid_db">Kan databank niet uitlezen.</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>
|
||||
<string name="error_nokeyfile">Kies een sleutelbestand.</string>
|
||||
<string name="error_out_of_memory">Onvoldoende vrij geheugen om de gehele databank te laden.</string>
|
||||
<string name="error_out_of_memory">Onvoldoende vrij geheugen om de gehele database te laden.</string>
|
||||
<string name="error_pass_gen_type">Je moet minimaal één soort wachtwoordgenerering kiezen.</string>
|
||||
<string name="error_pass_match">De wachtwoorden komen niet overeen.</string>
|
||||
<string name="error_rounds_too_large">\"Cycli-waarde\" te groot. Wordt ingesteld op 2147483648.</string>
|
||||
<string name="error_wrong_length">Voer een positief geheel getal in in het veld \"Lengte\".</string>
|
||||
<string name="file_browser">Bestandsverkenner</string>
|
||||
<string name="file_browser">Bestandsbeheer</string>
|
||||
<string name="generate_password">Wachtwoord genereren</string>
|
||||
<string name="hint_conf_pass">wachtwoord bevestigen</string>
|
||||
<string name="hint_generated_password">gegenereerd wachtwoord</string>
|
||||
<string name="hint_conf_pass">Wachtwoord bevestigen</string>
|
||||
<string name="hint_generated_password">Gegenereerd wachtwoord</string>
|
||||
<string name="hint_group_name">Groepsnaam</string>
|
||||
<string name="hint_keyfile">sleutelbestand</string>
|
||||
<string name="hint_length">lengte</string>
|
||||
<string name="hint_keyfile">Sleutelbestand</string>
|
||||
<string name="hint_length">Lengte</string>
|
||||
<string name="password">Wachtwoord</string>
|
||||
<string name="hint_pass">wachtwoord</string>
|
||||
<string name="invalid_credentials">Ongeldig wachtwoord of sleutelbestand.</string>
|
||||
<string name="invalid_db_sig">Databankformaat kan niet worden herkend.</string>
|
||||
<string name="hint_pass">Wachtwoord</string>
|
||||
<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">Grootte van itemlijst</string>
|
||||
<string name="list_size_summary">Tekstgrootte van itemlijst</string>
|
||||
<string name="loading_database">Bezig met laden van databank…</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>
|
||||
<string name="menu_database_settings">Databank-instellingen</string>
|
||||
<string name="menu_database_settings">Instellingen database</string>
|
||||
<string name="menu_delete">Verwijderen</string>
|
||||
<string name="menu_donate">Doneren</string>
|
||||
<string name="menu_edit">Bewerken</string>
|
||||
<string name="menu_hide_password">Wachtwoord verbergen</string>
|
||||
<string name="menu_lock">Databank vergrendelen</string>
|
||||
<string name="menu_lock">Database vergrendelen</string>
|
||||
<string name="menu_open">Openen</string>
|
||||
<string name="menu_search">Zoeken</string>
|
||||
<string name="menu_showpass">Wachtwoord tonen</string>
|
||||
@@ -106,14 +106,14 @@
|
||||
<string name="no_url_handler">Installeer een webbrowser om deze URL te openen.</string>
|
||||
<string name="omit_backup_search_title">Back-upitems niet doorzoeken</string>
|
||||
<string name="omit_backup_search_summary">Hiermee worden groepen \"Back-up\" en \"Prullenbak\" uit de zoekresultaten weggelaten</string>
|
||||
<string name="progress_create">Bezig met creëren van nieuwe databank…</string>
|
||||
<string name="progress_create">Nieuwe database aanmaken…</string>
|
||||
<string name="progress_title">Bezig met verwerken…</string>
|
||||
<string name="content_description_remove_from_list">Verwijderen</string>
|
||||
<string name="encryption_rijndael">Rijndael (AES)</string>
|
||||
<string name="root">Hoofdmap</string>
|
||||
<string name="rounds">Encryptie-cycli</string>
|
||||
<string name="rounds_explanation">Een hoger aantal encryptie-cycli geeft bijkomende bescherming tegen brute-force aanvallen, maar kan het laden en opslaan sterk vertragen.</string>
|
||||
<string name="saving_database">Bezig met opslaan van databank…</string>
|
||||
<string name="saving_database">Database opslaan…</string>
|
||||
<string name="space">Ruimte</string>
|
||||
<string name="search_label">Zoeken</string>
|
||||
<string name="sort_db">Natuurlijke volgorde</string>
|
||||
@@ -121,10 +121,10 @@
|
||||
<string name="search">Zoeken</string>
|
||||
<string name="encryption_twofish">Twofish</string>
|
||||
<string name="underline">Onderstrepen</string>
|
||||
<string name="unsupported_db_version">Niet-ondersteunde databankversie.</string>
|
||||
<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 databank 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">
|
||||
@@ -146,44 +146,43 @@
|
||||
<string name="edit_entry">Item bewerken</string>
|
||||
<string name="encryption">Versleuteling</string>
|
||||
<string name="key_derivation_function">Sleutelafleidingsfunctie</string>
|
||||
<string name="beta_dontask">Niet meer tonen</string>
|
||||
<string name="extended_ASCII">Uitgebreide ASCII</string>
|
||||
<string name="allow">Toestaan</string>
|
||||
<string name="clipboard_error_title">Klembordfout</string>
|
||||
<string name="clipboard_error">Op sommige Samsung-telefoons hebben apps geen toegang tot het klembord.</string>
|
||||
<string name="clipboard_error">Sommige apparaten staan niet toe dat apps het klembord gebruiken.</string>
|
||||
<string name="clipboard_error_clear">Wissen van klembord mislukt</string>
|
||||
<string name="clipboard_swipe_clean">Veeg om klembord nu te wissen</string>
|
||||
<string name="entry_not_found">Geen iteminhoud gevonden.</string>
|
||||
<string name="error_load_database">Je databank kan niet worden geladen.</string>
|
||||
<string name="error_load_database">Je database kan niet worden geladen.</string>
|
||||
<string name="error_load_database_KDF_memory">De sleutel kan niet worden geladen. Probeer om het \"geheugengebruik\" van KDF te verminderen.</string>
|
||||
<string name="error_string_key">Elke zin moet een veldnaam bevatten.</string>
|
||||
<string name="error_autofill_enable_service">De dienst automatisch aanvullen kan niet worden ingeschakeld.</string>
|
||||
<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="encryption_explanation">Het algoritme dat moet worden gebruikt om de gehele databank te versleutelen.</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>
|
||||
<string name="memory_usage_explanation">Het geheugen (in binaire bytes) dat de afleidingsfunctie mag gebruiken.</string>
|
||||
<string name="memory_usage_explanation">De hoeveelheid geheugen (bytes) dat de afleidingsfunctie mag gebruiken.</string>
|
||||
<string name="parallelism">Parallellen</string>
|
||||
<string name="parallelism_explanation">Het aantal parallellen (aantal threads) dat de afleidingsfunctie mag gebruiken.</string>
|
||||
<string name="sort_menu">Sorteren</string>
|
||||
@@ -198,15 +197,15 @@
|
||||
<string name="search_results">Zoekresultaten</string>
|
||||
<string name="warning">Waarschuwing</string>
|
||||
<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">Weet je zeker dat je geen wachtwoordontgrendelbescherming wilt\?</string>
|
||||
<string name="warning_no_encryption_key">Weet je zeker dat je geen sleutel wilt koppelen aan je versleuteling?</string>
|
||||
<string name="configure_biometric">Vingerafdruk wordt ondersteund, maar is niet ingesteld.</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Vingerafdrukscanning</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">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 vingerafdruksleutel niet lezen; herstel je wachtwoord.</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>
|
||||
@@ -214,32 +213,32 @@
|
||||
<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 wachtwoordgrootte</string>
|
||||
<string name="password_size_summary">Standaardgrootte instellen van gegenereerd wachtwoord</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>
|
||||
<string name="clipboard_warning">Als automatisch wissen van het klembord mislukt, doe dit dan handmatig.</string>
|
||||
<string name="lock">Vergrendelen</string>
|
||||
<string name="lock_database_screen_off_title">Schermvergrendeling</string>
|
||||
<string name="lock_database_screen_off_summary">Databank vergrendelen als het scherm uitgaat</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="biometric_delete_all_key_warning">Weet je zeker dat je alle sleutels van de vingerafdrukherkenning wilt verwijderen\?</string>
|
||||
<string name="lock_database_screen_off_summary">Database vergrendelen wanneer het scherm is uitgeschakeld</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>
|
||||
<string name="unavailable_feature_hardware">De bijbehorende hardware werd niet gevonden.</string>
|
||||
<string name="file_name">Bestandsnaam</string>
|
||||
<string name="path">Pad</string>
|
||||
<string name="assign_master_key">Hoofdsleutel toewijzen</string>
|
||||
<string name="create_keepass_file">Nieuwe databank creëren</string>
|
||||
<string name="create_keepass_file">Nieuwe database aanmaken</string>
|
||||
<string name="full_file_path_enable_title">Bestandspad</string>
|
||||
<string name="full_file_path_enable_summary">Volledig bestandspad tonen</string>
|
||||
<string name="recycle_bin_title">Prullenbak gebruiken</string>
|
||||
@@ -247,87 +246,84 @@
|
||||
<string name="monospace_font_fields_enable_title">Veldlettertype</string>
|
||||
<string name="monospace_font_fields_enable_summary">Wijzig het lettertype dat in velden wordt gebruikt voor een betere leesbaarheid</string>
|
||||
<string name="allow_copy_password_title">Klembord vertrouwen</string>
|
||||
<string name="allow_copy_password_summary">Toestaan dat het wachtwoord en beveiligde velden worden gekopieerd naar het klembord</string>
|
||||
<string name="allow_copy_password_warning">WAARSCHUWING: het klembord wordt gedeeld door alle apps. Als gevoelige gegevens worden gekopieerd, kan andere software deze opvragen.</string>
|
||||
<string name="database_name_title">Databanknaam</string>
|
||||
<string name="database_description_title">Databankomschrijving</string>
|
||||
<string name="database_version_title">Databankversie</string>
|
||||
<string name="allow_copy_password_summary">Toestaan dat het wachtwoord en beveiligde velden naar het klembord worden gekopieerd</string>
|
||||
<string name="allow_copy_password_warning">Waarschuwing: Het klembord wordt met alle aps gedeeld. Als gevoelige gegevens worden gekopieerd, kan andere software deze opvragen.</string>
|
||||
<string name="database_name_title">Databasenaam</string>
|
||||
<string name="database_description_title">Databaseomschrijving</string>
|
||||
<string name="database_version_title">Databaseversie</string>
|
||||
<string name="text_appearance">Tekst</string>
|
||||
<string name="application_appearance">App</string>
|
||||
<string name="other">Overig</string>
|
||||
<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 databank standaard alleen-lezen</string>
|
||||
<string name="enable_education_screens_title">Educatieve vensters</string>
|
||||
<string name="enable_education_screens_summary">Markeert de elementen om te leren hoe de app werkt</string>
|
||||
<string name="reset_education_screens_title">Standaardwaarden</string>
|
||||
<string name="reset_education_screens_summary">Educatieve vensters opnieuw weergeven</string>
|
||||
<string name="reset_education_screens_text">Educatieve vensters hersteld</string>
|
||||
<string name="education_create_database_title">Creëer je databankbestand</string>
|
||||
<string name="enable_read_only_summary">Open de database standaard alleen-lezen</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">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 databank</string>
|
||||
<string name="education_select_database_summary">Open vanuit je bestandsverkenner een bestaande databank om dit verder te gebruiken.</string>
|
||||
<string name="education_new_node_title">Voeg items toe aan de databank</string>
|
||||
<string name="education_new_node_summary">Voeg items toe om je digitale identiteiten te beheren.
|
||||
<string name="education_select_database_title">Open een bestaande database</string>
|
||||
<string name="education_select_database_summary">Open vanuit je bestandsverkenner een bestaande database om dit verder te gebruiken.</string>
|
||||
<string name="education_new_node_title">Voeg items toe aan de database</string>
|
||||
<string name="education_new_node_summary">Items helpen om je digitale identiteiten te beheren.
|
||||
\n
|
||||
\nVoeg groepen toe (groepen zijn gelijk aan mappen) om items in je databank te organiseren.</string>
|
||||
\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 databank met je vingerafdruk</string>
|
||||
<string name="education_biometric_summary">Koppel je wachtwoord en vingerafdruk om de databank 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 voor het item.</string>
|
||||
<string name="education_generate_password_title">Genereer een sterk wachtwoord</string>
|
||||
<string name="education_generate_password_summary">Genereer een sterk wachtwoord om aan het item te koppelen, definieer het eenvoudig volgens de criteria van het formulier en vergeet het veilige wachtwoord niet.</string>
|
||||
<string name="education_entry_new_field_title">Voeg aangepaste velden toe</string>
|
||||
<string name="education_entry_new_field_summary">Registreer een aanvullend veld door een nieuw aan te maken en dit tevens te beschermen.</string>
|
||||
<string name="education_unlock_title">Ontgrendel je databank</string>
|
||||
<string name="education_read_only_title">Databank alleen-lezen</string>
|
||||
<string name="education_entry_new_field_summary">Registreer een extra veld, voeg een waarde toe en bescherm dit desgewenst.</string>
|
||||
<string name="education_unlock_title">Ontgrendel je database</string>
|
||||
<string name="education_read_only_title">Database alleen-lezen</string>
|
||||
<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.
|
||||
\n
|
||||
\nJe kunt verschillende formulier-invulmethodes gebruiken; kies je voorkeursmethode.</string>
|
||||
<string name="education_lock_title">Databank vergrendelen</string>
|
||||
<string name="education_lock_summary">Databank snel vergrendelen. Je kunt de app zo instellen dat deze na een tijdje wordt vergrendeld en wanneer het scherm wordt uitgeschakeld.</string>
|
||||
<string name="education_lock_title">Database vergrendelen</string>
|
||||
<string name="education_lock_summary">Database snel vergrendelen. Je kunt de app zo instellen dat deze na een tijdje wordt vergrendeld en wanneer het scherm wordt uitgeschakeld.</string>
|
||||
<string name="education_sort_title">Items sorteren</string>
|
||||
<string name="education_sort_summary">Kies hoe items en groepen worden gesorteerd.</string>
|
||||
<string name="education_donation_title">Bijdragen</string>
|
||||
<string name="education_donation_summary">Draag bij om de stabiliteit en veiligheid te vergroten en door meer functies toe te voegen.</string>
|
||||
<string name="html_text_ad_free">In tegenstelling tot veel wachtwoordbeheerapps is deze <strong>reclamevrij</strong>, <strong>vrije software</strong> en slaat geen persoonlijke gegevens op op haar servers, ongeacht de versie die je gebruikt.</string>
|
||||
<string name="html_text_buy_pro">Door de pro-versie te kopen krijg je toegang tot deze <strong>visuele functie</strong> en draag je bij aan het <strong>realiseren van gemeenschapsprojecten.</strong>
|
||||
</string>
|
||||
<string name="html_text_feature_generosity">Deze <strong>visuele functie</strong> is beschikbaar gekomen door jullie gulheid.</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_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, 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>
|
||||
<string name="html_text_dev_feature_encourage">motiveer je ontwikkelaars om <strong>nieuwe functies</strong> te creëren en <strong>bugs op te lossen</strong>.</string>
|
||||
<string name="html_text_dev_feature_encourage">motiveer je ontwikkelaars om <strong>nieuwe functies</strong> te creëren en <strong>problemen op te lossen</strong>.</string>
|
||||
<string name="html_text_dev_feature_thanks">Hartelijk bedankt voor je bijdrage.</string>
|
||||
<string name="html_text_dev_feature_work_hard">We zijn druk bezig om deze functie snel beschikbaar te stellen.</string>
|
||||
<string name="html_text_dev_feature_upgrade">Vergeet niet om je app up-to-date te houden door nieuwe versies te installeren.</string>
|
||||
<string name="download">Downloaden</string>
|
||||
<string name="contribute">Bijdragen</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">App-thema</string>
|
||||
<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">Magikeyboard-instellingen</string>
|
||||
<string name="keyboard_setting_label">Instellingen Magikeyboard</string>
|
||||
<string name="keyboard_entry_category">Item</string>
|
||||
<string name="keyboard_entry_timeout_title">Time-out</string>
|
||||
<string name="keyboard_entry_timeout_summary">Time-out om de toetsenbordinvoer te wissen</string>
|
||||
@@ -337,7 +333,7 @@
|
||||
<string name="keyboard_notification_entry_content_title">%1$s beschikbaar op Magikeyboard</string>
|
||||
<string name="keyboard_notification_entry_content_text">%1$s</string>
|
||||
<string name="keyboard_notification_entry_clear_close_title">Wissen bij het sluiten</string>
|
||||
<string name="keyboard_notification_entry_clear_close_summary">Sluit de databank tegelijk met de melding</string>
|
||||
<string name="keyboard_notification_entry_clear_close_summary">Sluit de database tegelijk met de melding</string>
|
||||
<string name="keyboard_appearance_category">Uiterlijk</string>
|
||||
<string name="keyboard_theme_title">Toetsenbordthema</string>
|
||||
<string name="keyboard_keys_category">Toetsen</string>
|
||||
@@ -345,15 +341,15 @@
|
||||
<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_summary">Vergrendel de databank wanneer de gebruiker op de knop Terug in het hoofdscherm klikt</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">Sluit de databank tegelijk met de melding</string>
|
||||
<string name="clear_clipboard_notification_summary">Vergrendel de database wanneer u de melding sluit</string>
|
||||
<string name="recycle_bin">Prullenmand</string>
|
||||
<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>
|
||||
@@ -371,7 +367,7 @@
|
||||
<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>
|
||||
@@ -379,12 +375,12 @@
|
||||
<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">Databasereferenties opslaan met biometrische gegevens</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">Biometrische prompt automatisch openen wanneer een biometrische sleutel is gedefinieerd voor een database</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 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>
|
||||
@@ -399,7 +395,7 @@
|
||||
<string name="otp_algorithm">Algoritme</string>
|
||||
<string name="entry_otp">OTP</string>
|
||||
<string name="error_invalid_OTP">Ongeldig OTP-geheim.</string>
|
||||
<string name="error_disallow_no_credentials">Tenminste één referentie moet worden ingesteld.</string>
|
||||
<string name="error_disallow_no_credentials">Er moet tenminste één referentie worden ingesteld.</string>
|
||||
<string name="error_copy_group_here">Je kunt hier geen groep kopiëren.</string>
|
||||
<string name="error_otp_secret_key">Geheime sleutel moet in Base32-indeling zijn.</string>
|
||||
<string name="error_otp_counter">Teller moet tussen %1$d en %2$d liggen.</string>
|
||||
@@ -410,26 +406,74 @@
|
||||
<string name="menu_security_settings">Beveiligingsinstellingen</string>
|
||||
<string name="menu_master_key_settings">Instellingen hoofdsleutel</string>
|
||||
<string name="contains_duplicate_uuid">De database bevat dubbele UUID\'s.</string>
|
||||
<string name="contains_duplicate_uuid_procedure">Door dit dialoogvenster te valideren, zal KeePassDX het probleem oplossen (door nieuwe UUID\'s voor duplicaten te genereren) en doorgaan.</string>
|
||||
<string name="contains_duplicate_uuid_procedure">Probleem oplossen door nieuwe UUID\'s te genereren voor de duplicaten\?</string>
|
||||
<string name="database_opened">Database geopend</string>
|
||||
<string name="clipboard_explanation_summary">Kopieer invoervelden met behulp van het klembord van uw apparaat</string>
|
||||
<string name="advanced_unlock_explanation_summary">Geavanceerde ontgrendeling gebruiken om een database gemakkelijker te openen</string>
|
||||
<string name="database_data_compression_title">Gegevenscompressie</string>
|
||||
<string name="database_data_compression_summary">Gegevenscompressie verkleint de omvang van de database.</string>
|
||||
<string name="max_history_items_title">Max. geschiedenis items</string>
|
||||
<string name="max_history_items_title">Maximum aantal</string>
|
||||
<string name="max_history_items_summary">Beperk het aantal geschiedenisitems per item</string>
|
||||
<string name="max_history_size_title">Max. grootte van de geschiedenis</string>
|
||||
<string name="max_history_size_summary">Grootte van geschiedenis beperken per invoer (in binaire bytes)</string>
|
||||
<string name="settings_database_recommend_changing_master_key_title">Aanbevolen wijzigen</string>
|
||||
<string name="max_history_size_title">Maximum</string>
|
||||
<string name="max_history_size_summary">Geschiedenis (bytes) per item beperken</string>
|
||||
<string name="settings_database_recommend_changing_master_key_title">Vernieuwing aanbevelen</string>
|
||||
<string name="settings_database_recommend_changing_master_key_summary">Aanbeveling de hoofdsleutel te wijzigen (dagen)</string>
|
||||
<string name="settings_database_force_changing_master_key_title">Wijziging afdwingen</string>
|
||||
<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 wijzigen</string>
|
||||
<string name="settings_database_force_changing_master_key_next_time_summary">Het hoofdwachtwoord de volgende keer verplicht wijzigen (eenmalig)</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 (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="compression_gzip">gzip</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">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">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 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>
|
||||
<string name="warning_database_read_only">Bestandstoegang verlenen om databasewijzigingen op te slaan</string>
|
||||
<string name="command_execution">Opdracht uitvoeren…</string>
|
||||
<string name="hide_broken_locations_summary">Verberg gebroken links in de lijst met recente databases</string>
|
||||
<string name="hide_broken_locations_title">Verberg corrupte databasekoppelingen</string>
|
||||
<string name="remember_keyfile_locations_summary">Onthoud de locatie van databasesleutelbestanden</string>
|
||||
<string name="remember_database_locations_summary">Onthoud de locatie van databases</string>
|
||||
<string name="auto_focus_search_summary">Zoekopdracht aanmaken bij het openen van een database</string>
|
||||
<string name="auto_focus_search_title">Snel zoeken</string>
|
||||
<string name="menu_delete_entry_history">Geschiedenis wissen</string>
|
||||
<string name="menu_restore_entry_history">Geschiedenis herstellen</string>
|
||||
<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">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>, 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>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
<string name="hint_length">Długość</string>
|
||||
<string name="password">Hasło</string>
|
||||
<string name="hint_pass">Hasło</string>
|
||||
<string name="invalid_credentials">Nie można odczytać uwierzytelnień. Jeśli to się powtórzy, plik bazy danych może być uszkodzony.</string>
|
||||
<string name="invalid_credentials">Nie można odczytać uwierzytelnień.</string>
|
||||
<string name="invalid_db_sig">Nie można rozpoznać formatu bazy danych.</string>
|
||||
<string name="length">Długość</string>
|
||||
<string name="list_size_title">Wielkość listy grup</string>
|
||||
@@ -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>
|
||||
@@ -141,7 +141,6 @@
|
||||
<string name="edit_entry">Edytuj wpis</string>
|
||||
<string name="encryption">Szyfrowanie</string>
|
||||
<string name="key_derivation_function">Funkcja generująca klucz</string>
|
||||
<string name="beta_dontask">Nie pokazuj ponownie</string>
|
||||
<string name="extended_ASCII">Rozszerzone ASCII</string>
|
||||
<string name="allow">Zezwalaj</string>
|
||||
<string name="clipboard_error_title">Błąd schowka</string>
|
||||
@@ -198,7 +197,7 @@
|
||||
<string name="configure_biometric">Skanowanie odcisków palców jest obsługiwane, ale nie skonfigurowane.</string>
|
||||
<string name="encrypted_value_stored">Zapisano zaszyfrowane hasło</string>
|
||||
<string name="sort_groups_before">Grupy poprzednie</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Skanowanie odcisków palców</string>
|
||||
<string name="open_biometric_prompt_unlock_database">Otwórz żądanie biometryczne, aby odblokować bazę danych</string>
|
||||
<string name="biometric_invalid_key">Nie można odczytać klucza biometrycznego. Usuń go i powtórz procedurę rozpoznawania biometrycznego.</string>
|
||||
<string name="biometric_not_recognized">Nie można rozpoznać odcisku palca</string>
|
||||
<string name="biometric_scanning_error">Problem z odciskiem palca: %1$s</string>
|
||||
@@ -345,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>
|
||||
@@ -475,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>
|
||||
@@ -75,7 +75,7 @@
|
||||
<string name="hint_length">Tamanho</string>
|
||||
<string name="password">Senha</string>
|
||||
<string name="hint_pass">Senha</string>
|
||||
<string name="invalid_credentials">Não foi possível ler credenciais. Se isso ocorrer novamente, seu arquivo de banco de dados pode estar corrompido.</string>
|
||||
<string name="invalid_credentials">Não foi possível ler credenciais.</string>
|
||||
<string name="invalid_db_sig">Não pôde reconhecer formato do banco de dados.</string>
|
||||
<string name="length">Tamanho</string>
|
||||
<string name="list_size_title">Tamanho da lista de grupos</string>
|
||||
@@ -142,7 +142,6 @@
|
||||
</string-array>
|
||||
<string name="encryption">Encriptação</string>
|
||||
<string name="key_derivation_function">Função de derivação de chave</string>
|
||||
<string name="beta_dontask">Não mostrar novamente</string>
|
||||
<string name="extended_ASCII">ASCII Extendido</string>
|
||||
<string name="allow">Permitir</string>
|
||||
<string name="clipboard_error_title">Erro na área de transferência</string>
|
||||
@@ -193,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>
|
||||
@@ -348,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>
|
||||
@@ -475,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>
|
||||
@@ -29,7 +29,6 @@
|
||||
<string name="app_timeout_summary">Inatividade antes da app ser bloqueada</string>
|
||||
<string name="application">App</string>
|
||||
<string name="menu_app_settings">Configurações do aplicativo</string>
|
||||
<string name="beta_dontask">Não mostrar novamente</string>
|
||||
<string name="brackets">Parênteses</string>
|
||||
<string name="file_manager_install_description">Explore ficheiros instalando o gestor de ficheiros OpenIntents</string>
|
||||
<string name="clipboard_cleared">Área de transferência limpa</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user