Compare commits

...

160 Commits
3.0.0 ... 3.0.3

Author SHA1 Message Date
J-Jamet
0d91f07646 Merge branch 'release/3.0.3' 2021-12-08 17:58:37 +01:00
J-Jamet
db882a26ab Upgrade constraint layout lib 2021-12-08 11:37:02 +01:00
J-Jamet
7f01619358 Fix notification in older android versions 2021-12-07 18:14:36 +01:00
J-Jamet
ee109b4ceb Merge branch 'feature/StartActivityResult' into develop 2021-12-07 16:36:52 +01:00
J-Jamet
7a398e5453 Fix activity result for advanced unlocking 2021-12-07 16:20:57 +01:00
J-Jamet
d4655d7034 Fix search in activity 2021-12-02 13:31:41 +01:00
J-Jamet
9feb96b541 Fix start autofill service 2021-12-02 13:30:02 +01:00
J-Jamet
e939278193 Suppress deprecation with setTargetFragment 2021-12-02 13:21:25 +01:00
J-Jamet
d4ef1a2617 Fix small warnings 2021-12-02 11:39:42 +01:00
J-Jamet
5f8746ced3 Fix result with entry edit 2021-12-01 17:16:19 +01:00
J-Jamet
40a063e94f Fix result exit lock 2021-11-30 11:50:07 +01:00
J-Jamet
8f5439b958 Icon selection with activity result launcher 2021-11-30 11:20:09 +01:00
J-Jamet
e347f57d8b Refactor FileHelper and fix key file selection 2021-11-30 10:47:31 +01:00
J-Jamet
2efb8e8b8c Merge branch 'develop' into feature/StartActivityResult 2021-11-23 18:28:08 +01:00
J-Jamet
e5bb69ea5f Fix startActivityResult for Autofill 2021-11-23 18:28:01 +01:00
J-Jamet
6ae186b2af Fix exported and pending intent 2021-11-23 12:10:57 +01:00
J-Jamet
71fdd2d92d Fix lowercase and uppercase 2021-11-22 13:22:18 +01:00
J-Jamet
3656689ff3 Fix kotlin code warning 2021-11-22 13:10:42 +01:00
J-Jamet
7d78406db6 Fix pending intent 2021-11-22 12:24:22 +01:00
J-Jamet
ac47748e41 Fix pending intent 2021-11-22 11:51:30 +01:00
J-Jamet
80f9b46479 New lock icon in notification 2021-11-20 13:30:26 +01:00
J-Jamet
999f1bf47a New lock icon in notification 2021-11-20 13:10:23 +01:00
J-Jamet
9e114eb2b8 Add lock button in database notification 2021-11-20 12:30:58 +01:00
J-Jamet
d89b6529ef Upgrade kotlin and fragment versions 2021-11-16 16:51:06 +01:00
J-Jamet
5caf11556a Remove unused translation 2021-11-16 16:15:08 +01:00
J-Jamet
78cc6f0f40 Merge branch 'translations' into develop 2021-11-16 16:10:58 +01:00
J-Jamet
0007cd4668 Merge branch 'develop' of https://hosted.weblate.org/git/keepass-dx/strings into translations 2021-11-16 16:09:26 +01:00
J-Jamet
05195e41de Upgrade appcompat and material libs 2021-11-16 14:53:54 +01:00
J-Jamet
66f44ef87d Encapsulate lib version through modules 2021-11-16 12:48:38 +01:00
J-Jamet
a0585d9b11 Upgrade repo and libs 2021-11-16 12:07:48 +01:00
J-Jamet
5067946b13 Change backup configuration #1144 2021-11-16 11:12:07 +01:00
J-Jamet
f52241d5a8 Change backup configuration #1144 2021-11-16 11:09:14 +01:00
J-Jamet
04ccb25fa3 Catch key file out of memory exception 2021-11-15 12:25:27 +01:00
J-Jamet
5a3f4b60b8 Catch style exception 2021-11-15 12:19:36 +01:00
J-Jamet
4408b2e488 Catch exception in run action 2021-11-15 12:04:46 +01:00
J-Jamet
9a26acee35 Change version to 3.0.3 and add issue tag 2021-11-15 11:35:08 +01:00
Rsec
6ac377348b Translated using Weblate (Romanian)
Currently translated at 63.2% (359 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ro/
2021-11-10 18:49:56 +01:00
I. Musthafa
daeb88d4f4 Translated using Weblate (Indonesian)
Currently translated at 79.0% (449 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/id/
2021-11-08 07:50:09 +01:00
J-Jamet
47bf199f52 Merge branch 'feature/Biometric_Refactor' into develop 2021-11-03 14:46:55 +01:00
J-Jamet
91540b022d Use strong box to store in security chip #1145 2021-11-02 17:55:30 +01:00
J-Jamet
505a51b6b5 Update CHANGELOG 2021-11-02 17:31:09 +01:00
J-Jamet
28400488aa Fix advanced unlock menu button 2021-11-02 17:22:23 +01:00
J-Jamet
45ae600289 Change biometric views 2021-11-02 17:10:06 +01:00
J-Jamet
8be6874651 Auto remove all biometric keys when invalidated 2021-11-02 16:27:29 +01:00
Milo Ivir
f694a500e0 Translated using Weblate (Croatian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hr/
2021-10-30 00:37:53 +02:00
J-Jamet
c415fa01fc Update Autofill compatibility list #725 2021-10-29 17:40:16 +02:00
J-Jamet
5225a9459c Fix template chars limit 2021-10-27 20:01:47 +02:00
J-Jamet
2974b150af Fix template spinner 2021-10-27 19:55:14 +02:00
J-Jamet
cf353c8067 Fix template icons 2021-10-27 19:27:21 +02:00
Serdar Sağlam
3aacb5d8b3 Translated using Weblate (Turkish)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2021-10-27 01:38:42 +02:00
abidin toumi
114fbdbe01 Translated using Weblate (Arabic)
Currently translated at 77.4% (440 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2021-10-27 01:38:42 +02:00
abidin toumi
f1f83cbec4 Translated using Weblate (Arabic)
Currently translated at 76.5% (435 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2021-10-25 20:38:00 +02:00
J-Jamet
335c28c2c9 Fix save default username 2021-10-25 15:57:01 +02:00
J-Jamet
daf12cbcce Change Wifi to Wi-Fi 2021-10-25 15:44:18 +02:00
J-Jamet
bf56eca003 Fix templates #1128 2021-10-25 15:41:20 +02:00
J-Jamet
a12b7fd58a Merge branch 'SUPERYAO541-feature/Complete_zh-rTW' into develop 2021-10-25 11:30:33 +02:00
J-Jamet
98d004edbf Merge branch 'feature/Complete_zh-rTW' of git://github.com/SUPERYAO541/KeePassDX into SUPERYAO541-feature/Complete_zh-rTW 2021-10-25 11:30:18 +02:00
random r
67586a98b3 Translated using Weblate (Italian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2021-10-23 11:41:24 +02:00
Milo Ivir
c6d8911883 Translated using Weblate (Croatian)
Currently translated at 99.8% (567 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hr/
2021-10-21 21:36:24 +02:00
Neko Nekowazarashi
12e398ce9b Translated using Weblate (Indonesian)
Currently translated at 78.1% (444 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/id/
2021-10-16 13:40:45 +02:00
abidin toumi
5c4a202616 Translated using Weblate (Arabic)
Currently translated at 76.4% (434 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2021-10-14 23:34:38 +02:00
solokot
adc1ec8444 Translated using Weblate (Russian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2021-10-14 23:34:36 +02:00
Darin Avdeyeva
0227d2fcb4 Translated using Weblate (Russian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2021-10-13 19:02:33 +02:00
abidin toumi
95abe3b5ac Translated using Weblate (Arabic)
Currently translated at 67.6% (384 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2021-10-10 18:02:20 +02:00
abidin toumi
133a902c54 Translated using Weblate (Arabic)
Currently translated at 61.4% (349 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2021-10-09 17:05:15 +02:00
Stephan Paternotte
aacb03d9ef Translated using Weblate (Dutch)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2021-10-07 20:03:28 +02:00
J-Jamet
fbeaa1781f Add no internet connection required in description 2021-10-06 18:45:14 +02:00
J-Jamet
ca73aad538 Add dynamic templates in description 2021-10-06 18:09:54 +02:00
André Marcelo Alvarenga
4a4bfefd17 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-10-05 10:08:58 +02:00
J-Jamet
6796b0cd2a Upgrade gradle 2021-10-04 16:49:15 +02:00
abidin toumi
29e1f824b0 Translated using Weblate (Arabic)
Currently translated at 61.2% (348 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2021-10-03 17:19:42 +02:00
hokonch
51263a2911 Translated using Weblate (Japanese)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2021-09-30 06:36:59 +02:00
Kunzisoft
dd7f857475 Translated using Weblate (French)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/
2021-09-30 06:36:59 +02:00
J-Jamet
f0fdd4a537 Add & edit custom icon name #976 2021-09-28 18:12:49 +02:00
J-Jamet
9b847a0561 Change default Argon2 parameters #1098
and upgrade to 3.1.0
2021-09-28 12:57:14 +02:00
Hosted Weblate
469e76b80a Merge branch 'origin/develop' into Weblate. 2021-09-28 09:56:49 +02:00
SC
9c6994b476 Translated using Weblate (Portuguese)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt/
2021-09-27 19:36:47 +02:00
Oğuz Ersen
52ba487617 Translated using Weblate (Turkish)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2021-09-27 19:36:47 +02:00
Eric
21c57c9484 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2021-09-27 19:36:47 +02:00
Ihor Hordiichuk
9b1ea6a07a Translated using Weblate (Ukrainian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/
2021-09-27 19:36:47 +02:00
solokot
f7d7bb0ea3 Translated using Weblate (Russian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2021-09-27 19:36:46 +02:00
SC
dd96b9ef53 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_PT/
2021-09-27 19:36:46 +02:00
Matthaiks
b6b01893ba Translated using Weblate (Polish)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2021-09-27 19:36:46 +02:00
Óscar Fernández Díaz
ad531d793d Translated using Weblate (Spanish)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/
2021-09-27 19:36:45 +02:00
Retrial
a9dd11e24a Translated using Weblate (Greek)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/el/
2021-09-27 19:36:45 +02:00
VfBFan
115983830b Translated using Weblate (German)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2021-09-27 19:36:45 +02:00
zeritti
442cece081 Translated using Weblate (Czech)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2021-09-27 19:36:45 +02:00
SUPERYAO
14e08457b9 Complete and improve zh-rTW 2021-09-25 21:59:59 +08:00
J-Jamet
fabcc08cd5 Merge tag '3.0.2' into develop
3.0.2
2021-09-24 19:35:07 +02:00
J-Jamet
7750843b04 Merge branch 'release/3.0.2' 2021-09-24 19:34:58 +02:00
Hosted Weblate
c03188e976 Merge branch 'origin/develop' into Weblate. 2021-09-24 13:54:09 +02:00
J-Jamet
d7da1ce333 Upgrade to 3.0.2 and update CHANGELOG 2021-09-24 12:55:08 +02:00
J-Jamet
dd9ee8c3f8 Merge branch 'chenxiaolong-samsung_dex' into develop 2021-09-24 12:50:40 +02:00
Braja Yudhistira
34bbd8f439 Translated using Weblate (Indonesian)
Currently translated at 77.8% (442 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/id/
2021-09-23 21:34:44 +02:00
Milo Ivir
053f57cff5 Translated using Weblate (Croatian)
Currently translated at 99.8% (567 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hr/
2021-09-23 21:34:44 +02:00
Balázs Meskó
365d2e2844 Translated using Weblate (Hungarian)
Currently translated at 82.5% (469 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hu/
2021-09-23 21:34:43 +02:00
Andrew Gunnerson
c0ac01a34a Add workaround to support Samsung DeX
This commit changes the Magikeyboard service behavior so that KeePassDX
is able to run in Samsung DeX mode. Currently, the app cannot run in
DeX mode because apps which have services using `BIND_INPUT_METHOD` are
blocked.

A new broadcast receiver has been added to listen for DeX's enter/leave
events [1] and disable/enable the `Magikeyboard` service appropriately.
The enabled state of a service lives in the Android framework's
`PackageManager` and survives app crashes and device reboots (though it
does get reset when app data is cleared).

Additionally, an extra check is added to `FileDatabaseSelectActivity` to
ensure the service's enabled state is correct. This is necessary if the
app crashes or is force quit within DeX mode and then the user exits DeX
mode. Otherwise, the service would stay disabled until the user entered
and exited DeX again.

With the new behavior, KeePassDX will generally just work with DeX,
though there's one caveat: after the initial installation, the user must
open the app once outside of DeX. Otherwise, Android will not trigger
the broadcast receiver. This could be fixed by making the service
intially disabled in the manifest with `android:enabled="false"`, but
Android's Settings app in SDK 15 through 25 does not correctly refresh
the keyboard list when changing the service from disabled to enabled.
I opted *not* to introduce different behavior based on the API version.

[1] https://developer.samsung.com/sdp/blog/en-us/2017/07/27/samsung-dex-how-to-detect-the-samsung-dex-mode

Fixes: #245
Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
2021-09-18 23:30:37 -04:00
Stephan Paternotte
22c0bc0adb Translated using Weblate (Dutch)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2021-09-17 18:36:29 +02:00
J-Jamet
1b88f2ddf0 Merge tag '3.0.1' into develop
3.0.1
2021-09-15 13:25:03 +02:00
J-Jamet
b4f2a1eb89 Merge branch 'release/3.0.1' 2021-09-15 13:24:53 +02:00
J-Jamet
e9fc9cbc2a Capture cast exception 2021-09-15 12:21:44 +02:00
J-Jamet
b809180a1b Small changes 2021-09-15 11:25:15 +02:00
J-Jamet
ecc75df3a1 Fix search actions #1091 #1092 2021-09-15 11:16:32 +02:00
J-Jamet
d1b6863143 Update CHANGELOG 2021-09-15 10:36:41 +02:00
J-Jamet
faf27143aa Fix timeout reset #1107 2021-09-15 10:33:37 +02:00
J-Jamet
aee58a4475 Fix exception after group name change and save #1112 2021-09-15 09:48:48 +02:00
VfBFan
c4cbf07d78 Translated using Weblate (German)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2021-09-15 07:34:50 +02:00
J-Jamet
c5e07f643f Fix Magikeyboard URL auto action #1100 2021-09-14 20:40:22 +02:00
J-Jamet
818f5820d5 Update CHANGELOG 2021-09-14 20:13:35 +02:00
J-Jamet
77c6e28876 Fix max lines #1073 2021-09-14 20:06:49 +02:00
J-Jamet
fb7f66012d Upgrade to 3.0.1 2021-09-14 19:35:30 +02:00
J-Jamet
0f7f7bbe6c Min height to 48dp 2021-09-14 19:30:50 +02:00
J-Jamet
8dedb8deb4 Fix text dimension 2021-09-14 19:10:48 +02:00
Long Nguyễn Khánh
dbb2c10bba Translated using Weblate (Vietnamese)
Currently translated at 16.1% (92 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/vi/
2021-09-13 12:46:09 +02:00
Ihor Hordiichuk
67a5eef7d6 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/
2021-09-12 00:23:20 +02:00
HARADA Hiroyuki
979f651251 Translated using Weblate (Japanese)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2021-09-12 00:23:19 +02:00
SC
3b93cbb009 Translated using Weblate (Portuguese)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt/
2021-09-11 04:18:42 +02:00
SC
30c63bfc4b Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_PT/
2021-09-11 04:18:42 +02:00
SC
bed40324a1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-11 04:18:37 +02:00
Wilker Santana da Silva
bc035de377 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-11 04:18:37 +02:00
SC
4db3cb6936 Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.8% (567 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-11 01:07:20 +02:00
Wilker Santana da Silva
ed4b91f4bd Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.8% (567 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-11 01:07:20 +02:00
SC
24c7151276 Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.6% (566 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-11 01:00:00 +02:00
Wilker Santana da Silva
804a9c07b8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.6% (566 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-11 00:59:58 +02:00
SC
528ea56821 Translated using Weblate (Portuguese)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt/
2021-09-11 00:01:53 +02:00
SC
7ba9c69ff8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 88.7% (504 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-10 20:50:55 +02:00
Wilker Santana da Silva
0fc34da08a Translated using Weblate (Portuguese (Brazil))
Currently translated at 88.7% (504 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-10 20:50:54 +02:00
SC
3fbf8cdbc8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 83.0% (472 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-10 20:36:00 +02:00
Wilker Santana da Silva
e21f20d818 Translated using Weblate (Portuguese (Brazil))
Currently translated at 83.0% (472 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2021-09-10 20:35:59 +02:00
Sina bagheri
9fd9a60ca3 Translated using Weblate (Persian)
Currently translated at 56.6% (322 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fa/
2021-09-09 17:32:51 +02:00
Hosted Weblate
78b683d724 Merge branch 'origin/develop' into Weblate. 2021-09-08 07:26:45 +02:00
vachan-maker
ad2f5036e1 Translated using Weblate (Malayalam)
Currently translated at 70.2% (399 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ml/
2021-09-08 07:26:45 +02:00
random r
4afbad8faa Translated using Weblate (Italian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2021-09-08 07:26:44 +02:00
J-Jamet
d284db4d3c Merge tag '3.0.0' into develop
3.0.0
2021-09-07 18:43:40 +02:00
Oliver Cervera
ae8b1c0c29 Translated using Weblate (Italian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2021-09-06 21:34:18 +02:00
Óscar Fernández Díaz
27978c459c Translated using Weblate (Spanish)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/
2021-09-06 21:34:17 +02:00
Martin
1dc7f5c666 Translated using Weblate (Czech)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2021-09-06 21:34:17 +02:00
zeritti
12ac870d3a Translated using Weblate (Czech)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2021-09-06 21:34:17 +02:00
Aman Kirely
dd1baa0224 Translated using Weblate (Czech)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2021-09-06 21:34:17 +02:00
Oğuz Ersen
bb27ef41cc Translated using Weblate (Turkish)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2021-09-04 17:34:43 +02:00
Allan Nordhøy
2d35ac1df8 Translated using Weblate (Norwegian Bokmål)
Currently translated at 74.8% (425 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nb_NO/
2021-09-04 17:34:43 +02:00
Eric
589ffc0c06 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2021-09-04 17:34:42 +02:00
Ihor Hordiichuk
1f7f38c7d3 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/
2021-09-04 17:34:41 +02:00
solokot
83817a2dc0 Translated using Weblate (Russian)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2021-09-04 17:34:41 +02:00
Matthaiks
11af9da66f Translated using Weblate (Polish)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2021-09-04 17:34:40 +02:00
Retrial
af3926acf3 Translated using Weblate (Greek)
Currently translated at 100.0% (568 of 568 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/el/
2021-09-04 17:34:40 +02:00
Hosted Weblate
ab40c2b3fd Merge branch 'origin/develop' into Weblate. 2021-09-03 16:07:31 +02:00
Oliver Cervera
fd05670dbc Translated using Weblate (Italian)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2021-09-03 00:32:28 +02:00
Óscar Fernández Díaz
1ac094bfae Translated using Weblate (Spanish)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/
2021-09-03 00:32:27 +02:00
Oğuz Ersen
fdf052cddb Translated using Weblate (Turkish)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2021-09-01 10:34:02 +02:00
Eric
9a8d50ba6f Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2021-09-01 10:34:02 +02:00
Ihor Hordiichuk
136c97c312 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/
2021-09-01 10:34:02 +02:00
solokot
bf00b88ef3 Translated using Weblate (Russian)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2021-09-01 10:34:02 +02:00
Matthaiks
bafd1ea549 Translated using Weblate (Polish)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2021-09-01 10:34:01 +02:00
Hisikawa Mizuki
982618511b Translated using Weblate (Japanese)
Currently translated at 99.2% (561 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2021-09-01 10:34:01 +02:00
Oliver Cervera
a4ad7ca3b1 Translated using Weblate (Italian)
Currently translated at 99.4% (562 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2021-09-01 10:34:01 +02:00
Éfrit
99d71b57a4 Translated using Weblate (French)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/
2021-09-01 10:34:00 +02:00
Retrial
1b2d8502e0 Translated using Weblate (Greek)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/el/
2021-09-01 10:34:00 +02:00
VfBFan
53e4ea9334 Translated using Weblate (German)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2021-09-01 10:34:00 +02:00
zeritti
3ce704155c Translated using Weblate (Czech)
Currently translated at 100.0% (565 of 565 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2021-09-01 10:33:59 +02:00
129 changed files with 3505 additions and 1761 deletions

View File

@@ -1,3 +1,24 @@
KeePassDX(3.0.3)
* Change default Argon2 parameters #1098
* Add & edit custom icon name #976
* Fix templates #1128 #1133 #1138
* Update Autofill compatibility list #725 #1154
* Improve fingerprint usage #1137 #1145
* Change backup configuration #1144
* Add lock button in database notification
KeePassDX(3.0.2)
* Samsung DeX mode #1114 #245 (Thx @chenxiaolong)
KeePassDX(3.0.1)
* Fix text size and smallest margin #1085
* Fix number of lines during an edition #1073
* Fix Magikeyboard URL auto action #1100
* Fix exception after group name change and save #1112
* Fix timeout reset #1107
* Fix search actions #1091 #1092
* Small changes #1106 #1085
KeePassDX(3.0.0)
* Add / Manage dynamic templates #191
* Manually select RecycleBin group and Templates group #191

View File

@@ -15,6 +15,7 @@
- Material design with **themes**.
- **Auto-Fill** and Integration.
- Field filling **keyboard**.
- Dynamic **templates**
- **History** of each entry.
- Precise management of **settings**.
- Code written in **native languages** *(Kotlin / Java / JNI / C)*.

View File

@@ -11,8 +11,8 @@ android {
applicationId "com.kunzisoft.keepass"
minSdkVersion 15
targetSdkVersion 30
versionCode = 87
versionName = "3.0.0"
versionCode = 90
versionName = "3.0.3"
multiDexEnabled true
testApplicationId = "com.kunzisoft.keepass.tests"
@@ -99,33 +99,33 @@ android {
}
}
def room_version = "2.2.6"
def room_version = "2.3.0"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.appcompat:appcompat:$android_appcompat_version"
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'androidx.media:media:1.4.3'
// Lifecycle - LiveData - ViewModel - Coroutines
implementation "androidx.core:core-ktx:1.3.2"
implementation 'androidx.fragment:fragment-ktx:1.2.5'
// WARNING: Don't upgrade because slowdown https://github.com/Kunzisoft/KeePassDX/issues/923
implementation 'com.google.android.material:material:1.1.0'
implementation "androidx.core:core-ktx:$android_core_version"
implementation 'androidx.fragment:fragment-ktx:1.3.6'
implementation "com.google.android.material:material:$android_material_version"
// Database
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// Autofill
implementation "androidx.autofill:autofill:1.1.0"
// Time
implementation 'joda-time:joda-time:2.10.6'
implementation 'joda-time:joda-time:2.10.13'
// Color
implementation 'com.github.Kunzisoft:AndroidClearChroma:2.4'
// Education
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.0'
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.3'
// Apache Commons
implementation 'commons-io:commons-io:2.8.0'
implementation 'commons-codec:commons-codec:1.15'
@@ -136,6 +136,6 @@ dependencies {
implementation project(path: ':icon-pack-material')
// Tests
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test:rules:1.3.0'
androidTestImplementation "androidx.test:runner:$android_test_version"
androidTestImplementation "androidx.test:rules:$android_test_version"
}

View File

@@ -44,6 +44,7 @@
android:theme="@style/KeepassDXStyle.SplashScreen"
android:label="@string/app_name"
android:launchMode="singleTop"
android:exported="true"
android:configChanges="keyboardHidden"
android:windowSoftInputMode="stateHidden|stateAlwaysHidden" >
<intent-filter>
@@ -53,6 +54,7 @@
</activity>
<activity
android:name="com.kunzisoft.keepass.activities.PasswordActivity"
android:exported="true"
android:configChanges="keyboardHidden"
android:windowSoftInputMode="adjustResize|stateUnchanged">
<intent-filter>
@@ -111,6 +113,7 @@
<!-- Main Activity -->
<activity
android:name="com.kunzisoft.keepass.activities.GroupActivity"
android:exported="false"
android:configChanges="keyboardHidden"
android:windowSoftInputMode="adjustPan">
<meta-data
@@ -154,7 +157,8 @@
android:name="com.kunzisoft.keepass.settings.AutofillSettingsActivity" />
<activity
android:name="com.kunzisoft.keepass.activities.EntrySelectionLauncherActivity"
android:theme="@style/Theme.Transparent">
android:theme="@style/Theme.Transparent"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
@@ -173,7 +177,8 @@
android:theme="@style/Theme.Transparent" />
<activity
android:name="com.kunzisoft.keepass.settings.MagikeyboardSettingsActivity"
android:label="@string/keyboard_setting_label">
android:label="@string/keyboard_setting_label"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
@@ -199,6 +204,7 @@
<service
android:name="com.kunzisoft.keepass.autofill.KeeAutofillService"
android:label="@string/autofill_service_name"
android:exported="true"
android:permission="android.permission.BIND_AUTOFILL_SERVICE">
<meta-data
android:name="android.autofill"
@@ -210,6 +216,7 @@
<service
android:name="com.kunzisoft.keepass.magikeyboard.MagikeyboardService"
android:label="@string/keyboard_label"
android:exported="true"
android:permission="android.permission.BIND_INPUT_METHOD" >
<meta-data android:name="android.view.im"
android:resource="@xml/keyboard_method"/>
@@ -221,6 +228,14 @@
android:name="com.kunzisoft.keepass.services.KeyboardEntryNotificationService"
android:enabled="true"
android:exported="false" />
<receiver
android:name="com.kunzisoft.keepass.receivers.DexModeReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.app.action.ENTER_KNOX_DESKTOP_MODE" />
<action android:name="android.app.action.EXIT_KNOX_DESKTOP_MODE" />
</intent-filter>
</receiver>
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
</application>

View File

@@ -23,10 +23,10 @@ import android.app.Activity
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentSender
import android.os.Build
import android.view.inputmethod.InlineSuggestionsRequest
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
@@ -40,11 +40,15 @@ import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.utils.LOCK_ACTION
@RequiresApi(api = Build.VERSION_CODES.O)
class AutofillLauncherActivity : DatabaseModeActivity() {
private var mAutofillActivityResultLauncher: ActivityResultLauncher<Intent>? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
AutofillHelper.buildActivityResultLauncher(this, true)
else null
override fun applyCustomStyle(): Boolean {
return false
}
@@ -119,6 +123,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
// Show the database UI to select the entry
GroupActivity.launchForAutofillResult(this,
openedDatabase,
mAutofillActivityResultLauncher,
autofillComponent,
searchInfo,
false)
@@ -126,6 +131,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
{
// If database not open
FileDatabaseSelectActivity.launchForAutofillResult(this,
mAutofillActivityResultLauncher,
autofillComponent,
searchInfo)
}
@@ -186,17 +192,6 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
Toast.makeText(this.applicationContext, R.string.autofill_read_only_save, Toast.LENGTH_LONG).show()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data)
if (PreferencesUtil.isAutofillCloseDatabaseEnable(this)) {
// Close the database
sendBroadcast(Intent(LOCK_ACTION))
}
super.onActivityResult(requestCode, resultCode, data)
}
companion object {
private const val KEY_MANUAL_SELECTION = "KEY_MANUAL_SELECTION"
@@ -210,31 +205,41 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
searchInfo: SearchInfo? = null,
inlineSuggestionsRequest: InlineSuggestionsRequest? = null): PendingIntent {
return PendingIntent.getActivity(context, 0,
// Doesn't work with Parcelable (don't know why?)
Intent(context, AutofillLauncherActivity::class.java).apply {
searchInfo?.let {
putExtra(KEY_SEARCH_APPLICATION_ID, it.applicationId)
putExtra(KEY_SEARCH_DOMAIN, it.webDomain)
putExtra(KEY_SEARCH_SCHEME, it.webScheme)
putExtra(KEY_MANUAL_SELECTION, it.manualSelection)
// Doesn't work with Parcelable (don't know why?)
Intent(context, AutofillLauncherActivity::class.java).apply {
searchInfo?.let {
putExtra(KEY_SEARCH_APPLICATION_ID, it.applicationId)
putExtra(KEY_SEARCH_DOMAIN, it.webDomain)
putExtra(KEY_SEARCH_SCHEME, it.webScheme)
putExtra(KEY_MANUAL_SELECTION, it.manualSelection)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
inlineSuggestionsRequest?.let {
putExtra(EXTRA_INLINE_SUGGESTIONS_REQUEST, it)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
inlineSuggestionsRequest?.let {
putExtra(EXTRA_INLINE_SUGGESTIONS_REQUEST, it)
}
}
},
PendingIntent.FLAG_CANCEL_CURRENT)
}
},
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// TODO Mutable
PendingIntent.FLAG_CANCEL_CURRENT
} else {
PendingIntent.FLAG_CANCEL_CURRENT
})
}
fun getPendingIntentForRegistration(context: Context,
registerInfo: RegisterInfo): PendingIntent {
return PendingIntent.getActivity(context, 0,
Intent(context, AutofillLauncherActivity::class.java).apply {
EntrySelectionHelper.addSpecialModeInIntent(this, SpecialMode.REGISTRATION)
putExtra(KEY_REGISTER_INFO, registerInfo)
},
PendingIntent.FLAG_CANCEL_CURRENT)
Intent(context, AutofillLauncherActivity::class.java).apply {
EntrySelectionHelper.addSpecialModeInIntent(this, SpecialMode.REGISTRATION)
putExtra(KEY_REGISTER_INFO, registerInfo)
},
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// TODO Mutable
PendingIntent.FLAG_CANCEL_CURRENT
} else {
PendingIntent.FLAG_CANCEL_CURRENT
})
}
fun launchForRegistration(context: Context,

View File

@@ -32,6 +32,7 @@ import android.view.MenuItem
import android.view.View
import android.widget.ImageView
import android.widget.ProgressBar
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.viewModels
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
@@ -62,7 +63,6 @@ import com.kunzisoft.keepass.view.hideByFading
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.viewmodels.EntryViewModel
import java.util.*
import kotlin.collections.HashMap
class EntryActivity : DatabaseLockActivity() {
@@ -84,8 +84,13 @@ class EntryActivity : DatabaseLockActivity() {
private var mEntryLoaded = false
private var mAttachmentFileBinderManager: AttachmentFileBinderManager? = null
private var mAttachmentsToDownload: HashMap<Int, Attachment> = HashMap()
private var mExternalFileHelper: ExternalFileHelper? = null
private var mAttachmentSelected: Attachment? = null
private var mEntryActivityResultLauncher = EntryEditActivity.registerForEntryResult(this) {
// Reload the current id from database
mEntryViewModel.loadDatabase(mDatabase)
}
private var mIcon: IconImage? = null
private var mIconColor: Int = 0
@@ -133,6 +138,15 @@ class EntryActivity : DatabaseLockActivity() {
// Init SAF manager
mExternalFileHelper = ExternalFileHelper(this)
mExternalFileHelper?.buildCreateDocument { createdFileUri ->
mAttachmentSelected?.let { attachment ->
if (createdFileUri != null) {
mAttachmentFileBinderManager
?.startDownloadAttachment(createdFileUri, attachment)
}
mAttachmentSelected = null
}
}
// Init attachment service binder manager
mAttachmentFileBinderManager = AttachmentFileBinderManager(this)
@@ -209,9 +223,8 @@ class EntryActivity : DatabaseLockActivity() {
}
mEntryViewModel.attachmentSelected.observe(this) { attachmentSelected ->
mExternalFileHelper?.createDocument(attachmentSelected.name)?.let { requestCode ->
mAttachmentsToDownload[requestCode] = attachmentSelected
}
mAttachmentSelected = attachmentSelected
mExternalFileHelper?.createDocument(attachmentSelected.name)
}
mEntryViewModel.historySelected.observe(this) { historySelected ->
@@ -220,7 +233,8 @@ class EntryActivity : DatabaseLockActivity() {
this,
database,
historySelected.nodeId,
historySelected.historyPosition
historySelected.historyPosition,
mEntryActivityResultLauncher
)
}
}
@@ -290,26 +304,6 @@ class EntryActivity : DatabaseLockActivity() {
super.onPause()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
EntryEditActivity.ADD_OR_UPDATE_ENTRY_REQUEST_CODE -> {
// Reload the current id from database
mEntryViewModel.loadDatabase(mDatabase)
}
}
mExternalFileHelper?.onCreateDocumentResult(requestCode, resultCode, data) { createdFileUri ->
if (createdFileUri != null) {
mAttachmentsToDownload[requestCode]?.let { attachmentToDownload ->
mAttachmentFileBinderManager
?.startDownloadAttachment(createdFileUri, attachmentToDownload)
}
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
if (mEntryLoaded) {
@@ -391,7 +385,8 @@ class EntryActivity : DatabaseLockActivity() {
EntryEditActivity.launchToUpdate(
this,
database,
entryId
entryId,
mEntryActivityResultLauncher
)
}
}
@@ -432,7 +427,7 @@ class EntryActivity : DatabaseLockActivity() {
// Transit data in previous Activity after an update
Intent().apply {
putExtra(EntryEditActivity.ADD_OR_UPDATE_ENTRY_KEY, mMainEntryId)
setResult(EntryEditActivity.ADD_OR_UPDATE_ENTRY_RESULT_CODE, this)
setResult(Activity.RESULT_OK, this)
}
super.finish()
}
@@ -450,15 +445,13 @@ class EntryActivity : DatabaseLockActivity() {
*/
fun launch(activity: Activity,
database: Database,
entryId: NodeId<UUID>) {
entryId: NodeId<UUID>,
activityResultLauncher: ActivityResultLauncher<Intent>) {
if (database.loaded) {
if (TimeoutHelper.checkTimeAndLockIfTimeout(activity)) {
val intent = Intent(activity, EntryActivity::class.java)
intent.putExtra(KEY_ENTRY, entryId)
activity.startActivityForResult(
intent,
EntryEditActivity.ADD_OR_UPDATE_ENTRY_REQUEST_CODE
)
activityResultLauncher.launch(intent)
}
}
}
@@ -469,16 +462,14 @@ class EntryActivity : DatabaseLockActivity() {
fun launch(activity: Activity,
database: Database,
entryId: NodeId<UUID>,
historyPosition: Int) {
historyPosition: Int,
activityResultLauncher: ActivityResultLauncher<Intent>) {
if (database.loaded) {
if (TimeoutHelper.checkTimeAndLockIfTimeout(activity)) {
val intent = Intent(activity, EntryActivity::class.java)
intent.putExtra(KEY_ENTRY, entryId)
intent.putExtra(KEY_ENTRY_HISTORY_POSITION, historyPosition)
activity.startActivityForResult(
intent,
EntryEditActivity.ADD_OR_UPDATE_ENTRY_REQUEST_CODE
)
activityResultLauncher.launch(intent)
}
}
}

View File

@@ -33,12 +33,17 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.*
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.isVisible
import androidx.core.widget.NestedScrollView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.*
@@ -96,6 +101,7 @@ class EntryEditActivity : DatabaseLockActivity(),
private var mTemplate: Template? = null
private var mIsTemplate: Boolean = false
private var mEntryLoaded: Boolean = false
private var mTemplatesSelectorAdapter: TemplatesSelectorAdapter? = null
private var mAllowCustomFields = false
private var mAllowOTP = false
@@ -106,6 +112,10 @@ class EntryEditActivity : DatabaseLockActivity(),
// Education
private var entryEditActivityEducation: EntryEditActivityEducation? = null
private var mIconSelectionActivityResultLauncher = IconPickerActivity.registerIconSelectionForResult(this) { icon ->
mEntryEditViewModel.selectIcon(icon)
}
// To ask data lost only one time
private var backPressedAlreadyApproved = false
@@ -154,6 +164,21 @@ class EntryEditActivity : DatabaseLockActivity(),
// To retrieve attachment
mExternalFileHelper = ExternalFileHelper(this)
mExternalFileHelper?.buildOpenDocument { uri ->
uri?.let { attachmentToUploadUri ->
UriUtil.getFileData(this, attachmentToUploadUri)?.also { documentFile ->
documentFile.name?.let { fileName ->
if (documentFile.length() > MAX_WARNING_BINARY_FILE) {
FileTooBigDialogFragment.build(attachmentToUploadUri, fileName)
.show(supportFragmentManager, "fileTooBigFragment")
} else {
mEntryEditViewModel.buildNewAttachment(attachmentToUploadUri, fileName)
}
}
}
}
}
mAttachmentFileBinderManager = AttachmentFileBinderManager(this)
// Verify the education views
entryEditActivityEducation = EntryEditActivityEducation(this)
@@ -175,11 +200,13 @@ class EntryEditActivity : DatabaseLockActivity(),
templateSelectorSpinner?.apply {
// Build template selector
if (templates.isNotEmpty()) {
adapter = TemplatesSelectorAdapter(
mTemplatesSelectorAdapter = TemplatesSelectorAdapter(
this@EntryEditActivity,
mIconDrawableFactory,
templates
)
).apply {
iconDrawableFactory = mIconDrawableFactory
}
adapter = mTemplatesSelectorAdapter
val selectedTemplate = if (mTemplate != null)
mTemplate
else
@@ -213,7 +240,7 @@ class EntryEditActivity : DatabaseLockActivity(),
// View model listeners
mEntryEditViewModel.requestIconSelection.observe(this) { iconImage ->
IconPickerActivity.launch(this@EntryEditActivity, iconImage)
IconPickerActivity.launch(this@EntryEditActivity, iconImage, mIconSelectionActivityResultLauncher)
}
mEntryEditViewModel.requestDateTimeSelection.observe(this) { dateInstant ->
@@ -321,6 +348,10 @@ class EntryEditActivity : DatabaseLockActivity(),
mAllowCustomFields = database?.allowEntryCustomFields() == true
mAllowOTP = database?.allowOTP == true
mEntryEditViewModel.loadDatabase(database)
mTemplatesSelectorAdapter?.apply {
iconDrawableFactory = mIconDrawableFactory
notifyDataSetChanged()
}
}
override fun onDatabaseActionFinished(
@@ -472,29 +503,6 @@ class EntryEditActivity : DatabaseLockActivity(),
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
IconPickerActivity.onActivityResult(requestCode, resultCode, data) { icon ->
mEntryEditViewModel.selectIcon(icon)
}
mExternalFileHelper?.onOpenDocumentResult(requestCode, resultCode, data) { uri ->
uri?.let { attachmentToUploadUri ->
UriUtil.getFileData(this, attachmentToUploadUri)?.also { documentFile ->
documentFile.name?.let { fileName ->
if (documentFile.length() > MAX_WARNING_BINARY_FILE) {
FileTooBigDialogFragment.build(attachmentToUploadUri, fileName)
.show(supportFragmentManager, "fileTooBigFragment")
} else {
mEntryEditViewModel.buildNewAttachment(attachmentToUploadUri, fileName)
}
}
}
}
}
}
/**
* Set up OTP (HOTP or TOTP) and add it as extra field
*/
@@ -585,7 +593,7 @@ class EntryEditActivity : DatabaseLockActivity(),
&& entryEditActivityEducation.checkAndPerformedAttachmentEducation(
attachmentView,
{
mExternalFileHelper?.openDocument()
addNewAttachment()
},
{
performedNextEducation(entryEditActivityEducation)
@@ -686,7 +694,7 @@ class EntryEditActivity : DatabaseLockActivity(),
val intentEntry = Intent()
bundle.putParcelable(ADD_OR_UPDATE_ENTRY_KEY, entry.nodeId)
intentEntry.putExtras(bundle)
setResult(ADD_OR_UPDATE_ENTRY_RESULT_CODE, intentEntry)
setResult(Activity.RESULT_OK, intentEntry)
super.finish()
} catch (e: Exception) {
// Exception when parcelable can't be done
@@ -701,23 +709,46 @@ class EntryEditActivity : DatabaseLockActivity(),
// Keys for current Activity
const val KEY_ENTRY = "entry"
const val KEY_PARENT = "parent"
// Keys for callback
const val ADD_OR_UPDATE_ENTRY_RESULT_CODE = 31
const val ADD_OR_UPDATE_ENTRY_REQUEST_CODE = 7129
const val ADD_OR_UPDATE_ENTRY_KEY = "ADD_OR_UPDATE_ENTRY_KEY"
fun registerForEntryResult(fragment: Fragment,
entryAddedOrUpdatedListener: (NodeId<UUID>?) -> Unit): ActivityResultLauncher<Intent> {
return fragment.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
entryAddedOrUpdatedListener.invoke(
result.data?.getParcelableExtra(ADD_OR_UPDATE_ENTRY_KEY)
)
} else {
entryAddedOrUpdatedListener.invoke(null)
}
}
}
fun registerForEntryResult(activity: FragmentActivity,
entryAddedOrUpdatedListener: (NodeId<UUID>?) -> Unit): ActivityResultLauncher<Intent> {
return activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
entryAddedOrUpdatedListener.invoke(
result.data?.getParcelableExtra(ADD_OR_UPDATE_ENTRY_KEY)
)
} else {
entryAddedOrUpdatedListener.invoke(null)
}
}
}
/**
* Launch EntryEditActivity to update an existing entry by his [entryId]
*/
fun launchToUpdate(activity: Activity,
database: Database,
entryId: NodeId<UUID>) {
entryId: NodeId<UUID>,
activityResultLauncher: ActivityResultLauncher<Intent>) {
if (database.loaded && !database.isReadOnly) {
if (TimeoutHelper.checkTimeAndLockIfTimeout(activity)) {
val intent = Intent(activity, EntryEditActivity::class.java)
intent.putExtra(KEY_ENTRY, entryId)
activity.startActivityForResult(intent, ADD_OR_UPDATE_ENTRY_REQUEST_CODE)
activityResultLauncher.launch(intent)
}
}
}
@@ -727,12 +758,13 @@ class EntryEditActivity : DatabaseLockActivity(),
*/
fun launchToCreate(activity: Activity,
database: Database,
groupId: NodeId<*>) {
groupId: NodeId<*>,
activityResultLauncher: ActivityResultLauncher<Intent>) {
if (database.loaded && !database.isReadOnly) {
if (TimeoutHelper.checkTimeAndLockIfTimeout(activity)) {
val intent = Intent(activity, EntryEditActivity::class.java)
intent.putExtra(KEY_PARENT, groupId)
activity.startActivityForResult(intent, ADD_OR_UPDATE_ENTRY_REQUEST_CODE)
activityResultLauncher.launch(intent)
}
}
}
@@ -795,8 +827,9 @@ class EntryEditActivity : DatabaseLockActivity(),
* Launch EntryEditActivity to add a new entry in autofill selection
*/
@RequiresApi(api = Build.VERSION_CODES.O)
fun launchForAutofillResult(activity: Activity,
fun launchForAutofillResult(activity: AppCompatActivity,
database: Database,
activityResultLauncher: ActivityResultLauncher<Intent>?,
autofillComponent: AutofillComponent,
groupId: NodeId<*>,
searchInfo: SearchInfo? = null) {
@@ -807,6 +840,7 @@ class EntryEditActivity : DatabaseLockActivity(),
AutofillHelper.startActivityForAutofillResult(
activity,
intent,
activityResultLauncher,
autofillComponent,
searchInfo
)

View File

@@ -31,8 +31,10 @@ import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.recyclerview.widget.LinearLayoutManager
@@ -85,9 +87,20 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
private var mExternalFileHelper: ExternalFileHelper? = null
private var mAutofillActivityResultLauncher: ActivityResultLauncher<Intent>? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
AutofillHelper.buildActivityResultLauncher(this)
else null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Enabling/disabling MagikeyboardService is normally done by DexModeReceiver, but this
// additional check will allow the keyboard to be reenabled more easily if the app crashes
// or is force quit within DeX mode and then the user leaves DeX mode. Without this, the
// user would need to enter and exit DeX mode once to reenable the service.
MagikeyboardUtil.setEnabled(this, !DexUtil.isDexMode(resources.configuration))
mFileDatabaseHistoryAction = FileDatabaseHistoryAction.getInstance(applicationContext)
setContentView(R.layout.activity_file_selection)
@@ -103,6 +116,22 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
// Open database button
mExternalFileHelper = ExternalFileHelper(this)
mExternalFileHelper?.buildOpenDocument { uri ->
uri?.let {
launchPasswordActivityWithPath(uri)
}
}
mExternalFileHelper?.buildCreateDocument("application/x-keepass") { databaseFileCreatedUri ->
mDatabaseFileUri = databaseFileCreatedUri
if (mDatabaseFileUri != null) {
AssignMasterKeyDialogFragment.getInstance(true)
.show(supportFragmentManager, "passwordDialog")
} else {
val error = getString(R.string.error_create_database)
Snackbar.make(coordinatorLayout, error, Snackbar.LENGTH_LONG).asError().show()
Log.e(TAG, error)
}
}
openDatabaseButtonView = findViewById(R.id.open_keyfile_button)
openDatabaseButtonView?.setOpenDocumentClickListener(mExternalFileHelper)
@@ -250,8 +279,9 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
* Create a new file by calling the content provider
*/
private fun createNewFile() {
mExternalFileHelper?.createDocument( getString(R.string.database_file_name_default) +
getString(R.string.database_file_extension_default), "application/x-keepass")
mExternalFileHelper?.createDocument(
getString(R.string.database_file_name_default) +
getString(R.string.database_file_extension_default))
}
private fun fileNoFoundAction(e: FileNotFoundException) {
@@ -268,7 +298,8 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
fileNoFoundAction(exception)
},
{ onCancelSpecialMode() },
{ onLaunchActivitySpecialMode() })
{ onLaunchActivitySpecialMode() },
mAutofillActivityResultLauncher)
}
private fun launchGroupActivityIfLoaded(database: Database) {
@@ -277,7 +308,8 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
database,
{ onValidateSpecialMode() },
{ onCancelSpecialMode() },
{ onLaunchActivitySpecialMode() })
{ onLaunchActivitySpecialMode() },
mAutofillActivityResultLauncher)
}
}
@@ -353,33 +385,6 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
override fun onAssignKeyDialogNegativeClick(mainCredential: MainCredential) {}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data)
}
mExternalFileHelper?.onOpenDocumentResult(requestCode, resultCode, data) { uri ->
if (uri != null) {
launchPasswordActivityWithPath(uri)
}
}
// Retrieve the created URI from the file manager
mExternalFileHelper?.onCreateDocumentResult(requestCode, resultCode, data) { databaseFileCreatedUri ->
mDatabaseFileUri = databaseFileCreatedUri
if (mDatabaseFileUri != null) {
AssignMasterKeyDialogFragment.getInstance(true)
.show(supportFragmentManager, "passwordDialog")
} else {
val error = getString(R.string.error_create_database)
Snackbar.make(coordinatorLayout, error, Snackbar.LENGTH_LONG).asError().show()
Log.e(TAG, error)
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
@@ -493,11 +498,13 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
*/
@RequiresApi(api = Build.VERSION_CODES.O)
fun launchForAutofillResult(activity: Activity,
fun launchForAutofillResult(activity: AppCompatActivity,
activityResultLauncher: ActivityResultLauncher<Intent>?,
autofillComponent: AutofillComponent,
searchInfo: SearchInfo? = null) {
AutofillHelper.startActivityForAutofillResult(activity,
Intent(activity, FileDatabaseSelectActivity::class.java),
activityResultLauncher,
autofillComponent,
searchInfo)
}

View File

@@ -33,8 +33,10 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar
@@ -111,6 +113,16 @@ class GroupActivity : DatabaseLockActivity(),
private var mSearchSuggestionAdapter: SearchEntryCursorAdapter? = null
private var mOnSuggestionListener: SearchView.OnSuggestionListener? = null
private var mIconSelectionActivityResultLauncher = IconPickerActivity.registerIconSelectionForResult(this) { icon ->
// To create tree dialog for icon
mGroupEditViewModel.selectIcon(icon)
}
private var mAutofillActivityResultLauncher: ActivityResultLauncher<Intent>? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
AutofillHelper.buildActivityResultLauncher(this)
else null
private var mIconColor: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
@@ -211,11 +223,14 @@ class GroupActivity : DatabaseLockActivity(),
mDatabase?.let { database ->
EntrySelectionHelper.doSpecialAction(intent,
{
EntryEditActivity.launchToCreate(
this@GroupActivity,
database,
currentGroup.nodeId
)
mGroupFragment?.mEntryActivityResultLauncher?.let { resultLauncher ->
EntryEditActivity.launchToCreate(
this@GroupActivity,
database,
currentGroup.nodeId,
resultLauncher
)
}
},
{
// Search not used
@@ -243,6 +258,7 @@ class GroupActivity : DatabaseLockActivity(),
EntryEditActivity.launchForAutofillResult(
this@GroupActivity,
database,
mAutofillActivityResultLauncher,
autofillComponent,
currentGroup.nodeId,
searchInfo
@@ -277,7 +293,7 @@ class GroupActivity : DatabaseLockActivity(),
}
mGroupEditViewModel.requestIconSelection.observe(this) { iconImage ->
IconPickerActivity.launch(this@GroupActivity, iconImage)
IconPickerActivity.launch(this@GroupActivity, iconImage, mIconSelectionActivityResultLauncher)
}
mGroupEditViewModel.requestDateTimeSelection.observe(this) { dateInstant ->
@@ -594,11 +610,14 @@ class GroupActivity : DatabaseLockActivity(),
val entryVersioned = node as Entry
EntrySelectionHelper.doSpecialAction(intent,
{
EntryActivity.launch(
this@GroupActivity,
database,
entryVersioned.nodeId
)
mGroupFragment?.mEntryActivityResultLauncher?.let { resultLauncher ->
EntryActivity.launch(
this@GroupActivity,
database,
entryVersioned.nodeId,
resultLauncher
)
}
},
{
// Nothing here, a search is simply performed
@@ -653,6 +672,8 @@ class GroupActivity : DatabaseLockActivity(),
Log.e(TAG, "Node can't be cast in Entry")
}
}
reloadGroupIfSearch()
}
private fun entrySelectedForSave(database: Database, entry: Entry, searchInfo: SearchInfo) {
@@ -738,6 +759,12 @@ class GroupActivity : DatabaseLockActivity(),
actionNodeMode?.finish()
}
private fun reloadGroupIfSearch() {
if (Intent.ACTION_SEARCH == intent.action) {
reloadCurrentGroup()
}
}
override fun onNodeSelected(
database: Database,
nodes: List<Node>
@@ -787,12 +814,18 @@ class GroupActivity : DatabaseLockActivity(),
GroupEditDialogFragment.TAG_CREATE_GROUP
)
}
Type.ENTRY -> EntryEditActivity.launchToUpdate(
this@GroupActivity,
database,
(node as Entry).nodeId
)
Type.ENTRY -> {
mGroupFragment?.mEntryActivityResultLauncher?.let { resultLauncher ->
EntryEditActivity.launchToUpdate(
this@GroupActivity,
database,
(node as Entry).nodeId,
resultLauncher
)
}
}
}
reloadGroupIfSearch()
return true
}
@@ -847,6 +880,7 @@ class GroupActivity : DatabaseLockActivity(),
): Boolean {
deleteNodes(nodes)
finishNodeAction()
reloadGroupIfSearch()
return true
}
@@ -1047,6 +1081,7 @@ class GroupActivity : DatabaseLockActivity(),
}
}
@Suppress("DEPRECATION")
override fun startActivityForResult(intent: Intent, requestCode: Int, options: Bundle?) {
/*
* ACTION_SEARCH automatically forces a new task. This occurs when you open a kdb file in
@@ -1062,22 +1097,6 @@ class GroupActivity : DatabaseLockActivity(),
super.startActivityForResult(intent, requestCode, options)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// To create tree dialog for icon
IconPickerActivity.onActivityResult(requestCode, resultCode, data) { icon ->
mGroupEditViewModel.selectIcon(icon)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data)
}
// Directly used the onActivityResult in fragment
mGroupFragment?.onActivityResult(requestCode, resultCode, data)
}
private fun removeSearch() {
intent.removeExtra(AUTO_SEARCH_KEY)
if (Intent.ACTION_SEARCH == intent.action) {
@@ -1093,7 +1112,7 @@ class GroupActivity : DatabaseLockActivity(),
try {
mGroupViewModel.loadGroup(mDatabase, mCurrentGroupState)
} catch (e: Exception) {
Log.e(TAG, "Unable to rebuild the list after deletion", e)
Log.e(TAG, "Unable to rebuild the group", e)
}
}
@@ -1282,8 +1301,9 @@ class GroupActivity : DatabaseLockActivity(),
* -------------------------
*/
@RequiresApi(api = Build.VERSION_CODES.O)
fun launchForAutofillResult(activity: Activity,
fun launchForAutofillResult(activity: AppCompatActivity,
database: Database,
activityResultLaunch: ActivityResultLauncher<Intent>?,
autofillComponent: AutofillComponent,
searchInfo: SearchInfo? = null,
autoSearch: Boolean = false) {
@@ -1293,6 +1313,7 @@ class GroupActivity : DatabaseLockActivity(),
AutofillHelper.startActivityForAutofillResult(
activity,
intent,
activityResultLaunch,
autofillComponent,
searchInfo
)
@@ -1325,11 +1346,12 @@ class GroupActivity : DatabaseLockActivity(),
* Global Launch
* -------------------------
*/
fun launch(activity: Activity,
fun launch(activity: AppCompatActivity,
database: Database,
onValidateSpecialMode: () -> Unit,
onCancelSpecialMode: () -> Unit,
onLaunchActivitySpecialMode: () -> Unit) {
onLaunchActivitySpecialMode: () -> Unit,
autofillActivityResultLauncher: ActivityResultLauncher<Intent>?) {
EntrySelectionHelper.doSpecialAction(activity.intent,
{
GroupActivity.launch(
@@ -1441,6 +1463,7 @@ class GroupActivity : DatabaseLockActivity(),
// Here no search info found, disable auto search
GroupActivity.launchForAutofillResult(activity,
database,
autofillActivityResultLauncher,
autofillComponent,
searchInfo,
false)

View File

@@ -27,12 +27,16 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.commit
import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.IconEditDialogFragment
import com.kunzisoft.keepass.activities.fragments.IconPickerFragment
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener
@@ -81,6 +85,9 @@ class IconPickerActivity : DatabaseLockActivity() {
coordinatorLayout = findViewById(R.id.icon_picker_coordinator)
mExternalFileHelper = ExternalFileHelper(this)
mExternalFileHelper?.buildOpenDocument { uri ->
addCustomIcon(uri)
}
uploadButton = findViewById(R.id.icon_picker_upload)
@@ -139,6 +146,16 @@ class IconPickerActivity : DatabaseLockActivity() {
}
uploadButton.isEnabled = true
}
iconPickerViewModel.customIconUpdated.observe(this) { iconCustomUpdated ->
if (iconCustomUpdated.error && !iconCustomUpdated.errorConsumed) {
Snackbar.make(coordinatorLayout, iconCustomUpdated.errorStringId, Snackbar.LENGTH_LONG).asError().show()
iconCustomUpdated.errorConsumed = true
}
iconCustomUpdated.iconCustom?.let {
mDatabase?.updateCustomIcon(it)
}
iconPickerViewModel.deselectAllCustomIcons()
}
}
override fun viewToInvalidateTimeout(): View? {
@@ -197,6 +214,10 @@ class IconPickerActivity : DatabaseLockActivity() {
}
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
menu?.findItem(R.id.menu_edit)?.apply {
isEnabled = mIconsSelected.size == 1
isVisible = isEnabled
}
menu?.findItem(R.id.menu_delete)?.apply {
isEnabled = mCustomIconsSelectionMode
isVisible = isEnabled
@@ -213,6 +234,9 @@ class IconPickerActivity : DatabaseLockActivity() {
onBackPressed()
}
}
R.id.menu_edit -> {
updateCustomIcon(mIconsSelected[0])
}
R.id.menu_delete -> {
mIconsSelected.forEach { iconToRemove ->
removeCustomIcon(iconToRemove)
@@ -277,6 +301,11 @@ class IconPickerActivity : DatabaseLockActivity() {
}
}
private fun updateCustomIcon(iconImageCustom: IconImageCustom) {
IconEditDialogFragment.update(iconImageCustom)
.show(supportFragmentManager, IconEditDialogFragment.TAG_UPDATE_ICON)
}
private fun removeCustomIcon(iconImageCustom: IconImageCustom) {
uploadButton.isEnabled = false
iconPickerViewModel.deselectAllCustomIcons()
@@ -286,14 +315,6 @@ class IconPickerActivity : DatabaseLockActivity() {
)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
mExternalFileHelper?.onOpenDocumentResult(requestCode, resultCode, data) { uri ->
addCustomIcon(uri)
}
}
private fun setResult() {
setResult(Activity.RESULT_OK, Intent().apply {
putExtra(EXTRA_ICON, mIconImage)
@@ -308,30 +329,28 @@ class IconPickerActivity : DatabaseLockActivity() {
companion object {
private const val ICON_PICKER_FRAGMENT_TAG = "ICON_PICKER_FRAGMENT_TAG"
private const val ICON_SELECTED_REQUEST = 15861
private const val EXTRA_ICON = "EXTRA_ICON"
private const val MAX_ICON_SIZE = 5242880
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?, listener: (icon: IconImage) -> Unit) {
if (requestCode == ICON_SELECTED_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
listener.invoke(data?.getParcelableExtra(EXTRA_ICON) ?: IconImage())
fun registerIconSelectionForResult(context: FragmentActivity,
listener: (icon: IconImage) -> Unit): ActivityResultLauncher<Intent> {
return context.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
listener.invoke(result.data?.getParcelableExtra(EXTRA_ICON) ?: IconImage())
}
}
}
fun launch(context: Activity,
previousIcon: IconImage?) {
fun launch(context: FragmentActivity,
previousIcon: IconImage?,
resultLauncher: ActivityResultLauncher<Intent>) {
// Create an instance to return the picker icon
context.startActivityForResult(
Intent(context,
IconPickerActivity::class.java).apply {
resultLauncher.launch(
Intent(context, IconPickerActivity::class.java).apply {
if (previousIcon != null)
putExtra(EXTRA_ICON, previousIcon)
},
ICON_SELECTED_REQUEST)
}
)
}
}
}

View File

@@ -35,9 +35,10 @@ import android.view.KeyEvent.KEYCODE_ENTER
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE
import android.view.inputmethod.InputMethodManager
import android.widget.*
import android.widget.TextView.OnEditorActionListener
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.app.ActivityCompat
@@ -71,11 +72,12 @@ import com.kunzisoft.keepass.utils.MenuUtil
import com.kunzisoft.keepass.utils.UriUtil
import com.kunzisoft.keepass.view.KeyFileSelectionView
import com.kunzisoft.keepass.view.asError
import com.kunzisoft.keepass.viewmodels.AdvancedUnlockViewModel
import com.kunzisoft.keepass.viewmodels.DatabaseFileViewModel
import java.io.FileNotFoundException
open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.BuilderListener {
class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.BuilderListener {
// Views
private var toolbar: Toolbar? = null
@@ -89,7 +91,8 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
private lateinit var coordinatorLayout: CoordinatorLayout
private var advancedUnlockFragment: AdvancedUnlockFragment? = null
private val databaseFileViewModel: DatabaseFileViewModel by viewModels()
private val mDatabaseFileViewModel: DatabaseFileViewModel by viewModels()
private val mAdvancedUnlockViewModel: AdvancedUnlockViewModel by viewModels()
private var mDefaultDatabase: Boolean = false
private var mDatabaseFileUri: Uri? = null
@@ -111,7 +114,10 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
field = value
}
private var mAllowAutoOpenBiometricPrompt: Boolean = true
private var mAutofillActivityResultLauncher: ActivityResultLauncher<Intent>? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
AutofillHelper.buildActivityResultLauncher(this)
else null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -142,6 +148,12 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
mExternalFileHelper = ExternalFileHelper(this@PasswordActivity)
mExternalFileHelper?.buildOpenDocument { uri ->
if (uri != null) {
mDatabaseKeyFileUri = uri
populateKeyFileTextView(uri)
}
}
keyFileSelectionView?.setOpenDocumentClickListener(mExternalFileHelper)
passwordView?.setOnEditorActionListener(onEditorActionListener)
@@ -170,9 +182,6 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
if (savedInstanceState?.containsKey(KEY_KEYFILE) == true) {
mDatabaseKeyFileUri = UriUtil.parse(savedInstanceState.getString(KEY_KEYFILE))
}
if (savedInstanceState?.containsKey(ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT) == true) {
mAllowAutoOpenBiometricPrompt = savedInstanceState.getBoolean(ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT)
}
// Init Biometric elements
advancedUnlockFragment = supportFragmentManager
@@ -188,17 +197,17 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
// Listen password checkbox to init advanced unlock and confirmation button
checkboxPasswordView?.setOnCheckedChangeListener { _, _ ->
advancedUnlockFragment?.checkUnlockAvailability()
mAdvancedUnlockViewModel.checkUnlockAvailability()
enableOrNotTheConfirmationButton()
}
// Observe if default database
databaseFileViewModel.isDefaultDatabase.observe(this) { isDefaultDatabase ->
mDatabaseFileViewModel.isDefaultDatabase.observe(this) { isDefaultDatabase ->
mDefaultDatabase = isDefaultDatabase
}
// Observe database file change
databaseFileViewModel.databaseFileLoaded.observe(this) { databaseFile ->
mDatabaseFileViewModel.databaseFileLoaded.observe(this) { databaseFile ->
// Force read only if the file does not exists
mForceReadOnly = databaseFile?.let {
!it.databaseFileExists
@@ -232,12 +241,12 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
}
// Don't allow auto open prompt if lock become when UI visible
mAllowAutoOpenBiometricPrompt = if (DatabaseLockActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK == true)
false
else
mAllowAutoOpenBiometricPrompt
if (DatabaseLockActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK == true) {
mAdvancedUnlockViewModel.allowAutoOpenBiometricPrompt = false
}
mDatabaseFileUri?.let { databaseFileUri ->
databaseFileViewModel.loadDatabaseFile(databaseFileUri)
mDatabaseFileViewModel.loadDatabaseFile(databaseFileUri)
}
checkPermission()
@@ -263,7 +272,7 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
when (actionTask) {
ACTION_DATABASE_LOAD_TASK -> {
// Recheck advanced unlock if error
advancedUnlockFragment?.initAdvancedUnlockMode()
mAdvancedUnlockViewModel.initAdvancedUnlockMode()
if (result.isSuccess) {
launchGroupActivityIfLoaded(database)
@@ -311,7 +320,7 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
is FileNotFoundDatabaseException -> {
// Remove this default database inaccessible
if (mDefaultDatabase) {
databaseFileViewModel.removeDefaultDatabase()
mDatabaseFileViewModel.removeDefaultDatabase()
}
}
}
@@ -344,7 +353,7 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
mDatabaseKeyFileUri = intent?.getParcelableExtra(KEY_KEYFILE)
}
mDatabaseFileUri?.let {
databaseFileViewModel.checkIfIsDefaultDatabase(it)
mDatabaseFileViewModel.checkIfIsDefaultDatabase(it)
}
}
@@ -361,7 +370,8 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
database,
{ onValidateSpecialMode() },
{ onCancelSpecialMode() },
{ onLaunchActivitySpecialMode() }
{ onLaunchActivitySpecialMode() },
mAutofillActivityResultLauncher
)
}
}
@@ -435,8 +445,7 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
verifyCheckboxesAndLoadDatabase(password, keyFileUri)
} else {
// Init Biometric elements
advancedUnlockFragment?.loadDatabase(databaseFileUri,
mAllowAutoOpenBiometricPrompt)
mAdvancedUnlockViewModel.databaseFileLoaded(databaseFileUri)
}
enableOrNotTheConfirmationButton()
@@ -496,7 +505,6 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
override fun onPause() {
// Reinit locking activity UI variable
DatabaseLockActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = null
mAllowAutoOpenBiometricPrompt = true
super.onPause()
}
@@ -507,7 +515,6 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
outState.putString(KEY_KEYFILE, it.toString())
}
outState.putBoolean(KEY_READ_ONLY, mReadOnly)
outState.putBoolean(ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT, false)
super.onSaveInstanceState(outState)
}
@@ -709,45 +716,6 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
return super.onOptionsItemSelected(item)
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
mAllowAutoOpenBiometricPrompt = false
// To get device credential unlock result
advancedUnlockFragment?.onActivityResult(requestCode, resultCode, data)
// To get entry in result
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data)
}
var keyFileResult = false
mExternalFileHelper?.let {
keyFileResult = it.onOpenDocumentResult(requestCode, resultCode, data) { uri ->
if (uri != null) {
mDatabaseKeyFileUri = uri
populateKeyFileTextView(uri)
}
}
}
if (!keyFileResult) {
// this block if not a key file response
when (resultCode) {
DatabaseLockActivity.RESULT_EXIT_LOCK -> {
clearCredentialsViews()
closeDatabase()
}
Activity.RESULT_CANCELED -> {
clearCredentialsViews()
}
}
}
}
companion object {
private val TAG = PasswordActivity::class.java.name
@@ -764,8 +732,6 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
private const val KEY_PERMISSION_ASKED = "KEY_PERMISSION_ASKED"
private const val WRITE_EXTERNAL_STORAGE_REQUEST = 647
private const val ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT = "ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT"
private fun buildAndLaunchIntent(activity: Activity, databaseFile: Uri, keyFile: Uri?,
intentBuildLauncher: (Intent) -> Unit) {
val intent = Intent(activity, PasswordActivity::class.java)
@@ -855,15 +821,17 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
@RequiresApi(api = Build.VERSION_CODES.O)
@Throws(FileNotFoundException::class)
fun launchForAutofillResult(activity: Activity,
fun launchForAutofillResult(activity: AppCompatActivity,
databaseFile: Uri,
keyFile: Uri?,
activityResultLauncher: ActivityResultLauncher<Intent>?,
autofillComponent: AutofillComponent,
searchInfo: SearchInfo?) {
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
AutofillHelper.startActivityForAutofillResult(
activity,
intent,
activityResultLauncher,
autofillComponent,
searchInfo)
}
@@ -891,12 +859,13 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
* Global Launch
* -------------------------
*/
fun launch(activity: Activity,
fun launch(activity: AppCompatActivity,
databaseUri: Uri,
keyFile: Uri?,
fileNoFoundAction: (exception: FileNotFoundException) -> Unit,
onCancelSpecialMode: () -> Unit,
onLaunchActivitySpecialMode: () -> Unit) {
onLaunchActivitySpecialMode: () -> Unit,
autofillActivityResultLauncher: ActivityResultLauncher<Intent>?) {
try {
EntrySelectionHelper.doSpecialAction(activity.intent,
@@ -926,6 +895,7 @@ open class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bui
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PasswordActivity.launchForAutofillResult(activity,
databaseUri, keyFile,
autofillActivityResultLauncher,
autofillComponent,
searchInfo)
onLaunchActivitySpecialMode()

View File

@@ -22,7 +22,6 @@ package com.kunzisoft.keepass.activities.dialogs
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.Editable
@@ -133,6 +132,18 @@ class AssignMasterKeyDialogFragment : DatabaseDialogFragment() {
keyFileSelectionView = rootView?.findViewById(R.id.keyfile_selection)
mExternalFileHelper = ExternalFileHelper(this)
mExternalFileHelper?.buildOpenDocument { uri ->
uri?.let { pathUri ->
UriUtil.getFileData(requireContext(), uri)?.length()?.let { lengthFile ->
keyFileSelectionView?.error = null
keyFileCheckBox?.isChecked = true
keyFileSelectionView?.uri = pathUri
if (lengthFile <= 0L) {
showEmptyKeyFileConfirmationDialog()
}
}
}
}
keyFileSelectionView?.setOpenDocumentClickListener(mExternalFileHelper)
val dialog = builder.create()
@@ -208,7 +219,11 @@ class AssignMasterKeyDialogFragment : DatabaseDialogFragment() {
passwordRepeatTextInputLayout?.error = getString(R.string.error_pass_match)
}
if (mMasterPassword == null || mMasterPassword!!.isEmpty()) {
if ((mMasterPassword == null
|| mMasterPassword!!.isEmpty())
&& (keyFileCheckBox == null
|| !keyFileCheckBox!!.isChecked
|| keyFileSelectionView?.uri == null)) {
error = true
showEmptyPasswordConfirmationDialog()
}
@@ -282,23 +297,6 @@ class AssignMasterKeyDialogFragment : DatabaseDialogFragment() {
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
mExternalFileHelper?.onOpenDocumentResult(requestCode, resultCode, data) { uri ->
uri?.let { pathUri ->
UriUtil.getFileData(requireContext(), uri)?.length()?.let { lengthFile ->
keyFileSelectionView?.error = null
keyFileCheckBox?.isChecked = true
keyFileSelectionView?.uri = pathUri
if (lengthFile <= 0L) {
showEmptyKeyFileConfirmationDialog()
}
}
}
}
}
companion object {
private const val ALLOW_NO_MASTER_KEY_ARG = "ALLOW_NO_MASTER_KEY_ARG"

View File

@@ -29,6 +29,7 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
}
}
@Suppress("DEPRECATION")
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)

View File

@@ -0,0 +1,126 @@
/*
* Copyright 2021 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
* KeePassDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePassDX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.activities.dialogs
import android.app.Dialog
import android.os.Bundle
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.activityViewModels
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.DateInstant
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
import com.kunzisoft.keepass.viewmodels.IconPickerViewModel
class IconEditDialogFragment : DatabaseDialogFragment() {
private val mIconPickerViewModel: IconPickerViewModel by activityViewModels()
private var mPopulateIconMethod: ((ImageView, IconImage) -> Unit)? = null
private lateinit var iconView: ImageView
private lateinit var nameTextLayoutView: TextInputLayout
private lateinit var nameTextView: TextView
private var mCustomIcon: IconImageCustom? = null
override fun onDatabaseRetrieved(database: Database?) {
super.onDatabaseRetrieved(database)
mPopulateIconMethod = { imageView, icon ->
database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon)
}
mCustomIcon?.let { customIcon ->
populateViewsWithCustomIcon(customIcon)
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
activity?.let { activity ->
val root = activity.layoutInflater.inflate(R.layout.fragment_icon_edit, null)
iconView = root.findViewById(R.id.icon_edit_image)
nameTextLayoutView = root.findViewById(R.id.icon_edit_name_container)
nameTextView = root.findViewById(R.id.icon_edit_name)
if (savedInstanceState != null
&& savedInstanceState.containsKey(KEY_CUSTOM_ICON_ID)) {
mCustomIcon = savedInstanceState.getParcelable(KEY_CUSTOM_ICON_ID) ?: mCustomIcon
} else {
arguments?.apply {
if (containsKey(KEY_CUSTOM_ICON_ID)) {
mCustomIcon = getParcelable(KEY_CUSTOM_ICON_ID) ?: mCustomIcon
}
}
}
val builder = AlertDialog.Builder(activity)
builder.setView(root)
.setPositiveButton(android.R.string.ok) { _, _ ->
retrieveIconInfoFromViews()
mCustomIcon?.let { customIcon ->
mIconPickerViewModel.updateCustomIcon(
IconPickerViewModel.IconCustomState(customIcon, false)
)
}
}
.setNegativeButton(android.R.string.cancel) { _, _ ->
// Do nothing
mIconPickerViewModel.updateCustomIcon(
IconPickerViewModel.IconCustomState(null, false)
)
}
return builder.create()
}
return super.onCreateDialog(savedInstanceState)
}
private fun populateViewsWithCustomIcon(customIcon: IconImageCustom) {
mPopulateIconMethod?.invoke(iconView, customIcon.getIconImageToDraw())
nameTextView.text = customIcon.name
}
private fun retrieveIconInfoFromViews() {
mCustomIcon?.name = nameTextView.text.toString()
mCustomIcon?.lastModificationTime = DateInstant()
}
override fun onSaveInstanceState(outState: Bundle) {
retrieveIconInfoFromViews()
outState.putParcelable(KEY_CUSTOM_ICON_ID, mCustomIcon)
super.onSaveInstanceState(outState)
}
companion object {
const val TAG_UPDATE_ICON = "TAG_UPDATE_ICON"
const val KEY_CUSTOM_ICON_ID = "KEY_CUSTOM_ICON_ID"
fun update(customIcon: IconImageCustom): IconEditDialogFragment {
val bundle = Bundle()
bundle.putParcelable(KEY_CUSTOM_ICON_ID, IconImageCustom(customIcon))
val fragment = IconEditDialogFragment()
fragment.arguments = bundle
return fragment
}
}
}

View File

@@ -309,7 +309,7 @@ class SetOTPDialogFragment : DatabaseDialogFragment() {
override fun afterTextChanged(s: Editable?) {
s?.toString()?.let { userString ->
try {
mOtpElement.setBase32Secret(userString.toUpperCase(Locale.ENGLISH))
mOtpElement.setBase32Secret(userString.uppercase(Locale.ENGLISH))
otpSecretContainer?.error = null
} catch (exception: Exception) {
otpSecretContainer?.error = getString(R.string.error_otp_secret_key)

View File

@@ -74,6 +74,19 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
private var mRecycleBinEnable: Boolean = false
private var mRecycleBin: Group? = null
var mEntryActivityResultLauncher = EntryEditActivity.registerForEntryResult(this) { entryId ->
entryId?.let {
// Simply refresh the list
rebuildList()
// Scroll to the new entry
mDatabase?.getEntryById(it)?.let { entry ->
mAdapter?.indexOf(entry)?.let { position ->
mNodesRecyclerView?.scrollToPosition(position)
}
}
} ?: Log.e(this.javaClass.name, "Entry cannot be retrieved in Activity Result")
}
private var mRecycleViewScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
@@ -399,27 +412,6 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
EntryEditActivity.ADD_OR_UPDATE_ENTRY_REQUEST_CODE -> {
if (resultCode == EntryEditActivity.ADD_OR_UPDATE_ENTRY_RESULT_CODE) {
data?.getParcelableExtra<NodeId<UUID>>(EntryEditActivity.ADD_OR_UPDATE_ENTRY_KEY)?.let {
// Simply refresh the list
rebuildList()
// Scroll to the new entry
mDatabase?.getEntryById(it)?.let { entry ->
mAdapter?.indexOf(entry)?.let { position ->
mNodesRecyclerView?.scrollToPosition(position)
}
}
} ?: Log.e(this.javaClass.name, "Entry cannot be retrieved in Activity Result")
}
}
}
}
/**
* Callback listener to redefine to do an action when a node is click
*/

View File

@@ -55,8 +55,10 @@ class IconCustomFragment : IconFragment<IconImageCustom>() {
iconCustomAdded?.iconCustom?.let { icon ->
iconPickerAdapter.addIcon(icon)
iconCustomAdded.iconCustom = null
try {
iconsGridView.smoothScrollToPosition(iconPickerAdapter.lastPosition)
} catch (ignore: Exception) {}
}
iconsGridView.smoothScrollToPosition(iconPickerAdapter.lastPosition)
}
}
iconPickerViewModel.customIconRemoved.observe(viewLifecycleOwner) { iconCustomRemoved ->
@@ -67,6 +69,14 @@ class IconCustomFragment : IconFragment<IconImageCustom>() {
}
}
}
iconPickerViewModel.customIconUpdated.observe(viewLifecycleOwner) { iconCustomUpdated ->
if (!iconCustomUpdated.error) {
iconCustomUpdated?.iconCustom?.let { icon ->
iconPickerAdapter.updateIcon(icon)
iconCustomUpdated.iconCustom = null
}
}
}
}
override fun onIconClickListener(icon: IconImageCustom) {

View File

@@ -20,14 +20,16 @@
package com.kunzisoft.keepass.activities.helpers
import android.annotation.SuppressLint
import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.util.Log
import android.view.View
import androidx.annotation.RequiresApi
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.kunzisoft.keepass.activities.dialogs.FileManagerDialogFragment
@@ -38,6 +40,10 @@ class ExternalFileHelper {
private var activity: FragmentActivity? = null
private var fragment: Fragment? = null
private var getContentResultLauncher: ActivityResultLauncher<String>? = null
private var openDocumentResultLauncher: ActivityResultLauncher<Array<String>>? = null
private var createDocumentResultLauncher: ActivityResultLauncher<String>? = null
constructor(context: FragmentActivity) {
this.activity = context
this.fragment = null
@@ -48,94 +54,81 @@ class ExternalFileHelper {
this.fragment = context
}
fun buildOpenDocument(onFileSelected: ((uri: Uri?) -> Unit)?) {
val resultCallback = ActivityResultCallback<Uri> { result ->
result?.let { uri ->
UriUtil.takeUriPermission(activity?.contentResolver, uri)
onFileSelected?.invoke(uri)
}
}
getContentResultLauncher = if (fragment != null) {
fragment?.registerForActivityResult(
GetContent(),
resultCallback
)
} else {
activity?.registerForActivityResult(
GetContent(),
resultCallback
)
}
openDocumentResultLauncher = if (fragment != null) {
fragment?.registerForActivityResult(
OpenDocument(),
resultCallback
)
} else {
activity?.registerForActivityResult(
OpenDocument(),
resultCallback
)
}
}
fun buildCreateDocument(typeString: String = "application/octet-stream",
onFileCreated: (fileCreated: Uri?)->Unit) {
val resultCallback = ActivityResultCallback<Uri> { result ->
onFileCreated.invoke(result)
}
createDocumentResultLauncher = if (fragment != null) {
fragment?.registerForActivityResult(
CreateDocument(typeString),
resultCallback
)
} else {
activity?.registerForActivityResult(
CreateDocument(typeString),
resultCallback
)
}
}
fun openDocument(getContent: Boolean = false,
typeString: String = "*/*") {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
if (getContent) {
openActivityWithActionGetContent(typeString)
} else {
openActivityWithActionOpenDocument(typeString)
}
} catch (e: Exception) {
Log.e(TAG, "Unable to open document", e)
showFileManagerDialogFragment()
try {
if (getContent) {
getContentResultLauncher?.launch(typeString)
} else {
openDocumentResultLauncher?.launch(arrayOf(typeString))
}
} else {
} catch (e: Exception) {
Log.e(TAG, "Unable to open document", e)
showFileManagerDialogFragment()
}
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
private fun openActivityWithActionOpenDocument(typeString: String) {
val intentOpenDocument = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
}
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
fun createDocument(titleString: String) {
try {
createDocumentResultLauncher?.launch(titleString)
} catch (e: Exception) {
Log.e(TAG, "Unable to create document", e)
showFileManagerDialogFragment()
}
if (fragment != null)
fragment?.startActivityForResult(intentOpenDocument, OPEN_DOC)
else
activity?.startActivityForResult(intentOpenDocument, OPEN_DOC)
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
private fun openActivityWithActionGetContent(typeString: String) {
val intentGetContent = Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
}
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
if (fragment != null)
fragment?.startActivityForResult(intentGetContent, GET_CONTENT)
else
activity?.startActivityForResult(intentGetContent, GET_CONTENT)
}
/**
* To use in onActivityResultCallback in Fragment or Activity
* @param onFileSelected Callback retrieve from data
* @return true if requestCode was captured, false elsewhere
*/
fun onOpenDocumentResult(requestCode: Int, resultCode: Int, data: Intent?,
onFileSelected: ((uri: Uri?) -> Unit)?): Boolean {
when (requestCode) {
FILE_BROWSE -> {
if (resultCode == RESULT_OK) {
val filename = data?.dataString
var keyUri: Uri? = null
if (filename != null) {
keyUri = UriUtil.parse(filename)
}
onFileSelected?.invoke(keyUri)
}
return true
}
GET_CONTENT, OPEN_DOC -> {
if (resultCode == RESULT_OK) {
if (data != null) {
val uri = data.data
if (uri != null) {
UriUtil.takeUriPermission(activity?.contentResolver, uri)
onFileSelected?.invoke(uri)
}
}
}
return true
}
}
return false
}
/**
@@ -155,62 +148,50 @@ class ExternalFileHelper {
}
}
fun createDocument(titleString: String,
typeString: String = "application/octet-stream"): Int? {
val idCode = getUnusedCreateFileRequestCode()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
putExtra(Intent.EXTRA_TITLE, titleString)
class OpenDocument : ActivityResultContracts.OpenDocument() {
@SuppressLint("InlinedApi")
override fun createIntent(context: Context, input: Array<out String>): Intent {
return super.createIntent(context, input).apply {
addCategory(Intent.CATEGORY_OPENABLE)
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
}
if (fragment != null)
fragment?.startActivityForResult(intent, idCode)
else
activity?.startActivityForResult(intent, idCode)
return idCode
} catch (e: Exception) {
Log.e(TAG, "Unable to create document", e)
showFileManagerDialogFragment()
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
} else {
showFileManagerDialogFragment()
}
return null
}
/**
* To use in onActivityResultCallback in Fragment or Activity
* @param onFileCreated Callback retrieve from data
* @return true if requestCode was captured, false elsewhere
*/
fun onCreateDocumentResult(requestCode: Int, resultCode: Int, data: Intent?,
onFileCreated: (fileCreated: Uri?)->Unit) {
// Retrieve the created URI from the file manager
if (fileRequestCodes.contains(requestCode) && resultCode == RESULT_OK) {
onFileCreated.invoke(data?.data)
fileRequestCodes.remove(requestCode)
class GetContent : ActivityResultContracts.GetContent() {
@SuppressLint("InlinedApi")
override fun createIntent(context: Context, input: String): Intent {
return super.createIntent(context, input).apply {
addCategory(Intent.CATEGORY_OPENABLE)
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
}
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
}
}
class CreateDocument(private val typeString: String) : ActivityResultContracts.CreateDocument() {
override fun createIntent(context: Context, input: String): Intent {
return super.createIntent(context, input).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = typeString
}
}
}
companion object {
private const val TAG = "OpenFileHelper"
private const val GET_CONTENT = 25745
private const val OPEN_DOC = 25845
private const val FILE_BROWSE = 25645
private var CREATE_FILE_REQUEST_CODE_DEFAULT = 3853
private var fileRequestCodes = ArrayList<Int>()
private fun getUnusedCreateFileRequestCode(): Int {
val newCreateFileRequestCode = CREATE_FILE_REQUEST_CODE_DEFAULT++
fileRequestCodes.add(newCreateFileRequestCode)
return newCreateFileRequestCode
}
@SuppressLint("InlinedApi")
fun allowCreateDocumentByStorageAccessFramework(packageManager: PackageManager,
typeString: String = "application/octet-stream"): Boolean {
@@ -231,7 +212,7 @@ class ExternalFileHelper {
fun View.setOpenDocumentClickListener(externalFileHelper: ExternalFileHelper?) {
externalFileHelper?.let { fileHelper ->
setOnClickListener {
fileHelper.openDocument()
fileHelper.openDocument(false)
}
setOnLongClickListener {
fileHelper.openDocument(true)

View File

@@ -100,7 +100,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
}
mDatabaseViewModel.saveDefaultUsername.observe(this) {
mDatabaseTaskProvider?.startDatabaseSaveName(it.oldValue, it.newValue, it.save)
mDatabaseTaskProvider?.startDatabaseSaveDefaultUsername(it.oldValue, it.newValue, it.save)
}
mDatabaseViewModel.saveColor.observe(this) {
@@ -180,8 +180,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
closeDatabase(database)
if (LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK == null)
LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = LOCKING_ACTIVITY_UI_VISIBLE
// Add onActivityForResult response
setResult(RESULT_EXIT_LOCK)
mExitLock = true
closeOptionsMenu()
finish()
}
@@ -353,14 +352,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
mDatabaseTaskProvider?.startDatabaseDeleteEntryHistory(mainEntryId, entryHistoryPosition, mAutoSaveEnable)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_EXIT_LOCK) {
mExitLock = true
lockAndExit()
}
}
private fun checkRegister() {
// If in ave or registration mode, don't allow read only
if ((mSpecialMode == SpecialMode.SAVE
@@ -440,8 +431,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
const val TAG = "LockingActivity"
const val RESULT_EXIT_LOCK = 1450
const val TIMEOUT_ENABLE_KEY = "TIMEOUT_ENABLE_KEY"
const val TIMEOUT_ENABLE_KEY_DEFAULT = true

View File

@@ -39,7 +39,11 @@ object Stylish {
*/
fun load(context: Context) {
Log.d(Stylish::class.java.name, "Attatching to " + context.packageName)
themeString = PreferencesUtil.getStyle(context)
try {
themeString = PreferencesUtil.getStyle(context)
} catch (e: Exception) {
Log.e("Stylish", "Unable to get preference style", e)
}
}
fun retrieveEquivalentSystemStyle(context: Context, styleString: String): String {

View File

@@ -23,12 +23,12 @@ import android.content.Context
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import androidx.annotation.StyleRes
import androidx.fragment.app.Fragment
import androidx.appcompat.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StyleRes
import androidx.appcompat.view.ContextThemeWrapper
import androidx.fragment.app.Fragment
abstract class StylishFragment : Fragment() {
@@ -42,7 +42,6 @@ abstract class StylishFragment : Fragment() {
contextThemed = ContextThemeWrapper(context, themeId)
}
@Suppress("DEPRECATION")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// To fix status bar color
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -58,6 +57,7 @@ abstract class StylishFragment : Fragment() {
try {
val taWindowStatusLight = contextThemed?.theme?.obtainStyledAttributes(intArrayOf(android.R.attr.windowLightStatusBar))
if (taWindowStatusLight?.getBoolean(0, false) == true) {
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
}
taWindowStatusLight?.recycle()

View File

@@ -67,8 +67,10 @@ class NodeAdapter (private val context: Context,
private var mCalculateViewTypeTextSize = Array(2) { true } // number of view type
private var mTextSizeUnit: Int = TypedValue.COMPLEX_UNIT_PX
private var mPrefSizeMultiplier: Float = 0F
private var mSubtextDefaultDimension: Float = 0F
private var mInfoTextDefaultDimension: Float = 0F
private var mTextDefaultDimension: Float = 0F
private var mSubTextDefaultDimension: Float = 0F
private var mMetaTextDefaultDimension: Float = 0F
private var mOtpTokenTextDefaultDimension: Float = 0F
private var mNumberChildrenTextDefaultDimension: Float = 0F
private var mIconDefaultDimension: Float = 0F
@@ -303,8 +305,10 @@ class NodeAdapter (private val context: Context,
mInflater.inflate(R.layout.item_list_nodes_entry, parent, false)
}
val nodeViewHolder = NodeViewHolder(view)
mInfoTextDefaultDimension = nodeViewHolder.text.textSize
mSubtextDefaultDimension = nodeViewHolder.subText.textSize
mTextDefaultDimension = nodeViewHolder.text.textSize
mSubTextDefaultDimension = nodeViewHolder.subText?.textSize ?: mSubTextDefaultDimension
mMetaTextDefaultDimension = nodeViewHolder.meta.textSize
mOtpTokenTextDefaultDimension = nodeViewHolder.otpToken?.textSize ?: mOtpTokenTextDefaultDimension
nodeViewHolder.numberChildren?.let {
mNumberChildrenTextDefaultDimension = it.textSize
}
@@ -315,7 +319,9 @@ class NodeAdapter (private val context: Context,
val subNode = mNodeSortedList.get(position)
// Node selection
holder.container.isSelected = mActionNodesList.contains(subNode)
holder.container.apply {
isSelected = mActionNodesList.contains(subNode)
}
// Assign image
val iconColor = if (holder.container.isSelected)
@@ -337,19 +343,18 @@ class NodeAdapter (private val context: Context,
// Assign text
holder.text.apply {
text = subNode.title
setTextSize(mTextSizeUnit, mInfoTextDefaultDimension, mPrefSizeMultiplier)
setTextSize(mTextSizeUnit, mTextDefaultDimension, mPrefSizeMultiplier)
strikeOut(subNode.isCurrentlyExpires)
}
// Add subText with username
holder.subText.apply {
text = ""
strikeOut(subNode.isCurrentlyExpires)
visibility = View.GONE
}
// Add meta text to show UUID
holder.meta.apply {
text = subNode.nodeId.toString()
visibility = if (mShowUUID) View.VISIBLE else View.GONE
if (mShowUUID) {
text = subNode.nodeId.toString()
setTextSize(mTextSizeUnit, mMetaTextDefaultDimension, mPrefSizeMultiplier)
visibility = View.VISIBLE
} else {
visibility = View.GONE
}
}
// Specific elements for entry
@@ -358,12 +363,16 @@ class NodeAdapter (private val context: Context,
database.startManageEntry(entry)
holder.text.text = entry.getVisualTitle()
holder.subText.apply {
// Add subText with username
holder.subText?.apply {
val username = entry.username
if (mShowUserNames && username.isNotEmpty()) {
visibility = View.VISIBLE
text = username
setTextSize(mTextSizeUnit, mSubtextDefaultDimension, mPrefSizeMultiplier)
setTextSize(mTextSizeUnit, mSubTextDefaultDimension, mPrefSizeMultiplier)
strikeOut(subNode.isCurrentlyExpires)
} else {
visibility = View.GONE
}
}
@@ -431,7 +440,10 @@ class NodeAdapter (private val context: Context,
}
}
}
holder?.otpToken?.text = otpElement?.token
holder?.otpToken?.apply {
text = otpElement?.token
setTextSize(mTextSizeUnit, mOtpTokenTextDefaultDimension, mPrefSizeMultiplier)
}
holder?.otpContainer?.setOnClickListener {
otpElement?.token?.let { token ->
Toast.makeText(
@@ -483,7 +495,7 @@ class NodeAdapter (private val context: Context,
var imageIdentifier: ImageView? = itemView.findViewById(R.id.node_image_identifier)
var icon: ImageView = itemView.findViewById(R.id.node_icon)
var text: TextView = itemView.findViewById(R.id.node_text)
var subText: TextView = itemView.findViewById(R.id.node_subtext)
var subText: TextView? = itemView.findViewById(R.id.node_subtext)
var meta: TextView = itemView.findViewById(R.id.node_meta)
var otpContainer: ViewGroup? = itemView.findViewById(R.id.node_otp_container)
var otpProgress: ProgressBar? = itemView.findViewById(R.id.node_otp_progress)

View File

@@ -16,9 +16,9 @@ import com.kunzisoft.keepass.icons.IconDrawableFactory
class TemplatesSelectorAdapter(private val context: Context,
private val iconDrawableFactory: IconDrawableFactory?,
private var templates: List<Template>): BaseAdapter() {
var iconDrawableFactory: IconDrawableFactory? = null
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var mIconColor = Color.BLACK

View File

@@ -25,7 +25,6 @@ import android.app.PendingIntent
import android.app.assist.AssistStructure
import android.content.Context
import android.content.Intent
import android.content.IntentSender
import android.graphics.BlendMode
import android.graphics.drawable.Icon
import android.os.Build
@@ -39,7 +38,10 @@ import android.view.inputmethod.InlineSuggestionsRequest
import android.widget.RemoteViews
import android.widget.Toast
import android.widget.inline.InlinePresentationSpec
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.autofill.inline.UiVersions
import androidx.autofill.inline.v1.InlineSuggestionUi
import androidx.core.content.ContextCompat
@@ -49,19 +51,17 @@ import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.template.TemplateField
import com.kunzisoft.keepass.model.EntryInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.database.element.template.TemplateField
import com.kunzisoft.keepass.settings.AutofillSettingsActivity
import com.kunzisoft.keepass.settings.PreferencesUtil
import kotlin.collections.ArrayList
import com.kunzisoft.keepass.utils.LOCK_ACTION
@RequiresApi(api = Build.VERSION_CODES.O)
object AutofillHelper {
private const val AUTOFILL_RESPONSE_REQUEST_CODE = 8165
private const val EXTRA_ASSIST_STRUCTURE = AutofillManager.EXTRA_ASSIST_STRUCTURE
const val EXTRA_INLINE_SUGGESTIONS_REQUEST = "com.kunzisoft.keepass.autofill.INLINE_SUGGESTIONS_REQUEST"
@@ -253,9 +253,13 @@ object AutofillHelper {
// Build the content for IME UI
val pendingIntent = PendingIntent.getActivity(context,
0,
Intent(context, AutofillSettingsActivity::class.java),
0)
0,
Intent(context, AutofillSettingsActivity::class.java),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0
})
return InlinePresentation(
InlineSuggestionUi.newContentBuilder(pendingIntent).apply {
setContentDescription(context.getString(R.string.autofill_sign_in_prompt))
@@ -427,11 +431,33 @@ object AutofillHelper {
}
}
fun buildActivityResultLauncher(activity: AppCompatActivity,
lockDatabase: Boolean = false): ActivityResultLauncher<Intent> {
return activity.registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
// Utility method to loop and close each activity with return data
if (it.resultCode == Activity.RESULT_OK) {
activity.setResult(it.resultCode, it.data)
}
if (it.resultCode == Activity.RESULT_CANCELED) {
activity.setResult(Activity.RESULT_CANCELED)
}
activity.finish()
if (lockDatabase && PreferencesUtil.isAutofillCloseDatabaseEnable(activity)) {
// Close the database
activity.sendBroadcast(Intent(LOCK_ACTION))
}
}
}
/**
* Utility method to start an activity with an Autofill for result
*/
fun startActivityForAutofillResult(activity: Activity,
fun startActivityForAutofillResult(activity: AppCompatActivity,
intent: Intent,
activityResultLauncher: ActivityResultLauncher<Intent>?,
autofillComponent: AutofillComponent,
searchInfo: SearchInfo?) {
EntrySelectionHelper.addSpecialModeInIntent(intent, SpecialMode.SELECTION)
@@ -443,21 +469,6 @@ object AutofillHelper {
}
}
EntrySelectionHelper.addSearchInfoInIntent(intent, searchInfo)
activity.startActivityForResult(intent, AUTOFILL_RESPONSE_REQUEST_CODE)
}
/**
* Utility method to loop and close each activity with return data
*/
fun onActivityResultSetResultAndFinish(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == AUTOFILL_RESPONSE_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
activity.setResult(resultCode, data)
}
if (resultCode == Activity.RESULT_CANCELED) {
activity.setResult(Activity.RESULT_CANCELED)
}
activity.finish()
}
activityResultLauncher?.launch(intent)
}
}

View File

@@ -262,9 +262,13 @@ class KeeAutofillService : AutofillService() {
inlinePresentation = InlinePresentation(
InlineSuggestionUi.newContentBuilder(
PendingIntent.getActivity(this,
0,
Intent(this, AutofillSettingsActivity::class.java),
0)
0,
Intent(this, AutofillSettingsActivity::class.java),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0
})
).apply {
setContentDescription(getString(R.string.autofill_sign_in_prompt))
setTitle(getString(R.string.autofill_sign_in_prompt))

View File

@@ -272,12 +272,12 @@ class StructureParser(private val structure: AssistStructure) {
private fun parseNodeByHtmlAttributes(node: AssistStructure.ViewNode): Boolean {
val autofillId = node.autofillId
val nodHtml = node.htmlInfo
when (nodHtml?.tag?.toLowerCase(Locale.ENGLISH)) {
when (nodHtml?.tag?.lowercase(Locale.ENGLISH)) {
"input" -> {
nodHtml.attributes?.forEach { pairAttribute ->
when (pairAttribute.first.toLowerCase(Locale.ENGLISH)) {
when (pairAttribute.first.lowercase(Locale.ENGLISH)) {
"type" -> {
when (pairAttribute.second.toLowerCase(Locale.ENGLISH)) {
when (pairAttribute.second.lowercase(Locale.ENGLISH)) {
"tel", "email" -> {
result?.usernameId = autofillId
result?.usernameValue = node.autofillValue

View File

@@ -19,6 +19,7 @@
*/
package com.kunzisoft.keepass.biometric
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
@@ -27,9 +28,11 @@ import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.*
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import com.getkeepsafe.taptargetview.TapTargetView
import com.kunzisoft.keepass.R
@@ -39,6 +42,7 @@ import com.kunzisoft.keepass.database.exception.IODatabaseException
import com.kunzisoft.keepass.education.PasswordActivityEducation
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
import com.kunzisoft.keepass.viewmodels.AdvancedUnlockViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -59,9 +63,12 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
/**
* Manage setting to auto open biometric prompt
*/
private var mAutoOpenPrompt: Boolean = false
private var mAutoOpenPrompt: Boolean
get() {
return field && mAutoOpenPromptEnabled
return mAdvancedUnlockViewModel.allowAutoOpenBiometricPrompt && mAutoOpenPromptEnabled
}
set(value) {
mAdvancedUnlockViewModel.allowAutoOpenBiometricPrompt = value
}
// Variable to check if the prompt can be open (if the right activity is currently shown)
@@ -72,6 +79,8 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
private var cipherDatabaseListener: CipherDatabaseAction.CipherDatabaseListener? = null
private val mAdvancedUnlockViewModel: AdvancedUnlockViewModel by activityViewModels()
// Only to fix multiple fingerprint menu #332
private var mAllowAdvancedUnlockMenu = false
private var mAddBiometricMenuInProgress = false
@@ -79,6 +88,15 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
// Only keep connection when we request a device credential activity
private var keepConnection = false
private var mDeviceCredentialResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
mAdvancedUnlockViewModel.allowAutoOpenBiometricPrompt = false
// To wait resume
if (keepConnection) {
mAdvancedUnlockViewModel.deviceCredentialAuthSucceeded = result.resultCode == Activity.RESULT_OK
}
keepConnection = false
}
override fun onAttach(context: Context) {
super.onAttach(context)
@@ -97,10 +115,21 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
setHasOptionsMenu(true)
cipherDatabaseAction = CipherDatabaseAction.getInstance(requireContext().applicationContext)
mAdvancedUnlockViewModel.onInitAdvancedUnlockModeRequested.observe(this) {
initAdvancedUnlockMode()
}
mAdvancedUnlockViewModel.onUnlockAvailabilityCheckRequested.observe(this) {
checkUnlockAvailability()
}
mAdvancedUnlockViewModel.onDatabaseFileLoaded.observe(this) {
onDatabaseLoaded(it)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@@ -114,17 +143,6 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
return rootView
}
private data class ActivityResult(var requestCode: Int, var resultCode: Int, var data: Intent?)
private var activityResult: ActivityResult? = null
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// To wait resume
if (keepConnection) {
activityResult = ActivityResult(requestCode, resultCode, data)
}
keepConnection = false
}
override fun onResume() {
super.onResume()
context?.let {
@@ -154,32 +172,38 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
return super.onOptionsItemSelected(item)
}
fun loadDatabase(databaseUri: Uri?, autoOpenPrompt: Boolean) {
private fun onDatabaseLoaded(databaseUri: Uri?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// To get device credential unlock result, only if same database uri
if (databaseUri != null
&& mAdvancedUnlockEnabled) {
activityResult?.let {
val deviceCredentialAuthSucceeded = mAdvancedUnlockViewModel.deviceCredentialAuthSucceeded
deviceCredentialAuthSucceeded?.let {
if (databaseUri == databaseFileUri) {
advancedUnlockManager?.onActivityResult(it.requestCode, it.resultCode)
if (deviceCredentialAuthSucceeded == true) {
advancedUnlockManager?.advancedUnlockCallback?.onAuthenticationSucceeded()
} else {
advancedUnlockManager?.advancedUnlockCallback?.onAuthenticationFailed()
}
} else {
disconnect()
}
} ?: run {
this.mAutoOpenPrompt = autoOpenPrompt
connect(databaseUri)
if (databaseUri != databaseFileUri) {
connect(databaseUri)
}
}
} else {
disconnect()
}
activityResult = null
mAdvancedUnlockViewModel.deviceCredentialAuthSucceeded = null
}
}
/**
* Check unlock availability and change the current mode depending of device's state
*/
fun checkUnlockAvailability() {
private fun checkUnlockAvailability() {
context?.let { context ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
allowOpenBiometricPrompt = true
@@ -317,7 +341,8 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
if (cryptoPrompt.isDeviceCredentialOperation)
keepConnection = true
try {
advancedUnlockManager?.openAdvancedUnlockPrompt(cryptoPrompt)
advancedUnlockManager?.openAdvancedUnlockPrompt(cryptoPrompt,
mDeviceCredentialResultLauncher)
} catch (e: Exception) {
Log.e(TAG, "Unable to open advanced unlock prompt", e)
setAdvancedUnlockedTitleView(R.string.advanced_unlock_prompt_not_initialized)
@@ -369,8 +394,7 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
} ?: throw Exception("AdvancedUnlockManager not initialized")
}
@Synchronized
fun initAdvancedUnlockMode() {
private fun initAdvancedUnlockMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAllowAdvancedUnlockMenu = false
try {
@@ -444,6 +468,7 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
@RequiresApi(Build.VERSION_CODES.M)
fun deleteEncryptedDatabaseKey() {
mAllowAdvancedUnlockMenu = false
advancedUnlockManager?.closeBiometricPrompt()
databaseFileUri?.let { databaseUri ->
cipherDatabaseAction.deleteByDatabaseUri(databaseUri) {
@@ -516,6 +541,11 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
}
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onUnrecoverableKeyException(e: Exception) {
setAdvancedUnlockedMessageView(R.string.advanced_unlock_invalid_key)
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onInvalidKeyException(e: Exception) {
setAdvancedUnlockedMessageView(R.string.advanced_unlock_invalid_key)

View File

@@ -19,15 +19,18 @@
*/
package com.kunzisoft.keepass.biometric
import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyPermanentlyInvalidatedException
import android.security.keystore.KeyProperties
import android.util.Base64
import android.util.Log
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators.*
@@ -35,6 +38,7 @@ import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.settings.PreferencesUtil
import java.security.KeyStore
import java.security.UnrecoverableKeyException
@@ -136,18 +140,24 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
// and the constrains (purposes) in the constructor of the Builder
keyGenerator?.init(
KeyGenParameterSpec.Builder(
ADVANCED_UNLOCK_KEYSTORE_KEY,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
ADVANCED_UNLOCK_KEYSTORE_KEY,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.apply {
// Require the user to authenticate with a fingerprint to authorize every use
// of the key, don't use it for device credential because it's the user authentication
.apply {
if (biometricUnlockEnable) {
setUserAuthenticationRequired(true)
}
if (biometricUnlockEnable) {
setUserAuthenticationRequired(true)
}
.build())
// To store in the security chip
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
&& retrieveContext().packageManager.hasSystemFeature(
PackageManager.FEATURE_STRONGBOX_KEYSTORE)) {
setIsStrongBoxBacked(true)
}
}
.build())
keyGenerator?.generateKey()
}
} catch (e: Exception) {
@@ -164,8 +174,12 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
return null
}
fun initEncryptData(actionIfCypherInit
: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit) {
fun initEncryptData(actionIfCypherInit: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit,) {
initEncryptData(actionIfCypherInit, true)
}
private fun initEncryptData(actionIfCypherInit: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit,
firstLaunch: Boolean) {
if (!isKeyManagerInitialized) {
return
}
@@ -185,10 +199,15 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
}
} catch (unrecoverableKeyException: UnrecoverableKeyException) {
Log.e(TAG, "Unable to initialize encrypt data", unrecoverableKeyException)
advancedUnlockCallback?.onInvalidKeyException(unrecoverableKeyException)
advancedUnlockCallback?.onUnrecoverableKeyException(unrecoverableKeyException)
} catch (invalidKeyException: KeyPermanentlyInvalidatedException) {
Log.e(TAG, "Unable to initialize encrypt data", invalidKeyException)
advancedUnlockCallback?.onInvalidKeyException(invalidKeyException)
if (firstLaunch) {
deleteAllEntryKeysInKeystoreForBiometric(retrieveContext())
initEncryptData(actionIfCypherInit, false)
} else {
advancedUnlockCallback?.onInvalidKeyException(invalidKeyException)
}
} catch (e: Exception) {
Log.e(TAG, "Unable to initialize encrypt data", e)
advancedUnlockCallback?.onGenericException(e)
@@ -214,8 +233,14 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
}
}
fun initDecryptData(ivSpecValue: String, actionIfCypherInit
: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit) {
fun initDecryptData(ivSpecValue: String,
actionIfCypherInit: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit) {
initDecryptData(ivSpecValue, actionIfCypherInit, true)
}
private fun initDecryptData(ivSpecValue: String,
actionIfCypherInit: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit,
firstLaunch: Boolean = true) {
if (!isKeyManagerInitialized) {
return
}
@@ -239,10 +264,20 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
}
} catch (unrecoverableKeyException: UnrecoverableKeyException) {
Log.e(TAG, "Unable to initialize decrypt data", unrecoverableKeyException)
deleteKeystoreKey()
if (firstLaunch) {
deleteKeystoreKey()
initDecryptData(ivSpecValue, actionIfCypherInit, firstLaunch)
} else {
advancedUnlockCallback?.onUnrecoverableKeyException(unrecoverableKeyException)
}
} catch (invalidKeyException: KeyPermanentlyInvalidatedException) {
Log.e(TAG, "Unable to initialize decrypt data", invalidKeyException)
advancedUnlockCallback?.onInvalidKeyException(invalidKeyException)
if (firstLaunch) {
deleteAllEntryKeysInKeystoreForBiometric(retrieveContext())
initDecryptData(ivSpecValue, actionIfCypherInit, firstLaunch)
} else {
advancedUnlockCallback?.onInvalidKeyException(invalidKeyException)
}
} catch (e: Exception) {
Log.e(TAG, "Unable to initialize decrypt data", e)
advancedUnlockCallback?.onGenericException(e)
@@ -278,9 +313,9 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
}
}
@Suppress("DEPRECATION")
@Synchronized
fun openAdvancedUnlockPrompt(cryptoPrompt: AdvancedUnlockCryptoPrompt) {
fun openAdvancedUnlockPrompt(cryptoPrompt: AdvancedUnlockCryptoPrompt,
deviceCredentialResultLauncher: ActivityResultLauncher<Intent>
) {
// Init advanced unlock prompt
if (biometricPrompt == null) {
biometricPrompt = BiometricPrompt(retrieveContext(),
@@ -311,20 +346,10 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
}
else if (cryptoPrompt.isDeviceCredentialOperation) {
val keyGuardManager = ContextCompat.getSystemService(retrieveContext(), KeyguardManager::class.java)
retrieveContext().startActivityForResult(
keyGuardManager?.createConfirmDeviceCredentialIntent(promptTitle, promptDescription),
REQUEST_DEVICE_CREDENTIAL)
}
}
@Synchronized
fun onActivityResult(requestCode: Int, resultCode: Int) {
if (requestCode == REQUEST_DEVICE_CREDENTIAL) {
if (resultCode == Activity.RESULT_OK) {
advancedUnlockCallback?.onAuthenticationSucceeded()
} else {
advancedUnlockCallback?.onAuthenticationFailed()
}
@Suppress("DEPRECATION")
deviceCredentialResultLauncher.launch(
keyGuardManager?.createConfirmDeviceCredentialIntent(promptTitle, promptDescription)
)
}
}
@@ -333,6 +358,7 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
}
interface AdvancedUnlockErrorCallback {
fun onUnrecoverableKeyException(e: Exception)
fun onInvalidKeyException(e: Exception)
fun onGenericException(e: Exception)
}
@@ -355,8 +381,6 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
private const val ADVANCED_UNLOCK_BLOCKS_MODES = KeyProperties.BLOCK_MODE_CBC
private const val ADVANCED_UNLOCK_ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7
private const val REQUEST_DEVICE_CREDENTIAL = 556
@RequiresApi(api = Build.VERSION_CODES.M)
fun canAuthenticate(context: Context): Int {
return try {
@@ -449,6 +473,10 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
override fun handleDecryptedResult(decryptedValue: String) {}
override fun onUnrecoverableKeyException(e: Exception) {
advancedCallback.onUnrecoverableKeyException(e)
}
override fun onInvalidKeyException(e: Exception) {
advancedCallback.onInvalidKeyException(e)
}
@@ -460,6 +488,33 @@ class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity)
deleteKeystoreKey()
}
}
fun deleteAllEntryKeysInKeystoreForBiometric(activity: FragmentActivity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
deleteEntryKeyInKeystoreForBiometric(
activity,
object : AdvancedUnlockErrorCallback {
fun showException(e: Exception) {
Toast.makeText(activity,
activity.getString(R.string.advanced_unlock_scanning_error, e.localizedMessage),
Toast.LENGTH_SHORT).show()
}
override fun onUnrecoverableKeyException(e: Exception) {
showException(e)
}
override fun onInvalidKeyException(e: Exception) {
showException(e)
}
override fun onGenericException(e: Exception) {
showException(e)
}
})
}
CipherDatabaseAction.getInstance(activity.applicationContext).deleteAll()
}
}
}

View File

@@ -192,17 +192,17 @@ class Argon2Kdf(private val type: Type) : KdfEngine() {
private val MIN_VERSION = UnsignedInt(0x10)
private val MAX_VERSION = UnsignedInt(0x13)
private val DEFAULT_ITERATIONS = UnsignedLong(2L)
private val DEFAULT_ITERATIONS = UnsignedLong(3L)
private val MIN_ITERATIONS = UnsignedLong(1L)
private val MAX_ITERATIONS = UnsignedLong(4294967295L)
private val DEFAULT_MEMORY = UnsignedLong((1024L * 1024L))
private val DEFAULT_MEMORY = UnsignedLong((1024L * 1024L * 16L))
private val MIN_MEMORY = UnsignedLong(1024L * 8L)
private val MAX_MEMORY = UnsignedInt.MAX_VALUE.toKotlinLong()
private const val MEMORY_BLOCK_SIZE: Long = 1024L
private val DEFAULT_PARALLELISM = UnsignedInt(2)
private val DEFAULT_PARALLELISM = UnsignedInt(4)
private val MIN_PARALLELISM = UnsignedInt.fromKotlinLong(1L)
private val MAX_PARALLELISM = UnsignedInt.fromKotlinLong(((1 shl 24) - 1))
private val MAX_PARALLELISM = UnsignedInt.fromKotlinLong(((1 shl 24) - 1).toLong())
}
}

View File

@@ -68,7 +68,7 @@ abstract class EntryCursor<EntryId, PwEntryV : EntryVersioned<*, EntryId, *, *>>
pwEntry.notes = getString(getColumnIndex(COLUMN_INDEX_NOTES))
pwEntry.expiryTime = DateInstant(getString(getColumnIndex(COLUMN_INDEX_EXPIRY_TIME)))
pwEntry.expires = getString(getColumnIndex(COLUMN_INDEX_EXPIRES))
.toLowerCase(Locale.ENGLISH) != "false"
.lowercase(Locale.ENGLISH) != "false"
}
companion object {

View File

@@ -147,6 +147,10 @@ class Database {
iconsManager.removeCustomIcon(binaryCache, customIcon.uuid)
}
fun updateCustomIcon(customIcon: IconImageCustom) {
iconsManager.getIcon(customIcon.uuid).updateWith(customIcon)
}
fun getTemplates(templateCreation: Boolean): List<Template> {
return mDatabaseKDBX?.getTemplates(templateCreation) ?: listOf()
}

View File

@@ -177,16 +177,20 @@ class Group : Node, GroupVersionedInterface<Group, Entry> {
fun addChildrenFrom(group: Group) {
group.groupKDB?.getChildEntries()?.forEach { entryToAdd ->
groupKDB?.addChildEntry(entryToAdd)
entryToAdd.parent = groupKDB
}
group.groupKDB?.getChildGroups()?.forEach { groupToAdd ->
groupKDB?.addChildGroup(groupToAdd)
groupToAdd.parent = groupKDB
}
group.groupKDBX?.getChildEntries()?.forEach { entryToAdd ->
groupKDBX?.addChildEntry(entryToAdd)
entryToAdd.parent = groupKDBX
}
group.groupKDBX?.getChildGroups()?.forEach { groupToAdd ->
groupKDBX?.addChildGroup(groupToAdd)
groupToAdd.parent = groupKDBX
}
}

View File

@@ -31,6 +31,10 @@ class CustomIconPool(private val binaryCache: BinaryCache) : BinaryPool<UUID>(bi
return newUUID
}
fun getCustomIcon(key: UUID): IconImageCustom? {
return customIcons[key]
}
fun any(predicate: (IconImageCustom)-> Boolean): Boolean {
return customIcons.any { predicate(it.value) }
}

View File

@@ -41,7 +41,7 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
private var kdfListV3: MutableList<KdfEngine> = ArrayList()
override val version: String
get() = "KeePass 1"
get() = "V1"
init {
kdfListV3.add(KdfFactory.aesKdf)

View File

@@ -156,7 +156,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
FILE_VERSION_41 -> "4.1"
else -> "UNKNOWN"
}
return "KeePass 2 - KDBX$kdbxStringVersion"
return "V2 - KDBX$kdbxStringVersion"
}
override val kdfEngine: KdfEngine?

View File

@@ -124,25 +124,29 @@ abstract class DatabaseVersioned<
@Throws(IOException::class)
protected fun getFileKey(keyInputStream: InputStream): ByteArray {
val keyData = keyInputStream.readBytes()
try {
val keyData = keyInputStream.readBytes()
// Check XML key file
val xmlKeyByteArray = loadXmlKeyFile(ByteArrayInputStream(keyData))
if (xmlKeyByteArray != null) {
return xmlKeyByteArray
}
// Check 32 bytes key file
when (keyData.size) {
32 -> return keyData
64 -> try {
return Hex.decodeHex(String(keyData).toCharArray())
} catch (ignoredException: Exception) {
// Key is not base 64, treat it as binary data
// Check XML key file
val xmlKeyByteArray = loadXmlKeyFile(ByteArrayInputStream(keyData))
if (xmlKeyByteArray != null) {
return xmlKeyByteArray
}
// Check 32 bytes key file
when (keyData.size) {
32 -> return keyData
64 -> try {
return Hex.decodeHex(String(keyData).toCharArray())
} catch (ignoredException: Exception) {
// Key is not base 64, treat it as binary data
}
}
// Hash file as binary data
return HashManager.hashSha256(keyData)
} catch (outOfMemoryError: OutOfMemoryError) {
throw IOException("Keyfile data is too large", outOfMemoryError)
}
// Hash file as binary data
return HashManager.hashSha256(keyData)
}
protected open fun loadXmlKeyFile(keyInputStream: InputStream): ByteArray? {

View File

@@ -32,6 +32,16 @@ class IconImageCustom : IconImageDraw {
var name: String = ""
var lastModificationTime: DateInstant? = null
fun updateWith(icon: IconImageCustom) {
this.name = icon.name
this.lastModificationTime = icon.lastModificationTime
}
constructor(copy: IconImageCustom) {
this.uuid = copy.uuid
updateWith(copy)
}
constructor(name: String = "", lastModificationTime: DateInstant? = null) {
this.uuid = DatabaseVersioned.UUID_ZERO
this.name = name

View File

@@ -65,7 +65,7 @@ class IconsManager(binaryCache: BinaryCache) {
}
fun getIcon(iconUuid: UUID): IconImageCustom {
return IconImageCustom(iconUuid)
return customCache.getCustomIcon(iconUuid) ?: IconImageCustom(iconUuid)
}
fun isCustomIconBinaryDuplicate(binaryData: BinaryData): Boolean {

View File

@@ -208,16 +208,8 @@ class TemplateEngineCompatible(database: DatabaseKDBX): TemplateEngine(database)
when (attribute.type) {
TemplateAttributeType.TEXT -> {
try {
when (attribute.options.getNumberLines()) {
1 -> {
// If one line, default attribute option is number of chars
attribute.options.setNumberChars(defaultOption.toInt())
}
else -> {
// else it's number of lines
attribute.options.setNumberLines(defaultOption.toInt())
}
}
// It's always a number of lines...
attribute.options.setNumberLines(defaultOption.toInt())
} catch (e: Exception) {
Log.e(TAG, "Unable to transform default text option", e)
}

View File

@@ -27,7 +27,7 @@ object TemplateField {
const val LABEL_DATE_OF_ISSUE = "Date of issue"
const val LABEL_EMAIL = "Email"
const val LABEL_EMAIL_ADDRESS = "Email address"
const val LABEL_WIRELESS = "Wifi"
const val LABEL_WIRELESS = "Wi-Fi"
const val LABEL_SSID = "SSID"
const val LABEL_TYPE = "Type"
const val LABEL_CRYPTOCURRENCY = "Cryptocurrency wallet"

View File

@@ -130,6 +130,6 @@ constructor(private val databaseKDBX: DatabaseKDBX,
}
companion object {
private val EndHeaderValue = byteArrayOf('\r'.toByte(), '\n'.toByte(), '\r'.toByte(), '\n'.toByte())
private val EndHeaderValue = byteArrayOf('\r'.code.toByte(), '\n'.code.toByte(), '\r'.code.toByte(), '\n'.code.toByte())
}
}

View File

@@ -765,7 +765,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
var character: Char
for (element in text) {
character = element
val hexChar = character.toInt()
val hexChar = character.code
if (
hexChar in 0x20..0xD7FF ||
hexChar == 0x9 ||

View File

@@ -272,7 +272,7 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
if (entryInfoKey != null) {
currentInputConnection.commitText(entryInfoKey!!.url, 1)
}
actionTabAutomatically()
actionGoAutomatically()
}
KEY_FIELDS -> {
if (entryInfoKey != null) {

View File

@@ -234,7 +234,7 @@ data class OtpElement(var otpModel: OtpModel = OtpModel()) {
fun replaceBase32Chars(parameter: String): String {
// Add padding '=' at end if not Base32 length
var parameterNewSize = parameter.toUpperCase(Locale.ENGLISH).removeSpaceChars()
var parameterNewSize = parameter.uppercase(Locale.ENGLISH).removeSpaceChars()
while (parameterNewSize.length % 8 != 0) {
parameterNewSize += '='
}
@@ -264,7 +264,7 @@ enum class OtpTokenType {
companion object {
fun getFromString(tokenType: String): OtpTokenType {
return when (tokenType.toLowerCase(Locale.ENGLISH)) {
return when (tokenType.lowercase(Locale.ENGLISH)) {
"s", "steam" -> STEAM
"hotp" -> RFC4226
else -> RFC6238

View File

@@ -143,7 +143,7 @@ object OtpEntryFields {
if (otpPlainText != null && otpPlainText.isNotEmpty() && isOTPUri(otpPlainText)) {
val uri = Uri.parse(otpPlainText.removeSpaceChars())
if (uri.scheme == null || OTP_SCHEME != uri.scheme!!.toLowerCase(Locale.ENGLISH)) {
if (uri.scheme == null || OTP_SCHEME != uri.scheme!!.lowercase(Locale.ENGLISH)) {
Log.e(TAG, "Invalid or missing scheme in uri")
return false
}
@@ -309,7 +309,7 @@ object OtpEntryFields {
}
if (algorithmField != null) {
otpElement.algorithm =
when (algorithmField.toUpperCase(Locale.ENGLISH)) {
when (algorithmField.uppercase(Locale.ENGLISH)) {
TIMEOTP_ALGORITHM_SHA1_VALUE -> HashAlgorithm.SHA1
TIMEOTP_ALGORITHM_SHA256_VALUE -> HashAlgorithm.SHA256
TIMEOTP_ALGORITHM_SHA512_VALUE -> HashAlgorithm.SHA512
@@ -417,7 +417,7 @@ object OtpEntryFields {
val output = HashMap<String, String>()
for (element in elements) {
val pair = element.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
output[pair[0].toLowerCase(Locale.ENGLISH)] = pair[1]
output[pair[0].lowercase(Locale.ENGLISH)] = pair[1]
}
return output
}

View File

@@ -0,0 +1,33 @@
package com.kunzisoft.keepass.receivers
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.util.Log
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
import com.kunzisoft.keepass.utils.DexUtil
import com.kunzisoft.keepass.utils.MagikeyboardUtil
class DexModeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val enabled = when (intent?.action) {
"android.app.action.ENTER_KNOX_DESKTOP_MODE" -> {
Log.i(TAG, "Entered DeX mode")
false
}
"android.app.action.EXIT_KNOX_DESKTOP_MODE" -> {
Log.i(TAG, "Left DeX mode")
true
}
else -> return
}
MagikeyboardUtil.setEnabled(context!!, enabled)
}
companion object {
private val TAG = DexModeReceiver::class.java.name
}
}

View File

@@ -1,9 +1,11 @@
package com.kunzisoft.keepass.services
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.*
import android.net.Uri
import android.os.Binder
import android.os.Build
import android.os.IBinder
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
@@ -50,11 +52,20 @@ class AdvancedUnlockNotificationService : NotificationService() {
mTempCipherDao = ArrayList()
}
// It's simpler to use pendingIntent to perform REMOVE_ADVANCED_UNLOCK_KEY_ACTION
// because can be directly broadcast to another module or app
@SuppressLint("LaunchActivityFromNotification")
override fun onBind(intent: Intent): IBinder {
super.onBind(intent)
val pendingDeleteIntent = PendingIntent.getBroadcast(this,
4577, Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION), 0)
4577,
Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0
})
val biometricUnlockEnabled = PreferencesUtil.isBiometricUnlockEnable(this)
val notificationBuilder = buildNewNotification().apply {
setSmallIcon(if (biometricUnlockEnabled) {

View File

@@ -24,6 +24,7 @@ import android.content.ContentResolver
import android.content.Intent
import android.net.Uri
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.util.Log
import com.kunzisoft.keepass.R
@@ -188,20 +189,30 @@ class AttachmentFileNotificationService: LockNotificationService() {
private fun newNotification(attachmentNotification: AttachmentNotification) {
val pendingContentIntent = PendingIntent.getActivity(this,
0,
Intent().apply {
action = Intent.ACTION_VIEW
setDataAndType(attachmentNotification.uri,
contentResolver.getType(attachmentNotification.uri))
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}, PendingIntent.FLAG_CANCEL_CURRENT)
0,
Intent().apply {
action = Intent.ACTION_VIEW
setDataAndType(attachmentNotification.uri,
contentResolver.getType(attachmentNotification.uri))
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
} else {
PendingIntent.FLAG_CANCEL_CURRENT
}
)
val pendingDeleteIntent = PendingIntent.getService(this,
0,
Intent(this, AttachmentFileNotificationService::class.java).apply {
// No action to delete the service
putExtra(FILE_URI_KEY, attachmentNotification.uri)
}, PendingIntent.FLAG_CANCEL_CURRENT)
}, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
} else {
PendingIntent.FLAG_CANCEL_CURRENT
}
)
val fileName = UriUtil.getFileData(this, attachmentNotification.uri)?.name
?: attachmentNotification.uri.path

View File

@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.services
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.model.EntryInfo
@@ -112,7 +113,13 @@ class ClipboardEntryNotificationService : LockNotificationService() {
putParcelableArrayListExtra(EXTRA_CLIPBOARD_FIELDS, fieldsToAdd)
}
return PendingIntent.getService(
this, 0, copyIntent, PendingIntent.FLAG_UPDATE_CURRENT)
this, 0, copyIntent,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
)
}
private fun newNotification(title: String?, fieldsToAdd: ArrayList<ClipboardEntryNotificationField>) {
@@ -162,7 +169,13 @@ class ClipboardEntryNotificationService : LockNotificationService() {
val cleanIntent = Intent(this, ClipboardEntryNotificationService::class.java)
cleanIntent.action = ACTION_CLEAN_CLIPBOARD
val cleanPendingIntent = PendingIntent.getService(
this, 0, cleanIntent, PendingIntent.FLAG_UPDATE_CURRENT)
this, 0, cleanIntent,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
)
builder.setDeleteIntent(cleanPendingIntent)
//Get settings

View File

@@ -24,6 +24,7 @@ import android.content.Intent
import android.net.Uri
import android.os.*
import android.util.Log
import androidx.media.app.NotificationCompat
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.GroupActivity
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
@@ -407,11 +408,21 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
this,
0,
Intent(this, GroupActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
)
val pendingDeleteIntent = PendingIntent.getBroadcast(
this,
4576, Intent(LOCK_ACTION), 0
4576,
Intent(LOCK_ACTION),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0
}
)
// Add actions in notifications
notificationBuilder.apply {
@@ -420,9 +431,16 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
// Unfortunately swipe is disabled in lollipop+
setDeleteIntent(pendingDeleteIntent)
addAction(
R.drawable.ic_lock_white_24dp, getString(R.string.lock),
R.drawable.ic_lock_database_white_32dp, getString(R.string.lock),
pendingDeleteIntent
)
// Won't work with Xiaomi and Kitkat
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
setStyle(
NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0)
)
}
}
}
}

View File

@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.services
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.preference.PreferenceManager
@@ -93,7 +94,13 @@ class KeyboardEntryNotificationService : LockNotificationService() {
val deleteIntent = Intent(this, KeyboardEntryNotificationService::class.java).apply {
action = ACTION_CLEAN_KEYBOARD_ENTRY
}
pendingDeleteIntent = PendingIntent.getService(this, 0, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT)
pendingDeleteIntent = PendingIntent.getService(this, 0, deleteIntent,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
)
val builder = buildNewNotification()
.setSmallIcon(R.drawable.notification_ic_keyboard_key_24dp)

View File

@@ -57,6 +57,7 @@ class AutofillSettingsFragment : PreferenceFragmentCompat() {
}
if (dialogFragment != null) {
@Suppress("DEPRECATION")
dialogFragment.setTargetFragment(this, 0)
dialogFragment.show(parentFragmentManager, TAG_AUTOFILL_PREF_FRAGMENT)
}

View File

@@ -48,6 +48,7 @@ class MagikeyboardSettingsFragment : PreferenceFragmentCompat() {
}
if (dialogFragment != null) {
@Suppress("DEPRECATION")
dialogFragment.setTargetFragment(this, 0)
dialogFragment.show(parentFragmentManager, TAG_PREF_FRAGMENT)
}

View File

@@ -40,7 +40,6 @@ import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.ProFeatureDialogFragment
import com.kunzisoft.keepass.activities.dialogs.UnavailableFeatureDialogFragment
import com.kunzisoft.keepass.activities.stylish.Stylish
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.biometric.AdvancedUnlockManager
import com.kunzisoft.keepass.education.Education
@@ -157,7 +156,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
val intent = Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE)
intent.data = Uri.parse("package:com.kunzisoft.keepass.autofill.KeeAutofillService")
Log.d(javaClass.name, "Autofill enable service: intent=$intent")
startActivityForResult(intent, REQUEST_CODE_AUTOFILL)
startActivity(intent)
} else {
Log.d(javaClass.name, "Autofill service already enabled.")
}
@@ -366,26 +365,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
) { _, _ ->
validate?.invoke()
deleteKeysAlertDialog?.setOnDismissListener(null)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
AdvancedUnlockManager.deleteEntryKeyInKeystoreForBiometric(
activity,
object : AdvancedUnlockManager.AdvancedUnlockErrorCallback {
fun showException(e: Exception) {
Toast.makeText(context,
getString(R.string.advanced_unlock_scanning_error, e.localizedMessage),
Toast.LENGTH_SHORT).show()
}
override fun onInvalidKeyException(e: Exception) {
showException(e)
}
override fun onGenericException(e: Exception) {
showException(e)
}
})
}
CipherDatabaseAction.getInstance(activity.applicationContext).deleteAll()
AdvancedUnlockManager.deleteAllEntryKeysInKeystoreForBiometric(activity)
}
.setNegativeButton(resources.getString(android.R.string.cancel)
) { _, _ ->}
@@ -494,6 +474,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
}
if (dialogFragment != null) {
@Suppress("DEPRECATION")
dialogFragment.setTargetFragment(this, 0)
dialogFragment.show(parentFragmentManager, TAG_PREF_FRAGMENT)
}
@@ -533,7 +514,6 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
}
companion object {
private const val REQUEST_CODE_AUTOFILL = 5201
private const val TAG_PREF_FRAGMENT = "TAG_PREF_FRAGMENT"
var DATABASE_APPEARANCE_PREFERENCE_CHANGED = false

View File

@@ -57,7 +57,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
private var dbNamePref: InputTextPreference? = null
private var dbDescriptionPref: InputTextPreference? = null
private var dbDefaultUsername: InputTextPreference? = null
private var dbDefaultUsernamePref: InputTextPreference? = null
private var dbCustomColorPref: DialogColorPreference? = null
private var dbDataCompressionPref: Preference? = null
private var recycleBinGroupPref: DialogListExplanationPreference? = null
@@ -164,11 +164,11 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
}
// Database default username
dbDefaultUsername = findPreference(getString(R.string.database_default_username_key))
dbDefaultUsernamePref = findPreference(getString(R.string.database_default_username_key))
if (database.allowDefaultUsername) {
dbDefaultUsername?.summary = database.defaultUsername
dbDefaultUsernamePref?.summary = database.defaultUsername
} else {
dbDefaultUsername?.isEnabled = false
dbDefaultUsernamePref?.isEnabled = false
// TODO dbGeneralPrefCategory?.removePreference(dbDefaultUsername)
}
@@ -416,7 +416,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
mDatabase?.defaultUsername = oldDefaultUsername
oldDefaultUsername
}
dbDefaultUsername?.summary = defaultUsernameToShow
dbDefaultUsernamePref?.summary = defaultUsernameToShow
}
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_COLOR_TASK -> {
val oldColor = data.getString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)!!
@@ -632,6 +632,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
}
if (dialogFragment != null && !mDatabaseReadOnly) {
@Suppress("DEPRECATION")
dialogFragment.setTargetFragment(this, 0)
dialogFragment.show(parentFragmentManager, TAG_PREF_FRAGMENT)
}

View File

@@ -49,7 +49,6 @@ open class SettingsActivity
private var backupManager: BackupManager? = null
private var mExternalFileHelper: ExternalFileHelper? = null
private var appPropertiesFileCreationRequestCode: Int? = null
private var coordinatorLayout: CoordinatorLayout? = null
private var toolbar: Toolbar? = null
@@ -64,6 +63,41 @@ open class SettingsActivity
toolbar = findViewById(R.id.toolbar)
mExternalFileHelper = ExternalFileHelper(this)
mExternalFileHelper?.buildOpenDocument { selectedFileUri ->
// Import app properties result
try {
selectedFileUri?.let { uri ->
val appProperties = Properties()
contentResolver?.openInputStream(uri)?.use { inputStream ->
appProperties.load(inputStream)
}
PreferencesUtil.setAppProperties(this, appProperties)
// Restart the current activity
reloadActivity()
Toast.makeText(this, R.string.success_import_app_properties, Toast.LENGTH_LONG).show()
}
} catch (e: Exception) {
Toast.makeText(this, R.string.error_import_app_properties, Toast.LENGTH_LONG).show()
Log.e(TAG, "Unable to import app properties", e)
}
}
mExternalFileHelper?.buildCreateDocument { createdFileUri ->
// Export app properties result
try {
createdFileUri?.let { uri ->
contentResolver?.openOutputStream(uri)?.use { outputStream ->
PreferencesUtil
.getAppProperties(this)
.store(outputStream, getString(R.string.description_app_properties))
}
Toast.makeText(this, R.string.success_export_app_properties, Toast.LENGTH_LONG).show()
}
} catch (e: Exception) {
Toast.makeText(this, R.string.error_export_app_properties, Toast.LENGTH_LONG).show()
Log.e(DatabaseLockActivity.TAG, "Unable to export app properties", e)
}
}
if (savedInstanceState?.getString(TITLE_KEY).isNullOrEmpty())
toolbar?.setTitle(R.string.settings)
@@ -217,54 +251,10 @@ open class SettingsActivity
}
fun exportAppProperties() {
appPropertiesFileCreationRequestCode = mExternalFileHelper?.createDocument(getString(R.string.app_properties_file_name,
mExternalFileHelper?.createDocument(getString(R.string.app_properties_file_name,
DateTime.now().toLocalDateTime().toString("yyyy-MM-dd'_'HH-mm")))
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Import app properties result
try {
mExternalFileHelper?.onOpenDocumentResult(requestCode, resultCode, data) { selectedFileUri ->
selectedFileUri?.let { uri ->
val appProperties = Properties()
contentResolver?.openInputStream(uri)?.use { inputStream ->
appProperties.load(inputStream)
}
PreferencesUtil.setAppProperties(this, appProperties)
// Restart the current activity
reloadActivity()
Toast.makeText(this, R.string.success_import_app_properties, Toast.LENGTH_LONG).show()
}
}
} catch (e: Exception) {
Toast.makeText(this, R.string.error_import_app_properties, Toast.LENGTH_LONG).show()
Log.e(TAG, "Unable to import app properties", e)
}
// Export app properties result
try {
if (requestCode == appPropertiesFileCreationRequestCode) {
mExternalFileHelper?.onCreateDocumentResult(requestCode, resultCode, data) { createdFileUri ->
createdFileUri?.let { uri ->
contentResolver?.openOutputStream(uri)?.use { outputStream ->
PreferencesUtil
.getAppProperties(this)
.store(outputStream, getString(R.string.description_app_properties))
}
Toast.makeText(this, R.string.success_export_app_properties, Toast.LENGTH_LONG).show()
}
}
appPropertiesFileCreationRequestCode = null
}
} catch (e: Exception) {
Toast.makeText(this, R.string.error_export_app_properties, Toast.LENGTH_LONG).show()
Log.e(DatabaseLockActivity.TAG, "Unable to export app properties", e)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)

View File

@@ -64,11 +64,13 @@ class DurationDialogFragmentCompat : InputPreferenceDialogFragmentCompat() {
private fun durationToDaysHoursMinutesSeconds(duration: Long) {
if (duration < 0) {
mEnabled = false
mDays = 0
mHours = 0
mMinutes = 0
mSeconds = 0
} else {
mEnabled = true
mDays = (duration / (24L * 60L * 60L * 1000L)).toInt()
val daysMilliseconds = mDays * 24L * 60L * 60L * 1000L
mHours = ((duration - daysMilliseconds) / (60L * 60L * 1000L)).toInt()
@@ -125,10 +127,9 @@ class DurationDialogFragmentCompat : InputPreferenceDialogFragmentCompat() {
}
}
mEnabled = isSwitchActivated()
setSwitchAction({ isChecked ->
mEnabled = isChecked
}, mDays + mHours + mMinutes + mSeconds > 0)
}, mEnabled)
assignValuesInViews()
}

View File

@@ -31,9 +31,13 @@ abstract class ActionRunnable: Runnable {
var result: Result = Result()
override fun run() {
onStartRun()
onActionRun()
onFinishRun()
try {
onStartRun()
onActionRun()
onFinishRun()
} catch (runException: Exception) {
setError(runException)
}
}
abstract fun onStartRun()

View File

@@ -43,9 +43,14 @@ object TimeoutHelper {
private fun getLockPendingIntent(context: Context): PendingIntent {
return PendingIntent.getBroadcast(context.applicationContext,
REQUEST_ID,
Intent(LOCK_ACTION),
PendingIntent.FLAG_CANCEL_CURRENT)
REQUEST_ID,
Intent(LOCK_ACTION),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
} else {
PendingIntent.FLAG_CANCEL_CURRENT
}
)
}
/**

View File

@@ -60,11 +60,16 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
Intent.ACTION_SCREEN_OFF -> {
if (PreferencesUtil.isLockDatabaseWhenScreenShutOffEnable(context)) {
mLockPendingIntent = PendingIntent.getBroadcast(context,
4575,
Intent(intent).apply {
action = LOCK_ACTION
},
0)
4575,
Intent(intent).apply {
action = LOCK_ACTION
},
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0
}
)
// Launch the effective action after a small time
val first: Long = System.currentTimeMillis() + context.getString(R.string.timeout_screen_off).toLong()
val alarmManager = context.getSystemService(ALARM_SERVICE) as AlarmManager?

View File

@@ -0,0 +1,27 @@
package com.kunzisoft.keepass.utils
import android.content.res.Configuration
import android.util.Log
object DexUtil {
private val TAG = DexUtil::class.java.name
// Determine if the current environment is in DeX mode. Always returns false on non-Samsung
// devices.
fun isDexMode(config: Configuration): Boolean {
// This is the documented way to check this: https://developer.samsung.com/samsung-dex/modify-optimizing.html
return try {
val configClass = config.javaClass
val enabledConstant = configClass.getField("SEM_DESKTOP_MODE_ENABLED").getInt(configClass)
val enabledField = configClass.getField("semDesktopModeEnabled").getInt(config)
val isEnabled = enabledConstant == enabledField
Log.d(TAG, "DeX currently enabled: $isEnabled")
isEnabled
} catch (e: Exception) {
Log.d(TAG, "Failed to check for DeX mode; likely not Samsung device: $e")
false
}
}
}

View File

@@ -0,0 +1,27 @@
package com.kunzisoft.keepass.utils
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import android.util.Log
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
object MagikeyboardUtil {
private val TAG = MagikeyboardUtil::class.java.name
// Set whether MagikeyboardService is enabled. This change is persistent and survives app
// crashes and device restarts. The state is changed immediately and does not require an app
// restart.
fun setEnabled(context: Context, enabled: Boolean) {
val componentState = if (enabled) {
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
} else {
PackageManager.COMPONENT_ENABLED_STATE_DISABLED
}
Log.d(TAG, "Setting service state: $enabled")
val component = ComponentName(context, MagikeyboardService::class.java)
context.packageManager.setComponentEnabledSetting(component, componentState, PackageManager.DONT_KILL_APP)
}
}

View File

@@ -86,7 +86,7 @@ object UriUtil {
private fun isFileScheme(fileUri: Uri): Boolean {
val scheme = fileUri.scheme
if (scheme == null || scheme.isEmpty() || scheme.toLowerCase(Locale.ENGLISH) == "file") {
if (scheme == null || scheme.isEmpty() || scheme.lowercase(Locale.ENGLISH) == "file") {
return true
}
return false
@@ -94,7 +94,7 @@ object UriUtil {
private fun isContentScheme(fileUri: Uri): Boolean {
val scheme = fileUri.scheme
if (scheme != null && scheme.toLowerCase(Locale.ENGLISH) == "content") {
if (scheme != null && scheme.lowercase(Locale.ENGLISH) == "content") {
return true
}
return false

View File

@@ -104,10 +104,12 @@ class AdvancedUnlockInfoView @JvmOverloads constructor(context: Context,
return unlockMessageTextView?.text?.toString() ?: ""
}
set(value) {
if (value == null || value.isEmpty())
if (value == null || value.isEmpty()) {
unlockMessageTextView?.visibility = GONE
else
} else {
unlockMessageTextView?.visibility = VISIBLE
stopIconViewAnimation()
}
unlockMessageTextView?.text = value ?: ""
}

View File

@@ -2,6 +2,7 @@ package com.kunzisoft.keepass.view
import android.content.Context
import android.net.Uri
import android.os.Parcelable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.TextView
@@ -9,6 +10,9 @@ import androidx.constraintlayout.widget.ConstraintLayout
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.utils.UriUtil
import android.os.Parcel
import android.os.Parcelable.Creator
class KeyFileSelectionView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
@@ -54,4 +58,45 @@ class KeyFileSelectionView @JvmOverloads constructor(context: Context,
UriUtil.getFileData(context, value)?.name ?: value.path
} ?: ""
}
override fun onSaveInstanceState(): Parcelable {
val superState = super.onSaveInstanceState()
val saveState = SavedState(superState)
saveState.mUri = this.mUri
return saveState
}
override fun onRestoreInstanceState(state: Parcelable?) {
if (state !is SavedState) {
super.onRestoreInstanceState(state)
return
}
super.onRestoreInstanceState(state.superState)
this.mUri = state.mUri
}
internal class SavedState : BaseSavedState {
var mUri: Uri? = null
constructor(superState: Parcelable?) : super(superState) {}
private constructor(parcel: Parcel) : super(parcel) {
mUri = parcel.readParcelable(Uri::class.java.classLoader)
}
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeParcelable(mUri, flags)
}
companion object CREATOR : Creator<SavedState> {
override fun createFromParcel(parcel: Parcel): SavedState {
return SavedState(parcel)
}
override fun newArray(size: Int): Array<SavedState?> {
return arrayOfNulls(size)
}
}
}
}

View File

@@ -86,7 +86,8 @@ abstract class TemplateAbstractView<
if (mTemplate != template) {
mTemplate = template
if (mEntryInfo != null) {
populateEntryInfoWithViews(true)
populateEntryInfoWithViews(templateFieldNotEmpty = true,
retrieveDefaultValues = false)
}
buildTemplateAndPopulateInfo()
clearFocus()
@@ -203,9 +204,7 @@ abstract class TemplateAbstractView<
setNumberLines(20)
},
TemplateAttributeAction.CUSTOM_EDITION
).apply {
default = field.protectedValue.stringValue
}
)
return buildViewForTemplateField(customFieldTemplateAttribute, field, FIELD_CUSTOM_TAG)
}
@@ -275,22 +274,26 @@ abstract class TemplateAbstractView<
templateAttribute: TemplateAttribute,
entryInfoValue: String,
showEmptyFields: Boolean) {
var fieldView: TEntryFieldView? = findViewWithTag(fieldTag)
if (!showEmptyFields && entryInfoValue.isEmpty()) {
fieldView?.isFieldVisible = false
} else if (fieldView == null && entryInfoValue.isNotEmpty()) {
// Add new not referenced view if standard field not in template
fieldView = buildViewForNotReferencedField(
Field(templateAttribute.label,
ProtectedString(templateAttribute.protected, "")),
templateAttribute
) as? TEntryFieldView?
fieldView?.let {
addNotReferencedView(it as View)
try {
var fieldView: TEntryFieldView? = findViewWithTag(fieldTag)
if (!showEmptyFields && entryInfoValue.isEmpty()) {
fieldView?.isFieldVisible = false
} else if (fieldView == null && entryInfoValue.isNotEmpty()) {
// Add new not referenced view if standard field not in template
fieldView = buildViewForNotReferencedField(
Field(templateAttribute.label,
ProtectedString(templateAttribute.protected, "")),
templateAttribute
) as? TEntryFieldView?
fieldView?.let {
addNotReferencedView(it as View)
}
}
fieldView?.value = entryInfoValue
fieldView?.applyFontVisibility(mFontInVisibility)
} catch(e: Exception) {
Log.e(TAG, "Unable to populate entry field view", e)
}
fieldView?.value = entryInfoValue
fieldView?.applyFontVisibility(mFontInVisibility)
}
@Suppress("UNCHECKED_CAST")
@@ -299,22 +302,25 @@ abstract class TemplateAbstractView<
expires: Boolean,
expiryTime: DateInstant,
showEmptyFields: Boolean) {
var fieldView: TDateTimeView? = findViewWithTag(fieldTag)
if (!showEmptyFields && !expires) {
fieldView?.isFieldVisible = false
} else if (fieldView == null && expires) {
fieldView = buildViewForNotReferencedField(
Field(templateAttribute.label,
ProtectedString(templateAttribute.protected, "")),
templateAttribute
) as? TDateTimeView?
fieldView?.let {
addNotReferencedView(it as View)
try {
var fieldView: TDateTimeView? = findViewWithTag(fieldTag)
if (!showEmptyFields && !expires) {
fieldView?.isFieldVisible = false
} else if (fieldView == null && expires) {
fieldView = buildViewForNotReferencedField(
Field(templateAttribute.label,
ProtectedString(templateAttribute.protected, "")),
templateAttribute
) as? TDateTimeView?
fieldView?.let {
addNotReferencedView(it as View)
}
}
fieldView?.activation = expires
fieldView?.dateTime = expiryTime
} catch(e: Exception) {
Log.e(TAG, "Unable to populate date time view", e)
}
fieldView?.activation = expires
fieldView?.dateTime = expiryTime
}
/**
@@ -383,7 +389,8 @@ abstract class TemplateAbstractView<
return emptyList()
}
protected open fun populateEntryInfoWithViews(templateFieldNotEmpty: Boolean) {
protected open fun populateEntryInfoWithViews(templateFieldNotEmpty: Boolean,
retrieveDefaultValues: Boolean) {
if (mEntryInfo == null)
mEntryInfo = EntryInfo()
@@ -422,11 +429,12 @@ abstract class TemplateAbstractView<
mEntryInfo?.notes = it
}
retrieveCustomFieldsFromView(templateFieldNotEmpty)
retrieveCustomFieldsFromView(templateFieldNotEmpty, retrieveDefaultValues)
}
fun getEntryInfo(): EntryInfo {
populateEntryInfoWithViews(true)
populateEntryInfoWithViews(templateFieldNotEmpty = true,
retrieveDefaultValues = true)
return mEntryInfo ?: EntryInfo()
}
@@ -472,23 +480,31 @@ abstract class TemplateAbstractView<
return mViewFields.indexOfFirst { it.field.name.equals(name, true) }
}
private fun retrieveCustomFieldsFromView(templateFieldNotEmpty: Boolean = false) {
private fun retrieveCustomFieldsFromView(templateFieldNotEmpty: Boolean = false,
retrieveDefaultValues: Boolean = false) {
mEntryInfo?.customFields = mViewFields.mapNotNull {
getCustomField(it.field.name, templateFieldNotEmpty)
getCustomField(it.field.name, templateFieldNotEmpty, retrieveDefaultValues)
}.toMutableList()
}
protected fun getCustomField(fieldName: String): Field {
return getCustomField(fieldName, false)
?: Field(fieldName, ProtectedString(false))
return getCustomField(fieldName,
templateFieldNotEmpty = false,
retrieveDefaultValues = false
) ?: Field(fieldName, ProtectedString(false))
}
private fun getCustomField(fieldName: String, templateFieldNotEmpty: Boolean): Field? {
private fun getCustomField(fieldName: String,
templateFieldNotEmpty: Boolean,
retrieveDefaultValues: Boolean): Field? {
getViewFieldByName(fieldName)?.let { fieldId ->
val editView: View? = fieldId.view
val editView: View = fieldId.view
if (editView is GenericFieldView) {
// Do not return field with a default value
val defaultViewValue = if (editView.value == editView.default) "" else editView.value
val defaultViewValue =
if (retrieveDefaultValues || editView.value != editView.default) {
editView.value
} else ""
if (!templateFieldNotEmpty
|| (editView.tag == FIELD_CUSTOM_TAG && defaultViewValue.isNotEmpty())) {
return Field(
@@ -634,7 +650,8 @@ abstract class TemplateAbstractView<
override fun onSaveInstanceState(): Parcelable {
val superSave = super.onSaveInstanceState()
val saveState = SavedState(superSave)
populateEntryInfoWithViews(false)
populateEntryInfoWithViews(templateFieldNotEmpty = false,
retrieveDefaultValues = false)
saveState.template = this.mTemplate
saveState.entryInfo = this.mEntryInfo
onSaveEntryInstanceState(saveState)

View File

@@ -64,6 +64,7 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
TextEditFieldView(it).apply {
// hiddenProtectedValue (mHideProtectedValue) don't work with TextInputLayout
setProtection(field.protectedValue.isProtected)
default = templateAttribute.default
setMaxChars(templateAttribute.options.getNumberChars())
setMaxLines(templateAttribute.options.getNumberLines())
setActionClick(templateAttribute, field, this)
@@ -79,7 +80,7 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
return context?.let {
TextSelectFieldView(it).apply {
setItems(templateAttribute.options.getListItems())
default = field.protectedValue.stringValue
default = templateAttribute.default
setActionClick(templateAttribute, field, this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_NO
@@ -198,8 +199,9 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
return super.populateViewsWithEntryInfo(showEmptyFields)
}
override fun populateEntryInfoWithViews(templateFieldNotEmpty: Boolean) {
super.populateEntryInfoWithViews(templateFieldNotEmpty)
override fun populateEntryInfoWithViews(templateFieldNotEmpty: Boolean,
retrieveDefaultValues: Boolean) {
super.populateEntryInfoWithViews(templateFieldNotEmpty, retrieveDefaultValues)
mEntryInfo?.otpModel = OtpEntryFields.parseFields { key ->
getCustomField(key).protectedValue.toString()
}?.otpModel

View File

@@ -187,6 +187,6 @@ class TextEditFieldView @JvmOverloads constructor(context: Context,
companion object {
const val MAX_CHARS_LIMIT = Integer.MAX_VALUE
const val MAX_LINES_LIMIT = 40
const val MAX_LINES_LIMIT = Integer.MAX_VALUE
}
}

View File

@@ -194,6 +194,7 @@ class TextSelectFieldView @JvmOverloads constructor(context: Context,
get() = valueSpinnerAdapter.getItem(mDefaultPosition)
set(value) {
mDefaultPosition = valueSpinnerAdapter.getPosition(value)
valueSpinnerAdapter.notifyDataSetChanged()
}
override fun setOnActionClickListener(onActionClickListener: OnClickListener?,

View File

@@ -0,0 +1,32 @@
package com.kunzisoft.keepass.viewmodels
import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
class AdvancedUnlockViewModel : ViewModel() {
var allowAutoOpenBiometricPrompt : Boolean = true
var deviceCredentialAuthSucceeded: Boolean? = null
val onInitAdvancedUnlockModeRequested : LiveData<Void?> get() = _onInitAdvancedUnlockModeRequested
private val _onInitAdvancedUnlockModeRequested = SingleLiveEvent<Void?>()
val onUnlockAvailabilityCheckRequested : LiveData<Void?> get() = _onUnlockAvailabilityCheckRequested
private val _onUnlockAvailabilityCheckRequested = SingleLiveEvent<Void?>()
val onDatabaseFileLoaded : LiveData<Uri?> get() = _onDatabaseFileLoaded
private val _onDatabaseFileLoaded = SingleLiveEvent<Uri?>()
fun initAdvancedUnlockMode() {
_onInitAdvancedUnlockModeRequested.call()
}
fun checkUnlockAvailability() {
_onUnlockAvailabilityCheckRequested.call()
}
fun databaseFileLoaded(databaseUri: Uri?) {
_onDatabaseFileLoaded.value = databaseUri
}
}

View File

@@ -2,6 +2,7 @@ package com.kunzisoft.keepass.viewmodels
import android.os.Parcel
import android.os.Parcelable
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
@@ -30,6 +31,10 @@ class IconPickerViewModel: ViewModel() {
MutableLiveData<IconCustomState>()
}
val customIconUpdated : MutableLiveData<IconCustomState> by lazy {
MutableLiveData<IconCustomState>()
}
fun pickStandardIcon(icon: IconImageStandard) {
standardIconPicked.value = icon
}
@@ -54,6 +59,10 @@ class IconPickerViewModel: ViewModel() {
customIconRemoved.value = customIcon
}
fun updateCustomIcon(customIcon: IconCustomState) {
customIconUpdated.value = customIcon
}
data class IconCustomState(var iconCustom: IconImageCustom? = null,
var error: Boolean = true,
var errorStringId: Int = -1,

View File

@@ -144,7 +144,7 @@ internal class PublicSuffixListData(
}
companion object {
val WILDCARD_LABEL = byteArrayOf('*'.toByte())
val WILDCARD_LABEL = byteArrayOf('*'.code.toByte())
val PREVAILING_RULE = listOf("*")
val EMPTY_RULE = listOf<String>()
const val EXCEPTION_MARKER = '!'

View File

@@ -36,7 +36,7 @@ internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): S
while (true) {
val byte0 = if (expectDot) {
expectDot = false
'.'.toByte()
'.'.code.toByte()
} else {
labels[currentLabelIndex][currentLabelByteIndex] and BITMASK
}
@@ -103,7 +103,7 @@ internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): S
*/
private fun ByteArray.findStartOfLineFromIndex(start: Int): Int {
var index = start
while (index > -1 && this[index] != '\n'.toByte()) {
while (index > -1 && this[index] != '\n'.code.toByte()) {
index--
}
index++
@@ -115,7 +115,7 @@ private fun ByteArray.findStartOfLineFromIndex(start: Int): Int {
*/
private fun ByteArray.findEndOfLineFromIndex(start: Int): Int {
var end = 1
while (this[start + end] != '\n'.toByte()) {
while (this[start + end] != '\n'.code.toByte()) {
end++
}
return end

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ffffff"
android:pathData="M 11 2.0566406 C 6.762335 2.4220229 3.0067094 5.7987155 2.203125 9.9785156 C 1.3601753 13.960549 3.1781148 18.394742 6.7089844 20.480469 C 9.6237318 22.368157 13.514425 22.492178 16.582031 20.892578 C 17.959775 20.180473 19.316015 19.099467 20.087891 17.808594 L 18.402344 16.791016 C 16.277892 19.724364 12.039121 20.844605 8.7519531 19.306641 C 5.481064 17.911182 3.4461934 14.150571 4.109375 10.648438 C 4.6649664 7.2806969 7.5784749 4.4226117 11 4.0839844 L 11 2.0566406 z M 13 2.0644531 L 13 4.09375 C 16.367309 4.4801387 19.308002 7.2166099 19.861328 10.574219 C 20.123352 12.069186 19.935398 13.632674 19.367188 15.037109 C 19.94644 15.387646 20.527063 15.73602 21.105469 16.087891 C 22.671737 12.714066 22.120988 8.4920871 19.708984 5.6542969 C 18.063396 3.6246553 15.604973 2.2995704 13 2.0644531 z M 12 6.7148438 C 10.737143 6.7148437 9.7148438 7.737143 9.7148438 9 L 9.7148438 10.142578 L 9.1425781 10.142578 C 8.5140068 10.142578 8 10.656585 8 11.285156 L 8 15.857422 C 8 16.491709 8.5140068 17 9.1425781 17 L 14.857422 17 C 15.491709 17 16 16.491709 16 15.857422 L 16 11.285156 C 16 10.656585 15.491709 10.142578 14.857422 10.142578 L 14.285156 10.142578 L 14.285156 9 C 14.285156 7.737143 13.262857 6.7148438 12 6.7148438 z M 12 7.8574219 C 12.634286 7.8574219 13.142578 8.3714294 13.142578 9 L 13.142578 10.142578 L 10.857422 10.142578 L 10.857422 9 C 10.857422 8.3714294 11.371429 7.8574219 12 7.8574219 z M 12 12.427734 C 12.634286 12.427734 13.142578 12.943693 13.142578 13.572266 C 13.142578 14.20655 12.634286 14.714844 12 14.714844 C 11.371429 14.714844 10.857422 14.20655 10.857422 13.572266 C 10.857422 12.943693 11.371429 12.427734 12 12.427734 z" />
</vector>

View File

@@ -52,8 +52,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@+id/biometric_message"
tools:text="@string/advanced_unlock_prompt_store_credential_title"
style="@style/KeepassDXStyle.TextAppearance.Default.TextOnPrimary"
android:textSize="14sp"
style="@style/KeepassDXStyle.TextAppearance.Secondary.TextOnPrimary"
android:gravity="center" />
<TextView
@@ -67,7 +66,6 @@
app:layout_constraintTop_toBottomOf="@+id/biometric_title"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="Sample error"
style="@style/KeepassDXStyle.TextAppearance.Secondary.TextOnPrimary"
android:textSize="12sp"
style="@style/KeepassDXStyle.TextAppearance.Warning.TextOnPrimary"
android:gravity="center" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -23,6 +23,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
tools:targetApi="o">
<com.kunzisoft.keepass.view.SpecialModeView

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 Jeremy Jamet / Kunzisoft.
This file is part of KeePassDX.
KeePassDX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
KeePassDX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
-->
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/default_margin"
android:importantForAutofill="noExcludeDescendants"
tools:targetApi="o">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon_edit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginEnd="@dimen/default_margin"
android:src="@drawable/ic_blank_32dp"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/icon_edit_name_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/icon_edit_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:inputType="text"
android:maxLines="1"
android:singleLine="true"
android:hint="@string/hint_icon_name"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View File

@@ -56,7 +56,7 @@
android:layout_marginRight="20dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
style="@style/KeepassDXStyle.TextAppearance.WarningTextStyle"/>
style="@style/KeepassDXStyle.TextAppearance.Warning"/>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_dialog_bar"

View File

@@ -63,7 +63,7 @@
android:layout_marginEnd="@dimen/card_view_margin_horizontal"
android:layout_marginRight="@dimen/card_view_margin_horizontal"
android:text="@string/error_otp_type"
style="@style/KeepassDXStyle.TextAppearance.WarningTextStyle"/>
style="@style/KeepassDXStyle.TextAppearance.Warning"/>
<androidx.cardview.widget.CardView
android:id="@+id/card_view_otp_selection"

View File

@@ -30,8 +30,7 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:minHeight="56dp"
android:maxHeight="72dp"
android:minHeight="48dp"
app:layout_constraintWidth_percent="@dimen/content_percent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -104,10 +103,12 @@
tools:text="7543A7EAB2EA7CFD1394F1615EBEB08C" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
<LinearLayout
android:id="@+id/node_options"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="end"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
app:layout_constraintTop_toTopOf="parent"
@@ -164,7 +165,7 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/node_otp_container" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<View
android:layout_width="match_parent"

View File

@@ -30,8 +30,7 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:minHeight="56dp"
android:maxHeight="72dp"
android:minHeight="48dp"
app:layout_constraintWidth_percent="@dimen/content_percent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -89,18 +88,6 @@
android:maxLines="2"
tools:text="Node Title" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/node_subtext"
style="@style/KeepassDXStyle.TextAppearance.Group.SubTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-4dp"
android:gravity="center_vertical"
android:lines="1"
android:singleLine="true"
android:visibility="gone"
tools:text="Node SubTitle" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/node_meta"
style="@style/KeepassDXStyle.TextAppearance.Group.Meta"

View File

@@ -19,6 +19,12 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_edit"
android:icon="@drawable/ic_mode_edit_white_24dp"
android:title="@string/menu_edit"
android:orderInCategory="5"
app:iconTint="?attr/colorControlNormal"
app:showAsAction="ifRoom" />
<item android:id="@+id/menu_delete"
android:icon="@drawable/ic_delete_forever_white_24dp"
android:title="@string/menu_delete"

View File

@@ -79,7 +79,7 @@
<string name="no_url_handler">ثبت متصفح لزيارة هذا الرابط.</string>
<string name="progress_create">إنشاء قاعدة بيانات جديدة …</string>
<string name="protection">الحماية</string>
<string name="read_only">للقراءة فقط</string>
<string name="read_only">محمي من التعديل</string>
<string name="content_description_remove_from_list">حذف</string>
<string name="root">الجذر</string>
<string name="memory_usage">استخدام الذاكرة</string>
@@ -99,10 +99,10 @@
<string name="underline">تسطير</string>
<string name="uppercase">حروف كبيرة</string>
<string name="warning">تحذير</string>
<string name="warning_empty_password">هل تريد حقاً استخدام سلسلة فارغة ككلمة سرية ؟</string>
<string name="warning_no_encryption_key">هل أنت متأكد من أنك لا تريد استخدام أي مفتاح تشفير ؟</string>
<string name="warning_empty_password">هل تريد المتابعة دون حماية قاعدة البيانات بكلمة سر ؟</string>
<string name="warning_no_encryption_key">أمتأكد أنك لا تريد استخدام أي مفتاح لتشفير ؟</string>
<string name="version_label">الإصدار %1$s</string>
<string name="education_new_node_title">أضف عناصر جديدة إلى قاعدتك</string>
<string name="education_new_node_title">أضف عناصر إلى قاعدة البيانات</string>
<string name="education_entry_new_field_title">إضافة حقول مخصصة</string>
<string name="education_field_copy_title">نسخ حقل</string>
<string name="education_lock_title">تأمين قاعدة البيانات</string>
@@ -111,7 +111,7 @@
<string name="add_entry">إضافة مدخلة</string>
<string name="edit_entry">تحرير مدخلة</string>
<string name="key_derivation_function">وظيفة اشتقاق المفتاح</string>
<string name="app_timeout">مهلة التطبيق</string>
<string name="app_timeout">انتهت المهلة</string>
<string name="app_timeout_summary">مدة الانتظار قبل إقفال قاعدة البيانات</string>
<string name="file_manager_install_description">المحرر الذي يمتلك صلاحتي ACTION_CREATE_DOCUMENT و ACTION_OPEN_DOCUMENT ضروري لانشاء, وفتح وحفض قواعد البيانات.</string>
<string name="clipboard_error">بعض الأجهزة لا تسمح للتطبيقات باستعمال الحافظة.</string>
@@ -120,8 +120,8 @@
<string name="select_to_copy">اختر لنسخ %1$s إلى الحافظة</string>
<string name="retrieving_db_key">يجلب مفتاح قاعدة البيانات…</string>
<string name="default_checkbox">استخدامها كقاعدة بيانات افتراضية</string>
<string name="html_about_licence">KeePassDX © %1$d كونزيسوفت &lt;strong&gt;مفتوح المصدر&lt;/strong&gt; و &lt;strong&gt;بدون اعلانات&lt;/strong&gt;.
\n يوزع كما هو، بدون ضمان, تحت ترخيص &lt;strong&gt;GPLv3&lt;/strong&gt;</string>
<string name="html_about_licence">KeePassDX © %1$d كونزيسوفت <strong>مفتوح المصدر</strong> و <strong>بدون اعلانات</strong>.
\n يوزع كما هو، بدون ضمان, تحت ترخيص <strong>GPLv3</strong>.</string>
<string name="entry_accessed">نُفذ إليه</string>
<string name="entry_expires">تنتهي صلاحيته في</string>
<string name="entry_keyfile">ملف المفتاح</string>
@@ -133,7 +133,7 @@
<string name="error_load_database">تعذر تحميل قاعدة البيانات.</string>
<string name="error_load_database_KDF_memory">لا يمكن تحميل المفتاح، حاول تقليل \"الذاكرة المستخدمة\" من قبل KDF.</string>
<string name="error_pass_gen_type">يجب تحديد نوع واحد على الأقل لتوليد كلمة السر.</string>
<string name="error_rounds_too_large">\"جولات\" كبيرة جداً. الإعداد إلى 2147483648.</string>
<string name="error_rounds_too_large">\"جولات التحويل\" كثيرة جداً. الإعداد إلى 2147483648.</string>
<string name="error_string_key">يجب أن يكون لكل سلسلة اسم حقل.</string>
<string name="error_wrong_length">أدخل عددًا صحيحًا موجبًا في حقل «الطول».</string>
<string name="error_autofill_enable_service">تعذر تمكين خدمة الملء التلقائي.</string>
@@ -147,7 +147,7 @@
<string name="hint_generated_password">كلمة السر الموَلدة</string>
<string name="hint_keyfile">الملف المفتاحي</string>
<string name="hide_password_title">اخفاء كلمات السر</string>
<string name="copy_field">نُسخ %1$s</string>
<string name="copy_field">نُسخة من %1$s</string>
<string name="menu_copy">نسخ</string>
<string name="menu_move">نقل</string>
<string name="menu_paste">لصق</string>
@@ -166,8 +166,8 @@
<string name="unsupported_db_version">قاعدة بيانات غير مدعومة.</string>
<string name="build_label">بناء %1$s</string>
<string name="encrypted_value_stored">تم حفظ كلمة السر المشفرة</string>
<string name="no_credentials_stored">قاعدة البيانات لا تمتلك كلمة سر.</string>
<string name="menu_appearance_settings">مظهر</string>
<string name="no_credentials_stored">قاعدة البيانات لا تمتلك بيانات اعتماد.</string>
<string name="menu_appearance_settings">المظهر</string>
<string name="general">عام</string>
<string name="autofill">ملأ تلقائي</string>
<string name="autofill_sign_in_prompt">سجل باستخدام KeePassDX</string>
@@ -187,7 +187,7 @@
<string name="file_name">اسم الملف</string>
<string name="path">مسار</string>
<string name="database_history">تأريخ</string>
<string name="clipboard_notifications_summary">مكن اشعارات الحافظة لنسخ الحقول</string>
<string name="clipboard_notifications_summary">أظهر اشعارات الحافظة لنسخ الحقول عند عرض مدخل</string>
<string name="advanced_unlock">البصمة</string>
<string name="biometric_unlock_enable_title">فحص البصمة</string>
<string name="biometric_unlock_enable_summary">يسمح بفحص البصمة لفتح قاعدة البيانات</string>
@@ -210,23 +210,23 @@
<string name="keyboard_notification_entry_summary">أظهر إشعار عند توفر مدخل</string>
<string name="keyboard_notification_entry_content_title_text">مدخل</string>
<string name="keyboard_notification_entry_clear_close_title">إمسح عند الخروج</string>
<string name="keyboard_notification_entry_clear_close_summary">إمسح مدخل الحافظة عند إغلاق الإشعار</string>
<string name="keyboard_notification_entry_clear_close_summary">أغلق قاعدة البيانات عند إغلاق الإشعار</string>
<string name="keyboard_appearance_category">مظهر</string>
<string name="keyboard_theme_title">سمة لوحة المفاتيح</string>
<string name="keyboard_keys_category">مفاتيح</string>
<string name="keyboard_key_vibrate_title">إهتز عند اللمس</string>
<string name="keyboard_key_vibrate_title">إهتزاز عند اللمس</string>
<string name="keyboard_key_sound_title">صوت عند اللمس</string>
<string name="allow_no_password_title">"إسمح بالفتح دون كلمة سر "</string>
<string name="enable_read_only_title">محمي من التعديل</string>
<string name="enable_read_only_summary">افتح قاعدة البيانات للقراءة فقط افتراضيا</string>
<string name="enable_education_screens_title">شاشات تعليمية</string>
<string name="reset_education_screens_summary">أعد عرض كل العناصر التعليمية</string>
<string name="reset_education_screens_text">إعادة تعيين الشاشات التعليمية</string>
<string name="reset_education_screens_summary">أعد عرض كل المعلومات التعليمية</string>
<string name="reset_education_screens_text">إعادة تعيين الشاشات التلميحات</string>
<string name="education_create_database_title">أنشئ قاعدة بيانات</string>
<string name="education_create_database_summary">أنشئ ملف إدارة كلمات السر.</string>
<string name="education_select_database_title">إفتح قاعدة بيانات</string>
<string name="sort_recycle_bin_bottom">سلة المحذوفات في الأسفل</string>
<string name="sort_db">قاعده بيانات طبيعية</string>
<string name="sort_db">ترتيب طبيعي</string>
<string name="sort_last_access_time">الوصول</string>
<string name="lock">إقفال</string>
<string name="assign_master_key">تعيين مفتاح رئيسي</string>
@@ -246,9 +246,9 @@
<string name="content_description_background">الخلفية</string>
<string name="rounds">دورات التحويل</string>
<string name="rounds_explanation">توفر الدورات الاضافية ضد هجوم توليد التركيبات ،لكنها تبطئ التحميل والحفظ.</string>
<string name="memory_usage_explanation">مقدار الذاكرة لاستخدامها في دالة اشتقاق المفتاح.</string>
<string name="memory_usage_explanation">مقدار الذاكرة المستخدمة في دالة اشتقاق المفتاح.</string>
<string name="parallelism_explanation">درجة التوازي (عدد العمليات) لدالة اشتقاق المفتاح.</string>
<string name="sort_groups_before">مجموعات قبل</string>
<string name="sort_groups_before">المجموعات أولًا</string>
<string name="selection_mode">نمط التحديد</string>
<string name="do_not_kill_app">لا تقتل التطبيق…</string>
<string name="content_description_node_children">العقد الفرعية</string>
@@ -264,7 +264,7 @@
<string name="content_description_update_from_list">تحديث</string>
<string name="content_description_keyboard_close_fields">أغلق الحقول</string>
<string name="error_create_database_file">لا يمكن انشاء قاعدة بيانات بكلمة السر وملف المفتاح الحاليين.</string>
<string name="menu_advanced_unlock_settings">إلغاء القفل المتقدم</string>
<string name="menu_advanced_unlock_settings">فك القفل المتقدم</string>
<string name="entry_attachments">مرفقات</string>
<string name="entry_history">السجل</string>
<string name="entry_add_attachment">أضف مرفقا</string>
@@ -283,7 +283,7 @@
<string name="otp_algorithm">الخوارزمية</string>
<string name="otp_digits">أرقام</string>
<string name="otp_counter">العداد</string>
<string name="entry_setup_otp">كلمة المرور للمرة الواحدة</string>
<string name="entry_setup_otp">عيّن كلمة مرور لمرة واحدة</string>
<string name="entry_UUID">UUID</string>
<string name="html_about_contribution">من أجل &lt;strong&gt;حماية خصوصيتا&lt;/strong&gt;٫&lt;strong&gt; إصلاح العلل&lt;/strong&gt;٫ &lt;strong&gt;إضافة مميزات&lt;/strong&gt; &lt;strong&gt;وجعلنا نشطاء دائما&lt;/strong&gt;٫ نحن نعتمد على &lt;strong&gt;مساهمتك&lt;/strong&gt;.</string>
<string name="content_description_keyfile_checkbox">خانة تأشير الملف المفتاحي</string>
@@ -295,10 +295,10 @@
<string name="hide_broken_locations_title">اِخفي روابط قواعد البيانات المعطلة</string>
<string name="show_recent_files_summary">أظهر موقع قواعد البيانات الأخيرة</string>
<string name="show_recent_files_title">أظهر الملفات الأخيرة</string>
<string name="remember_keyfile_locations_summary">تذكر موقع الملفات المفتاحية لقاعدة البيانات</string>
<string name="remember_keyfile_locations_title">احفظ موقع الملف المفتاحي</string>
<string name="remember_database_locations_summary">تذكر موقع قاعدة البيانات</string>
<string name="remember_database_locations_title">موقع تخزين قاعدة البيانات</string>
<string name="remember_keyfile_locations_summary">تعقب موقع الملفات المفتاحية لقاعدة البيانات</string>
<string name="remember_keyfile_locations_title">تذكر موقع الملف المفتاحي</string>
<string name="remember_database_locations_summary">تعقب موقع قاعدة البيانات</string>
<string name="remember_database_locations_title">تذكر موقع تخزين قاعدة البيانات</string>
<string name="contains_duplicate_uuid_procedure">للمتابعة هل تريد حل المشكلة بتوليد UUID للعناصر المكررة ؟</string>
<string name="contains_duplicate_uuid">تحتوي قاعدة البيانات على UUID مكرر.</string>
<string name="auto_focus_search_title">البحث السريع</string>
@@ -379,8 +379,8 @@
<string name="keyboard_selection_entry_title">اختيار المدخلة</string>
<string name="device_keyboard_setting_title">إعدادات لوحة مفاتيح الجهاز</string>
<string name="magic_keyboard_explanation_summary">نشِّط لوحة مفاتيح مخصصة لملأ كلمة السر وحقول معرّفك</string>
<string name="biometric_auto_open_prompt_summary">اطلب فحص البصمة ان كانت قاعدة البيانات معدّة لذلك</string>
<string name="biometric_auto_open_prompt_title">افتح محث البصمة تلقائيا</string>
<string name="biometric_auto_open_prompt_summary">اطلب فك القفل المتقدم ان كانت قاعدة البيانات معدّة لذلك</string>
<string name="biometric_auto_open_prompt_title">افتح المحث تلقائيا</string>
<string name="keystore_not_accessible">لم يُهيأ مخزن المفاتيح بشكل صحيح.</string>
<string name="warning_remove_unlinked_attachment">حذف البيانات سيقلل من حجم قاعدة البيانات لكن احذر أن تكون إحدى هذه البيانات ملحقة لكي-باس.</string>
<string name="subdomain_search_summary">البحث في نطاقات الويب التي فيها قيود النطاقات الفرعية</string>
@@ -408,4 +408,79 @@
<string name="education_generate_password_title">أنشئ كلمة سر قوية</string>
<string name="save_mode">وضع الحفظ</string>
<string name="search_mode">وضع البحث</string>
<string name="version">النسخة</string>
<string name="template_group_name">النماذج</string>
<string name="holder">الحامل</string>
<string name="number">الرقم</string>
<string name="card_verification_value">CVV</string>
<string name="personal_identification_number">PIN</string>
<string name="id_card">بطاقة الهوية</string>
<string name="type">النوع</string>
<string name="cryptocurrency">محفظة عملات مشفرة</string>
<string name="public_key">المفتاح العمومي</string>
<string name="private_key">المفتاح الخاص</string>
<string name="account">الحساب</string>
<string name="bank">مصرف</string>
<string name="bank_name">اسم المصرف</string>
<string name="secure_note">ملاحظة آمنة</string>
<string name="error_word_reserved">هذه الكلمة محجوزة ولا يمكن استخدامها.</string>
<string name="error_field_name_already_exists">اسم الحقل موجود سلفًا.</string>
<string name="error_file_to_big">الملف الذي ترفعه كبير.</string>
<string name="error_upload_file">حدث خطأ أثناء رفع الملف.</string>
<string name="error_duplicate_file">بيانات الملف موجودة سلفًا.</string>
<string name="error_remove_file">حدث خطأ أثناء إزالة بيانات الملف.</string>
<string name="error_start_database_action">حدث خطأ أثناء تنفيذ إجراء على قاعدة البيانات.</string>
<string name="content_description_otp_information">معلومات السر لمرة واحدة</string>
<string name="membership">العضوية</string>
<string name="name">الاسم</string>
<string name="email">البريد الإلكتروني</string>
<string name="email_address">البريد الإلكتروني</string>
<string name="ssid">SSID</string>
<string name="debit_credit_card">بطاقة السحب الفوري / الإئتمان</string>
<string name="error_registration_read_only">لا يمكن حفظ عنصر في قاعدة بيانات مفتوحة للقراءة فقط</string>
<string name="otp_secret">الرمز السري</string>
<string name="place_of_issue">مكان المشكلة</string>
<string name="date_of_issue">تاريخ المشكلة</string>
<string name="standard">المعيار</string>
<string name="template">النموذج</string>
<string name="error_invalid_OTP">الرمز السري لـ OTP غير صالح.</string>
<string name="error_otp_digits">يجب أن الرمز محتوًا بين %1$d و %2$d رقمًا.</string>
<string name="autofill_select_entry">اختر مُدخلًا…</string>
<string name="content">المحتوى</string>
<string name="keyboard_save_search_info_title">احفظ المعلومات المشاركة</string>
<string name="custom_fields">حقول مخصصة</string>
<string name="back_to_previous_keyboard">عُد للوحة المفاتيح السابقة</string>
<string name="select_entry">اختر مدخلًا</string>
<string name="autofill_close_database_title">أغلق قاعدة البيانات</string>
<string name="success_import_app_properties">أّستوردت خصائص التطبيق</string>
<string name="success_export_app_properties">صُدرت خصائص التطبيق</string>
<string name="warning_database_revoked">أُجهض الوصول إلى الملف بواسطة مدير الملفات ، أغلق قاعدة البيانات ثم أعد فتحها.</string>
<string name="properties">الخصائص</string>
<string name="token">الرمز</string>
<string name="seed">البذرة</string>
<string name="error_database_uri_null">يتعذر استرداد مسار قاعدة البيانات.</string>
<string name="error_rebuild_list">يتعذر إعادة بناء القائمة بشكل صحيح.</string>
<string name="menu_keystore_remove_key">احذف رمز فك القفل المتقدم</string>
<string name="menu_form_filling_settings">تعبئة الحقول</string>
<string name="menu_reload_database">أعد تحميل قاعدة البيانات</string>
<string name="menu_external_icon">أيقونة خارجية</string>
<string name="registration_mode">وضع التسجيل</string>
<string name="import_app_properties_title">استورد خصائص التطبيق</string>
<string name="import_app_properties_summary">اختر ملفًا لاستيراد خصائص التطبيق</string>
<string name="export_app_properties_title">صدّر خصائص التطبيق</string>
<string name="export_app_properties_summary">أنشئ ملفًا لتصدير خصائص التطبيق</string>
<string name="error_import_app_properties">خطأ أثناء استيراد خصائص التطبيق</string>
<string name="error_export_app_properties">خطأ أثناء تصدير خصائص التطبيق</string>
<string name="warning_database_info_changed">غُيِّرت معلومات قاعدة البيانات من خارج هذا التطبيق.</string>
<string name="warning_database_info_changed_options">اكتب فوق التعديلات الخارجية عن طريق حفظ قاعدة البيانات أو أعد تحميلها لتضمين هذه التغييرات.</string>
<string name="open_advanced_unlock_prompt_store_credential">افتح محث فك القفل المتقدم لتخزين بيانات الاعتماد</string>
<string name="open_advanced_unlock_prompt_unlock_database">افتح محث فك القفل المتقدم لفتح قاعدة البيانات</string>
<string name="credential_before_click_advanced_unlock_button">اكتب كلمة السر، وأنقر هذا الزر.</string>
<string name="device_credential">بيانات الاعتماد للجهاز</string>
<string name="advanced_unlock_tap_delete">انفر لحذف مفاتيح فك القفل المتقدم</string>
<string name="keyboard_search_share_title">ابحث في المعلومات المشاركة</string>
<string name="keyboard_auto_go_action_title">إجراء اللمس التلقائي</string>
<string name="keyboard_previous_fill_in_title">إجراء لمس تلقائي</string>
<string name="keyboard_previous_lock_title">اقفل قاعدة البيانات</string>
<string name="education_advanced_unlock_title">فك القفل المتقدم لقاعدة البيانات</string>
</resources>

View File

@@ -197,7 +197,7 @@
<string name="clipboard_warning">Vymazat historii schránky manuálně, pokud automatické vymazání schránky selže.</string>
<string name="lock">Zamknout</string>
<string name="lock_database_screen_off_title">Zámek obrazovky</string>
<string name="lock_database_screen_off_summary">Při zhasnutí obrazovky uzamknout databázi</string>
<string name="lock_database_screen_off_summary">Několik vteřin po zhasnutí obrazovky uzamknout databázi</string>
<string name="advanced_unlock">Rozšířené odemknutí</string>
<string name="biometric_unlock_enable_title">Biometrické odemknutí</string>
<string name="biometric_unlock_enable_summary">Nechá otevřít databázi snímáním biometrického údaje</string>
@@ -224,7 +224,7 @@
<string name="application_appearance">Rozhraní</string>
<string name="other">Ostatní</string>
<string name="keyboard">Klávesnice</string>
<string name="magic_keyboard_title">Magikeyboard</string>
<string name="magic_keyboard_title">Klávesnice Magikeyboard</string>
<string name="magic_keyboard_explanation_summary">Aktivovat vlastní klávesnici, která snadno vyplní hesla a další položky identity</string>
<string name="allow_no_password_title">Umožnit bez hlavního klíče</string>
<string name="allow_no_password_summary">Povolit klepnutí na \"Otevřít\", i když není vybráno žádné heslo</string>
@@ -236,7 +236,7 @@
<string name="reset_education_screens_summary">Opět zobrazit všechny vzdělávací informace</string>
<string name="reset_education_screens_text">Nastavit vzdělávací nápovědy do výchozího stavu</string>
<string name="education_create_database_title">Vytvořit databázový soubor</string>
<string name="education_create_database_summary">Založte svůj první soubor pro správu hesel.</string>
<string name="education_create_database_summary">Vytvořte svůj první soubor pro správu hesel.</string>
<string name="education_select_database_title">Otevřít existující databázi</string>
<string name="education_select_database_summary">Otevřete svou dříve používanou databázi ze správce souborů a pokračujte v jejím používání.</string>
<string name="education_new_node_title">Přidejte záznamy do databáze</string>
@@ -267,7 +267,7 @@
<string name="education_sort_summary">Vyberte řazení položek a skupin.</string>
<string name="education_donation_title">Zapojit se</string>
<string name="education_donation_summary">Zapojte se a pomozte zvýšit stabilitu, bezpečnost a doplnění dalších funkcí.</string>
<string name="html_text_ad_free">Na rozdíl od mnoha aplikací pro správu hesel je tato &lt;strong&gt;bez reklam&lt;/strong&gt;, je \u0020&lt;strong&gt;svobodný software pod copyleft licencí&lt;/strong&gt; a nesbírá žádné osobní údaje na svých serverech bez ohledu na to, jakou verzi používáte.</string>
<string name="html_text_ad_free">Na rozdíl od mnoha aplikací pro správu hesel je tato <strong>bez reklam</strong>, je <strong>svobodný software pod copyleft licencí</strong> a nesbírá žádné osobní údaje na svých serverech bez ohledu na to, jakou verzi používáte.</string>
<string name="html_text_buy_pro">Zakoupením varianty \"pro\" získáte přístup k tomuto &lt;strong&gt;vizuálnímu stylu&lt;/strong&gt; a hlavně pomůžete &lt;strong&gt;uskutečnění komunitních projektů.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Tento &lt;strong&gt;vizuální styl&lt;/strong&gt; je k dispozici díky vaší štědrosti.</string>
<string name="html_text_donation">Pro zajištění svobody nás všech a pokračování aktivity počítáme s Vaším &lt;strong&gt;přispěním.&lt;/strong&gt;</string>
@@ -285,8 +285,8 @@
<string name="icon_pack_choose_title">Sada ikon</string>
<string name="icon_pack_choose_summary">Sada ikon používaných v aplikaci</string>
<string name="build_label">Sestavení %1$s</string>
<string name="keyboard_name">Magikeyboard</string>
<string name="keyboard_label">Magikeyboard (KeePassDX)</string>
<string name="keyboard_name">Klávesnice Magikeyboard</string>
<string name="keyboard_label">Klávesnice Magikeyboard (KeePassDX)</string>
<string name="keyboard_setting_label">Magikeyboard nastavení</string>
<string name="keyboard_entry_category">Záznam</string>
<string name="keyboard_entry_timeout_title">Časový limit</string>
@@ -315,7 +315,7 @@
<string name="delete_entered_password_title">Smazat heslo</string>
<string name="delete_entered_password_summary">Smaže heslo zadané po pokusu o připojení k databázi</string>
<string name="content_description_open_file">Otevřít soubor</string>
<string name="content_description_node_children">Podřazené prvky uzlu</string>
<string name="content_description_node_children">Podřazení uzlu</string>
<string name="content_description_add_node">Přidat uzel</string>
<string name="content_description_add_entry">Přidat záznam</string>
<string name="content_description_add_group">Přidat skupinu</string>
@@ -411,7 +411,7 @@
<string name="hide_expired_entries_summary">Propadlé záznamy nebudou ukázány</string>
<string name="contact">Kontakt</string>
<string name="contribution">Příspěvky</string>
<string name="feedback">Feedback</string>
<string name="feedback">Zpětná vazba</string>
<string name="auto_focus_search_title">Snadné hledání</string>
<string name="auto_focus_search_summary">Při otevření databáze žádat hledání</string>
<string name="remember_database_locations_title">Pamatovat si umístění databází</string>
@@ -474,13 +474,13 @@
<string name="database_data_remove_unlinked_attachments_summary">Odstraní přílohy obsažené v databázi, ale nikoli přílohy propojené se záznamem</string>
<string name="education_add_attachment_title">Přidat přílohu</string>
<string name="education_add_attachment_summary">Nahrát přílohu k záznamu pro uložení důležitých externích dat.</string>
<string name="show_uuid_summary">Ukáže UUID propojené se záznamem</string>
<string name="show_uuid_summary">Ukáže UUID propojené se záznamem nebo skupinou</string>
<string name="show_uuid_title">Ukázat UUID</string>
<string name="autofill_read_only_save">Uložení dat není povoleno, je-li databáze v režimu pouze pro čtení.</string>
<string name="autofill_ask_to_save_data_summary">Zeptat se na uložení dat, jakmile byl formulář přezkoušen</string>
<string name="autofill_ask_to_save_data_title">Zeptat se před uložením</string>
<string name="autofill_save_search_info_summary">Pokuste se uložit údaje hledání, když manuálně vybíráte položku</string>
<string name="autofill_save_search_info_title">Uložit info hledání</string>
<string name="autofill_save_search_info_title">Uložit výsledky vyhledá</string>
<string name="autofill_close_database_summary">Zavřít databázi po samovyplnění polí</string>
<string name="autofill_close_database_title">Zavřít databázi</string>
<string name="keyboard_previous_lock_summary">Po uzamknutí databáze automaticky přepnout zpět na předchozí klávesnici</string>
@@ -491,9 +491,9 @@
<string name="biometric_security_update_required">Vyžadována aktualizace biometrického zabezpečení.</string>
<string name="configure_biometric">Žádné přihlašovací ani biometrické údaje nejsou registrovány.</string>
<string name="warning_empty_recycle_bin">Trvale odstranit všechny uzly z koše\?</string>
<string name="registration_mode">Režim registrace</string>
<string name="save_mode">Režim ukládání</string>
<string name="search_mode">Režim vyhledávání</string>
<string name="registration_mode">Registrace</string>
<string name="save_mode">Uložit</string>
<string name="search_mode">Vyhledávání</string>
<string name="error_field_name_already_exists">Jméno kolonky již existuje.</string>
<string name="error_registration_read_only">Uložení nové položky v režimu databáze pouze pro čtení není povoleno</string>
<string name="enter">Enter</string>
@@ -596,4 +596,10 @@
<string name="holder">Majitel</string>
<string name="debit_credit_card">Debitní / Kreditní karta</string>
<string name="template_group_name">Předlohy</string>
<string name="show_otp_token_summary">Ukáže OTP tokeny v seznamu záznamů</string>
<string name="show_otp_token_title">Ukázat OTP token</string>
<string name="menu_external_icon">Externí ikona</string>
<string name="autofill_select_entry">Vyberte položku…</string>
<string name="autofill_manual_selection_summary">Zobrazit možnosti umožňující uživateli si vybrat položku z databáze</string>
<string name="autofill_manual_selection_title">Ruční výběr</string>
</resources>

View File

@@ -75,7 +75,7 @@
<string name="error_out_of_memory">Zu wenig Speicherplatz, um die ganze Datenbank zu laden.</string>
<string name="error_pass_gen_type">Mindestens eine Art der Passwortgenerierung muss ausgewählt sein.</string>
<string name="error_pass_match">Die Passwörter stimmen nicht überein.</string>
<string name="error_rounds_too_large">Transformationsrunden“ zu hoch. Wird auf 2147483648 eingestellt.</string>
<string name="error_rounds_too_large">Schlüsseltransformationen“ zu hoch. Wird auf 2147483648 eingestellt.</string>
<string name="error_string_key">Für jede Zeichenfolge ist ein Feldname notwendig.</string>
<string name="error_wrong_length">Eine positive ganze Zahl in das Feld „Länge“ eingeben.</string>
<string name="field_name">Feldname</string>
@@ -160,7 +160,7 @@
<string name="clipboard_notifications_title">Zwischenablage-Benachrichtigung</string>
<string name="clipboard_notifications_summary">Benachrichtigungen zur Zwischenablage anzeigen, um beim Betrachten eines Eintrags Felder kopieren zu können</string>
<string name="lock_database_screen_off_title">Bildschirmsperre</string>
<string name="lock_database_screen_off_summary">Datenbank sperren, wenn der Bildschirm ausgeschaltet wird</string>
<string name="lock_database_screen_off_summary">Datenbank sperren, einige Sekunden nachdem der Bildschirm ausgeschaltet wird</string>
<string name="create_keepass_file">Neue Datenbank erstellen</string>
<string name="assign_master_key">Hauptschlüssel zuweisen</string>
<string name="path">Pfad</string>
@@ -490,7 +490,7 @@
<string name="education_add_attachment_title">Anhang hinzufügen</string>
<string name="database_data_remove_unlinked_attachments_summary">Entfernt Anhänge die in der Datenbank enthalten, aber keinem Eintrag zugeordnet sind</string>
<string name="warning_sure_add_file">Soll die Datei trotzdem hinzugefügt werden\?</string>
<string name="show_uuid_summary">Zeigt die mit einem Eintrag verknüpfte UUID an</string>
<string name="show_uuid_summary">Zeigt die mit einem Eintrag oder einer Gruppe verknüpfte UUID an</string>
<string name="show_uuid_title">UUID anzeigen</string>
<string name="autofill_read_only_save">Das Speichern von Daten ist für eine als schreibgeschützt geöffnete Datenbank nicht zulässig.</string>
<string name="autofill_close_database_title">Datenbank schließen</string>
@@ -610,4 +610,7 @@
<string name="wireless">WLAN</string>
<string name="email_address">E-Mail-Adresse</string>
<string name="email">E-Mail</string>
<string name="menu_external_icon">Externes Symbol</string>
<string name="show_otp_token_summary">Zeigt OTP-Tokens in der Liste der Einträge an</string>
<string name="show_otp_token_title">OTP-Token anzeigen</string>
</resources>

View File

@@ -182,7 +182,7 @@
<string name="clipboard_notifications_summary">Εμφάνιση ειδοποιήσεων πρόχειρου για αντιγραφή πεδίων κατά την προβολή μιας καταχώρησης</string>
<string name="lock">Κλείδωμα</string>
<string name="lock_database_screen_off_title">Κλείδωμα Οθόνης</string>
<string name="lock_database_screen_off_summary">Κλείδωμα της βάσης δεδομένων όταν η οθόνη είναι απενεργοποιημένη</string>
<string name="lock_database_screen_off_summary">Κλείδωμα της βάση δεδομένων μετά από μερικά δευτερόλεπτα μόλις η οθόνη είναι απενεργοποιηθεί</string>
<string name="unavailable_feature_text">Δεν ήταν δυνατή η εκκίνηση αυτής της λειτουργίας.</string>
<string name="unavailable_feature_version">Η συσκευή τρέχει Android %1$s, αλλά χρειάζεται %2$s ή μεταγενέστερη έκδοση.</string>
<string name="unavailable_feature_hardware">Δεν ήταν δυνατή η εύρεση του αντίστοιχου υλικού.</string>
@@ -473,7 +473,7 @@
<string name="error_string_type">Αυτό το κείμενο δεν ταιριάζει με το ζητούμενο στοιχείο.</string>
<string name="content_description_credentials_information">Πληροφορίες Διαπιστευτηρίων</string>
<string name="content_description_add_item">Προσθήκη είδους</string>
<string name="show_uuid_summary">Εμφανίζει το UUID που είναι συνδεδεμένο σε μια καταχώριση</string>
<string name="show_uuid_summary">Εμφανίζει το UUID που είναι συνδεδεμένο σε μια καταχώρηση ή σε μια ομάδα</string>
<string name="show_uuid_title">Εμφάνιση UUID</string>
<string name="autofill_read_only_save">Δεν επιτρέπεται η αποθήκευση δεδομένων για μια βάση δεδομένων που ανοίγει ως μόνο για ανάγνωση.</string>
<string name="autofill_ask_to_save_data_summary">Ζητήστε να αποθηκεύσετε δεδομένα όταν επικυρώνεται μια φόρμα</string>
@@ -583,7 +583,7 @@
<string name="cryptocurrency">Πορτοφόλι κρυπτονομισμάτων</string>
<string name="type">Τύπος</string>
<string name="ssid">SSID</string>
<string name="wireless">Wifi</string>
<string name="wireless">Wi-Fi</string>
<string name="email_address">Διεύθυνση ηλεκτρονικού ταχυδρομείου</string>
<string name="email">Email</string>
<string name="date_of_issue">Ημερομηνία έκδοσης</string>
@@ -596,4 +596,10 @@
<string name="holder">Κάτοχος</string>
<string name="debit_credit_card">Χρεωστική / Πιστωτική Κάρτα</string>
<string name="template_group_name">Πρότυπα</string>
<string name="show_otp_token_summary">Εμφανίζει OTP tokens στη λίστα καταχωρήσεων</string>
<string name="show_otp_token_title">Εμφάνιση OTP Token</string>
<string name="menu_external_icon">Εξωτερικό εικονίδιο</string>
<string name="autofill_manual_selection_summary">Εμφάνισης επιλογής για να επιτρέψει στον χρήστη να επιλέξει την καταχώρηση βάσης δεδομένων</string>
<string name="autofill_manual_selection_title">Χειροκίνητη επιλογή</string>
<string name="autofill_select_entry">Επιλογή καταχώρησης…</string>
</resources>

View File

@@ -189,7 +189,7 @@
<string name="clipboard_notifications_summary">Mostrar las notificaciones del portapapeles para copiar campos al examinar una entrada</string>
<string name="lock">Bloquear</string>
<string name="lock_database_screen_off_title">Bloqueo de pantalla</string>
<string name="lock_database_screen_off_summary">Bloquear la base de datos cuando la pantalla esté apagada</string>
<string name="lock_database_screen_off_summary">Bloquear la base de datos después de unos segundos cuando la pantalla esté apagada</string>
<string name="advanced_unlock">Desbloqueo avanzado</string>
<string name="biometric_unlock_enable_title">Desbloqueo biométrico</string>
<string name="biometric_unlock_enable_summary">Le permite escanear sus datos biométricos para abrir la base de datos</string>
@@ -525,7 +525,7 @@
<string name="keyboard_save_search_info_summary">Luego de compartir un URL con KeePassDX, cuando se selecciona una entrada, intentar recordarla para futuros usos</string>
<string name="keyboard_save_search_info_title">Guardar información compartida</string>
<string name="keyboard_search_share_summary">Al compartir un URL con KeePassDX, filtrar las entradas utilizando el dominio de ese URL</string>
<string name="show_uuid_summary">Muestra el UUID vinculado a una entrada</string>
<string name="show_uuid_summary">Muestra el UUID vinculado a una entrada o a un grupo</string>
<string name="show_uuid_title">Mostrar UUID</string>
<string name="error_rebuild_list">No es posible reconstruir adecuadamente la lista.</string>
<string name="error_database_uri_null">La URI de la base de datos no puede ser recuperada.</string>
@@ -598,4 +598,10 @@
<string name="ssid">SSID</string>
<string name="personal_identification_number">Número de Identificación Personal</string>
<string name="card_verification_value">CVV</string>
<string name="show_otp_token_summary">Muestra los tokens OTP en la lista de entradas</string>
<string name="show_otp_token_title">Mostrar token OTP</string>
<string name="menu_external_icon">Icono externo</string>
<string name="autofill_manual_selection_summary">Mostrar opción para permitir al usuario seleccionar la entrada de la base de datos</string>
<string name="autofill_manual_selection_title">Selección manual</string>
<string name="autofill_select_entry">Seleccionar entrada…</string>
</resources>

View File

@@ -2,7 +2,7 @@
<resources>
<string name="menu_appearance_settings">ظاهر</string>
<string name="database_history">تاریخچه</string>
<string name="no_credentials_stored">این پایگاه داده هنوز اطلاعات کاربری ذخیره نشده است.</string>
<string name="no_credentials_stored">در این پایگاه داده هنوز اعتبار نامه ذخیره نشده است.</string>
<string name="encrypted_value_stored">رمز رمزگذاری شده ذخیره شده است</string>
<string name="keystore_not_accessible">فروشگاه اصلی به درستی تنظیم نشده است.</string>
<string name="build_label">%1$s را بسازید</string>
@@ -117,7 +117,7 @@
<string name="invalid_db_sig">نمی توانست فرمت پایگاه داده را تشخیص دهد.</string>
<string name="invalid_db_same_uuid">%1$s با همان UUID %2$s در حال حاضر وجود دارد.</string>
<string name="invalid_algorithm">الگوریتم اشتباه</string>
<string name="invalid_credentials">نمی توانست اعتبارنامه ها را بخواند.</string>
<string name="invalid_credentials">نمی توان اعتبار نامه را خواند.</string>
<string name="password">رمز عبور</string>
<string name="hint_pass">رمز عبور</string>
<string name="hint_length">طول</string>
@@ -138,11 +138,11 @@
<string name="error_save_database">نمی توانست پایگاه داده را ذخیره کند.</string>
<string name="error_create_database_file">قادر به ایجاد پایگاه داده با این رمز عبور و keyfile نیست.</string>
<string name="error_create_database">قادر به ایجاد فایل پایگاه داده نیست.</string>
<string name="error_copy_group_here">شما نمی توانید یک گروه را در اینجا کپی کنید.</string>
<string name="error_copy_group_here">در اینجا نمی توانید گروهی را کپی کنید.</string>
<string name="error_copy_entry_here">شما نمی توانید یک ورودی را در اینجا کپی کنید.</string>
<string name="error_move_entry_here">شما نمی توانید یک ورودی را به اینجا منتقل کنید.</string>
<string name="error_autofill_enable_service">قادر به فعال کردن سرویس پر کردن خودکار نبود.</string>
<string name="error_wrong_length">یک عدد کامل مثبت را در زمینه \"طول\" وارد کنید.</string>
<string name="error_wrong_length">در قسمت \"طول\" یک عدد صحیح مثبت وارد کنید.</string>
<string name="error_label_exists">این برچسب در حال حاضر وجود دارد.</string>
<string name="error_string_key">هر رشته باید یک نام فیلد داشته باشد.</string>
<string name="error_rounds_too_large">\"دور تحول\" بیش از حد بالا است. تنظیم به 2147483648.</string>
@@ -157,7 +157,7 @@
<string name="error_invalid_OTP">راز OTP نامعتبر.</string>
<string name="error_invalid_path">مطمئن شوید که مسیر درست است</string>
<string name="error_invalid_db">نمی توانست پایگاه داده را بخواند.</string>
<string name="error_file_not_create">نمی تواند پرونده ایجاد کند:</string>
<string name="error_file_not_create">نمی تواند پرونده ایجاد کند</string>
<string name="error_can_not_handle_uri">نمی تواند این URI در KeePassDX رسیدگی کند.</string>
<string name="error_arc4">رمز جریان Arcfour پشتیبانی نمی شود</string>
<string name="entry_user_name">نام کاربری</string>
@@ -194,12 +194,12 @@
<string name="database">پایگاه داده</string>
<string name="retrieving_db_key">بازیابی کلید پایگاه داده…</string>
<string name="select_to_copy">انتخاب برای کپی %1$s به کلیپ بورد</string>
<string name="content_description_keyboard_close_fields">زمینه های نزدیک</string>
<string name="content_description_keyboard_close_fields">بستن فیلد</string>
<string name="content_description_remove_from_list">حذف</string>
<string name="content_description_update_from_list">روز رسانی</string>
<string name="content_description_update_from_list">به روز رسانی</string>
<string name="content_description_remove_field">حذف فیلد</string>
<string name="entry_add_attachment">افزودن پیوست</string>
<string name="entry_add_field">اضافه کردن زمینه</string>
<string name="entry_add_field">اضافه کردن فیلد</string>
<string name="content_description_password_length">طول رمز عبور</string>
<string name="entry_password_generator">ژنراتور رمز عبور</string>
<string name="discard">دور انداختن</string>
@@ -224,12 +224,12 @@
<string name="clipboard_error_title">خطای کلیپ بورد</string>
<string name="clipboard_cleared">کلیپ بورد پاک شد</string>
<string name="allow">اجازه</string>
<string name="file_manager_install_description">یک مدیر پرونده که عمل Intent را می پذیرد ACTION_CREATE_DOCUMENT و ACTION_OPEN_DOCUMENT برای ایجاد، باز کردن و ذخیره فایل های پایگاه داده مورد نیاز است.</string>
<string name="file_manager_install_description">برای ایجاد ، بازکردن و ذخیره فایل های پایگاه داده ، یک مدیر فایل که عملیات ACTION_CREATE_DOCUMENT و ACTION_OPEN_DOCUMENT را می پذیرد ، مورد نیاز است.</string>
<string name="extended_ASCII">گسترش ASCII</string>
<string name="brackets">براکت</string>
<string name="application">برنامه</string>
<string name="app_timeout_summary">زمان بیکار قبل از قفل کردن پایگاه داده</string>
<string name="app_timeout">تایم آوت برنامه</string>
<string name="app_timeout">اتمام زمان</string>
<string name="key_derivation_function">تابع مشتق کلید</string>
<string name="encryption_algorithm">الگوریتم رمزنگاری</string>
<string name="encryption">رمزگذاری</string>
@@ -245,4 +245,83 @@
<string name="contribution">سهم</string>
<string name="contact">مخاطب</string>
<string name="filter">فیلتر</string>
<string name="allow_no_password_summary">در صورت عدم انتخاب اعتبار نامه ، ضربه زدن روی دکمه \"باز کردن\" امکان پذیر است</string>
<string name="keyboard_previous_database_credentials_summary">به طور خودکار به صفحه کلید قبلی در صفحه اعتبار نامه پایگاه داده برگردید</string>
<string name="keyboard_previous_database_credentials_title">صفحه اعتبار نامه پایگاه داده</string>
<string name="open_advanced_unlock_prompt_store_credential">برای ذخیره اعتبار نامه ، قفل پیشرفته را باز کنید</string>
<string name="open_advanced_unlock_prompt_unlock_database">برای باز کردن قفل پایگاه داده قفل پیشرفته را باز کنید</string>
<string name="biometric_security_update_required">به روز رسانی امنیتی بیومتریک مورد نیاز است.</string>
<string name="configure_biometric">هیچ بیومتریک یا اعتبار دستگاه ثبت نشده است.</string>
<string name="advanced_unlock_tap_delete">برای حذف کلیدهای پیشرفته باز کردن قفل ضربه بزنید</string>
<string name="advanced_unlock">باز کردن قفل پیشرفته</string>
<string name="content">محتوا</string>
<string name="warning_database_revoked">دسترسی به پرونده توسط مدیر فایل لغو شده ، پایگاه داده را ببندید و مجدداً از محل آن باز کنید.</string>
<string name="warning_database_info_changed_options">با ذخیره کردن پایگاه داده ، تغییرات خارجی را بازنویسی کنید یا با جدیدترین تغییرات آن را بارگیری کنید.</string>
<string name="warning_database_info_changed">اطلاعات موجود در فایل پایگاه داده شما خارج از برنامه دستکاری شده است.</string>
<string name="warning_empty_keyfile_explanation">محتوای فایل کلید هرگز نباید تغییر کند و در بهترین حالت باید حاوی داده های تصادفی تولید شده باشد.</string>
<string name="warning_empty_keyfile">توصیه نمی شود یک فایل کلید خالی اضافه کنید.</string>
<string name="warning_sure_remove_data">به هر حال این داده ها حذف شود؟</string>
<string name="warning_remove_unlinked_attachment">حذف داده های پیوند نشده ممکن است حجم پایگاه داده شما را کاهش دهد اما همچنین ممکن است داده های مورد استفاده برای افزونه های KeePass را حذف کند.</string>
<string name="warning_sure_add_file">به هر حال فایل اضافه شود؟</string>
<string name="warning_replace_file">بارگذاری این فایل جایگزین فایل موجود می شود.</string>
<string name="warning_file_too_big">قرار است پایگاه داده KeePass فقط حاوی فایلهای مفید کوچک (مانند فایلهای کلیدی PGP) باشد.
\n
\nممکن است پایگاه داده شما بسیار بزرگ شود و با این بارگذاری عملکرد را کاهش دهید.</string>
<string name="warning_empty_recycle_bin">آیا همه کلید ها از سطل بازیافت به طور دائم حذف می شوند؟</string>
<string name="error_export_app_properties">خطا در هنگام صادرات ویژگی های برنامه</string>
<string name="success_export_app_properties">ویژگی های برنامه صادر شد</string>
<string name="error_import_app_properties">خطا در هنگام وارد کردن ویژگی های برنامه</string>
<string name="success_import_app_properties">ویژگی های برنامه وارد شد</string>
<string name="description_app_properties">ویژگی های KeePassDX برای مدیریت تنظیمات برنامه</string>
<string name="export_app_properties_summary">یک فایل برای صادر کردن ویژگی های برنامه ایجاد کنید</string>
<string name="import_app_properties_summary">یک فایل برای وارد کردن ویژگی های برنامه انتخاب کنید</string>
<string name="import_app_properties_title">وارد کردن ویژگی های برنامه</string>
<string name="export_app_properties_title">صادر کردن ویژگی های برنامه</string>
<string name="registration_mode">حالت ثبت</string>
<string name="save_mode">حالت ذخیره</string>
<string name="search_mode">حالت جستجو</string>
<string name="menu_external_icon">نماد خارجی</string>
<string name="menu_keystore_remove_key">حذف کلید باز کردن پیشرفته</string>
<string name="menu_reload_database">بارگیری مجدد پایگاه داده</string>
<string name="error_start_database_action">هنگام انجام عملیات در پایگاه داده خطایی روی داد.</string>
<string name="error_remove_file">هنگام حذف داده های فایل خطایی روی داد.</string>
<string name="error_duplicate_file">داده های فایل قبلاً وجود دارد.</string>
<string name="error_upload_file">هنگام بارگذاری داده های فایل خطایی روی داد.</string>
<string name="error_file_to_big">فایلی که می خواهید بارگذاری کنید بسیار بزرگ است.</string>
<string name="error_rebuild_list">نمی توان لیست را به درستی بازسازی کرد.</string>
<string name="error_database_uri_null">URI پایگاه داده بازیابی نمی شود.</string>
<string name="error_field_name_already_exists">نام فیلد از قبل موجود است.</string>
<string name="error_registration_read_only">ذخیره یک مورد جدید در پایگاه داده \"فقط خواندنی\" مجاز نیست</string>
<string name="error_otp_type">نوع OTP موجود توسط این فرم شناخته نمی شود ، اعتبار آن ممکن است دیگر توکن را به درستی تولید نکند.</string>
<string name="id_card">ID Card</string>
<string name="card_verification_value">CVV</string>
<string name="error_word_reserved">این کلمه رزرو است و نمی توان از آن استفاده کرد.</string>
<string name="version">نسخه</string>
<string name="template">الگو</string>
<string name="standard">استاندارد</string>
<string name="membership">اعضا</string>
<string name="secure_note">یادداشت امن</string>
<string name="ssid">نام وای فای(SSID)</string>
<string name="bank_identifier_code">SWIFT / BIC</string>
<string name="international_bank_account_number">IBAN (شبا)</string>
<string name="bank_name">نام بانک</string>
<string name="bank">بانک</string>
<string name="account">حساب کاربری</string>
<string name="seed">بذر</string>
<string name="private_key">کلید خصوصی</string>
<string name="public_key">کلید عمومی</string>
<string name="token">توکن</string>
<string name="cryptocurrency">کیف پول ارز دیجیتال</string>
<string name="type">نوع</string>
<string name="email_address">آدرس ایمیل</string>
<string name="email">ایمیل</string>
<string name="date_of_issue">تاریخ صدور</string>
<string name="place_of_issue">محل صدور</string>
<string name="name">نام</string>
<string name="personal_identification_number">پین(رمز)</string>
<string name="number">عدد</string>
<string name="holder">صاحب</string>
<string name="template_group_name">الگو ها</string>
<string name="content_description_otp_information">اطلاعات رمز یکبار مصرف</string>
<string name="content_description_credentials_information">اطلاعات اعتبار نامه</string>
</resources>

View File

@@ -182,7 +182,7 @@
<string name="clipboard_warning">Si la suppression automatique du presse-papier échoue, supprimer son historique manuellement.</string>
<string name="lock">Verrouiller</string>
<string name="lock_database_screen_off_title">Verrouillage décran</string>
<string name="lock_database_screen_off_summary">Verrouille la base de données lorsque lécran est éteint</string>
<string name="lock_database_screen_off_summary">Verrouille la base de données après quelques secondes une fois lécran éteint</string>
<string name="advanced_unlock">Déverrouillage avancé</string>
<string name="biometric_unlock_enable_title">Déverrouillage biométrique</string>
<string name="biometric_unlock_enable_summary">Permet de numériser votre empreinte biométrique pour ouvrir la base de données</string>
@@ -487,7 +487,7 @@
<string name="database_data_remove_unlinked_attachments_title">Supprimer les données non-liées</string>
<string name="database_data_remove_unlinked_attachments_summary">Supprimer les pièces jointes contenues dans la base de données mais non-liées à une entrée</string>
<string name="data">Données</string>
<string name="show_uuid_summary">Affiche lUUID lié à une entrée</string>
<string name="show_uuid_summary">Affiche lUUID lié à une entrée ou un groupe</string>
<string name="show_uuid_title">Afficher lUUID</string>
<string name="autofill_read_only_save">Lenregistrement des données nest pas autorisé pour une base de données ouverte en lecture seule.</string>
<string name="autofill_ask_to_save_data_summary">Demande à enregistrer des données quand un formulaire est validé</string>
@@ -575,12 +575,12 @@
<string name="error_start_database_action">Une erreur s\'est produite lors de l\'exécution d\'une action sur la base de données.</string>
<string name="error_move_group_here">Vous ne pouvez pas déplacer un groupe ici.</string>
<string name="error_word_reserved">Ce mot est réservé et ne peut pas être utilisé.</string>
<string name="templates">Modèles</string>
<string name="templates_group_uuid_title">Groupe de modèles</string>
<string name="templates">Gabarits</string>
<string name="templates_group_uuid_title">Groupe de gabarits</string>
<string name="templates_group_enable_summary">Utiliser les modèles dynamiques pour remplir les champs d\'une entrée</string>
<string name="templates_group_enable_title">Utilisation des modèles</string>
<string name="templates_group_enable_title">Utilisation des gabarits</string>
<string name="version">Version</string>
<string name="template">Modèle</string>
<string name="template">Gabarit</string>
<string name="standard">Standard</string>
<string name="membership">Adhésion</string>
<string name="international_bank_account_number">IBAN</string>
@@ -602,6 +602,11 @@
<string name="name">Nom</string>
<string name="id_card">Carte d\'identité</string>
<string name="debit_credit_card">Carte de crédit</string>
<string name="template_group_name">Modèles</string>
<string name="template_group_name">Gabarits</string>
<string name="secure_note">Note sécurisée</string>
<string name="show_otp_token_summary">Affiche les jetons OTP dans la liste des entrées</string>
<string name="show_otp_token_title">Afficher le jeton OTP</string>
<string name="menu_external_icon">Icône externe</string>
<string name="autofill_manual_selection_summary">Afficher l\'option permettant à l\'utilisateur de sélectionner l\'entrée de la base de données</string>
<string name="autofill_manual_selection_title">Sélection manuelle</string>
</resources>

View File

@@ -188,7 +188,7 @@
<string name="clipboard">Međuspremnik</string>
<string name="clipboard_notifications_title">Obavijesti međuspremnika</string>
<string name="clipboard_warning">Ako automatsko brisanje međuspremnika ne uspije, izbriši njegovu povijest ručno.</string>
<string name="lock_database_screen_off_summary">Zaključaj bazu podataka kada je ekran ugašen</string>
<string name="lock_database_screen_off_summary">Zaključaj bazu podataka nakon par sekundi kad se ekran ugasi</string>
<string name="lock_database_back_root_title">Pritisni \'Natrag\' za zaključavanje</string>
<string name="advanced_unlock">Napredno otključavanje</string>
<string name="advanced_unlock_explanation_summary">Koristi napredno otključavanje za jednostavnije otvaranje baze podataka</string>
@@ -473,7 +473,7 @@
<string name="notification">Obavijest</string>
<string name="error_registration_read_only">Nije dopušteno spremati novi element u zaštićenoj bazi podataka</string>
<string name="autofill_read_only_save">Spremanje podataka nije dopušteno za bazu podataka koja je otvorena u zaštićenom stanju.</string>
<string name="show_uuid_summary">Prikazuje UUID povezan s unosom</string>
<string name="show_uuid_summary">Prikazuje UUID povezan s unosom ili grupom</string>
<string name="show_uuid_title">Prikaži UUID</string>
<string name="autofill_ask_to_save_data_summary">Zatraži spremanje podataka kad se obrazac provjeri</string>
<string name="autofill_ask_to_save_data_title">Zatraži spremanje podataka</string>
@@ -577,7 +577,7 @@
<string name="cryptocurrency">Novčanik za kriptovalute</string>
<string name="type">Vrsta</string>
<string name="ssid">SSID</string>
<string name="wireless">Wifi</string>
<string name="wireless">Wi-Fi</string>
<string name="email_address">E-mail adresa</string>
<string name="email">E-mail</string>
<string name="date_of_issue">Datum izdavanja</string>
@@ -590,4 +590,11 @@
<string name="holder">Vlasnik</string>
<string name="debit_credit_card">Debitna / kreditna kartica</string>
<string name="template_group_name">Predlošci</string>
<string name="autofill_manual_selection_summary">Opcija prikaza koja omogućuje korisniku biranje unosa baze podataka</string>
<string name="show_otp_token_summary">Prikazuje OTP tokene u popisu unosa</string>
<string name="show_otp_token_title">Prikaži OTP token</string>
<string name="autofill_manual_selection_title">Ručni odabir</string>
<string name="autofill_select_entry">Odaberi unos …</string>
<string name="menu_external_icon">Vanjska ikona</string>
<string name="seed">Tajna fraza</string>
</resources>

View File

@@ -24,12 +24,12 @@
<string name="add_entry">Bejegyzés hozzáadása</string>
<string name="add_group">Csoport hozzáadása</string>
<string name="encryption_algorithm">Titkosítási algoritmus</string>
<string name="app_timeout">Alkalmazás időkorlátja</string>
<string name="app_timeout">Időtúllépés</string>
<string name="app_timeout_summary">Tétlenség az adatbázis feloldása előtt</string>
<string name="application">Alkalmazás</string>
<string name="menu_app_settings">Alkalmazásbeállítások</string>
<string name="brackets">Zárójelek</string>
<string name="file_manager_install_description">Egy fájlkezelő, amely fogadja az ACTION_CREATE_DOCUMENT és ACTION_OPEN_DOCUMENT Intenteket, melyek az adatbázisfájlok létrehozásához, megnyitásához és mentéséhez szükségesek.</string>
<string name="file_manager_install_description">Az adatbázisfájlok létrehozásához, megnyitásához és mentéséhez szükség van egy fájlkezelőre, amely képes fogadni az ACTION_CREATE_DOCUMENT és ACTION_OPEN_DOCUMENT Intenteket.</string>
<string name="clipboard_cleared">Vágólap törölve</string>
<string name="clipboard_error_title">Vágólap hiba</string>
<string name="clipboard_error">Egyes eszközök nem engedik, hogy az alkalmazások használják a vágólapot.</string>
@@ -401,7 +401,7 @@
<string name="error_otp_period">Az időtartamnak %1$d és %2$d másodperc között kell lennie.</string>
<string name="error_otp_counter">A számlálónak %1$d és %2$d között kell lennie.</string>
<string name="error_otp_secret_key">A titkos kulcsnak Base32 formátumban kell lennie.</string>
<string name="error_copy_group_here">Csoport ide nem másolható.</string>
<string name="error_copy_group_here">Ide nem másolhat csoportot.</string>
<string name="error_disallow_no_credentials">Legalább egy hitelesíti módot be kell állítani.</string>
<string name="error_invalid_OTP">Érvénytelen OTP titok.</string>
<string name="entry_otp">OTP</string>
@@ -470,4 +470,51 @@
<string name="error_string_type">A szöveg nem egyezik a kért elemmel.</string>
<string name="content_description_credentials_information">Hitelesítő adatok információi</string>
<string name="content_description_add_item">Elem hozzáadása</string>
<string name="export_app_properties_summary">Fájl létrehozása az alkalmazástulajdonságok exportálásához</string>
<string name="export_app_properties_title">Alkalmazástulajdonságok exportálása</string>
<string name="import_app_properties_summary">Válasszon fájlt az alkalmazástulajdonságok importálásához</string>
<string name="import_app_properties_title">Alkalmazástulajdonságok importálása</string>
<string name="menu_external_icon">Külső ikon</string>
<string name="menu_keystore_remove_key">Speciális feloldási kulcs törlése</string>
<string name="menu_reload_database">Adatbázis újratöltése</string>
<string name="error_start_database_action">Hiba történt az adatbázison végzett művelet során.</string>
<string name="error_remove_file">Hiba történt a fájladatok eltávolítása során.</string>
<string name="error_duplicate_file">A fájladatok már léteznek.</string>
<string name="error_file_to_big">A feltöltendő fájl túl nagy.</string>
<string name="error_upload_file">Hiba történt a fájladatok feltöltése során.</string>
<string name="error_rebuild_list">A lista újbóli összeállítása sikertelen.</string>
<string name="error_database_uri_null">Az adatbázis URI nem kérhető le.</string>
<string name="error_field_name_already_exists">A mezőnév már létezik.</string>
<string name="error_otp_type">A meglévő OTP típus nem ismert ebben a formában, a kiértékelése nem biztos, hogy helyes tokent fog előállítani.</string>
<string name="error_word_reserved">Ez egy foglalt szó, és nem használható.</string>
<string name="version">Verzió</string>
<string name="template">Sablon</string>
<string name="standard">Szabványos</string>
<string name="membership">Tagság</string>
<string name="secure_note">Biztonságos jegyzet</string>
<string name="debit_credit_card">Bank- / hitelkártya</string>
<string name="seed">Kezdőérték</string>
<string name="international_bank_account_number">IBAN</string>
<string name="bank_identifier_code">SWIFT / BIC</string>
<string name="bank_name">Bank neve</string>
<string name="bank">Bank</string>
<string name="account">Fiók</string>
<string name="private_key">Privát kulcs</string>
<string name="public_key">Nyilvános kulcs</string>
<string name="token">Token</string>
<string name="cryptocurrency">Kriptopénztárca</string>
<string name="type">Típus</string>
<string name="ssid">SSID</string>
<string name="email_address">E-mail-cím</string>
<string name="email">E-mail</string>
<string name="date_of_issue">Kiállítás ideje</string>
<string name="place_of_issue">Kiállítás helye</string>
<string name="name">Név</string>
<string name="id_card">Személyigazolvány</string>
<string name="personal_identification_number">PIN-kód</string>
<string name="card_verification_value">Ellenőrzőszám</string>
<string name="number">Szám</string>
<string name="holder">Tulajdonos</string>
<string name="template_group_name">Sablonok</string>
<string name="content_description_otp_information">Egyszer használatos jelszó információ</string>
</resources>

View File

@@ -420,14 +420,14 @@
<string name="error_start_database_action">Timbul galat ketika melaksanakan sebuah aksi di basisdata.</string>
<string name="error_move_group_here">Anda tidak bisa memindahkan sebuah grup ke sini.</string>
<string name="device_credential_unlock_enable_title">Membuka kredensial perangkat</string>
<string name="biometric_unlock_enable_summary">Memperbolehkan pengguna memindai biometrik pengguna untuk membuka database”</string>
<string name="biometric_unlock_enable_summary">Memperbolehkan Anda memindai biometrik Anda untuk membuka basis data</string>
<string name="biometric_unlock_enable_title">Membuka kunci biometrik</string>
<string name="advanced_unlock_explanation_summary">Gunakan buka kunci lanjutan untuk membuka database dengan lebih mudah</string>
<string name="no_credentials_stored">Basis data ini belum menyimpan kredensial.</string>
<string name="advanced_unlock_not_recognized">Tidak dapat mengenali cetakan buka kunci lanjutan</string>
<string name="advanced_unlock_invalid_key">Tidak dapat membaca kunci pembuka lanjutan. Harap hapus dan ulangi prosedur pengenalan buka kunci.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Ekstrak kredensial basis data dengan membuka data lanjutan</string>
<string name="error_word_reserved">Kata ini telah dipakai dan tidak bisa digunakan</string>
<string name="advanced_unlock_prompt_extract_credential_message">Ekstrak kredensial basis data dengan pembuka kunci data lanjutan</string>
<string name="error_word_reserved">Kata ini telah dipakai dan tidak bisa digunakan.</string>
<string name="credential_before_click_advanced_unlock_button">Ketik kata sandi, lalu klik tombol ini.</string>
<string name="autofill_service_name">Isi formulir KeePassDX otomatis</string>
<string name="autofill_preference_title">Pengaturan isi otomatis</string>
@@ -440,5 +440,19 @@
<string name="biometric">Biometrik</string>
<string name="menu_appearance_settings">Tampilan</string>
<string name="database_history">Riwayat</string>
<string name="encrypted_value_stored">Enkripsi password telah disimpan.</string>
<string name="encrypted_value_stored">Enkripsi kata sandi disimpan</string>
<string name="international_bank_account_number">NRBI (IBAN)</string>
<string name="bank_name">Nama bank</string>
<string name="name">Nama</string>
<string name="debit_credit_card">Kartu Debit/Kredit</string>
<string name="type">Tipe</string>
<string name="version">Versi</string>
<string name="standard">Standar</string>
<string name="bank">Bank</string>
<string name="account">Akun</string>
<string name="cryptocurrency">Dompet kripto</string>
<string name="number">Nomor</string>
<string name="public_key">Kunci publik</string>
<string name="private_key">Kunci pribadi</string>
<string name="membership">Keanggotaan</string>
</resources>

View File

@@ -195,7 +195,7 @@
<string name="clipboard_warning">Se l\'eliminazione automatica degli appunti fallisce, cancellali manualmente.</string>
<string name="lock">Blocca</string>
<string name="lock_database_screen_off_title">Blocco schermo</string>
<string name="lock_database_screen_off_summary">Blocca il database quando lo schermo è spento</string>
<string name="lock_database_screen_off_summary">Blocca il database dopo alcuni secondi quando lo schermo è spento</string>
<string name="advanced_unlock">Impronta digitale</string>
<string name="biometric_unlock_enable_title">Scansione di impronte</string>
<string name="biometric_unlock_enable_summary">Consente la scansione biometrica per aprire il database</string>
@@ -289,7 +289,7 @@
<string name="list_entries_show_username_title">Mostra nomi utente</string>
<string name="list_entries_show_username_summary">Mostra i nomi utente negli elenchi</string>
<string name="clipboard">Appunti</string>
<string name="build_label">Costruzione %1$s</string>
<string name="build_label">Build %1$s</string>
<string name="keyboard_name">Magitastiera</string>
<string name="keyboard_label">Magitastiera (KeePassDX)</string>
<string name="keyboard_setting_label">Impostazioni Magitastiera</string>
@@ -346,7 +346,7 @@
<string name="menu_advanced_unlock_settings">Sblocco avanzato</string>
<string name="entry_history">Cronologia</string>
<string name="entry_setup_otp">Imposta password usa e getta</string>
<string name="otp_type">Tipo di password OTP</string>
<string name="otp_type">Tipo di OTP</string>
<string name="otp_secret">Segreto</string>
<string name="otp_period">Periodo (secondi)</string>
<string name="otp_counter">Contatore</string>
@@ -374,7 +374,7 @@
<string name="auto_focus_search_title">Ricerca rapida</string>
<string name="menu_delete_entry_history">Cancella cronologia</string>
<string name="menu_restore_entry_history">Ripristina cronologia</string>
<string name="html_about_contribution">Per poter &lt;strong&gt;mantenere la nostra libertà&lt;/strong&gt;, &lt;strong&gt;risolvere bug&lt;/strong&gt;, &lt;strong&gt;aggiungere funzionalità&lt;/strong&gt; ed &lt;strong&gt;essere sempre attivi&lt;/strong&gt;, facciamo affidamento sul tuo &lt;strong&gt;contributo&lt;/strong&gt;.</string>
<string name="html_about_contribution">Per poter <strong>mantenere la nostra libertà</strong>, <strong>correggere errori</strong>, <strong>aggiungere funzionalità</strong> ed <strong>essere sempre attivi</strong>, facciamo affidamento sul tuo <strong>contributo</strong>.</string>
<string name="contact">Contatto</string>
<string name="keystore_not_accessible">Il keystore non è inizializzato correttamente.</string>
<string name="menu_master_key_settings">Impostazioni della chiave principale</string>
@@ -476,7 +476,7 @@
\n
\nIl tuo database può diventare molto grande e ridurre le prestazioni con questo caricamento.</string>
<string name="content_description_credentials_information">Info credenziali</string>
<string name="show_uuid_summary">Visualizza l\'UUID collegato a una voce</string>
<string name="show_uuid_summary">Visualizza l\'UUID collegato a una voce o a un gruppo</string>
<string name="show_uuid_title">Mostra UUID</string>
<string name="autofill_read_only_save">Il salvataggio dei dati non è consentito per un database aperto in sola lettura.</string>
<string name="autofill_ask_to_save_data_summary">Chiedi di salvare i dati quando un modulo viene convalidato</string>
@@ -586,7 +586,7 @@
<string name="cryptocurrency">Portafoglio di criptovaluta</string>
<string name="type">Tipo</string>
<string name="ssid">SSID</string>
<string name="wireless">Wifi</string>
<string name="wireless">Wi-Fi</string>
<string name="email_address">Indirizzo email</string>
<string name="email">Email</string>
<string name="date_of_issue">Data di emissione</string>
@@ -599,4 +599,10 @@
<string name="holder">Titolare</string>
<string name="debit_credit_card">Carta di debito / credito</string>
<string name="template_group_name">Modelli</string>
<string name="menu_external_icon">Icona esterna</string>
<string name="show_otp_token_summary">Mostra i token OTP nella lista delle voci</string>
<string name="show_otp_token_title">Mostra token OTP</string>
<string name="autofill_manual_selection_summary">Mostra l\'opzione che permette all\'utente di scegliere la voce nel database</string>
<string name="autofill_manual_selection_title">Selezione manuale</string>
<string name="autofill_select_entry">Seleziona voce…</string>
</resources>

View File

@@ -78,7 +78,7 @@
<string name="html_about_contribution">&lt;strong&gt;自由を維持し&lt;/strong&gt;&lt;strong&gt;バグを修正し&lt;/strong&gt;&lt;strong&gt;機能を追加し&lt;/strong&gt;、そして&lt;strong&gt;活発に開発し続ける&lt;/strong&gt;ために、私たちはあなたの&lt;strong&gt;貢献&lt;/strong&gt;に期待しています。</string>
<string name="entry_accessed">最終アクセス</string>
<string name="entry_cancel">キャンセル</string>
<string name="entry_notes">備考</string>
<string name="entry_notes">メモ</string>
<string name="entry_confpassword">パスワードを確認</string>
<string name="entry_created">作成日時</string>
<string name="entry_expires">有効期限</string>
@@ -120,9 +120,9 @@
<string name="error_label_exists">このラベルはすでに存在します。</string>
<string name="error_wrong_length">[長さ] フィールドには正の整数を入力してください。</string>
<string name="error_autofill_enable_service">自動入力サービスを有効にできませんでした。</string>
<string name="error_move_entry_here">ここではエントリーを移動することはできません。</string>
<string name="error_copy_entry_here">ここではエントリーをコピーすることはできません。</string>
<string name="error_copy_group_here">ここではグループをコピーすることはできません。</string>
<string name="error_move_entry_here">エントリーをここに移動できません。</string>
<string name="error_copy_entry_here">エントリーをここにコピーできません。</string>
<string name="error_copy_group_here">グループをここにコピーできません。</string>
<string name="error_create_database">データベース ファイルを作成できません。</string>
<string name="error_create_database_file">このパスワードとキーファイルではデータベースを作成できません。</string>
<string name="error_save_database">データベースを保存できませんでした。</string>
@@ -180,7 +180,7 @@
<string name="menu_cancel">キャンセル</string>
<string name="menu_hide_password">パスワードを非表示にする</string>
<string name="menu_lock">データベースをロック</string>
<string name="menu_save_database">データベースを保存</string>
<string name="menu_save_database">保存する</string>
<string name="menu_open">開く</string>
<string name="menu_search">検索</string>
<string name="menu_showpass">パスワードを表示</string>
@@ -223,7 +223,7 @@
<string name="encryption_explanation">すべてのデータで使用するデータベース暗号化アルゴリズムです。</string>
<string name="kdf_explanation">暗号化アルゴリズム用の鍵を生成するために、マスターキーはランダムなソルト付き鍵導出関数を使用して変換されます。</string>
<string name="rounds">変換ラウンド</string>
<string name="rounds_explanation">変換ラウンドを増やすことでブルート フォース攻撃に対する保護が強化されますが、読み込みと保存が本当に遅くなる可能性があります。</string>
<string name="rounds_explanation">変換ラウンドを増やすことでブルートフォース攻撃に対する保護が強化されますが、読み込みと保存がとても遅くなる可能性があります。</string>
<string name="memory_usage">メモリ使用量</string>
<string name="memory_usage_explanation">鍵導出関数が使用するメモリの量です。</string>
<string name="parallelism">並列処理</string>
@@ -241,7 +241,7 @@
<string name="sort_db">並べ替えなし</string>
<string name="sort_title">タイトル</string>
<string name="sort_username">ユーザー名</string>
<string name="sort_creation_time">作成日</string>
<string name="sort_creation_time">作成日</string>
<string name="sort_last_modify_time">変更日時</string>
<string name="sort_last_access_time">最終アクセス</string>
<string name="special">特殊文字</string>
@@ -294,7 +294,7 @@
<string name="clipboard_warning">クリップボードの自動削除に失敗した場合は、手動でその履歴を削除してください。</string>
<string name="lock">ロック</string>
<string name="lock_database_screen_off_title">画面ロック</string>
<string name="lock_database_screen_off_summary">画面がオフのとき、データベースをロックします</string>
<string name="lock_database_screen_off_summary">画面がオフになった数秒後に、データベースをロックします</string>
<string name="lock_database_back_root_title">[戻る] を押してロック</string>
<string name="lock_database_back_root_summary">ユーザーがルート画面上で戻るボタンをタップしたとき、データベースをロックします</string>
<string name="lock_database_show_button_title">ロックボタンを表示</string>
@@ -362,13 +362,13 @@
<string name="keyboard_setting_label">Magikeyboard の設定</string>
<string name="keyboard_entry_category">エントリー</string>
<string name="keyboard_selection_entry_title">エントリーの選択</string>
<string name="keyboard_selection_entry_summary">エントリーを開いているとき、Magikeyboard に入力フィールドを表示します</string>
<string name="keyboard_selection_entry_summary">KeePassDX のエントリーを開いているとき、Magikeyboard にそのエントリーを格納します</string>
<string name="keyboard_notification_entry_title">通知情報</string>
<string name="keyboard_notification_entry_summary">エントリーが利用可能なとき、通知を表示します</string>
<string name="keyboard_search_share_title">共有情報の検索</string>
<string name="keyboard_search_share_summary">共有情報を自動的に検索して、結果をキーボードに格納します</string>
<string name="keyboard_search_share_summary">URL を KeePassDX に共有するとそのドメインを使ってエントリーを検索します</string>
<string name="keyboard_save_search_info_title">共有情報の保存</string>
<string name="keyboard_save_search_info_summary">手動でエントリー選択たとき、共有情報の保存を試みます</string>
<string name="keyboard_save_search_info_summary">KeePassDX に URL を共有して、エントリー選択されたとき、さらなる使用のためそのエントリーを記憶しておきます</string>
<string name="keyboard_notification_entry_clear_close_title">データベースを閉じて消去</string>
<string name="keyboard_notification_entry_clear_close_summary">通知を閉じるとき、データベースも閉じます</string>
<string name="keyboard_entry_timeout_title">タイムアウト</string>
@@ -489,7 +489,7 @@
<string name="hide_expired_entries_title">有効期限切れのエントリーを非表示にする</string>
<string name="hide_expired_entries_summary">有効期限切れのエントリーは非表示になります</string>
<string name="show_uuid_title">UUID を表示</string>
<string name="show_uuid_summary">エントリーにリンクされた UUID を表示します</string>
<string name="show_uuid_summary">エントリーやグループにリンクされた UUID を表示します</string>
<string name="autofill_read_only_save">データの保存は読み取り専用として開かれたデータベースでは許可されていません。</string>
<string name="save_mode">保存モード</string>
<string name="search_mode">検索モード</string>
@@ -531,7 +531,7 @@
<string name="warning_database_revoked">ファイルへのアクセス権がファイル マネージャーによって取り消されました。データベースを閉じて、ファイルの場所から再度開いてください。</string>
<string name="warning_database_info_changed_options">データベースを保存して外部の変更を上書きするか、再度読み込んで最新の変更を反映させてください。</string>
<string name="warning_database_info_changed">データベース ファイルに含まれる情報は、アプリの外部で変更されています。</string>
<string name="menu_reload_database">データベースを再度読み込む</string>
<string name="menu_reload_database">再度読み込む</string>
<string name="error_rebuild_list">リストを正しく再構築できません。</string>
<string name="unit_gibibyte">GiB</string>
<string name="unit_mebibyte">MiB</string>
@@ -561,13 +561,13 @@
<string name="error_start_database_action">データベースに対するアクションの実行中にエラーが発生しました。</string>
<string name="error_word_reserved">この単語は予約語のため使用できません。</string>
<string name="error_move_group_here">グループをここに移動できません。</string>
<string name="templates_group_enable_title">テンプレートの使用方法</string>
<string name="templates_group_enable_summary">エントリのフィールドの記入にダイナミックテンプレートを用います</string>
<string name="templates_group_enable_title">テンプレートの使用</string>
<string name="templates_group_enable_summary">エントリのフィールドへの入力に動的テンプレートを使用します</string>
<string name="ssid">SSID</string>
<string name="templates">Templates</string>
<string name="templates">テンプレート</string>
<string name="secure_note">セキュアメモ</string>
<string name="bank_identifier_code">SWIFTコード</string>
<string name="international_bank_account_number"></string>
<string name="bank_identifier_code">SWIFT / BIC</string>
<string name="international_bank_account_number">IBAN</string>
<string name="bank_name">銀行名</string>
<string name="bank">銀行</string>
<string name="account">口座</string>
@@ -581,11 +581,23 @@
<string name="date_of_issue">発行日</string>
<string name="place_of_issue">発行地</string>
<string name="name">名前</string>
<string name="id_card">IDカード</string>
<string name="id_card">ID カード</string>
<string name="personal_identification_number">PIN</string>
<string name="card_verification_value">CVV</string>
<string name="number">カード番号</string>
<string name="holder">所有者</string>
<string name="template_group_name">Templates</string>
<string name="debit_credit_card">クレジットカード/デビットカード</string>
<string name="number">番号</string>
<string name="holder">名義人</string>
<string name="template_group_name">テンプレート</string>
<string name="debit_credit_card">デビット / クレジットカード</string>
<string name="show_otp_token_summary">エントリーの一覧に OTP トークンを表示します</string>
<string name="show_otp_token_title">OTP トークンを表示</string>
<string name="version">バージョン</string>
<string name="standard">標準</string>
<string name="membership">メンバーシップ</string>
<string name="type">種類</string>
<string name="autofill_select_entry">エントリーを選択する…</string>
<string name="autofill_manual_selection_title">手動選択</string>
<string name="autofill_manual_selection_summary">ユーザーがデータベースのエントリーを選択できるようにオプションを表示します</string>
<string name="templates_group_uuid_title">テンプレート グループ</string>
<string name="menu_external_icon">外部アイコン</string>
<string name="template">テンプレート</string>
</resources>

View File

@@ -392,4 +392,23 @@
<string name="content">ഉള്ളടക്കം</string>
<string name="device_credential">ഉപകരണ ക്രെഡൻഷ്യൽ</string>
<string name="error_field_name_already_exists">ഈ ഫീൽഡ് നാമം ഇതിനകം ഉണ്ട്.</string>
<string name="version">പതിപ്പ്</string>
<string name="membership">അംഗത്വം</string>
<string name="secure_note">സുരക്ഷിത കുറിപ്പ്</string>
<string name="bank_name">ബാങ്കിന്റെ പേര്</string>
<string name="bank">ബാങ്ക്</string>
<string name="account">അക്കൗണ്ട്</string>
<string name="seed">സീഡ്</string>
<string name="token">ടോക്കൺ</string>
<string name="cryptocurrency">ക്രിപ്‌റ്റോകറൻസി വാലറ്റ്</string>
<string name="type">തരം</string>
<string name="ssid">എസ്എസ്ഐഡി</string>
<string name="email_address">ഇമെയിൽ വിലാസം</string>
<string name="email">ഇമെയിൽ</string>
<string name="name">പേര്</string>
<string name="id_card">ഐഡി കാർഡ്</string>
<string name="personal_identification_number">പിൻ</string>
<string name="card_verification_value">സിവിവി</string>
<string name="number">നമ്പർ</string>
<string name="debit_credit_card">ടെബിറ്റ്/ ക്രെഡിറ്റ് കാർഡ്</string>
</resources>

View File

@@ -467,4 +467,36 @@
<string name="autofill_preference_title">Autofyllings-innstillinger</string>
<string name="warning_sure_remove_data">Fjern denne dataen uansett\?</string>
<string name="warning_permanently_delete_nodes">Slett valgte noder for godt\?</string>
<string name="templates_group_uuid_title">Malgruppe</string>
<string name="advanced_unlock_prompt_store_credential_title">Avansert opplåsingsgjenkjennelse</string>
<string name="warning_empty_recycle_bin">Slett alle noder fra papirkurven for godt\?</string>
<string name="export_app_properties_title">Eksporter programegenskaper</string>
<string name="import_app_properties_title">Importer programegenskaper</string>
<string name="error_duplicate_file">Fildataen finnes allerede.</string>
<string name="error_file_to_big">Filen du prøver å laste opp er for stor.</string>
<string name="error_move_group_here">Du kan ikke flytte en gruppe hit.</string>
<string name="version">Versjon</string>
<string name="template">Mal</string>
<string name="membership">Medlemskap</string>
<string name="international_bank_account_number">IBAN</string>
<string name="bank_name">Banknavn</string>
<string name="bank">Bank</string>
<string name="account">Konto</string>
<string name="private_key">Privat nøkkel</string>
<string name="public_key">Offentlig nøkkel</string>
<string name="token">Symbol</string>
<string name="type">Type</string>
<string name="ssid">SSID</string>
<string name="email_address">E-postadresse</string>
<string name="email">E-post</string>
<string name="date_of_issue">Utstedsdato</string>
<string name="name">Navn</string>
<string name="id_card">ID-kort</string>
<string name="personal_identification_number">PIN</string>
<string name="card_verification_value">CVV</string>
<string name="number">Nummer</string>
<string name="holder">Innehaver</string>
<string name="content_description_otp_information">Éngangspassordsinfo</string>
<string name="template_group_name">Maler</string>
<string name="content_description_credentials_information">Identitetdetaljsinfo</string>
</resources>

View File

@@ -20,12 +20,12 @@
Dutch translation by Erik Devriendt, corrected by Erik Jan Meijer
--><resources>
<string name="feedback">Reacties</string>
<string name="homepage">Website</string>
<string name="homepage">Startpagina</string>
<string name="about_description">Android-implementatie van KeePass-wachtwoordbeheer</string>
<string name="accept">Accepteren</string>
<string name="add_entry">Item toevoegen</string>
<string name="add_group">Groep toevoegen</string>
<string name="encryption_algorithm">Algoritme</string>
<string name="encryption_algorithm">Versleutelingsalgoritme</string>
<string name="app_timeout">Time-out</string>
<string name="app_timeout_summary">Tijd tot vergrendeling bij inactiviteit</string>
<string name="application">App</string>
@@ -33,8 +33,8 @@
<string name="brackets">Haakjes</string>
<string name="file_manager_install_description">Bestandsbeheer dat de Intent-actie ACTION_CREATE_DOCUMENT en ACTION_OPEN_DOCUMENT accepteert, is nodig om databasebestanden aan te maken, te openen en op te slaan.</string>
<string name="clipboard_cleared">Klembord gewist</string>
<string name="clipboard_timeout">Klembordtime-out</string>
<string name="clipboard_timeout_summary">Tijd van opslag op het klembord (voor zover ondersteund op dit apparaat)</string>
<string name="clipboard_timeout">Time-out van het klembord</string>
<string name="clipboard_timeout_summary">Tijd van opslag op het klembord (indien ondersteund op dit apparaat)</string>
<string name="select_to_copy">Selecteer om %1$s naar klembord te kopiëren</string>
<string name="retrieving_db_key">Databasesleutel ophalen…</string>
<string name="database">Database</string>
@@ -203,7 +203,7 @@
<string name="clipboard_warning">Als automatisch wissen van het klembord mislukt, doe dit dan handmatig.</string>
<string name="lock">Vergrendelen</string>
<string name="lock_database_screen_off_title">Schermvergrendeling</string>
<string name="lock_database_screen_off_summary">Database vergrendelen wanneer het scherm is uitgeschakeld</string>
<string name="lock_database_screen_off_summary">Vergrendel de database een paar seconden nadat het scherm is uitgeschakeld</string>
<string name="advanced_unlock">Geavanceerd ontgrendelen</string>
<string name="biometric_unlock_enable_title">Ontgrendelen met biometrie</string>
<string name="biometric_unlock_enable_summary">Gebruik biometrische herkenning om de database te openen</string>
@@ -475,7 +475,7 @@
<string name="data">Gegevens</string>
<string name="database_data_remove_unlinked_attachments_title">Niet-gekoppelde gegevens verwijderen</string>
<string name="database_data_remove_unlinked_attachments_summary">Verwijdert bijlagen die in de database staan, maar niet aan een item zijn gekoppeld</string>
<string name="show_uuid_summary">Geeft de UUID weer die aan een item is gekoppeld</string>
<string name="show_uuid_summary">Geeft de UUID weer die is gekoppeld aan een item of een groep</string>
<string name="show_uuid_title">UUID tonen</string>
<string name="autofill_read_only_save">Het opslaan van gegevens is niet toegestaan voor een database die is geopend als alleen-lezen.</string>
<string name="autofill_ask_to_save_data_summary">Vraag om gegevens op te slaan wanneer een formulier is gevalideerd</string>
@@ -564,4 +564,43 @@
<string name="error_start_database_action">Er is een fout opgetreden bij het uitvoeren van een actie op de database.</string>
<string name="error_move_group_here">Je kunt hier geen groep verplaatsen.</string>
<string name="error_word_reserved">Dit woord is gereserveerd en kan niet worden gebruikt.</string>
<string name="id_card">Identiteitskaart</string>
<string name="personal_identification_number">Pincode</string>
<string name="holder">Kaarthouder</string>
<string name="show_otp_token_summary">Geeft OTP-tokens weer in de lijst met items</string>
<string name="show_otp_token_title">OTP-token weergeven</string>
<string name="autofill_manual_selection_summary">Toon optie om de gebruiker database-invoer te laten selecteren</string>
<string name="autofill_manual_selection_title">Handmatige selectie</string>
<string name="templates">Sjablonen</string>
<string name="templates_group_uuid_title">Sjabloongroep</string>
<string name="templates_group_enable_summary">Gebruik dynamische sjablonen om de velden van een item in te vullen</string>
<string name="templates_group_enable_title">Sjabloongebruik</string>
<string name="autofill_select_entry">Selecteer invoer…</string>
<string name="menu_external_icon">Extern pictogram</string>
<string name="version">Versie</string>
<string name="template">Sjabloon</string>
<string name="standard">Standaard</string>
<string name="membership">Lidmaatschap</string>
<string name="secure_note">Veilige notitie</string>
<string name="international_bank_account_number">IBAN</string>
<string name="bank_identifier_code">SWIFT / BIC</string>
<string name="bank_name">Banknaam</string>
<string name="bank">Bank</string>
<string name="account">Rekening</string>
<string name="seed">Seed</string>
<string name="private_key">Privésleutel</string>
<string name="public_key">Publieke sleutel</string>
<string name="token">Token</string>
<string name="cryptocurrency">Portemonnee voor cryptovaluta</string>
<string name="type">Type</string>
<string name="ssid">SSID</string>
<string name="email_address">E-mailadres</string>
<string name="email">E-mail</string>
<string name="date_of_issue">Datum van afgifte</string>
<string name="place_of_issue">Plaats van afgifte</string>
<string name="name">Naam</string>
<string name="card_verification_value">CVV</string>
<string name="number">Nummer</string>
<string name="debit_credit_card">Betaalkaart</string>
<string name="template_group_name">Sjablonen</string>
</resources>

View File

@@ -199,7 +199,7 @@
<string name="clipboard_warning">Jeśli automatyczne usuwanie schowka nie powiedzie się, ręcznie usuń jego historię.</string>
<string name="lock">Blokada</string>
<string name="lock_database_screen_off_title">Blokada ekranu</string>
<string name="lock_database_screen_off_summary">Zablokuj bazę danych, gdy ekran jest wyłączony</string>
<string name="lock_database_screen_off_summary">Zablokuj bazę danych po kilku sekundach od wyłączenia ekranu</string>
<string name="advanced_unlock">Odcisk palca</string>
<string name="biometric_unlock_enable_title">Skanowanie odcisków palców</string>
<string name="biometric_unlock_enable_summary">Umożliwia zeskanowanie danych biometrycznych w celu otwarcia bazy danych</string>
@@ -473,7 +473,7 @@
<string name="warning_sure_remove_data">Czy mimo to usunąć te dane\?</string>
<string name="warning_remove_unlinked_attachment">Usunięcie niepowiązanych danych może zmniejszyć rozmiar bazy danych, ale może również spowodować usunięcie danych używanych przez wtyczki KeePass.</string>
<string name="content_description_credentials_information">Informacje o poświadczeniach</string>
<string name="show_uuid_summary">Wyświetla identyfikator UUID powiązany z wpisem</string>
<string name="show_uuid_summary">Wyświetla identyfikator UUID powiązany z wpisem lub grupą</string>
<string name="show_uuid_title">Pokaż UUID</string>
<string name="autofill_read_only_save">Zapisywanie danych nie jest dozwolone dla bazy danych otwartej jako tylko do odczytu.</string>
<string name="autofill_ask_to_save_data_summary">Poproś o zapisanie danych po zatwierdzeniu formularza</string>
@@ -596,4 +596,10 @@
<string name="holder">Posiadacz</string>
<string name="debit_credit_card">Karta debetowa / kredytowa</string>
<string name="template_group_name">Szablony</string>
<string name="show_otp_token_summary">Wyświetla tokeny OTP na liście wpisów</string>
<string name="show_otp_token_title">Pokaż token OTP</string>
<string name="menu_external_icon">Ikona zewnętrzna</string>
<string name="autofill_manual_selection_summary">Wyświetl opcję pozwalającą użytkownikowi wybrać wpis bazy danych</string>
<string name="autofill_manual_selection_title">Wybór ręczny</string>
<string name="autofill_select_entry">Wybierz wpis…</string>
</resources>

View File

@@ -23,19 +23,19 @@
<string name="accept">Aceitar</string>
<string name="add_entry">Adicionar entrada</string>
<string name="add_group">Adicionar grupo</string>
<string name="encryption_algorithm">Algoritmo de Encriptação</string>
<string name="app_timeout">Tempo limite para o aplicativo</string>
<string name="app_timeout_summary">Inativo até que o aplicativo seja bloqueado</string>
<string name="encryption_algorithm">Algoritmo de cifragem</string>
<string name="app_timeout">Tempo de espera</string>
<string name="app_timeout_summary">Inatividade até que o aplicativo seja bloqueado</string>
<string name="application">Aplicativo</string>
<string name="menu_app_settings">Configurações do aplicativo</string>
<string name="brackets">Parênteses</string>
<string name="file_manager_install_description">É necessário um gerenciador de arquivos que aceite asões ACTION_CREATE_DOCUMENT e ACTION_OPEN_DOCUMENT para criar, abrir e salvar arquivos de banco de dados.</string>
<string name="file_manager_install_description">Um gerenciador de arquivos que aceita a ação Intenção ACTION_CREATE_DOCUMENT e ACTION_OPEN_DOCUMENT é necessário para criar, abrir e salvar arquivos de banco de dados.</string>
<string name="clipboard_cleared">Área de transferência limpa</string>
<string name="clipboard_timeout">Tempo limite para o clipboard</string>
<string name="clipboard_timeout_summary">Duração do armazenamento na área de transferência (se suportada pelo dispositivo)</string>
<string name="select_to_copy">Copiar %1$s para o clipboard</string>
<string name="clipboard_timeout">Tempo limite para a área de transferência</string>
<string name="clipboard_timeout_summary">Duração do armazenamento na área de transferência (se suportado pelo seu dispositivo)</string>
<string name="select_to_copy">Selecione para copiar %1$s para área de transferência</string>
<string name="retrieving_db_key">Criando a chave do banco de dados…</string>
<string name="database">Banco de Dados</string>
<string name="database">Banco de dados</string>
<string name="decrypting_db">Descriptografando conteúdo do banco de dados…</string>
<string name="default_checkbox">Usar como banco de dados padrão</string>
<string name="digits">Digitos</string>
@@ -52,7 +52,7 @@
<string name="entry_modified">Modificado</string>
<string name="entry_password">Senha</string>
<string name="save">Salvar</string>
<string name="entry_title">Nome</string>
<string name="entry_title">Titulo</string>
<string name="entry_url">URL</string>
<string name="entry_user_name">Nome de usuário</string>
<string name="error_arc4">A cifra de fluxo Arcfour não é suportada.</string>
@@ -62,23 +62,23 @@
<string name="error_invalid_path">Certifique-se de que o caminho está correto.</string>
<string name="error_no_name">Digite um nome.</string>
<string name="error_nokeyfile">Selecione um arquivo-chave.</string>
<string name="error_out_of_memory">Falta de memória para abrir todo o banco.</string>
<string name="error_out_of_memory">Falta de memória para abrir todo o banco de dados.</string>
<string name="error_pass_gen_type">Pelo menos um tipo de geração de senhas deve ser selecionado.</string>
<string name="error_pass_match">As senhas não combinam.</string>
<string name="error_rounds_too_large">\"Número de rodadas\" é muito grande. Modificado para 2147483648.</string>
<string name="error_wrong_length">Digite um número inteiro positivo no campo \"Tamanho\".</string>
<string name="file_browser">Localizador de arquivos</string>
<string name="error_rounds_too_large">\"Rodadas de transformação\" é muito grande. Modificado para 2147483648.</string>
<string name="error_wrong_length">Digite um número inteiro positivo no campo \"Comprimento\".</string>
<string name="file_browser">Explorador de arquivos</string>
<string name="generate_password">Gerar senha</string>
<string name="hint_conf_pass">Confirmar senha</string>
<string name="hint_generated_password">Senha gerada</string>
<string name="hint_group_name">Nome do Grupo</string>
<string name="hint_group_name">Nome do grupo</string>
<string name="hint_keyfile">Arquivo-chave</string>
<string name="hint_length">Tamanho</string>
<string name="hint_length">Comprimento</string>
<string name="password">Senha</string>
<string name="hint_pass">Senha</string>
<string name="invalid_credentials">Não foi possível ler credenciais.</string>
<string name="invalid_db_sig">Não pôde reconhecer formato do banco de dados.</string>
<string name="length">Tamanho</string>
<string name="invalid_db_sig">Não pôde reconhecer formato da base de dados.</string>
<string name="length">Comprimento</string>
<string name="list_size_title">Tamanho da lista de grupos</string>
<string name="list_size_summary">Tamanho do texto na lista de grupos</string>
<string name="loading_database">Carregando banco de dados…</string>
@@ -90,32 +90,32 @@
<string name="settings">Configurações</string>
<string name="menu_database_settings">Configurações do banco de dados</string>
<string name="menu_delete">Deletar</string>
<string name="menu_donate">Doaçoes</string>
<string name="menu_donate">Doar</string>
<string name="menu_edit">Editar</string>
<string name="menu_hide_password">Esconder senha</string>
<string name="menu_lock">Trancar base de dados</string>
<string name="menu_lock">Bloquear base de dados</string>
<string name="menu_open">Abrir</string>
<string name="menu_search">Procurar</string>
<string name="menu_search">Buscar</string>
<string name="menu_showpass">Mostrar senha</string>
<string name="menu_url">Ir para URL</string>
<string name="minus">Menos</string>
<string name="never">Nunca</string>
<string name="no_results">Sem resultados na busca</string>
<string name="no_url_handler">Instale um navegador para abrir esta URL.</string>
<string name="omit_backup_search_title">Não procurar por entradas no backup ou na lixeira</string>
<string name="omit_backup_search_title">Não buscar por entradas no backup ou na lixeira</string>
<string name="omit_backup_search_summary">Omite os grupos \"Backup\" e \"Lixeira\" dos resultados da busca</string>
<string name="progress_create">Criando novo banco de dados…</string>
<string name="progress_title">Trabalhando…</string>
<string name="content_description_remove_from_list">Remover</string>
<string name="root">Raiz</string>
<string name="rounds">Rodadas de criptografia</string>
<string name="rounds_explanation">Rodadas adicionais de criptografia adicionam mais proteção contra ataques de força bruta, mas podem tornar o processo de carregar e salvar mais lentos.</string>
<string name="rounds">Rodadas de transformação</string>
<string name="rounds_explanation">Rodadas adicionais de cifragem adicionam mais proteção contra ataques de força bruta, mas podem tornar o processo de carregar e salvar mais lentos.</string>
<string name="saving_database">Salvando banco de dados…</string>
<string name="space">Spaço</string>
<string name="space">Espaço</string>
<string name="search_label">Busca</string>
<string name="sort_db">Ordenação natural</string>
<string name="special">Caracteres Especiais</string>
<string name="search">Título/Descrição da entrada</string>
<string name="special">Especial</string>
<string name="search">Buscar</string>
<string name="underline">Sublinhado</string>
<string name="unsupported_db_version">Versão de banco de dados não suportada.</string>
<string name="uppercase">Letras maiúsculas</string>
@@ -128,36 +128,36 @@
<item>Médio</item>
<item>Grande</item>
</string-array>
<string name="encryption">Encriptação</string>
<string name="encryption">Cifragem</string>
<string name="key_derivation_function">Função de derivação de chave</string>
<string name="extended_ASCII">ASCII Extendido</string>
<string name="extended_ASCII">ASCII estendido</string>
<string name="allow">Permitir</string>
<string name="clipboard_error_title">Erro na área de transferência</string>
<string name="clipboard_error">Alguns dispositivos não permitem que aplicativos usem a área de transferência.</string>
<string name="clipboard_error_clear">Não foi possível limpar a área de transferência</string>
<string name="entry_not_found">Não pôde encontrar dado de entrada.</string>
<string name="entry_not_found">Não pôde encontrar dados de entrada.</string>
<string name="error_string_key">Um nome do campo é necessário para cada string.</string>
<string name="error_autofill_enable_service">Não pôde ser habilitado o serviço de preenchimento automático.</string>
<string name="field_name">Nome do campo</string>
<string name="field_value">Valor do campo</string>
<string name="file_not_found_content">Arquivo não encontrado. Tente reabri-lo de seu buscador de arquivos.</string>
<string name="file_not_found_content">Não pôde encontrar o arquivo. Tente reabri-lo de seu explorador de arquivos.</string>
<string name="invalid_algorithm">Algoritmo errado.</string>
<string name="keyfile_is_empty">O arquivo-chave está vazio.</string>
<string name="copy_field">Cópia de %1$s</string>
<string name="menu_form_filling_settings">Preenchimento de formulário</string>
<string name="menu_copy">Cópia</string>
<string name="menu_copy">Copiar</string>
<string name="menu_move">Mover</string>
<string name="menu_paste">Colar</string>
<string name="menu_cancel">Cancelar</string>
<string name="menu_file_selection_read_only">Somente leitura</string>
<string name="menu_open_file_read_and_write">Gravação</string>
<string name="menu_open_file_read_and_write">Modificável</string>
<string name="protection">Proteção</string>
<string name="read_only">Somente leitura</string>
<string name="read_only_warning">KeePassDX precisa de permissões de escrita para poder mudar qualquer coisa no seu banco.</string>
<string name="show_recent_files_title">Histórico de arquivos recentes</string>
<string name="show_recent_files_summary">Lembrar nomes recentes de arquivos</string>
<string name="encryption_explanation">Algoritmo de encriptação usado para todos os dados.</string>
<string name="kdf_explanation">Para gerar a chave para o algoritmo de criptografia, a chave mestra é transformada usando uma função de derivação de chave com sal aleatoriamente.</string>
<string name="show_recent_files_title">Exibir arquivos recentes</string>
<string name="show_recent_files_summary">Exibir locais de bancos de dados recentes</string>
<string name="encryption_explanation">Algoritmo de cifragem usado para todos os dados.</string>
<string name="kdf_explanation">Para gerar uma chave para o algoritmo de cifragem, a chave mestra é transformada usando uma função de derivação de chave salgada aleatoriamente.</string>
<string name="memory_usage">Uso de memória</string>
<string name="memory_usage_explanation">Quantidade de memória a ser usada pela função de derivação de chave.</string>
<string name="parallelism">Paralelismo</string>
@@ -171,36 +171,36 @@
<string name="sort_creation_time">Data de criação</string>
<string name="sort_last_modify_time">Última modificação</string>
<string name="sort_last_access_time">Último acesso</string>
<string name="search_results">Resultados da pesquisa</string>
<string name="search_results">Resultados da busca</string>
<string name="warning">Aviso</string>
<string name="warning_password_encoding">Evite caracteres fora do formato de codificação do arquivo do banco (todos os caracteres não reconhecidos são convertidos para a mesma letra).</string>
<string name="warning_empty_password">Continuar sem proteção de desbloqueio de senha\?</string>
<string name="warning_no_encryption_key">Continuar sem chave de criptografia\?</string>
<string name="encrypted_value_stored">Senha encriptada armazenada</string>
<string name="warning_no_encryption_key">Continuar sem chave de cifragem\?</string>
<string name="encrypted_value_stored">Senha cifrada armazenada</string>
<string name="no_credentials_stored">Ainda não há nenhuma senha armazenada nesse banco de dados.</string>
<string name="database_history">Histórico</string>
<string name="menu_appearance_settings">Aparência</string>
<string name="general">Geral</string>
<string name="autofill">Preenchimento automático</string>
<string name="autofill_service_name">Preenchimento Automático KeePassDX</string>
<string name="autofill_service_name">Preenchimento automático do KeePassDX</string>
<string name="autofill_sign_in_prompt">Entre com o KeePassDX</string>
<string name="set_autofill_service_title">Definir serviço padrão de preenchimento automático</string>
<string name="autofill_explanation_summary">Habilite o serviço para rapidamente preencher formulários em outros aplicativos</string>
<string name="password_size_title">Comprimento da senha gerada</string>
<string name="password_size_summary">Define o tamanho padrão para senhas geradas</string>
<string name="list_password_generator_options_title">Caracteres da senha</string>
<string name="list_password_generator_options_summary">Definir os caracteres padrão do gerador de senha</string>
<string name="list_password_generator_options_summary">Definir os caracteres padrão do gerador de senhas</string>
<string name="clipboard_notifications_title">Notificações da área de transferência</string>
<string name="clipboard_notifications_summary">Mostrar notificações da área de transferência para campos copiáveis quando estiver visualizando uma entrada</string>
<string name="clipboard_warning">Se a limpeza da área de transferência falhar, limpe seu histórico manualmente.</string>
<string name="lock">Bloquear</string>
<string name="lock_database_screen_off_title">Bloqueio de tela</string>
<string name="lock_database_screen_off_summary">Bloqueie o banco de dados quando a tela estiver desligada</string>
<string name="advanced_unlock">Impressão Digital</string>
<string name="biometric_unlock_enable_title">Escaneamento de impressão digital</string>
<string name="lock_database_screen_off_summary">Bloqueie o banco de dados após alguns segundos quando a tela for desligada</string>
<string name="advanced_unlock">Desbloqueio avançado</string>
<string name="biometric_unlock_enable_title">Desbloqueio biométrico</string>
<string name="biometric_unlock_enable_summary">Permite que você escaneie sua biometria para a abertura do banco de dados</string>
<string name="biometric_delete_all_key_title">Apague chaves de encriptação</string>
<string name="biometric_delete_all_key_summary">Apague todas as chaves de encriptação relacionadas ao reconhecimento de Impressões digitais</string>
<string name="biometric_delete_all_key_title">Apague chaves de cifragem</string>
<string name="biometric_delete_all_key_summary">Apagar todas as chaves de cifragem relacionadas ao reconhecimento de desbloqueio avançado</string>
<string name="unavailable_feature_text">Não foi possível iniciar esse recurso.</string>
<string name="unavailable_feature_version">O dispositivo está utilizando Android %1$s, mas precisa %2$s ou posterior.</string>
<string name="unavailable_feature_hardware">Não foi possível encontrar o hardware correspondente.</string>
@@ -210,16 +210,16 @@
<string name="create_keepass_file">Criar novo banco</string>
<string name="recycle_bin_title">Usar lixeira</string>
<string name="recycle_bin_summary">Mover grupos e entradas para o grupo \"Lixeira\" antes de apagar</string>
<string name="monospace_font_fields_enable_title">Fonte do Campo</string>
<string name="monospace_font_fields_enable_title">Tipo de letra nos campos</string>
<string name="monospace_font_fields_enable_summary">Muda a fonte usada nos campos para melhor visibilidade dos caracteres</string>
<string name="allow_copy_password_title">Confiança da área de transferência</string>
<string name="allow_copy_password_title">Confiança na área de transferência</string>
<string name="allow_copy_password_summary">Permitir a cópia da senha e de campos protegidos para a área de transferência</string>
<string name="allow_copy_password_warning">AVISO: A área de transferência é compartilhada por todos os aplicativos. Se dados sensíveis forem copiados, outros programas podem recuperá-los.</string>
<string name="database_name_title">Nome do banco de dados</string>
<string name="database_description_title">Descrição do banco de dados</string>
<string name="database_version_title">Versão do banco de dados</string>
<string name="text_appearance">Texto</string>
<string name="application_appearance">Aplicativo</string>
<string name="application_appearance">Interface</string>
<string name="other">Outros</string>
<string name="keyboard">Teclado</string>
<string name="magic_keyboard_title">Magikeyboard</string>
@@ -228,11 +228,11 @@
<string name="allow_no_password_summary">Permitir tocar no botão \"Abrir\" se nenhuma credencial for selecionada</string>
<string name="enable_read_only_title">Somente leitura</string>
<string name="enable_read_only_summary">Por padrão, abrir seu banco de dados no modo somente leitura</string>
<string name="enable_education_screens_title">Telas educacionais</string>
<string name="enable_education_screens_summary">Destaque os elementos para aprender como o app funciona</string>
<string name="enable_education_screens_title">Dicas educacionais</string>
<string name="enable_education_screens_summary">Destaque os elementos para aprender como o aplicativo funciona</string>
<string name="reset_education_screens_title">Reiniciar telas educacionais</string>
<string name="reset_education_screens_summary">Exibir todos os itens educacionais novamente</string>
<string name="reset_education_screens_text">Telas educacionais redefinidas</string>
<string name="reset_education_screens_summary">Mostrar todas as informações educacionais novamente</string>
<string name="reset_education_screens_text">Dicas educacionais redefinidas</string>
<string name="education_create_database_title">Crie um arquivo de banco de dados</string>
<string name="education_create_database_summary">Crie seu primeiro arquivo de gerenciamento de senhas.</string>
<string name="education_select_database_title">Abra um banco de dados existente</string>
@@ -246,7 +246,7 @@
<string name="education_entry_edit_title">Modifique a entrada</string>
<string name="education_entry_edit_summary">Edite a sua entrada com campos personalizados. Os conjuntos de dados podem ser referenciados entre campos de entradas diferentes.</string>
<string name="education_generate_password_title">Criar uma senha forte</string>
<string name="education_generate_password_summary">Gere uma senha forte para associar a sua entrada, defina-a facilmente de acordo com os critérios do formulário e não se esqueça de torná-la segura.</string>
<string name="education_generate_password_summary">Gere uma senha forte para associar a sua entrada, defina-a facilmente de acordo com os critérios do formulário e lembre-se de torná-la segura.</string>
<string name="education_entry_new_field_title">Adicione campos customizados</string>
<string name="education_entry_new_field_summary">Registrar um campo adicional, adicionar um valor e, opcionalmente, protegê-lo.</string>
<string name="education_unlock_title">Desbloqueie seu banco de dados</string>
@@ -254,7 +254,7 @@
<string name="education_read_only_summary">Altere o modo de abertura para a sessão.
\n
\n\"Somente leitura\" evita que você faça alterações não intencionais no banco de dados.
\n\"Gravação\" permite você a adicionar, excluir ou modificar todos os elementos.</string>
\n\"Modificável\" permite você adicionar, excluir ou modificar todos os elementos que desejar.</string>
<string name="education_field_copy_title">Copiar um campo</string>
<string name="education_field_copy_summary">Campos copiados podem ser colados em qualquer lugar.
\n
@@ -262,7 +262,7 @@
<string name="education_lock_title">Bloqueie o banco de dados</string>
<string name="education_lock_summary">Bloqueie seu banco de dados rapidamente, você pode parametrizar o aplicativo para bloqueá-lo depois de um tempo, e quando a tela se apaga.</string>
<string name="education_sort_title">Ordenação de itens</string>
<string name="education_sort_summary">Escolha como entradas e grupos são ordenadas.</string>
<string name="education_sort_summary">Escolha como entradas e grupos são ordenados.</string>
<string name="education_donation_title">Participar</string>
<string name="education_donation_summary">Ajude a aumentar a estabilidade, segurança e na adição de mais recursos.</string>
<string name="html_text_ad_free">Ao contrário de muitos aplicativos de gerenciamento de senhas, este aplicativo é &lt;strong&gt;livre de anúncios&lt;/strong&gt;, &lt;strong&gt;livre de direitos autorais&lt;/strong&gt; e não recupera dados pessoais em seus servidores, mesmo em sua versão gratuita.</string>
@@ -275,7 +275,7 @@
<string name="html_text_dev_feature_encourage">Você está incentivando os desenvolvedores a criar &lt;strong&gt;novos recursos&lt;/strong&gt; e a &lt;strong&gt;corrigir erros &lt;/strong&gt; de acordo com suas observações.</string>
<string name="html_text_dev_feature_thanks">Obrigado por sua contribuição.</string>
<string name="html_text_dev_feature_work_hard">Estamos trabalhando duro para lançar esse recurso o mais rápido possível.</string>
<string name="html_text_dev_feature_upgrade">Lembre-se de manter seu aplicativo atualizado.</string>
<string name="html_text_dev_feature_upgrade">Não se esqueça de instalar as novas versões para manter seu aplicativo atualizado.</string>
<string name="download">Baixar</string>
<string name="contribute">Contribuir</string>
<string name="style_choose_title">Tema do aplicativo</string>
@@ -283,7 +283,7 @@
<string name="icon_pack_choose_title">Pacote de ícones</string>
<string name="icon_pack_choose_summary">Pacote de ícones usado no aplicativo</string>
<string name="edit_entry">Editar entrada</string>
<string name="error_load_database">Falha ao carregar o banco.</string>
<string name="error_load_database">Não foi possível carregar seu banco de dados.</string>
<string name="error_load_database_KDF_memory">Não pôde carregar a chave. Tente diminuir o \"Uso de Memória\" do KDF.</string>
<string name="list_entries_show_username_title">Mostrar nomes de usuário</string>
<string name="list_entries_show_username_summary">Mostrar nomes de usuário em listas de entrada</string>
@@ -305,21 +305,21 @@
<string name="keyboard_appearance_category">Aparência</string>
<string name="keyboard_theme_title">Tema do teclado</string>
<string name="keyboard_keys_category">Teclas</string>
<string name="keyboard_key_vibrate_title">Vibrar ao clicar</string>
<string name="keyboard_key_sound_title">Clicar audível</string>
<string name="selection_mode">Modo de seleção</string>
<string name="keyboard_key_vibrate_title">Vibrar ao pressionar teclas</string>
<string name="keyboard_key_sound_title">Teclas audíveis</string>
<string name="selection_mode">Modo seleção</string>
<string name="do_not_kill_app">Não feche o aplicativo…</string>
<string name="lock_database_back_root_title">Pressione \'Voltar\' para trancar</string>
<string name="lock_database_back_root_title">Pressione \'Voltar\' para bloquear</string>
<string name="lock_database_back_root_summary">Trancar a base de dados quando o usuário pressiona o botão \"Voltar\" na tela inicial</string>
<string name="clear_clipboard_notification_title">Limpar ao fechar</string>
<string name="clear_clipboard_notification_summary">Bloquear o banco de dados quando a duração da área de transferência expirar ou a notificação for fechada depois do início do uso</string>
<string name="recycle_bin">Lixeira</string>
<string name="keyboard_selection_entry_title">Seleção de entrada</string>
<string name="keyboard_selection_entry_summary">Mostrar campos de entrada no Magikeyboard quando estiver visualizando uma Entrada</string>
<string name="delete_entered_password_title">Deletar senha</string>
<string name="keyboard_selection_entry_summary">Ao visualizar uma entrada no KeePassDX, preencher o Magikeyboard com essa entrada</string>
<string name="delete_entered_password_title">Excluir senha</string>
<string name="delete_entered_password_summary">Deleta a senha inserida após uma tentativa de conexão com o banco de dados</string>
<string name="content_description_open_file">Abrir arquivo</string>
<string name="content_description_add_node">Inserir nó</string>
<string name="content_description_add_node">Adicionar nó</string>
<string name="content_description_add_entry">Adicionar entrada</string>
<string name="content_description_add_group">Adicionar grupo</string>
<string name="content_description_file_information">Informações do arquivo</string>
@@ -327,14 +327,14 @@
<string name="entry_password_generator">Gerador de senhas</string>
<string name="content_description_password_length">Comprimento da senha</string>
<string name="entry_add_field">Adicionar campo</string>
<string name="content_description_remove_field">Remover campo</string>
<string name="content_description_remove_field">Excluir campo</string>
<string name="entry_UUID">UUID</string>
<string name="error_move_entry_here">Você não pode mover uma entrada para cá.</string>
<string name="error_copy_entry_here">Você não pode copiar uma entrada daqui.</string>
<string name="list_groups_show_number_entries_title">Mostrar número de entradas</string>
<string name="list_groups_show_number_entries_summary">Mostrar o número de entradas dentro de um grupo</string>
<string name="content_description_node_children">Nó filho</string>
<string name="content_description_password_checkbox">Caixa de seleção de senha</string>
<string name="content_description_password_checkbox">Caixa de seleção da senha</string>
<string name="content_description_keyfile_checkbox">Caixa de seleção do arquivo-chave</string>
<string name="content_description_repeat_toggle_password_visibility">Repetir mudança de visibilidade da senha</string>
<string name="content_description_background">Plano de fundo</string>
@@ -343,14 +343,14 @@
<string name="error_create_database_file">Impossibilitado de criar um banco de dados com essa senha e arquivo-chave.</string>
<string name="menu_advanced_unlock_settings">Desbloqueio avançado</string>
<string name="biometric">Biometria</string>
<string name="biometric_auto_open_prompt_title">Abrir automaticamente o prompt de biometria</string>
<string name="biometric_auto_open_prompt_summary">Pedir automaticamente pelo prompt de biometria se a base de dados estiver configurada para usá-la</string>
<string name="biometric_auto_open_prompt_title">Abrir automaticamente o prompt</string>
<string name="biometric_auto_open_prompt_summary">Solicitar desbloqueio avançado automaticamente se o banco de dados estiver configurado para usá-lo</string>
<string name="enable">Habilitado</string>
<string name="disable">Desabilitado</string>
<string name="master_key">Chave mestra</string>
<string name="security">Segurança</string>
<string name="entry_history">Histórico</string>
<string name="entry_setup_otp">Configurar OTP</string>
<string name="entry_setup_otp">Configure uma senha de uso único</string>
<string name="otp_type">Tipo OTP</string>
<string name="otp_secret">Segredo</string>
<string name="otp_period">Período (segundos)</string>
@@ -397,16 +397,16 @@
<string name="menu_empty_recycle_bin">Esvaziar lixeira</string>
<string name="command_execution">Executando o comando…</string>
<string name="warning_permanently_delete_nodes">Apagar permanentemente os nós selecionados\?</string>
<string name="keystore_not_accessible">A chave não foi propriamente inicializada.</string>
<string name="keystore_not_accessible">O armazenamento chaves não foi propriamente inicializado.</string>
<string name="recycle_bin_group_title">Grupo de lixeira</string>
<string name="enable_auto_save_database_title">Salvar automaticamente a base de dados</string>
<string name="enable_auto_save_database_summary">Salvar automaticamente a base de dados depois de uma ação importante (somente no modo \"Gravação\")</string>
<string name="enable_auto_save_database_summary">Salvar automaticamente a base de dados depois de uma ação importante (somente no modo \"Modificável\")</string>
<string name="discard">Descartar</string>
<string name="contact">Contato</string>
<string name="auto_focus_search_title">Pesquisa rápida</string>
<string name="auto_focus_search_title">Busca rápida</string>
<string name="menu_delete_entry_history">Apagar histórico</string>
<string name="menu_restore_entry_history">Restaurar histórico</string>
<string name="autofill_auto_search_summary">Sugerir resultados de pesquisa de domínios da internet ou de aplicações automaticamente</string>
<string name="autofill_auto_search_summary">Sugerir resultados de busca de domínios da internet ou de aplicativos automaticamente</string>
<string name="hide_expired_entries_summary">Entradas expiradas foram escondidas</string>
<string name="hide_expired_entries_title">Esconder entradas expiradas</string>
<string name="download_complete">Completo!</string>
@@ -416,33 +416,33 @@
<string name="download_attachment">Baixar %1$s</string>
<string name="education_setup_OTP_summary">Configure o gerenciamento de senha descartável (HOTP / TOTP) para gerar um token solicitado para autenticação de dois fatores (2FA).</string>
<string name="education_setup_OTP_title">Configurar OTP</string>
<string name="autofill_auto_search_title">Pesquisa automática</string>
<string name="keyboard_auto_go_action_summary">Ação da tecla \"Go\" após pressionar a tecla \"Field\"</string>
<string name="keyboard_auto_go_action_title">Ação automática de tecla</string>
<string name="autofill_auto_search_title">Busca automática</string>
<string name="keyboard_auto_go_action_summary">Ação da tecla \"Ir\" após pressionar a tecla \"Campo\"</string>
<string name="keyboard_auto_go_action_title">Ação de tecla automática</string>
<string name="lock_database_show_button_summary">Mostrar o botão de bloqueio na interface do usuário</string>
<string name="lock_database_show_button_title">Mostrar botão de bloqueio</string>
<string name="autofill_preference_title">Configurações de preenchimento automático</string>
<string name="warning_database_link_revoked">Acesso ao arquivo revogado pelo gerenciador de arquivos</string>
<string name="warning_database_read_only">Conceder acesso de gravação de arquivo para salvar alterações na base de dados</string>
<string name="hide_broken_locations_summary">Esconder links quebrados na lista de bases de dados recentes</string>
<string name="hide_broken_locations_title">Esconder links quebrados de bases de dados</string>
<string name="hide_broken_locations_title">Ocultar links quebrados do banco de dados</string>
<string name="remember_keyfile_locations_summary">Manter o local onde os arquivos-chave são armazenados</string>
<string name="remember_keyfile_locations_title">Lembrar a localização dos arquivos-chave</string>
<string name="remember_database_locations_summary">Manter o local onde os bancos de dados são armazenados</string>
<string name="remember_database_locations_summary">Lembra o local onde os bancos de dados são guardados</string>
<string name="remember_database_locations_title">Lembrar a localização dos bancos de dados</string>
<string name="auto_focus_search_summary">Solicitar uma pesquisa quando abrir a base de dados</string>
<string name="error_create_database">Incapaz de criar arquivo de base de dados.</string>
<string name="auto_focus_search_summary">Solicitar uma busca ao abrir um banco de dados</string>
<string name="error_create_database">Não foi possível criar o arquivo do banco de dados.</string>
<string name="error_label_exists">Este rótulo já existe.</string>
<string name="entry_attachments">Acessórios</string>
<string name="html_about_contribution">Para &lt;strong&gt;manter sua liberdade&lt;/strong&gt;, &lt;strong&gt;solucionar bugs&lt;/strong&gt;, &lt;strong&gt;adicionar funções&lt;/strong&gt; e &lt;strong&gt;para ser sempre ativo&lt;/strong&gt;, nós contamos com sua &lt;strong&gt;contribuição&lt;/strong&gt;.</string>
<string name="entry_attachments">Anexos</string>
<string name="html_about_contribution">Para <strong>manter nossa liberdade</strong>, <strong>consertar erros</strong>, <strong>adicionar recursos</strong> e <strong>para estar sempre ativo</strong>, contamos com sua <strong>contribuição</strong>.</string>
<string name="entry_add_attachment">Adicionar anexo</string>
<string name="discard_changes">Descartar alterações\?</string>
<string name="validate">Validação</string>
<string name="discard_changes">Descartar mudanças\?</string>
<string name="validate">Validar</string>
<string name="contribution">Contribuição</string>
<string name="keyboard_search_share_summary">Procurar automaticamente por informação compartilhada para popular o teclado</string>
<string name="keyboard_search_share_summary">Ao compartilhar um URL para KeePassDX, filtre as entradas usando esse domínio de URL</string>
<string name="keyboard_search_share_title">Procurar informação compartilhada</string>
<string name="upload_attachment">Upload %1$s</string>
<string name="keyboard_previous_fill_in_summary">Retornar automaticamente para o teclado anterior após executar a ação automática de tecla</string>
<string name="keyboard_previous_fill_in_summary">Retornar automaticamente para o teclado anterior após executar a \"ação de tecla automática\"</string>
<string name="keyboard_previous_fill_in_title">Ação automática de tecla</string>
<string name="warning_remove_unlinked_attachment">A remoção de dados não vinculados pode diminuir o tamanho do seu banco de dados, mas também pode excluir os dados usados para plug-ins KeePass.</string>
<string name="warning_replace_file">O upload deste arquivo substituirá o existente.</string>
@@ -463,14 +463,141 @@
<string name="warning_empty_keyfile">Não é recomendado adicionar um arquivo-chave vazio.</string>
<string name="warning_sure_remove_data">Remover esses dados mesmo assim\?</string>
<string name="warning_sure_add_file">Adicionar o arquivo mesmo assim\?</string>
<string name="warning_file_too_big">Um banco de dados KeePass deve conter somente pequenos arquivos de utilitários (como arquivos de chave PGP).
<string name="warning_file_too_big">Um banco de dados KeePass deve conter apenas pequenos arquivos de utilitários (como arquivos de chave PGP).
\n
\nSeu banco de dados pode ficar muito grande e reduzir o desempenho com este upload.</string>
<string name="filter">Filtro</string>
<string name="subdomain_search_summary">Pesquisar domínios da web com restrições de subdomínios</string>
<string name="subdomain_search_title">Pesquisa de subdomínio</string>
<string name="error_string_type">Esse texto não conbina com o item solicitado.</string>
<string name="subdomain_search_summary">Buscar por domínios na web com restrições de subdomínios</string>
<string name="subdomain_search_title">Busca de subdomínio</string>
<string name="error_string_type">Esse texto não coincide com o item requerido.</string>
<string name="content_description_credentials_information">Informações de credenciais</string>
<string name="content_description_add_item">Adicionar item</string>
<string name="autofill_block_restart">Reinicie o aplicativo que contém o formulário para ativar o bloqueio.</string>
<string name="menu_keystore_remove_key">Excluir chave de desbloqueio avançado</string>
<string name="menu_reload_database">Recarregar banco de dados</string>
<string name="error_start_database_action">Ocorreu um erro ao executar uma ação no banco de dados.</string>
<string name="error_remove_file">Ocorreu um erro ao remover os dados do arquivo.</string>
<string name="error_duplicate_file">Os dados do arquivo já existem.</string>
<string name="error_upload_file">Ocorreu um erro ao enviar os dados do arquivo.</string>
<string name="error_file_to_big">O arquivo que você está tentando enviar é muito grande.</string>
<string name="error_rebuild_list">Incapaz de reconstruir corretamente a lista.</string>
<string name="error_database_uri_null">O URI do banco de dados não pode ser recuperado.</string>
<string name="error_field_name_already_exists">O nome do campo já existe.</string>
<string name="error_registration_read_only">Não é permitido salvar um novo item em um banco de dados somente de leitura</string>
<string name="error_otp_type">O tipo de OTP existente não é reconhecido por este formulário, sua validação pode não gerar mais o token corretamente.</string>
<string name="error_word_reserved">Esta palavra é reservada e não pode ser usada.</string>
<string name="version">Versão</string>
<string name="template">Modelo</string>
<string name="standard">Padrão</string>
<string name="membership">Afiliação</string>
<string name="secure_note">Nota segura</string>
<string name="international_bank_account_number">IBAN</string>
<string name="bank_identifier_code">SWIFT / BIC</string>
<string name="bank_name">Nome do banco</string>
<string name="bank">Banco</string>
<string name="account">Conta</string>
<string name="seed">Semente</string>
<string name="private_key">Chave privada</string>
<string name="public_key">Chave pública</string>
<string name="token">Token</string>
<string name="cryptocurrency">Carteira de criptomoedas</string>
<string name="type">Tipo</string>
<string name="ssid">SSID</string>
<string name="email_address">Endereço eletrônico</string>
<string name="email">Email</string>
<string name="date_of_issue">Data de emissão</string>
<string name="place_of_issue">Local de emissão</string>
<string name="name">Nome</string>
<string name="id_card">Cédula de identidade</string>
<string name="personal_identification_number">PIN</string>
<string name="card_verification_value">CVV</string>
<string name="number">Número</string>
<string name="holder">Titular</string>
<string name="debit_credit_card">Cartão de débito / crédito</string>
<string name="template_group_name">Modelos</string>
<string name="content_description_otp_information">Informação de senha de uso único</string>
<string name="device_credential">Credencial do dispositivo</string>
<string name="properties">Propriedades</string>
<string name="credential_before_click_advanced_unlock_button">Digite a senha e clique neste botão.</string>
<string name="advanced_unlock_prompt_not_initialized">Incapaz de inicializar o prompt de desbloqueio avançado.</string>
<string name="advanced_unlock_scanning_error">Erro de desbloqueio avançado: %1$s</string>
<string name="advanced_unlock_not_recognized">Não foi possível reconhecer a impressão de desbloqueio avançado</string>
<string name="advanced_unlock_invalid_key">Não é possível ler a chave de desbloqueio avançado. Exclua-o e repita o procedimento de reconhecimento de desbloqueio.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Extraia credencial de banco de dados com dados de desbloqueio avançado</string>
<string name="advanced_unlock_prompt_extract_credential_title">Banco de dados aberto com reconhecimento avançado de desbloqueio</string>
<string name="advanced_unlock_prompt_store_credential_message">Aviso: você ainda precisa lembrar sua senha mestra se usar o reconhecimento de desbloqueio avançado.</string>
<string name="advanced_unlock_prompt_store_credential_title">Reconhecimento de desbloqueio avançado</string>
<string name="open_advanced_unlock_prompt_store_credential">Abra o prompt de desbloqueio avançado para armazenar credenciais</string>
<string name="open_advanced_unlock_prompt_unlock_database">Abra o prompt de desbloqueio avançado para desbloquear o banco de dados</string>
<string name="biometric_security_update_required">Atualização de segurança biométrica necessária.</string>
<string name="configure_biometric">Nenhuma credencial biométrica ou de dispositivo está registrada.</string>
<string name="warning_database_revoked">Acesso ao arquivo revogado pelo gerenciador de arquivos, feche o banco de dados e reabra-o de sua localização.</string>
<string name="warning_database_info_changed_options">Substitua as modificações externas salvando o banco de dados ou recarregue-o com as alterações mais recentes.</string>
<string name="warning_database_info_changed">As informações contidas em seu arquivo de banco de dados foram modificadas fora do aplicativo.</string>
<string name="warning_empty_recycle_bin">Deletar permanentemente todos os nós da lixeira\?</string>
<string name="error_export_app_properties">Erro durante a exportação de propriedades do aplicativo</string>
<string name="success_export_app_properties">Propriedades do aplicativo exportadas</string>
<string name="error_import_app_properties">Erro durante a importação de propriedades do aplicativo</string>
<string name="success_import_app_properties">Propriedades de aplicativos importadas</string>
<string name="description_app_properties">Propriedades KeePassDX para gerenciar configurações de aplicativos</string>
<string name="export_app_properties_summary">Crie um arquivo para exportar as propriedades do aplicativo</string>
<string name="export_app_properties_title">Exportar propriedades do aplicativo</string>
<string name="import_app_properties_summary">Selecione um arquivo para importar as propriedades do aplicativo</string>
<string name="import_app_properties_title">Importar propriedades do aplicativo</string>
<string name="registration_mode">Modo registro</string>
<string name="save_mode">Modo salvar</string>
<string name="search_mode">Modo busca</string>
<string name="menu_external_icon">Ícone externo</string>
<string name="show_otp_token_summary">Exibe tokens OTP na lista de entradas</string>
<string name="show_otp_token_title">Mostrar token OTP</string>
<string name="show_uuid_summary">Exibe o UUID vinculado a uma entrada ou grupo</string>
<string name="show_uuid_title">Mostrar UUID</string>
<string name="icon_section_custom">Personalizado</string>
<string name="icon_section_standard">Padrão</string>
<string name="style_brightness_summary">Selecione temas claros ou escuros</string>
<string name="style_brightness_title">Brilho do tema</string>
<string name="unit_gibibyte">GiB</string>
<string name="unit_mebibyte">MiB</string>
<string name="unit_kibibyte">KiB</string>
<string name="unit_byte">B</string>
<string name="download_canceled">Cancelado!</string>
<string name="education_advanced_unlock_summary">Vincule sua senha à credencial biométrica ou do dispositivo digitalizada para desbloquear rapidamente seu banco de dados.</string>
<string name="education_advanced_unlock_title">Desbloqueio avançado de banco de dados</string>
<string name="autofill_inline_suggestions_keyboard">Sugestões de preenchimento automático adicionadas.</string>
<string name="autofill_read_only_save">A salvação de dados não é permitida para um banco de dados aberto apenas como leitura.</string>
<string name="autofill_ask_to_save_data_summary">Pedir para salvar dados quando um formulário for validado</string>
<string name="autofill_ask_to_save_data_title">Perguntar para salvar dados</string>
<string name="autofill_save_search_info_summary">Tente salvar informações de pesquisa ao fazer uma seleção manual de entrada</string>
<string name="autofill_save_search_info_title">Salvar informações de busca</string>
<string name="autofill_manual_selection_summary">Exibir opção para permitir que o usuário selecione a entrada do banco de dados</string>
<string name="autofill_manual_selection_title">Seleção manual</string>
<string name="autofill_inline_suggestions_summary">Tente exibir sugestões de preenchimento automático diretamente de um teclado compatível</string>
<string name="autofill_inline_suggestions_title">Sugestões em linha</string>
<string name="autofill_close_database_summary">Feche o banco de dados após uma seleção de preenchimento automático</string>
<string name="autofill_close_database_title">Fechar banco de dados</string>
<string name="enter">Enter</string>
<string name="backspace">← Deletar</string>
<string name="select_entry">Selecionar entrada</string>
<string name="back_to_previous_keyboard">Voltar ao teclado anterior</string>
<string name="custom_fields">Campos personalizados</string>
<string name="keyboard_previous_lock_summary">Retornar automaticamente para o teclado anterior depois de bloquear o banco de dados</string>
<string name="keyboard_previous_lock_title">Bloquear banco de dados</string>
<string name="keyboard_save_search_info_summary">Depois de compartilhar uma URL para o KeePassDX, quando uma entrada é selecionada, tente lembrar que a entrada para usos adicionais</string>
<string name="keyboard_save_search_info_title">Salvar informações compartilhadas</string>
<string name="templates">Modelos</string>
<string name="notification">Notificação</string>
<string name="templates_group_uuid_title">Grupo de modelos</string>
<string name="templates_group_enable_summary">Use modelos dinâmicos para preencher os campos de uma entrada</string>
<string name="templates_group_enable_title">Uso de modelos</string>
<string name="advanced_unlock_delete_all_key_warning">Apagar todas as chaves de cifragem relacionadas ao reconhecimento de desbloqueio avançado\?</string>
<string name="advanced_unlock_timeout">Tempo limite de desbloqueio avançado</string>
<string name="temp_advanced_unlock_timeout_summary">Duração do uso de desbloqueio avançado antes de excluir seu conteúdo</string>
<string name="temp_advanced_unlock_timeout_title">Expiração de desbloqueio avançado</string>
<string name="temp_advanced_unlock_enable_summary">Não armazene nenhum conteúdo cifrado para usar desbloqueio avançado</string>
<string name="temp_advanced_unlock_enable_title">Desbloqueio avançado temporário</string>
<string name="device_credential_unlock_enable_summary">Permite que você use a credencial do seu dispositivo para abrir o banco de dados</string>
<string name="device_credential_unlock_enable_title">Desbloqueio de credencial de dispositivo</string>
<string name="advanced_unlock_tap_delete">Toque para excluir as chaves de desbloqueio avançado</string>
<string name="content">Conteúdo</string>
<string name="autofill_select_entry">Selecione a entrada…</string>
</resources>

View File

@@ -24,26 +24,26 @@
<string name="add_entry">Adicionar entrada</string>
<string name="add_group">Adicionar grupo</string>
<string name="encryption_algorithm">Algoritmo de encriptação</string>
<string name="app_timeout">Tempo de espera da app</string>
<string name="app_timeout">Tempo de espera</string>
<string name="app_timeout_summary">Inatividade antes de bloquear a base de dados</string>
<string name="application">App</string>
<string name="menu_app_settings">Configurações do app</string>
<string name="application">Aplicação</string>
<string name="menu_app_settings">Configurações da aplicação</string>
<string name="brackets">Parênteses</string>
<string name="file_manager_install_description">Um gestor de ficheiros que aceita a ação intencional ACTION_CREATE_DOCUMENT e ACTION_OPEN_DOCUMENT é necessário para criar, abrir e gravar ficheiros de base de dados.</string>
<string name="file_manager_install_description">Um gestor de ficheiros que aceita a ação intencional ACTION_CREATE_DOCUMENT e ACTION_OPEN_DOCUMENT é necessário para criar, abrir e gravar ficheiros da base de dados.</string>
<string name="clipboard_cleared">Área de transferência limpa</string>
<string name="clipboard_error_title">Erro na área de transferência</string>
<string name="clipboard_error">Alguns aparelhos não deixam as apps usarem a área de transferência.</string>
<string name="clipboard_error">Alguns dispositivos não permitem que as aplicações usem a área de transferência.</string>
<string name="clipboard_error_clear">Não foi possível limpar a área de transferência</string>
<string name="clipboard_timeout">Tempo de espera da área de transferência</string>
<string name="clipboard_timeout_summary">Duração do armazenamento na área de transferência (se for suportado pelo seu aparelho)</string>
<string name="clipboard_timeout_summary">Duração do armazenamento na área de transferência (se for suportado pelo seu dispositivo)</string>
<string name="select_to_copy">Selecione para copiar %1$s para a área de transferência</string>
<string name="retrieving_db_key">A criar a chave da base de dados…</string>
<string name="database">Base de dados</string>
<string name="decrypting_db">A desencriptar o conteúdo da base de dados…</string>
<string name="default_checkbox">Utilizar como base de dados predefinida</string>
<string name="digits">Dígitos</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft é &lt;strong&gt;open source&lt;/strong&gt; e &lt;strong&gt;sem publicidade&lt;/strong&gt;.
\nÉ fornecido como está, sob a &lt;strong&gt;licença GPLv3&lt;/strong&gt;, sem qualquer garantia.</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft tem o <strong>código-fonte aberto</strong> e <strong>sem publicidade</strong>.
\nÉ fornecido como está, sob a <strong>licença GPLv3</strong>, sem qualquer garantia.</string>
<string name="select_database_file">Abrir uma base de dados existente</string>
<string name="entry_accessed">Acedido</string>
<string name="entry_cancel">Cancelar</string>
@@ -51,103 +51,103 @@
<string name="entry_confpassword">Confirmar palavra-passe</string>
<string name="entry_created">Criado</string>
<string name="entry_expires">Expira</string>
<string name="entry_keyfile">Ficheiro chave</string>
<string name="entry_modified">Modificado</string>
<string name="entry_keyfile">Ficheiro-chave</string>
<string name="entry_modified">Alterado</string>
<string name="entry_not_found">Não foi possível encontrar os dados da entrada.</string>
<string name="entry_password">Palavra-passe</string>
<string name="save">Guardar</string>
<string name="entry_title">Nome</string>
<string name="entry_title">Título</string>
<string name="entry_url">URL</string>
<string name="entry_user_name">Nome de utilizador</string>
<string name="error_arc4">A cifra de fluxo Arcfour não é suportada.</string>
<string name="error_can_not_handle_uri">Não pôde tratar esta URI no KeePassDX.</string>
<string name="error_can_not_handle_uri">Não foi possível processar esta URI no KeePassDX.</string>
<string name="error_file_not_create">Não foi possível criar o ficheiro</string>
<string name="error_invalid_db">Não foi possível ler o banco de dados.</string>
<string name="error_invalid_db">Não foi possível ler a base de dados.</string>
<string name="error_invalid_path">Certifique-se que o caminho é válido.</string>
<string name="error_no_name">Introduza um nome.</string>
<string name="error_nokeyfile">Selecione um ficheiro chave.</string>
<string name="error_out_of_memory">Falta de memória para carregar toda a base de dados.</string>
<string name="error_pass_gen_type">Pelo menos um tipo de geração de palavra-chave deve ser selecionado.</string>
<string name="error_nokeyfile">Selecione um ficheiro-chave.</string>
<string name="error_out_of_memory">Sem memória suficiente para carregar toda a base de dados.</string>
<string name="error_pass_gen_type">Tem de ser selecionado pelo menos um tipo de geração de palavra-chave.</string>
<string name="error_pass_match">As palavras-passe não coincidem.</string>
<string name="error_rounds_too_large">\"Número de rodadas\" é muito grande. Modificado para 2147483648.</string>
<string name="error_string_key">Um nome do campo é necessário para cada string.</string>
<string name="error_wrong_length">Digite um número inteiro positivo no campo \"Tamanho\".</string>
<string name="error_rounds_too_large">\"Rodadas de transformação\" é muito grande. Alterado para 2147483648.</string>
<string name="error_string_key">É necessário um nome de campo para cada cadeia.</string>
<string name="error_wrong_length">Digite um número inteiro positivo no campo \"Comprimento\".</string>
<string name="field_name">Nome do campo</string>
<string name="field_value">Valor do campo</string>
<string name="file_not_found_content">Ficheiro não encontrado. Tente reabrí-lo de seu provedor de conteúdo.</string>
<string name="file_not_found_content">Não foi possível encontrar o ficheiro. Tente reabri-lo no seu navegador de ficheiros.</string>
<string name="file_browser">Gestor de ficheiros</string>
<string name="generate_password">Gerar palavra-chave</string>
<string name="generate_password">Gerar palavra-passe</string>
<string name="hint_conf_pass">Confirmar a palavra-passe</string>
<string name="hint_generated_password">Palavra-chave gerada</string>
<string name="hint_generated_password">Palavra-passe gerada</string>
<string name="hint_group_name">Nome do grupo</string>
<string name="hint_keyfile">Ficheiro-chave</string>
<string name="hint_length">Comprimento</string>
<string name="hint_pass">Palavra-passe</string>
<string name="password">Palavra-chave</string>
<string name="password">Palavra-passe</string>
<string name="invalid_credentials">Não foi possível ler as credenciais.</string>
<string name="invalid_algorithm">Algoritmo errado.</string>
<string name="invalid_db_sig">Não pôde reconhecer formato da base de dados.</string>
<string name="invalid_db_sig">Não foi possível reconhecer o formato da base de dados.</string>
<string name="keyfile_is_empty">O ficheiro-chave está vazio.</string>
<string name="length">Comprimento</string>
<string name="list_size_title">Tamanho da lista de grupos</string>
<string name="list_size_summary">Tamanho do texto na lista de grupos</string>
<string name="loading_database">A carregar base de dados…</string>
<string name="loading_database">A carregar a base de dados…</string>
<string name="lowercase">Minúsculas</string>
<string name="hide_password_title">Esconder palavras-passe</string>
<string name="hide_password_title">Ocultar palavras-passe</string>
<string name="hide_password_summary">Mascarar palavras-passe (***) por predefinição</string>
<string name="about">Sobre</string>
<string name="menu_change_key_settings">Alterar chave mestre</string>
<string name="menu_change_key_settings">Alterar chave mestra</string>
<string name="settings">Configurações</string>
<string name="menu_database_settings">Definições da base de dados</string>
<string name="menu_database_settings">Configurações da base de dados</string>
<string name="menu_delete">Eliminar</string>
<string name="menu_donate">Doar</string>
<string name="menu_donate">Donativos</string>
<string name="menu_edit">Editar</string>
<string name="menu_hide_password">Ocultar palavra-chave</string>
<string name="menu_lock">Trancar base de dados</string>
<string name="menu_lock">Bloquear base de dados</string>
<string name="menu_open">Abrir</string>
<string name="menu_search">Pesquisar</string>
<string name="menu_showpass">Mostrar palavra-chave</string>
<string name="menu_showpass">Mostrar palavra-passe</string>
<string name="menu_url">Ir para o URL</string>
<string name="minus">Menos</string>
<string name="never">Nunca</string>
<string name="no_results">A pesquisa não obteve resultados</string>
<string name="no_url_handler">Instale um navegador para abrir esta URL.</string>
<string name="omit_backup_search_title">Não procurar por entradas no backup ou na lixeira</string>
<string name="omit_backup_search_summary">Omite os grupos \"Backup\" e \"Cesto da reciclagem\" dos resultados da busca</string>
<string name="omit_backup_search_title">Não procurar por entradas na cópia de segurança e lixo</string>
<string name="omit_backup_search_summary">Omite os grupos \"Cópia de segurança\" e \"Caixote da reciclagem\" dos resultados da busca</string>
<string name="progress_create">A criar nova base de dados…</string>
<string name="progress_title">Em funcionamento…</string>
<string name="protection">Proteção</string>
<string name="read_only">Apenas leitura</string>
<string name="read_only_warning">KeePassDX precisa de permissões de escrita para poder mudar qualquer coisa no seu banco.</string>
<string name="read_only_warning">Dependendo do seu gestor de ficheiros, o KeePassDX pode não ter permissão de escrita no armazenamento.</string>
<string name="content_description_remove_from_list">Remover</string>
<string name="root">Raiz</string>
<string name="rounds">Rodadas de criptografia</string>
<string name="rounds_explanation">Rodadas adicionais de criptografia adicionam mais proteção contra ataques de força bruta, mas podem tornar o processo de carregar e gravar mais lentos.</string>
<string name="saving_database">A gravar a base de dados…</string>
<string name="rounds">Rodadas de transformação</string>
<string name="rounds_explanation">As rodadas adicionais de encriptação fornecem mais proteção contra ataques de força bruta, mas podem tornar o processo de carregar e guardar mais lentos.</string>
<string name="saving_database">A guardar a base de dados…</string>
<string name="space">Espaço</string>
<string name="search_label">Pesquisar</string>
<string name="sort_db">Ordenação natural</string>
<string name="special">Especiais</string>
<string name="search">Título/descrição da entrada</string>
<string name="search">Pesquisar</string>
<string name="search_results">Resultados da pesquisa</string>
<string name="underline">Sublinhado</string>
<string name="unsupported_db_version">Versão da base de dados não suportada.</string>
<string name="uppercase">Maiúsculas</string>
<string name="warning">Aviso</string>
<string name="warning_password_encoding">Evite caracteres fora do formato de codificação do ficheiro do banco (todos os caracteres não reconhecidos são convertidos para a mesma letra).</string>
<string name="warning_password_encoding">Evite caracteres fora do formato de codificação do ficheiro da base de dados (todos os caracteres não reconhecidos são convertidos para a mesma letra).</string>
<string name="version_label">Versão %1$s</string>
<string name="education_unlock_summary">Entre com a palavra-passe e/ou com o caminho para o ficheiro-chave da base de dados.
\n
\nGuarde uma cópia do seu ficheiro do banco num lugar mais seguro depois de cada alteração.</string>
<string name="education_unlock_summary">Introduza a palavra-passe e/ou com o caminho para o ficheiro-chave da base de dados.
\n
\nGuarde uma cópia de segurança do ficheiro da sua base de dados num lugar seguro depois de cada alteração.</string>
<string-array name="list_size_options">
<item>Pequena</item>
<item>Média</item>
<item>Grande</item>
</string-array>
<string name="extended_ASCII">ASCII Extendido</string>
<string name="extended_ASCII">ASCII estendido</string>
<string name="allow">Permitir</string>
<string name="error_load_database">Não foi possível abrir a sua base de dados.</string>
<string name="error_load_database_KDF_memory">Não foi possível carregar a chave. Tente descarregar o \"Uso de Memória\" do KDF.</string>
<string name="error_load_database_KDF_memory">Não foi possível carregar a chave. Tente diminuir o \"Uso de memória\" do KDF.</string>
<string name="list_entries_show_username_title">Mostrar nomes de utilizador</string>
<string name="copy_field">Cópia de %1$s</string>
<string name="menu_form_filling_settings">Preenchimento de formulário</string>
@@ -155,25 +155,25 @@
<string name="menu_move">Mover</string>
<string name="menu_paste">Colar</string>
<string name="menu_cancel">Cancelar</string>
<string name="menu_file_selection_read_only">Protegido contra escrita</string>
<string name="menu_open_file_read_and_write">Pode ser modificado</string>
<string name="menu_file_selection_read_only">Apenas leitura</string>
<string name="menu_open_file_read_and_write">Alterável</string>
<string name="create_keepass_file">Criar base de dados</string>
<string name="kdf_explanation">Para gerar uma chave para o algoritmo de encriptação, a chave mestre comprimida (SHA-256) é transformada usando uma função de derivação de chave (com um salt aleatório).</string>
<string name="kdf_explanation">Para gerar a chave para o algoritmo de encriptação, a chave mestra é transformada usando uma função de derivação de chave com um salt aleatório.</string>
<string name="memory_usage">Uso de memória</string>
<string name="memory_usage_explanation">Quantidade de memória a ser usada pela função de derivação de chave.</string>
<string name="parallelism">Paralelismo</string>
<string name="parallelism_explanation">Grau de paralelismo (ou seja, número de threads) usado pela função de derivação de chave.</string>
<string name="sort_menu">Ordenar</string>
<string name="sort_ascending">Ascendente</string>
<string name="sort_ascending">Mais baixo primeiro ↓</string>
<string name="sort_groups_before">Grupos primeiro</string>
<string name="sort_recycle_bin_bottom">Cesto da reciclagem no fundo</string>
<string name="sort_recycle_bin_bottom">Caixote da reciclagem no fundo</string>
<string name="sort_title">Título</string>
<string name="sort_username">Nome de utilizador</string>
<string name="sort_creation_time">Data de criação</string>
<string name="sort_last_modify_time">Última modificação</string>
<string name="sort_last_modify_time">Última alteração</string>
<string name="sort_last_access_time">Último acesso</string>
<string name="warning_empty_password">Continuar sem proteção de desbloqueio por palavra-passe\?</string>
<string name="warning_no_encryption_key">Continuar sem a chave de criptografia\?</string>
<string name="warning_no_encryption_key">Continuar sem a chave de encriptação\?</string>
<string name="build_label">Compilação %1$s</string>
<string name="encrypted_value_stored">Palavra-passe encriptada armazenada</string>
<string name="no_credentials_stored">Ainda não há nenhuma palavra-chave armazenada nesta base de dados.</string>
@@ -181,107 +181,105 @@
<string name="menu_appearance_settings">Aparência</string>
<string name="general">Geral</string>
<string name="autofill">Preenchimento automático</string>
<string name="autofill_service_name">Serviço de Preenchimento Automático do KeePassDX</string>
<string name="autofill_sign_in_prompt">Entrar com KeePassDX</string>
<string name="autofill_service_name">Serviço de preenchimento automático do KeePassDX</string>
<string name="autofill_sign_in_prompt">Iniciar sessão com KeePassDX</string>
<string name="set_autofill_service_title">Definir como serviço de preenchimento automático predefinido</string>
<string name="autofill_explanation_summary">Ativar o serviço para preencher formulários em outras aplicações</string>
<string name="password_size_title">Tamanho da palavra-chave gerada</string>
<string name="autofill_explanation_summary">Ative o serviço de preencher automático para preencher formulários noutras aplicações</string>
<string name="password_size_title">Tamanho da palavra-passe gerada</string>
<string name="edit_entry">Editar entrada</string>
<string name="encryption">Encriptação</string>
<string name="key_derivation_function">Função de derivação de chave</string>
<string name="error_autofill_enable_service">Não pôde ser ativado o serviço de preenchimento automático.</string>
<string name="error_autofill_enable_service">Não foi possível ativar o serviço de preenchimento automático.</string>
<string name="encryption_explanation">Algoritmo de encriptação usado para todos os dados.</string>
<string name="password_size_summary">Define o tamanho predefinido para palavras-passe geradas</string>
<string name="list_password_generator_options_title">Caracteres da palavra-passe</string>
<string name="list_password_generator_options_summary">Definir os caracteres permitodos para o gerador de palavra-passe</string>
<string name="password_size_summary">Define o tamanho predefinido para as palavras-passe geradas</string>
<string name="list_password_generator_options_title">Caracteres das palavras-passe</string>
<string name="list_password_generator_options_summary">Definir os caracteres permitidos para o gerador de palavras-passe</string>
<string name="clipboard_notifications_title">Notificações da área de transferência</string>
<string name="clipboard_notifications_summary">Mostrar notificações de área de transferência para copiar campos ao visualizar uma entrada</string>
<string name="clipboard_notifications_summary">Mostrar notificações da área de transferência para copiar campos ao visualizar uma entrada</string>
<string name="lock">Bloquear</string>
<string name="lock_database_screen_off_title">Bloqueio de ecrã</string>
<string name="lock_database_screen_off_summary">Bloqueie a base de dados quando o ecrã estiver desligado</string>
<string name="unavailable_feature_text">Não foi possível iniciar esse recurso.</string>
<string name="unavailable_feature_version">O aparelho está a executar Android %1$s, mas precisa de %2$s ou posterior.</string>
<string name="lock_database_screen_off_summary">Bloquear a base de dados após alguns segundos após o ecrã estar desligado</string>
<string name="unavailable_feature_text">Não foi possível iniciar esta funcionalidade.</string>
<string name="unavailable_feature_version">O dispositivo está a usar o Android %1$s, mas precisa do %2$s ou posterior.</string>
<string name="unavailable_feature_hardware">Não foi possível encontrar o hardware correspondente.</string>
<string name="file_name">Nome do ficheiro</string>
<string name="path">Caminho</string>
<string name="assign_master_key">Defina uma chave mestre</string>
<string name="recycle_bin_title">Usar cesto da reciclagem</string>
<string name="recycle_bin_summary">Move grupos e entradas para o \"Cesto da reciclagem\" antes de apagar</string>
<string name="monospace_font_fields_enable_title">Fonte do Campo</string>
<string name="monospace_font_fields_enable_summary">Muda a fonte usada nos campos para melhor visibilidade dos caracteres</string>
<string name="allow_copy_password_title">Confiança da área de transferência</string>
<string name="allow_copy_password_summary">Permite copiar a palavra-passe e campos protegidos à área de transferência</string>
<string name="assign_master_key">Atribuir uma chave mestra</string>
<string name="recycle_bin_title">Utilização do caixote da reciclagem</string>
<string name="recycle_bin_summary">Move grupos e entradas para o \"Caixote da reciclagem\" antes de eliminar</string>
<string name="monospace_font_fields_enable_title">Tipo de letra nos campos</string>
<string name="monospace_font_fields_enable_summary">Muda a fonte tipográfica usada nos campos de dados para melhor visibilidade dos caracteres</string>
<string name="allow_copy_password_title">Confiança na área de transferência</string>
<string name="allow_copy_password_summary">Permite copiar a palavra-passe e campos protegidos para a área de transferência</string>
<string name="database_name_title">Nome da base de dados</string>
<string name="database_description_title">Descrição da base de dados</string>
<string name="database_version_title">Versão da base de dados</string>
<string name="text_appearance">Texto</string>
<string name="application_appearance">App</string>
<string name="application_appearance">Interface</string>
<string name="other">Outros</string>
<string name="keyboard">Teclado</string>
<string name="magic_keyboard_title">Magikeyboard</string>
<string name="magic_keyboard_explanation_summary">Ative um teclado customizado, populando suas palavras-passe e todos os campos de identidade</string>
<string name="reset_education_screens_title">Reiniciar dicas educacionais</string>
<string name="reset_education_screens_summary">Exibir todas as informações educacionais novamente</string>
<string name="reset_education_screens_text">Dicas educacionais redefinidas</string>
<string name="education_create_database_title">Crie um ficheiro de base de dados</string>
<string name="magic_keyboard_explanation_summary">Ative um teclado personalizado para as suas palavras-passe e todos os campos de identidade</string>
<string name="reset_education_screens_title">Reiniciar as dicas</string>
<string name="reset_education_screens_summary">Mostrar todas as dicas novamente</string>
<string name="reset_education_screens_text">Dicas repostas</string>
<string name="education_create_database_title">Criar um ficheiro da base de dados</string>
<string name="education_create_database_summary">Crie o seu primeiro ficheiro de gestão de palavras-passe.</string>
<string name="education_select_database_title">Abra uma base de dados existente</string>
<string name="education_select_database_summary">Abra a sua base de dados de mais cedo pelo seu navegador de ficheiros.</string>
<string name="education_new_node_title">Adicione itens ao seu banco</string>
<string name="education_new_node_summary">Entradas ajudam a gerir as suas identidades digitais.
\n
\nGrupos (~pastas) organizam as suas entradas na sua base de dados.</string>
<string name="education_search_title">Pesquise suas entradas</string>
<string name="education_search_summary">Entre com título, nome de utilizador ou outros campos para recuperar facilmente as suas palavras-passe.</string>
<string name="education_entry_edit_title">Modifique a entrada</string>
<string name="education_select_database_title">Abrir uma base de dados existente</string>
<string name="education_select_database_summary">Abra a sua base de dados anterior no navegador de ficheiros para continuar a usá-la.</string>
<string name="education_new_node_title">Adicionar itens à base de dados</string>
<string name="education_new_node_summary">As entradas ajudam a gerir as suas identidades digitais.
\n
\nOs grupos (~pastas) organizam as suas entradas na base de dados.</string>
<string name="education_search_title">Pesquisar nas entradas</string>
<string name="education_search_summary">Digite o título, nome de utilizador ou outros campos para recuperar facilmente as suas palavras-passe.</string>
<string name="education_entry_edit_title">Editar a entrada</string>
<string name="education_entry_edit_summary">Edite a sua entrada com campos personalizados. Os conjuntos de dados podem ser referenciados entre campos de entradas diferentes.</string>
<string name="education_generate_password_title">Crie uma palavra-passe forte</string>
<string name="education_generate_password_summary">Gere uma palavra-passe forte para associar a sua entrada, defina-a facilmente de acordo com os critérios do formulário e não se esqueça de torná-la segura.</string>
<string name="education_entry_new_field_title">Adicione campos customizados</string>
<string name="education_entry_new_field_summary">Registe um campo adicional, acrescente um valor e proteja-o opcionalmente.</string>
<string name="education_unlock_title">Desbloqueie a sua base de dados</string>
<string name="education_generate_password_title">Criar uma palavra-passe forte</string>
<string name="education_generate_password_summary">Crie uma palavra-passe forte para associar à sua entrada, defina-a facilmente de acordo com os critérios do formulário e não se esqueça de torná-la segura.</string>
<string name="education_entry_new_field_title">Adicionar campos personalizados</string>
<string name="education_entry_new_field_summary">Registe um campo adicional, adicione um valor e proteja-o opcionalmente.</string>
<string name="education_unlock_title">Desbloquear a base de dados</string>
<string name="education_field_copy_title">Copiar um campo</string>
<string name="education_field_copy_summary">Campos copiados podem ser colados em qualquer lugar.
\n
\nUse a forma de preenchimento de formulário que preferir.</string>
<string name="education_lock_title">Bloqueie a base de dados</string>
<string name="education_lock_summary">Bloqueie a sua base de dados rapidamente, pode parametrizar a app para bloqueá-lo depois de um tempo, e quando o ecrã se apaga.</string>
<string name="education_field_copy_summary">Os campos copiados podem ser colados em qualquer lugar.
\n
\nUse o método de preenchimento de formulário que preferir.</string>
<string name="education_lock_title">Bloquear a base de dados</string>
<string name="education_lock_summary">Bloqueie a sua base de dados rapidamente. Pode configurar a aplicação para bloqueá-la após um tempo e quando o ecrã se desliga.</string>
<string name="education_sort_title">Ordenação de itens</string>
<string name="education_sort_summary">Escolha como entradas e grupos são ordenadas.</string>
<string name="education_sort_summary">Escolha como são ordenadas as entradas e os grupos.</string>
<string name="education_donation_title">Participar</string>
<string name="education_donation_summary">Ajude a aumentar a estabilidade, segurança e na adição de mais recursos.</string>
<string name="html_text_ad_free">Ao contrário de muitas apps de gestão de palavras-passe, esta app é &lt;strong&gt;livre de anúncios&lt;/strong&gt;, é &lt;strong&gt;software livre copyleft&lt;/strong&gt; e não coleta dados pessoais nos servidores dela, mesmo na sua versão gratuita.</string>
<string name="html_text_buy_pro">Ao comprar a versão pro, terá acesso a este &lt;strong&gt;recurso visual&lt;/strong&gt; e ajudará especialmente a &lt;strong&gt;realizar projetos comunitários.&lt;/strong&gt;</string>
<string name="education_donation_summary">Ajude a aumentar a estabilidade, segurança e novas funcionalidades.</string>
<string name="html_text_ad_free">Ao contrário de muitas aplicações de gestão de palavras-passe, esta aplicação <strong>não tem anúncios</strong>, é <strong>um programa de código-fonte livre</strong> e não recolhe dados pessoais para os servidores dela, seja qual for a versão que utiliza.</string>
<string name="html_text_buy_pro">Ao comprar a versão pro, terá acesso a este <strong>estilo visual</strong> e ajudará especialmente a <strong>realizar projetos comunitários.</strong></string>
<string name="html_text_feature_generosity">Este &lt;strong&gt;estilo visual&lt;/strong&gt; está disponível graças à sua generosidade.</string>
<string name="html_text_donation">Para manter a nossa liberdade e estarmos sempre ativos, nós contamos com a sua &lt;strong&gt;contribuição.&lt;/strong&gt;
</string>
<string name="html_text_dev_feature">Esse recurso está &lt;strong&gt;em desenvolvimento&lt;/strong&gt; e exige que sua &lt;strong&gt;contribuição&lt;/strong&gt; para que esteja disponível em breve.</string>
<string name="html_text_donation">Para manter a nossa liberdade e estarmos sempre ativos, contamos com a sua <strong>contribuição.</strong></string>
<string name="html_text_dev_feature">Esta funcionalidade está <strong>em desenvolvimento</strong> e necessita da sua <strong>contribuição</strong> para que esteja disponível brevemente.</string>
<string name="html_text_dev_feature_buy_pro">Ao comprar a versão &lt;strong&gt;pro&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_contibute">
&lt;strong&gt;Contribuindo &lt;/strong&gt;,</string>
<string name="html_text_dev_feature_encourage">está a incentivar os programadores a criar &lt;strong&gt;novos recursos&lt;/strong&gt; e a &lt;strong&gt;corrigir erros &lt;/strong&gt; de acordo com as suas observações.</string>
<string name="html_text_dev_feature_thanks">Obrigado por sua contribuição.</string>
<string name="html_text_dev_feature_work_hard">Estamos trabalhando duro para lançar esse recurso o mais rápido possível.</string>
<string name="html_text_dev_feature_upgrade">Lembre-se de manter o sua app atualizada, instalando novas versões.</string>
<string name="html_text_dev_feature_contibute">Ao <strong>contribuir</strong>,</string>
<string name="html_text_dev_feature_encourage">está a incentivar os programadores a adicionar <strong>novas funcionalidades</strong> e a <strong>corrigir erros</strong> reportados pelos utilizadores.</string>
<string name="html_text_dev_feature_thanks">Obrigado pela sua contribuição.</string>
<string name="html_text_dev_feature_work_hard">Estamos a trabalhar para lançar esta funcionalidade o mais rápido possível.</string>
<string name="html_text_dev_feature_upgrade">Lembre-se de manter a sua aplicação atualizada, instalando novas versões.</string>
<string name="download">Descarregar</string>
<string name="contribute">Contribuir</string>
<string name="style_choose_title">Tema da app</string>
<string name="style_choose_summary">Tema usado na app</string>
<string name="style_choose_title">Tema da aplicação</string>
<string name="style_choose_summary">Tema usado na aplicação</string>
<string name="icon_pack_choose_title">Pacote de ícones</string>
<string name="icon_pack_choose_summary">Pacote de ícones usado na app</string>
<string name="clipboard_warning">Se a limpeza da área de transferência falhar, limpe seu histórico manualmente.</string>
<string name="allow_copy_password_warning">Aviso: A área de transferência é compartilhada por todas as apps. Se dados sensíveis forem copiados, outros programas podem recuperá-lo.</string>
<string name="icon_pack_choose_summary">Pacote de ícones usado na aplicação</string>
<string name="clipboard_warning">Se a limpeza da área de transferência falhar, limpe o histórico desta manualmente.</string>
<string name="allow_copy_password_warning">Aviso: a área de transferência é partilhada por todas as aplicações. Se forem copiados dados sensíveis, os outros programas podem ler esses dados.</string>
<string name="allow_no_password_title">Não permitir chave mestra</string>
<string name="allow_no_password_summary">Permite tocar no botão \"Abrir\" se nenhumas credenciais estiverem selecionadas</string>
<string name="allow_no_password_summary">Permite tocar no botão \"Abrir\" se não estiverem selecionadas nenhumas credenciais</string>
<string name="enable_education_screens_title">Dicas educacionais</string>
<string name="enable_education_screens_summary">Destacar elementos para aprender como a app funciona</string>
<string name="enable_education_screens_summary">Destacar elementos para saber como a aplicação funciona</string>
<string name="enable_read_only_title">Apenas leitura</string>
<string name="enable_read_only_summary">Abrir a base de dados somente leitura por defeito</string>
<string name="education_read_only_title">Proteja seu banco de modificações</string>
<string name="education_read_only_summary">Altere o modo de abertura para a sessão.
\n
\n\"Somente leitura\" evita que faça alterações não intencionais na base de dados.
\n\"Gravação\" permite-o adicionar, apagar ou modificar todos os elementos.</string>
<string name="enable_read_only_summary">Abrir a base de dados com permissão de apenas leitura por predefinição</string>
<string name="education_read_only_title">Proteger a base de dados contra alterações</string>
<string name="education_read_only_summary">Altere o modo de abertura para a sessão.
\n
\n\"Apenas leitura\" evita que faça alterações não intencionais na base de dados.
\n\"Alterável\" permite adicionar, eliminar ou alterar todos os elementos.</string>
<string name="list_entries_show_username_summary">Mostrar nomes de utilizador na lista entradas</string>
<string name="clipboard">Área de transferência</string>
<string name="keyboard_name">Magikeyboard</string>
@@ -296,31 +294,31 @@
<string name="keyboard_notification_entry_content_title">%1$s disponível no Magikeyboard</string>
<string name="keyboard_notification_entry_content_text">%1$s</string>
<string name="keyboard_notification_entry_clear_close_title">Limpar ao fechar</string>
<string name="keyboard_notification_entry_clear_close_summary">Fecha a base de dados ao dispensar a notificação</string>
<string name="keyboard_notification_entry_clear_close_summary">Fecha a base de dados ao fechar a notificação</string>
<string name="keyboard_appearance_category">Aparência</string>
<string name="keyboard_theme_title">Tema do teclado</string>
<string name="keyboard_keys_category">Teclas</string>
<string name="keyboard_key_vibrate_title">Pressão de chaves vibratórias</string>
<string name="keyboard_key_vibrate_title">Vibrar ao pressionar teclas</string>
<string name="keyboard_key_sound_title">Som ao pressionar teclas</string>
<string name="selection_mode">Modo de seleção</string>
<string name="do_not_kill_app">Não mate a app</string>
<string name="do_not_kill_app">Não feche a aplicação</string>
<string name="lock_database_back_root_title">Pressione \'Voltar\' para bloquear</string>
<string name="lock_database_back_root_summary">Tranca a base de dados quando o utilizador pressiona o botão voltar no ecrã inicial</string>
<string name="clear_clipboard_notification_title">Limpar ao fechar</string>
<string name="clear_clipboard_notification_summary">Bloquear a base de dados quando a duração da área de transferência expirar ou quando a notificação for fechada depois de começar a utilizá-la</string>
<string name="recycle_bin">Cesto da reciclagem</string>
<string name="recycle_bin">Caixote da reciclagem</string>
<string name="keyboard_selection_entry_title">Seleção de entrada</string>
<string name="keyboard_selection_entry_summary">Mostrar campos de entrada no Magikeyboard quando estiver visualizando uma Entrada</string>
<string name="delete_entered_password_title">Deletar palavra-passe</string>
<string name="delete_entered_password_summary">Apaga a palavra-passe inserida após uma tentativa de conexão</string>
<string name="keyboard_selection_entry_summary">Ao ver uma entrada no KeePassDX, preencher o Magikeyboard com essa entrada</string>
<string name="delete_entered_password_title">Eliminar palavra-passe</string>
<string name="delete_entered_password_summary">Eliminar a palavra-passe inserida após uma tentativa de conexão a uma base de dados</string>
<string name="content_description_open_file">Abrir ficheiro</string>
<string name="content_description_node_children">Crianças do nó</string>
<string name="content_description_add_node">Inserir nó</string>
<string name="content_description_node_children">Nó filho</string>
<string name="content_description_add_node">Adicionar nó</string>
<string name="content_description_add_entry">Adicionar entrada</string>
<string name="content_description_add_group">Adicionar grupo</string>
<string name="content_description_file_information">Informações sobre ficheiro</string>
<string name="content_description_password_checkbox">Caixa de seleção da palavra-passe</string>
<string name="content_description_keyfile_checkbox">Caixa de seleção keyfile</string>
<string name="content_description_keyfile_checkbox">Caixa de seleção do ficheiro-chave</string>
<string name="content_description_repeat_toggle_password_visibility">Repetir alternar a visibilidade da palavra-passe</string>
<string name="content_description_entry_icon">Ícone da entrada</string>
<string name="entry_password_generator">Gerador de palavras-passe</string>
@@ -328,30 +326,30 @@
<string name="entry_add_field">Adicionar campo</string>
<string name="content_description_remove_field">Remover campo</string>
<string name="entry_UUID">UUID</string>
<string name="error_move_entry_here">Não pode mover uma entrada para .</string>
<string name="error_copy_entry_here">Não pode copiar uma entrada aqui.</string>
<string name="error_move_entry_here">Não se pode mover uma entrada para aqui.</string>
<string name="error_copy_entry_here">Não se pode copiar uma entrada aqui.</string>
<string name="list_groups_show_number_entries_title">Mostrar número de entradas</string>
<string name="list_groups_show_number_entries_summary">Mostrar o número de entradas dentro de um grupo</string>
<string name="database_custom_color_title">Cor personalizada da base de dados</string>
<string name="database_data_compression_summary">A compressão de dados reduz o tamanho da base de dados</string>
<string name="biometric_unlock_enable_summary">Permite que escaneie o seu biométrico para abrir a base de dados</string>
<string name="advanced_unlock_explanation_summary">Usar desbloqueamento avançado para abrir a base de dados mais facilmente</string>
<string name="biometric_unlock_enable_summary">Permite que leia os seus dados biométricos para abrir a base de dados</string>
<string name="advanced_unlock_explanation_summary">Usar desbloqueio avançado para abrir a base de dados mais facilmente</string>
<string name="database_opened">Base de dados aberta</string>
<string name="contains_duplicate_uuid">A base de dados contém UUIDs duplicados.</string>
<string name="menu_save_database">Gravar base de dados</string>
<string name="menu_save_database">Guardar base de dados</string>
<string name="creating_database">A criar a base de dados…</string>
<string name="error_save_database">Não foi possível gravar a base de dados.</string>
<string name="error_create_database_file">Impossível de criar uma base de dados com essa palavra-passe e ficheiro-chave.</string>
<string name="error_label_exists">Este rótulo já existe.</string>
<string name="autofill_block_restart">Reinicie a app que contém o formulário para ativar o bloqueio.</string>
<string name="error_save_database">Não foi possível guardar a base de dados.</string>
<string name="error_create_database_file">Não foi possível criar a base de dados com essa palavra-passe e ficheiro-chave.</string>
<string name="error_label_exists">Esta etiqueta já existe.</string>
<string name="autofill_block_restart">Reinicie a aplicação que contém o formulário para ativar o bloqueio.</string>
<string name="autofill_block">Bloquear preenchimento automático</string>
<string name="autofill_web_domain_blocklist_summary">Lista de bloqueio que impede o preenchimento automático de domínios da web</string>
<string name="autofill_web_domain_blocklist_title">Lista de bloqueio de domínio da web</string>
<string name="autofill_application_id_blocklist_summary">Lista de bloqueio que impede o preenchimento automático de apps</string>
<string name="autofill_web_domain_blocklist_summary">Lista de domínios da web bloqueados sem permissão de preenchimento automático</string>
<string name="autofill_web_domain_blocklist_title">Lista de bloqueio de domínios da web</string>
<string name="autofill_application_id_blocklist_summary">Lista de aplicações bloqueadas sem permissão de preenchimento automático</string>
<string name="autofill_application_id_blocklist_title">Lista de bloqueio de aplicações</string>
<string name="autofill_auto_search_summary">Sugerir resultados de pesquisa automaticamente do domínio da web ou do ID da aplicação</string>
<string name="keyboard_previous_fill_in_summary">Voltar automaticamente para o teclado anterior depois de executar a ação da tecla automática</string>
<string name="keyboard_previous_fill_in_title">Ação de tecla automática</string>
<string name="keyboard_previous_fill_in_summary">Mudar automaticamente para o teclado anterior depois de executar a \"tecla automática\"</string>
<string name="keyboard_previous_fill_in_title">Ação da tecla automática</string>
<string name="keyboard_previous_database_credentials_summary">Voltar automaticamente para o teclado anterior no ecrã de credenciais da base de dados</string>
<string name="keyboard_previous_database_credentials_title">Ecrã de credenciais da base de dados</string>
<string name="keyboard_change">Mudar de teclado</string>
@@ -361,145 +359,245 @@
<string name="subdomain_search_title">Pesquisa de subdomínios</string>
<string name="error_string_type">Este texto não corresponde ao item solicitado.</string>
<string name="content_description_add_item">Adicionar item</string>
<string name="error_otp_digits">O token deve conter de %1$d até %2$d dígitos.</string>
<string name="error_otp_digits">O token tem de ter entre %1$d e %2$d dígitos.</string>
<string name="max_history_items_title">Número máximo</string>
<string name="warning_permanently_delete_nodes">Apagar permanentemente os nós selecionados\?</string>
<string name="warning_permanently_delete_nodes">Eliminar permanentemente os nós selecionados\?</string>
<string name="max_history_size_title">Tamanho máximo</string>
<string name="recycle_bin_group_title">Grupo de cesto da reciclagem</string>
<string name="recycle_bin_group_title">Grupo do caixote da reciclagem</string>
<string name="otp_secret">Segredo</string>
<string name="keyboard_auto_go_action_summary">Ação da tecla \"Go\" após pressionar a tecla \"Field\"</string>
<string name="keyboard_auto_go_action_summary">Ação da tecla \"Ir\" após pressionar a tecla \"Campo\"</string>
<string name="otp_type">Tipo do OTP</string>
<string name="entry_add_attachment">Adicionar anexo</string>
<string name="education_setup_OTP_title">Configurar OTP</string>
<string name="education_setup_OTP_title">Configurar o OTP</string>
<string name="compression">Compressão</string>
<string name="validate">Validação</string>
<string name="remember_keyfile_locations_summary">Mantém o controle sobre onde os ficheiros de chaves são armazenados</string>
<string name="validate">Validar</string>
<string name="remember_keyfile_locations_summary">Mantém um registo dos locais onde os ficheiros-chave são armazenados</string>
<string name="entry_history">Histórico</string>
<string name="error_otp_period">O período deve estar entre %1$d e %2$d segundos.</string>
<string name="master_key">Chave Mestre</string>
<string name="settings_database_recommend_changing_master_key_summary">Recomendar mudança da chave mestre (em dias)</string>
<string name="error_otp_period">O período tem de estar entre %1$d e %2$d segundos.</string>
<string name="master_key">Chave mestra</string>
<string name="settings_database_recommend_changing_master_key_summary">Recomendar alteração da chave mestra (em dias)</string>
<string name="remember_database_locations_title">Lembrar locais das bases de dados</string>
<string name="download_initialization">A inicializar…</string>
<string name="menu_security_settings">Configurações de segurança</string>
<string name="disable">Desativar</string>
<string name="lock_database_show_button_summary">Mostrar o botão de bloqueio na interface do utilizador</string>
<string name="lock_database_show_button_summary">Mostrar o botão de bloqeuar na interface do utilizador</string>
<string name="max_history_size_summary">Limitar o tamanho do histórico por entrada</string>
<string name="error_otp_secret_key">A chave secreta deve estar em formato Base32.</string>
<string name="error_otp_secret_key">A chave secreta tem de ser no formato Base32.</string>
<string name="enable">Ativar</string>
<string name="database_data_compression_title">Compressão dos dados</string>
<string name="html_about_contribution">Para &lt;strong&gt;manter a liberdade&lt;/strong&gt;, &lt;strong&gt;solucionar bugs&lt;/strong&gt;, &lt;strong&gt;adicionar funções&lt;/strong&gt; e &lt;strong&gt;para sermos sempre ativoa&lt;/strong&gt;, contamos com sua &lt;strong&gt;contribuição&lt;/strong&gt;.</string>
<string name="biometric_unlock_enable_title">Desbloqueio por biométrico</string>
<string name="database_data_compression_title">Compressão de dados</string>
<string name="html_about_contribution">Para <strong>manter a liberdade</strong>, <strong>corrigir erros</strong>, <strong>adicionar funcionalidades</strong> e <strong>para sermos sempre ativos</strong>, contamos com sua <strong>contribuição</strong>.</string>
<string name="biometric_unlock_enable_title">Desbloqueio biométrico</string>
<string name="entry_attachments">Anexos</string>
<string name="compression_gzip">Gzip</string>
<string name="discard">Descartar</string>
<string name="remember_database_locations_summary">Mantém o controle sobre onde os bancos de dados são armazenados</string>
<string name="remember_database_locations_summary">Mantém um registo dos locais onde as bases de dados são armazenadas</string>
<string name="auto_focus_search_summary">Solicitar uma pesquisa quando abrir a base de dados</string>
<string name="show_recent_files_summary">Lembrar nomes recentes de ficheiros</string>
<string name="show_recent_files_summary">Mostrar localizações de bases de dados recentes</string>
<string name="download_finalization">A finalizar…</string>
<string name="autofill_preference_title">Configurações de preenchimento automático</string>
<string name="max_history_items_summary">Limitar a quantidade de itens do histórico por entrada</string>
<string name="max_history_items_summary">Limitar a quantidade de itens no histórico por entrada</string>
<string name="download_complete">Completo!</string>
<string name="content_description_update_from_list">Atualizar</string>
<string name="contribution">Contribuição</string>
<string name="hide_broken_locations_summary">Esconder ligações quebradas na lista de bases de dados recentes</string>
<string name="hide_broken_locations_summary">Ocultar ligações quebradas na lista de bases de dados recentes</string>
<string name="download_attachment">Descarregar %1$s</string>
<string name="warning_database_read_only">Conceder acesso de gravação de ficheiro para gravar alterações na base de dados</string>
<string name="clipboard_explanation_summary">Copiar campos de entrada usando a área de transferência do seu aparelho</string>
<string name="warning_database_read_only">Conceda o acesso de gravação de ficheiros para guardar as alterações na base de dados</string>
<string name="clipboard_explanation_summary">Copiar campos de entrada usando a área de transferência do seu dispositivo</string>
<string name="otp_digits">Dígitos</string>
<string name="discard_changes">Descartar alterações\?</string>
<string name="keystore_not_accessible">A chave não foi propriamente inicializada.</string>
<string name="keystore_not_accessible">O armazém de chaves não foi propriamente inicializado.</string>
<string name="auto_focus_search_title">Pesquisa rápida</string>
<string name="biometric_delete_all_key_title">Apague chaves de encriptação</string>
<string name="biometric_delete_all_key_title">Eliminar chaves de encriptação</string>
<string name="invalid_db_same_uuid">%1$s com o mesmo UUID %2$s já existe.</string>
<string name="autofill_auto_search_title">Pesquisa automática</string>
<string name="settings_database_force_changing_master_key_summary">Forçar mudança de chave-mestre (em dias)</string>
<string name="settings_database_force_changing_master_key_summary">Forçar alteração da chave mestra (em dias)</string>
<string name="command_execution">A executar o comando…</string>
<string name="otp_algorithm">Algorítimo</string>
<string name="show_recent_files_title">Histórico de ficheiros recentes</string>
<string name="show_recent_files_title">Mostrar ficheiros recentes</string>
<string name="content_description_background">Plano de fundo</string>
<string name="lock_database_show_button_title">Mostrar botão de bloqueio</string>
<string name="lock_database_show_button_title">Mostrar botão de bloquear</string>
<string name="security">Segurança</string>
<string name="hide_broken_locations_title">Esconder ligações quebradas de bases de dados</string>
<string name="hide_broken_locations_title">Ocultar ligações quebradas de bases de dados</string>
<string name="content_description_keyboard_close_fields">Fechar campos</string>
<string name="biometric">Biométrico</string>
<string name="error_create_database">Incapaz de criar o ficheiro de base de dados.</string>
<string name="keyboard_search_share_summary">Procurar automaticamente pela informação compartilhada para popular o teclado</string>
<string name="error_otp_counter">O contador deve estar entre %1$d e %2$d.</string>
<string name="error_create_database">Não foi possível criar o ficheiro da base de dados.</string>
<string name="keyboard_search_share_summary">Ao partilhar um URL com o KeePassDX, filtrar as entradas usando esse domínio de URL</string>
<string name="error_otp_counter">O contador tem de estar entre %1$d e %2$d.</string>
<string name="otp_period">Período (segundos)</string>
<string name="device_keyboard_setting_title">Configurações do teclado do aparelho</string>
<string name="biometric_delete_all_key_summary">Apague todas as chaves de encriptação relacionadas ao reconhecimento de biométrico</string>
<string name="biometric_auto_open_prompt_summary">Pedir pelo biométrico automaticamente se a base de dados estiver configurada para usá-la</string>
<string name="warning_database_link_revoked">Acesso ao ficheiro revogado pelo gestor de ficheiros</string>
<string name="device_keyboard_setting_title">Configurações do teclado do dispositivo</string>
<string name="biometric_delete_all_key_summary">Eliminar todas as chaves de encriptação relacionadas com o desbloqueio de reconhecimento avançado</string>
<string name="biometric_auto_open_prompt_summary">Pedir automaticamente o desbloqueio avançado se a base de dados estiver configurada para usá-lo</string>
<string name="warning_database_link_revoked">O acesso ao ficheiro foi revogado pelo gestor de ficheiros</string>
<string name="error_invalid_OTP">Segredo OTP inválido.</string>
<string name="contact">Contato</string>
<string name="contact">Contacto</string>
<string name="otp_counter">Contador</string>
<string name="menu_restore_entry_history">Restaurar histórico</string>
<string name="entry_otp">OTP</string>
<string name="compression_none">Nenhum</string>
<string name="enable_auto_save_database_summary">Gravar a base de dados automaticamente depois de uma ação importante (somente no modo \"Modificável\")</string>
<string name="error_copy_group_here">Não pode copiar um grupo aqui.</string>
<string name="menu_delete_entry_history">Apagar histórico</string>
<string name="error_disallow_no_credentials">Ao menos uma credencial deve ser definida.</string>
<string name="compression_none">Nenhuma</string>
<string name="enable_auto_save_database_summary">Guardar a base de dados automaticamente depois de uma ação importante (apenas no modo \"Alterável\")</string>
<string name="error_copy_group_here">Não se pode copiar um grupo aqui.</string>
<string name="menu_delete_entry_history">Eliminar histórico</string>
<string name="error_disallow_no_credentials">Tem de ser definida pelo menos uma credencial.</string>
<string name="settings_database_force_changing_master_key_title">Forçar renovação</string>
<string name="enable_auto_save_database_title">Gravar a base de dados automaticamente</string>
<string name="keyboard_auto_go_action_title">Ação de chave automática</string>
<string name="enable_auto_save_database_title">Guardar automaticamente a base de dados</string>
<string name="keyboard_auto_go_action_title">Ação de tecla automática</string>
<string name="hide_expired_entries_title">Ocultar entradas expiradas</string>
<string name="hide_expired_entries_summary">As entradas expiradas não são mostradas</string>
<string name="menu_master_key_settings">Configurações da chave-mestre</string>
<string name="entry_setup_otp">Configurar OTP</string>
<string name="keyboard_search_share_title">Procurar informação compartilhada</string>
<string name="menu_empty_recycle_bin">Esvaziar cesto da reciclagem</string>
<string name="settings_database_force_changing_master_key_next_time_summary">Forçar mudança da chave-mestre na próxima vez (uma vez)</string>
<string name="contains_duplicate_uuid_procedure">Consertar o problema gerando novas UUIDs para duplicatas para continuar\?</string>
<string name="menu_master_key_settings">Configurações da chave mestra</string>
<string name="entry_setup_otp">Configurar palavra-passe de uso único</string>
<string name="keyboard_search_share_title">Procurar informação partilhada</string>
<string name="menu_empty_recycle_bin">Esvaziar caixote da reciclagem</string>
<string name="settings_database_force_changing_master_key_next_time_summary">Forçar alteração da chave mestra na próxima vez (uma vez)</string>
<string name="contains_duplicate_uuid_procedure">Resolver o problema gerando novas UUIDs para os duplicados para continuar\?</string>
<string name="settings_database_force_changing_master_key_next_time_title">Forçar renovação na próxima vez</string>
<string name="menu_advanced_unlock_settings">Desbloqueio avançado</string>
<string name="education_setup_OTP_summary">Configurar a gestão de palavra-passe única (HOTP / TOTP) para gerar um token solicitado para autenticação de dois fatores (2FA).</string>
<string name="remember_keyfile_locations_title">Lembrar locais de ficheiros-chave</string>
<string name="education_setup_OTP_summary">Configure a gestão de palavra-passe única (HOTP / TOTP) para gerar um token solicitado para autenticação de dois fatores (2FA).</string>
<string name="remember_keyfile_locations_title">Lembrar locais dos ficheiros-chave</string>
<string name="download_progression">Em progresso: %1$d%%</string>
<string name="biometric_auto_open_prompt_title">Abrir automaticamente o escaneamento de biomẽtrico</string>
<string name="biometric_auto_open_prompt_title">Abrir automaticamente o leitor</string>
<string name="advanced_unlock">Desbloqueio avançado</string>
<string name="settings_database_recommend_changing_master_key_title">Renovação recomendada</string>
<string name="upload_attachment">Enviar %1$s</string>
<string name="education_add_attachment_summary">Envie um anexo à sua entrada para gravar dados externos importantes.</string>
<string name="education_add_attachment_title">Adicionar anexo</string>
<string name="education_add_attachment_summary">Envie um anexo para a sua entrada para guardar dados externos importantes.</string>
<string name="education_add_attachment_title">Adicionar um anexo</string>
<string name="database_data_remove_unlinked_attachments_summary">Remove anexos contidos na base de dados, mas não ligados a uma entrada</string>
<string name="database_data_remove_unlinked_attachments_title">Remover dados não ligados</string>
<string name="data">Dados</string>
<string name="warning_empty_keyfile_explanation">O conteúdo do ficheiro-chave nunca deve ser alterado e, no melhor dos casos, deve conter dados gerados aleatoriamente.</string>
<string name="warning_empty_keyfile">Não é recomendável adicionar um ficheiro de chave vazio.</string>
<string name="warning_sure_remove_data">Remover esses dados mesmo assim\?</string>
<string name="warning_remove_unlinked_attachment">Remover dados não ligados pode diminuir o tamanho da sua base de dados, mas também pode apagar dados utilizados para os plugins do KeePass.</string>
<string name="warning_empty_keyfile">Não é recomendável adicionar um ficheiro-chave vazio.</string>
<string name="warning_sure_remove_data">Remover estes dados mesmo assim\?</string>
<string name="warning_remove_unlinked_attachment">Remover dados não ligados pode diminuir o tamanho da sua base de dados, mas também pode eliminar dados utilizados para os plug-ins do KeePass.</string>
<string name="warning_sure_add_file">Adicionar o ficheiro mesmo assim\?</string>
<string name="warning_replace_file">Enviar deste ficheiro substituirá o existente.</string>
<string name="warning_file_too_big">Uma base de dados KeePass deve conter apenas pequenos ficheiros utilitários (tais como ficheiros chave PGP).
<string name="warning_replace_file">Este ficheiro enviado substituirá o existente.</string>
<string name="warning_file_too_big">Uma base de dados KeePass deve conter apenas pequenos ficheiros utilitários (tais como ficheiros-chave PGP).
\n
\nA sua base de dados pode se tornar muito grande e reduzir o desempenho com este envio.</string>
\nA sua base de dados pode-se tornar muito grande e reduzir o desempenho com este envio.</string>
<string name="content_description_credentials_information">Informações sobre credenciais</string>
<string name="device_credential">Credencial do dispositivo</string>
<string name="credential_before_click_advanced_unlock_button">Digite a palavra-chave, e depois clique no botão \"Desbloqueio avançado\".</string>
<string name="advanced_unlock_prompt_not_initialized">Incapaz de inicializar o desbloqueio antecipado.</string>
<string name="credential_before_click_advanced_unlock_button">Digite a palavra-passe e depois clique neste botão.</string>
<string name="advanced_unlock_prompt_not_initialized">Não foi possível inicializar o desbloqueio avançado.</string>
<string name="advanced_unlock_scanning_error">Erro de desbloqueio avançado: %1$s</string>
<string name="advanced_unlock_not_recognized">Não conseguia reconhecer impressão de desbloqueio avançado</string>
<string name="advanced_unlock_invalid_key">Não consegue ler a chave de desbloqueio avançada. Por favor, apague-a e repita o procedimento de desbloqueio de reconhecimento.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Extrair credencial de base de dados com dados de desbloqueio avançados</string>
<string name="advanced_unlock_prompt_extract_credential_title">Base de dados aberta com reconhecimento avançado de desbloqueio</string>
<string name="advanced_unlock_prompt_store_credential_message">Advertência: Ainda precisa de se lembrar da sua palavra-passe principal se usar o reconhecimento avançado de desbloqueio.</string>
<string name="advanced_unlock_prompt_store_credential_title">Reconhecimento avançado de desbloqueio</string>
<string name="advanced_unlock_not_recognized">Não foi possível reconhecer a impressão de desbloqueio avançado</string>
<string name="advanced_unlock_invalid_key">Não foi possível ler a chave de desbloqueio avançada. Por favor, elimine-a e repita o procedimento de reconhecimento de desbloqueio.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Extrair credencial da base de dados com dados de desbloqueio avançados</string>
<string name="advanced_unlock_prompt_extract_credential_title">Abrir base de dados com reconhecimento de desbloqueio avançado</string>
<string name="advanced_unlock_prompt_store_credential_message">Advertência: ainda tem de se lembrar da sua palavra-passe principal se usar o reconhecimento de desbloqueio avançado.</string>
<string name="advanced_unlock_prompt_store_credential_title">Reconhecimento de desbloqueio avançado</string>
<string name="open_advanced_unlock_prompt_store_credential">Abrir o alerta de desbloqueio avançado para armazenar as credenciais</string>
<string name="open_advanced_unlock_prompt_unlock_database">Abrir o alerta de desbloqueio avançado para desbloquear a base de dados</string>
<string name="biometric_security_update_required">É necessária uma actualização de segurança biométrica.</string>
<string name="configure_biometric">O escaneamento biométrico é suportado, mas não configurado.</string>
<string name="warning_database_revoked">Acesso ao ficheiro revogado pelo gestor do ficheiro, fechar a base de dados e reabri-la a partir da sua localização.</string>
<string name="warning_database_info_changed_options">Sobregravar as modificações externas, guardando a base de dados ou recarregando-a com as últimas alterações.</string>
<string name="warning_database_info_changed">A informação contida no seu ficheiro de base de dados foi modificada fora da aplicação.</string>
<string name="warning_empty_recycle_bin">Apagar permanentemente todos os nós do caixote do lixo da reciclagem\?</string>
<string name="biometric_security_update_required">É necessária uma atualização de segurança biométrica.</string>
<string name="configure_biometric">Não está registada nenhuma credencial biométrica ou de dispositivo.</string>
<string name="warning_database_revoked">Acesso ao ficheiro revogado pelo gestor de ficheiros. Feche a base de dados e reabra-a a partir da sua localização.</string>
<string name="warning_database_info_changed_options">Substitua as alterações externas, guardando a base de dados ou recarregando-a com as últimas alterações.</string>
<string name="warning_database_info_changed">A informação contida no seu ficheiro da base de dados foi alterada fora da aplicação.</string>
<string name="warning_empty_recycle_bin">Eliminar permanentemente todos os nós do caixote da reciclagem\?</string>
<string name="registration_mode">Modo de registo</string>
<string name="save_mode">Modo Guardar</string>
<string name="save_mode">Modo de guardar</string>
<string name="search_mode">Modo de pesquisa</string>
<string name="menu_keystore_remove_key">Apagar chave de desbloqueio avançada</string>
<string name="menu_keystore_remove_key">Eliminar chave de desbloqueio avançada</string>
<string name="menu_reload_database">Recarregar base de dados</string>
<string name="error_rebuild_list">Incapaz de reconstruir adequadamente a lista.</string>
<string name="error_database_uri_null">O URI da base de dados não pode ser recuperado.</string>
<string name="error_rebuild_list">Não foi possível reconstruir adequadamente a lista.</string>
<string name="error_database_uri_null">Não foi possível recuperar o URI da base de dados.</string>
<string name="error_field_name_already_exists">O nome do campo já existe.</string>
<string name="error_registration_read_only">Salvar um novo item não é permitido numa base de dados só de leitura</string>
<string name="error_registration_read_only">Não é permitido guardar um novo item numa base de dados só de leitura</string>
<string name="content_description_otp_information">Informações sobre a palavra-passe de uso único</string>
<string name="show_otp_token_summary">Mostra os tokens OTP na lista de entradas</string>
<string name="show_otp_token_title">Mostrar token OTP</string>
<string name="show_uuid_summary">Mostra o UUID ligado a uma entrada ou grupo</string>
<string name="show_uuid_title">Mostrar UUID</string>
<string name="icon_section_custom">Personalizado</string>
<string name="icon_section_standard">Predefinido</string>
<string name="style_brightness_summary">Escolha temas claros ou escuros</string>
<string name="style_brightness_title">Brilho do tema</string>
<string name="unit_gibibyte">GiB</string>
<string name="unit_mebibyte">MiB</string>
<string name="unit_kibibyte">KiB</string>
<string name="unit_byte">B</string>
<string name="download_canceled">Cancelado!</string>
<string name="education_advanced_unlock_summary">Ligue a sua palavra-passe às suas credenciais biométricas ou do dispositivo para desbloquear rapidamente a sua base de dados.</string>
<string name="education_advanced_unlock_title">Desbloqueio avançado da base de dados</string>
<string name="autofill_inline_suggestions_keyboard">Adicionadas sugestões de preenchimento automático.</string>
<string name="autofill_read_only_save">Não é possível guardar dados numa base de dados aberta apenas com permissão de leitura.</string>
<string name="autofill_ask_to_save_data_summary">Pedir para guardar dados quando é validado um formulário</string>
<string name="autofill_ask_to_save_data_title">Pedir para guardar dados</string>
<string name="autofill_save_search_info_summary">Tentar guardar as informações de pesquisas ao fazer uma seleção de entrada manual</string>
<string name="autofill_save_search_info_title">Guardar informações de pesquisas</string>
<string name="autofill_manual_selection_summary">Mostrar opção para permitir que o utilizador selecione a entrada da base de dados</string>
<string name="autofill_manual_selection_title">Seleção manual</string>
<string name="autofill_inline_suggestions_summary">Tentar mostrar sugestões de preenchimento automático diretamente de um teclado compatível</string>
<string name="autofill_inline_suggestions_title">Sugestões dentro da linha</string>
<string name="autofill_close_database_summary">Fechar a base de dados após a seleção de preencher automático</string>
<string name="autofill_close_database_title">Fechar base de dados</string>
<string name="enter">Enter</string>
<string name="backspace">← Apagar</string>
<string name="select_entry">Selecionar entrada</string>
<string name="back_to_previous_keyboard">Voltar ao teclado anterior</string>
<string name="custom_fields">Campos personalizados</string>
<string name="keyboard_previous_lock_summary">Mudar automaticamente para o teclado anterior após bloquear a base de dados</string>
<string name="keyboard_previous_lock_title">Bloquear base de dados</string>
<string name="keyboard_save_search_info_summary">Depois de partilhar um URL com o KeePassDX, quando uma entrada for selecionada, memorizar essa entrada para utilizações posteriores</string>
<string name="keyboard_save_search_info_title">Guardar informação partilhada</string>
<string name="templates">Modelos</string>
<string name="notification">Notificação</string>
<string name="autofill_select_entry">Selecionar entrada…</string>
<string name="properties">Propriedades</string>
<string name="error_export_app_properties">Erro ao exportar as propriedades da aplicação</string>
<string name="success_export_app_properties">Propriedades da aplicação exportadas</string>
<string name="error_import_app_properties">Erro ao importar as propriedades da aplicação</string>
<string name="success_import_app_properties">Propriedades da aplicação importadas</string>
<string name="description_app_properties">Propriedades do KeePassDX para gerir as configurações da aplicação</string>
<string name="export_app_properties_summary">Criar um ficheiro para exportar as propriedades da aplicação</string>
<string name="export_app_properties_title">Exportar as propriedades da aplicação</string>
<string name="import_app_properties_summary">Selecione um ficheiro para importar as propriedades da aplicação</string>
<string name="import_app_properties_title">Importar propriedades da aplicação</string>
<string name="menu_external_icon">Ícone externo</string>
<string name="error_start_database_action">Ocorreu um erro ao tentar executar uma ação na base de dados.</string>
<string name="error_remove_file">Ocorreu um erro ao tentar remover o ficheiro de dados.</string>
<string name="error_duplicate_file">O ficheiro de dados já existe.</string>
<string name="error_upload_file">Surgiu um erro ao tentar enviar o ficheiro de dados.</string>
<string name="error_file_to_big">O ficheiro que está a tentar enviar é demasiado grande.</string>
<string name="error_otp_type">O tipo de OTP existente não é reconhecido por este formulário, é possível que a sua validação possa não gerar o token corretamente.</string>
<string name="error_word_reserved">Esta palavra está reservada e não pode ser utilizada.</string>
<string name="version">Versão</string>
<string name="template">Modelo</string>
<string name="standard">Predefinido</string>
<string name="membership">Filiação</string>
<string name="secure_note">Nota segura</string>
<string name="international_bank_account_number">IBAN</string>
<string name="bank_identifier_code">SWIFT / BIC</string>
<string name="bank_name">Nome do banco</string>
<string name="bank">Banco</string>
<string name="account">Conta</string>
<string name="seed">Semente</string>
<string name="private_key">Chave privada</string>
<string name="public_key">Chave pública</string>
<string name="token">Token</string>
<string name="cryptocurrency">Carteira de criptomoedas</string>
<string name="type">Tipo</string>
<string name="ssid">SSID</string>
<string name="email_address">Endereço de email</string>
<string name="email">Email</string>
<string name="date_of_issue">Data de emissão</string>
<string name="place_of_issue">Local de emissão</string>
<string name="name">Nome</string>
<string name="id_card">Cartão de identificação</string>
<string name="personal_identification_number">PIN</string>
<string name="card_verification_value">CVV</string>
<string name="number">Número</string>
<string name="holder">Titular</string>
<string name="debit_credit_card">Cartão de crédito / débito</string>
<string name="template_group_name">Modelos</string>
<string name="templates_group_uuid_title">Grupo de modelos</string>
<string name="templates_group_enable_summary">Usa modelos dinâmicos para preencher os campos de uma entrada</string>
<string name="templates_group_enable_title">Utilização de modelos</string>
<string name="advanced_unlock_delete_all_key_warning">Eliminar todas as chaves de encriptação relacionadas com o desbloqueio de reconhecimento avançado\?</string>
<string name="advanced_unlock_timeout">Tempo limite do desbloqueio avançado</string>
<string name="temp_advanced_unlock_timeout_summary">Duração do uso do desbloqueio avançado antes de eliminar os seus conteúdos</string>
<string name="temp_advanced_unlock_timeout_title">Duração do desbloqueio avançado</string>
<string name="temp_advanced_unlock_enable_summary">Não armazenar nenhum conteúdo encriptado para usar o desbloqueio avançado</string>
<string name="temp_advanced_unlock_enable_title">Desbloqueio avançado temporário</string>
<string name="device_credential_unlock_enable_summary">Permite-lhe usar as credenciais do seu dispositivo para abrir a base de dados</string>
<string name="device_credential_unlock_enable_title">Desbloqueio das credenciais do dispositivo</string>
<string name="advanced_unlock_tap_delete">Tocar para as eliminar chaves de desbloqueio avançado</string>
<string name="content">Conteúdo</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More