Compare commits

...

58 Commits

Author SHA1 Message Date
J-Jamet
33beb57e9d Merge branch 'release/2.9.16' 2021-04-07 09:53:07 +02:00
J-Jamet
66eeadca0b Upgrade version code 2021-04-06 17:39:27 +02:00
J-Jamet
a10d1c98a8 Fix KDB parcelable 2021-04-06 17:32:40 +02:00
J-Jamet
59ead4986f Move Parent Parcelable 2021-04-06 15:05:11 +02:00
J-Jamet
09f6c18189 Small changes 2021-04-06 15:02:24 +02:00
J-Jamet
0f3ad7c8b1 Fix select custom icon 2021-04-05 19:06:54 +02:00
J-Jamet
0487dea7fc Fix null cache directory 2021-04-05 11:32:07 +02:00
J-Jamet
8cac1ee284 Merge branch 'feature/ExternalFileHelper' into develop 2021-04-05 00:06:03 +02:00
J-Jamet
196620e1bd Remove unused methods 2021-04-05 00:04:25 +02:00
J-Jamet
43d6c76873 Refactor open document click listener 2021-04-04 23:44:25 +02:00
J-Jamet
b864c39a0d Fix add database workflow in some devices 2021-04-04 23:13:24 +02:00
J-Jamet
818b975111 Change default type verification to create document 2021-04-04 09:56:09 +02:00
J-Jamet
d5fbc8393f Change file creation methods 2021-04-03 19:40:55 +02:00
J-Jamet
7b5e9d2344 Better parcelable entry CREATOR implementation #948 2021-04-02 09:37:18 +02:00
J-Jamet
7fc2d95886 Fix document file retrievment 2021-04-01 10:52:00 +02:00
J-Jamet
78d3b369bb Move Parcelable inheritance 2021-03-31 19:39:07 +02:00
J-Jamet
bb3620680b Upgrade version 2021-03-31 17:58:49 +02:00
J-Jamet
d4a45655ca Merge tag '2.9.15' into develop
2.9.15
2021-03-29 22:01:52 +02:00
J-Jamet
c9c739fd52 Merge branch 'release/2.9.15' 2021-03-29 22:01:44 +02:00
J-Jamet
2b359cc592 Remove unused code 2021-03-29 21:00:10 +02:00
J-Jamet
151b7a323d Upgrade version code 2021-03-29 13:58:30 +02:00
J-Jamet
1063dc2b63 Add TODO SparseArray 2021-03-29 13:57:30 +02:00
J-Jamet
f9f59a6eb1 Replace serializable UUID by Parcelable UUID 2021-03-29 13:49:49 +02:00
J-Jamet
73156cc337 Fix clipboard null exception 2021-03-29 13:09:22 +02:00
J-Jamet
7d53607f49 Capture exception when launching cipher action 2021-03-29 13:07:55 +02:00
J-Jamet
7539945465 Capture exception when error when launching database action 2021-03-29 13:01:31 +02:00
J-Jamet
51df8e7bb1 Try to fix rare bug 2021-03-29 12:52:12 +02:00
J-Jamet
17029ce67c Fix bad padding exception 2021-03-29 12:42:53 +02:00
J-Jamet
8cedc313cf Upgrade version code 2021-03-27 10:54:26 +01:00
J-Jamet
5afe3acac1 Remove unused string 2021-03-27 10:23:38 +01:00
J-Jamet
9887b58b71 Merge branch 'develop' of https://hosted.weblate.org/git/keepass-dx/strings into translations 2021-03-27 10:18:55 +01:00
J-Jamet
ec8363ba6a Merge branch 'develop' into release/2.9.15 2021-03-27 10:13:53 +01:00
J-Jamet
fcfb71f13b Fix disable Memory Usage setting with AES #941 2021-03-27 10:12:29 +01:00
J-Jamet
3a12e431ff Update CHANGELOG 2021-03-27 05:49:29 +01:00
J-Jamet
bc4ed8e123 Update CHANGELOG 2021-03-27 05:44:09 +01:00
J-Jamet
445e9540a5 Merge branch 'feature/Dynamic_Memory_And_Encrypt_Module' into develop 2021-03-26 20:06:12 +01:00
Joan Jaume Oliver
bbc2a2a9dd Translated using Weblate (Spanish)
Currently translated at 98.6% (515 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/
2021-03-26 19:29:42 +01:00
Joan Jaume Oliver
5117bc78b6 Translated using Weblate (Catalan)
Currently translated at 48.2% (252 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ca/
2021-03-26 19:29:41 +01:00
Reza Almanda
26d8b2fa22 Translated using Weblate (Indonesian)
Currently translated at 74.3% (388 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/id/
2021-03-25 01:29:42 +01:00
random r
2b7fe35305 Translated using Weblate (Italian)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2021-03-23 21:30:04 +01:00
Vít Šindlář
d5819ea4d0 Translated using Weblate (Czech)
Currently translated at 99.6% (520 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2021-03-23 21:30:04 +01:00
Hosted Weblate
0cf136712a Merge branch 'origin/develop' into Weblate. 2021-03-20 14:07:16 +01:00
Milo Ivir
34a453873a Translated using Weblate (Croatian)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hr/
2021-03-20 14:07:16 +01:00
Kunzisoft
0acac3b096 Translated using Weblate (French)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/
2021-03-20 14:07:04 +01:00
Oymate
ede6070e43 Translated using Weblate (Bengali (Bangladesh))
Currently translated at 4.2% (22 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/bn_BD/
2021-03-17 08:18:07 +01:00
jan madsen
a61b1d4337 Translated using Weblate (Danish)
Currently translated at 93.8% (490 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/da/
2021-03-17 08:18:06 +01:00
WaldiS
0f8c71a9df Translated using Weblate (Polish)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2021-03-14 13:02:53 +01:00
gnu-ewm
cb0b6e010d Translated using Weblate (Polish)
Currently translated at 99.8% (521 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2021-03-12 21:02:54 +01:00
Hisikawa Mizuki
23dc7be1ab Translated using Weblate (Japanese)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2021-03-12 21:02:54 +01:00
Oliver Cervera
4b14ad07d2 Translated using Weblate (Italian)
Currently translated at 99.8% (521 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2021-03-12 21:02:54 +01:00
Oğuz Ersen
8a4bf7896f Translated using Weblate (Turkish)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2021-03-11 17:14:10 +01:00
Allan Nordhøy
208ea29643 Translated using Weblate (Norwegian Bokmål)
Currently translated at 76.6% (400 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nb_NO/
2021-03-11 17:14:09 +01:00
Eric
7c52ec731a Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2021-03-11 17:14:09 +01:00
Ihor Hordiichuk
c6ee38e435 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/
2021-03-11 17:14:08 +01:00
solokot
65253cc5b9 Translated using Weblate (Russian)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2021-03-11 17:14:08 +01:00
Stephan Paternotte
d1a1a23cbc Translated using Weblate (Dutch)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2021-03-11 17:14:08 +01:00
HARADA Hiroyuki
e8bb3a5ba7 Translated using Weblate (Japanese)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2021-03-11 17:14:07 +01:00
Retrial
22b8f82770 Translated using Weblate (Greek)
Currently translated at 100.0% (522 of 522 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/el/
2021-03-11 17:14:07 +01:00
52 changed files with 559 additions and 423 deletions

View File

@@ -1,6 +1,11 @@
KeePassDX(2.9.16)
* Fix small bugs #948
KeePassDX(2.9.15)
* Fix themes #935
* Fix themes #935 #926
* Decrease default clipboard time #934
* Better opening performance #929 #933
* Fix memory usage setting #941
KeePassDX(2.9.14)
* Add custom icons #96

View File

@@ -11,8 +11,8 @@ android {
applicationId "com.kunzisoft.keepass"
minSdkVersion 15
targetSdkVersion 30
versionCode = 66
versionName = "2.9.15"
versionCode = 70
versionName = "2.9.16"
multiDexEnabled true
testApplicationId = "com.kunzisoft.keepass.tests"

View File

@@ -39,6 +39,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.appbar.CollapsingToolbarLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.lock.resetAppTimeoutWhenViewFocusedOrChanged
@@ -93,6 +94,8 @@ class EntryActivity : LockingActivity() {
private var clipboardHelper: ClipboardHelper? = null
private var mFirstLaunchOfActivity: Boolean = false
private var mExternalFileHelper: ExternalFileHelper? = null
private var iconColor: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
@@ -140,6 +143,9 @@ class EntryActivity : LockingActivity() {
clipboardHelper = ClipboardHelper(this)
mFirstLaunchOfActivity = savedInstanceState?.getBoolean(KEY_FIRST_LAUNCH_ACTIVITY) ?: true
// Init SAF manager
mExternalFileHelper = ExternalFileHelper(this)
// Init attachment service binder manager
mAttachmentFileBinderManager = AttachmentFileBinderManager(this)
@@ -344,7 +350,7 @@ class EntryActivity : LockingActivity() {
// Manage attachments
entryContentsView?.assignAttachments(entryInfo.attachments.toSet(), StreamDirection.DOWNLOAD) { attachmentItem ->
createDocument(this, attachmentItem.name)?.let { requestCode ->
mExternalFileHelper?.createDocument(attachmentItem.name)?.let { requestCode ->
mAttachmentsToDownload[requestCode] = attachmentItem
}
}
@@ -380,7 +386,7 @@ class EntryActivity : LockingActivity() {
}
}
onCreateDocumentResult(requestCode, resultCode, data) { createdFileUri ->
mExternalFileHelper?.onCreateDocumentResult(requestCode, resultCode, data) { createdFileUri ->
if (createdFileUri != null) {
mAttachmentsToDownload[requestCode]?.let { attachmentToDownload ->
mAttachmentFileBinderManager

View File

@@ -45,7 +45,7 @@ import com.kunzisoft.keepass.activities.dialogs.*
import com.kunzisoft.keepass.activities.dialogs.FileTooBigDialogFragment.Companion.MAX_WARNING_BINARY_FILE
import com.kunzisoft.keepass.activities.fragments.EntryEditFragment
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.lock.resetAppTimeoutWhenViewFocusedOrChanged
import com.kunzisoft.keepass.autofill.AutofillComponent
@@ -103,7 +103,7 @@ class EntryEditActivity : LockingActivity(),
private var lockView: View? = null
// To manage attachments
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var mAttachmentFileBinderManager: AttachmentFileBinderManager? = null
private var mAllowMultipleAttachments: Boolean = false
private var mTempAttachments = ArrayList<EntryAttachmentState>()
@@ -241,7 +241,7 @@ class EntryEditActivity : LockingActivity(),
}
// To retrieve attachment
mSelectFileHelper = SelectFileHelper(this)
mExternalFileHelper = ExternalFileHelper(this)
mAttachmentFileBinderManager = AttachmentFileBinderManager(this)
// Save button
@@ -458,8 +458,8 @@ class EntryEditActivity : LockingActivity(),
/**
* Add a new attachment
*/
private fun addNewAttachment(item: MenuItem) {
mSelectFileHelper?.selectFileOnClickViewListener?.onMenuItemClick(item)
private fun addNewAttachment() {
mExternalFileHelper?.openDocument()
}
override fun onValidateUploadFileTooBig(attachmentToUploadUri: Uri?, fileName: String?) {
@@ -505,7 +505,7 @@ class EntryEditActivity : LockingActivity(),
entryEditFragment?.icon = icon
}
mSelectFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
mExternalFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
uri?.let { attachmentToUploadUri ->
UriUtil.getFileData(this, attachmentToUploadUri)?.also { documentFile ->
documentFile.name?.let { fileName ->
@@ -655,7 +655,7 @@ class EntryEditActivity : LockingActivity(),
&& entryEditActivityEducation.checkAndPerformedAttachmentEducation(
attachmentView,
{
mSelectFileHelper?.selectFileOnClickViewListener?.onClick(attachmentView)
mExternalFileHelper?.openDocument()
},
{
performedNextEducation(entryEditActivityEducation)
@@ -683,7 +683,7 @@ class EntryEditActivity : LockingActivity(),
return true
}
R.id.menu_add_attachment -> {
addNewAttachment(item)
addNewAttachment()
return true
}
R.id.menu_add_otp -> {

View File

@@ -42,8 +42,9 @@ 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.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
@@ -82,7 +83,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
private var mDatabaseFileUri: Uri? = null
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var mProgressDatabaseTaskProvider: ProgressDatabaseTaskProvider? = null
@@ -103,14 +104,9 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
createDatabaseButtonView?.setOnClickListener { createNewFile() }
// Open database button
mSelectFileHelper = SelectFileHelper(this)
mExternalFileHelper = ExternalFileHelper(this)
openDatabaseButtonView = findViewById(R.id.open_keyfile_button)
openDatabaseButtonView?.apply {
mSelectFileHelper?.selectFileOnClickViewListener?.let {
setOnClickListener(it)
setOnLongClickListener(it)
}
}
openDatabaseButtonView?.setOpenDocumentClickListener(mExternalFileHelper)
// History list
val fileDatabaseHistoryRecyclerView = findViewById<RecyclerView>(R.id.file_list)
@@ -162,29 +158,31 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
// Observe list of databases
databaseFilesViewModel.databaseFilesLoaded.observe(this) { databaseFiles ->
when (databaseFiles.databaseFileAction) {
DatabaseFilesViewModel.DatabaseFileAction.NONE -> {
mAdapterDatabaseHistory?.replaceAllDatabaseFileHistoryList(databaseFiles.databaseFileList)
}
DatabaseFilesViewModel.DatabaseFileAction.ADD -> {
databaseFiles.databaseFileToActivate?.let { databaseFileToAdd ->
mAdapterDatabaseHistory?.addDatabaseFileHistory(databaseFileToAdd)
try {
when (databaseFiles.databaseFileAction) {
DatabaseFilesViewModel.DatabaseFileAction.NONE -> {
mAdapterDatabaseHistory?.replaceAllDatabaseFileHistoryList(databaseFiles.databaseFileList)
}
GroupActivity.launch(this@FileDatabaseSelectActivity,
PreferencesUtil.enableReadOnlyDatabase(this@FileDatabaseSelectActivity))
}
DatabaseFilesViewModel.DatabaseFileAction.UPDATE -> {
databaseFiles.databaseFileToActivate?.let { databaseFileToUpdate ->
mAdapterDatabaseHistory?.updateDatabaseFileHistory(databaseFileToUpdate)
}
}
DatabaseFilesViewModel.DatabaseFileAction.DELETE -> {
databaseFiles.databaseFileToActivate?.let { databaseFileToDelete ->
mAdapterDatabaseHistory?.deleteDatabaseFileHistory(databaseFileToDelete)
DatabaseFilesViewModel.DatabaseFileAction.ADD -> {
databaseFiles.databaseFileToActivate?.let { databaseFileToAdd ->
mAdapterDatabaseHistory?.addDatabaseFileHistory(databaseFileToAdd)
}
}
DatabaseFilesViewModel.DatabaseFileAction.UPDATE -> {
databaseFiles.databaseFileToActivate?.let { databaseFileToUpdate ->
mAdapterDatabaseHistory?.updateDatabaseFileHistory(databaseFileToUpdate)
}
}
DatabaseFilesViewModel.DatabaseFileAction.DELETE -> {
databaseFiles.databaseFileToActivate?.let { databaseFileToDelete ->
mAdapterDatabaseHistory?.deleteDatabaseFileHistory(databaseFileToDelete)
}
}
}
databaseFilesViewModel.consumeAction()
} catch (e: Exception) {
Log.e(TAG, "Unable to observe database action", e)
}
databaseFilesViewModel.consumeAction()
}
// Observe default database
@@ -202,6 +200,8 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
val mainCredential = result.data?.getParcelable(DatabaseTaskNotificationService.MAIN_CREDENTIAL_KEY) ?: MainCredential()
databaseFilesViewModel.addDatabaseFile(databaseUri, mainCredential.keyFileUri)
}
GroupActivity.launch(this@FileDatabaseSelectActivity,
PreferencesUtil.enableReadOnlyDatabase(this@FileDatabaseSelectActivity))
}
ACTION_DATABASE_LOAD_TASK -> {
val database = Database.getInstance()
@@ -230,7 +230,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
* Create a new file by calling the content provider
*/
private fun createNewFile() {
createDocument(this, getString(R.string.database_file_name_default) +
mExternalFileHelper?.createDocument( getString(R.string.database_file_name_default) +
getString(R.string.database_file_extension_default), "application/x-keepass")
}
@@ -282,7 +282,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
// Show open and create button or special mode
when (mSpecialMode) {
SpecialMode.DEFAULT -> {
if (allowCreateDocumentByStorageAccessFramework(packageManager)) {
if (ExternalFileHelper.allowCreateDocumentByStorageAccessFramework(packageManager)) {
// There is an activity which can handle this intent.
createDatabaseButtonView?.visibility = View.VISIBLE
} else{
@@ -355,14 +355,14 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data)
}
mSelectFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
mExternalFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
if (uri != null) {
launchPasswordActivityWithPath(uri)
}
}
// Retrieve the created URI from the file manager
onCreateDocumentResult(requestCode, resultCode, data) { databaseFileCreatedUri ->
mExternalFileHelper?.onCreateDocumentResult(requestCode, resultCode, data) { databaseFileCreatedUri ->
mDatabaseFileUri = databaseFileCreatedUri
if (mDatabaseFileUri != null) {
AssignMasterKeyDialogFragment.getInstance(true)
@@ -408,9 +408,9 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
openDatabaseButtonView != null
&& fileDatabaseSelectActivityEducation.checkAndPerformedSelectDatabaseEducation(
openDatabaseButtonView!!,
{tapTargetView ->
{ tapTargetView ->
tapTargetView?.let {
mSelectFileHelper?.selectFileOnClickViewListener?.onClick(it)
mExternalFileHelper?.openDocument()
}
},
{}

View File

@@ -34,7 +34,8 @@ import androidx.fragment.app.commit
import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.fragments.IconPickerFragment
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.lock.resetAppTimeoutWhenViewFocusedOrChanged
import com.kunzisoft.keepass.database.element.Database
@@ -66,7 +67,7 @@ class IconPickerActivity : LockingActivity() {
private var mDatabase: Database? = null
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -84,15 +85,11 @@ class IconPickerActivity : LockingActivity() {
coordinatorLayout = findViewById(R.id.icon_picker_coordinator)
mExternalFileHelper = ExternalFileHelper(this)
uploadButton = findViewById(R.id.icon_picker_upload)
if (mDatabase?.allowCustomIcons == true) {
uploadButton.setOnClickListener {
mSelectFileHelper?.selectFileOnClickViewListener?.onClick(it)
}
uploadButton.setOnLongClickListener {
mSelectFileHelper?.selectFileOnClickViewListener?.onLongClick(it)
true
}
uploadButton.setOpenDocumentClickListener(mExternalFileHelper)
} else {
uploadButton.visibility = View.GONE
}
@@ -124,8 +121,6 @@ class IconPickerActivity : LockingActivity() {
// Focus view to reinitialize timeout
findViewById<ViewGroup>(R.id.icon_picker_container)?.resetAppTimeoutWhenViewFocusedOrChanged(this)
mSelectFileHelper = SelectFileHelper(this)
iconPickerViewModel.standardIconPicked.observe(this) { iconStandard ->
mIconImage.standard = iconStandard
// Remove the custom icon if a standard one is selected
@@ -281,7 +276,7 @@ class IconPickerActivity : LockingActivity() {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
mSelectFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
mExternalFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
addCustomIcon(uri)
}
}

View File

@@ -42,10 +42,7 @@ import androidx.fragment.app.commit
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.ReadOnlyHelper
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.helpers.*
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
@@ -95,7 +92,7 @@ open class PasswordActivity : SpecialModeActivity(), AdvancedUnlockFragment.Buil
private var mDatabaseKeyFileUri: Uri? = null
private var mRememberKeyFile: Boolean = false
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var mPermissionAsked = false
private var readOnly: Boolean = false
@@ -138,13 +135,8 @@ open class PasswordActivity : SpecialModeActivity(), AdvancedUnlockFragment.Buil
readOnly = ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrPreference(this, savedInstanceState)
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
mSelectFileHelper = SelectFileHelper(this@PasswordActivity)
keyFileSelectionView?.apply {
mSelectFileHelper?.selectFileOnClickViewListener?.let {
setOnClickListener(it)
setOnLongClickListener(it)
}
}
mExternalFileHelper = ExternalFileHelper(this@PasswordActivity)
keyFileSelectionView?.setOpenDocumentClickListener(mExternalFileHelper)
passwordView?.setOnEditorActionListener(onEditorActionListener)
passwordView?.addTextChangedListener(object : TextWatcher {
@@ -702,7 +694,7 @@ open class PasswordActivity : SpecialModeActivity(), AdvancedUnlockFragment.Buil
}
var keyFileResult = false
mSelectFileHelper?.let {
mExternalFileHelper?.let {
keyFileResult = it.onActivityResultCallback(requestCode, resultCode, data
) { uri ->
if (uri != null) {

View File

@@ -30,13 +30,13 @@ import android.text.SpannableStringBuilder
import android.text.TextWatcher
import android.view.View
import android.widget.CompoundButton
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener
import com.kunzisoft.keepass.model.MainCredential
import com.kunzisoft.keepass.utils.UriUtil
import com.kunzisoft.keepass.view.KeyFileSelectionView
@@ -60,7 +60,7 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
private var mListener: AssignPasswordDialogListener? = null
private var mSelectFileHelper: SelectFileHelper? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var mEmptyPasswordConfirmationDialog: AlertDialog? = null
private var mNoKeyConfirmationDialog: AlertDialog? = null
@@ -133,11 +133,8 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
keyFileCheckBox = rootView?.findViewById(R.id.keyfile_checkox)
keyFileSelectionView = rootView?.findViewById(R.id.keyfile_selection)
mSelectFileHelper = SelectFileHelper(this)
keyFileSelectionView?.apply {
setOnClickListener(mSelectFileHelper?.selectFileOnClickViewListener)
setOnLongClickListener(mSelectFileHelper?.selectFileOnClickViewListener)
}
mExternalFileHelper = ExternalFileHelper(this)
keyFileSelectionView?.setOpenDocumentClickListener(mExternalFileHelper)
val dialog = builder.create()
@@ -289,7 +286,7 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
mSelectFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
mExternalFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
uri?.let { pathUri ->
UriUtil.getFileData(requireContext(), uri)?.length()?.let { lengthFile ->
keyFileSelectionView?.error = null

View File

@@ -20,30 +20,25 @@
package com.kunzisoft.keepass.activities.helpers
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.util.Log
import android.view.MenuItem
import android.view.View
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.kunzisoft.keepass.activities.dialogs.FileManagerDialogFragment
import com.kunzisoft.keepass.utils.UriUtil
class SelectFileHelper {
class ExternalFileHelper {
private var activity: Activity? = null
private var activity: FragmentActivity? = null
private var fragment: Fragment? = null
val selectFileOnClickViewListener: SelectFileOnClickViewListener
get() = SelectFileOnClickViewListener()
constructor(context: Activity) {
constructor(context: FragmentActivity) {
this.activity = context
this.fragment = null
}
@@ -53,56 +48,33 @@ class SelectFileHelper {
this.fragment = context
}
inner class SelectFileOnClickViewListener :
View.OnClickListener,
View.OnLongClickListener,
MenuItem.OnMenuItemClickListener {
private fun onAbstractClick(longClick: Boolean = false) {
fun openDocument(getContent: Boolean = false,
typeString: String = "*/*") {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
if (longClick) {
try {
openActivityWithActionGetContent()
} catch (e: Exception) {
openActivityWithActionOpenDocument()
}
if (getContent) {
openActivityWithActionGetContent(typeString)
} else {
try {
openActivityWithActionOpenDocument()
} catch (e: Exception) {
openActivityWithActionGetContent()
}
openActivityWithActionOpenDocument(typeString)
}
} catch (e: Exception) {
Log.e(TAG, "Enable to start the file picker activity", e)
// Open browser dialog
if (lookForOpenIntentsFilePicker())
showBrowserDialog()
Log.e(TAG, "Unable to open document", e)
showFileManagerDialogFragment()
}
}
override fun onClick(v: View) {
onAbstractClick()
}
override fun onLongClick(v: View?): Boolean {
onAbstractClick(true)
return true
}
override fun onMenuItemClick(item: MenuItem?): Boolean {
onAbstractClick()
return true
} else {
showFileManagerDialogFragment()
}
}
@SuppressLint("InlinedApi")
private fun openActivityWithActionOpenDocument() {
@RequiresApi(Build.VERSION_CODES.KITKAT)
private fun openActivityWithActionOpenDocument(typeString: String) {
val intentOpenDocument = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
type = typeString
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
}
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
@@ -112,13 +84,15 @@ class SelectFileHelper {
activity?.startActivityForResult(intentOpenDocument, OPEN_DOC)
}
@SuppressLint("InlinedApi")
private fun openActivityWithActionGetContent() {
@RequiresApi(Build.VERSION_CODES.KITKAT)
private fun openActivityWithActionGetContent(typeString: String) {
val intentGetContent = Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
type = typeString
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
}
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
@@ -128,69 +102,12 @@ class SelectFileHelper {
activity?.startActivityForResult(intentGetContent, GET_CONTENT)
}
private fun lookForOpenIntentsFilePicker(): Boolean {
var showBrowser = false
try {
if (isIntentAvailable(activity!!, OPEN_INTENTS_FILE_BROWSE)) {
val intent = Intent(OPEN_INTENTS_FILE_BROWSE)
if (fragment != null)
fragment?.startActivityForResult(intent, FILE_BROWSE)
else
activity?.startActivityForResult(intent, FILE_BROWSE)
} else {
showBrowser = true
}
} catch (e: Exception) {
Log.w(TAG, "Enable to start OPEN_INTENTS_FILE_BROWSE", e)
showBrowser = true
}
return showBrowser
}
/**
* Indicates whether the specified action can be used as an intent. This
* method queries the package manager for installed packages that can
* respond to an intent with the specified action. If no suitable package is
* found, this method returns false.
*
* @param context The application's environment.
* @param action The Intent action to check for availability.
*
* @return True if an Intent with the specified action can be sent and
* responded to, false otherwise.
*/
private fun isIntentAvailable(context: Context, action: String): Boolean {
val packageManager = context.packageManager
val intent = Intent(action)
val list = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY)
return list.size > 0
}
/**
* Show Browser dialog to select file picker app
*/
private fun showBrowserDialog() {
try {
val fileManagerDialogFragment = FileManagerDialogFragment()
fragment?.let {
fileManagerDialogFragment.show(it.parentFragmentManager, "browserDialog")
} ?: fileManagerDialogFragment.show((activity as FragmentActivity).supportFragmentManager, "browserDialog")
} catch (e: Exception) {
Log.e(TAG, "Can't open BrowserDialog", e)
}
}
/**
* To use in onActivityResultCallback in Fragment or Activity
* @param keyFileCallback Callback retrieve from data
* @return true if requestCode was captured, false elsechere
*/
fun onActivityResultCallback(
requestCode: Int,
resultCode: Int,
data: Intent?,
fun onActivityResultCallback(requestCode: Int, resultCode: Int, data: Intent?,
keyFileCallback: ((uri: Uri?) -> Unit)?): Boolean {
when (requestCode) {
@@ -231,14 +148,102 @@ class SelectFileHelper {
return false
}
/**
* Show Browser dialog to select file picker app
*/
private fun showFileManagerDialogFragment() {
try {
if (fragment != null) {
fragment?.parentFragmentManager
} else {
activity?.supportFragmentManager
}?.let { fragmentManager ->
FileManagerDialogFragment().show(fragmentManager, "browserDialog")
}
} catch (e: Exception) {
Log.e(TAG, "Can't open BrowserDialog", e)
}
}
fun createDocument(titleString: String,
typeString: String = "application/octet-stream"): Int? {
val idCode = getUnusedCreateFileRequestCode()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
putExtra(Intent.EXTRA_TITLE, titleString)
}
if (fragment != null)
fragment?.startActivityForResult(intent, idCode)
else
activity?.startActivityForResult(intent, idCode)
return idCode
} catch (e: Exception) {
Log.e(TAG, "Unable to create document", e)
showFileManagerDialogFragment()
}
} else {
showFileManagerDialogFragment()
}
return null
}
fun onCreateDocumentResult(requestCode: Int, resultCode: Int, data: Intent?,
action: (fileCreated: Uri?)->Unit) {
// Retrieve the created URI from the file manager
if (fileRequestCodes.contains(requestCode) && resultCode == RESULT_OK) {
action.invoke(data?.data)
fileRequestCodes.remove(requestCode)
}
}
companion object {
private const val TAG = "OpenFileHelper"
const val OPEN_INTENTS_FILE_BROWSE = "org.openintents.action.PICK_FILE"
private const val GET_CONTENT = 25745
private const val OPEN_DOC = 25845
private const val FILE_BROWSE = 25645
private var CREATE_FILE_REQUEST_CODE_DEFAULT = 3853
private var fileRequestCodes = ArrayList<Int>()
private fun getUnusedCreateFileRequestCode(): Int {
val newCreateFileRequestCode = CREATE_FILE_REQUEST_CODE_DEFAULT++
fileRequestCodes.add(newCreateFileRequestCode)
return newCreateFileRequestCode
}
@SuppressLint("InlinedApi")
fun allowCreateDocumentByStorageAccessFramework(packageManager: PackageManager,
typeString: String = "application/octet-stream"): Boolean {
return when {
// To check if a custom file manager can manage the ACTION_CREATE_DOCUMENT
Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT -> {
packageManager.queryIntentActivities(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
}, PackageManager.MATCH_DEFAULT_ONLY).isNotEmpty()
}
else -> true
}
}
}
}
fun View.setOpenDocumentClickListener(externalFileHelper: ExternalFileHelper?) {
externalFileHelper?.let { fileHelper ->
setOnClickListener {
fileHelper.openDocument()
}
setOnLongClickListener {
fileHelper.openDocument(true)
true
}
} ?: kotlin.run {
setOnClickListener(null)
setOnLongClickListener(null)
}
}

View File

@@ -25,6 +25,7 @@ import android.content.Intent
import android.content.ServiceConnection
import android.net.Uri
import android.os.IBinder
import android.util.Log
import com.kunzisoft.keepass.services.AdvancedUnlockNotificationService
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.utils.SingletonHolderParameter
@@ -76,7 +77,11 @@ class CipherDatabaseAction(context: Context) {
mServiceConnection!!,
Context.BIND_ABOVE_CLIENT)
if (mBinder == null) {
applicationContext.startService(mIntentAdvancedUnlockService)
try {
applicationContext.startService(mIntentAdvancedUnlockService)
} catch (e: Exception) {
Log.e(TAG, "Unable to start cipher action", e)
}
}
}
}
@@ -173,5 +178,7 @@ class CipherDatabaseAction(context: Context) {
).execute()
}
companion object : SingletonHolderParameter<CipherDatabaseAction, Context>(::CipherDatabaseAction)
companion object : SingletonHolderParameter<CipherDatabaseAction, Context>(::CipherDatabaseAction) {
private val TAG = CipherDatabaseAction::class.java.name
}
}

View File

@@ -25,7 +25,10 @@ import android.content.Context.BIND_NOT_FOREGROUND
import android.net.Uri
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment.Companion.DATABASE_CHANGED_DIALOG_TAG
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
@@ -251,11 +254,16 @@ class ProgressDatabaseTaskProvider(private val activity: FragmentActivity) {
}
private fun start(bundle: Bundle? = null, actionTask: String) {
activity.stopService(intentDatabaseTask)
if (bundle != null)
intentDatabaseTask.putExtras(bundle)
intentDatabaseTask.action = actionTask
activity.startService(intentDatabaseTask)
try {
activity.stopService(intentDatabaseTask)
if (bundle != null)
intentDatabaseTask.putExtras(bundle)
intentDatabaseTask.action = actionTask
activity.startService(intentDatabaseTask)
} catch (e: Exception) {
Log.e(TAG, "Unable to perform database action", e)
Toast.makeText(activity, R.string.error_start_database_action, Toast.LENGTH_LONG).show()
}
}
/*
@@ -591,4 +599,8 @@ class ProgressDatabaseTaskProvider(private val activity: FragmentActivity) {
}
, ACTION_DATABASE_SAVE)
}
companion object {
private val TAG = ProgressDatabaseTaskProvider::class.java.name
}
}

View File

@@ -105,10 +105,6 @@ class Database {
return mDatabaseKDB?.binaryCache ?: mDatabaseKDBX?.binaryCache ?: BinaryCache()
}
fun setCacheDirectory(cacheDirectory: File) {
binaryCache.cacheDirectory = cacheDirectory
}
private val iconsManager: IconsManager
get() {
return mDatabaseKDB?.iconsManager ?: mDatabaseKDBX?.iconsManager ?: IconsManager(binaryCache)

View File

@@ -466,16 +466,7 @@ class Entry : Node, EntryVersionedInterface<Group> {
return result
}
companion object CREATOR : Parcelable.Creator<Entry> {
override fun createFromParcel(parcel: Parcel): Entry {
return Entry(parcel)
}
override fun newArray(size: Int): Array<Entry?> {
return arrayOfNulls(size)
}
companion object {
const val PMS_TAN_ENTRY = "<TAN>"
/**
@@ -484,5 +475,16 @@ class Entry : Node, EntryVersionedInterface<Group> {
fun newExtraFieldNameAllowed(field: Field): Boolean {
return EntryKDBX.newCustomNameAllowed(field.name)
}
@JvmField
val CREATOR: Parcelable.Creator<Entry> = object : Parcelable.Creator<Entry> {
override fun createFromParcel(parcel: Parcel): Entry {
return Entry(parcel)
}
override fun newArray(size: Int): Array<Entry?> {
return arrayOfNulls(size)
}
}
}
}

View File

@@ -11,7 +11,7 @@ class BinaryCache {
*/
var loadedCipherKey: LoadedKey = LoadedKey.generateNewCipherKey()
lateinit var cacheDirectory: File
var cacheDirectory: File? = null
private val voidBinary = KeyByteArray(UNKNOWN, ByteArray(0))
@@ -19,15 +19,16 @@ class BinaryCache {
smallSize: Boolean = false,
compression: Boolean = false,
protection: Boolean = false): BinaryData {
return if (smallSize) {
val cacheDir = cacheDirectory
return if (smallSize || cacheDir == null) {
BinaryByte(binaryId, compression, protection)
} else {
val fileInCache = File(cacheDirectory, binaryId)
return BinaryFile(fileInCache, compression, protection)
val fileInCache = File(cacheDir, binaryId)
BinaryFile(fileInCache, compression, protection)
}
}
// Similar to file storage but much faster
// Similar to file storage but much faster TODO SparseArray
private val byteArrayList = HashMap<String, ByteArray>()
fun getByteArray(key: String): KeyByteArray {

View File

@@ -90,7 +90,8 @@ class EntryKDB : EntryVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
url = parcel.readString() ?: url
notes = parcel.readString() ?: notes
binaryDescription = parcel.readString() ?: binaryDescription
binaryDataId = parcel.readInt()
val rawBinaryDataId = parcel.readInt()
binaryDataId = if (rawBinaryDataId == -1) null else rawBinaryDataId
}
override fun readParentParcelable(parcel: Parcel): GroupKDB? {
@@ -109,9 +110,7 @@ class EntryKDB : EntryVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
dest.writeString(url)
dest.writeString(notes)
dest.writeString(binaryDescription)
binaryDataId?.let {
dest.writeInt(it)
}
dest.writeInt(binaryDataId ?: -1)
}
fun updateWith(source: EntryKDB) {

View File

@@ -56,32 +56,6 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
var additional = ""
var tags = ""
fun getSize(attachmentPool: AttachmentPool): Long {
var size = FIXED_LENGTH_SIZE
for (entry in fields.entries) {
size += entry.key.length.toLong()
size += entry.value.length().toLong()
}
size += getAttachmentsSize(attachmentPool)
size += autoType.defaultSequence.length.toLong()
for ((key, value) in autoType.entrySet()) {
size += key.length.toLong()
size += value.length.toLong()
}
for (entry in history) {
size += entry.getSize(attachmentPool)
}
size += overrideURL.length.toLong()
size += tags.length.toLong()
return size
}
override var expires: Boolean = false
constructor() : super()
@@ -102,6 +76,14 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
tags = parcel.readString() ?: tags
}
override fun readParentParcelable(parcel: Parcel): GroupKDBX? {
return parcel.readParcelable(GroupKDBX::class.java.classLoader)
}
override fun writeParentParcelable(parent: GroupKDBX?, parcel: Parcel, flags: Int) {
parcel.writeParcelable(parent, flags)
}
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeLong(usageCount.toKotlinLong())
@@ -164,14 +146,6 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
return NodeIdUUID(nodeId.id)
}
override fun readParentParcelable(parcel: Parcel): GroupKDBX? {
return parcel.readParcelable(GroupKDBX::class.java.classLoader)
}
override fun writeParentParcelable(parent: GroupKDBX?, parcel: Parcel, flags: Int) {
parcel.writeParcelable(parent, flags)
}
/**
* Decode a reference key with the FieldReferencesEngine
* @param decodeRef
@@ -228,6 +202,32 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
override var locationChanged = DateInstant()
fun getSize(attachmentPool: AttachmentPool): Long {
var size = FIXED_LENGTH_SIZE
for (entry in fields.entries) {
size += entry.key.length.toLong()
size += entry.value.length().toLong()
}
size += getAttachmentsSize(attachmentPool)
size += autoType.defaultSequence.length.toLong()
for ((key, value) in autoType.entrySet()) {
size += key.length.toLong()
size += value.length.toLong()
}
for (entry in history) {
size += entry.getSize(attachmentPool)
}
size += overrideURL.length.toLong()
size += tags.length.toLong()
return size
}
fun afterChangeParent() {
locationChanged = DateInstant()
}
@@ -349,6 +349,8 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
const val STR_URL = "URL"
const val STR_NOTES = "Notes"
private const val FIXED_LENGTH_SIZE: Long = 128 // Approximate fixed length size
fun newCustomNameAllowed(name: String): Boolean {
return !(name.equals(STR_TITLE, true)
|| name.equals(STR_USERNAME, true)
@@ -367,7 +369,5 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
return arrayOfNulls(size)
}
}
private const val FIXED_LENGTH_SIZE: Long = 128 // Approximate fixed length size
}
}

View File

@@ -36,6 +36,10 @@ abstract class EntryVersioned
constructor(parcel: Parcel) : super(parcel)
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
}
override fun nodeIndexInParentForNaturalOrder(): Int {
if (nodeIndexInParentForNaturalOrder == -1) {
val numberOfGroups = parent?.getChildGroups()?.size

View File

@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.database.element.icon
import android.os.Parcel
import android.os.Parcelable
class IconImage() : IconImageDraw(), Parcelable {
class IconImage() : IconImageDraw() {
var standard: IconImageStandard = IconImageStandard()
var custom: IconImageCustom = IconImageCustom()

View File

@@ -20,11 +20,12 @@
package com.kunzisoft.keepass.database.element.icon
import android.os.Parcel
import android.os.ParcelUuid
import android.os.Parcelable
import com.kunzisoft.keepass.database.element.database.DatabaseVersioned
import java.util.*
class IconImageCustom : Parcelable, IconImageDraw {
class IconImageCustom : IconImageDraw {
var uuid: UUID
@@ -37,17 +38,17 @@ class IconImageCustom : Parcelable, IconImageDraw {
}
constructor(parcel: Parcel) {
uuid = parcel.readSerializable() as UUID
uuid = parcel.readParcelable<ParcelUuid>(ParcelUuid::class.java.classLoader)?.uuid ?: DatabaseVersioned.UUID_ZERO
}
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeParcelable(ParcelUuid(uuid), flags)
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeSerializable(uuid)
}
override fun hashCode(): Int {
val prime = 31
var result = 1

View File

@@ -19,7 +19,9 @@
*/
package com.kunzisoft.keepass.database.element.icon
abstract class IconImageDraw {
import android.os.Parcelable
abstract class IconImageDraw : Parcelable {
var selected = false
/**

View File

@@ -23,7 +23,7 @@ import android.os.Parcel
import android.os.Parcelable
import com.kunzisoft.keepass.icons.IconPack.Companion.NB_ICONS
class IconImageStandard : Parcelable, IconImageDraw {
class IconImageStandard : IconImageDraw {
val id: Int

View File

@@ -20,6 +20,7 @@
package com.kunzisoft.keepass.database.element.node
import android.os.Parcel
import android.os.ParcelUuid
import android.os.Parcelable
import java.util.*
@@ -35,12 +36,12 @@ class NodeIdUUID : NodeId<UUID> {
}
constructor(parcel: Parcel) {
id = parcel.readSerializable() as UUID
id = parcel.readParcelable<ParcelUuid>(ParcelUuid::class.java.classLoader)?.uuid ?: id
}
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeSerializable(id)
dest.writeParcelable(ParcelUuid(id), flags)
}
override fun equals(other: Any?): Boolean {

View File

@@ -26,7 +26,6 @@ import android.net.Uri
import android.os.Binder
import android.os.IBinder
import android.util.Log
import androidx.documentfile.provider.DocumentFile
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.Attachment
import com.kunzisoft.keepass.database.element.Database
@@ -34,6 +33,7 @@ import com.kunzisoft.keepass.model.AttachmentState
import com.kunzisoft.keepass.model.EntryAttachmentState
import com.kunzisoft.keepass.model.StreamDirection
import com.kunzisoft.keepass.tasks.BinaryDatabaseManager
import com.kunzisoft.keepass.utils.UriUtil
import kotlinx.coroutines.*
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList
@@ -173,7 +173,8 @@ class AttachmentFileNotificationService: LockNotificationService() {
putExtra(FILE_URI_KEY, attachmentNotification.uri)
}, PendingIntent.FLAG_CANCEL_CURRENT)
val fileName = DocumentFile.fromSingleUri(this, attachmentNotification.uri)?.name ?: ""
val fileName = UriUtil.getFileData(this, attachmentNotification.uri)?.name
?: attachmentNotification.uri.path
val builder = buildNewNotification().apply {
when (attachmentNotification.entryAttachmentState.streamDirection) {

View File

@@ -32,7 +32,7 @@ class InputKdfSizePreference @JvmOverloads constructor(context: Context,
override fun setSummary(summary: CharSequence) {
if (summary == UNKNOWN_VALUE_STRING) {
super.setSummary("")
super.setSummary(summary)
} else {
var summaryString = summary
try {

View File

@@ -67,7 +67,7 @@ class ClipboardHelper(private val context: Context) {
fun getClipboard(context: Context): CharSequence {
if (getClipboardManager()?.hasPrimaryClip() == true) {
val data = getClipboardManager()?.primaryClip
if (data!!.itemCount > 0) {
if (data != null && data.itemCount > 0) {
val text = data.getItemAt(0).coerceToText(context)
if (text != null) {
return text

View File

@@ -1,86 +0,0 @@
/*
* 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.utils
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import androidx.fragment.app.FragmentActivity
import com.kunzisoft.keepass.activities.dialogs.FileManagerDialogFragment
private var CREATE_FILE_REQUEST_CODE_DEFAULT = 3853
private var fileRequestCodes = ArrayList<Int>()
fun getUnusedCreateFileRequestCode(): Int {
val newCreateFileRequestCode = CREATE_FILE_REQUEST_CODE_DEFAULT++
fileRequestCodes.add(newCreateFileRequestCode)
return newCreateFileRequestCode
}
@SuppressLint("InlinedApi")
fun allowCreateDocumentByStorageAccessFramework(packageManager: PackageManager): Boolean {
return when {
// To check if a custom file manager can manage the ACTION_CREATE_DOCUMENT
Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT -> {
packageManager.queryIntentActivities(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/x-keepass"
}, PackageManager.MATCH_DEFAULT_ONLY).isNotEmpty()
}
else -> true
}
}
fun createDocument(activity: FragmentActivity,
titleString: String,
typeString: String = "application/octet-stream"): Int? {
val idCode = getUnusedCreateFileRequestCode()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
activity.startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
putExtra(Intent.EXTRA_TITLE, titleString)
}, idCode)
return idCode
} catch (e: Exception) {
FileManagerDialogFragment().show(activity.supportFragmentManager, "browserDialog")
}
} else {
FileManagerDialogFragment().show(activity.supportFragmentManager, "browserDialog")
}
return null
}
fun onCreateDocumentResult(requestCode: Int, resultCode: Int, data: Intent?,
action: (fileCreated: Uri?)->Unit) {
// Retrieve the created URI from the file manager
if (fileRequestCodes.contains(requestCode) && resultCode == Activity.RESULT_OK) {
action.invoke(data?.data)
fileRequestCodes.remove(requestCode)
}
}

View File

@@ -38,16 +38,26 @@ object UriUtil {
fun getFileData(context: Context, fileUri: Uri?): DocumentFile? {
if (fileUri == null)
return null
return when {
isFileScheme(fileUri) -> {
fileUri.path?.let {
File(it).let { file ->
return DocumentFile.fromFile(file)
return try {
when {
isFileScheme(fileUri) -> {
fileUri.path?.let {
File(it).let { file ->
return DocumentFile.fromFile(file)
}
}
}
isContentScheme(fileUri) -> {
DocumentFile.fromSingleUri(context, fileUri)
}
else -> {
Log.e("FileData", "Content scheme not known")
null
}
}
isContentScheme(fileUri) -> DocumentFile.fromSingleUri(context, fileUri)
else -> null
} catch (e: Exception) {
Log.e("FileData", "Unable to get document file", e)
null
}
}

View File

@@ -6,9 +6,9 @@ import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.documentfile.provider.DocumentFile
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.utils.UriUtil
class KeyFileSelectionView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
@@ -51,7 +51,7 @@ class KeyFileSelectionView @JvmOverloads constructor(context: Context,
set(value) {
mUri = value
keyFileNameView.text = value?.let {
DocumentFile.fromSingleUri(context, value)?.name ?: value.path
UriUtil.getFileData(context, value)?.name ?: value.path
} ?: ""
}
}

View File

@@ -50,14 +50,18 @@ class DatabaseFilesViewModel(application: Application) : AndroidViewModel(applic
).execute()
}
private fun getDatabaseFilesLoadedValue(): DatabaseFileData {
var newValue = databaseFilesLoaded.value
if (newValue == null) {
newValue = DatabaseFileData()
}
return newValue
}
fun loadListOfDatabases() {
checkDefaultDatabase()
mFileDatabaseHistoryAction?.getDatabaseFileList { databaseFileListRetrieved ->
var newValue = databaseFilesLoaded.value
if (newValue == null) {
newValue = DatabaseFileData()
}
newValue.apply {
databaseFilesLoaded.value = getDatabaseFilesLoadedValue().apply {
databaseFileAction = DatabaseFileAction.NONE
databaseFileToActivate = null
databaseFileList.apply {
@@ -65,14 +69,13 @@ class DatabaseFilesViewModel(application: Application) : AndroidViewModel(applic
addAll(databaseFileListRetrieved)
}
}
databaseFilesLoaded.value = newValue
}
}
fun addDatabaseFile(databaseUri: Uri, keyFileUri: Uri?) {
mFileDatabaseHistoryAction?.addOrUpdateDatabaseUri(databaseUri, keyFileUri) { databaseFileAdded ->
databaseFileAdded?.let { _ ->
databaseFilesLoaded.value = databaseFilesLoaded.value?.apply {
databaseFilesLoaded.value = getDatabaseFilesLoadedValue().apply {
this.databaseFileAction = DatabaseFileAction.ADD
this.databaseFileList.add(databaseFileAdded)
this.databaseFileToActivate = databaseFileAdded
@@ -84,7 +87,7 @@ class DatabaseFilesViewModel(application: Application) : AndroidViewModel(applic
fun updateDatabaseFile(databaseFileToUpdate: DatabaseFile) {
mFileDatabaseHistoryAction?.addOrUpdateDatabaseFile(databaseFileToUpdate) { databaseFileUpdated ->
databaseFileUpdated?.let { _ ->
databaseFilesLoaded.value = databaseFilesLoaded.value?.apply {
databaseFilesLoaded.value = getDatabaseFilesLoadedValue().apply {
this.databaseFileAction = DatabaseFileAction.UPDATE
this.databaseFileList
.find { it.databaseUri == databaseFileUpdated.databaseUri }
@@ -104,7 +107,7 @@ class DatabaseFilesViewModel(application: Application) : AndroidViewModel(applic
fun deleteDatabaseFile(databaseFileToDelete: DatabaseFile) {
mFileDatabaseHistoryAction?.deleteDatabaseFile(databaseFileToDelete) { databaseFileDeleted ->
databaseFileDeleted?.let { _ ->
databaseFilesLoaded.value = databaseFilesLoaded.value?.apply {
databaseFilesLoaded.value = getDatabaseFilesLoadedValue().apply {
databaseFileAction = DatabaseFileAction.DELETE
databaseFileToActivate = databaseFileDeleted
databaseFileList.remove(databaseFileDeleted)

View File

@@ -19,4 +19,7 @@
<string name="add_entry">এন্টরি যোগ করুন</string>
<string name="accept">গ্রহণ</string>
<string name="about_description">কিপাস পাসওয়ার্ড ম্যানেজারের অ্যান্ড্রয়েড বাস্তবায়ন</string>
</resources>
<string name="clipboard_error_title">ক্লিপবোর্ড ত্রুটি</string>
<string name="allow">অনুমোদন</string>
<string name="file_manager_install_description">ACTION_CREATE_DOCUMENT এবং ACTION_OPEN_DOCUMENT অভিপ্রায় গ্রহণ করে এমন একটি ফাইল ম্যানেজার ডাটাবেস ফাইলগুলো তৈরি করা, খোলা এবং সংরক্ষণ করতে প্রয়োজন।</string>
</resources>

View File

@@ -19,21 +19,21 @@
Catalan translation by Oriol Garrote
--><resources>
<string name="feedback">Comentaris</string>
<string name="homepage">Pàgina inici:</string>
<string name="homepage">Pàgina d\'inici</string>
<string name="about_description">KeePassDX és una implementació per a Android de KeePass password manager</string>
<string name="accept">Accepta</string>
<string name="add_entry">Afegeix entrada</string>
<string name="add_group">Afegeix grup</string>
<string name="encryption_algorithm">Algorisme de xifratge</string>
<string name="encryption_algorithm">Algoritme de xifrat</string>
<string name="app_timeout">Temps d\'espera de l\'aplicació</string>
<string name="app_timeout_summary">Temps d\'inactivitat abans de blocar la base de dades</string>
<string name="application">Aplicació</string>
<string name="menu_app_settings">Paràmetres de l\'aplicació</string>
<string name="menu_app_settings">Configuració de l\'aplicació</string>
<string name="brackets">Parèntesis</string>
<string name="file_manager_install_description">L\'exploració d\'arxius necessita l\'aplicació Open Intents File Manager, clica a sota per instal·lar-la. Degut a peculiaritats de l\'explorador d\'arxius pot ser que no funcioni correctament la primera execució.</string>
<string name="clipboard_cleared">Porta-retalls netejat.</string>
<string name="clipboard_timeout">Temps d\'espera del porta-retalls</string>
<string name="clipboard_timeout_summary">Temps abans de netejar el porta-retalls</string>
<string name="clipboard_timeout_summary">Temps abans de netejar el porta-retalls (si el teu dispositiu ho suporta)</string>
<string name="select_to_copy">Selecciona per copiar %1$s al porta-retalls</string>
<string name="retrieving_db_key">Creant clau de base de dades…</string>
<string name="database">Base de dades</string>
@@ -115,7 +115,7 @@
<string name="search_label">Cerca</string>
<string name="sort_db">Ordre natural</string>
<string name="special">Especial</string>
<string name="search">Títol/descripció d\'entrada</string>
<string name="search">Cercar</string>
<string name="search_results">Resultats de cerca</string>
<string name="underline">Subratllat</string>
<string name="unsupported_db_version">Versió de la base de dades no suportada.</string>
@@ -144,7 +144,7 @@
<string name="edit_entry">Edita l\'entrada</string>
<string name="contribution">Contribució</string>
<string name="contact">Contacte</string>
<string name="extended_ASCII">ASCII ampliat</string>
<string name="extended_ASCII">ASCII estès</string>
<string name="sort_username">Nom d\'usuari</string>
<string name="sort_title">Títol</string>
<string name="sort_menu">Ordena</string>
@@ -199,8 +199,8 @@
<string name="sort_last_access_time">Accés</string>
<string name="sort_last_modify_time">Modificació</string>
<string name="sort_creation_time">Creació</string>
<string name="sort_recycle_bin_bottom">Paperera a baix</string>
<string name="sort_groups_before">Primer els grups</string>
<string name="sort_recycle_bin_bottom">La paperera de reciclatge es troba a la part inferior</string>
<string name="sort_groups_before">Grups primer</string>
<string name="sort_ascending">El menor primer ↓</string>
<string name="command_execution">S\'executa l\'ordre…</string>
<string name="parallelism_explanation">Grau de paral·lelisme (és a dir, nombre de fils) fets servir per la funció de derivació de la clau.</string>
@@ -228,21 +228,21 @@
<string name="menu_open_file_read_and_write">Modificable</string>
<string name="menu_file_selection_read_only">Protegit contra escriptura</string>
<string name="menu_save_database">Desa la base de dades</string>
<string name="menu_cancel">Cancel·la</string>
<string name="menu_paste">Enganxa</string>
<string name="menu_move">Mou</string>
<string name="menu_copy">Copia</string>
<string name="menu_cancel">Cancel·lar</string>
<string name="menu_paste">Enganxar</string>
<string name="menu_move">Moure</string>
<string name="menu_copy">Copiar</string>
<string name="menu_master_key_settings">Paràmetres de la contrasenya mestra</string>
<string name="menu_security_settings">Paràmetres de seguretat</string>
<string name="menu_advanced_unlock_settings">Desblocatge avançat</string>
<string name="menu_form_filling_settings">Reompliment de formularis</string>
<string name="menu_form_filling_settings">Emplenat de formularis</string>
<string name="copy_field">Còpia de %1$s</string>
<string name="creating_database">Es crea la base de dades…</string>
<string name="list_groups_show_number_entries_summary">Mostra el nombre d\'entrades en un grup</string>
<string name="list_groups_show_number_entries_title">Mostra el nombre d\'entades</string>
<string name="list_entries_show_username_summary">Mostra els noms d\'usuari en les llistes d\'entrades</string>
<string name="list_entries_show_username_title">Mostra noms d\'usuari</string>
<string name="keyfile_is_empty">El fitxer de claus és buit.</string>
<string name="keyfile_is_empty">El fitxer de clau és buit.</string>
<string name="invalid_algorithm">Algorisme incorrecte.</string>
<string name="file_not_found_content">No s\'ha trobat el fitxer. Mireu de reobrir-lo des de l\'explorador de fitxers.</string>
<string name="field_value">Valor del camp</string>
@@ -290,5 +290,15 @@
<string name="content_description_background">Fons</string>
<string name="clipboard_error_clear">No ha estat possible netejar el porta-retalls</string>
<string name="clipboard_error">Alguns dispositius no permeten que les aplicacions facin servir el porta-retalls.</string>
<string name="clipboard_error_title">Error del porta-retalls</string>
<string name="clipboard_error_title">Error del Porta Retalls</string>
<string name="error_string_key">Cada cadena ha de tenir un nom de camp.</string>
<string name="error_rebuild_list">La llista no s\'ha pogut reconstruir correctament.</string>
<string name="error_database_uri_null">No es pot recuperar l\'URI de la base de dades.</string>
<string name="error_field_name_already_exists">El nom del camp ja existeix.</string>
<string name="error_registration_read_only">No es permet desar un element nou en una base de dades de només lectura</string>
<string name="error_string_type">Aquest text no coincideix amb l\'element sol·licitat.</string>
<string name="error_otp_type">L\'OTP existent no està reconegut per aquest formulari, la seva validació ja no pot generar correctament el token.</string>
<string name="error_create_database_file">No s\'ha pogut crear una base de dades amb aquesta contrasenya i arxiu de clau.</string>
<string name="error_move_folder_in_itself">No pots moure un grup dintre d\'ell mateix.</string>
<string name="error_autofill_enable_service">No s\'ha pogut habilitar el servei d\'autocompletat.</string>
</resources>

View File

@@ -39,7 +39,7 @@
<string name="select_to_copy">Vyberte zkopírovat %1$s do schránky</string>
<string name="retrieving_db_key">Načítám klíč databáze…</string>
<string name="database">Databáze</string>
<string name="decrypting_db">Dešifruji obsah databáze…</string>
<string name="decrypting_db">Dešifrování obsahu databáze…</string>
<string name="default_checkbox">Použít jako výchozí databázi</string>
<string name="digits">Číslice</string>
<string name="select_database_file">Otevřít existující databázi</string>
@@ -88,7 +88,7 @@
<string name="length">Délka</string>
<string name="list_size_title">Velikost položek seznamu</string>
<string name="list_size_summary">Velikost textu v seznamu prvků</string>
<string name="loading_database">Načítám databázi</string>
<string name="loading_database">Načítá databáze</string>
<string name="lowercase">Malá písmena</string>
<string name="hide_password_title">Skrýt hesla</string>
<string name="hide_password_summary">Ve výchozím stavu zobrazit (***) místo hesla</string>
@@ -111,7 +111,7 @@
<string name="no_url_handler">Pro otevření tohoto URL nainstalujte webový prohlížeč.</string>
<string name="omit_backup_search_title">Neprohledávat položky v záloze</string>
<string name="omit_backup_search_summary">Vynechat skupiny „Záloha“ a \"Koš\" z výsledků vyhledávání</string>
<string name="progress_create">Zakládám novou databázi</string>
<string name="progress_create">Zakládá nové databáze</string>
<string name="progress_title">Pracuji…</string>
<string name="protection">Ochrana</string>
<string name="read_only_warning">Ke změně v databáze potřebuje KeePassDX oprávnění pro zápis.</string>
@@ -119,8 +119,8 @@
<string name="root">Kořen</string>
<string name="rounds">Transformační průchody</string>
<string name="rounds_explanation">Vyšší počet šifrovacích průchodů zvýší odolnost proti útoku zkoušením všech možných hesel, ale může výrazně zpomalit načítání a ukládání.</string>
<string name="saving_database">Ukládám databázi</string>
<string name="space">Místo</string>
<string name="saving_database">Ukládá databáze</string>
<string name="space">Mezera</string>
<string name="search_label">Hledat</string>
<string name="sort_db">Přirozené řazení</string>
<string name="special">Speciální</string>
@@ -374,7 +374,7 @@
<string name="error_otp_period">Interval musít být mezi %1$d a %2$d vteřinami.</string>
<string name="error_otp_digits">Token musí obsahovat mezi %1$d a %2$d číslicemi.</string>
<string name="invalid_db_same_uuid">%1$s s totožným UUID %2$s již existuje.</string>
<string name="creating_database">Zakládám databázi</string>
<string name="creating_database">Zakládá databáze</string>
<string name="menu_security_settings">Nastavení zabezpečení</string>
<string name="menu_master_key_settings">Nastavení hlavního klíče</string>
<string name="contains_duplicate_uuid">Databáze obsahuje duplikátní UUID.</string>
@@ -403,11 +403,11 @@
<string name="error_save_database">Nebylo možno uložit databázi.</string>
<string name="menu_save_database">Uložit databázi</string>
<string name="menu_empty_recycle_bin">Vysypat koš</string>
<string name="command_execution">Provádím příkaz…</string>
<string name="command_execution">Provádění příkazu</string>
<string name="warning_permanently_delete_nodes">Natrvalo smazat vybrané uzly\?</string>
<string name="keystore_not_accessible">Úložiště klíčů není řádně inicializováno.</string>
<string name="recycle_bin_group_title">Název skupiny</string>
<string name="enable_auto_save_database_title">Uložit databázi automaticky</string>
<string name="enable_auto_save_database_title">Automatické ukládání</string>
<string name="enable_auto_save_database_summary">Uložit databázi po každé důležité akci (v režimu \"Zápis\")</string>
<string name="entry_attachments">Přílohy</string>
<string name="menu_restore_entry_history">Obnovit historii</string>
@@ -415,9 +415,9 @@
<string name="keyboard_auto_go_action_title">Akce auto-klávesy</string>
<string name="keyboard_auto_go_action_summary">Akce klávesy \"Jít\" po stisknutí klávesy \"Kolonka\"</string>
<string name="download_attachment">Stáhnout %1$s</string>
<string name="download_initialization">Zahajuji</string>
<string name="download_initialization">Zahájení</string>
<string name="download_progression">Probíhá: %1$d%%</string>
<string name="download_finalization">Dokončuji</string>
<string name="download_finalization">Dokončování</string>
<string name="download_complete">Kompletní!</string>
<string name="hide_expired_entries_title">Skrýt propadlé záznamy</string>
<string name="hide_expired_entries_summary">Propadlé záznamy nebudou ukázány</string>
@@ -437,7 +437,7 @@
<string name="warning_database_read_only">Udělit právo zápisu pro uložení změn v databázi</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft je <strong>open source</strong> a <strong>bez reklam</strong>.
\nJe poskytován jak je, od licencí <strong>GPLv3</strong>, bez jakékoli záruky.</string>
<string name="html_about_contribution">Abychom si &lt;strong&gt;udrželi svoji svobodu&lt;/strong&gt;, &lt;strong&gt;opravili chyby&lt;/strong&gt;,&lt;strong&gt;doplnili funkce&lt;/strong&gt; a &lt;strong&gt;byli vždy aktivní&lt;/strong&gt;, počítáme s Vaším &lt;strong&gt;přispěním&lt;/strong&gt;.</string>
<string name="html_about_contribution">Abychom si <strong>udrželi svoji svobodu</strong>, <strong>mohli opravovat chyby</strong>, <strong>přidávat nové funkce</strong> a <strong>byli pořád aktivní</strong>, počítáme s Vaším <strong>přispěním</strong>.</string>
<string name="error_create_database">Nepodařilo se vytvořit soubor databáze.</string>
<string name="entry_add_attachment">Přidat přílohu</string>
<string name="discard">Zavrhnout</string>
@@ -523,11 +523,11 @@
<string name="advanced_unlock_not_recognized">Otisk pro rozšířené odemknutí nebyl rozpoznán</string>
<string name="advanced_unlock_invalid_key">Nelze načíst klíč rozšířeného odemknutí. Prosím, smažte jej a opakujte proces rozpoznání odemknutí.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Načíst důvěrný údaj pomocí dat rozšířeného odemknutí</string>
<string name="advanced_unlock_prompt_extract_credential_title">Otevřít databázi pomocí rozpoznání rozšířeného odemknutí</string>
<string name="advanced_unlock_prompt_extract_credential_title">Otevřít pomocí rozšířeného odemykání</string>
<string name="advanced_unlock_prompt_store_credential_message">Varování: Pokud použijete rozpoznání rozšířeného odemknutí, musíte si i nadále pamatovat hlavní heslo.</string>
<string name="advanced_unlock_prompt_store_credential_title">Rozpoznání rozšířeného odemknutí</string>
<string name="open_advanced_unlock_prompt_store_credential">Pro uložení důvěrných údajů otevřete pobídku rozšířeného odemknutí</string>
<string name="open_advanced_unlock_prompt_unlock_database">Pro odemknutí databáze otevřete pobídku rozšířeného odemknutí</string>
<string name="open_advanced_unlock_prompt_unlock_database">Databázi otevřete i pomocí nabídky rozšířeného odemykání</string>
<string name="menu_keystore_remove_key">Smazat klíč rozšířeného odemknutí</string>
<string name="education_advanced_unlock_title">Rozšířené odemknutí databáze</string>
<string name="advanced_unlock_timeout">Časový limit rozšířeného odemknutí</string>

View File

@@ -508,4 +508,38 @@
<string name="autofill_save_search_info_summary">Forsøger at gemme delte oplysninger, når der foretages et manuelt indtastningsvalg</string>
<string name="keyboard_save_search_info_summary">Forsøger at gemme delte oplysninger, når der foretages et manuelt indtastningsvalg</string>
<string name="error_field_name_already_exists">Feltnavnet findes allerede.</string>
<string name="icon_section_custom">Brugerdefineret</string>
<string name="icon_section_standard">Standard</string>
<string name="style_brightness_summary">Vælg lys eller mørk tema</string>
<string name="style_brightness_title">Temalysstyrke</string>
<string name="unit_gibibyte">GiB</string>
<string name="unit_mebibyte">MiB</string>
<string name="unit_kibibyte">KiB</string>
<string name="unit_byte">B</string>
<string name="download_canceled">Annulleret!</string>
<string name="education_advanced_unlock_title">Avanceret database-oplåsning</string>
<string name="autofill_inline_suggestions_keyboard">Forslag til autofyld tilføjet.</string>
<string name="select_entry">Vælg post</string>
<string name="back_to_previous_keyboard">Tilbage til forrige tastatur</string>
<string name="custom_fields">Brugerdefinerede felter</string>
<string name="advanced_unlock_delete_all_key_warning">Slet alle krypteringsnøgler relateret til avanceret oplåsningsgenkendelse\?</string>
<string name="advanced_unlock_tap_delete">Tryk for at slette avancerede oplåsningstaster</string>
<string name="content">Indhold</string>
<string name="credential_before_click_advanced_unlock_button">Indtast adgangskoden, og klik derefter på denne knap.</string>
<string name="advanced_unlock_prompt_not_initialized">Kunne ikke initialisere avanceret oplåsningsprompt.</string>
<string name="advanced_unlock_scanning_error">Fejl ved avanceret oplåsning: %1$s</string>
<string name="advanced_unlock_not_recognized">Kunne ikke genkende avanceret oplåsning</string>
<string name="advanced_unlock_invalid_key">Den avancerede oplåsningsnøgle kan ikke læses. Slet den, og gentag proceduren for genkendelse af oplåsning.</string>
<string name="advanced_unlock_prompt_extract_credential_title">Åbn database med avanceret oplåsningsgenkendelse</string>
<string name="advanced_unlock_prompt_store_credential_title">Avanceret oplåsningsgenkendelse</string>
<string name="warning_database_info_changed_options">Overskriv de eksterne ændringer ved at gemme databasen eller genindlæse den med de seneste ændringer.</string>
<string name="warning_database_info_changed">Oplysningerne i databasefilen er blevet ændret uden for appen.</string>
<string name="menu_keystore_remove_key">Slet avanceret oplåsningsnøgle</string>
<string name="menu_reload_database">Genindlæs database</string>
<string name="error_duplicate_file">Fildataene findes allerede.</string>
<string name="error_upload_file">Der opstod en fejl under overførsel af fildataene.</string>
<string name="error_file_to_big">Filen, du prøver at overføre, er for stor.</string>
<string name="error_rebuild_list">Listen kan ikke genopbygges korrekt.</string>
<string name="error_database_uri_null">Database-URI kan ikke hentes.</string>
<string name="content_description_otp_information">Oplysninger om engangsadgangskode</string>
</resources>

View File

@@ -559,4 +559,6 @@
<string name="error_upload_file">Παρουσιάστηκε σφάλμα κατά τη μεταφόρτωση των δεδομένων αρχείου.</string>
<string name="error_file_to_big">Το αρχείο που προσπαθείτε να ανεβάσετε είναι πολύ μεγάλο.</string>
<string name="content_description_otp_information">Πληροφορίες One-time κωδικού πρόσβασης</string>
<string name="error_remove_file">Παρουσιάστηκε σφάλμα κατά την κατάργηση των δεδομένων αρχείου.</string>
<string name="error_duplicate_file">Τα δεδομένα αρχείου υπάρχουν ήδη.</string>
</resources>

View File

@@ -470,7 +470,7 @@
<string name="content">Contenido</string>
<string name="clipboard_explanation_summary">Copiar los campos de entrada usando el portapapeles de su dispositivo</string>
<string name="device_credential">Credenciales del dispositivo</string>
<string name="credential_before_click_advanced_unlock_button">Introduzca la contraseña y luego haga clic en el botón \"Desbloqueo avanzado\".</string>
<string name="credential_before_click_advanced_unlock_button">Introduzca la contraseña y luego haga clic en este botón.</string>
<string name="advanced_unlock_prompt_not_initialized">No se pudo inicializar el indicador de desbloqueo avanzado.</string>
<string name="advanced_unlock_scanning_error">Error de desbloqueo avanzado: %1$s</string>
<string name="advanced_unlock_not_recognized">No se pudo reconocer la impresión de desbloqueo avanzado</string>
@@ -554,4 +554,6 @@
<string name="menu_reload_database">Recargar la base de datos</string>
<string name="error_otp_type">El tipo de OTP existente no es reconocido por este formulario, su validación ya no puede generar correctamente el token.</string>
<string name="download_canceled">¡Cancelado!</string>
<string name="error_duplicate_file">Los datos de archivo ya existen.</string>
<string name="error_upload_file">Ha habido un error al subir el archivo de datos.</string>
</resources>

View File

@@ -519,7 +519,7 @@
<string name="device_credential_unlock_enable_summary">Vous permet d\'utiliser les informations d\'identification de votre appareil pour ouvrir la base de données</string>
<string name="device_credential_unlock_enable_title">Déverrouillage par identifiants de l\'appareil</string>
<string name="device_credential">Déverouillage de l\'appareil</string>
<string name="credential_before_click_advanced_unlock_button">Tapez le mot de passe, puis cliquez sur le bouton \"Déverrouillage avancé\".</string>
<string name="credential_before_click_advanced_unlock_button">Tapez le mot de passe, puis cliquez sur ce bouton.</string>
<string name="advanced_unlock_prompt_not_initialized">Impossible d\'initialiser l\'invite de déverrouillage avancé.</string>
<string name="advanced_unlock_scanning_error">Erreur de déverrouillage avancé : %1$s</string>
<string name="advanced_unlock_not_recognized">Impossible de reconnaître l\'empreinte de déverrouillage avancé</string>
@@ -560,4 +560,13 @@
<string name="unit_byte">Octets</string>
<string name="error_otp_type">Le type OTP existant n\'est pas reconnu par ce formulaire, sa validation peut ne plus générer correctement le jeton.</string>
<string name="download_canceled">Annulé!</string>
<string name="icon_section_custom">Customisé</string>
<string name="icon_section_standard">Standard</string>
<string name="style_brightness_summary">Sélectionnez des thèmes clairs ou foncés</string>
<string name="style_brightness_title">Luminosité de thème</string>
<string name="error_remove_file">Une erreur s\'est produite lors de la suppression des données du fichier.</string>
<string name="error_duplicate_file">Les données du fichier existent déjà.</string>
<string name="error_upload_file">Une erreur s\'est produite lors du téléchargement des données du fichier.</string>
<string name="error_file_to_big">Le fichier que vous essayez de téléverser est trop gros.</string>
<string name="content_description_otp_information">Information sur le mot de passe à usage unique</string>
</resources>

View File

@@ -543,4 +543,6 @@
<string name="error_upload_file">Tijekom prijenosa podataka datoteke došlo je do greške.</string>
<string name="error_file_to_big">Datoteka koju pokušavaš prenijeti je prevelika.</string>
<string name="content_description_otp_information">Podaci jednokratne lozinke</string>
<string name="error_remove_file">Tijekom uklanjanja podataka datoteke došlo je do greške.</string>
<string name="error_duplicate_file">Podaci datoteke već postoje.</string>
</resources>

View File

@@ -322,4 +322,67 @@
<string name="error_registration_read_only">Menyimpan item baru tidak diperbolehkan dalam database read-only</string>
<string name="error_otp_type">Tipe OTP yang ada tidak dikenali oleh formulir ini, validasinya mungkin tidak lagi menghasilkan token dengan benar.</string>
<string name="content_description_credentials_information">Info kredensial</string>
<string name="autofill_inline_suggestions_keyboard">Saran pengisian otomatis ditambahkan.</string>
<string name="autofill_block_restart">Mulai ulang aplikasi yang berisi formulir untuk mengaktifkan pemblokiran.</string>
<string name="autofill_block">Blokir pengisian otomatis</string>
<string name="autofill_web_domain_blocklist_summary">Daftar blokir yang mencegah pengisian otomatis domain web</string>
<string name="autofill_web_domain_blocklist_title">Daftar blokir domain web</string>
<string name="autofill_application_id_blocklist_summary">Daftar blokir yang mencegah pengisian otomatis aplikasi</string>
<string name="autofill_application_id_blocklist_title">Daftar blokir aplikasi</string>
<string name="autofill_ask_to_save_data_summary">Meminta untuk menyimpan data saat formulir divalidasi</string>
<string name="autofill_ask_to_save_data_title">Minta untuk menyimpan data</string>
<string name="autofill_save_search_info_summary">Cobalah untuk menyimpan informasi pencarian saat membuat pilihan entri manual</string>
<string name="autofill_save_search_info_title">Simpan info pencarian</string>
<string name="autofill_inline_suggestions_title">Saran sebaris</string>
<string name="autofill_auto_search_summary">Secara otomatis menyarankan hasil pencarian dari domain web atau ID aplikasi</string>
<string name="autofill_auto_search_title">Pencarian otomatis</string>
<string name="autofill_close_database_summary">Menutup database setelah pilihan isi-auto</string>
<string name="autofill_close_database_title">Tutup database</string>
<string name="enter">Enter</string>
<string name="backspace">Hapus</string>
<string name="select_entry">Pilih entri</string>
<string name="back_to_previous_keyboard">Kembali ke papan tik sebelumnya</string>
<string name="custom_fields">Bidang kustom</string>
<string name="keyboard_previous_lock_title">Kunci database</string>
<string name="keyboard_auto_go_action_title">Aksi tombol otomatis</string>
<string name="keyboard_keys_category">Tombol</string>
<string name="keyboard_previous_database_credentials_title">Layar kredensial database</string>
<string name="keyboard_change">Ganti papan tik</string>
<string name="keyboard_key_sound_title">Tombol terdengar</string>
<string name="keyboard_key_vibrate_title">Getar saat menekan tombol</string>
<string name="keyboard_auto_go_action_summary">Tindakan tombol \"Go\" setelah menekan tombol \"Field\"</string>
<string name="keyboard_theme_title">Tema papan tik</string>
<string name="keyboard_appearance_category">Tampilan</string>
<string name="keyboard_notification_entry_content_text">%1$s</string>
<string name="keyboard_notification_entry_content_title">%1$s tersedia di Magikeyboard</string>
<string name="keyboard_notification_entry_content_title_text">Entri</string>
<string name="keyboard_entry_timeout_summary">Waktu habis untuk menghapus entri papan tik</string>
<string name="keyboard_entry_timeout_title">Waktu habis</string>
<string name="keyboard_notification_entry_clear_close_summary">Tutup database saat menutup notifikasi</string>
<string name="keyboard_notification_entry_clear_close_title">Bersihkan saat menutup</string>
<string name="keyboard_search_share_title">Telusuri info yang dibagikan</string>
<string name="keyboard_notification_entry_summary">Tampilkan notifikasi ketika entri tersedia</string>
<string name="keyboard_notification_entry_title">Info notifikasi</string>
<string name="keyboard_selection_entry_summary">Tampilkan bidang input di Magikeyboard saat melihat entri</string>
<string name="keyboard_selection_entry_title">Pilihan entri</string>
<string name="keyboard_entry_category">Entri</string>
<string name="keyboard_setting_label">Pengaturan Magikeyboard</string>
<string name="keyboard_label">Magikeyboard (KeePassDX)</string>
<string name="keyboard_name">Magikeyboard</string>
<string name="device_keyboard_setting_title">Pengaturan papan tik perangkat</string>
<string name="education_add_attachment_title">Tambah lampiran</string>
<string name="html_text_dev_feature_work_hard">Kami bekerja keras untuk merilis fitur ini segera.</string>
<string name="icon_section_custom">Kustom</string>
<string name="icon_section_standard">Standar</string>
<string name="style_brightness_summary">Pilih tema terang atau gelap</string>
<string name="style_brightness_title">Kecerahan tema</string>
<string name="download_attachment">Unduh %1$s</string>
<string name="contribute">Kontribusi</string>
<string name="download">Unduh</string>
<string name="html_text_dev_feature_upgrade">Ingatlah untuk selalu memperbarui aplikasi Anda.</string>
<string name="error_remove_file">Timbul galat saat menghapus data berkas.</string>
<string name="error_duplicate_file">Data berkas sudah ada.</string>
<string name="error_upload_file">Timbul galat saat mengunggah data berkas.</string>
<string name="error_file_to_big">File yang Anda unggah terlalu besar.</string>
<string name="content_description_otp_information">Info sandi satu kali</string>
</resources>

View File

@@ -534,7 +534,7 @@
<string name="advanced_unlock_prompt_store_credential_message">Attenzione: dovrai sempre ricordare la password principale anche se usi lo sblocco avanzato.</string>
<string name="advanced_unlock_prompt_store_credential_title">Riconoscimento con sblocco avanzato</string>
<string name="device_credential">Credenziali del dispositivo</string>
<string name="credential_before_click_advanced_unlock_button">Inserisci la password, quindi clicca sull\'icona \"Sblocco avanzato\".</string>
<string name="credential_before_click_advanced_unlock_button">Inserisci la password, poi clicca questo pulsante.</string>
<string name="advanced_unlock_scanning_error">Errore sblocco avanzato: %1$s</string>
<string name="advanced_unlock_prompt_extract_credential_title">Apri il database con lo sblocco avanzato</string>
<string name="open_advanced_unlock_prompt_unlock_database">Autentica con lo sblocco avanzato per sbloccare il database</string>
@@ -556,4 +556,12 @@
<string name="unit_kibibyte">KiB</string>
<string name="unit_byte">B</string>
<string name="content_description_otp_information">Info password usa e getta</string>
<string name="icon_section_custom">Personalizzato</string>
<string name="icon_section_standard">Standard</string>
<string name="style_brightness_summary">Scegli un tema scuro o chiaro</string>
<string name="style_brightness_title">Luminosità del tema</string>
<string name="error_remove_file">Si è verificato un errore durante la rimozione del file.</string>
<string name="error_duplicate_file">Il file esiste già.</string>
<string name="error_upload_file">Si è verificato un errore durante il caricamento del file.</string>
<string name="error_file_to_big">Il file che stai cercando di caricare è troppo grande.</string>
</resources>

View File

@@ -57,7 +57,7 @@
<string name="content_description_keyfile_checkbox">キーファイルのチェックボックス</string>
<string name="content_description_repeat_toggle_password_visibility">パスワードの可視性を再び切り替える</string>
<string name="content_description_entry_icon">エントリーのアイコン</string>
<string name="validate">承認</string>
<string name="validate">検証</string>
<string name="discard_changes">変更を破棄しますか?</string>
<string name="discard">破棄</string>
<string name="entry_password_generator">パスワード生成機能</string>
@@ -80,13 +80,13 @@
<string name="entry_cancel">キャンセル</string>
<string name="entry_notes">備考</string>
<string name="entry_confpassword">パスワードを確認</string>
<string name="entry_created">作成日</string>
<string name="entry_created">作成日</string>
<string name="entry_expires">有効期限</string>
<string name="entry_UUID">UUID</string>
<string name="entry_history">履歴</string>
<string name="entry_attachments">添付ファイル</string>
<string name="entry_keyfile">キーファイル</string>
<string name="entry_modified">変更日</string>
<string name="entry_modified">変更日</string>
<string name="entry_not_found">エントリーのデータが見つかりませんでした。</string>
<string name="entry_password">パスワード</string>
<string name="save">保存</string>
@@ -185,7 +185,7 @@
<string name="menu_open">開く</string>
<string name="menu_search">検索</string>
<string name="menu_showpass">パスワードを表示</string>
<string name="menu_url">URL に移動</string>
<string name="menu_url">URL にアクセス</string>
<string name="menu_file_selection_read_only">書き込み禁止</string>
<string name="menu_open_file_read_and_write">変更可能</string>
<string name="menu_empty_recycle_bin">ゴミ箱を空にする</string>
@@ -222,7 +222,7 @@
<string name="hide_broken_locations_summary">最近使ったデータベースの一覧で、壊れたリンクを非表示にします</string>
<string name="root">ルート</string>
<string name="encryption_explanation">すべてのデータで使用するデータベース暗号化アルゴリズムです。</string>
<string name="kdf_explanation">暗号化アルゴリズム用の鍵を生成するために、マスターキーはランダムなソルトを加える鍵導出関数を使用して変換されます。</string>
<string name="kdf_explanation">暗号化アルゴリズム用の鍵を生成するために、マスターキーはランダムなソルト付き鍵導出関数を使用して変換されます。</string>
<string name="rounds">変換ラウンド</string>
<string name="rounds_explanation">変換ラウンドを増やすことでブルート フォース攻撃に対する保護が強化されますが、読み込みと保存が本当に遅くなる可能性があります。</string>
<string name="memory_usage">メモリ使用量</string>
@@ -516,7 +516,7 @@
<string name="device_credential_unlock_enable_summary">デバイス認証情報を使用してデータベースを開くことができるようにします</string>
<string name="device_credential_unlock_enable_title">デバイス認証情報によるロック解除</string>
<string name="device_credential">デバイス認証情報</string>
<string name="credential_before_click_advanced_unlock_button">パスワードを入力し、[高度なロック解除] ボタンをタップします。</string>
<string name="credential_before_click_advanced_unlock_button">パスワードを入力し、このボタンをタップします。</string>
<string name="advanced_unlock_prompt_not_initialized">高度なロック解除プロンプトを初期化できません。</string>
<string name="advanced_unlock_scanning_error">高度なロック解除のエラー:%1$s</string>
<string name="advanced_unlock_invalid_key">高度なロック解除用の鍵が読み取れません。削除してロック解除の手順をやり直してください。</string>
@@ -549,6 +549,15 @@
<string name="unit_mebibyte">MiB</string>
<string name="unit_kibibyte">KiB</string>
<string name="unit_byte">B</string>
<string name="download_canceled">キャンセルされました!</string>
<string name="error_otp_type">既存の OTP 形式がこのフォームで認識されない場合、検証によってトークンが正しく生成されなくなる可能性があります。</string>
<string name="download_canceled">キャンセルました</string>
<string name="error_otp_type">既存の OTP の種類がこのフォームで認識されていないため、フォームの検証によってトークンが正しく生成されなくなる可能性があります。</string>
<string name="icon_section_custom">カスタム</string>
<string name="icon_section_standard">標準</string>
<string name="style_brightness_summary">ライトテーマとダークテーマのどちらかを選択します</string>
<string name="style_brightness_title">テーマの明るさ</string>
<string name="error_remove_file">ファイルデータの削除中にエラーが発生しました。</string>
<string name="error_duplicate_file">ファイルデータはすでに存在します。</string>
<string name="error_upload_file">ファイルデータのアップロード中にエラーが発生しました。</string>
<string name="error_file_to_big">アップロードしようとしているファイルが大きすぎます。</string>
<string name="content_description_otp_information">ワンタイムパスワードについて</string>
</resources>

View File

@@ -453,4 +453,19 @@
<string name="error_string_type">Denne teksten samsvarer ikke med det valgte elementet.</string>
<string name="html_about_contribution">For å <strong> beholde vår frihet </strong>, <strong> fikse feil </strong>, <strong> legge til funksjoner </strong> og <strong> være alltid aktiv </strong>, stoler vi på ditt <strong> bidrag </strong>.</string>
<string name="content_description_repeat_toggle_password_visibility">Gjenta for å skifte passordsynlighet</string>
<string name="icon_section_custom">Egendefinert</string>
<string name="icon_section_standard">Forvalg</string>
<string name="style_brightness_summary">Velg lys eller mørk drakt</string>
<string name="style_brightness_title">Draktlysstyrke</string>
<string name="backspace">Rettetast</string>
<string name="keyboard_save_search_info_title">Lagre delt info</string>
<string name="keyboard_search_share_title">Søk i delt info</string>
<string name="device_keyboard_setting_title">Innstillinger for enhetens tastatur</string>
<string name="notification">Merknad</string>
<string name="data">Data</string>
<string name="advanced_unlock_tap_delete">Trykk for å slette avanserte opplåsningsnøkler</string>
<string name="clipboard_explanation_summary">Kopier inntastingsfelter ved bruk av utklippstavlen på din enhet</string>
<string name="autofill_preference_title">Autofyllings-innstillinger</string>
<string name="warning_sure_remove_data">Fjern denne dataen uansett\?</string>
<string name="warning_permanently_delete_nodes">Slett valgte noder for godt\?</string>
</resources>

View File

@@ -526,7 +526,7 @@
<string name="advanced_unlock_tap_delete">Tik om geavanceerde ontgrendelingstoetsen te verwijderen</string>
<string name="content">Inhoud</string>
<string name="device_credential">Apparaatreferentie</string>
<string name="credential_before_click_advanced_unlock_button">Typ het wachtwoord en klik vervolgens op de knop \"Geavanceerd ontgrendelen\".</string>
<string name="credential_before_click_advanced_unlock_button">Typ het wachtwoord en klik vervolgens op deze knop.</string>
<string name="advanced_unlock_prompt_not_initialized">Kan geavanceerde ontgrendelingsprompt niet initialiseren.</string>
<string name="advanced_unlock_scanning_error">Geavanceerde ontgrendelingsfout: %1$s</string>
<string name="advanced_unlock_not_recognized">Kan geavanceerde ontgrendelingsafdruk niet herkennen</string>
@@ -554,4 +554,13 @@
<string name="error_rebuild_list">Kan de lijst niet correct opnieuw opbouwen.</string>
<string name="error_database_uri_null">Database-URI kan niet worden opgehaald.</string>
<string name="error_otp_type">Het bestaande OTP-type wordt niet herkend door dit formulier, de validatie ervan genereert het token mogelijk niet langer.</string>
<string name="icon_section_custom">Aangepast</string>
<string name="icon_section_standard">Standaard</string>
<string name="style_brightness_summary">Selecteer lichte of donkere thema\'s</string>
<string name="style_brightness_title">Helderheid van het thema</string>
<string name="error_remove_file">Er is een fout opgetreden bij het verwijderen van de bestandsgegevens.</string>
<string name="error_duplicate_file">De bestandsgegevens bestaan al.</string>
<string name="error_upload_file">Er is een fout opgetreden bij het uploaden van de bestandsgegevens.</string>
<string name="error_file_to_big">Het bestand dat je probeert te uploaden, is te groot.</string>
<string name="content_description_otp_information">Eenmalig wachtwoord-informatie</string>
</resources>

View File

@@ -559,4 +559,6 @@
<string name="error_upload_file">Wystąpił błąd podczas przesyłania danych pliku.</string>
<string name="error_file_to_big">Plik, który próbujesz przesłać, jest za duży.</string>
<string name="content_description_otp_information">Informacje o hasłach jednorazowych</string>
<string name="error_remove_file">Wystąpił błąd podczas usuwania danych z pliku.</string>
<string name="error_duplicate_file">Dane pliku już istnieją.</string>
</resources>

View File

@@ -559,4 +559,6 @@
<string name="error_upload_file">Ошибка при загрузке данных файла.</string>
<string name="error_file_to_big">Файл слишком большой для загрузки.</string>
<string name="content_description_otp_information">Информация об одноразовом пароле</string>
<string name="error_duplicate_file">Данные файла уже существует.</string>
<string name="error_remove_file">Ошибка при удалении данных файла.</string>
</resources>

View File

@@ -543,4 +543,6 @@
<string name="error_upload_file">Dosya verileri karşıya yüklenirken bir hata oluştu.</string>
<string name="error_file_to_big">Karşıya yüklemeye çalıştığınız dosya çok büyük.</string>
<string name="content_description_otp_information">Tek seferlik parola bilgileri</string>
<string name="error_remove_file">Dosya verilerini kaldırırken bir hata oluştu.</string>
<string name="error_duplicate_file">Dosya verileri zaten var.</string>
</resources>

View File

@@ -559,4 +559,6 @@
<string name="error_upload_file">Під час передавання даних файлу сталася помилка.</string>
<string name="error_file_to_big">Файл, який ви намагаєтеся передати, завеликий.</string>
<string name="content_description_otp_information">Відомості про одноразовий пароль</string>
<string name="error_remove_file">Сталася помилка під час вилучення даних файлу.</string>
<string name="error_duplicate_file">Дані файлу вже існують.</string>
</resources>

View File

@@ -559,4 +559,6 @@
<string name="error_upload_file">上传文件数据时发生错误。</string>
<string name="error_file_to_big">你尝试上传的文件太大。</string>
<string name="content_description_otp_information">一次性密码信息</string>
<string name="error_remove_file">删除文件数据时发生了一个错误。</string>
<string name="error_duplicate_file">文件数据已存在。</string>
</resources>

View File

@@ -142,6 +142,7 @@
<string name="error_upload_file">An error occurred while uploading the file data.</string>
<string name="error_duplicate_file">The file data already exists.</string>
<string name="error_remove_file">An error occurred while removing the file data.</string>
<string name="error_start_database_action">An error occurred while performing an action on the database.</string>
<string name="field_name">Field name</string>
<string name="field_value">Field value</string>
<string name="file_not_found_content">Could not find file. Try reopening it from your file browser.</string>

View File

@@ -1,2 +1,4 @@
* Fix themes #935
* Decrease default clipboard time #934
* Fix themes #935 #926
* Decrease default clipboard time #934
* Better opening performance #929 #933
* Fix memory usage setting #941

View File

@@ -0,0 +1 @@
* Fix small bugs #948

View File

@@ -1,2 +1,4 @@
* Correction des themes #935
* Baisse du temps du presse-papier par defaut #934
* Correction des themes #935 #926
* Baisse du temps du presse-papier par defaut #934
* Meilleures performaces d'ouverture #929 #933
* Correction du paramètre d'usage mémoire #941

View File

@@ -0,0 +1 @@
* Correction de petits bugs #948