Compare commits

..
Author SHA1 Message Date
Sylvia van Os 7f64449167 Codedump 2023-09-27 22:54:03 +02:00
Sylvia van Os 488c542cd5 Merge remote-tracking branch 'weblate/main' 2023-09-26 20:05:45 +02:00
Sylvia van Os 0e0693bdad Fix changelog to fastlane action 2023-09-26 19:57:12 +02:00
TheScientistPT 86267a2e38 Translated using Weblate (Portuguese)
Currently translated at 98.3% (294 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2023-09-26 19:55:16 +02:00
Sylvia van Os e2171856ff Update CHANGELOG 2023-09-26 19:32:39 +02:00
Sylvia van Os 3c3a37a9e8 Merge pull request #1524 from CatimaLoyalty/betterDefaultCardColours
Better default card colours
2023-09-26 19:30:59 +02:00
Sylvia van Os 573da1e4ff New add card workflow (#1512) 2023-09-26 19:30:35 +02:00
Sylvia van OsandFC Stegerman 1f70446bce Fix typo
Co-authored-by: FC (Fay) Stegerman <flx@obfusk.net>
2023-09-25 22:22:40 +02:00
TheScientistPT ff4ef15dfc Translated using Weblate (Portuguese)
Currently translated at 98.3% (294 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2023-09-25 22:01:46 +02:00
Sylvia van Os 926f3adb18 Remove default card colour which uses wrong foreground colour 2023-09-24 15:44:26 +02:00
Sylvia van Os 4b2d981cc6 Add test to ensure colours have white foreground 2023-09-24 15:44:22 +02:00
Sylvia van Os 93d5c5e03e Link feature graphic to homepage 2023-09-24 15:13:11 +02:00
Sylvia van Os 475f071575 Merge pull request #1522 from CatimaLoyalty/create-pull-request/patch-1695546611
Update feature graphic
2023-09-24 11:18:57 +02:00
TheLastProject f77fa88ced Update feature graphic 2023-09-24 09:10:11 +00:00
Sand Smith 7fe5c18cb8 Translated using Weblate (Chinese (Traditional))
Currently translated at 94.9% (284 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2023-09-24 11:03:13 +02:00
109247019824 7e16798b33 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-09-24 11:03:13 +02:00
Jiri Grönroos 3edfb68bd7 Translated using Weblate (Finnish)
Currently translated at 99.3% (297 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2023-09-24 11:03:13 +02:00
Eric 4f307af6bd Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-09-24 11:03:13 +02:00
Skrripy 08848af908 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (129 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-09-24 11:03:13 +02:00
Skrripy f4e9b85ae3 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-09-24 11:03:12 +02:00
HudobniVolk 73ccb0ce65 Translated using Weblate (Slovenian)
Currently translated at 91.6% (274 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2023-09-24 11:02:27 +02:00
Sylvia van Os 15c5ee7f2c Merge pull request #1521 from CatimaLoyalty/create-pull-request/patch-1695528761
Update contributors
2023-09-24 09:42:31 +02:00
Sand Smith f08be0d13f Translated using Weblate (Chinese (Traditional))
Currently translated at 94.9% (284 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2023-09-24 06:03:21 +00:00
109247019824 aa115e36fd Translated using Weblate (Bulgarian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-09-24 06:03:20 +00:00
Jiri Grönroos cfa45013f4 Translated using Weblate (Finnish)
Currently translated at 99.3% (297 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2023-09-24 06:03:19 +00:00
Eric cca01ae5a3 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-09-24 06:03:18 +00:00
Skrripy 44af31f6d4 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (129 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-09-24 06:03:17 +00:00
Skrripy 8fb076421a Translated using Weblate (Ukrainian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-09-24 06:03:05 +00:00
HudobniVolk 89f8ca1387 Translated using Weblate (Slovenian)
Currently translated at 91.6% (274 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2023-09-24 06:03:04 +00:00
TheLastProject fddb462618 Update contributors 2023-09-24 04:12:40 +00:00
Sylvia van Os 97343515a3 Consistency: may not/cannot -> must not 2023-09-23 18:11:42 +02:00
Sylvia van Os dcbd2aa390 Merge pull request #1514 from CatimaLoyalty/improveValidation
Improve validation
2023-09-22 22:32:21 +02:00
Sylvia van Os 12e7aaa615 Trim spaces in store name 2023-09-22 22:02:15 +02:00
Sylvia van Os 50f93b87f5 Cleanups 2023-09-22 21:18:52 +02:00
Sylvia van Os b4cefbc15e Merge pull request #1517 from CatimaLoyalty/returnToLastViewAfterEdit
Return to last view after edit
2023-09-22 21:04:17 +02:00
Sylvia van Os 4ce17c3742 Merge pull request #1520 from obfusk/rm-unused-setgroupnameerror
ManageGroupsActivity: rm unused setGroupNameError()
2023-09-22 20:55:57 +02:00
FC Stegerman 5035b83ae1 ManageGroupsActivity: rm unused setGroupNameError() 2023-09-22 20:13:32 +02:00
Sylvia van Os dc327a3e24 Merge pull request #1519 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-09-21 19:03:08 +02:00
solokot 4ddceb83d5 Translated using Weblate (Russian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-09-21 15:44:20 +02:00
Heimen Stoffels 31048218af Translated using Weblate (Dutch)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-09-21 15:44:20 +02:00
Slávek Banko 6e3a9ca380 Translated using Weblate (Czech)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-09-21 15:44:20 +02:00
lassr8 09134f4c5f Translated using Weblate (Spanish)
Currently translated at 28.6% (37 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2023-09-21 05:03:56 +02:00
Sylvia van Os 89c9271726 Improve permission string 2023-09-20 18:11:08 +02:00
Sylvia van Os 473f8e6b72 Fix barcode not showing when returning and changing from none to some barcode 2023-09-19 20:45:34 +02:00
Sylvia van Os 8310f09641 Hide keyboard when switching back to view view 2023-09-19 19:40:13 +02:00
Sylvia van Os 31b9123a8f Don't close view activity when entering edit activity 2023-09-19 19:39:33 +02:00
Sylvia van Os cc4aed6773 Update Fastlane 2023-09-18 19:30:20 +02:00
Sylvia van Os a868aac579 Merge pull request #1515 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-09-18 19:24:37 +02:00
Áron Dubovszky da48eec787 Translated using Weblate (Hungarian)
Currently translated at 98.6% (295 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2023-09-18 19:00:19 +02:00
Sylvia van Os 4aa56a55fe Balance validation fixes
Remove old string which may sometimes display "does not seem like a
valid balance." and default to 0 as balance if field is emptied.
2023-09-17 17:59:42 +02:00
Sylvia van Os c3daa1cc86 Remove no longer used strings 2023-09-17 17:37:24 +02:00
Sylvia van Os 00d08d741c Don't regenerate barcode if value is empty 2023-09-17 17:37:24 +02:00
Sylvia van Os 2f33be6b3c Improve validation
If a field is empty when it shouldn't be, show it at the correct UI
element and focus
2023-09-17 17:37:21 +02:00
Sylvia van Os d54a3127a6 Improve create group dialog
Don't show error from the start, disable OK button unless state is okay
2023-09-17 16:39:57 +02:00
Sylvia van Os 40ecf46b40 Merge branch 'main' of github.com:CatimaLoyalty/Android 2023-09-17 12:21:09 +02:00
Sylvia van Os dd9b6a8fed Update fastlane 2023-09-17 12:21:02 +02:00
Sylvia van Os 194e1d5c26 Merge pull request #1513 from CatimaLoyalty/create-pull-request/patch-1694923968
Update contributors
2023-09-17 10:10:28 +02:00
TheLastProject 9360f2a1e0 Update contributors 2023-09-17 04:12:47 +00:00
Sylvia van Os 2030b6b08d Release Catima 2.26.0 2023-09-14 20:10:38 +02:00
Sylvia van Os 0b2ad13df9 Merge pull request #1508 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-09-14 19:52:19 +02:00
Kristoffer Grundström dbc60c39b1 Translated using Weblate (Swedish)
Currently translated at 98.3% (294 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2023-09-14 19:45:37 +02:00
Alexandra Moroz 7db52fe1db Translated using Weblate (Romanian)
Currently translated at 45.8% (137 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ro/
2023-09-14 19:45:37 +02:00
J. Lavoie f8bcfd6bdf Translated using Weblate (Italian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-09-14 19:45:37 +02:00
J. Lavoie 16f79b4e23 Translated using Weblate (French)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-09-14 19:45:37 +02:00
J. Lavoie b1273a1c8a Translated using Weblate (German)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-09-14 19:45:37 +02:00
Sylvia van Os d127d7fce5 Merge pull request #1507 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-09-13 18:05:24 +02:00
sarami 0aaa4120c7 Translated using Weblate (Korean)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ko/
2023-09-13 10:52:44 +02:00
Lionel HANNEQUIN 9a11669e6d Translated using Weblate (French)
Currently translated at 99.6% (298 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-09-13 10:52:44 +02:00
FC Stegerman 3e7859b265 Translated using Weblate (German)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-09-13 10:52:44 +02:00
Sylvia van Os 34a3f79f9c Update compat 2023-09-11 20:21:59 +02:00
Sylvia van Os 8b8737fa23 Update actions 2023-09-11 19:48:39 +02:00
Sylvia van Os cf1a53f1b4 Limit permissions for CI jobs where possible 2023-09-10 20:52:56 +02:00
Sylvia van Os fea4c63840 Allow triggering workflows manually 2023-09-10 12:03:27 +02:00
Sylvia van Os d0881151fe Update contributors-to-file to v3 2023-09-10 11:58:51 +02:00
Sylvia van Os e692d27973 Merge pull request #1499 from obfusk/locale-res
app locale improvements
2023-09-10 11:37:50 +02:00
Sylvia van Os c16a5bc6f6 Merge pull request #1504 from CatimaLoyalty/create-pull-request/patch-1694329960
Update contributors
2023-09-10 09:16:13 +02:00
TheLastProject df765410d8 Update contributors 2023-09-10 07:12:39 +00:00
Sylvia van Os 0b5e10040d Merge pull request #1503 from CatimaLoyalty/create-pull-request/patch-1694245801
Update feature graphic
2023-09-09 11:13:11 +02:00
TheLastProject 9ff6d78345 Update feature graphic 2023-09-09 07:50:00 +00:00
Sylvia van Os 7a35cba4de Merge pull request #1502 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-09-09 09:48:46 +02:00
Mykola Skira cbfe761cb8 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (129 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-09-09 02:54:22 +02:00
Ziad OUALHADJ e0256d07a5 Translated using Weblate (French)
Currently translated at 99.2% (128 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-09-09 02:54:22 +02:00
Mykola Skira 39caf35ae5 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-09-09 02:54:22 +02:00
FC Stegerman 704a420e5e disable ast & lb again 2023-09-07 23:39:39 +02:00
Sylvia van Os f2605ca7f2 Fix Weblate oops 2023-09-07 20:00:24 +02:00
Sylvia van Os c75657c58a Merge pull request #1500 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-09-06 18:47:53 +02:00
Govind S Nair 63ec0cf098 Translated using Weblate (Hindi)
Currently translated at 56.8% (170 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hi/
2023-09-06 16:30:19 +02:00
Sex Garo 589b532e9f Translated using Weblate (Arabic)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-09-06 16:30:18 +02:00
EngageIndo 4c9e057394 Translated using Weblate (Indonesian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2023-09-06 16:30:18 +02:00
Sabrina f7f4156a78 Translated using Weblate (Korean)
Currently translated at 97.6% (292 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ko/
2023-09-06 16:30:17 +02:00
Sylvia van Os f9f235af5c Translated using Weblate (German)
Currently translated at 99.3% (297 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-09-06 16:30:11 +02:00
essys f6c74a7da5 Translated using Weblate (German)
Currently translated at 99.3% (297 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-09-06 16:30:11 +02:00
FC Stegerman 1367e29bd4 disable languages < 29% translated 2023-09-05 02:56:38 +02:00
FC Stegerman f025d72a11 add comment about locales to settings.xml 2023-09-05 02:49:13 +02:00
FC Stegerman 30f2eb1fb9 CI: add update-locales workflow 2023-09-05 02:46:45 +02:00
FC Stegerman e8c2e6ecd0 add all langs & rm empty ones 2023-09-05 02:42:30 +02:00
FC Stegerman 025be0e5e3 add & use .scripts/locales.py for localeConfig 2023-09-05 02:17:20 +02:00
FC Stegerman b9f380a2b8 s/zh-TW/zh-rTW/ 2023-09-05 02:16:55 +02:00
pesta007 b2632a03b7 Translated using Weblate (Arabic)
Currently translated at 91.9% (275 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-09-04 06:57:46 +02:00
Jean-Luc Tibaux ad4275ae45 Translated using Weblate (German)
Currently translated at 98.6% (295 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-09-04 06:57:46 +02:00
Sylvia van Os 2376517858 Merge pull request #1495 from CatimaLoyalty/create-pull-request/patch-1693725203
Update contributors
2023-09-03 10:22:47 +02:00
TheLastProject a666885b22 Update contributors 2023-09-03 07:13:23 +00:00
FC (Fay) Stegerman 62d4b3ab0d feature graphic: only run on title.txt changes & clean png (#1494) 2023-09-03 02:07:35 +02:00
Sylvia van Os e20ac7738b Merge pull request #1492 from CatimaLoyalty/create-pull-request/patch-1693693712
Update feature graphic
2023-09-03 01:30:10 +02:00
TheLastProject cef64004d1 Update feature graphic 2023-09-02 22:28:32 +00:00
Sylvia van Os 35d2408a0e Merge pull request #1491 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-09-03 00:27:08 +02:00
michaelpratana 1055ba1ca0 Translated using Weblate (Indonesian)
Currently translated at 98.6% (295 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2023-09-02 23:57:25 +02:00
solokot 2bbdb873cc Translated using Weblate (Russian)
Currently translated at 100.0% (129 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-09-02 23:57:25 +02:00
Ziad OUALHADJ b22d76ac02 Translated using Weblate (French)
Currently translated at 97.6% (126 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-09-02 23:57:25 +02:00
Daniel Sych 6975688b9f Translated using Weblate (Polish)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-09-02 23:57:25 +02:00
Heimen Stoffels 310800f28a Translated using Weblate (Dutch)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-09-02 23:57:25 +02:00
Ziad OUALHADJ 525fdf064c Translated using Weblate (Italian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-09-02 23:57:25 +02:00
gallegonovato 5f74f1fbb5 Translated using Weblate (Spanish)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2023-09-02 23:57:25 +02:00
Sylvia van Os 5caae534fc Don't run the changelog job unnecessarily 2023-09-01 19:47:58 +02:00
Sylvia van Os 9ebd312c08 Merge pull request #1488 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-09-01 19:46:53 +02:00
Sylvia van Os 9e77b671e0 Merge pull request #1490 from CatimaLoyalty/fix/ci_updates
CI cleanups
2023-09-01 19:42:40 +02:00
Sylvia van Os 7a361c9afe CI cleanups 2023-09-01 19:41:03 +02:00
Sylvia van Os 6ef86ef29b Merge pull request #1489 from CatimaLoyalty/feature/generatedFeatureGraphic
Feature/generated feature graphic
2023-09-01 19:26:22 +02:00
Sylvia van Os b9bf8e166a Programmatically generate feature graphic
Also use Noto as font for languages not supported by Lexend Deca and
move the text slightly futher down for better looks in CJK languages
2023-09-01 19:25:51 +02:00
Eric 3d55c2c82c Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (129 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-09-01 13:40:44 +02:00
Eric ef56aea88d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-09-01 13:40:39 +02:00
J. Lavoie 40a3fa7b5b Translated using Weblate (French)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-09-01 13:40:38 +02:00
Younes Bouhouche 184d2aeebd Translated using Weblate (Arabic)
Currently translated at 91.3% (273 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-08-31 20:11:37 +02:00
Oğuz Ersen 8f6603dc79 Translated using Weblate (Turkish)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2023-08-31 20:11:37 +02:00
109247019824 68b53467d0 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-08-31 20:11:37 +02:00
Slávek Banko 9c401c7e85 Translated using Weblate (Czech)
Currently translated at 100.0% (129 of 129 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-08-31 20:11:37 +02:00
solokot 3b0440b9fa Translated using Weblate (Russian)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-08-31 20:11:37 +02:00
Heimen Stoffels cd148d2bb0 Translated using Weblate (Dutch)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-08-31 20:11:37 +02:00
Allan Nordhøy 487cffac30 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.3% (297 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2023-08-31 20:11:37 +02:00
Slávek Banko 0ab557e29c Translated using Weblate (Czech)
Currently translated at 100.0% (299 of 299 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-08-31 20:11:37 +02:00
Ziad OUALHADJ 05125f86cd New feature graphic 2023-08-31 19:52:19 +02:00
Sylvia van Os b35ccd7d58 Merge pull request #1487 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-08-31 19:34:53 +02:00
Younes Bouhouche eab6538f1c Translated using Weblate (Arabic)
Currently translated at 92.6% (276 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-08-31 09:53:07 +02:00
Sylvia van Os 53753690aa Merge pull request #1486 from CatimaLoyalty/create-pull-request/patch-1693340314
Update Fastlane changelogs
2023-08-29 22:21:01 +02:00
TheLastProject c42a02e532 Update Fastlane changelogs 2023-08-29 20:18:34 +00:00
Sylvia van Os 2d75ebe395 Update CHANGELOG 2023-08-29 22:18:14 +02:00
FC (Fay) Stegerman 8ba860f6c3 embed history/privacy policy/license in app (#1346) 2023-08-29 21:57:49 +02:00
Sylvia van Os 68a638e93e Merge pull request #1485 from CatimaLoyalty/create-pull-request/patch-1693328819
Update Fastlane changelogs
2023-08-29 19:08:04 +02:00
TheLastProject 306e413d94 Update Fastlane changelogs 2023-08-29 17:06:59 +00:00
Sylvia van Os c57aefa5a3 Update CHANGELOG 2023-08-29 19:06:43 +02:00
Quang Trung 5668fb1152 Android 13 per app language support (#1447) 2023-08-29 19:06:07 +02:00
Sylvia van Os d62de3d641 Merge pull request #1484 from obfusk/copyright
About: explicitly mention contributors' copyright
2023-08-28 20:20:44 +02:00
FC Stegerman 727eb13a6f remove app_copyright_fmt when identical to untranslated original 2023-08-28 20:12:36 +02:00
FC Stegerman 4ebbe758e3 About: explicitly mention contributors' copyright 2023-08-28 19:28:39 +02:00
Sylvia van Os c6071263e0 Merge pull request #1483 from CatimaLoyalty/create-pull-request/patch-1693170785
Update Fastlane changelogs
2023-08-27 23:13:24 +02:00
TheLastProject ecb861c9a1 Update Fastlane changelogs 2023-08-27 21:13:05 +00:00
Sylvia van Os 4cf16d92d4 Merge pull request #1482 from obfusk/patch-6
fix typo in CHANGELOG.md
2023-08-27 23:12:47 +02:00
FC (Fay) Stegerman 8fde18c46a fix typo in CHANGELOG.md 2023-08-27 20:58:23 +00:00
Sylvia van Os f63eca0747 Merge pull request #1481 from CatimaLoyalty/create-pull-request/patch-1693169829
Update Fastlane changelogs
2023-08-27 22:57:20 +02:00
TheLastProject 5053d63a33 Update Fastlane changelogs 2023-08-27 20:57:09 +00:00
Sylvia van Os 4d08613b3c Update CHANGELOG 2023-08-27 22:56:52 +02:00
Sylvia van Os 715df432a9 Move archive mode into a display option (#1477) 2023-08-27 22:55:45 +02:00
Sylvia van Os 92802fd467 Merge pull request #1480 from CatimaLoyalty/create-pull-request/patch-1693120402
Update contributors
2023-08-27 22:27:52 +02:00
TheLastProject f0a6593c1a Update contributors 2023-08-27 07:13:21 +00:00
Sylvia van Os 86c4e46293 Merge pull request #1474 from CatimaLoyalty/dependabot/gradle/com.github.spotbugs-5.1.3
Bump com.github.spotbugs from 5.1.2 to 5.1.3
2023-08-25 20:09:08 +02:00
Sylvia van Os 2d4fa0fd85 Release Catima 2.25.3 2023-08-25 18:23:57 +02:00
Sylvia van Os 42863418a4 Merge pull request #1475 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-08-23 17:53:21 +02:00
Aya Ichrak ac4ccf2635 Translated using Weblate (Arabic)
Currently translated at 92.9% (277 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-08-23 16:53:52 +02:00
Sylvia van Os 89762864ff Translated using Weblate (Arabic)
Currently translated at 92.6% (276 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-08-23 11:52:22 +02:00
ChaoticNeutralCzech 22b8f4b387 Translated using Weblate (Czech)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-08-23 11:52:22 +02:00
Osama ALSHBIBI aebb0e84dc Translated using Weblate (Arabic)
Currently translated at 92.6% (276 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-08-23 11:52:21 +02:00
IllusiveMan196 b75862532c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (128 of 128 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-08-23 11:52:21 +02:00
Sylvia van Os f30fa04d56 Add chat badge 2023-08-22 20:02:29 +02:00
Sylvia van Os 053b51f086 Merge pull request #1476 from CatimaLoyalty/create-pull-request/patch-1692514045
Update contributors
2023-08-20 08:50:28 +02:00
TheLastProject f8960d9a1e Update contributors 2023-08-20 06:47:25 +00:00
dependabot[bot] eb84900fab Bump com.github.spotbugs from 5.1.2 to 5.1.3
Bumps com.github.spotbugs from 5.1.2 to 5.1.3.

---
updated-dependencies:
- dependency-name: com.github.spotbugs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-16 02:54:47 +00:00
Sylvia van Os 8949166ed1 Merge pull request #1473 from CatimaLoyalty/create-pull-request/patch-1691910455
Update contributors
2023-08-13 11:19:16 +02:00
TheLastProject 23c437580a Update contributors 2023-08-13 07:07:35 +00:00
Sylvia van Os 3e46e84b5d Merge pull request #1472 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-08-11 08:22:05 +02:00
solokot 3146e25a46 Translated using Weblate (Russian)
Currently translated at 100.0% (128 of 128 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-08-11 07:51:46 +02:00
Sylvia van Os dc7b1b032b Merge pull request #1471 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-08-10 09:07:11 +02:00
Eric 18716fb333 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (128 of 128 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-08-10 00:52:13 +02:00
Slávek Banko 5879b8716b Translated using Weblate (Czech)
Currently translated at 100.0% (128 of 128 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-08-10 00:52:13 +02:00
Sylvia van Os 970e4b4a31 Merge pull request #1470 from CatimaLoyalty/dependabot/gradle/com.github.spotbugs-5.1.2
Bump com.github.spotbugs from 5.1.1 to 5.1.2
2023-08-09 08:12:10 +02:00
dependabot[bot] b25e07d37a Bump com.github.spotbugs from 5.1.1 to 5.1.2
Bumps com.github.spotbugs from 5.1.1 to 5.1.2.

---
updated-dependencies:
- dependency-name: com.github.spotbugs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-09 02:17:50 +00:00
Sylvia van Os c1041a09f5 Merge pull request #1469 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-08-08 18:07:33 +02:00
Clxff H3r4ld0 a4a70f44e0 Translated using Weblate (Indonesian)
Currently translated at 95.3% (122 of 128 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-08-08 17:52:18 +02:00
しいたけ 2e52e7b231 Translated using Weblate (Japanese)
Currently translated at 78.1% (233 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2023-08-08 17:52:18 +02:00
skauVictor a7b1864c6b Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2023-08-08 17:52:18 +02:00
Sylvia van Os ee3af751fe Merge pull request #1468 from CatimaLoyalty/create-pull-request/patch-1691305961
Update contributors
2023-08-06 09:35:54 +02:00
TheLastProject 34698c7bdd Update contributors 2023-08-06 07:12:41 +00:00
Sylvia van Os a45875ef25 Merge pull request #1465 from CatimaLoyalty/create-pull-request/patch-1691229717
Update Fastlane changelogs
2023-08-05 12:02:09 +02:00
TheLastProject c4df103c02 Update Fastlane changelogs 2023-08-05 10:01:57 +00:00
Sylvia van Os 44211accc9 Update CHANGELOG 2023-08-05 12:01:41 +02:00
Sylvia van Os 7be1ee99ca Merge pull request #1463 from obfusk/fix-colorpicker
LoyaltyCardEditActivity: fix color picker dialog crash & bug
2023-08-05 12:00:49 +02:00
FC Stegerman b83dbb3a87 StocardImporter: refactor (#1443)
* StocardImporter: refactor

* StocardImporter: trim CSV fields

* LoyaltyCard: add .toString()

* StocardRecord: add .toString()

* StocardImporter: handle usages better

* StocardImporter: use label

* ImportExportTest: add importStocard2 + stocard2.zip

* StocardImporter: iterate over card map in key order

* StocardImporter: cleanup, handle label better, use providers file

* make spotbugs happy

* StocardImporter: can't use providersFileName, list known files, log unknown

* StocardImporter: fix regex, log properly, s/Provider/Store/

* StocardImporter: test /usages/ timestamp, nicer if/else flow

* StocardImporter: fix label usage

* StocardImporter: remove label prefix, improve error
2023-08-05 11:52:59 +02:00
FC Stegerman 7e3a5a9831 LoyaltyCardEditActivity: fix wrong balance parse after locale changes (#1454) 2023-08-05 11:29:59 +02:00
Sylvia van Os 1b2f939c5a Merge pull request #1462 from CatimaLoyalty/dependabot/gradle/com.github.spotbugs-5.1.1
Bump com.github.spotbugs from 5.1.0 to 5.1.1
2023-08-04 23:50:07 +02:00
FC Stegerman 29919851f5 LoyaltyCardEditActivity: fix color picker dialog crash & bug 2023-08-04 04:15:45 +02:00
dependabot[bot] b255cd63de Bump com.github.spotbugs from 5.1.0 to 5.1.1
Bumps com.github.spotbugs from 5.1.0 to 5.1.1.

---
updated-dependencies:
- dependency-name: com.github.spotbugs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-04 02:13:47 +00:00
Sylvia van Os 5d022ee1d1 Merge pull request #1460 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-08-02 18:23:57 +02:00
Montazer Al-Taiee ecd8fe6d43 Translated using Weblate (Arabic)
Currently translated at 92.6% (276 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-08-02 15:07:57 +02:00
Eric 340046905d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (128 of 128 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-08-02 15:07:57 +02:00
Slávek Banko aba6dc9070 Translated using Weblate (Czech)
Currently translated at 100.0% (128 of 128 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-08-02 15:07:57 +02:00
Sylvia van Os 7e75f86aba Merge pull request #1459 from CatimaLoyalty/dependabot/gradle/com.github.spotbugs-5.1.0
Bump com.github.spotbugs from 5.0.14 to 5.1.0
2023-08-01 08:23:55 +02:00
Sylvia van Os 8c021141b0 Merge pull request #1458 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-08-01 08:23:19 +02:00
dependabot[bot] 1739ac827a Bump com.github.spotbugs from 5.0.14 to 5.1.0
Bumps com.github.spotbugs from 5.0.14 to 5.1.0.

---
updated-dependencies:
- dependency-name: com.github.spotbugs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-01 02:59:27 +00:00
Reza Almanda 2c8bbd3f44 Translated using Weblate (Indonesian)
Currently translated at 95.2% (121 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-08-01 03:16:37 +02:00
Slávek Banko 2afad63f31 Translated using Weblate (Czech)
Currently translated at 100.0% (127 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-08-01 03:16:37 +02:00
Sylvia van Os e4d2196892 Merge pull request #1457 from CatimaLoyalty/create-pull-request/patch-1690827013
Update Fastlane changelogs
2023-07-31 20:10:25 +02:00
TheLastProject b26aced825 Update Fastlane changelogs 2023-07-31 18:10:12 +00:00
Sylvia van Os a9625fc1cf Update CHANGELOG 2023-07-31 20:09:54 +02:00
Sylvia van Os d86fb9475f Merge pull request #1452 from obfusk/fix-date-rotate
LoyaltyCardEditActivity: fix state loss on rotation for dates
2023-07-31 20:08:40 +02:00
Sylvia van Os b6ea845236 Merge pull request #1456 from CatimaLoyalty/dependabot/gradle/com.google.zxing-core-3.5.2
Bump com.google.zxing:core from 3.5.1 to 3.5.2
2023-07-31 19:22:18 +02:00
dependabot[bot] 1e88e0c1cc Bump com.google.zxing:core from 3.5.1 to 3.5.2
Bumps [com.google.zxing:core](https://github.com/zxing/zxing) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/zxing/zxing/releases)
- [Changelog](https://github.com/zxing/zxing/blob/master/CHANGES)
- [Commits](https://github.com/zxing/zxing/compare/zxing-3.5.1...zxing-3.5.2)

---
updated-dependencies:
- dependency-name: com.google.zxing:core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-31 02:58:42 +00:00
Sylvia van Os 72b8781eec Merge pull request #1455 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-30 13:22:12 +02:00
Reza Almanda dd8c63b088 Translated using Weblate (Indonesian)
Currently translated at 95.2% (121 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-07-30 13:08:02 +02:00
Eric ec9affd8c3 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (127 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-07-30 13:08:02 +02:00
Sylvia van Os 605e9711fa Translated using Weblate (Polish)
Currently translated at 36.2% (46 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pl/
2023-07-30 13:08:02 +02:00
FC Stegerman 6dfbb169df LoyaltyCardEditActivity: fix noDataLossOnResumeOrRotate test 2023-07-29 21:30:08 +02:00
FC Stegerman f671c6b0d1 LoyaltyCardEditActivity: fix state loss on rotation for dates 2023-07-29 21:14:51 +02:00
Sylvia van Os b98ee46566 Merge pull request #1451 from obfusk/fix-divider
only show divider with name/note + extra field
2023-07-29 16:52:20 +02:00
FC Stegerman 3353cf288f only show divider with name/note + extra field 2023-07-29 15:49:09 +02:00
Sylvia van Os a408f8d727 Release Catima 2.25.2 2023-07-27 19:14:44 +02:00
Sylvia van Os 2d7bb02d1a Update fastlane 2023-07-27 19:07:10 +02:00
Sylvia van Os 38c8e38ed6 Merge pull request #1446 from CatimaLoyalty/create-pull-request/patch-1690299279
Update Fastlane changelogs
2023-07-25 17:35:15 +02:00
TheLastProject 28b95b8f75 Update Fastlane changelogs 2023-07-25 15:34:39 +00:00
Sylvia van Os c1ebbdb997 Update CHANGELOG.md 2023-07-25 17:34:22 +02:00
Sylvia van Os fadba7a11c Merge pull request #1445 from obfusk/stocard-csv
add python script & update stocard csv
2023-07-24 20:54:41 +02:00
FC Stegerman fd61434565 move stocard readme & script 2023-07-24 20:35:25 +02:00
Sylvia van Os 398dff4b3c Merge pull request #1444 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-24 19:35:57 +02:00
FC Stegerman 5c95b750b2 rename to dump_stocard_stores.py 2023-07-24 18:24:42 +02:00
FC Stegerman 9851c0a2fa update stocard_stores.csv 2023-07-24 18:22:03 +02:00
FC Stegerman c121f846c5 add stocard_stores.py script 2023-07-24 18:17:57 +02:00
ChengCheng c20ba027cf Added translation using Weblate (Chinese (Literary)) 2023-07-24 11:42:49 +02:00
Kamborio e5dd26b8ee Translated using Weblate (Spanish)
Currently translated at 29.1% (37 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2023-07-24 11:41:46 +02:00
Danylo Lystopadov 3b449464ac Translated using Weblate (Ukrainian)
Currently translated at 100.0% (127 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-07-24 11:41:46 +02:00
Danylo Lystopadov 3f4d4e38cd Translated using Weblate (Ukrainian)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-07-24 11:41:46 +02:00
Sylvia van Os 30ccd03686 Merge pull request #1442 from obfusk/usages-len
StocardImporter: check usages is not empty just in case
2023-07-23 21:57:48 +02:00
FC Stegerman 5493947c28 StocardImporter: check usages is not empty just in case 2023-07-23 20:56:24 +02:00
Sylvia van Os 4172903b42 Merge pull request #1441 from CatimaLoyalty/stocard_20230721
Update Stocard importer
2023-07-23 16:48:53 +02:00
Sylvia van Os 00b1368176 Fix image import 2023-07-23 16:29:55 +02:00
Sylvia van Os 09fee5628f Read usage-statistics/content.json file for lastUsed data 2023-07-23 14:28:14 +02:00
Sylvia van Os 7a7a2f8361 Read input_provider_name in field if available 2023-07-23 14:25:56 +02:00
Sylvia van Os a9ced56023 Include newer Stocard export 2023-07-23 14:01:59 +02:00
Sylvia van Os a4af171598 Small credits dialog tweak 2023-07-23 13:06:16 +02:00
Sylvia van Os 164c82a779 Merge pull request #1440 from CatimaLoyalty/create-pull-request/patch-1690096427
Update contributors
2023-07-23 10:01:30 +02:00
TheLastProject 608c3ab863 Update contributors 2023-07-23 07:13:47 +00:00
Sylvia van Os 379a71c7ad Merge pull request #1439 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-22 17:21:15 +02:00
Jiri Grönroos ee6a6dffcf Translated using Weblate (Finnish)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2023-07-22 17:08:30 +02:00
solokot 1d6a393914 Translated using Weblate (Russian)
Currently translated at 100.0% (127 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-07-22 17:08:30 +02:00
Tim Trek 5c4a905ac0 Translated using Weblate (German)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-07-22 17:08:30 +02:00
Sylvia van Os 91ce71ea68 Merge pull request #1438 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-22 10:42:18 +02:00
Eric f07ac3e026 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (127 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-07-22 03:11:31 +02:00
Slávek Banko 649f2c47b4 Translated using Weblate (Czech)
Currently translated at 100.0% (127 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-07-22 03:11:31 +02:00
Milan Šalka 62dcc373ed Translated using Weblate (Slovak)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2023-07-22 03:11:31 +02:00
Wiktor e9b04adec6 Translated using Weblate (Polish)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-07-22 03:11:31 +02:00
Sylvia van Os 636be16bdd Merge pull request #1436 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-20 17:26:50 +02:00
Sylvia van Os 5ad28f37b8 Merge pull request #1437 from CatimaLoyalty/feature/elevatedMainScreen
Small main screen layout tweaks
2023-07-20 17:26:17 +02:00
Sylvia van Os 5ff6059e86 Small main screen layout tweaks 2023-07-20 16:59:39 +02:00
Balázs Meskó b9df712394 Translated using Weblate (Hungarian)
Currently translated at 33.0% (42 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hu/
2023-07-20 13:07:59 +02:00
Eric 790fd7e48f Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (127 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-07-20 13:07:59 +02:00
Slávek Banko bb43266a01 Translated using Weblate (Czech)
Currently translated at 100.0% (127 of 127 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-07-20 13:07:58 +02:00
Sylvia van Os 450cfce84a Merge pull request #1434 from obfusk/refactor-importer-part-2
refactor importer part 2
2023-07-19 21:17:22 +02:00
Sylvia van Os 6cef56b38b Merge pull request #1435 from CatimaLoyalty/create-pull-request/patch-1689792805
Update Fastlane changelogs
2023-07-19 20:53:53 +02:00
TheLastProject fbb7cf7e9c Update Fastlane changelogs 2023-07-19 18:53:24 +00:00
Sylvia van Os 9ab2a6a5b2 Update CHANGELOG 2023-07-19 20:53:06 +02:00
Quang Trung 682fc8303c Fix crash on configuration changes in DatePickerFragment (#1431) 2023-07-19 20:52:25 +02:00
FC Stegerman aa1274566b refactor FidmeImporter 2023-07-19 01:25:00 +02:00
FC Stegerman d8cd581cb0 refactor StocardImporter 2023-07-19 01:10:39 +02:00
FC Stegerman 2cd00f9103 refactor VoucherVaultImporter 2023-07-19 00:24:09 +02:00
Sylvia van Os ae07f94b25 Merge pull request #1433 from obfusk/test-bitmaps
use JPGs instead of LetterBitmap b/c of partial robolectric Canvas support
2023-07-18 23:53:15 +02:00
FC Stegerman 22d671263a JPGs instead of LetterBitmap (robolectric missing Canvas support) 2023-07-18 23:27:44 +02:00
Sylvia van Os 227f30361f Try to fix autoclose for real 2023-07-17 21:15:14 +02:00
Sylvia van Os b964652b83 Merge pull request #1429 from CatimaLoyalty/create-pull-request/patch-1689620901
Update Fastlane changelogs
2023-07-17 21:09:32 +02:00
TheLastProject f926ffa1d0 Update Fastlane changelogs 2023-07-17 19:08:21 +00:00
Sylvia van Os d03b8b5635 Merge branch 'main' of github.com:CatimaLoyalty/Android 2023-07-17 21:08:02 +02:00
Sylvia van Os 4e5fea7a52 Update CHANGELOG 2023-07-17 21:07:54 +02:00
Sylvia van Os 95cb6c0a08 Merge pull request #1422 from obfusk/refactor-importer-part-1
refactor importer part 1
2023-07-17 21:06:00 +02:00
FC StegermanandSylvia van Os d350d0b2c7 CatimaImporter: add comment about card group import
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2023-07-17 20:42:36 +02:00
FC StegermanandSylvia van Os ac0f6f6f3e Utils.getRenamedCardImageFileName(): add javadoc
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2023-07-17 20:35:02 +02:00
FC StegermanandSylvia van Os ab030ba002 LocaltyCard.isDuplicate(): reformat & add comments
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2023-07-17 20:23:52 +02:00
Sylvia van Os 93103c8c6d Merge branch 'main' of github.com:CatimaLoyalty/Android 2023-07-17 18:36:28 +02:00
Sylvia van Os 576ec1e6de Release Catima 2.25.1 2023-07-17 18:35:50 +02:00
Sylvia van Os b602ce5d78 Merge pull request #1426 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-17 18:29:08 +02:00
Cabrito 0ecd38ed1c Translated using Weblate (Portuguese)
Currently translated at 100.0% (126 of 126 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2023-07-17 18:03:59 +02:00
Cabrito d48e02463c Translated using Weblate (Portuguese)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2023-07-17 18:03:59 +02:00
Sylvia van Os b9d9c8d2e3 Use chevron-style up/down icons in groups layout 2023-07-16 21:34:03 +02:00
FC Stegerman 3ae665b70f DBHelper: add note to DEFAULT_ZOOM_LEVEL 2023-07-16 20:16:01 +02:00
FC Stegerman 9cf9959b6b add importExistingCardsAfterModification test 2023-07-16 19:53:41 +02:00
FC Stegerman d11e2c166b Utils.copyToTempFile(): use try for resource management 2023-07-16 18:29:38 +02:00
FC Stegerman f783be7a4f importer: handle inputFile errors better 2023-07-16 18:16:41 +02:00
FC Stegerman 9ee96b88e8 CatimaImporter: add .close() 2023-07-16 18:04:26 +02:00
FC Stegerman ba896fc1db DBHelper: don't use DEFAULT_ZOOM_LEVEL in migration 2023-07-16 18:02:52 +02:00
Sylvia van Os 47f1ea80b6 Merge pull request #1424 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-16 15:14:48 +02:00
Projjal Moitra b5efa28e85 Translated using Weblate (Bengali (India))
Currently translated at 96.3% (287 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-07-16 15:05:41 +02:00
solokot d456a8920d Translated using Weblate (Russian)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-07-16 15:05:41 +02:00
Sylvia van Os 4ef0c96b29 Merge pull request #1423 from CatimaLoyalty/create-pull-request/patch-1689492043
Update contributors
2023-07-16 10:03:08 +02:00
TheLastProject 343c77f9e3 Update contributors 2023-07-16 07:20:43 +00:00
FC Stegerman 1425d4af58 CatimaImporter: add saveAndDeduplicate() & refactor 2023-07-16 05:08:44 +02:00
FC Stegerman 48510494eb Utils: split off CARD_IMAGE_FILENAME_REGEX 2023-07-16 05:05:44 +02:00
FC Stegerman d5d53b241a Utils: add getRenamedCardImageFileName() 2023-07-16 04:44:24 +02:00
FC Stegerman 901c2d8154 LoyaltyCard: fix isDuplicate() 2023-07-16 04:43:27 +02:00
FC Stegerman 84d7e15b5c LoyaltyCard: add isDuplicate(); Utils: add equals() 2023-07-16 03:29:31 +02:00
FC Stegerman b8fa4d7060 DBHelper: add DEFAULT_ZOOM_LEVEL 2023-07-16 03:12:29 +02:00
FC Stegerman da9e3bb6b2 CatimaImporter: read ZIP twice, get checksums 2023-07-16 02:23:54 +02:00
FC Stegerman 3a5973a04d Utils: add checksum() 2023-07-16 02:13:34 +02:00
Sylvia van Os 673e64924b Add security policy 2023-07-16 01:25:53 +02:00
FC Stegerman 5f99f2b17e Utils: add imageFiles() 2023-07-16 00:57:00 +02:00
FC Stegerman bf05103955 import: copy ZIP, use File instead of InputStream 2023-07-16 00:45:18 +02:00
Sylvia van Os 5ea6155c39 Merge pull request #1421 from obfusk/patch-5
revert s/Frie/Gratis/ in nb-rNO translation
2023-07-14 20:07:25 +02:00
FC Stegerman abb1cd29f0 revert s/Frie/Gratis/ in nb-rNO translation 2023-07-14 17:31:56 +00:00
Sylvia van Os 52363cdff4 Merge pull request #1420 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-14 17:52:25 +02:00
Bottan Hermawan ac4f4e3a9a Translated using Weblate (Indonesian)
Currently translated at 95.2% (120 of 126 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-07-14 16:53:20 +02:00
Bottan Hermawan 555387e20d Translated using Weblate (Indonesian)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2023-07-14 16:53:20 +02:00
Sylvia van Os 70ae8ff167 Merge pull request #1419 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-13 19:03:47 +02:00
Balázs Meskó 86512532f1 Translated using Weblate (Hungarian)
Currently translated at 30.9% (39 of 126 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hu/
2023-07-13 14:45:59 +02:00
Eric ebf6318aa2 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (126 of 126 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-07-13 14:45:59 +02:00
Slávek Banko fd482a4cba Translated using Weblate (Czech)
Currently translated at 100.0% (126 of 126 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-07-13 14:45:59 +02:00
Erik Spjelkavik 54d91dc8a1 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.3% (296 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2023-07-13 14:45:59 +02:00
J. Lavoie 9fa7fe388f Translated using Weblate (French)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-07-13 14:45:59 +02:00
Kamborio 1415d8da3e Translated using Weblate (Spanish)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2023-07-13 14:45:59 +02:00
J. Lavoie 0ad5de18e1 Translated using Weblate (German)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-07-13 14:45:59 +02:00
Sylvia van Os 9659a2a2cd Merge pull request #1418 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-12 17:12:10 +02:00
Giovanni Donisi 1dd894bd27 Translated using Weblate (Italian)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-07-12 16:52:59 +02:00
Sylvia van Os 0d9151294e Merge pull request #1416 from CatimaLoyalty/create-pull-request/patch-1689096450
Update Fastlane changelogs
2023-07-11 19:31:39 +02:00
Sylvia van Os 09dda99afc Merge pull request #1415 from obfusk/fix-shortcuts
ShortcutHelper: trim after skipping missing cards
2023-07-11 19:31:18 +02:00
TheLastProject a4fb91b9aa Update Fastlane changelogs 2023-07-11 17:27:30 +00:00
Sylvia van Os 036b821b28 Update CHANGELOG 2023-07-11 19:27:12 +02:00
Sylvia van Os 479a35657f Merge pull request #1414 from obfusk/fix-shortcuts
ShortcutHelper: skip outdated cards that no longer exist
2023-07-11 19:19:14 +02:00
FC Stegerman eca9d1c74c ShortcutHelper: trim after skipping missing cards 2023-07-11 19:18:41 +02:00
FC Stegerman 95055f1ce6 ShortcutHelper: skip outdated cards that no longer exist 2023-07-11 18:14:34 +02:00
Sylvia van Os f4a5ae74d6 Release Catima 2.25.0 2023-07-09 18:31:06 +02:00
Sylvia van Os 16952186c7 Merge pull request #1411 from joserebelo/permissions-conflict-fix
Fix content provider permissions conflict
2023-07-09 15:55:02 +02:00
José Rebelo 7d12279b0d Fix content provider permissions conflict 2023-07-09 14:03:34 +01:00
Sylvia van Os 15a49344a3 Merge pull request #1409 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-09 13:35:10 +02:00
Eric ff15ce0615 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-07-09 13:13:46 +02:00
Slávek Banko 57144c4cd1 Translated using Weblate (Czech)
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-07-09 13:13:46 +02:00
Allan Nordhøy 50387f55d4 Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.9% (295 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2023-07-09 13:13:46 +02:00
Sylvia van Os 0fa07d3d0b Merge pull request #1408 from CatimaLoyalty/create-pull-request/patch-1688886665
Update contributors
2023-07-09 09:34:07 +02:00
TheLastProject 05516f88fc Update contributors 2023-07-09 07:11:04 +00:00
Sylvia van Os 841a5e3ddb Merge pull request #1407 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-08 18:22:17 +02:00
Kis Dominik 2889b45c51 Translated using Weblate (Hungarian)
Currently translated at 31.2% (39 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hu/
2023-07-08 17:53:57 +02:00
Kis Dominik 9ebb53b224 Translated using Weblate (Hungarian)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2023-07-08 17:53:56 +02:00
109247019824 14b8b3bd7a Translated using Weblate (Bulgarian)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-07-08 17:53:56 +02:00
Sylvia van Os 3e4c3e9852 Merge pull request #1406 from CatimaLoyalty/create-pull-request/patch-1688747814
Update Fastlane changelogs
2023-07-07 18:41:25 +02:00
TheLastProject fa417cdfe5 Update Fastlane changelogs 2023-07-07 16:36:53 +00:00
Sylvia van Os a9863d1921 Update CHANGELOG 2023-07-07 18:36:36 +02:00
Sylvia van Os f2b7a63a02 Merge pull request #1404 from joserebelo/import-trailing-slash
Fix parse of import URI with trailing slash
2023-07-07 18:35:25 +02:00
Sylvia van Os 8e0a40ee3f Merge pull request #1405 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-07 17:35:54 +02:00
enescan201 21064803eb Translated using Weblate (Turkish)
Currently translated at 61.6% (77 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2023-07-07 12:53:18 +02:00
enescan201 031b751a9d Translated using Weblate (Turkish)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2023-07-07 12:53:18 +02:00
109247019824 bb9b640aa5 Translated using Weblate (Bulgarian)
Currently translated at 96.6% (288 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-07-07 12:53:18 +02:00
Eric 1681d077b6 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-07-07 12:53:18 +02:00
yangyangdaji 3500444e0c Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-07-07 12:53:18 +02:00
Slávek Banko e05ebbe607 Translated using Weblate (Czech)
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-07-07 12:53:18 +02:00
solokot b3bb20c795 Translated using Weblate (Russian)
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-07-07 12:53:18 +02:00
solokot b0315f279a Translated using Weblate (Russian)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-07-07 12:53:18 +02:00
Heimen Stoffels 9e788cb604 Translated using Weblate (Dutch)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-07-07 12:53:17 +02:00
Slávek Banko 090f3dc80b Translated using Weblate (Czech)
Currently translated at 100.0% (298 of 298 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-07-07 12:53:17 +02:00
Sylvia van Os e4f2f8f46b Remove unused imports 2023-07-05 21:57:20 +02:00
Eric e5ecd59569 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-07-05 17:18:24 +02:00
tjw123hh 441ae9587e Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (292 of 292 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-07-05 17:18:23 +02:00
Slávek Banko 0c1e16592d Translated using Weblate (Czech)
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-07-05 17:18:00 +02:00
solokot 02659f840e Translated using Weblate (Russian)
Currently translated at 100.0% (292 of 292 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-07-05 17:17:59 +02:00
Heimen Stoffels eca5ec10d3 Translated using Weblate (Dutch)
Currently translated at 100.0% (292 of 292 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-07-05 17:17:43 +02:00
J. Lavoie dbc8df018d Translated using Weblate (Italian)
Currently translated at 100.0% (292 of 292 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-07-05 17:17:25 +02:00
J. Lavoie 874b887da1 Translated using Weblate (French)
Currently translated at 100.0% (292 of 292 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-07-05 17:17:08 +02:00
J. Lavoie 5367324219 Translated using Weblate (German)
Currently translated at 100.0% (292 of 292 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-07-05 17:16:41 +02:00
Slávek Banko 6df58e0574 Translated using Weblate (Czech)
Currently translated at 100.0% (292 of 292 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-07-05 17:16:18 +02:00
José Rebelo c8b6328cc6 Fix parse of import URI with trailing slash 2023-07-05 13:05:47 +01:00
Sylvia van Os 90616214f0 Merge pull request #1403 from CatimaLoyalty/create-pull-request/patch-1688507089
Update Fastlane changelogs
2023-07-04 23:44:59 +02:00
TheLastProject e3bce7eb50 Update Fastlane changelogs 2023-07-04 21:44:49 +00:00
Sylvia van Os b2d1660cf8 Update CHANGELOG 2023-07-04 23:44:33 +02:00
Sylvia van Os 3de24bb6f0 Merge pull request #1402 from CatimaLoyalty/feature/improveSettingsScreen
Reorganize settings screen
2023-07-04 23:43:33 +02:00
Sylvia van Os b4e403d214 Reorganize settings screen 2023-07-04 23:30:46 +02:00
Sylvia van Os b66351ab58 Fix needs info autoclose 2023-07-04 21:01:36 +02:00
Sylvia van Os c9d775f426 Merge pull request #1401 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-04 20:53:24 +02:00
notlin4 6d4af3d86b Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2023-07-04 08:52:51 +02:00
Sylvia van Os 37803bd906 Merge pull request #1400 from CatimaLoyalty/create-pull-request/patch-1688410909
Update Fastlane changelogs
2023-07-03 21:08:22 +02:00
TheLastProject f3fcea7ab1 Update Fastlane changelogs 2023-07-03 19:01:49 +00:00
Sylvia van Os 9a67ea039c Update CHANGELOG 2023-07-03 21:01:33 +02:00
José Rebelo bf94d208bd Introduce read-only ContentProvider for cards (#1121) 2023-07-03 20:59:39 +02:00
Sylvia van Os 28c0b488e6 Merge pull request #1399 from CatimaLoyalty/create-pull-request/patch-1688280270
Update contributors
2023-07-02 13:02:55 +02:00
TheLastProject dc926bbfe7 Update contributors 2023-07-02 06:44:30 +00:00
Sylvia van Os 00d5fa4c2d Merge pull request #1398 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-07-02 00:06:18 +02:00
Giacomo Alessandroni 9aca91fb86 Translated using Weblate (Italian)
Currently translated at 77.6% (97 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2023-07-01 23:53:28 +02:00
Sylvia van Os bdab8624b5 Merge pull request #1390 from obfusk/timeout
CI: on retry, stop gradle daemon and timeout
2023-07-01 15:05:03 +02:00
Sylvia van Os 9bdfe64c79 Merge pull request #1397 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-30 11:54:05 +02:00
Tomislav Kraljević f5f7e40219 Translated using Weblate (Croatian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hr/
2023-06-30 10:53:48 +02:00
Sylvia van Os 2f51e7db68 Merge pull request #1396 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-28 13:07:22 +02:00
Eric 2cb9846f42 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-06-28 12:52:55 +02:00
Sylvia van Os 1dbe46b97e Merge pull request #1395 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-26 23:17:40 +02:00
Projjal Moitra 7e5611b062 Translated using Weblate (Bengali (India))
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-06-26 20:53:09 +02:00
Sylvia van Os d3a7acd9ab Merge pull request #1393 from CatimaLoyalty/create-pull-request/patch-1687677398
Update contributors
2023-06-25 09:38:20 +02:00
TheLastProject c023a9787d Update contributors 2023-06-25 07:16:38 +00:00
Sylvia van Os 6de0ed6956 Merge pull request #1391 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-24 18:57:03 +02:00
ayuyydev aa5f0a7bf8 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2023-06-24 15:53:29 +02:00
Slávek Banko 6dd5bd957c Translated using Weblate (Czech)
Currently translated at 100.0% (125 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-06-24 15:53:28 +02:00
Michael Moroni c69df5edfd Translated using Weblate (Italian)
Currently translated at 62.4% (78 of 125 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2023-06-24 15:53:28 +02:00
FC Stegerman 758d034c31 CI: on retry, stop gradle daemon and timeout 2023-06-24 00:29:51 +02:00
Sylvia van Os 7bcf82a619 Merge pull request #1386 from obfusk/data-matrix-not-square
CatimaBarcode: DATA_MATRIX is not always square
2023-06-23 23:16:02 +02:00
FC Stegerman fd755185b9 BarcodeImageWriterTask: treat DATA_MATRIX as 1D for max width 2023-06-23 22:23:12 +02:00
FC Stegerman 0ac57be5f1 CatimaBarcode: DATA_MATRIX is not always square 2023-06-23 22:21:42 +02:00
Sylvia van Os bb929a48ea Merge pull request #1388 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-23 17:48:12 +02:00
Hosam Elzubair 218850be33 Translated using Weblate (Arabic)
Currently translated at 3.2% (4 of 124 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ar/
2023-06-23 14:58:05 +02:00
notlin4 ec07cceced Translated using Weblate (Chinese (Traditional))
Currently translated at 95.4% (274 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2023-06-23 14:58:05 +02:00
yangyangdaji 71ac1c5dad Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (124 of 124 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-06-23 14:58:05 +02:00
yangyangdaji b16ecfbb2c Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-06-23 14:58:05 +02:00
남현정 c64bfbabc0 Translated using Weblate (Korean)
Currently translated at 97.5% (121 of 124 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ko/
2023-06-23 14:58:05 +02:00
남현정 fc8073f717 Translated using Weblate (Korean)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ko/
2023-06-23 14:58:05 +02:00
Sylvia van Os 7f56617a3c Merge pull request #1385 from CatimaLoyalty/create-pull-request/patch-1687468237
Update Fastlane changelogs
2023-06-22 23:10:53 +02:00
TheLastProject f5dc2930b5 Update Fastlane changelogs 2023-06-22 21:10:37 +00:00
Sylvia van Os 4bdc0fef70 Update CHANGELOG 2023-06-22 23:10:21 +02:00
Sylvia van Os 2f3c96b97c Merge pull request #1359 from obfusk/barcode-rendering
Improve barcode rendering (square codes & padding)
2023-06-22 23:09:23 +02:00
FC Stegerman 6ff11e22e1 Improve barcode rendering (square codes & padding) 2023-06-22 21:41:33 +02:00
Sylvia van Os 0b188f2ba7 Merge pull request #1371 from obfusk/currency-symbols
LoyaltyCardEditActivity: work around Currency.getSymbol() bug
2023-06-22 19:58:17 +02:00
Sylvia van Os 827d5ba3f9 Merge pull request #1384 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-22 07:06:53 +02:00
IllusiveMan196 05fea6e208 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (124 of 124 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-06-22 02:53:45 +02:00
Sylvia van Os 6064d29cb0 Merge pull request #1383 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-20 20:54:46 +02:00
Oğuz Ersen 0a92daa77a Translated using Weblate (Turkish)
Currently translated at 99.6% (286 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2023-06-20 19:49:45 +02:00
Slávek Banko bb065aead4 Translated using Weblate (Czech)
Currently translated at 100.0% (124 of 124 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-06-20 19:49:45 +02:00
Michael Moroni 56467c2680 Translated using Weblate (Italian)
Currently translated at 59.6% (74 of 124 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2023-06-20 19:49:45 +02:00
solokot 1941db1e52 Translated using Weblate (Russian)
Currently translated at 100.0% (124 of 124 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-06-20 19:49:45 +02:00
Allan Nordhøy c595981996 Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.9% (284 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2023-06-20 19:49:45 +02:00
Michael Moroni 0145a820de Translated using Weblate (Italian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-06-20 19:49:45 +02:00
Sylvia van Os 224ab7f2e7 Release Catima v2.24.2 2023-06-18 18:15:55 +02:00
Sylvia van Os 1b47a62c70 Merge pull request #1380 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-18 16:48:15 +02:00
Sylvia van Os f241bad3e4 Fix broken translation 2023-06-18 16:42:40 +02:00
Viktor Broov c8657870af Translated using Weblate (Esperanto)
Currently translated at 37.6% (108 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/eo/
2023-06-18 16:38:07 +02:00
Sylvia van Os 0ed7a0a6e1 Merge pull request #1378 from CatimaLoyalty/create-pull-request/patch-1687070038
Update contributors
2023-06-18 10:25:47 +02:00
TheLastProject 325330c542 Update contributors 2023-06-18 06:33:57 +00:00
Sylvia van Os 2506f60348 Merge pull request #1377 from CatimaLoyalty/create-pull-request/patch-1686995327
Update Fastlane changelogs
2023-06-17 11:51:42 +02:00
TheLastProject 5bf6f52425 Update Fastlane changelogs 2023-06-17 09:48:47 +00:00
Sylvia van Os fb1728e5de Update CHANGELOG 2023-06-17 11:48:32 +02:00
Sylvia van Os d321f733c1 Merge pull request #1376 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-16 21:00:30 +02:00
SC 8ff46f8754 Translated using Weblate (Portuguese)
Currently translated at 95.9% (118 of 123 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2023-06-16 20:51:09 +02:00
SC a061978c93 Translated using Weblate (Portuguese)
Currently translated at 97.9% (281 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2023-06-16 20:51:09 +02:00
solokot f3bfc9b278 Translated using Weblate (Russian)
Currently translated at 100.0% (123 of 123 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-06-16 20:51:09 +02:00
gallegonovato 43ebe5e029 Translated using Weblate (Spanish)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2023-06-16 20:51:09 +02:00
Sylvia van Os 2357f4d430 Merge pull request #1375 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-15 23:35:41 +02:00
Pierre NIKOLOV 7869feb3a1 Translated using Weblate (French)
Currently translated at 98.3% (121 of 123 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-06-14 05:54:10 +02:00
Sylvia van Os 53ce856c33 Merge pull request #1372 from obfusk/rtl-buttons
LoyaltyCardViewActivity: RTL fixes for buttons
2023-06-13 23:53:04 +02:00
Sylvia van Os aa321a71ad Merge pull request #1370 from obfusk/sort-rtl
sorting_option.xml: RTL fix
2023-06-13 19:35:16 +02:00
Sylvia van Os f721237fbc Merge pull request #1373 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-13 19:29:43 +02:00
FC Stegerman 194a7ae365 improve button bar RTL handling using linear layouts 2023-06-12 15:26:21 +02:00
Slávek Banko 1aa1d8bcc1 Translated using Weblate (Czech)
Currently translated at 100.0% (123 of 123 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-06-12 10:54:13 +02:00
FC Stegerman a8355f609b LoyaltyCardViewActivity: RTL fixes for buttons 2023-06-11 23:09:47 +02:00
FC Stegerman 7c766d0832 LoyaltyCardEditActivity: work around Currency.getSymbol() bug 2023-06-11 17:30:19 +02:00
FC Stegerman 3abe99470e sorting_option.xml: RTL fix 2023-06-11 15:34:42 +02:00
Sylvia van Os 6937342226 Release Catima 2.24.1 2023-06-11 10:57:10 +02:00
Sylvia van Os e229aa9565 Merge pull request #1368 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-11 10:52:29 +02:00
Sabri Ünal 5fd629bdbc Translated using Weblate (Turkish)
Currently translated at 98.2% (282 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2023-06-11 10:44:09 +02:00
109247019824 4c261e1e04 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-06-11 10:44:09 +02:00
Tymofii Lytvynenko c8be038b81 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-06-11 10:44:08 +02:00
Kacper Małecki 268b4cf827 Translated using Weblate (Polish)
Currently translated at 98.9% (284 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-06-11 10:44:08 +02:00
Daniele Tricoli ada8fd9bd4 Translated using Weblate (Italian)
Currently translated at 98.6% (283 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-06-11 10:44:07 +02:00
Sylvia van Os 285c3d6a38 Merge pull request #1367 from CatimaLoyalty/create-pull-request/patch-1686465528
Update contributors
2023-06-11 09:32:15 +02:00
TheLastProject 07efe99630 Update contributors 2023-06-11 06:38:48 +00:00
Sylvia van Os a7d3a1c30d Merge pull request #1365 from CatimaLoyalty/create-pull-request/patch-1686414904
Update Fastlane changelogs
2023-06-10 18:38:26 +02:00
Sylvia van Os fcc995397f Merge pull request #1364 from obfusk/about-rtl
about_activity: make _sub layout consistent (fixes RTL)
2023-06-10 18:38:11 +02:00
TheLastProject cef0d037f7 Update Fastlane changelogs 2023-06-10 16:35:03 +00:00
Sylvia van Os 6e390717da Make header colour code more consistent (#1363)
- Ensure a header colour is picked for the main screen
- Simplify all different header colour code pickers into a single code
  path
2023-06-10 18:34:49 +02:00
FC Stegerman f785586c71 about_activity: make _sub layout consistent (fixes RTL) 2023-06-10 16:44:05 +02:00
Sylvia van Os e66c5e36fb Release Catima 2.24.0 2023-06-10 10:44:42 +02:00
Sylvia van Os fd0ca37a6a Merge branch 'main' of github.com:CatimaLoyalty/Android 2023-06-08 20:26:39 +02:00
Sylvia van Os e926a397a7 Add missing dates to CHANGELOG 2023-06-08 20:26:31 +02:00
Sylvia van Os 4f9a6b307f Merge pull request #1358 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-08 19:59:39 +02:00
Clxff H3r4ld0 df60f6adc2 Translated using Weblate (Indonesian)
Currently translated at 93.4% (114 of 122 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-06-08 16:49:14 +02:00
Clxff H3r4ld0 d6287a3cf1 Translated using Weblate (Indonesian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2023-06-08 16:49:14 +02:00
Sylvia van Os 7f81d727f0 Merge pull request #1357 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-07 18:37:15 +02:00
Sylvia van Os 03239f0cab Fix dark mode rendering glitch (#1355) 2023-06-07 18:35:30 +02:00
Sylvia van Os 4b6497cba2 Merge pull request #1356 from obfusk/gha-ubuntu-openjdk
CI: use OpenJDK 17 from Ubuntu
2023-06-07 18:31:29 +02:00
109247019824 99008291fb Translated using Weblate (Bulgarian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-06-07 15:49:23 +02:00
solokot 079049722c Translated using Weblate (Russian)
Currently translated at 100.0% (122 of 122 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-06-07 15:49:23 +02:00
FineFindus 73200e1ac3 Translated using Weblate (German)
Currently translated at 100.0% (122 of 122 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2023-06-07 15:49:23 +02:00
frablock 39b816ddb1 Translated using Weblate (French)
Currently translated at 99.1% (121 of 122 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-06-07 15:49:23 +02:00
Hubert Maciejewicz be43c1633d Translated using Weblate (Polish)
Currently translated at 98.6% (283 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-06-07 15:49:23 +02:00
J. Lavoie f6c9613731 Translated using Weblate (French)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-06-07 15:49:23 +02:00
FineFindus 99de8cffd8 Translated using Weblate (German)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-06-07 15:49:23 +02:00
FC Stegerman a867265c66 CI: use OpenJDK 17 from Ubuntu 2023-06-07 13:19:40 +02:00
Sylvia van Os f43df37c80 Merge pull request #1353 from obfusk/patch-4
CI: add 5m timeout (before retry) to unit test that gets stuck
2023-06-06 23:31:39 +02:00
FC Stegerman cb70b1229f CI: add 5m timeout (before retry) to unit test that gets stuck 2023-06-05 18:58:58 +00:00
Ziad OUALHADJ b0b54a1065 Fixed the sorting option to match the other filters 2023-06-05 20:22:07 +02:00
Sylvia van Os 4ccfa7fb84 Merge pull request #1352 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-05 19:35:12 +02:00
Sylvia van Os 9932b10652 Fix broken translation 2023-06-05 19:15:18 +02:00
Mai Tnt 60fe6a13ff Translated using Weblate (Croatian)
Currently translated at 97.9% (281 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hr/
2023-06-05 12:22:44 +02:00
Slávek Banko 0bf30f08a1 Translated using Weblate (Czech)
Currently translated at 100.0% (122 of 122 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-06-05 12:22:43 +02:00
solokot 112fca041b Translated using Weblate (Russian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-06-05 12:22:38 +02:00
Heimen Stoffels 59af5cb07b Translated using Weblate (Dutch)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-06-05 12:22:38 +02:00
Slávek Banko 9182837ae8 Translated using Weblate (Czech)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-06-05 12:22:37 +02:00
Mr. Adil 3f3d85c8b6 Translated using Weblate (Bengali)
Currently translated at 31.7% (89 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn/
2023-06-05 09:53:14 +02:00
Jason Li 29c068df47 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (121 of 121 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-06-05 09:53:13 +02:00
Jason Li 03a480f3b9 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-06-05 09:53:13 +02:00
Slávek Banko 0feb0fcd16 Translated using Weblate (Czech)
Currently translated at 100.0% (121 of 121 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-06-05 09:53:13 +02:00
J. Lavoie 7f1a221fec Translated using Weblate (Italian)
Currently translated at 99.6% (279 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-06-05 09:53:13 +02:00
J. Lavoie 7b52338669 Translated using Weblate (French)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-06-05 09:53:13 +02:00
J. Lavoie 0a2925eafa Translated using Weblate (German)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-06-05 09:53:13 +02:00
Sylvia van Os 92f37376a6 Merge pull request #1351 from obfusk/patch-3
README: explicitly say "OpenJDK 17", not just "Java 17"
2023-06-04 22:00:20 +02:00
FC Stegerman 08fbc30a29 README: explicitly say "OpenJDK 17", not just "Java 17" 2023-06-04 19:07:43 +00:00
Sylvia van Os 91dbcf339f Catima uses Java 17 to build 2023-06-04 20:59:26 +02:00
Sylvia van Os 24fe6886c9 Lower fullscreen bottom padding to reduce the chance of overlapping UI elements
Partially fixes https://github.com/CatimaLoyalty/Android/issues/1332
2023-06-04 19:20:00 +02:00
Sylvia van Os 270546d022 Update screenshots 2023-06-04 19:00:59 +02:00
Sylvia van Os fe278324f3 Merge pull request #1349 from CatimaLoyalty/create-pull-request/patch-1685896355
Update Fastlane changelogs
2023-06-04 18:34:52 +02:00
TheLastProject c7c18a0a14 Update Fastlane changelogs 2023-06-04 16:32:35 +00:00
Sylvia van Os d6fcb71722 Merge pull request #1347 from CatimaLoyalty/feature/detailSettings
Support selecting exactly which details to view in main view
2023-06-04 18:32:20 +02:00
Sylvia van Os 32ce1e02aa Smaller store name font on main screen 2023-06-04 18:14:23 +02:00
Sylvia van Os 8a8faac201 Merge pull request #1345 from obfusk/dialog-top-padding
add top content padding to dialogs
2023-06-04 16:11:31 +02:00
Sylvia van Os 2793f38d19 Move store name below card image 2023-06-04 14:55:26 +02:00
Sylvia van Os 654e3f7843 Improve text readability on icon 2023-06-04 11:20:17 +02:00
Sylvia van Os 2a6fe92b1b Support selecting exactly which details to view in main view 2023-06-04 11:06:35 +02:00
Sylvia van Os b3cd102332 Merge pull request #1348 from CatimaLoyalty/create-pull-request/patch-1685860707
Update contributors
2023-06-04 11:03:31 +02:00
TheLastProject e12bfa81dc Update contributors 2023-06-04 06:38:26 +00:00
FC Stegerman e859e7849d add top content padding to dialogs 2023-06-03 23:14:49 +02:00
Sylvia van Os 7a4c9ce84f Release Catima 2.23.3 2023-06-03 17:12:27 +02:00
Sylvia van Os 6419ca7d11 Merge pull request #1341 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-03 15:59:03 +02:00
Clxff H3r4ld0 d1b23c712a Translated using Weblate (Indonesian)
Currently translated at 94.1% (113 of 120 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-06-03 15:44:42 +02:00
Sabri Ünal ef5b525401 Translated using Weblate (Turkish)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2023-06-03 15:44:42 +02:00
frablock a8d5cb9ef8 Translated using Weblate (French)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-06-03 15:44:42 +02:00
Sylvia van Os 42090310d4 Merge pull request #1340 from CatimaLoyalty/create-pull-request/patch-1685795604
Update Fastlane changelogs
2023-06-03 14:34:32 +02:00
TheLastProject 9d8da2a451 Update Fastlane changelogs 2023-06-03 12:33:24 +00:00
Sylvia van Os fb488af2b7 Fix barcode being invisible on square screens
See https://github.com/CatimaLoyalty/Android/issues/1339
2023-06-03 14:33:04 +02:00
Sylvia van Os 71052c9f69 Merge pull request #1338 from CatimaLoyalty/create-pull-request/patch-1685789977
Update Fastlane changelogs
2023-06-03 13:00:10 +02:00
TheLastProject 2a285f6d21 Update Fastlane changelogs 2023-06-03 10:59:37 +00:00
Sylvia van Os e668ae7d9d Update CHANGELOG 2023-06-03 12:59:20 +02:00
Sylvia van Os 4a197c542a Merge pull request #1329 from obfusk/patch-2
make checkBox_reverse font size match sort type radio buttons
2023-06-03 12:58:44 +02:00
Sylvia van Os 720c6b6510 Merge pull request #1337 from obfusk/view-card-id
LoyaltyCardViewActivity: use "Card ID" as title for dialog
2023-06-02 20:24:14 +02:00
FC Stegerman d932ebb9f2 LoyaltyCardViewActivity: use "Card ID" as title for dialog 2023-06-02 20:17:04 +02:00
Poorva Patidar 77b6d8724b Made barcode value text Selectable (#1331) 2023-06-02 19:57:51 +02:00
Swayam Khare 5ff002da51 Added margin to EditText in AlertDialog (#1328) 2023-06-02 19:47:23 +02:00
Sylvia van Os 16b3fbdf9c Merge pull request #1334 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-06-02 08:32:18 +02:00
109247019824 4f11eceb3b Translated using Weblate (Bulgarian)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-06-02 06:47:46 +02:00
Eryk Michalak c11d777bcc Translated using Weblate (Polish)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-06-02 06:47:46 +02:00
Sylvia van Os 49cda90ac6 Merge pull request #1330 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-31 21:13:11 +02:00
Balázs Meskó 63e4f4fd0d Translated using Weblate (Hungarian)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2023-05-31 20:49:42 +02:00
109247019824 c44845582c Translated using Weblate (Bulgarian)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-05-31 20:49:42 +02:00
solokot b0771d3b01 Translated using Weblate (Russian)
Currently translated at 100.0% (120 of 120 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-05-31 20:49:42 +02:00
FC Stegerman 285a7a9aa7 make checkBox_reverse font size match sort type radio buttons 2023-05-31 15:40:04 +00:00
Sylvia van Os 818c5e1643 Merge branch 'main' of github.com:TheLastProject/loyalty-card-locker 2023-05-30 18:54:50 +02:00
Sylvia van Os 7ffaf65635 Use regular title in info dialog 2023-05-30 18:54:42 +02:00
Sylvia van Os bf50dcbaf3 Merge pull request #1321 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-30 18:25:02 +02:00
Balanda Nazarii 3e83035cf6 Translated using Weblate (Ukrainian)
Currently translated at 98.3% (118 of 120 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-05-30 13:24:00 +02:00
Sylvia van Os e921aab322 Release Catima 2.23.2 2023-05-30 12:59:21 +02:00
Sylvia van Os 1ea125d7f9 Merge pull request #1317 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-30 12:48:13 +02:00
Sylvia van Os c828ec516c Merge pull request #1319 from CatimaLoyalty/create-pull-request/patch-1685442708
Update Fastlane changelogs
2023-05-30 12:32:31 +02:00
TheLastProject 5704ce1381 Update Fastlane changelogs 2023-05-30 10:31:47 +00:00
Sylvia van Os ca33184e81 Merge branch 'main' of github.com:TheLastProject/loyalty-card-locker 2023-05-30 12:31:31 +02:00
Sylvia van Os 82db76f3a9 Fix long barcode values causing barcode to scale down to nothing 2023-05-30 12:31:21 +02:00
Sylvia van Os ab6955cf9b Fix set icon menu sometimes re-opening after returning from image cropper 2023-05-30 12:29:55 +02:00
Enol P a1c81c3223 Translated using Weblate (Asturian)
Currently translated at 0.8% (1 of 120 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ast/
2023-05-30 12:06:46 +02:00
Enol P 43e7114f16 Translated using Weblate (Asturian)
Currently translated at 30.3% (85 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ast/
2023-05-30 12:06:46 +02:00
Slávek Banko d1b84097f6 Translated using Weblate (Czech)
Currently translated at 100.0% (120 of 120 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-05-30 12:06:45 +02:00
solokot 2c9b3896c9 Translated using Weblate (Russian)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-05-30 12:06:40 +02:00
Heimen Stoffels 3dbee69847 Translated using Weblate (Dutch)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-05-30 12:06:39 +02:00
Slávek Banko 4f9414ab4f Translated using Weblate (Czech)
Currently translated at 100.0% (280 of 280 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-05-30 12:06:39 +02:00
Enol P 5a4043bf90 Added translation using Weblate (Asturian) 2023-05-30 02:00:59 +02:00
Balanda Nazarii f742639925 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-05-30 00:10:19 +02:00
Eryk Michalak e50cca781e Translated using Weblate (Polish)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-05-30 00:10:19 +02:00
Sylvia van Os 1abff7c900 Merge pull request #1316 from CatimaLoyalty/create-pull-request/patch-1685381842
Update Fastlane changelogs
2023-05-29 19:40:10 +02:00
TheLastProject 8f24fcee96 Update Fastlane changelogs 2023-05-29 17:37:22 +00:00
Sylvia van Os f3e1bfc503 Improve button styling in Groups screen 2023-05-29 19:37:03 +02:00
Sylvia van Os 65e3b87df4 Merge branch 'main' of github.com:TheLastProject/loyalty-card-locker 2023-05-29 18:20:08 +02:00
Sylvia van Os 2dbe9ebb8a Fix text and icon alignment on home screen 2023-05-29 18:06:49 +02:00
Sylvia van Os ccfbe1f679 Merge pull request #1315 from CatimaLoyalty/create-pull-request/patch-1685369384
Update Fastlane changelogs
2023-05-29 16:27:57 +02:00
TheLastProject 3a4467db83 Update Fastlane changelogs 2023-05-29 14:09:44 +00:00
Sylvia van Os 419d28163e Long-press card icon in view activity to change it 2023-05-29 16:09:27 +02:00
Sylvia van Os 89483c4c4e Merge branch 'main' of github.com:TheLastProject/loyalty-card-locker 2023-05-28 21:18:24 +02:00
Sylvia van Os 4e921eb5d7 Update fastlane 2023-05-28 21:18:16 +02:00
Sylvia van Os 0cf266c6f1 Merge pull request #1314 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-28 14:24:58 +02:00
Slávek Banko 20f9f971a1 Translated using Weblate (Czech)
Currently translated at 100.0% (119 of 119 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-05-28 12:49:56 +02:00
Heimen Stoffels 0150ca81cf Translated using Weblate (Dutch)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-05-28 12:49:56 +02:00
Sylvia van Os 4fd6092f8d Merge pull request #1313 from CatimaLoyalty/create-pull-request/patch-1685258004
Update contributors
2023-05-28 10:33:47 +02:00
TheLastProject a488003e4a Update contributors 2023-05-28 07:13:23 +00:00
Sylvia van Os 9e0e8bab75 Release Catima 2.23.1 2023-05-27 17:53:03 +02:00
Sylvia van Os 0eca05d656 Merge pull request #1310 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-27 12:45:32 +02:00
Sylvia van Os 1c5d102a59 Fix lint 2023-05-27 12:39:20 +02:00
Eudes-alencar 400d0f4e22 Translated using Weblate (Portuguese)
Currently translated at 100.0% (118 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2023-05-27 12:31:19 +02:00
Clxff H3r4ld0 4c0593d333 Translated using Weblate (Indonesian)
Currently translated at 94.0% (111 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-05-27 12:31:19 +02:00
Eudes-alencar 87d82b1b6d Translated using Weblate (Portuguese)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2023-05-27 12:31:19 +02:00
WaldiS 8ea4a3309d Translated using Weblate (Polish)
Currently translated at 99.6% (287 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-05-27 12:31:19 +02:00
Sylvia van Os 18088b30bd Delete unused resources 2023-05-25 22:43:58 +02:00
Sylvia van Os 875309bc5e Merge pull request #1309 from CatimaLoyalty/create-pull-request/patch-1685044413
Update Fastlane changelogs
2023-05-25 22:04:46 +02:00
TheLastProject 95520a7051 Update Fastlane changelogs 2023-05-25 19:53:32 +00:00
Sylvia van Os ab9391db38 Update libraries
It seems Material 1.9.0 slightly changes some paddings, so created new
screenshots
2023-05-25 21:52:38 +02:00
Sylvia van Os e43e4b37ae Merge branch 'main' of github.com:TheLastProject/loyalty-card-locker 2023-05-25 21:28:47 +02:00
Sylvia van Os f2d856b661 Actually properly remove font scale setting 2023-05-25 21:20:32 +02:00
Sylvia van Os 8c6c5fb767 Merge pull request #1308 from obfusk/patch-1
fix typo in RELEASE_STEPS.md
2023-05-25 21:10:41 +02:00
FC Stegerman bb4ec8f8be fix typo in RELEASE_STEPS.md 2023-05-25 18:55:53 +00:00
Sylvia van Os e5fd277198 Release Catima 2.23.0 2023-05-25 19:01:37 +02:00
Sylvia van Os 93b089c646 Merge pull request #1306 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-25 18:12:36 +02:00
Clxff Heraldo 5e37a9b89f Translated using Weblate (Indonesian)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2023-05-25 18:05:27 +02:00
Slávek Banko 27cc7b9008 Translated using Weblate (Czech)
Currently translated at 100.0% (118 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-05-25 18:05:27 +02:00
Slávek Banko 0749bbd432 Translated using Weblate (Czech)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-05-25 18:05:27 +02:00
Sylvia van Os 9b1e0537c9 Merge pull request #1305 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-24 18:00:00 +02:00
Balázs Meskó 3b2b45f08f Translated using Weblate (Hungarian)
Currently translated at 25.4% (30 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hu/
2023-05-24 13:50:37 +02:00
Milo Ivir 60a5e60ae0 Translated using Weblate (Croatian)
Currently translated at 2.5% (3 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hr/
2023-05-24 13:50:37 +02:00
Milo Ivir 77513d5528 Translated using Weblate (Croatian)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hr/
2023-05-24 13:50:37 +02:00
丛林意志 15fa483490 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (118 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-05-24 13:50:37 +02:00
SilverFS 40ba47d60c Translated using Weblate (Dutch)
Currently translated at 11.8% (14 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nl/
2023-05-24 13:50:37 +02:00
solokot 986327d141 Translated using Weblate (Russian)
Currently translated at 100.0% (118 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-05-24 13:50:37 +02:00
Jean Mareilles 36f0dde3b2 Translated using Weblate (French)
Currently translated at 99.1% (117 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-05-24 13:50:37 +02:00
Giovanni Donisi f0a695a616 Translated using Weblate (Italian)
Currently translated at 99.6% (287 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-05-24 13:50:37 +02:00
Jean Mareilles 810b0f3c14 Translated using Weblate (French)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-05-24 13:50:37 +02:00
Mateo Gomez fcf08a8900 Translated using Weblate (Spanish)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2023-05-24 13:50:37 +02:00
Sylvia van Os 939bf6a788 Merge pull request #1304 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-22 20:15:09 +02:00
Minecraft boom 935f899d0f Translated using Weblate (Arabic)
Currently translated at 97.2% (280 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-05-22 06:54:30 +02:00
Balázs Meskó 6c8d79ef36 Translated using Weblate (Hungarian)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2023-05-22 06:54:30 +02:00
Oğuz Ersen 178707b482 Translated using Weblate (Turkish)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2023-05-22 06:54:30 +02:00
109247019824 0f2c9cb63d Translated using Weblate (Bulgarian)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-05-22 06:54:30 +02:00
丛林意志 0869a00f0c Translated using Weblate (Chinese (Simplified))
Currently translated at 99.1% (117 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2023-05-22 06:54:30 +02:00
丛林意志 b63b8c4ea7 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-05-22 06:54:30 +02:00
solokot 76d77a2af4 Translated using Weblate (Russian)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-05-22 06:54:30 +02:00
Heimen Stoffels dade0b7a54 Translated using Weblate (Dutch)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-05-22 06:54:30 +02:00
Artūras Kalenda 68801d6958 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (288 of 288 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2023-05-22 06:54:30 +02:00
Sylvia van Os 5c3ec85043 Merge pull request #1303 from CatimaLoyalty/create-pull-request/patch-1684674032
Update Fastlane changelogs
2023-05-21 15:02:20 +02:00
TheLastProject 6332e396cb Update Fastlane changelogs 2023-05-21 13:00:31 +00:00
Sylvia van Os 7f022feb6a Fix crash when using "Take a photo" with disabled camera app 2023-05-21 15:00:11 +02:00
Sylvia van Os 1fa8487474 Bump AGP 2023-05-21 14:48:20 +02:00
Sylvia van Os 0e040a73eb Merge branch 'main' of github.com:TheLastProject/loyalty-card-locker 2023-05-21 14:34:51 +02:00
Sylvia van Os 65acb885af Fix crash on disabled camera app 2023-05-21 14:34:39 +02:00
Sylvia van Os ee28957cbd Merge pull request #1302 from CatimaLoyalty/create-pull-request/patch-1684649320
Update contributors
2023-05-21 09:23:27 +02:00
TheLastProject 0e9f4d9f2b Update contributors 2023-05-21 06:08:39 +00:00
Sylvia van Os 58974cf738 Merge pull request #1301 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-20 13:32:23 +02:00
Balázs Meskó c56c931a70 Translated using Weblate (Hungarian)
Currently translated at 15.2% (18 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hu/
2023-05-20 11:53:50 +02:00
Quentin PAGÈS c83e8b6682 Translated using Weblate (Occitan)
Currently translated at 34.8% (100 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/oc/
2023-05-20 11:53:50 +02:00
109247019824 449ab86b5a Translated using Weblate (Bulgarian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-05-20 11:53:50 +02:00
solokot 8f18bbe0ac Translated using Weblate (Russian)
Currently translated at 100.0% (118 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-05-20 11:53:50 +02:00
Altons 992e61b88a Translated using Weblate (French)
Currently translated at 97.4% (115 of 118 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-05-20 11:53:50 +02:00
solokot 47b92fb38c Translated using Weblate (Russian)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-05-20 11:53:50 +02:00
Heimen Stoffels b9963bb967 Translated using Weblate (Dutch)
Currently translated at 100.0% (287 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-05-20 11:53:50 +02:00
Carlo Cuoghi d642d57b85 Translated using Weblate (Italian)
Currently translated at 98.2% (282 of 287 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-05-20 11:53:50 +02:00
Sylvia van Os 9e0e8f6d7f Redo all screenshots with exact same Material colour 2023-05-18 22:54:38 +02:00
Sylvia van Os e486755e6a Merge pull request #1273 from CatimaLoyalty/feature/donationLink
Add donation link on non-Google installs
2023-05-18 21:44:48 +02:00
Sylvia van Os 1bb803ef0a Add donation link on non-Google installs
Inspired by https://git.zx2c4.com/wireguard-android/commit/?id=dc1860c74dd67e18a66fe9e243eeffa689bef043
2023-05-18 19:33:06 +02:00
Sylvia van Os f729f9758b Merge pull request #1299 from CatimaLoyalty/dependabot/gradle/org.robolectric-robolectric-4.10.3
Bump org.robolectric:robolectric from 4.10.2 to 4.10.3
2023-05-18 19:03:47 +02:00
Sylvia van Os abe3bc7d87 Merge pull request #1300 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-18 19:03:27 +02:00
Balázs Meskó 454bb6a1aa Translated using Weblate (Hungarian)
Currently translated at 7.6% (9 of 117 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hu/
2023-05-18 18:52:16 +02:00
Balázs Meskó 2d4d4e2309 Translated using Weblate (Hungarian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2023-05-18 18:52:16 +02:00
IllusiveMan196 e7c4010e8d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (117 of 117 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-05-18 18:52:16 +02:00
dependabot[bot] cc363e0c04 Bump org.robolectric:robolectric from 4.10.2 to 4.10.3
Bumps [org.robolectric:robolectric](https://github.com/robolectric/robolectric) from 4.10.2 to 4.10.3.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.10.2...robolectric-4.10.3)

---
updated-dependencies:
- dependency-name: org.robolectric:robolectric
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-18 02:58:51 +00:00
Sylvia van Os deacc4a69b Merge pull request #1298 from CatimaLoyalty/create-pull-request/patch-1684361188
Update Fastlane changelogs
2023-05-18 00:26:17 +02:00
TheLastProject ac6e6e0985 Update Fastlane changelogs 2023-05-17 22:06:27 +00:00
Sylvia van Os fd37a2708f Update CHANGELOG 2023-05-18 00:06:13 +02:00
Sylvia van Os 85ea314dc9 Merge pull request #1294 from pokegh0st/fix/preferences
Update Settings screen to use Material You design
2023-05-18 00:05:22 +02:00
Sylvia van Os 7fd5fe6ee0 Merge pull request #1290 from CatimaLoyalty/dependabot/gradle/org.robolectric-robolectric-4.10.2
Bump org.robolectric:robolectric from 4.10.1 to 4.10.2
2023-05-17 21:17:10 +02:00
Sylvia van Os 2c35ad3044 Merge pull request #1297 from CatimaLoyalty/create-pull-request/patch-1684350973
Update Fastlane changelogs
2023-05-17 21:16:47 +02:00
TheLastProject 210e305bae Update Fastlane changelogs 2023-05-17 19:16:13 +00:00
Sylvia van Os b48de921fc Redesign of home screen and view UI (#1296)
* Redesign of home screen and view UI

* Update screenshots and CHANGELOG

* Make spotbugs happy

* Fix double store name announcement
2023-05-17 21:15:56 +02:00
Sylvia van Os ebc2bfcbbb Merge pull request #1295 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-16 20:01:45 +02:00
Subhradeep Bera b1ec67928f Translated using Weblate (Bengali (India))
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-05-16 19:51:02 +02:00
pokegh0st 2beafe954b fix: Change dialog windows to Material 3 2023-05-16 18:52:07 +03:00
pokegh0st 25b6c4d8cc fix: Change switches to Material 3 2023-05-15 19:49:00 +03:00
Sylvia van Os a3f1b9c0b9 Merge pull request #1293 from CatimaLoyalty/create-pull-request/patch-1684044523
Update contributors
2023-05-14 09:45:50 +02:00
TheLastProject 14d5545c88 Update contributors 2023-05-14 06:08:42 +00:00
Sylvia van Os 0977b9d20a Merge pull request #1292 from CatimaLoyalty/create-pull-request/patch-1683439738
Update contributors
2023-05-07 10:38:07 +02:00
Sylvia van Os bad0990dfb Merge pull request #1291 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-05-07 10:37:50 +02:00
TheLastProject 98c34abd66 Update contributors 2023-05-07 06:08:58 +00:00
Clxff Heraldo b4d1463453 Translated using Weblate (Indonesian)
Currently translated at 94.0% (110 of 117 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-05-07 06:54:09 +02:00
dependabot[bot] 659b86e31a Bump org.robolectric:robolectric from 4.10.1 to 4.10.2
Bumps [org.robolectric:robolectric](https://github.com/robolectric/robolectric) from 4.10.1 to 4.10.2.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.10.1...robolectric-4.10.2)

---
updated-dependencies:
- dependency-name: org.robolectric:robolectric
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-05 02:58:25 +00:00
Sylvia van Os d63e269172 Merge pull request #1286 from CatimaLoyalty/dependabot/gradle/org.robolectric-robolectric-4.10.1
Bump org.robolectric:robolectric from 4.10 to 4.10.1
2023-05-03 18:17:01 +02:00
dependabot[bot] 77aa768c5c Bump org.robolectric:robolectric from 4.10 to 4.10.1
Bumps [org.robolectric:robolectric](https://github.com/robolectric/robolectric) from 4.10 to 4.10.1.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.10...robolectric-4.10.1)

---
updated-dependencies:
- dependency-name: org.robolectric:robolectric
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-03 02:58:28 +00:00
Sylvia van Os 8c74d4c2d0 Merge pull request #1283 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-04-30 13:44:34 +02:00
Sylvia van Os a6280108ec Delete invalid translation 2023-04-30 13:37:44 +02:00
Sylvia van Os 829630219f Merge pull request #1284 from CatimaLoyalty/create-pull-request/patch-1682832840
Update contributors
2023-04-30 11:11:14 +02:00
TheLastProject 22a736d7fd Update contributors 2023-04-30 05:34:00 +00:00
Gael Caraballo 4418492e7c Translated using Weblate (Catalan)
Currently translated at 19.3% (54 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ca/
2023-04-30 06:52:58 +02:00
Cap Amr Karam c21e12bbf0 Translated using Weblate (Arabic)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-04-30 06:52:58 +02:00
liva 9af05be128 Translated using Weblate (Latvian)
Currently translated at 98.2% (274 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lv/
2023-04-30 06:52:58 +02:00
Sylvia van Os e036443233 Merge pull request #1280 from CatimaLoyalty/create-pull-request/patch-1682233171
Update contributors
2023-04-23 11:01:43 +02:00
TheLastProject 7e605f284d Update contributors 2023-04-23 06:59:30 +00:00
Sylvia van Os e712b8e18d Update fastlane 2023-04-19 17:44:53 +02:00
Sylvia van Os 2ff137ee04 Merge pull request #1278 from CatimaLoyalty/simplify_tests
Move all import unit test strings to their own files
2023-04-18 18:42:15 +02:00
Sylvia van Os 3b45802a7f Move all import unit test strings to their own files
They should've been files from the start, because you import files, not
text string.
2023-04-17 20:48:27 +02:00
Sylvia van Os 0de4847f6a Merge pull request #1276 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-04-16 22:02:19 +02:00
Projjal Moitra 47e2566043 Translated using Weblate (Bengali (India))
Currently translated at 78.4% (219 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-04-16 20:49:48 +02:00
Sylvia van Os 18c17796b9 Merge pull request #1275 from CatimaLoyalty/fix/unitTestsTarget
Ensure unit tests use targetSdk instead of API 23 (Android 6)
2023-04-16 16:11:34 +02:00
Sylvia van Os 4b2b999653 Ensure unit tests use targetSdk instead of API 23 (Android 6) 2023-04-16 15:20:30 +02:00
Sylvia van Os 3b51121c9e Merge pull request #1274 from CatimaLoyalty/create-pull-request/patch-1681625007
Update contributors
2023-04-16 09:45:59 +02:00
TheLastProject 2fc9581643 Update contributors 2023-04-16 06:03:27 +00:00
Sylvia van Os 68f3f37e23 Merge pull request #1272 from CatimaLoyalty/fix/ci
Fix CI build
2023-04-14 21:10:04 +02:00
Sylvia van Os 38658d0aa7 Fix CI build 2023-04-14 21:02:53 +02:00
Sylvia van Os 339750e97c Update AGP to 8.0.0 2023-04-14 20:56:29 +02:00
Sylvia van Os 510995a5c5 Release Catima 2.22.1 2023-04-14 18:38:48 +02:00
Sylvia van Os a039d5de9e Merge pull request #1270 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-04-14 18:10:52 +02:00
Projjal Moitra df11bd8f69 Translated using Weblate (Bengali (India))
Currently translated at 73.8% (206 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-04-14 17:48:15 +02:00
Sylvia van Os 17c80573bd Merge pull request #1269 from CatimaLoyalty/dependabot/gradle/org.robolectric-robolectric-4.10
Bump org.robolectric:robolectric from 4.9.2 to 4.10
2023-04-12 17:36:52 +02:00
dependabot[bot] bc71c02e87 Bump org.robolectric:robolectric from 4.9.2 to 4.10
Bumps [org.robolectric:robolectric](https://github.com/robolectric/robolectric) from 4.9.2 to 4.10.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.9.2...robolectric-4.10)

---
updated-dependencies:
- dependency-name: org.robolectric:robolectric
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-12 02:59:34 +00:00
Sylvia van Os d892fe40ba Merge pull request #1268 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-04-11 18:08:38 +02:00
SC 06839f6ddb Translated using Weblate (Portuguese)
Currently translated at 100.0% (117 of 117 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2023-04-11 16:54:22 +02:00
Projjal Moitra ee57703ffc Translated using Weblate (Bengali (India))
Currently translated at 72.0% (201 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-04-11 16:54:22 +02:00
solokot e780f5fb87 Translated using Weblate (Russian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-04-11 16:54:22 +02:00
Sylvia van Os 6b9a0a0696 Merge pull request #1266 from CatimaLoyalty/deps/update_spotbugs
Update spotbugs
2023-04-10 22:38:01 +02:00
Sylvia van Os 6653a940ed Make spotbugs happy 2023-04-10 21:36:35 +02:00
Sylvia van Os 47821752f0 Merge pull request #1267 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-04-10 13:19:47 +02:00
Sylvia van Os bf05bd7e56 Fix lint 2023-04-10 13:12:10 +02:00
Projjal Moitra 2dd622b9c4 Translated using Weblate (Bengali (India))
Currently translated at 68.1% (190 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-04-10 09:53:13 +02:00
Sylvia van Os 643527a7fb Translated using Weblate (Bengali (India))
Currently translated at 68.1% (190 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-04-10 09:53:13 +02:00
Slávek Banko 0aae4c9c64 Translated using Weblate (Czech)
Currently translated at 100.0% (117 of 117 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-04-10 09:53:13 +02:00
solokot 14c5b756f7 Translated using Weblate (Russian)
Currently translated at 100.0% (117 of 117 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-04-10 09:53:13 +02:00
Sylvia van Os ded3c63ec5 Translated using Weblate (Bengali)
Currently translated at 31.1% (87 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn/
2023-04-10 09:53:13 +02:00
يوسف لطفي e3a22e425b Translated using Weblate (Arabic)
Currently translated at 98.5% (275 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-04-10 09:53:13 +02:00
Projjal Moitra 275d387f3c Translated using Weblate (Bengali (India))
Currently translated at 62.7% (175 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2023-04-10 09:53:13 +02:00
Mobashir Raihan fbbad75c15 Translated using Weblate (Bengali)
Currently translated at 31.5% (88 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn/
2023-04-10 09:53:13 +02:00
Sylvia van Os a55e9da067 Merge pull request #1265 from CatimaLoyalty/create-pull-request/patch-1681019014
Update contributors
2023-04-09 08:52:12 +02:00
TheLastProject a5116395c8 Update contributors 2023-04-09 05:43:33 +00:00
dependabot[bot] 5cf41ed664 Bump com.github.spotbugs from 4.7.5 to 5.0.14
Bumps com.github.spotbugs from 4.7.5 to 5.0.14.

---
updated-dependencies:
- dependency-name: com.github.spotbugs
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-05 16:44:16 +00:00
Sylvia van Os bbde3ec3b8 Merge pull request #1260 from CatimaLoyalty/create-pull-request/patch-1680713019
Update Fastlane changelogs
2023-04-05 18:43:53 +02:00
TheLastProject db56d56e3b Update Fastlane changelogs 2023-04-05 16:43:39 +00:00
Sylvia van Os f4c0628366 Merge pull request #1259 from CatimaLoyalty/library_updates
Update all libraries
2023-04-05 18:43:20 +02:00
Sylvia van Os 1e6641a884 Disable MissingQuantity due to Weblate bug
See https://github.com/WeblateOrg/weblate/issues/7520
2023-04-04 22:57:54 +02:00
Sylvia van Os b9bd3f5967 Update all libraries 2023-04-04 22:22:51 +02:00
Sylvia van Os 28eaac0c67 Merge pull request #1257 from CatimaLoyalty/create-pull-request/patch-1680414497
Update contributors
2023-04-02 09:59:58 +02:00
TheLastProject 5690ca03e7 Update contributors 2023-04-02 05:48:17 +00:00
Sylvia van Os 71f7b21112 Merge pull request #1256 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-31 19:54:27 +02:00
Slávek Banko f9ece83f2b Translated using Weblate (Czech)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-03-30 17:42:01 +02:00
Sylvia van Os 3bab0f43eb Merge pull request #1255 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-26 14:53:46 +02:00
SC 941fa929dd Translated using Weblate (Portuguese)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2023-03-26 14:42:11 +02:00
Szia Tomi 46846d2448 Translated using Weblate (Hungarian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2023-03-26 14:42:11 +02:00
Sylvia van Os 7b7c1b88b9 Merge pull request #1254 from CatimaLoyalty/create-pull-request/patch-1679813344
Update contributors
2023-03-26 12:33:46 +02:00
TheLastProject 0926bb71e1 Update contributors 2023-03-26 06:49:04 +00:00
Sylvia van Os cfc4ce7c3c Merge pull request #1251 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-20 12:50:12 +01:00
109247019824 1f217dd846 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-03-20 01:05:23 +01:00
Michael Moroni 6c74b95e90 Translated using Weblate (Italian)
Currently translated at 62.0% (72 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2023-03-20 01:05:23 +01:00
Denis Shilin 9fca77d561 Translated using Weblate (Russian)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-03-20 01:05:23 +01:00
Altons 1f0873aab4 Translated using Weblate (French)
Currently translated at 98.2% (114 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-03-20 01:05:23 +01:00
Sylvia van Os ca3a09740a Merge pull request #1250 from CatimaLoyalty/create-pull-request/patch-1679204700
Update contributors
2023-03-19 11:04:38 +01:00
TheLastProject c104de839e Update contributors 2023-03-19 05:45:00 +00:00
Sylvia van Os 0f4380c1e2 Merge pull request #1249 from CatimaLoyalty/fix/stocard_export_name
Fix Stocard export filenames
2023-03-18 17:59:46 +01:00
Sylvia van Os 64e3b047d9 Fix Stocard export filenames
Stocard renamed their exports to no longer contain sync, only your user
id.
2023-03-18 17:48:53 +01:00
Sylvia van Os 729639e0e6 Release Catima 2.22.0 2023-03-18 17:01:58 +01:00
Sylvia van Os 3e79147673 Merge pull request #1247 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-18 15:39:46 +01:00
Tom Sawyer 59a656c422 Translated using Weblate (Swedish)
Currently translated at 2.5% (3 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sv/
2023-03-18 15:34:29 +01:00
Altons bdf8994fed Translated using Weblate (French)
Currently translated at 97.4% (113 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-03-18 15:34:29 +01:00
Sylvia van Os 3aa595083b Show new Valid from feature in screenshots 2023-03-17 23:33:41 +01:00
Sylvia van Os 37f1183208 Merge pull request #1246 from CatimaLoyalty/create-pull-request/patch-1679091521
Update Fastlane changelogs
2023-03-17 23:19:21 +01:00
TheLastProject 839496aa04 Update Fastlane changelogs 2023-03-17 22:18:40 +00:00
Sylvia van Os 4a7a6b109c Merge pull request #1245 from CatimaLoyalty/fix/stocard_import
Fix Stocard import
2023-03-17 23:18:22 +01:00
Sylvia van Os 2b2d5ca7cf Fix Stocard import 2023-03-17 23:09:00 +01:00
Sylvia van Os 463af746fa Merge pull request #1244 from CatimaLoyalty/create-pull-request/patch-1678989883
Update Fastlane changelogs
2023-03-16 19:05:30 +01:00
TheLastProject d75b79fce4 Update Fastlane changelogs 2023-03-16 18:04:43 +00:00
Sylvia van Os 2ec29da6b1 Merge pull request #1243 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-16 19:04:26 +01:00
ahmed-awad26 e80bebe887 Translated using Weblate (Arabic)
Currently translated at 98.2% (274 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2023-03-16 13:38:03 +01:00
Denis Shilin 1555b3b24b Translated using Weblate (Russian)
Currently translated at 94.8% (110 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-03-16 13:38:03 +01:00
Allan Nordhøy 12f42f86a5 Translated using Weblate (English)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/en/
2023-03-16 13:38:03 +01:00
Sylvia van Os a74e17db10 Merge pull request #1241 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-13 21:39:53 +01:00
Denis Shilin 96335d3ee8 Translated using Weblate (Russian)
Currently translated at 93.9% (109 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-03-13 15:42:46 +01:00
Patrik fb3d945f51 Translated using Weblate (Slovak)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2023-03-13 15:42:46 +01:00
Sylvia van Os 843ffbb87e Merge pull request #1240 from CatimaLoyalty/create-pull-request/patch-1678623157
Update Fastlane changelogs
2023-03-12 13:13:35 +01:00
TheLastProject 99e19321f0 Update Fastlane changelogs 2023-03-12 12:12:36 +00:00
Sylvia van Os 4e5a90eb93 Fix typo in old CHANGELOG 2023-03-12 13:12:21 +01:00
Sylvia van Os 9745ea671e Merge pull request #1238 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-12 13:10:38 +01:00
Denis Shilin 94a63d6e0c Translated using Weblate (Russian)
Currently translated at 81.0% (94 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-03-12 13:00:09 +01:00
Sylvia van Os 725ca3b9ca Merge pull request #1236 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-12 12:57:35 +01:00
Denis Shilin 46a2164143 Translated using Weblate (Russian)
Currently translated at 76.7% (89 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-03-12 12:40:30 +01:00
Sylvia van Os 5304be6f54 Translated using Weblate (English)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/en/
2023-03-12 12:40:30 +01:00
Sylvia van Os 8321e796f5 Merge pull request #1235 from CatimaLoyalty/create-pull-request/patch-1678600178
Update contributors
2023-03-12 12:37:46 +01:00
TheLastProject c1f82e90be Update contributors 2023-03-12 05:49:38 +00:00
Sylvia van Os 758f265638 Merge pull request #1234 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-09 17:57:17 +01:00
Nosnahc 590020bb6f Translated using Weblate (French)
Currently translated at 98.2% (114 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2023-03-09 10:42:20 +01:00
Sylvia van Os f18c2a2d0c Merge pull request #1231 from CatimaLoyalty/create-pull-request/patch-1677996975
Update contributors
2023-03-05 12:55:58 +01:00
TheLastProject 3a17ee83e0 Update contributors 2023-03-05 06:16:15 +00:00
Sylvia van Os f36d4aebb6 Merge pull request #1230 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-04 14:23:47 +01:00
Tian Jiale 71cb1cace4 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-03-04 13:39:54 +01:00
lucafont2 1e4e035281 Translated using Weblate (Italian)
Currently translated at 62.0% (72 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2023-03-04 13:39:54 +01:00
Sylvia van Os 7da4eb6587 Merge pull request #1229 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-03 13:57:26 +01:00
Tian Jiale d454864fa7 Translated using Weblate (Chinese (Simplified))
Currently translated at 98.2% (274 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-03-03 13:36:36 +01:00
Sylvia van Os f5e6d7be71 Merge pull request #1227 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-03-02 22:21:29 +01:00
Sylvia van Os 967a17242d Fix lint 2023-03-02 14:02:22 +01:00
Luna Jernberg 6c5dd7a713 Translated using Weblate (Swedish)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2023-03-02 09:37:09 +01:00
Alexander 139b144cb3 Translated using Weblate (Icelandic)
Currently translated at 42.2% (118 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/is/
2023-03-01 03:39:16 +01:00
Sylvia van Os 5deacf7ecc Merge pull request #1224 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-02-28 21:32:38 +01:00
Jesse Davids 6e49aea713 Translated using Weblate (Dutch)
Currently translated at 11.2% (13 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nl/
2023-02-26 06:40:23 +01:00
Jesse Davids 68257ce3ad Translated using Weblate (Dutch)
Currently translated at 6.0% (7 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nl/
2023-02-25 04:40:19 +01:00
Sirius Chan 149a1caeff Translated using Weblate (Chinese (Traditional))
Currently translated at 7.7% (9 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hant/
2023-02-25 04:40:19 +01:00
Sirius Chan 07e5788cb2 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2023-02-25 04:40:19 +01:00
Sylvia van Os c072e2e70d Merge pull request #1225 from CatimaLoyalty/dependabot/gradle/net.lingala.zip4j-zip4j-2.11.5
Bump net.lingala.zip4j:zip4j from 2.11.4 to 2.11.5
2023-02-23 15:13:43 +01:00
dependabot[bot] 0701b9b3de Bump net.lingala.zip4j:zip4j from 2.11.4 to 2.11.5
Bumps [net.lingala.zip4j:zip4j](https://github.com/srikanth-lingala/zip4j) from 2.11.4 to 2.11.5.
- [Release notes](https://github.com/srikanth-lingala/zip4j/releases)
- [Commits](https://github.com/srikanth-lingala/zip4j/compare/v2.11.4...v2.11.5)

---
updated-dependencies:
- dependency-name: net.lingala.zip4j:zip4j
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-23 02:16:17 +00:00
Sylvia van Os f84242d97c Merge pull request #1223 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-02-15 21:10:51 +01:00
IllusiveMan196 79f35ed715 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-02-15 20:40:26 +01:00
Sylvia van Os eff4f3f8df Merge pull request #1221 from CatimaLoyalty/create-pull-request/patch-1676182226
Update contributors
2023-02-12 09:32:03 +01:00
TheLastProject ee405f670d Update contributors 2023-02-12 06:10:25 +00:00
Sylvia van Os 7dcb9b336d Merge pull request #1219 from CatimaLoyalty/dependabot/gradle/net.lingala.zip4j-zip4j-2.11.4
Bump net.lingala.zip4j:zip4j from 2.11.3 to 2.11.4
2023-02-11 18:35:03 +01:00
Sylvia van Os 923e6dc062 Merge pull request #1220 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-02-11 18:13:10 +01:00
Allan Nordhøy 2ea04e8715 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2023-02-11 06:57:05 +01:00
SC f264941ae4 Translated using Weblate (Portuguese)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2023-02-11 06:57:05 +01:00
SC e6ef5c9bb2 Translated using Weblate (Portuguese)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2023-02-11 06:57:05 +01:00
HudobniVolk 024cc2d50e Translated using Weblate (Slovenian)
Currently translated at 27.5% (32 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sl/
2023-02-11 06:57:05 +01:00
Brage Nesteby Reitan 48b62f6aea Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2023-02-11 06:57:05 +01:00
dependabot[bot] ff07fe71cc Bump net.lingala.zip4j:zip4j from 2.11.3 to 2.11.4
Bumps [net.lingala.zip4j:zip4j](https://github.com/srikanth-lingala/zip4j) from 2.11.3 to 2.11.4.
- [Release notes](https://github.com/srikanth-lingala/zip4j/releases)
- [Commits](https://github.com/srikanth-lingala/zip4j/compare/v2.11.3...v2.11.4)

---
updated-dependencies:
- dependency-name: net.lingala.zip4j:zip4j
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-10 02:58:35 +00:00
Sylvia van Os 402cf57c29 Add Catalan to supported languages 2023-02-09 23:27:56 +01:00
Sylvia van Os e19ac0d0c2 Merge pull request #1218 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-02-09 20:16:40 +01:00
Francesc Bassas i Bullich fc5d4a6435 Translated using Weblate (Catalan)
Currently translated at 18.9% (53 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ca/
2023-02-09 19:40:22 +01:00
gittyboy-cell 50754a3430 Translated using Weblate (Indonesian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2023-02-09 19:40:22 +01:00
HudobniVolk 0375f6dbe5 Translated using Weblate (Slovenian)
Currently translated at 26.7% (31 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sl/
2023-02-09 19:40:22 +01:00
HudobniVolk deb808ffb6 Translated using Weblate (Slovenian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2023-02-09 19:40:22 +01:00
Sylvia van Os 166c1e7bc6 Merge pull request #1216 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-02-07 22:44:27 +01:00
Hamustra Scans bfa19d0166 Translated using Weblate (Korean)
Currently translated at 37.9% (106 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ko/
2023-02-07 22:22:31 +01:00
sal0max f92805ec64 Translated using Weblate (German)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2023-02-07 22:22:31 +01:00
sal0max 73e6e9f34a Translated using Weblate (German)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-02-07 22:22:31 +01:00
Francesc Bassas i Bullich 6a76681412 Added translation using Weblate (Catalan) 2023-02-07 22:22:31 +01:00
Sylvia van Os f05a5dde1e Merge pull request #1213 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-02-06 19:41:51 +01:00
gnu-ewm 4a93ba3478 Translated using Weblate (Polish)
Currently translated at 39.6% (46 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pl/
2023-02-06 17:39:42 +01:00
Michael Moroni af43138ae9 Translated using Weblate (Italian)
Currently translated at 58.6% (68 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2023-02-06 17:39:42 +01:00
Günter Neiß dcd6e4b9a9 Translated using Weblate (German)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2023-02-06 17:39:42 +01:00
Dan 0ce2395605 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-02-06 17:39:42 +01:00
solokot 89dbc9e9aa Translated using Weblate (Russian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-02-06 17:39:42 +01:00
gnu-ewm 788a8f0efe Translated using Weblate (Polish)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-02-06 17:39:42 +01:00
J. Lavoie d0c9ae2a4a Translated using Weblate (Italian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-02-06 17:39:42 +01:00
J. Lavoie c000a8129c Translated using Weblate (French)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-02-06 17:39:42 +01:00
J. Lavoie bfb4fdb61c Translated using Weblate (German)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-02-06 17:39:42 +01:00
Sylvia van Os 1929401d3e Merge pull request #1210 from CatimaLoyalty/create-pull-request/patch-1675576485
Update contributors
2023-02-05 12:06:41 +01:00
TheLastProject eef13a1a91 Update contributors 2023-02-05 05:54:45 +00:00
Sylvia van Os 64f340d798 Merge pull request #1208 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-02-05 01:01:09 +01:00
Oğuz Ersen f12422fc07 Translated using Weblate (Turkish)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2023-02-04 22:08:08 +01:00
109247019824 d78315ef12 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-02-04 22:08:08 +01:00
Jorma Karvonen af8c3eeb54 Translated using Weblate (Finnish)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2023-02-04 22:08:08 +01:00
Slávek Banko 16e4205028 Translated using Weblate (Czech)
Currently translated at 100.0% (116 of 116 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-02-04 22:08:08 +01:00
Heimen Stoffels 399aa767d2 Translated using Weblate (Dutch)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-02-04 22:08:08 +01:00
Allan Nordhøy 96c735cf80 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.7% (270 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2023-02-04 22:08:07 +01:00
gallegonovato 50a8395ec6 Translated using Weblate (Spanish)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2023-02-04 22:08:07 +01:00
Slávek Banko c720ca1085 Translated using Weblate (Czech)
Currently translated at 100.0% (279 of 279 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-02-04 22:08:07 +01:00
Sylvia van Os d82088f66a Merge pull request #1207 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-02-04 15:51:09 +01:00
Jiri Grönroos 1fce3e17f6 Translated using Weblate (Finnish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2023-02-04 15:35:30 +01:00
Evgeniy Khramov 569db96f81 Translated using Weblate (Russian)
Currently translated at 35.6% (41 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2023-02-04 15:35:30 +01:00
Salem Malus b7cb1dffc1 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2023-02-04 15:35:30 +01:00
Sylvia van Os e17fc66d35 Update dependencies (#1205)
* Update appcompat to 1.6.0

* Update constraintlayout to 2.1.4

* Update exifinterface to 1.3.5

* Update test:core to 1.5.0
2023-02-03 22:56:23 +01:00
Sylvia van Os 8dac7ae9d1 Merge pull request #1203 from CatimaLoyalty/create-pull-request/patch-1675277210
Update Fastlane changelogs
2023-02-01 19:48:43 +01:00
TheLastProject 28a0417fa8 Update Fastlane changelogs 2023-02-01 18:46:49 +00:00
Sylvia van Os 58d4bd7f47 Update CHANGELOG 2023-02-01 19:46:31 +01:00
Sylvia van Os 1779aef162 Merge pull request #1083 from vanogrid/feature/validFromField
Add Valid From field
2023-02-01 19:29:38 +01:00
Sylvia van Os 557ec68428 Fix info button being hidden when only validFrom is set 2023-02-01 19:22:22 +01:00
Sylvia van Os 96a7c8ee36 String consistency improvement 2023-02-01 19:22:22 +01:00
Alexander Ivanov 3a9b92231e Set min/max date in the DatePickerDialog when 'valid from' or 'expiry' dates are set
Signed-off-by: Alexander Ivanov <vanogrid@gmail.com>
2023-02-01 19:22:22 +01:00
Alexander Ivanov f1753ea943 Add Valid From field
Signed-off-by: Alexander Ivanov <vanogrid@gmail.com>
2023-02-01 19:22:20 +01:00
Sylvia van Os 36ab78ec6e Merge pull request #1202 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-30 17:55:11 +01:00
Cliff Heraldo 8a3a782558 Translated using Weblate (Indonesian)
Currently translated at 20.0% (23 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2023-01-30 16:41:04 +01:00
Cliff Heraldo 2c5606bf0a Translated using Weblate (Indonesian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2023-01-30 16:41:04 +01:00
gnu-ewm 5eb36aad5b Translated using Weblate (Polish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-01-30 16:41:04 +01:00
Sylvia van Os b028d32e2c Merge pull request #1200 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-29 13:30:29 +01:00
Sylvia van Os dfefdda9f9 Translated using Weblate (Romanian)
Currently translated at 1.7% (2 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ro/
2023-01-29 13:09:25 +01:00
Sylvia van Os bc1cc68f27 Update Fastlane 2023-01-29 13:05:11 +01:00
Sylvia van Os 386a5f75b0 Merge pull request #1198 from CatimaLoyalty/create-pull-request/patch-1674969594
Update contributors
2023-01-29 12:04:10 +01:00
Sylvia van Os d30a9fd1e5 Merge pull request #1197 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-29 12:02:46 +01:00
TheLastProject 0c8e5576b8 Update contributors 2023-01-29 05:19:54 +00:00
Cliff Heraldo 93e40c08aa Translated using Weblate (Indonesian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2023-01-29 02:19:44 +01:00
HudobniVolk 24eb1e9627 Translated using Weblate (Slovenian)
Currently translated at 25.2% (29 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sl/
2023-01-29 00:54:59 +01:00
Dan 19e6b8bea9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (115 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-01-29 00:54:59 +01:00
HudobniVolk 87f844943e Translated using Weblate (Slovenian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2023-01-29 00:54:59 +01:00
J. Lavoie 718738ff78 Translated using Weblate (French)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2023-01-29 00:54:59 +01:00
J. Lavoie d7bb019068 Translated using Weblate (German)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2023-01-29 00:54:59 +01:00
Sylvia van Os f925404ab7 Revert "Fix filename"
This reverts commit 38495546e0.
2023-01-27 21:50:34 +01:00
Sylvia van Os 38495546e0 Fix filename 2023-01-27 19:19:26 +01:00
Sylvia van Os 36e7ea5b20 Release Catima 2.21.2 2023-01-27 18:36:24 +01:00
Sylvia van Os 85d53ae3c7 Merge pull request #1194 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-27 18:07:26 +01:00
Sylvia van Os e9b6b5682e Translated using Weblate (Dutch)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-01-27 18:01:46 +01:00
SC 0abc583d10 Translated using Weblate (Portuguese)
Currently translated at 100.0% (115 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2023-01-27 17:56:35 +01:00
SC 8c91d30b4c Translated using Weblate (Portuguese)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2023-01-27 17:56:31 +01:00
Oğuz Ersen 76e8715ab2 Translated using Weblate (Turkish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2023-01-27 17:56:31 +01:00
Quentin PAGÈS f5f2edca75 Translated using Weblate (Occitan)
Currently translated at 0.8% (1 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/oc/
2023-01-27 17:56:31 +01:00
109247019824 e648e22ecc Translated using Weblate (Bulgarian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2023-01-27 17:56:31 +01:00
HudobniVolk 02b020e9e5 Translated using Weblate (Slovenian)
Currently translated at 21.7% (25 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sl/
2023-01-27 17:56:31 +01:00
Slávek Banko e7dc3cd511 Translated using Weblate (Czech)
Currently translated at 100.0% (115 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2023-01-27 17:56:30 +01:00
Michael Moroni eb3ac53e46 Translated using Weblate (Italian)
Currently translated at 56.5% (65 of 115 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2023-01-27 17:56:26 +01:00
Dan dd683b4a8c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-01-27 17:56:24 +01:00
solokot e90ba5d2db Translated using Weblate (Russian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2023-01-27 17:56:24 +01:00
Heimen Stoffels 07cff7eac4 Translated using Weblate (Dutch)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2023-01-27 17:56:24 +01:00
Michael Moroni 3eea18fc82 Translated using Weblate (Italian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-01-27 17:56:23 +01:00
gallegonovato 5d3ceb6d49 Translated using Weblate (Spanish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2023-01-27 17:56:23 +01:00
Slávek Banko 3dc7a25d88 Translated using Weblate (Czech)
Currently translated at 100.0% (275 of 275 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2023-01-27 17:56:23 +01:00
Sylvia van Os 95e02d1646 Merge pull request #1191 from CatimaLoyalty/dependabot/gradle/net.lingala.zip4j-zip4j-2.11.3
Bump zip4j from 2.11.2 to 2.11.3
2023-01-26 19:15:58 +01:00
Sylvia van Os 81ecf8ba92 Merge pull request #1193 from CatimaLoyalty/security/gradle_wrapper_verification
Add Gradle wrapper verification
2023-01-26 19:10:13 +01:00
Sylvia van Os bf0e1a2e77 Add Gradle wrapper verification 2023-01-26 19:02:04 +01:00
Sylvia van Os 4d1c9244fd Merge pull request #1192 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-26 18:48:57 +01:00
HudobniVolk 1f1e523100 Translated using Weblate (Slovenian)
Currently translated at 20.1% (23 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sl/
2023-01-26 17:55:06 +01:00
HudobniVolk cb32cf9e52 Translated using Weblate (Slovenian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2023-01-26 17:55:06 +01:00
dependabot[bot] af812d8cda Bump zip4j from 2.11.2 to 2.11.3
Bumps [zip4j](https://github.com/srikanth-lingala/zip4j) from 2.11.2 to 2.11.3.
- [Release notes](https://github.com/srikanth-lingala/zip4j/releases)
- [Commits](https://github.com/srikanth-lingala/zip4j/compare/v2.11.2...v2.11.3)

---
updated-dependencies:
- dependency-name: net.lingala.zip4j:zip4j
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-26 02:03:45 +00:00
Sylvia van Os c8a7addc52 Merge pull request #1190 from CatimaLoyalty/create-pull-request/patch-1674683901
Update Fastlane changelogs
2023-01-25 22:58:43 +01:00
TheLastProject 3e64d7c5ad Update Fastlane changelogs 2023-01-25 21:58:21 +00:00
Sylvia van Os 277462a939 Update CHANGELOG 2023-01-25 22:58:03 +01:00
Sylvia van Os 24623d5c58 Merge pull request #1189 from CatimaLoyalty/sdk/33
Update targetSdk to 33
2023-01-25 22:57:34 +01:00
Sylvia van Os 4b25b7ad39 Update targetSdk to 33 2023-01-25 19:59:08 +01:00
Sylvia van Os 4016d5499b Merge pull request #1188 from CatimaLoyalty/sdk/32
Update targetSdk to 32
2023-01-25 19:40:53 +01:00
Sylvia van Os d8b96a8c5f Update targetSdk to 32 2023-01-25 19:36:09 +01:00
Sylvia van Os 614753303f Fix crash when permissionRequestResult gets cancelled 2023-01-25 18:30:47 +01:00
Sylvia van Os 50a344b97f Merge branch 'main' of github.com:TheLastProject/loyalty-card-locker 2023-01-25 18:23:54 +01:00
Sylvia van Os 2cd6da6ffc Fix crash on invalid import URI 2023-01-25 18:13:58 +01:00
Sylvia van Os c03fba133f Merge pull request #1187 from CatimaLoyalty/create-pull-request/patch-1674662809
Update Fastlane changelogs
2023-01-25 17:32:55 +01:00
TheLastProject f3cba588f6 Update Fastlane changelogs 2023-01-25 16:06:48 +00:00
Sylvia van Os ad364ad0ac Merge branch 'main' of github.com:TheLastProject/loyalty-card-locker 2023-01-25 17:06:19 +01:00
Sylvia van Os f4cff85d93 Document permission change 2023-01-25 17:06:08 +01:00
Sylvia van Os cbc86ff131 Merge pull request #1185 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-24 23:31:38 +01:00
Sylvia van Os 5f733474a9 Merge pull request #1186 from CatimaLoyalty/fix/permissionRefactor
Refactor permission code
2023-01-24 23:28:38 +01:00
Sylvia van Os 89a13cecf5 Create extra result function to work around onPermissionResult not existing on Android 5 2023-01-24 23:14:57 +01:00
Sylvia van Os fd2400eaf5 Refactor permission code
- Remove write permission (was never needed)
- Only use read permission for Android 5 and 6
- Simplify logic by mocking a valid permission result if permission
  already granted
2023-01-24 20:44:17 +01:00
Sylvia van Os 9598f2f4ff Translated using Weblate (Slovenian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2023-01-24 07:53:22 +01:00
IllusiveMan196 acca53787c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (114 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2023-01-23 02:12:44 +01:00
HudobniVolk 060e360344 Translated using Weblate (Slovenian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2023-01-23 02:12:44 +01:00
Sylvia van Os 9ef014e05c Fix main rename breaking github scripts 2023-01-22 13:12:25 +01:00
Sylvia van Os 4cb27d3bd5 Merge pull request #1182 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-20 17:00:24 +01:00
stone wow 95e21cc112 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2023-01-20 16:09:32 +01:00
Sylvia van Os d5f915a290 Merge pull request #1181 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-18 22:03:04 +01:00
HudobniVolk 42e89bb5cc Translated using Weblate (Slovenian)
Currently translated at 19.2% (22 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sl/
2023-01-18 21:51:11 +01:00
Sylvia van Os 048fb48300 Fix reproducible build script 2023-01-16 20:32:42 +01:00
Sylvia van Os b1c82dbae0 Merge pull request #1159 from CatimaLoyalty/feature/rb
Add script to build reproducibly
2023-01-16 19:48:56 +01:00
Sylvia van Os ea8c6f96f7 Merge pull request #1180 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-16 19:05:26 +01:00
HudobniVolk 201ec78694 Translated using Weblate (Slovenian)
Currently translated at 7.0% (8 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sl/
2023-01-16 18:53:07 +01:00
Dan 05a03455c1 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2023-01-16 18:53:07 +01:00
HudobniVolk 63f4cbb8ca Translated using Weblate (Slovenian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2023-01-16 18:53:07 +01:00
Sylvia van Os a444607476 Merge pull request #1178 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-14 23:58:58 +01:00
Giovanni Donisi 89102ad0bf Translated using Weblate (Italian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2023-01-14 23:12:40 +01:00
Sylvia van Os d2623b8690 Merge pull request #1177 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-13 23:08:03 +01:00
Jiri Grönroos 80ddd48184 Translated using Weblate (Finnish)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2023-01-13 18:50:22 +01:00
Sylvia van Os 410a619a70 Merge pull request #1175 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-08 12:04:45 +01:00
Jiri Grönroos 1771f42860 Translated using Weblate (Finnish)
Currently translated at 95.9% (263 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2023-01-08 11:51:01 +01:00
Sylvia van Os 1e7af7ab4e Merge pull request #1174 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2023-01-06 13:59:27 +01:00
Piotr Strebski f4c5af04e3 Translated using Weblate (Polish)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2023-01-06 13:51:24 +01:00
Sylvia van Os 5bcd2cdc32 Merge pull request #1171 from CatimaLoyalty/dependabot/gradle/org.robolectric-robolectric-4.9.2
Bump robolectric from 4.9.1 to 4.9.2
2022-12-28 06:48:50 +00:00
dependabot[bot] c69a5ae4d2 Bump robolectric from 4.9.1 to 4.9.2
Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.9.1 to 4.9.2.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.9.1...robolectric-4.9.2)

---
updated-dependencies:
- dependency-name: org.robolectric:robolectric
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-28 02:04:26 +00:00
Sylvia van Os 6bd750a60b Add script to build reproducibly 2022-12-22 22:57:55 +01:00
Sylvia van Os 8d77cc3565 Merge pull request #1169 from CatimaLoyalty/dependabot/gradle/org.robolectric-robolectric-4.9.1
Bump robolectric from 4.9 to 4.9.1
2022-12-21 12:25:35 +00:00
Sylvia van Os 7a99e0056d Merge pull request #1170 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-20 22:14:48 +00:00
Shailendra Maurya 03e07bc48d Translated using Weblate (Hindi)
Currently translated at 61.6% (169 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hi/
2022-12-20 22:43:29 +01:00
dependabot[bot] 460d6c2b71 Bump robolectric from 4.9 to 4.9.1
Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.9 to 4.9.1.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.9...robolectric-4.9.1)

---
updated-dependencies:
- dependency-name: org.robolectric:robolectric
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-20 02:04:38 +00:00
Sylvia van Os 9f946094db Merge pull request #1168 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-18 21:06:09 +00:00
wmilan 17 4e92f82176 Translated using Weblate (Hungarian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2022-12-18 21:48:04 +01:00
Sylvia van Os 7b905ac120 Translated using Weblate (English)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2022-12-17 11:46:57 +01:00
Tomasz Cukier 55c5ec929c Translated using Weblate (English)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2022-12-17 11:46:57 +01:00
Sylvia van Os 5441231f03 Merge pull request #1165 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-14 22:55:09 +01:00
ssantos 1818d24bc0 Translated using Weblate (Portuguese)
Currently translated at 100.0% (114 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2022-12-14 22:50:15 +01:00
Sylvia van Os ca88c070c3 Merge pull request #1163 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-13 23:19:14 +01:00
gallegonovato 1be387c4ec Translated using Weblate (Spanish)
Currently translated at 11.4% (13 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-12-13 20:50:09 +01:00
Sylvia van Os fa3a956d69 Merge pull request #1162 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-12 17:07:13 +01:00
gallegonovato 8fd244e3a3 Translated using Weblate (Spanish)
Currently translated at 8.7% (10 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-12-12 15:51:47 +01:00
Sylvia van Os a0e2fe11dd Merge pull request #1160 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-11 15:50:06 +01:00
gallegonovato 893f34e72a Translated using Weblate (Spanish)
Currently translated at 7.0% (8 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-12-11 14:49:57 +01:00
Sylvia van Os cf13a9fc60 Merge pull request #1158 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-09 22:00:23 +01:00
IllusiveMan196 c6e6d96313 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (114 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-12-09 21:50:03 +01:00
Sylvia van Os 20ed9cac88 Update Google Play badge
See https://github.com/cvzi/play
2022-12-06 19:34:51 +01:00
Sylvia van Os ae6bd937a9 Move to main 2022-12-06 19:33:04 +01:00
Sylvia van Os e4b69e5cc5 Release Catima 2.21.1 2022-12-06 19:13:02 +01:00
Sylvia van Os 5b1062b8d1 Merge pull request #1155 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-06 18:41:27 +01:00
Slávek Banko e06009852e Translated using Weblate (Czech)
Currently translated at 100.0% (114 of 114 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-12-06 18:35:01 +01:00
Sylvia van Os 50268f6bd1 Merge pull request #1154 from CatimaLoyalty/create-pull-request/patch-1670271647
Update Fastlane changelogs
2022-12-05 21:21:13 +01:00
TheLastProject a85e28d46d Update Fastlane changelogs 2022-12-05 20:20:47 +00:00
Sylvia van Os 78b6be911f Merge pull request #1153 from CatimaLoyalty/fix/localeQuickSpend
Fix/locale quick spend
2022-12-05 21:20:32 +01:00
Sylvia van Os bb80478650 Update CHANGELOG 2022-12-05 21:14:07 +01:00
Sylvia van Os e0c06cc480 Fix locale separator in quick spend dialog 2022-12-05 21:14:00 +01:00
Sylvia van Os b8a508649c Merge pull request #1151 from CatimaLoyalty/create-pull-request/patch-1670133932
Update contributors
2022-12-04 09:38:51 +01:00
TheLastProject a8ce37d936 Update contributors 2022-12-04 06:05:31 +00:00
Sylvia van Os 43015abbad Merge pull request #1147 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-12-02 08:09:44 +01:00
Mario M. Viscovich 47c8dff52d Translated using Weblate (Croatian)
Currently translated at 38.3% (105 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hr/
2022-12-02 03:47:15 +01:00
Sylvia van Os 436cf7a068 Merge pull request #1146 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-29 20:53:31 +01:00
IllusiveMan196 31cc3cd5d0 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-11-29 20:47:20 +01:00
gallegonovato 3c11c2ef1e Translated using Weblate (Spanish)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2022-11-29 20:47:15 +01:00
Sylvia van Os fac70f0210 Merge pull request #1145 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-28 07:41:24 +01:00
IllusiveMan196 6e99a29312 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-11-28 02:49:19 +01:00
IllusiveMan196 5b67ecf157 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2022-11-28 02:49:19 +01:00
Sylvia van Os 312470cf20 Merge pull request #1144 from CatimaLoyalty/create-pull-request/patch-1669529773
Update contributors
2022-11-27 09:34:00 +01:00
TheLastProject 4371f46ff8 Update contributors 2022-11-27 06:16:12 +00:00
Sylvia van Os 5468415b04 Merge pull request #1143 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-26 16:40:26 +01:00
CherryMonster222 6a68ad5d19 Translated using Weblate (Arabic)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2022-11-26 15:48:38 +01:00
IllusiveMan196 7576505044 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-11-26 15:48:38 +01:00
Sylvia van Os b34a43902a Merge pull request #1141 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-24 18:34:31 +01:00
안재범 d3524a50a3 Translated using Weblate (Korean)
Currently translated at 38.6% (106 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ko/
2022-11-24 16:46:55 +01:00
Sylvia van Os 6508a6d5f7 Merge pull request #1116 from pfaffenrodt/feature/pick-image-file
Add support to pick image from content provider
2022-11-22 19:04:48 +01:00
Sylvia van Os 49a6cf8ae3 Merge pull request #1140 from CatimaLoyalty/create-pull-request/patch-1668925172
Update contributors
2022-11-20 10:21:12 +01:00
TheLastProject b4238e0072 Update contributors 2022-11-20 06:19:31 +00:00
Sylvia van Os 374170bf05 Merge pull request #1139 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-19 23:17:41 +01:00
Jacek ab11345c3d Translated using Weblate (Polish)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-11-19 21:47:02 +01:00
Sylvia van Os 10498ce1a4 Prevent NullPointerException in onBackPressed
This crash seems to somehow only happen on Huawei and Xiaomi devices.
While fairly rare, it is the most common Catima crash currently logged
on Google Play Console (8 crashes over the last 28 days).

While I don't understand how this would happen, I think it should be
relatively safe to assume that if the searchview is null the user isn't
currently searching so running the normal back code should always be the
expected behaviour.
2022-11-16 21:42:52 +01:00
Sylvia van Os 28901487ff Merge pull request #1138 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-15 23:17:53 +01:00
Sylvia van Os 8414f51ee8 Translated using Weblate (Polish)
Currently translated at 39.8% (45 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pl/
2022-11-15 21:48:36 +01:00
Slávek Banko 94f8adb6d7 Translated using Weblate (Czech)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-11-15 21:48:35 +01:00
Sylvia van Os 844a921a1a Merge pull request #1134 from CatimaLoyalty/create-pull-request/patch-1668320636
Update contributors
2022-11-14 19:47:10 +01:00
Sylvia van Os ae8be3eda8 Merge pull request #1135 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-14 06:27:25 +01:00
gallegonovato c4c15dbef8 Translated using Weblate (Spanish)
Currently translated at 3.5% (4 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-11-13 23:48:54 +01:00
Evgeniy Khramov ac72035500 Translated using Weblate (Russian)
Currently translated at 32.7% (37 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2022-11-13 23:48:54 +01:00
Freddo espresso abff3bcd39 Translated using Weblate (Greek)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/el/
2022-11-13 23:48:54 +01:00
TheLastProject 05aea28602 Update contributors 2022-11-13 06:23:55 +00:00
Sylvia van Os e4c4dbf5a0 Merge pull request #1133 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-11 23:02:41 +01:00
Sylvia van Os bb2393b6c6 Translated using Weblate (Polish)
Currently translated at 99.2% (272 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-11-11 22:49:16 +01:00
Gediminas Murauskas fb330d16b5 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2022-11-11 22:49:16 +01:00
Slávek Banko c8f1b986ec Translated using Weblate (Czech)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-11-11 22:49:15 +01:00
Євгеній Нешта 49a2c93d28 Translated using Weblate (Ukrainian)
Currently translated at 99.1% (112 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-11-09 20:48:23 +01:00
Євгеній Нешта 0992ac4099 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2022-11-09 20:48:23 +01:00
truestorybaby 9ff29af616 Translated using Weblate (Polish)
Currently translated at 99.2% (272 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-11-09 20:48:23 +01:00
Sylvia van Os fbc696047b Merge pull request #1124 from CatimaLoyalty/dependabot/gradle/com.google.zxing-core-3.5.1
Bump core from 3.5.0 to 3.5.1
2022-11-06 11:21:30 +01:00
Sylvia van Os 08a4d4b114 Release Catima 2.21.0 2022-11-06 11:16:07 +01:00
Sylvia van Os 329056301b Add Hindi to language picker 2022-11-06 10:53:39 +01:00
Sylvia van Os fac8da69e7 Merge pull request #1127 from CatimaLoyalty/create-pull-request/patch-1667715884
Update contributors
2022-11-06 08:33:33 +01:00
TheLastProject fad9eed43e Update contributors 2022-11-06 06:24:44 +00:00
Sylvia van Os 58a18bdd7b Merge pull request #1126 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-05 11:35:49 +01:00
Eric 90cb524560 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2022-11-05 11:05:28 +01:00
Sylvia van Os ef4c57ce29 Merge pull request #1125 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-11-04 08:21:51 +01:00
Jean Mareilles 8872fad73e Translated using Weblate (French)
Currently translated at 99.1% (112 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-11-04 06:12:38 +01:00
dependabot[bot] 63c3330571 Bump core from 3.5.0 to 3.5.1
Bumps [core](https://github.com/zxing/zxing) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/zxing/zxing/releases)
- [Changelog](https://github.com/zxing/zxing/blob/master/CHANGES)
- [Commits](https://github.com/zxing/zxing/compare/zxing-3.5.0...zxing-3.5.1)

---
updated-dependencies:
- dependency-name: com.google.zxing:core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-03 02:03:03 +00:00
Sylvia van Os 37d1bb9477 Merge pull request #1118 from pfaffenrodt/feature/clean-about
Cleaning code in about page
2022-11-01 22:00:55 +01:00
Pfaffenrodt 8a67d1d02b Rename open to openBrowser 2022-11-01 10:52:11 +01:00
Pfaffenrodt 6f777068ab Remove map from id to link. make link handler more solid 2022-10-30 21:04:35 +01:00
Sylvia van Os 8607e1c23c Merge pull request #1120 from CatimaLoyalty/create-pull-request/patch-1667112218
Update contributors
2022-10-30 11:17:13 +01:00
Sylvia van Os 04a319066c Merge pull request #1119 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-30 11:02:06 +01:00
Sylvia van Os 39f89ca943 Also replace "smart quotes" in broken translation 2022-10-30 10:33:03 +01:00
Sylvia van Os 1092d7a9ba Fix broken translation 2022-10-30 10:29:30 +01:00
TheLastProject b54052182d Update contributors 2022-10-30 06:43:37 +00:00
SC b971c392cf Translated using Weblate (Portuguese)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2022-10-29 21:01:09 +02:00
SC cec9306387 Translated using Weblate (Portuguese)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2022-10-29 21:01:09 +02:00
元气 f6a5cbbf80 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2022-10-29 21:01:09 +02:00
pfaffenrodt 4b55c414f3 Fix spacings in custom view of alert dialogs (#1117) 2022-10-29 15:12:45 +02:00
Pfaffenrodt 1aafcdc6ae Revert to reading file. Missing encoding 2022-10-29 14:44:02 +02:00
Pfaffenrodt 332e37b2eb Extract page title to about content 2022-10-29 14:19:36 +02:00
Pfaffenrodt dff33d3bab Simplify reading contributors file 2022-10-29 14:19:36 +02:00
Pfaffenrodt 85ddc9689c Extract common html link of third party info 2022-10-29 14:19:36 +02:00
Pfaffenrodt d91c207b60 Extract last about content 2022-10-29 14:19:36 +02:00
Pfaffenrodt 653606fae3 Extract show credits dialog. remove empty listener 2022-10-29 14:19:36 +02:00
Pfaffenrodt f5a0c8f375 Extract about content 2022-10-29 14:19:36 +02:00
Pfaffenrodt c71019951c Extract open link handler 2022-10-29 14:19:36 +02:00
Pfaffenrodt ed7b79ce17 Refactor AboutActivity to avoid leaks that hold activity as reference 2022-10-29 14:19:36 +02:00
Pfaffenrodt 08cfb490d4 Remove redundant title
setTitle was called twice
2022-10-29 14:19:36 +02:00
Pfaffenrodt 7d284a85bc Extract about content from onCreate 2022-10-29 14:19:36 +02:00
Pfaffenrodt 77ef0a2833 Extract same logic to enable back button of toolbar
ManageGroupActivity setDisplayShowHomeEnabled was redundant
2022-10-29 14:19:34 +02:00
Pfaffenrodt 80130654ec Remove unused field properties 2022-10-29 14:18:50 +02:00
Pfaffenrodt e97f7c8645 Add support to pick image from content provider 2022-10-28 23:46:40 +02:00
Sylvia van Os e489ff6a22 Merge pull request #1115 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-28 17:31:58 +02:00
Jean-Luc Tibaux de549d724c Translated using Weblate (German)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-10-28 09:05:42 +02:00
Sylvia van Os 5fb2dbd252 Merge pull request #1111 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-26 18:04:56 +02:00
Yusril A 20013cf7b7 Translated using Weblate (Indonesian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2022-10-26 08:04:56 +02:00
J. Lavoie 78c3146c78 Translated using Weblate (French)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2022-10-26 08:04:56 +02:00
J. Lavoie ddd7bb9968 Translated using Weblate (German)
Currently translated at 98.9% (271 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-10-26 08:04:56 +02:00
Tong Liu 68935f1489 Closes #1092 - Fixed contents cut off on smaller screen issue. (#1095) 2022-10-25 19:38:02 +02:00
Sylvia van Os d9a25e1eb9 Merge pull request #1108 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-24 20:54:17 +02:00
Oğuz Ersen 73a837bab5 Translated using Weblate (Turkish)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2022-10-24 20:42:31 +02:00
109247019824 03be45f5a2 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2022-10-24 20:42:31 +02:00
Eric 692adafd8e Translated using Weblate (Chinese (Simplified))
Currently translated at 97.0% (266 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2022-10-24 20:42:31 +02:00
Slávek Banko 4ff9eb5219 Translated using Weblate (Czech)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-10-24 20:42:31 +02:00
solokot 286e9fa315 Translated using Weblate (Russian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-10-24 20:42:31 +02:00
Heimen Stoffels e0b6773d2a Translated using Weblate (Dutch)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2022-10-24 20:42:31 +02:00
Allan Nordhøy a7cb8a51a3 Translated using Weblate (Norwegian Bokmål)
Currently translated at 97.0% (266 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2022-10-24 20:42:31 +02:00
Gediminas Murauskas 56c7ffa4df Translated using Weblate (Lithuanian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2022-10-24 20:42:31 +02:00
Michael Moroni 1498f902c2 Translated using Weblate (Italian)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-10-24 20:42:31 +02:00
gallegonovato eea0dd9081 Translated using Weblate (Spanish)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2022-10-24 20:42:31 +02:00
Slávek Banko 1a8c8c07aa Translated using Weblate (Czech)
Currently translated at 100.0% (274 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-10-24 20:42:31 +02:00
Allan Nordhøy 3901172757 Translated using Weblate (English)
Currently translated at 99.2% (272 of 274 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2022-10-24 20:42:31 +02:00
Sylvia van Os 3c9507cb7f Merge pull request #1107 from vanogrid/fix/expiryFieldTextRemainingRed
Fix Expiry field text remaining red after the card is no longer expired
2022-10-24 19:13:53 +02:00
Alexander Ivanov bfc38807c8 Fix Expiry field text remaining red after the card is no longer expired
Signed-off-by: Alexander Ivanov <vanogrid@gmail.com>
2022-10-24 02:14:43 +03:00
Sylvia van Os 6dc3a28026 Merge pull request #1105 from CatimaLoyalty/create-pull-request/patch-1666508787
Update contributors
2022-10-23 11:58:29 +02:00
Sylvia van Os eeb507f04e Merge pull request #1104 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-23 11:58:08 +02:00
Sylvia van Os 2746547194 Merge pull request #1103 from vanogrid/fix/storingDateAt12pm
Fix DatePickerDialog sometimes storing dates at 12 PM instead of 12 AM
2022-10-23 11:55:25 +02:00
TheLastProject c9a8e81047 Update contributors 2022-10-23 07:06:27 +00:00
huang ivan d87b8ddd4b Translated using Weblate (Chinese (Simplified))
Currently translated at 97.0% (265 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2022-10-23 06:00:18 +02:00
Alexander Ivanov 7dfa7071e3 Fix DatePickerDialog sometimes storing dates at 12:00 PM instead of 12:00 AM 2022-10-22 20:46:22 +03:00
Sylvia van Os 92f0091b1d Merge pull request #1086 from recursiveribbons/refactor-importer
Refactor Importer to not read entire file as String
2022-10-22 18:13:38 +02:00
Tomer Ben-Rachel 54d8f30bf1 Offer import when users click on supported import files (#1096) 2022-10-22 12:13:06 +02:00
f7ef13d594 Merge #1101
1101: Translations update from Hosted Weblate r=TheLastProject a=weblate

Translations update from [Hosted Weblate](https://hosted.weblate.org) for [Catima/Android](https://hosted.weblate.org/projects/catima/catima/).


It also includes following components:

* [Catima/Android (Fastlane)](https://hosted.weblate.org/projects/catima/fastlane/)



Current translation status:

![Weblate translation status](https://hosted.weblate.org/widgets/catima/-/catima/horizontal-auto.svg)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Co-authored-by: Gediminas Murauskas <muziejusinfo@gmail.com>
Co-authored-by: Mindaugas <mindaugasjurgelenas1997@gmail.com>
Co-authored-by: Angela Enogieru <angys1may@gmail.com>
Co-authored-by: SKULD <ala20031028@163.com>
Co-authored-by: AnimeshChatterjee1 <animesh.chatterjee02@gmail.com>
Co-authored-by: Rishi Agarwal <rishiagarwal130903@gmail.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2022-10-21 18:02:41 +00:00
Rishi Agarwal 2a1157256b Translated using Weblate (Hindi)
Currently translated at 54.5% (149 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hi/
2022-10-21 19:57:29 +02:00
Sylvia van Os 213ef5060f Translated using Weblate (Slovak)
Currently translated at 74.7% (204 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2022-10-21 19:57:28 +02:00
Gediminas Murauskas bc24e263b9 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2022-10-21 19:57:28 +02:00
Gediminas Murauskas 8da70c41b2 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2022-10-21 16:36:01 +02:00
Rishi Agarwal 4d81846fe0 Translated using Weblate (Hindi)
Currently translated at 44.3% (121 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hi/
2022-10-21 16:36:01 +02:00
AnimeshChatterjee1 2afdedd0b6 Translated using Weblate (Hindi)
Currently translated at 44.3% (121 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hi/
2022-10-21 16:36:01 +02:00
SKULD 8d944cbb24 Translated using Weblate (Chinese (Simplified))
Currently translated at 97.0% (265 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2022-10-21 16:36:01 +02:00
Angela Enogieru 3ffec94b47 Translated using Weblate (Slovak)
Currently translated at 75.0% (205 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2022-10-21 16:36:01 +02:00
Mindaugas 9176dc98ee Translated using Weblate (Lithuanian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2022-10-21 16:36:01 +02:00
Gediminas Murauskas 9881854d13 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2022-10-21 16:36:01 +02:00
J. Lavoie 2e4d1fa448 Translated using Weblate (Italian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-10-21 16:36:01 +02:00
J. Lavoie 97ca1440b0 Translated using Weblate (French)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2022-10-21 16:36:01 +02:00
J. Lavoie a4688c4450 Translated using Weblate (German)
Currently translated at 98.9% (270 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-10-21 16:36:01 +02:00
Sylvia van Os a7ae2a333a Merge pull request #1100 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-20 19:03:44 +02:00
Laura Ferraz 823e99bd90 Translated using Weblate (Portuguese)
Currently translated at 97.8% (267 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2022-10-20 16:06:34 +02:00
Oğuz Ersen e32fccc694 Translated using Weblate (Turkish)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2022-10-20 16:06:34 +02:00
109247019824 dd568ab51d Translated using Weblate (Bulgarian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2022-10-20 16:06:34 +02:00
Max 17f55e577b Translated using Weblate (Polish)
Currently translated at 39.8% (45 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pl/
2022-10-20 16:06:33 +02:00
solokot 3f77223e65 Translated using Weblate (Russian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-10-20 16:06:33 +02:00
Max 28aad933c5 Translated using Weblate (Polish)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-10-20 16:06:33 +02:00
Heimen Stoffels 52ca8396db Translated using Weblate (Dutch)
Currently translated at 99.6% (272 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2022-10-20 16:06:33 +02:00
Michael Moroni bc941544ae Translated using Weblate (Italian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-10-20 16:06:33 +02:00
gallegonovato e3c3b176eb Translated using Weblate (Spanish)
Currently translated at 100.0% (273 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2022-10-20 16:06:33 +02:00
Max 3b0b92b954 Translated using Weblate (English)
Currently translated at 99.2% (271 of 273 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2022-10-20 16:06:33 +02:00
diksha-2911 bfcae03420 Translated using Weblate (Hindi)
Currently translated at 34.9% (93 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hi/
2022-10-20 16:06:33 +02:00
Md. Al-Amin ad4db1ef37 Translated using Weblate (Bengali)
Currently translated at 33.4% (89 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn/
2022-10-20 16:06:33 +02:00
Ágata Leuck fa1a7fd2f1 Translated using Weblate (Portuguese)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2022-10-20 16:06:33 +02:00
Gediminas Murauskas 7eac08d0a1 Translated using Weblate (Lithuanian)
Currently translated at 80.0% (213 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2022-10-20 16:06:33 +02:00
Ágata Leuck dab984b0d4 Translated using Weblate (Portuguese)
Currently translated at 95.5% (108 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2022-10-20 16:06:33 +02:00
Arnis Jaundzeikars 66361dede2 Translated using Weblate (Latvian)
Currently translated at 1.7% (2 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/lv/
2022-10-20 16:06:33 +02:00
Arnis Jaundzeikars 628c62fd4b Translated using Weblate (Latvian)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lv/
2022-10-20 16:06:33 +02:00
Nicolas 84a7e95856 Translated using Weblate (French)
Currently translated at 99.1% (112 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-10-20 16:06:33 +02:00
Sylvia van Os fc256d2c4a Merge pull request #1097 from pfaffenrodt/feature/security-maven-repos
Add limitation for jitpack maven repository
2022-10-19 18:34:57 +02:00
Pfaffenrodt 7f81ceeb7e Add limitation for jitpack maven repository 2022-10-18 21:11:50 +02:00
Tong Liu 3179644fbc Issue #1084 - adding text for permission denial. (#1085) 2022-10-16 19:58:29 +02:00
Sylvia van Os 274a58bcb0 Merge pull request #1093 from CatimaLoyalty/create-pull-request/patch-1665923209
Update Fastlane changelogs
2022-10-16 14:27:21 +02:00
TheLastProject dc7f42b0b6 Update Fastlane changelogs 2022-10-16 12:26:48 +00:00
Sylvia van Os f859627d7f Document quick spend feature 2022-10-16 14:26:34 +02:00
polarhun ccf12bf028 #1044 - Automatic Balance Update (#1073) 2022-10-16 14:25:26 +02:00
Sylvia van Os c34e2fdd70 Merge pull request #1091 from CatimaLoyalty/fix/crashCancelScanActivity
Fix crash on cancelling ScanActivity
2022-10-16 11:41:58 +02:00
Sylvia van Os ea482c6fad Fix crash on cancelling ScanActivity
Introduced in https://github.com/CatimaLoyalty/Android/pull/1078
2022-10-16 11:07:40 +02:00
Sylvia van Os 54f223b5b0 Merge pull request #1090 from CatimaLoyalty/create-pull-request/patch-1665903989
Update contributors
2022-10-16 10:12:22 +02:00
TheLastProject 74e083bb62 Update contributors 2022-10-16 07:06:28 +00:00
Robin Syl a9c36cd171 A more reliable and customizable method to parse version from an import file 2022-10-15 20:06:49 +02:00
Sylvia van Os 876b0beb2f Merge pull request #1088 from CatimaLoyalty/fix/cursorAdapterDRY
Reduce repeated code in LoyaltyCardCursorAdapter
2022-10-15 14:40:38 +02:00
Sylvia van Os 1f73beb895 Reduce repeated code in LoyaltyCardCursorAdapter
This also more explicitly sets the text colour to prevent RecyclerView
state bugs
2022-10-15 14:30:42 +02:00
Sylvia van Os b13aaacdff Merge pull request #1087 from CatimaLoyalty/create-pull-request/patch-1665820428
Update Fastlane changelogs
2022-10-15 09:54:07 +02:00
TheLastProject ba67c122fa Update Fastlane changelogs 2022-10-15 07:53:48 +00:00
Sylvia van Os f16550aa9c Document new share intenet receiver in changelog 2022-10-15 09:53:28 +02:00
Robin Syl ba57fbbf85 Close inputstream in importData 2022-10-14 21:36:02 +02:00
Simon Rusinov ebedb43e72 issue-614 add receiver for share intent (#1078) 2022-10-14 21:33:59 +02:00
Robin Syl c10f859919 Refactor Importer to not read entire file as String 2022-10-14 16:56:35 +02:00
Sylvia van Os 8e6e83dfc6 Merge pull request #1080 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-10 21:36:16 +02:00
Jen Kung-chih 326379d222 Translated using Weblate (Chinese (Traditional))
Currently translated at 99.6% (265 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2022-10-10 20:07:48 +02:00
Sylvia van Os 105e85cc63 Translated using Weblate (Spanish)
Currently translated at 2.6% (3 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-10-10 20:07:48 +02:00
Sylvia van Os e21dbc85e8 Translated using Weblate (Romanian)
Currently translated at 2.6% (3 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ro/
2022-10-10 20:07:47 +02:00
Simon Rusinov 78348a6f9c issue-1054 handle all deprecation warnings (#1072) 2022-10-10 18:28:35 +02:00
Sneakyturtle22 f98b98b4f3 Translated using Weblate (Hindi)
Currently translated at 27.4% (73 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hi/
2022-10-10 15:24:11 +02:00
Arnis Jaundzeikars d362305a25 Translated using Weblate (Latvian)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lv/
2022-10-10 15:24:11 +02:00
Sylvia van Os 623cfc671c Translated using Weblate (Indonesian)
Currently translated at 17.6% (20 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2022-10-10 15:24:11 +02:00
Magnitudee 456e2112b8 Translated using Weblate (Indonesian)
Currently translated at 98.8% (263 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2022-10-10 15:24:11 +02:00
gallegonovato af2fbd1ce3 Translated using Weblate (Spanish)
Currently translated at 2.6% (3 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-10-10 15:24:11 +02:00
Sylvia van Os 91211f07cb Translated using Weblate (Polish)
Currently translated at 36.2% (41 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pl/
2022-10-10 15:24:11 +02:00
BootVirtual 9c183e84dd Translated using Weblate (Romanian)
Currently translated at 2.6% (3 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ro/
2022-10-10 15:24:11 +02:00
Thomas Cruveilher 5e3cebf4a1 Translated using Weblate (French)
Currently translated at 63.7% (72 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-10-10 15:24:11 +02:00
Piotr Zet 9437d23e6e Translated using Weblate (Polish)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-10-10 15:24:11 +02:00
Sneakyturtle22 925a66a12a Added translation using Weblate (Hindi) 2022-10-10 15:24:11 +02:00
gallegonovato 5db8af72a1 Translated using Weblate (Spanish)
Currently translated at 2.6% (3 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-10-10 15:24:11 +02:00
Mawuena M. KODZO A 2b605eb193 Translated using Weblate (French)
Currently translated at 44.2% (50 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-10-10 15:24:11 +02:00
BootVirtual f16d10995c Translated using Weblate (Romanian)
Currently translated at 51.1% (136 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ro/
2022-10-10 15:24:11 +02:00
Sylvia van Os 3ef17404b7 Merge pull request #1077 from CatimaLoyalty/fix/groupNameValidation
Improve group name validation flow
2022-10-09 17:19:20 +02:00
Sylvia van Os 1316ac731c Improve group name validation flow 2022-10-09 16:45:54 +02:00
Sylvia van Os 6283a90217 Merge pull request #1075 from CatimaLoyalty/create-pull-request/patch-1665298778
Update contributors
2022-10-09 10:42:13 +02:00
TheLastProject 84e8857067 Update contributors 2022-10-09 06:59:37 +00:00
Sylvia van Os 05a53d7985 Add missing languages to language chooser 2022-10-07 19:41:35 +02:00
Sylvia van Os 94b13b7145 Merge pull request #1071 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-07 19:09:23 +02:00
Mohamed A. Salah 3e55a147c7 Translated using Weblate (Arabic)
Currently translated at 99.2% (264 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2022-10-07 17:20:03 +02:00
109247019824 f05ed2571f Translated using Weblate (Bulgarian)
Currently translated at 12.3% (14 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/bg/
2022-10-07 17:20:03 +02:00
Sylvia van Os c1a37eb2a4 Translated using Weblate (Spanish)
Currently translated at 1.7% (2 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-10-07 17:20:02 +02:00
Katarzyna 4d8d863780 Translated using Weblate (Polish)
Currently translated at 36.2% (41 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pl/
2022-10-07 17:20:02 +02:00
Slávek Banko d56eec4ba9 Translated using Weblate (Czech)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-10-07 17:20:00 +02:00
Thomas Cruveilher a05356d0e1 Translated using Weblate (French)
Currently translated at 43.3% (49 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-10-07 17:19:56 +02:00
TenTraicion 4eea6f7f53 Translated using Weblate (Bengali)
Currently translated at 25.5% (68 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn/
2022-10-06 22:43:18 +02:00
Tapu 24e19cc5f8 Translated using Weblate (Bengali)
Currently translated at 25.5% (68 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn/
2022-10-06 22:43:18 +02:00
gallegonovato cd7631451b Translated using Weblate (Spanish)
Currently translated at 1.7% (2 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2022-10-06 22:43:18 +02:00
이정희 d140130b0d Translated using Weblate (Korean)
Currently translated at 39.8% (106 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ko/
2022-10-06 22:43:18 +02:00
BMN f0453943da Translated using Weblate (German)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2022-10-06 22:43:18 +02:00
Mawuena M. KODZO A 42152ccbb5 Translated using Weblate (French)
Currently translated at 32.7% (37 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-10-06 22:43:18 +02:00
Mohamed A. Salah 27f8647243 Added translation using Weblate (Arabic (Najdi)) 2022-10-06 22:43:18 +02:00
Sylvia van Os b7d520ded6 Merge pull request #1069 from CatimaLoyalty/create-pull-request/patch-1665000141
Update Fastlane changelogs
2022-10-05 22:03:15 +02:00
TheLastProject 04088ff366 Update Fastlane changelogs 2022-10-05 20:02:21 +00:00
Sylvia van Os d4dcec1a9b Document switch to MaterialAlertDialog 2022-10-05 22:01:56 +02:00
Sylvia van Os c8306616e3 Merge pull request #1067 from theimpulson/alertDialogImprovements
Alert dialog improvements
2022-10-05 22:01:13 +02:00
Sylvia van Os b34bdebb5c Merge pull request #1068 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-05 10:42:25 +02:00
Lucas da Costa 9643cb9f94 Translated using Weblate (Portuguese)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2022-10-05 07:58:58 +02:00
Tapu 645b29226e Translated using Weblate (Bengali (India))
Currently translated at 48.8% (130 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bn_IN/
2022-10-05 07:58:58 +02:00
Tarik Dzambic c56faba922 Translated using Weblate (Bosnian)
Currently translated at 17.6% (20 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/bs/
2022-10-05 07:58:58 +02:00
Tarik Dzambic 55a19eacc9 Translated using Weblate (Bosnian)
Currently translated at 53.3% (142 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bs/
2022-10-05 07:58:58 +02:00
Katarzyna 464a2350ae Translated using Weblate (Polish)
Currently translated at 36.2% (41 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pl/
2022-10-05 07:58:58 +02:00
Lisa c44f737c99 Translated using Weblate (Italian)
Currently translated at 57.5% (65 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2022-10-05 07:58:58 +02:00
Mawuena M. KODZO A a8794ce60c Translated using Weblate (French)
Currently translated at 25.6% (29 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-10-05 07:58:58 +02:00
gallegonovato 11329ba786 Translated using Weblate (Spanish)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2022-10-05 07:58:58 +02:00
Tapu e568bd1af9 Added translation using Weblate (Bengali) 2022-10-05 07:58:58 +02:00
Aayush Gupta b3fbfdbf9d ManageGroupsActivity: Add spacing between EditText and AlertDialog bounds
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2022-10-05 11:04:40 +05:30
Aayush Gupta aec4292203 Catima: Migrate to MaterialAlertDialogBuilder everywhere
This follows Material theme and looks much better compared to AlertDialog

Ref: https://developer.android.com/reference/com/google/android/material/dialog/MaterialAlertDialogBuilder

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2022-10-05 10:37:03 +05:30
Sylvia van Os 82733ca414 Merge pull request #1053 from theimpulson/gradle-improvements
Misc Gradle improvements
2022-10-04 21:03:31 +02:00
Aayush Gupta 887424af80 spotbugs: Exclude gradle generated view binding classes
Spot bugs complains about EI_EXPOSE_REP and BC_UNCONFIRMED_CAST bugs in these
classes but they are being generated by Gradle and are out of our control if
we want to use view binding to interact with the views.

Ref: https://developer.android.com/topic/libraries/view-binding

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2022-10-05 00:20:31 +05:30
Aayush Gupta f63a25f582 gradle: Move lint params to specific config
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2022-10-05 00:20:31 +05:30
Aayush Gupta 635ec748b3 Catima: Migrate to view binding
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2022-10-05 00:20:31 +05:30
Aayush Gupta fa510e3ffa gradle: Switch to new Int only SDK version properties
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2022-10-05 00:20:31 +05:30
Aayush Gupta 24a5efd5f8 gradle: Migrate to new plugins and dependency management system
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2022-10-05 00:20:31 +05:30
Aayush Gupta 547dd55240 gradle: Drop buildToolsVersion
Not required as the latest one is always used

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2022-10-05 00:20:31 +05:30
bors[bot]andSylvia van Os 774705d9ad Merge #1065
1065: Remove CodeQL r=TheLastProject a=TheLastProject

It's getting in the way of #1053 and in a year of usage has not once given any type of alert

Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2022-10-04 18:40:08 +00:00
Sylvia van Os 3d756e271c Remove CodeQL
It's getting in the way of #1053 and in a year of usage has not once given any type of alert
2022-10-04 20:39:39 +02:00
Sylvia van Os 2da9a9c1a8 Merge pull request #1064 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-03 22:05:32 +02:00
Lisa cd67d3c919 Translated using Weblate (Italian)
Currently translated at 18.5% (21 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2022-10-03 19:48:19 +02:00
Aya Elsaadany c080fdb244 Translated using Weblate (Arabic)
Currently translated at 99.2% (264 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2022-10-03 19:48:19 +02:00
Arnis Jaundzeikars 9ee61812b8 Translated using Weblate (Latvian)
Currently translated at 94.7% (252 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lv/
2022-10-03 19:48:19 +02:00
Oğuz Ersen bccf0a656b Translated using Weblate (Turkish)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2022-10-03 19:48:19 +02:00
109247019824 47ca66e9c7 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2022-10-03 19:48:19 +02:00
Eric 972315ad00 Translated using Weblate (Chinese (Simplified))
Currently translated at 98.8% (263 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2022-10-03 19:48:19 +02:00
Katarzyna 0aa8b63c0c Translated using Weblate (Polish)
Currently translated at 15.9% (18 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pl/
2022-10-03 19:48:18 +02:00
Slávek Banko e77cf403eb Translated using Weblate (Czech)
Currently translated at 100.0% (113 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-10-03 19:48:18 +02:00
Jacopo Gennaro Esposito df89ab29eb Translated using Weblate (Italian)
Currently translated at 17.6% (20 of 113 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2022-10-03 19:48:18 +02:00
IllusiveMan196 6c6829bfd5 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2022-10-03 19:48:18 +02:00
solokot fa531dce81 Translated using Weblate (Russian)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-10-03 19:48:18 +02:00
Katarzyna 61bc7ad24a Translated using Weblate (Polish)
Currently translated at 99.6% (265 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-10-03 19:48:18 +02:00
Heimen Stoffels ce0964e6a7 Translated using Weblate (Dutch)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2022-10-03 19:48:18 +02:00
Allan Nordhøy 4979ac9d34 Translated using Weblate (Norwegian Bokmål)
Currently translated at 97.7% (260 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2022-10-03 19:48:18 +02:00
Michael Moroni 912bcdf7f7 Translated using Weblate (Italian)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-10-03 19:48:18 +02:00
J. Lavoie 09174e646b Translated using Weblate (French)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2022-10-03 19:48:18 +02:00
J. Lavoie 0c729cb092 Translated using Weblate (German)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-10-03 19:48:18 +02:00
Slávek Banko 61faa4aa09 Translated using Weblate (Czech)
Currently translated at 100.0% (266 of 266 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-10-03 19:48:18 +02:00
Sylvia van Os 0e7a5428f6 Merge pull request #1062 from CatimaLoyalty/dependabot/gradle/org.robolectric-robolectric-4.9
Bump robolectric from 4.8.2 to 4.9
2022-10-03 18:18:38 +02:00
dependabot[bot] 8030eb52f3 Bump robolectric from 4.8.2 to 4.9
Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.8.2 to 4.9.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.8.2...robolectric-4.9)

---
updated-dependencies:
- dependency-name: org.robolectric:robolectric
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-03 02:36:38 +00:00
Sylvia van Os 9fc315158f Name Weblate in CONTRIBUTING.md 2022-10-02 19:24:48 +02:00
Sylvia van Os 971f68b0a1 Merge pull request #1059 from CatimaLoyalty/create-pull-request/patch-1664690892
Update contributors
2022-10-02 10:10:22 +02:00
TheLastProject adfc17d5c2 Update contributors 2022-10-02 06:08:12 +00:00
Sylvia van Os 5ee2852e4c Merge pull request #1058 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-10-02 00:48:46 +02:00
J. Lavoie ea1d42fa35 Translated using Weblate (Finnish)
Currently translated at 98.1% (259 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2022-10-01 21:20:34 +02:00
Lisa f8b90f2c07 Translated using Weblate (Italian)
Currently translated at 16.9% (19 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2022-10-01 21:20:34 +02:00
J. Lavoie 6dc9821891 Translated using Weblate (French)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2022-10-01 21:20:34 +02:00
J. Lavoie 93a2e9cdbf Translated using Weblate (Spanish)
Currently translated at 99.6% (263 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2022-10-01 21:20:34 +02:00
Sylvia van Os 6a9d54d6f0 Merge pull request #1055 from CatimaLoyalty/create-pull-request/patch-1664626344
Update Fastlane changelogs
2022-10-01 14:13:08 +02:00
TheLastProject 28f0b407b5 Update Fastlane changelogs 2022-10-01 12:12:24 +00:00
Sylvia van Os 89ed31ffe0 Update CHANGELOG 2022-10-01 14:12:08 +02:00
Manan Jhaveri aa481ea094 View photos in gallery when Long Pressed (#1052)
* Open Native Image Viewer on long pressing a photo inside LoyaltyCardViewActivity

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.

Signed-off-by: Manan Jhaveri <incrediblemanan@gmail.com>
2022-10-01 14:11:15 +02:00
523aaef650 Merge #1051
1051: Translations update from Hosted Weblate r=TheLastProject a=weblate

Translations update from [Hosted Weblate](https://hosted.weblate.org) for [Catima/Android](https://hosted.weblate.org/projects/catima/catima/).


It also includes following components:

* [Catima/Android (Fastlane)](https://hosted.weblate.org/projects/catima/fastlane/)



Current translation status:

![Weblate translation status](https://hosted.weblate.org/widgets/catima/-/catima/horizontal-auto.svg)

Co-authored-by: Tomer Ben Rachel <tomerpacific@gmail.com>
Co-authored-by: Evgeniy Khramov <thejenjagamertjg@gmail.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2022-10-01 09:50:55 +00:00
Sylvia van Os a56c4d449d Remove broken translation 2022-10-01 11:50:22 +02:00
Evgeniy Khramov 1468130477 Translated using Weblate (Russian)
Currently translated at 28.5% (32 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2022-09-28 21:16:13 +02:00
Tomer Ben Rachel 0b5571a065 Translated using Weblate (Hebrew (Israel))
Currently translated at 35.2% (93 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/he_IL/
2022-09-28 21:16:13 +02:00
Sylvia van Os 002c221390 Merge pull request #1050 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-26 21:25:16 +02:00
Oğuz Ersen 2272c88d04 Translated using Weblate (English)
Currently translated at 98.8% (261 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2022-09-26 20:28:50 +02:00
Wanath 6a58bd632f Translated using Weblate (Korean)
Currently translated at 35.9% (95 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ko/
2022-09-26 20:28:50 +02:00
Wanath 027a7f798d Translated using Weblate (English)
Currently translated at 98.8% (261 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2022-09-26 20:28:50 +02:00
Sylvia van Os dd4ad6d860 Merge pull request #1048 from CatimaLoyalty/create-pull-request/patch-1664085704
Update contributors
2022-09-25 10:27:46 +02:00
TheLastProject 3342b8f83f Update contributors 2022-09-25 06:01:43 +00:00
Sylvia van Os 5951c74fc4 Merge pull request #1047 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-24 12:46:35 +02:00
Nate Higgers 2cae83c84f Translated using Weblate (Chinese (Traditional))
Currently translated at 93.1% (246 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hant/
2022-09-24 12:27:25 +02:00
Sylvia van Os 65ac1a2558 Release Catima 2.20.0 2022-09-21 18:54:19 +02:00
Sylvia van Os 6e064e1533 Merge pull request #1042 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-21 18:41:06 +02:00
Sylvia van Os 0d1c3051c8 Translated using Weblate (Ukrainian)
Currently translated at 97.3% (109 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-09-21 18:34:34 +02:00
Slávek Banko f2885cd96e Translated using Weblate (Czech)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-09-21 18:28:57 +02:00
michael ramirez 98de0a7acb Translated using Weblate (Spanish)
Currently translated at 72.7% (192 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2022-09-21 18:28:54 +02:00
mondstern 6622d0f4db Translated using Weblate (Ukrainian)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-09-20 19:22:31 +02:00
mondstern ccc269ab3e Translated using Weblate (Ukrainian)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-09-20 19:22:31 +02:00
mondstern 4008cc2349 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2022-09-20 19:22:31 +02:00
Sylvia van Os 02bb266762 Merge pull request #1039 from CatimaLoyalty/create-pull-request/patch-1663610798
Update Fastlane changelogs
2022-09-19 20:13:00 +02:00
TheLastProject 5e64400faf Update Fastlane changelogs 2022-09-19 18:06:37 +00:00
Sylvia van Os da2a444ae8 Merge pull request #1036 from CatimaLoyalty/undoArchiveText
Move Archive back into overflow menu
2022-09-19 20:06:23 +02:00
Sylvia van Os 1a22c27326 Move Archive back into overflow menu
While I much prefer the design introduced in
https://github.com/CatimaLoyalty/Android/pull/1009, it sadly caused a
serious performance regression
(https://github.com/CatimaLoyalty/Android/issues/1026).

This commit restores the old behaviour so that a new release isn't
blocked while this is figured out.
2022-09-19 19:49:07 +02:00
Sylvia van Os b5a7824179 Merge pull request #1035 from CatimaLoyalty/create-pull-request/patch-1663480209
Update contributors
2022-09-18 11:08:07 +02:00
TheLastProject 1f84aa9dc7 Update contributors 2022-09-18 05:50:08 +00:00
Sylvia van Os 942336e281 Merge pull request #1034 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-18 00:08:21 +02:00
Daniel Uhrinyi 27cda3a949 Translated using Weblate (Hungarian)
Currently translated at 98.8% (261 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2022-09-17 19:20:58 +02:00
Magnitudee 1d5d105f8a Translated using Weblate (Indonesian)
Currently translated at 18.7% (21 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2022-09-17 19:20:58 +02:00
Sylvia van Os 5c886d443f Merge pull request #1028 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-16 19:33:58 +02:00
Sylvia van Os aa306ad11d Remove wrong newline 2022-09-16 18:33:06 +02:00
Magnitudee d1cc0d9aac Translated using Weblate (Indonesian)
Currently translated at 3.5% (4 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2022-09-16 18:19:04 +02:00
Magnitudee f8e08f76b8 Translated using Weblate (Indonesian)
Currently translated at 95.4% (252 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2022-09-16 18:19:04 +02:00
tygyh 27c18fa5ff Translated using Weblate (Swedish)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2022-09-16 18:19:04 +02:00
Sylvia van Os 0017e767c9 Cleanups 2022-09-15 21:18:40 +02:00
Ashish Yadav 4d742dc9e4 Update used libraries in AboutActivity 2022-09-15 21:08:14 +02:00
Sylvia van Os 96245543e0 Merge pull request #1021 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-13 19:27:08 +02:00
SC 59767a7c7f Translated using Weblate (Portuguese)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2022-09-13 19:18:51 +02:00
Titas Pažereckas 8766bcbc71 Translated using Weblate (Lithuanian)
Currently translated at 78.0% (206 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2022-09-13 19:18:51 +02:00
Sylvia van Os 47e87736ca Merge pull request #1020 from CatimaLoyalty/dependabot/gradle/net.lingala.zip4j-zip4j-2.11.2
Bump zip4j from 2.11.1 to 2.11.2
2022-09-13 08:18:27 +02:00
dependabot[bot] f8af01de24 Bump zip4j from 2.11.1 to 2.11.2
Bumps [zip4j](https://github.com/srikanth-lingala/zip4j) from 2.11.1 to 2.11.2.
- [Release notes](https://github.com/srikanth-lingala/zip4j/releases)
- [Commits](https://github.com/srikanth-lingala/zip4j/compare/v2.11.1...v2.11.2)

---
updated-dependencies:
- dependency-name: net.lingala.zip4j:zip4j
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-13 02:37:32 +00:00
Sylvia van Os 4b5a1f8009 Merge pull request #1018 from CatimaLoyalty/create-pull-request/patch-1662872854
Update contributors
2022-09-11 10:00:01 +02:00
TheLastProject e55773c8d3 Update contributors 2022-09-11 05:07:33 +00:00
Sylvia van Os e83671eee0 Merge pull request #1017 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-09 20:56:10 +02:00
Colgrave 8b04e36a88 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.6% (263 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2022-09-09 20:15:49 +02:00
Fede Pujol 76cd06904c Translated using Weblate (Spanish (Argentina))
Currently translated at 1.7% (2 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es_AR/
2022-09-09 20:15:49 +02:00
Slávek Banko cac7a60708 Translated using Weblate (Czech)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-09-09 20:15:49 +02:00
Michael Moroni aef1078e74 Translated using Weblate (Italian)
Currently translated at 16.9% (19 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2022-09-09 20:15:46 +02:00
Sylvia van Os 20c891ee28 Merge pull request #1014 from CatimaLoyalty/fix/alwaysUpdateLastUsed
Always update last used when creating or editing a card
2022-09-08 19:29:27 +02:00
Sylvia van Os 5bfca6e428 Always update last used when creating or editing a card 2022-09-08 19:27:31 +02:00
Sylvia van Os 5971e48ab6 Merge pull request #1015 from CatimaLoyalty/revert-1010-theme
Revert "[UI] Fix colors on navigationBarColor"
2022-09-07 21:20:18 +02:00
Sylvia van Os 427b4d64ed Revert "[UI] Fix colors on navigationBarColor (#1010)"
This reverts commit d0e80f76d6.
2022-09-07 21:18:40 +02:00
Sylvia van Os 41995b5bdd Merge pull request #1013 from CatimaLoyalty/create-pull-request/patch-1662572014
Update Fastlane changelogs
2022-09-07 19:57:37 +02:00
TheLastProject c74e372c76 Update Fastlane changelogs 2022-09-07 17:33:34 +00:00
Sylvia van Os e0650bc6f9 Ignore cards without card ID in Fidme import 2022-09-07 19:33:07 +02:00
Sylvia van Os 0de6a91bab Merge pull request #1012 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-07 17:11:41 +02:00
Oğuz Ersen 54b854eb64 Translated using Weblate (Turkish)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2022-09-07 15:38:17 +02:00
109247019824 47dd3a35ce Translated using Weblate (Bulgarian)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2022-09-07 15:38:17 +02:00
Slávek Banko d16f11d9b7 Translated using Weblate (Czech)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-09-07 15:38:17 +02:00
solokot ce190ba3f0 Translated using Weblate (Russian)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-09-07 15:38:16 +02:00
Heimen Stoffels 070419c888 Translated using Weblate (Dutch)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2022-09-07 15:38:16 +02:00
Allan Nordhøy 5b6489af9f Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.4% (260 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2022-09-07 15:38:16 +02:00
Michael Moroni 84c2c59038 Translated using Weblate (Italian)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-09-07 15:38:16 +02:00
J. Lavoie 8b5efac70a Translated using Weblate (French)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2022-09-07 15:38:16 +02:00
J. Lavoie f82860ddd9 Translated using Weblate (German)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-09-07 15:38:16 +02:00
Slávek Banko d3af048fd5 Translated using Weblate (Czech)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-09-07 15:38:16 +02:00
J. Lavoie 2b3c908298 Translated using Weblate (Italian)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-09-07 15:38:16 +02:00
Michael Moroni 14f35edb0f Translated using Weblate (Italian)
Currently translated at 100.0% (264 of 264 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-09-07 15:38:16 +02:00
Jean-BaptisteandSylvia van Os d0e80f76d6 [UI] Fix colors on navigationBarColor (#1010)
* [UI]Add colors for navigationBarColor

* Add color on Navigation Bar to more activities

* Fix navigation colour on non-view layouts

Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2022-09-06 23:01:28 +02:00
Sylvia van Os ee155c721c Merge pull request #1011 from CatimaLoyalty/create-pull-request/patch-1662400409
Update Fastlane changelogs
2022-09-05 21:41:42 +02:00
TheLastProject 8adc43c9a2 Update Fastlane changelogs 2022-09-05 17:53:28 +00:00
Sylvia van Os 02d59dc71d Merge pull request #1009 from CatimaLoyalty/feature/archiveTextLinkBelowCards
Put archive link below card list
2022-09-05 19:53:12 +02:00
Sylvia van Os 3edb0f6a5d Improve welcome screen 2022-09-04 22:29:59 +02:00
Sylvia van Os acf9029394 Put archive link below card list 2022-09-04 22:09:18 +02:00
bors[bot]andAlexander Ivanov 10588769b3 Merge #1007
1007: Fix a crash when there's no web browser installed r=TheLastProject a=vanogrid

Fixes #984

I tested it by running emulators with different API versions and disabling the default web browser. Tested on Android 8.1, 12 and 13.

Signed-off-by: Alexander Ivanov <vanogrid@gmail.com>

Co-authored-by: Alexander Ivanov <vanogrid@gmail.com>
2022-09-04 13:25:51 +00:00
Alexander Ivanov 68a24fae2f Fix a crash when there's no web browser installed
Signed-off-by: Alexander Ivanov <vanogrid@gmail.com>
2022-09-04 15:33:43 +03:00
Sylvia van Os 625ea26b0a Merge pull request #1008 from CatimaLoyalty/create-pull-request/patch-1662271250
Update contributors
2022-09-04 10:08:42 +02:00
TheLastProject dc2c73baa6 Update contributors 2022-09-04 06:00:50 +00:00
Sylvia van Os b8db8bffd4 Merge pull request #1004 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-09-01 19:04:31 +02:00
Csaba 6a078e983b Translated using Weblate (Hungarian)
Currently translated at 93.4% (244 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2022-09-01 14:20:07 +02:00
Neko Nekowazarashi bdfc74759f Translated using Weblate (Indonesian)
Currently translated at 2.6% (3 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/id/
2022-09-01 14:20:07 +02:00
Neko Nekowazarashi b13e14c916 Translated using Weblate (Indonesian)
Currently translated at 79.6% (208 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2022-09-01 14:20:07 +02:00
Tom Sawyer 32adb85c5b Translated using Weblate (Swedish)
Currently translated at 100.0% (261 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2022-09-01 14:20:07 +02:00
J. Lavoie a51854e5de Translated using Weblate (Finnish)
Currently translated at 98.0% (256 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2022-09-01 14:20:07 +02:00
Fede Pujol 9ce72bbaaa Translated using Weblate (Spanish (Argentina))
Currently translated at 32.1% (84 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es_AR/
2022-09-01 14:20:07 +02:00
Jean-Luc Tibaux 544020febf Translated using Weblate (German)
Currently translated at 64.2% (72 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2022-09-01 14:20:07 +02:00
Sylvia van Os 9cfc45e495 Merge pull request #1000 from CatimaLoyalty/create-pull-request/patch-1661666017
Update contributors
2022-08-28 11:22:22 +02:00
TheLastProject 992ed32d7c Update contributors 2022-08-28 05:53:36 +00:00
Sylvia van Os ac4f83b9e0 Merge pull request #999 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-08-27 08:53:31 +02:00
ce i moa 5810d199fc Translated using Weblate (Ukrainian)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-08-27 01:18:43 +02:00
Sylvia van Os 8528e5d8f2 Make spotBugs happy 2022-08-25 19:38:53 +02:00
Sylvia van Os 83d19c30c2 Throw more exceptions
We want to know when the code is wrong instead of silently failing
2022-08-25 19:28:09 +02:00
646dab336d Merge #997
997: Translations update from Hosted Weblate r=TheLastProject a=weblate

Translations update from [Hosted Weblate](https://hosted.weblate.org) for [Catima/Android](https://hosted.weblate.org/projects/catima/catima/).


It also includes following components:

* [Catima/Android (Fastlane)](https://hosted.weblate.org/projects/catima/fastlane/)



Current translation status:

![Weblate translation status](https://hosted.weblate.org/widgets/catima/-/catima/horizontal-auto.svg)

Co-authored-by: Booc Sylvan <sylvanbooc@gmail.com>
Co-authored-by: ce i moa <serhiilinnyk96@gmail.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2022-08-24 20:49:25 +00:00
Sylvia van Os d05e86cd41 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-08-24 22:45:34 +02:00
ce i moa 6d1c5b31f4 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-08-24 22:05:55 +02:00
Booc Sylvan 583cb49949 Added translation using Weblate (English (Middle)) 2022-08-24 22:05:55 +02:00
Sylvia van Os 7f5c7b4cd9 Merge pull request #996 from CatimaLoyalty/dependabot/gradle/org.robolectric-robolectric-4.8.2
Bump robolectric from 4.8.1 to 4.8.2
2022-08-23 06:29:27 +02:00
Sylvia van Os 17350639aa Merge pull request #995 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-08-23 06:28:39 +02:00
dependabot[bot] edb961085a Bump robolectric from 4.8.1 to 4.8.2
Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.8.1 to 4.8.2.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.8.1...robolectric-4.8.2)

---
updated-dependencies:
- dependency-name: org.robolectric:robolectric
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-23 02:25:42 +00:00
Slávek Banko 96c5952869 Translated using Weblate (Czech)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-08-23 03:15:52 +02:00
Michael Moroni 2bac1700d1 Translated using Weblate (Italian)
Currently translated at 16.9% (19 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2022-08-23 03:15:52 +02:00
tfuxu fe2695e6af Translated using Weblate (Polish)
Currently translated at 100.0% (261 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-08-23 03:15:52 +02:00
Sylvia van Os 2120eb9574 Merge pull request #993 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-08-22 08:01:54 +02:00
Slávek Banko 03917a4067 Translated using Weblate (Czech)
Currently translated at 100.0% (112 of 112 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-08-22 01:19:30 +02:00
bc09a23c84 Merge #992
992: Translations update from Hosted Weblate r=TheLastProject a=weblate

Translations update from [Hosted Weblate](https://hosted.weblate.org) for [Catima/Android](https://hosted.weblate.org/projects/catima/catima/).


It also includes following components:

* [Catima/Android (Fastlane)](https://hosted.weblate.org/projects/catima/fastlane/)



Current translation status:

![Weblate translation status](https://hosted.weblate.org/widgets/catima/-/catima/horizontal-auto.svg)

Co-authored-by: tfuxu <igormakarowicz@gmail.com>
Co-authored-by: Altons <marsupilami450@gmail.com>
2022-08-21 22:24:54 +00:00
Altons 0ed800634c Translated using Weblate (French)
Currently translated at 21.6% (24 of 111 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-08-22 00:21:45 +02:00
tfuxu ff4ecfe780 Translated using Weblate (Polish)
Currently translated at 100.0% (261 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-08-22 00:21:45 +02:00
Sylvia van Os 2691442809 Merge pull request #990 from CatimaLoyalty/create-pull-request/patch-1661059784
Update contributors
2022-08-21 11:37:19 +02:00
TheLastProject 18515e2660 Update contributors 2022-08-21 05:29:43 +00:00
Sylvia van Os df5cbaf7ad Merge pull request #989 from CatimaLoyalty/create-pull-request/patch-1661004562
Update Fastlane changelogs
2022-08-20 16:11:32 +02:00
TheLastProject 3cacd03ccd Update Fastlane changelogs 2022-08-20 14:09:21 +00:00
Sylvia van Os 2ec04dfa9e Update CHANGELOG 2022-08-20 16:09:05 +02:00
Sylvia van Os 6943956c37 Merge pull request #988 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-08-20 16:06:20 +02:00
Sylvia van Os 26f0f7909e Merge pull request #987 from Donnnno/monochrome-icon
monochrome icon
2022-08-20 16:05:50 +02:00
gbonaspetti 2a1682133b Translated using Weblate (Portuguese)
Currently translated at 100.0% (261 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2022-08-20 15:22:38 +02:00
Donnnno 02897f312e monochrome icon 2022-08-20 14:46:52 +02:00
Sylvia van Os 7d4d4cf5c0 Merge pull request #986 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-08-19 17:12:21 +02:00
IllusiveMan196 1fcf797bfe Translated using Weblate (Ukrainian)
Currently translated at 40.5% (45 of 111 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-08-19 04:20:01 +02:00
IllusiveMan196 b94d417157 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (261 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2022-08-19 04:20:01 +02:00
HowITsDone 330227d09b Translated using Weblate (Spanish)
Currently translated at 72.0% (188 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2022-08-19 04:20:01 +02:00
Sylvia van Os 67f1ffe617 Merge pull request #985 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-08-16 19:07:24 +02:00
Ahmed Saleh 220d7a5ea2 Translated using Weblate (Arabic)
Currently translated at 100.0% (261 of 261 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ar/
2022-08-16 16:15:41 +02:00
1503 changed files with 20848 additions and 8167 deletions

No files matched your search

+6 -7
View File
@@ -1,11 +1,10 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gradle" # See documentation for possible values
directory: "/" # Location of package manifests
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
+27 -14
View File
@@ -1,41 +1,54 @@
name: Android CI
on:
workflow_dispatch:
push:
branches:
- master
- main
- staging
- trying
pull_request:
branches:
- master
- main
permissions:
actions: none
checks: none
contents: read
deployments: none
discussions: none
id-token: none
issues: none
packages: none
pages: none
pull-requests: none
repository-projects: none
security-events: none
statuses: none
env:
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4.0.0
- 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/wrapper-validation-action@v1
- name: set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
- name: set up OpenJDK 17
run: |
sudo apt-get update
sudo apt-get install -y openjdk-17-jdk-headless
sudo update-alternatives --auto java
- name: Build
run: ./gradlew assembleRelease
- name: Check lint
run: ./gradlew lintRelease
- name: Run unit tests
run: ./gradlew testReleaseUnitTest || ./gradlew testReleaseUnitTest
run: timeout 5m ./gradlew testReleaseUnitTest || { ./gradlew --stop && timeout 5m ./gradlew testReleaseUnitTest; }
- name: SpotBugs
run: ./gradlew spotbugsRelease
- name: Archive test results
if: always()
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3.1.3
with:
name: test-results
path: app/build/reports
@@ -1,24 +0,0 @@
name: 'Close issues and PRs needing info for too long'
on:
schedule:
- cron: '30 1 * * *'
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
with:
days-before-stale: -1
days-before-close: 90
close-issue-message: 'This issue is missing necessary information and cannot be worked on in its current state. It has therefore been closed to keep the issue tracker clean. If you have more information, feel free to reopen it.'
close-pr-message: 'This PR is missing necessary information and cannot be merged in its current state. It has therefore been closed to keep the issue tracker clean. If you have more information, feel free to reopen it.'
only-labels: 'state: needs info'
stale-issue-label: 'state: needs info'
stale-pr-label: 'state: needs info'
remove-stale-when-updated: false
enable-statistics: true
@@ -1,34 +0,0 @@
name: Compress Images on Push to Master
on:
push:
branches:
- master
paths:
- '**.jpg'
- '**.jpeg'
- '**.png'
- '**.webp'
jobs:
build:
# Only run on Pull Requests within the same repository, and not from forks.
if: github.event.pull_request.head.repo.full_name == github.repository
name: calibreapp/image-actions
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v2
- name: Compress Images
id: calibre
uses: calibreapp/image-actions@1.1.0
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
ignorePaths: 'app/src/test'
compressOnly: true
- name: Create New Pull Request If Needed
if: steps.calibre.outputs.markdown != ''
uses: peter-evans/create-pull-request@v3
with:
title: Compressed Images
branch-suffix: timestamp
commit-message: Compressed Images
body: ${{ steps.calibre.outputs.markdown }}
+21 -5
View File
@@ -1,9 +1,25 @@
name: Convert CHANGELOG to Fastlane
on:
workflow_dispatch:
push:
branches:
- master
- main
paths:
- 'CHANGELOG.md'
permissions:
actions: none
checks: none
contents: write
deployments: none
discussions: none
id-token: none
issues: none
packages: none
pages: none
pull-requests: write
repository-projects: none
security-events: none
statuses: none
jobs:
convert_changelog_to_fastlane:
runs-on: ubuntu-latest
@@ -11,15 +27,15 @@ jobs:
steps:
- name: Checkout repo
id: checkout
uses: actions/checkout@v2
uses: actions/checkout@v4.0.0
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4.7.0
with:
python-version: '3.x'
- name: Run converter script
run: python .scripts/changelog_to_fastlane.py
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
uses: peter-evans/create-pull-request@v5.0.2
with:
title: "Update Fastlane changelogs"
commit-message: "Update Fastlane changelogs"
-73
View File
@@ -1,73 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches:
- master
pull_request:
# The branches below must be a subset of the branches above
branches:
- master
schedule:
- cron: '33 1 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+19 -5
View File
@@ -1,24 +1,38 @@
name: Write contributors to file
on:
workflow_dispatch:
schedule:
- cron: '3 4 * * 0'
permissions:
actions: none
checks: none
contents: write
deployments: none
discussions: none
id-token: none
issues: none
packages: none
pages: none
pull-requests: write
repository-projects: none
security-events: none
statuses: none
jobs:
contributors_to_file:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
if: github.ref == 'refs/heads/main'
name: Write contributors to file
steps:
- name: Checkout repo
id: checkout
uses: actions/checkout@v2
uses: actions/checkout@v4.0.0
- name: Update contributors
id: update_contributors
uses: TheLastProject/contributors-to-file-action@v2
uses: TheLastProject/contributors-to-file-action@v3.0.1
with:
file_in_repo: app/src/main/res/raw/contributors.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
uses: peter-evans/create-pull-request@v5.0.2
with:
title: "Update contributors"
commit-message: "Update contributors"
@@ -0,0 +1,77 @@
name: Generate feature graphic
on:
workflow_dispatch:
push:
branches:
- main
paths:
- 'fastlane/**/title.txt'
permissions:
actions: none
checks: none
contents: write
deployments: none
discussions: none
id-token: none
issues: none
packages: none
pages: none
pull-requests: write
repository-projects: none
security-events: none
statuses: none
jobs:
generate-feature-graphic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.0.0
- name: Install requirements
run: |
sudo apt-get update
sudo apt-get install optipng mat2
# Install 200 weight versions of relevant Noto (to use for languages not supported by Lexend Deca)
sudo apt-get install fonts-noto-extra fonts-noto-cjk-extra
# Custom fonts
mkdir "$HOME/.fonts"
find .scripts/generate_feature_graphic/fonts -name '*.ttf' -exec cp {} "$HOME/.fonts" \;
fc-cache
- name: Generate featureGraphic.png for each language
run: |
for lang in fastlane/metadata/android/*; do
pushd "$lang"
# Place temporary copy for editing if needed
cp ../../../../.scripts/generate_feature_graphic/featureGraphic.svg featureGraphic.svg
# Extract text after 'Catima - '
export subtext="$(grep -oP '(?<=Catima \S ).*' title.txt || true)"
# If there is subtext, change the .svg accordingly
if [ -n "$subtext" ]; then
perl -pi -e 's/Loyalty Card Wallet/$ENV{subtext}/' featureGraphic.svg
# Set correct font for language if needed (Lexend Deca has limited support)
# We specifically need the Serif version because of the 200 weight
case "$(basename "$lang")" in
bg|el-GR|ru-RU|uk) sed -i "s/Lexend Deca/Noto Serif/" featureGraphic.svg ;;
ja-JP) sed -i "s/Lexend Deca/Noto Serif CJK JP/" featureGraphic.svg ;;
ko) sed -i "s/Lexend Deca/Noto Serif CJK KR/" featureGraphic.svg ;;
zh-CN) sed -i "s/Lexend Deca/Noto Serif CJK SC/" featureGraphic.svg ;;
zh-TW) sed -i "s/Lexend Deca/Noto Serif CJK TC/" featureGraphic.svg ;;
*) ;;
esac
fi
# Ensure images directory exists
mkdir -p images
# Generate .png
convert featureGraphic.svg images/featureGraphic.png
# Optimize .png
optipng images/featureGraphic.png
# Remove metadata (timestamps) from .png
mat2 --inplace images/featureGraphic.png
# Remove temporary .svg
rm featureGraphic.svg
popd
done
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5.0.2
with:
title: "Update feature graphic"
commit-message: "Update feature graphic"
branch-suffix: timestamp
+35
View File
@@ -0,0 +1,35 @@
name: Update locales
on:
workflow_dispatch:
push:
branches:
- main
paths:
- app/src/main/res/values/settings.xml
permissions:
actions: none
checks: none
contents: write
deployments: none
discussions: none
id-token: none
issues: none
packages: none
pages: none
pull-requests: write
repository-projects: none
security-events: none
statuses: none
jobs:
update-locales:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.0.0
- name: Update locales
run: .scripts/locales.py
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5.0.2
with:
title: "Update locales"
commit-message: "Update locales"
branch-suffix: timestamp
+5
View File
@@ -8,3 +8,8 @@ captures/
**/release
**/debug
app/*.log
# Bundle
/.bundle/
/vendor/bundle
/lib/bundler/man/
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/python3
import csv
import json
import msgpack
MSGPACK = "bootstrapdata.msgpack"
OUTFILE = "stocard_stores.csv"
def load(fh):
data = []
for r in msgpack.Unpacker(fh, raw=False):
if r["collection"] == "/loyalty-card-providers/":
d = json.loads(r["data"])
data.append([r["resource_id"], d["name"], d["default_barcode_format"]])
return data
def save(data, output_file=OUTFILE):
with open(output_file, "w") as fh:
writer = csv.writer(fh, lineterminator="\n")
writer.writerow(["_id", "name", "barcodeFormat"])
for row in data:
writer.writerow(row)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(
epilog=f"INPUT_FILE must be a .msgpack or .apk and defaults to {MSGPACK}; "
f"OUTPUT_FILE defaults to {OUTFILE}")
parser.add_argument("input_file", metavar="INPUT_FILE", nargs="?", default=MSGPACK)
parser.add_argument("output_file", metavar="OUTPUT_FILE", nargs="?", default=OUTFILE)
args = parser.parse_args()
if args.input_file.lower().endswith(".apk"):
import zipfile
with zipfile.ZipFile(args.input_file) as zf:
with zf.open(f"assets/{MSGPACK}") as fh:
data = load(fh)
else:
with open(args.input_file, "rb") as fh:
data = load(fh)
save(data, args.output_file)
@@ -0,0 +1,15 @@
<svg width="1024" height="500" viewBox="0 0 1024 500" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="1024" height="500" fill="#223355"/>
<text fill="white" xml:space="preserve" style="" font-family="Yesteryear" font-size="150" letter-spacing="0em"><tspan x="470.082" y="285.511">Catima
</tspan></text>
<path d="M381.046 147.001L236.3 211.446L276.524 301.79L421.27 237.345L381.046 147.001Z" fill="#F0F0F0" stroke="#C80000" stroke-width="2"/>
<path d="M402.077 219.13L240.07 147L191.984 255.004L353.99 327.135L402.077 219.13Z" fill="#F0F0F0" stroke="#C80000" stroke-width="2"/>
<path d="M437.17 236.241L251.831 183.096L220.071 293.855L405.41 347L437.17 236.241Z" fill="#C80000" stroke="#C80000" stroke-width="6" stroke-linejoin="round"/>
<path d="M412.879 178.633H220.071V293.855H412.879V178.633Z" fill="#FF0000" stroke="#FF0000" stroke-width="6" stroke-linejoin="round"/>
<path d="M221.482 296.217C238.316 296.217 251.963 269.366 251.963 236.244C251.963 203.121 238.316 176.27 221.482 176.27C204.647 176.27 191 203.121 191 236.244C191 269.366 204.647 296.217 221.482 296.217Z" fill="#FF0000" stroke="#FF0000" stroke-width="3.44232" stroke-linejoin="round"/>
<path d="M307.256 250.444C307.256 253.187 306.289 255.842 304.526 257.944C302.763 260.045 300.316 261.458 297.614 261.934C294.913 262.41 292.13 261.92 289.755 260.548C287.379 259.177 285.563 257.012 284.625 254.435" stroke="#F0F0F0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M330.301 254.298C329.363 256.875 327.547 259.04 325.171 260.411C322.796 261.783 320.013 262.273 317.312 261.797C314.61 261.321 312.163 259.908 310.4 257.807C308.637 255.706 307.671 253.05 307.671 250.307" stroke="#F0F0F0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M248.345 225.937L266.818 207.465L285.29 225.937" stroke="#F0F0F0" stroke-width="2"/>
<path d="M329.625 225.937L348.098 207.465L366.571 225.937" stroke="#F0F0F0" stroke-width="2"/>
<text fill="white" xml:space="preserve" style="" font-family="Lexend Deca" font-size="35" font-weight="200" letter-spacing="0em"><tspan x="466" y="340">Loyalty Card Wallet</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,93 @@
Copyright 2018 The Lexend Project Authors (https://github.com/googlefonts/lexend), with Reserved Font Name “RevReading Lexend”.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,94 @@
Copyright (c) 2011 by Brian J. Bonislawsky DBA Astigmatic (AOETI)
(astigma@astigmatic.com), with Reserved Font Names "Yesteryear"
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/python3
import subprocess
import xml.etree.ElementTree as ET
root = ET.parse("app/src/main/res/values/settings.xml").getroot()
for e in root.findall("string-array"):
if e.get("name") == "locale_values":
locales = [x.text for x in e if x.text]
break
locales = [
# e.g. de or es-rAR (not es-AR)
loc.replace("-", "-r") if "-" in loc and loc[loc.index("-") + 1] != "r" else loc
for loc in locales
]
res = ", ".join(f'"{loc}"' for loc in locales)
sed = [
"sed",
"-i",
f"s/resourceConfigurations .*/resourceConfigurations += [{res}]/",
"app/build.gradle"
]
subprocess.run(sed, check=True)
with open("app/src/main/res/xml/locales_config.xml", "w") 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')
for loc in locales:
if loc != "en":
# e.g. de or en-AR (not es-rAR)
loc = loc.replace("-r", "-")
fh.write(f' <locale android:name="{loc}" />\n')
fh.write('</locale-config>\n')
+106 -6
View File
@@ -1,16 +1,116 @@
# Changelog
## v2.19.0 - 113
## Unreleased - 132
- Refine "Add card" workflow
- Validation flow improvements
## v2.26.0 - 131 (2023-09-14)
- Move "Archive mode" into "Display options" (previously "Show details") menu
- Android 13 per-app language support
- Embed privacy policy, changelog and license in the app
## v2.25.3 - 130 (2023-08-25)
- Minor UI fixes
- Fix valid from and expiry dates being reset when rotating the card editing screen
- Fix crash when rotating screen while the color picker is shown
- Stocard import fixes
## v2.25.2 - 129 (2023-07-27)
- Improved Catima importer (fixes cards missing when importing)
- Fix crash when rotating screen while setting valid from/expiry date
- Minor UI tweaks
## v2.25.1 - 128 (2023-07-17)
- Fix rare crash
## v2.25.0 - 127 (2023-07-09)
- Barcode rendering improvements
- Basic interoperability with external apps (Android 6.0+)
- Reorganized settings screen
- Fix importing from some browsers that add a trailing / to the share URL
## v2.24.2 - 126 (2023-06-18)
- Various RTL fixes
## v2.24.1 - 125 (2023-06-11)
- Deal more gracefully with missing header colours
## v2.24.0 - 124 (2023-06-10)
- Support selecting exactly which details to view in card overview
## v2.23.3 - 123 (2023-06-03)
- Minor UI improvements
- Fix new design not being usable on devices with square screens
## v2.23.2 - 122 (2023-05-30)
- Long-press card icon in view activity to change it
- Improve button styling in Groups screen
- Fix long barcode values causing barcode to scale down to nothing
## v2.23.1 - 121 (2023-05-27)
- Update used libraries
## v2.23.0 - 120 (2023-05-25)
- Complete redesign of main and loyalty card view screens
- Material You design for the settings screen
- Fix crash when using "Take a photo" with disabled camera app
## v2.22.1 - 119 (2023-04-14)
- Use Material You colours on more devices (Google library update)
## v2.22.0 - 118 (2023-03-18)
- Support setting start of card validity
- Fix Stocard import (Stocard's export format changed)
## v2.21.2 - 117 (2023-01-27)
- Remove unnecessary permissions
- Target Android 13
## v2.21.1 - 116 (2022-12-06)
- Fix quick spend dialog not allowing , separator
- Support loading image from file manager
## v2.21.0 - 115 (2022-11-06)
- Open image in gallery on long-press
- Apply Material style to dialogs
- Support creating card by sharing an image to Catima
- Add quick spend button to card screen
## v2.20.0 - 114 (2022-09-21)
- Add Monochrome icon for Android 13
- Improve first launch screen
- Fidme import fixes
## v2.19.0 - 113 (2022-08-14)
- Add previous and next buttons to the loyalty card view
- Fix foreground colour on edit button
- Replace floppy disk save icon with checkmark
## v2.18.2 - 112
## v2.18.2 - 112 (2022-07-29)
- Make the possibility to set a custom header more visible
## v2.18.1 - 111
## v2.18.1 - 111 (2022-07-24)
- Arabic language support
- Display archived card count in group overview
@@ -20,11 +120,11 @@
- Fix crash when leaving cardview in RTL layouts for cards with expiry or balance
- Fix back arrow in card view pointing the wrong way in RTL layouts
## v2.17.1 - 109
## v2.17.1 - 109 (2022-06-28)
- Fix incorrect text colour on "No barcode" button
## v2.17.0 - 108
## v2.17.0 - 108 (2022-06-24)
- Add card duplication feature
- Don't allow choosing expiry before 1970 (they never worked anyway)
@@ -586,7 +686,7 @@ Additional features/improvements:
## v0.7 - 7 (2016-07-14)
- Long-click of a card brings up option to copy card ID to the clipboard. ([pull #49](https://github.com/brarcher/loyalty-card-locker/issues/49))
- Back button on Input/Export view now works, moving user to main view
- Back button on Import/Export view now works, moving user to main view
## v0.6 - 6 (2016-05-23)
+19 -6
View File
@@ -8,7 +8,20 @@ to the rules described here, but by following the instructions below you
should have a much easier time getting your work merged with the upstream
project.
## Test Your Code
## Translation Changes
Translation changes are managed through [Weblate](https://hosted.weblate.org/projects/catima/).
Please do not supply translation updates directly through GitHub.
Weblate requires an account to translate changes, so please log in before
you start translating.
While using Weblate, please do not ignore any of its warnings. They exist
for good reason.
## Code Changes
### Test Your Code
There are four possible tests you can run to verify your code. The first
is unit tests, which check the basic functionality of the application, and
@@ -28,14 +41,14 @@ and SpotBugs, run using:
The final check is by testing the application on a live device and verifying
the basic functionality works as expected.
## Make Sure Your Code is Tested
### Make Sure Your Code is Tested
The Catima code uses a fair number of unit tests to verify that
the basic functionality is working. Submissions which add functionality
or significantly change the existing code should include additional tests
to verify the proper operation of the proposed changes.
## Explain Your Work
### Explain Your Work
At the top of every patch you should include a description of the problem you
are trying to solve, how you solved it, and why you chose the solution you
@@ -44,7 +57,7 @@ if you can describe/include a reproducer for the problem in the description as
well as instructions on how to test for the bug and verify that it has been
fixed.
## Sign Your Work
### Sign Your Work
The sign-off is a simple line at the end of the patch description, which
certifies that you wrote it or otherwise have the right to pass it on as an
@@ -82,10 +95,10 @@ your real name, saying:
Signed-off-by: Random J Developer <random@developer.example.org>
## Submit Patch(es) for Review
### Submit Patch(es) for Review
Finally, you will need to submit your patches so that they can be reviewed
and potentially merged into the main Catima repository. The preferred
way to do this is to submit a Pull Request to the Catima project.
Changes need to apply cleanly onto the master branch and pass all
Changes need to apply cleanly onto the main branch and pass all
unit tests and produce no errors during static analysis.
+53 -54
View File
@@ -1,27 +1,27 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.5)
CFPropertyList (3.0.6)
rexml
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.597.0)
aws-sdk-core (3.131.1)
aws-partitions (1.824.0)
aws-sdk-core (3.181.1)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.57.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (1.71.0)
aws-sdk-core (~> 3, >= 3.177.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.114.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-s3 (1.134.0)
aws-sdk-core (~> 3, >= 3.181.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.0)
aws-sigv4 (~> 1.6)
aws-sigv4 (1.6.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.1.0)
@@ -30,14 +30,14 @@ GEM
commander (4.6.0)
highline (~> 2.0.0)
declarative (0.0.20)
digest-crc (0.6.4)
digest-crc (0.6.5)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
dotenv (2.8.1)
emoji_regex (3.2.3)
excon (0.92.3)
faraday (1.10.0)
excon (0.103.0)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
@@ -65,8 +65,8 @@ GEM
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.6)
fastlane (2.206.2)
fastimage (2.2.7)
fastlane (2.215.1)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@@ -87,10 +87,11 @@ GEM
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2)
optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0)
@@ -98,7 +99,7 @@ GEM
security (= 0.1.3)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
@@ -106,9 +107,9 @@ GEM
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.21.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-core (0.5.0)
google-apis-androidpublisher_v3 (0.49.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.1)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
@@ -117,30 +118,29 @@ GEM
retriable (>= 2.0, < 4.a)
rexml
webrick
google-apis-iamcredentials_v1 (0.10.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-playcustomapp_v1 (0.7.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-storage_v1 (0.14.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.19.0)
google-apis-core (>= 0.9.0, < 2.a)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.2.0)
google-cloud-storage (1.36.2)
google-cloud-errors (1.3.1)
google-cloud-storage (1.44.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.19.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.1.3)
googleauth (1.8.0)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
@@ -148,42 +148,41 @@ GEM
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.6.1)
json (2.6.2)
jwt (2.4.1)
memoist (0.16.2)
mini_magick (4.11.0)
mini_mime (1.1.2)
jmespath (1.6.2)
json (2.6.3)
jwt (2.7.1)
mini_magick (4.12.0)
mini_mime (1.1.5)
multi_json (1.15.0)
multipart-post (2.0.0)
multipart-post (2.3.0)
nanaimo (0.3.0)
naturally (2.2.1)
optparse (0.1.1)
os (1.1.4)
plist (3.6.0)
public_suffix (4.0.7)
plist (3.7.0)
public_suffix (5.0.3)
rake (13.0.6)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.5)
rexml (3.2.6)
rouge (2.0.7)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.3)
signet (0.16.1)
signet (0.18.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.0)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
simctl (1.6.10)
CFPropertyList
naturally
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.1)
@@ -193,10 +192,10 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
webrick (1.7.0)
unicode-display_width (2.4.2)
webrick (1.8.1)
word_wrap (1.0.0)
xcodeproj (1.21.0)
xcodeproj (1.22.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
@@ -215,4 +214,4 @@ DEPENDENCIES
fastlane
BUNDLED WITH
2.1.4
2.3.26
+18
View File
@@ -0,0 +1,18 @@
**Last updated**
August 30 2023
# Privacy Policy
Catima does not collect or transmit any personal information.
To ensure correct app functionality, we require access to the following:
- Camera: We need access to your camera to be able to scan barcodes. The app can still be used when camera access is denied, but you will have to manually type the barcode information.
- Storage (Android 5 and 6 only): We need access to your device storage to create or import backups. The app can still be used when storage access is denied, but you will not be able to create or import backups.
Catima offers a feature to share cards with other users. All the relevant data is in the generated shareable URLs and never transmitted to our servers. When viewed through catima.app, the data in the URL is rendered using client-side Javascript to further ensure no data is ever transmitted to us.
# Changes
This Privacy Policy may be updated from time to time for any reason. We will notify you of any changes to our Privacy Policy by posting the new Privacy Policy to https://catima.app/privacy-policy/. A snapshot of the Privacy Policy is available within the Catima app, though it may be outdated. When the Privacy Policy on the website and in the app differ, the website should be considered leading. You are advised to consult the Privacy Policy regularly for any changes, as continued use is deemed approval of all changes.
# Contact us
If you have any questions regarding privacy while using the Application, or have questions about our practices, please contact us via email at catima.g9ex3@hackerchick.me.
+13
View File
@@ -0,0 +1,13 @@
# Security Policy
Catima is designed to use as little permissions as possible to limit both the attack surface as well as the damage that can be done when abusing a security flaw.
## Supported Versions
Only the most recent stable release is supported.
## Reporting a Vulnerability
Security vulnerabilities can be reported through [GitHub Security Advisories](https://github.com/CatimaLoyalty/Android/security/advisories) or [the contact info written on my personal website](https://sylviavanos.nl/#contact). Currently, Matrix is the only end-to-end encrypted option.
Please note that only security vulnerabilities in Catima should be reported as stated above. For other issues, including antivirus false positives and malicious applications trying to trick people into granting them Catima's "Read Cards" permission, please use [regular issues](https://github.com/CatimaLoyalty/Android/issues).
+63 -23
View File
@@ -1,7 +1,9 @@
import com.github.spotbugs.snom.SpotBugsTask
apply plugin: 'com.android.application'
apply plugin: 'com.github.spotbugs'
plugins {
id 'com.android.application'
id 'com.github.spotbugs'
}
spotbugs {
ignoreFailures = false
@@ -11,18 +13,32 @@ spotbugs {
}
android {
compileSdkVersion 31
buildToolsVersion "31.0.0"
compileSdk 33
defaultConfig {
applicationId "me.hackerchick.catima"
minSdkVersion 21
targetSdkVersion 31
versionCode 113
versionName "2.19.0"
minSdk 21
targetSdk 33
versionCode 131
versionName "2.26.0"
vectorDrawables.useSupportLibrary true
multiDexEnabled true
resourceConfigurations += ["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", "ro-rRO", "ru", "sk", "sl", "sv", "tr", "uk", "zh-rTW", "zh-rCN"]
//testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
flavorDimensions "version"
productFlavors {
fdroid {
dimension "version"
}
screengrab {
dimension "version"
applicationIdSuffix = ".screengrab"
}
}
buildTypes {
@@ -37,6 +53,10 @@ android {
}
}
buildFeatures {
viewBinding true
}
bundle {
language {
enableSplit = false
@@ -53,10 +73,6 @@ android {
targetCompatibility JavaVersion.VERSION_11
}
lintOptions {
disable "GoogleAppIndexingWarning", "ButtonStyle", "AlwaysShowAction",
"MissingTranslation", "MissingPrefix"
}
sourceSets {
test {
@@ -76,37 +92,46 @@ android {
includeAndroidResources true
}
}
lint {
lintConfig file('lint.xml')
}
namespace 'protect.card_locker'
}
dependencies {
// AndroidX
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.exifinterface:exifinterface:1.3.6'
implementation 'androidx.palette:palette:1.0.0'
implementation 'androidx.preference:preference:1.2.0'
implementation 'com.google.android.material:material:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'com.github.yalantis:ucrop:2.2.8'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
// Splash Screen
implementation 'androidx.core:core-splashscreen:1.0.0'
implementation 'androidx.core:core-splashscreen:1.0.1'
// Third-party
implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
implementation 'com.google.zxing:core:3.5.0'
implementation 'com.google.zxing:core:3.5.2'
implementation 'org.apache.commons:commons-csv:1.9.0'
implementation 'com.jaredrummler:colorpicker:1.1.0'
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.4'
implementation 'net.lingala.zip4j:zip4j:2.11.1'
implementation 'net.lingala.zip4j:zip4j:2.11.5'
// SpotBugs
implementation 'io.wcm.tooling.spotbugs:io.wcm.tooling.spotbugs.annotations:1.0.0'
// Testing
testImplementation 'androidx.test:core:1.4.0'
testImplementation 'androidx.test:core:1.5.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.8.1'
testImplementation 'org.robolectric:robolectric:4.10.3'
// Screenshots
testImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
testImplementation 'com.android.support.test:rules:1.0.2'
testImplementation 'com.android.support.test:runner:1.0.2'
testImplementation 'tools.fastlane:screengrab:2.1.1'
}
tasks.withType(SpotBugsTask) {
@@ -123,3 +148,18 @@ tasks.withType(SpotBugsTask) {
html.enabled = true
}
}
tasks.register('copyRawResFiles', Copy) {
from layout.projectDirectory.file("../CHANGELOG.md"),
layout.projectDirectory.file("../PRIVACY.md")
into layout.projectDirectory.dir("src/main/res/raw")
rename { String fileName -> fileName.toLowerCase() }
}
project.afterEvaluate {
tasks.each { task ->
if (task != copyRawResFiles) {
task.dependsOn(copyRawResFiles)
}
}
}
+3
View File
@@ -6,5 +6,8 @@
<Match>
<Class name="~.*Manifest\$.*"/>
</Match>
<Match>
<Class name="~.*Binding" />
</Match>
</FindBugsFilter>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="AlwaysShowAction" severity="ignore" />
<issue id="ButtonStyle" severity="ignore" />
<issue id="GoogleAppIndexingWarning" severity="ignore" />
<issue id="MissingTranslation" severity="ignore" />
<issue id="MissingPrefix" severity="ignore" />
</lint>
+57 -7
View File
@@ -1,13 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="protect.card_locker">
xmlns:tools="http://schemas.android.com/tools">
<permission
android:description="@string/permissionReadCardsDescription"
android:icon="@drawable/ic_launcher_foreground"
android:label="@string/permissionReadCardsLabel"
android:name="${applicationId}.READ_CARDS"
android:protectionLevel="dangerous" />
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="23" />
<uses-feature
android:name="android.hardware.camera"
@@ -22,7 +27,8 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme"
android:localeConfig="@xml/locales_config">
<activity
android:name=".MainActivity"
android:exported="true"
@@ -33,6 +39,12 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
<activity
android:name=".AboutActivity"
@@ -102,7 +114,39 @@
<activity
android:name=".ImportExportActivity"
android:label="@string/importExport"
android:theme="@style/AppTheme.NoActionBar" />
android:exported="true"
android:theme="@style/AppTheme.NoActionBar">
<!-- ZIP Intent Filter -->
<intent-filter
android:label="@string/importCards">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/zip" />
<data android:scheme="content"/>
<data android:host="*"/>
</intent-filter>
<!-- JSON Intent Filter -->
<intent-filter
android:label="@string/importCards">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/json" />
<data android:scheme="content"/>
<data android:host="*"/>
</intent-filter>
<!-- CSV Intent Filter -->
<intent-filter
android:label="@string/importCards">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content"/>
<data android:host="*" />
<data android:mimeType="text/comma-separated-values" />
</intent-filter>
</activity>
<activity
android:name=".CardShortcutConfigure"
android:exported="true"
@@ -119,6 +163,12 @@
android:name=".UCropWrapper"
android:theme="@style/AppTheme.NoActionBar" />
<provider
android:name=".contentprovider.CardsContentProvider"
android:authorities="${applicationId}.contentprovider.cards"
android:exported="true"
android:readPermission="${applicationId}.READ_CARDS"/>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
@@ -135,4 +185,4 @@
</intent-filter>
</service>
</application>
</manifest>
</manifest>
@@ -1,135 +1,57 @@
package protect.card_locker;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.text.Spanned;
import android.view.MenuItem;
import android.view.View;
import android.widget.ScrollView;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import androidx.annotation.StringRes;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.text.HtmlCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import protect.card_locker.databinding.AboutActivityBinding;
public class AboutActivity extends CatimaAppCompatActivity {
public class AboutActivity extends CatimaAppCompatActivity implements View.OnClickListener {
private static final String TAG = "Catima";
ConstraintLayout version_history, translate, license, repo, privacy, error, credits, rate;
private AboutActivityBinding binding;
private AboutContent content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.about);
setContentView(R.layout.about_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
binding = AboutActivityBinding.inflate(getLayoutInflater());
content = new AboutContent(this);
setTitle(content.getPageTitle());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
enableToolbarBackButton();
StringBuilder contributors = new StringBuilder().append("<br/>");
TextView copyright = binding.creditsSub;
copyright.setText(content.getCopyrightShort());
TextView versionHistory = binding.versionHistorySub;
versionHistory.setText(content.getVersionHistory());
BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.contributors), StandardCharsets.UTF_8));
binding.versionHistory.setTag("https://catima.app/changelog/");
binding.translate.setTag("https://hosted.weblate.org/engage/catima/");
binding.license.setTag("https://github.com/CatimaLoyalty/Android/blob/main/LICENSE");
binding.repo.setTag("https://github.com/CatimaLoyalty/Android/");
binding.privacy.setTag("https://catima.app/privacy-policy/");
binding.reportError.setTag("https://github.com/CatimaLoyalty/Android/issues");
binding.rate.setTag("https://play.google.com/store/apps/details?id=me.hackerchick.catima");
binding.donate.setTag("https://catima.app/contribute/#donating");
try {
while (true) {
String tmp = reader.readLine();
boolean installedFromGooglePlay = Utils.installedFromGooglePlay(this);
// Hide Google Play rate button if not on Google Play
binding.rate.setVisibility(installedFromGooglePlay ? View.VISIBLE : View.GONE);
// Hide donate button on Google Play (Google Play doesn't allow donation links)
binding.donate.setVisibility(installedFromGooglePlay ? View.GONE : View.VISIBLE);
if (tmp == null || tmp.isEmpty()) {
reader.close();
break;
}
contributors.append("<br/>");
contributors.append(tmp);
}
} catch (IOException ignored) {
}
final List<ThirdPartyInfo> USED_LIBRARIES = new ArrayList<>();
USED_LIBRARIES.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("Commons CSV", "https://commons.apache.org/proper/commons-csv/", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("NumberPickerPreference", "https://github.com/invissvenska/NumberPickerPreference", "GNU LGPL 3.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("Zip4j", "https://github.com/srikanth-lingala/zip4j", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("ZXing", "https://github.com/zxing/zxing", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded", "Apache 2.0"));
final List<ThirdPartyInfo> USED_ASSETS = new ArrayList<>();
USED_ASSETS.add(new ThirdPartyInfo("Android icons", "https://fonts.google.com/icons?selected=Material+Icons", "Apache 2.0"));
StringBuilder libs = new StringBuilder().append("<br/>");
for (ThirdPartyInfo entry : USED_LIBRARIES) {
libs.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")");
}
StringBuilder resources = new StringBuilder().append("<br/>");
for (ThirdPartyInfo entry : USED_ASSETS) {
resources.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")");
}
String appName = getString(R.string.app_name);
int year = Calendar.getInstance().get(Calendar.YEAR);
String version = "?";
try {
PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0);
version = pi.versionName;
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Package name not found", e);
}
TextView copyright = findViewById(R.id.credits_sub);
copyright.setText(String.format(getString(R.string.app_copyright_fmt), year));
TextView vHistory = findViewById(R.id.version_history_sub);
vHistory.setText(String.format(getString(R.string.debug_version_fmt), version));
setTitle(String.format(getString(R.string.about_title_fmt), appName));
version_history = findViewById(R.id.version_history);
translate = findViewById(R.id.translate);
license = findViewById(R.id.license);
repo = findViewById(R.id.repo);
privacy = findViewById(R.id.privacy);
error = findViewById(R.id.report_error);
credits = findViewById(R.id.credits);
rate = findViewById(R.id.rate);
version_history.setOnClickListener(this);
translate.setOnClickListener(this);
license.setOnClickListener(this);
repo.setOnClickListener(this);
privacy.setOnClickListener(this);
error.setOnClickListener(this);
rate.setOnClickListener(this);
StringBuilder contributorInfo = new StringBuilder();
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_contributors), contributors.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
contributorInfo.append("\n\n");
contributorInfo.append(getString(R.string.app_copyright_old));
contributorInfo.append("\n\n");
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_libraries), libs.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
contributorInfo.append("\n\n");
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_resources), resources.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
credits.setOnClickListener(view -> new AlertDialog.Builder(this)
.setTitle(R.string.credits)
.setMessage(contributorInfo.toString())
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
})
.show());
bindClickListeners();
}
@Override
@@ -142,31 +64,79 @@ public class AboutActivity extends CatimaAppCompatActivity implements View.OnCli
}
@Override
public void onClick(View view) {
int id = view.getId();
String url;
if (id == R.id.version_history) {
url = "https://catima.app/changelog/";
} else if (id == R.id.translate) {
url = "https://hosted.weblate.org/engage/catima/";
} else if (id == R.id.license) {
url = "https://github.com/CatimaLoyalty/Android/blob/master/LICENSE";
} else if (id == R.id.repo) {
url = "https://github.com/CatimaLoyalty/Android/";
} else if (id == R.id.privacy) {
url = "https://catima.app/privacy-policy/";
} else if (id == R.id.report_error) {
url = "https://github.com/CatimaLoyalty/Android/issues";
} else if (id == R.id.rate) {
url = "https://play.google.com/store/apps/details?id=me.hackerchick.catima";
} else {
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
protected void onDestroy() {
super.onDestroy();
content.destroy();
clearClickListeners();
binding = null;
}
private void bindClickListeners() {
binding.versionHistory.setOnClickListener(this::showHistory);
binding.translate.setOnClickListener(this::openExternalBrowser);
binding.license.setOnClickListener(this::showLicense);
binding.repo.setOnClickListener(this::openExternalBrowser);
binding.privacy.setOnClickListener(this::showPrivacy);
binding.reportError.setOnClickListener(this::openExternalBrowser);
binding.rate.setOnClickListener(this::openExternalBrowser);
binding.donate.setOnClickListener(this::openExternalBrowser);
binding.credits.setOnClickListener(view -> showCredits());
}
private void clearClickListeners() {
binding.versionHistory.setOnClickListener(null);
binding.translate.setOnClickListener(null);
binding.license.setOnClickListener(null);
binding.repo.setOnClickListener(null);
binding.privacy.setOnClickListener(null);
binding.reportError.setOnClickListener(null);
binding.rate.setOnClickListener(null);
binding.donate.setOnClickListener(null);
binding.credits.setOnClickListener(null);
}
private void showCredits() {
new MaterialAlertDialogBuilder(this)
.setTitle(R.string.credits)
.setMessage(content.getContributorInfo())
.setPositiveButton(R.string.ok, null)
.show();
}
private void showHistory(View view) {
showHTML(R.string.version_history, content.getHistoryInfo(), view);
}
private void showLicense(View view) {
showHTML(R.string.license, content.getLicenseInfo(), view);
}
private void showPrivacy(View view) {
showHTML(R.string.privacy_policy, content.getPrivacyInfo(), view);
}
private void showHTML(@StringRes int title, final Spanned text, View view) {
int dialogContentPadding = getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_padding);
TextView textView = new TextView(this);
textView.setText(text);
Utils.makeTextViewLinksClickable(textView, text);
ScrollView scrollView = new ScrollView(this);
scrollView.addView(textView);
scrollView.setPadding(dialogContentPadding, dialogContentPadding / 2, dialogContentPadding, 0);
new MaterialAlertDialogBuilder(this)
.setTitle(title)
.setView(scrollView)
.setPositiveButton(R.string.ok, null)
.setNeutralButton(R.string.view_online, (dialog, which) -> openExternalBrowser(view))
.show();
}
private void openExternalBrowser(View view) {
Object tag = view.getTag();
if (tag instanceof String && ((String) tag).startsWith("https://")) {
(new OpenWebLinkHandler()).openBrowser(this, (String) tag);
}
}
}
@@ -0,0 +1,162 @@
package protect.card_locker;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.Spanned;
import android.util.Log;
import androidx.core.text.HtmlCompat;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class AboutContent {
public static final String TAG = "Catima";
public Context context;
public AboutContent(Context context) {
this.context = context;
}
public void destroy() {
this.context = null;
}
public String getPageTitle() {
return String.format(context.getString(R.string.about_title_fmt), context.getString(R.string.app_name));
}
public String getAppVersion() {
String version = "?";
try {
PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
version = pi.versionName;
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Package name not found", e);
}
return version;
}
public int getCurrentYear() {
return Calendar.getInstance().get(Calendar.YEAR);
}
public String getCopyright() {
return String.format(context.getString(R.string.app_copyright_fmt), getCurrentYear());
}
public String getCopyrightShort() {
return context.getString(R.string.app_copyright_short);
}
public String getContributors() {
String contributors;
try {
contributors = "<br/>" + Utils.readTextFile(context, R.raw.contributors);
} catch (IOException ignored) {
return "";
}
return contributors.replace("\n", "<br />");
}
public String getHistory() {
String versionHistory;
try {
versionHistory = Utils.readTextFile(context, R.raw.changelog)
.replace("# Changelog\n\n", "");
} catch (IOException ignored) {
return "";
}
return Utils.linkify(Utils.basicMDToHTML(versionHistory))
.replace("\n", "<br />");
}
public String getLicense() {
try {
return Utils.readTextFile(context, R.raw.license);
} catch (IOException ignored) {
return "";
}
}
public String getPrivacy() {
String privacyPolicy;
try {
privacyPolicy = Utils.readTextFile(context, R.raw.privacy)
.replace("# Privacy Policy\n", "");
} catch (IOException ignored) {
return "";
}
return Utils.linkify(Utils.basicMDToHTML(privacyPolicy))
.replace("\n", "<br />");
}
public String getThirdPartyLibraries() {
final List<ThirdPartyInfo> usedLibraries = new ArrayList<>();
usedLibraries.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0"));
usedLibraries.add(new ThirdPartyInfo("Commons CSV", "https://commons.apache.org/proper/commons-csv/", "Apache 2.0"));
usedLibraries.add(new ThirdPartyInfo("NumberPickerPreference", "https://github.com/invissvenska/NumberPickerPreference", "GNU LGPL 3.0"));
usedLibraries.add(new ThirdPartyInfo("uCrop", "https://github.com/Yalantis/uCrop", "Apache 2.0"));
usedLibraries.add(new ThirdPartyInfo("Zip4j", "https://github.com/srikanth-lingala/zip4j", "Apache 2.0"));
usedLibraries.add(new ThirdPartyInfo("ZXing", "https://github.com/zxing/zxing", "Apache 2.0"));
usedLibraries.add(new ThirdPartyInfo("ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded", "Apache 2.0"));
StringBuilder result = new StringBuilder("<br/>");
for (ThirdPartyInfo entry : usedLibraries) {
result.append("<br/>")
.append(entry.toHtml());
}
return result.toString();
}
public String getUsedThirdPartyAssets() {
final List<ThirdPartyInfo> usedAssets = new ArrayList<>();
usedAssets.add(new ThirdPartyInfo("Android icons", "https://fonts.google.com/icons?selected=Material+Icons", "Apache 2.0"));
StringBuilder result = new StringBuilder().append("<br/>");
for (ThirdPartyInfo entry : usedAssets) {
result.append("<br/>")
.append(entry.toHtml());
}
return result.toString();
}
public String getContributorInfo() {
StringBuilder contributorInfo = new StringBuilder();
contributorInfo.append(getCopyright());
contributorInfo.append("\n\n");
contributorInfo.append(context.getString(R.string.app_copyright_old));
contributorInfo.append("\n\n");
contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_contributors), getContributors()), HtmlCompat.FROM_HTML_MODE_COMPACT));
contributorInfo.append("\n\n");
contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_libraries), getThirdPartyLibraries()), HtmlCompat.FROM_HTML_MODE_COMPACT));
contributorInfo.append("\n\n");
contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_resources), getUsedThirdPartyAssets()), HtmlCompat.FROM_HTML_MODE_COMPACT));
return contributorInfo.toString();
}
public Spanned getHistoryInfo() {
return HtmlCompat.fromHtml(getHistory(), HtmlCompat.FROM_HTML_MODE_COMPACT);
}
public Spanned getLicenseInfo() {
return HtmlCompat.fromHtml(getLicense(), HtmlCompat.FROM_HTML_MODE_LEGACY);
}
public Spanned getPrivacyInfo() {
return HtmlCompat.fromHtml(getPrivacy(), HtmlCompat.FROM_HTML_MODE_COMPACT);
}
public String getVersionHistory() {
return String.format(context.getString(R.string.debug_version_fmt), getAppVersion());
}
}
@@ -0,0 +1,5 @@
package protect.card_locker;
public interface BarcodeImageWriterResultCallback {
void onBarcodeImageWriterResult(boolean success);
}
@@ -41,13 +41,15 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
private final CatimaBarcode format;
private final int imageHeight;
private final int imageWidth;
private final int imagePadding;
private final boolean widthPadding;
private final boolean showFallback;
private final Runnable callback;
private final BarcodeImageWriterResultCallback callback;
BarcodeImageWriterTask(
Context context, ImageView imageView, String cardIdString,
CatimaBarcode barcodeFormat, TextView textView,
boolean showFallback, Runnable callback, boolean roundCornerPadding
boolean showFallback, BarcodeImageWriterResultCallback callback, boolean roundCornerPadding
) {
mContext = context;
@@ -61,32 +63,39 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
cardId = cardIdString;
format = barcodeFormat;
int padding = 0;
int imageViewHeight = imageView.getHeight();
int imageViewWidth = imageView.getWidth();
// Some barcodes already have internal whitespace and shouldn't get extra padding
// TODO: Get rid of this hack by somehow detecting this extra whitespace
if (roundCornerPadding && !barcodeFormat.hasInternalPadding()) {
padding = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, context.getResources().getDisplayMetrics()));
imagePadding = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, context.getResources().getDisplayMetrics()));
} else {
imagePadding = 0;
}
if (format.isSquare() && imageViewWidth > imageViewHeight) {
imageViewWidth -= imagePadding;
widthPadding = true;
} else {
imageViewHeight -= imagePadding;
widthPadding = false;
}
final int MAX_WIDTH = getMaxWidth(format);
int tempImageHeight;
int tempImageWidth;
if (imageView.getWidth() < MAX_WIDTH) {
tempImageHeight = imageView.getHeight();
tempImageWidth = imageView.getWidth();
if (format.isSquare()) {
imageHeight = imageWidth = Math.min(imageViewHeight, Math.min(MAX_WIDTH, imageViewWidth));
} else if (imageView.getWidth() < MAX_WIDTH) {
imageHeight = imageViewHeight;
imageWidth = imageViewWidth;
} else {
// Scale down the image to reduce the memory needed to produce it
tempImageWidth = MAX_WIDTH;
double ratio = (double) MAX_WIDTH / (double) imageView.getWidth();
tempImageHeight = (int) (imageView.getHeight() * ratio);
imageWidth = MAX_WIDTH;
double ratio = (double) MAX_WIDTH / (double) imageViewWidth;
imageHeight = (int) (imageViewHeight * ratio);
}
// Ensure space for padding if wanted
imageWidth = tempImageWidth;
imageHeight = tempImageHeight - padding;
this.showFallback = showFallback;
}
@@ -94,12 +103,15 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
switch (format.format()) {
// 2D barcodes
case AZTEC:
case DATA_MATRIX:
case MAXICODE:
case PDF_417:
case QR_CODE:
return MAX_WIDTH_2D;
// 2D but rectangular versions get blurry otherwise
case DATA_MATRIX:
return MAX_WIDTH_1D;
// 1D barcodes:
case CODABAR:
case CODE_39:
@@ -261,6 +273,11 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
if (result != null) {
Log.i(TAG, "Displaying barcode");
if (widthPadding) {
imageView.setPadding(imagePadding / 2, 0, imagePadding / 2, 0);
} else {
imageView.setPadding(0, imagePadding / 2, 0, imagePadding / 2);
}
imageView.setVisibility(View.VISIBLE);
if (isSuccesful) {
@@ -282,7 +299,7 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
}
if (callback != null) {
callback.run();
callback.onBarcodeImageWriterResult(isSuccesful);
}
}
@@ -16,9 +16,10 @@ import com.google.zxing.BarcodeFormat;
import java.util.ArrayList;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import protect.card_locker.databinding.BarcodeSelectorActivityBinding;
/**
* This activity is callable and will allow a user to enter
* barcode data and generate all barcodes possible for
@@ -26,6 +27,7 @@ import androidx.appcompat.widget.Toolbar;
* data and type will be returned to the caller.
*/
public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements BarcodeSelectorAdapter.BarcodeSelectorListener {
private BarcodeSelectorActivityBinding binding;
private static final String TAG = "Catima";
// Result this activity will return
@@ -40,17 +42,15 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = BarcodeSelectorActivityBinding.inflate(getLayoutInflater());
setTitle(R.string.selectBarcodeTitle);
setContentView(R.layout.barcode_selector_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setContentView(binding.getRoot());
Toolbar toolbar = binding.toolbar;
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
enableToolbarBackButton();
EditText cardId = findViewById(R.id.cardId);
ListView mBarcodeList = findViewById(R.id.barcodes);
EditText cardId = binding.cardId;
ListView mBarcodeList = binding.barcodes;
mAdapter = new BarcodeSelectorAdapter(this, new ArrayList<>(), this);
mBarcodeList.setAdapter(mAdapter);
@@ -65,10 +65,6 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements
runOnUiThread(() -> {
generateBarcodes(s.toString());
View noBarcodeButtonView = findViewById(R.id.noBarcode);
setButtonListener(noBarcodeButtonView, s.toString());
noBarcodeButtonView.setEnabled(s.length() > 0);
});
}, INPUT_DELAY);
}
@@ -94,17 +90,6 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements
mAdapter.setBarcodes(barcodes);
}
private void setButtonListener(final View button, final String cardId) {
button.setOnClickListener(view -> {
Log.d(TAG, "Selected no barcode");
Intent result = new Intent();
result.putExtra(BARCODE_FORMAT, "");
result.putExtra(BARCODE_CONTENTS, cardId);
BarcodeSelectorActivity.this.setResult(RESULT_OK, result);
finish();
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
@@ -13,6 +13,7 @@ import android.widget.TextView;
import java.util.ArrayList;
import protect.card_locker.async.TaskHandler;
import protect.card_locker.databinding.BarcodeLayoutBinding;
public class BarcodeSelectorAdapter extends ArrayAdapter<CatimaBarcodeWithValue> {
private static final String TAG = "Catima";
@@ -51,9 +52,10 @@ public class BarcodeSelectorAdapter extends ArrayAdapter<CatimaBarcodeWithValue>
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.barcode_layout, parent, false);
viewHolder.image = convertView.findViewById(R.id.barcodeImage);
viewHolder.text = convertView.findViewById(R.id.barcodeName);
BarcodeLayoutBinding barcodeLayoutBinding = BarcodeLayoutBinding.inflate(inflater, parent, false);
convertView = barcodeLayoutBinding.getRoot();
viewHolder.image = barcodeLayoutBinding.barcodeImage;
viewHolder.text = barcodeLayoutBinding.barcodeName;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
@@ -14,10 +14,13 @@ import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.databinding.SimpleToolbarListActivityBinding;
/**
* The configuration screen for creating a shortcut.
*/
public class CardShortcutConfigure extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener {
private SimpleToolbarListActivityBinding binding;
static final String TAG = "Catima";
private SQLiteDatabase mDatabase;
private LoyaltyCardCursorAdapter mAdapter;
@@ -25,15 +28,15 @@ public class CardShortcutConfigure extends CatimaAppCompatActivity implements Lo
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
binding = SimpleToolbarListActivityBinding.inflate(getLayoutInflater());
mDatabase = new DBHelper(this).getReadableDatabase();
// Set the result to CANCELED. This will cause nothing to happen if the
// aback button is pressed.
setResult(RESULT_CANCELED);
setContentView(R.layout.simple_toolbar_list_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setContentView(binding.getRoot());
Toolbar toolbar = binding.toolbar;
toolbar.setTitle(R.string.shortcutSelectCard);
setSupportActionBar(toolbar);
@@ -44,25 +47,19 @@ public class CardShortcutConfigure extends CatimaAppCompatActivity implements Lo
finish();
}
// If all cards are archived, bail
if (DBHelper.getArchivedCardsCount(mDatabase) == cardCount) {
Toast.makeText(this, R.string.noUnarchivedCardsMessage, Toast.LENGTH_LONG).show();
finish();
}
final RecyclerView cardList = findViewById(R.id.list);
final RecyclerView cardList = binding.list;
GridLayoutManager layoutManager = (GridLayoutManager) cardList.getLayoutManager();
if (layoutManager != null) {
layoutManager.setSpanCount(getResources().getInteger(R.integer.main_view_card_columns));
}
Cursor cardCursor = DBHelper.getLoyaltyCardCursor(mDatabase, DBHelper.LoyaltyCardArchiveFilter.Unarchived);
mAdapter = new LoyaltyCardCursorAdapter(this, cardCursor, this);
Cursor cardCursor = DBHelper.getLoyaltyCardCursor(mDatabase, DBHelper.LoyaltyCardArchiveFilter.All);
mAdapter = new LoyaltyCardCursorAdapter(this, cardCursor, this, null);
cardList.setAdapter(mAdapter);
}
private void onClickAction(int position) {
Cursor selected = DBHelper.getLoyaltyCardCursor(mDatabase, DBHelper.LoyaltyCardArchiveFilter.Unarchived);
Cursor selected = DBHelper.getLoyaltyCardCursor(mDatabase, DBHelper.LoyaltyCardArchiveFilter.All);
selected.moveToPosition(position);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
@@ -78,7 +75,7 @@ public class CardShortcutConfigure extends CatimaAppCompatActivity implements Lo
@Override
public boolean onCreateOptionsMenu(Menu inputMenu) {
getMenuInflater().inflate(R.menu.card_details_menu, inputMenu);
Utils.updateMenuCardDetailsButtonState(inputMenu.findItem(R.id.action_unfold), mAdapter.showingDetails());
return super.onCreateOptionsMenu(inputMenu);
}
@@ -86,8 +83,8 @@ public class CardShortcutConfigure extends CatimaAppCompatActivity implements Lo
public boolean onOptionsItemSelected(MenuItem inputItem) {
int id = inputItem.getItemId();
if (id == R.id.action_unfold) {
mAdapter.showDetails(!mAdapter.showingDetails());
if (id == R.id.action_display_options) {
mAdapter.showDisplayOptionsDialog();
invalidateOptionsMenu();
return true;
@@ -1,6 +1,5 @@
package protect.card_locker;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -69,10 +68,9 @@ public class CardsOnPowerScreenService extends ControlsProviderService {
subscriber.onSubscribe(new NoOpSubscription());
for (String controlId : controlIds) {
Control control;
try {
Integer cardId = this.controlIdToCardId(controlId);
LoyaltyCard card = DBHelper.getLoyaltyCard(mDatabase, cardId);
Integer cardId = this.controlIdToCardId(controlId);
LoyaltyCard card = DBHelper.getLoyaltyCard(mDatabase, cardId);
if (card != null) {
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("id", card.id);
@@ -85,7 +83,7 @@ public class CardsOnPowerScreenService extends ControlsProviderService {
.setControlTemplate(new StatelessTemplate(controlId))
.setCustomIcon(Icon.createWithBitmap(getIcon(this, card)))
.build();
} catch (NullPointerException ignored) {
} else {
Intent mainScreenIntent = new Intent(this, MainActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), -1, mainScreenIntent, PendingIntent.FLAG_IMMUTABLE);
@@ -137,7 +135,7 @@ public class CardsOnPowerScreenService extends ControlsProviderService {
closePowerScreenOnAndroid11();
}
@SuppressLint({"MissingPermission", "deprecation"})
@SuppressWarnings({"MissingPermission", "deprecation"})
private void closePowerScreenOnAndroid11() {
// Android 12 will auto-close the power screen, but earlier versions won't
// Lint complains about this but on Android 11 the permission is not needed
@@ -6,8 +6,11 @@ import android.os.Build;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.WindowInsetsControllerCompat;
public class CatimaAppCompatActivity extends AppCompatActivity {
@Override
@@ -29,8 +32,10 @@ public class CatimaAppCompatActivity extends AppCompatActivity {
// XXX changing this in onCreate causes issues with the splash screen activity, so doing this here
boolean darkMode = Utils.isDarkModeEnabled(this);
if (Build.VERSION.SDK_INT >= 23) {
View decorView = getWindow().getDecorView();
WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(getWindow(), decorView);
wic.setAppearanceLightStatusBars(!darkMode);
getWindow().setStatusBarColor(Color.TRANSPARENT);
getWindow().getDecorView().setSystemUiVisibility(darkMode ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
// icons are always white back then
getWindow().setStatusBarColor(darkMode ? Color.TRANSPARENT : Color.argb(127, 0, 0, 0));
@@ -38,4 +43,14 @@ public class CatimaAppCompatActivity extends AppCompatActivity {
// XXX android 9 and below has a nasty rendering bug if the theme was patched earlier
Utils.postPatchColors(this);
}
protected void enableToolbarBackButton() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
public void onMockedRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
}
}
@@ -67,7 +67,6 @@ public class CatimaBarcode {
public boolean isSquare() {
return mBarcodeFormat == BarcodeFormat.AZTEC
|| mBarcodeFormat == BarcodeFormat.DATA_MATRIX
|| mBarcodeFormat == BarcodeFormat.MAXICODE
|| mBarcodeFormat == BarcodeFormat.QR_CODE;
}
@@ -16,12 +16,17 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Currency;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class DBHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "Catima.db";
public static final int ORIGINAL_DATABASE_VERSION = 1;
public static final int DATABASE_VERSION = 15;
public static final int DATABASE_VERSION = 16;
// NB: changing this value requires a migration
public static final int DEFAULT_ZOOM_LEVEL = 100;
public static class LoyaltyCardDbGroups {
public static final String TABLE = "groups";
@@ -33,6 +38,7 @@ public class DBHelper extends SQLiteOpenHelper {
public static final String TABLE = "cards";
public static final String ID = "_id";
public static final String STORE = "store";
public static final String VALID_FROM = "validfrom";
public static final String EXPIRY = "expiry";
public static final String BALANCE = "balance";
public static final String BALANCE_TYPE = "balancetype";
@@ -95,6 +101,7 @@ public class DBHelper extends SQLiteOpenHelper {
LoyaltyCardDbIds.ID + " INTEGER primary key autoincrement," +
LoyaltyCardDbIds.STORE + " TEXT not null," +
LoyaltyCardDbIds.NOTE + " TEXT not null," +
LoyaltyCardDbIds.VALID_FROM + " INTEGER," +
LoyaltyCardDbIds.EXPIRY + " INTEGER," +
LoyaltyCardDbIds.BALANCE + " TEXT not null DEFAULT '0'," +
LoyaltyCardDbIds.BALANCE_TYPE + " TEXT," +
@@ -104,7 +111,7 @@ public class DBHelper extends SQLiteOpenHelper {
LoyaltyCardDbIds.BARCODE_TYPE + " TEXT," +
LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0'," +
LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0', " +
LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '100', " +
LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '" + DEFAULT_ZOOM_LEVEL + "', " +
LoyaltyCardDbIds.ARCHIVE_STATUS + " INTEGER DEFAULT '0' )");
// create associative table for cards in groups
@@ -314,6 +321,26 @@ public class DBHelper extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.ARCHIVE_STATUS + " INTEGER DEFAULT '0' ");
}
if (oldVersion < 16 && newVersion >= 16) {
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.VALID_FROM + " INTEGER");
}
}
public static Set<String> imageFiles(Context context, final SQLiteDatabase database) {
Set<String> files = new HashSet<>();
Cursor cardCursor = getLoyaltyCardCursor(database);
while (cardCursor.moveToNext()) {
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor);
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
String name = Utils.getCardImageFileName(card.id, imageLocationType);
if (Utils.retrieveCardImageAsFile(context, name).exists()) {
files.add(name);
}
}
}
return files;
}
private static ContentValues generateFTSContentValues(final int id, final String store, final String note) {
@@ -358,16 +385,17 @@ public class DBHelper extends SQLiteOpenHelper {
}
public static long insertLoyaltyCard(
final SQLiteDatabase database, final String store, final String note, final Date expiry,
final BigDecimal balance, final Currency balanceType, final String cardId,
final SQLiteDatabase database, final String store, final String note, final Date validFrom,
final Date expiry, final BigDecimal balance, final Currency balanceType, final String cardId,
final String barcodeId, final CatimaBarcode barcodeType, final Integer headerColor,
final int starStatus, final Long lastUsed,final int archiveStatus) {
final int starStatus, final Long lastUsed, final int archiveStatus) {
database.beginTransaction();
// Card
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.STORE, store);
contentValues.put(LoyaltyCardDbIds.NOTE, note);
contentValues.put(LoyaltyCardDbIds.VALID_FROM, validFrom != null ? validFrom.getTime() : null);
contentValues.put(LoyaltyCardDbIds.EXPIRY, expiry != null ? expiry.getTime() : null);
contentValues.put(LoyaltyCardDbIds.BALANCE, balance.toString());
contentValues.put(LoyaltyCardDbIds.BALANCE_TYPE, balanceType != null ? balanceType.getCurrencyCode() : null);
@@ -391,9 +419,10 @@ public class DBHelper extends SQLiteOpenHelper {
public static long insertLoyaltyCard(
final SQLiteDatabase database, final int id, final String store, final String note,
final Date expiry, final BigDecimal balance, final Currency balanceType,
final String cardId, final String barcodeId, final CatimaBarcode barcodeType,
final Integer headerColor, final int starStatus, final Long lastUsed, final int archiveStatus) {
final Date validFrom, final Date expiry, final BigDecimal balance,
final Currency balanceType, final String cardId, final String barcodeId,
final CatimaBarcode barcodeType, final Integer headerColor, final int starStatus,
final Long lastUsed, final int archiveStatus) {
database.beginTransaction();
// Card
@@ -401,6 +430,7 @@ public class DBHelper extends SQLiteOpenHelper {
contentValues.put(LoyaltyCardDbIds.ID, id);
contentValues.put(LoyaltyCardDbIds.STORE, store);
contentValues.put(LoyaltyCardDbIds.NOTE, note);
contentValues.put(LoyaltyCardDbIds.VALID_FROM, validFrom != null ? validFrom.getTime() : null);
contentValues.put(LoyaltyCardDbIds.EXPIRY, expiry != null ? expiry.getTime() : null);
contentValues.put(LoyaltyCardDbIds.BALANCE, balance.toString());
contentValues.put(LoyaltyCardDbIds.BALANCE_TYPE, balanceType != null ? balanceType.getCurrencyCode() : null);
@@ -424,15 +454,17 @@ public class DBHelper extends SQLiteOpenHelper {
public static boolean updateLoyaltyCard(
SQLiteDatabase database, final int id, final String store, final String note,
final Date expiry, final BigDecimal balance, final Currency balanceType,
final String cardId, final String barcodeId, final CatimaBarcode barcodeType,
final Integer headerColor) {
final Date validFrom, final Date expiry, final BigDecimal balance,
final Currency balanceType, final String cardId, final String barcodeId,
final CatimaBarcode barcodeType, final Integer headerColor, final int starStatus,
final Long lastUsed, final int archiveStatus) {
database.beginTransaction();
// Card
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.STORE, store);
contentValues.put(LoyaltyCardDbIds.NOTE, note);
contentValues.put(LoyaltyCardDbIds.VALID_FROM, validFrom != null ? validFrom.getTime() : null);
contentValues.put(LoyaltyCardDbIds.EXPIRY, expiry != null ? expiry.getTime() : null);
contentValues.put(LoyaltyCardDbIds.BALANCE, balance.toString());
contentValues.put(LoyaltyCardDbIds.BALANCE_TYPE, balanceType != null ? balanceType.getCurrencyCode() : null);
@@ -440,6 +472,10 @@ public class DBHelper extends SQLiteOpenHelper {
contentValues.put(LoyaltyCardDbIds.BARCODE_ID, barcodeId);
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.name() : null);
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
contentValues.put(LoyaltyCardDbIds.ARCHIVE_STATUS, archiveStatus);
int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues,
whereAttrs(LoyaltyCardDbIds.ID), withArgs(id));
@@ -490,6 +526,15 @@ public class DBHelper extends SQLiteOpenHelper {
return (rowsUpdated == 1);
}
public static boolean updateLoyaltyCardBalance(SQLiteDatabase database, final int id, final BigDecimal newBalance) {
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.BALANCE, newBalance.toString());
int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues,
whereAttrs(LoyaltyCardDbIds.ID),
withArgs(id));
return (rowsUpdated == 1);
}
public static LoyaltyCard getLoyaltyCard(SQLiteDatabase database, final int id) {
Cursor data = database.query(LoyaltyCardDbIds.TABLE, null, whereAttrs(LoyaltyCardDbIds.ID), withArgs(id), null, null, null);
@@ -7,15 +7,17 @@ import android.database.sqlite.SQLiteDatabase;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageButton;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.databinding.GroupLayoutBinding;
import protect.card_locker.preferences.Settings;
public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder> {
Settings mSettings;
public final Context mContext;
private final GroupAdapterListener mListener;
SQLiteDatabase mDatabase;
@@ -23,7 +25,6 @@ public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.Gro
public GroupCursorAdapter(Context inputContext, Cursor inputCursor, GroupAdapterListener inputListener) {
super(inputCursor, DBHelper.LoyaltyCardDbGroups.ORDER);
setHasStableIds(true);
mSettings = new Settings(inputContext);
mContext = inputContext;
mListener = inputListener;
mDatabase = new DBHelper(inputContext).getReadableDatabase();
@@ -33,9 +34,14 @@ public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.Gro
@NonNull
@Override
public GroupCursorAdapter.GroupListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType) {
View itemView = LayoutInflater.from(inputParent.getContext()).inflate(R.layout.group_layout, inputParent, false);
return new GroupListItemViewHolder(itemView);
public GroupCursorAdapter.GroupListItemViewHolder onCreateViewHolder(@NonNull ViewGroup inputParent, int inputViewType) {
return new GroupListItemViewHolder(
GroupLayoutBinding.inflate(
LayoutInflater.from(inputParent.getContext()),
inputParent,
false
)
);
}
public void onBindViewHolder(GroupListItemViewHolder inputHolder, Cursor inputCursor) {
@@ -56,8 +62,6 @@ public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.Gro
}
inputHolder.mCardCount.setText(cardCountText);
inputHolder.mName.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
inputHolder.mCardCount.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
applyClickEvents(inputHolder);
}
@@ -81,16 +85,16 @@ public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.Gro
public static class GroupListItemViewHolder extends RecyclerView.ViewHolder {
public TextView mName, mCardCount;
public AppCompatImageButton mMoveUp, mMoveDown, mEdit, mDelete;
public Button mMoveUp, mMoveDown, mEdit, mDelete;
public GroupListItemViewHolder(View inputView) {
super(inputView);
mName = inputView.findViewById(R.id.name);
mCardCount = inputView.findViewById(R.id.cardCount);
mMoveUp = inputView.findViewById(R.id.moveUp);
mMoveDown = inputView.findViewById(R.id.moveDown);
mEdit = inputView.findViewById(R.id.edit);
mDelete = inputView.findViewById(R.id.delete);
public GroupListItemViewHolder(GroupLayoutBinding groupLayoutBinding) {
super(groupLayoutBinding.getRoot());
mName = groupLayoutBinding.name;
mCardCount = groupLayoutBinding.cardCount;
mMoveUp = groupLayoutBinding.moveUp;
mMoveDown = groupLayoutBinding.moveDown;
mEdit = groupLayoutBinding.edit;
mDelete = groupLayoutBinding.delete;
}
}
}
@@ -24,21 +24,25 @@ import java.util.List;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import protect.card_locker.async.TaskHandler;
import protect.card_locker.databinding.ImportExportActivityBinding;
import protect.card_locker.importexport.DataFormat;
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 static final int PERMISSIONS_EXTERNAL_STORAGE = 1;
private ImportExportTask importExporter;
private String importAlertTitle;
@@ -55,26 +59,16 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ImportExportActivityBinding.inflate(getLayoutInflater());
setTitle(R.string.importExport);
setContentView(R.layout.import_export_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setContentView(binding.getRoot());
Toolbar toolbar = binding.toolbar;
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
enableToolbarBackButton();
// If the application does not have permissions to external
// storage, ask for it now
if (ContextCompat.checkSelfPermission(ImportExportActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(ImportExportActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(ImportExportActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSIONS_EXTERNAL_STORAGE);
Intent fileIntent = getIntent();
if (fileIntent != null && fileIntent.getType() != null) {
chooseImportType(false, fileIntent.getData());
}
// would use ActivityResultContracts.CreateDocument() but mime type cannot be set
@@ -126,9 +120,9 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
intentCreateDocumentAction.setType("application/zip");
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "catima.zip");
Button exportButton = findViewById(R.id.exportButton);
Button exportButton = binding.exportButton;
exportButton.setOnClickListener(v -> {
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(ImportExportActivity.this);
builder.setTitle(R.string.exportPassword);
FrameLayout container = new FrameLayout(ImportExportActivity.this);
@@ -158,12 +152,12 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
});
// Check that there is a file manager available
Button importFilesystem = findViewById(R.id.importOptionFilesystemButton);
importFilesystem.setOnClickListener(v -> chooseImportType(false));
Button importFilesystem = binding.importOptionFilesystemButton;
importFilesystem.setOnClickListener(v -> chooseImportType(false, null));
// Check that there is an app that data can be imported from
Button importApplication = findViewById(R.id.importOptionApplicationButton);
importApplication.setOnClickListener(v -> chooseImportType(true));
Button importApplication = binding.importOptionApplicationButton;
importApplication.setOnClickListener(v -> chooseImportType(true, null));
}
private void openFileForImport(Uri uri, char[] password) {
@@ -177,7 +171,9 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
}
}
private void chooseImportType(boolean choosePicker) {
private void chooseImportType(boolean choosePicker,
@Nullable Uri fileData) {
List<CharSequence> betaImportOptions = new ArrayList<>();
betaImportOptions.add("Fidme");
betaImportOptions.add("Stocard");
@@ -191,7 +187,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
importOptions.add(importOption);
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(R.string.chooseImportType)
.setItems(importOptions.toArray(new CharSequence[importOptions.size()]), (dialog, which) -> {
switch (which) {
@@ -229,7 +225,12 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
throw new IllegalArgumentException("Unknown DataFormat");
}
new AlertDialog.Builder(this)
if (fileData != null) {
openFileForImport(fileData, null);
return;
}
new MaterialAlertDialogBuilder(this)
.setTitle(importAlertTitle)
.setMessage(importAlertMessage)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@@ -296,30 +297,6 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
mTasks.executeTask(TaskHandler.TYPE.EXPORT, importExporter);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_EXTERNAL_STORAGE) {
// If request is cancelled, the result arrays are empty.
boolean success = grantResults.length > 0;
for (int grant : grantResults) {
if (grant != PackageManager.PERMISSION_GRANTED) {
success = false;
}
}
if (!success) {
// External storage permission rejected, inform user that
// import/export is prevented
Toast.makeText(getApplicationContext(), R.string.noExternalStoragePermissionError,
Toast.LENGTH_LONG).show();
}
}
}
@Override
protected void onDestroy() {
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, true, false, false);
@@ -340,7 +317,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
}
private void retryWithPassword(DataFormat dataFormat, Uri uri) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(R.string.passwordRequired);
final EditText input = new EditText(this);
@@ -383,7 +360,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
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());
@@ -394,7 +371,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
private void onExportComplete(ImportExportResult result, final Uri path) {
ImportExportResultType resultType = result.resultType();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
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());
@@ -18,6 +18,7 @@ import java.util.List;
public class ImportURIHelper {
private static final String STORE = DBHelper.LoyaltyCardDbIds.STORE;
private static final String NOTE = DBHelper.LoyaltyCardDbIds.NOTE;
private static final String VALID_FROM = DBHelper.LoyaltyCardDbIds.VALID_FROM;
private static final String EXPIRY = DBHelper.LoyaltyCardDbIds.EXPIRY;
private static final String BALANCE = DBHelper.LoyaltyCardDbIds.BALANCE;
private static final String BALANCE_TYPE = DBHelper.LoyaltyCardDbIds.BALANCE_TYPE;
@@ -45,8 +46,11 @@ public class ImportURIHelper {
}
private boolean isImportUri(Uri uri) {
// Remove trailing slash added by some browsers (if it exists)
final String uriPath = uri.getPath().replaceAll("/$", "");
for (int i = 0; i < hosts.length; i++) {
if (uri.getHost().equals(hosts[i]) && uri.getPath().equals(paths[i])) {
if (uri.getHost().equals(hosts[i]) && uriPath.equals(paths[i])) {
return true;
}
}
@@ -62,6 +66,7 @@ public class ImportURIHelper {
try {
// These values are allowed to be null
CatimaBarcode barcodeType = null;
Date validFrom = null;
Date expiry = null;
BigDecimal balance = new BigDecimal("0");
Currency balanceType = null;
@@ -106,6 +111,10 @@ public class ImportURIHelper {
if (unparsedBalanceType != null && !unparsedBalanceType.equals("")) {
balanceType = Currency.getInstance(unparsedBalanceType);
}
String unparsedValidFrom = kv.get(VALID_FROM);
if (unparsedValidFrom != null && !unparsedValidFrom.equals("")) {
validFrom = new Date(Long.parseLong(unparsedValidFrom));
}
String unparsedExpiry = kv.get(EXPIRY);
if (unparsedExpiry != null && !unparsedExpiry.equals("")) {
expiry = new Date(Long.parseLong(unparsedExpiry));
@@ -116,8 +125,8 @@ public class ImportURIHelper {
headerColor = Integer.parseInt(unparsedHeaderColor);
}
return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100,0);
} catch (NullPointerException | NumberFormatException | UnsupportedEncodingException ex) {
return new LoyaltyCard(-1, store, note, validFrom, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100, 0);
} catch (NumberFormatException | UnsupportedEncodingException | ArrayIndexOutOfBoundsException ex) {
throw new InvalidObjectException("Not a valid import URI");
}
}
@@ -149,6 +158,9 @@ public class ImportURIHelper {
if (loyaltyCard.balanceType != null) {
fragment = appendFragment(fragment, BALANCE_TYPE, loyaltyCard.balanceType.getCurrencyCode());
}
if (loyaltyCard.validFrom != null) {
fragment = appendFragment(fragment, VALID_FROM, String.valueOf(loyaltyCard.validFrom.getTime()));
}
if (loyaltyCard.expiry != null) {
fragment = appendFragment(fragment, EXPIRY, String.valueOf(loyaltyCard.expiry.getTime()));
}
@@ -8,38 +8,41 @@ import java.math.BigDecimal;
import java.util.Currency;
import java.util.Date;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class LoyaltyCard implements Parcelable {
public final int id;
public final String store;
public final String note;
@Nullable
public final Date validFrom;
@Nullable
public final Date expiry;
public final BigDecimal balance;
@Nullable
public final Currency balanceType;
public final String cardId;
@Nullable
public final String barcodeId;
@Nullable
public final CatimaBarcode barcodeType;
@Nullable
public final Integer headerColor;
public final int starStatus;
public final int archiveStatus;
public final long lastUsed;
public int zoomLevel;
public LoyaltyCard(final int id, final String store, final String note, final Date expiry,
final BigDecimal balance, final Currency balanceType, final String cardId,
@Nullable final String barcodeId, @Nullable final CatimaBarcode barcodeType,
@Nullable final Integer headerColor, final int starStatus, final long lastUsed, final int zoomLevel,final int archiveStatus) {
public LoyaltyCard(final int id, final String store, final String note, @Nullable final Date validFrom,
@Nullable final Date expiry, final BigDecimal balance, @Nullable final Currency balanceType,
final String cardId, @Nullable final String barcodeId, @Nullable final CatimaBarcode barcodeType,
@Nullable final Integer headerColor, final int starStatus,
final long lastUsed, final int zoomLevel, final int archiveStatus) {
this.id = id;
this.store = store;
this.note = note;
this.validFrom = validFrom;
this.expiry = expiry;
this.balance = balance;
this.balanceType = balanceType;
@@ -57,6 +60,8 @@ public class LoyaltyCard implements Parcelable {
id = in.readInt();
store = in.readString();
note = in.readString();
long tmpValidFrom = in.readLong();
validFrom = tmpValidFrom != -1 ? new Date(tmpValidFrom) : null;
long tmpExpiry = in.readLong();
expiry = tmpExpiry != -1 ? new Date(tmpExpiry) : null;
balance = (BigDecimal) in.readValue(BigDecimal.class.getClassLoader());
@@ -78,6 +83,7 @@ public class LoyaltyCard implements Parcelable {
parcel.writeInt(id);
parcel.writeString(store);
parcel.writeString(note);
parcel.writeLong(validFrom != null ? validFrom.getTime() : -1);
parcel.writeLong(expiry != null ? expiry.getTime() : -1);
parcel.writeValue(balance);
parcel.writeValue(balanceType);
@@ -95,6 +101,7 @@ public class LoyaltyCard implements Parcelable {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID));
String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE));
String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE));
long validFromLong = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.VALID_FROM));
long expiryLong = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY));
BigDecimal balance = new BigDecimal(cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE)));
String cardId = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID));
@@ -110,6 +117,7 @@ public class LoyaltyCard implements Parcelable {
CatimaBarcode barcodeType = null;
Currency balanceType = null;
Date validFrom = null;
Date expiry = null;
Integer headerColor = null;
@@ -121,6 +129,10 @@ public class LoyaltyCard implements Parcelable {
balanceType = Currency.getInstance(cursor.getString(balanceTypeColumn));
}
if (validFromLong > 0) {
validFrom = new Date(validFromLong);
}
if (expiryLong > 0) {
expiry = new Date(expiryLong);
}
@@ -129,7 +141,25 @@ public class LoyaltyCard implements Parcelable {
headerColor = cursor.getInt(headerColorColumn);
}
return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed, zoomLevel,archived);
return new LoyaltyCard(id, store, note, validFrom, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed, zoomLevel, archived);
}
public static boolean isDuplicate(final LoyaltyCard a, final LoyaltyCard b) {
// Skip lastUsed & zoomLevel
return a.id == b.id && // non-nullable int
a.store.equals(b.store) && // non-nullable String
a.note.equals(b.note) && // non-nullable String
Utils.equals(a.validFrom, b.validFrom) && // nullable Date
Utils.equals(a.expiry, b.expiry) && // nullable Date
a.balance.equals(b.balance) && // non-nullable BigDecimal
Utils.equals(a.balanceType, b.balanceType) && // nullable Currency
a.cardId.equals(b.cardId) && // non-nullable String
Utils.equals(a.barcodeId, b.barcodeId) && // nullable String
Utils.equals(a.barcodeType == null ? null : a.barcodeType.format(),
b.barcodeType == null ? null : b.barcodeType.format()) && // nullable CatimaBarcode with no overridden .equals(), so we need to check .format()
Utils.equals(a.headerColor, b.headerColor) && // nullable Integer
a.starStatus == b.starStatus && // non-nullable int
a.archiveStatus == b.archiveStatus; // non-nullable int
}
@Override
@@ -137,6 +167,31 @@ public class LoyaltyCard implements Parcelable {
return id;
}
@NonNull
@Override
public String toString() {
return String.format(
"LoyaltyCard{%n id=%s,%n store=%s,%n note=%s,%n validFrom=%s,%n expiry=%s,%n"
+ " balance=%s,%n balanceType=%s,%n cardId=%s,%n barcodeId=%s,%n barcodeType=%s,%n"
+ " headerColor=%s,%n starStatus=%s,%n lastUsed=%s,%n zoomLevel=%s,%n archiveStatus=%s%n}",
this.id,
this.store,
this.note,
this.validFrom,
this.expiry,
this.balance,
this.balanceType,
this.cardId,
this.barcodeId,
this.barcodeType != null ? this.barcodeType.format() : null,
this.headerColor,
this.starStatus,
this.lastUsed,
this.zoomLevel,
this.archiveStatus
);
}
public static final Creator<LoyaltyCard> CREATOR = new Creator<LoyaltyCard>() {
@Override
public LoyaltyCard createFromParcel(Parcel in) {
@@ -1,7 +1,6 @@
package protect.card_locker;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -17,75 +16,65 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.google.android.material.card.MaterialCardView;
import com.google.android.material.color.MaterialColors;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Currency;
import java.util.Date;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.BlendModeColorFilterCompat;
import androidx.core.graphics.BlendModeCompat;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.Settings;
import protect.card_locker.databinding.LoyaltyCardLayoutBinding;
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder> {
private int mCurrentSelectedIndex = -1;
Settings mSettings;
boolean mDarkModeEnabled;
public final Context mContext;
private final CardAdapterListener mListener;
private final LoyaltyCardListDisplayOptionsManager mLoyaltyCardListDisplayOptions;
protected SparseBooleanArray mSelectedItems;
protected SparseBooleanArray mAnimationItemsIndex;
private boolean mReverseAllAnimations = false;
private boolean mShowDetails;
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener) {
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener, Runnable inputSwapCursorCallback) {
super(inputCursor, DBHelper.LoyaltyCardDbIds.ID);
setHasStableIds(true);
mSettings = new Settings(inputContext);
mContext = inputContext;
mListener = inputListener;
Runnable refreshCardsCallback = () -> notifyDataSetChanged();
mLoyaltyCardListDisplayOptions = new LoyaltyCardListDisplayOptionsManager(mContext, refreshCardsCallback, inputSwapCursorCallback);
mSelectedItems = new SparseBooleanArray();
mAnimationItemsIndex = new SparseBooleanArray();
mDarkModeEnabled = Utils.isDarkModeEnabled(inputContext);
refreshState();
swapCursor(inputCursor);
}
public void refreshState() {
// Retrieve user details preference
SharedPreferences cardDetailsPref = mContext.getSharedPreferences(
mContext.getString(R.string.sharedpreference_card_details),
Context.MODE_PRIVATE);
mShowDetails = cardDetailsPref.getBoolean(mContext.getString(R.string.sharedpreference_card_details_show), true);
public void showDisplayOptionsDialog() {
mLoyaltyCardListDisplayOptions.showDisplayOptionsDialog();
}
public void showDetails(boolean show) {
mShowDetails = show;
notifyDataSetChanged();
// Store in Shared Preference to restore next adapter launch
SharedPreferences cardDetailsPref = mContext.getSharedPreferences(
mContext.getString(R.string.sharedpreference_card_details),
Context.MODE_PRIVATE);
SharedPreferences.Editor cardDetailsPrefEditor = cardDetailsPref.edit();
cardDetailsPrefEditor.putBoolean(mContext.getString(R.string.sharedpreference_card_details_show), show);
cardDetailsPrefEditor.apply();
}
public boolean showingDetails() {
return mShowDetails;
public boolean showingArchivedCards() {
return mLoyaltyCardListDisplayOptions.showingArchivedCards();
}
@NonNull
@Override
public LoyaltyCardListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType) {
View itemView = LayoutInflater.from(inputParent.getContext()).inflate(R.layout.loyalty_card_layout, inputParent, false);
return new LoyaltyCardListItemViewHolder(itemView, mListener);
public LoyaltyCardListItemViewHolder onCreateViewHolder(@NonNull ViewGroup inputParent, int inputViewType) {
LoyaltyCardLayoutBinding loyaltyCardLayoutBinding = LoyaltyCardLayoutBinding.inflate(
LayoutInflater.from(inputParent.getContext()),
inputParent,
false
);
return new LoyaltyCardListItemViewHolder(loyaltyCardLayoutBinding, mListener);
}
public LoyaltyCard getCard(int position) {
@@ -95,39 +84,47 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor inputCursor) {
// Invisible until we want to show something more
boolean showDivider = false;
inputHolder.mDivider.setVisibility(View.GONE);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(inputCursor);
Bitmap icon = Utils.retrieveCardImage(mContext, loyaltyCard.id, ImageLocationType.icon);
inputHolder.setStoreField(loyaltyCard.store);
if (mShowDetails && !loyaltyCard.note.isEmpty()) {
if (mLoyaltyCardListDisplayOptions.showingNameBelowThumbnail() && icon != null) {
showDivider = true;
inputHolder.setStoreField(loyaltyCard.store);
} else {
inputHolder.setStoreField(null);
}
if (mLoyaltyCardListDisplayOptions.showingNote() && !loyaltyCard.note.isEmpty()) {
showDivider = true;
inputHolder.setNoteField(loyaltyCard.note);
} else {
inputHolder.setNoteField(null);
}
if (mShowDetails && !loyaltyCard.balance.equals(new BigDecimal("0"))) {
inputHolder.setBalanceField(loyaltyCard.balance, loyaltyCard.balanceType);
if (mLoyaltyCardListDisplayOptions.showingBalance() && !loyaltyCard.balance.equals(new BigDecimal("0"))) {
inputHolder.setExtraField(inputHolder.mBalanceField, Utils.formatBalance(mContext, loyaltyCard.balance, loyaltyCard.balanceType), null, showDivider);
} else {
inputHolder.setBalanceField(null, null);
inputHolder.setExtraField(inputHolder.mBalanceField, null, null, false);
}
if (mShowDetails && loyaltyCard.expiry != null) {
inputHolder.setExpiryField(loyaltyCard.expiry);
if (mLoyaltyCardListDisplayOptions.showingValidity() && loyaltyCard.validFrom != null) {
inputHolder.setExtraField(inputHolder.mValidFromField, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.validFrom), Utils.isNotYetValid(loyaltyCard.validFrom) ? Color.RED : null, showDivider);
} else {
inputHolder.setExpiryField(null);
inputHolder.setExtraField(inputHolder.mValidFromField, null, null, false);
}
setHeaderHeight(inputHolder, mShowDetails);
Bitmap cardIcon = Utils.retrieveCardImage(mContext, loyaltyCard.id, ImageLocationType.icon);
if (cardIcon != null) {
inputHolder.mCardIcon.setImageBitmap(cardIcon);
inputHolder.mCardIcon.setScaleType(ImageView.ScaleType.CENTER_CROP);
if (mLoyaltyCardListDisplayOptions.showingValidity() && loyaltyCard.expiry != null) {
inputHolder.setExtraField(inputHolder.mExpiryField, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry), Utils.hasExpired(loyaltyCard.expiry) ? Color.RED : null, showDivider);
} else {
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
inputHolder.mCardIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
inputHolder.setExtraField(inputHolder.mExpiryField, null, null, false);
}
inputHolder.setIconBackgroundColor(loyaltyCard.headerColor != null ? loyaltyCard.headerColor : R.attr.colorPrimary);
inputHolder.mCardIcon.setContentDescription(loyaltyCard.store);
Utils.setIconOrTextWithBackground(mContext, loyaltyCard, icon, inputHolder.mCardIcon, inputHolder.mCardText);
inputHolder.setIconBackgroundColor(Utils.getHeaderColor(mContext, loyaltyCard));
inputHolder.toggleCardStateIcon(loyaltyCard.starStatus != 0, loyaltyCard.archiveStatus != 0, itemSelected(inputCursor.getPosition()));
@@ -139,19 +136,6 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
inputHolder.mRow.requestLayout();
}
private void setHeaderHeight(LoyaltyCardListItemViewHolder inputHolder, boolean expanded) {
int iconHeight;
if (expanded) {
iconHeight = ViewGroup.LayoutParams.MATCH_PARENT;
} else {
iconHeight = (int) mContext.getResources().getDimension(R.dimen.cardThumbnailSize);
}
inputHolder.mIconLayout.getLayoutParams().height = expanded ? 0 : iconHeight;
inputHolder.mCardIcon.getLayoutParams().height = iconHeight;
inputHolder.mTickIcon.getLayoutParams().height = iconHeight;
}
private void applyClickEvents(LoyaltyCardListItemViewHolder inputHolder, final int inputPosition) {
inputHolder.mRow.setOnClickListener(inputView -> mListener.onRowClicked(inputPosition));
@@ -227,32 +211,32 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
public class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder {
public TextView mStoreField, mNoteField, mBalanceField, mExpiryField;
public TextView mCardText, mStoreField, mNoteField, mBalanceField, mValidFromField, mExpiryField;
public ImageView mCardIcon, mStarBackground, mStarBorder, mTickIcon, mArchivedBackground;
public MaterialCardView mRow, mIconLayout;
public MaterialCardView mRow;
public ConstraintLayout mStar, mArchived;
public View mDivider;
private int mIconBackgroundColor;
protected LoyaltyCardListItemViewHolder(View inputView, CardAdapterListener inputListener) {
super(inputView);
mRow = inputView.findViewById(R.id.row);
mDivider = inputView.findViewById(R.id.info_divider);
mStoreField = inputView.findViewById(R.id.store);
mNoteField = inputView.findViewById(R.id.note);
mBalanceField = inputView.findViewById(R.id.balance);
mExpiryField = inputView.findViewById(R.id.expiry);
mIconLayout = inputView.findViewById(R.id.icon_layout);
mCardIcon = inputView.findViewById(R.id.thumbnail);
mStar = inputView.findViewById(R.id.star);
mStarBackground = inputView.findViewById(R.id.star_background);
mStarBorder = inputView.findViewById(R.id.star_border);
mArchived = inputView.findViewById(R.id.archivedIcon);
mArchivedBackground = inputView.findViewById(R.id.archive_background);
mTickIcon = inputView.findViewById(R.id.selected_thumbnail);
protected LoyaltyCardListItemViewHolder(LoyaltyCardLayoutBinding loyaltyCardLayoutBinding, CardAdapterListener inputListener) {
super(loyaltyCardLayoutBinding.getRoot());
View inputView = loyaltyCardLayoutBinding.getRoot();
mRow = loyaltyCardLayoutBinding.row;
mDivider = loyaltyCardLayoutBinding.infoDivider;
mStoreField = loyaltyCardLayoutBinding.store;
mNoteField = loyaltyCardLayoutBinding.note;
mBalanceField = loyaltyCardLayoutBinding.balance;
mValidFromField = loyaltyCardLayoutBinding.validFrom;
mExpiryField = loyaltyCardLayoutBinding.expiry;
mCardIcon = loyaltyCardLayoutBinding.thumbnail;
mCardText = loyaltyCardLayoutBinding.thumbnailText;
mStar = loyaltyCardLayoutBinding.star;
mStarBackground = loyaltyCardLayoutBinding.starBackground;
mStarBorder = loyaltyCardLayoutBinding.starBorder;
mArchived = loyaltyCardLayoutBinding.archivedIcon;
mArchivedBackground = loyaltyCardLayoutBinding.archiveBackground;
mTickIcon = loyaltyCardLayoutBinding.selectedThumbnail;
inputView.setOnLongClickListener(view -> {
inputListener.onRowClicked(getAdapterPosition());
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
@@ -260,9 +244,46 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
});
}
private void setExtraField(TextView field, String text, Integer color, boolean showDivider) {
// If text is null, hide the field
// If iconColor is null, use the default text and icon color based on theme
if (text == null) {
field.setVisibility(View.GONE);
field.requestLayout();
return;
}
// Shown when there is a name and/or note and at least 1 extra field
if (showDivider) {
mDivider.setVisibility(View.VISIBLE);
}
field.setText(text);
field.setTextColor(color != null ? color : MaterialColors.getColor(mContext, com.google.android.material.R.attr.colorSecondary, ContextCompat.getColor(mContext, mDarkModeEnabled ? R.color.md_theme_dark_secondary : R.color.md_theme_light_secondary)));
field.setVisibility(View.VISIBLE);
Drawable icon = field.getCompoundDrawables()[0];
if (icon != null) {
icon.mutate();
field.setCompoundDrawablesRelative(icon, null, null, null);
if (color != null) {
icon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, BlendModeCompat.SRC_ATOP));
} else {
icon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(mDarkModeEnabled ? Color.WHITE : Color.BLACK, BlendModeCompat.SRC_ATOP));
}
}
field.requestLayout();
}
public void setStoreField(String text) {
mStoreField.setText(text);
mStoreField.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
if (text == null) {
mStoreField.setVisibility(View.GONE);
} else {
mStoreField.setVisibility(View.VISIBLE);
mStoreField.setText(text);
}
mStoreField.requestLayout();
}
@@ -272,60 +293,10 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
} else {
mNoteField.setVisibility(View.VISIBLE);
mNoteField.setText(text);
mNoteField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
}
mNoteField.requestLayout();
}
public void setBalanceField(BigDecimal balance, Currency balanceType) {
if (balance == null) {
mBalanceField.setVisibility(View.GONE);
} else {
int size = mSettings.getFontSizeMax(mSettings.getSmallFont());
int drawableSize = dpToPx((size * 24) / 14, mContext);
mDivider.setVisibility(View.VISIBLE);
mBalanceField.setVisibility(View.VISIBLE);
Drawable balanceIcon = mBalanceField.getCompoundDrawables()[0];
if (balanceIcon != null) {
balanceIcon.setBounds(0, 0, drawableSize, drawableSize);
mBalanceField.setCompoundDrawablesRelative(balanceIcon, null, null, null);
if (mDarkModeEnabled) {
balanceIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
}
}
mBalanceField.setText(Utils.formatBalance(mContext, balance, balanceType));
mBalanceField.setTextSize(size);
}
mBalanceField.requestLayout();
}
public void setExpiryField(Date expiry) {
if (expiry == null) {
mExpiryField.setVisibility(View.GONE);
} else {
int size = mSettings.getFontSizeMax(mSettings.getSmallFont());
int drawableSize = dpToPx((size * 24) / 14, mContext);
mDivider.setVisibility(View.VISIBLE);
mExpiryField.setVisibility(View.VISIBLE);
Drawable expiryIcon = mExpiryField.getCompoundDrawables()[0];
if (expiryIcon != null) {
expiryIcon.setBounds(0, 0, drawableSize, drawableSize);
mExpiryField.setCompoundDrawablesRelative(expiryIcon, null, null, null);
if (Utils.hasExpired(expiry)) {
expiryIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.RED, BlendModeCompat.SRC_ATOP));
} else if (mDarkModeEnabled) {
expiryIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
}
}
mExpiryField.setText(DateFormat.getDateInstance(DateFormat.LONG).format(expiry));
if (Utils.hasExpired(expiry)) {
mExpiryField.setTextColor(Color.RED);
}
mExpiryField.setTextSize(size);
}
mExpiryField.requestLayout();
}
public void toggleCardStateIcon(boolean enableStar, boolean enableArchive, boolean colorByTheme) {
/* the below code does not work in android 5! hence the change of drawable instead
boolean needDarkForeground = Utils.needsDarkForeground(mIconBackgroundColor);
File diff suppressed because it is too large. Load diff
@@ -4,6 +4,7 @@ public enum LoyaltyCardField {
id,
store,
note,
validFrom,
expiry,
balance,
balanceType,
@@ -0,0 +1,176 @@
package protect.card_locker;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class LoyaltyCardListDisplayOptionsManager {
public static class LoyaltyCardDisplayOption {
public String name;
public boolean value;
public Consumer<Boolean> callback;
LoyaltyCardDisplayOption(String name, boolean value, Consumer<Boolean> callback) {
this.name = name;
this.value = value;
this.callback = callback;
}
}
public final Context mContext;
private final Runnable mRefreshCardsCallback;
private final Runnable mSwapCursorCallback;
protected SharedPreferences mCardDetailsPref;
private boolean mShowNameBelowThumbnail;
private boolean mShowNote;
private boolean mShowBalance;
private boolean mShowValidity;
private boolean mShowArchivedCards;
public LoyaltyCardListDisplayOptionsManager(Context context, @NonNull Runnable refreshCardsCallback, @Nullable Runnable swapCursorCallback) {
mContext = context;
mRefreshCardsCallback = refreshCardsCallback;
mSwapCursorCallback = swapCursorCallback;
// Retrieve user details preference
mCardDetailsPref = mContext.getSharedPreferences(
mContext.getString(R.string.sharedpreference_card_details),
Context.MODE_PRIVATE);
mShowNameBelowThumbnail = mCardDetailsPref.getBoolean(mContext.getString(R.string.sharedpreference_card_details_show_name_below_thumbnail), false);
mShowNote = mCardDetailsPref.getBoolean(mContext.getString(R.string.sharedpreference_card_details_show_note), true);
mShowBalance = mCardDetailsPref.getBoolean(mContext.getString(R.string.sharedpreference_card_details_show_balance), true);
mShowValidity = mCardDetailsPref.getBoolean(mContext.getString(R.string.sharedpreference_card_details_show_validity), true);
mShowArchivedCards = mCardDetailsPref.getBoolean(mContext.getString(R.string.sharedpreference_card_details_show_archived_cards), true);
}
void saveDetailState(int stateId, boolean value) {
SharedPreferences.Editor cardDetailsPrefEditor = mCardDetailsPref.edit();
cardDetailsPrefEditor.putBoolean(mContext.getString(stateId), value);
cardDetailsPrefEditor.apply();
}
public void showNameBelowThumbnail(boolean show) {
mShowNameBelowThumbnail = show;
mRefreshCardsCallback.run();
saveDetailState(R.string.sharedpreference_card_details_show_name_below_thumbnail, show);
}
public boolean showingNameBelowThumbnail() {
return mShowNameBelowThumbnail;
}
public void showNote(boolean show) {
mShowNote = show;
mRefreshCardsCallback.run();
saveDetailState(R.string.sharedpreference_card_details_show_note, show);
}
public boolean showingNote() {
return mShowNote;
}
public void showBalance(boolean show) {
mShowBalance = show;
mRefreshCardsCallback.run();
saveDetailState(R.string.sharedpreference_card_details_show_balance, show);
}
public boolean showingBalance() {
return mShowBalance;
}
public void showValidity(boolean show) {
mShowValidity = show;
mRefreshCardsCallback.run();
saveDetailState(R.string.sharedpreference_card_details_show_validity, show);
}
public boolean showingValidity() {
return mShowValidity;
}
public void showArchivedCards(boolean show) {
if (mSwapCursorCallback == null) {
throw new IllegalStateException("No swap cursor callback is available, can not manage archive state");
}
mShowArchivedCards = show;
mSwapCursorCallback.run();
saveDetailState(R.string.sharedpreference_card_details_show_archived_cards, show);
}
public boolean showingArchivedCards() {
if (mSwapCursorCallback == null) {
throw new IllegalStateException("No swap cursor callback is available, can not manage archive state");
}
return mShowArchivedCards;
}
public void showDisplayOptionsDialog() {
List<LoyaltyCardDisplayOption> displayOptions = new ArrayList<>();
displayOptions.add(new LoyaltyCardDisplayOption(
mContext.getString(R.string.show_name_below_image_thumbnail),
showingNameBelowThumbnail(),
this::showNameBelowThumbnail
));
displayOptions.add(new LoyaltyCardDisplayOption(
mContext.getString(R.string.show_note),
showingNote(),
this::showNote
));
displayOptions.add(new LoyaltyCardDisplayOption(
mContext.getString(R.string.show_balance),
showingBalance(),
this::showBalance
));
displayOptions.add(new LoyaltyCardDisplayOption(
mContext.getString(R.string.show_validity),
showingValidity(),
this::showValidity
));
// Hide "Show archived cards" option unless the callback exists
if (mSwapCursorCallback != null) {
displayOptions.add(new LoyaltyCardDisplayOption(
mContext.getString(R.string.show_archived_cards),
showingArchivedCards(),
this::showArchivedCards
));
}
// We need to convert Boolean[] to boolean[]
boolean[] values = new boolean[displayOptions.size()];
for (int i = 0; i < values.length; i++) values[i] = displayOptions.get(i).value;
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(mContext);
builder.setTitle(R.string.action_display_options);
builder.setMultiChoiceItems(
displayOptions.stream().map(x -> x.name).toArray(String[]::new),
values,
(dialogInterface, i, b) -> displayOptions.get(i).callback.accept(b)
);
builder.setPositiveButton(R.string.ok, (dialog, i) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
}
}
File diff suppressed because it is too large. Load diff
@@ -9,54 +9,55 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.database.CursorIndexOutOfBoundsException;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.splashscreen.SplashScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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.preferences.SettingsActivity;
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener {
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener {
private MainActivityBinding binding;
private ContentMainBinding contentMainBinding;
private static final String TAG = "Catima";
public static final String RESTART_ACTIVITY_INTENT = "restart_activity_intent";
private static final int MEDIUM_SCALE_FACTOR_DIP = 460;
private SQLiteDatabase mDatabase;
private LoyaltyCardCursorAdapter mAdapter;
private ActionMode mCurrentActionMode;
private SearchView mSearchView;
private GestureDetector mGestureDetector;
private int mLoyaltyCardCount = 0;
protected String mFilter = "";
protected Object mGroup = null;
@@ -64,12 +65,12 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
protected DBHelper.LoyaltyCardOrderDirection mOrderDirection = DBHelper.LoyaltyCardOrderDirection.Ascending;
protected int selectedTab = 0;
private RecyclerView mCardList;
private View mHelpText;
private View mHelpSection;
private View mNoMatchingCardsText;
private View mNoGroupCardsText;
private TabLayout groupsTabLayout;
private boolean mArchiveMode;
public static final String BUNDLE_ARCHIVE_MODE = "archiveMode";
private Runnable mSwapLoyaltyCardListCursor;
private ActivityResultLauncher<Intent> mBarcodeScannerLauncher;
private ActivityResultLauncher<Intent> mSettingsLauncher;
@@ -140,7 +141,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
inputMode.finish();
return true;
} else if (inputItem.getItemId() == R.id.action_delete) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(MainActivity.this);
// The following may seem weird, but it is necessary to give translators enough flexibility.
// For example, in Russian, Android's plural quantity "one" actually refers to "any number ending on 1 but not ending in 11".
// So while in English the extra non-plural form seems unnecessary duplication, it is necessary to give translators enough flexibility.
@@ -162,7 +163,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
ShortcutHelper.removeShortcut(MainActivity.this, loyaltyCard.id);
}
TabLayout.Tab tab = ((TabLayout) findViewById(R.id.groups)).getTabAt(selectedTab);
TabLayout.Tab tab = groupsTabLayout.getTabAt(selectedTab);
mGroup = tab != null ? tab.getTag() : null;
updateLoyaltyCardList(true);
@@ -174,28 +175,25 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
dialog.show();
return true;
}
else if(inputItem.getItemId() == R.id.action_archive){
} else if (inputItem.getItemId() == R.id.action_archive) {
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
Log.d(TAG, "Archiving card: " + loyaltyCard.id);
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id,1);
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id, 1);
updateLoyaltyCardList(false);
inputMode.finish();
invalidateOptionsMenu();
}
return true;
}
else if(inputItem.getItemId() == R.id.action_unarchive){
} else if (inputItem.getItemId() == R.id.action_unarchive) {
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
Log.d(TAG, "Unarchiving card: " + loyaltyCard.id);
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id,0);
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id, 0);
updateLoyaltyCardList(false);
inputMode.finish();
invalidateOptionsMenu();
}
return true;
}
else if(inputItem.getItemId() == R.id.action_star){
} else if (inputItem.getItemId() == R.id.action_star) {
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
Log.d(TAG, "Starring card: " + loyaltyCard.id);
DBHelper.updateLoyaltyCardStarStatus(mDatabase, loyaltyCard.id, 1);
@@ -203,8 +201,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
inputMode.finish();
}
return true;
}
else if(inputItem.getItemId() == R.id.action_unstar){
} else if (inputItem.getItemId() == R.id.action_unstar) {
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
Log.d(TAG, "Unstarring card: " + loyaltyCard.id);
DBHelper.updateLoyaltyCardStarStatus(mDatabase, loyaltyCard.id, 0);
@@ -229,28 +226,25 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
extractIntentFields(getIntent());
SplashScreen.installSplashScreen(this);
super.onCreate(inputSavedInstanceState);
if(!mArchiveMode) {
setTitle(R.string.app_name);
setContentView(R.layout.main_activity);
}
else{
setTitle(R.string.archiveList);
setContentView(R.layout.archive_activity);
}
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if(mArchiveMode){
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
binding = MainActivityBinding.inflate(getLayoutInflater());
setTitle(R.string.app_name);
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
groupsTabLayout = binding.groups;
contentMainBinding = ContentMainBinding.bind(binding.include.getRoot());
mDatabase = new DBHelper(this).getWritableDatabase();
TabLayout groupsTabLayout = findViewById(R.id.groups);
mSwapLoyaltyCardListCursor = () -> {
Group group = null;
if (mGroup != null) {
group = (Group) mGroup;
}
mAdapter.swapCursor(DBHelper.getLoyaltyCardCursor(mDatabase, mFilter, group, mOrder, mOrderDirection, mAdapter.showingArchivedCards() ? DBHelper.LoyaltyCardArchiveFilter.All : DBHelper.LoyaltyCardArchiveFilter.Unarchived));
};
groupsTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
@@ -278,21 +272,12 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
});
mGestureDetector = new GestureDetector(this, this);
mHelpSection = contentMainBinding.helpSection;
mNoMatchingCardsText = contentMainBinding.noMatchingCardsText;
mNoGroupCardsText = contentMainBinding.noGroupCardsText;
mCardList = contentMainBinding.list;
View.OnTouchListener gestureTouchListener = (v, event) -> mGestureDetector.onTouchEvent(event);
mHelpText = findViewById(R.id.helpText);
mNoMatchingCardsText = findViewById(R.id.noMatchingCardsText);
mNoGroupCardsText = findViewById(R.id.noGroupCardsText);
mCardList = findViewById(R.id.list);
mHelpText.setOnTouchListener(gestureTouchListener);
mNoMatchingCardsText.setOnTouchListener(gestureTouchListener);
mCardList.setOnTouchListener(gestureTouchListener);
mNoGroupCardsText.setOnTouchListener(gestureTouchListener);
mAdapter = new LoyaltyCardCursorAdapter(this, null, this);
mAdapter = new LoyaltyCardCursorAdapter(this, null, this, mSwapLoyaltyCardListCursor);
mCardList.setAdapter(mAdapter);
registerForContextMenu(mCardList);
@@ -331,21 +316,17 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
*/
mBarcodeScannerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
// Exit early if the user cancelled the scan (pressed back/home)
if (result.getResultCode() != RESULT_OK) {
return;
}
Intent intent = result.getData();
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(Utils.BARCODE_SCAN, result.getResultCode(), intent, this);
if (!barcodeValues.isEmpty()) {
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
Bundle newBundle = new Bundle();
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_BARCODETYPE, barcodeValues.format());
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, barcodeValues.content());
Bundle inputBundle = intent.getExtras();
if (inputBundle != null && inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) != null) {
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP));
}
newIntent.putExtras(newBundle);
startActivity(newIntent);
}
Bundle inputBundle = intent.getExtras();
String group = inputBundle != null ? inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) : null;
processBarcodeValues(barcodeValues, group);
});
mSettingsLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
@@ -362,8 +343,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
protected void onResume() {
super.onResume();
mAdapter.refreshState();
if (mCurrentActionMode != null) {
mAdapter.clearSelections();
mCurrentActionMode.finish();
@@ -374,21 +353,30 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
// Start of active tab logic
TabLayout groupsTabLayout = findViewById(R.id.groups);
updateTabGroups(groupsTabLayout);
// Restore settings from Shared Preference
// Restore selected tab from Shared Preference
SharedPreferences activeTabPref = getApplicationContext().getSharedPreferences(
getString(R.string.sharedpreference_active_tab),
Context.MODE_PRIVATE);
selectedTab = activeTabPref.getInt(getString(R.string.sharedpreference_active_tab), 0);
// Restore sort preferences from Shared Preferences
// If one of the sorting prefererences has never been set or is set to an invalid value,
// stick to the defaults.
SharedPreferences sortPref = getApplicationContext().getSharedPreferences(
getString(R.string.sharedpreference_sort),
Context.MODE_PRIVATE);
try {
mOrder = DBHelper.LoyaltyCardOrder.valueOf(sortPref.getString(getString(R.string.sharedpreference_sort_order), null));
mOrderDirection = DBHelper.LoyaltyCardOrderDirection.valueOf(sortPref.getString(getString(R.string.sharedpreference_sort_direction), null));
} catch (IllegalArgumentException | NullPointerException ignored) {
String orderString = sortPref.getString(getString(R.string.sharedpreference_sort_order), null);
String orderDirectionString = sortPref.getString(getString(R.string.sharedpreference_sort_direction), null);
if (orderString != null && orderDirectionString != null) {
try {
mOrder = DBHelper.LoyaltyCardOrder.valueOf(orderString);
mOrderDirection = DBHelper.LoyaltyCardOrderDirection.valueOf(orderDirectionString);
} catch (IllegalArgumentException ignored) {
}
}
mGroup = null;
@@ -402,30 +390,30 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
groupsTabLayout.selectTab(tab);
assert tab != null;
mGroup = tab.getTag();
} else {
scaleScreen();
}
updateLoyaltyCardList(true);
// End of active tab logic
if (!mArchiveMode) {
FloatingActionButton addButton = findViewById(R.id.fabAdd);
FloatingActionButton addButton = binding.fabAdd;
addButton.setOnClickListener(v -> {
Intent intent = new Intent(getApplicationContext(), ScanActivity.class);
Bundle bundle = new Bundle();
if (selectedTab != 0) {
bundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, groupsTabLayout.getTabAt(selectedTab).getText().toString());
}
intent.putExtras(bundle);
mBarcodeScannerLauncher.launch(intent);
});
addButton.bringToFront();
}
addButton.setOnClickListener(v -> {
Intent intent = new Intent(getApplicationContext(), ScanActivity.class);
Bundle bundle = new Bundle();
if (selectedTab != 0) {
bundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, groupsTabLayout.getTabAt(selectedTab).getText().toString());
}
intent.putExtras(bundle);
mBarcodeScannerLauncher.launch(intent);
});
addButton.bringToFront();
}
@Override
public void onBackPressed() {
if (!mSearchView.isIconified()) {
if (mSearchView != null && !mSearchView.isIconified()) {
mSearchView.setIconified(true);
return;
}
@@ -434,7 +422,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
private void displayCardSetupOptions(Menu menu, boolean shouldShow) {
for (int id : new int[]{R.id.action_search, R.id.action_unfold, R.id.action_sort}) {
for (int id : new int[]{R.id.action_search, R.id.action_display_options, R.id.action_sort}) {
menu.findItem(id).setVisible(shouldShow);
}
}
@@ -444,12 +432,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
private void updateLoyaltyCardList(boolean updateCount) {
Group group = null;
if (mGroup != null) {
group = (Group) mGroup;
}
mAdapter.swapCursor(DBHelper.getLoyaltyCardCursor(mDatabase, mFilter, group, mOrder, mOrderDirection, mArchiveMode ? DBHelper.LoyaltyCardArchiveFilter.Archived : DBHelper.LoyaltyCardArchiveFilter.Unarchived));
mSwapLoyaltyCardListCursor.run();
if (updateCount) {
updateLoyaltyCardCount();
@@ -461,7 +444,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
// We want the cardList to be visible regardless of the filtered match count
// to ensure that the noMatchingCardsText doesn't end up being shown below
// the keyboard
mHelpText.setVisibility(View.GONE);
mHelpSection.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.GONE);
if (mAdapter.getItemCount() > 0) {
@@ -481,7 +464,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
} else {
mCardList.setVisibility(View.GONE);
mHelpText.setVisibility(View.VISIBLE);
mHelpSection.setVisibility(View.VISIBLE);
mNoMatchingCardsText.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.GONE);
@@ -492,9 +475,68 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
}
private void processBarcodeValues(BarcodeValues barcodeValues, String group) {
if (barcodeValues.isEmpty()) {
throw new IllegalArgumentException("barcodesValues may not be empty");
}
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
Bundle newBundle = new Bundle();
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_BARCODETYPE, barcodeValues.format());
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, barcodeValues.content());
if (group != null) {
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, group);
}
newIntent.putExtras(newBundle);
startActivity(newIntent);
}
private void onSharedIntent(Intent intent) {
String receivedAction = intent.getAction();
String receivedType = intent.getType();
// Check if an image was shared to us
if (Intent.ACTION_SEND.equals(receivedAction)) {
if (!receivedType.startsWith("image/")) {
Log.e(TAG, "Wrong mime-type");
return;
}
BarcodeValues barcodeValues;
Bitmap bitmap;
Uri data = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (data == null) {
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
finish();
return;
}
try {
bitmap = Utils.retrieveImageFromUri(this, data);
} catch (IOException e) {
Log.e(TAG, "Error getting data from image file");
e.printStackTrace();
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
finish();
return;
}
barcodeValues = Utils.getBarcodeFromBitmap(bitmap);
if (barcodeValues.isEmpty()) {
Log.i(TAG, "No barcode found in image file");
Toast.makeText(this, R.string.noBarcodeFound, Toast.LENGTH_LONG).show();
finish();
return;
}
processBarcodeValues(barcodeValues, null);
}
}
private void extractIntentFields(Intent intent) {
final Bundle b = intent.getExtras();
mArchiveMode = b != null && b.getBoolean(BUNDLE_ARCHIVE_MODE, false);
onSharedIntent(intent);
}
public void updateTabGroups(TabLayout groupsTabLayout) {
@@ -526,13 +568,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
@Override
public boolean onCreateOptionsMenu(Menu inputMenu) {
if(!mArchiveMode)
getMenuInflater().inflate(R.menu.main_menu, inputMenu);
else{
getMenuInflater().inflate(R.menu.archive_menu, inputMenu);
}
getMenuInflater().inflate(R.menu.main_menu, inputMenu);
Utils.updateMenuCardDetailsButtonState(inputMenu.findItem(R.id.action_unfold), mAdapter.showingDetails());
displayCardSetupOptions(inputMenu, mLoyaltyCardCount > 0);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
@@ -556,7 +593,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
public boolean onQueryTextChange(String newText) {
mFilter = newText;
TabLayout groupsTabLayout = findViewById(R.id.groups);
TabLayout.Tab currentTab = groupsTabLayout.getTabAt(groupsTabLayout.getSelectedTabPosition());
mGroup = currentTab != null ? currentTab.getTag() : null;
@@ -566,13 +602,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
});
}
if(!mArchiveMode) {
if (DBHelper.getArchivedCardsCount(mDatabase) == 0) {
inputMenu.findItem(R.id.action_archived).setVisible(false);
} else {
inputMenu.findItem(R.id.action_archived).setVisible(true);
}
}
return super.onCreateOptionsMenu(inputMenu);
}
@@ -585,8 +614,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
onBackPressed();
}
if (id == R.id.action_unfold) {
mAdapter.showDetails(!mAdapter.showingDetails());
if (id == R.id.action_display_options) {
mAdapter.showDisplayOptionsDialog();
invalidateOptionsMenu();
return true;
@@ -602,13 +631,15 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(MainActivity.this);
builder.setTitle(R.string.sort_by);
final View customLayout = getLayoutInflater().inflate(R.layout.sorting_option, null);
SortingOptionBinding sortingOptionBinding = SortingOptionBinding
.inflate(LayoutInflater.from(MainActivity.this), null, false);
final View customLayout = sortingOptionBinding.getRoot();
builder.setView(customLayout);
CheckBox showReversed = (CheckBox) customLayout.findViewById(R.id.checkBox_reverse);
CheckBox showReversed = sortingOptionBinding.checkBoxReverse;
showReversed.setChecked(mOrderDirection == DBHelper.LoyaltyCardOrderDirection.Descending);
@@ -658,15 +689,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
return true;
}
if(id == R.id.action_archived){
Intent i = new Intent(getApplicationContext(), MainActivity.class);
Bundle bundle = new Bundle();
bundle.putBoolean("archiveMode", true);
i.putExtras(bundle);
startActivity(i);
return true;
}
return super.onOptionsItemSelected(inputItem);
}
@@ -689,84 +711,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
updateLoyaltyCardList(false);
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
mGestureDetector.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.d(TAG, "On fling");
// Don't swipe if we have too much vertical movement
if (Math.abs(velocityY) > (0.75 * Math.abs(velocityX))) {
return false;
}
TabLayout groupsTabLayout = findViewById(R.id.groups);
if (groupsTabLayout.getTabCount() < 2) {
return false;
}
Integer currentTab = groupsTabLayout.getSelectedTabPosition();
Log.d("onFling", "Current Tab " + currentTab);
// Swipe right
if (velocityX < -150) {
Log.d("onFling", "Right Swipe detected " + velocityX);
Integer nextTab = currentTab + 1;
if (nextTab == groupsTabLayout.getTabCount()) {
groupsTabLayout.selectTab(groupsTabLayout.getTabAt(0));
} else {
groupsTabLayout.selectTab(groupsTabLayout.getTabAt(nextTab));
}
return true;
}
// Swipe left
if (velocityX > 150) {
Log.d("onFling", "Left Swipe detected " + velocityX);
Integer nextTab = currentTab - 1;
if (nextTab < 0) {
groupsTabLayout.selectTab(groupsTabLayout.getTabAt(groupsTabLayout.getTabCount() - 1));
} else {
groupsTabLayout.selectTab(groupsTabLayout.getTabAt(nextTab));
}
return true;
}
return false;
}
@Override
public void onRowLongClicked(int inputPosition) {
enableActionMode(inputPosition);
@@ -779,6 +723,16 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
toggleSelection(inputPosition);
}
private void scaleScreen() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenHeight = displayMetrics.heightPixels;
float mediumSizePx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,MEDIUM_SCALE_FACTOR_DIP,getResources().getDisplayMetrics());
boolean shouldScaleSmaller = screenHeight < mediumSizePx;
binding.include.welcomeIcon.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
}
private void toggleSelection(int inputPosition) {
mAdapter.toggleSelection(inputPosition);
int count = mAdapter.getSelectedItemCount();
@@ -796,31 +750,31 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
boolean hasStarred = false;
boolean hasUnstarred = false;
if(!mArchiveMode) {
unarchiveItem.setVisible(false);
archiveItem.setVisible(true);
}
else{
unarchiveItem.setVisible(true);
archiveItem.setVisible(false);
}
boolean hasArchived = false;
boolean hasUnarchived = false;
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
if (loyaltyCard.starStatus == 1) {
hasStarred = true;
} else {
hasUnstarred = true;
}
if (hasStarred && hasUnstarred) {
hasStarred = true;
hasUnstarred = true;
if (loyaltyCard.archiveStatus == 1) {
hasArchived = true;
} else {
hasUnarchived = true;
}
// We have all types, no need to keep checking
if (hasStarred && hasUnstarred && hasArchived && hasUnarchived) {
break;
}
}
unarchiveItem.setVisible(hasArchived);
archiveItem.setVisible(hasUnarchived);
if (count == 1) {
starItem.setVisible(!hasStarred);
unstarItem.setVisible(!hasUnstarred);
@@ -13,6 +13,7 @@ import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
@@ -20,13 +21,14 @@ import java.util.HashMap;
import java.util.Map;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.RecyclerView;
public class ManageGroupActivity extends CatimaAppCompatActivity implements ManageGroupCursorAdapter.CardAdapterListener {
import protect.card_locker.databinding.ActivityManageGroupBinding;
public class ManageGroupActivity extends CatimaAppCompatActivity implements ManageGroupCursorAdapter.CardAdapterListener {
private ActivityManageGroupBinding binding;
private SQLiteDatabase mDatabase;
private ManageGroupCursorAdapter mAdapter;
@@ -35,7 +37,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
protected Group mGroup = null;
private RecyclerView mCardList;
private TextView mHelpText;
private TextView noGroupCardsText;
private EditText mGroupNameText;
private boolean mGroupNameNotInUse;
@@ -43,17 +45,18 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
@Override
protected void onCreate(Bundle inputSavedInstanceState) {
super.onCreate(inputSavedInstanceState);
setContentView(R.layout.activity_manage_group);
Toolbar toolbar = findViewById(R.id.toolbar);
binding = ActivityManageGroupBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Toolbar toolbar = binding.toolbar;
setSupportActionBar(toolbar);
mDatabase = new DBHelper(this).getWritableDatabase();
mHelpText = findViewById(R.id.helpText);
mCardList = findViewById(R.id.list);
FloatingActionButton saveButton = findViewById(R.id.fabSave);
noGroupCardsText = binding.include.noGroupCardsText;
mCardList = binding.include.list;
FloatingActionButton saveButton = binding.fabSave;
mGroupNameText = findViewById(R.id.editTextGroupName);
mGroupNameText = binding.editTextGroupName;
mGroupNameText.addTextChangedListener(new TextWatcher() {
@Override
@@ -96,7 +99,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
}
mGroupNameText.setText(mGroup._id);
setTitle(getString(R.string.editGroup, mGroup._id));
mAdapter = new ManageGroupCursorAdapter(this, null, this, mGroup);
mAdapter = new ManageGroupCursorAdapter(this, null, this, mGroup, null);
mCardList.setAdapter(mAdapter);
registerForContextMenu(mCardList);
@@ -105,12 +108,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
mGroupNameText.setText(inputSavedInstanceState.getString(SAVE_INSTANCE_CURRENT_GROUP_NAME));
}
ActionBar actionBar = getSupportActionBar();
if (actionBar == null) {
throw (new RuntimeException("mActionBar is not expected to be null here"));
}
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
enableToolbarBackButton();
saveButton.setOnClickListener(v -> {
String currentGroupName = mGroupNameText.getText().toString().trim();
@@ -133,7 +131,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
finish();
});
// this setText is here because content_main.xml is reused from main activity
mHelpText.setText(getResources().getText(R.string.noGiftCardsGroup));
noGroupCardsText.setText(getResources().getText(R.string.noGiftCardsGroup));
updateLoyaltyCardList();
}
@@ -160,7 +158,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
@Override
public boolean onCreateOptionsMenu(Menu inputMenu) {
getMenuInflater().inflate(R.menu.card_details_menu, inputMenu);
Utils.updateMenuCardDetailsButtonState(inputMenu.findItem(R.id.action_unfold), mAdapter.showingDetails());
return super.onCreateOptionsMenu(inputMenu);
}
@@ -168,8 +166,8 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
public boolean onOptionsItemSelected(MenuItem inputItem) {
int id = inputItem.getItemId();
if (id == R.id.action_unfold) {
mAdapter.showDetails(!mAdapter.showingDetails());
if (id == R.id.action_display_options) {
mAdapter.showDisplayOptionsDialog();
invalidateOptionsMenu();
return true;
@@ -191,16 +189,16 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
if (mAdapter.getItemCount() == 0) {
mCardList.setVisibility(View.GONE);
mHelpText.setVisibility(View.VISIBLE);
noGroupCardsText.setVisibility(View.VISIBLE);
} else {
mCardList.setVisibility(View.VISIBLE);
mHelpText.setVisibility(View.GONE);
noGroupCardsText.setVisibility(View.GONE);
}
}
private void leaveWithoutSaving() {
if (hasChanged()) {
AlertDialog.Builder builder = new AlertDialog.Builder(ManageGroupActivity.this);
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(ManageGroupActivity.this);
builder.setTitle(R.string.leaveWithoutSaveTitle);
builder.setMessage(R.string.leaveWithoutSaveConfirmation);
builder.setPositiveButton(R.string.confirm, (dialog, which) -> finish());
@@ -16,8 +16,8 @@ public class ManageGroupCursorAdapter extends LoyaltyCardCursorAdapter {
final private Group mGroup;
final private SQLiteDatabase mDatabase;
public ManageGroupCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener, Group group) {
super(inputContext, inputCursor, inputListener);
public ManageGroupCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener, Group group, Runnable inputSwapCursorCallback) {
super(inputContext, inputCursor, inputListener, inputSwapCursorCallback);
mGroup = new Group(group._id, group.order);
mInGroupOverlay = new HashMap<>();
mDatabase = new DBHelper(inputContext).getWritableDatabase();
@@ -8,23 +8,27 @@ import android.os.Bundle;
import android.text.InputType;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.databinding.ManageGroupsActivityBinding;
public class ManageGroupsActivity extends CatimaAppCompatActivity implements GroupCursorAdapter.GroupAdapterListener {
private ManageGroupsActivityBinding binding;
private static final String TAG = "Catima";
private SQLiteDatabase mDatabase;
@@ -35,14 +39,12 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ManageGroupsActivityBinding.inflate(getLayoutInflater());
setTitle(R.string.groups);
setContentView(R.layout.manage_groups_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setContentView(binding.getRoot());
Toolbar toolbar = binding.toolbar;
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
enableToolbarBackButton();
mDatabase = new DBHelper(this).getWritableDatabase();
}
@@ -51,12 +53,12 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
protected void onResume() {
super.onResume();
FloatingActionButton addButton = findViewById(R.id.fabAdd);
FloatingActionButton addButton = binding.fabAdd;
addButton.setOnClickListener(v -> createGroup());
addButton.bringToFront();
mGroupList = findViewById(R.id.list);
mHelpText = findViewById(R.id.helpText);
mGroupList = binding.include.list;
mHelpText = binding.include.helpText;
// Init group list
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
@@ -109,28 +111,67 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
}
private void createGroup() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
// Header
builder.setTitle(R.string.enter_group_name);
// Layout
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
int contentPadding = getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_padding);
params.leftMargin = contentPadding;
params.topMargin = contentPadding / 2;
params.rightMargin = contentPadding;
// EditText with spacing
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
input.setLayoutParams(params);
layout.addView(input);
// Set layout
builder.setView(layout);
// Buttons
builder.setPositiveButton(getString(R.string.ok), (dialog, which) -> {
String inputString = input.getText().toString().trim();
if (inputString.length() == 0) {
Toast.makeText(getApplicationContext(), R.string.group_name_is_empty, Toast.LENGTH_SHORT).show();
return;
}
if (DBHelper.getGroup(mDatabase, inputString) != null) {
Toast.makeText(getApplicationContext(), R.string.group_name_already_in_use, Toast.LENGTH_SHORT).show();
return;
}
DBHelper.insertGroup(mDatabase, inputString);
DBHelper.insertGroup(mDatabase, input.getText().toString().trim());
updateGroupList();
});
builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel());
AlertDialog dialog = builder.create();
// Now that the dialog exists, we can bind something that affects the OK button
input.addTextChangedListener(new SimpleTextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
String groupName = s.toString().trim();
if (groupName.length() == 0) {
input.setError(getString(R.string.group_name_is_empty));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
return;
}
if (DBHelper.getGroup(mDatabase, groupName) != null) {
input.setError(getString(R.string.group_name_already_in_use));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
return;
}
input.setError(null);
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
}
});
dialog.show();
// Disable button (must be done **after** dialog is shown to prevent crash
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
// Set focus on input field
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
input.requestFocus();
}
@@ -193,7 +234,7 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
public void onDeleteButtonClicked(View view) {
final String groupName = getGroupName(view);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(R.string.deleteConfirmationGroup);
builder.setMessage(groupName);
@@ -0,0 +1,29 @@
package protect.card_locker;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class OpenWebLinkHandler {
private static final String TAG = "Catima";
public void openBrowser(AppCompatActivity activity, String url) {
if (url == null) {
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
try {
activity.startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(activity, R.string.failedToOpenUrl, Toast.LENGTH_LONG).show();
Log.e(TAG, "No activity found to handle intent", e);
}
}
}
@@ -0,0 +1,94 @@
package protect.card_locker;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class PermissionUtils {
/**
* Check if storage read permission is needed.
*
* This is only necessary on Android 6.0 (Marshmallow) and below. See
* https://github.com/CatimaLoyalty/Android/issues/979 for more info.
*
* @param activity
* @return
*/
private static boolean needsStorageReadPermission(Activity activity) {
// Testing showed this permission wasn't needed for anything Catima did past Marshmallow
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return false;
}
return ContextCompat.checkSelfPermission(activity, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
}
/**
* Check if camera permission is needed.
*
* @param activity
* @return
*/
public static boolean needsCameraPermission(Activity activity) {
// Android only introduced the runtime permission system in Marshmallow (Android 6.0)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return false;
}
return ContextCompat.checkSelfPermission(activity, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED;
}
/**
* Call onRequestPermissionsResult after storage read permission was granted.
* Mocks a successful grant if a grant is not necessary.
*
* @param activity
* @param requestCode
*/
public static void requestStorageReadPermission(CatimaAppCompatActivity activity, int requestCode) {
String[] permissions = new String[]{ android.Manifest.permission.READ_EXTERNAL_STORAGE };
int[] mockedResults = new int[]{ PackageManager.PERMISSION_GRANTED };
if (needsStorageReadPermission(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);
}
}
/**
* Call onRequestPermissionsResult after camera permission was granted.
* Mocks a successful grant if a grant is not necessary.
*
* @param activity
* @param requestCode
*/
public static void requestCameraPermission(CatimaAppCompatActivity activity, int requestCode) {
String[] permissions = new String[]{ Manifest.permission.CAMERA };
int[] mockedResults = new int[]{ PackageManager.PERMISSION_GRANTED };
if (needsCameraPermission(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);
}
}
}
@@ -1,17 +1,41 @@
package protect.card_locker;
import static protect.card_locker.BarcodeSelectorActivity.BARCODE_CONTENTS;
import static protect.card_locker.BarcodeSelectorActivity.BARCODE_FORMAT;
import android.Manifest;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.Intents;
import com.journeyapps.barcodescanner.BarcodeCallback;
@@ -21,10 +45,8 @@ import com.journeyapps.barcodescanner.DecoratedBarcodeView;
import java.util.List;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import protect.card_locker.databinding.CustomBarcodeScannerBinding;
import protect.card_locker.databinding.ScanActivityBinding;
/**
* Custom Scannner Activity extending from Activity to display a custom layout form scanner view.
@@ -33,8 +55,15 @@ import androidx.appcompat.widget.Toolbar;
* originally licensed under Apache 2.0
*/
public class ScanActivity extends CatimaAppCompatActivity {
private ScanActivityBinding binding;
private CustomBarcodeScannerBinding customBarcodeScannerBinding;
private static final String TAG = "Catima";
private static final int MEDIUM_SCALE_FACTOR_DIP = 460;
private static final int COMPAT_SCALE_FACTOR_DIP = 320;
private static final int PERMISSION_SCAN_ADD_FROM_IMAGE = 100;
private CaptureManager capture;
private DecoratedBarcodeView barcodeScannerView;
@@ -46,6 +75,9 @@ public class ScanActivity extends CatimaAppCompatActivity {
// can't use the pre-made contract because that launches the file manager for image type instead of gallery
private ActivityResultLauncher<Intent> photoPickerLauncher;
static final String STATE_SCANNER_ACTIVE = "scannerActive";
private boolean mScannerActive = true;
private void extractIntentFields(Intent intent) {
final Bundle b = intent.getExtras();
cardId = b != null ? b.getString(LoyaltyCardEditActivity.BUNDLE_CARDID) : null;
@@ -56,23 +88,50 @@ public class ScanActivity extends CatimaAppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ScanActivityBinding.inflate(getLayoutInflater());
customBarcodeScannerBinding = CustomBarcodeScannerBinding.bind(binding.zxingBarcodeScanner);
setTitle(R.string.scanCardBarcode);
setContentView(R.layout.scan_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setContentView(binding.getRoot());
Toolbar toolbar = binding.toolbar;
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
enableToolbarBackButton();
extractIntentFields(getIntent());
manualAddLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.SELECT_BARCODE_REQUEST, result.getResultCode(), result.getData()));
photoPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_IMAGE_FILE, result.getResultCode(), result.getData()));
findViewById(R.id.add_from_image).setOnClickListener(this::addFromImage);
findViewById(R.id.add_manually).setOnClickListener(this::addManually);
customBarcodeScannerBinding.fabOtherOptions.setOnClickListener(view -> {
setScannerActive(false);
barcodeScannerView = findViewById(R.id.zxing_barcode_scanner);
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ScanActivity.this);
builder.setTitle(getString(R.string.add_a_card_in_a_different_way));
builder.setItems(
new CharSequence[]{
getString(R.string.addWithoutBarcode),
getString(R.string.addManually),
getString(R.string.addFromImage)
},
(dialogInterface, i) -> {
switch (i) {
case 0:
addWithoutBarcode();
break;
case 1:
addManually();
break;
case 2:
addFromImage();
break;
default:
throw new IllegalArgumentException("Unknown 'Add a card in a different way' dialog option");
}
}
);
builder.setOnCancelListener(dialogInterface -> setScannerActive(true));
builder.show();
});
barcodeScannerView = binding.zxingBarcodeScanner;
// Even though we do the actual decoding with the barcodeScannerView
// CaptureManager needs to be running to show the camera and scanning bar
@@ -88,8 +147,8 @@ public class ScanActivity extends CatimaAppCompatActivity {
public void barcodeResult(BarcodeResult result) {
Intent scanResult = new Intent();
Bundle scanResultBundle = new Bundle();
scanResultBundle.putString(BarcodeSelectorActivity.BARCODE_CONTENTS, result.getText());
scanResultBundle.putString(BarcodeSelectorActivity.BARCODE_FORMAT, result.getBarcodeFormat().name());
scanResultBundle.putString(BARCODE_CONTENTS, result.getText());
scanResultBundle.putString(BARCODE_FORMAT, result.getBarcodeFormat().name());
if (addGroup != null) {
scanResultBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, addGroup);
}
@@ -108,7 +167,15 @@ public class ScanActivity extends CatimaAppCompatActivity {
@Override
protected void onResume() {
super.onResume();
capture.onResume();
if (mScannerActive) {
capture.onResume();
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
showCameraPermissionMissingText(false);
}
scaleScreen();
}
@Override
@@ -124,9 +191,18 @@ public class ScanActivity extends CatimaAppCompatActivity {
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
capture.onSaveInstanceState(outState);
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
capture.onSaveInstanceState(savedInstanceState);
savedInstanceState.putBoolean(STATE_SCANNER_ACTIVE, mScannerActive);
}
@Override
public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mScannerActive = savedInstanceState.getBoolean(STATE_SCANNER_ACTIVE);
}
@Override
@@ -168,33 +244,106 @@ public class ScanActivity extends CatimaAppCompatActivity {
return super.onOptionsItemSelected(item);
}
private void setScannerActive(boolean isActive) {
if (isActive) {
barcodeScannerView.resume();
} else {
barcodeScannerView.pause();
}
mScannerActive = isActive;
}
private void returnResult(String barcodeContents, String barcodeFormat) {
Intent manualResult = new Intent();
Bundle manualResultBundle = new Bundle();
manualResultBundle.putString(BARCODE_CONTENTS, barcodeContents);
manualResultBundle.putString(BARCODE_FORMAT, barcodeFormat);
if (addGroup != null) {
manualResultBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, addGroup);
}
manualResult.putExtras(manualResultBundle);
ScanActivity.this.setResult(RESULT_OK, manualResult);
finish();
}
private void handleActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
BarcodeValues barcodeValues;
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
try {
barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
} catch (NullPointerException e) {
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
if (barcodeValues.isEmpty()) {
setScannerActive(true);
return;
}
if (!barcodeValues.isEmpty()) {
Intent manualResult = new Intent();
Bundle manualResultBundle = new Bundle();
manualResultBundle.putString(BarcodeSelectorActivity.BARCODE_CONTENTS, barcodeValues.content());
manualResultBundle.putString(BarcodeSelectorActivity.BARCODE_FORMAT, barcodeValues.format());
if (addGroup != null) {
manualResultBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, addGroup);
}
manualResult.putExtras(manualResultBundle);
ScanActivity.this.setResult(RESULT_OK, manualResult);
finish();
}
returnResult(barcodeValues.content(), barcodeValues.format());
}
public void addManually(View view) {
private void addWithoutBarcode() {
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
builder.setOnCancelListener(dialogInterface -> setScannerActive(true));
// Header
builder.setTitle(R.string.addWithoutBarcode);
// Layout
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
int contentPadding = getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_padding);
params.leftMargin = contentPadding;
params.topMargin = contentPadding / 2;
params.rightMargin = contentPadding;
// Description
TextView currentTextview = new TextView(this);
currentTextview.setText(getString(R.string.enter_card_id));
currentTextview.setLayoutParams(params);
layout.addView(currentTextview);
// EditText with spacing
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setLayoutParams(params);
layout.addView(input);
// Set layout
builder.setView(layout);
// Buttons
builder.setPositiveButton(getString(R.string.ok), (dialog, which) -> {
returnResult(input.getText().toString(), "");
});
builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel());
AlertDialog dialog = builder.create();
// Now that the dialog exists, we can bind something that affects the OK button
input.addTextChangedListener(new SimpleTextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length() == 0) {
input.setError(getString(R.string.card_id_must_not_be_empty));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
} else {
input.setError(null);
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
}
}
});
dialog.show();
// Disable button (must be done **after** dialog is shown to prevent crash
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
// Set focus on input field
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
input.requestFocus();
}
public void addManually() {
Intent i = new Intent(getApplicationContext(), BarcodeSelectorActivity.class);
if (cardId != null) {
final Bundle b = new Bundle();
@@ -204,14 +353,77 @@ public class ScanActivity extends CatimaAppCompatActivity {
manualAddLauncher.launch(i);
}
public void addFromImage(View view) {
public void addFromImage() {
PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_IMAGE);
}
private void addFromImageAfterPermission() {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
Intent contentIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentIntent.setType("image/*");
Intent chooserIntent = Intent.createChooser(photoPickerIntent, getString(R.string.addFromImage));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { contentIntent });
try {
photoPickerLauncher.launch(photoPickerIntent);
photoPickerLauncher.launch(chooserIntent);
} catch (ActivityNotFoundException e) {
setScannerActive(true);
Toast.makeText(getApplicationContext(), R.string.failedLaunchingPhotoPicker, Toast.LENGTH_LONG).show();
Log.e(TAG, "No activity found to handle intent", e);
}
}
private void showCameraPermissionMissingText(boolean show) {
customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedClickableArea.setOnClickListener(show ? 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);
}
private void scaleScreen() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenHeight = displayMetrics.heightPixels;
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);
}
private int obtainThemeAttribute(int attribute) {
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(attribute, typedValue, true);
return typedValue.data;
}
private void navigateToSystemPermissionSetting() {
Intent permissionIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", getPackageName(), null));
permissionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(permissionIntent);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
onMockedRequestPermissionsResult(requestCode, permissions, grantResults);
}
public void onMockedRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (requestCode == CaptureManager.getCameraPermissionReqCode()) {
showCameraPermissionMissingText(!granted);
} else if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE) {
if (granted) {
addFromImageAfterPermission();
} else {
setScannerActive(true);
Toast.makeText(this, R.string.storageReadPermissionRequired, Toast.LENGTH_LONG).show();
}
}
}
}
@@ -33,7 +33,6 @@ class ShortcutHelper {
private static final int ADAPTIVE_BITMAP_SIZE = 108 * ADAPTIVE_BITMAP_SCALE;
private static final int ADAPTIVE_BITMAP_VISIBLE_SIZE = 72 * ADAPTIVE_BITMAP_SCALE;
private static final int ADAPTIVE_BITMAP_IMAGE_SIZE = ADAPTIVE_BITMAP_VISIBLE_SIZE + 5 * ADAPTIVE_BITMAP_SCALE;
private static final int PADDING_COLOR = Color.argb(255, 255, 255, 255);
private static final int PADDING_COLOR_OVERLAY = Color.argb(127, 0, 0, 0);
/**
@@ -71,19 +70,13 @@ class ShortcutHelper {
ShortcutInfoCompat found = list.remove(foundIndex.intValue());
list.addFirst(found);
} else {
// The item is new to the list. First, we need to trim the list
// until it is able to accept a new item, then the item is
// inserted.
while (list.size() >= MAX_SHORTCUTS) {
list.pollLast();
}
// The item is new to the list. We add it and trim the list later.
ShortcutInfoCompat shortcut = createShortcutBuilder(context, card).build();
list.addFirst(shortcut);
}
LinkedList<ShortcutInfoCompat> finalList = new LinkedList<>();
int rank = 0;
// The ranks are now updated; the order in the list is the rank.
for (int index = 0; index < list.size(); index++) {
@@ -91,11 +84,20 @@ class ShortcutHelper {
LoyaltyCard loyaltyCard = DBHelper.getLoyaltyCard(database, Integer.parseInt(prevShortcut.getId()));
ShortcutInfoCompat updatedShortcut = createShortcutBuilder(context, loyaltyCard)
.setRank(index)
.build();
// skip outdated cards that no longer exist
if (loyaltyCard != null) {
ShortcutInfoCompat updatedShortcut = createShortcutBuilder(context, loyaltyCard)
.setRank(rank)
.build();
finalList.addLast(updatedShortcut);
finalList.addLast(updatedShortcut);
rank++;
// trim the list
if (rank >= MAX_SHORTCUTS) {
break;
}
}
}
ShortcutManagerCompat.setDynamicShortcuts(context, finalList);
@@ -145,7 +147,7 @@ class ShortcutHelper {
if (iconBitmap == null) {
iconBitmap = Utils.generateIcon(context, loyaltyCard, true).getLetterTile();
} else {
iconBitmap = createAdaptiveBitmap(iconBitmap, loyaltyCard.headerColor == null ? PADDING_COLOR : loyaltyCard.headerColor);
iconBitmap = createAdaptiveBitmap(iconBitmap, Utils.getHeaderColor(context, loyaltyCard));
}
IconCompat icon = IconCompat.createWithAdaptiveBitmap(iconBitmap);
@@ -22,4 +22,8 @@ public class ThirdPartyInfo {
public String license() {
return mLicense;
}
public String toHtml() {
return String.format("<a href=\"%s\">%s</a> (%s)", url(), name(), license());
}
}
@@ -18,6 +18,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.core.view.WindowInsetsControllerCompat;
public class UCropWrapper extends UCropActivity {
public static final String UCROP_TOOLBAR_TYPEFACE_STYLE = "ucop_toolbar_typeface_style";
@@ -28,7 +29,9 @@ public class UCropWrapper extends UCropActivity {
boolean darkMode = Utils.isDarkModeEnabled(this);
// setup status bar to look like the rest of the app
if (Build.VERSION.SDK_INT >= 23) {
getWindow().getDecorView().setSystemUiVisibility(darkMode ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
View decorView = getWindow().getDecorView();
WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(getWindow(), decorView);
wic.setAppearanceLightStatusBars(!darkMode);
} else {
// icons are always white back then
if (!darkMode) {
@@ -50,8 +53,8 @@ public class UCropWrapper extends UCropActivity {
AppCompatImageView controlsBackgroundImage = (AppCompatImageView) check;
// everything gathered and are as expected, now perform color patching
Utils.patchColors(this);
int colorSurface = MaterialColors.getColor(this, R.attr.colorSurface, ContextCompat.getColor(this, R.color.md_theme_light_surface));
int colorOnSurface = MaterialColors.getColor(this, R.attr.colorOnSurface, ContextCompat.getColor(this, R.color.md_theme_light_onSurface));
int colorSurface = MaterialColors.getColor(this, com.google.android.material.R.attr.colorSurface, ContextCompat.getColor(this, R.color.md_theme_light_surface));
int colorOnSurface = MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface, ContextCompat.getColor(this, R.color.md_theme_light_onSurface));
Drawable controlsBackgroundImageDrawable = controlsBackgroundImage.getBackground();
controlsBackgroundImageDrawable.mutate();
+329 -35
View File
@@ -1,5 +1,6 @@
package protect.card_locker;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -11,14 +12,29 @@ import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageDecoder;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Build;
import android.os.LocaleList;
import android.provider.MediaStore;
import android.text.Layout;
import android.text.Spanned;
import android.text.style.ClickableSpan;
import android.util.Log;
import android.util.TypedValue;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RawRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.graphics.ColorUtils;
import androidx.core.os.LocaleListCompat;
import androidx.exifinterface.media.ExifInterface;
import androidx.palette.graphics.Palette;
import com.google.android.material.color.DynamicColors;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
@@ -28,27 +44,32 @@ import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.graphics.ColorUtils;
import androidx.exifinterface.media.ExifInterface;
import androidx.palette.graphics.Palette;
import protect.card_locker.preferences.Settings;
public class Utils {
@@ -66,6 +87,8 @@ public class Utils {
public static final int CARD_IMAGE_FROM_FILE_BACK = 9;
public static final int CARD_IMAGE_FROM_FILE_ICON = 10;
public static final String CARD_IMAGE_FILENAME_REGEX = "^(card_)(\\d+)(_(?:front|back|icon)\\.png)$";
static final double LUMINANCE_MIDPOINT = 0.5;
static final int BITMAP_SIZE_SMALL = 512;
@@ -105,6 +128,17 @@ public class Utils {
return ColorUtils.calculateLuminance(backgroundColor) > LUMINANCE_MIDPOINT;
}
/**
* Returns the Barcode format and content based on the result of an activity.
* It shows toasts to notify the end-user as needed itself and will return an empty
* BarcodeValues object if the activity was cancelled or nothing could be found.
*
* @param requestCode
* @param resultCode
* @param intent
* @param context
* @return BarcodeValues
*/
static public BarcodeValues parseSetBarcodeActivityResult(int requestCode, int resultCode, Intent intent, Context context) {
String contents;
String format;
@@ -116,14 +150,16 @@ public class Utils {
if (requestCode == Utils.BARCODE_IMPORT_FROM_IMAGE_FILE) {
Log.i(TAG, "Received image file with possible barcode");
Uri data = intent.getData();
if (data == null) {
Log.e(TAG, "Intent did not contain any data");
Toast.makeText(context, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
return new BarcodeValues(null, null);
}
Bitmap bitmap;
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ImageDecoder.Source image_source = ImageDecoder.createSource(context.getContentResolver(), intent.getData());
bitmap = ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true));
} else {
bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), intent.getData());
}
bitmap = retrieveImageFromUri(context, data);
} catch (IOException e) {
Log.e(TAG, "Error getting data from image file");
e.printStackTrace();
@@ -163,6 +199,20 @@ public class Utils {
throw new UnsupportedOperationException("Unknown request code for parseSetBarcodeActivityResult");
}
static public Bitmap retrieveImageFromUri(Context context, Uri data) throws IOException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ImageDecoder.Source image_source = ImageDecoder.createSource(context.getContentResolver(), data);
return ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true));
} else {
return getBitmapSdkLessThan29(data, context);
}
}
@SuppressWarnings("deprecation")
private static Bitmap getBitmapSdkLessThan29(Uri data, Context context) throws IOException {
return MediaStore.Images.Media.getBitmap(context.getContentResolver(), data);
}
static public BarcodeValues getBarcodeFromBitmap(Bitmap bitmap) {
// This function is vulnerable to OOM, so we try again with a smaller bitmap is we get OOM
for (int i = 0; i < 10; i++) {
@@ -196,7 +246,21 @@ public class Utils {
}
}
static public Boolean isNotYetValid(Date validFromDate) {
// The note in `hasExpired` does not apply here, since the bug was fixed before this feature was added.
return validFromDate.after(getStartOfToday().getTime());
}
static public Boolean hasExpired(Date expiryDate) {
// Note: In #1083 it was discovered that `DatePickerFragment` may sometimes store the expiryDate
// at 12:00 PM instead of 12:00 AM in the DB. While this has been fixed and the 12-hour difference
// is not a problem for the way the comparison currently works, it's good to keep in mind such
// dates may exist in the DB in case the comparison changes in the future and the new one relies
// on both dates being set at 12:00 AM.
return expiryDate.before(getStartOfToday().getTime());
}
static private Calendar getStartOfToday() {
// today
Calendar date = new GregorianCalendar();
// reset hour, minutes, seconds and millis
@@ -204,8 +268,7 @@ public class Utils {
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
return expiryDate.before(date.getTime());
return date;
}
static public String formatBalance(Context context, BigDecimal value, Currency currency) {
@@ -330,6 +393,31 @@ public class Utils {
return cardImageFileNameBuilder.toString();
}
/**
* Returns a card image filename (string) with the ID replaced according to the map if the input is a valid card image filename (string), otherwise null.
*
* @param fileName e.g. "card_1_front.png"
* @param idMap e.g. Map.of(1, 2)
* @return String e.g. "card_2_front.png"
*/
static public String getRenamedCardImageFileName(final String fileName, final Map<Integer, Integer> idMap) {
Pattern pattern = Pattern.compile(CARD_IMAGE_FILENAME_REGEX);
Matcher matcher = pattern.matcher(fileName);
if (matcher.matches()) {
StringBuilder cardImageFileNameBuilder = new StringBuilder();
cardImageFileNameBuilder.append(matcher.group(1));
try {
int id = Integer.parseInt(matcher.group(2));
cardImageFileNameBuilder.append(idMap.getOrDefault(id, id));
} catch (NumberFormatException _e) {
return null;
}
cardImageFileNameBuilder.append(matcher.group(3));
return cardImageFileNameBuilder.toString();
}
return null;
}
static public void saveCardImage(Context context, Bitmap bitmap, String fileName) throws FileNotFoundException {
if (bitmap == null) {
context.deleteFile(fileName);
@@ -345,6 +433,14 @@ public class Utils {
saveCardImage(context, bitmap, getCardImageFileName(loyaltyCardId, type));
}
public static File retrieveCardImageAsFile(Context context, String fileName) {
return context.getFileStreamPath(fileName);
}
public static File retrieveCardImageAsFile(Context context, int loyaltyCardId, ImageLocationType type) {
return retrieveCardImageAsFile(context, getCardImageFileName(loyaltyCardId, type));
}
static public Bitmap retrieveCardImage(Context context, String fileName) {
FileInputStream in;
try {
@@ -385,18 +481,85 @@ public class Utils {
Locale chosenLocale = settings.getLocale();
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
// New API is broken on Android 6 and lower when selecting locales with both language and country, so still keeping this
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
configuration.locale = chosenLocale != null ? chosenLocale : Locale.getDefault();
res.updateConfiguration(configuration, res.getDisplayMetrics());
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
setLocalesSdkLessThan24(chosenLocale, configuration, res);
return context;
}
LocaleList localeList = chosenLocale != null ? new LocaleList(chosenLocale) : LocaleList.getDefault();
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
return context.createConfigurationContext(configuration);
/* Documentation at https://developer.android.com/reference/androidx/appcompat/app/AppCompatDelegate#setApplicationLocales(androidx.core.os.LocaleListCompat)
For API levels below that, the developer has two options:
- They can opt-in to automatic storage handled through the library...
- The second option is that they can choose to handle storage themselves.
In order to do so they must use this API to initialize locales during app-start up and provide their stored locales.
In this case, API should be called before Activity.onCreate() in the activity lifecycle, e.g. in attachBaseContext().
Note: Developers should gate this to API versions <33.
We are handling storage ourselves (courtesy of the in-app language picker), so we take the second approach.
So according to docs, we should have the API < 33 check.
*/
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
AppCompatDelegate.setApplicationLocales(chosenLocale != null ? LocaleListCompat.create(chosenLocale) : LocaleListCompat.getEmptyLocaleList());
}
return context;
}
@SuppressWarnings("deprecation")
private static void setLocalesSdkLessThan24(Locale chosenLocale, Configuration configuration, Resources res) {
configuration.locale = chosenLocale != null ? chosenLocale : Locale.getDefault();
res.updateConfiguration(configuration, res.getDisplayMetrics());
}
/**
* Android 13 settings seems to "force" the user to select country of locale, but many app-supported locales either only have language, not country
* or have a country the user doesn't want, which creates a mismatch between the app's supported locales and the system locale.
* <br>
* Example: The user chooses Espanol (Espana) in system settings, but the app only supports Espanol (Argentina) and the "plain" Espanol.
* <br>
* This method returns the app-supported locale that is most similar to the system one.
* @param appLocales Locales supported by the app
* @param sysLocale Per-app locale in system settings
* @return The app-supported locale that best matches the system per-app locale
*/
@NonNull
public static Locale getBestMatchLocale(@NonNull List<Locale> appLocales, @NonNull Locale sysLocale) {
int highestMatchMagnitude = appLocales.stream()
.mapToInt(appLocale -> calculateMatchMagnitudeOfTwoLocales(appLocale, sysLocale))
.max()
.orElseThrow(() -> new IllegalArgumentException("appLocales is empty"));
for (int i = 0; i < appLocales.size(); i++) {
Locale appLocale = appLocales.get(i);
if (calculateMatchMagnitudeOfTwoLocales(appLocale, sysLocale) == highestMatchMagnitude) {
return appLocale;
}
}
throw new AssertionError("This is not possible; there must be a locale whose match magnitude == " + highestMatchMagnitude + " with " + sysLocale.toLanguageTag());
}
private static int calculateMatchMagnitudeOfTwoLocales(@NonNull Locale appLocale, @NonNull Locale sysLocale) {
List<String> appLocaleAdjusted = new ArrayList<>();
List<String> sysLocaleAdjusted = new ArrayList<>();
appLocaleAdjusted.add(appLocale.getLanguage());
sysLocaleAdjusted.add(sysLocale.getLanguage());
if (!appLocale.getCountry().isEmpty() && !sysLocale.getCountry().isEmpty()) {
appLocaleAdjusted.add(appLocale.getCountry());
sysLocaleAdjusted.add(sysLocale.getCountry());
}
if (!appLocale.getVariant().isEmpty() && !sysLocale.getVariant().isEmpty()) {
appLocaleAdjusted.add(appLocale.getVariant());
sysLocaleAdjusted.add(sysLocale.getVariant());
}
if (!appLocale.getScript().isEmpty() && !sysLocale.getScript().isEmpty()) {
appLocaleAdjusted.add(appLocale.getScript());
sysLocaleAdjusted.add(sysLocale.getScript());
}
if (appLocaleAdjusted.equals(sysLocaleAdjusted)) {
return appLocaleAdjusted.size();
}
return 0;
}
static public long getUnixTime() {
@@ -418,6 +581,18 @@ public class Utils {
return new File(context.getCacheDir() + "/" + name);
}
public static File copyToTempFile(Context context, InputStream input, String name) throws IOException {
File file = createTempFile(context, name);
try (input; FileOutputStream out = new FileOutputStream(file)) {
byte[] buf = new byte[4096];
int len;
while ((len = input.read(buf)) != -1) {
out.write(buf, 0, len);
}
return file;
}
}
public static String saveTempImage(Context context, Bitmap in, String name, Bitmap.CompressFormat format) {
File image = createTempFile(context, name);
try (FileOutputStream out = new FileOutputStream(image)) {
@@ -480,7 +655,7 @@ public class Utils {
} else {
// final catch all in case of invalid theme value from older versions
// also handles R.string.settings_key_system_theme
DynamicColors.applyIfAvailable(activity);
DynamicColors.applyToActivityIfAvailable(activity);
}
if (isDarkModeEnabled(activity) && settings.getOledDark()) {
@@ -497,22 +672,12 @@ public class Utils {
activity.findViewById(android.R.id.content).setBackgroundColor(typedValue.data);
}
public static void updateMenuCardDetailsButtonState(MenuItem item, boolean currentlyExpanded) {
if (currentlyExpanded) {
item.setIcon(R.drawable.ic_baseline_unfold_less_24);
item.setTitle(R.string.action_hide_details);
} else {
item.setIcon(R.drawable.ic_baseline_unfold_more_24);
item.setTitle(R.string.action_show_details);
}
}
public static int getHeaderColorFromImage(Bitmap image, int fallback) {
if (image == null) {
return fallback;
}
return new Palette.Builder(image).generate().getDominantColor(R.attr.colorPrimary);
return new Palette.Builder(image).generate().getDominantColor(androidx.appcompat.R.attr.colorPrimary);
}
public static int getRandomHeaderColor(Context context) {
@@ -520,4 +685,133 @@ public class Utils {
final int color = (int) (Math.random() * colors.length());
return colors.getColor(color, Color.BLACK);
}
public static String readTextFile(Context context, @RawRes int resourceId) throws IOException {
InputStream input = context.getResources().openRawResource(resourceId);
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
StringBuilder result = new StringBuilder();
while (true) {
String nextLine = reader.readLine();
if (nextLine == null) {
reader.close();
break;
}
result.append("\n");
result.append(nextLine);
}
return result.toString();
}
// Very crude Markdown to HTML conversion.
// Only supports what's currently being used in CHANGELOG.md and PRIVACY.md.
// May break easily.
public static String basicMDToHTML(final String input) {
return input
.replaceAll("(?m)^#\\s+(.*)", "<h1>$1</h1>")
.replaceAll("(?m)^##\\s+(.*)", "<h2>$1</h2>")
.replaceAll("\\[([^]]+)\\]\\((https?://[\\w@#%&+=:?/.-]+)\\)", "<a href=\"$2\">$1</a>")
.replaceAll("\\*\\*([^*]+)\\*\\*", "<b>$1</b>")
.replaceAll("(?m)^-\\s+(.*)", "<ul><li>&nbsp;$1</li></ul>")
.replace("</ul>\n<ul>", "");
}
// Very crude autolinking.
// Only supports what's currently being used in CHANGELOG.md and PRIVACY.md.
// May break easily.
public static String linkify(final String input) {
return input
.replaceAll("([\\w.-]+@[\\w-]+(\\.[\\w-]+)+)", "<a href=\"mailto:$1\">$1</a>")
.replaceAll("(?<!href=\")\\b(https?://[\\w@#%&+=:?/.-]*[\\w@#%&+=:?/-])", "<a href=\"$1\">$1</a>");
}
public static void setIconOrTextWithBackground(Context context, LoyaltyCard loyaltyCard, Bitmap icon, ImageView backgroundOrIcon, TextView textWhenNoImage) {
if (icon != null) {
Log.d("onResume", "setting icon image");
textWhenNoImage.setVisibility(View.GONE);
backgroundOrIcon.setImageBitmap(icon);
backgroundOrIcon.setBackgroundColor(Color.TRANSPARENT);
} else {
textWhenNoImage.setVisibility(View.VISIBLE);
int headerColor = getHeaderColor(context, loyaltyCard);
backgroundOrIcon.setImageBitmap(null);
backgroundOrIcon.setBackgroundColor(headerColor);
textWhenNoImage.setText(loyaltyCard.store);
textWhenNoImage.setTextColor(Utils.needsDarkForeground(headerColor) ? Color.BLACK : Color.WHITE);
}
}
public static boolean installedFromGooglePlay(Context context) {
try {
String packageName = context.getPackageName();
String installer;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
installer = context.getPackageManager().getInstallSourceInfo(packageName).getInstallingPackageName();
} else {
installer = context.getPackageManager().getInstallerPackageName(packageName);
}
return installer.equals("com.android.vending");
} catch (Throwable ignored) {
return false;
}
}
public static int getHeaderColor(Context context, LoyaltyCard loyaltyCard) {
return loyaltyCard.headerColor != null ? loyaltyCard.headerColor : LetterBitmap.getDefaultColor(context, loyaltyCard.store);
}
public static String checksum(InputStream input) throws IOException {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] buf = new byte[4096];
int len;
while ((len = input.read(buf)) != -1) {
md.update(buf, 0, len);
}
StringBuilder sb = new StringBuilder();
for (byte b : md.digest()) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException _e) {
return null;
}
}
public static boolean equals(final Object a, final Object b) {
if (a == null && b == null) {
return true;
} else if (a == null || b == null) {
return false;
}
return a.equals(b);
}
@SuppressLint("ClickableViewAccessibility")
public static void makeTextViewLinksClickable(final TextView textView, final Spanned text) {
textView.setOnTouchListener((v, event) -> {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX() - textView.getTotalPaddingLeft() + textView.getScrollX();
int y = (int) event.getY() - textView.getTotalPaddingTop() + textView.getScrollY();
Layout layout = textView.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] links = text.getSpans(off, off, ClickableSpan.class);
if (links.length != 0) {
ClickableSpan link = links[0];
if (action == MotionEvent.ACTION_UP) {
link.onClick(textView);
}
return true;
}
}
return false;
});
}
}
@@ -15,7 +15,15 @@ import java.io.Reader;
import java.nio.charset.StandardCharsets;
public class ZipUtils {
static public String read(ZipInputStream zipInputStream) throws IOException {
public static Bitmap readImage(ZipInputStream zipInputStream) {
return BitmapFactory.decodeStream(zipInputStream);
}
public static JSONObject readJSON(ZipInputStream zipInputStream) throws IOException, JSONException {
return new JSONObject(read(zipInputStream));
}
private static String read(ZipInputStream zipInputStream) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
Reader reader = new BufferedReader(new InputStreamReader(zipInputStream, StandardCharsets.UTF_8));
int c;
@@ -24,12 +32,4 @@ public class ZipUtils {
}
return stringBuilder.toString();
}
static public Bitmap readImage(ZipInputStream zipInputStream) {
return BitmapFactory.decodeStream(zipInputStream);
}
static public JSONObject readJSON(ZipInputStream zipInputStream) throws IOException, JSONException {
return new JSONObject(read(zipInputStream));
}
}
@@ -0,0 +1,172 @@
package protect.card_locker.contentprovider;
import static protect.card_locker.DBHelper.LoyaltyCardDbIds;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import protect.card_locker.BuildConfig;
import protect.card_locker.DBHelper;
import protect.card_locker.preferences.Settings;
public class CardsContentProvider extends ContentProvider {
private static final String TAG = "Catima";
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".contentprovider.cards";
public static class Version {
public static final String MAJOR_COLUMN = "major";
public static final String MINOR_COLUMN = "minor";
public static final int MAJOR = 1;
public static final int MINOR = 0;
}
private static final int URI_VERSION = 0;
private static final int URI_CARDS = 1;
private static final int URI_GROUPS = 2;
private static final int URI_CARD_GROUPS = 3;
private static final String[] CARDS_DEFAULT_PROJECTION = new String[]{
LoyaltyCardDbIds.ID,
LoyaltyCardDbIds.STORE,
LoyaltyCardDbIds.VALID_FROM,
LoyaltyCardDbIds.EXPIRY,
LoyaltyCardDbIds.BALANCE,
LoyaltyCardDbIds.BALANCE_TYPE,
LoyaltyCardDbIds.NOTE,
LoyaltyCardDbIds.HEADER_COLOR,
LoyaltyCardDbIds.CARD_ID,
LoyaltyCardDbIds.BARCODE_ID,
LoyaltyCardDbIds.BARCODE_TYPE,
LoyaltyCardDbIds.STAR_STATUS,
LoyaltyCardDbIds.LAST_USED,
LoyaltyCardDbIds.ARCHIVE_STATUS,
};
private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH) {{
addURI(AUTHORITY, "version", URI_VERSION);
addURI(AUTHORITY, "cards", URI_CARDS);
addURI(AUTHORITY, "groups", URI_GROUPS);
addURI(AUTHORITY, "card_groups", URI_CARD_GROUPS);
}};
@Override
public boolean onCreate() {
return true;
}
@Nullable
@Override
public Cursor query(@NonNull final Uri uri,
@Nullable final String[] projection,
@Nullable final String selection,
@Nullable final String[] selectionArgs,
@Nullable final String sortOrder) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Disable the content provider on SDK < 23 since it grants dangerous
// permissions at install-time
Log.w(TAG, "Content provider read is only available for SDK >= 23");
return null;
}
final Settings settings = new Settings(getContext());
if (!settings.getAllowContentProviderRead()) {
Log.w(TAG, "Content provider read is disabled");
return null;
}
final String table;
String[] updatedProjection = projection;
switch (uriMatcher.match(uri)) {
case URI_VERSION:
return queryVersion();
case URI_CARDS:
table = DBHelper.LoyaltyCardDbIds.TABLE;
// Restrict columns to the default projection (omit internal columns such as zoom level)
if (projection == null) {
updatedProjection = CARDS_DEFAULT_PROJECTION;
} else {
final Set<String> defaultProjection = new HashSet<>(Arrays.asList(CARDS_DEFAULT_PROJECTION));
updatedProjection = Arrays.stream(projection).filter(defaultProjection::contains).toArray(String[]::new);
}
break;
case URI_GROUPS:
table = DBHelper.LoyaltyCardDbGroups.TABLE;
break;
case URI_CARD_GROUPS:
table = DBHelper.LoyaltyCardDbIdsGroups.TABLE;
break;
default:
Log.w(TAG, "Unrecognized URI " + uri);
return null;
}
final DBHelper dbHelper = new DBHelper(getContext());
final SQLiteDatabase database = dbHelper.getReadableDatabase();
return database.query(
table,
updatedProjection,
selection,
selectionArgs,
null,
null,
sortOrder
);
}
private Cursor queryVersion() {
final String[] columns = new String[]{Version.MAJOR_COLUMN, Version.MINOR_COLUMN};
final MatrixCursor matrixCursor = new MatrixCursor(columns);
matrixCursor.addRow(new Object[]{Version.MAJOR, Version.MINOR});
return matrixCursor;
}
@Nullable
@Override
public String getType(@NonNull final Uri uri) {
// MIME types are not relevant (for now at least)
return null;
}
@Nullable
@Override
public Uri insert(@NonNull final Uri uri,
@Nullable final ContentValues values) {
// This content provider is read-only for now, so we always return null
return null;
}
@Override
public int delete(@NonNull final Uri uri,
@Nullable final String selection,
@Nullable final String[] selectionArgs) {
// This content provider is read-only for now, so we always return 0
return 0;
}
@Override
public int update(@NonNull final Uri uri,
@Nullable final ContentValues values,
@Nullable final String selection,
@Nullable final String[] selectionArgs) {
// This content provider is read-only for now, so we always return 0
return 0;
}
}
@@ -8,22 +8,14 @@ public class CSVHelpers {
/**
* Extract a string from the items array. The index into the array
* is determined by looking up the index in the fields map using the
* "key" as the key. If no such key exists, defaultValue is returned
* if it is not null. Otherwise, a FormatException is thrown.
* "key" as the key. If no such key exists, defaultValue is returned.
*/
static String extractString(String key, CSVRecord record, String defaultValue)
throws FormatException {
String toReturn = defaultValue;
static String extractString(String key, CSVRecord record, String defaultValue) {
if (record.isMapped(key)) {
toReturn = record.get(key);
} else {
if (defaultValue == null) {
throw new FormatException("Field not used but expected: " + key);
}
return record.get(key);
}
return toReturn;
return defaultValue;
}
/**
@@ -32,15 +24,15 @@ public class CSVHelpers {
* "key" as the key. If no such key exists, or the data is not a valid
* int, a FormatException is thrown.
*/
static Integer extractInt(String key, CSVRecord record, boolean nullIsOk)
static Integer extractInt(String key, CSVRecord record)
throws FormatException {
if (record.isMapped(key) == false) {
if (!record.isMapped(key)) {
throw new FormatException("Field not used but expected: " + key);
}
String value = record.get(key);
if (value.isEmpty() && nullIsOk) {
return null;
if (value.isEmpty()) {
throw new FormatException("Field is empty: " + key);
}
try {
@@ -56,15 +48,15 @@ public class CSVHelpers {
* "key" as the key. If no such key exists, or the data is not a valid
* int, a FormatException is thrown.
*/
static Long extractLong(String key, CSVRecord record, boolean nullIsOk)
static Long extractLong(String key, CSVRecord record)
throws FormatException {
if (record.isMapped(key) == false) {
if (!record.isMapped(key)) {
throw new FormatException("Field not used but expected: " + key);
}
String value = record.get(key);
if (value.isEmpty() && nullIsOk) {
return null;
if (value.isEmpty()) {
throw new FormatException("Field is empty: " + key);
}
try {
@@ -127,6 +127,7 @@ public class CatimaExporter implements Exporter {
printer.printRecord(DBHelper.LoyaltyCardDbIds.ID,
DBHelper.LoyaltyCardDbIds.STORE,
DBHelper.LoyaltyCardDbIds.NOTE,
DBHelper.LoyaltyCardDbIds.VALID_FROM,
DBHelper.LoyaltyCardDbIds.EXPIRY,
DBHelper.LoyaltyCardDbIds.BALANCE,
DBHelper.LoyaltyCardDbIds.BALANCE_TYPE,
@@ -146,6 +147,7 @@ public class CatimaExporter implements Exporter {
printer.printRecord(card.id,
card.store,
card.note,
card.validFrom != null ? card.validFrom.getTime() : "",
card.expiry != null ? card.expiry.getTime() : "",
card.balance,
card.balanceType,
@@ -13,7 +13,8 @@ import org.apache.commons.csv.CSVRecord;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -23,12 +24,17 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Currency;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import protect.card_locker.CatimaBarcode;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
import protect.card_locker.Group;
import protect.card_locker.ImageLocationType;
import protect.card_locker.LoyaltyCard;
import protect.card_locker.Utils;
import protect.card_locker.ZipUtils;
@@ -40,24 +46,42 @@ import protect.card_locker.ZipUtils;
* A header is expected for the each table showing the names of the columns.
*/
public class CatimaImporter implements Importer {
public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, InterruptedException {
InputStream bufferedInputStream = new BufferedInputStream(input);
bufferedInputStream.mark(100);
public static class ImportedData {
public final List<LoyaltyCard> cards;
public final List<String> groups;
public final List<Map.Entry<Integer, String>> cardGroups;
ImportedData(final List<LoyaltyCard> cards, final List<String> groups, final List<Map.Entry<Integer, String>> cardGroups) {
this.cards = cards;
this.groups = groups;
this.cardGroups = cardGroups;
}
}
public void importData(Context context, SQLiteDatabase database, File inputFile, char[] password) throws IOException, FormatException, InterruptedException {
// Pass #1: get hashes and parse CSV
InputStream input1 = new FileInputStream(inputFile);
InputStream bufferedInputStream1 = new BufferedInputStream(input1);
bufferedInputStream1.mark(100);
ZipInputStream zipInputStream1 = new ZipInputStream(bufferedInputStream1, password);
// First, check if this is a zip file
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream, password);
boolean isZipFile = false;
LocalFileHeader localFileHeader;
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
Map<String, String> imageChecksums = new HashMap<>();
ImportedData importedData = null;
while ((localFileHeader = zipInputStream1.getNextEntry()) != null) {
isZipFile = true;
String fileName = Uri.parse(localFileHeader.getFileName()).getLastPathSegment();
if (fileName.equals("catima.csv")) {
importCSV(context, database, new ByteArrayInputStream(ZipUtils.read(zipInputStream).getBytes(StandardCharsets.UTF_8)));
importedData = importCSV(zipInputStream1);
} else if (fileName.endsWith(".png")) {
Utils.saveCardImage(context, ZipUtils.readImage(zipInputStream), fileName);
if (!fileName.matches(Utils.CARD_IMAGE_FILENAME_REGEX)) {
throw new FormatException("Unexpected PNG file in import: " + fileName);
}
imageChecksums.put(fileName, Utils.checksum(zipInputStream1));
} else {
throw new FormatException("Unexpected file in import: " + fileName);
}
@@ -65,46 +89,110 @@ public class CatimaImporter implements Importer {
if (!isZipFile) {
// This is not a zip file, try importing as bare CSV
bufferedInputStream.reset();
importCSV(context, database, bufferedInputStream);
bufferedInputStream1.reset();
importedData = importCSV(bufferedInputStream1);
}
input1.close();
if (importedData == null) {
throw new FormatException("No imported data");
}
Map<Integer, Integer> idMap = saveAndDeduplicate(context, database, importedData, imageChecksums);
if (isZipFile) {
// Pass #2: save images
InputStream input2 = new FileInputStream(inputFile);
InputStream bufferedInputStream2 = new BufferedInputStream(input2);
ZipInputStream zipInputStream2 = new ZipInputStream(bufferedInputStream2, password);
while ((localFileHeader = zipInputStream2.getNextEntry()) != null) {
String fileName = Uri.parse(localFileHeader.getFileName()).getLastPathSegment();
if (fileName.endsWith(".png")) {
String newFileName = Utils.getRenamedCardImageFileName(fileName, idMap);
Utils.saveCardImage(context, ZipUtils.readImage(zipInputStream2), newFileName);
}
}
input2.close();
}
}
public void importCSV(Context context, SQLiteDatabase database, InputStream input) throws IOException, FormatException, InterruptedException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
public Map<Integer, Integer> saveAndDeduplicate(Context context, SQLiteDatabase database, final ImportedData data, final Map<String, String> imageChecksums) throws IOException {
Map<Integer, Integer> idMap = new HashMap<>();
Set<String> existingImages = DBHelper.imageFiles(context, database);
bufferedReader.mark(100);
Integer version = 1;
try {
version = Integer.parseInt(bufferedReader.readLine());
} catch (NumberFormatException _e) {
// Assume version 1
for (LoyaltyCard card : data.cards) {
LoyaltyCard existing = DBHelper.getLoyaltyCard(database, card.id);
if (existing == null) {
DBHelper.insertLoyaltyCard(database, card.id, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
} else if (!isDuplicate(context, existing, card, existingImages, imageChecksums)) {
long newId = DBHelper.insertLoyaltyCard(database, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
idMap.put(card.id, (int) newId);
}
}
bufferedReader.reset();
for (String group : data.groups) {
DBHelper.insertGroup(database, group);
}
for (Map.Entry<Integer, String> entry : data.cardGroups) {
int cardId = idMap.getOrDefault(entry.getKey(), entry.getKey());
String groupId = entry.getValue();
// For existing & newly imported cards, add the groups from the import to the internal state
List<Group> cardGroups = DBHelper.getLoyaltyCardGroups(database, cardId);
cardGroups.add(DBHelper.getGroup(database, groupId));
DBHelper.setLoyaltyCardGroups(database, cardId, cardGroups);
}
return idMap;
}
public boolean isDuplicate(Context context, final LoyaltyCard existing, final LoyaltyCard card, final Set<String> existingImages, final Map<String, String> imageChecksums) throws IOException {
if (!LoyaltyCard.isDuplicate(existing, card)) {
return false;
}
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
String name = Utils.getCardImageFileName(existing.id, imageLocationType);
boolean exists = existingImages.contains(name);
if (exists != imageChecksums.containsKey(name)) {
return false;
}
if (exists) {
File file = Utils.retrieveCardImageAsFile(context, name);
if (!imageChecksums.get(name).equals(Utils.checksum(new FileInputStream(file)))) {
return false;
}
}
}
return true;
}
public ImportedData importCSV(InputStream input) throws IOException, FormatException, InterruptedException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
int version = parseVersion(bufferedReader);
switch (version) {
case 1:
parseV1(context, database, bufferedReader);
break;
return parseV1(bufferedReader);
case 2:
parseV2(context, database, bufferedReader);
break;
return parseV2(bufferedReader);
default:
throw new FormatException(String.format("No code to parse version %s", version));
}
bufferedReader.close();
}
public void parseV1(Context context, SQLiteDatabase database, BufferedReader input) throws IOException, FormatException, InterruptedException {
public ImportedData parseV1(BufferedReader input) throws IOException, FormatException, InterruptedException {
ImportedData data = new ImportedData(new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
final CSVParser parser = new CSVParser(input, CSVFormat.RFC4180.builder().setHeader().build());
try {
for (CSVRecord record : parser) {
importLoyaltyCard(context, database, record);
LoyaltyCard card = importLoyaltyCard(record);
data.cards.add(card);
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
@@ -115,11 +203,17 @@ public class CatimaImporter implements Importer {
} catch (IllegalArgumentException | IllegalStateException e) {
throw new FormatException("Issue parsing CSV data", e);
}
return data;
}
public void parseV2(Context context, SQLiteDatabase database, BufferedReader input) throws IOException, FormatException, InterruptedException {
Integer part = 0;
String stringPart = "";
public ImportedData parseV2(BufferedReader input) throws IOException, FormatException, InterruptedException {
List<LoyaltyCard> cards = new ArrayList<>();
List<String> groups = new ArrayList<>();
List<Map.Entry<Integer, String>> cardGroups = new ArrayList<>();
int part = 0;
StringBuilder stringPart = new StringBuilder();
try {
while (true) {
@@ -135,7 +229,7 @@ public class CatimaImporter implements Importer {
break;
case 1:
try {
parseV2Groups(database, stringPart);
groups = parseV2Groups(stringPart.toString());
sectionParsed = true;
} catch (FormatException e) {
// We may have a multiline field, try again
@@ -143,7 +237,7 @@ public class CatimaImporter implements Importer {
break;
case 2:
try {
parseV2Cards(context, database, stringPart);
cards = parseV2Cards(stringPart.toString());
sectionParsed = true;
} catch (FormatException e) {
// We may have a multiline field, try again
@@ -151,7 +245,7 @@ public class CatimaImporter implements Importer {
break;
case 3:
try {
parseV2CardGroups(database, stringPart);
cardGroups = parseV2CardGroups(stringPart.toString());
sectionParsed = true;
} catch (FormatException e) {
// We may have a multiline field, try again
@@ -167,20 +261,22 @@ public class CatimaImporter implements Importer {
if (sectionParsed) {
part += 1;
stringPart = "";
stringPart = new StringBuilder();
} else {
stringPart += tmp + "\n";
stringPart.append(tmp).append('\n');
}
} else {
stringPart += tmp + "\n";
stringPart.append(tmp).append('\n');
}
}
} catch (FormatException e) {
throw new FormatException("Issue parsing CSV data", e);
}
return new ImportedData(cards, groups, cardGroups);
}
public void parseV2Groups(SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
public List<String> parseV2Groups(String data) throws IOException, FormatException, InterruptedException {
// Parse groups
final CSVParser groupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
@@ -200,12 +296,15 @@ public class CatimaImporter implements Importer {
groupParser.close();
}
List<String> groups = new ArrayList<>();
for (CSVRecord record : records) {
importGroup(database, record);
String group = importGroup(record);
groups.add(group);
}
return groups;
}
public void parseV2Cards(Context context, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
public List<LoyaltyCard> parseV2Cards(String data) throws IOException, FormatException, InterruptedException {
// Parse cards
final CSVParser cardParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
@@ -225,12 +324,15 @@ public class CatimaImporter implements Importer {
cardParser.close();
}
List<LoyaltyCard> cards = new ArrayList<>();
for (CSVRecord record : records) {
importLoyaltyCard(context, database, record);
LoyaltyCard card = importLoyaltyCard(record);
cards.add(card);
}
return cards;
}
public void parseV2CardGroups(SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
public List<Map.Entry<Integer, String>> parseV2CardGroups(String data) throws IOException, FormatException, InterruptedException {
// Parse card group mappings
final CSVParser cardGroupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
@@ -250,18 +352,49 @@ public class CatimaImporter implements Importer {
cardGroupParser.close();
}
List<Map.Entry<Integer, String>> cardGroups = new ArrayList<>();
for (CSVRecord record : records) {
importCardGroupMapping(database, record);
Map.Entry<Integer, String> entry = importCardGroupMapping(record);
cardGroups.add(entry);
}
return cardGroups;
}
/**
* Parse the version number of the import file
*
* @param reader the reader containing the import file
* @return the parsed version number, defaulting to 1 if none is found
* @throws IOException there was a problem reading the file
*/
private int parseVersion(BufferedReader reader) throws IOException {
reader.mark(10); // slightly over the search limit just to be sure
StringBuilder sb = new StringBuilder();
int searchLimit = 5; // gives you version numbers up to 99999
int codePoint;
// search until the next whitespace, indicating the end of the version
while (!Character.isWhitespace(codePoint = reader.read())) {
// we found something that isn't a digit, or we ran out of chars
if (!Character.isDigit(codePoint) || searchLimit <= 0) {
reader.reset();
return 1; // default value
}
sb.append((char) codePoint);
searchLimit--;
}
reader.reset();
if (sb.length() == 0) {
return 1;
}
return Integer.parseInt(sb.toString());
}
/**
* Import a single loyalty card into the database using the given
* session.
*/
private void importLoyaltyCard(Context context, SQLiteDatabase database, CSVRecord record)
throws IOException, FormatException {
int id = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ID, record, false);
private LoyaltyCard importLoyaltyCard(CSVRecord record) throws FormatException {
int id = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ID, record);
String store = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.STORE, record, "");
if (store.isEmpty()) {
@@ -269,19 +402,38 @@ public class CatimaImporter implements Importer {
}
String note = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.NOTE, record, "");
Date expiry = null;
Date validFrom = null;
Long validFromLong;
try {
expiry = new Date(CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.EXPIRY, record, true));
} catch (NullPointerException | FormatException e) {
validFromLong = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.VALID_FROM, record);
} catch (FormatException ignored) {
validFromLong = null;
}
if (validFromLong != null) {
validFrom = new Date(validFromLong);
}
BigDecimal balance;
Date expiry = null;
Long expiryLong;
try {
balance = new BigDecimal(CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE, record, null));
} catch (FormatException _e) {
// These fields did not exist in versions 1.8.1 and before
// We catch this exception so we can still import old backups
balance = new BigDecimal("0");
expiryLong = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.EXPIRY, record);
} catch (FormatException ignored) {
expiryLong = null;
}
if (expiryLong != null) {
expiry = new Date(expiryLong);
}
// These fields did not exist in versions 1.8.1 and before
// We default to 0 so we can still import old backups
BigDecimal balance = new BigDecimal("0");
String balanceString = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE, record, null);
if (balanceString != null) {
try {
balance = new BigDecimal(CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE, record, null));
} catch (NumberFormatException ignored) {
}
}
Currency balanceType = null;
@@ -307,14 +459,14 @@ public class CatimaImporter implements Importer {
}
Integer headerColor = null;
if (record.isMapped(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)) {
headerColor = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.HEADER_COLOR, record, true);
try {
headerColor = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.HEADER_COLOR, record);
} catch (FormatException ignored) {
}
int starStatus = 0;
try {
starStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.STAR_STATUS, record, false);
starStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.STAR_STATUS, record);
} catch (FormatException _e) {
// This field did not exist in versions 0.28 and before
// We catch this exception so we can still import old backups
@@ -323,7 +475,7 @@ public class CatimaImporter implements Importer {
int archiveStatus = 0;
try {
archiveStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ARCHIVE_STATUS, record, false);
archiveStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ARCHIVE_STATUS, record);
} catch (FormatException _e) {
// This field did not exist in versions 2.16.3 and before
// We catch this exception so we can still import old backups
@@ -332,35 +484,41 @@ public class CatimaImporter implements Importer {
Long lastUsed = 0L;
try {
lastUsed = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.LAST_USED, record, false);
lastUsed = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.LAST_USED, record);
} catch (FormatException _e) {
// This field did not exist in versions 2.5.0 and before
// We catch this exception so we can still import old backups
}
DBHelper.insertLoyaltyCard(database, id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starStatus, lastUsed,archiveStatus);
return new LoyaltyCard(id, store, note, validFrom, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starStatus, lastUsed, DBHelper.DEFAULT_ZOOM_LEVEL, archiveStatus);
}
/**
* Import a single group into the database using the given
* session.
*/
private void importGroup(SQLiteDatabase database, CSVRecord record) throws FormatException {
private String importGroup(CSVRecord record) throws FormatException {
String id = CSVHelpers.extractString(DBHelper.LoyaltyCardDbGroups.ID, record, null);
DBHelper.insertGroup(database, id);
if (id == null) {
throw new FormatException("Group has no ID: " + record);
}
return id;
}
/**
* Import a single card to group mapping into the database using the given
* session.
*/
private void importCardGroupMapping(SQLiteDatabase database, CSVRecord record) throws FormatException {
Integer cardId = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIdsGroups.cardID, record, false);
private Map.Entry<Integer, String> importCardGroupMapping(CSVRecord record) throws FormatException {
int cardId = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIdsGroups.cardID, record);
String groupId = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIdsGroups.groupID, record, null);
List<Group> cardGroups = DBHelper.getLoyaltyCardGroups(database, cardId);
cardGroups.add(DBHelper.getGroup(database, groupId));
DBHelper.setLoyaltyCardGroups(database, cardId, cardGroups);
if (groupId == null) {
throw new FormatException("Group has no ID: " + record);
}
return Map.entry(cardId, groupId);
}
}
}
@@ -11,16 +11,21 @@ import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.json.JSONException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import protect.card_locker.CatimaBarcode;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
import protect.card_locker.LoyaltyCard;
import protect.card_locker.Utils;
/**
@@ -31,7 +36,16 @@ import protect.card_locker.Utils;
* A header is expected for the each table showing the names of the columns.
*/
public class FidmeImporter implements Importer {
public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
public static class ImportedData {
public final List<LoyaltyCard> cards;
ImportedData(final List<LoyaltyCard> cards) {
this.cards = cards;
}
}
public void importData(Context context, SQLiteDatabase database, File inputFile, char[] password) throws IOException, FormatException, JSONException, ParseException {
InputStream input = new FileInputStream(inputFile);
// We actually retrieve a .zip file
ZipInputStream zipInputStream = new ZipInputStream(input, password);
@@ -54,10 +68,14 @@ public class FidmeImporter implements Importer {
}
final CSVParser fidmeParser = new CSVParser(new StringReader(loyaltyCards.toString()), CSVFormat.RFC4180.builder().setDelimiter(';').setHeader().build());
ImportedData importedData = new ImportedData(new ArrayList<>());
try {
for (CSVRecord record : fidmeParser) {
importLoyaltyCard(context, database, record);
LoyaltyCard card = importLoyaltyCard(context, record);
if (card != null) {
importedData.cards.add(card);
}
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
@@ -70,14 +88,16 @@ public class FidmeImporter implements Importer {
}
zipInputStream.close();
input.close();
saveAndDeduplicate(database, importedData);
}
/**
* Import a single loyalty card into the database using the given
* session.
*/
private void importLoyaltyCard(Context context, SQLiteDatabase database, CSVRecord record)
throws FormatException {
private LoyaltyCard importLoyaltyCard(Context context, CSVRecord record) throws FormatException {
// A loyalty card export from Fidme contains the following fields:
// Retailer (store name)
// Program (program name)
@@ -110,7 +130,10 @@ public class FidmeImporter implements Importer {
// The ID is called reference
String cardId = CSVHelpers.extractString("Reference", record, "");
if (cardId.isEmpty()) {
throw new FormatException("No card ID listed, but is required");
// Fidme deletes the card id if a card is expired
// Because Catima considers the card id a required field, we ignore these expired cards
// https://github.com/CatimaLoyalty/Android/issues/1005
return null;
}
// Sadly, Fidme exports don't contain the card type
@@ -125,6 +148,17 @@ public class FidmeImporter implements Importer {
// TODO: Front and back image
DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, starStatus, null,archiveStatus);
// use -1 for the ID, it will be ignored when inserting the card into the DB
return new LoyaltyCard(-1, store, note, null, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, starStatus, Utils.getUnixTime(), DBHelper.DEFAULT_ZOOM_LEVEL, archiveStatus);
}
public void saveAndDeduplicate(SQLiteDatabase database, final ImportedData data) {
// This format does not have IDs that can cause conflicts
// Proper deduplication for all formats will be implemented later
for (LoyaltyCard card : data.cards) {
// Do not use card.id which is set to -1
DBHelper.insertLoyaltyCard(database, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
}
}
}
@@ -5,8 +5,8 @@ import android.database.sqlite.SQLiteDatabase;
import org.json.JSONException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import protect.card_locker.FormatException;
@@ -23,5 +23,5 @@ public interface Importer {
* @throws IOException
* @throws FormatException
*/
void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, InterruptedException, JSONException, ParseException;
void importData(Context context, SQLiteDatabase database, File inputFile, char[] password) throws IOException, FormatException, InterruptedException, JSONException, ParseException;
}
@@ -6,10 +6,15 @@ import android.util.Log;
import net.lingala.zip4j.exception.ZipException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import protect.card_locker.Utils;
public class MultiFormatImporter {
private static final String TAG = "Catima";
private static final String TEMP_ZIP_NAME = MultiFormatImporter.class.getSimpleName() + ".zip";
/**
* Attempts to import data from the input stream of the
@@ -42,23 +47,33 @@ public class MultiFormatImporter {
String error = null;
if (importer != null) {
database.beginTransaction();
File inputFile;
try {
importer.importData(context, database, input, password);
database.setTransactionSuccessful();
return new ImportExportResult(ImportExportResultType.Success);
} catch (ZipException e) {
if (e.getType().equals(ZipException.Type.WRONG_PASSWORD)) {
return new ImportExportResult(ImportExportResultType.BadPassword);
} else {
inputFile = Utils.copyToTempFile(context, input, TEMP_ZIP_NAME);
database.beginTransaction();
try {
importer.importData(context, database, inputFile, password);
database.setTransactionSuccessful();
return new ImportExportResult(ImportExportResultType.Success);
} catch (ZipException e) {
if (e.getType().equals(ZipException.Type.WRONG_PASSWORD)) {
return new ImportExportResult(ImportExportResultType.BadPassword);
} else {
Log.e(TAG, "Failed to import data", e);
error = e.toString();
}
} catch (Exception e) {
Log.e(TAG, "Failed to import data", e);
error = e.toString();
} finally {
database.endTransaction();
if (!inputFile.delete()) {
Log.w(TAG, "Failed to delete temporary ZIP file (should not be a problem) " + inputFile);
}
}
} catch (Exception e) {
Log.e(TAG, "Failed to import data", e);
} catch (IOException e) {
Log.e(TAG, "Failed to copy ZIP file", e);
error = e.toString();
} finally {
database.endTransaction();
}
} else {
error = "Unsupported data format imported: " + format.name();
@@ -5,6 +5,8 @@ import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.zxing.BarcodeFormat;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
@@ -13,21 +15,30 @@ import net.lingala.zip4j.model.LocalFileHeader;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import protect.card_locker.CatimaBarcode;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
import protect.card_locker.ImageLocationType;
import protect.card_locker.LoyaltyCard;
import protect.card_locker.R;
import protect.card_locker.Utils;
import protect.card_locker.ZipUtils;
@@ -40,21 +51,78 @@ import protect.card_locker.ZipUtils;
* A header is expected for the each table showing the names of the columns.
*/
public class StocardImporter implements Importer {
public static class StocardProvider {
public String name = null;
public String barcodeFormat = null;
public Bitmap logo = null;
}
public static class StocardRecord {
public String providerId = null;
public String store = null;
public String label = null;
public String note = null;
public String cardId = null;
public String barcodeType = null;
public Long lastUsed = null;
public Bitmap frontImage = null;
public Bitmap backImage = null;
@NonNull
@Override
public String toString() {
return String.format(
"StocardRecord{%n providerId=%s,%n store=%s,%n label=%s,%n note=%s,%n cardId=%s,%n"
+ " barcodeType=%s,%n lastUsed=%s,%n frontImage=%s,%n backImage=%s%n}",
this.providerId,
this.store,
this.label,
this.note,
this.cardId,
this.barcodeType,
this.lastUsed,
this.frontImage,
this.backImage
);
}
}
public static class ZIPData {
public final Map<String, StocardRecord> cards;
public final Map<String, StocardProvider> providers;
ZIPData(final Map<String, StocardRecord> cards, final Map<String, StocardProvider> providers) {
this.cards = cards;
this.providers = providers;
}
}
public static class ImportedData {
public final List<LoyaltyCard> cards;
public final Map<Integer, Map<ImageLocationType, Bitmap>> images;
ImportedData(final List<LoyaltyCard> cards, final Map<Integer, Map<ImageLocationType, Bitmap>> images) {
this.cards = cards;
this.images = images;
}
}
public static final String PROVIDER_PREFIX = "/loyalty-card-providers/";
private static final String TAG = "Catima";
public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
HashMap<String, HashMap<String, Object>> loyaltyCardHashMap = new HashMap<>();
HashMap<String, HashMap<String, Object>> providers = new HashMap<>();
public void importData(Context context, SQLiteDatabase database, File inputFile, char[] password) throws IOException, FormatException, JSONException, ParseException {
ZIPData zipData = new ZIPData(new HashMap<>(), new HashMap<>());
final CSVParser parser = new CSVParser(new InputStreamReader(context.getResources().openRawResource(R.raw.stocard_stores), StandardCharsets.UTF_8), CSVFormat.RFC4180.builder().setHeader().build());
try {
for (CSVRecord record : parser) {
HashMap<String, Object> recordData = new HashMap<>();
recordData.put("name", record.get("name"));
recordData.put("barcodeFormat", record.get("barcodeFormat"));
StocardProvider provider = new StocardProvider();
provider.name = record.get("name").trim();
provider.barcodeFormat = record.get("barcodeFormat").trim();
providers.put(record.get("_id"), recordData);
zipData.providers.put(record.get("_id").trim(), provider);
}
parser.close();
@@ -62,160 +130,213 @@ public class StocardImporter implements Importer {
throw new FormatException("Issue parsing CSV data", e);
}
InputStream input = new FileInputStream(inputFile);
ZipInputStream zipInputStream = new ZipInputStream(input, password);
zipData = importZIP(zipInputStream, zipData);
zipInputStream.close();
input.close();
if (zipData.cards.keySet().size() == 0) {
throw new FormatException("Couldn't find any loyalty cards in this Stocard export.");
}
ImportedData importedData = importLoyaltyCardHashMap(context, zipData);
saveAndDeduplicate(context, database, importedData);
}
public ZIPData importZIP(ZipInputStream zipInputStream, final ZIPData zipData) throws IOException, FormatException, JSONException {
Map<String, StocardRecord> cards = zipData.cards;
Map<String, StocardProvider> providers = zipData.providers;
String[] providersFileName = null;
String[] customProvidersBaseName = null;
String customProviderId = "";
String[] cardBaseName = null;
String customProviderId = "";
String cardName = "";
LocalFileHeader localFileHeader;
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
String fileName = localFileHeader.getFileName();
String[] nameParts = fileName.split("/");
if (providersFileName == null) {
providersFileName = new String[]{
nameParts[0],
"sync",
"data",
"users",
nameParts[0],
"analytics-properties.json"
};
if (nameParts.length < 2) {
continue;
}
String userId = nameParts[1];
if (customProvidersBaseName == null) {
// FIXME: can we use the points-account/statement/content.json balance info somehow?
/*
Known files:
extracts/<user-UUID>/users/<user-UUID>/
analytics-properties/content.json
devices/<device-UUID>/
analytics-properties/content.json
content.json
ip-location-wifi/content.json
enabled-regions/<UUID>/content.json
loyalty-card-custom-providers/<provider-UUID>/content.json - custom providers
loyalty-cards/<card-UUID>/
card-linked-coupons/accounts/default/
content.json
user-coupons/<UUID>/content.json
content.json - card itself
images/back.png - back image (legacy)
images/back/back.jpg - back image
images/back/content.json
images/front.png - front image (legacy)
images/front/content.json
images/front/front.jpg - front image
notes/default/content.json - note
points-account/
content.json
statement/content.json
usages/<UUID>/content.json - timestamps
usage-statistics/content.json - timestamps
reward-program-balances/<UUID>/content.json
*/
customProvidersBaseName = new String[]{
nameParts[0],
"sync",
"data",
"extracts",
userId,
"users",
nameParts[0],
userId,
"loyalty-card-custom-providers"
};
cardBaseName = new String[]{
nameParts[0],
"sync",
"data",
"extracts",
userId,
"users",
nameParts[0],
userId,
"loyalty-cards"
};
}
if (startsWith(nameParts, customProvidersBaseName, 1)) {
// Extract providerId
customProviderId = nameParts[customProvidersBaseName.length].split("\\.", 2)[0];
customProviderId = nameParts[customProvidersBaseName.length];
StocardProvider provider = providers.get(customProviderId);
if (provider == null) {
provider = new StocardProvider();
providers.put(customProviderId, provider);
}
// Name file
if (nameParts.length == customProvidersBaseName.length + 1) {
// Ignore the .txt file
if (fileName.endsWith(".json")) {
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
providers = appendToHashMap(
providers,
customProviderId,
"name",
jsonObject.getString("name")
);
}
if (fileName.endsWith(customProviderId + "/content.json")) {
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
provider.name = jsonObject.getString("name");
} else if (fileName.endsWith("logo.png")) {
providers = appendToHashMap(
providers,
customProviderId,
"logo",
ZipUtils.readImage(zipInputStream)
);
provider.logo = ZipUtils.readImage(zipInputStream);
} else if (!fileName.endsWith("/")) {
Log.d(TAG, "Unknown or unused loyalty-card-custom-providers file " + fileName + ", skipping...");
}
}
if (startsWith(nameParts, cardBaseName, 1)) {
} else if (startsWith(nameParts, cardBaseName, 1)) {
// Extract cardName
cardName = nameParts[cardBaseName.length].split("\\.", 2)[0];
cardName = nameParts[cardBaseName.length];
StocardRecord record = cards.get(cardName);
if (record == null) {
record = new StocardRecord();
cards.put(cardName, record);
}
// This is the card itself
if (nameParts.length == cardBaseName.length + 1) {
// Ignore the .txt file
if (fileName.endsWith(".json")) {
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
if (fileName.endsWith(cardName + "/content.json")) {
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
record.cardId = jsonObject.getString("input_id");
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"cardId",
jsonObject.getString("input_id")
);
if (jsonObject.has("input_provider_name")) {
record.store = jsonObject.getString("input_provider_name");
}
// Provider ID can be either custom or not, extract whatever version is relevant
String customProviderPrefix = "/users/" + nameParts[0] + "/loyalty-card-custom-providers/";
String providerId = jsonObject
.getJSONObject("input_provider_reference")
.getString("identifier");
if (providerId.startsWith(customProviderPrefix)) {
providerId = providerId.substring(customProviderPrefix.length());
} else {
providerId = providerId.substring("/loyalty-card-providers/".length());
}
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"_providerId",
providerId
);
if (jsonObject.has("input_barcode_format")) {
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"barcodeType",
jsonObject.getString("input_barcode_format")
);
if (jsonObject.has("label")) {
String label = jsonObject.getString("label");
if (!label.isBlank()) {
record.label = label;
}
}
} else if (fileName.endsWith("notes/default.json")) {
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"note",
ZipUtils.readJSON(zipInputStream)
.getString("content")
);
} else if (fileName.endsWith("/images/front.png")) {
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"frontImage",
ZipUtils.readImage(zipInputStream)
);
} else if (fileName.endsWith("/images/back.png")) {
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"backImage",
ZipUtils.readImage(zipInputStream)
);
// Provider ID can be either custom or not, extract whatever version is relevant
String customProviderPrefix = "/users/" + userId + "/loyalty-card-custom-providers/";
String providerId = jsonObject
.getJSONObject("input_provider_reference")
.getString("identifier");
if (providerId.startsWith(customProviderPrefix)) {
providerId = providerId.substring(customProviderPrefix.length());
} else if (providerId.startsWith(PROVIDER_PREFIX)) {
providerId = providerId.substring(PROVIDER_PREFIX.length());
} else {
throw new FormatException("Unsupported provider ID format: " + providerId);
}
record.providerId = providerId;
if (jsonObject.has("input_barcode_format")) {
record.barcodeType = jsonObject.getString("input_barcode_format");
}
} else if (fileName.endsWith("notes/default/content.json")) {
record.note = ZipUtils.readJSON(zipInputStream).getString("content");
} else if (fileName.endsWith("usage-statistics/content.json")) {
JSONArray usages = ZipUtils.readJSON(zipInputStream).getJSONArray("usages");
for (int i = 0; i < usages.length(); i++) {
JSONObject lastUsedObject = usages.getJSONObject(i);
String lastUsedString = lastUsedObject.getJSONObject("time").getString("value");
long timeStamp = Instant.parse(lastUsedString).getEpochSecond();
if (record.lastUsed == null || timeStamp > record.lastUsed) {
record.lastUsed = timeStamp;
}
}
} else if (fileName.matches(".*/usages/[^/]+/content.json")) {
JSONObject lastUsedObject = ZipUtils.readJSON(zipInputStream);
String lastUsedString = lastUsedObject.getJSONObject("time").getString("value");
long timeStamp = Instant.parse(lastUsedString).getEpochSecond();
if (record.lastUsed == null || timeStamp > record.lastUsed) {
record.lastUsed = timeStamp;
}
} else if (fileName.endsWith("/images/front.png") || fileName.endsWith("/images/front/front.jpg")) {
record.frontImage = ZipUtils.readImage(zipInputStream);
} else if (fileName.endsWith("/images/back.png") || fileName.endsWith("/images/back/back.jpg")) {
record.backImage = ZipUtils.readImage(zipInputStream);
} else if (!fileName.endsWith("/")) {
Log.d(TAG, "Unknown or unused loyalty-cards file " + fileName + ", skipping...");
}
} else if (!fileName.endsWith("/")) {
Log.d(TAG, "Unknown or unused file " + fileName + ", skipping...");
}
}
if (loyaltyCardHashMap.keySet().size() == 0) {
throw new FormatException("Couldn't find any loyalty cards in this Stocard export.");
}
return new ZIPData(cards, providers);
}
for (HashMap<String, Object> loyaltyCardData : loyaltyCardHashMap.values()) {
String providerId = (String) loyaltyCardData.get("_providerId");
public ImportedData importLoyaltyCardHashMap(Context context, final ZIPData zipData) throws FormatException {
ImportedData importedData = new ImportedData(new ArrayList<>(), new HashMap<>());
int tempID = 0;
if (providerId == null) {
Log.d(TAG, "Missing providerId for card " + loyaltyCardData + ", ignoring...");
List<String> cardKeys = new ArrayList<>(zipData.cards.keySet());
Collections.sort(cardKeys);
for (String key : cardKeys) {
StocardRecord record = zipData.cards.get(key);
if (record.providerId == null) {
Log.d(TAG, "Missing providerId for card " + record + ", ignoring...");
continue;
}
HashMap<String, Object> providerData = providers.get(providerId);
if (record.cardId == null) {
throw new FormatException("No card ID listed, but is required");
}
StocardProvider provider = zipData.providers.get(record.providerId);
// Read store from card, if not available (old export), fall back to providerData
String store = record.store != null ? record.store : provider != null ? provider.name : record.providerId;
String note = record.note != null ? record.note : "";
String barcodeTypeString = record.barcodeType != null ? record.barcodeType : provider != null ? provider.barcodeFormat : null;
if (record.label != null && !record.label.equals(store) && !record.label.equals(note)) {
note = note.isEmpty() ? record.label : note + "\n" + record.label;
}
String store = providerData != null ? providerData.get("name").toString() : providerId;
String note = (String) Utils.mapGetOrDefault(loyaltyCardData, "note", "");
String cardId = (String) loyaltyCardData.get("cardId");
String barcodeTypeString = (String) Utils.mapGetOrDefault(loyaltyCardData, "barcodeType", providerData != null ? providerData.get("barcodeFormat") : null);
CatimaBarcode barcodeType = null;
if (barcodeTypeString != null && !barcodeTypeString.isEmpty()) {
if (barcodeTypeString.equals("RSS_DATABAR_EXPANDED")) {
@@ -228,27 +349,45 @@ public class StocardImporter implements Importer {
}
int headerColor = Utils.getRandomHeaderColor(context);
Bitmap cardIcon = null;
if (providerData != null && providerData.containsKey("logo")) {
cardIcon = (Bitmap) providerData.get("logo");
headerColor = Utils.getHeaderColorFromImage(cardIcon, headerColor);
if (provider != null && provider.logo != null) {
headerColor = Utils.getHeaderColorFromImage(provider.logo, headerColor);
}
long loyaltyCardInternalId = DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, 0, null,0);
long lastUsed = record.lastUsed != null ? record.lastUsed : Utils.getUnixTime();
if (cardIcon != null) {
Utils.saveCardImage(context, cardIcon, (int) loyaltyCardInternalId, ImageLocationType.icon);
LoyaltyCard card = new LoyaltyCard(tempID, store, note, null, null, BigDecimal.valueOf(0), null, record.cardId, null, barcodeType, headerColor, 0, lastUsed, DBHelper.DEFAULT_ZOOM_LEVEL, 0);
importedData.cards.add(card);
Map<ImageLocationType, Bitmap> images = new HashMap<>();
if (provider != null && provider.logo != null) {
images.put(ImageLocationType.icon, provider.logo);
}
if (record.frontImage != null) {
images.put(ImageLocationType.front, record.frontImage);
}
if (record.backImage != null) {
images.put(ImageLocationType.back, record.backImage);
}
if (loyaltyCardData.containsKey("frontImage")) {
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("frontImage"), (int) loyaltyCardInternalId, ImageLocationType.front);
}
if (loyaltyCardData.containsKey("backImage")) {
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("backImage"), (int) loyaltyCardInternalId, ImageLocationType.back);
}
importedData.images.put(tempID, images);
tempID++;
}
zipInputStream.close();
return importedData;
}
public void saveAndDeduplicate(Context context, SQLiteDatabase database, final ImportedData data) throws IOException {
// This format does not have IDs that can cause conflicts
// Proper deduplication for all formats will be implemented later
for (LoyaltyCard card : data.cards) {
// card.id is temporary and only used to index the images Map
long id = DBHelper.insertLoyaltyCard(database, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
for (Map.Entry<ImageLocationType, Bitmap> entry : data.images.get(card.id).entrySet()) {
Utils.saveCardImage(context, entry.getValue(), (int) id, entry.getKey());
}
}
}
private boolean startsWith(String[] full, String[] start, int minExtraLength) {
@@ -264,16 +403,4 @@ public class StocardImporter implements Importer {
return true;
}
private HashMap<String, HashMap<String, Object>> appendToHashMap(HashMap<String, HashMap<String, Object>> loyaltyCardHashMap, String cardID, String key, Object value) {
HashMap<String, Object> loyaltyCardData = loyaltyCardHashMap.get(cardID);
if (loyaltyCardData == null) {
loyaltyCardData = new HashMap<>();
}
loyaltyCardData.put(key, value);
loyaltyCardHashMap.put(cardID, loyaltyCardData);
return loyaltyCardHashMap;
}
}
}
@@ -12,6 +12,8 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -19,13 +21,16 @@ import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Currency;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import protect.card_locker.CatimaBarcode;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
import protect.card_locker.LoyaltyCard;
import protect.card_locker.Utils;
/**
@@ -36,7 +41,16 @@ import protect.card_locker.Utils;
* A header is expected for the each table showing the names of the columns.
*/
public class VoucherVaultImporter implements Importer {
public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
public static class ImportedData {
public final List<LoyaltyCard> cards;
ImportedData(final List<LoyaltyCard> cards) {
this.cards = cards;
}
}
public void importData(Context context, SQLiteDatabase database, File inputFile, char[] password) throws IOException, FormatException, JSONException, ParseException {
InputStream input = new FileInputStream(inputFile);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
@@ -46,6 +60,16 @@ public class VoucherVaultImporter implements Importer {
}
JSONArray jsonArray = new JSONArray(sb.toString());
bufferedReader.close();
input.close();
ImportedData importedData = importJSON(jsonArray);
saveAndDeduplicate(database, importedData);
}
public ImportedData importJSON(JSONArray jsonArray) throws FormatException, JSONException, ParseException {
ImportedData importedData = new ImportedData(new ArrayList<>());
// See https://github.com/tim-smart/vouchervault/issues/4#issuecomment-788226503 for more info
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonCard = jsonArray.getJSONObject(i);
@@ -126,9 +150,20 @@ public class VoucherVaultImporter implements Importer {
throw new FormatException("Unknown colour type found: " + colorFromJSON);
}
DBHelper.insertLoyaltyCard(database, store, "", expiry, balance, balanceType, cardId, null, barcodeType, headerColor, 0, Utils.getUnixTime(),0);
// use -1 for the ID, it will be ignored when inserting the card into the DB
importedData.cards.add(new LoyaltyCard(-1, store, "", null, expiry, balance, balanceType, cardId, null, barcodeType, headerColor, 0, Utils.getUnixTime(), DBHelper.DEFAULT_ZOOM_LEVEL, 0));
}
bufferedReader.close();
return importedData;
}
public void saveAndDeduplicate(SQLiteDatabase database, final ImportedData data) {
// This format does not have IDs that can cause conflicts
// Proper deduplication for all formats will be implemented later
for (LoyaltyCard card : data.cards) {
// Do not use card.id which is set to -1
DBHelper.insertLoyaltyCard(database, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
}
}
}
@@ -63,30 +63,6 @@ public class Settings {
return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
}
public double getFontSizeScale() {
return getInt(R.string.settings_key_max_font_size_scale, R.integer.settings_max_font_size_scale_pct) / 100.0;
}
public int getSmallFont() {
return 14;
}
public int getMediumFont() {
return 28;
}
public int getLargeFont() {
return 40;
}
public int getFontSizeMin(int fontSize) {
return (int) (Math.round(fontSize / 2.0) - 1);
}
public int getFontSizeMax(int fontSize) {
return (int) Math.round(fontSize * getFontSizeScale());
}
public boolean useMaxBrightnessDisplayingBarcode() {
return getBoolean(R.string.settings_key_display_barcode_max_brightness, true);
}
@@ -103,6 +79,10 @@ public class Settings {
return getBoolean(R.string.settings_key_disable_lockscreen_while_viewing_card, true);
}
public boolean getAllowContentProviderRead() {
return getBoolean(R.string.settings_key_allow_content_provider_read, true);
}
public boolean getOledDark() {
return getBoolean(R.string.settings_key_oled_dark, false);
}
@@ -3,46 +3,48 @@ package protect.card_locker.preferences;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.core.os.LocaleListCompat;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import com.google.android.material.color.DynamicColors;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.DialogFragment;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import nl.invissvenska.numberpickerpreference.NumberDialogPreference;
import nl.invissvenska.numberpickerpreference.NumberPickerPreferenceDialogFragment;
import protect.card_locker.CatimaAppCompatActivity;
import protect.card_locker.MainActivity;
import protect.card_locker.R;
import protect.card_locker.Utils;
import protect.card_locker.databinding.SettingsActivityBinding;
public class SettingsActivity extends CatimaAppCompatActivity {
private SettingsActivityBinding binding;
private final static String RELOAD_MAIN_STATE = "mReloadMain";
private SettingsFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = SettingsActivityBinding.inflate(getLayoutInflater());
setTitle(R.string.settings);
setContentView(R.layout.settings_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setContentView(binding.getRoot());
Toolbar toolbar = binding.toolbar;
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
enableToolbarBackButton();
// Display the fragment as the main content.
fragment = new SettingsFragment();
@@ -100,23 +102,8 @@ public class SettingsActivity extends CatimaAppCompatActivity {
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
// Show pretty names
ListPreference localePreference = findPreference(getResources().getString(R.string.settings_key_locale));
assert localePreference != null;
CharSequence[] entryValues = localePreference.getEntryValues();
List<CharSequence> entries = new ArrayList<>();
for (CharSequence entry : entryValues) {
if (entry.length() == 0) {
entries.add(getResources().getString(R.string.settings_system_locale));
} else {
Locale entryLocale = Utils.stringToLocale(entry.toString());
entries.add(entryLocale.getDisplayName(entryLocale));
}
}
localePreference.setEntries(entries.toArray(new CharSequence[entryValues.length]));
Preference themePreference = findPreference(getResources().getString(R.string.settings_key_theme));
// Show pretty names and summaries
ListPreference themePreference = findPreference(getResources().getString(R.string.settings_key_theme));
assert themePreference != null;
themePreference.setOnPreferenceChangeListener((preference, o) -> {
if (o.toString().equals(getResources().getString(R.string.settings_key_light_theme))) {
@@ -130,10 +117,16 @@ public class SettingsActivity extends CatimaAppCompatActivity {
return true;
});
localePreference.setOnPreferenceChangeListener((preference, newValue) -> {
ListPreference themeColorPreference = findPreference(getResources().getString(R.string.setting_key_theme_color));
assert themeColorPreference != null;
themeColorPreference.setOnPreferenceChangeListener((preference, o) -> {
refreshActivity(true);
return true;
});
if (!DynamicColors.isDynamicColorAvailable()) {
themeColorPreference.setEntryValues(R.array.color_values_no_dynamic);
themeColorPreference.setEntries(R.array.color_value_strings_no_dynamic);
}
Preference oledDarkPreference = findPreference(getResources().getString(R.string.settings_key_oled_dark));
assert oledDarkPreference != null;
@@ -142,16 +135,61 @@ public class SettingsActivity extends CatimaAppCompatActivity {
return true;
});
ListPreference colorPreference = findPreference(getResources().getString(R.string.setting_key_theme_color));
assert colorPreference != null;
colorPreference.setOnPreferenceChangeListener((preference, o) -> {
refreshActivity(true);
ListPreference localePreference = findPreference(getResources().getString(R.string.settings_key_locale));
assert localePreference != null;
CharSequence[] entryValues = localePreference.getEntryValues();
List<CharSequence> entries = new ArrayList<>();
for (CharSequence entry : entryValues) {
if (entry.length() == 0) {
entries.add(getResources().getString(R.string.settings_system_locale));
} else {
Locale entryLocale = Utils.stringToLocale(entry.toString());
entries.add(entryLocale.getDisplayName(entryLocale));
}
}
localePreference.setEntries(entries.toArray(new CharSequence[entryValues.length]));
// Make locale picker preference in sync with system settings
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Locale sysLocale = AppCompatDelegate.getApplicationLocales().get(0);
if (sysLocale == null) {
// Corresponds to "System"
localePreference.setValue("");
} else {
// Need to set preference's value to one of localePreference.getEntryValues() to match the locale.
// Locale.toLanguageTag() theoretically should be one of the values in localePreference.getEntryValues()...
// But it doesn't work for some locales. so trying something more heavyweight.
// Obtain all locales supported by the app.
List<Locale> appLocales = Arrays.stream(localePreference.getEntryValues())
.map(Objects::toString)
.map(Utils::stringToLocale)
.collect(Collectors.toList());
// Get the app locale that best matches the system one
Locale bestMatchLocale = Utils.getBestMatchLocale(appLocales, sysLocale);
// Get its index in supported locales
int index = appLocales.indexOf(bestMatchLocale);
// Set preference value to entry value at that index
localePreference.setValue(localePreference.getEntryValues()[index].toString());
}
}
localePreference.setOnPreferenceChangeListener((preference, newValue) -> {
// See corresponding comment in Utils.updateBaseContextLocale for Android 6- notes
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
refreshActivity(true);
return true;
}
String newLocale = (String) newValue;
// If newLocale is empty, that means "System" was selected
AppCompatDelegate.setApplicationLocales(newLocale.isEmpty() ? LocaleListCompat.getEmptyLocaleList() : LocaleListCompat.create(Utils.stringToLocale(newLocale)));
return true;
});
if (!DynamicColors.isDynamicColorAvailable()) {
colorPreference.setEntryValues(R.array.color_values_no_dynamic);
colorPreference.setEntries(R.array.color_value_strings_no_dynamic);
}
// Disable content provider on SDK < 23 since dangerous permissions
// are granted at install-time
Preference contentProviderReadPreference = findPreference(getResources().getString(R.string.settings_key_allow_content_provider_read));
assert contentProviderReadPreference != null;
contentProviderReadPreference.setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
}
private void refreshActivity(boolean reloadMain) {
@@ -161,25 +199,5 @@ public class SettingsActivity extends CatimaAppCompatActivity {
activity.recreate();
}
}
@Override
public void onDisplayPreferenceDialog(Preference preference) {
if (preference instanceof NumberDialogPreference) {
NumberDialogPreference dialogPreference = (NumberDialogPreference) preference;
DialogFragment dialogFragment = NumberPickerPreferenceDialogFragment
.newInstance(
dialogPreference.getKey(),
dialogPreference.getMinValue(),
dialogPreference.getMaxValue(),
dialogPreference.getStepValue(),
dialogPreference.getUnitText()
);
dialogFragment.setTargetFragment(this, 0);
dialogFragment.show(getParentFragmentManager(), DIALOG_FRAGMENT_TAG);
} else {
super.onDisplayPreferenceDialog(preference);
}
}
}
}
-9
View File
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" android:useLevel="true"
android:dither="true">
<size android:height="12dip" android:width="12dip"/>
<solid android:color="@android:color/white"/>
</shape>
@@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/>
<path android:fillColor="@android:color/white" android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
</vector>
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#BD0000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M10.94,8.12L7.48,4.66L9,3h6l1.83,2H20c1.1,0 2,0.9 2,2v12c0,0.05 -0.01,0.1 -0.02,0.16l-5.1,-5.1C16.96,13.71 17,13.36 17,13c0,-2.76 -2.24,-5 -5,-5C11.64,8 11.29,8.04 10.94,8.12zM20.49,23.31L18.17,21H4c-1.1,0 -2,-0.9 -2,-2V7c0,-0.59 0.27,-1.12 0.68,-1.49l-2,-2L2.1,2.1l19.8,19.8L20.49,23.31zM14.49,17.32l-1.5,-1.5C12.67,15.92 12.35,16 12,16c-1.66,0 -3,-1.34 -3,-3c0,-0.35 0.08,-0.67 0.19,-0.98l-1.5,-1.5C7.25,11.24 7,12.09 7,13c0,2.76 2.24,5 5,5C12.91,18 13.76,17.75 14.49,17.32z"/>
</vector>
@@ -0,0 +1,24 @@
<layer-list xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="?attr/colorSurface" />
<corners
android:bottomLeftRadius="28dp"
android:bottomRightRadius="28dp"
android:topLeftRadius="28dp"
android:topRightRadius="28dp" />
</shape>
</item>
<item>
<shape>
<solid android:color="@color/m3_popupmenu_overlay_color"
tools:ignore="PrivateResource" />
<corners
android:bottomLeftRadius="28dp"
android:bottomRightRadius="28dp"
android:topLeftRadius="28dp"
android:topRightRadius="28dp" />
</shape>
</item>
</layer-list>
@@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#FFFFFF"
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/>
@@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#FFFFFF"
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M16.59,8.59L12,13.17 7.41,8.59 6,10l6,6 6,-6z"/>
</vector>
@@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M7,14l5,-5 5,5z"/>
<path android:fillColor="@android:color/white" android:pathData="M7.41,8.59L12,13.17l4.59,-4.58L18,10l-6,6 -6,-6 1.41,-1.41z"/>
</vector>
@@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M7,10l5,5 5,-5z"/>
<path android:fillColor="@android:color/white" android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
</vector>
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2zM1,2v2h2l3.6,7.59 -1.35,2.45c-0.16,0.28 -0.25,0.61 -0.25,0.96 0,1.1 0.9,2 2,2h12v-2L7.42,15c-0.14,0 -0.25,-0.11 -0.25,-0.25l0.03,-0.12 0.9,-1.63h7.45c0.75,0 1.41,-0.41 1.75,-1.03l3.58,-6.49c0.08,-0.14 0.12,-0.31 0.12,-0.48 0,-0.55 -0.45,-1 -1,-1L5.21,4l-0.94,-2L1,2zM17,18c-1.1,0 -1.99,0.9 -1.99,2s0.89,2 1.99,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>
-10
View File
@@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>
@@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#FF000000"
android:pathData="M53.26,40.92l14.35,-6.39l2.86,6.42"
android:strokeAlpha="0.4"
android:fillAlpha="0.4"/>
<path
android:fillColor="#FF000000"
android:pathData="M36.14,40.95l2.86,-6.42l14.24,6.34"
android:strokeAlpha="0.4"
android:fillAlpha="0.4"/>
<path
android:fillColor="#FF000000"
android:pathData="M40.01,37.17l7.73,3.44H38.48l1.53,-3.44m26.58,0 l1.53,3.44H58.86l7.73,-3.44M39,34.53l-2.86,6.42v1.66H70.47V40.95L67.61,34.53 53.27,40.92l-0.02,-0.05L39,34.53Z"/>
<path
android:fillColor="#FF000000"
android:pathData="M74.07,51.23l4.93,1.41l-6.44,22.48l-37.61,-10.79l39.13,0l0,-13.11z"
android:strokeAlpha="0.7"
android:fillAlpha="0.7"/>
<path
android:fillColor="#FF000000"
android:pathData="M34.94,40.95C31.66,40.95 29,46.19 29,52.64s2.66,11.69 5.94,11.69L74.07,64.34L74.07,40.95ZM41.21,51.08 L40.15,50.02 44.43,45.74 48.71,50.02 47.65,51.08 44.43,47.86ZM58.02,56.56a3.11,3.11 0,0 1,-2.93 2.05,3.15 3.15,0 0,1 -0.55,-0.05 3.11,3.11 0,0 1,-1.83 -1.04,3.12 3.12,0 0,1 -5.3,-0.96 0.75,0.75 0,0 1,1.41 -0.51,1.62 1.62,0 0,0 3.14,-0.55 0.75,0.75 0,0 1,1.5 0,1.62 1.62,0 0,0 3.14,0.55 0.75,0.75 0,0 1,1.41 0.51ZM64.14,51.08 L60.92,47.86L57.71,51.08l-1.06,-1.06 4.28,-4.28 4.28,4.28Z"/>
</vector>
@@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>
@@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp" android:tint="?attr/colorControlNormal"
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
<path android:fillColor="@android:color/white" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>
@@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h1.9c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z"/>
<path android:fillColor="@android:color/white" android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
</vector>
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z" />
<path
android:fillColor="@android:color/white"
android:pathData="M18,15.782V22l4.886,-3.109z" />
<path
android:fillColor="@android:color/white"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12C2,17.52 6.47,22 11.99,22C13.417,22 14.772,21.699 16,21.162L16,18.928C14.823,19.608 13.458,20 12,20C7.58,20 4,16.42 4,12C4,7.58 7.58,4 12,4C16.42,4 20,7.58 20,12C20,13.061 19.791,14.073 19.416,15L21.541,15C21.839,14.053 22,13.045 22,12C22,6.48 17.52,2 11.99,2zM11,7L11,13L16,16L16,15L16.951,15L17,14.92L12.5,12.25L12.5,7L11,7z" />
</vector>
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" android:useLevel="true"
android:dither="true">
<size android:height="8dip" android:width="8dip"/>
<solid android:color="@android:color/white"/>
</shape>
+32 -4
View File
@@ -128,11 +128,10 @@
<TextView
android:id="@+id/translate_sub"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/translate_platform"
android:layout_marginEnd="20dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/translate_main"/>
@@ -169,11 +168,10 @@
<TextView
android:id="@+id/license_sub"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/app_license"
android:layout_marginEnd="20dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/license_main"/>
@@ -271,6 +269,36 @@
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/donate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/donate_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/donate"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:importantForAccessibility="no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/rate"
android:layout_width="match_parent"
@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="protect.card_locker.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
style="?attr/toolbarStyle" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/groups"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"
android:visibility="gone"/>
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -34,7 +34,7 @@
app:layout_constraintBottom_toTopOf="@+id/barcodeIdLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/enterBarcodeInstructions" />
android:text="@string/manually_enter_barcode_instructions" />
<LinearLayout
android:id="@+id/barcodeIdLayout"
android:orientation="horizontal"
@@ -42,7 +42,7 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/explanationText"
app:layout_constraintBottom_toTopOf="@+id/noBarcode"
app:layout_constraintBottom_toTopOf="@+id/barcodes"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<TextView android:textSize="16.0sp"
@@ -65,21 +65,11 @@
android:minHeight="48dp"
tools:ignore="ContentDescription" />
</LinearLayout>
<Button
android:id="@+id/noBarcode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/barcodeIdLayout"
app:layout_constraintBottom_toTopOf="@+id/barcodes"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/barcodeNoBarcode"
android:enabled="false" />
<ListView
android:id="@+id/barcodes"
android:layout_width="match_parent"
android:layout_height="fill_parent"
app:layout_constraintTop_toBottomOf="@+id/noBarcode"
app:layout_constraintTop_toBottomOf="@+id/barcodeIdLayout"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="protect.card_locker.MainActivity"
tools:showIn="@layout/custom_barcode_scanner">
<LinearLayout
android:id="@+id/camera_permission_denied_clickable_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/camera_permission_denied_icon"
android:layout_width="match_parent"
android:layout_height="84dp"
android:scaleType="fitCenter"
android:src="@drawable/camera_permission_denied" />
<TextView
android:id="@+id/camera_permission_denied_title"
style="@style/TextAppearance.Material3.HeadlineLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/cameraPermissionDeniedTitle" />
<TextView
android:id="@+id/camera_permission_denied_message"
style="@style/AppTheme.TextView.NoData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/noCameraPermissionDirectToSystemSetting" />
</LinearLayout>
</RelativeLayout>
+40 -20
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@@ -9,42 +8,63 @@
tools:context="protect.card_locker.MainActivity"
tools:showIn="@layout/main_activity">
<TextView
style="@style/AppTheme.TextView.NoData"
android:id="@+id/helpText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/noGiftCards"
android:visibility="gone"/>
<LinearLayout
android:visibility="gone"
android:id="@+id/helpSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/welcome_icon"
android:layout_width="match_parent"
android:layout_height="184dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_launcher_foreground" />
<TextView
android:id="@+id/welcome_text"
style="@style/TextAppearance.Material3.HeadlineLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/welcome" />
<TextView
android:id="@+id/add_card_instruction"
style="@style/AppTheme.TextView.NoData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/noGiftCards" />
</LinearLayout>
<TextView
style="@style/AppTheme.TextView.NoData"
android:id="@+id/noMatchingCardsText"
style="@style/AppTheme.TextView.NoData"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/noMatchingGiftCards"
android:visibility="gone"/>
android:visibility="gone" />
<TextView
style="@style/AppTheme.TextView.NoData"
android:id="@+id/noGroupCardsText"
style="@style/AppTheme.TextView.NoData"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/noGroupCards"
android:visibility="gone"/>
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="@integer/main_view_card_columns"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="80dp"
android:clipToPadding="false"
android:paddingBottom="80dp"
android:scrollbars="vertical"
android:visibility="gone"/>
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="@integer/main_view_card_columns" />
</RelativeLayout>
@@ -1,41 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Based on https://github.com/journeyapps/zxing-android-embedded/blob/0fdfbce9fb3285e985bad9971c5f7c0a7a334e7b/sample/src/main/res/layout/custom_barcode_scanner.xml originally released under Apache 2.0 -->
<?xml version="1.0" encoding="utf-8"?><!-- Based on https://github.com/journeyapps/zxing-android-embedded/blob/0fdfbce9fb3285e985bad9971c5f7c0a7a334e7b/sample/src/main/res/layout/custom_barcode_scanner.xml originally released under Apache 2.0 -->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/fabOtherOptions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
app:icon="@drawable/ic_baseline_unfold_more_24"
android:text="@string/action_more_options"
android:layout_margin="16dp" />
<com.journeyapps.barcodescanner.BarcodeView
android:id="@+id/zxing_barcode_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/zxing_barcode_surface"
app:zxing_framing_rect_width="250dp"
app:zxing_framing_rect_height="250dp"/>
app:zxing_framing_rect_height="250dp"
app:zxing_framing_rect_width="250dp" />
<com.journeyapps.barcodescanner.ViewfinderView
android:id="@+id/zxing_viewfinder_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/zxing_viewfinder_view"
app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
app:zxing_result_view="@color/zxing_custom_result_view"
app:zxing_viewfinder_laser="@color/zxing_custom_viewfinder_laser"
app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask"/>
app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:gravity="center_horizontal"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/card_input_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_scanner_padding">
<Button
android:id="@+id/add_from_image"
<include
android:id="@+id/camera_permission_denied_layout"
layout="@layout/camera_permission_failed_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/addFromImage" />
<Button
android:id="@+id/add_manually"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/addManually" />
</LinearLayout>
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</merge>
+28 -16
View File
@@ -37,36 +37,48 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageButton
<Button
android:id="@+id/moveUp"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24"
app:icon="@drawable/ic_baseline_keyboard_arrow_up_24"
app:iconGravity="textStart"
app:tint="?attr/colorOnPrimary"
android:contentDescription="@string/moveUp"/>
<ImageButton
<Button
android:id="@+id/moveDown"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="@drawable/ic_baseline_arrow_drop_down_24"
app:icon="@drawable/ic_baseline_keyboard_arrow_down_24"
app:iconGravity="textStart"
app:tint="?attr/colorOnPrimary"
android:contentDescription="@string/moveDown"/>
<ImageButton
<Button
android:id="@+id/edit"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="@drawable/ic_mode_edit_white_24dp"
app:icon="@drawable/ic_mode_edit_white_24dp"
app:iconGravity="textStart"
app:tint="?attr/colorOnPrimary"
android:contentDescription="@string/edit"/>
<ImageButton
<Button
android:id="@+id/delete"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="@drawable/ic_delete_white_24dp"
app:icon="@drawable/ic_delete_white_24dp"
app:iconGravity="textStart"
app:tint="?attr/colorOnPrimary"
android:contentDescription="@string/delete"/>
</LinearLayout>
@@ -288,7 +288,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:digits="0123456789.,$" />
android:digits="0123456789,." />
</com.google.android.material.textfield.TextInputLayout>
@@ -311,6 +311,32 @@
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<!-- Valid from -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="@dimen/inputPadding"
android:paddingTop="@dimen/inputPadding"
android:orientation="horizontal">
<!-- Valid from -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/validFromView"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:hint="@string/validFromDate"
android:labelFor="@+id/validFromField">
<AutoCompleteTextView
android:id="@+id/validFromField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<!-- Expiration -->
<LinearLayout
android:layout_width="match_parent"
+44 -11
View File
@@ -2,15 +2,15 @@
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="?attr/materialCardViewElevatedStyle"
android:id="@+id/row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
android:layout_margin="5dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp">
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="@+id/icon_layout"
@@ -24,7 +24,6 @@
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:importantForAccessibility="no"
android:id="@+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -36,6 +35,20 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/thumbnail_text"
android:importantForAccessibility="no"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textStyle="bold"
app:autoSizeTextType="uniform"
app:autoSizeMinTextSize="12sp"
app:autoSizeMaxTextSize="100sp"
app:autoSizeStepGranularity="2sp"
android:gravity="center"
android:maxLines="1"
android:layout_margin="20dp" />
<ImageView
android:importantForAccessibility="no"
android:id="@+id/selected_thumbnail"
@@ -124,7 +137,9 @@
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceHeadline1"
android:textAppearance="?attr/textAppearanceHeadlineSmall"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintTop_toBottomOf="@+id/icon_layout"
app:layout_constraintBottom_toTopOf="@+id/note"
app:layout_constraintEnd_toEndOf="parent"
@@ -139,7 +154,6 @@
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintTop_toBottomOf="@+id/store"
@@ -167,34 +181,53 @@
android:id="@+id/balance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
app:drawableLeftCompat="@drawable/ic_baseline_payments_24"
android:drawablePadding="4dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/info_divider"
app:layout_constraintBottom_toTopOf="@+id/expiry"
app:layout_constraintBottom_toTopOf="@+id/validFrom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible"
tools:text="525 points"/>
<TextView
android:id="@+id/expiry"
android:id="@+id/validFrom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
app:drawableLeftCompat="@drawable/ic_baseline_access_time_24"
app:drawableLeftCompat="@drawable/ic_valid_from_24dp"
android:drawablePadding="4dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/balance"
app:layout_constraintBottom_toTopOf="@+id/expiry"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible"
tools:text="Today"/>
<TextView
android:id="@+id/expiry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceBody2"
app:drawableLeftCompat="@drawable/ic_baseline_access_time_24"
android:drawablePadding="4dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/validFrom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -6,214 +6,200 @@
android:id="@+id/coordinator_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fitsSystemWindows="true">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:clipChildren="false"
android:clipToPadding="false"
android:fitsSystemWindows="true"
android:weightSum="1.0">
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_landscape"
android:layout_width="fill_parent"
android:layout_height="?actionBarSize"
android:background="@android:color/transparent"
android:fitsSystemWindows="false"
android:paddingTop="0dp"
android:visibility="gone"
app:contentInsetStart="72.0dip"
app:layout_collapseMode="pin" />
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
style="?attr/toolbarStyle" />
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"
android:layout_width="fill_parent"
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:layout_marginBottom="100dp"
android:orientation="vertical"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp">
<LinearLayout
android:id="@+id/icon_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:minHeight="56.0dip"
app:contentScrim="?colorPrimary"
app:expandedTitleGravity="top"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp">
android:layout_marginBottom="20dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/storeName"
<Space
android:layout_width="50dp"
android:layout_height="0dp"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<com.google.android.material.card.MaterialCardView
android:id="@+id/icon_holder"
android:layout_width="match_parent"
android:layout_height="0dp"
app:cardCornerRadius="8dp"
android:layout_margin="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="85.6f:53.98f">
<ImageView
android:id="@+id/icon_image"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/icon_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textStyle="bold"
app:autoSizeTextType="uniform"
app:autoSizeMinTextSize="12sp"
app:autoSizeMaxTextSize="100sp"
app:autoSizeStepGranularity="2sp"
android:gravity="center"
android:maxLines="1"
android:layout_margin="20dp" />
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<Space
android:layout_width="50dp"
android:layout_height="0dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layoutDirection="ltr">
<!-- We don't use these buttons for Talkback -->
<ImageButton
android:importantForAccessibility="no"
android:id="@+id/main_left_button"
android:layout_width="50dp"
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_baseline_chevron_left_24"
android:background="@android:color/transparent"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/card_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<com.google.android.material.card.MaterialCardView
android:id="@+id/main_card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardCornerRadius="8dp"
android:layout_margin="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:orientation="vertical">
<ImageView
android:id="@+id/main_image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<TextView
android:id="@+id/card_id_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/text_size_large"
android:ellipsize="end"
android:singleLine="true"
android:gravity="center"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- We don't use these buttons for Talkback -->
<ImageButton
android:importantForAccessibility="no"
android:id="@+id/main_right_button"
android:layout_width="50dp"
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_baseline_chevron_right_24"
android:background="@android:color/transparent"/>
</LinearLayout>
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/fullscreen_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:importantForAccessibility="no"
android:id="@+id/fullscreen_image"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/scaler_guideline"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/scaler_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/fullscreen_button_minimize"
android:layout_marginBottom="25dp"
android:layout_marginStart="15.0dip"
android:layout_marginEnd="15.0dip">
<TextView
android:importantForAccessibility="no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/height"/>
<SeekBar
android:id="@+id/barcode_scaler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="?actionBarSize"
android:layout_marginBottom="?actionBarSize"
android:ellipsize="end"
android:maxLines="1"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="40sp"
app:layout_collapseMode="parallax" />
android:contentDescription="@string/setBarcodeHeight"
android:max="100" />
</LinearLayout>
<androidx.appcompat.widget.Toolbar
android:id="@id/toolbar"
android:layout_width="fill_parent"
android:layout_height="?actionBarSize"
android:background="@android:color/transparent"
app:contentInsetStart="72.0dip"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ImageView
android:id="@+id/icon_image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_launcher_foreground"
tools:ignore="ContentDescription" />
<FrameLayout
android:clipChildren="false"
android:clipToPadding="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/centerGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/scalerGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.75"/>
<ImageButton
android:id="@+id/maximizeButton"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="15.0dip"
android:layout_marginTop="10dp"
android:layout_marginEnd="15.0dip"
android:background="?attr/colorPrimary"
android:contentDescription="@string/moveBarcodeToTopOfScreen"
android:padding="0dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/mainImage"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24"
app:tint="?attr/colorOnPrimary"
tools:visibility="visible" />
<ImageView
android:id="@+id/mainImage"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginStart="15.0dip"
android:layout_marginEnd="15.0dip"
app:layout_constraintBottom_toTopOf="@+id/centerGuideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/maximizeButton"/>
<ImageButton
android:id="@+id/minimizeButton"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="15.0dip"
android:layout_marginTop="10dp"
android:layout_marginEnd="15.0dip"
android:background="?attr/colorPrimary"
android:contentDescription="@string/moveBarcodeToCenterOfScreen"
android:padding="0dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/mainImage"
app:srcCompat="@drawable/ic_baseline_arrow_drop_down_24"
app:tint="?attr/colorOnPrimary"
tools:visibility="visible" />
<LinearLayout
android:id="@+id/dotIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15.0dip"
android:layout_marginTop="10dp"
android:layout_marginEnd="15.0dip"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/minimizeButton"
tools:visibility="visible" />
<SeekBar
android:id="@+id/barcodeScaler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/inputPadding"
android:layout_marginStart="15.0dip"
android:layout_marginEnd="15.0dip"
android:contentDescription="@string/set_scale"
android:max="100"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/scalerGuideline" />
<TextView
android:id="@+id/cardIdView"
android:enabled="true"
android:textIsSelectable="true"
android:focusable="true"
android:longClickable="true"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="10.0dip"
android:layout_marginRight="10.0dip"
android:paddingBottom="80dp"
app:layout_constraintTop_toBottomOf="@+id/dotIndicator"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:textAlignment="center"
app:autoSizeTextType="uniform"
app:autoSizeMinTextSize="@dimen/singleCardCardIdTextSizeMin"
app:autoSizeMaxTextSize="@dimen/singleCardCardIdTextSizeMax"
android:ellipsize="end"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:id="@+id/drop_shadow_actionbar"
android:layout_width="fill_parent"
android:layout_height="5.0dip"
android:layout_gravity="top"/>
</FrameLayout>
<ImageButton
android:id="@+id/fullscreen_button_minimize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_baseline_expand_more_24"
android:tooltipText="@string/moveDown"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="25dp"
android:background="@android:color/transparent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottom_app_bar"
@@ -228,41 +214,70 @@
app:contentInsetEnd="0dp"
app:fabAlignmentMode="center">
<ImageButton
android:id="@+id/button_previous"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="left"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="@android:color/transparent"
android:src="@drawable/ic_baseline_chevron_left_24"
android:tooltipText="@string/previousCard"
android:visibility="gone" />
android:layoutDirection="ltr">
<ImageButton
android:id="@+id/button_show_info"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="@android:color/transparent"
android:src="@drawable/ic_baseline_info_24"
android:tooltipText="@string/showMoreInfo"
android:visibility="gone" />
<ImageButton
android:id="@+id/bottom_app_bar_previous_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="@android:color/transparent"
android:src="@drawable/ic_baseline_chevron_left_24"
android:tooltipText="@string/previousCard"
android:visibility="gone" />
<ImageButton
android:id="@+id/button_next"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="@android:color/transparent"
android:src="@drawable/ic_baseline_chevron_right_24"
android:tooltipText="@string/nextCard"
android:visibility="gone" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
android:layoutDirection="locale">
<ImageButton
android:id="@+id/bottom_app_bar_info_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="@android:color/transparent"
android:src="@drawable/ic_baseline_info_24"
android:tooltipText="@string/showMoreInfo"
android:visibility="gone" />
<Space
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<ImageButton
android:id="@+id/bottom_app_bar_update_balance_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="@android:color/transparent"
android:src="@drawable/ic_baseline_shopping_cart_24"
android:tooltipText="@string/updateBalance"
android:visibility="gone" />
</LinearLayout>
<ImageButton
android:id="@+id/bottom_app_bar_next_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="@android:color/transparent"
android:src="@drawable/ic_baseline_chevron_right_24"
android:tooltipText="@string/nextCard"
android:visibility="gone" />
</LinearLayout>
</com.google.android.material.bottomappbar.BottomAppBar>
+3 -1
View File
@@ -36,6 +36,8 @@
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main"/>
<include
android:id="@+id/include"
layout="@layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -29,6 +29,8 @@
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/group_main"/>
<include
android:id="@+id/include"
layout="@layout/group_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.materialswitch.MaterialSwitch xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/switchWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:focusable="false" />
+6 -5
View File
@@ -10,12 +10,13 @@
<CheckBox
android:id="@+id/checkBox_reverse"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:paddingLeft="20dp"
android:layout_marginStart="20dp"
android:paddingStart="20dp"
android:text="@string/reverse"
android:textSize="19sp"/>
android:textSize="16sp"
android:textColor="?attr/colorOnSurfaceVariant"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Loaded 100 of 1503 files, more files were not shown because too many files have changed in this diff. Show more