Compare commits

..

106 Commits

Author SHA1 Message Date
Sylvia van Os
61d2e9545e Release Catima 2.30.0 2024-06-18 18:01:49 +02:00
Sylvia van Os
b1ea40abeb Merge pull request #1938 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-18 18:00:49 +02:00
Jose Delvani
b898be199c Translated using Weblate (Portuguese (Brazil))
Currently translated at 2.2% (3 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt_BR/
2024-06-18 06:09:26 +02:00
Jose Delvani
e82b61ed7e Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (1 of 1 strings)

Translation: Catima/Android (Debug)
Translate-URL: https://hosted.weblate.org/projects/catima/android-debug/pt_BR/
2024-06-18 06:09:25 +02:00
Jose Delvani
31aef55343 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_BR/
2024-06-18 06:09:24 +02:00
Sylvia van Os
3da7797ecc Merge pull request #1935 from CatimaLoyalty/dependabot/github_actions/actions/checkout-4.1.7
Bump actions/checkout from 4.1.6 to 4.1.7
2024-06-17 07:26:29 +02:00
Sylvia van Os
b677a34942 Merge pull request #1937 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-17 07:24:32 +02:00
Jose Delvani
8275a0da69 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_BR/
2024-06-17 05:47:41 +02:00
Jose Delvani
cc86506868 Added translation using Weblate (Portuguese (Brazil)) 2024-06-17 05:47:41 +02:00
dependabot[bot]
83ee75dc55 Bump actions/checkout from 4.1.6 to 4.1.7
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.6...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 02:25:13 +00:00
Sylvia van Os
a8d92c1e69 Merge pull request #1932 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-16 10:34:05 +02:00
Bruno Fernandes
ccf98f9b32 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.4% (308 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_BR/
2024-06-16 07:22:42 +00:00
Jose Delvani
6c17498481 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.4% (308 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_BR/
2024-06-16 07:22:41 +00:00
Sylvia van Os
ce9794f72f Merge pull request #1931 from CatimaLoyalty/create-pull-request/patch-1718511342
Update contributors
2024-06-16 09:13:17 +02:00
TheLastProject
a48ddeef7f Update contributors 2024-06-16 04:15:41 +00:00
Sylvia van Os
864298cee8 Merge pull request #1928 from CatimaLoyalty/create-pull-request/patch-1718441664
Update locales
2024-06-15 11:08:09 +02:00
TheLastProject
63b48685a6 Update locales 2024-06-15 08:54:23 +00:00
Sylvia van Os
37d4c2c552 Merge pull request #1927 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-15 10:54:09 +02:00
Bruno Fernandes
0515f7876b Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.8% (303 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_BR/
2024-06-14 22:09:59 +02:00
grgergo
9e801f0f1c Translated using Weblate (Hungarian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2024-06-14 22:09:58 +02:00
IllusiveMan196
c7a8d6ddae Translated using Weblate (Ukrainian)
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2024-06-14 22:09:58 +02:00
Kachelkaiser
0f828b5663 Translated using Weblate (German)
Currently translated at 94.0% (126 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2024-06-14 22:09:57 +02:00
IllusiveMan196
3f28a69d7d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2024-06-14 22:09:56 +02:00
Cosmin Humeniuc
8980d92263 Translated using Weblate (Romanian)
Currently translated at 99.0% (310 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ro/
2024-06-14 22:09:56 +02:00
Francisco Gabriel Chardin
dd7512cc62 Translated using Weblate (Spanish (Argentina))
Currently translated at 74.1% (232 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es_AR/
2024-06-14 22:09:55 +02:00
Kachelkaiser
3005f7d845 Translated using Weblate (German)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2024-06-14 22:09:55 +02:00
Sylvia van Os
cbbd90a884 Merge pull request #1926 from CatimaLoyalty/dependabot/gradle/com.android.application-8.5.0
Bump com.android.application from 8.4.2 to 8.5.0
2024-06-14 08:18:08 +02:00
dependabot[bot]
883803d348 Bump com.android.application from 8.4.2 to 8.5.0
Bumps com.android.application from 8.4.2 to 8.5.0.

---
updated-dependencies:
- dependency-name: com.android.application
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-14 03:00:13 +00:00
Sylvia van Os
56b73ef7e2 Merge pull request #1925 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-13 20:24:01 +02:00
Martijn Westerink
b1c98d33e5 Translated using Weblate (Dutch)
Currently translated at 19.4% (26 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nl/
2024-06-13 19:08:13 +02:00
Martijn Westerink
4a4feea1be Translated using Weblate (Dutch)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2024-06-13 19:08:12 +02:00
Sylvia van Os
ea015b531a Merge pull request #1924 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-12 18:07:58 +02:00
Scrambled777
5b8c40dd8a Translated using Weblate (Hindi)
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hi/
2024-06-12 01:04:25 +00:00
Scrambled777
4859499179 Translated using Weblate (Hindi)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hi/
2024-06-12 01:04:24 +00:00
grgergo
0e6cdbbb6b Translated using Weblate (Hungarian)
Currently translated at 99.6% (312 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2024-06-12 01:04:23 +00:00
Sylvia van Os
cc8c8ead2e Merge pull request #1922 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-11 18:44:04 +02:00
Sylvia van Os
2b6a4ef466 Merge pull request #1921 from CatimaLoyalty/dependabot/gradle/com.android.application-8.4.2
Bump com.android.application from 8.4.1 to 8.4.2
2024-06-11 18:42:55 +02:00
Wei-Cheng Yeh (IID)
a3b9d78463 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (1 of 1 strings)

Translation: Catima/Android (Debug)
Translate-URL: https://hosted.weblate.org/projects/catima/android-debug/zh_Hant/
2024-06-11 10:09:57 +02:00
ngocanhtve
7873d21644 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/vi/
2024-06-11 10:09:56 +02:00
GrassWarlock
2ad1b08de2 Translated using Weblate (Arabic)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2024-06-11 10:09:55 +02:00
Wei-Cheng Yeh (IID)
4fae252d0a Translated using Weblate (Chinese (Traditional))
Currently translated at 6.7% (9 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hant/
2024-06-11 10:09:54 +02:00
Wei-Cheng Yeh (IID)
f89179da21 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2024-06-11 10:09:54 +02:00
GregoryWarn
b4e63f89ce Translated using Weblate (Italian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2024-06-11 10:09:53 +02:00
dependabot[bot]
ff872edc4b Bump com.android.application from 8.4.1 to 8.4.2
Bumps com.android.application from 8.4.1 to 8.4.2.

---
updated-dependencies:
- dependency-name: com.android.application
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-11 02:22:30 +00:00
Sylvia van Os
013258d421 Merge pull request #1919 from CatimaLoyalty/create-pull-request/patch-1717928359
Update locales
2024-06-09 12:29:42 +02:00
TheLastProject
15575e4189 Update locales 2024-06-09 10:19:18 +00:00
Sylvia van Os
3c051cde95 Merge pull request #1918 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-09 12:19:03 +02:00
Hosted Weblate
5d2a173e22 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/
2024-06-09 10:10:13 +00:00
Sylvia van Os
a2032ab730 Translated using Weblate (Filipino)
Currently translated at 15.3% (48 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fil/
2024-06-09 10:10:12 +00:00
しいたけ
9e4d8b846c Translated using Weblate (Japanese)
Currently translated at 84.0% (263 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2024-06-09 10:10:12 +00:00
solokot
7e8dd2dc2e Translated using Weblate (Russian)
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2024-06-09 10:10:11 +00:00
Mael
b73d0f1836 Translated using Weblate (French)
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2024-06-09 10:10:11 +00:00
solokot
b478e54ec0 Translated using Weblate (Russian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2024-06-09 10:10:10 +00:00
Sylvia van Os
cf8c6b8c24 Translated using Weblate (Hebrew (Israel))
Currently translated at 29.0% (91 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/he_IL/
2024-06-09 10:10:09 +00:00
Mael
d64294284a Translated using Weblate (French)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2024-06-09 10:10:09 +00:00
Alik Majid
098468e6bd Translated using Weblate (Russian)
Currently translated at 99.3% (311 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2024-06-09 10:10:08 +00:00
SC
cebc87a197 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_PT/
2024-06-09 10:10:07 +00:00
SC
0d3ceb0e61 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt_PT/
2024-06-09 10:10:07 +00:00
Oğuz Ersen
e017b07337 Translated using Weblate (Turkish)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2024-06-09 10:10:06 +00:00
大王叫我来巡山
c4ec81f22b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2024-06-09 10:10:05 +00:00
大王叫我来巡山
c597df056d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2024-06-09 10:10:05 +00:00
Wendell Nicolas
5517b418ac Translated using Weblate (Filipino)
Currently translated at 15.6% (49 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fil/
2024-06-09 10:10:04 +00:00
拉夫西奧·羅齊奧馬爾
81e7642bb8 Translated using Weblate (Polish)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2024-06-09 10:10:03 +00:00
Wendell Nicolas
17718d5349 Translated using Weblate (Hebrew (Israel))
Currently translated at 29.0% (91 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/he_IL/
2024-06-09 10:10:03 +00:00
gallegonovato
f5ef97fa30 Translated using Weblate (Spanish)
Currently translated at 100.0% (313 of 313 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2024-06-09 10:10:02 +00:00
Wendell Nicolas
30c6657148 Added translation using Weblate (Filipino) 2024-06-09 10:10:01 +00:00
Sylvia van Os
2b173dc7f6 Merge pull request #1917 from CatimaLoyalty/create-pull-request/patch-1717906588
Update contributors
2024-06-09 11:00:17 +02:00
TheLastProject
cd48a28b5a Update contributors 2024-06-09 04:16:27 +00:00
Sylvia van Os
b7ad5f1f42 Merge pull request #1915 from CatimaLoyalty/create-pull-request/patch-1717619102
Update Fastlane changelogs
2024-06-05 22:25:39 +02:00
TheLastProject
9bf6795328 Update Fastlane changelogs 2024-06-05 20:25:01 +00:00
Sylvia van Os
4364189b3e Update CHANGELOG 2024-06-05 22:24:42 +02:00
Sylvia van Os
40676a365f Merge pull request #1912 from CatimaLoyalty/fix/1907
Support for devices without camera
2024-06-05 22:13:38 +02:00
Sylvia van Os
97314a0436 Rename camera permission denied layout to more logical generic error layout name 2024-06-05 20:07:52 +02:00
Sylvia van Os
d1b93018e3 Show generic zxing errors on the camera error screen 2024-06-05 20:07:46 +02:00
Sylvia van Os
a6b7b227f7 Support for devices without camera
This hides the take photo options for thumbnail and front/back image and
shows a different alert if no camera is available
2024-06-04 18:18:29 +02:00
Sylvia van Os
1c6a5454b8 Merge pull request #1913 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-03 18:55:37 +02:00
Marian Turba
06745becd7 Translated using Weblate (Slovak)
Currently translated at 95.5% (128 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sk/
2024-06-03 11:09:59 +02:00
solokot
c172a12956 Translated using Weblate (Russian)
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2024-06-03 11:09:59 +02:00
Marian Turba
c6f18fb7b2 Translated using Weblate (Slovak)
Currently translated at 100.0% (312 of 312 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2024-06-03 11:09:58 +02:00
min7-i
dc3fabbbb9 Translated using Weblate (German)
Currently translated at 100.0% (312 of 312 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2024-06-03 11:09:58 +02:00
Sylvia van Os
905402ebab Merge pull request #1911 from CatimaLoyalty/create-pull-request/patch-1717222760
Update Gradle to 8.8
2024-06-01 09:52:10 +02:00
Sylvia van Os
fbed0d7857 Merge pull request #1910 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-06-01 09:48:00 +02:00
TheLastProject
cc74395297 Update Gradle to 8.8 2024-06-01 06:19:20 +00:00
HackerSinhos
560c55d5db Translated using Weblate (Portuguese (Brazil))
Currently translated at 32.0% (100 of 312 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_BR/
2024-06-01 05:10:42 +00:00
Sylvia van Os
a45c972a38 Merge pull request #1908 from CatimaLoyalty/dependabot/gradle/androidx.appcompat-appcompat-1.7.0
Bump androidx.appcompat:appcompat from 1.6.1 to 1.7.0
2024-05-31 17:40:00 +02:00
dependabot[bot]
51c1af5ad9 Bump androidx.appcompat:appcompat from 1.6.1 to 1.7.0
Bumps androidx.appcompat:appcompat from 1.6.1 to 1.7.0.

---
updated-dependencies:
- dependency-name: androidx.appcompat:appcompat
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-30 02:11:34 +00:00
Sylvia van Os
d537164799 Merge pull request #1906 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-05-27 19:40:12 +02:00
hugoalh
012910268b Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (312 of 312 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2024-05-27 14:09:37 +02:00
tabby
74d9068925 Translated using Weblate (Korean)
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ko/
2024-05-27 14:09:36 +02:00
Allan Nordhøy
5d68f558a1 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.7% (302 of 312 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2024-05-27 14:09:35 +02:00
Sylvia van Os
2164c1a51a Merge pull request #1904 from CatimaLoyalty/create-pull-request/patch-1716696873
Update contributors
2024-05-26 11:27:55 +02:00
TheLastProject
5f180fc289 Update contributors 2024-05-26 04:14:33 +00:00
Sylvia van Os
5be44d9bd2 Merge pull request #1903 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-05-25 14:41:31 +02:00
Asmodeus
54c9857072 Translated using Weblate (Portuguese (Brazil))
Currently translated at 20.8% (65 of 312 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_BR/
2024-05-25 14:09:48 +02:00
Scrambled777
c48ac797f6 Translated using Weblate (Hindi)
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hi/
2024-05-25 14:09:47 +02:00
大王叫我来巡山
9180d22629 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (134 of 134 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2024-05-25 14:09:47 +02:00
Sylvia van Os
aa0274534c Merge pull request #1902 from obfusk/fix-new-locales-script
new-locales.py: fix weblate pagination
2024-05-24 21:36:24 +02:00
FC (Fay) Stegerman
c97b37f279 run new-locales.py 2024-05-24 21:03:06 +02:00
FC (Fay) Stegerman
14c12533a7 new-locales.py: fix weblate pagination 2024-05-24 21:01:42 +02:00
Sylvia van Os
39f50bad30 Merge pull request #1901 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2024-05-24 18:16:32 +02:00
Asmodeus
014061d0a4 Added translation using Weblate (Portuguese (Brazil)) 2024-05-24 13:14:19 +02:00
Sylvia van Os
76c498a7f9 Merge pull request #1899 from CatimaLoyalty/create-pull-request/patch-1716394569
Update Fastlane changelogs
2024-05-22 18:17:23 +02:00
TheLastProject
fa9229c687 Update Fastlane changelogs 2024-05-22 16:16:09 +00:00
Sylvia van Os
182e7ef9a6 Merge pull request #1897 from CatimaLoyalty/fix/threadedImportExport
Run Import/Export on non-UI thread
2024-05-22 18:15:54 +02:00
Sylvia van Os
08e6600880 Lower severity of import/export starting log entries to debug
Co-authored-by: FC (Fay) Stegerman <flx@obfusk.net>
2024-05-22 18:08:37 +02:00
Sylvia van Os
edeb95aee0 Run Import/Export on non-UI thread
This seems to fix Android sometimes throwing
NetworkOnMainThreadException when importing bit files through the
Nextcloud app.

I'm not sure if this is necessary for the export too, but it doesn't
seem to break anything so for consistency it makes sense to also wrap
the exporter into a thread.

This change is suboptimal because it will still block the UI with a
ProgressDialog (which is deprecated) and force the user to wait until
the import/export completes (and will kill the import/export if the app
gets backgrounded) but it should at least fix the most common crash for
most users.
2024-05-21 21:04:25 +02:00
92 changed files with 1058 additions and 630 deletions

View File

@@ -29,7 +29,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.6
- uses: actions/checkout@v4.1.7
- name: Fail on bad translations
run: if grep -ri "&lt;xliff" app/src/main/res/values*/strings.xml; then echo "Invalidly escaped translations found"; exit 1; fi
- uses: gradle/actions/wrapper-validation@v3

View File

@@ -27,7 +27,7 @@ jobs:
steps:
- name: Checkout repo
id: checkout
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Setup Python
uses: actions/setup-python@v5.1.0
with:

View File

@@ -25,7 +25,7 @@ jobs:
steps:
- name: Checkout repo
id: checkout
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Update contributors
id: update_contributors
uses: TheLastProject/contributors-to-file-action@v3.2.0

View File

@@ -24,7 +24,7 @@ jobs:
generate-feature-graphic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.6
- uses: actions/checkout@v4.1.7
- name: Install requirements
run: |
sudo apt-get update

View File

@@ -21,7 +21,7 @@ jobs:
gradle-update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.6
- uses: actions/checkout@v4.1.7
- uses: obfusk/gradle-update-action@v2.0.0
id: gradle-update
- uses: gradle/actions/wrapper-validation@v3

View File

@@ -25,7 +25,7 @@ jobs:
update-locales:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.6
- uses: actions/checkout@v4.1.7
- name: Add new locales
run: .scripts/new-locales.py
- name: Update locales

View File

@@ -24,7 +24,7 @@ sed = [
]
subprocess.run(sed, check=True)
with open("app/src/main/res/xml/locales_config.xml", "w") as fh:
with open("app/src/main/res/xml/locales_config.xml", "w", encoding="utf-8") as fh:
fh.write('<?xml version="1.0" encoding="utf-8"?>\n')
fh.write('<locale-config xmlns:android="http://schemas.android.com/apk/res/android">\n')
fh.write(' <locale android:name="en-US" />\n')

View File

@@ -19,15 +19,27 @@ REPLACE_CODES = {
STATS_URL = "https://hosted.weblate.org/api/components/catima/catima/statistics/"
class Error(Exception):
pass
def get_weblate_langs() -> List[Tuple[str, int]]:
r = requests.get(STATS_URL, timeout=5)
r.raise_for_status()
url = STATS_URL
results = []
for lang in r.json()["results"]:
if lang["code"] != "en":
code = REPLACE_CODES.get(lang["code"], lang["code"]).replace("_", "-r")
results.append((code, round(lang["translated_percent"])))
return sorted(results)
for _ in range(16): # avoid endless loops just in case
r = requests.get(url, timeout=5)
r.raise_for_status()
data = r.json()
for lang in data["results"]:
if lang["code"] != "en":
code = REPLACE_CODES.get(lang["code"], lang["code"]).replace("_", "-r")
results.append((code, round(lang["translated_percent"])))
url = data["next"]
if not url:
return sorted(results)
if not url.split("?")[0] == STATS_URL:
raise Error(f"Unexpected next URL: {url}")
raise Error("Too many pages")
def get_dir_langs() -> List[str]:
@@ -42,7 +54,7 @@ def get_dir_langs() -> List[str]:
def get_xml_langs() -> List[Tuple[str, bool]]:
results = []
in_section = False
with open("app/src/main/res/values/settings.xml") as fh:
with open("app/src/main/res/values/settings.xml", encoding="utf-8") as fh:
for line in fh:
if not in_section and 'name="locale_values"' in line:
in_section = True
@@ -59,7 +71,7 @@ def get_xml_langs() -> List[Tuple[str, bool]]:
def update_xml_langs(langs: List[Tuple[str, bool]]) -> None:
lines: List[str] = []
in_section = False
with open("app/src/main/res/values/settings.xml") as fh:
with open("app/src/main/res/values/settings.xml", encoding="utf-8") as fh:
for line in fh:
if not in_section and 'name="locale_values"' in line:
in_section = True
@@ -70,7 +82,7 @@ def update_xml_langs(langs: List[Tuple[str, bool]]) -> None:
else:
continue
lines.append(line)
with open("app/src/main/res/values/settings.xml", "w") as fh:
with open("app/src/main/res/values/settings.xml", "w", encoding="utf-8") as fh:
for line in lines:
fh.write(line)

View File

@@ -1,9 +1,11 @@
# Changelog
## Unreleased - 136
## v2.30.0 - 136
- Support for creating a card when sharing plain text
- Display image type instead of barcode below images
- Fix possible crash when trying to import a backup from the Nextcloud app
- Improved support for devices without camera
## v2.29.1 - 135 (2024-05-19)

View File

@@ -21,13 +21,13 @@ android {
applicationId = "me.hackerchick.catima"
minSdk = 21
targetSdk = 34
versionCode = 135
versionName = "2.29.1"
versionCode = 136
versionName = "2.30.0"
vectorDrawables.useSupportLibrary = true
multiDexEnabled = true
resourceConfigurations += listOf("ar", "bg", "bn", "bn-rIN", "bs", "cs", "da", "de", "el-rGR", "en", "eo", "es", "es-rAR", "fi", "fr", "he-rIL", "hi", "hr", "hu", "in-rID", "is", "it", "ja", "ko", "lt", "lv", "nb-rNO", "nl", "oc", "pl", "pt-rPT", "ro-rRO", "ru", "sk", "sl", "sv", "tr", "uk", "vi", "zh-rCN", "zh-rTW")
resourceConfigurations += listOf("ar", "bg", "bn", "bn-rIN", "bs", "cs", "da", "de", "el-rGR", "en", "eo", "es", "es-rAR", "fi", "fr", "he-rIL", "hi", "hr", "hu", "in-rID", "is", "it", "ja", "ko", "lt", "lv", "nb-rNO", "nl", "oc", "pl", "pt-rBR", "pt-rPT", "ro-rRO", "ru", "sk", "sl", "sv", "tr", "uk", "vi", "zh-rCN", "zh-rTW")
}
buildTypes {
@@ -87,14 +87,13 @@ android {
dependencies {
// AndroidX
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.exifinterface:exifinterface:1.3.7")
implementation("androidx.palette:palette:1.0.0")
implementation("androidx.preference:preference:1.2.1")
implementation("com.google.android.material:material:1.12.0")
implementation("com.github.yalantis:ucrop:2.2.9")
implementation("androidx.work:work-runtime:2.9.0")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
// Splash Screen

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Depuração do Catima</string>
</resources>

View File

@@ -1,2 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>
<resources>
<string name="app_name">Catima 除錯版</string>
</resources>

View File

@@ -12,13 +12,11 @@
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="23" />
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
android:required="false" />
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="false" />
@@ -190,6 +188,5 @@
<action android:name="android.service.controls.ControlsProviderService" />
</intent-filter>
</service>
<service android:name=".importexport.ImportExportWorker"/>
</application>
</manifest>

View File

@@ -4,22 +4,24 @@ import android.app.Activity;
import android.content.Context;
import android.widget.Toast;
import androidx.core.util.Consumer;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
public class CatimaCaptureManager extends CaptureManager {
private final Context mContext;
private final Consumer<String> mErrorCallback;
public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView, Consumer<String> errorCallback) {
super(activity, barcodeView);
mContext = activity.getApplicationContext();
mErrorCallback = errorCallback;
}
@Override
protected void displayFrameworkBugMessageAndExit(String message) {
// We don't want to exit, as we also have a enter from card image and add manually button here
// So we show a toast instead
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
// So, instead, we call our error callback
mErrorCallback.accept(message);
}
}

View File

@@ -1,9 +1,8 @@
package protect.card_locker;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.text.InputType;
@@ -18,31 +17,31 @@ import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.work.Data;
import androidx.work.ExistingWorkPolicy;
import androidx.work.OneTimeWorkRequest;
import androidx.work.OutOfQuotaPolicy;
import androidx.work.WorkManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputLayout;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import protect.card_locker.async.TaskHandler;
import protect.card_locker.databinding.ImportExportActivityBinding;
import protect.card_locker.importexport.DataFormat;
import protect.card_locker.importexport.ImportExportWorker;
import protect.card_locker.importexport.ImportExportResult;
import protect.card_locker.importexport.ImportExportResultType;
public class ImportExportActivity extends CatimaAppCompatActivity {
private ImportExportActivityBinding binding;
private static final String TAG = "Catima";
private ImportExportTask importExporter;
private String importAlertTitle;
private String importAlertMessage;
private DataFormat importDataFormat;
@@ -52,10 +51,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
private ActivityResultLauncher<String> fileOpenLauncher;
private ActivityResultLauncher<Intent> filePickerLauncher;
private static final int PERMISSION_REQUEST_EXPORT = 100;
private static final int PERMISSION_REQUEST_IMPORT = 101;
private OneTimeWorkRequest mRequestedWorkRequest;
final private TaskHandler mTasks = new TaskHandler();
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -84,20 +80,21 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
Log.e(TAG, "Activity returned NULL uri");
return;
}
Data exportRequestData = new Data.Builder()
.putString(ImportExportWorker.INPUT_URI, uri.toString())
.putString(ImportExportWorker.INPUT_ACTION, ImportExportWorker.ACTION_EXPORT)
.putString(ImportExportWorker.INPUT_FORMAT, DataFormat.Catima.name())
.putString(ImportExportWorker.INPUT_PASSWORD, exportPassword)
.build();
mRequestedWorkRequest = new OneTimeWorkRequest.Builder(ImportExportWorker.class)
.setInputData(exportRequestData)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build();
PermissionUtils.requestPostNotificationsPermission(this, PERMISSION_REQUEST_EXPORT);
// Running this in a thread prevents Android from throwing a NetworkOnMainThreadException for large files
// FIXME: This is still suboptimal, because showing that the export started is delayed until the network request finishes
new Thread() {
@Override
public void run() {
try {
OutputStream writer = getContentResolver().openOutputStream(uri);
Log.d(TAG, "Starting file export with: " + result);
startExport(writer, uri, exportPassword.toCharArray(), true);
} catch (IOException e) {
Log.e(TAG, "Failed to export file: " + result, e);
onExportComplete(new ImportExportResult(ImportExportResultType.GenericFailure, result.toString()), uri);
}
}
}.start();
});
fileOpenLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), result -> {
if (result == null) {
@@ -168,24 +165,22 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
importApplication.setOnClickListener(v -> chooseImportType(true, null));
}
public static OneTimeWorkRequest buildImportRequest(DataFormat dataFormat, Uri uri, char[] password) {
Data importRequestData = new Data.Builder()
.putString(ImportExportWorker.INPUT_URI, uri.toString())
.putString(ImportExportWorker.INPUT_ACTION, ImportExportWorker.ACTION_IMPORT)
.putString(ImportExportWorker.INPUT_FORMAT, dataFormat.name())
.putString(ImportExportWorker.INPUT_PASSWORD, Arrays.toString(password))
.build();
return new OneTimeWorkRequest.Builder(ImportExportWorker.class)
.setInputData(importRequestData)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build();
}
private void openFileForImport(Uri uri, char[] password) {
mRequestedWorkRequest = buildImportRequest(importDataFormat, uri, password);
PermissionUtils.requestPostNotificationsPermission(this, PERMISSION_REQUEST_IMPORT);
// Running this in a thread prevents Android from throwing a NetworkOnMainThreadException for large files
// FIXME: This is still suboptimal, because showing that the import started is delayed until the network request finishes
new Thread() {
@Override
public void run() {
try {
InputStream reader = getContentResolver().openInputStream(uri);
Log.d(TAG, "Starting file import with: " + uri);
startImport(reader, uri, importDataFormat, password, true);
} catch (IOException e) {
Log.e(TAG, "Failed to import file: " + uri, e);
onImportComplete(new ImportExportResult(ImportExportResultType.GenericFailure, e.toString()), uri, importDataFormat);
}
}
}.start();
}
private void chooseImportType(boolean choosePicker,
@@ -250,17 +245,20 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
new MaterialAlertDialogBuilder(this)
.setTitle(importAlertTitle)
.setMessage(importAlertMessage)
.setPositiveButton(R.string.ok, (dialog1, which1) -> {
try {
if (choosePicker) {
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
filePickerLauncher.launch(intentPickAction);
} else {
fileOpenLauncher.launch("*/*");
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
try {
if (choosePicker) {
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
filePickerLauncher.launch(intentPickAction);
} else {
fileOpenLauncher.launch("*/*");
}
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
Log.e(TAG, "No activity found to handle intent", e);
}
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
Log.e(TAG, "No activity found to handle intent", e);
}
})
.setNegativeButton(R.string.cancel, null)
@@ -269,12 +267,60 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
builder.show();
}
private void startImport(final InputStream target, final Uri targetUri, final DataFormat dataFormat, final char[] password, final boolean closeWhenDone) {
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, true, false, false);
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener() {
@Override
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat) {
onImportComplete(result, targetUri, dataFormat);
if (closeWhenDone) {
try {
target.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
};
importExporter = new ImportExportTask(ImportExportActivity.this,
dataFormat, target, password, listener);
mTasks.executeTask(TaskHandler.TYPE.IMPORT, importExporter);
}
private void startExport(final OutputStream target, final Uri targetUri, char[] password, final boolean closeWhenDone) {
mTasks.flushTaskList(TaskHandler.TYPE.EXPORT, true, false, false);
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener() {
@Override
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat) {
onExportComplete(result, targetUri);
if (closeWhenDone) {
try {
target.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
};
importExporter = new ImportExportTask(ImportExportActivity.this,
DataFormat.Catima, target, password, listener);
mTasks.executeTask(TaskHandler.TYPE.EXPORT, importExporter);
}
@Override
protected void onDestroy() {
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, true, false, false);
mTasks.flushTaskList(TaskHandler.TYPE.EXPORT, true, false, false);
super.onDestroy();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
setResult(RESULT_CANCELED);
finish();
return true;
}
@@ -282,19 +328,19 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
return super.onOptionsItemSelected(item);
}
public static void retryWithPassword(Context context, DataFormat dataFormat, Uri uri) {
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(context);
private void retryWithPassword(DataFormat dataFormat, Uri uri) {
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(R.string.passwordRequired);
FrameLayout container = new FrameLayout(context);
FrameLayout container = new FrameLayout(ImportExportActivity.this);
final TextInputLayout textInputLayout = new TextInputLayout(context);
final TextInputLayout textInputLayout = new TextInputLayout(ImportExportActivity.this);
textInputLayout.setEndIconMode(TextInputLayout.END_ICON_PASSWORD_TOGGLE);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(50, 10, 50, 0);
textInputLayout.setLayoutParams(params);
final EditText input = new EditText(context);
final EditText input = new EditText(ImportExportActivity.this);
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
input.setHint(R.string.exportPasswordHint);
@@ -303,55 +349,75 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
builder.setView(container);
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
OneTimeWorkRequest importRequest = ImportExportActivity.buildImportRequest(dataFormat, uri, input.getText().toString().toCharArray());
WorkManager.getInstance(context).enqueueUniqueWork(ImportExportWorker.ACTION_IMPORT, ExistingWorkPolicy.REPLACE, importRequest);
openFileForImport(uri, input.getText().toString().toCharArray());
});
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
builder.show();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
private String buildResultDialogMessage(ImportExportResult result, boolean isImport) {
int messageId;
onMockedRequestPermissionsResult(requestCode, permissions, grantResults);
if (result.resultType() == ImportExportResultType.Success) {
messageId = isImport ? R.string.importSuccessful : R.string.exportSuccessful;
} else {
messageId = isImport ? R.string.importFailed : R.string.exportFailed;
}
StringBuilder messageBuilder = new StringBuilder(getResources().getString(messageId));
if (result.developerDetails() != null) {
messageBuilder.append("\n\n");
messageBuilder.append(getResources().getString(R.string.include_if_asking_support));
messageBuilder.append("\n\n");
messageBuilder.append(result.developerDetails());
}
return messageBuilder.toString();
}
public void onMockedRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
Integer failureReason = null;
private void onImportComplete(ImportExportResult result, Uri path, DataFormat dataFormat) {
ImportExportResultType resultType = result.resultType();
if (requestCode == PERMISSION_REQUEST_EXPORT) {
if (granted) {
WorkManager.getInstance(this).enqueueUniqueWork(ImportExportWorker.ACTION_EXPORT, ExistingWorkPolicy.REPLACE, mRequestedWorkRequest);
Toast.makeText(this, R.string.exportStartedCheckNotifications, Toast.LENGTH_LONG).show();
// Import/export started
setResult(RESULT_OK);
finish();
return;
}
failureReason = R.string.postNotificationsPermissionRequired;
} else if (requestCode == PERMISSION_REQUEST_IMPORT) {
if (granted) {
WorkManager.getInstance(this).enqueueUniqueWork(ImportExportWorker.ACTION_IMPORT, ExistingWorkPolicy.REPLACE, mRequestedWorkRequest);
// Import/export started
setResult(RESULT_OK);
finish();
return;
}
failureReason = R.string.postNotificationsPermissionRequired;
if (resultType == ImportExportResultType.BadPassword) {
retryWithPassword(dataFormat, path);
return;
}
if (failureReason != null) {
Toast.makeText(this, failureReason, Toast.LENGTH_LONG).show();
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(resultType == ImportExportResultType.Success ? R.string.importSuccessfulTitle : R.string.importFailedTitle);
builder.setMessage(buildResultDialogMessage(result, true));
builder.setNeutralButton(R.string.ok, (dialog, which) -> dialog.dismiss());
builder.create().show();
}
private void onExportComplete(ImportExportResult result, final Uri path) {
ImportExportResultType resultType = result.resultType();
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(resultType == ImportExportResultType.Success ? R.string.exportSuccessfulTitle : R.string.exportFailedTitle);
builder.setMessage(buildResultDialogMessage(result, false));
builder.setNeutralButton(R.string.ok, (dialog, which) -> dialog.dismiss());
if (resultType == ImportExportResultType.Success) {
final CharSequence sendLabel = ImportExportActivity.this.getResources().getText(R.string.sendLabel);
builder.setPositiveButton(sendLabel, (dialog, which) -> {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, path);
sendIntent.setType("text/csv");
// set flag to give temporary permission to external app to use the FileProvider
sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
ImportExportActivity.this.startActivity(Intent.createChooser(sendIntent,
sendLabel));
dialog.dismiss();
});
}
builder.create().show();
}
}

View File

@@ -0,0 +1,143 @@
package protect.card_locker;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import protect.card_locker.async.CompatCallable;
import protect.card_locker.importexport.DataFormat;
import protect.card_locker.importexport.ImportExportResult;
import protect.card_locker.importexport.ImportExportResultType;
import protect.card_locker.importexport.MultiFormatExporter;
import protect.card_locker.importexport.MultiFormatImporter;
public class ImportExportTask implements CompatCallable<ImportExportResult> {
private static final String TAG = "Catima";
private Activity activity;
private boolean doImport;
private DataFormat format;
private OutputStream outputStream;
private InputStream inputStream;
private char[] password;
private TaskCompleteListener listener;
private ProgressDialog progress;
/**
* Constructor which will setup a task for exporting to the given file
*/
ImportExportTask(Activity activity, DataFormat format, OutputStream output, char[] password,
TaskCompleteListener listener) {
super();
this.activity = activity;
this.doImport = false;
this.format = format;
this.outputStream = output;
this.password = password;
this.listener = listener;
}
/**
* Constructor which will setup a task for importing from the given InputStream.
*/
ImportExportTask(Activity activity, DataFormat format, InputStream input, char[] password,
TaskCompleteListener listener) {
super();
this.activity = activity;
this.doImport = true;
this.format = format;
this.inputStream = input;
this.password = password;
this.listener = listener;
}
private ImportExportResult performImport(Context context, InputStream stream, SQLiteDatabase database, char[] password) {
ImportExportResult importResult = MultiFormatImporter.importData(context, database, stream, format, password);
Log.i(TAG, "Import result: " + importResult);
return importResult;
}
private ImportExportResult performExport(Context context, OutputStream stream, SQLiteDatabase database, char[] password) {
ImportExportResult result;
try {
OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
result = MultiFormatExporter.exportData(context, database, stream, format, password);
writer.close();
} catch (IOException e) {
result = new ImportExportResult(ImportExportResultType.GenericFailure, e.toString());
Log.e(TAG, "Unable to export file", e);
}
Log.i(TAG, "Export result: " + result);
return result;
}
public void onPreExecute() {
progress = new ProgressDialog(activity);
progress.setTitle(doImport ? R.string.importing : R.string.exporting);
progress.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
ImportExportTask.this.stop();
}
});
progress.show();
}
protected ImportExportResult doInBackground(Void... nothing) {
final SQLiteDatabase database = new DBHelper(activity).getWritableDatabase();
ImportExportResult result;
if (doImport) {
result = performImport(activity.getApplicationContext(), inputStream, database, password);
} else {
result = performExport(activity.getApplicationContext(), outputStream, database, password);
}
database.close();
return result;
}
public void onPostExecute(Object castResult) {
listener.onTaskComplete((ImportExportResult) castResult, format);
progress.dismiss();
Log.i(TAG, (doImport ? "Import" : "Export") + " Complete");
}
protected void onCancelled() {
progress.dismiss();
Log.i(TAG, (doImport ? "Import" : "Export") + " Cancelled");
}
protected void stop() {
// Whelp
}
@Override
public ImportExportResult call() {
return doInBackground();
}
interface TaskCompleteListener {
void onTaskComplete(ImportExportResult result, DataFormat format);
}
}

View File

@@ -26,13 +26,9 @@ import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.core.splashscreen.SplashScreen;
import androidx.recyclerview.widget.RecyclerView;
import androidx.work.Data;
import androidx.work.WorkInfo;
import androidx.work.WorkManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import java.io.UnsupportedEncodingException;
@@ -40,15 +36,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import protect.card_locker.databinding.ContentMainBinding;
import protect.card_locker.databinding.MainActivityBinding;
import protect.card_locker.databinding.SortingOptionBinding;
import protect.card_locker.importexport.DataFormat;
import protect.card_locker.importexport.ImportExportWorker;
import protect.card_locker.preferences.SettingsActivity;
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener {
@@ -79,7 +71,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
private ActivityResultLauncher<Intent> mBarcodeScannerLauncher;
private ActivityResultLauncher<Intent> mSettingsLauncher;
private ActivityResultLauncher<Intent> mImportExportLauncher;
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback() {
@Override
@@ -313,69 +304,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
});
mImportExportLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
// User didn't ask for import or export
if (result.getResultCode() != RESULT_OK) {
return;
}
// Watch for active imports/exports
new Thread(() -> {
WorkManager workManager = WorkManager.getInstance(MainActivity.this);
Snackbar importRunning = Snackbar.make(binding.getRoot(), R.string.importing, Snackbar.LENGTH_INDEFINITE);
while (true) {
try {
List<WorkInfo> activeImports = workManager.getWorkInfosForUniqueWork(ImportExportWorker.ACTION_IMPORT).get();
// We should only have one import running at a time, so it should be safe to always grab the latest
WorkInfo activeImport = activeImports.get(activeImports.size() - 1);
WorkInfo.State importState = activeImport.getState();
if (importState == WorkInfo.State.RUNNING || importState == WorkInfo.State.ENQUEUED || importState == WorkInfo.State.BLOCKED) {
importRunning.show();
} else if (importState == WorkInfo.State.SUCCEEDED) {
importRunning.dismiss();
runOnUiThread(() -> {
Toast.makeText(getApplicationContext(), getString(R.string.importSuccessful), Toast.LENGTH_LONG).show();
updateLoyaltyCardList(true);
});
break;
} else {
importRunning.dismiss();
Data outputData = activeImport.getOutputData();
// FIXME: This dialog will asynchronously be accepted or declined and we don't know the status of it so we can't show the import state
// We want to get back into this function
// A cheap fix would be to keep looping but if the user dismissed the dialog that could mean we're looping forever...
if (Objects.equals(outputData.getString(ImportExportWorker.OUTPUT_ERROR_REASON), ImportExportWorker.ERROR_PASSWORD_REQUIRED)) {
runOnUiThread(() -> ImportExportActivity.retryWithPassword(
MainActivity.this,
DataFormat.valueOf(outputData.getString(ImportExportWorker.INPUT_FORMAT)),
Uri.parse(outputData.getString(ImportExportWorker.INPUT_URI))
));
} else {
runOnUiThread(() -> {
Toast.makeText(getApplicationContext(), getString(R.string.importFailed), Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), activeImport.getOutputData().getString(ImportExportWorker.OUTPUT_ERROR_REASON), Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), activeImport.getOutputData().getString(ImportExportWorker.OUTPUT_ERROR_DETAILS), Toast.LENGTH_LONG).show();
});
}
break;
}
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
});
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
@@ -713,7 +641,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
if (id == R.id.action_import_export) {
Intent i = new Intent(getApplicationContext(), ImportExportActivity.class);
mImportExportLauncher.launch(i);
startActivity(i);
return true;
}

View File

@@ -1,63 +0,0 @@
package protect.card_locker;
import static android.content.Context.NOTIFICATION_SERVICE;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class NotificationHelper {
// Do not change these IDs!
public static final String CHANNEL_IMPORT = "import";
public static final String CHANNEL_EXPORT = "export";
public static final int IMPORT_ID = 100;
public static final int IMPORT_PROGRESS_ID = 101;
public static final int EXPORT_ID = 103;
public static final int EXPORT_PROGRESS_ID = 104;
public static Notification.Builder createNotificationBuilder(@NonNull Context context, @NonNull String channel, @NonNull int icon, @NonNull String title, @Nullable String message) {
Notification.Builder notificationBuilder = new Notification.Builder(context)
.setSmallIcon(icon)
.setTicker(title)
.setContentTitle(title);
if (message != null) {
notificationBuilder.setContentText(message);
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel(channel, getChannelName(channel), NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(notificationChannel);
notificationBuilder.setChannelId(channel);
}
return notificationBuilder;
}
public static void sendNotification(@NonNull Context context, @NonNull int notificationId, @NonNull Notification notification) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, notification);
}
private static String getChannelName(@NonNull String channel) {
switch(channel) {
case CHANNEL_IMPORT:
return "Import";
case CHANNEL_EXPORT:
return "Export";
default:
throw new IllegalArgumentException("Unknown notification channel");
}
}
}

View File

@@ -42,16 +42,6 @@ public class PermissionUtils {
return ContextCompat.checkSelfPermission(activity, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED;
}
/**
* Check if post notifications permission is needed
*
* @param activity
* @return
*/
public static boolean needsPostNotificationsPermission(Activity activity) {
return ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED;
}
/**
* Call onRequestPermissionsResult after storage read permission was granted.
* Mocks a successful grant if a grant is not necessary.
@@ -101,37 +91,4 @@ public class PermissionUtils {
activity.onMockedRequestPermissionsResult(requestCode, permissions, mockedResults);
}
}
/**
* Call onRequestPermissionsResult after notification permission was granted.
* Mocks a successful grant if a grant is not necessary.
*
* @param activity
* @param requestCode
*/
public static void requestPostNotificationsPermission(CatimaAppCompatActivity activity, int requestCode) {
int[] mockedResults = new int[]{ PackageManager.PERMISSION_GRANTED };
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.TIRAMISU) {
String[] permissions = new String[0];
activity.onMockedRequestPermissionsResult(requestCode, permissions, mockedResults);
return;
}
String[] permissions = new String[]{ Manifest.permission.POST_NOTIFICATIONS};
if (needsPostNotificationsPermission(activity)) {
ActivityCompat.requestPermissions(activity, permissions, requestCode);
} else {
// FIXME: This points to onMockedRequestPermissionResult instead of to
// onRequestPermissionResult because onRequestPermissionResult was only introduced in
// Android 6.0 (SDK 23) and we and to support Android 5.0 (SDK 21) too.
//
// When minSdk becomes 23, this should point to onRequestPermissionResult directly and
// the activity input variable should be changed from CatimaAppCompatActivity to
// Activity.
activity.onMockedRequestPermissionsResult(requestCode, permissions, mockedResults);
}
}
}

View File

@@ -78,6 +78,7 @@ public class ScanActivity extends CatimaAppCompatActivity {
static final String STATE_SCANNER_ACTIVE = "scannerActive";
private boolean mScannerActive = true;
private boolean mHasError = false;
private void extractIntentFields(Intent intent) {
final Bundle b = intent.getExtras();
@@ -141,7 +142,7 @@ public class ScanActivity extends CatimaAppCompatActivity {
// Even though we do the actual decoding with the barcodeScannerView
// CaptureManager needs to be running to show the camera and scanning bar
capture = new CatimaCaptureManager(this, barcodeScannerView);
capture = new CatimaCaptureManager(this, barcodeScannerView, this::onCaptureManagerError);
Intent captureIntent = new Intent();
Bundle captureIntentBundle = new Bundle();
captureIntentBundle.putBoolean(Intents.Scan.BEEP_ENABLED, false);
@@ -178,9 +179,14 @@ public class ScanActivity extends CatimaAppCompatActivity {
capture.onResume();
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
showCameraPermissionMissingText(false);
if (!Utils.deviceHasCamera(this)) {
showCameraError(getString(R.string.noCameraFoundGuideText), false);
} else if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
showCameraPermissionMissingText();
} else {
hideCameraError();
}
scaleScreen();
}
@@ -402,12 +408,37 @@ public class ScanActivity extends CatimaAppCompatActivity {
}
}
private void showCameraPermissionMissingText(boolean show) {
customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedClickableArea.setOnClickListener(show ? v -> {
public void onCaptureManagerError(String errorMessage) {
if (mHasError) {
// We're already showing an error, ignore this new error
return;
}
showCameraError(errorMessage, false);
}
private void showCameraPermissionMissingText() {
showCameraError(getString(R.string.noCameraPermissionDirectToSystemSetting), true);
}
private void showCameraError(String message, boolean setOnClick) {
customBarcodeScannerBinding.cameraErrorLayout.cameraErrorMessage.setText(message);
setCameraErrorState(true, setOnClick);
}
private void hideCameraError() {
setCameraErrorState(false, false);
}
private void setCameraErrorState(boolean visible, boolean setOnClick) {
mHasError = visible;
customBarcodeScannerBinding.cameraErrorLayout.cameraErrorClickableArea.setOnClickListener(visible && setOnClick ? v -> {
navigateToSystemPermissionSetting();
} : null);
customBarcodeScannerBinding.cardInputContainer.setBackgroundColor(show ? obtainThemeAttribute(com.google.android.material.R.attr.colorSurface) : Color.TRANSPARENT);
customBarcodeScannerBinding.cameraPermissionDeniedLayout.getRoot().setVisibility(show ? View.VISIBLE : View.GONE);
customBarcodeScannerBinding.cardInputContainer.setBackgroundColor(visible ? obtainThemeAttribute(com.google.android.material.R.attr.colorSurface) : Color.TRANSPARENT);
customBarcodeScannerBinding.cameraErrorLayout.getRoot().setVisibility(visible ? View.VISIBLE : View.GONE);
}
private void scaleScreen() {
@@ -417,8 +448,8 @@ public class ScanActivity extends CatimaAppCompatActivity {
float mediumSizePx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,MEDIUM_SCALE_FACTOR_DIP,getResources().getDisplayMetrics());
boolean shouldScaleSmaller = screenHeight < mediumSizePx;
customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedIcon.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedTitle.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
customBarcodeScannerBinding.cameraErrorLayout.cameraErrorIcon.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
customBarcodeScannerBinding.cameraErrorLayout.cameraErrorTitle.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
}
private int obtainThemeAttribute(int attribute) {
@@ -444,7 +475,11 @@ public class ScanActivity extends CatimaAppCompatActivity {
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (requestCode == CaptureManager.getCameraPermissionReqCode()) {
showCameraPermissionMissingText(!granted);
if (granted) {
hideCameraError();
} else {
showCameraPermissionMissingText();
}
} else if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE || requestCode == PERMISSION_SCAN_ADD_FROM_PDF) {
if (granted) {
if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE) {

View File

@@ -13,6 +13,8 @@ import android.graphics.Color;
import android.graphics.ImageDecoder;
import android.graphics.Matrix;
import android.graphics.pdf.PdfRenderer;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
import android.os.Build;
import android.os.ParcelFileDescriptor;
@@ -1015,4 +1017,12 @@ public class Utils {
return false;
});
}
public static boolean deviceHasCamera(Context context) {
try {
return ((CameraManager) context.getSystemService(Context.CAMERA_SERVICE)).getCameraIdList().length > 0;
} catch (CameraAccessException e) {
return false;
}
}
}

View File

@@ -1,212 +0,0 @@
package protect.card_locker.importexport;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.work.Data;
import androidx.work.ForegroundInfo;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import protect.card_locker.DBHelper;
import protect.card_locker.NotificationHelper;
import protect.card_locker.R;
public class ImportExportWorker extends Worker {
private final String TAG = "Catima";
public static final String INPUT_URI = "uri";
public static final String INPUT_ACTION = "action";
public static final String INPUT_FORMAT = "format";
public static final String INPUT_PASSWORD = "password";
public static final String ACTION_IMPORT = "import";
public static final String ACTION_EXPORT = "export";
public static final String OUTPUT_ERROR_REASON = "errorReason";
public static final String ERROR_GENERIC = "errorTypeGeneric";
public static final String ERROR_PASSWORD_REQUIRED = "errorTypePasswordRequired";
public static final String OUTPUT_ERROR_DETAILS = "errorDetails";
public ImportExportWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
Log.e("CATIMA", "Started import/export worker");
Context context = getApplicationContext();
Data inputData = getInputData();
String uriString = inputData.getString(INPUT_URI);
String action = inputData.getString(INPUT_ACTION);
String format = inputData.getString(INPUT_FORMAT);
String password = inputData.getString(INPUT_PASSWORD);
if (action.equals(ACTION_IMPORT)) {
Log.e("CATIMA", "Import requested");
setForegroundAsync(createForegroundInfo(NotificationHelper.CHANNEL_IMPORT, NotificationHelper.IMPORT_PROGRESS_ID, R.string.importing));
ImportExportResult result;
InputStream stream;
try {
stream = context.getContentResolver().openInputStream(Uri.parse(uriString));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
final SQLiteDatabase database = new DBHelper(context).getWritableDatabase();
try {
InputStreamReader writer = new InputStreamReader(stream, StandardCharsets.UTF_8);
result = MultiFormatImporter.importData(context, database, stream, DataFormat.valueOf(format), password.toCharArray());
writer.close();
} catch (IOException e) {
Log.e(TAG, "Unable to import file", e);
NotificationHelper.sendNotification(context, NotificationHelper.IMPORT_ID, NotificationHelper.createNotificationBuilder(context, NotificationHelper.CHANNEL_IMPORT, R.drawable.ic_import_export_white_24dp, context.getString(R.string.importFailedTitle), e.getLocalizedMessage()).build());
Data failureData = new Data.Builder()
.putString(OUTPUT_ERROR_REASON, ERROR_GENERIC)
.putString(OUTPUT_ERROR_DETAILS, e.getLocalizedMessage())
.putString(INPUT_URI, uriString)
.putString(INPUT_ACTION, action)
.putString(INPUT_FORMAT, format)
.putString(INPUT_PASSWORD, password)
.build();
return Result.failure(failureData);
}
Log.i(TAG, "Import result: " + result);
if (result.resultType() == ImportExportResultType.Success) {
NotificationHelper.sendNotification(context, NotificationHelper.IMPORT_ID, NotificationHelper.createNotificationBuilder(context, NotificationHelper.CHANNEL_IMPORT, R.drawable.ic_import_export_white_24dp, context.getString(R.string.importSuccessfulTitle), context.getString(R.string.importSuccessful)).build());
return Result.success();
} else if (result.resultType() == ImportExportResultType.BadPassword) {
Log.e(TAG, "Needs password, unhandled for now");
NotificationHelper.sendNotification(context, NotificationHelper.IMPORT_ID, NotificationHelper.createNotificationBuilder(context, NotificationHelper.CHANNEL_IMPORT, R.drawable.ic_import_export_white_24dp, context.getString(R.string.importing), context.getString(R.string.passwordRequired)).build());
Data failureData = new Data.Builder()
.putString(OUTPUT_ERROR_REASON, ERROR_PASSWORD_REQUIRED)
.putString(OUTPUT_ERROR_DETAILS, result.developerDetails())
.putString(INPUT_URI, uriString)
.putString(INPUT_ACTION, action)
.putString(INPUT_FORMAT, format)
.putString(INPUT_PASSWORD, password)
.build();
return Result.failure(failureData);
} else {
NotificationHelper.sendNotification(context, NotificationHelper.IMPORT_ID, NotificationHelper.createNotificationBuilder(context, NotificationHelper.CHANNEL_IMPORT, R.drawable.ic_import_export_white_24dp, context.getString(R.string.importFailedTitle), context.getString(R.string.importFailed)).build());
Data failureData = new Data.Builder()
.putString(OUTPUT_ERROR_REASON, ERROR_GENERIC)
.putString(OUTPUT_ERROR_DETAILS, result.developerDetails())
.putString(INPUT_URI, uriString)
.putString(INPUT_ACTION, action)
.putString(INPUT_FORMAT, format)
.putString(INPUT_PASSWORD, password)
.build();
return Result.failure(failureData);
}
} else {
Log.e("CATIMA", "Export requested");
setForegroundAsync(createForegroundInfo(NotificationHelper.CHANNEL_EXPORT, NotificationHelper.EXPORT_PROGRESS_ID, R.string.exporting));
ImportExportResult result;
OutputStream stream;
try {
stream = context.getContentResolver().openOutputStream(Uri.parse(uriString));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
final SQLiteDatabase database = new DBHelper(context).getReadableDatabase();
try {
OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
result = MultiFormatExporter.exportData(context, database, stream, DataFormat.valueOf(format), password.toCharArray());
writer.close();
} catch (IOException e) {
Log.e(TAG, "Unable to export file", e);
NotificationHelper.sendNotification(context, NotificationHelper.EXPORT_ID, NotificationHelper.createNotificationBuilder(context, NotificationHelper.CHANNEL_EXPORT, R.drawable.ic_import_export_white_24dp, context.getString(R.string.exportFailedTitle), e.getLocalizedMessage()).build());
Data failureData = new Data.Builder()
.putString(OUTPUT_ERROR_REASON, ERROR_GENERIC)
.putString(OUTPUT_ERROR_DETAILS, e.getLocalizedMessage())
.putString(INPUT_URI, uriString)
.putString(INPUT_ACTION, action)
.putString(INPUT_FORMAT, format)
.putString(INPUT_PASSWORD, password)
.build();
return Result.failure(failureData);
}
Log.i(TAG, "Export result: " + result);
if (result.resultType() == ImportExportResultType.Success) {
NotificationHelper.sendNotification(context, NotificationHelper.EXPORT_ID, NotificationHelper.createNotificationBuilder(context, NotificationHelper.CHANNEL_EXPORT, R.drawable.ic_import_export_white_24dp, context.getString(R.string.exportSuccessfulTitle), context.getString(R.string.exportSuccessful)).build());
return Result.success();
} else {
NotificationHelper.sendNotification(context, NotificationHelper.EXPORT_ID, NotificationHelper.createNotificationBuilder(context, NotificationHelper.CHANNEL_EXPORT, R.drawable.ic_import_export_white_24dp, context.getString(R.string.exportFailedTitle), context.getString(R.string.exportFailed)).build());
Data failureData = new Data.Builder()
.putString(OUTPUT_ERROR_REASON, ERROR_GENERIC)
.putString(OUTPUT_ERROR_DETAILS, result.developerDetails())
.putString(INPUT_URI, uriString)
.putString(INPUT_ACTION, action)
.putString(INPUT_FORMAT, format)
.putString(INPUT_PASSWORD, password)
.build();
return Result.failure(failureData);
}
}
}
@NonNull
private ForegroundInfo createForegroundInfo(@NonNull String channel, int notificationId, int title) {
Context context = getApplicationContext();
String cancel = context.getString(R.string.cancel);
// This PendingIntent can be used to cancel the worker
PendingIntent intent = WorkManager.getInstance(context)
.createCancelPendingIntent(getId());
Notification.Builder notificationBuilder = NotificationHelper.createNotificationBuilder(context, channel, R.drawable.ic_import_export_white_24dp, context.getString(title), null);
Notification notification = notificationBuilder
.setOngoing(true)
// Add the cancel action to the notification which can
// be used to cancel the worker
.addAction(android.R.drawable.ic_delete, cancel, intent)
.build();
return new ForegroundInfo(notificationId, notification);
}
}

View File

@@ -45,7 +45,7 @@ public class MultiFormatImporter {
break;
}
String error;
String error = null;
if (importer != null) {
File inputFile;
try {

View File

@@ -9,20 +9,20 @@
tools:showIn="@layout/custom_barcode_scanner">
<LinearLayout
android:id="@+id/camera_permission_denied_clickable_area"
android:id="@+id/camera_error_clickable_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/camera_permission_denied_icon"
android:id="@+id/camera_error_icon"
android:layout_width="match_parent"
android:layout_height="84dp"
android:scaleType="fitCenter"
android:src="@drawable/camera_permission_denied" />
android:src="@drawable/camera_error" />
<TextView
android:id="@+id/camera_permission_denied_title"
android:id="@+id/camera_error_title"
style="@style/TextAppearance.Material3.HeadlineLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -30,12 +30,12 @@
android:text="@string/cameraPermissionDeniedTitle" />
<TextView
android:id="@+id/camera_permission_denied_message"
android:id="@+id/camera_error_message"
style="@style/AppTheme.TextView.NoData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/noCameraPermissionDirectToSystemSetting" />
android:text="@string/zxing_msg_camera_framework_bug" />
</LinearLayout>
</RelativeLayout>

View File

@@ -34,8 +34,8 @@
android:padding="@dimen/activity_scanner_padding">
<include
android:id="@+id/camera_permission_denied_layout"
layout="@layout/camera_permission_failed_layout"
android:id="@+id/camera_error_layout"
layout="@layout/camera_error_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"

View File

@@ -15,40 +15,40 @@ Altonss
Michael Moroni
GM
Eric
laralem
Petr Novák
Joel A
laralem
Taco
pfaffenrodt
Aayush Gupta
HudobniVolk
大王叫我来巡山
Nyatsuki
Scrambled777
Giovanni Donisi
Jiri Grönroos
大王叫我来巡山
Samantaz Fox
arno-github
Cliff Heraldo
Sergio Paredes
Ankit Tiwari
Scrambled777
Milo Ivir
Milan Šalka
mdvhimself
Balázs Meskó
Skrripy
huuhaa
waffshappen
ikanakova
Projjal Moitra
Quentin PAGÈS
Denis Shilin
Robin Liu
Ziad OUALHADJ
ikanakova
ngocanhtve
waffshappen
Ziad OUALHADJ
Robin Liu
Denis Shilin
Alexander Ivanov
Miha Frangež
Viet Nguyen Hoang
Miha Frangež
Silvério Santos
Virginie
Michael Gangolf
@@ -58,3 +58,4 @@ Govind S Nair
Freddo espresso
arshbeerSingh
MisterCosta96
しいたけ

View File

@@ -267,7 +267,7 @@
<string name="noCameraPermissionDirectToSystemSetting">لمسح الباركود، ستحتاج Catima إلى الوصول إلى الكاميرا. اضغط هنا لتغيير إعدادات الأذونات.</string>
<string name="updateBalance">تحديث الرصيد</string>
<string name="updateBalanceHint">أدخل المبلغ</string>
<string name="storageReadPermissionRequired">الصلاحيه للوصل للتخزين مطلوبة لهذا الاجراء</string>
<string name="storageReadPermissionRequired">الصلاحيه للوصل للتخزين مطلوبة لهذا الاجراء</string>
<string name="validFromDate">عربيه</string>
<string name="cameraPermissionRequired">إذن للوصول إلى الكاميرا اللازمة لهذا الإجراء…</string>
<string name="anyDate">أي تاريخ</string>
@@ -310,7 +310,7 @@
<string name="enter_card_id">أدخل رقم الهوية أو النص الموجود على بطاقتك</string>
<string name="addWithoutBarcode">إضافة بدون باركود</string>
<string name="field_must_not_be_empty">يجب ألا يكون الحقل فارغا</string>
<string name="app_name">كاتيما</string>
<string name="app_name">Catima</string>
<string name="settings_follow_sensor_orientation">التدوير دائمًا ( تجاهل إعدادات النظام)</string>
<string name="add_manually_warning_title">الفحص موصى به</string>
<string name="continue_">استمر</string>
@@ -322,5 +322,6 @@
<string name="errorReadingFile">لا يمكن قراءة الملف</string>
<string name="failedLaunchingFileManager">لم يتم العثور على مدير ملفات مدعوم</string>
<string name="multipleBarcodesFoundPleaseChooseOne">اي من الـbarcodes تريد استخدامه؟</string>
<string name="pageWithNumber">صفحة<xliff:g>%d</xliff:g></string>
<string name="pageWithNumber">صفحة <xliff:g>%d</xliff:g></string>
<string name="noCameraFoundGuideText">يبدوا أن جهازك لا يمتلك كاميرا. إذا كان يمتلكها، أطفئ الجهاز وحاول مرة اخرى. اذا لم ينجح ذلك، أضغط على زر \"المزيد من الأختيارات\" في الأسفل لإضافة الباركود بطريقة أخرى.</string>
</resources>

View File

@@ -12,16 +12,16 @@
<string name="edit">Bearbeiten</string>
<string name="delete">Löschen</string>
<string name="confirm">Bestätigen</string>
<string name="star">Zu den Favoriten hinzufügen</string>
<string name="unstar">Aus den Favoriten entfernen</string>
<string name="star">Zu Favoriten hinzufügen</string>
<string name="unstar">Aus Favoriten entfernen</string>
<string name="ok">OK</string>
<string name="sendLabel">Senden </string>
<string name="sendLabel">Senden…</string>
<string name="editCardTitle">Karte bearbeiten</string>
<string name="addCardTitle">Neue Karte</string>
<string name="scanCardBarcode">Barcode scannen</string>
<string name="cardShortcut">Shortcut zu einer Karte</string>
<string name="cardShortcut">Kartenkürzel</string>
<string name="noCardsMessage">Füge zuerst eine Karte hinzu</string>
<string name="noCardExistsError">Diese Karte konnte nicht gefunden werden</string>
<string name="noCardExistsError">Konnte die Karte nicht finden</string>
<string name="importExport">Import/Export</string>
<string name="exportName">Export</string>
<string name="importExportHelp">Wenn du deine Daten sicherst, kannst du sie auf ein anderes Gerät übertragen.</string>
@@ -33,12 +33,12 @@
<string name="exportFailed">Export konnte nicht durchgeführt werden</string>
<string name="importing">Importiere…</string>
<string name="exporting">Exportiere…</string>
<string name="importOptionFilesystemTitle">Importiere aus dem Dateisystem</string>
<string name="importOptionFilesystemExplanation">Wähle eine Datei vom Dateisystem aus.</string>
<string name="importOptionFilesystemButton">Wähle vom Dateisystem</string>
<string name="importOptionApplicationTitle">Andere Anwendungen</string>
<string name="importOptionFilesystemTitle">Aus Dateisystem importieren</string>
<string name="importOptionFilesystemExplanation">Eine bestimmte Datei aus dem Dateisystem auswählen.</string>
<string name="importOptionFilesystemButton">vom Dateisystem</string>
<string name="importOptionApplicationTitle">Andere App verwenden</string>
<string name="importOptionApplicationExplanation">Beliebige Anwendung oder deinen bevorzugten Dateimanager zur Dateiauswahl verwenden.</string>
<string name="importOptionApplicationButton">Aus anderer Anwendung</string>
<string name="importOptionApplicationButton">Andere App verwenden</string>
<string name="about">Über</string>
<string name="app_license">Freie Software, lizensiert unter der GPLv3+</string>
<string name="about_title_fmt">Über <xliff:g id="app_name">%s</xliff:g></string>
@@ -66,7 +66,7 @@
<string name="noGroups">Klicke auf das Pluszeichen +, um eine Gruppe hinzuzufügen.</string>
<string name="noGroupCards">Diese Gruppe ist leer</string>
<string name="groups">Gruppen</string>
<string name="enter_group_name">Gib einen Gruppennamen ein</string>
<string name="enter_group_name">Gruppennamen eingeben</string>
<string name="leaveWithoutSaveConfirmation">Beenden ohne zu speichern\?</string>
<string name="leaveWithoutSaveTitle">Beenden</string>
<string name="failedOpeningFileManager">Installiere zuerst einen Dateimanager.</string>
@@ -95,7 +95,7 @@
<string name="expiryStateSentence">Läuft ab: <xliff:g>%s</xliff:g></string>
<string name="settings_disable_lockscreen_while_viewing_card">Sperrbildschirm verhindern</string>
<string name="settings_keep_screen_on">Bildschirm aktiv lassen</string>
<string name="privacy_policy_popup_text">Hinweis zum Datenschutz (oft gefordert):
<string name="privacy_policy_popup_text">Hinweis zum Datenschutz (von einigen App-Stores verlangt):
\n
\nKEINE DATEN WERDEN GESAMMELT, was jeder bestätigen kann, da unsere Anwendung eine freie Software ist.</string>
<string name="accept">Annehmen</string>
@@ -112,10 +112,10 @@
<string name="importCatimaMessage">Wähle deinen <i>catima.zip</i>-Export aus Catima zum Importieren aus.
\nErstelle ihn aus dem Import/Export-Menü einer anderen Catima-Anwendung, indem du dort zuerst Export drückst.</string>
<string name="importCatima">Aus Catima importieren</string>
<string name="setBarcodeId">Manuell eingeben</string>
<string name="setBarcodeId">Barcodewert festlegen</string>
<string name="sameAsCardId">Entspricht Kartennummer</string>
<string name="barcodeId">Barcodewert</string>
<string name="errorReadingImage">Bildverarbeitung fehlgeschlagen</string>
<string name="errorReadingImage">Konnte das Bild nicht lesen</string>
<string name="noBarcodeFound">Kein Barcode erkannt</string>
<string name="addFromImage">Bild aus der Galerie wählen</string>
<string name="unsupportedBarcodeType">Dieser Barcodetyp kann noch nicht angezeigt werden. Wir hoffen das Format in einer zukünftigen Version zu unterstützen.</string>
@@ -129,17 +129,17 @@
<string name="updateBarcodeQuestionTitle">Barcodewert aktualisieren?</string>
<string name="takePhoto">Foto aufnehmen</string>
<string name="removeImage">Bild entfernen</string>
<string name="setBackImage">Kartenrückseite</string>
<string name="setFrontImage">Kartenvorderseite</string>
<string name="setBackImage">Rückseite einstellen</string>
<string name="setFrontImage">Vorderseite einstellen</string>
<string name="photos">Fotos</string>
<string name="frontImageDescription">Bild der Vorseite</string>
<string name="backImageDescription">Bild der Rückseite</string>
<string name="frontImageDescription">Vorderseite</string>
<string name="backImageDescription">Rückseite</string>
<string name="passwordRequired">Bitte gib das Passwort ein</string>
<string name="importStocardMessage">Wähle deinen <i>***.zip</i>-Export aus Stocard zum Importieren aus.
\nSie erhalten ihn, indem du eine E-Mail an support@stocardapp.com sendest und um einen Export deiner Daten bitten.</string>
<string name="importStocard">Von Stocard importieren</string>
<string name="turn_flashlight_off">Licht ausschalten</string>
<string name="turn_flashlight_on">Licht einschalten</string>
<string name="turn_flashlight_off">Blitzlicht ausschalten</string>
<string name="turn_flashlight_on">Blitzlicht einschalten</string>
<string name="failedGeneratingShareURL">URL konnte nicht erstellt werden. Bitte melde das an uns.</string>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> ausgewählt</item>
@@ -193,10 +193,10 @@
<string name="editGroup">Gruppe wird bearbeitet: <xliff:g>%s</xliff:g></string>
<string name="group_edit">Gruppe bearbeiten</string>
<string name="noGiftCardsGroup">Erstelle einige Karten und ordne sie dann hier der Gruppe zu.</string>
<string name="setIcon">Vorschaubild setzen</string>
<string name="setIcon">Vorschaubild festlegen</string>
<string name="selectColor">Farbe auswählen</string>
<string name="translate_platform">auf Weblate</string>
<string name="shortcutSelectCard">Wählen Sie eine Karte</string>
<string name="shortcutSelectCard">Wähle eine Karte</string>
<string name="options">Optionen</string>
<string name="showMoreInfo">Infos anzeigen</string>
<string name="starred">als Favorit</string>
@@ -233,7 +233,7 @@
<string name="failedToRetrieveImageFile">Bilddatei konnte nicht abgerufen werden</string>
<string name="updateBalanceTitle">Wie viel hast du ausgegeben oder erhalten?</string>
<string name="cameraPermissionDeniedTitle">Kein Zugriff auf die Kamera möglich</string>
<string name="noCameraPermissionDirectToSystemSetting">Um Strichcodes zu scannen, benötigt Catima Zugriff auf Ihre Kamera. Tippen Sie hier, um Ihre Berechtigungseinstellungen zu ändern.</string>
<string name="noCameraPermissionDirectToSystemSetting">Um Strichcodes zu scannen, benötigt Catima Zugriff auf deine Kamera. Tippe hier, um deine Berechtigungseinstellungen zu ändern.</string>
<string name="updateBalanceHint">Betrag eingeben</string>
<string name="importCards">Karten importieren</string>
<string name="currentBalanceSentence">Aktuelles Guthaben: <xliff:g>%s</xliff:g></string>
@@ -245,23 +245,23 @@
<string name="validFromSentence">Gültig ab: <xliff:g>%s</xliff:g></string>
<string name="chooseValidFromDate">Gültig-ab-Datum wählen</string>
<string name="anyDate">Beliebiges Datum</string>
<string name="icon_header_click_text">Langes Drücken zum Bearbeiten der Vorschau</string>
<string name="switchToBarcode">Umschalten auf Barcode</string>
<string name="openFrontImageInGalleryApp">Vorderes Bild in der Galerie öffnen</string>
<string name="openBackImageInGalleryApp">Hinteres Bild in der Galerie öffnen</string>
<string name="icon_header_click_text">Zum Bearbeiten des Vorschaubildes lang drücken</string>
<string name="switchToBarcode">Zum Barcode wechseln</string>
<string name="openFrontImageInGalleryApp">Vorderseite in Galerie öffnen</string>
<string name="openBackImageInGalleryApp">Rückseite in Galerie öffnen</string>
<string name="height">Höhe:</string>
<string name="switchToFrontImage">Zum vorderen Bild wechseln</string>
<string name="switchToBackImage">Zum hinteren Bild wechseln</string>
<string name="switchToFrontImage">Zur Vorderseite wechseln</string>
<string name="switchToBackImage">Zur Rückseite wechseln</string>
<string name="setBarcodeHeight">Barcode-Höhe einstellen</string>
<string name="donate">Spenden</string>
<string name="show_note">Notiz anzeigen</string>
<string name="show_balance">Betrag anzeigen</string>
<string name="show_validity">Gültigkeitsdauer anzeigen</string>
<string name="show_name_below_image_thumbnail">Namen unter Bildvorschau anzeigen</string>
<string name="settings_allow_content_provider_read_title">Anderen Anwendungen den Zugriff auf meine Daten gestatten</string>
<string name="show_name_below_image_thumbnail">Namen unter Vorschaubild anzeigen</string>
<string name="settings_allow_content_provider_read_title">Anderen Apps den Zugriff auf meine Daten gestatten</string>
<string name="permissionReadCardsLabel">Catima-Karten lesen</string>
<string name="permissionReadCardsDescription">lesen deiner Catima Karten mit allen Details, einschließlich Notizen und Bildern</string>
<string name="settings_allow_content_provider_read_summary">Anwendungen müssen weiterhin eine Genehmigung beantragen, um Zugriff zu erhalten</string>
<string name="permissionReadCardsDescription">Lesen deiner Catima Karten mit allen Details, einschließlich Notizen und Bildern</string>
<string name="settings_allow_content_provider_read_summary">Apps müssen weiterhin eine Genehmigung beantragen, um Zugriff zu erhalten</string>
<string name="settings_display_barcode_max_brightness_summary">Erforderlich für das Funktionieren einiger Scanner</string>
<string name="settings_keep_screen_on_summary">Deaktiviert die Bildschirmzeitüberschreitung beim Anzeigen einer Karte</string>
<string name="settings_disable_lockscreen_while_viewing_card_summary">Deaktiviert die Bildschirmsperre während der Anzeige einer Karte</string>
@@ -269,9 +269,9 @@
<string name="settings_category_title_cards">Karten</string>
<string name="settings_category_title_privacy">Datenschutz</string>
<string name="settings_category_title_general">Allgemein</string>
<string name="view_online">Zeige online</string>
<string name="view_online">Online anzeigen</string>
<string name="action_display_options">Anzeigeoptionen</string>
<string name="show_archived_cards">Zeige archivierte Karten</string>
<string name="show_archived_cards">Archivierte Karten anzeigen</string>
<string name="app_copyright_short">Copyright © Sylvia van Os und Mitwirkende</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os und Mitwirkende</string>
<string name="card_id_must_not_be_empty">Kartennummer darf nicht leer sein</string>
@@ -279,9 +279,9 @@
<string name="add_a_card_in_a_different_way">Karte anders hinzufügen</string>
<string name="action_more_options">Mehr Optionen</string>
<string name="enter_card_id">Gib die Codenummer oder Ziffernfolge deiner Karte an</string>
<string name="addWithoutBarcode">Eine Karde ohne Code hinzufügen</string>
<string name="addWithoutBarcode">Eine Karte ohne Code hinzufügen</string>
<string name="field_must_not_be_empty">Feld darf nicht leer sein</string>
<string name="manually_enter_barcode_instructions">Trage die ID Nummer oder Text deiner Karte ein und drücke auf den Barcode, der wie auf deiner Karte aussieht.</string>
<string name="manually_enter_barcode_instructions">Trage die ID Nummer oder Text deiner Karte ein und drücke auf den Barcode, der wie der auf deiner Karte aussieht.</string>
<string name="app_name">Catima</string>
<string name="settings_follow_sensor_orientation">Immer drehen (ignoriert Systemeinstellungen)</string>
<string name="continue_">Fortfahren</string>
@@ -293,6 +293,7 @@
<string name="addFromPdfFile">PDF-Datei auswählen</string>
<string name="errorReadingFile">Datei konnte nicht gelesen werden</string>
<string name="failedLaunchingFileManager">Konnte keinen unterstützten Dateimanager finden</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Welchen der gefundenen Barcodes möchten Sie verwenden?</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Welchen der gefundenen Barcodes möchtest du verwenden?</string>
<string name="pageWithNumber">Seite <xliff:g>%d</xliff:g></string>
<string name="noCameraFoundGuideText">Dein Gerät scheint nicht über eine Kamera zu verfügen. Wenn dies der Fall ist, versuche, das Gerät neu zu starten. Andernfalls verwende die Schaltfläche Weitere Optionen unten, um einen Barcode auf andere Weise hinzuzufügen.</string>
</resources>

View File

@@ -70,7 +70,7 @@
<string name="backImageDescription">Imágen dorsal</string>
<string name="noCameraPermissionDirectToSystemSetting">Para escanear códigos de barra, Catima necesitará acceso a la cámara. Presione aquí para cambiar la configuración de sus permisos.</string>
<string name="settings_lock_on_opening_orientation">Bloquear a la orientación utilizada al abrir la tarjeta</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="app_loyalty_card_keychain">Cartera para Tarjetas de Fidelización</string>
<string name="importOptionFilesystemTitle">Importar desde su sistema de archivos</string>
<string name="leaveWithoutSaveTitle">Salir</string>
<string name="expiryStateSentence">Expira: <xliff:g>%s</xliff:g></string>
@@ -184,4 +184,37 @@
<string name="settings_keep_screen_on_summary">Deshabilita el tiempo de espera de la pantalla mientras se ve una tarjeta</string>
<string name="thumbnailDescription">Miniatura</string>
<string name="deleteConfirmationGroup">¿Eliminar grupo\?</string>
<string name="updateBarcodeQuestionText">Has cambiado el ID. ¿Quieres actualizar también el código de barras para usar el mismo valor?</string>
<string name="settings_locale">Idioma</string>
<string name="settings_system_locale">Sistema</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_pink_theme">Rosa</string>
<string name="exportPassword">Agregar una contraseña para protejer tu exportación (opcional)</string>
<string name="settings_sky_blue_theme">Celeste</string>
<string name="settings_green_theme">Verde</string>
<string name="settings_grey_theme">Gris</string>
<string name="exportPasswordHint">Ingresar contraseña</string>
<string name="setIcon">Establecer miniatura</string>
<string name="showMoreInfo">Mostrar información</string>
<string name="turn_flashlight_on">Encender linterna</string>
<string name="turn_flashlight_off">Apagar linterna</string>
<string name="updateBalance">Actualizar balance</string>
<string name="failedToRetrieveImageFile">Error al obtener archivo de imagen</string>
<string name="settings_oled_dark_summary">Reduce uso de batería en pantallas OLED</string>
<string name="settings_oled_dark">Fondo negro puro para tema oscuro</string>
<string name="selectColor">Seleccionar color</string>
<string name="settings_theme_color">Color del tema</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_violet_theme">Violeta</string>
<string name="settings_brown_theme">Marrón</string>
<string name="sort">Ordenar</string>
<string name="settings_blue_theme">Azul</string>
<string name="app_contributors">Hecho posible por: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="barcodeLongPressMessage">Solo se puede abrir imágenes en la aplicación de galería</string>
<string name="settings_follow_sensor_orientation">Siempre rotar (ignora configuración del sistema)</string>
<string name="yes">Si</string>
<string name="no">No</string>
<string name="passwordRequired">Por favor ingresa la contraseña</string>
<string name="failedGeneratingShareURL">No se pudo generar URL compartible. Por favor reporte esto.</string>
<string name="sort_by_name">Nombre</string>
</resources>

View File

@@ -302,4 +302,5 @@
<string name="failedLaunchingFileManager">No se ha podido encontrar un gestor de archivos compatible</string>
<string name="multipleBarcodesFoundPleaseChooseOne">¿Cuál de los códigos de barras encontrados desea utilizar?</string>
<string name="pageWithNumber">Página <xliff:g>%d</xliff:g></string>
<string name="noCameraFoundGuideText">Tu dispositivo no parece tener cámara. Si la tiene, intente reiniciar el dispositivo. De lo contrario, utilice el botón Más opciones a continuación para añadir un código de barras de otra manera.</string>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="action_search">Hanap</string>
<string name="app_name">Catima</string>
</resources>

View File

@@ -302,4 +302,5 @@
<string name="failedLaunchingFileManager">Impossible de trouver un gestionnaire de fichiers supporté</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Quel code-barre, parmi ceux trouvés, voulez-vous utiliser?</string>
<string name="pageWithNumber">Page <xliff:g>%d</xliff:g></string>
<string name="noCameraFoundGuideText">Votre appareil ne semble pas disposer d\'une caméra. Si c\'est le cas, veuillez essayer de redémarrer l\'appareil. Sinon, vous pouvez utiliser le bouton \"Plus d\'options\" ci-dessous pour ajouter un code-barre d\'une autre manière.</string>
</resources>

View File

@@ -295,4 +295,5 @@
<string name="addFromPdfFile">एक PDF फाइल चुनें</string>
<string name="errorReadingFile">फाइल को पढ़ा नहीं जा सका</string>
<string name="failedLaunchingFileManager">समर्थित फाइल प्रबंधक नहीं मिल सका</string>
<string name="noCameraFoundGuideText">ऐसा लगता है कि आपके डिवाइस में कैमरा नहीं है। अगर है, तो डिवाइस को रीबूट करने का प्रयास करें। अन्यथा, किसी अन्य तरीके से बारकोड जोड़ने के लिए नीचे दिए गए अधिक विकल्प बटन का उपयोग करें।</string>
</resources>

View File

@@ -290,4 +290,10 @@
<string name="continue_">Tovább</string>
<string name="spend">Költött</string>
<string name="receive">Megkapott</string>
<string name="addFromPdfFile">PDF fájl kiválasztása</string>
<string name="errorReadingFile">A fájl nem olvasható</string>
<string name="pageWithNumber"><xliff:g>%d</xliff:g>. oldal</string>
<string name="failedLaunchingFileManager">Nem található támogatott fájlkezelő</string>
<string name="multipleBarcodesFoundPleaseChooseOne">A talált vonalkódok közül melyiket szeretné használni?</string>
<string name="noCameraFoundGuideText">Úgy tűnik, az eszközén nincs kamera. Ha van, próbálja meg újraindítani az eszközt. Másképp, használja a További beállítások gombot alul, hogy máshogy hozzáadjon egy vonalkódot.</string>
</resources>

View File

@@ -302,4 +302,5 @@
<string name="addFromPdfFile">Seleziona un file PDF</string>
<string name="failedLaunchingFileManager">Impossibile trovare un file manager supportato</string>
<string name="pageWithNumber">Pagina <xliff:g>%d</xliff:g></string>
<string name="noCameraFoundGuideText">Sembra che il tuo dispositivo non abbia una fotocamera. In tal caso, prova a riavviare il dispositivo. Altrimenti, utilizza il pulsante Altre opzioni di seguito per aggiungere un codice a barre in un altro modo.</string>
</resources>

View File

@@ -52,8 +52,8 @@
<string name="exportSuccessful">データがエクスポートされました</string>
<string name="importSuccessful">データがインポートされました</string>
<string name="intent_import_card_from_url_share_text">カード共有をしましょう</string>
<string name="settings_disable_lockscreen_while_viewing_card">バーコード表示中画面をロックしない</string>
<string name="settings_keep_screen_on">バーコード表示中画面を消灯しない</string>
<string name="settings_disable_lockscreen_while_viewing_card">バーコード表示中画面をロックしない</string>
<string name="settings_keep_screen_on">バーコード表示中画面を点けたままにする</string>
<string name="settings_display_barcode_max_brightness">バーコード表示画面を明るくする</string>
<string name="settings_dark_theme">ダーク</string>
<string name="settings_light_theme">ライト</string>
@@ -64,11 +64,11 @@
<string name="thumbnailDescription">サムネイル</string>
<string name="selectBarcodeTitle">バーコード選択</string>
<string name="app_libraries">Libre third-party libraries: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
<string name="about_title_fmt">About <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">バージョン: <xliff:g id="version">%s</xliff:g></string>
<string name="about_title_fmt"><xliff:g id="app_name">%s</xliff:g> について</string>
<string name="app_license">Copylefted libre software, licensed GPLv3+</string>
<string name="app_resources">Libre third-party resources: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="about">Catimaについて</string>
<string name="about">このアプリについて</string>
<string name="importOptionApplicationButton">外部のアプリを使う</string>
<string name="importOptionApplicationExplanation">任意のアプリやお気に入りのファイルマネージャーからファイルを開く。</string>
<string name="importOptionApplicationTitle">外部アプリを使う</string>
@@ -130,8 +130,8 @@
<string name="takePhoto">写真を撮影する</string>
<string name="removeImage">画像を削除</string>
<string name="setBackImage">裏面の画像を設定</string>
<string name="setFrontImage">オモテ面の画像を設定</string>
<string name="photos">フォト</string>
<string name="setFrontImage">面の画像を設定</string>
<string name="photos">画像</string>
<string name="backImageDescription"></string>
<string name="frontImageDescription"></string>
<string name="importStocardMessage">Stocardでエクスポートした<i>***.zip</i>ファイルを選択してください。
@@ -175,12 +175,12 @@
<string name="exportPasswordHint">パスワードを入力してください</string>
<string name="version_history">更新履歴</string>
<string name="credits">貢献者</string>
<string name="help_translate_this_app">このアプリの翻訳を手伝う</string>
<string name="help_translate_this_app">翻訳を手伝う</string>
<string name="license">ライセンス</string>
<string name="on_google_play">Google Play</string>
<string name="report_error">エラーを報告する</string>
<string name="report_error">問題を報告する</string>
<string name="reverse">逆順</string>
<string name="and_data_usage">and data usage</string>
<string name="and_data_usage">データの扱いなど</string>
<string name="group_updated">グループを更新しました</string>
<string name="editGroup">グループ編集: <xliff:g>%s</xliff:g></string>
<string name="selectColor">色を選択</string>
@@ -189,7 +189,7 @@
<string name="group_name_already_in_use">このグループ名は既に使用されています</string>
<string name="group_name_is_empty">空欄にすることはできません</string>
<string name="shortcutSelectCard">カードを選択してください</string>
<string name="translate_platform">on Weblate</string>
<string name="translate_platform">Weblate</string>
<string name="options">オプション</string>
<string name="show_note">メモを表示</string>
<string name="validFromDate">有効期限</string>
@@ -207,4 +207,31 @@
<string name="settings_portrait_orientation"></string>
<string name="noGiftCardsGroup">いくつかのカードを作って、それらをこのグループにアサインします。</string>
<string name="noCameraPermissionDirectToSystemSetting">バーコードをスキャンするためには、Catimaはカメラへのアクセスを必要とします。ここをタップして権限設定の変更をお願いします。</string>
<string name="importCards">カードをインポート</string>
<string name="show_balance">残高を表示</string>
<string name="show_validity">有効期限を表示</string>
<string name="donate">寄付する</string>
<string name="duplicateCard">複製</string>
<string name="unarchived">アーカイブを解除しました</string>
<string name="welcome">Catimaへようこそ</string>
<string name="show_name_below_image_thumbnail">画像サムネイルの下に名前を表示</string>
<string name="settings_keep_screen_on_summary">画面の自動消灯を無効化します</string>
<string name="settings_category_title_cards">カード</string>
<string name="settings_category_title_general">一般</string>
<string name="settings_disable_lockscreen_while_viewing_card_summary">画面のロックを無効化します</string>
<string name="action_display_options">表示の設定</string>
<string name="unarchive">アーカイブ解除</string>
<string name="archive">アーカイブ</string>
<string name="archived">アーカイブしました</string>
<string name="show_archived_cards">アーカイブしたカードを表示</string>
<string name="addFromPdfFile">PDFファイルを選択</string>
<string name="addWithoutBarcode">バーコードを登録せずにカードを追加</string>
<string name="failedToOpenUrl">ブラウザーをインストールしてください</string>
<string name="previousCard">前へ</string>
<string name="nextCard">次へ</string>
<string name="settings_lock_on_opening_orientation">カードを開いた時の向きに固定</string>
<string name="settings_oled_dark">ダークテーマで黒い背景を使用する</string>
<string name="settings_oled_dark_summary">有機ELディスプレイでの電池の使用量を削減します</string>
<string name="action_more_options">オプション</string>
<string name="add_a_card_in_a_different_way">別の方法でカードを追加</string>
</resources>

View File

@@ -260,7 +260,7 @@
<string name="setBarcodeHeight">Sett strekkodehøyde</string>
<string name="donate">Doner</string>
<string name="permissionReadCardsLabel">Les Catima-kort</string>
<string name="permissionReadCardsDescription">Les kortene dine og detaljene om dem, inkludert notater og bilder</string>
<string name="permissionReadCardsDescription">Les Catima-kortene dine og detaljene om dem, inkludert notater og bilder</string>
<string name="settings_allow_content_provider_read_summary">Programmer vil fremdeles måtte forespørre tilgang for å få det innvilget</string>
<string name="settings_display_barcode_max_brightness_summary">Nødvendig for noen skannere</string>
<string name="settings_keep_screen_on_summary">Skrur av skjermtidsavbrudd under visning av et kort</string>
@@ -290,4 +290,9 @@
<string name="receive">Inntekt</string>
<string name="settings_follow_sensor_orientation">Alltid roter (ignorerer systeminnstilling)</string>
<string name="add_manually_warning_message">I noen butikker er strekkoden forskjellig fra nummeret på kortet. Som følge av dette kan det hende at å skrive inn strekkoden ikke virker. Det anbefales å skanne strekkoden med kameraet istedenfor. Fortsett?</string>
<string name="pageWithNumber">Side <xliff:g>%d</xliff:g></string>
<string name="addFromPdfFile">Velg en PDF-fil</string>
<string name="errorReadingFile">Kunne ikke lese filen</string>
<string name="failedLaunchingFileManager">Fant ikke støttet filbehandler</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Hvilken av de oppdagede strekkodene vil du bruke?</string>
</resources>

View File

@@ -295,4 +295,5 @@
<string name="failedLaunchingFileManager">Geen ondersteunde bestandsbeheerder aangetroffen</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Welke van de gevonden barcodes wil je gebruiken?</string>
<string name="pageWithNumber">Pagina <xliff:g>%d</xliff:g></string>
<string name="noCameraFoundGuideText">Uw apparaat lijkt niet over een camera te beschikken. Als het dat wel doet, probeer uw apparaat dan opnieuw op te starten. Anders gebruikt u de knop \"Meer opties\" beneden om handmatig een streepjescode in te voeren.</string>
</resources>

View File

@@ -309,4 +309,5 @@
<string name="failedLaunchingFileManager">Nie można znaleźć obsługiwanego menedżera plików</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Którego ze znalezionych kodów kreskowych chciałbyś użyć?</string>
<string name="add_manually_warning_message">W przypadku niektórych sklepów wartość kodu kreskowego różni się od liczby zapisanej na karcie. Z tego powodu ręczne wprowadzanie kodu kreskowego może nie zawsze działać. Zdecydowanie zaleca się zeskanowanie kodu kreskowego za pomocą aparatu. Czy nadal chcesz kontynuować?</string>
<string name="noCameraFoundGuideText">Nie wykryto kamery. Jeśli twoje urządzenie posiada kamerę, spróbuj uruchomić je ponownie. W innym wypadku wybierz Więcej opcji i dodaj kartę w inny sposób.</string>
</resources>

View File

@@ -0,0 +1,306 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
<string name="app_name">Catima</string>
<string name="action_search">Pesquisar</string>
<string name="action_add">Adicionar</string>
<string name="noGiftCards">Clique no botão \"+\" para adicionar um cartão ou importar a partir do menu \"⋮\".</string>
<string name="noGiftCardsGroup">Crie alguns cartões e, em seguida, atribua-os ao grupo aqui.</string>
<string name="noMatchingGiftCards">Nenhum resultado. Tente alterar sua pesquisa.</string>
<string name="storeName">Nome</string>
<string name="note">Nota</string>
<string name="cardId">ID do cartão</string>
<string name="barcodeType">Tipo de código de barras</string>
<string name="noBarcode">Nenhum código de barras</string>
<string name="star">Adicionar aos favoritos</string>
<string name="unstar">Remover dos favoritos</string>
<string name="cancel">Cancelar</string>
<string name="save">Salvar</string>
<string name="edit">Editar</string>
<string name="delete">Excluir</string>
<string name="confirm">Confirmar</string>
<string name="deleteTitle">Excluir cartão</string>
<string name="share">Compartilhar</string>
<string name="importExport">Importar/Exportar</string>
<string name="exportSuccessfulTitle">Exportado</string>
<string name="importing">Importando…</string>
<string name="exporting">Exportando…</string>
<string name="noCameraPermissionDirectToSystemSetting">Para ler códigos de barras, Catima precisará de acesso à sua câmera. Toque aqui para alterar suas configurações de permissão.</string>
<string name="importOptionFilesystemTitle">Importar dos seus arquivos</string>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> selecionado</item>
<item quantity="many"><xliff:g>%d</xliff:g> selecionados</item>
<item quantity="other"><xliff:g>%d</xliff:g> selecionados</item>
</plurals>
<plurals name="deleteCardsTitle">
<item quantity="one">Excluir <xliff:g>%d</xliff:g> cartão</item>
<item quantity="many">Excluir <xliff:g>%d</xliff:g> cartões</item>
<item quantity="other">Excluir <xliff:g>%d</xliff:g> cartões</item>
</plurals>
<string name="deleteConfirmation">Excluir esse cartão permanentemente?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Excluir <xliff:g>%d</xliff:g> cartão permanentemente?</item>
<item quantity="many">Excluir <xliff:g>%d</xliff:g> cartões permanentemente?</item>
<item quantity="other">Excluir <xliff:g>%d</xliff:g> cartões permanentemente?</item>
</plurals>
<string name="ok">OK</string>
<string name="sendLabel">Enviar…</string>
<string name="editCardTitle">Editar cartão</string>
<string name="addCardTitle">Adicionar cartão</string>
<string name="scanCardBarcode">Ler código de barras</string>
<string name="cardShortcut">Atalho de cartões</string>
<string name="noCardsMessage">Adicione um cartão primeiro</string>
<string name="barcodeImageDescriptionWithType">Imagem <xliff:g>%s</xliff:g> do código de barras</string>
<string name="noCardExistsError">Não foi possível encontrar esse cartão</string>
<string name="failedParsingImportUriError">Não foi possível analisar o URI de importação</string>
<string name="exportName">Exportar</string>
<string name="importExportHelp">Fazer backup de seus dados permite movê-los para outro dispositivo.</string>
<string name="importSuccessfulTitle">Importado</string>
<string name="importFailedTitle">Falha na importação</string>
<string name="importFailed">Não foi possível importar</string>
<string name="exportFailedTitle">Falha na exportação</string>
<string name="exportFailed">Não foi possível exportar</string>
<string name="storageReadPermissionRequired">Permissão para ler o armazenamento é necessário para esta ação…</string>
<string name="cameraPermissionRequired">Permissão para acessar a câmera é necessária para esta ação…</string>
<string name="permissionReadCardsLabel">Ler cartões Catima</string>
<string name="permissionReadCardsDescription">ler seus cartões Catima e todos os seus detalhes, incluindo notas e imagens</string>
<string name="cameraPermissionDeniedTitle">Não foi possível acessar a câmera</string>
<string name="exportOptionExplanation">Os dados serão gravados em um local de sua escolha.</string>
<string name="importOptionFilesystemExplanation">Escolha um arquivo específico nos seus arquivos.</string>
<plurals name="balancePoints">
<item quantity="one"><xliff:g>%s</xliff:g> ponto</item>
<item quantity="many"><xliff:g>%s</xliff:g> pontos</item>
<item quantity="other"><xliff:g>%s</xliff:g> pontos</item>
</plurals>
<plurals name="groupCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> cartão</item>
<item quantity="many"><xliff:g>%d</xliff:g> cartões</item>
<item quantity="other"><xliff:g>%d</xliff:g> cartões</item>
</plurals>
<string name="noCameraFoundGuideText">Seu dispositivo parece não ter uma câmera. Se tiver, tente reiniciar o dispositivo. Caso contrário, tente usar o botão \"Mais opções\" abaixo para adicionar um código de barras manualmente.</string>
<string name="settings_follow_system_orientation">Padrão do sistema</string>
<string name="settings_lock_on_opening_orientation">Bloquear para orientação usada ao abrir o cartão</string>
<string name="importCatimaMessage">Selecionar arquivo <i>catima.zip</i>, exportado do Catima, para importação.
\nPrimeiro, crie-o pelo menu Importar/Exportar em outro aplicativo Catima clicando em Exportar.</string>
<string name="importLoyaltyCardKeychain">Importar do Loyalty Card Keychain</string>
<string name="importLoyaltyCardKeychainMessage">Selecionar arquivo <i>LoyaltyCardKeychain.csv</i>, exportado do Loyalty Card Keychain, para importação.
\nPrimeiro, crie-o pelo menu Importar/Exportar no Loyalty Card Keychain clicando em Exportar.</string>
<string name="setBarcodeId">Definir valor do código de barras</string>
<string name="importStocard">Importar de Stocard</string>
<string name="importVoucherVault">Importar de Cofre de Vouchers</string>
<string name="barcodeId">Valor no código de barras</string>
<string name="sameAsCardId">Igual ao ID</string>
<string name="photos">Fotos</string>
<string name="unsupportedBarcodeType">Este tipo de código de barras não pode ser exibido. É possível que seja trazido em uma versão futura do aplicativo.</string>
<string name="wrongValueForBarcodeType">O valor não é válido para o tipo de código de barras selecionado</string>
<string name="intent_import_card_from_url_share_multiple_text">Quero compartilhar alguns cartões com você</string>
<string name="backImageDescription">Imagem traseira</string>
<string name="frontImageDescription">Imagem frontal</string>
<string name="setFrontImage">Definir imagem frontal</string>
<string name="setBackImage">Definir imagem traseira</string>
<string name="removeImage">Remover imagem</string>
<string name="takePhoto">Tirar uma photo</string>
<string name="updateBarcodeQuestionTitle">Atualizar valor do código de barras?</string>
<string name="exportPasswordHint">Insira sua senha</string>
<string name="passwordRequired">Por favor, insira a senha</string>
<string name="exportPassword">Defina uma senha para proteger o arquivo exportado (opcional)</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="add_manually_warning_message">Em algumas lojas, o valor do código de barras é diferente do número escrito no cartão. Por esse motivo, inserir um código de barras manualmente pode nem sempre funcionar. É altamente recomendável digitalizar o código de barras com a câmera. Você ainda deseja continuar?</string>
<string name="importOptionApplicationTitle">Usar outro aplicativo</string>
<string name="importOptionApplicationExplanation">Use qualquer aplicativo ou o seu gerenciador de arquivos favorito para abrir um arquivo.</string>
<string name="importOptionApplicationButton">Usar outro aplicativo</string>
<string name="about">Sobre</string>
<string name="about_title_fmt">Sobre <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versão: <xliff:g id="version">%s</xliff:g></string>
<string name="selectBarcodeTitle">Selecionar código de barras</string>
<string name="settings">Configurações</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os e contribuidores</string>
<string name="app_copyright_short">Copyright © Sylvia van Os e contribuidores</string>
<string name="app_copyright_old">Baseado no Loyalty Card Keychain
\ncopyright © 20162020 Branden Archert</string>
<string name="importOptionFilesystemButton">A partir do Sistema de Arquivos</string>
<string name="thumbnailDescription">Miniatura</string>
<string name="starImage">Item favorito</string>
<string name="app_libraries">Bibliotecas open source de terceiros : <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources">Recursos open source de terceiros: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="updateBarcodeQuestionText">Você mudou o ID. Também quer atualizar o código de barras para usar o mesmo valor?</string>
<string name="yes">Sim</string>
<string name="no">Não</string>
<string name="failedGeneratingShareURL">Não foi possível gerar uma URL compartilhável. Por favor, reporte isto.</string>
<string name="turn_flashlight_on">Ligar lanterna</string>
<string name="turn_flashlight_off">Desligar lanterna</string>
<string name="settings_locale">Idioma</string>
<string name="settings_oled_dark_summary">Reduz o uso da bateria em telas OLED</string>
<string name="settings_system_locale">Sistema</string>
<string name="settings_oled_dark">Preto puro como cor de fundo para o tema escuro</string>
<string name="settings_pink_theme">Rosa</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_blue_theme">Azul</string>
<string name="settings_sky_blue_theme">Azul celeste</string>
<string name="settings_green_theme">Verde</string>
<string name="settings_grey_theme">Cinza</string>
<string name="settings_brown_theme">Marrom</string>
<string name="app_contributors">Só foi possível graças a: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="sort">Ordenar</string>
<string name="showMoreInfo">Mostrar informações</string>
<string name="updateBalance">Atualizar saldo</string>
<string name="failedToRetrieveImageFile">Falha ao recuperar o arquivo de imagem</string>
<string name="barcodeLongPressMessage">Apenas imagens podem ser abertas na galeria</string>
<string name="sort_by_most_recently_used">Usado mais recentemente</string>
<string name="reverse">...em ordem inversa</string>
<string name="sort_by">Ordenar por</string>
<string name="version_history">Histórico de Atualização</string>
<string name="and_data_usage">e uso de dados</string>
<string name="rate_this_app">Avalie este aplicativo</string>
<string name="on_google_play">na Google Play</string>
<string name="report_error">Informar erro</string>
<string name="setIcon">Definir miniatura</string>
<string name="options">Opções</string>
<string name="starred">Favoritos</string>
<string name="duplicateCard">Duplicar</string>
<string name="archived">Cartão arquivado</string>
<string name="unarchived">Cartão desarquivado</string>
<string name="failedLaunchingPhotoPicker">Não foi possível encontrar um aplicativo de galeria compatível</string>
<string name="failedToOpenUrl">Instale um navegador primeiro</string>
<string name="welcome">Bem-vindo(a) ao Catima</string>
<string name="importCards">Importar cartões</string>
<plurals name="viewArchivedCardsWithCount">
<item quantity="one">Ver arquivamento (<xliff:g>%1$d</xliff:g> cartão)</item>
<item quantity="many">Ver arquivamento (<xliff:g>%1$d</xliff:g> cartões)</item>
<item quantity="other">Ver arquivamento (<xliff:g>%1$d</xliff:g> cartões)</item>
</plurals>
<string name="height">Altura:</string>
<string name="switchToBarcode">Mudar para código de barras</string>
<string name="switchToFrontImage">Mudar para imagem frontal</string>
<string name="switchToBackImage">Mudar para imagem traseira</string>
<string name="openFrontImageInGalleryApp">Abrir imagem frontal no aplicativo da galeria</string>
<string name="openBackImageInGalleryApp">Abrir imagem traseira no aplicativo da galeria</string>
<string name="setBarcodeHeight">Definir altura do código de barras</string>
<string name="donate">Doar</string>
<string name="icon_header_click_text">Pressione e segure para editar a miniatura</string>
<string name="show_name_below_image_thumbnail">Mostrar nome abaixo da miniatura</string>
<string name="show_note">Mostrar nota</string>
<string name="show_balance">Mostrar saldo</string>
<string name="show_validity">Mostrar validade</string>
<string name="action_more_options">Mais opções</string>
<string name="addWithoutBarcode">Adicionar cartão sem código de barras</string>
<string name="card_id_must_not_be_empty">O ID do cartão não pode estar vazio</string>
<string name="add_a_card_in_a_different_way">Adicionar cartão de outra forma</string>
<string name="field_must_not_be_empty">O campo não pode estar vazio</string>
<string name="spend">Gastar</string>
<string name="receive">Receber</string>
<string name="amountParsingFailed">Quantidade inválida</string>
<string name="addFromPdfFile">Selecionar arquivo PDF</string>
<string name="settings_theme_color">Cor do tema</string>
<string name="settings_catima_theme">Catima</string>
<string name="selectColor">Selecionar cor</string>
<string name="settings_violet_theme">Violeta</string>
<string name="sort_by_name">Nome</string>
<string name="sort_by_expiry">Expiração</string>
<string name="credits">Créditos</string>
<string name="license">Licença</string>
<string name="source_repository">Repositório de Origem</string>
<string name="on_github">no GitHub</string>
<string name="translate_platform">no Weblate</string>
<string name="help_translate_this_app">Ajude a traduzir este aplicativo</string>
<string name="shortcutSelectCard">Selecione um cartão</string>
<string name="include_if_asking_support">Se você gostaria de solicitar suporte, inclua as seguintes informações:</string>
<plurals name="groupCardCountWithArchived">
<item quantity="one"><xliff:g>%1$d</xliff:g> cartão (<xliff:g id="archivedCount">%2$d</xliff:g> arquivado)</item>
<item quantity="many"><xliff:g>%1$d</xliff:g> cartões (<xliff:g id="archivedCount">%2$d</xliff:g> arquivados)</item>
<item quantity="other"><xliff:g>%1$d</xliff:g> cartões (<xliff:g id="archivedCount">%2$d</xliff:g> arquivados)</item>
</plurals>
<string name="archive">Arquivar</string>
<string name="unarchive">Desarquivar</string>
<string name="previousCard">Anterior</string>
<string name="nextCard">Próximo</string>
<string name="updateBalanceTitle">Quanto você gastou ou recebeu?</string>
<string name="currentBalanceSentence">Saldo atual: <xliff:g>%s</xliff:g></string>
<string name="newBalanceSentence">Novo saldo: <xliff:g>%s</xliff:g></string>
<string name="settings_category_title_cards">Cartões</string>
<string name="updateBalanceHint">Inserir quantidade</string>
<string name="anyDate">Qualquer data</string>
<string name="settings_category_title_general">Geral</string>
<string name="settings_category_title_privacy">Privacidade</string>
<string name="action_display_options">Configurações de exibição</string>
<string name="show_archived_cards">Mostrar cartões arquivados</string>
<string name="add_manually_warning_title">A digitalização é recomendada</string>
<string name="continue_">Continuar</string>
<string name="errorReadingFile">Não foi possível fazer a leitura do arquivo</string>
<string name="failedLaunchingFileManager">Não foi possível encontrar um gerenciador de arquivos compatível</string>
<string name="pageWithNumber">Página <xliff:g>%d</xliff:g></string>
<string name="multipleBarcodesFoundPleaseChooseOne">Qual dos códigos de barras encontrados você quer usar?</string>
<string name="settings_display_barcode_max_brightness">Clarear visão do código de barras</string>
<string name="settings_display_barcode_max_brightness_summary">Necessário para alguns scanners funcionarem</string>
<string name="balanceSentence">Saldo: <xliff:g>%s</xliff:g></string>
<string name="balance">Saldo</string>
<string name="settings_follow_sensor_orientation">Sempre girar (ignora as configurações do sistema)</string>
<string name="settings_theme">Tema</string>
<string name="settings_light_theme">Claro</string>
<string name="settings_system_theme">Sistema</string>
<string name="settings_dark_theme">Escuro</string>
<string name="moveBarcodeToTopOfScreen">Mover o código de barras para o topo da tela</string>
<string name="settings_card_orientation">Orientação do código de barras</string>
<string name="settings_portrait_orientation">Retrato</string>
<string name="settings_landscape_orientation">Paisagem</string>
<string name="settings_keep_screen_on_summary">Desativa o tempo limite de tela enquanto estiver vendo um cartão</string>
<string name="importSuccessful">Dados importados</string>
<string name="settings_disable_lockscreen_while_viewing_card_summary">Desativa bloqueio de tela enquanto estiver vendo um cartão</string>
<string name="intent_import_card_from_url_share_text">Eu quero compartilhar um cartão com você</string>
<string name="settings_keep_screen_on">Manter tela ligada</string>
<string name="settings_disable_lockscreen_while_viewing_card">Previnir bloqueio de tela</string>
<string name="settings_allow_content_provider_read_title">Permitir que outros aplicativos acessem meus dados</string>
<string name="settings_allow_content_provider_read_summary">Aplicativos ainda precisarão pedir permissão para ter acesso concedido</string>
<string name="group_edit">Editar grupo</string>
<string name="exportSuccessful">Dados exportados</string>
<string name="noGroups">Clique no botão \"+\" para adicionar grupos a serem categorizados.</string>
<string name="group_name_already_in_use">Nome do grupo já em uso</string>
<string name="deleteConfirmationGroup">Excluir grupo?</string>
<string name="failedOpeningFileManager">Instale um gerenciador de arquivos primeiro.</string>
<string name="enter_group_name">Inserir nome do grupo</string>
<string name="groups">Grupos</string>
<string name="noGroupCards">Este grupo está vazio</string>
<string name="group_name_is_empty">O nome do grupo não pode estar vazio</string>
<string name="group_updated">Grupo atualizado</string>
<string name="all">Todos</string>
<string name="addManually">Insira o código de barras manualmente</string>
<string name="chooseExpiryDate">Escolher data de expiração</string>
<string name="moveUp">Mover para cima</string>
<string name="never">Nunca</string>
<string name="moveDown">Mover para baixo</string>
<string name="leaveWithoutSaveTitle">Sair</string>
<string name="leaveWithoutSaveConfirmation">Sair sem salvar?</string>
<string name="groupsList">Grupos: <xliff:g>%s</xliff:g></string>
<string name="editGroup">Editando grupo: <xliff:g>%s</xliff:g></string>
<string name="editBarcode">Editar código de barras</string>
<string name="expiryDate">Data de expiração</string>
<string name="noBarcodeFound">Nenhum código de barras foi encontrado</string>
<string name="addFromImage">Selecionar uma imagem da galeria</string>
<string name="expiryStateSentence">Expira: <xliff:g>%s</xliff:g></string>
<string name="expiryStateSentenceExpired">Expirado: <xliff:g>%s</xliff:g></string>
<string name="card">Cartão</string>
<string name="errorReadingImage">Não foi possível ler a imagem</string>
<string name="points">Pontos</string>
<string name="privacy_policy">Política de Privacidade</string>
<string name="currency">Moeda</string>
<string name="chooseImportType">Importar dados de</string>
<string name="privacy_policy_popup_text">Declaração de Política de Privacidade
\n
\nNENHUM DADO É COLETADO, o que pode ser confimado por qualquer pessoa já que o nosso aplicativo é software livre.</string>
<string name="importCatima">Importar do Catima</string>
<string name="balanceParsingFailed">Saldo inválido</string>
<string name="accept">Aceitar</string>
<string name="importFidme">Importar de FidMe</string>
<string name="importFidmeMessage">Selecione o arquivo <i>fidme-export-request-xxxxxx.zip</i>, exportado de FidMe, para importação e em seguida selecione o tipo de código de barras manualmente.
\nCrie-o pelo seu perfil no FidMe escolhendo \'Proteção de Dados\' (Data Protection) e então clicando em \"Extrair meus dados\".</string>
<string name="importStocardMessage">Selecionar arquivo <i>***.zip</i>, exportado de Stocard, para importação.
\nObtenha-o enviando um e-mail para support@stocardapp.com solicitando exportação dos seus dados.</string>
<string name="importVoucherVaultMessage">Selecionar arquivo<i>vouchervault.json</i>, exportado de Voucher Vault, para importação.
\nPrimeiro, crie-o pressionando em Exportar no Voucher Vault.</string>
<string name="enter_card_id">Insira o ID ou texto escrito no seu cartão</string>
<string name="manually_enter_barcode_instructions">Insira o ID ou texto escrito no seu cartão e clique no código de barras que se parece com o do seu cartão.</string>
<string name="app_license">Software livre com copyleft, licenciado sob a licença GPLv3+</string>
<string name="validFromDate">Válido a partir de</string>
<string name="chooseValidFromDate">Escolha uma data válida a partir de</string>
<string name="validFromSentence">Válido a partir de: <xliff:g>%s</xliff:g></string>
<string name="view_online">Ver online</string>
</resources>

View File

@@ -123,7 +123,7 @@
<string name="groupsList">Grupos: <xliff:g>%s</xliff:g></string>
<string name="balanceSentence">Saldo: <xliff:g>%s</xliff:g></string>
<string name="editBarcode">Editar código de barras</string>
<string name="expiryDate">Data de expiração</string>
<string name="expiryDate">Data de validade</string>
<string name="never">Nunca</string>
<string name="chooseExpiryDate">Escolher validade</string>
<string name="moveBarcodeToTopOfScreen">Mover o código de barras para o topo do ecrã</string>
@@ -152,7 +152,7 @@
<string name="unsupportedBarcodeType">Este tipo de código de barras ainda não pode ser mostrado. Pode vir a ser suportado numa versão posterior da aplicação.</string>
<string name="setFrontImage">Definir imagem frontal</string>
<string name="setBackImage">Definir imagem de trás</string>
<string name="failedGeneratingShareURL">Não foi possível gerar uma URL partilhável. Por favor reporte isto aos programadores.</string>
<string name="failedGeneratingShareURL">Não foi possível gerar um URL partilhável. Por favor reporte isto aos programadores.</string>
<string name="turn_flashlight_on">Ligar lanterna</string>
<string name="turn_flashlight_off">Desligar lanterna</string>
<string name="settings_locale">Idioma</string>
@@ -167,7 +167,7 @@
<string name="sort">Ordenar</string>
<string name="sort_by_name">Nome</string>
<string name="sort_by_most_recently_used">Mais usados recentemente</string>
<string name="sort_by_expiry">Expiração</string>
<string name="sort_by_expiry">Validade</string>
<string name="reverse">…na ordem inversa</string>
<string name="sort_by">Ordenar por</string>
<string name="version_history">Histórico de versões</string>
@@ -203,7 +203,7 @@
<string name="shortcutSelectCard">Selecione um cartão</string>
<string name="translate_platform">no Weblate</string>
<string name="starred">Estrela</string>
<string name="showMoreInfo">Mostrar info</string>
<string name="showMoreInfo">Mostrar informação</string>
<string name="options">Opções</string>
<plurals name="balancePoints">
<item quantity="one"><xliff:g>%s</xliff:g> ponto</item>
@@ -230,7 +230,7 @@
<string name="failedLaunchingPhotoPicker">Não foi encontrada nenhuma aplicação de galeria de imagens</string>
<string name="nextCard">Próximo</string>
<string name="previousCard">Anterior</string>
<string name="failedToOpenUrl">Instale primeiro um navegador da Internet</string>
<string name="failedToOpenUrl">Instale primeiro um navegador de Internet</string>
<plurals name="viewArchivedCardsWithCount">
<item quantity="one">Ver arquivo (<xliff:g>%1$d</xliff:g> cartão)</item>
<item quantity="many">Ver arquivo (<xliff:g>%1$d</xliff:g> cartões)</item>
@@ -238,7 +238,7 @@
</plurals>
<string name="welcome">Bem-vindo ao Catima</string>
<string name="failedToRetrieveImageFile">Falha ao recuperar o ficheiro de imagem</string>
<string name="barcodeLongPressMessage">Apenas imagens podem ser abertas na aplicação de galeria</string>
<string name="barcodeLongPressMessage"> podem ser abertas imagens na aplicação da galeria</string>
<string name="noCameraPermissionDirectToSystemSetting">Para digitalizar código de barras, o Catima tem de aceder à câmara. Clique aqui para mudar as configurações de permissão.</string>
<string name="cameraPermissionDeniedTitle">Não foi possível aceder à câmara</string>
<string name="importCards">Importar cartões</string>
@@ -272,34 +272,35 @@
<string name="settings_keep_screen_on_summary">Desativa o tempo limite da tela ao visualizar um cartão</string>
<string name="settings_allow_content_provider_read_title">Permitir que outros aplicativos acessem meus dados</string>
<string name="settings_allow_content_provider_read_summary">Os aplicativos ainda terão que solicitar permissão para receber acesso</string>
<string name="settings_oled_dark_summary">Reduz o uso da bateria em telas OLED</string>
<string name="settings_oled_dark_summary">Reduz a utilização da bateria em ecrãs OLED</string>
<string name="icon_header_click_text">Pressione e segure para editar o icone</string>
<string name="settings_category_title_cards">cartões</string>
<string name="settings_category_title_general">geral</string>
<string name="settings_category_title_cards">Cartões</string>
<string name="settings_category_title_general">Geral</string>
<string name="settings_category_title_privacy">Privacidade</string>
<string name="card_id_must_not_be_empty">O ID do cartão não pode estar vazio</string>
<string name="balanceParsingFailed">Saldo inválido</string>
<string name="add_a_card_in_a_different_way">Adicione um cartão de uma forma diferente</string>
<string name="view_online">Exibir online</string>
<string name="view_online">Ver online</string>
<string name="manually_enter_barcode_instructions">Digite o número ID ou o texto em seu cartão e pressione o código de barras que se parece com o que está em seu cartão.</string>
<string name="action_more_options">Mais opções</string>
<string name="enter_card_id">Digite o número ID ou o texto em seu cartão</string>
<string name="action_display_options">Opções de exibição</string>
<string name="action_display_options">Opções de visualização</string>
<string name="addWithoutBarcode">Adicione um cartão sem código de barras</string>
<string name="app_copyright_short">Copyright © Sylvia van Os e colaboradores</string>
<string name="field_must_not_be_empty">O campo não pode estar vazio</string>
<string name="show_archived_cards">Exibir cartões arquivados</string>
<string name="show_archived_cards">Mostrar cartões arquivados</string>
<string name="app_name">Catima</string>
<string name="continue_">Continuar</string>
<string name="add_manually_warning_title">Recomenda-se a digitalização</string>
<string name="add_manually_warning_message">Em algumas lojas, o valor do código de barras é diferente do número escrito no cartão. Por este motivo, a introdução manual de um código de barras pode nem sempre funcionar. Recomenda-se vivamente que, em vez disso, digitalize o código de barras com a sua câmara. Ainda quer continuar?</string>
<string name="spend">Gastar</string>
<string name="receive">Receber</string>
<string name="amountParsingFailed">Montante inválida</string>
<string name="amountParsingFailed">Montante inválido</string>
<string name="settings_follow_sensor_orientation">Rodar sempre (ignora as definições do sistema)</string>
<string name="addFromPdfFile">Selecionar um ficheiro PDF</string>
<string name="errorReadingFile">Não foi possível ler o ficheiro</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Qual dos códigos de barras encontrados pretende utilizar?</string>
<string name="pageWithNumber">Página <xliff:g>%d</xliff:g></string>
<string name="failedLaunchingFileManager">Não foi possível encontrar um gestor de ficheiros suportado</string>
<string name="noCameraFoundGuideText">O seu dispositivo não parece ter uma câmara. Se tiver, tente reiniciar o dispositivo. Caso contrário, utilize o botão \"Mais opções\" abaixo para adicionar um código de barras de outra maneira.</string>
</resources>

View File

@@ -24,10 +24,10 @@
<string name="card">Cardul</string>
<string name="settings_theme">Tema</string>
<string name="all">Toate</string>
<string name="noCardsMessage">Adăugați mai întâi o carte</string>
<string name="noCardsMessage">Adăugați mai întâi un card</string>
<string name="noCardExistsError">Acel card nu a putut fi găsit</string>
<string name="failedParsingImportUriError">Nu s-a putut analiza URI-ul de import</string>
<string name="importExport">Importație/Export</string>
<string name="importExport">Importă/Exportă</string>
<string name="exportName">Exportați</string>
<string name="importSuccessfulTitle">Importat</string>
<string name="importFailedTitle">Importul a eșuat</string>

View File

@@ -309,4 +309,5 @@
<string name="pageWithNumber">Страница <xliff:g>%d</xliff:g></string>
<string name="failedLaunchingFileManager">Не найден поддерживаемый файловый менеджер</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Какой из найденных штрих-кодов вы хотите использовать?</string>
<string name="noCameraFoundGuideText">Похоже, ваше устройство не оснащено камерой. Если это не так, попробуйте перезагрузить устройство. В противном случае воспользуйтесь кнопкой \"Ещё\", чтобы добавить штри-хкод другим способом.</string>
</resources>

View File

@@ -297,4 +297,9 @@
<string name="amountParsingFailed">Neplatná hodnota</string>
<string name="add_manually_warning_title">Skenovanie je odporúčané</string>
<string name="add_manually_warning_message">V niektorých obchodoch nie je číslo na cenovke totožné s čiarovým kódom, preto je lepšie zoskenovať čiarový kód. Chcete napriek tomu pokračovať?</string>
<string name="addFromPdfFile">Vyberte súbor PDF</string>
<string name="errorReadingFile">Súbor sa nepodarilo prečítať</string>
<string name="failedLaunchingFileManager">Nepodarilo sa nájsť podporovaného správcu súborov</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Ktorý z nájdených čiarových kódov chcete použiť?</string>
<string name="pageWithNumber">Stránka <xliff:g>%d</xliff:g></string>
</resources>

View File

@@ -295,4 +295,5 @@
<string name="addFromPdfFile">PDF dosyası seç</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Bulunan barkodlardan hangisini kullanmak istiyorsunuz?</string>
<string name="pageWithNumber">Sayfa <xliff:g>%d</xliff:g></string>
<string name="noCameraFoundGuideText">Aygıtınızda kamera yok gibi görünüyor. Eğer varsa, aygıtı yeniden başlatmayı deneyin. Aksi takdirde, barkodu başka bir şekilde eklemek için aşağıdaki daha fazla seçenek düğmesini kullanın.</string>
</resources>

View File

@@ -309,4 +309,5 @@
<string name="spend">Витратити</string>
<string name="receive">Отримайте</string>
<string name="amountParsingFailed">Неправильна сума</string>
<string name="noCameraFoundGuideText">Ваш пристрій може не мати камери. перезавантажте пристрій, якщо це не так. В іншому випадку додайте штрих-код за допомогою кнопки \"Більше опцій\".</string>
</resources>

View File

@@ -288,4 +288,5 @@
<string name="pageWithNumber">Page <xliff:g>%d</xliff:g></string>
<string name="multipleBarcodesFoundPleaseChooseOne">Bạn muốn sử dụng mã vạch nào được tìm thấy?</string>
<string name="failedLaunchingFileManager">Không thể tìm thấy trình quản lý tệp được hỗ trợ</string>
<string name="noCameraFoundGuideText">Có vẻ như thiết bị của bạn không có camera. Nếu có, hãy thử khởi động lại thiết bị. Nếu không, hãy sử dụng nút Tùy chọn khác bên dưới để thêm mã vạch theo cách khác.</string>
</resources>

View File

@@ -288,4 +288,5 @@
<string name="pageWithNumber"><xliff:g>%d</xliff:g></string>
<string name="addFromPdfFile">选择 PDF 文件</string>
<string name="multipleBarcodesFoundPleaseChooseOne">找到的多个条形码中,你希望使用哪个?</string>
<string name="noCameraFoundGuideText">你的设备似乎没有相机。如果的确如此,请尝试重启设备。否则,使用下方的“更多”按钮以另一种方式添加条形码。</string>
</resources>

View File

@@ -234,7 +234,7 @@
<string name="cameraPermissionRequired">這個行動需要使用鏡頭的權限…</string>
<string name="cameraPermissionDeniedTitle">不能使用鏡頭</string>
<string name="updateBalance">更新餘額</string>
<string name="updateBalanceTitle">了多少?</string>
<string name="updateBalanceTitle">花費或收到了多少</string>
<string name="updateBalanceHint">輸入金額</string>
<string name="currentBalanceSentence">餘額:<xliff:g>%s</xliff:g></string>
<string name="newBalanceSentence">新的餘額:<xliff:g>%s</xliff:g></string>
@@ -282,4 +282,10 @@
<string name="errorReadingFile">無法讀取此檔案</string>
<string name="receive">接收</string>
<string name="amountParsingFailed">無效的數值</string>
<string name="continue_">繼續</string>
<string name="multipleBarcodesFoundPleaseChooseOne">你想要使用哪個找到的條碼?</string>
<string name="pageWithNumber"><xliff:g>%d</xliff:g></string>
<string name="add_manually_warning_message">對於某些商店,條碼值與卡片上寫的數字並不相同。因此,手動輸入條碼可能並不總是有效。強烈建議使用相機掃描條碼。你還想繼續嗎?</string>
<string name="spend">花費</string>
<string name="noCameraFoundGuideText">您的裝置似乎沒有相機鏡頭。如果實際上有相機鏡頭,請嘗試重新啟動此裝置,否則請點選下方的「更多」按鈕,以其它方式新增條碼。</string>
</resources>

View File

@@ -83,6 +83,7 @@
<item>es-rAR</item>
<!-- <item>fa</item> -->
<item>fi</item>
<!-- <item>fil</item> -->
<item>fr</item>
<item>he-rIL</item>
<item>hi</item>
@@ -103,6 +104,7 @@
<item>nl</item>
<item>oc</item>
<item>pl</item>
<item>pt-rBR</item>
<item>pt-rPT</item>
<item>ro-rRO</item>
<item>ru</item>

View File

@@ -346,7 +346,5 @@
<string name="failedLaunchingFileManager">Could not find a supported file manager</string>
<string name="multipleBarcodesFoundPleaseChooseOne">Which of the found barcodes do you want to use?</string>
<string name="pageWithNumber">Page <xliff:g>%d</xliff:g></string>
<string name="exportStartedCheckNotifications">Export started, check your notifications for the result</string>
<string name="importStartedCheckNotifications">Import started, check your notifications for the result</string>
<string name="postNotificationsPermissionRequired">Permission to show notifications needed for this action…</string>
<string name="noCameraFoundGuideText">Your device does not seem to have a camera. If it does, try rebooting the device. Otherwise, use the "More options" button below to add a barcode another way.</string>
</resources>

View File

@@ -30,6 +30,7 @@
<locale android:name="nl" />
<locale android:name="oc" />
<locale android:name="pl" />
<locale android:name="pt-BR" />
<locale android:name="pt-PT" />
<locale android:name="ro-RO" />
<locale android:name="ru" />

View File

@@ -574,6 +574,72 @@ public class ImportExportTest {
}
}
class TestTaskCompleteListener implements ImportExportTask.TaskCompleteListener {
ImportExportResult result;
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat) {
this.result = result;
}
}
@Test
@LooperMode(LooperMode.Mode.PAUSED)
public void useImportExportTask() throws FileNotFoundException {
final int NUM_CARDS = 10;
final File sdcardDir = Environment.getExternalStorageDirectory();
final File exportFile = new File(sdcardDir, "Catima.csv");
TestHelpers.addLoyaltyCards(mDatabase, NUM_CARDS);
TestTaskCompleteListener listener = new TestTaskCompleteListener();
// Export to the file
final String password = "123456789";
FileOutputStream fileOutputStream = new FileOutputStream(exportFile);
ImportExportTask task = new ImportExportTask(activity, DataFormat.Catima, fileOutputStream, password.toCharArray(), listener);
TaskHandler mTasks = new TaskHandler();
mTasks.executeTask(TaskHandler.TYPE.EXPORT, task);
// Actually run the task to completion
mTasks.flushTaskList(TaskHandler.TYPE.EXPORT, false, false, true);
shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(5000));
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
// Check that the listener was executed
assertNotNull(listener.result);
assertEquals(ImportExportResultType.Success, listener.result.resultType());
TestHelpers.getEmptyDb(activity);
// Import everything back from the default location
listener = new TestTaskCompleteListener();
FileInputStream fileStream = new FileInputStream(exportFile);
task = new ImportExportTask(activity, DataFormat.Catima, fileStream, password.toCharArray(), listener);
mTasks.executeTask(TaskHandler.TYPE.IMPORT, task);
// Actually run the task to completion
// I am CONVINCED there must be a better way than to wait on this Queue with a flush.
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, false, false, true);
shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(5000));
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
// Check that the listener was executed
assertNotNull(listener.result);
assertEquals(ImportExportResultType.Success, listener.result.resultType());
assertEquals(NUM_CARDS, DBHelper.getLoyaltyCardCount(mDatabase));
checkLoyaltyCards();
// Clear the database for the next format under test
TestHelpers.getEmptyDb(activity);
}
@Test
public void importWithoutColorsV1() {
InputStream inputStream = getClass().getResourceAsStream("catima_v1_no_colors.csv");

View File

@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.4.1" apply false
id("com.android.application") version "8.5.0" apply false
id("com.github.spotbugs") version "5.1.4" apply false
}

View File

@@ -0,0 +1,3 @@
- Unterstützung für das Scannen von PDF-Dateien nach Barcodes
- Unterstützung für Bilddateien mit mehreren Barcodes
- Kleinere UI-Korrekturen

View File

@@ -0,0 +1 @@
- Verschiedene Fehlerbehebungen und Verbesserungen bei der Handhabung der Balance

View File

@@ -0,0 +1,4 @@
- Unterstützung für die Erstellung einer Karte beim Teilen von einfachem Text
- Anzeige des Bildtyps anstelle des Barcodes unter Bildern
- Behebung eines möglichen Absturzes beim Versuch, ein Backup aus der Nextcloud-App zu importieren
- Verbesserte Unterstützung für Geräte ohne Kamera

View File

@@ -1,2 +1,4 @@
- Support for creating a card when sharing plain text
- Display image type instead of barcode below images
- Display image type instead of barcode below images
- Fix possible crash when trying to import a backup from the Nextcloud app
- Improved support for devices without camera

View File

@@ -0,0 +1,4 @@
- Cible Android 14
- Ouvre l'icône de la carte dans la galerie au toucher
- Améliore la conception de l'onglet "Photos" en mode édition
- Mis à jour l'écran des dépenses pour prendre également en charge la réception

View File

@@ -0,0 +1,3 @@
- Prise en charge de la numérisation des fichiers PDF pour les codes-barres
- Prise en charge des fichiers d'image avec plusieurs codes-barres
- Corrections mineures de l'interface utilisateur

View File

@@ -0,0 +1 @@
- Divers correctifs et améliorations pour la gestion du solde

View File

@@ -0,0 +1,4 @@
- Prise en charge de la création d'une carte lors du partage de texte brut
- Affiche le type d'image au lieu du code-barre sous les images
- Correction d'un crash possible lors de la tentative d'importation d'une sauvegarde depuis l'application Nextcloud
- Amélioration de la prise en charge des appareils sans caméra

View File

@@ -0,0 +1 @@
- संतुलन प्रबंधन के लिए विभिन्न सुधार और सुधार

View File

@@ -0,0 +1,4 @@
- सादा पाठ साझा करते समय कार्ड बनाने का समर्थन करता है
- छवियों के नीचे बारकोड के बजाय छवि प्रकार प्रदर्शित करता है
- नेक्स्टक्लाउड ऐप से बैकअप आयात करने का प्रयास करते समय संभावित क्रैश को ठीक किया गया
- बिना कैमरे वाले उपकरणों के लिए बेहतर समर्थन

View File

@@ -0,0 +1 @@
- 밸런스 처리에 대한 다양한 수정 및 개선

View File

@@ -0,0 +1,3 @@
- 일반 텍스트 공유 시 카드 생성 지원
- 이미지 아래에 바코드 대신 이미지 유형을 표시합니다.
- Nextcloud 앱에서 백업을 가져오려고 할 때 발생할 수 있는 충돌 수정

View File

@@ -0,0 +1 @@
- Gebruikte bibliotheken bijgewerkt

View File

@@ -0,0 +1 @@
- Verscheidene rechts-naar-links oplossingen

View File

@@ -0,0 +1 @@
- Uitzonderlijke crash opgelost

View File

@@ -0,0 +1 @@
- Vertalingen bijgewerkt en toegevoegd

View File

@@ -0,0 +1 @@
- Vertaling naar het Russisch bijgewerkt

View File

@@ -0,0 +1 @@
- Kleine oplossingen en verbeteringen

View File

@@ -0,0 +1 @@
- Zoeken met spaties is verbeterd

View File

@@ -0,0 +1 @@
- Opnieuw ontworpen volgens Material You

View File

@@ -0,0 +1,4 @@
- Suporte para a criação de um cartão ao compartilhar texto simples
- Exibição do tipo de imagem em vez do código de barras abaixo das imagens
- Correção de possível falha ao tentar importar um backup do aplicativo Nextcloud
- Suporte aprimorado para dispositivos sem câmera

View File

@@ -0,0 +1 @@
- Material You aprimorado

View File

@@ -0,0 +1 @@
Catima

View File

@@ -0,0 +1 @@
- Várias correções e melhorias no manuseamento do saldo

View File

@@ -0,0 +1,4 @@
- Suporte para a criação de um cartão quando se partilha texto simples
- Mostrar tipo de imagem em vez de código de barras abaixo das imagens
- Correção de possível falha ao tentar importar uma cópia de segurança da aplicação Nextcloud
- Suporte melhorado para dispositivos sem câmara

View File

@@ -0,0 +1 @@
- Различные исправления и улучшения в управлении балансом

View File

@@ -0,0 +1,4 @@
- Поддержка создания карты из текста, полученного через функцию "Поделиться"
- Отображение типа изображения вместо штрих-кода под изображениями
- Исправление возможного сбоя при попытке импортировать резервную копию из приложения Nextcloud
- Улучшена поддержка устройств без камеры

View File

@@ -13,7 +13,7 @@ S týmto základným každodenným nosením (EDC) nástroj môžete nahradiť zb
- Zdieľať kupóny, exkluzívne ponuky, promo kódy, alebo karty a kódy pomocou akejkoľvek aplikácie.
- Tmavo téma a možnosti prístupnosti pre videnie postihnutých užívateľov.
- Vyrobený pre každého prostredníctvom renomovanej softvérovej komunity.
- Miestne preklady ručne vyrobené pre 20+ jazykov.
- Miestne preklady ručne vyrobené pre 40+ jazykov.
- Gratis, podporované komunitnými príspevokmi.
- Použitie, štúdium, zmena a zdieľanie ako si prajete; <i> so všetkými</i>.
- Nielen Voľný softvér / Open Source. <i>Copylefted</i> libre softvér (GPLv3+) Správa kariet.

View File

@@ -1 +1,4 @@
- Цільова система: Android 14
- Натискання на значок картки відкриває його в галереї
- Покращено дизайн фото вкладки у режимі редагування
- До екрану витрат додали статистику надходжень

View File

@@ -0,0 +1,3 @@
- Підтримка сканування PDF для пошуку штрих-кодів
- Підтримка зображень з кількома штрих-кодами
- Підправили інтерфейс

View File

@@ -0,0 +1 @@
- Виправлення та покращення опрацювання балансу

View File

@@ -0,0 +1,4 @@
- Підтримка створення карти з переданого тексту
- Відображення типу зображення замість штрих-коду під зображенням
- Запобігли можливим збоям від імпорту даних з Nextcloud
- Покращення підтримки пристроїв без камери

View File

@@ -0,0 +1 @@
- 余额处理的多处修复和改进

View File

@@ -0,0 +1,4 @@
- 支持分享纯文本时创建卡片
- 在图片下方展示图片类型而非条形码
- 修复尝试从 Nextcloud 应用导入备份时应用可能崩溃的问题
- 改进了对无相机设备的支持

View File

@@ -13,7 +13,7 @@
- 可直接分享優惠券、獨家優惠、折價券或卡片條碼至任何應用程式。
- 支援暗色主題以及無障礙選項。
- 由自由開發軟體社群開發。
- 支援 20 種語言的在地化翻譯。
- 支援超過 40 種語言的在地化翻譯。
- 完全免費,但也很樂意接受捐款。
- 如您所願地<i>與所有人</i>使用、鑽研、修改和分享。
- 不但只是自由軟體/開源。本專案為 <i>Copylefted</i> 自由軟體 (GPLv3+)。

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

2
gradlew vendored
View File

@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.