Compare commits

...

35 Commits

Author SHA1 Message Date
J-Jamet
1b98bd740c Merge branch 'release/4.1.9' 2025-10-06 17:27:26 +02:00
J-Jamet
5adeb5cde0 fix: Tags 2025-10-06 17:20:59 +02:00
J-Jamet
b949d5d861 Merge branch 'develop' of https://hosted.weblate.org/projects/keepass-dx/strings into translations 2025-10-06 17:18:20 +02:00
J-Jamet
b4264a30a4 fix: Update description 2025-10-06 17:16:57 +02:00
J-Jamet
cf799c0f68 fix: Update to 4.1.9 2025-10-06 17:14:10 +02:00
J-Jamet
97f0ca519b fix: Killed service #2201 2025-10-06 16:59:42 +02:00
J-Jamet
cf4047b701 Merge branch 'chenxiaolong-landscape-insets' into develop 2025-10-06 13:58:39 +02:00
J-Jamet
40608a3eb5 Merge branch 'landscape-insets' of github.com:chenxiaolong/KeePassDX into chenxiaolong-landscape-insets 2025-10-06 13:58:20 +02:00
J-Jamet
99cb50d031 fix: Bug report title 2025-10-06 12:47:30 +02:00
Oğuz Ersen
b0d0c35241 Translated using Weblate (Turkish)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/tr/
2025-10-05 18:02:07 +00:00
Mekyla Credo
6044c93a4a Translated using Weblate (Filipino)
Currently translated at 46.5% (309 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fil/
2025-10-05 18:02:05 +00:00
Oğuz Ersen
b544b5d54d Translated using Weblate (Turkish)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2025-10-05 18:02:02 +00:00
Andrew Gunnerson
852378e484 Simplify inset logic, fix landscape mode, fix cutout overlapping
The commit primarily fixes a few overlapping issues caused by the window
inset handling. Previously, there were two main issues:

* Because setTransparentNavigationBar() checked for portrait mode, the
  inset logic never executed in landscape mode. This caused the app to
  overlap the status bar and navigation bar.

* The inset logic did not have handling for displayCutout insets. In
  landscape mode, this would cause the app to overlap the notch or
  camera hole punch area on phones.

In addition to fixing those issues, this commit simplifies the inset
logic a bit:

* applyWindowInsets() now accepts an EnumSet of WindowInsetPosition to
  avoid needing to duplicate logic for the various position
  combinations.

* Insets are now applied to the main container in the layout instead of
  individual elements where possible. This eliminates the need for the
  previous manual IME height handling logic in BOTTOM_IME vs
  TOP_BOTTOM_IME (for avoiding the insets being applied twice).

* Since insets are now applied to the main layout container,
  applyWindowInsets() now takes systemBars, displayCutout, and ime all
  into consideration. This should avoid all possible overlapping.

* Add support for using padding instead of margins for insets. This is
  used for GroupActivity's navigation drawer, where Material design
  intends for the drawer background to be drawn behind system bars.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2025-10-04 17:24:24 -04:00
Alonso González Chaves
711a344860 Translated using Weblate (Spanish)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/es/
2025-10-04 14:02:05 +02:00
Alonso González Chaves
72087c7e5c Translated using Weblate (Spanish)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/
2025-10-04 14:02:01 +02:00
J-Jamet
f17d211fbd fix: Change appearance summary #2171 2025-09-24 13:19:57 +02:00
Xo
ae903ad236 Translated using Weblate (Hebrew)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/he/
2025-09-15 09:02:00 +00:00
Milo Ivir
7c3a15ce79 Translated using Weblate (Croatian)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hr/
2025-09-12 16:01:59 +00:00
J-Jamet
2230fe66ab Merge tag '4.1.8' into develop
4.1.8
2025-09-12 16:04:08 +02:00
J-Jamet
84a62a32ff Merge branch 'release/4.1.8' 2025-09-12 16:03:59 +02:00
J-Jamet
da8ef9340c fix: Loading ViewModel 2025-09-12 15:23:32 +02:00
J-Jamet
af068349e4 fix: Upgrade to 4.1.8 2025-09-12 14:14:06 +02:00
J-Jamet
56cb5953dd fix: Deletable recycle bin #2163 2025-09-12 13:00:56 +02:00
J-Jamet
2fc2a9c7c1 fix: Delete algo during merge #1516 2025-09-11 21:19:40 +02:00
J-Jamet
69e7cdbc47 fix: Search with space #175 2025-09-11 16:43:40 +02:00
J-Jamet
39d9a74a73 fix: Warnings 2025-09-11 16:36:35 +02:00
shinebrillant
b609d4e182 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/zh_Hant/
2025-09-11 13:02:01 +00:00
J-Jamet
7212c73481 fix: Warnings 2025-09-11 14:55:37 +02:00
J-Jamet
3ee4caa153 fix: Warnings 2025-09-11 14:53:41 +02:00
J-Jamet
28e4d929bb fix: Warnings 2025-09-11 14:51:35 +02:00
Artyom Rybakov
e8ecf28f7c Translated using Weblate (Russian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ru/
2025-09-10 14:21:47 +02:00
shinebrillant
3d5adbfc01 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hant/
2025-09-10 14:21:46 +02:00
Matthaiks
72bfc50703 Translated using Weblate (Polish)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2025-09-10 14:21:46 +02:00
Matthaiks
a60e2e780d Translated using Weblate (Polish)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2025-09-09 12:01:58 +00:00
Retrial
9210851765 Translated using Weblate (Greek)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/el/
2025-09-09 12:01:56 +00:00
40 changed files with 432 additions and 231 deletions

View File

@@ -1,4 +1,4 @@
name: Bug Report name: Bug report
description: Report a bug. description: Report a bug.
labels: ["bug"] labels: ["bug"]
body: body:

View File

@@ -1,3 +1,16 @@
KeePassDX(4.1.9)
* Fix landscape UI #2198 #2200 (@chenxiaolong)
* Fix start loop and flash screen #2201
* Small fixes
KeePassDX(4.1.8)
* Updated to API 35 minimum SDK 19 #2073 #2138 #2067 #2133 #1687 (Thx @Dev-ClayP)
* Remember last read-only state #2099 #2100 (Thx @rmacklin)
* Fix merge deletion #1516
* Fix space in search #175
* Fix deletable recycle bin #2163
* Small fixes
KeePassDX(4.1.7) KeePassDX(4.1.7)
* Fix CipherDatabase for biometric states #2119 * Fix CipherDatabase for biometric states #2119

View File

@@ -11,8 +11,8 @@ android {
applicationId "com.kunzisoft.keepass" applicationId "com.kunzisoft.keepass"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 35 targetSdkVersion 35
versionCode = 139 versionCode = 143
versionName = "4.1.7" versionName = "4.1.9"
multiDexEnabled true multiDexEnabled true
testApplicationId = "com.kunzisoft.keepass.tests" testApplicationId = "com.kunzisoft.keepass.tests"

View File

@@ -23,7 +23,6 @@ import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@@ -38,13 +37,10 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.BlendModeColorFilterCompat import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat import androidx.core.graphics.BlendModeCompat
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
@@ -83,11 +79,13 @@ import com.kunzisoft.keepass.view.hideByFading
import com.kunzisoft.keepass.view.setTransparentNavigationBar import com.kunzisoft.keepass.view.setTransparentNavigationBar
import com.kunzisoft.keepass.view.showActionErrorIfNeeded import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.viewmodels.EntryViewModel import com.kunzisoft.keepass.viewmodels.EntryViewModel
import java.util.EnumSet
import java.util.UUID import java.util.UUID
class EntryActivity : DatabaseLockActivity() { class EntryActivity : DatabaseLockActivity() {
private var footer: ViewGroup? = null private var footer: ViewGroup? = null
private var container: View? = null
private var coordinatorLayout: CoordinatorLayout? = null private var coordinatorLayout: CoordinatorLayout? = null
private var collapsingToolbarLayout: CollapsingToolbarLayout? = null private var collapsingToolbarLayout: CollapsingToolbarLayout? = null
private var appBarLayout: AppBarLayout? = null private var appBarLayout: AppBarLayout? = null
@@ -139,6 +137,7 @@ class EntryActivity : DatabaseLockActivity() {
// Get views // Get views
footer = findViewById(R.id.activity_entry_footer) footer = findViewById(R.id.activity_entry_footer)
container = findViewById(R.id.activity_entry_container)
coordinatorLayout = findViewById(R.id.toolbar_coordinator) coordinatorLayout = findViewById(R.id.toolbar_coordinator)
collapsingToolbarLayout = findViewById(R.id.toolbar_layout) collapsingToolbarLayout = findViewById(R.id.toolbar_layout)
appBarLayout = findViewById(R.id.app_bar) appBarLayout = findViewById(R.id.app_bar)
@@ -154,8 +153,12 @@ class EntryActivity : DatabaseLockActivity() {
setTransparentNavigationBar { setTransparentNavigationBar {
// To fix margin with API 27 // To fix margin with API 27
ViewCompat.setOnApplyWindowInsetsListener(collapsingToolbarLayout!!, null) ViewCompat.setOnApplyWindowInsetsListener(collapsingToolbarLayout!!, null)
coordinatorLayout?.applyWindowInsets(WindowInsetPosition.TOP) container?.applyWindowInsets(EnumSet.of(
footer?.applyWindowInsets(WindowInsetPosition.BOTTOM) WindowInsetPosition.TOP_MARGINS,
WindowInsetPosition.BOTTOM_MARGINS,
WindowInsetPosition.START_MARGINS,
WindowInsetPosition.END_MARGINS,
))
} }
// Empty title // Empty title

View File

@@ -100,6 +100,7 @@ import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.view.updateLockPaddingStart import com.kunzisoft.keepass.view.updateLockPaddingStart
import com.kunzisoft.keepass.viewmodels.ColorPickerViewModel import com.kunzisoft.keepass.viewmodels.ColorPickerViewModel
import com.kunzisoft.keepass.viewmodels.EntryEditViewModel import com.kunzisoft.keepass.viewmodels.EntryEditViewModel
import java.util.EnumSet
import java.util.UUID import java.util.UUID
class EntryEditActivity : DatabaseLockActivity(), class EntryEditActivity : DatabaseLockActivity(),
@@ -180,8 +181,12 @@ class EntryEditActivity : DatabaseLockActivity(),
// To apply fit window with transparency // To apply fit window with transparency
setTransparentNavigationBar(applyToStatusBar = true) { setTransparentNavigationBar(applyToStatusBar = true) {
container?.applyWindowInsets(WindowInsetPosition.TOP_BOTTOM_IME) container?.applyWindowInsets(EnumSet.of(
footer?.applyWindowInsets(WindowInsetPosition.BOTTOM_IME) WindowInsetPosition.TOP_MARGINS,
WindowInsetPosition.BOTTOM_MARGINS,
WindowInsetPosition.START_MARGINS,
WindowInsetPosition.END_MARGINS,
))
} }
stopService(Intent(this, ClipboardEntryNotificationService::class.java)) stopService(Intent(this, ClipboardEntryNotificationService::class.java))

View File

@@ -48,6 +48,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.GravityCompat import androidx.core.view.GravityCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
@@ -117,6 +118,7 @@ import com.kunzisoft.keepass.view.updateLockPaddingStart
import com.kunzisoft.keepass.viewmodels.GroupEditViewModel import com.kunzisoft.keepass.viewmodels.GroupEditViewModel
import com.kunzisoft.keepass.viewmodels.GroupViewModel import com.kunzisoft.keepass.viewmodels.GroupViewModel
import org.joda.time.LocalDateTime import org.joda.time.LocalDateTime
import java.util.EnumSet
class GroupActivity : DatabaseLockActivity(), class GroupActivity : DatabaseLockActivity(),
@@ -131,6 +133,7 @@ class GroupActivity : DatabaseLockActivity(),
private var header: ViewGroup? = null private var header: ViewGroup? = null
private var footer: ViewGroup? = null private var footer: ViewGroup? = null
private var drawerLayout: DrawerLayout? = null private var drawerLayout: DrawerLayout? = null
private var constraintLayout: ConstraintLayout? = null
private var databaseNavView: NavigationDatabaseView? = null private var databaseNavView: NavigationDatabaseView? = null
private var coordinatorLayout: CoordinatorLayout? = null private var coordinatorLayout: CoordinatorLayout? = null
private var coordinatorError: CoordinatorLayout? = null private var coordinatorError: CoordinatorLayout? = null
@@ -279,6 +282,7 @@ class GroupActivity : DatabaseLockActivity(),
header = findViewById(R.id.activity_group_header) header = findViewById(R.id.activity_group_header)
footer = findViewById(R.id.activity_group_footer) footer = findViewById(R.id.activity_group_footer)
drawerLayout = findViewById(R.id.drawer_layout) drawerLayout = findViewById(R.id.drawer_layout)
constraintLayout = findViewById(R.id.activity_group_container_view)
databaseNavView = findViewById(R.id.database_nav_view) databaseNavView = findViewById(R.id.database_nav_view)
coordinatorLayout = findViewById(R.id.group_coordinator) coordinatorLayout = findViewById(R.id.group_coordinator)
coordinatorError = findViewById(R.id.error_coordinator) coordinatorError = findViewById(R.id.error_coordinator)
@@ -296,8 +300,19 @@ class GroupActivity : DatabaseLockActivity(),
// To apply fit window with transparency // To apply fit window with transparency
setTransparentNavigationBar(applyToStatusBar = true) { setTransparentNavigationBar(applyToStatusBar = true) {
drawerLayout?.applyWindowInsets(WindowInsetPosition.TOP_BOTTOM_IME) constraintLayout?.applyWindowInsets(EnumSet.of(
footer?.applyWindowInsets(WindowInsetPosition.BOTTOM_IME) WindowInsetPosition.TOP_MARGINS,
WindowInsetPosition.BOTTOM_MARGINS,
WindowInsetPosition.START_MARGINS,
WindowInsetPosition.END_MARGINS,
))
// The background of the drawer is meant to overlap system bars, so use padding
databaseNavView?.applyWindowInsets(EnumSet.of(
WindowInsetPosition.TOP_PADDING,
WindowInsetPosition.BOTTOM_PADDING,
// Only on the start side, since the drawer is anchored to one side of the screen
WindowInsetPosition.START_PADDING,
))
} }
lockView?.setOnClickListener { lockView?.setOnClickListener {

View File

@@ -43,6 +43,7 @@ import androidx.biometric.BiometricManager
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.fragment.app.commit import androidx.fragment.app.commit
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@@ -75,8 +76,8 @@ import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.MAIN_CREDENTIAL_KEY import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.MAIN_CREDENTIAL_KEY
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.READ_ONLY_KEY import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.READ_ONLY_KEY
import com.kunzisoft.keepass.settings.DeviceUnlockSettingsActivity
import com.kunzisoft.keepass.settings.AppearanceSettingsActivity import com.kunzisoft.keepass.settings.AppearanceSettingsActivity
import com.kunzisoft.keepass.settings.DeviceUnlockSettingsActivity
import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION
@@ -107,7 +108,11 @@ class MainCredentialActivity : DatabaseModeActivity() {
private var deviceUnlockFragment: DeviceUnlockFragment? = null private var deviceUnlockFragment: DeviceUnlockFragment? = null
private val mDatabaseFileViewModel: DatabaseFileViewModel by viewModels() private val mDatabaseFileViewModel: DatabaseFileViewModel by viewModels()
private val mDeviceUnlockViewModel: DeviceUnlockViewModel by viewModels() private val mDeviceUnlockViewModel: DeviceUnlockViewModel? by lazy {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ViewModelProvider(this)[DeviceUnlockViewModel::class.java]
} else null
}
private val mPasswordActivityEducation = PasswordActivityEducation(this) private val mPasswordActivityEducation = PasswordActivityEducation(this)
@@ -177,7 +182,7 @@ class MainCredentialActivity : DatabaseModeActivity() {
// Listen password checkbox to init advanced unlock and confirmation button // Listen password checkbox to init advanced unlock and confirmation button
mainCredentialView?.onConditionToStoreCredentialChanged = { _, verified -> mainCredentialView?.onConditionToStoreCredentialChanged = { _, verified ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mDeviceUnlockViewModel.checkConditionToStoreCredential( mDeviceUnlockViewModel?.checkConditionToStoreCredential(
condition = verified condition = verified
) )
} }
@@ -242,29 +247,31 @@ class MainCredentialActivity : DatabaseModeActivity() {
lifecycleScope.launch { lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) { repeatOnLifecycle(Lifecycle.State.STARTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mDeviceUnlockViewModel.uiState.collect { uiState -> mDeviceUnlockViewModel?.let { deviceUnlockViewModel ->
// New value received deviceUnlockViewModel.uiState.collect { uiState ->
uiState.credentialRequiredCipher?.let { cipher -> // New value received
mDeviceUnlockViewModel.encryptCredential( uiState.credentialRequiredCipher?.let { cipher ->
credential = getCredentialForEncryption(), deviceUnlockViewModel.encryptCredential(
cipher = cipher credential = getCredentialForEncryption(),
) cipher = cipher
} )
uiState.cipherEncryptDatabase?.let { cipherEncryptDatabase -> }
onCredentialEncrypted(cipherEncryptDatabase) uiState.cipherEncryptDatabase?.let { cipherEncryptDatabase ->
mDeviceUnlockViewModel.consumeCredentialEncrypted() onCredentialEncrypted(cipherEncryptDatabase)
} deviceUnlockViewModel.consumeCredentialEncrypted()
uiState.cipherDecryptDatabase?.let { cipherDecryptDatabase -> }
onCredentialDecrypted(cipherDecryptDatabase) uiState.cipherDecryptDatabase?.let { cipherDecryptDatabase ->
mDeviceUnlockViewModel.consumeCredentialDecrypted() onCredentialDecrypted(cipherDecryptDatabase)
} deviceUnlockViewModel.consumeCredentialDecrypted()
uiState.exception?.let { error -> }
Snackbar.make( uiState.exception?.let { error ->
coordinatorLayout, Snackbar.make(
deviceUnlockError(error, this@MainCredentialActivity), coordinatorLayout,
Snackbar.LENGTH_LONG deviceUnlockError(error, this@MainCredentialActivity),
).asError().show() Snackbar.LENGTH_LONG
mDeviceUnlockViewModel.exceptionShown() ).asError().show()
deviceUnlockViewModel.exceptionShown()
}
} }
} }
} }
@@ -304,10 +311,6 @@ class MainCredentialActivity : DatabaseModeActivity() {
mDatabaseFileUri?.let { databaseFileUri -> mDatabaseFileUri?.let { databaseFileUri ->
mDatabaseFileViewModel.loadDatabaseFile(databaseFileUri) mDatabaseFileViewModel.loadDatabaseFile(databaseFileUri)
} }
mDatabase?.let { database ->
launchGroupActivityIfLoaded(database)
}
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase?) {
@@ -517,7 +520,7 @@ class MainCredentialActivity : DatabaseModeActivity() {
} else { } else {
// Init Biometric elements // Init Biometric elements
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mDeviceUnlockViewModel.connect(databaseFileUri) mDeviceUnlockViewModel?.connect(databaseFileUri)
} }
} }
@@ -661,7 +664,7 @@ class MainCredentialActivity : DatabaseModeActivity() {
try { try {
menu.findItem(R.id.menu_open_file_read_mode_key) menu.findItem(R.id.menu_open_file_read_mode_key)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Unable to find read mode menu") Log.e(TAG, "Unable to find read mode menu", e)
} }
performedNextEducation(menu) performedNextEducation(menu)
}, },
@@ -690,7 +693,7 @@ class MainCredentialActivity : DatabaseModeActivity() {
}) })
} }
} }
} catch (ignored: Exception) {} } catch (_: Exception) {}
} }
} }
@@ -727,7 +730,7 @@ class MainCredentialActivity : DatabaseModeActivity() {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mDeviceUnlockViewModel.disconnect() mDeviceUnlockViewModel?.disconnect()
} }
} }

View File

@@ -176,21 +176,14 @@ class SortDialogFragment : DatabaseDialogFragment() {
return bundle return bundle
} }
fun getInstance(sortNodeEnum: SortNodeEnum,
ascending: Boolean,
groupsBefore: Boolean): SortDialogFragment {
val bundle = buildBundle(sortNodeEnum, ascending, groupsBefore)
val fragment = SortDialogFragment()
fragment.arguments = bundle
return fragment
}
fun getInstance(sortNodeEnum: SortNodeEnum, fun getInstance(sortNodeEnum: SortNodeEnum,
ascending: Boolean, ascending: Boolean,
groupsBefore: Boolean, groupsBefore: Boolean,
recycleBinBottom: Boolean): SortDialogFragment { recycleBinBottom: Boolean?): SortDialogFragment {
val bundle = buildBundle(sortNodeEnum, ascending, groupsBefore) val bundle = buildBundle(sortNodeEnum, ascending, groupsBefore)
bundle.putBoolean(SORT_RECYCLE_BIN_BOTTOM_BUNDLE_KEY, recycleBinBottom) recycleBinBottom?.let {
bundle.putBoolean(SORT_RECYCLE_BIN_BOTTOM_BUNDLE_KEY, recycleBinBottom)
}
val fragment = SortDialogFragment() val fragment = SortDialogFragment()
fragment.arguments = bundle fragment.arguments = bundle
return fragment return fragment

View File

@@ -76,9 +76,6 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
private var specialMode: SpecialMode = SpecialMode.DEFAULT private var specialMode: SpecialMode = SpecialMode.DEFAULT
private var mRecycleBinEnable: Boolean = false
private var mRecycleBin: Group? = null
private var mRecycleViewScrollListener = object : RecyclerView.OnScrollListener() { private var mRecycleViewScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState) super.onScrollStateChanged(recyclerView, newState)
@@ -102,21 +99,14 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
R.id.menu_sort -> { R.id.menu_sort -> {
context?.let { context -> context?.let { context ->
val sortDialogFragment: SortDialogFragment = val sortDialogFragment: SortDialogFragment =
if (mRecycleBinEnable) { SortDialogFragment.getInstance(
SortDialogFragment.getInstance( PreferencesUtil.getListSort(context),
PreferencesUtil.getListSort(context), PreferencesUtil.getAscendingSort(context),
PreferencesUtil.getAscendingSort(context), PreferencesUtil.getGroupsBeforeSort(context),
PreferencesUtil.getGroupsBeforeSort(context), if (mDatabase?.isRecycleBinEnabled == true) {
PreferencesUtil.getRecycleBinBottomSort(context) PreferencesUtil.getRecycleBinBottomSort(context)
) } else null
} else { )
SortDialogFragment.getInstance(
PreferencesUtil.getListSort(context),
PreferencesUtil.getAscendingSort(context),
PreferencesUtil.getGroupsBeforeSort(context)
)
}
sortDialogFragment.show(childFragmentManager, "sortDialog") sortDialogFragment.show(childFragmentManager, "sortDialog")
} }
true true
@@ -165,9 +155,6 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase?) {
mRecycleBinEnable = database?.isRecycleBinEnabled == true
mRecycleBin = database?.recycleBin
context?.let { context -> context?.let { context ->
database?.let { database -> database?.let { database ->
mAdapter = NodesAdapter(context, database).apply { mAdapter = NodesAdapter(context, database).apply {
@@ -312,6 +299,11 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
} }
} }
private fun containsRecycleBin(nodes: List<Node>): Boolean {
return mDatabase?.isRecycleBinEnabled == true
&& nodes.any { it == mDatabase?.recycleBin }
}
fun actionNodesCallback(database: ContextualDatabase, fun actionNodesCallback(database: ContextualDatabase,
nodes: List<Node>, nodes: List<Node>,
menuListener: NodesActionMenuListener?, menuListener: NodesActionMenuListener?,
@@ -336,8 +328,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
// Open and Edit for a single item // Open and Edit for a single item
if (nodes.size == 1) { if (nodes.size == 1) {
// Edition // Edition
if (database.isReadOnly if (database.isReadOnly || containsRecycleBin(nodes)) {
|| (mRecycleBinEnable && nodes[0] == mRecycleBin)) {
menu?.removeItem(R.id.menu_edit) menu?.removeItem(R.id.menu_edit)
} }
} else { } else {
@@ -357,8 +348,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
} }
// Deletion // Deletion
if (database.isReadOnly if (database.isReadOnly || containsRecycleBin(nodes)) {
|| (mRecycleBinEnable && nodes.any { it == mRecycleBin })) {
menu?.removeItem(R.id.menu_delete) menu?.removeItem(R.id.menu_delete)
} }
} }

View File

@@ -254,6 +254,7 @@ class DatabaseTaskProvider(
} }
private fun initServiceConnection() { private fun initServiceConnection() {
stopDialog()
if (serviceConnection == null) { if (serviceConnection == null) {
serviceConnection = object : ServiceConnection { serviceConnection = object : ServiceConnection {
override fun onBindingDied(name: ComponentName?) { override fun onBindingDied(name: ComponentName?) {

View File

@@ -59,9 +59,9 @@ object SearchHelper {
&& !searchInfo.containsOnlyNullValues()) { && !searchInfo.containsOnlyNullValues()) {
// If search provide results // If search provide results
database.createVirtualGroupFromSearchInfo( database.createVirtualGroupFromSearchInfo(
searchInfo.toString(), searchInfoString = searchInfo.toString(),
searchInfo.isASearchByDomain(), searchInfoByDomain = searchInfo.isASearchByDomain(),
MAX_SEARCH_ENTRY max = MAX_SEARCH_ENTRY
)?.let { searchGroup -> )?.let { searchGroup ->
if (searchGroup.numberOfChildEntries > 0) { if (searchGroup.numberOfChildEntries > 0) {
searchWithoutUI = true searchWithoutUI = true

View File

@@ -70,8 +70,12 @@ open class SettingsActivity
// To apply navigation bar with background color // To apply navigation bar with background color
/* TODO Settings nav bar /* TODO Settings nav bar
setTransparentNavigationBar { setTransparentNavigationBar {
coordinatorLayout?.applyWindowInsets(WindowInsetPosition.TOP) coordinatorLayout?.applyWindowInsets(EnumSet.of(
footer?.applyWindowInsets(WindowInsetPosition.BOTTOM) WindowInsetPosition.TOP_MARGINS,
WindowInsetPosition.BOTTOM_MARGINS,
WindowInsetPosition.START_MARGINS,
WindowInsetPosition.END_MARGINS,
))
}*/ }*/
mExternalFileHelper = ExternalFileHelper(this) mExternalFileHelper = ExternalFileHelper(this)

View File

@@ -24,7 +24,6 @@ import android.animation.AnimatorSet
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.res.Configuration
import android.graphics.Color import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
import android.graphics.PorterDuff import android.graphics.PorterDuff
@@ -58,7 +57,6 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.forEach import androidx.core.view.forEach
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative import androidx.core.view.updatePaddingRelative
import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.appbar.CollapsingToolbarLayout
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@@ -66,6 +64,7 @@ import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.helper.getLocalizedMessage import com.kunzisoft.keepass.database.helper.getLocalizedMessage
import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ActionRunnable
import java.util.EnumSet
/** /**
@@ -304,10 +303,9 @@ fun CollapsingToolbarLayout.changeTitleColor(color: Int) {
invalidate() invalidate()
} }
@Suppress("DEPRECATION")
fun Activity.setTransparentNavigationBar(applyToStatusBar: Boolean = false, applyWindowInsets: () -> Unit) { fun Activity.setTransparentNavigationBar(applyToStatusBar: Boolean = false, applyWindowInsets: () -> Unit) {
// Only in portrait if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1
&& resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
window.navigationBarColor = ContextCompat.getColor(this, R.color.surface_selector) window.navigationBarColor = ContextCompat.getColor(this, R.color.surface_selector)
if (applyToStatusBar) { if (applyToStatusBar) {
@@ -323,7 +321,7 @@ fun Activity.setTransparentNavigationBar(applyToStatusBar: Boolean = false, appl
/** /**
* Apply a margin to a view to fix the window inset * Apply a margin to a view to fix the window inset
*/ */
fun View.applyWindowInsets(position: WindowInsetPosition = WindowInsetPosition.BOTTOM) { fun View.applyWindowInsets(positions: EnumSet<WindowInsetPosition>) {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets -> ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
var consumed = false var consumed = false
@@ -339,52 +337,78 @@ fun View.applyWindowInsets(position: WindowInsetPosition = WindowInsetPosition.B
} }
} }
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()
when (position) { or WindowInsetsCompat.Type.displayCutout()
WindowInsetPosition.TOP -> { or WindowInsetsCompat.Type.ime())
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> { val isRtl = layoutDirection == View.LAYOUT_DIRECTION_RTL
topMargin = insets.top
val wantTopMargins = positions.contains(WindowInsetPosition.TOP_MARGINS)
val wantBottomMargins = positions.contains(WindowInsetPosition.BOTTOM_MARGINS)
val wantStartMargins = positions.contains(WindowInsetPosition.START_MARGINS)
val wantEndMargins = positions.contains(WindowInsetPosition.END_MARGINS)
if (view.layoutParams is ViewGroup.MarginLayoutParams
&& (wantTopMargins || wantBottomMargins || wantStartMargins || wantEndMargins)) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
if (wantTopMargins) {
topMargin = insets.top
}
if (wantBottomMargins) {
bottomMargin = insets.bottom
}
if (wantStartMargins) {
if (isRtl) {
rightMargin = insets.right
} else {
leftMargin = insets.left
} }
} }
} if (wantEndMargins) {
WindowInsetPosition.LEGIT_TOP -> { if (isRtl) {
if (view.layoutParams is ViewGroup.MarginLayoutParams) { leftMargin = insets.left
view.updateLayoutParams<ViewGroup.MarginLayoutParams> { } else {
topMargin = 0 rightMargin = insets.right
}
}
}
WindowInsetPosition.BOTTOM -> {
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = insets.bottom
}
}
}
WindowInsetPosition.BOTTOM_IME -> {
val imeHeight = windowInsets.getInsets(WindowInsetsCompat.Type.ime()).bottom
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = if (imeHeight > 1) 0 else insets.bottom
}
}
}
WindowInsetPosition.TOP_BOTTOM_IME -> {
val imeHeight = windowInsets.getInsets(WindowInsetsCompat.Type.ime()).bottom
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
bottomMargin = if (imeHeight > 1) imeHeight else 0
} }
} }
} }
} }
val wantTopPadding = positions.contains(WindowInsetPosition.TOP_PADDING)
val wantBottomPadding = positions.contains(WindowInsetPosition.BOTTOM_PADDING)
val wantStartPadding = positions.contains(WindowInsetPosition.START_PADDING)
val wantEndPadding = positions.contains(WindowInsetPosition.END_PADDING)
if (wantTopPadding || wantBottomPadding || wantStartPadding || wantEndPadding) {
val topPadding = if (wantTopPadding) insets.top else 0
val bottomPadding = if (wantBottomPadding) insets.bottom else 0
var leftPadding = 0
var rightPadding = 0
if (wantStartPadding) {
if (isRtl) {
rightPadding = insets.right
} else {
leftPadding = insets.left
}
}
if (wantEndPadding) {
if (isRtl) {
leftPadding = insets.left
} else {
rightPadding = insets.right
}
}
setPadding(leftPadding, topPadding, rightPadding, bottomPadding)
}
// If any of the children consumed the insets, return an appropriate value // If any of the children consumed the insets, return an appropriate value
if (consumed) WindowInsetsCompat.CONSUMED else windowInsets if (consumed) WindowInsetsCompat.CONSUMED else windowInsets
} }
} }
enum class WindowInsetPosition { enum class WindowInsetPosition {
TOP, BOTTOM, LEGIT_TOP, BOTTOM_IME, TOP_BOTTOM_IME TOP_MARGINS, BOTTOM_MARGINS, START_MARGINS, END_MARGINS,
TOP_PADDING, BOTTOM_PADDING, START_PADDING, END_PADDING,
} }

View File

@@ -20,6 +20,7 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_entry_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:filterTouchesWhenObscured="true"> android:filterTouchesWhenObscured="true">

View File

@@ -19,7 +19,7 @@
--><resources> --><resources>
<string name="feedback">Σχόλια</string> <string name="feedback">Σχόλια</string>
<string name="homepage">Αρχική Σελίδα</string> <string name="homepage">Αρχική Σελίδα</string>
<string name="about_description">Το KeePassDX είναι μία εφαρμογή Android του διαχειριστή κωδικών KeePass</string> <string name="about_description">Υλοποίηση του διαχειριστή κωδικών πρόσβασης KeePass για Android.</string>
<string name="accept">Αποδοχή</string> <string name="accept">Αποδοχή</string>
<string name="add_entry">Προσθήκη καταχώρησης</string> <string name="add_entry">Προσθήκη καταχώρησης</string>
<string name="add_group">Προσθήκη ομάδας</string> <string name="add_group">Προσθήκη ομάδας</string>

View File

@@ -21,7 +21,7 @@
--><resources> --><resources>
<string name="feedback">Comentarios</string> <string name="feedback">Comentarios</string>
<string name="homepage">Página de inicio</string> <string name="homepage">Página de inicio</string>
<string name="about_description">Implementación para Android del gestor de contraseñas KeePass</string> <string name="about_description">Implementación para Android del gestor de contraseñas KeePass.</string>
<string name="accept">Aceptar</string> <string name="accept">Aceptar</string>
<string name="add_entry">Añadir apunte</string> <string name="add_entry">Añadir apunte</string>
<string name="add_group">Añadir grupo</string> <string name="add_group">Añadir grupo</string>
@@ -691,4 +691,5 @@
<string name="generate_keyfile">Generar archivo de claves</string> <string name="generate_keyfile">Generar archivo de claves</string>
<string name="recursive_number_entries_title">Número recursivo de entradas</string> <string name="recursive_number_entries_title">Número recursivo de entradas</string>
<string name="hide_templates_summary">Las plantillas no se muestran</string> <string name="hide_templates_summary">Las plantillas no se muestran</string>
<string name="error_otp_secret_length">La clave secreta debe tener al menos %1$d caracteres.</string>
</resources> </resources>

View File

@@ -75,7 +75,7 @@
<string name="content_description_update_from_list">I-update</string> <string name="content_description_update_from_list">I-update</string>
<string name="content_description_keyboard_close_fields">Isara ang mga field</string> <string name="content_description_keyboard_close_fields">Isara ang mga field</string>
<string name="select_to_copy">Piliin para kopyahin ang %1$s sa clipboard</string> <string name="select_to_copy">Piliin para kopyahin ang %1$s sa clipboard</string>
<string name="html_about_licence">KeePassDX © %1$d Ang Kunzisoft ay &lt;strong&gt;open source&lt;/strong&gt; at &lt;strong&gt;walang advertising&lt;/strong&gt;. \nIbinigay ito nang as is, sa ilalim &lt;strong&gt;GPLv3&lt;/strong&gt; na lisensya, nang walang anumang warranty.</string> <string name="html_about_licence">Ang KeePassDX © Kunzisoft ay open source at walang kasamang patalastas.\nIbinibigay ito nang buo sa ilalim ng lisensiyang GPLv3, nang walang anumang garantiya.</string>
<string name="html_about_privacy">&lt;strong&gt;Walang user data ay kinukuha&lt;/strong&gt;, ang aplikasyon na ito ay hindi kumokonekta sa anumang server, gumanagana ng lokal at ganap na ginagalang ang pagkapribado ng mga gumagamit.</string> <string name="html_about_privacy">&lt;strong&gt;Walang user data ay kinukuha&lt;/strong&gt;, ang aplikasyon na ito ay hindi kumokonekta sa anumang server, gumanagana ng lokal at ganap na ginagalang ang pagkapribado ng mga gumagamit.</string>
<string name="html_about_contribution">Para &lt;strong&gt;panatilihin ang aming kalayaan&lt;/strong&gt;, &lt;strong&gt;ayusin ang mga bug&lt;/strong&gt;, &lt;strong&gt;magdagdag ng mga feature&lt;/strong&gt; at &lt;strong&gt;maging palaging aktibo&lt;/strong&gt;, umaasa kami sa iyong &lt;strong&gt;kontribusyon&lt;/strong&gt;.</string> <string name="html_about_contribution">Para &lt;strong&gt;panatilihin ang aming kalayaan&lt;/strong&gt;, &lt;strong&gt;ayusin ang mga bug&lt;/strong&gt;, &lt;strong&gt;magdagdag ng mga feature&lt;/strong&gt; at &lt;strong&gt;maging palaging aktibo&lt;/strong&gt;, umaasa kami sa iyong &lt;strong&gt;kontribusyon&lt;/strong&gt;.</string>
<string name="entry_accessed">Na-access</string> <string name="entry_accessed">Na-access</string>

View File

@@ -383,7 +383,7 @@
<string name="education_lock_summary">Zaključaj bazu podataka brzo, aplikaciju možeš postaviti tako da bazu nakon nekog vremena zaključa i kad se ekran isključi.</string> <string name="education_lock_summary">Zaključaj bazu podataka brzo, aplikaciju možeš postaviti tako da bazu nakon nekog vremena zaključa i kad se ekran isključi.</string>
<string name="show_recent_files_summary">Prikaži mjesto nedavnih baza podataka</string> <string name="show_recent_files_summary">Prikaži mjesto nedavnih baza podataka</string>
<string name="education_device_unlock_summary">Za brzo otključavanje baze podataka, poveži lozinku sa skeniranom biometrijom ili podacima za prijavu uređaja.</string> <string name="education_device_unlock_summary">Za brzo otključavanje baze podataka, poveži lozinku sa skeniranom biometrijom ili podacima za prijavu uređaja.</string>
<string name="html_text_donation">&lt;strong&gt;Doprinosom&lt;/strong&gt; projektu &lt;i&gt;(novčano, kodom, prijevodom)&lt;/i&gt; pomažeš mu da živi i napreduje, a također stječeš pravo na postupak otključavanja &lt;strong&gt;tema&lt;/strong&gt;.&lt;/strong&gt;</string> <string name="html_text_donation">&lt;strong&gt;Doprinosom&lt;/strong&gt; projektu &lt;i&gt;(novčano, kodom, prijevodom)&lt;/i&gt; pomažeš mu da živi i napreduje, a također stječeš pravo na postupak otključavanja &lt;strong&gt;tema&lt;/strong&gt;.</string>
<string name="kdf_explanation">Za stvaranje ključa za algoritam šifriranja, glavni ključ se transformira pomoću funkcije za generiranje ključeva koja sadrži slučajnu komponentu.</string> <string name="kdf_explanation">Za stvaranje ključa za algoritam šifriranja, glavni ključ se transformira pomoću funkcije za generiranje ključeva koja sadrži slučajnu komponentu.</string>
<string name="lock_database_back_root_summary">Zaključaj bazu podataka kad korisnik pritisne gumb za natrag na glavnom ekranu</string> <string name="lock_database_back_root_summary">Zaključaj bazu podataka kad korisnik pritisne gumb za natrag na glavnom ekranu</string>
<string name="hide_broken_locations_title">Sakrij pokvarene poveznice baze podataka</string> <string name="hide_broken_locations_title">Sakrij pokvarene poveznice baze podataka</string>

View File

@@ -20,7 +20,7 @@
--><resources> --><resources>
<string name="feedback">משוב</string> <string name="feedback">משוב</string>
<string name="homepage">דף הבית</string> <string name="homepage">דף הבית</string>
<string name="about_description">מימוש אנדרואיד של מנהל הסיסמאות KeePass</string> <string name="about_description">מימוש אנדרואיד של מנהל הסיסמאות KeePass.</string>
<string name="accept">קבל</string> <string name="accept">קבל</string>
<string name="add_entry">הוסף ערך</string> <string name="add_entry">הוסף ערך</string>
<string name="add_group">הוסף קבוצה</string> <string name="add_group">הוסף קבוצה</string>

View File

@@ -24,12 +24,12 @@
<string name="add_entry">Dodaj wpis</string> <string name="add_entry">Dodaj wpis</string>
<string name="add_group">Dodaj grupę</string> <string name="add_group">Dodaj grupę</string>
<string name="encryption_algorithm">Algorytm szyfrowania</string> <string name="encryption_algorithm">Algorytm szyfrowania</string>
<string name="app_timeout">Koniec czasu</string> <string name="app_timeout">Limit czasu</string>
<string name="app_timeout_summary">Czas bezczynności przed zablokowaniem bazy danych</string> <string name="app_timeout_summary">Czas bezczynności przed zablokowaniem bazy danych</string>
<string name="application">Aplikacja</string> <string name="application">Aplikacja</string>
<string name="menu_app_settings">Ustawienia ogólne</string> <string name="menu_app_settings">Ustawienia ogólne</string>
<string name="brackets">Nawiasy</string> <string name="brackets">Nawiasy</string>
<string name="file_manager_install_description">Do tworzenia, otwierania i zapisywania plików bazy danych potrzebny jest menedżer plików, który akceptuje działanie Intent Action ACTION_CREATE_DOCUMENT i ACTION_OPEN_DOCUMENT.</string> <string name="file_manager_install_description">Do tworzenia, otwierania i zapisywania plików bazy danych wymagany jest menedżer plików akceptujący zamierzone działania ACTION_CREATE_DOCUMENT i ACTION_OPEN_DOCUMENT.</string>
<string name="clipboard_cleared">Schowek został wyczyszczony</string> <string name="clipboard_cleared">Schowek został wyczyszczony</string>
<string name="clipboard_timeout">Czas wygaśnięcia schowka</string> <string name="clipboard_timeout">Czas wygaśnięcia schowka</string>
<string name="clipboard_timeout_summary">Czas przechowywania w schowku (jeśli jest obsługiwany przez urządzenie)</string> <string name="clipboard_timeout_summary">Czas przechowywania w schowku (jeśli jest obsługiwany przez urządzenie)</string>
@@ -60,11 +60,11 @@
<string name="error_invalid_path">Upewnij się, że ścieżka jest prawidłowa.</string> <string name="error_invalid_path">Upewnij się, że ścieżka jest prawidłowa.</string>
<string name="error_no_name">Wpisz nazwę.</string> <string name="error_no_name">Wpisz nazwę.</string>
<string name="error_nokeyfile">Wybierz plik klucza.</string> <string name="error_nokeyfile">Wybierz plik klucza.</string>
<string name="error_out_of_memory">W urządzeniu zabrakło pamięci do załadowania całej bazy danych.</string> <string name="error_out_of_memory">Brak pamięci na załadowanie całej bazy danych.</string>
<string name="error_pass_gen_type">Należy wybrać co najmniej jeden rodzaj generowania hasła.</string> <string name="error_pass_gen_type">Należy wybrać co najmniej jeden rodzaj generowania hasła.</string>
<string name="error_pass_match">Hasła nie pasują do siebie.</string> <string name="error_pass_match">Hasła nie pasują do siebie.</string>
<string name="error_rounds_too_large">\"Rundy szyfrowania\" są zbyt wysokie. Ustaw na 2147483648.</string> <string name="error_rounds_too_large">Rundy transformacji” są zbyt wysokie. Ustaw na 2147483648.</string>
<string name="error_wrong_length">Wprowadź dodatnią liczbę całkowitą w polu \"Długość\".</string> <string name="error_wrong_length">Wprowadź dodatnią liczbę całkowitą w polu Długość.</string>
<string name="file_browser">Menedżer plików</string> <string name="file_browser">Menedżer plików</string>
<string name="generate_password">Generuj hasło</string> <string name="generate_password">Generuj hasło</string>
<string name="hint_conf_pass">Potwierdź hasło</string> <string name="hint_conf_pass">Potwierdź hasło</string>
@@ -77,8 +77,8 @@
<string name="invalid_credentials">Nie można odczytać uwierzytelnień.</string> <string name="invalid_credentials">Nie można odczytać uwierzytelnień.</string>
<string name="invalid_db_sig">Nie można rozpoznać formatu bazy danych.</string> <string name="invalid_db_sig">Nie można rozpoznać formatu bazy danych.</string>
<string name="length">Długość</string> <string name="length">Długość</string>
<string name="list_size_title">Wielkość listy grup</string> <string name="list_size_title">Rozmiar elementów listy</string>
<string name="list_size_summary">Wielkość tekstu w liście grup</string> <string name="list_size_summary">Rozmiar tekstu na liście elementów</string>
<string name="loading_database">Wczytywanie bazy danych…</string> <string name="loading_database">Wczytywanie bazy danych…</string>
<string name="lowercase">Małe litery</string> <string name="lowercase">Małe litery</string>
<string name="hide_password_title">Ukryj hasła</string> <string name="hide_password_title">Ukryj hasła</string>
@@ -103,7 +103,7 @@
<string name="progress_create">Tworzenie nowej bazy danych…</string> <string name="progress_create">Tworzenie nowej bazy danych…</string>
<string name="progress_title">Pracuję…</string> <string name="progress_title">Pracuję…</string>
<string name="content_description_remove_from_list">Usuń</string> <string name="content_description_remove_from_list">Usuń</string>
<string name="root">Root</string> <string name="root">Główny</string>
<string name="rounds">Rundy szyfrowania</string> <string name="rounds">Rundy szyfrowania</string>
<string name="rounds_explanation">Dodatkowe rundy szyfrowania zapewniają lepszą ochronę przed atakami typu brute force, ale mogą znacznie spowolnić ładowanie i zapisywanie.</string> <string name="rounds_explanation">Dodatkowe rundy szyfrowania zapewniają lepszą ochronę przed atakami typu brute force, ale mogą znacznie spowolnić ładowanie i zapisywanie.</string>
<string name="saving_database">Zapisywanie bazy danych…</string> <string name="saving_database">Zapisywanie bazy danych…</string>
@@ -133,7 +133,7 @@
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft jest &lt;strong&gt;open source&lt;/strong&gt; i &lt;strong&gt;bez reklam&lt;/strong&gt;. \nJest on dostarczany w stanie, zgodnie z licencją &lt;strong&gt;GPLv3&lt;/strong&gt; bez żadnych gwarancji.</string> <string name="html_about_licence">KeePassDX © %1$d Kunzisoft jest &lt;strong&gt;open source&lt;/strong&gt; i &lt;strong&gt;bez reklam&lt;/strong&gt;. \nJest on dostarczany w stanie, zgodnie z licencją &lt;strong&gt;GPLv3&lt;/strong&gt; bez żadnych gwarancji.</string>
<string name="entry_not_found">Nie znaleziono danych wejściowych.</string> <string name="entry_not_found">Nie znaleziono danych wejściowych.</string>
<string name="error_load_database">Nie można załadować bazy danych.</string> <string name="error_load_database">Nie można załadować bazy danych.</string>
<string name="error_load_database_KDF_memory">Nie można załadować klucza. Spróbuj zmniejszyć użycie pamięć KDF.</string> <string name="error_load_database_KDF_memory">Nie można załadować klucza. Spróbuj zmniejszyć „Użycie pamięci” KDF.</string>
<string name="error_string_key">Każdy ciąg musi mieć nazwę pola.</string> <string name="error_string_key">Każdy ciąg musi mieć nazwę pola.</string>
<string name="error_autofill_enable_service">Nie można włączyć usługi autouzupełniania.</string> <string name="error_autofill_enable_service">Nie można włączyć usługi autouzupełniania.</string>
<string name="field_name">Nazwa pola</string> <string name="field_name">Nazwa pola</string>
@@ -149,8 +149,8 @@
<string name="menu_move">Przenieś</string> <string name="menu_move">Przenieś</string>
<string name="menu_paste">Wklej</string> <string name="menu_paste">Wklej</string>
<string name="menu_cancel">Anuluj</string> <string name="menu_cancel">Anuluj</string>
<string name="menu_file_selection_read_only">Chroniony przed zapisem</string> <string name="menu_file_selection_read_only">Ochrona przed zapisem</string>
<string name="menu_open_file_read_and_write">Modyfikowalne</string> <string name="menu_open_file_read_and_write">Modyfikowalny</string>
<string name="protection">Ochrona</string> <string name="protection">Ochrona</string>
<string name="read_only">Ochrona przed zapisem</string> <string name="read_only">Ochrona przed zapisem</string>
<string name="read_only_warning">KeePassDX potrzebuje uprawnień do zapisu, aby mógł modyfikować bazę danych.</string> <string name="read_only_warning">KeePassDX potrzebuje uprawnień do zapisu, aby mógł modyfikować bazę danych.</string>
@@ -208,12 +208,12 @@
<string name="assign_master_key">Przypisz klucz główny</string> <string name="assign_master_key">Przypisz klucz główny</string>
<string name="create_keepass_file">Utwórz nowy sejf</string> <string name="create_keepass_file">Utwórz nowy sejf</string>
<string name="recycle_bin_title">Wykorzystanie kosza</string> <string name="recycle_bin_title">Wykorzystanie kosza</string>
<string name="recycle_bin_summary">Przenosi grupy i wpisy do grupy \"Kosz\" przed usunięciem</string> <string name="recycle_bin_summary">Przenosi grupy i wpisy do grupy Kosz przed usunięciem</string>
<string name="monospace_font_fields_enable_title">Czcionka pola</string> <string name="monospace_font_fields_enable_title">Czcionka pola</string>
<string name="monospace_font_fields_enable_summary">Zmień czcionkę użytą w polach, aby poprawić widoczność znaków</string> <string name="monospace_font_fields_enable_summary">Zmień czcionkę użytą w polach, aby poprawić widoczność znaków</string>
<string name="allow_copy_password_title">Ochrona schowka</string> <string name="allow_copy_password_title">Ochrona schowka</string>
<string name="allow_copy_password_summary">Zezwalanie na kopiowanie hasła wejściowego i chronionych pól do schowka</string> <string name="allow_copy_password_summary">Zezwalanie na kopiowanie hasła wejściowego i chronionych pól do schowka</string>
<string name="allow_copy_password_warning">Ostrzeżenie: Schowek jest współużytkowany przez wszystkie aplikacje. Jeśli poufne dane są kopiowane, inne oprogramowanie może je odzyskać.</string> <string name="allow_copy_password_warning">Ostrzeżenie: schowek jest współużytkowany przez wszystkie aplikacje. Jeśli poufne dane są kopiowane, inne oprogramowanie może je odzyskać.</string>
<string name="database_name_title">Nazwa bazy danych</string> <string name="database_name_title">Nazwa bazy danych</string>
<string name="database_description_title">Opis bazy danych</string> <string name="database_description_title">Opis bazy danych</string>
<string name="database_version_title">Wersja bazy danych</string> <string name="database_version_title">Wersja bazy danych</string>
@@ -224,7 +224,7 @@
<string name="magic_keyboard_title">Magikeyboard</string> <string name="magic_keyboard_title">Magikeyboard</string>
<string name="magic_keyboard_explanation_summary">Aktywuj niestandardową klawiaturę wypełniającą hasła i wszystkie pola tożsamości</string> <string name="magic_keyboard_explanation_summary">Aktywuj niestandardową klawiaturę wypełniającą hasła i wszystkie pola tożsamości</string>
<string name="allow_no_password_title">Zezwalaj na brak klucza głównego</string> <string name="allow_no_password_title">Zezwalaj na brak klucza głównego</string>
<string name="allow_no_password_summary">Umożliwia naciśnięcie przycisku \"Otwórz\", jeśli nie wybrano żadnych poświadczeń</string> <string name="allow_no_password_summary">Umożliwia naciśnięcie przycisku Otwórz, jeśli nie wybrano żadnych poświadczeń</string>
<string name="enable_education_screens_title">Wskazówki edukacyjne</string> <string name="enable_education_screens_title">Wskazówki edukacyjne</string>
<string name="enable_education_screens_summary">Podświetl elementy, aby dowiedzieć się, jak działa aplikacja</string> <string name="enable_education_screens_summary">Podświetl elementy, aby dowiedzieć się, jak działa aplikacja</string>
<string name="reset_education_screens_title">Zresetuj wskazówki edukacyjne</string> <string name="reset_education_screens_title">Zresetuj wskazówki edukacyjne</string>
@@ -248,10 +248,7 @@
<string name="education_entry_new_field_summary">Zarejestruj dodatkowe pole, dodaj wartość i opcjonalnie chroń je.</string> <string name="education_entry_new_field_summary">Zarejestruj dodatkowe pole, dodaj wartość i opcjonalnie chroń je.</string>
<string name="education_unlock_title">Odblokuj swoją bazę danych</string> <string name="education_unlock_title">Odblokuj swoją bazę danych</string>
<string name="education_read_only_title">Zapisz ochronę swojej bazy danych</string> <string name="education_read_only_title">Zapisz ochronę swojej bazy danych</string>
<string name="education_read_only_summary">Zmień tryb otwierania sesji. <string name="education_read_only_summary">Zmień tryb otwierania sesji. \n \n„Ochrona przed zapisem” zapobiega niezamierzonym zmianom w bazie danych. \n„Modyfikowalny” pozwala dodawać, usuwać lub modyfikować wszystkie elementy według uznania.</string>
\n
\n\"Ochrona przed zapisem\" zapobiega niezamierzonych zmian w bazie danych.
\n\"Modyfikowalne\" pozwala dodawać, usuwać lub modyfikować wszystkie elementy, jak chcesz.</string>
<string name="education_field_copy_title">Skopiuj pole</string> <string name="education_field_copy_title">Skopiuj pole</string>
<string name="education_field_copy_summary">Skopiowane pola można wkleić w dowolnym miejscu. <string name="education_field_copy_summary">Skopiowane pola można wkleić w dowolnym miejscu.
\n \n
@@ -295,17 +292,17 @@
<string name="keyboard_notification_entry_clear_close_summary">Zamknij bazę danych podczas zamykania powiadomienia</string> <string name="keyboard_notification_entry_clear_close_summary">Zamknij bazę danych podczas zamykania powiadomienia</string>
<string name="keyboard_appearance_category">Wygląd</string> <string name="keyboard_appearance_category">Wygląd</string>
<string name="keyboard_theme_title">Motyw klawiatury</string> <string name="keyboard_theme_title">Motyw klawiatury</string>
<string name="keyboard_keys_category">Klawiatura</string> <string name="keyboard_keys_category">Klawisze</string>
<string name="keyboard_key_vibrate_title">Wibracja po naciśnięciu klawisza</string> <string name="keyboard_key_vibrate_title">Wibracje przy naciskaniu klawiszy</string>
<string name="keyboard_key_sound_title">Dźwięk przy naciśnięciu</string> <string name="keyboard_key_sound_title">Dźwięk przy naciskaniu klawiszy</string>
<string name="do_not_kill_app">Nie zabijaj aplikacji…</string> <string name="do_not_kill_app">Nie zamykaj aplikacji…</string>
<string name="lock_database_back_root_title">Wciśnij \'Powrót\', aby zablokować</string> <string name="lock_database_back_root_title">Naciśnij „Wstecz”, aby zablokować</string>
<string name="lock_database_back_root_summary">Zablokuj bazę danych, gdy użytkownik kliknie przycisk \"Wstecz\" na ekranie głównym</string> <string name="lock_database_back_root_summary">Zablokuj bazę danych, gdy użytkownik kliknie przycisk Wstecz na ekranie głównym</string>
<string name="clear_clipboard_notification_title">Wyczyść po zamknięciu</string> <string name="clear_clipboard_notification_title">Wyczyść po zamknięciu</string>
<string name="clear_clipboard_notification_summary">Blokowanie bazy danych po wygaśnięciu czasu trwania schowka lub zamknięciu powiadomienia po rozpoczęciu korzystania z niej</string> <string name="clear_clipboard_notification_summary">Blokowanie bazy danych po wygaśnięciu czasu trwania schowka lub zamknięciu powiadomienia po rozpoczęciu korzystania z niej</string>
<string name="recycle_bin">Kosz</string> <string name="recycle_bin">Kosz</string>
<string name="keyboard_selection_entry_title">Wybór wpisu</string> <string name="keyboard_selection_entry_title">Wybór wpisu</string>
<string name="keyboard_selection_entry_summary">Podczas przeglądania wpisu w KeePassDX zapełnij Magikeyboard tym wpisem</string> <string name="keyboard_selection_entry_summary">Podczas przeglądania wpisu w KeePassDX zapełnij Magikeyboard tym wpisem</string>
<string name="delete_entered_password_title">Usuń hasło</string> <string name="delete_entered_password_title">Usuń hasło</string>
<string name="delete_entered_password_summary">Usuwa hasło wprowadzone po próbie połączenia z bazą danych</string> <string name="delete_entered_password_summary">Usuwa hasło wprowadzone po próbie połączenia z bazą danych</string>
<string name="content_description_open_file">Otwórz plik</string> <string name="content_description_open_file">Otwórz plik</string>
@@ -367,7 +364,7 @@
<string name="compression_none">Żadna</string> <string name="compression_none">Żadna</string>
<string name="compression_gzip">Gzip</string> <string name="compression_gzip">Gzip</string>
<string name="device_keyboard_setting_title">Ustawienia klawiatury urządzenia</string> <string name="device_keyboard_setting_title">Ustawienia klawiatury urządzenia</string>
<string name="error_invalid_OTP">Nieprawidłowy klucz OTP.</string> <string name="error_invalid_OTP">Nieprawidłowy klucz tajny OTP.</string>
<string name="error_disallow_no_credentials">Należy ustawić co najmniej jedno poświadczenie.</string> <string name="error_disallow_no_credentials">Należy ustawić co najmniej jedno poświadczenie.</string>
<string name="error_otp_secret_key">Klucz tajny musi być w formacie Base32.</string> <string name="error_otp_secret_key">Klucz tajny musi być w formacie Base32.</string>
<string name="error_otp_counter">Licznik musi być między %1$d a %2$d.</string> <string name="error_otp_counter">Licznik musi być między %1$d a %2$d.</string>
@@ -391,11 +388,11 @@
<string name="keystore_not_accessible">Magazyn kluczy nie został poprawnie zainicjowany.</string> <string name="keystore_not_accessible">Magazyn kluczy nie został poprawnie zainicjowany.</string>
<string name="recycle_bin_group_title">Kosz grupy</string> <string name="recycle_bin_group_title">Kosz grupy</string>
<string name="enable_auto_save_database_title">Automatycznie zapisuj bazę danych</string> <string name="enable_auto_save_database_title">Automatycznie zapisuj bazę danych</string>
<string name="enable_auto_save_database_summary">Zapisz bazę danych po każdym ważnym działaniu (w trybie „Modyfikowalnym”)</string> <string name="enable_auto_save_database_summary">Zapisz bazę danych po każdym ważnym działaniu (w trybie „Modyfikowalny”)</string>
<string name="entry_attachments">Załączniki</string> <string name="entry_attachments">Załączniki</string>
<string name="menu_restore_entry_history">Przywróć historię</string> <string name="menu_restore_entry_history">Przywróć historię</string>
<string name="menu_delete_entry_history">Usuń historię</string> <string name="menu_delete_entry_history">Usuń historię</string>
<string name="keyboard_auto_go_action_title">Automatyczne działanie klucza</string> <string name="keyboard_auto_go_action_title">Automatyczna akcja klawiszy</string>
<string name="keyboard_auto_go_action_summary">Akcja klawisza „Idź” po naciśnięciu klawisza „Pole”</string> <string name="keyboard_auto_go_action_summary">Akcja klawisza „Idź” po naciśnięciu klawisza „Pole”</string>
<string name="download_attachment">Pobierz %1$s</string> <string name="download_attachment">Pobierz %1$s</string>
<string name="download_initialization">Inicjowanie…</string> <string name="download_initialization">Inicjowanie…</string>
@@ -428,7 +425,7 @@
<string name="lock_database_show_button_summary">Wyświetla przycisk blokady w interfejsie użytkownika</string> <string name="lock_database_show_button_summary">Wyświetla przycisk blokady w interfejsie użytkownika</string>
<string name="lock_database_show_button_title">Pokaż przycisk blokady</string> <string name="lock_database_show_button_title">Pokaż przycisk blokady</string>
<string name="autofill_preference_title">Ustawienia autouzupełniania</string> <string name="autofill_preference_title">Ustawienia autouzupełniania</string>
<string name="warning_database_link_revoked">Dostęp do pliku anulowany przez menedżera plików</string> <string name="warning_database_link_revoked">Dostęp do pliku anulowany przez menedżer plików</string>
<string name="error_label_exists">Ta etykieta już istnieje.</string> <string name="error_label_exists">Ta etykieta już istnieje.</string>
<string name="autofill_block_restart">Zrestartuj aplikację zawierającą formularz, aby aktywować blokadę.</string> <string name="autofill_block_restart">Zrestartuj aplikację zawierającą formularz, aby aktywować blokadę.</string>
<string name="autofill_block">Blokowanie autouzupełniania</string> <string name="autofill_block">Blokowanie autouzupełniania</string>
@@ -441,9 +438,9 @@
<string name="autofill_web_domain_blocklist_summary">Lista zablokowanych, która uniemożliwia automatyczne wypełnianie domen internetowych</string> <string name="autofill_web_domain_blocklist_summary">Lista zablokowanych, która uniemożliwia automatyczne wypełnianie domen internetowych</string>
<string name="autofill_web_domain_blocklist_title">Lista zablokowanych domen internetowych</string> <string name="autofill_web_domain_blocklist_title">Lista zablokowanych domen internetowych</string>
<string name="autofill_application_id_blocklist_title">Lista zablokowanych aplikacji</string> <string name="autofill_application_id_blocklist_title">Lista zablokowanych aplikacji</string>
<string name="keyboard_previous_fill_in_summary">Automatycznie przełącz się z powrotem na poprzednią klawiaturę po wykonaniu automatycznej akcji klawiszy</string> <string name="keyboard_previous_fill_in_summary">Automatycznie przełącz z powrotem do poprzedniej klawiatury po wykonaniu automatycznej akcji klawiszy</string>
<string name="keyboard_previous_fill_in_title">Przełącz się z powrotem</string> <string name="keyboard_previous_fill_in_title">Przełącz z powrotem</string>
<string name="keyboard_previous_database_credentials_summary">Automatycznie przełącz się z powrotem do poprzedniej klawiatury na ekranie poświadczeń bazy danych</string> <string name="keyboard_previous_database_credentials_summary">Automatycznie przełącz z powrotem do poprzedniej klawiatury na ekranie poświadczeń bazy danych</string>
<string name="keyboard_previous_database_credentials_title">Ekran poświadczeń bazy danych</string> <string name="keyboard_previous_database_credentials_title">Ekran poświadczeń bazy danych</string>
<string name="keyboard_change">Przełącz klawiaturę</string> <string name="keyboard_change">Przełącz klawiaturę</string>
<string name="upload_attachment">Prześlij %1$s</string> <string name="upload_attachment">Prześlij %1$s</string>
@@ -451,9 +448,7 @@
<string name="education_add_attachment_title">Dodaj załącznik</string> <string name="education_add_attachment_title">Dodaj załącznik</string>
<string name="warning_sure_add_file">Czy mimo to dodać plik\?</string> <string name="warning_sure_add_file">Czy mimo to dodać plik\?</string>
<string name="warning_replace_file">Przesłanie tego pliku spowoduje zastąpienie istniejącego.</string> <string name="warning_replace_file">Przesłanie tego pliku spowoduje zastąpienie istniejącego.</string>
<string name="warning_file_too_big">Baza danych KeePass powinna zawierać tylko małe pliki narzędziowe (takie jak pliki kluczy PGP). <string name="warning_file_too_big">Baza danych KeePass powinna zawierać tylko małe pliki narzędziowe (takie jak pliki kluczy PGP). \n \nTwoja baza danych może stać się bardzo duża i obniżyć wydajność w wyniku tego przesyłania.</string>
\n
\nTwoja baza danych może stać się bardzo duża i zmniejszyć wydajność dzięki temu wgrywaniu danych.</string>
<string name="database_data_remove_unlinked_attachments_summary">Usuwa załączniki znajdujące się w bazie danych, ale niepowiązane z danym wpisem</string> <string name="database_data_remove_unlinked_attachments_summary">Usuwa załączniki znajdujące się w bazie danych, ale niepowiązane z danym wpisem</string>
<string name="database_data_remove_unlinked_attachments_title">Usuń niepołączone dane</string> <string name="database_data_remove_unlinked_attachments_title">Usuń niepołączone dane</string>
<string name="data">Dane</string> <string name="data">Dane</string>
@@ -471,7 +466,7 @@
<string name="autofill_save_search_info_title">Zapisz informacje wyszukiwania</string> <string name="autofill_save_search_info_title">Zapisz informacje wyszukiwania</string>
<string name="autofill_close_database_summary">Zamknij bazę danych po wybraniu autouzupełniania</string> <string name="autofill_close_database_summary">Zamknij bazę danych po wybraniu autouzupełniania</string>
<string name="autofill_close_database_title">Zamknij bazę danych</string> <string name="autofill_close_database_title">Zamknij bazę danych</string>
<string name="keyboard_previous_lock_summary">Automatycznie przełącz się z powrotem do poprzedniej klawiatury po zablokowaniu bazy danych</string> <string name="keyboard_previous_lock_summary">Automatycznie przełącz z powrotem do poprzedniej klawiatury po zablokowaniu bazy danych</string>
<string name="keyboard_previous_lock_title">Zablokuj bazę danych</string> <string name="keyboard_previous_lock_title">Zablokuj bazę danych</string>
<string name="keyboard_save_search_info_summary">Staraj się zapisywać udostępnione informacje podczas dokonywania ręcznego wyboru wpisu, aby ułatwić sobie przyszłe użycie</string> <string name="keyboard_save_search_info_summary">Staraj się zapisywać udostępnione informacje podczas dokonywania ręcznego wyboru wpisu, aby ułatwić sobie przyszłe użycie</string>
<string name="keyboard_save_search_info_title">Zapisz udostępnione informacje</string> <string name="keyboard_save_search_info_title">Zapisz udostępnione informacje</string>
@@ -618,17 +613,13 @@
<string name="menu_save_copy_to">Zapisz kopię w …</string> <string name="menu_save_copy_to">Zapisz kopię w …</string>
<string name="expired">Wygasłe</string> <string name="expired">Wygasłe</string>
<string name="warning_database_already_opened">Baza danych jest już otwarta, należy ją najpierw zamknąć, aby otworzyć nową</string> <string name="warning_database_already_opened">Baza danych jest już otwarta, należy ją najpierw zamknąć, aby otworzyć nową</string>
<string name="device_unlock_keystore_warning">Ta funkcja umożliwia przechowywanie zaszyfrowanych danych uwierzytelniających w bezpiecznym magazynie kluczy urządzenia. <string name="device_unlock_keystore_warning">Ta funkcja umożliwia przechowywanie zaszyfrowanych danych uwierzytelniających w bezpiecznym magazynie kluczy urządzenia. \n \nMoże nie być w pełni funkcjonalna w zależności od konkretnej implementacji interfejsu API systemu operacyjnego. \n \nSprawdź kompatybilność i bezpieczeństwo magazynu kluczy u producenta urządzenia i twórcy używanego ROM-u.</string>
\n
\nW zależności od konkretnej implementacji interfejsu API systemu operacyjnego, może nie być w pełni funkcjonalna.
\n
\nSprawdź kompatybilność i bezpieczeństwo magazynu kluczy u producenta urządzenia i twórcy używanego ROM-u.</string>
<string name="passphrase">Fraza hasła</string> <string name="passphrase">Fraza hasła</string>
<string name="colorize_password_summary">Koloruj znaki hasła według typu</string> <string name="colorize_password_summary">Koloruj znaki hasła według typu</string>
<string name="keyboard_previous_search_title">Ekran wyszukiwania</string> <string name="keyboard_previous_search_title">Ekran wyszukiwania</string>
<string name="entropy">Entropia: %1$s bitowa</string> <string name="entropy">Entropia: %1$s bitowa</string>
<string name="entropy_high">Entropia: Wysoka</string> <string name="entropy_high">Entropia: wysoka</string>
<string name="entropy_calculate">Entropia: Oblicz…</string> <string name="entropy_calculate">Entropia: oblicz…</string>
<string name="at_least_one_char">Co najmniej po jednym znaku z każdego</string> <string name="at_least_one_char">Co najmniej po jednym znaku z każdego</string>
<string name="exclude_ambiguous_chars">Wyklucz niejednoznaczne znaki</string> <string name="exclude_ambiguous_chars">Wyklucz niejednoznaczne znaki</string>
<string name="consider_chars_filter">Rozważ znaki</string> <string name="consider_chars_filter">Rozważ znaki</string>
@@ -640,7 +631,7 @@
<string name="content_description_passphrase_word_count">Liczba słów frazy hasła</string> <string name="content_description_passphrase_word_count">Liczba słów frazy hasła</string>
<string name="ignore_chars_filter">Ignoruj znaki</string> <string name="ignore_chars_filter">Ignoruj znaki</string>
<string name="colorize_password_title">Koloruj hasła</string> <string name="colorize_password_title">Koloruj hasła</string>
<string name="keyboard_previous_search_summary">Automatycznie przełączaj z powrotem do poprzedniej klawiatury na ekranie wyszukiwania</string> <string name="keyboard_previous_search_summary">Automatycznie przełącz z powrotem do poprzedniej klawiatury na ekranie wyszukiwania</string>
<string name="waiting_challenge_request">Oczekiwanie na żądanie wyzwania…</string> <string name="waiting_challenge_request">Oczekiwanie na żądanie wyzwania…</string>
<string name="waiting_challenge_response">Oczekiwanie na odpowiedź na wyzwanie…</string> <string name="waiting_challenge_response">Oczekiwanie na odpowiedź na wyzwanie…</string>
<string name="error_challenge_already_requested">Wyzwanie już zażądane.</string> <string name="error_challenge_already_requested">Wyzwanie już zażądane.</string>
@@ -700,7 +691,7 @@
<string name="nodes">Węzły</string> <string name="nodes">Węzły</string>
<string name="warning_large_keyfile">Nie zaleca się dodawania dużego pliku klucza, ponieważ może to uniemożliwić otwarcie bazy danych.</string> <string name="warning_large_keyfile">Nie zaleca się dodawania dużego pliku klucza, ponieważ może to uniemożliwić otwarcie bazy danych.</string>
<string name="generate_keyfile">Wygeneruj plik klucza</string> <string name="generate_keyfile">Wygeneruj plik klucza</string>
<string name="recursive_number_entries_summary">Rekurencyjnie oblicza liczbę wpisów w grupie</string> <string name="recursive_number_entries_summary">Rekurencyjnie oblicza liczbę wpisów w grupie</string>
<string name="recursive_number_entries_title">Rekurencyjna liczba wpisów</string> <string name="recursive_number_entries_title">Rekurencyjna liczba wpisów</string>
<string name="hide_templates_title">Ukryj szablony</string> <string name="hide_templates_title">Ukryj szablony</string>
<string name="hide_templates_summary">Szablony nie są wyświetlane</string> <string name="hide_templates_summary">Szablony nie są wyświetlane</string>

View File

@@ -19,7 +19,7 @@
--><resources> --><resources>
<string name="feedback">Geri bildirim</string> <string name="feedback">Geri bildirim</string>
<string name="homepage">Ana Sayfa</string> <string name="homepage">Ana Sayfa</string>
<string name="about_description">KeePass Parola Yöneticisi\'nin Android uygulama uyarlaması</string> <string name="about_description">KeePass Parola Yöneticisi\'nin Android uygulama uyarlaması.</string>
<string name="accept">Kabul et</string> <string name="accept">Kabul et</string>
<string name="add_entry">Girdi ekle</string> <string name="add_entry">Girdi ekle</string>
<string name="edit_entry">Girdi düzenle</string> <string name="edit_entry">Girdi düzenle</string>

View File

@@ -14,7 +14,7 @@
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>. along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
--><resources> --><resources>
<string name="about">關於</string> <string name="about">關於</string>
<string name="about_description">兼容KeePass密碼管理軟體的Android程式</string> <string name="about_description">兼容KeePass密碼管理軟體的Android程式</string>
<string name="accept">接受</string> <string name="accept">接受</string>
<string name="account">帳戶</string> <string name="account">帳戶</string>
<string name="add_entry">新增項目</string> <string name="add_entry">新增項目</string>
@@ -224,7 +224,7 @@
<string name="encryption_explanation">資料庫所有資料均採用加密演算法</string> <string name="encryption_explanation">資料庫所有資料均採用加密演算法</string>
<string name="enter">輸入</string> <string name="enter">輸入</string>
<string name="entry_UUID">UUID</string> <string name="entry_UUID">UUID</string>
<string name="entry_accessed">存取</string> <string name="entry_accessed">存取時間</string>
<string name="entry_add_attachment">添加附件</string> <string name="entry_add_attachment">添加附件</string>
<string name="entry_add_field">添加欄位</string> <string name="entry_add_field">添加欄位</string>
<string name="entry_attachments">附件</string> <string name="entry_attachments">附件</string>
@@ -643,7 +643,7 @@
<string name="auto_type">自動填入</string> <string name="auto_type">自動填入</string>
<string name="info">資訊</string> <string name="info">資訊</string>
<string name="html_about_privacy">&lt;strong&gt;不收集用戶資料。&lt;/strong&gt;,此應用程式不連接任何伺服器,僅在裝置上運作,而且完全尊重用戶私穩。</string> <string name="html_about_privacy">&lt;strong&gt;不收集用戶資料。&lt;/strong&gt;,此應用程式不連接任何伺服器,僅在裝置上運作,而且完全尊重用戶私穩。</string>
<string name="waiting_challenge_request">正在等待挑戰請求…</string> <string name="waiting_challenge_request">正在等待開發請求…</string>
<string name="waiting_challenge_response">正等待Challenge回應……</string> <string name="waiting_challenge_response">正等待Challenge回應……</string>
<string name="error_XML_malformed">XML格式錯誤。</string> <string name="error_XML_malformed">XML格式錯誤。</string>
<string name="error_challenge_already_requested">已請求Challenge。</string> <string name="error_challenge_already_requested">已請求Challenge。</string>
@@ -665,10 +665,10 @@
<string name="menu_appearance_settings_summary">主題、顏色、屬性</string> <string name="menu_appearance_settings_summary">主題、顏色、屬性</string>
<string name="unlock">解鎖</string> <string name="unlock">解鎖</string>
<string name="at_least_one_char">從每組中選擇字完</string> <string name="at_least_one_char">從每組中選擇字完</string>
<string name="consider_chars_filter">可以包</string> <string name="consider_chars_filter">可以包</string>
<string name="ignore_chars_filter">不要包括</string> <string name="ignore_chars_filter">不要包括</string>
<string name="title_case">標題大小寫</string> <string name="title_case">標題大小寫</string>
<string name="content_description_nav_header">導航列</string> <string name="content_description_nav_header">導航列標題</string>
<string name="education_validate_entry_summary">記得驗證和儲存你的資料庫。 <string name="education_validate_entry_summary">記得驗證和儲存你的資料庫。
\n \n
\n如果自動鎖定已啓用而你又忘記你在更改資料你可能會失去你的資料。</string> \n如果自動鎖定已啓用而你又忘記你在更改資料你可能會失去你的資料。</string>

View File

@@ -413,7 +413,7 @@
<string name="database_history">History</string> <string name="database_history">History</string>
<string name="properties">Properties</string> <string name="properties">Properties</string>
<string name="menu_appearance_settings">Appearance</string> <string name="menu_appearance_settings">Appearance</string>
<string name="menu_appearance_settings_summary">Themes, colors, attributes</string> <string name="menu_appearance_settings_summary">Themes, colors, icons, fonts, attributes</string>
<string name="biometric">Biometric</string> <string name="biometric">Biometric</string>
<string name="device_credential">Device credential</string> <string name="device_credential">Device credential</string>
<string name="general">General</string> <string name="general">General</string>

View File

@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.database.merge
import com.kunzisoft.keepass.database.element.Attachment import com.kunzisoft.keepass.database.element.Attachment
import com.kunzisoft.keepass.database.element.CustomData import com.kunzisoft.keepass.database.element.CustomData
import com.kunzisoft.keepass.database.element.DateInstant import com.kunzisoft.keepass.database.element.DateInstant
import com.kunzisoft.keepass.database.element.DeletedObject
import com.kunzisoft.keepass.database.element.database.DatabaseKDB import com.kunzisoft.keepass.database.element.database.DatabaseKDB
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX import com.kunzisoft.keepass.database.element.database.DatabaseKDBX
import com.kunzisoft.keepass.database.element.entry.EntryKDB import com.kunzisoft.keepass.database.element.entry.EntryKDB
@@ -32,9 +33,10 @@ import com.kunzisoft.keepass.database.element.node.NodeHandler
import com.kunzisoft.keepass.database.element.node.NodeId import com.kunzisoft.keepass.database.element.node.NodeId
import com.kunzisoft.keepass.database.element.node.NodeIdInt import com.kunzisoft.keepass.database.element.node.NodeIdInt
import com.kunzisoft.keepass.database.element.node.NodeIdUUID import com.kunzisoft.keepass.database.element.node.NodeIdUUID
import com.kunzisoft.keepass.database.element.node.NodeVersioned
import com.kunzisoft.keepass.utils.readAllBytes import com.kunzisoft.keepass.utils.readAllBytes
import java.io.IOException import java.io.IOException
import java.util.* import java.util.UUID
class DatabaseKDBXMerger(private var database: DatabaseKDBX) { class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
@@ -180,7 +182,7 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
} }
/** /**
* Merge a KDB> database in a KDBX database, * Merge a KDBX database in a KDBX database,
* Try to take into account the modification date of each element * Try to take into account the modification date of each element
* To make a merge as accurate as possible * To make a merge as accurate as possible
*/ */
@@ -302,32 +304,113 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
} }
// Manage deleted objects // Manage deleted objects
databaseToMerge.deletedObjects.forEach { deletedObject -> val deletedObjects = databaseToMerge.deletedObjects
val deletedObjectId = deletedObject.uuid deletedObjects.forEach { deletedObject ->
val databaseEntry = database.getEntryById(deletedObjectId) deleteEntry(deletedObject)
val databaseGroup = database.getGroupById(deletedObjectId) deleteGroup(deletedObject, deletedObjects)
val databaseIcon = database.iconsManager.getIcon(deletedObjectId) deleteIcon(deletedObject)
val databaseIconModificationTime = databaseIcon?.lastModificationTime
if (databaseEntry != null
&& deletedObject.deletionTime.isAfter(databaseEntry.lastModificationTime)) {
database.removeEntryFrom(databaseEntry, databaseEntry.parent)
}
if (databaseGroup != null
&& deletedObject.deletionTime.isAfter(databaseGroup.lastModificationTime)) {
database.removeGroupFrom(databaseGroup, databaseGroup.parent)
}
if (databaseIcon != null
&& (
databaseIconModificationTime == null
|| (deletedObject.deletionTime.isAfter(databaseIconModificationTime))
)
) {
database.removeCustomIcon(deletedObjectId)
}
// Attachments are removed and optimized during the database save // Attachments are removed and optimized during the database save
} }
} }
/**
* Delete an entry from the database with the [deletedEntry] id
*/
private fun deleteEntry(deletedEntry: DeletedObject) {
val databaseEntry = database.getEntryById(deletedEntry.uuid)
if (databaseEntry != null
&& deletedEntry.deletionTime.isAfter(databaseEntry.lastModificationTime)) {
database.removeEntryFrom(databaseEntry, databaseEntry.parent)
}
}
/**
* Check whether a node is in the list of deleted objects
*/
private fun Set<DeletedObject>.containsNode(node: NodeVersioned<UUID, GroupKDBX, EntryKDBX>): Boolean {
return this.any { it.uuid == node.nodeId.id }
}
/**
* Check whether a node is not in the list of deleted objects
*/
private fun Set<DeletedObject>.notContainsNode(node: NodeVersioned<UUID, GroupKDBX, EntryKDBX>): Boolean {
return !this.containsNode(node)
}
/**
* Get the first parent not deleted
*/
private fun firstNotDeletedParent(
node: NodeVersioned<UUID, GroupKDBX, EntryKDBX>,
deletedObjects: Set<DeletedObject>
): GroupKDBX? {
var parent = node.parent
while (parent != null && deletedObjects.containsNode(parent)) {
parent = node.parent
}
return parent
}
/**
* Delete a group from the database with the [deletedGroup] id
* Recursively check whether a group to be deleted contains a node not to be deleted with [deletedObjects]
* and move it to the first parent that has not been deleted.
*/
private fun deleteGroup(deletedGroup: DeletedObject, deletedObjects: Set<DeletedObject>) {
val databaseGroup = database.getGroupById(deletedGroup.uuid)
if (databaseGroup != null
&& deletedGroup.deletionTime.isAfter(databaseGroup.lastModificationTime)) {
// Must be in dedicated list to prevent modification collision
val entriesToMove = mutableListOf<EntryKDBX>()
databaseGroup.getChildEntries().forEach { child ->
// If the child entry is not a deleted object,
if (deletedObjects.notContainsNode(child)) {
entriesToMove.add(child)
}
}
val groupsToMove = mutableListOf<GroupKDBX>()
databaseGroup.getChildGroups().forEach { child ->
// Move the group to the first parent not deleted
// the deleted objects will take care of remove it later
groupsToMove.add(child)
}
// For each node to move, move it
// try to move the child entry in the first parent not deleted
entriesToMove.forEach { child ->
database.removeEntryFrom(child, child.parent)
database.addEntryTo(
child,
firstNotDeletedParent(databaseGroup, deletedObjects)
)
}
groupsToMove.forEach { child ->
database.removeGroupFrom(child, child.parent)
database.addGroupTo(
child,
firstNotDeletedParent(databaseGroup, deletedObjects)
)
}
// Then delete the group
database.removeGroupFrom(databaseGroup, databaseGroup.parent)
}
}
/**
* Delete an icon from the database with the [deletedIcon] id
*/
private fun deleteIcon(deletedIcon: DeletedObject) {
val deletedObjectId = deletedIcon.uuid
val databaseIcon = database.iconsManager.getIcon(deletedObjectId)
val databaseIconModificationTime = databaseIcon?.lastModificationTime
if (databaseIcon != null
&& (databaseIconModificationTime == null
|| (deletedIcon.deletionTime.isAfter(databaseIconModificationTime)))
) {
database.removeCustomIcon(deletedObjectId)
}
}
/** /**
* Merge [customDataToMerge] in [customData] * Merge [customDataToMerge] in [customData]
*/ */

View File

@@ -151,7 +151,7 @@ class SearchHelper {
if (searchParameters.searchByDomain) { if (searchParameters.searchByDomain) {
try { try {
stringToCheck.inTheSameDomainAs(word, sameSubDomain = true) stringToCheck.inTheSameDomainAs(word, sameSubDomain = true)
} catch (e: Exception) { } catch (_: Exception) {
false false
} }
} else null } else null
@@ -204,10 +204,18 @@ class SearchHelper {
regex.matches(stringToCheck) regex.matches(stringToCheck)
} else { } else {
specialComparison?.invoke(stringToCheck, searchParameters.searchQuery) specialComparison?.invoke(stringToCheck, searchParameters.searchQuery)
?: stringToCheck.contains( ?: run {
searchParameters.searchQuery, // Search with space separator #175
!searchParameters.caseSensitive var searchFound = true
) searchParameters.searchQuery.split(" ").forEach { word ->
searchFound = searchFound
&& stringToCheck.contains(
word,
!searchParameters.caseSensitive
)
}
searchFound
}
} }
} }
} }

View File

@@ -92,7 +92,7 @@ inline fun <reified T : Parcelable> Parcel.readParcelableCompat(): T? = when {
fun <T> Parcel.readParcelableCompat(clazz: Class<T>): T? = when { fun <T> Parcel.readParcelableCompat(clazz: Class<T>): T? = when {
SDK_INT >= 33 -> readParcelable(clazz.classLoader, clazz) SDK_INT >= 33 -> readParcelable(clazz.classLoader, clazz)
else -> @Suppress("DEPRECATION") readParcelable(clazz.classLoader) as? T else -> @Suppress("DEPRECATION", "UNCHECKED_CAST") (readParcelable(clazz.classLoader) as? T)
} }
inline fun <reified T : Serializable> Parcel.readSerializableCompat(): T? = when { inline fun <reified T : Serializable> Parcel.readSerializableCompat(): T? = when {
@@ -120,19 +120,19 @@ fun <K : Parcelable, V : Parcelable> Parcel.writeParcelableMap(map: Map<K, V>, f
inline fun <reified K : Parcelable, reified V : Parcelable> Parcel.readParcelableMap(): Map<K, V> { inline fun <reified K : Parcelable, reified V : Parcelable> Parcel.readParcelableMap(): Map<K, V> {
val size = readInt() val size = readInt()
val map = HashMap<K, V>(size) val map = HashMap<K, V>(size)
for (i in 0 until size) { (0 until size).forEach { i ->
val key: K? = try { val key: K? = try {
when { when {
SDK_INT >= 33 -> readParcelable(K::class.java.classLoader, K::class.java) SDK_INT >= 33 -> readParcelable(K::class.java.classLoader, K::class.java)
else -> @Suppress("DEPRECATION") readParcelable(K::class.java.classLoader) else -> @Suppress("DEPRECATION") readParcelable(K::class.java.classLoader)
} }
} catch (e: Exception) { null } } catch (_: Exception) { null }
val value: V? = try { val value: V? = try {
when { when {
SDK_INT >= 33 -> readParcelable(V::class.java.classLoader, V::class.java) SDK_INT >= 33 -> readParcelable(V::class.java.classLoader, V::class.java)
else -> @Suppress("DEPRECATION") readParcelable(V::class.java.classLoader) else -> @Suppress("DEPRECATION") readParcelable(V::class.java.classLoader)
} }
} catch (e: Exception) { null } } catch (_: Exception) { null }
if (key != null && value != null) if (key != null && value != null)
map[key] = value map[key] = value
} }
@@ -152,14 +152,14 @@ fun <V : Parcelable> Parcel.writeStringParcelableMap(map: HashMap<String, V>, fl
inline fun <reified V : Parcelable> Parcel.readStringParcelableMap(): LinkedHashMap<String, V> { inline fun <reified V : Parcelable> Parcel.readStringParcelableMap(): LinkedHashMap<String, V> {
val size = readInt() val size = readInt()
val map = LinkedHashMap<String, V>(size) val map = LinkedHashMap<String, V>(size)
for (i in 0 until size) { (0 until size).forEach { i ->
val key: String? = readString() val key: String? = readString()
val value: V? = try { val value: V? = try {
when { when {
SDK_INT >= 33 -> readParcelable(V::class.java.classLoader, V::class.java) SDK_INT >= 33 -> readParcelable(V::class.java.classLoader, V::class.java)
else -> @Suppress("DEPRECATION") readParcelable(V::class.java.classLoader) else -> @Suppress("DEPRECATION") readParcelable(V::class.java.classLoader)
} }
} catch (e: Exception) { null } } catch (_: Exception) { null }
if (key != null && value != null) if (key != null && value != null)
map[key] = value map[key] = value
} }
@@ -179,7 +179,7 @@ fun Parcel.writeStringIntMap(map: LinkedHashMap<String, Int>) {
fun Parcel.readStringIntMap(): LinkedHashMap<String, Int> { fun Parcel.readStringIntMap(): LinkedHashMap<String, Int> {
val size = readInt() val size = readInt()
val map = LinkedHashMap<String, Int>(size) val map = LinkedHashMap<String, Int>(size)
for (i in 0 until size) { (0 until size).forEach { i ->
val key: String? = readString() val key: String? = readString()
val value: Int = readInt() val value: Int = readInt()
if (key != null) if (key != null)
@@ -201,7 +201,7 @@ fun Parcel.writeStringStringMap(map: MutableMap<String, String>) {
fun Parcel.readStringStringMap(): LinkedHashMap<String, String> { fun Parcel.readStringStringMap(): LinkedHashMap<String, String> {
val size = readInt() val size = readInt()
val map = LinkedHashMap<String, String>(size) val map = LinkedHashMap<String, String>(size)
for (i in 0 until size) { (0 until size).forEach { i ->
val key: String? = readString() val key: String? = readString()
val value: String? = readString() val value: String? = readString()
if (key != null && value != null) if (key != null && value != null)

View File

@@ -0,0 +1,6 @@
* Updated to API 35 minimum SDK 19 #2073 #2138 #2067 #2133 #1687 (Thx @Dev-ClayP)
* Remember last read-only state #2099 #2100 (Thx @rmacklin)
* Fix merge deletion #1516
* Fix space in search #175
* Fix deletable recycle bin #2163
* Small fixes

View File

@@ -0,0 +1,3 @@
* Fix landscape UI #2198 #2200 (@chenxiaolong)
* Fix start loop and flash screen #2201
* Small fixes

View File

@@ -1,4 +1,4 @@
KeePassDX es un <b> Administrador de contraseñas seguro </b> que permite editar <b>datos cifrados en un solo archivo</b> en el formato abierto de KeePass permite <b>completar los formularios de manera segura</b>, no requiere<b>conexión a internet</b> e integra los estándares de diseño de Android. La aplicación es <b> de código abierto, sin publicidad</b>. KeePassDX es un <b>gestor y almacén de contraseñas</b> que permite editar <b>datos cifrados en un único archivo</b> en formato KeePass abierto y <b>rellenar formularios de forma segura</b>, no requiere <b>conexión a Internet</b> e integra los estándares de diseño de Android. La aplicación es <b>de código abierto y sin publicidad</b>.
<b>Funciones</b> <b>Funciones</b>

View File

@@ -1 +1 @@
KeePassDX - FOSS Administrador de contraseñas KeePassDX - Contraseñas FOSS

View File

@@ -0,0 +1,6 @@
* Mise à jour vers API 35 minimum SDK 19 #2073 #2138 #2067 #2133 #1687 (Thx @Dev-ClayP)
* Sauvegarde du dernier état lecture seule #2099 #2100 (Thx @rmacklin)
* Correction de la suppression lors d'un merge #1516
* Correction des espaces dans la recherche #175
* Correction de la poubelle supprimable #2163
* Petites corrections

View File

@@ -0,0 +1,3 @@
* Correction de l'interface en paysage #2198 #2200 (@chenxiaolong)
* Correction du démarrage en boucle et de l'écran clignotant #2201
* Petites corrections

View File

@@ -1,4 +1,4 @@
KeePassDX имеет <b>открытый исходный код</b> и <b>без рекламы</b>. <b>Многоформатный менеджер паролей KeePass</b> это приложение которое позволяет безопасно сохранять и использовать пароли, ключи и цифровые идентификаторы за счет интеграции стандартов дизайна Android и <b>не требует подключения к Интернету</b>. KeePassDX — это приложение <b> для хранения и управления паролями</b>, которая позволяет редактировать <b>зашифрованные данные в одном файле</b> в открытом формате KeePass, <b>безопасно заполнять формы</b>, <b>не требует подключения к Интернету</b> и соответствует стандартам дизайна Android. Приложение с <b>открытым исходным кодом, без рекламы</b>.
<b>Возможности</b> <b>Возможности</b>
@@ -16,8 +16,8 @@ KeePassDX имеет <b>открытый исходный код</b> и <b>бе
- Точное управление настройками. - Точное управление настройками.
- Код написан на родных языках для платформы (Kotlin / Java / JNI / C). - Код написан на родных языках для платформы (Kotlin / Java / JNI / C).
Вы можете пожертвовать или купить профессиональную версию чтобы улучшить обслуживание и ускорить разработку нужных вам возможностей: <a href="https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.pro">KeePass Pro</a> Вы можете пожертвовать или купить профессиональную версию для улучшения обслуживания и быстрой разработки нужных вам возможностей: <a href="https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.pro">https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.pro</a>
Проект постоянно развивается. Не стесняйтесь проверять статус разработки и следующих обновлений тут: <a href="https://github.com/Kunzisoft/KeePassDX/projects">github.com/Kunzisoft/KeePassDX/projects</a> Проект постоянно развивается. Не стесняйтесь проверять статус разработки следующих обновлений: <a href="https://github.com/Kunzisoft/KeePassDX/projects">https://github.com/Kunzisoft/KeePassDX/projects</a>
Сообщить о проблеме:<a href="https://github.com/Kunzisoft/KeePassDX/issues">https://github.com/Kunzisoft/KeePassDX/issues</a> Сообщить о проблеме:<a href="https://github.com/Kunzisoft/KeePassDX/issues">https://github.com/Kunzisoft/KeePassDX/issues</a>

View File

@@ -0,0 +1,23 @@
KeePassDX, açık KeePass biçiminde <b>tek bir dosyada şifreli verileri</b> düzenlemeye ve <b>formları güvenli bir şekilde doldurmaya</b> olanak tanıyan bir <b>şifre kasası ve yöneticisi</b> olup, <b>internet bağlantısı gerektirmez</b> ve Android tasarım standartlarını takip eder. Uygulama <b>açık kaynaklıdır ve reklam içermez</b>.
<b>Özellikler</b>
- Veri tabanı dosyaları / girdileri ve grupları oluşturun.
- AES - Twofish - ChaCha20 - Argon2 algoritması ile .kdb ve .kdbx dosyaları (sürüm 1 ile 4 arası) desteği.
- Birçok farklı programla uyumludur (KeePass, KeePassXC, KeeWeb, …).
- URI / URL alanlarını hızlı bir şekilde açma ve kopyalama imkanı.
- Hızlı kilit açma için biyometrik tanıma (parmak izi / yüz tanıma / …).
- İki aşamalı kimlik doğrulama (2FA) için tek kullanımlık şifre yönetimi (HOTP / TOTP).
- Temalı Material tasarımı.
- Otomatik doldurma ve bütünleşme.
- Alan doldurma klavyesi.
- Değişken şablonlar.
- Her girdinin geçmişi.
- Ayarların hassas yönetimi.
- Yerel dillerde (Kotlin / Java / JNI / C) yazılmış kod.
Daha iyi hizmet ve istediğiniz özelliklerin hızlı bir şekilde geliştirilmesi için bağış yapabilir veya pro sürümü satın alabilirsiniz: <a href="https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.pro">https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.pro</a>
Proje sürekli gelişmektedir. Bir sonraki güncellemelerin geliştirme durumuna bakmaktan çekinmeyin: <a href="https://github.com/Kunzisoft/KeePassDX/projects">https://github.com/Kunzisoft/KeePassDX/projects</a>
Sorunlarınızı şu adrese gönderin: <a href="https://github.com/Kunzisoft/KeePassDX/issues">https://github.com/Kunzisoft/KeePassDX/issues</a>

View File

@@ -0,0 +1,23 @@
KeePassDX 是一款<b>密碼保險箱和管理器</b>,允許以開放的 KeePass 格式編輯<b>單一檔案中的加密資料</b>,並<b>以安全的方式填寫表單</b>,無需<b>網路連線</b>,並整合了 Android 設計標準。該應用程式<b>開源,無廣告</b>。
<b>功能</b>
- 建立資料庫檔案/條目和群組。
- 支援 .kdb 和 .kdbx 檔案(版本 1 至 4並採用 AES - Twofish - ChaCha20 - Argon2 演算法。
- 與大多數替代方案KeePass、KeePassXC、KeeWeb 等)相容。
- 允許快速開啟和複製 URI/URL 欄位。
- 生物辨識技術,可快速解鎖(指紋/人臉解鎖等)。
- 一次性密碼管理 (HOTP / TOTP),用於雙重認證 (2FA)。
- 帶主題的 Material Design 設計。
- 自動填充和整合。
- 字段填充鍵盤。
- 動態模板。
- 每次輸入的歷史記錄。
- 精確的設定管理。
- 使用原生語言編寫程式碼 (Kotlin / Java / JNI / C)。
您可以捐款或購買專業版,以獲得更好的服務並快速開發您想要的功能:<a href="https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.pro">https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.pro</a>
該項目正在不斷發展。請隨時查看後續更新的開發狀態:<a href="https://github.com/Kunzisoft/KeePassDX/projects">https://github.com/Kunzisoft/KeePassDX/projects</a>
請將問題寄至:<a href="https://github.com/Kunzisoft/KeePassDX/issues">https://github.com/Kunzisoft/KeePassDX/issues</a>

View File

@@ -0,0 +1 @@
安全的開源密碼保險箱和管理器

View File

@@ -0,0 +1 @@
KeePassDX - FOSS 密碼管理器