From 450ab34721c16671ff5c8a6e1e82a34dd200e27e Mon Sep 17 00:00:00 2001 From: VfBFan Date: Thu, 18 Nov 2021 18:45:11 +0000 Subject: [PATCH 001/110] Translated using Weblate (German) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/ --- app/src/main/res/values-de/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index c6c557b30..60dabca2e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -613,4 +613,5 @@ Externes Symbol Zeigt OTP-Tokens in der Liste der Einträge an OTP-Token anzeigen + Symbolname \ No newline at end of file From 27e4d7b56396a9fd176b280bc18541363cca4ed7 Mon Sep 17 00:00:00 2001 From: Retrial Date: Wed, 17 Nov 2021 19:36:09 +0000 Subject: [PATCH 002/110] Translated using Weblate (Greek) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/el/ --- app/src/main/res/values-el/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 26e785db3..d626e7422 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -602,4 +602,5 @@ Εμφάνισης επιλογής για να επιτρέψει στον χρήστη να επιλέξει την καταχώρηση βάσης δεδομένων Χειροκίνητη επιλογή Επιλογή καταχώρησης… + Όνομα εικονιδίου \ No newline at end of file From c5af1241e95721fad58427907fe24f56935cbac0 Mon Sep 17 00:00:00 2001 From: Stephan Paternotte Date: Thu, 18 Nov 2021 18:00:18 +0000 Subject: [PATCH 003/110] Translated using Weblate (Dutch) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/ --- app/src/main/res/values-nl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 775ab66d1..3c831f3b6 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -603,4 +603,5 @@ Nummer Betaalkaart Sjablonen + Naam van het pictogram \ No newline at end of file From 719776d66eaeca7d8ec7e4b102fc811d86c2ee61 Mon Sep 17 00:00:00 2001 From: Matthaiks Date: Wed, 17 Nov 2021 20:44:16 +0000 Subject: [PATCH 004/110] Translated using Weblate (Polish) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/ --- app/src/main/res/values-pl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 80b3f3a69..b73f48556 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -602,4 +602,5 @@ Wyświetl opcję pozwalającą użytkownikowi wybrać wpis bazy danych Wybór ręczny Wybierz wpis… + Nazwa ikony \ No newline at end of file From a079e0d86488ec3bd676f480f91c23cc8a90226f Mon Sep 17 00:00:00 2001 From: solokot Date: Thu, 18 Nov 2021 17:43:20 +0000 Subject: [PATCH 005/110] Translated using Weblate (Russian) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/ --- app/src/main/res/values-ru/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ab949eae8..7d9628f5a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -494,7 +494,7 @@ Режим записи Режим поиска Сохранение новых записей невозможно, т.к. база открыта только для чтения - Поле с таким именем уже существует. + Поле с таким названием уже существует. Позволяет использовать учётные данные вашего устройства для открытия базы Разблокировка учётными данными устройства Учётные данные устройства @@ -602,4 +602,5 @@ Выбор записи… Показывать функцию, позволяющую пользователю вручную выбирать запить из базы Ручной выбор + Название значка \ No newline at end of file From 6a3db90c1e14cacc21f4778fa384999eababb22c Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Wed, 17 Nov 2021 19:47:35 +0000 Subject: [PATCH 006/110] Translated using Weblate (Ukrainian) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/ --- app/src/main/res/values-uk/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index cccca9b16..df6c76e90 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -602,4 +602,5 @@ Параметр показу, який дає користувачеві змогу вибрати запис бази даних Вибір вручну Вибрати запис… + Назва піктограми \ No newline at end of file From a877c068b6e39800765f2cc2410ed07ac547458b Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 18 Nov 2021 00:40:19 +0000 Subject: [PATCH 007/110] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/ --- app/src/main/res/values-zh-rCN/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5a407a5d0..3a02fa3a2 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -400,7 +400,7 @@ 回收站(组) 自动保存数据库 在每次执行重要操作后保存数据库(仅在编辑模式下有效) - 密钥库未正确地初始化 + 密钥库未正确地初始化。 附件 恢复历史记录 删除历史记录 @@ -602,4 +602,5 @@ 显示让用户选择数据库条目的选项 手动选择 选择条目… + 图标名称 \ No newline at end of file From 3ec5c04bf69029c19c20155afa600bd4488cd3d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20Sa=C4=9Flam?= Date: Wed, 17 Nov 2021 19:40:39 +0000 Subject: [PATCH 008/110] Translated using Weblate (Turkish) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/ --- app/src/main/res/values-tr/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 2d7edcad1..881d0e8df 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -597,4 +597,5 @@ Kullanıcının veri tabanı girdisini seçmesine izin veren seçeneği göster Elle seçim Girdi seç… + Simge adı \ No newline at end of file From 4177d34b0070f404249a7db5204a8cefe025146d Mon Sep 17 00:00:00 2001 From: SC Date: Wed, 17 Nov 2021 23:18:47 +0000 Subject: [PATCH 009/110] Translated using Weblate (Portuguese) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt/ --- app/src/main/res/values-pt/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 0ae34a929..779d2a604 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -578,4 +578,5 @@ Cartão de crédito / débito Modelos Informação de palavra-passe de uso único + Nome do ícone \ No newline at end of file From d68510bbaa1ae3503d3f369b4e11d14c436d47c7 Mon Sep 17 00:00:00 2001 From: JY3 Date: Sun, 21 Nov 2021 13:38:19 +0000 Subject: [PATCH 010/110] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/ --- app/src/main/res/values-zh-rCN/strings.xml | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 3a02fa3a2..59cce5658 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -128,11 +128,11 @@ ASCII拓展区字符 允许 剪切板错误 - 某些设备不允许应用程序使用剪贴板。 + 某些设备不允许应用使用剪贴板。 无法清空剪切板 主题 图标包 - 程序中使用的图标包 + 应用中使用的图标包 编辑条目 密钥推导函数 找不到条目数据。 @@ -199,7 +199,7 @@ 默认以只读方式打开数据库 下载 贡献 - 程序中使用的主题 + 应用中使用的主题 每个字符串必须有字段名。 字段名 字段值 @@ -236,7 +236,7 @@ 字段字型 更改字段字体,可以使字符更清楚 允许复制整段密码和受保护的字段至剪切板 - 警告:复制密码时密码在剪贴板中,而所有程序都可访问剪切板。因此复制密码时,设备上的其他程序也能看到密码。 + 警告:复制密码时密码在剪贴板中,而所有应用都可访问剪切板。因此复制密码时,设备上的其他应用也能看到密码。 激活自定义键盘以填写密码和所有身份字段 信任剪贴板 魔法键盘 @@ -296,7 +296,7 @@ 选择条目和群组的排序方式。 参与开发 帮助增加稳定性,安全性并添加更多的功能。 - 不同于大多数的密码管理程序,无论您是使用免费版本还是付费版本的 KeePassDX,这都是一款<strong>没有广告</strong>,<strong>基于 copylefted 版权协议的自由软件</strong>。同时,本软件的任何版本都不会收集您的任何个人信息。 + 不同于大多数的密码管理应用,无论您是使用免费版本还是付费版本的 KeePassDX,这都是一款没有广告基于 copylefted 版权协议的自由软件。同时,本软件的任何版本都不会收集您的任何个人信息。 通过购买高级版本,您将解锁全部<strong>主题样式</strong>,重要的是,您会为<strong>社区项目的进行</strong>提供帮助 此<strong>主题样式</strong>已可用,感谢您的慷慨相助。 为继续建设此自由项目让其保持活跃,我们需要您的<strong>捐赠。</strong> @@ -306,12 +306,12 @@ 您的留言,是对开发人员添加<strong>新功能</strong>及<strong>修复 bugs</strong> 的鼓励。 非常感谢您的捐助和贡献。 我们正在努力的研发并尽快发布新特性。 - 别忘了通过安装新版本来保持你的应用程序是最新的。 + 别忘了通过安装新版本来保持你的应用是最新的。 选择模式 - 不要终止程序… + 不要终止应用… 按返回键以锁定 当用户单击根屏幕上的返回按钮时锁定数据库 - 关闭程序时清空剪贴板 + 关闭应用时清空剪贴板 剪贴板持续时间过期或通知在您开始使用后关闭时,锁定数据库 回收站 条目选择 @@ -432,7 +432,7 @@ 添加附件 放弃更改? 验证 - 自动建议匹配的网址域名或应用程序 ID 的搜索结果 + 自动建议匹配的网址域名或应用 ID 的搜索结果 自动搜索 在用户界面中显示锁定数据库按钮 显示锁定数据库按钮 @@ -441,11 +441,11 @@ 该标签已经存在。 将 URL 共享给 KeePassDX 时,使用该 URL 域过滤条目 搜索分享的信息 - 重新启动包含该表单的应用程序以激活拦截。 + 重新启动包含该表单的应用以激活拦截。 阻止自动填充 禁止在下列域名中自动填充凭证 网址域名黑名单 - 禁止应用程序自动填充的黑名单 + 禁止应用自动填充的黑名单 应用拦截列表 过滤器 搜索带有子域约束的网址域名 @@ -532,7 +532,7 @@ 内联建议 文件管理器撤销了对此文件的访问,关闭数据库并从其位置重新打开它。 通过保存数据库或用最新的更改重新加载数据库来覆盖外部修改。 - 数据库文件中包含的信息已在应用程序之外被修改。 + 数据库文件中包含的信息已在应用之外被修改。 重新加载数据库 GiB 兆字节 From 98fb27f77d8542a183624ec91c07a7a6934b7774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beytullah=20AKY=C3=9CZ?= Date: Sun, 21 Nov 2021 11:03:32 +0000 Subject: [PATCH 011/110] Translated using Weblate (Turkish) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/ --- app/src/main/res/values-tr/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 881d0e8df..f70e10c53 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -300,7 +300,7 @@ Simge paketi Uygulamada kullanılan simge paketi Seçim modu - Uygulamayı öldürmeyin… + Uygulamayı sonlandırmayın… Kullanıcı kök ekranda geri düğmesine tıkladığında veri tabanını kilitle Kapanışta temizle Panonun süresi dolduğunda veya kullanmaya başladıktan sonra bildirim kapatıldığında veri tabanını kilitle From 0979ca607d8613c1199a49c4f26e0653b53846f2 Mon Sep 17 00:00:00 2001 From: random r Date: Tue, 23 Nov 2021 13:55:00 +0000 Subject: [PATCH 012/110] Translated using Weblate (Italian) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/ --- app/src/main/res/values-it/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index a3e0d8426..0fa4fdf54 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -605,4 +605,5 @@ Mostra l\'opzione che permette all\'utente di scegliere la voce nel database Selezione manuale Seleziona voce… + Nome icona \ No newline at end of file From ef43837af100222f0a05130d06adfedc48c3dfac Mon Sep 17 00:00:00 2001 From: Mr-Update Date: Tue, 23 Nov 2021 22:34:47 +0000 Subject: [PATCH 013/110] Translated using Weblate (German) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/ --- app/src/main/res/values-de/strings.xml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 60dabca2e..fa0997588 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -160,7 +160,7 @@ Zwischenablage-Benachrichtigung Benachrichtigungen zur Zwischenablage anzeigen, um beim Betrachten eines Eintrags Felder kopieren zu können Bildschirmsperre - Datenbank sperren, einige Sekunden nachdem der Bildschirm ausgeschaltet wird + Datenbank einige Sekunden, nachdem der Bildschirm ausgeschaltet ist, sperren Neue Datenbank erstellen Hauptschlüssel zuweisen Pfad @@ -253,7 +253,7 @@ Sortierung der Einträge Auswählen, wie Einträge und Gruppen sortiert werden. Mitmachen - Mithelfen, um Stabilität und Sicherheit zu verbessern und weitere Funktionen zu ermöglichen. + Mithelfen, um Stabilität und Sicherheit zu verbessern sowie weitere Funktionen zu ermöglichen. Anders als viele andere Passwortmanager ist dieser <strong>werbefrei</strong>, <strong>quelloffen</strong> und unter einer <strong>Copyleft-Lizenz</strong>. Es werden keine persönlichen Daten gesammelt, in welcher Form auch immer, unabhängig von der verwendeten Version (kostenlos oder Pro). Mit dem Kauf der Pro-Version erhalten Sie Zugriff auf diesen <strong>visuellen Stil</strong> und unterstützen insbesondere <strong>die Umsetzung gemeinschaftlicher Projekte.</strong> Dieser <strong>visuelle Stil</strong> wurde wegen Ihrer Großzügigkeit freigeschaltet. @@ -343,7 +343,7 @@ Anzahl der Einträge in einer Gruppe anzeigen Knoten hinzufügen „Zurück“ drücken, um zu sperren - Die Datenbank sperren, wenn die Dauer der Zwischenablage abläuft oder die Benachrichtigung geschlossen wird, nachdem Sie sie zu benutzen begonnen haben + Die Datenbank sperren, wenn die Dauer der Zwischenablage abläuft oder die Benachrichtigung geschlossen wird, nachdem Sie sie benutzt haben Untergeordneter Knotenpunkt Schlüsseldatei-Kontrollkästchen Hierher kann kein Eintrag verschoben werden. @@ -450,7 +450,7 @@ Suchergebnisse automatisch nach Web-Domain oder Anwendungs-ID vorschlagen Automatische Suche Manuelle Auswahl - Manuelle Auswahl des Datenbank-Eintrags ermöglichen + Manuelle Auswahl des Datenbankeintrags ermöglichen Zeigt die Sperrtaste in der Benutzeroberfläche an Sperrtaste anzeigen Einstellungen für automatisches Ausfüllen @@ -488,13 +488,13 @@ \nMit diesem Upload könnte Ihre Datenbank sehr groß werden und an Geschwindigkeit verlieren. %1$s hochladen Anhang hinzufügen - Entfernt Anhänge die in der Datenbank enthalten, aber keinem Eintrag zugeordnet sind + Entfernt Anhänge, die in der Datenbank enthalten, aber keinem Eintrag zugeordnet sind Soll die Datei trotzdem hinzugefügt werden\? Zeigt die mit einem Eintrag oder einer Gruppe verknüpfte UUID an UUID anzeigen Das Speichern von Daten ist für eine als schreibgeschützt geöffnete Datenbank nicht zulässig. Datenbank schließen - Automatisches Zurückschalten zur vorherigen Tastatur nach dem Sperren der Datenbank + Nach dem Sperren der Datenbank automatisch zur vorherigen Tastatur zurückschalten Datenbank sperren Benachrichtigung Biometrisches Sicherheitsupdate erforderlich. @@ -503,12 +503,12 @@ Speichermodus Suchmodus Das Speichern eines neuen Elements in einer schreibgeschützten Datenbank ist nicht zulässig - Suchdaten bei manueller Auswahl einer Eingabe wenn möglich speichern + Suchdaten bei manueller Auswahl einer Eingabe, wenn möglich, speichern Nachfragen, ob die Daten gespeichert werden sollen, wenn ein Formular ausgefüllt ist Speichern von Daten abfragen Suchinformationen speichern Datenbank nach Auswahl eines Eintrags zum automatischen Ausfüllen schließen - Nachdem eine URL mit KeePassDX geteilt und ein Eintrag gewählt wurde, wird versucht sich diesen Eintrag für weitere Nutzungen zu merken + Nachdem eine URL mit KeePassDX geteilt und ein Eintrag gewählt wurde, wird versucht, sich diesen Eintrag für die weitere Nutzung zu merken Gemeinsam genutzte Informationen speichern Sollen alle ausgewählten Knoten wirklich aus dem Papierkorb gelöscht werden\? Der Feldname existiert bereits. @@ -519,8 +519,8 @@ Moderne Entsperrerkennung Verknüpfen Sie Ihr Passwort mit Ihren gescannten Biometriedaten oder Daten zur Geräteanmeldung, um schnell Ihre Datenbank zu entsperren. Moderne Entsperrung der Datenbank - Verfallzeit der modernen Entsperrung - Laufzeit der modernen Entsperrung bevor ihr Inhalt gelöscht wird + Verfallszeit der modernen Entsperrung + Laufzeit der modernen Entsperrung, bevor ihr Inhalt gelöscht wird Verfall der modernen Entsperrung Keine zur modernen Entsperrung verwendeten, verschlüsselten Inhalte speichern Befristete moderne Entsperrung @@ -530,7 +530,7 @@ Datenbank mit moderner Entsperrerkennung öffnen Eingabetaste Rücktaste - Wähle Eintrag + Eintrag auswählen Zurück zur vorherigen Tastatur Benutzerdefinierte Felder Alle Verschlüsselungsschlüssel, die mit der modernen Entsperrerkennung zusammenhängen, löschen\? @@ -576,7 +576,7 @@ B Abgebrochen! Vorschläge für automatisches Ausfüllen hinzugefügt. - Wenn möglich unmittelbar Vorschläge zum automatischen Ausfüllen auf einer kompatiblen Tastatur anzeigen + Wenn möglich, Vorschläge zum automatischen Ausfüllen direkt auf einer kompatiblen Tastatur anzeigen Eigenschaften KeePassDX-Eigenschaften zur Verwaltung der App-Einstellungen Sicherer Hinweis From f9def8c96fb3b83909929337f70eaba161514e54 Mon Sep 17 00:00:00 2001 From: abidin toumi Date: Sun, 28 Nov 2021 09:56:16 +0000 Subject: [PATCH 014/110] Translated using Weblate (Arabic) Currently translated at 78.7% (448 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/ --- app/src/main/res/values-ar/strings.xml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 8acd105ef..f5c907c10 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -88,7 +88,7 @@ المساحة البحث الفرز - تصاعدياً + تصاعدي ↓ العنوان اسم المستخدِم تاريخ الإنشاء @@ -472,7 +472,7 @@ خطأ أثناء استيراد خصائص التطبيق خطأ أثناء تصدير خصائص التطبيق غُيِّرت معلومات قاعدة البيانات من خارج هذا التطبيق. - اكتب فوق التعديلات الخارجية عن طريق حفظ قاعدة البيانات أو أعد تحميلها لتضمين هذه التغييرات. + اكتب فوق التعديلات الخارجية عن طريق حفظ قاعدة البيانات أو أعد تحميلها لجلب آخر التغييرات. افتح محث فك القفل المتقدم لتخزين بيانات الاعتماد افتح محث فك القفل المتقدم لفتح قاعدة البيانات اكتب كلمة السر، وأنقر هذا الزر. @@ -483,4 +483,10 @@ إجراء لمس تلقائي اقفل قاعدة البيانات فك القفل المتقدم لقاعدة البيانات + اسم الأيقونة + اختيار يدوي + خصائص KeePassDX لإدارة إعدادات التطبيقات + هل تريد حذف جميع العقد نهائيًا من سلة المهملات؟ + احفظ معلومات البحث + اسأل لحفظ البيانات \ No newline at end of file From 7169b15fd8da53bad81f3bf6708968b843f5af5a Mon Sep 17 00:00:00 2001 From: Milo Ivir Date: Sun, 28 Nov 2021 15:21:45 +0000 Subject: [PATCH 015/110] Translated using Weblate (Croatian) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hr/ --- app/src/main/res/values-hr/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 41c1caaf2..64aaf5cee 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -597,4 +597,5 @@ Odaberi unos … Vanjska ikona Tajna fraza + Ime ikone \ No newline at end of file From 23a548f9b4f33f8ddd10c2b74b8b7b3a8f728f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Fern=C3=A1ndez=20D=C3=ADaz?= Date: Wed, 1 Dec 2021 18:40:32 +0000 Subject: [PATCH 016/110] Translated using Weblate (Spanish) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/ --- app/src/main/res/values-es/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 899959ad4..47b83fad2 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -604,4 +604,5 @@ Mostrar opción para permitir al usuario seleccionar la entrada de la base de datos Selección manual Seleccionar entrada… + Nombre del icono \ No newline at end of file From 35c8ea22b1c4e02e32dd78284e397475b3fc7d0b Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Tue, 7 Dec 2021 01:51:38 +0000 Subject: [PATCH 017/110] Translated using Weblate (Ukrainian) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/ --- app/src/main/res/values-uk/strings.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index df6c76e90..b38435cff 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -134,7 +134,7 @@ Відкрити файл Розширений ASCII Змінити запис - Блокувати базу даних після закінчення терміну дії буфера обміну, або закрито сповіщення після початку користування ним + Блокувати базу даних після закриття сповіщення після використання або якщо вичерпано час очікування Додати групу Оновити Клавіатура @@ -159,7 +159,7 @@ Деякі пристрої не дозволяють застосункам користуватися буфером обміну. Помилка буфера обміну Дозволити - Функція створення ключа + Функція генерування ключа Шифрування Безпека Головний ключ @@ -375,7 +375,7 @@ Назва файлу Пристрій працює під керуванням Android %1$s, але необхідний %2$s чи пізніші. Не вдалось запустити цю функцію. - Видалити всі ключі шифрування, пов\'язані з розпізнаванням розширеного розблокування + Видалити всі ключі шифрування, пов’язані з розпізнаванням розширеного розблокування Видалити ключі шифрування Автоматично запитувати розширене розблокування, якщо базу даних налаштовано для роботи з ним Автозапит ключа @@ -471,8 +471,8 @@ Не рекомендовано додавати порожній файл ключа. Вміст файлу ключів ніколи не слід змінювати, а в кращому випадку повинен містити випадково згенеровані дані. Дані - Вилучити незв\'язані дані - Вилучає вкладення, що містяться в базі даних, але не пов’язані із записом + Вилучити непов’язані дані + Вилучає вкладення, що містяться в базі даних, але не пов’язані з записом Показ пов\'язаного з записом чи групою UUID Показувати UUID Збереження даних заборонено для бази даних, відкритої лише для читання. @@ -495,7 +495,7 @@ Режим пошуку Збереження нового елемента заборонено в базі даних лише для читання Назва поля вже існує. - Видалити всі ключі шифрування, пов\'язані з розширеним розпізнаванням розблокування\? + Видалити всі ключі шифрування, пов’язані з розширеним розпізнаванням розблокування\? Дає змогу використовувати облікові дані пристрою для відкриття бази даних Розблокування облікових даних пристрою Облікові дані пристрою @@ -521,7 +521,7 @@ Пов’яжіть свій пароль зі сканованими біометричними даними або даними пристрою, щоб швидко розблокувати базу даних. Розширене розблокування бази даних Тривалість використання розширеного розблокування перед видаленням його вмісту - Не зберігайте зашифрований вміст для використання розширеного розблокування + Не зберігати зашифрований вміст для використання розширеного розблокування Тимчасове розширене розблокування Торкнутися, щоб видалити клавіші розширеного розблокування Вміст @@ -542,7 +542,7 @@ Скасовано! Власні Стандартні - Вибрати світлі або темні теми + Вибрати світлу або темну теми Яскравість теми Під час передавання даних файлу сталася помилка. Файл, який ви намагаєтеся передати, завеликий. From aa643c4a8287368f05f8fbcadc1e2459a02428a9 Mon Sep 17 00:00:00 2001 From: Oymate Date: Sat, 11 Dec 2021 05:55:26 +0000 Subject: [PATCH 018/110] Translated using Weblate (Bengali (Bangladesh)) Currently translated at 7.7% (44 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/bn_BD/ --- app/src/main/res/values-bn-rBD/strings.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index 9cf593557..76ef0db6b 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -29,4 +29,16 @@ বাতিল সত্যায়ন পটভূমি + বাতিল + দ্রষ্টব্য + তৈরিকৃত + মেয়াদ + বিশেষ শনাক্তকরণ সংকেত(ইউইউআইডি) + ইতিহাস + সংযুক্তি + চাবিনথি(কিফাইল) + পরিবর্তিত + ক্লিপবোর্ড পরিষ্কার করা হয়েছে + শেষ ব্যবহার + কিছু ডিভাইস অ্যাপ্লিকেশনগুলোকে ক্লিপবোর্ড ব্যবহার করতে দেয় না। \ No newline at end of file From 17bc18b8816b8ba72f75b7fcf444939f1234b848 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Mon, 13 Dec 2021 14:24:12 +0100 Subject: [PATCH 019/110] Add breadcrumb for group --- .../keepass/activities/GroupActivity.kt | 29 +++++++++ .../keepass/adapters/BreadcrumbAdapter.kt | 58 +++++++++++++++++ app/src/main/res/layout/activity_group.xml | 18 ++++++ app/src/main/res/layout/item_breadcrumb.xml | 62 +++++++++++++++++++ app/src/main/res/values/styles.xml | 4 ++ 5 files changed, 171 insertions(+) create mode 100644 app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt create mode 100644 app/src/main/res/layout/item_breadcrumb.xml diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index f71724b17..a1e6f2cd9 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -41,12 +41,14 @@ import androidx.appcompat.view.ActionMode import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.Toolbar import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.recyclerview.widget.RecyclerView import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.* import com.kunzisoft.keepass.activities.fragments.GroupFragment import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper import com.kunzisoft.keepass.activities.helpers.SpecialMode import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity +import com.kunzisoft.keepass.adapters.BreadcrumbAdapter import com.kunzisoft.keepass.adapters.SearchEntryCursorAdapter import com.kunzisoft.keepass.autofill.AutofillComponent import com.kunzisoft.keepass.autofill.AutofillHelper @@ -84,6 +86,7 @@ class GroupActivity : DatabaseLockActivity(), private var coordinatorLayout: CoordinatorLayout? = null private var lockView: View? = null private var toolbar: Toolbar? = null + private var breadcrumbToolbar: Toolbar? = null private var searchTitleView: View? = null private var toolbarAction: ToolbarAction? = null private var iconView: ImageView? = null @@ -91,11 +94,14 @@ class GroupActivity : DatabaseLockActivity(), private var addNodeButtonView: AddNodeButtonView? = null private var groupNameView: TextView? = null private var groupMetaView: TextView? = null + private var breadcrumbListView: RecyclerView? = null private var loadingView: ProgressBar? = null private val mGroupViewModel: GroupViewModel by viewModels() private val mGroupEditViewModel: GroupEditViewModel by viewModels() + private var mBreadcrumbAdapter: BreadcrumbAdapter? = null + private var mGroupFragment: GroupFragment? = null private var mRecyclingBinEnabled = false private var mRecyclingBinIsCurrentGroup = false @@ -138,9 +144,11 @@ class GroupActivity : DatabaseLockActivity(), numberChildrenView = findViewById(R.id.group_numbers) addNodeButtonView = findViewById(R.id.add_node_button) toolbar = findViewById(R.id.toolbar) + breadcrumbToolbar = findViewById(R.id.toolbar_breadcrumb) searchTitleView = findViewById(R.id.search_title) groupNameView = findViewById(R.id.group_name) groupMetaView = findViewById(R.id.group_meta) + breadcrumbListView = findViewById(R.id.breadcrumb_list) toolbarAction = findViewById(R.id.toolbar_action) lockView = findViewById(R.id.lock_button) loadingView = findViewById(R.id.loading) @@ -152,6 +160,19 @@ class GroupActivity : DatabaseLockActivity(), toolbar?.title = "" setSupportActionBar(toolbar) + mBreadcrumbAdapter = BreadcrumbAdapter(this).apply { + // Open group on breadcrumb click + onItemClickListener = { node, _ -> + finishNodeAction() + mDatabase?.let { database -> + onNodeClick(database, node) + } + } + } + breadcrumbListView?.apply { + adapter = mBreadcrumbAdapter + } + // Retrieve the textColor to tint the icon val taTextColor = theme.obtainStyledAttributes(intArrayOf(R.attr.textColorInverse)) mIconColor = taTextColor.getColor(0, Color.WHITE) @@ -211,6 +232,12 @@ class GroupActivity : DatabaseLockActivity(), // Update last access time. currentGroup.touch(modified = false, touchParents = false) + // Add breadcrumb + mBreadcrumbAdapter?.apply { + setNode(currentGroup) + breadcrumbListView?.scrollToPosition(itemCount -1) + } + // Add listeners to the add buttons addNodeButtonView?.setAddGroupClickListener { GroupEditDialogFragment.create(GroupInfo().apply { @@ -528,6 +555,7 @@ class GroupActivity : DatabaseLockActivity(), toolbar?.navigationIcon = null } iconView?.visibility = View.GONE + breadcrumbToolbar?.visibility = View.GONE } else { searchTitleView?.visibility = View.GONE // Assign the group icon depending of IconPack or custom icon @@ -549,6 +577,7 @@ class GroupActivity : DatabaseLockActivity(), } } } + breadcrumbToolbar?.visibility = View.VISIBLE } // Assign number of children diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt new file mode 100644 index 000000000..d2a93e75c --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt @@ -0,0 +1,58 @@ +package com.kunzisoft.keepass.adapters + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.database.element.node.Node + +class BreadcrumbAdapter(val context: Context) : RecyclerView.Adapter() { + + private val inflater: LayoutInflater = LayoutInflater.from(context) + private var mNodeBreadcrumb: MutableList = mutableListOf() + var onItemClickListener: ((item: Node, position: Int)->Unit)? = null + + fun setNode(node: Node) { + mNodeBreadcrumb.clear() + var currentNode = node + while (currentNode.containsParent()) { + currentNode.parent?.let { parent -> + currentNode = parent + mNodeBreadcrumb.add(0, currentNode) + } + } + mNodeBreadcrumb.add(0, null) + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BreadcrumbGroupViewHolder { + return BreadcrumbGroupViewHolder(inflater.inflate(R.layout.item_breadcrumb, parent, false)) + } + + override fun onBindViewHolder(holder: BreadcrumbGroupViewHolder, position: Int) { + val node = mNodeBreadcrumb[position] + + holder.breadcrumbTextView.text = when { + node == null -> "" + node.title.isEmpty() -> context.getString(R.string.root) + else -> node.title + } + + holder.breadcrumbTextView.setOnClickListener { + node?.let { + onItemClickListener?.invoke(it, position) + } + } + } + + override fun getItemCount(): Int { + return mNodeBreadcrumb.size + } + + inner class BreadcrumbGroupViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var breadcrumbTextView: TextView = itemView.findViewById(R.id.breadcrumb_text) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_group.xml b/app/src/main/res/layout/activity_group.xml index 1ba069e24..66a0cfa48 100644 --- a/app/src/main/res/layout/activity_group.xml +++ b/app/src/main/res/layout/activity_group.xml @@ -54,6 +54,7 @@ android:background="?attr/colorPrimary" android:theme="?attr/toolbarAppearance" android:elevation="4dp" + app:layout_scrollFlags="scroll|snap|enterAlways" tools:targetApi="lollipop"> + + + + + + + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index e15a03b01..dad0ea830 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -313,6 +313,10 @@ 18sp bold + From a927c33ef15de2642d65a6bf2b25f8215f1885c6 Mon Sep 17 00:00:00 2001 From: Kunzisoft Date: Tue, 14 Dec 2021 11:43:12 +0000 Subject: [PATCH 020/110] Translated using Weblate (French) Currently translated at 100.0% (569 of 569 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/ --- app/src/main/res/values-fr/strings.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9fd15cbde..164b0a891 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -569,9 +569,9 @@ Propriétés de l\'application importées Propriétés KeePassDX pour gérer les paramètres de l\'application Créer un fichier pour exporter les propriétés de l\'application - Export des propriétés de l\'app + Exporter les propriétés de l\'application Sélectionner un fichier pour importer les propriétés de l\'application - Importation des propriétés de l\'appli + Importer les propriétés de l\'application Une erreur s\'est produite lors de l\'exécution d\'une action sur la base de données. Vous ne pouvez pas déplacer un groupe ici. Ce mot est réservé et ne peut pas être utilisé. @@ -609,4 +609,5 @@ Icône externe Afficher l\'option permettant à l\'utilisateur de sélectionner l\'entrée de la base de données Sélection manuelle + Nom de l\'icône \ No newline at end of file From 66db2e7d1606ff16fe7f7dad260d3176e76580b5 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 16 Dec 2021 11:26:17 +0100 Subject: [PATCH 021/110] Better breadcrumb implementation --- .../keepass/activities/GroupActivity.kt | 54 +-------- .../keepass/adapters/BreadcrumbAdapter.kt | 101 ++++++++++++++-- app/src/main/res/layout/activity_group.xml | 111 +++++------------- app/src/main/res/layout/item_breadcrumb.xml | 59 +++++----- .../res/layout/item_breadcrumb_current.xml | 75 ++++++++++++ app/src/main/res/values/styles.xml | 4 +- 6 files changed, 231 insertions(+), 173 deletions(-) create mode 100644 app/src/main/res/layout/item_breadcrumb_current.xml diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index a1e6f2cd9..d63a78927 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -86,14 +86,13 @@ class GroupActivity : DatabaseLockActivity(), private var coordinatorLayout: CoordinatorLayout? = null private var lockView: View? = null private var toolbar: Toolbar? = null + private var toolbarTitleView: TextView? = null private var breadcrumbToolbar: Toolbar? = null private var searchTitleView: View? = null private var toolbarAction: ToolbarAction? = null private var iconView: ImageView? = null private var numberChildrenView: TextView? = null private var addNodeButtonView: AddNodeButtonView? = null - private var groupNameView: TextView? = null - private var groupMetaView: TextView? = null private var breadcrumbListView: RecyclerView? = null private var loadingView: ProgressBar? = null @@ -129,8 +128,6 @@ class GroupActivity : DatabaseLockActivity(), AutofillHelper.buildActivityResultLauncher(this) else null - private var mIconColor: Int = 0 - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -144,10 +141,9 @@ class GroupActivity : DatabaseLockActivity(), numberChildrenView = findViewById(R.id.group_numbers) addNodeButtonView = findViewById(R.id.add_node_button) toolbar = findViewById(R.id.toolbar) + toolbarTitleView = findViewById(R.id.toolbar_title) breadcrumbToolbar = findViewById(R.id.toolbar_breadcrumb) searchTitleView = findViewById(R.id.search_title) - groupNameView = findViewById(R.id.group_name) - groupMetaView = findViewById(R.id.group_meta) breadcrumbListView = findViewById(R.id.breadcrumb_list) toolbarAction = findViewById(R.id.toolbar_action) lockView = findViewById(R.id.lock_button) @@ -173,11 +169,6 @@ class GroupActivity : DatabaseLockActivity(), adapter = mBreadcrumbAdapter } - // Retrieve the textColor to tint the icon - val taTextColor = theme.obtainStyledAttributes(intArrayOf(R.attr.textColorInverse)) - mIconColor = taTextColor.getColor(0, Color.WHITE) - taTextColor.recycle() - // Retrieve group if defined at launch manageIntent(intent) @@ -398,7 +389,9 @@ class GroupActivity : DatabaseLockActivity(), // Search suggestion database?.let { + toolbarTitleView?.text = it.name mSearchSuggestionAdapter = SearchEntryCursorAdapter(this, it) + mBreadcrumbAdapter?.iconDrawableFactory = it.iconDrawableFactory mOnSuggestionListener = object : SearchView.OnSuggestionListener { override fun onSuggestionClick(position: Int): Boolean { mSearchSuggestionAdapter?.let { searchAdapter -> @@ -529,25 +522,6 @@ class GroupActivity : DatabaseLockActivity(), private fun assignGroupViewElements(group: Group?) { // Assign title - if (group != null) { - if (groupNameView != null) { - val title = group.title - groupNameView?.text = if (title.isNotEmpty()) title else getText(R.string.root) - groupNameView?.invalidate() - } - if (groupMetaView != null) { - val meta = group.nodeId.toString() - groupMetaView?.text = meta - if (meta.isNotEmpty() - && !group.isVirtual - && PreferencesUtil.showUUID(this)) { - groupMetaView?.visibility = View.VISIBLE - } else { - groupMetaView?.visibility = View.GONE - } - groupMetaView?.invalidate() - } - } if (group?.isVirtual == true) { searchTitleView?.visibility = View.VISIBLE @@ -560,15 +534,7 @@ class GroupActivity : DatabaseLockActivity(), searchTitleView?.visibility = View.GONE // Assign the group icon depending of IconPack or custom icon iconView?.visibility = View.VISIBLE - group?.let { currentGroup -> - iconView?.let { imageView -> - mIconDrawableFactory?.assignDatabaseIcon( - imageView, - currentGroup.icon, - mIconColor - ) - } - + group?.let { if (toolbar != null) { if (group.containsParent()) toolbar?.setNavigationIcon(R.drawable.ic_arrow_up_white_24dp) @@ -607,15 +573,7 @@ class GroupActivity : DatabaseLockActivity(), } private fun refreshNumberOfChildren(group: Group?) { - numberChildrenView?.apply { - if (PreferencesUtil.showNumberEntries(context)) { - group?.refreshNumberOfChildEntries(Group.ChildFilter.getDefaults(context)) - text = group?.numberOfChildEntries?.toString() ?: "" - visibility = View.VISIBLE - } else { - visibility = View.GONE - } - } + // TODO } override fun onScrolled(dy: Int) { diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt index d2a93e75c..99b9c385c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt @@ -1,51 +1,127 @@ package com.kunzisoft.keepass.adapters import android.content.Context +import android.graphics.Color import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.database.element.Group import com.kunzisoft.keepass.database.element.node.Node +import com.kunzisoft.keepass.database.element.node.Type +import com.kunzisoft.keepass.icons.IconDrawableFactory +import com.kunzisoft.keepass.settings.PreferencesUtil -class BreadcrumbAdapter(val context: Context) : RecyclerView.Adapter() { +class BreadcrumbAdapter(val context: Context) + : RecyclerView.Adapter() { private val inflater: LayoutInflater = LayoutInflater.from(context) + var iconDrawableFactory: IconDrawableFactory? = null + set(value) { + field = value + notifyDataSetChanged() + } private var mNodeBreadcrumb: MutableList = mutableListOf() var onItemClickListener: ((item: Node, position: Int)->Unit)? = null + private var mShowNumberEntries = false + private var mShowUUID = false + private var mIconColor: Int = 0 + + init { + mShowNumberEntries = PreferencesUtil.showNumberEntries(context) + mShowUUID = PreferencesUtil.showUUID(context) + + // Retrieve the textColor to tint the icon + val taTextColor = context.theme.obtainStyledAttributes(intArrayOf(R.attr.textColorInverse)) + mIconColor = taTextColor.getColor(0, Color.WHITE) + taTextColor.recycle() + } + fun setNode(node: Node) { mNodeBreadcrumb.clear() var currentNode = node + mNodeBreadcrumb.add(0, currentNode) while (currentNode.containsParent()) { currentNode.parent?.let { parent -> currentNode = parent mNodeBreadcrumb.add(0, currentNode) } } - mNodeBreadcrumb.add(0, null) notifyDataSetChanged() } + override fun getItemViewType(position: Int): Int { + return when (position) { + mNodeBreadcrumb.size - 1 -> 0 + else -> 1 + } + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BreadcrumbGroupViewHolder { - return BreadcrumbGroupViewHolder(inflater.inflate(R.layout.item_breadcrumb, parent, false)) + return BreadcrumbGroupViewHolder(inflater.inflate( + when (viewType) { + 0 -> R.layout.item_breadcrumb_current + else -> R.layout.item_breadcrumb + }, parent, false) + ) } override fun onBindViewHolder(holder: BreadcrumbGroupViewHolder, position: Int) { val node = mNodeBreadcrumb[position] - holder.breadcrumbTextView.text = when { - node == null -> "" - node.title.isEmpty() -> context.getString(R.string.root) - else -> node.title + holder.groupNameView.apply { + text = when { + node == null -> "" + node.title.isEmpty() -> context.getString(R.string.root) + else -> node.title + } + setOnClickListener { + node?.let { + onItemClickListener?.invoke(it, position) + } + } } - holder.breadcrumbTextView.setOnClickListener { - node?.let { - onItemClickListener?.invoke(it, position) + if (node?.type == Type.GROUP) { + (node as Group).let { group -> + + holder.groupIconView?.let { imageView -> + iconDrawableFactory?.assignDatabaseIcon( + imageView, + group.icon, + mIconColor + ) + } + + holder.groupNumbersView?.apply { + if (mShowNumberEntries) { + group.refreshNumberOfChildEntries(Group.ChildFilter.getDefaults(context)) + text = group.numberOfChildEntries.toString() + visibility = View.VISIBLE + } else { + visibility = View.GONE + } + } + + holder.groupMetaView?.apply { + val meta = group.nodeId.toString() + text = meta + visibility = if (meta.isNotEmpty() + && !group.isVirtual + && mShowUUID + ) { + View.VISIBLE + } else { + View.GONE + } + } } } + } override fun getItemCount(): Int { @@ -53,6 +129,9 @@ class BreadcrumbAdapter(val context: Context) : RecyclerView.Adapter + + + + + + + android:layout_below="@+id/toolbar" + android:layout_above="@+id/toolbar_action" + android:elevation="4dp" + tools:targetApi="lollipop"> - - - - - - - - - - - - - - - - . --> - + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center_vertical" + android:layout_marginStart="4dp" + android:layout_marginLeft="4dp" + android:layout_marginEnd="4dp" + android:layout_marginRight="4dp" + android:baselineAligned="false"> + - + - + diff --git a/app/src/main/res/layout/item_breadcrumb_current.xml b/app/src/main/res/layout/item_breadcrumb_current.xml new file mode 100644 index 000000000..d972e7ecc --- /dev/null +++ b/app/src/main/res/layout/item_breadcrumb_current.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index dad0ea830..cf77cf221 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -298,6 +298,8 @@ - diff --git a/fastlane/metadata/android/en-US/changelogs/92.txt b/fastlane/metadata/android/en-US/changelogs/92.txt index ff0dfcf68..c54828038 100644 --- a/fastlane/metadata/android/en-US/changelogs/92.txt +++ b/fastlane/metadata/android/en-US/changelogs/92.txt @@ -1,6 +1,8 @@ * Add breadcrumb * Add path in search results #1148 * Add group info dialog #1177 + * Add database color #913 * Fix UI in Android 8 #509 * Upgrade libs and SDK to 31 #833 - * Stop asking WRITE_EXTERNAL_STORAGE permission \ No newline at end of file + * Stop asking WRITE_EXTERNAL_STORAGE permission + * Fix parser of database v1 \ No newline at end of file diff --git a/fastlane/metadata/android/fr-FR/changelogs/92.txt b/fastlane/metadata/android/fr-FR/changelogs/92.txt index ecf180cc5..a215414e4 100644 --- a/fastlane/metadata/android/fr-FR/changelogs/92.txt +++ b/fastlane/metadata/android/fr-FR/changelogs/92.txt @@ -1,6 +1,8 @@ * Ajout d'un fil d'ariane * Ajout du chemin pour les résultats de recherche #1148 * Ajout d'un dialogue pour les informations de groupe #1177 + * Ajout de couleur de base de données #913 * Correction de l'interface utilisateur dans Android 8 #509 * Mise à jour des librairies et du SDK vers 31 #833 - * Ne demande plus la permission WRITE_EXTERNAL_STORAGE permission \ No newline at end of file + * Ne demande plus la permission WRITE_EXTERNAL_STORAGE permission + * Correction du parseur de la base de données v1 \ No newline at end of file From 12c07cf79305320b3041df92479734266ffcd9eb Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Sat, 8 Jan 2022 20:22:39 +0100 Subject: [PATCH 074/110] Fix refresh database metadata --- .../keepass/activities/GroupActivity.kt | 10 ++++++++- .../activities/stylish/StylishActivity.kt | 6 +++--- .../settings/NestedAppSettingsFragment.kt | 4 ++-- .../NestedDatabaseSettingsFragment.kt | 21 +++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index c7da55580..b8559e0a0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -418,7 +418,15 @@ class GroupActivity : DatabaseLockActivity(), // Search suggestion database?.let { databaseNameView?.text = if (it.name.isNotEmpty()) it.name else getString(R.string.database) - databaseColorView?.setColorFilter(Color.parseColor(it.customColor), PorterDuff.Mode.SRC_IN) + try { + databaseColorView?.visibility = View.VISIBLE + databaseColorView?.setColorFilter( + Color.parseColor(it.customColor), + PorterDuff.Mode.SRC_IN + ) + } catch (e: Exception) { + databaseColorView?.visibility = View.GONE + } mSearchSuggestionAdapter = SearchEntryCursorAdapter(this, it) mBreadcrumbAdapter?.iconDrawableFactory = it.iconDrawableFactory mOnSuggestionListener = object : SearchView.OnSuggestionListener { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/stylish/StylishActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/stylish/StylishActivity.kt index 15f76e4f6..32904c342 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/stylish/StylishActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/stylish/StylishActivity.kt @@ -28,7 +28,7 @@ import android.util.Log import android.view.WindowManager import androidx.annotation.StyleRes import androidx.appcompat.app.AppCompatActivity -import com.kunzisoft.keepass.settings.NestedAppSettingsFragment.Companion.DATABASE_APPEARANCE_PREFERENCE_CHANGED +import com.kunzisoft.keepass.settings.NestedAppSettingsFragment.Companion.DATABASE_PREFERENCE_CHANGED /** * Stylish Hide Activity that apply a dynamic style and sets FLAG_SECURE to prevent screenshots / from @@ -89,8 +89,8 @@ abstract class StylishActivity : AppCompatActivity() { super.onResume() if ((customStyle && Stylish.getThemeId(this) != this.themeId) - || DATABASE_APPEARANCE_PREFERENCE_CHANGED) { - DATABASE_APPEARANCE_PREFERENCE_CHANGED = false + || DATABASE_PREFERENCE_CHANGED) { + DATABASE_PREFERENCE_CHANGED = false Log.d(this.javaClass.name, "Theme change detected, restarting activity") recreateActivity() } diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt index 291d12379..10bbb3c8a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt @@ -452,7 +452,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { getString(R.string.show_uuid_key), getString(R.string.enable_education_screens_key), getString(R.string.reset_education_screens_key) -> { - DATABASE_APPEARANCE_PREFERENCE_CHANGED = true + DATABASE_PREFERENCE_CHANGED = true } } return super.onPreferenceTreeClick(preference) @@ -516,6 +516,6 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { companion object { private const val TAG_PREF_FRAGMENT = "TAG_PREF_FRAGMENT" - var DATABASE_APPEARANCE_PREFERENCE_CHANGED = false + var DATABASE_PREFERENCE_CHANGED = false } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt index 7072fb4d9..dcda198f1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt @@ -671,6 +671,27 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev } } + override fun onPreferenceTreeClick(preference: Preference?): Boolean { + // To reload group when database settings are modified + when (preference?.key) { + getString(R.string.database_name_key), + getString(R.string.database_description_key), + getString(R.string.database_default_username_key), + getString(R.string.database_custom_color_key), + getString(R.string.database_data_compression_key), + getString(R.string.database_data_remove_unlinked_attachments_key), + getString(R.string.recycle_bin_enable_key), + getString(R.string.recycle_bin_group_key), + getString(R.string.templates_group_enable_key), + getString(R.string.templates_group_uuid_key), + getString(R.string.max_history_items_key), + getString(R.string.max_history_size_key) -> { + NestedAppSettingsFragment.DATABASE_PREFERENCE_CHANGED = true + } + } + return super.onPreferenceTreeClick(preference) + } + companion object { private const val TAG_PREF_FRAGMENT = "TAG_PREF_FRAGMENT" } From f0f5258bc96ff70910a0cdad547b41f0c0b30f9a Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Sat, 8 Jan 2022 20:36:59 +0100 Subject: [PATCH 075/110] Fix refresh UI --- .../java/com/kunzisoft/keepass/activities/GroupActivity.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index b8559e0a0..8c8354aaa 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -328,9 +328,6 @@ class GroupActivity : DatabaseLockActivity(), } } - assignGroupViewElements(currentGroup) - invalidateOptionsMenu() - loadingView?.hideByFading() } @@ -597,9 +594,8 @@ class GroupActivity : DatabaseLockActivity(), setBreadcrumbNode(group) } } - - // Hide button initAddButton(group) + invalidateOptionsMenu() } private fun setBreadcrumbNode(group: Group?) { From c7b3e0926cd13584ac05e55aec7f73d11d11e278 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Sat, 8 Jan 2022 21:45:11 +0100 Subject: [PATCH 076/110] Fix save database color --- .../database/file/input/DatabaseInputKDB.kt | 9 ++++- .../database/file/output/DatabaseOutputKDB.kt | 35 ++++++++----------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDB.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDB.kt index 49f886f68..857d1c0cc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDB.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDB.kt @@ -20,6 +20,7 @@ package com.kunzisoft.keepass.database.file.input +import android.graphics.Color import com.kunzisoft.encrypt.HashManager import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm import com.kunzisoft.keepass.database.element.DateInstant @@ -311,7 +312,13 @@ class DatabaseInputKDB(cacheDirectory: File, var color: Int? = null entry.getBinary(mDatabase.attachmentPool) ?.getInputDataStream(mDatabase.binaryCache)?.use { - color = it.read() + val reverseColor = UnsignedInt(it.readBytes4ToUInt()).toKotlinInt() + color = Color.argb( + Color.alpha(255), + Color.blue(reverseColor), + Color.green(reverseColor), + Color.red(reverseColor) + ) } mDatabase.color = color } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDB.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDB.kt index 5a6fde286..07cd964b7 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDB.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDB.kt @@ -19,6 +19,7 @@ */ package com.kunzisoft.keepass.database.file.output +import android.graphics.Color import com.kunzisoft.encrypt.HashManager import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm import com.kunzisoft.keepass.database.element.database.DatabaseKDB @@ -47,9 +48,6 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB, private var mGroupList = mutableListOf() private var mEntryList = mutableListOf() - private var mDefaultUsernameAdded = false - private var mDatabaseColorAdded = false - @Throws(DatabaseOutputException::class) fun getFinalKey(header: DatabaseHeader): ByteArray? { try { @@ -216,7 +214,6 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB, private fun clearParser() { mGroupList.clear() mEntryList.clear() - mDefaultUsernameAdded = false } private fun sortNodesForOutput() { @@ -235,24 +232,14 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB, mGroupList.add(group) for (childEntry in group.getChildEntries()) { - if (childEntry.isMetaStreamDefaultUsername() - && mDatabaseKDB.defaultUserName.isNotEmpty()) { - setDefaultUsername(childEntry) - mEntryList.add(childEntry) - mDefaultUsernameAdded = true - } else if (childEntry.isMetaStreamDatabaseColor() - && mDatabaseKDB.color != null) { - setDatabaseColor(childEntry) - mEntryList.add(childEntry) - mDatabaseColorAdded = true - } else { + if (!childEntry.isMetaStreamDefaultUsername() + && !childEntry.isMetaStreamDatabaseColor()) { mEntryList.add(childEntry) } } // Add MetaStream - if (!mDefaultUsernameAdded - && mDatabaseKDB.defaultUserName.isNotEmpty()) { + if (mDatabaseKDB.defaultUserName.isNotEmpty()) { val metaEntry = EntryKDB().apply { setMetaStreamDefaultUsername() setDefaultUsername(this) @@ -260,8 +247,7 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB, mDatabaseKDB.addEntryTo(metaEntry, group) mEntryList.add(metaEntry) } - if (!mDatabaseColorAdded - && mDatabaseKDB.color != null) { + if (mDatabaseKDB.color != null) { val metaEntry = EntryKDB().apply { setMetaStreamDatabaseColor() setDatabaseColor(this) @@ -288,7 +274,16 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB, val binaryData = mDatabaseKDB.buildNewAttachment() entryKDB.putBinary(binaryData, mDatabaseKDB.attachmentPool) BufferedOutputStream(binaryData.getOutputDataStream(mDatabaseKDB.binaryCache)).use { outputStream -> - outputStream.write(mDatabaseKDB.color!!) + var reversColor = Color.BLACK + mDatabaseKDB.color?.let { + reversColor = Color.argb( + Color.alpha(255), + Color.blue(it), + Color.green(it), + Color.red(it) + ) + } + outputStream.write4BytesUInt(UnsignedInt(reversColor)) } } From a59f4d45ca5ce456636c34adc44ebcb701ac0a45 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Sat, 8 Jan 2022 22:29:43 +0100 Subject: [PATCH 077/110] Better color implementation --- .../keepass/activities/GroupActivity.kt | 8 +++---- .../keepass/database/element/Database.kt | 21 ++++++++++--------- .../database/element/database/DatabaseKDB.kt | 1 + .../database/file/input/DatabaseInputKDB.kt | 3 +-- .../database/file/output/DatabaseOutputKDB.kt | 3 +-- .../file/output/DatabaseOutputKDBX.kt | 1 - .../NestedDatabaseSettingsFragment.kt | 11 +++++----- ...baseColorPreferenceDialogFragmentCompat.kt | 13 ++++++------ ...abaseSavePreferenceDialogFragmentCompat.kt | 15 ++++++++++--- 9 files changed, 42 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index 8c8354aaa..5b8455680 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -25,7 +25,6 @@ import android.app.TimePickerDialog import android.content.ComponentName import android.content.Context import android.content.Intent -import android.graphics.Color import android.graphics.PorterDuff import android.os.* import android.util.Log @@ -415,13 +414,14 @@ class GroupActivity : DatabaseLockActivity(), // Search suggestion database?.let { databaseNameView?.text = if (it.name.isNotEmpty()) it.name else getString(R.string.database) - try { + val customColor = it.customColor + if (customColor != null) { databaseColorView?.visibility = View.VISIBLE databaseColorView?.setColorFilter( - Color.parseColor(it.customColor), + customColor, PorterDuff.Mode.SRC_IN ) - } catch (e: Exception) { + } else { databaseColorView?.visibility = View.GONE } mSearchSuggestionAdapter = SearchEntryCursorAdapter(this, it) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt index 550bda556..5e5c6def2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt @@ -236,22 +236,23 @@ class Database { mDatabaseKDBX?.defaultUserNameChanged = DateInstant() } - // with format "#000000" - var customColor: String + var customColor: Int? get() { - var colorString = "" - mDatabaseKDB?.color?.let { - colorString = ChromaUtil.getFormattedColorString(it, false) + var colorInt: Int? = null + mDatabaseKDBX?.color?.let { + try { + colorInt = Color.parseColor(it) + } catch (e: Exception) {} } - return mDatabaseKDBX?.color ?: colorString + return mDatabaseKDB?.color ?: colorInt } set(value) { - mDatabaseKDB?.color = if (value == "") { - null + mDatabaseKDB?.color = value + mDatabaseKDBX?.color = if (value == null) { + "" } else { - Color.parseColor(value) + ChromaUtil.getFormattedColorString(value, false) } - mDatabaseKDBX?.color = value } val allowOTP: Boolean diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDB.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDB.kt index 168c259b9..2bd047f8b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDB.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDB.kt @@ -62,6 +62,7 @@ class DatabaseKDB : DatabaseVersioned() { } var defaultUserName: String = "" + var color: Int? = null override val kdfEngine: KdfEngine diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDB.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDB.kt index 857d1c0cc..1411d8a3b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDB.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/input/DatabaseInputKDB.kt @@ -313,8 +313,7 @@ class DatabaseInputKDB(cacheDirectory: File, entry.getBinary(mDatabase.attachmentPool) ?.getInputDataStream(mDatabase.binaryCache)?.use { val reverseColor = UnsignedInt(it.readBytes4ToUInt()).toKotlinInt() - color = Color.argb( - Color.alpha(255), + color = Color.rgb( Color.blue(reverseColor), Color.green(reverseColor), Color.red(reverseColor) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDB.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDB.kt index 07cd964b7..9b92122ca 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDB.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDB.kt @@ -276,8 +276,7 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB, BufferedOutputStream(binaryData.getOutputDataStream(mDatabaseKDB.binaryCache)).use { outputStream -> var reversColor = Color.BLACK mDatabaseKDB.color?.let { - reversColor = Color.argb( - Color.alpha(255), + reversColor = Color.rgb( Color.blue(it), Color.green(it), Color.red(it) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDBX.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDBX.kt index 474e441b5..885b882a6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDBX.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/output/DatabaseOutputKDBX.kt @@ -48,7 +48,6 @@ import com.kunzisoft.keepass.database.file.DateKDBXUtil import com.kunzisoft.keepass.stream.HashedBlockOutputStream import com.kunzisoft.keepass.stream.HmacBlockOutputStream import com.kunzisoft.keepass.utils.* -import org.joda.time.DateTime import org.xmlpull.v1.XmlSerializer import java.io.IOException import java.io.OutputStream diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt index dcda198f1..a922ecd6b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt @@ -170,10 +170,11 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev // Database custom color dbCustomColorPref = findPreference(getString(R.string.database_custom_color_key)) dbCustomColorPref?.apply { - try { - color = Color.parseColor(database.customColor) - summary = database.customColor - } catch (e: Exception) { + val customColor = database.customColor + if (customColor != null) { + color = customColor + summary = ChromaUtil.getFormattedColorString(customColor, false) + } else{ color = DialogColorPreference.DISABLE_COLOR summary = "" } @@ -416,7 +417,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev if (result.isSuccess) { newColor } else { - mDatabase?.customColor = oldColor + mDatabase?.customColor = Color.parseColor(oldColor) oldColor } dbCustomColorPref?.summary = defaultColorToShow diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseColorPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseColorPreferenceDialogFragmentCompat.kt index 8eaeb9c0a..ebd20dd9f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseColorPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseColorPreferenceDialogFragmentCompat.kt @@ -30,7 +30,6 @@ import android.view.Window import android.widget.CompoundButton import androidx.annotation.ColorInt import androidx.appcompat.app.AlertDialog -import com.kunzisoft.androidclearchroma.ChromaUtil import com.kunzisoft.androidclearchroma.IndicatorMode import com.kunzisoft.androidclearchroma.colormode.ColorMode import com.kunzisoft.androidclearchroma.fragment.ChromaColorFragment @@ -77,12 +76,12 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog super.onDatabaseRetrieved(database) database?.let { - val initColor = try { + var initColor = it.customColor + if (initColor != null) { enableSwitchView.isChecked = true - Color.parseColor(it.customColor) - } catch (e: Exception) { + } else { enableSwitchView.isChecked = false - DEFAULT_COLOR + initColor = DEFAULT_COLOR } arguments?.putInt(ARG_INITIAL_COLOR, initColor) } @@ -107,9 +106,9 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog onColorSelectedListener?.invoke(customColorEnable, currentColor) database?.let { val newColor = if (customColorEnable) { - ChromaUtil.getFormattedColorString(currentColor, false) + currentColor } else { - "" + null } val oldColor = database.customColor database.customColor = newColor diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt index b10afb610..06a7bae25 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt @@ -22,6 +22,7 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment import android.content.Context import android.os.Bundle import androidx.fragment.app.activityViewModels +import com.kunzisoft.androidclearchroma.ChromaUtil import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine @@ -76,9 +77,17 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat // To inherit to save element in database } - protected fun saveColor(oldColor: String, - newColor: String) { - mDatabaseViewModel.saveColor(oldColor, newColor, mDatabaseAutoSaveEnable) + protected fun saveColor(oldColor: Int?, + newColor: Int?) { + val oldColorString = if (oldColor != null) + ChromaUtil.getFormattedColorString(oldColor, false) + else + "" + val newColorString = if (newColor != null) + ChromaUtil.getFormattedColorString(newColor, false) + else + "" + mDatabaseViewModel.saveColor(oldColorString, newColorString, mDatabaseAutoSaveEnable) } protected fun saveCompression(oldCompression: CompressionAlgorithm, From e9db24429a2abe2e7a604fe5d099dbe29f8b799d Mon Sep 17 00:00:00 2001 From: zeritti Date: Thu, 6 Jan 2022 15:05:07 +0000 Subject: [PATCH 078/110] Translated using Weblate (Czech) Currently translated at 100.0% (571 of 571 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/ --- app/src/main/res/values-cs/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index eef58049c..0a58b1bfe 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -602,4 +602,7 @@ Vyberte položku… Zobrazit možnosti umožňující uživateli si vybrat položku z databáze Ruční výběr + Jméno symbolu + Nepovolili jste aplikaci použít přesný alarm. Výsledkem je, že funkce požadující časovač nebudou provedeny v přesný okamžik. + Povolení \ No newline at end of file From 1874f06f421cfca791230e60f140b320d916dc39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Ng=E1=BB=8Dc=20=C4=90=E1=BB=A9c=20Huy?= Date: Fri, 7 Jan 2022 06:03:41 +0000 Subject: [PATCH 079/110] Translated using Weblate (Vietnamese) Currently translated at 29.4% (168 of 571 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/vi/ --- app/src/main/res/values-vi/strings.xml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 0caddd66e..be9d77dd9 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -51,7 +51,7 @@ Thêm trường Độ dài mật khẩu Trình tạo mật khẩu - Huỷ bỏ + Xoá Huỷ thay đổi\? Xác nhận Biểu tượng của mục @@ -150,4 +150,25 @@ Lưu một mục mới không được phép trong cơ sở dữ liệu chỉ đọc Tên trường đã tồn tại. Không thể truy xuất URI cơ sở dữ liệu. + Độ dài + Hiển thị tên người dùng + Độ dài + Mật khẩu + Mật khẩu + Sai thuật toán. + Không đọc được định dạng cơ sở dữ liệu. + Hãy cài đặt trình duyệt web để mở đường dẫn này. + Mở cơ sở dữ liệu có sẵn + Chữ thường + Ẩn mật khẩu + Có lỗi xảy ra khi tải dữ liệu từ tệp lên. + Dữ liệu trong tệp đã tồn tại. + Không thể tìm thấy tệp. Hãy thử mở lại bằng trình duyệt tệp của bạn. + Tạo mật khẩu + Xác nhận mật khẩu + Tệp bạn muốn tải lên quá lớn. + Mật khẩu được tạo + Tên nhóm + Mở + Có thể sửa \ No newline at end of file From ed16e06676ba390cd024048ae83f03033b501fb4 Mon Sep 17 00:00:00 2001 From: Matthaiks Date: Tue, 11 Jan 2022 05:55:14 +0000 Subject: [PATCH 080/110] Translated using Weblate (Polish) Currently translated at 100.0% (571 of 571 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/ --- app/src/main/res/values-pl/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 8f4b8a74c..11555e1dd 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -162,8 +162,8 @@ Aby wygenerować klucz dla algorytmu szyfrowania, klucz główny jest transformowany przy użyciu losowo solonej funkcji wyprowadzania klucza. Użycie pamięci Ilość pamięci do użycia przez funkcję wyprowadzania klucza. - Równoległy - Stopień równoległości (tj. Liczba wątków) wykorzystywany przez funkcję wyprowadzania klucza. + Równoległość + Stopień równoległości (tj. liczba wątków) wykorzystywany przez funkcję wyprowadzania klucza. Sortuj Od najniższej ↓ Nazwa Użytkownika From 6f172fffa8c377dbeb840a6005aa3a6fb1d5303f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Ng=E1=BB=8Dc=20=C4=90=E1=BB=A9c=20Huy?= Date: Tue, 11 Jan 2022 12:45:45 +0000 Subject: [PATCH 081/110] Translated using Weblate (Vietnamese) Currently translated at 29.5% (169 of 571 strings) Translation: KeePassDX/Strings Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/vi/ --- app/src/main/res/values-vi/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index be9d77dd9..26de2983b 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -171,4 +171,5 @@ Tên nhóm Mở Có thể sửa + Mặc định che mật khẩu (***) \ No newline at end of file From 6547f0ffadeb05683099219e9d57480ff1840c8a Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 11 Jan 2022 17:46:50 +0100 Subject: [PATCH 082/110] First entry color test --- .../main/res/layout/item_list_nodes_entry.xml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/app/src/main/res/layout/item_list_nodes_entry.xml b/app/src/main/res/layout/item_list_nodes_entry.xml index 4d250ab6b..377d7e2aa 100644 --- a/app/src/main/res/layout/item_list_nodes_entry.xml +++ b/app/src/main/res/layout/item_list_nodes_entry.xml @@ -56,6 +56,43 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintLeft_toLeftOf="parent" /> + + + + Date: Tue, 11 Jan 2022 18:02:43 +0100 Subject: [PATCH 083/110] Invert info container visibility --- .../keepass/activities/PasswordActivity.kt | 20 +++++++++---------- app/src/main/res/layout/activity_password.xml | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index 24067dd5e..79277962c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -101,15 +101,6 @@ class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.BuilderL private var mReadOnly: Boolean = false private var mForceReadOnly: Boolean = false - set(value) { - infoContainerView?.visibility = if (value) { - mReadOnly = true - View.VISIBLE - } else { - View.GONE - } - field = value - } private var mAutofillActivityResultLauncher: ActivityResultLauncher? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) @@ -204,10 +195,19 @@ class PasswordActivity : DatabaseModeActivity(), AdvancedUnlockFragment.BuilderL // Observe database file change mDatabaseFileViewModel.databaseFileLoaded.observe(this) { databaseFile -> + // Force read only if the file does not exists - mForceReadOnly = databaseFile?.let { + val databaseFileNotExists = databaseFile?.let { !it.databaseFileExists } ?: true + infoContainerView?.visibility = if (databaseFileNotExists) { + mReadOnly = true + View.VISIBLE + } else { + View.GONE + } + mForceReadOnly = databaseFileNotExists + invalidateOptionsMenu() // Post init uri with KeyFile only if needed diff --git a/app/src/main/res/layout/activity_password.xml b/app/src/main/res/layout/activity_password.xml index ee9e08253..d253d5624 100644 --- a/app/src/main/res/layout/activity_password.xml +++ b/app/src/main/res/layout/activity_password.xml @@ -220,6 +220,7 @@ android:id="@+id/activity_password_info_container" android:layout_width="match_parent" android:layout_height="wrap_content" + android:visibility="gone" android:orientation="vertical"> Date: Wed, 12 Jan 2022 14:19:04 +0100 Subject: [PATCH 084/110] Select entry colors --- .../keepass/activities/EntryEditActivity.kt | 11 +++ .../dialogs/ColorPickerDialogFragment.kt | 73 ++++++++++++++ .../activities/fragments/EntryEditFragment.kt | 14 +++ .../keepass/adapters/NodesAdapter.kt | 27 +++++- .../keepass/database/element/Entry.kt | 42 ++++++++ .../com/kunzisoft/keepass/model/EntryInfo.kt | 12 +++ .../keepass/view/TemplateAbstractView.kt | 4 + .../keepass/view/TemplateEditView.kt | 24 +++++ .../viewmodels/ColorPickerViewModel.kt | 15 +++ .../keepass/viewmodels/NodeEditViewModel.kt | 29 ++++++ .../ic_color_background_white_24dp.xml | 13 +++ .../ic_color_foreground_white_24dp.xml | 13 +++ app/src/main/res/layout/activity_group.xml | 2 +- .../main/res/layout/fragment_color_picker.xml | 50 ++++++++++ .../main/res/layout/item_list_nodes_entry.xml | 53 +++++----- app/src/main/res/layout/view_template.xml | 68 +++++++++---- app/src/main/res/values/strings.xml | 3 + art/ic_color_background.svg | 97 +++++++++++++++++++ art/ic_color_foreground.svg | 97 +++++++++++++++++++ 19 files changed, 593 insertions(+), 54 deletions(-) create mode 100644 app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ColorPickerDialogFragment.kt create mode 100644 app/src/main/java/com/kunzisoft/keepass/viewmodels/ColorPickerViewModel.kt create mode 100644 app/src/main/res/drawable/ic_color_background_white_24dp.xml create mode 100644 app/src/main/res/drawable/ic_color_foreground_white_24dp.xml create mode 100644 app/src/main/res/layout/fragment_color_picker.xml create mode 100644 art/ic_color_background.svg create mode 100644 art/ic_color_foreground.svg diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index db73bf28d..8fb0cad02 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -74,6 +74,7 @@ import com.kunzisoft.keepass.tasks.AttachmentFileBinderManager import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.UriUtil import com.kunzisoft.keepass.view.* +import com.kunzisoft.keepass.viewmodels.ColorPickerViewModel import com.kunzisoft.keepass.viewmodels.EntryEditViewModel import org.joda.time.DateTime import java.util.* @@ -103,6 +104,8 @@ class EntryEditActivity : DatabaseLockActivity(), private var mEntryLoaded: Boolean = false private var mTemplatesSelectorAdapter: TemplatesSelectorAdapter? = null + private val mColorPickerViewModel: ColorPickerViewModel by viewModels() + private var mAllowCustomFields = false private var mAllowOTP = false @@ -243,6 +246,14 @@ class EntryEditActivity : DatabaseLockActivity(), IconPickerActivity.launch(this@EntryEditActivity, iconImage, mIconSelectionActivityResultLauncher) } + mEntryEditViewModel.requestColorSelection.observe(this) { color -> + ColorPickerDialogFragment().show(supportFragmentManager, "ColorPickerFragment") + } + + mColorPickerViewModel.colorPicked.observe(this) { color -> + mEntryEditViewModel.selectColor(color) + } + mEntryEditViewModel.requestDateTimeSelection.observe(this) { dateInstant -> if (dateInstant.type == DateInstant.Type.TIME) { // Launch the time picker diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ColorPickerDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ColorPickerDialogFragment.kt new file mode 100644 index 000000000..e11010cbc --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ColorPickerDialogFragment.kt @@ -0,0 +1,73 @@ +package com.kunzisoft.keepass.activities.dialogs + +import android.app.Dialog +import android.graphics.Color +import android.os.Bundle +import android.widget.CompoundButton +import androidx.annotation.ColorInt +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.activityViewModels +import com.kunzisoft.androidclearchroma.view.ChromaColorView +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.viewmodels.ColorPickerViewModel + +class ColorPickerDialogFragment : DatabaseDialogFragment() { + + private val mColorPickerViewModel: ColorPickerViewModel by activityViewModels() + + private lateinit var enableSwitchView: CompoundButton + private lateinit var chromaColorView: ChromaColorView + + private var mDefaultColor = Color.WHITE + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + + activity?.let { activity -> + val root = activity.layoutInflater.inflate(R.layout.fragment_color_picker, null) + enableSwitchView = root.findViewById(R.id.switch_element) + chromaColorView = root.findViewById(R.id.chroma_color_view) + + var activated = false + arguments?.apply { + if (containsKey(ARG_INITIAL_COLOR)) { + mDefaultColor = getInt(ARG_INITIAL_COLOR) + } + if (containsKey(ARG_ACTIVATED)) { + activated = getBoolean(ARG_ACTIVATED) + } + } + enableSwitchView.isChecked = activated + + val builder = AlertDialog.Builder(activity) + builder.setView(root) + .setPositiveButton(android.R.string.ok) { _, _ -> + val color: Int? = if (enableSwitchView.isChecked) + chromaColorView.currentColor + else + null + mColorPickerViewModel.pickColor(color) + } + .setNegativeButton(android.R.string.cancel) { _, _ -> + // Do nothing + } + + return builder.create() + } + return super.onCreateDialog(savedInstanceState) + } + + companion object { + private const val ARG_INITIAL_COLOR = "ARG_INITIAL_COLOR" + private const val ARG_ACTIVATED = "ARG_ACTIVATED" + + fun newInstance( + @ColorInt initialColor: Int?, + ): ColorPickerDialogFragment { + val colorPickerDialogFragment = ColorPickerDialogFragment() + val args = Bundle() + args.putInt(ARG_INITIAL_COLOR, initialColor ?: Color.WHITE) + args.putBoolean(ARG_ACTIVATED, initialColor != null) + return colorPickerDialogFragment + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/fragments/EntryEditFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/fragments/EntryEditFragment.kt index 1d8bea4bf..4f31ad15a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/fragments/EntryEditFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/fragments/EntryEditFragment.kt @@ -99,6 +99,12 @@ class EntryEditFragment: DatabaseFragment() { setOnIconClickListener { mEntryEditViewModel.requestIconSelection(templateView.getIcon()) } + setOnBackgroundColorClickListener { + mEntryEditViewModel.requestBackgroundColorSelection(templateView.getBackgroundColor()) + } + setOnForegroundColorClickListener { + mEntryEditViewModel.requestForegroundColorSelection(templateView.getForegroundColor()) + } setOnCustomEditionActionClickListener { field -> mEntryEditViewModel.requestCustomFieldEdition(field) } @@ -147,6 +153,14 @@ class EntryEditFragment: DatabaseFragment() { templateView.setIcon(iconImage) } + mEntryEditViewModel.onBackgroundColorSelected.observe(this) { color -> + templateView.setBackgroundColor(color) + } + + mEntryEditViewModel.onForegroundColorSelected.observe(this) { color -> + templateView.setForegroundColor(color) + } + mEntryEditViewModel.onPasswordSelected.observe(viewLifecycleOwner) { passwordField -> templateView.setPasswordField(passwordField) } diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt index 6018b49bd..892301c39 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt @@ -21,6 +21,7 @@ package com.kunzisoft.keepass.adapters import android.content.Context import android.graphics.Color +import android.graphics.PorterDuff import android.util.TypedValue import android.view.LayoutInflater import android.view.View @@ -31,6 +32,7 @@ import android.widget.TextView import android.widget.Toast import androidx.annotation.ColorInt import androidx.core.content.ContextCompat +import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.SortedList import androidx.recyclerview.widget.SortedListAdapterCallback @@ -39,7 +41,9 @@ import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.Entry import com.kunzisoft.keepass.database.element.Group import com.kunzisoft.keepass.database.element.SortNodeEnum -import com.kunzisoft.keepass.database.element.node.* +import com.kunzisoft.keepass.database.element.node.Node +import com.kunzisoft.keepass.database.element.node.NodeVersionedInterface +import com.kunzisoft.keepass.database.element.node.Type import com.kunzisoft.keepass.database.element.template.TemplateField import com.kunzisoft.keepass.otp.OtpElement import com.kunzisoft.keepass.otp.OtpType @@ -377,6 +381,25 @@ class NodesAdapter (private val context: Context, val entry = subNode as Entry database.startManageEntry(entry) + // Assign colors + val backgroundColor = entry.backgroundColor + if (backgroundColor != null) { + holder.backgroundView?.setColorFilter(backgroundColor, PorterDuff.Mode.SRC_ATOP) + holder.backgroundView?.isVisible = true + } else { + holder.backgroundView?.isVisible = false + } + val foregroundColor = entry.foregroundColor + if (foregroundColor != null) { + holder.foregroundView?.setColorFilter(foregroundColor, PorterDuff.Mode.SRC_ATOP) + holder.icon.apply { + database.iconDrawableFactory.assignDatabaseIcon(this, subNode.icon, foregroundColor) + } + holder.foregroundView?.isVisible = true + } else { + holder.foregroundView?.isVisible = false + } + holder.text.text = entry.getVisualTitle() // Add subText with username holder.subText?.apply { @@ -510,6 +533,8 @@ class NodesAdapter (private val context: Context, var container: View = itemView.findViewById(R.id.node_container) var imageIdentifier: ImageView? = itemView.findViewById(R.id.node_image_identifier) var icon: ImageView = itemView.findViewById(R.id.node_icon) + var backgroundView: ImageView? = itemView.findViewById(R.id.background_view) + var foregroundView: ImageView? = itemView.findViewById(R.id.foreground_view) var text: TextView = itemView.findViewById(R.id.node_text) var subText: TextView? = itemView.findViewById(R.id.node_subtext) var meta: TextView = itemView.findViewById(R.id.node_meta) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt index 83e2707a0..65bcef378 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt @@ -19,8 +19,10 @@ */ package com.kunzisoft.keepass.database.element +import android.graphics.Color import android.os.Parcel import android.os.Parcelable +import com.kunzisoft.androidclearchroma.ChromaUtil import com.kunzisoft.keepass.database.element.binary.AttachmentPool import com.kunzisoft.keepass.database.element.database.DatabaseKDBX import com.kunzisoft.keepass.database.element.database.DatabaseVersioned @@ -238,6 +240,42 @@ class Entry : Node, EntryVersionedInterface { entryKDBX?.notes = value } + var backgroundColor: Int? + get() { + var colorInt: Int? = null + entryKDBX?.backgroundColor?.let { + try { + colorInt = Color.parseColor(it) + } catch (e: Exception) {} + } + return colorInt + } + set(value) { + entryKDBX?.backgroundColor = if (value == null) { + "" + } else { + ChromaUtil.getFormattedColorString(value, false) + } + } + + var foregroundColor: Int? + get() { + var colorInt: Int? = null + entryKDBX?.foregroundColor?.let { + try { + colorInt = Color.parseColor(it) + } catch (e: Exception) {} + } + return colorInt + } + set(value) { + entryKDBX?.foregroundColor = if (value == null) { + "" + } else { + ChromaUtil.getFormattedColorString(value, false) + } + } + private fun isTan(): Boolean { return title == PMS_TAN_ENTRY && username.isNotEmpty() } @@ -419,6 +457,8 @@ class Entry : Node, EntryVersionedInterface { entryInfo.expiryTime = expiryTime entryInfo.url = url entryInfo.notes = notes + entryInfo.backgroundColor = backgroundColor + entryInfo.foregroundColor = foregroundColor entryInfo.customFields = getExtraFields().toMutableList() // Add otpElement to generate token entryInfo.otpModel = getOtpElement()?.otpModel @@ -453,6 +493,8 @@ class Entry : Node, EntryVersionedInterface { expiryTime = newEntryInfo.expiryTime url = newEntryInfo.url notes = newEntryInfo.notes + backgroundColor = newEntryInfo.backgroundColor + foregroundColor = newEntryInfo.foregroundColor addExtraFields(newEntryInfo.customFields) database?.attachmentPool?.let { binaryPool -> newEntryInfo.attachments.forEach { attachment -> diff --git a/app/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt b/app/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt index 9324ea9a8..5ae5fc0fc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt +++ b/app/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt @@ -40,6 +40,8 @@ class EntryInfo : NodeInfo { var password: String = "" var url: String = "" var notes: String = "" + var backgroundColor: Int? = null + var foregroundColor: Int? = null var customFields: MutableList = mutableListOf() var attachments: MutableList = mutableListOf() var otpModel: OtpModel? = null @@ -53,6 +55,10 @@ class EntryInfo : NodeInfo { password = parcel.readString() ?: password url = parcel.readString() ?: url notes = parcel.readString() ?: notes + val readBgColor = parcel.readInt() + backgroundColor = if (readBgColor == -1) null else readBgColor + val readFgColor = parcel.readInt() + foregroundColor = if (readFgColor == -1) null else readFgColor parcel.readList(customFields, Field::class.java.classLoader) parcel.readList(attachments, Attachment::class.java.classLoader) otpModel = parcel.readParcelable(OtpModel::class.java.classLoader) ?: otpModel @@ -70,6 +76,8 @@ class EntryInfo : NodeInfo { parcel.writeString(password) parcel.writeString(url) parcel.writeString(notes) + parcel.writeInt(backgroundColor ?: -1) + parcel.writeInt(foregroundColor ?: -1) parcel.writeList(customFields) parcel.writeList(attachments) parcel.writeParcelable(otpModel, flags) @@ -196,6 +204,8 @@ class EntryInfo : NodeInfo { if (password != other.password) return false if (url != other.url) return false if (notes != other.notes) return false + if (backgroundColor != other.backgroundColor) return false + if (foregroundColor != other.foregroundColor) return false if (customFields != other.customFields) return false if (attachments != other.attachments) return false if (otpModel != other.otpModel) return false @@ -211,6 +221,8 @@ class EntryInfo : NodeInfo { result = 31 * result + password.hashCode() result = 31 * result + url.hashCode() result = 31 * result + notes.hashCode() + result = 31 * result + backgroundColor.hashCode() + result = 31 * result + foregroundColor.hashCode() result = 31 * result + customFields.hashCode() result = 31 * result + attachments.hashCode() result = 31 * result + (otpModel?.hashCode() ?: 0) diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt index 5a8697daa..c8271d7d3 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt @@ -46,6 +46,8 @@ abstract class TemplateAbstractView< protected var headerContainerView: ViewGroup protected var entryIconView: ImageView + protected var backgroundColorButton: ImageView + protected var foregroundColorButton: ImageView private var titleContainerView: ViewGroup protected var templateContainerView: ViewGroup private var customFieldsContainerView: SectionView @@ -57,6 +59,8 @@ abstract class TemplateAbstractView< headerContainerView = findViewById(R.id.template_header_container) entryIconView = findViewById(R.id.template_icon_button) + backgroundColorButton = findViewById(R.id.template_background_color_button) + foregroundColorButton = findViewById(R.id.template_foreground_color_button) titleContainerView = findViewById(R.id.template_title_container) templateContainerView = findViewById(R.id.template_fields_container) // To fix card view margin below Marshmallow diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt index d3918be16..e2a32b0fd 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt @@ -54,6 +54,30 @@ class TemplateEditView @JvmOverloads constructor(context: Context, populateIconMethod?.invoke(entryIconView, iconImage) } + fun setOnBackgroundColorClickListener(onClickListener: OnClickListener) { + backgroundColorButton.setOnClickListener(onClickListener) + } + + fun getBackgroundColor(): Int? { + return mEntryInfo?.backgroundColor + } + + fun setBackgroundColor(color: Int?) { + mEntryInfo?.backgroundColor = color + } + + fun setOnForegroundColorClickListener(onClickListener: OnClickListener) { + foregroundColorButton.setOnClickListener(onClickListener) + } + + fun getForegroundColor(): Int? { + return mEntryInfo?.foregroundColor + } + + fun setForegroundColor(color: Int?) { + mEntryInfo?.foregroundColor = color + } + override fun preProcessTemplate() { headerContainerView.isVisible = true } diff --git a/app/src/main/java/com/kunzisoft/keepass/viewmodels/ColorPickerViewModel.kt b/app/src/main/java/com/kunzisoft/keepass/viewmodels/ColorPickerViewModel.kt new file mode 100644 index 000000000..282e3f425 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/viewmodels/ColorPickerViewModel.kt @@ -0,0 +1,15 @@ +package com.kunzisoft.keepass.viewmodels + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class ColorPickerViewModel: ViewModel() { + + val colorPicked : LiveData get() = _colorPicked + private val _colorPicked = MutableLiveData() + + fun pickColor(color: Int?) { + _colorPicked.value = color + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/viewmodels/NodeEditViewModel.kt b/app/src/main/java/com/kunzisoft/keepass/viewmodels/NodeEditViewModel.kt index 80d9ea79a..4c55af246 100644 --- a/app/src/main/java/com/kunzisoft/keepass/viewmodels/NodeEditViewModel.kt +++ b/app/src/main/java/com/kunzisoft/keepass/viewmodels/NodeEditViewModel.kt @@ -14,6 +14,14 @@ abstract class NodeEditViewModel : ViewModel() { val onIconSelected : LiveData get() = _onIconSelected private val _onIconSelected = SingleLiveEvent() + private var mColorRequest: ColorRequest = ColorRequest.BACKGROUND + val requestColorSelection : LiveData get() = _requestColorSelection + private val _requestColorSelection = SingleLiveEvent() + val onBackgroundColorSelected : LiveData get() = _onBackgroundColorSelected + private val _onBackgroundColorSelected = SingleLiveEvent() + val onForegroundColorSelected : LiveData get() = _onForegroundColorSelected + private val _onForegroundColorSelected = SingleLiveEvent() + val requestDateTimeSelection : LiveData get() = _requestDateTimeSelection private val _requestDateTimeSelection = SingleLiveEvent() val onDateSelected : LiveData get() = _onDateSelected @@ -29,6 +37,23 @@ abstract class NodeEditViewModel : ViewModel() { _onIconSelected.value = iconImage } + fun requestBackgroundColorSelection(initialColor: Int?) { + mColorRequest = ColorRequest.BACKGROUND + _requestColorSelection.value = initialColor + } + + fun requestForegroundColorSelection(initialColor: Int?) { + mColorRequest = ColorRequest.FOREGROUND + _requestColorSelection.value = initialColor + } + + fun selectColor(color: Int?) { + when (mColorRequest) { + ColorRequest.BACKGROUND -> _onBackgroundColorSelected.value = color + ColorRequest.FOREGROUND -> _onForegroundColorSelected.value = color + } + } + fun requestDateTimeSelection(dateInstant: DateInstant) { _requestDateTimeSelection.value = dateInstant } @@ -40,4 +65,8 @@ abstract class NodeEditViewModel : ViewModel() { fun selectTime(hours: Int, minutes: Int) { _onTimeSelected.value = DataTime(hours, minutes) } + + private enum class ColorRequest { + BACKGROUND, FOREGROUND + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_color_background_white_24dp.xml b/app/src/main/res/drawable/ic_color_background_white_24dp.xml new file mode 100644 index 000000000..ea4549a72 --- /dev/null +++ b/app/src/main/res/drawable/ic_color_background_white_24dp.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_color_foreground_white_24dp.xml b/app/src/main/res/drawable/ic_color_foreground_white_24dp.xml new file mode 100644 index 000000000..558ef76ec --- /dev/null +++ b/app/src/main/res/drawable/ic_color_foreground_white_24dp.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_group.xml b/app/src/main/res/layout/activity_group.xml index 7d0372d8d..3edfdcbd6 100644 --- a/app/src/main/res/layout/activity_group.xml +++ b/app/src/main/res/layout/activity_group.xml @@ -51,7 +51,7 @@ android:src="@drawable/background_rounded_square" android:layout_marginRight="6dp" android:layout_marginEnd="6dp" - android:contentDescription="@string/database"/> + android:contentDescription="@string/content_description_database_color"/> + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_list_nodes_entry.xml b/app/src/main/res/layout/item_list_nodes_entry.xml index 377d7e2aa..e32c28440 100644 --- a/app/src/main/res/layout/item_list_nodes_entry.xml +++ b/app/src/main/res/layout/item_list_nodes_entry.xml @@ -38,6 +38,20 @@ app:layout_constraintEnd_toEndOf="parent" android:background="?android:attr/selectableItemBackground" > + + - - + android:contentDescription="@string/content_description_entry_foreground_color" + android:src="@drawable/background_rounded_square" /> . --> - - + + android:layout_height="wrap_content"> + - - + + + + + + - - - - + android:layout_gravity="end"> + + + + Keyfile checkbox Repeat toggle password visibility Entry icon + Database color + Entry foreground color + Entry background color Validate Discard changes? Discard diff --git a/art/ic_color_background.svg b/art/ic_color_background.svg new file mode 100644 index 000000000..76548ca12 --- /dev/null +++ b/art/ic_color_background.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/art/ic_color_foreground.svg b/art/ic_color_foreground.svg new file mode 100644 index 000000000..db19395c5 --- /dev/null +++ b/art/ic_color_foreground.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + From 05fad24edaa36c61e0df43721d7265a06da8bfdb Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Wed, 12 Jan 2022 17:01:35 +0100 Subject: [PATCH 085/110] Fix color picker fragment --- .../keepass/activities/EntryEditActivity.kt | 3 +- .../dialogs/ColorPickerDialogFragment.kt | 41 +++++++++++++------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index 8fb0cad02..3afc45150 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -247,7 +247,8 @@ class EntryEditActivity : DatabaseLockActivity(), } mEntryEditViewModel.requestColorSelection.observe(this) { color -> - ColorPickerDialogFragment().show(supportFragmentManager, "ColorPickerFragment") + ColorPickerDialogFragment.newInstance(color) + .show(supportFragmentManager, "ColorPickerFragment") } mColorPickerViewModel.colorPicked.observe(this) { color -> diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ColorPickerDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ColorPickerDialogFragment.kt index e11010cbc..180a81a53 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ColorPickerDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ColorPickerDialogFragment.kt @@ -19,6 +19,7 @@ class ColorPickerDialogFragment : DatabaseDialogFragment() { private lateinit var chromaColorView: ChromaColorView private var mDefaultColor = Color.WHITE + private var mActivated = false override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { @@ -27,16 +28,25 @@ class ColorPickerDialogFragment : DatabaseDialogFragment() { enableSwitchView = root.findViewById(R.id.switch_element) chromaColorView = root.findViewById(R.id.chroma_color_view) - var activated = false - arguments?.apply { - if (containsKey(ARG_INITIAL_COLOR)) { - mDefaultColor = getInt(ARG_INITIAL_COLOR) + if (savedInstanceState != null) { + if (savedInstanceState.containsKey(ARG_INITIAL_COLOR)) { + mDefaultColor = savedInstanceState.getInt(ARG_INITIAL_COLOR) } - if (containsKey(ARG_ACTIVATED)) { - activated = getBoolean(ARG_ACTIVATED) + if (savedInstanceState.containsKey(ARG_ACTIVATED)) { + mActivated = savedInstanceState.getBoolean(ARG_ACTIVATED) + } + } else { + arguments?.apply { + if (containsKey(ARG_INITIAL_COLOR)) { + mDefaultColor = getInt(ARG_INITIAL_COLOR) + } + if (containsKey(ARG_ACTIVATED)) { + mActivated = getBoolean(ARG_ACTIVATED) + } } } - enableSwitchView.isChecked = activated + enableSwitchView.isChecked = mActivated + chromaColorView.currentColor = mDefaultColor val builder = AlertDialog.Builder(activity) builder.setView(root) @@ -56,6 +66,12 @@ class ColorPickerDialogFragment : DatabaseDialogFragment() { return super.onCreateDialog(savedInstanceState) } + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + outState.putInt(ARG_INITIAL_COLOR, chromaColorView.currentColor) + outState.putBoolean(ARG_ACTIVATED, mActivated) + } + companion object { private const val ARG_INITIAL_COLOR = "ARG_INITIAL_COLOR" private const val ARG_ACTIVATED = "ARG_ACTIVATED" @@ -63,11 +79,12 @@ class ColorPickerDialogFragment : DatabaseDialogFragment() { fun newInstance( @ColorInt initialColor: Int?, ): ColorPickerDialogFragment { - val colorPickerDialogFragment = ColorPickerDialogFragment() - val args = Bundle() - args.putInt(ARG_INITIAL_COLOR, initialColor ?: Color.WHITE) - args.putBoolean(ARG_ACTIVATED, initialColor != null) - return colorPickerDialogFragment + return ColorPickerDialogFragment().apply { + arguments = Bundle().apply { + putInt(ARG_INITIAL_COLOR, initialColor ?: Color.WHITE) + putBoolean(ARG_ACTIVATED, initialColor != null) + } + } } } } \ No newline at end of file From cfdc0237d70171b566c088abd72bb9b680188a8a Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Wed, 12 Jan 2022 19:50:38 +0100 Subject: [PATCH 086/110] Add foreground and background colors in list --- .../keepass/adapters/NodesAdapter.kt | 122 +++++++++++++----- .../keepass/view/TemplateEditView.kt | 14 ++ app/src/main/res/layout/item_icon.xml | 2 +- .../main/res/layout/item_list_nodes_entry.xml | 105 ++++++--------- app/src/main/res/layout/view_template.xml | 47 ++++--- app/src/main/res/values/styles.xml | 11 +- 6 files changed, 173 insertions(+), 128 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt index 892301c39..c81171923 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt @@ -21,7 +21,6 @@ package com.kunzisoft.keepass.adapters import android.content.Context import android.graphics.Color -import android.graphics.PorterDuff import android.util.TypedValue import android.view.LayoutInflater import android.view.View @@ -32,10 +31,10 @@ import android.widget.TextView import android.widget.Toast import androidx.annotation.ColorInt import androidx.core.content.ContextCompat -import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.SortedList import androidx.recyclerview.widget.SortedListAdapterCallback +import com.google.android.material.progressindicator.CircularProgressIndicator import com.kunzisoft.keepass.R import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.Entry @@ -91,9 +90,15 @@ class NodesAdapter (private val context: Context, @ColorInt private val mContentSelectionColor: Int @ColorInt - private val mIconGroupColor: Int + private val mTextColorPrimary: Int @ColorInt - private val mIconEntryColor: Int + private val mTextColor: Int + @ColorInt + private val mTextColorSecondary: Int + @ColorInt + private val mColorAccentLight: Int + @ColorInt + private val mTextColorInverse: Int /** * Determine if the adapter contains or not any element @@ -114,12 +119,24 @@ class NodesAdapter (private val context: Context, this.mContentSelectionColor = ContextCompat.getColor(context, R.color.white) // Retrieve the color to tint the icon val taTextColorPrimary = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColorPrimary)) - this.mIconGroupColor = taTextColorPrimary.getColor(0, Color.BLACK) + this.mTextColorPrimary = taTextColorPrimary.getColor(0, Color.BLACK) taTextColorPrimary.recycle() - // In two times to fix bug compilation + // To get text color val taTextColor = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColor)) - this.mIconEntryColor = taTextColor.getColor(0, Color.BLACK) + this.mTextColor = taTextColor.getColor(0, Color.BLACK) taTextColor.recycle() + // To get text color secondary + val taTextColorSecondary = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColorSecondary)) + this.mTextColorSecondary = taTextColorSecondary.getColor(0, Color.BLACK) + taTextColorSecondary.recycle() + // To get background color for selection + val taSelectionColor = context.theme.obtainStyledAttributes(intArrayOf(R.attr.colorAccentLight)) + this.mColorAccentLight = taSelectionColor.getColor(0, Color.GRAY) + taSelectionColor.recycle() + // To get text color for selection + val taSelectionTextColor = context.theme.obtainStyledAttributes(intArrayOf(R.attr.textColorInverse)) + this.mTextColorInverse = taSelectionTextColor.getColor(0, Color.WHITE) + taSelectionTextColor.recycle() } private fun assignPreferences() { @@ -167,6 +184,8 @@ class NodesAdapter (private val context: Context, if (oldItem is Entry && newItem is Entry) { typeContentTheSame = oldItem.getVisualTitle() == newItem.getVisualTitle() && oldItem.username == newItem.username + && oldItem.backgroundColor == newItem.backgroundColor + && oldItem.foregroundColor == newItem.foregroundColor && oldItem.getOtpElement() == newItem.getOtpElement() && oldItem.containsAttachment() == newItem.containsAttachment() } else if (oldItem is Group && newItem is Group) { @@ -336,8 +355,8 @@ class NodesAdapter (private val context: Context, val iconColor = if (holder.container.isSelected) mContentSelectionColor else when (subNode.type) { - Type.GROUP -> mIconGroupColor - Type.ENTRY -> mIconEntryColor + Type.GROUP -> mTextColorPrimary + Type.ENTRY -> mTextColor } holder.imageIdentifier?.setColorFilter(iconColor) holder.icon.apply { @@ -381,25 +400,6 @@ class NodesAdapter (private val context: Context, val entry = subNode as Entry database.startManageEntry(entry) - // Assign colors - val backgroundColor = entry.backgroundColor - if (backgroundColor != null) { - holder.backgroundView?.setColorFilter(backgroundColor, PorterDuff.Mode.SRC_ATOP) - holder.backgroundView?.isVisible = true - } else { - holder.backgroundView?.isVisible = false - } - val foregroundColor = entry.foregroundColor - if (foregroundColor != null) { - holder.foregroundView?.setColorFilter(foregroundColor, PorterDuff.Mode.SRC_ATOP) - holder.icon.apply { - database.iconDrawableFactory.assignDatabaseIcon(this, subNode.icon, foregroundColor) - } - holder.foregroundView?.isVisible = true - } else { - holder.foregroundView?.isVisible = false - } - holder.text.text = entry.getVisualTitle() // Add subText with username holder.subText?.apply { @@ -436,6 +436,64 @@ class NodesAdapter (private val context: Context, holder.attachmentIcon?.visibility = if (entry.containsAttachment()) View.VISIBLE else View.GONE + // Assign colors + val backgroundColor = entry.backgroundColor + if (!holder.container.isSelected) { + if (backgroundColor != null) { + holder.container.setBackgroundColor(backgroundColor) + } else { + holder.container.setBackgroundColor(Color.TRANSPARENT) + } + } else { + holder.container.setBackgroundColor(mColorAccentLight) + } + val foregroundColor = entry.foregroundColor + if (!holder.container.isSelected) { + if (foregroundColor != null) { + holder.text.setTextColor(foregroundColor) + holder.subText?.setTextColor(foregroundColor) + holder.otpToken?.setTextColor(foregroundColor) + holder.otpProgress?.setIndicatorColor(foregroundColor) + holder.attachmentIcon?.setColorFilter(foregroundColor) + holder.meta.setTextColor(foregroundColor) + holder.icon.apply { + database.iconDrawableFactory.assignDatabaseIcon( + this, + subNode.icon, + foregroundColor + ) + } + } else { + holder.text.setTextColor(mTextColor) + holder.subText?.setTextColor(mTextColorSecondary) + holder.otpToken?.setTextColor(mTextColorSecondary) + holder.otpProgress?.setIndicatorColor(mTextColorSecondary) + holder.attachmentIcon?.setColorFilter(mTextColorSecondary) + holder.meta.setTextColor(mTextColor) + holder.icon.apply { + database.iconDrawableFactory.assignDatabaseIcon( + this, + subNode.icon, + mTextColor + ) + } + } + } else { + holder.text.setTextColor(mTextColorInverse) + holder.subText?.setTextColor(mTextColorInverse) + holder.otpToken?.setTextColor(mTextColorInverse) + holder.otpProgress?.setIndicatorColor(mTextColorInverse) + holder.attachmentIcon?.setColorFilter(mTextColorInverse) + holder.meta.setTextColor(mTextColorInverse) + holder.icon.apply { + database.iconDrawableFactory.assignDatabaseIcon( + this, + subNode.icon, + mTextColorInverse + ) + } + } + database.stopManageEntry(entry) } @@ -468,13 +526,13 @@ class NodesAdapter (private val context: Context, OtpType.HOTP -> { holder?.otpProgress?.apply { max = 100 - progress = 100 + setProgressCompat(100, true) } } OtpType.TOTP -> { holder?.otpProgress?.apply { max = otpElement.period - progress = otpElement.secondsRemaining + setProgressCompat(otpElement.secondsRemaining, true) } } null -> {} @@ -533,14 +591,12 @@ class NodesAdapter (private val context: Context, var container: View = itemView.findViewById(R.id.node_container) var imageIdentifier: ImageView? = itemView.findViewById(R.id.node_image_identifier) var icon: ImageView = itemView.findViewById(R.id.node_icon) - var backgroundView: ImageView? = itemView.findViewById(R.id.background_view) - var foregroundView: ImageView? = itemView.findViewById(R.id.foreground_view) var text: TextView = itemView.findViewById(R.id.node_text) var subText: TextView? = itemView.findViewById(R.id.node_subtext) var meta: TextView = itemView.findViewById(R.id.node_meta) var path: TextView? = itemView.findViewById(R.id.node_path) var otpContainer: ViewGroup? = itemView.findViewById(R.id.node_otp_container) - var otpProgress: ProgressBar? = itemView.findViewById(R.id.node_otp_progress) + var otpProgress: CircularProgressIndicator? = itemView.findViewById(R.id.node_otp_progress) var otpToken: TextView? = itemView.findViewById(R.id.node_otp_token) var otpRunnable: OtpRunnable = OtpRunnable(otpContainer) var numberChildren: TextView? = itemView.findViewById(R.id.node_child_numbers) diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt index e2a32b0fd..7d5c76a06 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt @@ -1,6 +1,8 @@ package com.kunzisoft.keepass.view import android.content.Context +import android.graphics.PorterDuff +import android.graphics.PorterDuffColorFilter import android.os.Build import android.util.AttributeSet import android.view.View @@ -63,6 +65,9 @@ class TemplateEditView @JvmOverloads constructor(context: Context, } fun setBackgroundColor(color: Int?) { + color?.let { + backgroundColorButton.colorFilter = PorterDuffColorFilter(it, PorterDuff.Mode.SRC_ATOP) + } mEntryInfo?.backgroundColor = color } @@ -75,6 +80,9 @@ class TemplateEditView @JvmOverloads constructor(context: Context, } fun setForegroundColor(color: Int?) { + color?.let { + foregroundColorButton.colorFilter = PorterDuffColorFilter(it, PorterDuff.Mode.SRC_ATOP) + } mEntryInfo?.foregroundColor = color } @@ -220,6 +228,12 @@ class TemplateEditView @JvmOverloads constructor(context: Context, override fun populateViewsWithEntryInfo(showEmptyFields: Boolean): List { refreshIcon() + mEntryInfo?.backgroundColor?.let { + backgroundColorButton.colorFilter = PorterDuffColorFilter(it, PorterDuff.Mode.SRC_ATOP) + } + mEntryInfo?.foregroundColor?.let { + foregroundColorButton.colorFilter = PorterDuffColorFilter(it, PorterDuff.Mode.SRC_ATOP) + } return super.populateViewsWithEntryInfo(showEmptyFields) } diff --git a/app/src/main/res/layout/item_icon.xml b/app/src/main/res/layout/item_icon.xml index b854e916e..9e6469044 100644 --- a/app/src/main/res/layout/item_icon.xml +++ b/app/src/main/res/layout/item_icon.xml @@ -22,7 +22,7 @@ android:id="@+id/icon_container" android:layout_width="match_parent" android:layout_height="80dp" - android:background="@drawable/background_item_selection"> + style="@style/KeepassDXStyle.Selectable.Item"> - - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_percent="@dimen/content_percent"> - - + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintLeft_toRightOf="@+id/node_icon" + app:layout_constraintRight_toLeftOf="@+id/node_options" + app:layout_constraintStart_toEndOf="@+id/node_icon" + app:layout_constraintTop_toTopOf="parent"> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent"> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent"> + - + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:indicatorSize="16dp" + app:trackThickness="2dp" + app:indicatorDirectionCircular="counterclockwise" + android:layout_gravity="center" /> @@ -207,12 +182,12 @@ + android:layout_marginRight="48dp" + android:background="?android:attr/listDivider" + app:layout_constraintBottom_toBottomOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/view_template.xml b/app/src/main/res/layout/view_template.xml index 8b15faf89..d07d12258 100644 --- a/app/src/main/res/layout/view_template.xml +++ b/app/src/main/res/layout/view_template.xml @@ -33,6 +33,26 @@ + + + + + android:layout_gravity="center" + android:contentDescription="@string/content_description_entry_icon"/> - - - - diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 621de6eca..0155638e0 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -436,6 +436,13 @@ @color/background_button_color_secondary @color/background_button_color_secondary + -