Compare commits

..
1158 Commits
Author SHA1 Message Date
Sylvia van Os 4dfa6206ad Experiment: Use Extended Floating Action Buttons 2022-02-03 22:37:25 +01:00
Sylvia van Os a20f8b58f8 Fix more missing screenshots 2022-02-02 22:52:43 +01:00
Sylvia van Os fc8d0ac1aa Fix screenshots 2022-02-02 22:17:00 +01:00
Sylvia van Os 7290c4aa28 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-02-02 21:47:25 +01:00
Sylvia van Os f28e614c7f Update screenshots 2022-02-02 21:47:16 +01:00
Sylvia van Os 616b23d3a8 Merge pull request #785 from CatimaLoyalty/create-pull-request/patch-1643833796
Update Fastlane changelogs
2022-02-02 21:31:05 +01:00
TheLastProject 5fda774626 Update Fastlane changelogs 2022-02-02 20:29:56 +00:00
Sylvia van Os 30941a9e16 Update CHANGELOG 2022-02-02 21:28:48 +01:00
Sylvia van Os 9289d3cf0b Merge pull request #783 from Kethen/color_fixes
various color fixes
2022-02-02 20:30:27 +01:00
Sylvia van Os 0ecc36a83c Merge pull request #784 from ratneshnavlakhe/add-padding-to-main-list
Add padding to the bottom of the main list.
2022-02-02 19:54:53 +01:00
Katharine Chui d3b8569ef7 settings for pure black oled 2022-02-03 00:29:49 +08:00
Ratnesh Navlakhe 19722af65f Add padding to the bottom of the main list. 2022-02-01 23:37:43 +05:30
Katharine Chui 329be8abbb various color fixes
band-aid fixes for splash screen and material 3 dynamic color api

change editbutton icon's color in card view based on editbutton background color

make status bar transparent as per material 3, or tainted transparent for api level < 23 + light theme
2022-02-02 01:46:09 +08:00
bors[bot]andPetr Novák 9aa6acccda Merge #780
780: 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: Petr Novák <nit.monkey@gmail.com>
2022-02-01 11:19:59 +00:00
Petr Novák ba05c6872b Translated using Weblate (Czech)
Currently translated at 99.0% (99 of 100 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-02-01 09:53:24 +01:00
Petr Novák ca1fc214ff Translated using Weblate (Czech)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-02-01 09:53:24 +01:00
Sylvia van Os 2ebb3e1837 Merge pull request #778 from Altonss/patch-1
Update to 2.2.8 version of ucrop!
2022-01-31 17:33:52 +01:00
Altonss 019c5e232d Update to 2.2.8 version of ucrop! 2022-01-31 11:24:32 +01:00
dda527a72f Merge #775
775: 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: mondstern <mondstern@snopyta.org>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
2022-01-31 05:10:02 +00:00
Allan Nordhøy df0bbe773f Translated using Weblate (Norwegian Bokmål)
Currently translated at 21.0% (21 of 100 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nb_NO/
2022-01-31 04:55:15 +01:00
mondstern a320e1c776 Translated using Weblate (German)
Currently translated at 6.0% (6 of 100 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2022-01-30 15:56:23 +01:00
Sylvia van Os 607669a74c Merge pull request #774 from CatimaLoyalty/create-pull-request/patch-1643519707
Update contributors
2022-01-30 09:48:50 +01:00
TheLastProject f50dfeac9e Update contributors 2022-01-30 05:15:07 +00:00
bors[bot]andOğuz Ersen ef46f6a00b Merge #772
772: 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: Oğuz Ersen <oguzersen@protonmail.com>
2022-01-28 19:01:20 +00:00
Oğuz Ersen eafedb52ad Translated using Weblate (Turkish)
Currently translated at 58.0% (58 of 100 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2022-01-28 19:55:48 +01:00
bors[bot]andsolokot 423384fae6 Merge #770
770: 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: solokot <solokot@gmail.com>
2022-01-27 17:55:15 +00:00
solokot 09e96eba53 Translated using Weblate (Russian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-01-27 18:53:35 +01:00
Sylvia van Os 4b0a4a7db9 Merge pull request #769 from CatimaLoyalty/dependabot/gradle/androidx.preference-preference-1.2.0
Bump preference from 1.1.1 to 1.2.0
2022-01-27 17:45:06 +01:00
dependabot[bot] 2371738a15 Bump preference from 1.1.1 to 1.2.0
Bumps preference from 1.1.1 to 1.2.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-27 02:30:12 +00:00
Sylvia van Os e22d11f8e9 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-26 22:58:25 +01:00
Sylvia van Os 917e60a7f5 Fix lint 2022-01-26 22:58:02 +01:00
Sylvia van Os 4d09f66ac6 Merge pull request #768 from CatimaLoyalty/create-pull-request/patch-1643233121
Update Fastlane changelogs
2022-01-26 22:42:53 +01:00
TheLastProject 622aa96464 Update Fastlane changelogs 2022-01-26 21:38:41 +00:00
Sylvia van Os 9887e19ec9 Fix cropper not using theme colour 2022-01-26 22:38:02 +01:00
a308634868 Merge #766
766: 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: Quentin PAGÈS <quentinantonin@free.fr>
Co-authored-by: H Tamás <hovanszki@gmail.com>
2022-01-26 16:46:59 +00:00
H Tamás 44c3c8b32f Translated using Weblate (Hungarian)
Currently translated at 9.0% (9 of 99 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/hu/
2022-01-26 14:56:20 +01:00
H Tamás 69835ff0c9 Translated using Weblate (Hungarian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2022-01-26 14:56:20 +01:00
Quentin PAGÈS 8270bc6c03 Translated using Weblate (Occitan)
Currently translated at 38.2% (91 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/oc/
2022-01-26 14:56:20 +01:00
Sylvia van Os 9e8ea3384e Add PayPal 2022-01-24 22:21:21 +01:00
Sylvia van Os c8b258cd62 Merge pull request #760 from CatimaLoyalty/create-pull-request/patch-1642912504
Update contributors
2022-01-23 09:45:38 +01:00
TheLastProject f23c73a67a Update contributors 2022-01-23 04:35:04 +00:00
8ba3295ba1 Merge #759
759: 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: Oğuz Ersen <oguzersen@protonmail.com>
Co-authored-by: H Tamás <hovanszki@gmail.com>
2022-01-22 17:57:33 +00:00
H Tamás 6e3d61304f Translated using Weblate (Hungarian)
Currently translated at 33.6% (80 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hu/
2022-01-22 18:54:21 +01:00
Oğuz Ersen 9b7b3c4b9f Translated using Weblate (Turkish)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2022-01-22 18:54:21 +01:00
b993221af5 Merge #758
758: 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: H Tamás <hovanszki@gmail.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Co-authored-by: Michael Moroni <michaelmoroni@disroot.org>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: solokot <solokot@gmail.com>
Co-authored-by: Eric <alchemillatruth@purelymail.com>
Co-authored-by: 109247019824 <stoyan@gmx.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2022-01-21 22:03:16 +00:00
Oğuz Ersen 86c029fe92 Translated using Weblate (Turkish)
Currently translated at 99.5% (237 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2022-01-21 14:10:45 +01:00
109247019824 fbe857a5cf Translated using Weblate (Bulgarian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2022-01-21 14:10:45 +01:00
Eric 1717560c05 Translated using Weblate (Chinese (Simplified))
Currently translated at 79.4% (189 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2022-01-21 14:10:45 +01:00
solokot 02f85cd49a Translated using Weblate (Russian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-01-21 14:10:45 +01:00
Heimen Stoffels 69a6afe611 Translated using Weblate (Dutch)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2022-01-21 14:10:45 +01:00
Michael Moroni 94fa6d19c4 Translated using Weblate (Italian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-01-21 14:10:45 +01:00
J. Lavoie 211ee9ce69 Translated using Weblate (French)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2022-01-21 14:10:45 +01:00
J. Lavoie e818be3d50 Translated using Weblate (German)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-01-21 14:10:45 +01:00
Sylvia van Os 6620369616 Translated using Weblate (English)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2022-01-21 14:10:45 +01:00
H Tamás 9d9ce1d11f Added translation using Weblate (Hungarian) 2022-01-21 14:10:45 +01:00
76ba3c333e Merge #757
757: 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: Ati <ati@tutamail.com>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2022-01-20 19:21:08 +00:00
Sylvia van Os 0429086c57 Fix build 2022-01-20 20:20:36 +01:00
Ati 4a4b534813 Translated using Weblate (Slovak)
Currently translated at 84.0% (200 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2022-01-20 19:54:13 +01:00
Allan Nordhøy 8cfae80ea8 Translated using Weblate (Norwegian Bokmål)
Currently translated at 97.4% (232 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2022-01-20 19:54:13 +01:00
Ati 517a9cf37a Translated using Weblate (Czech)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-01-20 19:54:13 +01:00
Sylvia van Os 242f4b7ad9 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-18 23:14:25 +01:00
Sylvia van Os ce1a210650 Correctly make balancePoints a plural string 2022-01-18 23:14:12 +01:00
9d369a8e6f Merge #754
754: 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: Ati <ati@tutamail.com>
Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
Co-authored-by: Altons <marsupilami450@gmail.com>
Co-authored-by: Michael Moroni <michaelmoroni@disroot.org>
2022-01-18 21:56:59 +00:00
IllusiveMan196 240f73f743 Translated using Weblate (Ukrainian)
Currently translated at 24.2% (24 of 99 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2022-01-18 22:55:16 +01:00
Michael Moroni 3cf1579bb0 Translated using Weblate (Italian)
Currently translated at 5.0% (5 of 99 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2022-01-18 22:55:16 +01:00
Altons 171fb83249 Translated using Weblate (German)
Currently translated at 5.0% (5 of 99 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2022-01-18 22:55:16 +01:00
Altons 603b02911b Translated using Weblate (French)
Currently translated at 15.1% (15 of 99 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-01-18 22:55:16 +01:00
IllusiveMan196 ab5eb62bc1 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2022-01-18 22:55:16 +01:00
Ati 40b2b5c96f Translated using Weblate (Slovak)
Currently translated at 48.7% (116 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2022-01-18 22:55:16 +01:00
Sylvia van Os 6efe0f6c54 Merge pull request #752 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2022-01-17 20:41:05 +01:00
mondstern 00a78c6030 Translated using Weblate (Portuguese)
Currently translated at 87.8% (209 of 238 strings)

Translation: Catima/Android
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2022-01-16 14:55:06 +01:00
Oğuz Ersen 0db46614a8 Translated using Weblate (Turkish)
Currently translated at 55.5% (55 of 99 strings)

Translation: Catima/Android (Fastlane)
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2022-01-16 14:55:06 +01:00
Sylvia van Os 32d139f756 Merge pull request #750 from CatimaLoyalty/create-pull-request/patch-1642310230
Update contributors
2022-01-16 09:56:06 +01:00
TheLastProject c2c8b780c8 Update contributors 2022-01-16 05:17:09 +00:00
Sylvia van Os 057a58a3d6 Add FUNDING.yml 2022-01-15 14:01:16 +01:00
Sylvia van Os 551fbed8ad Release Catima 2.14.1 2022-01-15 13:46:49 +01:00
Sylvia van Os 468c86b5ea Merge pull request #748 from CatimaLoyalty/create-pull-request/patch-1642250378
Update Fastlane changelogs
2022-01-15 13:40:17 +01:00
TheLastProject 50cb3146bf Update Fastlane changelogs 2022-01-15 12:39:37 +00:00
Sylvia van Os 0853bd88a4 Various theming fixes 2022-01-15 13:39:19 +01:00
Sylvia van Os 3bbe8e9524 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-15 12:12:04 +01:00
Sylvia van Os ebc2e07fc4 Use new URLs 2022-01-15 12:11:57 +01:00
Sylvia van Os ad368e68eb Merge pull request #747 from CatimaLoyalty/create-pull-request/patch-1642244294
Update Fastlane changelogs
2022-01-15 11:59:07 +01:00
TheLastProject a1d4bb746f Update Fastlane changelogs 2022-01-15 10:58:14 +00:00
Sylvia van Os 44473ae921 Hide search, expand and sort icons until there is at least one card 2022-01-15 11:57:52 +01:00
Sylvia van Os 2c3d9f714c Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-14 23:07:21 +01:00
Sylvia van Os 13121e9869 Also colour scaler with card colour 2022-01-14 23:07:14 +01:00
Sylvia van Os 14116324fb Merge pull request #743 from CatimaLoyalty/create-pull-request/patch-1642196358
Update Fastlane changelogs
2022-01-14 22:40:14 +01:00
TheLastProject d207197055 Update Fastlane changelogs 2022-01-14 21:39:18 +00:00
Sylvia van Os a36775c6fd Release Catima 2.14.0 2022-01-14 22:38:52 +01:00
Sylvia van Os cae95d2577 Update screenshots to Material You 2022-01-14 21:54:10 +01:00
1c95a767c0 Merge #741
741: Material You redesign r=TheLastProject a=TheLastProject

I'm not super excited about the new dark theme's primary colour as generated by https://material-foundation.github.io/material-theme-builder/ for primary colour `#A83536` but alas...

![image](https://user-images.githubusercontent.com/1885159/149578453-72a6c345-e2ec-4271-9110-7ee39356b385.png)


Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2022-01-14 20:36:05 +00:00
Sylvia van Os 26fd3e3a58 Make spotBugs happy 2022-01-14 21:35:02 +01:00
Sylvia van Os e79be213fc Fix lint 2022-01-14 21:26:29 +01:00
Sylvia van Os 2010b9a25c Card-related colours on view screen 2022-01-14 21:05:50 +01:00
Sylvia van Os 355c2f9ceb Material You redesign 2022-01-14 20:27:11 +01:00
Sylvia van Os 43daeec5c3 Merge pull request #738 from TheLastProject/dependabot/gradle/androidx.constraintlayout-constraintlayout-2.1.3
Bump constraintlayout from 2.1.2 to 2.1.3
2022-01-14 07:23:26 +01:00
dependabot[bot] 5ddf77dd63 Bump material from 1.4.0 to 1.5.0
Bumps [material](https://github.com/material-components/material-components-android) from 1.4.0 to 1.5.0.
- [Release notes](https://github.com/material-components/material-components-android/releases)
- [Commits](https://github.com/material-components/material-components-android/compare/1.4.0...1.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-14 02:26:18 +00:00
dependabot[bot] 64fb91d644 Bump constraintlayout from 2.1.2 to 2.1.3
Bumps [constraintlayout](https://github.com/androidx/constraintlayout) from 2.1.2 to 2.1.3.
- [Release notes](https://github.com/androidx/constraintlayout/releases)
- [Commits](https://github.com/androidx/constraintlayout/commits)

---
updated-dependencies:
- dependency-name: androidx.constraintlayout:constraintlayout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-14 02:26:13 +00:00
Sylvia van Os 4921d9f4b0 Merge pull request #736 from TheLastProject/dependabot/gradle/androidx.core-core-splashscreen-1.0.0-beta01
Bump core-splashscreen from 1.0.0-alpha02 to 1.0.0-beta01
2022-01-13 08:19:33 +01:00
Sylvia van Os 8f9dd584b1 Merge pull request #735 from TheLastProject/dependabot/gradle/androidx.appcompat-appcompat-1.4.1
Bump appcompat from 1.4.0 to 1.4.1
2022-01-13 08:17:16 +01:00
dependabot[bot] 04f2cffeb3 Bump core-splashscreen from 1.0.0-alpha02 to 1.0.0-beta01
Bumps core-splashscreen from 1.0.0-alpha02 to 1.0.0-beta01.

---
updated-dependencies:
- dependency-name: androidx.core:core-splashscreen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-13 02:24:29 +00:00
dependabot[bot] 8ca899b7d1 Bump appcompat from 1.4.0 to 1.4.1
Bumps appcompat from 1.4.0 to 1.4.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-13 02:24:23 +00:00
c0f3e814a0 Merge #734
734: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: DEL <mylnico@yahoo.fr>
Co-authored-by: 109247019824 <stoyan@gmx.com>
2022-01-12 07:03:19 +00:00
109247019824 1eb8d03b74 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2022-01-12 07:53:48 +01:00
DEL ec0dc6bd4c Translated using Weblate (French)
Currently translated at 13.4% (13 of 97 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-01-12 07:53:48 +01:00
cd7b3d5970 Merge #733
733: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: vesp <vesp@post.cz>
Co-authored-by: Altons <marsupilami450@gmail.com>
Co-authored-by: Petr Novák <nit.monkey@gmail.com>
2022-01-10 22:55:22 +00:00
Petr Novák 55843899da Translated using Weblate (Czech)
Currently translated at 98.9% (96 of 97 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2022-01-10 23:53:36 +01:00
Altons d639013bea Translated using Weblate (German)
Currently translated at 4.1% (4 of 97 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2022-01-10 23:53:33 +01:00
Altons 45785b66e7 Translated using Weblate (French)
Currently translated at 9.2% (9 of 97 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-01-10 23:53:33 +01:00
Altons 6a20366cc9 Translated using Weblate (German)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-01-10 23:53:32 +01:00
vesp 4856e9e971 Translated using Weblate (Czech)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-01-10 23:53:32 +01:00
bors[bot]andPetr Novák 4141856287 Merge #732
732: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Petr Novák <nit.monkey@gmail.com>
2022-01-09 22:24:51 +00:00
Petr Novák 12196fc9b1 Translated using Weblate (Czech)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-01-09 23:21:07 +01:00
Sylvia van Os c73e7924ad Release Catima 2.13.1 2022-01-09 15:51:50 +01:00
Sylvia van Os acf83087f4 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-09 15:00:26 +01:00
Sylvia van Os 8ef507c011 Fix breaking scrolling 2022-01-09 15:00:20 +01:00
d36f82df05 Merge #728
728: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: vesp <vesp@post.cz>
Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: Maciej Błędkowski <mble@tuta.io>
Co-authored-by: solokot <solokot@gmail.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2022-01-09 09:47:42 +00:00
Oğuz Ersen 5f50e86234 Translated using Weblate (Turkish)
Currently translated at 49.4% (48 of 97 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2022-01-09 10:45:38 +01:00
Oğuz Ersen 733c9885e8 Translated using Weblate (Turkish)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2022-01-09 10:45:38 +01:00
solokot 4b7acefece Translated using Weblate (Russian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-01-09 10:45:38 +01:00
Maciej Błędkowski a6b950e2e1 Translated using Weblate (Polish)
Currently translated at 98.3% (234 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-01-09 10:45:37 +01:00
Heimen Stoffels c21f8098ef Translated using Weblate (Dutch)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2022-01-09 10:45:37 +01:00
J. Lavoie 3ccce45f17 Translated using Weblate (Italian)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-01-09 10:45:37 +01:00
J. Lavoie f096f63352 Translated using Weblate (French)
Currently translated at 100.0% (238 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2022-01-09 10:45:37 +01:00
J. Lavoie babd6ff9bb Translated using Weblate (German)
Currently translated at 99.5% (237 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-01-09 10:45:37 +01:00
vesp 3c5dea6fbf Translated using Weblate (Czech)
Currently translated at 86.5% (206 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-01-09 10:45:37 +01:00
Sylvia van Os 3bf7d827a1 Merge pull request #727 from TheLastProject/create-pull-request/patch-1641705432
Update contributors
2022-01-09 10:45:34 +01:00
TheLastProject eea03dd516 Update contributors 2022-01-09 05:17:12 +00:00
bors[bot]andAllan Nordhøy 92ceb7ee50 Merge #726
726: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Allan Nordhøy <epost@anotheragency.no>
2022-01-07 21:28:52 +00:00
Allan Nordhøy aba5dbfb38 Translated using Weblate (Norwegian Bokmål)
Currently translated at 97.8% (233 of 238 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2022-01-07 22:26:43 +01:00
Sylvia van Os 1ba4839544 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-07 22:26:37 +01:00
Sylvia van Os cca68cfcc5 Simplify 2022-01-07 22:26:29 +01:00
bors[bot]andMaciej Błędkowski d2043c331a Merge #725
725: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Maciej Błędkowski <mble@tuta.io>
2022-01-07 21:09:35 +00:00
Maciej Błędkowski b57bc7d7b6 Translated using Weblate (Polish)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2022-01-07 22:08:54 +01:00
Sylvia van Os 23fb6d9c6a Merge pull request #724 from TheLastProject/create-pull-request/patch-1641589559
Update Fastlane changelogs
2022-01-07 22:08:50 +01:00
TheLastProject 2498ee0354 Update Fastlane changelogs 2022-01-07 21:05:59 +00:00
Sylvia van Os eb38d0a8aa Accessibility fixes 2022-01-07 22:02:51 +01:00
cb0deaae27 Merge #720
720: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: solokot <solokot@gmail.com>
Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
2022-01-06 17:00:49 +00:00
IllusiveMan196 8220c8b32e Translated using Weblate (Ukrainian)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2022-01-06 17:54:58 +01:00
solokot 8458a2e79a Translated using Weblate (Russian)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-01-06 17:54:57 +01:00
bors[bot]andAltons d436a20b23 Merge #718
718: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Altons <marsupilami450@gmail.com>
2022-01-04 19:39:02 +00:00
Altons c24f3b6ece Translated using Weblate (French)
Currently translated at 8.3% (8 of 96 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2022-01-04 19:55:38 +01:00
Altons d5cb1a79d2 Translated using Weblate (French)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2022-01-04 19:55:38 +01:00
Altons 7040dbf997 Translated using Weblate (German)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2022-01-04 19:55:38 +01:00
Sylvia van Os d1685f2557 More metadata fixes 2022-01-03 21:05:11 +01:00
Sylvia van Os 36237d9b3e Release Catima 2.13.0 2022-01-03 19:19:34 +01:00
f968aba926 Merge #716
716: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Michael Moroni <michaelmoroni@disroot.org>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: solokot <solokot@gmail.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2022-01-03 18:00:48 +00:00
Oğuz Ersen 2d7960ddc4 Translated using Weblate (Turkish)
Currently translated at 48.9% (47 of 96 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2022-01-03 18:59:01 +01:00
Oğuz Ersen 4cdd168b8c Translated using Weblate (Turkish)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2022-01-03 18:59:00 +01:00
solokot 9de54872f3 Translated using Weblate (Russian)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2022-01-03 18:58:59 +01:00
Heimen Stoffels f8f0edd8d3 Translated using Weblate (Dutch)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2022-01-03 18:58:59 +01:00
Allan Nordhøy 3703f3d1ac Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.7% (232 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2022-01-03 18:58:59 +01:00
Michael Moroni 3bbd16e3a9 Translated using Weblate (Italian)
Currently translated at 100.0% (235 of 235 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-01-03 18:58:59 +01:00
Sylvia van Os a2947d1f58 Metadata fixes 2022-01-03 18:30:06 +01:00
Sylvia van Os 4b94dd8b48 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-03 17:47:57 +01:00
Sylvia van Os 62376769cd Update screenshots 2022-01-03 17:47:48 +01:00
Sylvia van Os e057a24526 Merge pull request #715 from TheLastProject/create-pull-request/patch-1641158322
Update Fastlane changelogs
2022-01-02 22:19:54 +01:00
TheLastProject 25cc1a1160 Update Fastlane changelogs 2022-01-02 21:18:42 +00:00
Sylvia van Os d7ed4aeff8 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-02 22:18:22 +01:00
Sylvia van Os 58ebb7c7bf Improve star icon contrast in main view 2022-01-02 22:18:11 +01:00
be2c586820 Merge #714
714: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Michael Moroni <michaelmoroni@disroot.org>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Co-authored-by: ssantos <ssantos@web.de>
2022-01-02 20:43:24 +00:00
ssantos 8a0b2d9460 Translated using Weblate (Portuguese)
Currently translated at 13.5% (13 of 96 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2022-01-02 21:42:33 +01:00
ssantos 4b1583ce4c Translated using Weblate (Portuguese (Portugal))
Currently translated at 87.6% (205 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt_PT/
2022-01-02 21:42:33 +01:00
ssantos 83c611f4ae Translated using Weblate (Portuguese)
Currently translated at 87.6% (205 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2022-01-02 21:42:33 +01:00
Oğuz Ersen 0a7082bed5 Translated using Weblate (Turkish)
Currently translated at 44.7% (43 of 96 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2022-01-02 21:42:33 +01:00
Allan Nordhøy 94c84c60f5 Translated using Weblate (Norwegian Bokmål)
Currently translated at 20.8% (20 of 96 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nb_NO/
2022-01-02 21:42:33 +01:00
Allan Nordhøy 4ce7f475f4 Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.7% (231 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2022-01-02 21:42:33 +01:00
Michael Moroni 75057d3c41 Translated using Weblate (Italian)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2022-01-02 21:42:33 +01:00
Sylvia van Os 62fce7231d Merge pull request #713 from TheLastProject/create-pull-request/patch-1641156077
Update Fastlane changelogs
2022-01-02 21:42:30 +01:00
TheLastProject d201d2e98f Update Fastlane changelogs 2022-01-02 20:41:17 +00:00
Sylvia van Os 36ff4ca9ae Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2022-01-02 21:40:57 +01:00
Sylvia van Os a7a775bc01 Put all barcode related fields together in the edit screen 2022-01-02 21:40:44 +01:00
Sylvia van Os d217ac8752 Merge pull request #709 from TheLastProject/create-pull-request/patch-1641100630
Update contributors
2022-01-02 09:07:47 +01:00
TheLastProject d376569ba1 Update contributors 2022-01-02 05:17:10 +00:00
bors[bot]andTheLastProject 1a09b1bd5e Merge #708
708: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2022-01-01 23:19:19 +00:00
TheLastProject ec1f4f8fbd Update Fastlane changelogs 2022-01-01 23:14:01 +00:00
Sylvia van Os 3883617a34 Smaller header when details are hidden 2022-01-02 00:10:37 +01:00
bors[bot]andvesp 2e7c8f39a7 Merge #705
705: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: vesp <vesp@post.cz>
2022-01-01 18:00:31 +00:00
vesp 7fc2bdc46e Translated using Weblate (Czech)
Currently translated at 87.6% (205 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2022-01-01 18:54:31 +01:00
bors[bot]andMaciej Błędkowski c141a8986c Merge #703
703: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Maciej Błędkowski <mble@tuta.io>
2022-01-01 13:27:48 +00:00
Maciej Błędkowski 70ad884aa3 Translated using Weblate (Polish)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2021-12-31 13:50:31 +01:00
bors[bot]andOğuz Ersen 2bd8aed853 Merge #702
702: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Oğuz Ersen <oguzersen@protonmail.com>
2021-12-28 16:14:08 +00:00
Oğuz Ersen 78f5908c33 Translated using Weblate (Turkish)
Currently translated at 33.3% (32 of 96 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-12-28 16:53:31 +01:00
Sylvia van Os 2f43febe95 Merge pull request #701 from TheLastProject/create-pull-request/patch-1640550052
Update Fastlane changelogs
2021-12-26 21:22:34 +01:00
TheLastProject 17d23de518 Update Fastlane changelogs 2021-12-26 20:20:52 +00:00
Sylvia van Os af831cfdbd Fixed pressing the save button multiple times creating multiple entries
Fixes #691
2021-12-26 21:20:27 +01:00
bors[bot]andTheLastProject 4476646317 Merge #700
700: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-12-26 07:44:16 +00:00
TheLastProject 958dc29689 Update contributors 2021-12-26 05:16:50 +00:00
Sylvia van Os 21216f3aa6 Release Catima 2.12.0 2021-12-23 17:41:06 +01:00
bors[bot]andOğuz Ersen 808dd73221 Merge #697
697: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Oğuz Ersen <oguzersen@protonmail.com>
2021-12-23 16:03:57 +00:00
Oğuz Ersen e3bd82f4a2 Translated using Weblate (Turkish)
Currently translated at 28.4% (27 of 95 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-12-23 16:53:14 +01:00
Sylvia van Os 2cbb105c21 Merge pull request #696 from TheLastProject/create-pull-request/patch-1640123935
Update Fastlane changelogs
2021-12-21 23:01:58 +01:00
TheLastProject 40c364a5e8 Update Fastlane changelogs 2021-12-21 21:58:54 +00:00
Sylvia van Os 8c484078b4 Mention various small fixes 2021-12-21 22:58:33 +01:00
f93f3b912d Merge #695
695: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Yevgeny M <yevgenym.lg3@gmail.com>
Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-12-20 17:09:03 +00:00
Sylvia van Os 934ef22a8c Translated using Weblate (Hebrew (Israel))
Currently translated at 33.7% (79 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/he_IL/
2021-12-20 12:51:14 +01:00
IllusiveMan196 732679f3f8 Translated using Weblate (Ukrainian)
Currently translated at 14.7% (14 of 95 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2021-12-19 08:33:17 +01:00
IllusiveMan196 2e7cbcbac9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-12-19 08:33:17 +01:00
Yevgeny M eb5161a382 Translated using Weblate (Hebrew (Israel))
Currently translated at 34.1% (80 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/he_IL/
2021-12-19 08:33:16 +01:00
bors[bot]andTheLastProject b765d77145 Merge #693
693: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-12-19 07:28:43 +00:00
TheLastProject ad344c7d12 Update contributors 2021-12-19 05:16:53 +00:00
Sylvia van Os d84ce6ff82 Remove Google-declined title 2021-12-17 16:59:50 +01:00
Sylvia van Os d4e388cf5d Fix some crashes after DB refactor 2021-12-16 22:49:22 +01:00
bors[bot]andNyatsuki 34fcedfa28 Merge #688
688: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Nyatsuki <Odamaki@yandex.ru>
2021-12-16 16:23:48 +00:00
Nyatsuki c75eed56f0 Translated using Weblate (Japanese)
Currently translated at 99.1% (232 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2021-12-16 10:51:04 +01:00
bors[bot]andSylvia van Os 8ce0ce82ef Merge #680
680: Cleanup DBHelper r=TheLastProject a=TheLastProject

Should fix #661 

Supersedes #678 

While #678 does fix the issue too, the real issue was that an importer could cause such a state issue. So I've instead been seriously cleaning up. While all the tests pass, I do want to test this slightly longer before merging it into master.

Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-12-14 19:24:29 +00:00
bors[bot]andKatharine 304754f991 Merge #677
677: 671 adding English to list of languages, 672, 607 relaunch main activity after language, theme change r=TheLastProject a=Kethen

#671, #672 please review
added #607

Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
Co-authored-by: Katharine Chui <kwchuiaa@connect.ust.hk>
2021-12-14 17:38:17 +00:00
Katharine Chui ab6e90d9f6 reload main activity with splash screen skip 2021-12-15 00:38:17 +08:00
Katharine 9df22f18f0 671 adding English to list of languages, 672 relaunch main activity after language change 2021-12-15 00:33:15 +08:00
bors[bot]andKatharine Chui 2eeec777d7 Merge #684
684: 681 fix star icon vector graphics, star color by theme when selected r=TheLastProject a=Kethen

#681 please review
![image](https://user-images.githubusercontent.com/22017945/145991885-991e09d5-913f-499d-94b1-03ae6326eb9f.png)
![image](https://user-images.githubusercontent.com/22017945/145992155-589f45d0-218b-4ab9-b351-2a58d19990bc.png)

![image](https://user-images.githubusercontent.com/22017945/145992048-a08f8e88-bce3-4bfc-a112-35dd991f4516.png)
![image](https://user-images.githubusercontent.com/22017945/145992074-e7699e72-e4d4-44d5-851c-5cd3c453a745.png)


Co-authored-by: Katharine Chui <kwchuiaa@connect.ust.hk>
2021-12-14 16:27:57 +00:00
Katharine Chui 1d41039de2 674 currency symbol order fixes (#679) 2021-12-14 17:26:18 +01:00
Katharine Chui 112b4a034c fix card icon layout 2021-12-14 20:16:36 +08:00
Katharine Chui 8c06427976 681 fix vector graphics, star color by theme when selected 2021-12-14 19:41:11 +08:00
486a2b887e Merge #682
682: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Altons <marsupilami450@gmail.com>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: solokot <solokot@gmail.com>
Co-authored-by: Eric <spice2wolf@gmail.com>
Co-authored-by: Joel A <joeax910@student.liu.se>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-12-14 07:44:19 +00:00
Oğuz Ersen 3f3f289f62 Translated using Weblate (Turkish)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-12-14 02:53:59 +01:00
Joel A bf2b28065d Translated using Weblate (Swedish)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-12-14 02:53:58 +01:00
Eric d00d25ad00 Translated using Weblate (Chinese (Simplified))
Currently translated at 80.7% (189 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2021-12-14 02:53:58 +01:00
solokot f1371daecb Translated using Weblate (Russian)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-12-14 02:53:58 +01:00
Heimen Stoffels 2fecc524f0 Translated using Weblate (Dutch)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-12-14 02:53:58 +01:00
Altons f5beffcad5 Translated using Weblate (French)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-12-14 02:53:58 +01:00
Altons b78bdb3ced Translated using Weblate (German)
Currently translated at 100.0% (234 of 234 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-12-14 02:53:57 +01:00
bors[bot]andKatharine f16b3ca119 Merge #675
675: 635 android 5 stuck row height, 619 star icon color r=TheLastProject a=Kethen

please review, for #635 and #619

https://user-images.githubusercontent.com/22017945/145800150-b3afa43e-de80-4172-bbdd-5d06af6276d1.mp4




Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
2021-12-13 22:06:26 +00:00
Sylvia van Os f2e820f7bb Cleanup DBHelper 2021-12-13 22:47:12 +01:00
Katharine cf38357f3e spotbug 2021-12-13 17:32:44 +08:00
Katharine 9862a9912f 619 adapt star color to card icon 2021-12-13 16:52:21 +08:00
Katharine 990968a67b 635 trigger requestLayout on possible card text view shrink 2021-12-13 15:08:46 +08:00
Sylvia van Os 3331cf9ccf Make spotBugs happy 2021-12-12 19:25:51 +01:00
Sylvia van Os 8a45222783 Simplify card shortcut code 2021-12-12 19:18:13 +01:00
d92efc020b Merge #670
670: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Michael Moroni <michaelmoroni@disroot.org>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
2021-12-12 10:48:38 +00:00
Michael Moroni deb1edb7a6 Translated using Weblate (Italian)
Currently translated at 4.2% (4 of 95 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/it/
2021-12-12 11:45:54 +01:00
Heimen Stoffels 3265a9eb4d Translated using Weblate (Dutch)
Currently translated at 100.0% (233 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-12-12 11:45:54 +01:00
Michael Moroni c0ed86818f Translated using Weblate (Italian)
Currently translated at 100.0% (233 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-12-12 11:45:54 +01:00
bors[bot]andTheLastProject 67d8a242b5 Merge #673
673: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-12-12 10:41:17 +00:00
TheLastProject d12a4bf75d Update contributors 2021-12-12 05:16:31 +00:00
e86db3887b Merge #667
667: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Altons <marsupilami450@gmail.com>
Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: solokot <solokot@gmail.com>
Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
Co-authored-by: Joel A <joeax910@student.liu.se>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-12-09 21:00:45 +00:00
Oğuz Ersen ce8488e515 Translated using Weblate (Turkish)
Currently translated at 28.4% (27 of 95 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-12-09 21:53:29 +01:00
Oğuz Ersen 5ef9aad5a7 Translated using Weblate (Turkish)
Currently translated at 100.0% (233 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-12-09 21:53:28 +01:00
Joel A d9fd3fd001 Translated using Weblate (Swedish)
Currently translated at 99.5% (232 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-12-09 21:53:28 +01:00
J. Lavoie f9f3efe1e2 Translated using Weblate (Finnish)
Currently translated at 71.6% (167 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2021-12-09 21:53:27 +01:00
Altons c5b9399fc4 Translated using Weblate (French)
Currently translated at 5.2% (5 of 95 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fr/
2021-12-09 21:53:27 +01:00
IllusiveMan196 19ad303508 Translated using Weblate (Ukrainian)
Currently translated at 99.5% (232 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-12-09 21:53:27 +01:00
solokot d5b9bb9ca1 Translated using Weblate (Russian)
Currently translated at 99.5% (232 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-12-09 21:53:26 +01:00
Heimen Stoffels c50661f1bd Translated using Weblate (Dutch)
Currently translated at 99.5% (232 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-12-09 21:53:26 +01:00
J. Lavoie afd8d2e675 Translated using Weblate (Italian)
Currently translated at 99.5% (232 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-12-09 21:53:26 +01:00
Altons be8765aab1 Translated using Weblate (French)
Currently translated at 100.0% (233 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-12-09 21:53:25 +01:00
J. Lavoie 5656751a14 Translated using Weblate (French)
Currently translated at 100.0% (233 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-12-09 21:53:25 +01:00
Altons 12b81f7fe5 Translated using Weblate (German)
Currently translated at 100.0% (233 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-12-09 21:53:24 +01:00
J. Lavoie 3ff64d9abc Translated using Weblate (German)
Currently translated at 100.0% (233 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-12-09 21:53:24 +01:00
Altons 0a39a8bb5b Translated using Weblate (English)
Currently translated at 100.0% (233 of 233 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2021-12-09 21:53:24 +01:00
bors[bot]andAltonss 64f68d5c19 Merge #666
666: Add long press to add card to group r=TheLastProject a=Altonss

Fixed issue #649.

Co-authored-by: Altonss <66519591+Altonss@users.noreply.github.com>
2021-12-09 18:48:15 +00:00
Altonss 2975c46f96 Update ManageGroupActivity.java
Fix long press to add card to group
2021-12-09 19:28:00 +01:00
bors[bot]anddependabot[bot] f6762df1cf Merge #665
665: Bump gradle from 7.0.3 to 7.0.4 r=TheLastProject a=dependabot[bot]

Bumps gradle from 7.0.3 to 7.0.4.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.android.tools.build:gradle&package-manager=gradle&previous-version=7.0.3&new-version=7.0.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-09 16:30:19 +00:00
dependabot[bot] 1aa0585909 Bump gradle from 7.0.3 to 7.0.4
Bumps gradle from 7.0.3 to 7.0.4.

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-09 02:19:09 +00:00
1cb20eeab3 Merge #663
663: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Andreas Blaser <andreas.blaser@outlook.com>
Co-authored-by: Altons <marsupilami450@gmail.com>
2021-12-08 19:31:49 +00:00
Altons c8acee2fbd Translated using Weblate (German)
Currently translated at 3.1% (3 of 94 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2021-12-08 20:31:13 +01:00
Andreas Blaser ff35773eed Translated using Weblate (German)
Currently translated at 3.1% (3 of 94 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/de/
2021-12-08 20:31:13 +01:00
Sylvia van Os 48403399ab Merge pull request #664 from TheLastProject/create-pull-request/patch-1638991178
Update Fastlane changelogs
2021-12-08 20:31:10 +01:00
TheLastProject 96dafeab70 Update Fastlane changelogs 2021-12-08 19:19:37 +00:00
Sylvia van Os d10e358e7d Document CODE 93 support 2021-12-08 20:19:20 +01:00
Altonss 71eb8c53bc Add code 93 (#659) 2021-12-08 20:18:15 +01:00
186c2d1d56 Merge #657
657: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Marco <magliano32@gmail.com>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: Eric <spice2wolf@gmail.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-12-07 17:34:52 +00:00
Oğuz Ersen 2efa35504f Translated using Weblate (Turkish)
Currently translated at 99.5% (231 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-12-07 18:32:34 +01:00
Eric ca1996da53 Translated using Weblate (Chinese (Simplified))
Currently translated at 81.4% (189 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2021-12-07 18:32:34 +01:00
Heimen Stoffels b8d0724446 Translated using Weblate (Dutch)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-12-07 18:32:34 +01:00
Marco c9a08e4f5b Translated using Weblate (Italian)
Currently translated at 89.2% (207 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-12-07 18:32:34 +01:00
Altonss 4920b67d0c Add translation platform details in about page (#656) 2021-12-07 18:32:28 +01:00
e8eb3fce5c Merge #655
655: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: solokot <solokot@gmail.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
Co-authored-by: Altons <marsupilami450@gmail.com>
2021-12-06 23:11:18 +00:00
solokot aaccae647a Translated using Weblate (Russian)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-12-07 00:06:32 +01:00
Altons df4e851bfe Translated using Weblate (French)
Currently translated at 90.0% (209 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-12-07 00:06:31 +01:00
Sylvia van Os 05c85dac14 Translated using Weblate (Russian)
Currently translated at 87.9% (204 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-12-06 21:03:58 +01:00
solokot 86d953bb74 Translated using Weblate (Russian)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-12-06 20:34:00 +01:00
Allan Nordhøy 1ecc39bea5 Less verbose strings (#645) 2021-12-06 20:33:56 +01:00
Sylvia van Os 4c9182eb0b Merge pull request #651 from weblate/weblate-catima-catima
Translations update from Hosted Weblate
2021-12-05 13:36:48 +01:00
Oğuz Ersen 62fafaff95 Translated using Weblate (Turkish)
Currently translated at 27.6% (26 of 94 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-12-05 12:53:33 +01:00
Oğuz Ersen aa0fdcc6b6 Translated using Weblate (Turkish)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-12-05 12:53:32 +01:00
Heimen Stoffels 6c33dba401 Translated using Weblate (Dutch)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-12-05 12:53:32 +01:00
Allan Nordhøy c07d9805e4 Translated using Weblate (Norwegian Bokmål)
Currently translated at 97.8% (227 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-12-05 12:53:31 +01:00
Arco 941a123db0 Translated using Weblate (French)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-12-05 12:53:31 +01:00
Arco 2e58421a80 Translated using Weblate (English)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2021-12-05 12:53:31 +01:00
Sylvia van Os ae28e02cce Merge pull request #650 from TheLastProject/create-pull-request/patch-1638681427
Update contributors
2021-12-05 12:17:48 +01:00
TheLastProject e5d8dc8d59 Update contributors 2021-12-05 05:17:07 +00:00
Sylvia van Os b85de0e089 Merge pull request #647 from TheLastProject/create-pull-request/patch-1638623066
Update Fastlane changelogs
2021-12-04 14:04:59 +01:00
TheLastProject 4264155837 Update Fastlane changelogs 2021-12-04 13:04:25 +00:00
Sylvia van Os d2a500824a Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-12-04 14:04:01 +01:00
Sylvia van Os 6a91d59050 Fix crash on sharing card + release 2.11.2 2021-12-04 14:03:52 +01:00
451c49d05f Merge #643
643: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Nyatsuki <Odamaki@yandex.ru>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-12-02 11:24:18 +00:00
Oğuz Ersen b4ec4b74ca Translated using Weblate (Turkish)
Currently translated at 26.8% (25 of 93 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-12-02 10:54:32 +01:00
Nyatsuki 6c254315af Translated using Weblate (Japanese)
Currently translated at 99.1% (230 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2021-12-02 10:54:31 +01:00
Allan Nordhøy dfaf61722f Translated using Weblate (Norwegian Bokmål)
Currently translated at 20.4% (19 of 93 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nb_NO/
2021-12-02 10:54:30 +01:00
bors[bot]anddependabot[bot] 2dbebea884 Merge #642
642: Bump robolectric from 4.7.2 to 4.7.3 r=TheLastProject a=dependabot[bot]

Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.7.2 to 4.7.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/robolectric/robolectric/releases">robolectric's releases</a>.</em></p>
<blockquote>
<h2>Robolectric 4.7.3</h2>
<p>This is a minor release that fixes <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6883">#6883</a>, a NoClassDefError that can occur if the <code>compileSdk</code> &lt; 31. Thanks for <a href="https://github.com/ninniuz"><code>`@​ninniuz</code></a>` for reporting and <a href="https://github.com/utzcoz"><code>`@​utzcoz</code></a>` for the fix (<a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6884">#6884</a>).</p>
<p>It also fixes a minor case of test pollution, where a single Activity could leak across tests (see 5a1f02aaf37f425f8938ae41df5d7aa1b72bba9c for details).</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/robolectric/robolectric/commit/3e1d0a34a16fa8dc8c39b4bafe22143ddaa179ca"><code>3e1d0a3</code></a> Bump version to 4.7.3.</li>
<li><a href="https://github.com/robolectric/robolectric/commit/aab519415eb1eddce706fbb6494a0141f0b11e8f"><code>aab5194</code></a> Use 'processResources' task instead of 'jar' task for nativeruntime</li>
<li><a href="https://github.com/robolectric/robolectric/commit/66829f64e1f1a9115d339c9b9f0b5b5a0013ca6c"><code>66829f6</code></a> Clear InputMethodManager.sInstance for SDK &gt; P</li>
<li><a href="https://github.com/robolectric/robolectric/commit/3e596affabe50eb376d47d65519d222f87f7e855"><code>3e596af</code></a> Only using AttributionSource for compile SDK 31 and above</li>
<li>See full diff in <a href="https://github.com/robolectric/robolectric/compare/robolectric-4.7.2...robolectric-4.7.3">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.robolectric:robolectric&package-manager=gradle&previous-version=4.7.2&new-version=4.7.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 07:09:06 +00:00
dependabot[bot] d7da942481 Bump robolectric from 4.7.2 to 4.7.3
Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.7.2 to 4.7.3.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.7.2...robolectric-4.7.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>
2021-12-02 02:22:33 +00:00
Sylvia van Os 6b4a01c954 Release Catima 2.11.1 2021-11-30 18:30:29 +01:00
Sylvia van Os aee7728f56 Merge pull request #639 from TheLastProject/create-pull-request/patch-1638292575
Update Fastlane changelogs
2021-11-30 18:16:54 +01:00
TheLastProject 6fbbe38542 Update Fastlane changelogs 2021-11-30 17:16:15 +00:00
Sylvia van Os 651744b770 Update CHANGELOG 2021-11-30 18:15:51 +01:00
Sylvia van Os a189ac22ce Prevent white on white status bar on Android 5 2021-11-29 21:29:44 +01:00
Sylvia van Os f4d71e4525 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-11-29 20:23:24 +01:00
Sylvia van Os 45ec062499 Remove selection animator as it can break (fixes #630) 2021-11-29 20:23:17 +01:00
Sylvia van Os 82d8e84d78 Merge pull request #633 from TheLastProject/create-pull-request/patch-1638210607
Update Fastlane changelogs
2021-11-29 19:31:13 +01:00
TheLastProject fa25bff46f Update Fastlane changelogs 2021-11-29 18:30:07 +00:00
Sylvia van Os 5648061a31 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-11-29 19:29:44 +01:00
Sylvia van Os 9cd2f66b40 Naively fix blurriness of letter icons 2021-11-29 19:29:36 +01:00
90b7b43faf Merge #626
626: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: 109247019824 <stoyan@gmx.com>
2021-11-29 07:09:59 +00:00
109247019824 cfe5865d35 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-11-29 00:52:08 +01:00
Allan Nordhøy 243898c441 Translated using Weblate (Norwegian Bokmål)
Currently translated at 19.5% (18 of 92 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nb_NO/
2021-11-29 00:52:08 +01:00
Sylvia van Os 0afc6f3976 Release Catima 2.11.0 2021-11-28 23:05:54 +01:00
Sylvia van Os fa95ea6a62 Make spotBugs happy 2021-11-28 22:57:10 +01:00
Sylvia van Os abb559afd6 Merge pull request #624 from TheLastProject/create-pull-request/patch-1638136040
Update Fastlane changelogs
2021-11-28 22:49:05 +01:00
TheLastProject 61e7d1b154 Update Fastlane changelogs 2021-11-28 21:47:20 +00:00
Sylvia van Os da594a8287 Fix getItemId mistake (fixes #623) 2021-11-28 22:47:02 +01:00
Sylvia van Os 15f5c4a67b Make cropper respect custom theme choice 2021-11-28 14:54:49 +01:00
Sylvia van Os 19f7af1e42 Use cropper card ratio (default) for icon layout 2021-11-28 14:14:45 +01:00
bors[bot]andTheLastProject b5b994642a Merge #621
621: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-11-28 08:38:54 +00:00
TheLastProject 45da445866 Update contributors 2021-11-28 05:15:51 +00:00
bors[bot]anddependabot[bot] 55b1ad1c55 Merge #613
613: Bump NumberPickerPreference from 1.0.3 to 1.0.4 r=TheLastProject a=dependabot[bot]

Bumps [NumberPickerPreference](https://github.com/invissvenska/NumberPickerPreference) from 1.0.3 to 1.0.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/invissvenska/NumberPickerPreference/releases">NumberPickerPreference's releases</a>.</em></p>
<blockquote>
<h2>Version 1.0.4</h2>
<h2>What's Changed</h2>
<ul>
<li>Migrate to latest Gradle version and Maven Publish plugin by <a href="https://github.com/invissvenska"><code>`@​invissvenska</code></a>` in <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/pull/10">invissvenska/NumberPickerPreference#10</a></li>
<li>Feature/migrate to new gradle and maven plugin by <a href="https://github.com/invissvenska"><code>`@​invissvenska</code></a>` in <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/pull/11">invissvenska/NumberPickerPreference#11</a></li>
<li>Develop by <a href="https://github.com/invissvenska"><code>`@​invissvenska</code></a>` in <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/pull/12">invissvenska/NumberPickerPreference#12</a></li>
<li>Develop by <a href="https://github.com/invissvenska"><code>`@​invissvenska</code></a>` in <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/pull/14">invissvenska/NumberPickerPreference#14</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/invissvenska/NumberPickerPreference/compare/1.0.3...1.0.4">https://github.com/invissvenska/NumberPickerPreference/compare/1.0.3...1.0.4</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/9ee00acc93e646eb2067f4945a5cc0ddcfde0de0"><code>9ee00ac</code></a> Develop (<a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/issues/14">#14</a>)</li>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/1035c87ae18f790868114d3e02186ab299e0cce6"><code>1035c87</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/issues/12">#12</a> from invissvenska/develop</li>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/93a5d495df29d5940286f963569ae816c4631ae6"><code>93a5d49</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/issues/11">#11</a> from invissvenska/feature/migrate_to_new_gradle_and_ma...</li>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/300af7866a488470d02aa8014b6d9049b4212235"><code>300af78</code></a> fix <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/issues/9">#9</a></li>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/391b8a85931df92ce24b2a2d00fce381edf90040"><code>391b8a8</code></a> increment version, removed commented code from gradle</li>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/ef4a9b3a63a2777d42de2b9e0728c3046c32d383"><code>ef4a9b3</code></a> set java version to 11 for jitpack by adding the jitpack yml</li>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/c28b95e5c82611d6b1fee98b93780a1246977cb3"><code>c28b95e</code></a> set java version to 11</li>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/2df1805d8242a7b66410fea3074efd7ae0902ece"><code>2df1805</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/issues/10">#10</a> from invissvenska/feature/migrate_to_new_gradle_and_ma...</li>
<li><a href="https://github.com/invissvenska/NumberPickerPreference/commit/71f4f5992e484da19a486095fd4afd7fb8d9673b"><code>71f4f59</code></a> Migrate to latest Gradle version and Maven Publish plugin</li>
<li>See full diff in <a href="https://github.com/invissvenska/NumberPickerPreference/compare/1.0.3...1.0.4">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.github.invissvenska:NumberPickerPreference&package-manager=gradle&previous-version=1.0.3&new-version=1.0.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-26 23:09:26 +00:00
bors[bot]andJoel A fcd6f075f6 Merge #617
617: Translations update from Hosted Weblate r=TheLastProject a=weblate

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


It also includes following components:

* [Catima/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: Joel A <joeax910@student.liu.se>
2021-11-26 22:15:35 +00:00
Joel A 3d2f119fdb Translated using Weblate (Swedish)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-11-26 22:53:13 +01:00
Sylvia van Os 05f4add5cd Merge pull request #616 from TheLastProject/create-pull-request/patch-1637958232
Update Fastlane changelogs
2021-11-26 21:24:28 +01:00
TheLastProject eb71d5f717 Update Fastlane changelogs 2021-11-26 20:23:51 +00:00
Sylvia van Os a64603d64e Fix Fastlane converter 2021-11-26 21:23:33 +01:00
Sylvia van Os e686bb36ce Mention power screen controls support 2021-11-26 21:21:49 +01:00
351a805046 Merge #505
505: Feature/power screen widgets r=TheLastProject a=TheLastProject

Continuation of #427

Fixes #146

Co-authored-by: /usr/local/ΕΨΗΕΛΩΝ <djechelon@zighinetto.org>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-11-26 20:12:33 +00:00
Sylvia van Os 466ac404bc Show "Not found" if card was removed 2021-11-26 20:25:41 +01:00
Sylvia van Os b5c0be8ed5 Make lint happy 2021-11-25 19:34:11 +01:00
Sylvia van Os f963b2fd4c Make spotBugs happy 2021-11-25 19:18:14 +01:00
dependabot[bot] c26ae45cdc Bump NumberPickerPreference from 1.0.3 to 1.0.4
Bumps [NumberPickerPreference](https://github.com/invissvenska/NumberPickerPreference) from 1.0.3 to 1.0.4.
- [Release notes](https://github.com/invissvenska/NumberPickerPreference/releases)
- [Commits](https://github.com/invissvenska/NumberPickerPreference/compare/1.0.3...1.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-25 02:15:52 +00:00
Sylvia van Os addb0896c0 Surrender to Google (fixes #439)
I can't do it anymore. I am just sick of wasting so much time trying to
get Google to listen. I am sick of talking to a brick wall. I am sick of
the complete lack of competence in Google's entire review department. I
am so tired of having the goalpost moved in front of my eyes over and
over again. And above all, I am sick and tired of asking my translators,
who I appreciate so damn much, to keep wasting their time on Google's
whims.

So here you go, Google. You win. I give up. I will not use a word that
Google Translate translates to "free", because saying my app is "free of
charge" is not allowed. I will not tell your employees over and over
again how to use a dictionary. I will not try to make your staff
understand that "free" meaning both "free of charge" and "freedom" is a
very English concept and is not a thing in the majority of languages.

It is a shame you have cornered the market, because if I could, I would
have avoided your Play Store altogether. At least F-Droid still exists,
so my users are not completely screwed whenever you next decide to
punish me for something arbitrary and incorrect again.

Please, Google, let this be the end of this nonsense.
2021-11-24 17:05:52 +01:00
Sylvia van Os c75bef4f01 Open on single click 2021-11-23 23:25:10 +01:00
Sylvia van Os f633fb39aa Use card icon image if available 2021-11-23 23:24:36 +01:00
Sylvia van Os 49200fff48 Fix most spotBugs issues 2021-11-23 23:23:58 +01:00
Sylvia van Os f4bd6a3f59 Merge remote-tracking branch 'origin' into feature/power_screen_widgets 2021-11-23 20:42:16 +01:00
Sylvia van Os 18021e7653 Remove unicode character from Norwegian title as per Google guidelines 2021-11-23 20:25:17 +01:00
bors[bot]andKatharine de364a4cc4 Merge #612
612: Replaced StartActivityForResult with ResultLaunchers r=TheLastProject a=Kethen

redoing #470

currently spotBug complains about an InputStream is not being closed properly, which it didn't catch before the refactoring

I'd suggest moving opening an inputStream inside the import thread

Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
Co-authored-by: Katharine Chui <kwchuiaa@connect.ust.hk>
2021-11-23 18:17:36 +00:00
Katharine Chui 3ba42aad6d always use getContentResolver().open(Input/Output)Stream, opening streams diffrently from URIs seems to be redundent
https://developer.android.com/reference/android/content/ContentResolver#openInputStream(android.net.Uri)

spotBug is also happier with those streams not getting closed within the scope of that function, for some reason unknown
2021-11-23 18:42:21 +08:00
Katharine 63fad8bae1 ImportExportActivity ActivityResultLauncher, minor clean ups 2021-11-23 18:35:29 +08:00
Katharine ad418bc9bd ScanActivity ActivityResultLauncher 2021-11-23 18:35:29 +08:00
Katharine b0263d8eb5 MainActivity ActivityResultLauncher 2021-11-23 18:35:29 +08:00
Sylvia van Os 97d3969f93 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-11-22 19:11:39 +01:00
Sylvia van Os 1c85172206 Google can't decide 2021-11-22 19:11:24 +01:00
bors[bot]anddependabot[bot] 711fa7ef81 Merge #611
611: Bump robolectric from 4.7.1 to 4.7.2 r=TheLastProject a=dependabot[bot]

Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.7.1 to 4.7.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/robolectric/robolectric/releases">robolectric's releases</a>.</em></p>
<blockquote>
<h2>Robolectric 4.7.2</h2>
<p>This is a minor release that fixes a memory leak of Theme objects in binary resources for Android S (<a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6872">#6872</a>). Thanks <a href="https://github.com/calvarez-ov"><code>`@​calvarez-ov</code></a>` for the report and helping debug.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/robolectric/robolectric/commit/9ed0797525050a0580cd685308d858c5988575ba"><code>9ed0797</code></a> Bump version to 4.7.2.</li>
<li><a href="https://github.com/robolectric/robolectric/commit/5a8c5def4f8b6a87b316e6a7666146c77127b6c9"><code>5a8c5de</code></a> Fix theme native object collection in Android S</li>
<li><a href="https://github.com/robolectric/robolectric/commit/666a5213a7ef00fc0840fafecf1c759a725e8084"><code>666a521</code></a> Migrate ShadowAccessibilityNodeInfo to reflector</li>
<li>See full diff in <a href="https://github.com/robolectric/robolectric/compare/robolectric-4.7.1...robolectric-4.7.2">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.robolectric:robolectric&package-manager=gradle&previous-version=4.7.1&new-version=4.7.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-22 17:48:11 +00:00
dependabot[bot] 2220a8e3c6 Bump robolectric from 4.7.1 to 4.7.2
Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.7.1 to 4.7.2.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.7.1...robolectric-4.7.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>
2021-11-22 02:25:20 +00:00
cd1bd31e23 Merge #610
610: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
Co-authored-by: SC <lalocas@protonmail.com>
2021-11-21 23:01:08 +00:00
SC f812194b1a Translated using Weblate (Portuguese)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2021-11-21 23:53:04 +01:00
IllusiveMan196 79c26cfed7 Translated using Weblate (Ukrainian)
Currently translated at 15.3% (14 of 91 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2021-11-21 23:53:04 +01:00
Sylvia van Os 85ea10303a Merge pull request #609 from TheLastProject/create-pull-request/patch-1637471752
Update contributors
2021-11-21 07:05:15 +01:00
TheLastProject 4196ad8d61 Update contributors 2021-11-21 05:15:51 +00:00
bors[bot]andIllusiveMan196 90be6a418b Merge #608
608: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
2021-11-20 21:59:18 +00:00
IllusiveMan196 2e2563cfc0 Translated using Weblate (Ukrainian)
Currently translated at 5.4% (5 of 91 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2021-11-20 22:53:02 +01:00
IllusiveMan196 983c207019 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-11-20 22:51:35 +01:00
Sylvia van Os 6a5983b7bf Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-11-20 14:37:23 +01:00
Sylvia van Os b34e69d5d5 Delete Portuguese title because it has been disallowed by Google 2021-11-20 14:36:55 +01:00
f1cd9ac935 Merge #606
606: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



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: g <muziejusinfo@gmail.com>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: solokot <solokot@gmail.com>
2021-11-20 12:02:05 +00:00
solokot 5eb56c934b Translated using Weblate (Russian)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-11-20 12:53:08 +01:00
Heimen Stoffels f9b24d4b1b Translated using Weblate (Dutch)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-11-20 12:53:07 +01:00
Allan Nordhøy 537b2cba82 Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.2% (228 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-11-20 12:53:07 +01:00
g d788a274a8 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-11-20 12:53:07 +01:00
J. Lavoie 57c383c064 Translated using Weblate (Italian)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-11-20 12:53:07 +01:00
J. Lavoie 49a8828007 Translated using Weblate (French)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-11-20 12:53:06 +01:00
J. Lavoie d56a31160a Translated using Weblate (German)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-11-20 12:53:06 +01:00
Sylvia van Os bb78f9c12a Fastlane cleanup 2021-11-20 00:32:15 +01:00
Sylvia van Os 00c005afce Tag CHANGELOG 2021-11-20 00:15:09 +01:00
Sylvia van Os c008767bd6 Release Catima 2.10.0 2021-11-20 00:14:33 +01:00
Sylvia van Os 5e15555ad4 Fix deprecations 2021-11-19 15:07:04 +01:00
bors[bot]anddependabot[bot] 916d12c504 Merge #604
604: Bump robolectric from 4.7 to 4.7.1 r=TheLastProject a=dependabot[bot]

Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.7 to 4.7.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/robolectric/robolectric/releases">robolectric's releases</a>.</em></p>
<blockquote>
<h2>Robolectric 4.7.1</h2>
<p>This is a minor release that fixes <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6858">#6858</a>. In that issue, certain Android classes could not be mocked by Mockito due to some changes to Robolectric instrumentation performed on interfaces.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/robolectric/robolectric/commit/c1e4fed8669a16de3b0281b2b15f3290aee1747c"><code>c1e4fed</code></a> Bump version to 4.7.1.</li>
<li><a href="https://github.com/robolectric/robolectric/commit/c9e861d3d70bd29617246f2d7c7cf31931d59b0a"><code>c9e861d</code></a> Bump to version 3 of preinstrumented jars</li>
<li><a href="https://github.com/robolectric/robolectric/commit/434a5347f18dc6bbe7a5381a30c6f20ac567bad5"><code>434a534</code></a> Limit instrumentation on interfaces</li>
<li>See full diff in <a href="https://github.com/robolectric/robolectric/compare/robolectric-4.7...robolectric-4.7.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.robolectric:robolectric&package-manager=gradle&previous-version=4.7&new-version=4.7.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-19 07:49:40 +00:00
bors[bot]anddependabot[bot] 854958e364 Merge #603
603: Bump zip4j from 2.9.0 to 2.9.1 r=TheLastProject a=dependabot[bot]

Bumps [zip4j](https://github.com/srikanth-lingala/zip4j) from 2.9.0 to 2.9.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/srikanth-lingala/zip4j/releases">zip4j's releases</a>.</em></p>
<blockquote>
<h2>v2.9.1</h2>
<p>Improvements:</p>
<ul>
<li><a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/341">#341</a> Add caching to Travis build process</li>
<li><a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/359">#359</a> Add PasswordCallback for encrypted Input Streams</li>
</ul>
<p>Bug fixes:</p>
<ul>
<li><a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/354">#354</a> Skip checking for directory when reading entries</li>
<li><a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/347">#347</a> Extract contents of sub-directory even when sub-directory entry does not exist</li>
<li><a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/348">#348</a> Fix bug in sub-folder extraction when folder name appears at the end of central directory</li>
<li><a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/363">#363</a> Avoid replacing Windows file name separator</li>
<li><a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/365">#365</a> Improve file header equals check to include offset of local file header</li>
<li><a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/380">#380</a> Use exception type WRONG_PASSWORD when password is null or empty for AES</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/860965237a746e481071a656377633f84dfb388b"><code>8609652</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/365">#365</a> Improve file header equals check to include offset of local file header</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/9eab02b675d23079fc87fe9a6c0d5503465d2e3e"><code>9eab02b</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/380">#380</a> Use exception type WRONG_PASSWORD when password is null or empty for AES</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/4e5e2d45ffb69255e8266b6d994b579c47fe9e2f"><code>4e5e2d4</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/363">#363</a> Removed invalid test</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/de9bb5f35d4e01451381c113c04040bd70f50f1c"><code>de9bb5f</code></a> Remove functional interface annotation</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/ec78cea98c505292a6d22d0ad6fbdccb38aa4b22"><code>ec78cea</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/363">#363</a> Avoid replacing Windows file name separator</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/2ec68db8b7dcac1e6867362c3cb1c80d5d793762"><code>2ec68db</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/359">#359</a> Add PasswordCallback for encrypted Input Streams</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/7a139612cea3b7abe5c666087e24d587de9ebeda"><code>7a13961</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/347">#347</a> Use exception type FILE_NOT_FOUND when entry does not exist in zip</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/3224fb8ef5b3f9dd8fc9b18683f20384f550d274"><code>3224fb8</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/347">#347</a> Fix failing tests</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/9ae5253f4b8bcf8ca9d8bf6263354d73fa6e19a4"><code>9ae5253</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/347">#347</a> Extract contents of sub-directory even when sub-directory entry does not...</li>
<li><a href="https://github.com/srikanth-lingala/zip4j/commit/14aebe0d05e7c7c3537fb2e4fcb80a31b07e8168"><code>14aebe0</code></a> <a href="https://github-redirect.dependabot.com/srikanth-lingala/zip4j/issues/348">#348</a> Fix bug in sub-folder extraction when folder name appears at the end of ...</li>
<li>Additional commits viewable in <a href="https://github.com/srikanth-lingala/zip4j/compare/v2.9.0...v2.9.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=net.lingala.zip4j:zip4j&package-manager=gradle&previous-version=2.9.0&new-version=2.9.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-19 07:45:09 +00:00
dependabot[bot] d295dd40fd Bump robolectric from 4.7 to 4.7.1
Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.7 to 4.7.1.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.7...robolectric-4.7.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>
2021-11-19 02:24:23 +00:00
dependabot[bot] 069a3c99ef Bump zip4j from 2.9.0 to 2.9.1
Bumps [zip4j](https://github.com/srikanth-lingala/zip4j) from 2.9.0 to 2.9.1.
- [Release notes](https://github.com/srikanth-lingala/zip4j/releases)
- [Commits](https://github.com/srikanth-lingala/zip4j/compare/v2.9.0...v2.9.1)

---
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>
2021-11-19 02:24:13 +00:00
bors[bot]andOğuz Ersen f1e7e5494d Merge #602
602: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-11-18 15:58:55 +00:00
Oğuz Ersen 189fe7d101 Translated using Weblate (Turkish)
Currently translated at 19.7% (18 of 91 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-11-18 16:53:14 +01:00
Oğuz Ersen 9a9ff77d1c Translated using Weblate (Turkish)
Currently translated at 100.0% (232 of 232 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-11-18 16:53:13 +01:00
bors[bot]andsolokot b8c1eaf88e Merge #601
601: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: solokot <solokot@gmail.com>
2021-11-18 15:23:53 +00:00
solokot e525a32511 Translated using Weblate (Russian)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-11-18 16:20:39 +01:00
Sylvia van Os de9f108534 Merge branch 'master' of github.com:TheLastProject/Catima 2021-11-18 16:20:28 +01:00
Sylvia van Os c5f0d03a1c Add button to toggle showing details on main screen 2021-11-18 16:20:00 +01:00
Sylvia van Os e592452d02 Use card shape for icons by default 2021-11-18 15:41:48 +01:00
d3d2b37001 Merge #599 #600
599: Bump appcompat from 1.3.1 to 1.4.0 r=TheLastProject a=dependabot[bot]

Bumps appcompat from 1.3.1 to 1.4.0.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=androidx.appcompat:appcompat&package-manager=gradle&previous-version=1.3.1&new-version=1.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

600: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: solokot <solokot@gmail.com>
2021-11-18 11:13:17 +00:00
solokot 3dbe4f8327 Translated using Weblate (Russian)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-11-18 09:53:07 +01:00
dependabot[bot] 3d81c1be08 Bump appcompat from 1.3.1 to 1.4.0
Bumps appcompat from 1.3.1 to 1.4.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-18 02:15:36 +00:00
bors[bot]andbors[bot] 333874e5e1 Merge #598
598: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: bors[bot] <bors[bot]@users.noreply.github.com>
2021-11-17 19:46:55 +00:00
bors[bot] 69a53a8408 Update Fastlane changelogs 2021-11-17 19:45:07 +00:00
bors[bot]andSylvia van Os 8dc479793b Merge #597
597: New card layout r=TheLastProject a=TheLastProject

TODO:
- [x] Fix cards sizing up to stay equal size but failing to size back down on group switch

Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-11-17 19:39:27 +00:00
Sylvia van Os a2d48a236b Tweak margins 2021-11-17 20:35:47 +01:00
Sylvia van Os 67f390f594 Update screenshots 2021-11-17 20:12:18 +01:00
Sylvia van Os 1a5109e036 Fix card sizing 2021-11-17 19:56:27 +01:00
bors[bot]andSylvia van Os ff42ead6b7 Merge #595
595: Cleanup barcode selector r=TheLastProject a=TheLastProject

Should make #592 easier to implement.

Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-11-17 18:17:41 +00:00
Sylvia van Os 2f8d8e79c1 Make spotBugs happy 2021-11-17 19:13:28 +01:00
bors[bot]anddependabot[bot] efa6ac1f6c Merge #596
596: Bump constraintlayout from 2.1.1 to 2.1.2 r=TheLastProject a=dependabot[bot]

Bumps [constraintlayout](https://github.com/androidx/constraintlayout) from 2.1.1 to 2.1.2.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/androidx/constraintlayout/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=androidx.constraintlayout:constraintlayout&package-manager=gradle&previous-version=2.1.1&new-version=2.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-17 17:50:21 +00:00
bors[bot]andKatharine Chui 4fc56068e1 Merge #593
593: prevent bottomSheet from growing a padding getting into/leaving fullscreen r=TheLastProject a=Kethen

From android 5 to 9, going into full screen then back adds a top padding onto the coordinator layout bottom sheet

This aims to prevent that by removing the bottom sheet before entering full screen, then adding it back after leaving full screen

Co-authored-by: Katharine Chui <kwchuiaa@connect.ust.hk>
2021-11-17 17:46:24 +00:00
Sylvia van Os 7a0253ddcd New card layout 2021-11-17 17:44:19 +01:00
dependabot[bot] ac3647695b Bump constraintlayout from 2.1.1 to 2.1.2
Bumps [constraintlayout](https://github.com/androidx/constraintlayout) from 2.1.1 to 2.1.2.
- [Release notes](https://github.com/androidx/constraintlayout/releases)
- [Commits](https://github.com/androidx/constraintlayout/commits)

---
updated-dependencies:
- dependency-name: androidx.constraintlayout:constraintlayout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-17 02:18:51 +00:00
Sylvia van Os fc902db170 Cleanup barcode selector 2021-11-16 23:57:56 +01:00
b7230ba2a7 Merge #594
594: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: solokot <solokot@gmail.com>
Co-authored-by: Joel A <joeax910@student.liu.se>
Co-authored-by: SC <lalocas@protonmail.com>
2021-11-16 19:56:20 +00:00
SC f5b71beb4b Translated using Weblate (Portuguese)
Currently translated at 17.7% (16 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2021-11-16 20:53:18 +01:00
Joel A 380a12e926 Translated using Weblate (Swedish)
Currently translated at 98.6% (227 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-11-16 20:53:17 +01:00
solokot f92f84ee5c Translated using Weblate (Russian)
Currently translated at 3.3% (3 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2021-11-16 20:53:16 +01:00
Katharine Chui e1eb049d05 prevent bottomSheet from growing a padding getting into/leaving fullscreen 2021-11-16 23:44:45 +08:00
bors[bot]anddependabot[bot] e03ca71728 Merge #591
591: Bump robolectric from 4.6.1 to 4.7 r=TheLastProject a=dependabot[bot]

Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.6.1 to 4.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/robolectric/robolectric/releases">robolectric's releases</a>.</em></p>
<blockquote>
<p>Robolectric 4.7 adds support for Android S (API level 31).</p>
<p>Another big feature is support for Apple Silicon (Mac M1). Robolectric 4.7 now contains its own native implementation of the android.database.sqlite package. For Mac M1 machines, this SQLite mode is the default. For other OS's and architecture, use <code>`@SQLiteMode(NATIVE)</code>` to enable it. This new mode is currently only available for Mac and Linux. Native SQLite should be <strong>significantly</strong> faster, around 50-90% faster for SQLite operations, than the <code>LEGACY</code> SQLite mode. There were also several other performance improvements made for SQLite operations -- <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6687">#6687</a>, <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6690">#6690</a>,  and <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6711">#6711</a> (thanks <a href="https://github.com/al-broco"><code>`@​al-broco</code></a>!).</p>`
<p>The support v4 shadows are also deprecated at this release, and they will be removed at Robolectric 4.8.</p>
<p>Robolectric 4.7 also supports JDK 17.</p>
<h2>What's Changed</h2>
<ul>
<li>Clear cookies after test finished for CookieManagerTest by <a href="https://github.com/utzcoz"><code>`@​utzcoz</code></a>` in <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6581">robolectric/robolectric#6581</a></li>
<li>Only using ApplicationExitInfo for compile sdk 30 and above by <a href="https://github.com/utzcoz"><code>`@​utzcoz</code></a>` in <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6590">robolectric/robolectric#6590</a></li>
<li>Rebase PR 4064 - Fix NPE during saving state of WebView by <a href="https://github.com/utzcoz"><code>`@​utzcoz</code></a>` in <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6597">robolectric/robolectric#6597</a></li>
<li>Converting the String version of directlyOn(...) to <a href="https://github.com/Direct"><code>`@​Direct</code></a>` with reflector(...). by <a href="https://github.com/hoisie"><code>`@​hoisie</code></a>` in <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6598">robolectric/robolectric#6598</a></li>
<li>Add ITelephonyRegistry to ShadowServiceManager <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6605">robolectric/robolectric#6605</a></li>
<li>Implement new #startActivity methods for ShadowCrossProfileApps. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6601">robolectric/robolectric#6601</a></li>
<li>Add ShadowMediaExtractor. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6592">robolectric/robolectric#6592</a></li>
<li>Converting onVsync calls from ReflectionHelpers to use <a href="https://github.com/Direct"><code>`@​Direct</code></a>` with reflector(...) instead. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6602">robolectric/robolectric#6602</a></li>
<li>Update ShadowDisplayEventReceiver to support S <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6609">robolectric/robolectric#6609</a></li>
<li>Converting the proxy version of directlyOn(...) to <a href="https://github.com/Direct"><code>`@​Direct</code></a>` with reflector(...). by <a href="https://github.com/hoisie"><code>`@​hoisie</code></a>` in <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6610">robolectric/robolectric#6610</a></li>
<li>Fix Robolectric camera shadows to work with newer SDK versions. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6611">robolectric/robolectric#6611</a></li>
<li>Converting recycleUnchecked calls to use <a href="https://github.com/Direct"><code>`@​Direct</code></a>` with reflector(...) in place of ReflectionHelpers. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6603">robolectric/robolectric#6603</a></li>
<li>Cleaning up unnecessary <a href="https://github.com/Direct"><code>`@​Direct</code></a>` annotations in DirectActivityReflector. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6616">robolectric/robolectric#6616</a></li>
<li>Fixing the incorrect method signature in AssetManagerReflector that breaks GitHub CI. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6612">robolectric/robolectric#6612</a></li>
<li>No longer automatically log everything in ShadowLog if stream is specified <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6617">robolectric/robolectric#6617</a></li>
<li>Support IntBuffer with copyPixelsFromBuffer <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6613">robolectric/robolectric#6613</a></li>
<li>Suppress missing /system/etc/fonts.xml log noise for SDK 27 <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6618">robolectric/robolectric#6618</a></li>
<li>Add perf stats for reflector class definition <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6624">robolectric/robolectric#6624</a></li>
<li>Use Object to replace GnssAntennaInfo.Listener at ShadowLocationManager by <a href="https://github.com/utzcoz"><code>`@​utzcoz</code></a>` in <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6623">robolectric/robolectric#6623</a></li>
<li>Trimming the localrepository string. by <a href="https://github.com/Squadella"><code>`@​Squadella</code></a>` in <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6653">robolectric/robolectric#6653</a></li>
<li>Merging the the separate Reflector interfaces for Message into one main interface. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6619">robolectric/robolectric#6619</a></li>
<li>Remove OldClassInstrumentor <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6621">robolectric/robolectric#6621</a></li>
<li>Remove unnecessary ShadowLegacyMessage.isInUse <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6626">robolectric/robolectric#6626</a></li>
<li>Converting directlyOn(...) to <a href="https://github.com/Direct"><code>`@​Direct</code></a>` with reflector(...) in ShadowWindow and ShadowPhoneWindow. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6625">robolectric/robolectric#6625</a></li>
<li>Intercept calls to methods in {<a href="https://github.com/link"><code>`@​link</code></a>` Socket} not present in the OpenJDK. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6622">robolectric/robolectric#6622</a></li>
<li>Use bulk operations in copyPixels{to,from}Buffer <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6628">robolectric/robolectric#6628</a></li>
<li>Improve reflector caching using a regular HashMap <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6629">robolectric/robolectric#6629</a></li>
<li>Add shadow method ShadowLauncherApps#getShortcutConfigActivityList.  <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6631">robolectric/robolectric#6631</a></li>
<li>Add OnPermissionChangedListener implementation to ShadowPackageManager. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6627">robolectric/robolectric#6627</a></li>
<li>Update minSdkVersion to 14 in some integration_test manifests <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6630">robolectric/robolectric#6630</a></li>
<li>Merge InvokeDynamicClassInstrumentor into ClassInstrumentor <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6632">robolectric/robolectric#6632</a></li>
<li>Add a shadow method for PackageManager#getText which gets a String associated with package name and resource id. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6634">robolectric/robolectric#6634</a></li>
<li>Pass through openInputStream calls for SCHEME_ANDROID_RESOURCE <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6636">robolectric/robolectric#6636</a></li>
<li>Names thread used by ShadowFileObserver to match behavior of FileObserver. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6640">robolectric/robolectric#6640</a></li>
<li>Migrate from <code>AnnotationValue#toString</code> to <code>auto-common</code>'s <code>AnnotationValues.toString</code>. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6638">robolectric/robolectric#6638</a></li>
<li>Fix fidelity issue with Cursor.getBlob on a String column <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6641">robolectric/robolectric#6641</a></li>
<li>Remove InvokeDynamic perf stats <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6644">robolectric/robolectric#6644</a></li>
<li>Fix SQLiteDatabaseTest foreign key test to match Android behavior <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6643">robolectric/robolectric#6643</a></li>
<li>Add cardId support for ShadowEuiccManager. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6642">robolectric/robolectric#6642</a></li>
<li>Add OnUidImportanceListener implementation to ShadowActivityManager and SCREEN_ON/SCREEN_OFF broadcasts to ShadowPowerManager. <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6639">robolectric/robolectric#6639</a></li>
<li>Instrument default interface methods <a href="https://github-redirect.dependabot.com/robolectric/robolectric/pull/6645">robolectric/robolectric#6645</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/robolectric/robolectric/commit/dc7bcfd314f196984a6626be0f253e733c98718b"><code>dc7bcfd</code></a> Bump version to 4.7.</li>
<li><a href="https://github.com/robolectric/robolectric/commit/b2706bf5c24c6153b27121c154099a45f1477b51"><code>b2706bf</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6827">#6827</a> from hoisie/artifact-build</li>
<li><a href="https://github.com/robolectric/robolectric/commit/ba989616d510ba9d6cb32db45e892ee77b42153c"><code>ba98961</code></a> Add a workflow to build the nativeruntime libraries</li>
<li><a href="https://github.com/robolectric/robolectric/commit/a5db353b55710a2a9a9a013bf11c79ccaddb10b7"><code>a5db353</code></a> Move clang/clang++ specification to CMakeLists</li>
<li><a href="https://github.com/robolectric/robolectric/commit/0388825391a387a3da5b14e3661bc66c0e6ea919"><code>0388825</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6844">#6844</a> from utzcoz/bump-asm-to-9.2</li>
<li><a href="https://github.com/robolectric/robolectric/commit/7d44fa13a24c3d508773538830b93ff087c0eace"><code>7d44fa1</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6845">#6845</a> from hoisie/disable-mac-universal-build</li>
<li><a href="https://github.com/robolectric/robolectric/commit/fe3bb986589a6edfcf8ebfbe5c9abae4f14c3e6e"><code>fe3bb98</code></a> Disable the universal library for Mac OS</li>
<li><a href="https://github.com/robolectric/robolectric/commit/5b1bd881a46eff5a28f0dc3e4606a8bd0ad231e0"><code>5b1bd88</code></a> Bump asm to 9.2 to support JDK 17 and 18</li>
<li><a href="https://github.com/robolectric/robolectric/commit/6a3305348df9007f1d52ccfd898583a2ef5bc0dc"><code>6a33053</code></a> Bump AGP to 7.1.0-beta03</li>
<li><a href="https://github.com/robolectric/robolectric/commit/4b2ecb9b59b3fd5b6d060c5e9149cde17c8c6884"><code>4b2ecb9</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/robolectric/robolectric/issues/6833">#6833</a> from hoisie/add-icu-submodule</li>
<li>Additional commits viewable in <a href="https://github.com/robolectric/robolectric/compare/robolectric-4.6.1...robolectric-4.7">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.robolectric:robolectric&package-manager=gradle&previous-version=4.6.1&new-version=4.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-15 07:17:16 +00:00
dependabot[bot] 9f3633b2ef Bump robolectric from 4.6.1 to 4.7
Bumps [robolectric](https://github.com/robolectric/robolectric) from 4.6.1 to 4.7.
- [Release notes](https://github.com/robolectric/robolectric/releases)
- [Commits](https://github.com/robolectric/robolectric/compare/robolectric-4.6.1...robolectric-4.7)

---
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>
2021-11-15 02:18:03 +00:00
Sylvia van Os 0b53bdf6eb Tag CHANGELOG release 2021-11-14 22:12:14 +01:00
Sylvia van Os 2536767437 Android Studio -> Reformat Code 2021-11-14 21:55:33 +01:00
Sylvia van Os 2bc7d13d50 Release Catima 2.9.0 2021-11-14 16:05:32 +01:00
bors[bot]andKatharine 84fef5a615 Merge #585
585: using icon on card view headers r=TheLastProject a=Kethen

some previews
![image](https://user-images.githubusercontent.com/22017945/141508586-9cf1a1e7-6312-4bea-8362-16f0bbed2a27.png)
![image](https://user-images.githubusercontent.com/22017945/141508626-b97fd7bd-701b-4fe8-8883-23f71489c57a.png)
![image](https://user-images.githubusercontent.com/22017945/141508668-790d0038-d6ae-429b-9c9b-efdb341ad1e3.png)
![image](https://user-images.githubusercontent.com/22017945/141508688-10c1ee3f-c215-4955-b941-16d94ef87e60.png)
![image](https://user-images.githubusercontent.com/22017945/141508745-c344bd7d-b0db-4d53-b98d-495a3b43423f.png)
![image](https://user-images.githubusercontent.com/22017945/141508774-7bdb111f-e3c2-41d0-87b3-4f75b067840b.png)


Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
Co-authored-by: Katharine Chui <kwchuiaa@connect.ust.hk>
2021-11-14 14:45:16 +00:00
Katharine Chui 0993f3180b show icon image under system topbar, fix bottom sheet UI after rotation 2021-11-14 22:10:16 +08:00
Katharine Chui f143e01685 fixes bottom sheet height after rotating in fullscreen, removes extra top padding in fullscreen mode, 204(5)->8 2021-11-14 22:10:16 +08:00
Katharine cb5a98edad using icon on card view headers 2021-11-14 22:10:16 +08:00
bors[bot]andTheLastProject 74157b2fe5 Merge #589
589: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-11-14 08:48:52 +00:00
TheLastProject 5b7d5599f9 Update contributors 2021-11-14 05:15:51 +00:00
bors[bot]andOğuz Ersen cdfcfebd77 Merge #588
588: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-11-13 17:07:14 +00:00
Oğuz Ersen 301fd880f5 Translated using Weblate (Turkish)
Currently translated at 18.8% (17 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-11-13 17:53:54 +01:00
bors[bot]andKatharine Chui 4a4ef1b148 Merge #587
587: use daynight theme for toolbar r=TheLastProject a=Kethen

Before:
![image](https://user-images.githubusercontent.com/22017945/141610761-9cff9903-1074-4bd2-9a29-e9273bfee90c.png)

After:
![image](https://user-images.githubusercontent.com/22017945/141610679-ff5a1110-139a-487f-9954-565887c53f7a.png)
![image](https://user-images.githubusercontent.com/22017945/141610688-9b727e9c-dbab-49d9-aa32-ac231fea647c.png)


Co-authored-by: Katharine Chui <kwchuiaa@connect.ust.hk>
2021-11-13 12:58:06 +00:00
Katharine Chui 0bc7f4a164 use daynight theme for toolbar 2021-11-13 15:47:34 +08:00
5e593d0ded Merge #584
584: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
Co-authored-by: SC <lalocas@protonmail.com>
2021-11-12 16:42:04 +00:00
SC e958fff7b4 Translated using Weblate (Portuguese)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2021-11-12 15:52:15 +01:00
IllusiveMan196 d81b236aa6 Translated using Weblate (Ukrainian)
Currently translated at 4.4% (4 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2021-11-12 15:52:15 +01:00
bors[bot]and109247019824 8be8737459 Merge #583
583: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: 109247019824 <stoyan@gmx.com>
2021-11-11 07:06:39 +00:00
109247019824 e80238bfcf Translated using Weblate (Bulgarian)
Currently translated at 99.5% (229 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-11-11 06:51:21 +01:00
bors[bot]andWeblate 211032c152 Merge #582
582: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Weblate <noreply@weblate.org>
2021-11-10 19:30:44 +00:00
Weblate 0bf50fb491 Added translation using Weblate (Portuguese (Portugal)) 2021-11-10 20:29:33 +01:00
Sylvia van Os 6f22e2d185 Fastlane fixes 2021-11-10 20:29:18 +01:00
bors[bot]andKatharine 31c341663f Merge #578
578: preserve shortcut icon shape by padding, getting round corners back on card lists r=TheLastProject a=Kethen

adding padding to icons referencing https://developer.android.com/reference/android/graphics/drawable/AdaptiveIconDrawable.html
![image](https://user-images.githubusercontent.com/22017945/140962982-88becacc-677d-4593-8b7e-15fcc2f9df7e.png)
![image](https://user-images.githubusercontent.com/22017945/140889147-a40ea4ed-5fb1-47b8-9ec1-59bab7d6577f.png)



Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
2021-11-10 18:31:16 +00:00
Katharine 40a68a55e2 simplify adaptive bitmap creation with Canvas, trigger shortcut list refresh on card save 2021-11-10 14:06:08 +08:00
Katharine 1fd0acf6e4 padding images with darken header color, remove outline artifacts behind thumbnail on card lists 2021-11-10 14:06:08 +08:00
127d288ace Merge #581
581: Translations update from Hosted Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Petr Novák <nit.monkey@gmail.com>
Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Co-authored-by: g <muziejusinfo@gmail.com>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: solokot <solokot@gmail.com>
Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-11-09 21:56:30 +00:00
Oğuz Ersen 11587631a9 Translated using Weblate (Turkish)
Currently translated at 18.8% (17 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-11-09 22:53:04 +01:00
Oğuz Ersen 466b3d91d3 Translated using Weblate (Turkish)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-11-09 22:53:03 +01:00
Petr Novák 8f4f7524c4 Translated using Weblate (Czech)
Currently translated at 98.8% (89 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-11-09 22:53:03 +01:00
IllusiveMan196 f35aa2a064 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-11-09 22:53:00 +01:00
solokot c20206fe28 Translated using Weblate (Russian)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-11-09 22:53:00 +01:00
Heimen Stoffels 45de3f6616 Translated using Weblate (Dutch)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-11-09 22:52:59 +01:00
g 6f42b30790 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-11-09 22:52:59 +01:00
J. Lavoie 35eab50775 Translated using Weblate (Italian)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-11-09 22:52:59 +01:00
J. Lavoie 19d302e0a4 Translated using Weblate (French)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-11-09 22:52:59 +01:00
J. Lavoie a17ccfa41a Translated using Weblate (German)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-11-09 22:52:58 +01:00
Petr Novák a22e05284c Translated using Weblate (Czech)
Currently translated at 100.0% (230 of 230 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-11-09 22:52:58 +01:00
bors[bot]anddependabot[bot] 64491a1f7a Merge #576
576: Bump ucrop from 2.2.6 to 2.2.7 r=TheLastProject a=dependabot[bot]

Bumps [ucrop](https://github.com/Yalantis/uCrop) from 2.2.6 to 2.2.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/Yalantis/uCrop/releases">ucrop's releases</a>.</em></p>
<blockquote>
<h2>2.2.7</h2>
<p>Merged <a href="https://github-redirect.dependabot.com/Yalantis/uCrop/pull/732">PR 732</a>:
-- added support of &quot;content&quot; schema
-- added support for SAF requirements</p>
<p>Merged <a href="https://github-redirect.dependabot.com/Yalantis/uCrop/pull/758">PR 758</a>:
-- added ability to set OkHttpClient with custom settings
-- updated dependencies (exif interface, app compat, transition, okhttp3)</p>
<h2>2.2.6-native</h2>
<p>-- Fixed Bitmap too large exception</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/Yalantis/uCrop/commit/64c8f5b085056e127fb05bd6631cfbe2d5d005a1"><code>64c8f5b</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/Yalantis/uCrop/issues/762">#762</a> from Yalantis/improve/update_sample_app</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/70546c1016b52f1624a5d3e95860f68eb57084ef"><code>70546c1</code></a> Updated dependencies</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/0ff3e6a8e8224a3dadefdf68ca00383c8e25d443"><code>0ff3e6a</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/Yalantis/uCrop/issues/732">#732</a> from fabio-blanco/fix/non_native_android-10_saf-desti...</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/cd17761b36ce38bdd42a71e1c931d1bda56594d4"><code>cd17761</code></a> Merge branch 'master-non-native' into merge_non_native_android-10_saf-destina...</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/586493a7629eea0748da854565998e3dbc077b43"><code>586493a</code></a> Added an IllegalArgumentException in the copyFile method to inform that an un...</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/32e0fcd887b31e24bd142f2745c7e9148a0700d5"><code>32e0fcd</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/Yalantis/uCrop/issues/758">#758</a> from Yalantis/fix/non_native_ssl_handshake_exception</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/eb2d32fe9607f4ff9a5db3824eb4fa2e3678add8"><code>eb2d32f</code></a> Refactorings on BitmapCropTask for improving readability protections against ...</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/fd651666f6a64157f2d13b564993dddf0056c2b1"><code>fd65166</code></a> added UCropInitializer,</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/22b24bafa3990f3e50b9bf6eca1057207430734b"><code>22b24ba</code></a> NullPointerException protection on weak reference of context get on crop method.</li>
<li><a href="https://github.com/Yalantis/uCrop/commit/fd919ea5403c48470fd5beca81361aa8391b4256"><code>fd919ea</code></a> added documentation for UCropHttpClientStore methods</li>
<li>Additional commits viewable in <a href="https://github.com/Yalantis/uCrop/compare/2.2.6...2.2.7">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.github.yalantis:ucrop&package-manager=gradle&previous-version=2.2.6&new-version=2.2.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-09 17:33:46 +00:00
bors[bot]andKatharine 472d8ae18d Merge #577
577: offer 1:1 by default when cropping icon, set header color only for icon r=TheLastProject a=Kethen

header color is only change after an icon is set
cropper offers 1:1 by default instead when an icon is getting cropped

Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
2021-11-08 18:45:38 +00:00
Sylvia van Os 388db6feab Uppercase Card for consistency too 2021-11-08 19:42:51 +01:00
Katharine 5833d49fbf offer 1:1 by default when cropping icon, set header color only for icon 2021-11-08 19:10:41 +08:00
dependabot[bot] ffb2fadcfc Bump ucrop from 2.2.6 to 2.2.7
Bumps [ucrop](https://github.com/Yalantis/uCrop) from 2.2.6 to 2.2.7.
- [Release notes](https://github.com/Yalantis/uCrop/releases)
- [Commits](https://github.com/Yalantis/uCrop/compare/2.2.6...2.2.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-08 02:26:27 +00:00
Sylvia van Os 5f534b9646 Merge pull request #573 from TheLastProject/create-pull-request/patch-1636313316
Update Fastlane changelogs
2021-11-07 20:46:20 +01:00
e011324b9f Merge #572
572: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Marnick L'Eau <leaumar@mailbox.org>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-11-07 19:29:09 +00:00
TheLastProject 21df76a2b6 Update Fastlane changelogs 2021-11-07 19:28:36 +00:00
Oğuz Ersen 1af9789cf6 Translated using Weblate (Turkish)
Currently translated at 18.8% (17 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-11-07 20:28:20 +01:00
Marnick L'Eau b891e05fb9 Translated using Weblate (Dutch)
Currently translated at 10.0% (9 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nl/
2021-11-07 20:28:20 +01:00
Sylvia van Os 55e09b602f Update CHANGELOG 2021-11-07 20:28:09 +01:00
Sylvia van Os af4075b9e2 Choose image as card icon (#333) 2021-11-07 20:27:28 +01:00
+1 da0a221c85 Merge #571
571: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Co-authored-by: g <muziejusinfo@gmail.com>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
Co-authored-by: Marnick L'Eau <leaumar@mailbox.org>
Co-authored-by: Eric <spice2wolf@gmail.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Co-authored-by: SC <lalocas@protonmail.com>
2021-11-07 16:57:03 +00:00
SC 191445b822 Translated using Weblate (Portuguese)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2021-11-07 17:51:18 +01:00
Oğuz Ersen d890b062a9 Translated using Weblate (Turkish)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-11-07 17:51:18 +01:00
Eric 59173443e7 Translated using Weblate (Chinese (Simplified))
Currently translated at 82.8% (189 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2021-11-07 17:51:18 +01:00
Marnick L'Eau 5da76c9d9c Translated using Weblate (Dutch)
Currently translated at 5.5% (5 of 90 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nl/
2021-11-07 17:51:17 +01:00
IllusiveMan196 f048566929 Translated using Weblate (Ukrainian)
Currently translated at 99.5% (227 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-11-07 17:51:17 +01:00
Heimen Stoffels fe0f4314db Translated using Weblate (Dutch)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-11-07 17:51:16 +01:00
Allan Nordhøy 8d39bd671c Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.2% (224 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-11-07 17:51:16 +01:00
g 9ad33a047f Translated using Weblate (Lithuanian)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-11-07 17:51:16 +01:00
J. Lavoie 2a78335607 Translated using Weblate (Italian)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-11-07 17:51:16 +01:00
J. Lavoie d99c72982d Translated using Weblate (French)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-11-07 17:51:15 +01:00
J. Lavoie 79ced018d5 Translated using Weblate (German)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-11-07 17:51:15 +01:00
Sylvia van Os f80c79ffb1 Translated using Weblate (English)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2021-11-07 17:51:15 +01:00
Sylvia van Os 11970004f0 Android Studio reformat 2021-11-07 15:38:55 +01:00
bors[bot]andTheLastProject a348ad62a2 Merge #570
570: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-11-07 12:01:42 +00:00
TheLastProject 22d612427f Update contributors 2021-11-07 05:15:30 +00:00
Sylvia van Os a907b28fe8 Merge pull request #569 from TheLastProject/create-pull-request/patch-1636205659
Update Fastlane changelogs
2021-11-06 14:34:58 +01:00
TheLastProject 663612dce9 Update Fastlane changelogs 2021-11-06 13:34:18 +00:00
Sylvia van Os a55da89eb2 Update CHANGELOG 2021-11-06 14:33:59 +01:00
bors[bot]andKatharine 63ceb2589f Merge #559
559: #372 image rotation and crop r=TheLastProject a=Kethen

`@waffshappen` suggested https://github.com/Yalantis/uCrop
targets #372



https://user-images.githubusercontent.com/22017945/139484703-e33a5da8-ccb5-4d6a-b70c-3325e34fcec9.mp4

 


Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
2021-11-06 13:25:39 +00:00
Katharine dd981d72d7 do not attempt image load if removed, typo fixes, do not cast literals, offer full image on cropper start 2021-11-06 12:47:08 +08:00
Katharine 8940a8ea77 card edit activity: revised instance saving, revised temp image handling 2021-11-05 00:01:03 +08:00
Katharine 57cfac3172 save state for cropper 2021-11-04 10:48:47 +08:00
Katharine f475844bd0 wrapping up test case debugging 2021-11-04 10:48:47 +08:00
Katharine 4536453fdf debugging test case breakage 2021-11-04 10:48:47 +08:00
Katharine 3ee533b815 migrate to registerForActivityResult callbacks 2021-11-04 10:48:47 +08:00
Katharine a744c19cce handle null intent from ucrop for when user just exits without finish cropping 2021-11-04 10:48:46 +08:00
Katharine 9cc66c5d67 minor touch ups from android studio suggestions 2021-11-04 10:48:46 +08:00
Katharine 3e5b018b55 fxing spotbug raised issues 2021-11-04 10:48:46 +08:00
Katharine f6fee780ee cropper poc 2021-11-04 10:48:32 +08:00
6971f23d0a Merge #567
567: Translations update from Weblate r=TheLastProject a=weblate

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



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: solokot <solokot@gmail.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-11-03 21:34:43 +00:00
Oğuz Ersen 6d33576936 Translated using Weblate (Turkish)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-11-03 22:33:22 +01:00
solokot b6c9b9059e Translated using Weblate (Russian)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-11-03 22:33:21 +01:00
J. Lavoie 000bd7b734 Translated using Weblate (Italian)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-11-03 22:33:21 +01:00
J. Lavoie 3dde4de775 Translated using Weblate (French)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-11-03 22:33:21 +01:00
J. Lavoie 9b867370c2 Translated using Weblate (German)
Currently translated at 100.0% (228 of 228 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-11-03 22:33:20 +01:00
bors[bot]andTheLastProject c092a04390 Merge #566
566: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-11-03 20:40:54 +00:00
TheLastProject 50d80c1a9e Update Fastlane changelogs 2021-11-03 20:38:28 +00:00
Sylvia van Os 67e2147d33 Document awesome new group editing 2021-11-03 21:37:59 +01:00
bors[bot]andKatharine cfe2aaaad8 Merge #557
557: Group management POC for #129 r=TheLastProject a=Kethen

Proof of concept for #129, please review and comment on desired changes
A few new strings are added so translations will be needed

meanwhile I think all added group has to be trimmed to avoid having identical groups like in the example

https://user-images.githubusercontent.com/22017945/139289359-32f42b48-a40e-4039-8f0b-72bbe43cd0de.mp4



https://user-images.githubusercontent.com/22017945/139294845-28c88e03-871f-49d1-9b45-f0648f2f7b50.mp4






Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
Co-authored-by: Katharine Chui <kwchuiaa@connect.ust.hk>
2021-11-03 18:40:28 +00:00
Katharine 88a91de63b removed commented code, input check for group add, input check and minor revisions 2021-11-03 10:13:59 +08:00
Katharine 2cdeb1af9c use HashMap<> constructor to clone HashMap in LoyaltyCardCursorAdapter 2021-11-03 10:13:59 +08:00
Katharine c815c3908f added a comment explaining why setText is used there 2021-11-03 10:13:59 +08:00
Katharine 9e831924c6 remove Parcel in Group, remove onResume/onPause in ManageGroupActivity and clean ups 2021-11-03 10:13:59 +08:00
Katharine cfc901855b update help text in group edit activity 2021-11-03 10:13:59 +08:00
Katharine Chui a00a69e0c0 UI changes, group cache, code cleanup
hash maps are cloned manually to make android studio and spotbug happy
2021-11-03 10:13:59 +08:00
Katharine 426acc701e remove setSort which will likely not be implemented in here 2021-11-03 10:13:59 +08:00
Katharine d6eccd11a5 UI touch ups 2021-11-03 10:13:59 +08:00
Katharine cb8275771f remove database shortcuts 2021-11-03 10:13:59 +08:00
Katharine 9252c01aa7 Group does not need to be a Parcelable anymore 2021-11-03 10:13:59 +08:00
Katharine b4b544e342 remove modularity 2021-11-03 10:13:59 +08:00
Katharine f667fcbebe requested manifest changes 2021-11-03 10:13:59 +08:00
Katharine cc402c39be fixing errors reported by spotbugs 2021-11-03 10:13:59 +08:00
Katharine d5d921a1c8 Group management POC 2021-11-03 10:13:59 +08:00
bors[bot]andAllan Nordhøy d8794811a1 Merge #565
565: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
2021-11-02 16:17:28 +00:00
Allan Nordhøy e56795307e Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.5% (221 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-11-02 16:35:12 +01:00
bors[bot]andTheLastProject 6ad99d47aa Merge #561
561: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-10-31 06:12:36 +00:00
TheLastProject 2998a4d553 Update contributors 2021-10-31 05:15:42 +00:00
bors[bot]andSC 63db8fa0f3 Merge #560
560: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: SC <lalocas@protonmail.com>
2021-10-30 16:40:26 +00:00
SC ee14d9e0c5 Translated using Weblate (Portuguese)
Currently translated at 16.8% (15 of 89 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/pt/
2021-10-30 18:38:21 +02:00
SC 1455265045 Translated using Weblate (Portuguese)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2021-10-30 18:38:17 +02:00
4f5cd87912 Merge #558
558: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Eric <spice2wolf@gmail.com>
Co-authored-by: Joel A <joeax910@student.liu.se>
Co-authored-by: mondstern <mondstern@snopyta.org>
2021-10-28 21:11:28 +00:00
mondstern d5516c59a6 Translated using Weblate (Welsh)
Currently translated at 16.2% (36 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cy/
2021-10-28 23:01:42 +02:00
mondstern 5654abe6e9 Translated using Weblate (Latvian)
Currently translated at 56.3% (125 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lv/
2021-10-28 23:01:42 +02:00
Joel A b17a50f9c2 Translated using Weblate (Swedish)
Currently translated at 99.0% (220 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-10-28 23:01:42 +02:00
Eric 87c9bb590b Translated using Weblate (Chinese (Simplified))
Currently translated at 81.5% (181 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2021-10-28 23:01:42 +02:00
dc9360eb8a Merge #556
556: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: 109247019824 <stoyan@gmx.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Co-authored-by: mondstern <mondstern@snopyta.org>
Co-authored-by: Reza Almanda <rezaalmanda27@gmail.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-10-28 20:57:28 +00:00
Sylvia van Os c8d2aa26f5 Add cy to selector 2021-10-28 22:56:59 +02:00
Sylvia van Os a5074eb191 Fix invalid translation 2021-10-28 22:37:00 +02:00
mondstern 9df0a8ff57 Added translation using Weblate (Welsh) 2021-10-28 20:01:19 +02:00
mondstern a79cf72ad7 Translated using Weblate (Latvian)
Currently translated at 21.1% (47 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lv/
2021-10-28 12:01:22 +02:00
mondstern db0134a44c Translated using Weblate (Croatian)
Currently translated at 51.8% (115 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hr/
2021-10-28 12:01:21 +02:00
Reza Almanda 5f6424778a Translated using Weblate (Indonesian)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2021-10-28 12:01:21 +02:00
mondstern 950264105b Translated using Weblate (Portuguese)
Currently translated at 51.3% (114 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2021-10-28 12:01:20 +02:00
Oğuz Ersen 7b2d9eb47f Translated using Weblate (Turkish)
Currently translated at 17.9% (16 of 89 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-28 12:01:19 +02:00
109247019824 088ee66b5a Translated using Weblate (Bulgarian)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-10-28 12:01:18 +02:00
bors[bot]andMiha Frangež 2487edf4b2 Merge #554
554: Made name and ID inputs single-line r=TheLastProject a=franga2000

Since I already had the IDE open... (also still need that last Hacktoberfest PR 😅)

Fixes #553 

Co-authored-by: Miha Frangež <miha.frangez@gmail.com>
2021-10-27 21:39:37 +00:00
Miha Frangež e16d2e22ac Made name and ID inputs single-line 2021-10-27 23:24:06 +02:00
7b335c69ba Merge #552
552: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: mondstern <mondstern@snopyta.org>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-10-27 18:33:36 +00:00
Sylvia van Os c1bd7043b1 Add Latvian to language selector 2021-10-27 20:32:58 +02:00
mondstern 71f3b5bc5f Added translation using Weblate (Latvian) 2021-10-27 20:26:24 +02:00
Sylvia van Os e2f33bf4b4 Release Catima 2.8.1 2021-10-27 18:24:46 +02:00
bors[bot]andTheLastProject b1685ac90e Merge #549
549: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-10-27 15:40:23 +00:00
TheLastProject 394cc6b30f Update Fastlane changelogs 2021-10-27 15:38:49 +00:00
Sylvia van Os 75e320e108 Update CHANGELOG 2021-10-27 17:38:19 +02:00
bors[bot]andDheeraj e8b38b3367 Merge #548
548: fix: Overlapping TextView and ImageView. r=TheLastProject a=KasinaDheeraj

fixes #542 

Co-authored-by: Dheeraj <dheerukd2002@gmail.com>
2021-10-27 15:30:33 +00:00
Dheeraj ffb24c973a fix: Overlapping TextView and ImageView. 2021-10-27 19:21:09 +05:30
bors[bot]andTheLastProject d43693b1d8 Merge #547
547: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-10-27 11:13:39 +00:00
TheLastProject b7f17181f9 Update Fastlane changelogs 2021-10-27 11:12:50 +00:00
Sylvia van Os 10dc84820c Update CHANGELOG.md 2021-10-27 13:12:30 +02:00
bors[bot]andSylvia van Os 5f0d92470e Merge #545
545: Update CHANGELOG r=TheLastProject a=TheLastProject

bors r+

Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-10-27 11:04:35 +00:00
Sylvia van Os 6bb4376e4d Update CHANGELOG 2021-10-27 12:57:24 +02:00
bors[bot]andKatharine 92da792378 Merge #539
539: fix for #533, fix for #510 + LoyaltyCardViewActivity crashing on returning from day/night theme change r=TheLastProject a=Kethen

please review, fixes #533, and avoids a crash from loading LoyaltyCardViewActivity, switch out to settings and switch day/night mode, switch back, which fixes #510 as well

Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
2021-10-27 10:55:51 +00:00
Katharine 81499cd362 onProgressChanged handles only user input now, always store user zoom level input 2021-10-27 18:49:09 +08:00
Katharine fc91f1ae63 avoid system theme change activity crash 2021-10-27 18:24:23 +08:00
Katharine cec7bc880e view dots that respects themening in app settings 2021-10-27 18:24:23 +08:00
Katharine 4027df2119 refactor centerGuideLine resizing logic -sylvia 2021-10-27 18:24:23 +08:00
bors[bot]andKatharine 93132961d3 Merge #544
544: fixing #320 by not recreating main activity returning from another activity, requires testing r=TheLastProject a=Kethen

targetting #320

Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
2021-10-27 09:34:24 +00:00
Katharine 638528d4fc do not recreate main activity returning from another activity 2021-10-27 15:22:31 +08:00
67ef623761 Merge #543
543: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: mondstern <mondstern@snopyta.org>
Co-authored-by: Rosdyana Kusuma <rosdyana.kusuma@gmail.com>
2021-10-27 06:58:40 +00:00
mondstern cb3afe1878 Translated using Weblate (Croatian)
Currently translated at 27.4% (61 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/hr/
2021-10-27 08:02:54 +02:00
mondstern e3f4aec1c5 Translated using Weblate (Luxembourgish)
Currently translated at 51.8% (115 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lb/
2021-10-27 08:02:53 +02:00
Rosdyana Kusuma d2f196da21 Translated using Weblate (Indonesian)
Currently translated at 98.6% (219 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/id/
2021-10-27 08:02:52 +02:00
mondstern e491a960d7 Translated using Weblate (Icelandic)
Currently translated at 52.2% (116 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/is/
2021-10-27 08:02:52 +02:00
mondstern f5c83793bf Translated using Weblate (Portuguese)
Currently translated at 33.3% (74 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2021-10-27 08:02:51 +02:00
Sylvia van Os 1624d56edb Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker into feature/power_screen_widgets 2021-10-26 21:42:14 +02:00
bors[bot]anddependabot[bot] e334a5e454 Merge #538
538: Bump zxing-android-embedded from 4.2.0 to 4.3.0 r=TheLastProject a=dependabot[bot]

Bumps [zxing-android-embedded](https://github.com/journeyapps/zxing-android-embedded) from 4.2.0 to 4.3.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/journeyapps/zxing-android-embedded/releases">zxing-android-embedded's releases</a>.</em></p>
<blockquote>
<h2>v4.3.0</h2>
<ul>
<li>Minimum SDK version 19, but requires additional config (see readme) for &lt; 24 compatibility.</li>
<li>Add ScanOptions and ScanContract for use with <code>registerForActivityResult()</code>.</li>
<li>Deprecates IntentIntegrator. It is still available, but <code>registerForActivityResult()</code> is recommended instead.</li>
<li>Use minimal AndroidX libraries.</li>
<li>Use zxing:core 3.4.1 by default.</li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/journeyapps/zxing-android-embedded/compare/v4.2.0...v4.3.0">https://github.com/journeyapps/zxing-android-embedded/compare/v4.2.0...v4.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/journeyapps/zxing-android-embedded/blob/master/CHANGES.md">zxing-android-embedded's changelog</a>.</em></p>
<blockquote>
<h3>4.3.0 (2021-10-25)</h3>
<ul>
<li>Minimum SDK version 19, but requires additional config (see readme) for &lt; 24 compatibility.</li>
<li>Add ScanOptions and ScanContract for use with <code>registerForActivityResult()</code>.</li>
<li>Deprecates IntentIntegrator.</li>
<li>Use minimal AndroidX libraries.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/24d02945fec5f2c5a65b24ea7848cb5ca18f9f81"><code>24d0294</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/journeyapps/zxing-android-embedded/issues/665">#665</a> from journeyapps/fixes</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/6ccf3a9d1a8919dfc06e4aeb2754354d267fe978"><code>6ccf3a9</code></a> Fix lint report location.</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/23f29e5a560fb5026928a7a2aa4099646405d0de"><code>23f29e5</code></a> Ignore lint error.</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/1a8d94932511cd82968cd18d737b574d28f4c05d"><code>1a8d949</code></a> Tweaks.</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/f1554b7478c313841ef2814fb6dc17554387633b"><code>f1554b7</code></a> Use GitHub Actions.</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/cc12c103e0f1f9f37da5aea59224a2e88e32141c"><code>cc12c10</code></a> v4.3.0 and cleanup.</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/a13ce2b161033a0cee33d9629deeb7cd3eff55bb"><code>a13ce2b</code></a> Cleanup.</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/0c97cf70cc9d562431e771fcc026c9c8bdf412ca"><code>0c97cf7</code></a> ScanOptions and ScanContract.</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/9beeac79603c6aae8f86338fabc2e5a4a757dd54"><code>9beeac7</code></a> minSdkVersion 19. Multidex and desugaring.</li>
<li><a href="https://github.com/journeyapps/zxing-android-embedded/commit/cc34502f13a04d9cd30b3508f2844fba61abfad6"><code>cc34502</code></a> Smaller libs.</li>
<li>Additional commits viewable in <a href="https://github.com/journeyapps/zxing-android-embedded/compare/v4.2.0...v4.3.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.journeyapps:zxing-android-embedded&package-manager=gradle&previous-version=4.2.0&new-version=4.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting ``@dependabot` rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- ``@dependabot` rebase` will rebase this PR
- ``@dependabot` recreate` will recreate this PR, overwriting any edits that have been made to it
- ``@dependabot` merge` will merge this PR after your CI passes on it
- ``@dependabot` squash and merge` will squash and merge this PR after your CI passes on it
- ``@dependabot` cancel merge` will cancel a previously requested merge and block automerging
- ``@dependabot` reopen` will reopen this PR if it is closed
- ``@dependabot` close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- ``@dependabot` ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- ``@dependabot` ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-26 19:19:40 +00:00
cbbd071f4f Merge #541
541: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: mondstern <mondstern@snopyta.org>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-10-26 18:39:49 +00:00
Sylvia van Os 524a6b1ffb Add hr to language selector 2021-10-26 20:38:38 +02:00
mondstern 7954adf7e3 Added translation using Weblate (Croatian) 2021-10-26 20:11:22 +02:00
Sylvia van Os 0b31a08b9f Really fix 2021-10-26 19:23:39 +02:00
Sylvia van Os a0884aa81c Fix empty changelog check 2021-10-26 19:20:11 +02:00
Sylvia van Os 46f64d1a61 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-26 19:12:26 +02:00
Sylvia van Os 81cb6ad4fd Don't generate fastlane file if changelog entry is empty 2021-10-26 19:12:05 +02:00
dependabot[bot] f2f330e3e4 Bump zxing-android-embedded from 4.2.0 to 4.3.0
Bumps [zxing-android-embedded](https://github.com/journeyapps/zxing-android-embedded) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/journeyapps/zxing-android-embedded/releases)
- [Changelog](https://github.com/journeyapps/zxing-android-embedded/blob/master/CHANGES.md)
- [Commits](https://github.com/journeyapps/zxing-android-embedded/compare/v4.2.0...v4.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-26 02:16:29 +00:00
Sylvia van Os 5b14670785 Fix changelog 2021-10-26 00:06:52 +02:00
bors[bot]andmondstern c5f68aa50f Merge #535
535: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: mondstern <mondstern@snopyta.org>
2021-10-25 18:12:29 +00:00
mondstern 5203f89e9d Added translation using Weblate (Luxembourgish) 2021-10-25 20:09:59 +02:00
Sylvia van Os 8f11d73649 Merge pull request #534 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-25 20:00:17 +02:00
mondstern 3d376e2a90 Translated using Weblate (Icelandic)
Currently translated at 31.9% (71 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/is/
2021-10-25 19:53:19 +02:00
Sylvia van Os 0e814c3359 Merge pull request #531 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-25 17:56:26 +02:00
Oğuz Ersen 4755cc3f7f Translated using Weblate (Turkish)
Currently translated at 17.0% (15 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-25 17:55:10 +02:00
Sylvia van Os 7afbe41f95 Release Catima 2.8.0 2021-10-25 17:28:02 +02:00
Sylvia van Os 6d4cbee499 Merge pull request #529 from TheLastProject/create-pull-request/patch-1635175160
Update Fastlane changelogs
2021-10-25 17:20:22 +02:00
TheLastProject f16a597b91 Update Fastlane changelogs 2021-10-25 15:19:19 +00:00
Sylvia van Os 3ba0649891 Add missing languages 2021-10-25 17:18:51 +02:00
Sylvia van Os 297ecc371e Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-25 17:14:57 +02:00
Sylvia van Os 79c8570507 Work around a race condition crash 2021-10-25 17:11:19 +02:00
Ronak Upadhyay 8f81d2d141 Fixes #516 Image scale according to text size (#517) 2021-10-24 22:26:41 +02:00
bors[bot]andNyatsuki 325535af12 Merge #528
528: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Nyatsuki <Odamaki@yandex.ru>
2021-10-24 08:34:37 +00:00
Nyatsuki f7af4169a3 Translated using Weblate (Japanese)
Currently translated at 98.6% (219 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2021-10-24 10:33:11 +02:00
bors[bot]andRosdyana Kusuma e5ec45f877 Merge #527
527: i18n: Add in-rID r=TheLastProject a=rosdyana

This PR adds localization strings for Bahasa Indonesia (in-rID) and adds the option to the locale menu.

Co-authored-by: Rosdyana Kusuma <rosdyana.kusuma@gmail.com>
2021-10-24 08:27:19 +00:00
bors[bot]andTheLastProject 902a4e411b Merge #526
526: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-10-24 08:18:33 +00:00
Rosdyana Kusuma 03ec2b4492 Add localization for Bahasa Indonesia 2021-10-24 14:14:57 +08:00
TheLastProject 6a2f8a630a Update contributors 2021-10-24 05:15:59 +00:00
78e998fad9 Merge #525
525: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Co-authored-by: mondstern <mondstern@snopyta.org>
2021-10-23 22:06:40 +00:00
mondstern e6ccef8ad0 Translated using Weblate (Icelandic)
Currently translated at 25.6% (57 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/is/
2021-10-24 00:04:22 +02:00
Oğuz Ersen acbd614b50 Translated using Weblate (Turkish)
Currently translated at 17.0% (15 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-24 00:04:22 +02:00
bors[bot]andStill Hsu 445e661fac Merge #523
523: i18n: Add zh-tw r=TheLastProject a=Still34

# Summary

This PR adds localization strings for Chinese (Taiwan) (`zh-TW`) and adds the option to the locale menu.

Co-authored-by: Still Hsu <dev@stillu.cc>
2021-10-23 21:59:30 +00:00
Still Hsu d774231c05 Add zh-tw strings 2021-10-24 05:54:36 +08:00
bors[bot]andmondstern b5d2a5dbab Merge #522
522: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: mondstern <mondstern@snopyta.org>
2021-10-23 19:34:13 +00:00
mondstern 6ab61eb78a Added translation using Weblate (Icelandic) 2021-10-23 21:31:36 +02:00
bors[bot]andTheLastProject bbd8bb7d29 Merge #521
521: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-10-22 21:35:28 +00:00
TheLastProject 3e082b598f Update Fastlane changelogs 2021-10-22 21:34:15 +00:00
Sylvia van Os 70510ed9d1 Fix unit tests 2021-10-22 23:33:50 +02:00
Sylvia van Os 5da1c67dd6 Update CHANGELOG 2021-10-22 22:17:39 +02:00
Sylvia van Os dfa237958e Fix several small sizing bugs 2021-10-22 22:17:13 +02:00
Ankit Tiwari 127d53e85a Save Size of code (#508) 2021-10-22 21:11:51 +02:00
bors[bot]andmondstern 7cce782143 Merge #518
518: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: mondstern <mondstern@snopyta.org>
2021-10-21 20:51:42 +00:00
mondstern 662eb853d7 Translated using Weblate (Portuguese)
Currently translated at 23.8% (53 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pt/
2021-10-21 22:37:14 +02:00
mondstern d8e58f8b38 Translated using Weblate (Esperanto)
Currently translated at 52.2% (116 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/eo/
2021-10-21 22:37:14 +02:00
mondstern 4748e24dda Translated using Weblate (Romanian)
Currently translated at 59.0% (131 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ro/
2021-10-21 22:37:13 +02:00
bors[bot]andmondstern 5af024f482 Merge #515
515: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: mondstern <mondstern@snopyta.org>
2021-10-20 19:45:55 +00:00
mondstern 8adc013330 Added translation using Weblate (Portuguese) 2021-10-20 21:44:55 +02:00
4edfe962ef Merge #514
514: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Petr Novák <nit.monkey@gmail.com>
Co-authored-by: IllusiveMan196 <hamsterrv@gmail.com>
Co-authored-by: mondstern <mondstern@snopyta.org>
2021-10-20 18:15:27 +00:00
mondstern d80a71c852 Translated using Weblate (Danish)
Currently translated at 52.7% (117 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/da/
2021-10-20 20:07:38 +02:00
Petr Novák 299c9f2b4d Translated using Weblate (Czech)
Currently translated at 98.8% (87 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-10-20 20:07:37 +02:00
IllusiveMan196 03e3e45f07 Translated using Weblate (Ukrainian)
Currently translated at 3.4% (3 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2021-10-20 20:07:34 +02:00
IllusiveMan196 c35c316788 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-10-20 20:07:33 +02:00
Petr Novák d68f0c60d4 Translated using Weblate (Czech)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-10-20 20:07:33 +02:00
waffshappen 5faa28a7e7 Replace AsyncTask with a Compatiblity Layer and further Compat Fixes (#511) 2021-10-20 19:47:06 +02:00
2fffb89179 Merge #509
509: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Gediminas Murauskas <muziejusinfo@gmail.com>
Co-authored-by: 109247019824 <stoyan@gmx.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-10-19 16:02:41 +00:00
Oğuz Ersen bd27ccd535 Translated using Weblate (Turkish)
Currently translated at 17.0% (15 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-19 15:39:49 +02:00
109247019824 3149234f5d Translated using Weblate (Bulgarian)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-10-19 15:39:48 +02:00
Gediminas Murauskas dcf55c93a8 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-10-19 15:39:48 +02:00
bors[bot]andaditya3901 3f3394c1e9 Merge #507
507: feat/copyable-textview r=TheLastProject a=aditya3901

## Issue Fix
Fixes #389 
Made textviews copyable :)

Co-authored-by: aditya3901 <2020itb058.aditya@students.iiests.ac.in>
2021-10-18 16:06:10 +00:00
aditya3901 2b22dd4a1f feat/copyable-textview 2021-10-18 14:29:30 +05:30
Sylvia van Os 7f1b1484ac Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker into feature/power_screen_widgets 2021-10-17 20:02:42 +02:00
bors[bot]andTheLastProject a70710ca6a Merge #504
504: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-10-17 17:09:24 +00:00
TheLastProject cd3baf5bd9 Update Fastlane changelogs 2021-10-17 17:08:28 +00:00
Sylvia van Os 1138d6387e Update CHANGELOG 2021-10-17 19:08:08 +02:00
b664fd391a Merge #503
503: Translations update from Weblate r=TheLastProject a=weblate

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



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: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
Co-authored-by: solokot <solokot@gmail.com>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
2021-10-17 15:51:25 +00:00
Oğuz Ersen 11cc65bae3 Translated using Weblate (Turkish)
Currently translated at 17.0% (15 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-17 17:41:02 +02:00
Oğuz Ersen eaafa56503 Translated using Weblate (Turkish)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-10-17 17:41:02 +02:00
solokot 09c6d58639 Translated using Weblate (Russian)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-10-17 17:41:02 +02:00
Heimen Stoffels 1767a009a7 Translated using Weblate (Dutch)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-10-17 17:41:02 +02:00
Allan Nordhøy a2e25512ec Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.5% (221 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-10-17 17:41:02 +02:00
J. Lavoie 824b931764 Translated using Weblate (Italian)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-10-17 17:41:02 +02:00
J. Lavoie 0cb75fd421 Translated using Weblate (French)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-10-17 17:41:02 +02:00
J. Lavoie 36f0d814f6 Translated using Weblate (German)
Currently translated at 100.0% (222 of 222 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-10-17 17:41:02 +02:00
bors[bot]andMiha Frangež 2aa0c46d30 Merge #502
502: Slovenian translations r=TheLastProject a=franga2000

Added some new strings and fixed a few obvious mistakes that I'm guessing came from machine translation

Co-authored-by: Miha Frangež <miha.frangez@gmail.com>
2021-10-17 15:35:00 +00:00
Miha Frangež ff63dbfdaa Fixed bad machine translations 2021-10-17 17:16:44 +02:00
Miha Frangež 5cacdbd192 New Slovenian translations 2021-10-17 17:07:32 +02:00
Ankit Tiwari c99bf206cc Dynamically size barcode based on their shape (square or rectangle) (#501) 2021-10-17 14:42:56 +02:00
bors[bot]andTheLastProject f546bb2681 Merge #500
500: Update contributors r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-10-17 08:56:26 +00:00
TheLastProject bef750e047 Update contributors 2021-10-17 05:10:28 +00:00
bors[bot]andTheLastProject 6998599377 Merge #499
499: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-10-16 15:23:34 +00:00
TheLastProject 11164f9a73 Update Fastlane changelogs 2021-10-16 15:21:38 +00:00
Sylvia van Os b867795a08 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-16 17:21:18 +02:00
Sylvia van Os 9998205051 Update CHANGELOG 2021-10-16 17:21:05 +02:00
7692f19ea6 Merge #494
494: Inter Related Code changes for exporting encrypted zip r=TheLastProject a=ankittiwari101

1. Created new method `multipleCardsExportImportPasswordProtected()` in ImportExportTest.java
2. Added 5th Parameter `char[] password` to exportData method of MultiFormater.java
3. From this new method passed password field to `importData` and `exportData` method calls.
4. In CatimaExporter.java added a password parameter to ZipOutputStream(output,password) if a non null char[] array of non zero length is received for password parameter and setEncryptFiles(true) using AES 256 Encryption(by default)"

Remaining - Dialogue Box for entering password.

Note - This is only a draft pull request, if everything here looks good, I'll work next on The Password Dialog which is the final piece in the puzzle.

Co-authored-by: Ankit Tiwari <ankitr.tiwari@gmail.com>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-10-16 15:13:11 +00:00
Sylvia van Os d8361cc288 String improvements 2021-10-16 16:49:47 +02:00
93d0724c60 Merge #498
498: Translations update from Weblate r=TheLastProject a=weblate

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



Current translation status:

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


Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-10-16 14:43:46 +00:00
Sylvia van Os 2c03f193f0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 19.3% (17 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nb_NO/
2021-10-16 16:40:17 +02:00
Ankit Tiwari 7028a1f4ca Changes to AlertDialog for entering password 2021-10-16 20:04:24 +05:30
Ankit Tiwari 32d62dd9ba Requested Modifications Made. 2021-10-16 01:34:44 +05:30
Ankit Tiwari 401fc98b4d Passing password to ZipInputStream constructor in importData method of CatimaImporter.java 2021-10-16 00:15:32 +05:30
Ankit Tiwari 993589427b Changed password parameter to a char[] instead of null in ImportExportTest.java line 613 2021-10-15 23:10:38 +05:30
Ankit Tiwari 2390568bdf Added Encrypted Backup feature.The Zip File is Password Protected, which is asked from the user at the time of export immediately on click of Export Button. 2021-10-15 22:51:52 +05:30
Allan Nordhøy 50ccf6da46 Translated using Weblate (Norwegian Bokmål)
Currently translated at 19.3% (17 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nb_NO/
2021-10-15 15:45:28 +02:00
Ankit Tiwari 44066e6599 Extracted zip parameter logic into a new function and used it on imageZipParameters as well 2021-10-15 00:22:51 +05:30
Ankit Tiwari fc9c616869 1.Created new method multipleCardsExportImportPasswordProtected() in ImportExportTest.java \n 2.Added 5th Paramete 2021-10-14 23:23:01 +05:30
bors[bot]andSylvia van Os f09f35e44b Merge #493
493: Delete merged branch r=TheLastProject a=TheLastProject



Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-10-14 17:45:05 +00:00
Sylvia van Os f81fb0c673 Delete merged branch 2021-10-14 19:44:36 +02:00
bors[bot]andSylvia van Os b0b4e80da4 Merge #492
492: Setup bors r=TheLastProject a=TheLastProject



Co-authored-by: Sylvia van Os <sylvia@hackerchick.me>
2021-10-14 17:37:40 +00:00
Sylvia van Os 923982e449 Don't override author info 2021-10-14 19:37:03 +02:00
Sylvia van Os d05c97946d Setup bors 2021-10-14 19:07:24 +02:00
Sylvia van Os 504a1fd01b Prepare for Bors 2021-10-14 18:37:46 +02:00
Sylvia van Os 5efacec417 Merge pull request #491 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-13 20:03:00 +02:00
Oğuz Ersen 595d10fc44 Translated using Weblate (Turkish)
Currently translated at 17.0% (15 of 88 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-13 19:55:32 +02:00
Sylvia van Os 2128f0a601 Merge pull request #490 from TheLastProject/create-pull-request/patch-1634144237
Update Fastlane changelogs
2021-10-13 19:07:15 +02:00
TheLastProject 0b0a45da05 Update Fastlane changelogs 2021-10-13 16:57:17 +00:00
Sylvia van Os 94fb4b4411 Update CHANGELOG 2021-10-13 18:56:54 +02:00
Sylvia van Os fc7932d3bf Merge pull request #489 from ankittiwari101/fix-sliding-bug
Fixed Sliding Bug in MainActivity.java
2021-10-13 18:54:59 +02:00
Ankit Tiwari 97a5311593 Fixed Bug where an Empty List (consisting of only a single textview) within the Tab would not swipe left or right 2021-10-13 16:55:05 +05:30
Sylvia van Os c7db676b2b Add IzzyOnDroid badge 2021-10-12 17:31:51 +02:00
Sylvia van Os f8c8b3b2e6 Merge pull request #487 from TheLastProject/dependabot/gradle/com.android.tools.build-gradle-7.0.3
Bump gradle from 7.0.2 to 7.0.3
2021-10-12 17:23:04 +02:00
dependabot[bot] df4cb5b189 Bump gradle from 7.0.2 to 7.0.3
Bumps gradle from 7.0.2 to 7.0.3.

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-12 02:21:39 +00:00
Sylvia van Os d2b2a53109 Merge pull request #485 from TacoTheDank/materialCardview
Use MaterialCardView
2021-10-11 21:27:30 +02:00
Sylvia van Os 5107f88998 Merge pull request #483 from TheLastProject/dependabot/gradle/gradle.plugin.com.github.spotbugs.snom-spotbugs-gradle-plugin-4.7.5
Bump spotbugs-gradle-plugin from 4.7.0 to 4.7.5
2021-10-11 21:25:48 +02:00
dependabot[bot] 78f2e1698f Bump spotbugs-gradle-plugin from 4.7.0 to 4.7.5
Bumps spotbugs-gradle-plugin from 4.7.0 to 4.7.5.

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-11 19:20:03 +00:00
Sylvia van Os 6887cd098b Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-11 21:19:15 +02:00
Sylvia van Os 0881d745f5 Fix more spotbugs EI_EXPOSE_REP2 2021-10-11 21:18:22 +02:00
Sylvia van Os 94b3a07f90 Merge pull request #484 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-11 20:42:40 +02:00
Joel A dc280b4023 Translated using Weblate (Swedish)
Currently translated at 2.2% (2 of 87 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sv/
2021-10-11 20:22:20 +02:00
Joel A edce6d6cd3 Translated using Weblate (Swedish)
Currently translated at 99.0% (218 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-10-11 20:22:20 +02:00
solokot 23dc47a5b9 Translated using Weblate (Russian)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-10-11 20:22:20 +02:00
Sylvia van Os 683b4f46d9 Fix spotbugs EI_EXPOSE_REP2 2021-10-11 20:22:06 +02:00
Sylvia van Os ac021bce2a Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-11 19:58:26 +02:00
Sylvia van Os b0c34cbca0 Fix spotbugs RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE 2021-10-11 19:58:09 +02:00
TacoTheDank 4a0c8270ef Replace CardView with MaterialCardView 2021-10-10 22:34:53 -04:00
TacoTheDank 793f1e2f87 Remove unneeded MultiDex 2021-10-10 22:34:40 -04:00
avikkundu 0101b6fa25 added translation in bengali (#480) 2021-10-10 17:04:49 +02:00
Sylvia van Os 47dff850fb Merge pull request #479 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-10 12:33:11 +02:00
Oğuz Ersen fe7503c3ac Translated using Weblate (Turkish)
Currently translated at 16.0% (14 of 87 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-10 12:31:11 +02:00
Petr Novák 5df7d8a530 Translated using Weblate (Czech)
Currently translated at 98.8% (86 of 87 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-10-10 12:31:10 +02:00
Sylvia van Os ee129a3373 Merge pull request #478 from TheLastProject/create-pull-request/patch-1633842920
Update contributors
2021-10-10 08:17:10 +02:00
TheLastProject b979b1fc86 Update contributors 2021-10-10 05:15:20 +00:00
Sylvia van Os 361ebb8b80 Merge pull request #476 from TheLastProject/create-pull-request/patch-1633819619
Update Fastlane changelogs
2021-10-10 00:49:36 +02:00
TheLastProject fd49466e0d Update Fastlane changelogs 2021-10-09 22:46:59 +00:00
Sylvia van Os bf8f00f877 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-10 00:46:33 +02:00
Sylvia van Os 9f0b7604cb Fix botched migration and release 2.7.3 2021-10-10 00:46:20 +02:00
Sylvia van Os 6d151e7377 Merge pull request #474 from TheLastProject/create-pull-request/patch-1633816331
Update Fastlane changelogs
2021-10-10 00:02:54 +02:00
TheLastProject 6ecc94526e Update Fastlane changelogs 2021-10-09 21:52:10 +00:00
Sylvia van Os 1462911ffa Fix regression and release 2.7.2 2021-10-09 23:50:57 +02:00
Sylvia van Os 952f7a933b Merge pull request #471 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-09 21:12:21 +02:00
109247019824 b76c4ef352 Translated using Weblate (Bulgarian)
Currently translated at 4.7% (4 of 85 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/bg/
2021-10-09 21:04:49 +02:00
Sylvia van Os 48048cdb82 Merge pull request #468 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-08 18:56:48 +02:00
Michael Gangolf a555f1c41b Translated using Weblate (German)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-10-08 17:30:09 +02:00
Sylvia van Os 2ab7ebb2c0 Merge pull request #466 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-08 09:22:00 +02:00
Oğuz Ersen e2b0113687 Translated using Weblate (Turkish)
Currently translated at 14.1% (12 of 85 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-08 07:04:26 +02:00
Heimen Stoffels dc7e9b541a Translated using Weblate (Dutch)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-10-08 07:04:26 +02:00
Allan Nordhøy b44ef7dfc0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.5% (219 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-10-08 07:04:25 +02:00
Gediminas Murauskas 4d1f4a64fa Translated using Weblate (Lithuanian)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-10-08 07:04:24 +02:00
Sylvia van Os fd7e6e4993 Release Catima 2.7.1 2021-10-07 20:04:19 +02:00
Sylvia van Os b749c79a81 Merge pull request #464 from TheLastProject/create-pull-request/patch-1633550408
Update Fastlane changelogs
2021-10-06 22:01:05 +02:00
TheLastProject 5d019a8e5b Update Fastlane changelogs 2021-10-06 20:00:07 +00:00
Sylvia van Os 4e203aebfe Improve search with spaces 2021-10-06 21:59:45 +02:00
Sylvia van Os fb2bede135 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-06 19:58:44 +02:00
Sylvia van Os 5a88909cd2 Make spotbugs happy 2021-10-06 19:58:29 +02:00
/usr/local/ΕΨΗΕΛΩΝ ab1e6eed0c Cards on power screen 2021-10-06 15:07:06 +02:00
/usr/local/ΕΨΗΕΛΩΝ ba5cf81bb4 Upgrade Java version to 11
Required to use java.util.concurrent.Flow
Could opt for Java 9, but 11 is LTS
2021-10-06 14:40:02 +02:00
Sylvia van Os 017034a788 Google. Again. 2021-10-06 12:03:09 +02:00
Sylvia van Os 66ff6f8199 Merge branch 'master' of github.com:TheLastProject/Catima 2021-10-06 11:17:38 +02:00
Sylvia van Os ddccbad020 Fuck you, Google. Fuck you. 2021-10-06 11:17:28 +02:00
Sylvia van Os 578fb068ee Merge pull request #463 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-06 09:28:31 +02:00
Petr Novák d624eb3842 Translated using Weblate (Czech)
Currently translated at 98.8% (83 of 84 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-10-06 09:23:05 +02:00
Oğuz Ersen f46fedda4b Translated using Weblate (Turkish)
Currently translated at 13.0% (11 of 84 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-06 09:23:05 +02:00
109247019824 6e5ac2ca3d Translated using Weblate (Bulgarian)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-10-06 09:23:05 +02:00
IllusiveMan196 20de874ea1 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-10-06 09:23:05 +02:00
Petr Novák c8a207083b Translated using Weblate (Czech)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-10-06 09:23:05 +02:00
Sylvia van Os ab7505c67a Work around Google's incompetence 2021-10-06 09:22:57 +02:00
Sylvia van Os b26050b6bf Fix version name 2021-10-05 20:39:20 +02:00
Sylvia van Os 84e9c8efd4 Merge remote-tracking branch 'weblate/master' 2021-10-05 20:35:52 +02:00
Sylvia van Os 2811a14627 Release Catima 2.7.0 2021-10-05 20:28:36 +02:00
Sylvia van Os 3b6d4d44b0 Release Catima 2.7 2021-10-05 20:27:54 +02:00
Sylvia van Os 71bc304c51 Fix version upgrade 2021-10-05 20:27:11 +02:00
Sylvia van Os 7b0652ff11 Fix no results sometimes not correctly displayed 2021-10-05 20:15:10 +02:00
Sylvia van Os 61a3054655 Cleanup 2021-10-05 20:04:03 +02:00
Sylvia van Os 54c1cc3661 Merge pull request #457 from TheLastProject/create-pull-request/patch-1633455787
Update Fastlane changelogs
2021-10-05 19:45:20 +02:00
TheLastProject ee0f9e04de Update Fastlane changelogs 2021-10-05 17:43:07 +00:00
Sylvia van Os ebe5289d6e Implement FTS (#455)
This allows for unicode insensitive search and fast search over both
store and note data
2021-10-05 19:42:52 +02:00
Sylvia van Os 15ba15c602 Cleanup 2021-10-04 21:03:50 +02:00
Sylvia van Os fd0448efc4 Merge pull request #454 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-04 19:28:39 +02:00
Oğuz Ersen 43fa2623d4 Translated using Weblate (Turkish)
Currently translated at 13.0% (11 of 84 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-10-04 19:08:55 +02:00
Oğuz Ersen c1b9babf33 Translated using Weblate (Turkish)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-10-04 19:08:55 +02:00
Petr Novák 4c8edf9d9a Translated using Weblate (Czech)
Currently translated at 75.0% (63 of 84 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-10-04 19:08:55 +02:00
solokot ff4271f51d Translated using Weblate (Russian)
Currently translated at 3.5% (3 of 84 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/ru/
2021-10-04 19:08:55 +02:00
IllusiveMan196 2424ab01cf Translated using Weblate (Ukrainian)
Currently translated at 95.9% (211 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-10-04 19:08:55 +02:00
solokot b38dfeeed7 Translated using Weblate (Russian)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-10-04 19:08:55 +02:00
Thomas Bertels 7912cd190f Translated using Weblate (French)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-10-04 19:08:55 +02:00
Petr Novák 11962ad930 Translated using Weblate (Czech)
Currently translated at 97.7% (215 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-10-04 19:08:55 +02:00
Thomas Bertels a8e2c65072 Translated using Weblate (English)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2021-10-04 19:08:55 +02:00
Sylvia van Os 1b8ca5f467 Merge pull request #453 from LunarWatcher/master
Additional Norwegian translations
2021-10-04 19:08:46 +02:00
Olivia 46fff6da5b More changelogs 2021-10-04 18:40:45 +02:00
Olivia 47e75f64ed Import/Eksport is not an action in that form 2021-10-04 18:32:35 +02:00
Olivia fb95c8c9d4 never seen that word used before, and we use copyleft
https://no.wikipedia.org/wiki/Copyleft
2021-10-04 18:27:21 +02:00
Olivia 66cc97214c Add translations 2021-10-04 18:21:36 +02:00
Biren f52423ed70 Removed click listener from card icon (#452)
* Removed the unnecessary click listener in the card icon from LoyaltyCardCursorAdapter.java

* Removed declaration and assignment of mThumbnailContainer from LoyaltyCardCursorAdapter.java
2021-10-04 17:38:34 +02:00
Sylvia van Os 29bea052eb Merge pull request #451 from TheLastProject/create-pull-request/patch-1633349604
Update Fastlane changelogs
2021-10-04 14:15:35 +02:00
TheLastProject b683f1fce4 Update Fastlane changelogs 2021-10-04 12:13:24 +00:00
Sylvia van Os 2ec55473a5 Add support expiration notice for Android 4.4 2021-10-04 14:13:09 +02:00
Sylvia van Os 2fe89ffcbc Merge pull request #448 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-04 07:38:09 +02:00
Allan Nordhøy 7e88a10884 Translated using Weblate (Russian)
Currently translated at 99.5% (219 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-10-04 07:32:30 +02:00
solokot f260051160 Translated using Weblate (Russian)
Currently translated at 99.5% (219 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-10-04 07:24:49 +02:00
Allan Nordhøy b8dacc2459 Translated using Weblate (English)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/en/
2021-10-04 07:24:49 +02:00
Sylvia van Os b311dd99dc Merge branch 'master' of https://hosted.weblate.org/git/catima/catima 2021-10-03 23:00:27 +02:00
Petr Novák 1d7a9843d8 Translated using Weblate (Czech)
Currently translated at 99.0% (218 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-10-03 22:57:01 +02:00
Sylvia van Os 03e59ad00f Make lint happy 2021-10-03 22:56:53 +02:00
Sylvia van Os c083af1c76 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-03 22:53:43 +02:00
Sylvia van Os 6abb0a2a75 Fix tests 2021-10-03 22:53:31 +02:00
Sylvia van Os e672e7f1a6 Merge pull request #446 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-03 22:50:56 +02:00
Heimen Stoffels 852a638ea1 Translated using Weblate (Dutch)
Currently translated at 100.0% (220 of 220 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-10-03 22:50:04 +02:00
Petr Novák ec1b642614 Translated using Weblate (Czech)
Currently translated at 22.8% (19 of 83 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-10-03 22:50:04 +02:00
solokot 145dac72af Translated using Weblate (Russian)
Currently translated at 95.9% (212 of 221 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-10-03 22:50:04 +02:00
Heimen Stoffels 7d2679b2a3 Translated using Weblate (Dutch)
Currently translated at 100.0% (221 of 221 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-10-03 22:50:04 +02:00
Petr Novák ffbcd2183b Translated using Weblate (Czech)
Currently translated at 95.4% (211 of 221 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-10-03 22:50:04 +02:00
Sylvia van Os b9d646868c Merge pull request #447 from TheLastProject/create-pull-request/patch-1633294115
Update Fastlane changelogs
2021-10-03 22:50:01 +02:00
TheLastProject 2ce530a644 Update Fastlane changelogs 2021-10-03 20:48:34 +00:00
Sylvia van Os 1c8e9ba1cf Fix CHANGELOG header 2021-10-03 22:48:15 +02:00
Sylvia van Os 9a2560dbc2 Fix translatable 2021-10-03 22:46:36 +02:00
Sylvia van Os f900c4299d Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-03 22:44:05 +02:00
Sylvia van Os f78494f882 Cleanups 2021-10-03 22:43:51 +02:00
Sylvia van Os b55f10b59d Merge pull request #445 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-03 22:26:03 +02:00
Petr Novák 277ee90421 Translated using Weblate (Czech)
Currently translated at 20.4% (17 of 83 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-10-03 22:17:50 +02:00
Aditya Das fcdde83038 feature/About-Page (#440) 2021-10-03 22:17:45 +02:00
Sylvia van Os 12fb29ecce Merge pull request #442 from TheLastProject/create-pull-request/patch-1633234512
Update contributors
2021-10-03 10:29:56 +02:00
TheLastProject ae7dd63d6b Update contributors 2021-10-03 04:15:12 +00:00
Sylvia van Os 48f680f7bd Merge pull request #436 from TheLastProject/dependabot/gradle/com.journeyapps-zxing-android-embedded-4.2.0
Bump zxing-android-embedded from 4.1.0 to 4.2.0
2021-10-02 15:22:25 +02:00
dependabot[bot] e3d4e393b3 Bump zxing-android-embedded from 4.1.0 to 4.2.0
Bumps [zxing-android-embedded](https://github.com/journeyapps/zxing-android-embedded) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/journeyapps/zxing-android-embedded/releases)
- [Changelog](https://github.com/journeyapps/zxing-android-embedded/blob/master/CHANGES.md)
- [Commits](https://github.com/journeyapps/zxing-android-embedded/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-02 12:00:39 +00:00
Sylvia van Os 81f13c255a Merge pull request #435 from TheLastProject/dependabot/gradle/org.apache.commons-commons-csv-1.9.0
Bump commons-csv from 1.8 to 1.9.0
2021-10-02 13:59:50 +02:00
dependabot[bot] 97ce322d0c Bump commons-csv from 1.8 to 1.9.0
Bumps commons-csv from 1.8 to 1.9.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-csv
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-02 11:56:02 +00:00
Sylvia van Os a3e876d9a2 Merge pull request #434 from TheLastProject/dependabot/gradle/net.lingala.zip4j-zip4j-2.9.0
Bump zip4j from 2.8.0 to 2.9.0
2021-10-02 13:55:22 +02:00
Rohan Babbar 234356f8f2 Modified to Android 12 Splash Screen (#430) 2021-10-02 13:44:41 +02:00
Sylvia van Os d3222f7bdc Merge pull request #438 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-02 12:14:48 +02:00
Nyatsuki a5658e72c7 Translated using Weblate (Japanese)
Currently translated at 98.5% (206 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2021-10-02 08:34:54 +02:00
dependabot[bot] d1e1fcfabe Bump zip4j from 2.8.0 to 2.9.0
Bumps [zip4j](https://github.com/srikanth-lingala/zip4j) from 2.8.0 to 2.9.0.
- [Release notes](https://github.com/srikanth-lingala/zip4j/releases)
- [Commits](https://github.com/srikanth-lingala/zip4j/compare/v2.8.0...v2.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-01 22:24:58 +00:00
Sylvia van Os 9d6bd0770c Configure dependabot 2021-10-02 00:24:33 +02:00
Sylvia van Os 6f76ee389b Merge pull request #431 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-01 10:04:50 +02:00
mondstern 87aa74f231 Translated using Weblate (Danish)
Currently translated at 52.6% (110 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/da/
2021-09-30 23:35:10 +02:00
IllusiveMan196 a0dc80c1a5 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-09-30 23:35:09 +02:00
mondstern d8dbe25a64 Translated using Weblate (Romanian)
Currently translated at 26.3% (55 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ro/
2021-09-30 23:35:08 +02:00
Sylvia van Os e3bec085df Merge pull request #426 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-27 23:01:02 +02:00
mondstern 4d4b92b33f Translated using Weblate (Bosnian)
Currently translated at 21.6% (18 of 83 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/bs/
2021-09-27 22:39:12 +02:00
mondstern cc58c769cc Translated using Weblate (Bosnian)
Currently translated at 56.4% (118 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bs/
2021-09-27 22:39:11 +02:00
IllusiveMan196 37f08f6fc4 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-09-27 22:39:10 +02:00
Sylvia van Os 73e02e7c06 Merge pull request #425 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-26 19:43:32 +02:00
mondstern 7a1b6fccc2 Translated using Weblate (Bosnian)
Currently translated at 20.0% (42 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bs/
2021-09-26 19:38:46 +02:00
Allan Nordhøy 2473e3f91a Translated using Weblate (Norwegian Bokmål)
Currently translated at 4.8% (4 of 83 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nb_NO/
2021-09-26 19:38:45 +02:00
Allan Nordhøy 0a6bb2805c Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.0% (207 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-09-26 19:38:45 +02:00
Sylvia van Os 1eecc6f065 Merge pull request #424 from TheLastProject/create-pull-request/patch-1632629697
Update contributors
2021-09-26 11:35:13 +02:00
TheLastProject b8b4fe4958 Update contributors 2021-09-26 04:14:56 +00:00
Sylvia van Os 6dd8b6798b Merge pull request #423 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-25 23:50:30 +02:00
mondstern 69d0a3f4aa Added translation using Weblate (Bosnian) 2021-09-25 23:45:29 +02:00
Sylvia van Os ce81934890 Merge pull request #422 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-25 22:58:07 +02:00
Oğuz Ersen ba06f47e3e Translated using Weblate (Turkish)
Currently translated at 12.0% (10 of 83 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-09-25 16:38:09 +02:00
Sylvia van Os cfc37d4af6 Merge pull request #419 from TheLastProject/create-pull-request/patch-1632573184
Update Fastlane changelogs
2021-09-25 14:33:36 +02:00
TheLastProject 43cd6edda2 Update Fastlane changelogs 2021-09-25 12:33:04 +00:00
Sylvia van Os 0bd262d82f Release Catima 2.6.1 2021-09-25 14:32:43 +02:00
Sylvia van Os f09bafa104 Update contributors on schedule instead 2021-09-25 13:17:28 +02:00
Sylvia van Os 20e34ee365 Merge pull request #417 from TheLastProject/create-pull-request/patch-1632560906
Update contributors
2021-09-25 11:09:38 +02:00
TheLastProject 7a6bd8f661 Update contributors 2021-09-25 09:08:25 +00:00
Sylvia van Os 54c3765e36 Merge pull request #415 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-25 11:07:58 +02:00
J. Lavoie 4d7f563b0d Translated using Weblate (German)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-09-25 11:06:49 +02:00
QuangDNguyen2211 4e0ecaa7be Changing Reverse button in sorting into a checkbox (#406) 2021-09-25 11:06:44 +02:00
Sylvia van Os 4f41d238eb Merge pull request #414 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-24 21:15:04 +02:00
mondstern 7c3d021427 Translated using Weblate (Romanian)
Currently translated at 18.6% (39 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ro/
2021-09-24 20:35:55 +02:00
Sylvia van Os bfde036484 Merge pull request #413 from TheLastProject/create-pull-request/patch-1632296753
Update contributors
2021-09-22 09:46:53 +02:00
TheLastProject 84ef4ad030 Update contributors 2021-09-22 07:45:52 +00:00
Sylvia van Os 3b85fccd60 Merge pull request #412 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-22 09:45:24 +02:00
Petr Novák 830d0f6e6a Translated using Weblate (Czech)
Currently translated at 6.0% (5 of 82 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-09-22 09:35:00 +02:00
Petr Novák 1ceede27a3 Translated using Weblate (Czech)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-09-22 09:34:59 +02:00
Sylvia van Os fa33cdaca4 Enable autoVerify for Android 12 on catima.app 2021-09-21 21:13:04 +02:00
Sylvia van Os f39fbb55a1 Merge pull request #411 from TheLastProject/create-pull-request/patch-1632248508
Update contributors
2021-09-21 20:23:17 +02:00
TheLastProject f3ffa0ab88 Update contributors 2021-09-21 18:21:48 +00:00
waffshappen 48e1fcc38e TargetSDK, Version Upgrades, Deprecations and XLint (#405)
* Updated TargetSdk, enabled showing Deprecations by default (Warn) and implement some replacements for deprecated Methods
2021-09-21 20:21:02 +02:00
Sylvia van Os 5b889c4c0c Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-09-20 23:00:31 +02:00
Sylvia van Os 616ca77c39 Fix possible crash
I don't think this should ever happen, unless someone manually edited
their import or DB, but this crash was logged in Google Play Console
anyway so...
2021-09-20 22:58:37 +02:00
Sylvia van Os 59bf064783 Merge pull request #404 from TheLastProject/create-pull-request/patch-1632167904
Update contributors
2021-09-20 21:59:46 +02:00
TheLastProject 220393c445 Update contributors 2021-09-20 19:58:24 +00:00
Sylvia van Os b976c03fb0 Merge pull request #403 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-20 21:57:42 +02:00
mondstern dad0493666 Translated using Weblate (Danish)
Currently translated at 34.4% (72 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/da/
2021-09-20 21:39:12 +02:00
109247019824 776613c507 Translated using Weblate (Bulgarian)
Currently translated at 3.6% (3 of 82 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/bg/
2021-09-20 21:39:11 +02:00
109247019824 7570d9d319 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-09-20 21:39:11 +02:00
Sylvia van Os 2e648d1062 Remove cat face everywhere 2021-09-19 15:46:00 +02:00
Sylvia van Os 5ad02ae9cc Release Catima 2.6.0 2021-09-19 14:48:52 +02:00
Sylvia van Os 99fc568419 Make full description nicer for screen readers 2021-09-19 12:35:41 +02:00
Sylvia van Os 5f835716e0 Consistent badge colouring 2021-09-18 16:46:25 +02:00
Sylvia van Os 1f6fe787eb Remove Python from CodeQL 2021-09-17 21:04:34 +02:00
Sylvia van Os 1b08d30611 Enable CodeQL 2021-09-17 20:57:29 +02:00
Sylvia van Os 05ad33a756 Fix Google Play badge 2021-09-17 20:55:14 +02:00
Sylvia van Os b103366a10 Merge pull request #398 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-17 15:41:52 +02:00
J. Lavoie 343d37d4b8 Translated using Weblate (Italian)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-09-17 15:36:59 +02:00
J. Lavoie 60dc050633 Translated using Weblate (French)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-09-17 15:36:59 +02:00
J. Lavoie 96c3583393 Translated using Weblate (German)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-09-17 15:36:58 +02:00
Sylvia van Os 43656dbcca Merge pull request #396 from TheLastProject/create-pull-request/patch-1631739087
Update contributors
2021-09-15 22:51:48 +02:00
TheLastProject 7c38bbe6ab Update contributors 2021-09-15 20:51:26 +00:00
Sylvia van Os c6c6448501 Merge pull request #395 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-15 22:50:52 +02:00
Oğuz Ersen 7ff9da2d7f Translated using Weblate (Turkish)
Currently translated at 10.9% (9 of 82 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-09-15 22:36:50 +02:00
Oğuz Ersen 39893cc66d Translated using Weblate (Turkish)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-09-15 22:36:49 +02:00
Joel A 5110618d7d Translated using Weblate (Swedish)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-09-15 22:36:49 +02:00
mondstern a856831ee1 Translated using Weblate (Slovak)
Currently translated at 53.5% (112 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2021-09-15 22:36:48 +02:00
solokot c5fc6a4212 Translated using Weblate (Russian)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-09-15 22:36:48 +02:00
Heimen Stoffels 7708646c68 Translated using Weblate (Dutch)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-09-15 22:36:47 +02:00
Gediminas Murauskas c84dbac020 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (209 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-09-15 22:36:47 +02:00
Flav 56c2297e02 Translated using Weblate (French)
Currently translated at 97.6% (204 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-09-15 22:36:47 +02:00
String E. Fighter 6956805e62 Translated using Weblate (German)
Currently translated at 99.5% (208 of 209 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-09-15 22:36:46 +02:00
Sylvia van Os 7736e30043 Merge pull request #394 from TheLastProject/create-pull-request/patch-1631641876
Update Fastlane changelogs
2021-09-14 19:53:27 +02:00
TheLastProject ace441f072 Update Fastlane changelogs 2021-09-14 17:51:15 +00:00
Sylvia van Os a37e99ce39 Prevent OOM on scanning large images for barcode 2021-09-14 19:50:50 +02:00
github-actions[bot]andTheLastProject 6b1bdbaa78 Update Fastlane changelogs (#393)
Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-09-14 19:19:12 +02:00
Sylvia van Os b4077a2fc3 Accept changelog entry without date (unreleased) 2021-09-14 19:17:26 +02:00
Sylvia van Os 2f660c6fec Basic ordering support (#367) 2021-09-14 19:14:38 +02:00
Sylvia van Os cc0511a2aa Merge pull request #391 from TheLastProject/create-pull-request/patch-1631555183
Update contributors
2021-09-13 19:46:59 +02:00
TheLastProject 2f367efa70 Update contributors 2021-09-13 17:46:22 +00:00
Sylvia van Os bff1b54b7e Merge pull request #390 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-13 19:45:46 +02:00
Joel A 010e9556b8 Translated using Weblate (Swedish)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-09-13 19:35:39 +02:00
Sylvia van Os 7c54c01dfe Release Catima 2.5.0 2021-09-10 20:58:17 +02:00
Sylvia van Os 5709c8dbec Fix spotBugs 2021-09-10 19:30:10 +02:00
Sylvia van Os 0f434d7fe7 Merge pull request #387 from TheLastProject/create-pull-request/patch-1631269680
Update contributors
2021-09-10 12:29:51 +02:00
TheLastProject a2d7e70431 Update contributors 2021-09-10 10:28:00 +00:00
Sylvia van Os 0c0c462372 Merge pull request #386 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-10 12:27:31 +02:00
Oğuz Ersen f630539d9a Translated using Weblate (Turkish)
Currently translated at 9.8% (8 of 81 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/tr/
2021-09-10 07:35:44 +02:00
Oğuz Ersen 7e27ddcc94 Translated using Weblate (Turkish)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/tr/
2021-09-10 07:35:43 +02:00
Nyatsuki f9b61c24e9 Translated using Weblate (Japanese)
Currently translated at 99.4% (198 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2021-09-10 07:35:41 +02:00
IllusiveMan196 d26a138e3e Translated using Weblate (Ukrainian)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-09-10 07:35:40 +02:00
solokot e695a4e993 Translated using Weblate (Russian)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-09-10 07:35:40 +02:00
Heimen Stoffels 8cae6aed4a Translated using Weblate (Dutch)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-09-10 07:35:40 +02:00
Allan Nordhøy 56b72dd544 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.4% (198 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-09-10 07:35:40 +02:00
Gediminas Murauskas b935b30e00 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-09-10 07:35:40 +02:00
J. Lavoie b9a6c6248d Translated using Weblate (Italian)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-09-10 07:35:39 +02:00
J. Lavoie 09d8703545 Translated using Weblate (French)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-09-10 07:35:39 +02:00
J. Lavoie 6e25211f12 Translated using Weblate (German)
Currently translated at 100.0% (199 of 199 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-09-10 07:35:39 +02:00
Sylvia van Os 6f1dc74f66 Consistent barcode naming 2021-09-10 00:49:06 +02:00
Sylvia van Os 61b1317fc5 Fix dots increasing each onResume 2021-09-09 22:48:02 +02:00
Sylvia van Os 129ee2d5aa Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-09-08 23:14:00 +02:00
Sylvia van Os 2358ea1f89 Swipe logic fixes 2021-09-08 23:13:43 +02:00
Sylvia van Os 87a172afd5 Merge pull request #384 from TheLastProject/create-pull-request/patch-1631124290
Update Fastlane changelogs
2021-09-08 20:05:30 +02:00
TheLastProject 5a64b6996e Update Fastlane changelogs 2021-09-08 18:04:50 +00:00
Sylvia van Os 9ba07982bf Don't reset group on back button press 2021-09-08 20:04:19 +02:00
Sylvia van Os 98c41ec003 Merge pull request #383 from TheLastProject/create-pull-request/patch-1631118155
Update contributors
2021-09-08 18:23:16 +02:00
TheLastProject bc9875e7fc Update contributors 2021-09-08 16:22:34 +00:00
Sylvia van Os b8bc7eded3 Merge pull request #382 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-08 18:22:06 +02:00
Oğuz Ersen 6625deadf7 Added translation using Weblate (Turkish) 2021-09-08 16:28:03 +02:00
Sylvia van Os c781e4ff4e Merge pull request #380 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-07 19:51:37 +02:00
Joel A b5a2508027 Translated using Weblate (Swedish)
Currently translated at 4.9% (4 of 81 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sv/
2021-09-07 19:51:22 +02:00
github-actions[bot]andTheLastProject 4916917ac9 Update Fastlane changelogs (#381)
Co-authored-by: TheLastProject <TheLastProject@users.noreply.github.com>
2021-09-07 19:51:19 +02:00
Sylvia van Os 4f9b1dae04 Show first image as main (#377) 2021-09-07 19:50:26 +02:00
Sylvia van Os 9b841399f7 Merge pull request #379 from TheLastProject/create-pull-request/patch-1630965291
Update contributors
2021-09-06 23:55:36 +02:00
TheLastProject 45fdc81aa7 Update contributors 2021-09-06 21:54:51 +00:00
Sylvia van Os fdb28a3e52 Merge pull request #378 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-06 23:54:23 +02:00
Joel A a151a9334e Translated using Weblate (Swedish)
Currently translated at 3.7% (3 of 81 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sv/
2021-09-06 23:34:40 +02:00
Sylvia van Os 618c7a294d Merge pull request #376 from TheLastProject/create-pull-request/patch-1630874360
Update contributors
2021-09-05 22:39:57 +02:00
TheLastProject f926d61213 Update contributors 2021-09-05 20:39:19 +00:00
Sylvia van Os d572add506 Merge pull request #375 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-05 22:38:51 +02:00
Joel A 012da7397f Translated using Weblate (Swedish)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-09-05 22:34:42 +02:00
109247019824 92e4908ea8 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-09-05 22:34:42 +02:00
IllusiveMan196 a051d628ab Translated using Weblate (Ukrainian)
Currently translated at 3.7% (3 of 81 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/uk/
2021-09-05 22:34:42 +02:00
Nyatsuki 0116346035 Translated using Weblate (Japanese)
Currently translated at 99.4% (197 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2021-09-05 22:34:41 +02:00
IllusiveMan196 3049b7b0ae Translated using Weblate (Ukrainian)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-09-05 22:34:41 +02:00
solokot 0c484d26ee Translated using Weblate (Russian)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-09-05 22:34:41 +02:00
Heimen Stoffels 55bea5262e Translated using Weblate (Dutch)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-09-05 22:34:40 +02:00
Allan Nordhøy f64d0dcc16 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.4% (197 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-09-05 22:34:40 +02:00
Gediminas Murauskas ad23a671a2 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-09-05 22:34:40 +02:00
J. Lavoie 718e6b433d Translated using Weblate (Italian)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-09-05 22:34:40 +02:00
J. Lavoie 65e2965df2 Translated using Weblate (French)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-09-05 22:34:39 +02:00
J. Lavoie 2bf815942c Translated using Weblate (German)
Currently translated at 100.0% (198 of 198 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-09-05 22:34:39 +02:00
Sylvia van Os b5547c5cdf Merge pull request #371 from TheLastProject/create-pull-request/patch-1630770974
Update Fastlane changelogs
2021-09-04 17:58:08 +02:00
TheLastProject 371fd00606 Update Fastlane changelogs 2021-09-04 15:56:14 +00:00
Sylvia van Os 4f2a448e7e Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-09-04 17:55:52 +02:00
Sylvia van Os 2755641e6b Fix could not read image not always appearing 2021-09-04 17:55:38 +02:00
Sylvia van Os 3e80066a68 Don't crash when selecting video in scan activity 2021-09-04 17:55:21 +02:00
Sylvia van Os 2e78f77be6 Merge pull request #368 from TheLastProject/create-pull-request/patch-1630691444
Update Fastlane changelogs
2021-09-03 19:52:24 +02:00
TheLastProject d042d9a7e8 Update Fastlane changelogs 2021-09-03 17:50:44 +00:00
Sylvia van Os c4064a2ed1 Fix various small accessibility issues 2021-09-03 19:50:17 +02:00
Sylvia van Os 0ac0fad091 Merge pull request #366 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-02 23:50:05 +02:00
mondstern 7fdad67ea4 Translated using Weblate (Slovak)
Currently translated at 35.0% (69 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sk/
2021-09-02 21:32:45 +02:00
Sylvia van Os be21bc1654 Merge pull request #365 from TheLastProject/create-pull-request/patch-1630602047
Update contributors
2021-09-02 19:02:28 +02:00
TheLastProject e65fb4390f Update contributors 2021-09-02 17:00:46 +00:00
Sylvia van Os 9f7bd4a0bd Update CONTRIBUTING.md 2021-09-02 19:00:07 +02:00
Sylvia van Os b43817cbde Merge pull request #363 from weblate/weblate-catima-catima
Translations update from Weblate
2021-09-01 18:06:34 +02:00
Sylvia van Os da0e2ebb99 Fix bad escaping 2021-09-01 17:23:29 +02:00
mondstern aa87f33676 Translated using Weblate (Swedish)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-09-01 17:14:49 +02:00
mondstern 4e7d4383e8 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-09-01 17:14:49 +02:00
mondstern 0702aa1c79 Translated using Weblate (Esperanto)
Currently translated at 53.8% (106 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/eo/
2021-09-01 17:14:49 +02:00
mondstern cd97f89d90 Translated using Weblate (Finnish)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2021-09-01 17:14:49 +02:00
Heimen Stoffels eab6c4d2bd Translated using Weblate (Dutch)
Currently translated at 5.0% (4 of 80 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nl/
2021-09-01 17:14:49 +02:00
mondstern 20775cbc79 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-09-01 17:14:49 +02:00
mondstern 90ecb1997f Translated using Weblate (Slovenian)
Currently translated at 57.8% (114 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sl/
2021-09-01 17:14:49 +02:00
Allan Nordhøy 64b1483fa5 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.4% (196 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-09-01 17:14:49 +02:00
mondstern 8365a719d8 Translated using Weblate (Spanish)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2021-09-01 17:14:49 +02:00
mondstern 068e793682 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-09-01 17:14:49 +02:00
Sylvia van Os 2e1c72e401 Fail build on bad translations 2021-09-01 17:14:38 +02:00
Sylvia van Os 3e213c6996 Unit tests are very unstable, retry once on fail 2021-09-01 12:32:30 +02:00
Sylvia van Os ec65abadc3 PR consistency 2021-09-01 12:27:06 +02:00
Sylvia van Os d24b56b5c1 Merge pull request #360 from TheLastProject/create-pull-request/patch
Update Fastlane changelogs
2021-08-31 20:38:09 +02:00
TheLastProject b56f4e1653 Update Fastlane changelogs 2021-08-31 18:36:29 +00:00
Sylvia van Os efba8773c5 Convert Markdown to simple link for Fastlane 2021-08-31 20:30:21 +02:00
Sylvia van Os 15339a8c44 Merge pull request #358 from TheLastProject/create-pull-request/patch
Update contributors
2021-08-31 18:13:47 +02:00
TheLastProject 050021de5c Update contributors 2021-08-31 16:12:42 +00:00
Sylvia van Os 16cff71cfb Merge pull request #357 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-31 18:12:10 +02:00
Heimen Stoffels 76226a319f Translated using Weblate (Dutch)
Currently translated at 5.0% (4 of 80 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nl/
2021-08-31 16:33:12 +02:00
Maciej Błędkowski eed138a2fb Translated using Weblate (Polish)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/pl/
2021-08-31 16:33:12 +02:00
Sylvia van Os fd202fc940 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-08-30 21:36:29 +02:00
Sylvia van Os 5364b57cee Make PR instead of auto-committing 2021-08-30 21:35:51 +02:00
Sylvia van Os 3136b80f26 Merge pull request #356 from TheLastProject/create-pull-request/patch
Update Fastlane changelogs
2021-08-30 21:29:33 +02:00
TheLastProject f3471b082f Update Fastlane changelogs 2021-08-30 19:28:21 +00:00
Sylvia van Os 9d24ef7791 Move to correct location 2021-08-30 21:27:55 +02:00
Sylvia van Os 6223ccd4bc Automatically Convert CHANGELOG to Fastlane 2021-08-30 21:26:30 +02:00
Sylvia van Os a81cc27414 Add badges showing current available versions 2021-08-29 23:39:04 +02:00
Sylvia van Os 78481516b0 Bump versioncode 2021-08-29 16:38:07 +02:00
Sylvia van Os 423b74273e Release 2.4.0 2021-08-29 16:28:00 +02:00
Sylvia van Os 83e0a988d9 Improve contrast of cards 2021-08-29 16:14:32 +02:00
Sylvia van Os 1adea88ff1 Merge pull request #352 from TheLastProject/feature/cardLayout
Main screen card layout
2021-08-29 01:33:06 +02:00
Sylvia van Os dda912c8c5 Update CHANGELOG 2021-08-29 01:27:47 +02:00
Sylvia van Os f3b31bb306 Update screenshots 2021-08-29 01:27:10 +02:00
Sylvia van Os 3b31c4e05a Set min-height for long store names 2021-08-29 01:16:31 +02:00
Sylvia van Os 1155108086 Fix title layout issue 2021-08-29 00:46:36 +02:00
Sylvia van Os 73bb7ded09 Fix recyclerview not rendering all in unit test 2021-08-28 01:51:44 +02:00
Sylvia van Os d8655eb631 Don't make cards bigger than needed 2021-08-28 01:42:19 +02:00
Sylvia van Os 55cddfef91 Fix incorrect data due to recycling 2021-08-28 01:39:33 +02:00
Sylvia van Os c35dc736f4 Cleanup buggy code 2021-08-28 01:03:25 +02:00
Sylvia van Os 23b762a500 2 colums in landscape 2021-08-28 00:05:33 +02:00
Sylvia van Os b9b638de45 Initial card layout 2021-08-27 23:42:03 +02:00
thelastproject/contributors-to-file 5f57507dda Update contributor list 2021-08-27 20:40:38 +00:00
Sylvia van Os 852eb6612c Merge pull request #351 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-27 22:40:04 +02:00
solokot d96aac7bbf Translated using Weblate (Russian)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-27 22:32:54 +02:00
Allan Nordhøy 9018479959 Translated using Weblate (Norwegian Bokmål)
Currently translated at 90.8% (179 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-08-27 22:32:54 +02:00
Gediminas Murauskas ce8a99e840 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-08-27 22:32:54 +02:00
J. Lavoie 9236f66bc6 Translated using Weblate (Italian)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-08-27 22:32:53 +02:00
J. Lavoie 37b3964351 Translated using Weblate (French)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-08-27 22:32:53 +02:00
J. Lavoie a60d902fda Translated using Weblate (German)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-08-27 22:32:53 +02:00
Petr Novák a97ce6f9aa Translated using Weblate (Czech)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-08-27 22:32:53 +02:00
waffshappen a15bce04e8 German Translation (#349) 2021-08-26 00:03:39 +02:00
thelastproject/contributors-to-file 34fa68f852 Update contributor list 2021-08-25 21:31:08 +00:00
Sylvia van Os e5fef55fc7 Ignore bots 2021-08-25 23:30:41 +02:00
Sylvia van Os c5cca1b14d Merge pull request #348 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-25 23:24:45 +02:00
Heimen Stoffels f34ec1cc4b Translated using Weblate (Dutch)
Currently translated at 100.0% (197 of 197 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-25 23:23:34 +02:00
solokot 95aafa5c99 Translated using Weblate (Russian)
Currently translated at 100.0% (196 of 196 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-25 23:23:34 +02:00
Heimen Stoffels 00160b0c45 Translated using Weblate (Dutch)
Currently translated at 100.0% (196 of 196 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-25 23:23:34 +02:00
Allan Nordhøy a7e6d56bc9 Translated using Weblate (Norwegian Bokmål)
Currently translated at 91.3% (179 of 196 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-08-25 23:23:34 +02:00
Gediminas Murauskas 9dc8d5e2f4 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (196 of 196 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-08-25 23:23:34 +02:00
thelastproject/contributors-to-file cf7cf679e0 Update contributor list 2021-08-25 21:23:31 +00:00
Sylvia van Os 4e7e0d9480 Fix pagination in contributors-to-file 2021-08-25 23:23:05 +02:00
thelastproject/contributors-to-file fbb3013b20 Update contributor list 2021-08-25 20:57:46 +00:00
waffshappen ca37e2aa84 Introduce a fallback text when a group is empty (#347) 2021-08-25 22:57:22 +02:00
Sylvia van Os e6bf60d457 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-08-25 21:39:10 +02:00
Sylvia van Os 35835fda34 Make spotBugs happy 2021-08-25 21:38:52 +02:00
Sylvia van Os a3133de6cf Merge pull request #346 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-25 21:27:31 +02:00
solokot 40fb10a2ec Translated using Weblate (Russian)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-25 21:18:16 +02:00
Sylvia van Os 856c735ba3 Add all contributors to About screen
You all are amazing, thank you for helping me make this app :)
2021-08-25 21:17:55 +02:00
thelastproject/contributors-to-file 16fb0df55d Update contributor list 2021-08-25 18:40:47 +00:00
Sylvia van Os 5658acbb07 Update contributor list on push not on schedule 2021-08-25 20:38:51 +02:00
Sylvia van Os 8b5faac0e0 Fix filename 2021-08-25 20:37:39 +02:00
Sylvia van Os 10be9b58ce Write contributors to file 2021-08-25 20:37:24 +02:00
Sylvia van Os 832840be08 Merge pull request #345 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-25 12:10:31 +02:00
Quentin PAGÈS 5806156495 Translated using Weblate (Occitan)
Currently translated at 37.4% (73 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/oc/
2021-08-25 11:32:59 +02:00
Petr Novák 0be9b908ab Translated using Weblate (Czech)
Currently translated at 66.6% (2 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-08-25 11:32:59 +02:00
IllusiveMan196 718d2b7567 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-08-25 11:32:58 +02:00
IllusiveMan196 fed9754908 Translated using Weblate (Russian)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-25 11:32:58 +02:00
solokot c0e09ca429 Translated using Weblate (Russian)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-25 11:32:58 +02:00
Heimen Stoffels 4a3737b846 Translated using Weblate (Dutch)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-25 11:32:57 +02:00
Gediminas Murauskas b4add4a0ea Translated using Weblate (Lithuanian)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-08-25 11:32:57 +02:00
J. Lavoie 5aabbd629e Translated using Weblate (Italian)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-08-25 11:32:57 +02:00
J. Lavoie a5ef50317d Translated using Weblate (French)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-08-25 11:32:56 +02:00
J. Lavoie 48a8cc927a Translated using Weblate (German)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-08-25 11:32:56 +02:00
Petr Novák cbb97d7d57 Translated using Weblate (Czech)
Currently translated at 100.0% (195 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-08-25 11:32:56 +02:00
Sylvia van Os 5eee344035 Don't close ScanActivity on camera error 2021-08-25 00:29:40 +02:00
Sylvia van Os 4c7e0c7174 Fix build 2021-08-23 18:40:48 +02:00
Sylvia van Os 37bb9c86f4 More small cleanups 2021-08-23 00:59:31 +02:00
Sylvia van Os 83ea6ffbf7 Cleanups 2021-08-22 16:16:27 +02:00
Sylvia van Os f4945c2cd2 Merge pull request #342 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-22 10:45:01 +02:00
IllusiveMan196 24d9c7825a Translated using Weblate (Ukrainian)
Currently translated at 97.9% (191 of 195 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-08-22 02:43:38 +02:00
Sylvia van Os 2aa7bb4639 Update CHANGELOG 2021-08-22 01:29:14 +02:00
Subhashish Anand 110b3bcef3 Add theme colour support 2021-08-22 01:14:24 +02:00
Sylvia van Os f625efc76d Merge pull request #341 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-21 21:36:27 +02:00
Sylvia van Os 22608a9802 Translated using Weblate (Dutch)
Currently translated at 100.0% (175 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-21 21:35:36 +02:00
Sylvia van Os abf6c1328d Update importers list 2021-08-20 22:33:26 +02:00
Sylvia van Os 225058ab2b Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-08-19 21:26:04 +02:00
Sylvia van Os 275dc6caa2 Release Catima 2.3.0 2021-08-19 21:25:35 +02:00
Sylvia van Os ceb7b12154 Merge pull request #335 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-18 17:41:48 +02:00
Luna Jernberg 849da26198 Translated using Weblate (Swedish)
Currently translated at 99.4% (174 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-08-18 17:36:39 +02:00
solokot 5808c991bb Translated using Weblate (Russian)
Currently translated at 100.0% (175 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-18 17:36:39 +02:00
Heimen Stoffels e8554cb221 Translated using Weblate (Dutch)
Currently translated at 100.0% (175 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-18 17:36:39 +02:00
Allan Nordhøy 46092c060d Translated using Weblate (Norwegian Bokmål)
Currently translated at 90.2% (158 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-08-18 17:36:38 +02:00
Gediminas Murauskas 736eebd45c Translated using Weblate (Lithuanian)
Currently translated at 100.0% (175 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-08-18 17:36:38 +02:00
J. Lavoie f72db53345 Translated using Weblate (Italian)
Currently translated at 100.0% (175 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-08-18 17:36:38 +02:00
J. Lavoie b8c017259e Translated using Weblate (French)
Currently translated at 100.0% (175 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-08-18 17:36:38 +02:00
J. Lavoie 4b4a237b9a Translated using Weblate (German)
Currently translated at 100.0% (175 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-08-18 17:36:37 +02:00
Petr Novák 17034e992f Translated using Weblate (Czech)
Currently translated at 60.0% (105 of 175 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-08-18 17:36:37 +02:00
Sylvia van Os bf143038b0 Update CHANGELOG 2021-08-17 22:46:53 +02:00
Sylvia van Os 73805ad3bb Fix importing images from export 2021-08-17 22:46:03 +02:00
Sylvia van Os 7006e35ebf Remove pages managed in Catima-Website repository 2021-08-16 18:23:03 +02:00
Sylvia van Os fc598018b2 Remove duplicate Privacy Policy
It is managed in https://github.com/TheLastProject/Catima-Website/ now
2021-08-16 18:21:36 +02:00
Sylvia van Os d01ec85c32 Merge pull request #332 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-15 22:23:59 +02:00
Nyatsuki 04ee918152 Translated using Weblate (Japanese)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ja/
2021-08-15 22:18:44 +02:00
Tymofii Lytvynenko 943b70647b Translated using Weblate (Ukrainian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-08-15 22:18:44 +02:00
Sylvia van Os edba5d5dca Add locale chooser (#304)
* Add locale chooser

* Prevent AppBundle crashes

* Reload activity on language change

* Make spotBugs happy
2021-08-15 22:18:40 +02:00
Sylvia van Os 86be5d1994 Update image-actions 2021-08-15 17:44:42 +02:00
Sylvia van Os 5be2308606 Release 2.2.3 2021-08-13 20:21:02 +02:00
Sylvia van Os a2e81d08d7 Merge pull request #330 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-13 15:34:50 +02:00
Joel A 9f5f0e79f4 Translated using Weblate (Swedish)
Currently translated at 66.6% (2 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sv/
2021-08-13 13:32:16 +02:00
Joel A 3f8c4c94ce Translated using Weblate (Swedish)
Currently translated at 99.4% (171 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-08-13 13:32:16 +02:00
mondstern 46895c0037 Translated using Weblate (Finnish)
Currently translated at 100.0% (3 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/fi/
2021-08-13 13:32:15 +02:00
mondstern 65c98a4840 Translated using Weblate (Finnish)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fi/
2021-08-13 13:32:15 +02:00
Sylvia van Os 67c58c10b2 Create splash screen 2021-08-12 23:36:55 +02:00
Sylvia van Os 8d82a4616f Don't remove needs info 2021-08-12 13:06:15 +02:00
Sylvia van Os 01a272f8e6 Autoclose issues being in needs info state for over 90 days 2021-08-11 17:57:22 +02:00
Sylvia van Os 0235a397cf Merge pull request #328 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-11 09:04:18 +02:00
Joel A e37ee6f812 Translated using Weblate (Swedish)
Currently translated at 85.4% (147 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-08-11 05:32:37 +02:00
mondstern 2b5ea47d9f Translated using Weblate (Bulgarian)
Currently translated at 100.0% (3 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/bg/
2021-08-11 05:32:37 +02:00
mondstern 0fcdaf3f60 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-08-11 05:32:37 +02:00
Jane Kong b2cb38b61d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (3 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/zh_Hans/
2021-08-11 05:32:36 +02:00
Jane Kong fd1fe168cc Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/zh_Hans/
2021-08-11 05:32:36 +02:00
mondstern 9deb80ff9b Translated using Weblate (Ukrainian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-08-11 05:32:35 +02:00
Sylvia van Os 75fdd7390f Merge pull request #325 from recursiveribbons/sql-refactor
Refactored DBHelper
2021-08-09 20:35:55 +02:00
recursiveribbons 7cd6c17b55 Refactored DBHelper 2021-08-09 17:35:25 +02:00
Sylvia van Os c273d8d17f Fix widget creating different-looking shortcut than app shortcuts 2021-08-08 23:49:10 +02:00
Sylvia van Os c1b02f58ff Fix indent 2021-08-08 23:04:55 +02:00
Sylvia van Os 0bac2dfb62 Merge pull request #322 from TacoTheDank/master
Some cleanup and compatibility stuff
2021-08-08 23:03:58 +02:00
TacoTheDank 4f0288e396 Use ActivityCompat.recreate 2021-08-08 16:33:55 -04:00
TacoTheDank 55f0399325 Use ShortcutInfoCompat 2021-08-08 16:33:42 -04:00
Sylvia van Os e756c6e50b Fix dir names 2021-08-08 19:30:37 +02:00
Sylvia van Os b8c022dc70 Merge pull request #323 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-08 19:18:06 +02:00
Joel A d823ddd8aa Translated using Weblate (Swedish)
Currently translated at 33.3% (1 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/sv/
2021-08-08 19:13:17 +02:00
Joel A 352b42bba0 Translated using Weblate (Swedish)
Currently translated at 82.5% (142 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/sv/
2021-08-08 19:13:17 +02:00
Sylvia van Os 89894131d9 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-08-08 19:12:49 +02:00
Sylvia van Os 5ddcb0a668 Fix crash on rotation in edit view 2021-08-08 19:12:25 +02:00
TacoTheDank 5d5b1f0a63 Use AndroidX ExifInterface 2021-08-07 17:08:50 -04:00
TacoTheDank 03e638786b Create TextWatcher stub 2021-08-07 17:08:28 -04:00
TacoTheDank 7d5b2f8dc8 Update NumberPickerPreference library 2021-08-07 16:47:01 -04:00
Sylvia van Os 13257d17fc Merge pull request #321 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-07 13:48:38 +02:00
Joel A 5e8a589d9a Added translation using Weblate (Swedish) 2021-08-07 13:47:51 +02:00
Sylvia van Os 44711043b9 Release Catima 2.2.1 2021-08-07 13:28:02 +02:00
Sylvia van Os 80ee8aa860 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-08-07 13:16:35 +02:00
Sylvia van Os cd6685b974 Fix flashing in ManageGroupsActivity 2021-08-07 13:16:21 +02:00
Sylvia van Os b5f464000b Merge pull request #318 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-07 05:54:03 +02:00
J. Lavoie 27159323d5 Translated using Weblate (Italian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-08-07 02:41:29 +02:00
J. Lavoie 9551ce8a8b Translated using Weblate (French)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-08-07 02:41:29 +02:00
J. Lavoie 525471f749 Translated using Weblate (German)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-08-07 02:41:28 +02:00
Sylvia van Os 57bedd0300 Actually fix properly 2021-08-05 20:51:29 +02:00
Sylvia van Os c3345a1a15 Fix last commit 2021-08-05 20:35:44 +02:00
Sylvia van Os 15f6bd86a1 Change card title size within range 2021-08-05 20:21:18 +02:00
Sylvia van Os e2ad1c9da2 Add animations to card list 2021-08-05 19:38:37 +02:00
Sylvia van Os 7082669612 Fix importing Catima export with multiline note 2021-08-05 18:28:14 +02:00
Sylvia van Os d595d24769 Merge pull request #313 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-04 23:26:51 +02:00
Gediminas Murauskas 4287d66f6f Translated using Weblate (Lithuanian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-08-04 23:24:45 +02:00
Sylvia van Os 311361d105 Merge pull request #312 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-04 23:24:41 +02:00
Sylvia van Os 4a88e39deb Fix syntax 2021-08-04 22:38:13 +02:00
mondstern 4511590263 Translated using Weblate (Danish)
Currently translated at 66.6% (2 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/da/
2021-08-04 22:32:46 +02:00
mondstern d0c30ffa1c Translated using Weblate (Danish)
Currently translated at 27.3% (47 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/da/
2021-08-04 22:32:46 +02:00
Allan Nordhøy 813c2bff85 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (3 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/nb_NO/
2021-08-04 22:32:45 +02:00
solokot 0c3cf43841 Translated using Weblate (Russian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-04 22:32:45 +02:00
Heimen Stoffels 6c651f7e3e Translated using Weblate (Dutch)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-04 22:32:45 +02:00
Allan Nordhøy ef7fc92920 Translated using Weblate (Norwegian Bokmål)
Currently translated at 90.1% (155 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-08-04 22:32:44 +02:00
Sylvia van Os ccaf70c749 Merge pull request #311 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-03 20:59:42 +02:00
mondstern 2299bf9d86 Added translation using Weblate (Danish) 2021-08-03 20:58:37 +02:00
Sylvia van Os b65f8f32ca Merge pull request #310 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-03 20:48:23 +02:00
mondstern 47695d3a72 Translated using Weblate (Czech)
Currently translated at 66.6% (2 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/cs/
2021-08-03 20:43:07 +02:00
solokot 439c660b2e Translated using Weblate (Russian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-03 20:43:07 +02:00
Gediminas Murauskas 4293d7d4b2 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-08-03 20:43:07 +02:00
J. Lavoie e368e66b8a Translated using Weblate (Italian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-08-03 20:43:07 +02:00
Mattia 992a7f9e84 Translated using Weblate (Italian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-08-03 20:43:07 +02:00
J. Lavoie ecf0faf00a Translated using Weblate (French)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-08-03 20:43:07 +02:00
J. Lavoie 64178f3fd1 Translated using Weblate (Spanish)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2021-08-03 20:43:07 +02:00
J. Lavoie dab6588800 Translated using Weblate (German)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-08-03 20:43:07 +02:00
mondstern f71bb32592 Translated using Weblate (Czech)
Currently translated at 51.1% (88 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/cs/
2021-08-03 20:43:07 +02:00
Sylvia van Os 0c44212d92 Make SpotBugs happy 2021-08-03 20:42:57 +02:00
Sylvia van Os ce149c91e9 Improve Stocard importer 2021-08-03 20:34:44 +02:00
Sylvia van Os 05dfd48f57 Release Catima 2.2.0 2021-08-02 23:42:32 +02:00
Sylvia van Os ef955b866d Remove unused imports 2021-08-02 23:09:49 +02:00
Sylvia van Os a843b5a1b9 Make lint happier 2021-08-02 22:58:06 +02:00
Sylvia van Os 8305d58ccc Fix maximize button appearing on no barcode 2021-08-02 22:57:55 +02:00
Sylvia van Os 6af79d5f41 General cleanups 2021-08-02 20:47:48 +02:00
Sylvia van Os 3b326d6f9c Also remove from AboutActivity 2021-08-02 20:37:13 +02:00
Sylvia van Os 1456e5073e Get rid of barely used dependency 2021-08-02 20:36:20 +02:00
Sylvia van Os 6a13dbf66a Comma-separate group names in loyalty card view 2021-08-01 23:03:56 +02:00
Sylvia van Os c5b1718e8e Pre-select active group on creating new card 2021-08-01 22:33:44 +02:00
Sylvia van Os e2bcc24867 Make links in notes clickable 2021-08-01 21:39:48 +02:00
Sylvia van Os c86cc22a93 Release v2.1.0 2021-08-01 21:00:12 +02:00
Sylvia van Os 765577ae9e Merge pull request #306 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-01 20:50:42 +02:00
Heimen Stoffels d1d15644b5 Translated using Weblate (Dutch)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-01 20:36:29 +02:00
Sylvia van Os 5d41b213db Remove translations to break lint 2021-08-01 20:36:17 +02:00
Sylvia van Os aa515b1192 Be more explicit in quantity
Translators still keep triggering the linter with errors such as the
following:
Error: The quantity 'one' matches more than one specific number in this locale (1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …), but the message did not include a formatting argument (such as %d). This is usually an internationalization error. See full issue explanation for more. [ImpliedQuantity]
2021-08-01 12:50:56 +02:00
Sylvia van Os 068660fe3f Merge pull request #305 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-01 12:42:14 +02:00
solokot 99ffaf97d1 Translated using Weblate (Russian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-01 12:32:51 +02:00
Heimen Stoffels b53999c1cf Translated using Weblate (Dutch)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-01 12:32:51 +02:00
Allan Nordhøy 57f87d7dc0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 90.6% (156 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-08-01 12:32:50 +02:00
J. Lavoie 760f6a873d Translated using Weblate (Italian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-08-01 12:32:50 +02:00
J. Lavoie 675bd43ff8 Translated using Weblate (French)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-08-01 12:32:50 +02:00
J. Lavoie 07532ce001 Translated using Weblate (Spanish)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2021-08-01 12:32:50 +02:00
J. Lavoie 908a7055c7 Translated using Weblate (German)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-08-01 12:32:49 +02:00
Sylvia van Os 2be371caed Forgot number 2021-07-30 19:46:10 +02:00
Sylvia van Os f4f3f2e307 Increase i18n flexibility
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. Therefore, we use the plain string when meaning exactly 1, and otherwise use the plural forms.
2021-07-30 19:40:43 +02:00
Sylvia van Os edbf76c7dc Merge pull request #303 from weblate/weblate-catima-catima
Translations update from Weblate
2021-07-30 19:02:48 +02:00
109247019824 f8615f45f0 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-07-30 18:18:55 +02:00
IllusiveMan196 c3bc3e9911 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-07-30 18:18:55 +02:00
solokot 8adcca1df2 Translated using Weblate (Russian)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-07-30 18:18:55 +02:00
Heimen Stoffels bdde8669ac Translated using Weblate (Dutch)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-07-30 18:18:55 +02:00
solokot 59db2df525 Translated using Weblate (Russian)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-07-30 18:18:55 +02:00
Sylvia van Os 3b83ff5b0e Fix syntax 2021-07-30 18:18:32 +02:00
Heimen Stoffels 19fb290a51 Translated using Weblate (Dutch)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-07-30 18:15:39 +02:00
Allan Nordhøy e1e823d9e0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 90.0% (153 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-07-30 18:15:30 +02:00
Sylvia van Os 7ed477b670 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-07-29 22:16:47 +02:00
Sylvia van Os 1960fb0b6a Fix fullscreen loss on rotation 2021-07-29 22:16:36 +02:00
Sylvia van Os e913482790 Merge pull request #299 from comradekingu/patch-7
New strings reworked
2021-07-29 21:54:43 +02:00
Allan Nordhøy 2e5bd76d31 New strings reworked 2021-07-29 19:47:10 +00:00
Sylvia van Os 876ae979da Simplify updateTempState
Hopefully fixes the few weird crashes on Google Play
2021-07-29 21:42:21 +02:00
Sylvia van Os d918c15ad6 Prevent ArithmeticException 2021-07-29 21:18:21 +02:00
Sylvia van Os d57cb307c3 Support multi-deleting cards 2021-07-29 20:38:37 +02:00
Sylvia van Os cbcf1bcd99 Use desugaring to upgrade zxing without having to increase minSdk
As documented by the zxing team on https://github.com/zxing/zxing/wiki/Frequently-Asked-Questions#it-doesnt-work-with-java-7--no-interface-method-sortljavautilcomparator
2021-07-28 23:05:27 +02:00
Sylvia van Os 96bc10583f Fix colour dialog selected colour 2021-07-27 22:04:09 +02:00
598 changed files with 17425 additions and 5974 deletions

No files matched your search

+11
View File
@@ -0,0 +1,11 @@
# 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
schedule:
interval: "daily"
+13 -6
View File
@@ -2,9 +2,13 @@ name: Android CI
on:
push:
branches: [ master ]
branches:
- master
- staging
- trying
pull_request:
branches: [ master ]
branches:
- master
jobs:
build:
@@ -13,17 +17,20 @@ jobs:
steps:
- uses: actions/checkout@v2
- 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 1.8
uses: actions/setup-java@v1
- name: set up JDK 11
uses: actions/setup-java@v2
with:
java-version: 1.8
distribution: 'adopt'
java-version: '11'
- name: Build
run: ./gradlew assembleRelease
- name: Check lint
run: ./gradlew lintRelease
- name: Run unit tests
run: ./gradlew testReleaseUnitTest
run: ./gradlew testReleaseUnitTest || ./gradlew testReleaseUnitTest
- name: SpotBugs
run: ./gradlew spotbugsRelease
- name: Archive test results
@@ -0,0 +1,23 @@
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: 'needs info'
stale-issue-label: 'needs info'
stale-pr-label: 'needs info'
remove-stale-when-updated: false
@@ -10,20 +10,23 @@ on:
- '**.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@master
uses: actions/checkout@v2
- name: Compress Images
id: calibre
uses: calibreapp/image-actions@master
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@master
uses: peter-evans/create-pull-request@v3
with:
title: Compressed Images
branch-suffix: timestamp
@@ -0,0 +1,26 @@
name: Convert CHANGELOG to Fastlane
on:
push:
branches:
- master
jobs:
convert_changelog_to_fastlane:
runs-on: ubuntu-latest
name: Convert CHANGELOG to Fastlane
steps:
- name: Checkout repo
id: checkout
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
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
with:
title: "Update Fastlane changelogs"
commit-message: "Update Fastlane changelogs"
branch-suffix: timestamp
+73
View File
@@ -0,0 +1,73 @@
# 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
@@ -0,0 +1,25 @@
name: Write contributors to file
on:
schedule:
- cron: '3 4 * * 0'
jobs:
contributors_to_file:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
name: Write contributors to file
steps:
- name: Checkout repo
id: checkout
uses: actions/checkout@v2
- name: Update contributors
id: update_contributors
uses: TheLastProject/contributors-to-file-action@v2
with:
file_in_repo: app/src/main/res/raw/contributors.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
title: "Update contributors"
commit-message: "Update contributors"
branch-suffix: timestamp
+1
View File
@@ -7,3 +7,4 @@ build/
captures/
**/release
**/debug
app/*.log
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/python3
import os
import re
changelogs = {}
with open('CHANGELOG.md') as changelog:
version_code = None
text = []
for line in changelog:
if line.startswith("## "):
if version_code != None:
changelogs[version_code] = text
text = []
match = re.match("## \S* - (\d*).*", line)
if not match:
raise ValueError(f"Invalid version line: {line}")
version_code = match.group(1)
elif line:
# Turn Markdown [links](to_url) into links (to_url)
text.append(re.sub(r'\[(.*?)\]\((.*?)\)', r'\1 (\2)', line))
for version, description in changelogs.items():
description = "".join(description).strip()
if not description:
continue
with open(os.path.join("fastlane", "metadata", "android", "en-US", "changelogs", f"{version}.txt"), "w") as fastlane_file:
fastlane_file.write(description)
+224 -220
View File
@@ -1,40 +1,179 @@
# Changelog
## v2.0.4 (2021-07-27)
## Unreleased - 101
Changes:
- Fix cropper not using theme colour
- Fix minor theming issues
- Add pure black dark theme for OLED screens
## v2.14.1 - 100 (2022-01-15)
- Hide search, expand and sort icons until there is at least 1 card
- Various theming fixes
## v2.14.0 - 99 (2022-01-14)
- Material You redesign
## v2.13.1 - 98 (2022-01-09)
- Fix various TalkBack-related bugs
## v2.13.0 - 97 (2022-01-03)
- Fixed pressing the save button multiple times creating multiple entries
- Lower card header size when hiding details to fit even more cards
- Restructure edit screen
- Improve star icon contrast in main view
## v2.12.0 - 96 (2021-12-23)
- Add CODE 93 support
- Various minor bugfixes and improvements
## v2.11.2 - 95 (2021-12-04)
- Fix crash on sharing card
## v2.11.1 - 94 (2021-11-30)
- Fix blurriness of main screen letter icons
- Fix icons sometimes disappearing after selection
- Fix status bar icons possibly being invisible on Android 5
## v2.11.0 - 93 (2021-11-28)
- Add Catima to [Quick Access Device Controls](https://developer.android.com/guide/topics/ui/device-control)
- Fix some groups not showing up correctly in group management screen
## v2.10.0 - 92 (2021-11-20)
- New main screen layout
- Fix bottomsheet sizing issues when switching in and out of fullscreen
## v2.9.0 - 91 (2021-11-14)
- Improved group management support
- Support cropping images
- Fix image data loss when saving after rotating in edit view
- Ability to set a custom image as card icon
## v2.8.1 - 90 (2021-10-27)
- Fix dots in card view having the wrong colour when changing theme manually
- Fix crash in card view on rotation/theme change
- Fix flashing of cards list
- Fix text overlaying star icon
## v2.8.0 - 89 (2021-10-25)
- Fix swiping between groups not working on an empty group
- Allow password-protecting exports
- Improve usage of space for QR codes
- Save the last used zoom level per card
- Fix a crash when swiping right after a tap
## v2.7.3 - 88 (2021-10-10)
- Fix incorrect migration making first card become invisible
## v2.7.2 - 87 (2021-10-09)
- Fix regression breaking import/export
## v2.7.1 - 86 (2021-10-07)
- Improve search with spaces
## v2.7.0 - 85 (2021-10-05)
Android 4.4 is no longer supported starting with this release. If you want to use Catima on Android 4.4, please use version 2.6.1.
- Improved Android 12 support
- Improved about screen
- Search now ignores accents
## v2.6.1 - 84 (2021-09-25)
- Minor bugfixes and improvements
## v2.6.0 - 83 (2021-09-19)
- Support for changing the sorting order
- Prevent Out Of Memory on scanning large pictures for barcode
## v2.5.0 - 82 (2021-09-10)
- Improved support for screen readers
- Don't crash when trying to open a video from gallery
- Swipe support on loyalty card view screen
- Don't reset group on back button press
## v2.4.0 - 81 (2021-08-29)
- Improve card list for landscape and tablet display
- Add theming colour support (thanks, Subhashish Anand!)
- Don't close scan activity on camera error (so manual entry is still possible)
- Add all contributors to the about dialog
## v2.3.0 - 80 (2021-08-19)
- Fix images not imported from backup
- Option to override language
## v2.2.3 - 79 (2021-08-13)
- Fix widget creating different-looking shortcut than app shortcuts
- Replace default Android black screen with splash screen
## v2.2.2 - 78 (2021-08-08)
- Fix crash on rotation in loyalty card edit activity
## v2.2.1 - 77 (2021-08-07)
- Improve Stocard importer
- Fix importing Catima export with multiline note
- Scale card title in acceptable range
- Animation improvements
## v2.2.0 - 76 (2021-08-02)
- Make links in notes clickable
- Pre-select group the user is currently in when creating a new card
- Comma-separate group names in loyalty card view
- Fix maximize button appearing on no barcode
## v2.1.0 - 75 (2021-08-01)
- Fix selected colour in colour changing dialog
- Support for deleting multiple cards at once
- Fix possible ArithmeticException when resizing image
- Fix fullscreen is closed when rotating device
## v2.0.4 - 74 (2021-07-27)
- Fix shortcut creation
- Generate card-specific shortcut icon
- Fix ability to change loyalty card colour
## v2.0.3 (2021-07-25)
Changes:
## v2.0.3 - 73 (2021-07-25)
- Fix loading photos when editing existing card
## v2.0.2 (2021-07-25)
Changes:
## v2.0.2 - 72 (2021-07-25)
- Fix inability to configure photos in new loyalty card
## v2.0.1 (2021-07-21)
Changes:
## v2.0.1 - 71 (2021-07-21)
- Several minor translation and UI fixes
- Fix crash in import/sharing loyalty card on Android 6
## v2.0 (2021-07-14)
Breaking changes:
- The backup format changed, see https://github.com/TheLastProject/Catima/wiki/Export-format
- The URL sharing format changed, see https://github.com/TheLastProject/Catima/wiki/Card-sharing-URL-format
Changes:
## v2.0 - 70 (2021-07-14)
- BREAKING CHANGE: The backup format changed, see https://github.com/TheLastProject/Catima/wiki/Export-format
- BREAKING CHANGE: The URL sharing format changed, see https://github.com/TheLastProject/Catima/wiki/Card-sharing-URL-format
- Make it possible to enable or disable the flashlight while scanning
- Add UPC-E support
- Support adding a front and back photo to each card
@@ -45,26 +184,20 @@ Changes:
- Fix Floating Action Buttons being behind other UI elements on Android 4
- Fix loyalty card viewer appbar top margin
## v1.14.1 (2021-06-14)
Changes:
## v1.14.1 - 69 (2021-06-14)
- Add missing barcode ID to export
- Don't show update barcode dialog if value is the same as card ID
- Add Finnish translation
## v1.14 (2021-06-07)
Changes:
## v1.14 - 68 (2021-06-07)
- Support new PDF417 export from Voucher Vault
- Support copying multiple barcodes at once
- Support sharing multiple loyalty cards at once
- Ask to update barcode value if card ID changes
## v1.13 (2021-04-10)
Changes:
## v1.13 - 67 (2021-04-10)
- Add option to set a separate barcode value from card ID
- Simplify font sizing configuration
@@ -73,175 +206,125 @@ Changes:
- Always show all barcode types in manual entry
- Remove privacy policy first start dialog
## v1.12 (2021-03-30)
Changes:
## v1.12 - 66 (2021-03-30)
- Support importing [Fidme](https://play.google.com/store/apps/details?id=fr.snapp.fidme) exports
- Allow importing a card from a picture stored in the user's Android gallery
- Fix multiline note cutoff
- Change "Thank you" text on privacy dialog to "Accept" because Huawei is overly pedantic
## v1.11 (2021-03-21)
Changes:
## v1.11 - 64 (2021-03-21)
- Add privacy policy dialog on first start (required by Huawei)
## v1.10 (2021-03-07)
Changes:
## v1.10 - 63 (2021-03-07)
- Support importing [Voucher Vault](https://github.com/tim-smart/vouchervault/) exports
- Option to keep the screen on while viewing a loyalty card
- Option to suspend the lock screen while viewing a loyalty card
## v1.9.2 (2021-02-24)
Changes:
## v1.9.2 - 62 (2021-02-24)
- Fix parsing balance for countries using space as separator
## v1.9.1 (2021-02-23)
Changes:
## v1.9.1 - 61 (2021-02-23)
- Improve balance parsing logic
- Fix currency decimal display on main screen
## v1.9 (2021-02-22)
Changes:
## v1.9 - 59 (2021-02-22)
- Add balance support
- Reorganize barcode tab of edit view
## v1.8.1 (2021-02-12)
Changes:
## v1.8.1 - 58 (2021-02-12)
- Fix Crash on versions before Android 7
## v1.8 (2021-01-28)
Changes:
## v1.8 - 57 (2021-01-28)
- Add support for scaling the barcode when moving to top to fit even more small scanners
- Fix bottom sheet jumping after switching to fullscreen
- Make header in loyalty card view small in landscape mode
- Fix cards not staying in group when group gets renamed
## v1.7.1 (2021-01-18)
Changes:
## v1.7.1 - 56 (2021-01-18)
- Fix crash on switching to barcode tab in edit view if there is no barcode
## v1.7.0 (2021-01-18)
Changes:
## v1.7.0 - 55 (2021-01-18)
- Separate edit UI in tabs to make it feel more spacious
- Add expiry field support
## v1.6.2 (2021-01-04)
Changes:
## v1.6.2 - 54 (2021-01-04)
- Fix edit button or more info bottom sheet drawing over barcode ID
## v1.6.1 (2020-12-16)
Changes:
## v1.6.1 - 64 (2020-12-16)
- Fix regression causing manual barcode entry to not be saved
## v1.6.0 (2020-12-15)
Changes:
## v1.6.0 - 52 (2020-12-15)
- Automatically focus text field when creating or editing a group
- Fix blurry icons (use SVG everywhere)
- Always open camera but add manual scan button to camera view
## v1.5.1 (2020-12-03)
Changes:
## v1.5.1 - 51 (2020-12-03)
- Fix bottomsheet background being transparent
## v1.5.0 (2020-12-03)
Changes:
## v1.5.0 - 50 (2020-12-03)
- Improve contrast by always using white text on red buttons
- Draggable bottom sheet in loyalty card view
## v1.4.1 (2020-12-01)
Changes:
## v1.4.1 - 49 (2020-12-01)
- Improved translations
- Small UI fixes
## v1.4.0 (2020-11-28)
Changes:
## v1.4.0 - 48 (2020-11-28)
- Move About screen into its own activity
- Ask user if they want to use their camera or manually enter ID on add/edit card
- Make group ordering manual instead of forced alphabetically
## v1.3.0 (2020-11-22)
Changes:
## v1.3.0 - 47 (2020-11-22)
- Always show all import/export options and show a toast on actual issues (improves compat with XPrivacyLua)
- Ask for confirmation when leaving edit view after making changes without saving
## v1.2.2 (2020-11-19)
Changes:
## v1.2.2 - 46 (2020-11-19)
- Remember active group tab between screens and sessions
## v1.2.1 (2020-11-17)
Changes:
## v1.2.1 - 45 (2020-11-17)
- Fix home screen swiping triggering during vertical swipes too
## v1.2.0 (2020-11-17)
Changes:
## v1.2.0 - 44 (2020-11-17)
- Add swiping between groups on the home screen
- Fix crash with cards lacking header colour
## v1.1.0 (2020-11-11)
Changes:
## v1.1.0 - 43 (2020-11-11)
- Improved edit UI
- Removed header text colour option (now automatically generated based on brightness)
- Updated translations
## v1.0.1 (2020-11-07)
Changes:
## v1.0.1 - 42 (2020-11-07)
- Fix crash in search with no groups
## v1.0 (2020-11-06)
Changes:
## v1.0 - 41 (2020-11-06)
- Added rounded edges to card icons on main overview
- Added support for grouping entries
## v0.29 (2020-10-29)
Changes:
## v0.29 - 40 (2020-10-29)
- Rebrand to Catima
- Removed intro
@@ -250,31 +333,23 @@ Changes:
- Add favourites support
- Fix disabled auto-rotate being ignored
## v0.28 (2020-03-09)
Changes:
## v0.28 - 39 (2020-03-09)
- Fix barcode centering when exiting full screen ([#351](https://github.com/brarcher/loyalty-card-locker/pull/351))
- Allow backup export location to be selected ([#352](https://github.com/brarcher/loyalty-card-locker/pull/352))
- Update translations ([#357](https://github.com/brarcher/loyalty-card-locker/pull/357)) & ([#362](https://github.com/brarcher/loyalty-card-locker/pull/362))
## v0.27 (2020-01-26)
Changes:
## v0.27 - 38 (2020-01-26)
- Tapping on a barcode now moves it to the top of the screen ([#348](https://github.com/brarcher/loyalty-card-locker/pull/348))
- Add white space around barcodes to improve scanning in dark mode ([#328](https://github.com/brarcher/loyalty-card-locker/issues/328))
- Fix swapped import buttons. ([#346](https://github.com/brarcher/loyalty-card-locker/pull/346))
## v0.26.1 (2020-01-09)
Changes:
## v0.26.1 - 37 (2020-01-09)
- Fix issue with sharing cards without background color ([#343](https://github.com/brarcher/loyalty-card-locker/pull/343))
## v0.26 (2020-01-05)
Changes:
## v0.26 - 36 (2020-01-05)
- Add ability to search for a card ([#320](https://github.com/brarcher/loyalty-card-locker/pull/320))
- Add ability to share and receive loyalty cards ([#321](https://github.com/brarcher/loyalty-card-locker/pull/321))
@@ -291,57 +366,41 @@ Changes:
- Polish
- Russian
## v0.25.4 (2019-10-04)
Changes:
## v0.25.4 - 35 (2019-10-04)
- Enable app backups
- Update French and Slovenian translations
## v0.25.3 (2019-03-02)
Changes:
## v0.25.3 - 34 (2019-03-02)
- Update Russian translations
## v0.25.2 (2019-01-05)
Changes:
## v0.25.2 - 33 (2019-01-05)
- Update and add translations
## v0.25.1 (2018-10-14)
Changes:
## v0.25.1 - 32 (2018-10-14)
- Fix creating new card by manually entering barcode ([issue #272](https://github.com/brarcher/loyalty-card-locker/issues/272))
## v0.25 (2018-10-07)
Changes:
## v0.25 - 31 (2018-10-07)
- Sort card list case insensitive ([pull #266](https://github.com/brarcher/loyalty-card-locker/pull/266))
- Add setting to lock orientation for all cards ([pull #269](https://github.com/brarcher/loyalty-card-locker/pull/269)
## v0.24 (2018-07-31)
Changes:
## v0.24 - 30 (2018-07-31)
- Add a setting to control screen brightness when displaying a barcode ([pull #259](https://github.com/brarcher/loyalty-card-locker/pull/259))
- Add Greek translations ([pull #252](https://github.com/brarcher/loyalty-card-locker/pull/252))
- Add Slovenian translations ([pull #260](https://github.com/brarcher/loyalty-card-locker/pull/260))
- Update translations ([pull #260](https://github.com/brarcher/loyalty-card-locker/pull/260), [pull #254](https://github.com/brarcher/loyalty-card-locker/pull/254))
## v0.23.4 (2018-05-12)
Changes:
## v0.23.4 - 29 (2018-05-12)
- Fix Spanish translations ([pull #244](https://github.com/brarcher/loyalty-card-locker/pull/244))
- Update translations ([pull #244](https://github.com/brarcher/loyalty-card-locker/pull/244))
## v0.23.3 (2018-05-05)
Changes:
## v0.23.3 - 28 (2018-05-05)
- Added translations
- Polish ([pull #232](https://github.com/brarcher/loyalty-card-locker/pull/232))
@@ -349,87 +408,63 @@ Changes:
- Slovak ([pull #232](https://github.com/brarcher/loyalty-card-locker/pull/232))
- Updated translations ([pull #239](https://github.com/brarcher/loyalty-card-locker/pull/239))
## v0.23.2 (2018-03-11)
Changes:
## v0.23.2 - 27 (2018-03-11)
- Reduce min SDK from 17 to 15. ([pull #226](https://github.com/brarcher/loyalty-card-locker/pull/226))
- Remove usage of legacy apache library, used only in unit tests but no longer needed. ([pull #225](https://github.com/brarcher/loyalty-card-locker/pull/225))
## v0.23.1 (2018-03-07)
Changes:
## v0.23.1 - 26 (2018-03-07)
- Prevent crash when rendering a barcode exhausts the application's memory. ([pull #219](https://github.com/brarcher/loyalty-card-locker/pull/219))
## v0.23 (2018-02-28)
Changes:
## v0.23 - 25 (2018-02-28)
- Reduce space in header when viewing a card. ([pull #213](https://github.com/brarcher/loyalty-card-locker/pull/213))
- Disable beep when scanning a barcode. ([pull #216](https://github.com/brarcher/loyalty-card-locker/pull/216))
## v0.22 (2018-02-19)
Changes:
## v0.22 - 24 (2018-02-19)
- Update translations. ([pull #208](https://github.com/brarcher/loyalty-card-locker/pull/208))
- Barcode rendering updates: ([pull #209](https://github.com/brarcher/loyalty-card-locker/pull/209))
- Reload card view activity when screen is rotated, so barcode image is correct size.
- Render 1D barcodes in a larger space, allowing them to better fill the screen.
## v0.21 (2018-02-17)
Changes:
## v0.21 - 23 (2018-02-17)
- Add quiet space at the start/end of barcodes. ([pull #200](https://github.com/brarcher/loyalty-card-locker/pull/200))
- Add options to configure the colors used for the store name font and background. ([pull #203](https://github.com/brarcher/loyalty-card-locker/pull/203))
- Add options to adjust font sizes on the card listing page and single card page. ([pull #204](https://github.com/brarcher/loyalty-card-locker/pull/204))
## v0.20 (2018-02-10)
Changes:
## v0.20 - 22 (2018-02-10)
- Changes to Card view to display the note, allow the card ID to take multiple lines, and show the store name. ([pull #197](https://github.com/brarcher/loyalty-card-locker/pull/197))
## v0.19 (2018-02-01)
Changes:
## v0.19 - 21 (2018-02-01)
- Improved layout for card list. ([pull #188](https://github.com/brarcher/loyalty-card-locker/pull/188))
- Improved layout when viewing a card. ([pull #190](https://github.com/brarcher/loyalty-card-locker/pull/190))
## v0.18.1 (2018-01-24)
Changes:
## v0.18.1 - 20 (2018-01-24)
- Workaround crash during install on some Android versions (likely Android 5 and below). ([pull #184](https://github.com/brarcher/loyalty-card-locker/pull/184))
## v0.18 (2018-01-19)
Changes:
## v0.18 - 19 (2018-01-19)
- Fix crash when importing certain types of corrupted CSV files. ([pull #177](https://github.com/brarcher/loyalty-card-locker/pull/177))
- Fix importing backups directly from the file system. ([pull #180](https://github.com/brarcher/loyalty-card-locker/pull/180))
- Fix importing backups from certain types of content providers. ([pull #179](https://github.com/brarcher/loyalty-card-locker/pull/179))
## v0.17 (2018-01-11)
Changes:
## v0.17 - 18 (2018-01-11)
- Fix issue on Android SDK 24+ where using the file chooser import option would cause a crash. ([pull #170](https://github.com/brarcher/loyalty-card-locker/pull/170))
- New icon and color scheme. ([pull #171](https://github.com/brarcher/loyalty-card-locker/pull/171))
## v0.16 (2017-11-29)
Changes:
## v0.16 - 17 (2017-11-29)
- Add support for adding loyalty card shortcuts from the launcher/homescreen. ([pull #161](https://github.com/brarcher/loyalty-card-locker/pull/161))
- Remove support for adding loyalty card shortcuts from the app itself. This removes the need for the shortcut permission. ([pull #163](https://github.com/brarcher/loyalty-card-locker/pull/163))
## v0.15 (2017-11-25)
Changes:
## v0.15 - 16 (2017-11-25)
- Add support for adding shortcuts to home screen when adding or editing a card. ([pull #155](https://github.com/brarcher/loyalty-card-locker/pull/155))
- Remove widget, as it was a poor substitute for shortcuts. ([pull #155](https://github.com/brarcher/loyalty-card-locker/pull/155))
@@ -437,37 +472,27 @@ Changes:
- Report more accurate mime type when exporting backup data. ([pull #156](https://github.com/brarcher/loyalty-card-locker/pull/156))
- Fix bug where a card could not be edited. ([pull #155](https://github.com/brarcher/loyalty-card-locker/pull/155))
## v0.14 (2017-10-26)
Changes:
## v0.14 - 15 (2017-10-26)
- Add support for app shortcuts (Android 7.1+), where the most recently used cards will appear as shortcuts. ([pull #145](https://github.com/brarcher/loyalty-card-locker/pull/145))
- Add a widget which works like a pinned app shortcut, to support devices which run below Android 7.1. ([pull #142](https://github.com/brarcher/loyalty-card-locker/pull/142))
## v0.13 (2017-07-25)
Changes:
## v0.13 - 14 (2017-07-25)
- Add screen rotation lock menu option when displaying a card. If locked, the screen will transition to its "natural" orientation and further screen rotation will be blocked. ([pull #128](https://github.com/brarcher/loyalty-card-locker/pull/128))
- If a card is selected from the main screen but cannot be loaded, the application fails gracefully and posts a message. ([pull #132](https://github.com/brarcher/loyalty-card-locker/pull/132))
- Fix case where layout IDs for intro wizard could not be found. ([pull #128](https://github.com/brarcher/loyalty-card-locker/pull/128))
## v0.12 (2017-07-16)
Changes:
## v0.12 - 13 (2017-07-16)
- A change in v0.11 reduced the memory usage of barcode drawing, but affected the barcode dimensions. This is now changed to maintain the barcode dimensions while reducing memory usage. ([pull #126](https://github.com/brarcher/loyalty-card-locker/pull/126))
- Update German and French translations. ([pull #122](https://github.com/brarcher/loyalty-card-locker/pull/122), [pull #124](https://github.com/brarcher/loyalty-card-locker/pull/124), [pull #125](https://github.com/brarcher/loyalty-card-locker/pull/125))
## v0.11.1 (2017-06-29)
Changes:
## v0.11.1 - 12 (2017-06-29)
- Prevent a crash when rotation the screen in the first run intro wizard.
## v0.11 (2017-06-26)
Improvements:
## v0.11 - 11 (2017-06-26)
- When editing a card ID, pre-populate the existing ID to start. ([pull #94](https://github.com/brarcher/loyalty-card-locker/pull/94))
- Limit the width of generated barcodes to reduce memory usage and out of memory errors. ([pull #103](https://github.com/brarcher/loyalty-card-locker/pull/103))
@@ -475,15 +500,13 @@ Improvements:
- Change the color scheme to be softer and compatible with the app icon, and change the layout when viewing a card to be cleaner. ([pull #107](https://github.com/brarcher/loyalty-card-locker/pull/107))
- Add an intro wizard which launches on the app's first launch. ([pull #108](https://github.com/brarcher/loyalty-card-locker/pull/108))
## v0.10 (2017-02-12)
Improvements:
## v0.10 - 10 (2017-02-12)
- Changed the default import/export filename. ([pull #84](https://github.com/brarcher/loyalty-card-locker/pull/84))
- Correct string on the import/export page. ([pull #87](https://github.com/brarcher/loyalty-card-locker/pull/87))
- Improve layout of card view page. The text should be easier to read, and is selectable with a long click. ([pull #91](https://github.com/brarcher/loyalty-card-locker/pull/91))
## v0.9 (2017-01-17)
## v0.9 - 9 (2017-01-17)
The "Locker" part of the name was not intuitive. To help remedy this a new application icon was created by betsythefc which better represents the purpose of the application: to store loyalty cards which use barcodes. Along with this new icon the name of the application has been changed to "Loyalty Card Keychain".
@@ -493,55 +516,36 @@ Additional features/improvements:
- Translations for Lithuanian added. ([pull #62](https://github.com/brarcher/loyalty-card-locker/pull/62))
- Translations for French added. ([pull #80](https://github.com/brarcher/loyalty-card-locker/pull/80))
## v0.8 (2016-11-22)
New features/improvements:
## v0.8 - 8 (2016-11-22)
- Screen brightness increased to its maximum when displaying a card, to help barcode scanners successfully capture the barcode. ([pull #54](https://github.com/brarcher/loyalty-card-locker/pull/54))
- Add a delete confirmation when deleting a card. ([pull #55](https://github.com/brarcher/loyalty-card-locker/pull/55))
- Add translations for German ([pull #57](https://github.com/brarcher/loyalty-card-locker/pull/57)) and Czech ([pull #58](https://github.com/brarcher/loyalty-card-locker/pull/58)).
- Clarification change for Italian translation. ([pull #66](https://github.com/brarcher/loyalty-card-locker/pull/66))
## v0.7 (2016-07-14)
New 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))
Bug fixes:
- Back button on Input/Export view now works, moving user to main view
## v0.6 (2016-05-23)
New features/improvements:
## v0.6 - 6 (2016-05-23)
- Allow user to enter barcode manually. If a user elects to enter a barcode manually, a list of all valid and supported barcode images is displayed. The user then may select the barcode image which matches what the user wants. [issue #33](https://github.com/brarcher/loyalty-card-locker/issues/33), [pull #44](https://github.com/brarcher/loyalty-card-locker/pull/44)
Bug fixes:
- Resolve issue where some displayed barcodes were blurry. ([issue #37](https://github.com/brarcher/loyalty-card-locker/issues/37))
## v0.5 (2016-05-16)
New features/improvements:
## v0.5 - 5 (2016-05-16)
- An about dialog can be opened from the main screen, which gives details about the application and project on GitHub ([issue #19](https://github.com/brarcher/loyalty-card-locker/issues/19))
- Allow loyalty card information to be imported from/exported to a CSV file in external storage ([issue #36](https://github.com/brarcher/loyalty-card-locker/issues/36), [issue #20](https://github.com/brarcher/loyalty-card-locker/issues/20))
## v0.4 (2016-04-09)
New features/improvements:
## v0.4 - 4 (2016-04-09)
- Dutch translation
- Allow name field to be editable after adding loyalty card
- Add an optional note field
Bug fixes:
- Resolve all issues identified by FindBugs and require all FindBugs issues be resolved prior to pull request acceptance
## v0.3 (2016-02-11)
## v0.3 - 3 (2016-02-11)
- Now officially supports the following list of 1D and 2D barcodes:
- AZTEC
@@ -558,13 +562,13 @@ Bug fixes:
- Generated barcodes are larger, easier to scan from a scanning device
## v0.2 (2016-02-07)
## v0.2 - 2 (2016-02-07)
- Italian translations
- Support for all 1D barcode types. (Originally only product 1D barcodes were supported)
- Add required camera permission, which was initially missing.
## v0.1 (2016-01-30)
## v0.1 - 1 (2016-01-30)
- Ability to create/edit/delete loyalty cards
- Capture barcode of loyalty card using a camera
+8 -8
View File
@@ -1,9 +1,9 @@
How to Submit Patches to the Loyalty Card Keychain Project
How to Submit Patches to the Catima Project
===============================================================================
https://github.com/brarcher/budget-watch
https://github.com/TheLastProject/Catima
This document is intended to act as a guide to help you contribute to the
Loyalty Card Keychain project. It is not perfect, and there will always be exceptions
Catima project. It is not perfect, and there will always be exceptions
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.
@@ -21,16 +21,16 @@ These are the Android lint checker, run using:
# ./gradlew lintRelease
and FindBugs, run using:
and SpotBugs, run using:
# ./gradlew findbugs
# ./gradlew spotbugsRelease
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
The Loyalty Card Keychain code uses a fair number of unit tests to verify that
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.
@@ -85,7 +85,7 @@ your real name, saying:
## 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 Loyalty Card Keychain repository. The preferred
way to do this is to submit a Pull Request to the Loyalty Card Keychain project.
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
unit tests and produce no errors during static analysis.
+3
View File
@@ -0,0 +1,3 @@
github: TheLastProject
custom:
- "https://paypal.me/sylviavanos"
+94 -61
View File
@@ -1,58 +1,75 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.2)
CFPropertyList (3.0.3)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.1.0)
aws-partitions (1.388.0)
aws-sdk-core (3.109.1)
aws-eventstream (1.2.0)
aws-partitions (1.501.0)
aws-sdk-core (3.121.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.39.0)
aws-sdk-core (~> 3, >= 3.109.0)
aws-sdk-kms (1.48.0)
aws-sdk-core (~> 3, >= 3.120.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.83.1)
aws-sdk-core (~> 3, >= 3.109.0)
aws-sdk-s3 (1.102.0)
aws-sdk-core (~> 3, >= 3.120.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.2)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.4.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.0.3)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
commander (4.6.0)
highline (~> 2.0.0)
declarative (0.0.20)
declarative-option (0.1.0)
digest-crc (0.6.1)
rake (~> 13.0)
digest-crc (0.6.4)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
emoji_regex (3.2.0)
excon (0.78.0)
faraday (1.1.0)
emoji_regex (3.2.2)
excon (0.85.0)
faraday (1.7.2)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday_middleware (1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday_middleware (1.1.0)
faraday (~> 1.0)
fastimage (2.2.0)
fastlane (2.165.0)
fastimage (2.2.5)
fastlane (2.193.1)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
@@ -61,18 +78,20 @@ GEM
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.37.0, < 0.39.0)
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
naturally (~> 2.2)
optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
@@ -82,73 +101,85 @@ GEM
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
google-api-client (0.38.0)
google-apis-androidpublisher_v3 (0.11.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-core (0.4.1)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.12)
google-cloud-core (1.5.0)
retriable (>= 2.0, < 4.a)
rexml
webrick
google-apis-iamcredentials_v1 (0.7.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-playcustomapp_v1 (0.5.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-storage_v1 (0.6.0)
google-apis-core (>= 0.4, < 2.a)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.4.0)
google-cloud-env (1.5.0)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.1)
google-cloud-storage (1.29.1)
google-cloud-errors (1.1.0)
google-cloud-storage (1.34.1)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-api-client (~> 0.33)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (0.14.0)
googleauth (0.17.1)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.14)
highline (1.7.10)
http-cookie (1.0.3)
signet (~> 0.15)
highline (2.0.3)
http-cookie (1.0.4)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.4.0)
json (2.3.1)
jwt (2.2.2)
json (2.5.1)
jwt (2.2.3)
memoist (0.16.2)
mini_magick (4.10.1)
mini_mime (1.0.2)
mini_magick (4.11.0)
mini_mime (1.1.1)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
naturally (2.2.0)
naturally (2.2.1)
optparse (0.1.1)
os (1.1.1)
plist (3.5.0)
plist (3.6.0)
public_suffix (4.0.6)
rake (13.0.1)
representable (3.0.4)
rake (13.0.6)
representable (3.1.1)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.5)
rouge (2.0.7)
ruby2_keywords (0.0.2)
rubyzip (2.3.0)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.3)
signet (0.14.0)
addressable (~> 2.3)
signet (0.16.0)
addressable (~> 2.8)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
trailblazer-option (0.1.1)
tty-cursor (0.7.1)
tty-screen (0.8.1)
tty-spinner (0.9.3)
@@ -156,18 +187,20 @@ GEM
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unf_ext (0.0.8)
unicode-display_width (1.7.0)
webrick (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.19.0)
xcodeproj (1.21.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.0)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
+36 -22
View File
@@ -11,17 +11,18 @@ spotbugs {
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
compileSdkVersion 31
buildToolsVersion "31.0.0"
defaultConfig {
applicationId "me.hackerchick.catima"
minSdkVersion 19
targetSdkVersion 30
versionCode 74
versionName "2.0.4"
minSdkVersion 21
targetSdkVersion 31
versionCode 100
versionName "2.14.1"
vectorDrawables.useSupportLibrary true
multiDexEnabled true
}
buildTypes {
@@ -36,10 +37,20 @@ android {
}
}
bundle {
language {
enableSplit = false
}
}
compileOptions {
encoding "UTF-8"
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
lintOptions {
@@ -69,22 +80,25 @@ android {
dependencies {
// AndroidX
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'androidx.palette:palette:1.0.0'
implementation 'androidx.preference:preference:1.2.0'
implementation 'com.google.android.material:material:1.5.0'
implementation 'com.github.yalantis:ucrop:2.2.8'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
// Splash Screen
implementation 'androidx.core:core-splashscreen:1.0.0-beta01'
// Third-party
implementation 'com.journeyapps:zxing-android-embedded:4.1.0@aar'
// Do not upgrade past 3.3.3! Causes a crash on versions before Android Nougat
//noinspection GradleDependency
implementation 'com.google.zxing:core:3.3.3'
implementation 'org.apache.commons:commons-csv:1.8'
implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
implementation 'com.google.zxing:core:3.4.1'
implementation 'org.apache.commons:commons-csv:1.9.0'
implementation 'com.jaredrummler:colorpicker:1.1.0'
implementation 'com.google.guava:guava:30.1.1-jre'
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.2'
implementation 'net.lingala.zip4j:zip4j:2.8.0'
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.4'
implementation 'net.lingala.zip4j:zip4j:2.9.1'
// SpotBugs
implementation 'io.wcm.tooling.spotbugs:io.wcm.tooling.spotbugs.annotations:1.0.0'
@@ -92,7 +106,7 @@ dependencies {
// Testing
testImplementation 'androidx.test:core:1.4.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.4'
testImplementation 'org.robolectric:robolectric:4.7.3'
}
tasks.withType(SpotBugsTask) {
+67 -38
View File
@@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="protect.card_locker"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="protect.card_locker">
<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-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-feature
android:name="android.hardware.camera"
@@ -17,8 +16,6 @@
android:name="android.hardware.camera.autofocus"
android:required="false" />
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
<application
android:name=".LoyaltyCardLockerApplication"
android:allowBackup="true"
@@ -27,47 +24,64 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="protect.card_locker.MainActivity"
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
android:theme="@style/Theme.App.Starting">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AboutActivity"
android:label="@string/about"
android:theme="@style/AppTheme.NoActionBar">
</activity>
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ManageGroupsActivity"
android:label="@string/groups"
android:theme="@style/AppTheme.NoActionBar">
</activity>
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ManageGroupActivity"
android:label="@string/group_edit"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".LoyaltyCardViewActivity"
android:exported="true"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="stateHidden"
android:exported="true"/>
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".LoyaltyCardEditActivity"
android:exported="true"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="stateHidden"
android:exported="true">
<intent-filter android:label="@string/app_name">
android:windowSoftInputMode="stateHidden">
<intent-filter
android:autoVerify="true"
android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Listen to known card sharing URIs -->
<data android:scheme="https"
<!-- Main card sharing URIs -->
<data android:scheme="http" />
<data android:scheme="https" />
<data
android:host="@string/intent_import_card_from_url_host_catima_app"
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_catima_app" />
<data android:scheme="https"
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Old card sharing URIs -->
<data android:scheme="http" />
<data android:scheme="https" />
<data
android:host="@string/intent_import_card_from_url_host_thelastproject"
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_thelastproject" />
<data android:scheme="https"
<data
android:host="@string/intent_import_card_from_url_host_brarcher"
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_brarcher" />
</intent-filter>
@@ -75,37 +89,52 @@
<activity
android:name=".ScanActivity"
android:label="@string/scanCardBarcode"
android:theme="@style/AppTheme.NoActionBar"/>
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".BarcodeSelectorActivity"
android:label="@string/selectBarcodeTitle"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="stateHidden"/>
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".preferences.SettingsActivity"
android:label="@string/settings"/>
android:label="@string/settings"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ImportExportActivity"
android:label="@string/importExport"
android:theme="@style/AppTheme.NoActionBar"/>
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".CardShortcutConfigure"
android:exported="true"
android:label="@string/cardShortcut"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:theme="@style/AppTheme.NoActionBar" />
<provider
android:name="androidx.core.content.FileProvider"
android:grantUriPermissions="true"
android:authorities="${applicationId}"
android:exported="false"
android:authorities="${applicationId}">
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths"/>
android:resource="@xml/file_provider_paths" />
</provider>
<service android:name=".CardsOnPowerScreenService" android:label="@string/app_name"
android:permission="android.permission.BIND_CONTROLS" android:exported="true">
<intent-filter>
<action android:name="android.service.controls.ControlsProviderService" />
</intent-filter>
</service>
</application>
</manifest>
</manifest>
@@ -1,43 +1,67 @@
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.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
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.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.text.HtmlCompat;
public class AboutActivity extends AppCompatActivity
{
public class AboutActivity extends CatimaAppCompatActivity implements View.OnClickListener {
private static final String TAG = "Catima";
ConstraintLayout version_history, translate, license, repo, privacy, error, credits, rate;
@Override
protected void onCreate(Bundle savedInstanceState)
{
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)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
StringBuilder contributors = new StringBuilder().append("<br/>");
BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.contributors), StandardCharsets.UTF_8));
try {
while (true) {
String tmp = reader.readLine();
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("Guava", "https://github.com/google/guava", "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"));
@@ -47,62 +71,102 @@ public class AboutActivity extends AppCompatActivity
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(")<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(")<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
{
try {
PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0);
version = pi.versionName;
}
catch (PackageManager.NameNotFoundException e)
{
} 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));
TextView aboutTextView = findViewById(R.id.aboutText);
aboutTextView.setText(HtmlCompat.fromHtml(String.format(getString(R.string.debug_version_fmt), version) +
"<br/><br/>" +
String.format(getString(R.string.app_revision_fmt),
"<a href=\"" + getString(R.string.app_revision_url) + "\">" +
"GitHub" +
"</a>") +
"<br/><br/>" +
String.format(getString(R.string.app_copyright_fmt), year) +
"<br/><br/>" +
getString(R.string.app_copyright_old) +
"<br/><br/>" +
getString(R.string.app_license) +
"<br/><br/>" +
String.format(getString(R.string.app_libraries), libs.toString()) +
"<br/><br/>" +
String.format(getString(R.string.app_resources), resources.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
aboutTextView.setMovementMethod(LinkMovementMethod.getInstance());
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());
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
@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);
}
}
@@ -1,31 +1,32 @@
package protect.card_locker;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import java.lang.ref.WeakReference;
import protect.card_locker.async.CompatCallable;
/**
* This task will generate a barcode and load it into an ImageView.
* Only a weak reference of the ImageView is kept, so this class will not
* prevent the ImageView from being garbage collected.
*/
class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
{
public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
private static final String TAG = "Catima";
private static final int IS_VALID = 999;
private final Context mContext;
private boolean isSuccesful;
// When drawn in a smaller window 1D barcodes for some reason end up
@@ -36,16 +37,19 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
private final WeakReference<ImageView> imageViewReference;
private final WeakReference<TextView> textViewReference;
private String cardId;
private final BarcodeFormat format;
private final CatimaBarcode format;
private final int imageHeight;
private final int imageWidth;
private final boolean showFallback;
private final Runnable callback;
BarcodeImageWriterTask(ImageView imageView, String cardIdString,
BarcodeFormat barcodeFormat, TextView textView,
boolean showFallback, Runnable callback)
{
BarcodeImageWriterTask(
Context context, ImageView imageView, String cardIdString,
CatimaBarcode barcodeFormat, TextView textView,
boolean showFallback, Runnable callback
) {
mContext = context;
isSuccesful = true;
this.callback = callback;
@@ -58,26 +62,21 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
final int MAX_WIDTH = getMaxWidth(format);
if(imageView.getWidth() < MAX_WIDTH)
{
if (imageView.getWidth() < MAX_WIDTH) {
imageHeight = imageView.getHeight();
imageWidth = imageView.getWidth();
}
else
{
} else {
// Scale down the image to reduce the memory needed to produce it
imageWidth = MAX_WIDTH;
double ratio = (double)MAX_WIDTH / (double)imageView.getWidth();
imageHeight = (int)(imageView.getHeight() * ratio);
double ratio = (double) MAX_WIDTH / (double) imageView.getWidth();
imageHeight = (int) (imageView.getHeight() * ratio);
}
this.showFallback = showFallback;
}
private int getMaxWidth(BarcodeFormat format)
{
switch(format)
{
private int getMaxWidth(CatimaBarcode format) {
switch (format.format()) {
// 2D barcodes
case AZTEC:
case DATA_MATRIX:
@@ -104,10 +103,8 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
}
}
private String getFallbackString(BarcodeFormat format)
{
switch(format)
{
private String getFallbackString(CatimaBarcode format) {
switch (format.format()) {
// 2D barcodes
case AZTEC:
return "AZTEC";
@@ -123,6 +120,8 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
return "C0C";
case CODE_39:
return "CODE_39";
case CODE_93:
return "CODE_93";
case CODE_128:
return "CODE_128";
case EAN_8:
@@ -140,23 +139,17 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
}
}
private Bitmap generate()
{
if (cardId.isEmpty())
{
private Bitmap generate() {
if (cardId.isEmpty()) {
return null;
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix bitMatrix;
try
{
try
{
bitMatrix = writer.encode(cardId, format, imageWidth, imageHeight, null);
}
catch(Exception e)
{
try {
try {
bitMatrix = writer.encode(cardId, format.format(), imageWidth, imageHeight, null);
} catch (Exception e) {
// Cast a wider net here and catch any exception, as there are some
// cases where an encoder may fail if the data is invalid for the
// barcode type. If this happens, we want to fail gracefully.
@@ -171,11 +164,9 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
int[] pixels = new int[bitMatrixWidth * bitMatrixHeight];
for (int y = 0; y < bitMatrixHeight; y++)
{
for (int y = 0; y < bitMatrixHeight; y++) {
int offset = y * bitMatrixWidth;
for (int x = 0; x < bitMatrixWidth; x++)
{
for (int x = 0; x < bitMatrixWidth; x++) {
int color = bitMatrix.get(x, y) ? BLACK : WHITE;
pixels[offset + x] = color;
}
@@ -195,19 +186,14 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
int widthScale = imageWidth / bitMatrixHeight;
int scalingFactor = Math.min(heightScale, widthScale);
if(scalingFactor > 1)
{
if (scalingFactor > 1) {
bitmap = Bitmap.createScaledBitmap(bitmap, bitMatrixWidth * scalingFactor, bitMatrixHeight * scalingFactor, false);
}
return bitmap;
}
catch (WriterException e)
{
} catch (WriterException e) {
Log.e(TAG, "Failed to generate barcode of type " + format + ": " + cardId, e);
}
catch(OutOfMemoryError e)
{
} catch (OutOfMemoryError e) {
Log.w(TAG, "Insufficient memory to render barcode, "
+ imageWidth + "x" + imageHeight + ", " + format.name()
+ ", length=" + cardId.length(), e);
@@ -216,40 +202,49 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
return null;
}
public Bitmap doInBackground(Void... params)
{
Bitmap bitmap = generate();
public Bitmap doInBackground(Void... params) {
// Only do the hard tasks if we've not already been cancelled
if (!Thread.currentThread().isInterrupted()) {
Bitmap bitmap = generate();
if (bitmap == null) {
isSuccesful = false;
if (bitmap == null) {
isSuccesful = false;
if (showFallback) {
Log.i(TAG, "Barcode generation failed, generating fallback...");
cardId = getFallbackString(format);
bitmap = generate();
if (showFallback && !Thread.currentThread().isInterrupted()) {
Log.i(TAG, "Barcode generation failed, generating fallback...");
cardId = getFallbackString(format);
bitmap = generate();
return bitmap;
}
} else {
return bitmap;
}
}
return bitmap;
// We've been interrupted - create a empty fallback
Bitmap.Config config = Bitmap.Config.ARGB_8888;
return Bitmap.createBitmap(imageWidth, imageHeight, config);
}
protected void onPostExecute(Bitmap result)
{
public void onPostExecute(Object castResult) {
Bitmap result = (Bitmap) castResult;
Log.i(TAG, "Finished generating barcode image of type " + format + ": " + cardId);
ImageView imageView = imageViewReference.get();
if(imageView == null)
{
if (imageView == null) {
// The ImageView no longer exists, nothing to do
return;
}
String formatPrettyName = format.prettyName();
imageView.setTag(isSuccesful);
imageView.setImageBitmap(result);
imageView.setContentDescription(mContext.getString(R.string.barcodeImageDescriptionWithType, formatPrettyName));
TextView textView = textViewReference.get();
if(result != null)
{
if (result != null) {
Log.i(TAG, "Displaying barcode");
imageView.setVisibility(View.VISIBLE);
@@ -261,11 +256,9 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
if (textView != null) {
textView.setVisibility(View.VISIBLE);
textView.setText(format.name());
textView.setText(formatPrettyName);
}
}
else
{
} else {
Log.i(TAG, "Barcode generation failed, removing image from display");
imageView.setVisibility(View.GONE);
if (textView != null) {
@@ -277,4 +270,19 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
callback.run();
}
}
@Override
public void onPreExecute() {
// No Action
}
/**
* Provided to comply with Callable while keeping the original Syntax of AsyncTask
*
* @return generated Bitmap
*/
@Override
public Bitmap call() {
return doInBackground();
}
}
@@ -2,31 +2,21 @@ package protect.card_locker;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.Pair;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ListView;
import android.widget.Toast;
import com.google.common.collect.ImmutableMap;
import com.google.zxing.BarcodeFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Map;
import java.util.ArrayList;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
/**
@@ -35,98 +25,59 @@ import androidx.appcompat.widget.Toolbar;
* the data. The user may then select any barcode, where its
* data and type will be returned to the caller.
*/
public class BarcodeSelectorActivity extends AppCompatActivity
{
public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements BarcodeSelectorAdapter.BarcodeSelectorListener {
private static final String TAG = "Catima";
// Result this activity will return
public static final String BARCODE_CONTENTS = "contents";
public static final String BARCODE_FORMAT = "format";
// These are all the barcode types that the zxing library
// is able to generate a barcode for, and thus should be
// the only barcodes which we should attempt to scan.
public static final Collection<String> SUPPORTED_BARCODE_TYPES = Collections.unmodifiableList(
Arrays.asList(
BarcodeFormat.AZTEC.name(),
BarcodeFormat.CODE_39.name(),
BarcodeFormat.CODE_128.name(),
BarcodeFormat.CODABAR.name(),
BarcodeFormat.DATA_MATRIX.name(),
BarcodeFormat.EAN_8.name(),
BarcodeFormat.EAN_13.name(),
BarcodeFormat.ITF.name(),
BarcodeFormat.PDF_417.name(),
BarcodeFormat.QR_CODE.name(),
BarcodeFormat.UPC_A.name(),
BarcodeFormat.UPC_E.name()
));
private final Handler typingDelayHandler = new Handler(Looper.getMainLooper());
public static final Integer INPUT_DELAY = 250;
private Map<String, Pair<Integer, Integer>> barcodeViewMap;
private LinkedList<AsyncTask> barcodeGeneratorTasks = new LinkedList<>();
private BarcodeSelectorAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.selectBarcodeTitle);
setContentView(R.layout.barcode_selector_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
barcodeViewMap = ImmutableMap.<String, Pair<Integer, Integer>>builder()
.put(BarcodeFormat.AZTEC.name(), new Pair<>(R.id.aztecBarcode, R.id.aztecBarcodeText))
.put(BarcodeFormat.CODE_39.name(), new Pair<>(R.id.code39Barcode, R.id.code39BarcodeText))
.put(BarcodeFormat.CODE_128.name(), new Pair<>(R.id.code128Barcode, R.id.code128BarcodeText))
.put(BarcodeFormat.CODABAR.name(), new Pair<>(R.id.codabarBarcode, R.id.codabarBarcodeText))
.put(BarcodeFormat.DATA_MATRIX.name(), new Pair<>(R.id.datamatrixBarcode, R.id.datamatrixBarcodeText))
.put(BarcodeFormat.EAN_8.name(), new Pair<>(R.id.ean8Barcode, R.id.ean8BarcodeText))
.put(BarcodeFormat.EAN_13.name(), new Pair<>(R.id.ean13Barcode, R.id.ean13BarcodeText))
.put(BarcodeFormat.ITF.name(), new Pair<>(R.id.itfBarcode, R.id.itfBarcodeText))
.put(BarcodeFormat.PDF_417.name(), new Pair<>(R.id.pdf417Barcode, R.id.pdf417BarcodeText))
.put(BarcodeFormat.QR_CODE.name(), new Pair<>(R.id.qrcodeBarcode, R.id.qrcodeBarcodeText))
.put(BarcodeFormat.UPC_A.name(), new Pair<>(R.id.upcaBarcode, R.id.upcaBarcodeText))
.put(BarcodeFormat.UPC_E.name(), new Pair<>(R.id.upceBarcode, R.id.upceBarcodeText))
.build();
EditText cardId = findViewById(R.id.cardId);
cardId.addTextChangedListener(new TextWatcher()
{
ListView mBarcodeList = findViewById(R.id.barcodes);
mAdapter = new BarcodeSelectorAdapter(this, new ArrayList<>(), this);
mBarcodeList.setAdapter(mAdapter);
cardId.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
// Noting to do
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Delay the input processing so we avoid overload
typingDelayHandler.removeCallbacksAndMessages(null);
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
Log.d(TAG, "Entered text: " + s);
typingDelayHandler.postDelayed(() -> {
Log.d(TAG, "Entered text: " + s);
generateBarcodes(s.toString());
runOnUiThread(() -> {
generateBarcodes(s.toString());
View noBarcodeButtonView = findViewById(R.id.noBarcode);
setButtonListener(noBarcodeButtonView, s.toString());
noBarcodeButtonView.setEnabled(s.length() > 0);
}
@Override
public void afterTextChanged(Editable s)
{
// Noting to do
View noBarcodeButtonView = findViewById(R.id.noBarcode);
setButtonListener(noBarcodeButtonView, s.toString());
noBarcodeButtonView.setEnabled(s.length() > 0);
});
}, INPUT_DELAY);
}
});
final Bundle b = getIntent().getExtras();
final String initialCardId = b != null ? b.getString("initialCardId") : null;
if(initialCardId != null)
{
if (initialCardId != null) {
cardId.setText(initialCardId);
} else {
generateBarcodes("");
@@ -134,101 +85,29 @@ public class BarcodeSelectorActivity extends AppCompatActivity
}
private void generateBarcodes(String value) {
// Stop any async tasks which may not have been started yet
for(AsyncTask task : barcodeGeneratorTasks)
{
task.cancel(false);
}
barcodeGeneratorTasks.clear();
// Update barcodes
for(Map.Entry<String, Pair<Integer, Integer>> entry : barcodeViewMap.entrySet())
{
ImageView image = findViewById(entry.getValue().first);
TextView text = findViewById(entry.getValue().second);
createBarcodeOption(image, entry.getKey(), value, text);
ArrayList<CatimaBarcodeWithValue> barcodes = new ArrayList<>();
for (BarcodeFormat barcodeFormat : CatimaBarcode.barcodeFormats) {
CatimaBarcode catimaBarcode = CatimaBarcode.fromBarcode(barcodeFormat);
barcodes.add(new CatimaBarcodeWithValue(catimaBarcode, value));
}
mAdapter.setBarcodes(barcodes);
}
private void setButtonListener(final View button, final String cardId)
{
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View 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();
}
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();
});
}
private void createBarcodeOption(final ImageView image, final String formatType, final String cardId, final TextView text)
{
final BarcodeFormat format = BarcodeFormat.valueOf(formatType);
if(format == null)
{
Log.w(TAG, "Unsupported barcode format: " + formatType);
return;
}
image.setImageBitmap(null);
image.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Log.d(TAG, "Selected barcode type " + formatType);
if (!((boolean) image.getTag())) {
Toast.makeText(BarcodeSelectorActivity.this, getString(R.string.wrongValueForBarcodeType), Toast.LENGTH_LONG).show();
return;
}
Intent result = new Intent();
result.putExtra(BARCODE_FORMAT, formatType);
result.putExtra(BARCODE_CONTENTS, cardId);
BarcodeSelectorActivity.this.setResult(RESULT_OK, result);
finish();
}
});
if(image.getHeight() == 0)
{
// The size of the ImageView is not yet available as it has not
// yet been drawn. Wait for it to be drawn so the size is available.
image.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
Log.d(TAG, "Global layout finished, type: + " + formatType + ", width: " + image.getWidth());
image.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Log.d(TAG, "Generating barcode for type " + formatType);
BarcodeImageWriterTask task = new BarcodeImageWriterTask(image, cardId, format, text, true, null);
barcodeGeneratorTasks.add(task);
task.execute();
}
});
}
else
{
Log.d(TAG, "Generating barcode for type " + formatType);
BarcodeImageWriterTask task = new BarcodeImageWriterTask(image, cardId, format, text, true, null);
barcodeGeneratorTasks.add(task);
task.execute();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
if (item.getItemId() == android.R.id.home)
{
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
setResult(Activity.RESULT_CANCELED);
finish();
return true;
@@ -236,4 +115,26 @@ public class BarcodeSelectorActivity extends AppCompatActivity
return super.onOptionsItemSelected(item);
}
@Override
public void onRowClicked(int inputPosition, View view) {
CatimaBarcodeWithValue barcodeWithValue = mAdapter.getItem(inputPosition);
CatimaBarcode catimaBarcode = barcodeWithValue.catimaBarcode();
if (!mAdapter.isValid(view)) {
Toast.makeText(this, getString(R.string.wrongValueForBarcodeType), Toast.LENGTH_LONG).show();
return;
}
String barcodeFormat = catimaBarcode.format().name();
String value = barcodeWithValue.value();
Log.d(TAG, "Selected barcode type " + barcodeFormat);
Intent result = new Intent();
result.putExtra(BARCODE_FORMAT, barcodeFormat);
result.putExtra(BARCODE_CONTENTS, value);
BarcodeSelectorActivity.this.setResult(RESULT_OK, result);
finish();
}
}
@@ -0,0 +1,102 @@
package protect.card_locker;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import protect.card_locker.async.TaskHandler;
public class BarcodeSelectorAdapter extends ArrayAdapter<CatimaBarcodeWithValue> {
private static final String TAG = "Catima";
private final TaskHandler mTasks = new TaskHandler();
private final BarcodeSelectorListener mListener;
private static class ViewHolder {
ImageView image;
TextView text;
}
public interface BarcodeSelectorListener {
void onRowClicked(int inputPosition, View view);
}
public BarcodeSelectorAdapter(Context context, ArrayList<CatimaBarcodeWithValue> barcodes, BarcodeSelectorListener barcodeSelectorListener) {
super(context, 0, barcodes);
mListener = barcodeSelectorListener;
}
public void setBarcodes(ArrayList<CatimaBarcodeWithValue> barcodes) {
clear();
addAll(barcodes);
notifyDataSetChanged();
mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
CatimaBarcodeWithValue catimaBarcodeWithValue = getItem(position);
CatimaBarcode catimaBarcode = catimaBarcodeWithValue.catimaBarcode();
String value = catimaBarcodeWithValue.value();
ViewHolder viewHolder;
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);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
createBarcodeOption(viewHolder.image, catimaBarcode.format().name(), value, viewHolder.text);
View finalConvertView = convertView;
convertView.setOnClickListener(view -> mListener.onRowClicked(position, finalConvertView));
return convertView;
}
public boolean isValid(View view) {
ViewHolder viewHolder = (ViewHolder) view.getTag();
return viewHolder.image.getTag() != null && (boolean) viewHolder.image.getTag();
}
private void createBarcodeOption(final ImageView image, final String formatType, final String cardId, final TextView text) {
final CatimaBarcode format = CatimaBarcode.fromName(formatType);
image.setImageBitmap(null);
if (image.getHeight() == 0) {
// The size of the ImageView is not yet available as it has not
// yet been drawn. Wait for it to be drawn so the size is available.
image.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Log.d(TAG, "Global layout finished, type: + " + formatType + ", width: " + image.getWidth());
image.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Log.d(TAG, "Generating barcode for type " + formatType);
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getContext(), image, cardId, format, text, true, null);
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
}
});
} else {
Log.d(TAG, "Generating barcode for type " + formatType);
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getContext(), image, cardId, format, text, true, null);
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
}
}
}
@@ -4,30 +4,30 @@ import android.database.Cursor;
import androidx.recyclerview.widget.RecyclerView;
public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V>
{
private Cursor mCursor;
public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V> {
public Cursor mCursor;
private boolean mDataValid;
private int mRowIDColumn;
public BaseCursorAdapter(Cursor inputCursor)
{
private String mRowIDColumnName;
public BaseCursorAdapter(Cursor inputCursor, String rowIDColumnName) {
setHasStableIds(true);
mRowIDColumnName = rowIDColumnName;
swapCursor(inputCursor);
}
public abstract void onBindViewHolder(V inputHolder, Cursor inputCursor);
@Override
public void onBindViewHolder(V inputHolder, int inputPosition)
{
if (!mDataValid)
{
public void onBindViewHolder(V inputHolder, int inputPosition) {
if (!mDataValid) {
throw new IllegalStateException("Cannot bind view holder when cursor is in invalid state.");
}
if (!mCursor.moveToPosition(inputPosition))
{
if (!mCursor.moveToPosition(inputPosition)) {
throw new IllegalStateException("Could not move cursor to position " + inputPosition + " when trying to bind view holder");
}
@@ -35,49 +35,38 @@ public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> exten
}
@Override
public int getItemCount()
{
if (mDataValid)
{
public int getItemCount() {
if (mDataValid) {
return mCursor.getCount();
}
else
{
} else {
return 0;
}
}
@Override
public long getItemId(int inputPosition)
{
if (!mDataValid)
{
public long getItemId(int inputPosition) {
if (!mDataValid) {
throw new IllegalStateException("Cannot lookup item id when cursor is in invalid state.");
}
if (!mCursor.moveToPosition(inputPosition))
{
if (!mCursor.moveToPosition(inputPosition)) {
throw new IllegalStateException("Could not move cursor to position " + inputPosition + " when trying to get an item id");
}
return mCursor.getLong(mRowIDColumn);
}
public void swapCursor(Cursor inputCursor)
{
if (inputCursor == mCursor)
{
public void swapCursor(Cursor inputCursor) {
if (inputCursor == mCursor) {
return;
}
if (inputCursor != null)
{
if (inputCursor != null) {
mCursor = inputCursor;
mRowIDColumn = mCursor.getColumnIndex(mRowIDColumnName);
mDataValid = true;
notifyDataSetChanged();
}
else
{
} else {
notifyItemRangeRemoved(0, getItemCount());
mCursor = null;
mRowIDColumn = -1;
@@ -1,99 +1,70 @@
package protect.card_locker;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
* The configuration screen for creating a shortcut.
*/
public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener
{
public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener {
static final String TAG = "Catima";
final DBHelper mDb = new DBHelper(this);
private SQLiteDatabase mDatabase;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
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.main_activity);
setContentView(R.layout.simple_toolbar_list_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setVisibility(View.GONE);
// Hide new button because it won't work here anyway
FloatingActionButton newFab = findViewById(R.id.fabAdd);
newFab.setVisibility(View.GONE);
final DBHelper db = new DBHelper(this);
toolbar.setTitle(R.string.shortcutSelectCard);
// If there are no cards, bail
if (db.getLoyaltyCardCount() == 0) {
if (DBHelper.getLoyaltyCardCount(mDatabase) == 0) {
Toast.makeText(this, R.string.noCardsMessage, Toast.LENGTH_LONG).show();
finish();
}
final RecyclerView cardList = findViewById(R.id.list);
GridLayoutManager layoutManager = (GridLayoutManager) cardList.getLayoutManager();
if (layoutManager != null) {
layoutManager.setSpanCount(getResources().getInteger(R.integer.main_view_card_columns));
}
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
cardList.setLayoutManager(mLayoutManager);
cardList.setItemAnimator(new DefaultItemAnimator());
cardList.setVisibility(View.VISIBLE);
Cursor cardCursor = db.getLoyaltyCardCursor();
Cursor cardCursor = DBHelper.getLoyaltyCardCursor(mDatabase);
final LoyaltyCardCursorAdapter adapter = new LoyaltyCardCursorAdapter(this, cardCursor, this);
cardList.setAdapter(adapter);
}
private void onClickAction(int position) {
Cursor selected = mDb.getLoyaltyCardCursor();
Cursor selected = DBHelper.getLoyaltyCardCursor(mDatabase);
selected.moveToPosition(position);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
Log.d(TAG, "Creating shortcut for card " + loyaltyCard.store + "," + loyaltyCard.id);
Intent shortcutIntent = new Intent(CardShortcutConfigure.this, LoyaltyCardViewActivity.class);
shortcutIntent.setAction(Intent.ACTION_MAIN);
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle bundle = new Bundle();
bundle.putInt("id", loyaltyCard.id);
bundle.putBoolean("view", true);
shortcutIntent.putExtras(bundle);
ShortcutInfoCompat shortcut = ShortcutHelper.createShortcutBuilder(CardShortcutConfigure.this, loyaltyCard).build();
Bitmap iconBitmap = Utils.generateIcon(CardShortcutConfigure.this, loyaltyCard, true).getLetterTile();
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, loyaltyCard.store);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, iconBitmap);
setResult(RESULT_OK, intent);
setResult(RESULT_OK, ShortcutManagerCompat.createShortcutResultIntent(CardShortcutConfigure.this, shortcut));
finish();
}
@Override
public void onIconClicked(int inputPosition) {
onClickAction(inputPosition);
}
@Override
public void onRowClicked(int inputPosition) {
@@ -0,0 +1,167 @@
package protect.card_locker;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.service.controls.Control;
import android.service.controls.ControlsProviderService;
import android.service.controls.DeviceTypes;
import android.service.controls.actions.ControlAction;
import android.service.controls.templates.StatelessTemplate;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import java.util.List;
import java.util.concurrent.Flow;
import java.util.function.Consumer;
@RequiresApi(Build.VERSION_CODES.R)
public class CardsOnPowerScreenService extends ControlsProviderService {
public static final String PREFIX = "catima-";
static final String TAG = "Catima";
private SQLiteDatabase mDatabase;
@Override
public void onCreate() {
super.onCreate();
mDatabase = new DBHelper(this).getReadableDatabase();
}
@NonNull
@Override
public Flow.Publisher<Control> createPublisherForAllAvailable() {
Cursor loyaltyCardCursor = DBHelper.getLoyaltyCardCursor(mDatabase);
return subscriber -> {
while (loyaltyCardCursor.moveToNext()) {
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(loyaltyCardCursor);
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("id", card.id);
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), card.id, openIntent, PendingIntent.FLAG_IMMUTABLE);
subscriber.onNext(
new Control.StatelessBuilder(PREFIX + card.id, pendingIntent)
.setControlId(PREFIX + card.id)
.setTitle(card.store)
.setDeviceType(DeviceTypes.TYPE_GENERIC_OPEN_CLOSE)
.setSubtitle(card.note)
.setCustomIcon(Icon.createWithBitmap(getIcon(this, card)))
.build()
);
}
subscriber.onComplete();
};
}
@NonNull
@Override
public Flow.Publisher<Control> createPublisherFor(@NonNull List<String> controlIds) {
return subscriber -> {
subscriber.onSubscribe(new NoOpSubscription());
for (String controlId : controlIds) {
Control control;
try {
Integer cardId = this.controlIdToCardId(controlId);
LoyaltyCard card = DBHelper.getLoyaltyCard(mDatabase, cardId);
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("id", card.id);
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), card.id, openIntent, PendingIntent.FLAG_IMMUTABLE);
control = new Control.StatefulBuilder(controlId, pendingIntent)
.setTitle(card.store)
.setDeviceType(DeviceTypes.TYPE_GENERIC_OPEN_CLOSE)
.setSubtitle(card.note)
.setStatus(Control.STATUS_OK)
.setControlTemplate(new StatelessTemplate(controlId))
.setCustomIcon(Icon.createWithBitmap(getIcon(this, card)))
.build();
} catch (NullPointerException ignored) {
Intent mainScreenIntent = new Intent(this, MainActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), -1, mainScreenIntent, PendingIntent.FLAG_IMMUTABLE);
control = new Control.StatefulBuilder(controlId, pendingIntent)
.setStatus(Control.STATUS_NOT_FOUND)
.build();
}
Log.d(TAG, "Dispatching widget " + controlId);
subscriber.onNext(control);
}
subscriber.onComplete();
};
}
private Bitmap getIcon(Context context, LoyaltyCard loyaltyCard) {
Bitmap cardIcon = Utils.retrieveCardImage(context, loyaltyCard.id, ImageLocationType.icon);
if (cardIcon != null) {
return cardIcon;
}
return Utils.generateIcon(this, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile();
}
private Integer controlIdToCardId(String controlId) {
if (controlId == null)
return null;
if (!controlId.startsWith(PREFIX)) {
Log.w(TAG, "Unsupported control ID format: " + controlId);
return null;
}
controlId = controlId.substring(PREFIX.length());
try {
return Integer.parseInt(controlId);
} catch (RuntimeException ex) {
Log.e(TAG, "Unsupported control ID format. Expected numeric after prefix, found: " + controlId);
return null;
}
}
@Override
public void performControlAction(@NonNull String controlId, @NonNull ControlAction action, @NonNull Consumer<Integer> consumer) {
consumer.accept(ControlAction.RESPONSE_OK);
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("id", controlIdToCardId(controlId));
startActivity(openIntent);
closePowerScreenOnAndroid11();
}
@SuppressLint({"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
// On Android 12, we don't need it, and Google will probably get angry if we ask for it
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
}
}
/**
* A no-op subscription.
* <p>
* Flow.Subscriptions are made to last during time and receive periodic updates.
* Our app does not require sending periodic updates of loyalty cards, so we are just ignoring anything in the subscription
* Also, our db is quick enough to respond that the Publisher is immediately sending and completing data.
* This facility is overkill, but if we don't call onSubscribe the service won't work
*/
private static class NoOpSubscription implements Flow.Subscription {
@Override
public void request(long l) {
}
@Override
public void cancel() {
}
}
}
@@ -0,0 +1,47 @@
package protect.card_locker;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class CatimaAppCompatActivity extends AppCompatActivity {
@Override
protected void attachBaseContext(Context base) {
// Apply chosen language
super.attachBaseContext(Utils.updateBaseContextLocale(base));
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// XXX on the splash screen activity, aka the main activity, this has to be executed after applying dynamic colors, not before
// so running this only on non main for now
if (!this.getClass().getSimpleName().equals(MainActivity.class.getSimpleName())) {
Utils.patchOledDarkTheme(this);
}
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// material 3 designer does not consider status bar colors
// XXX changing this in onCreate causes issues with the splash screen activity, so doing this here
if (Build.VERSION.SDK_INT >= 23) {
getWindow().setStatusBarColor(Color.TRANSPARENT);
getWindow().getDecorView().setSystemUiVisibility(Utils.isDarkModeEnabled(this) ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
// icons are always white back then
getWindow().setStatusBarColor(Utils.isDarkModeEnabled(this) ? Color.TRANSPARENT : Color.argb(127, 0, 0, 0));
}
// XXX android 9 and below has a nasty rendering bug if the theme was patched earlier
// the splash screen activity needs the fix regardless to solve a dynamic color api issue
if (!this.getClass().getSimpleName().equals(MainActivity.class.getSimpleName())) {
Utils.postPatchOledDarkTheme(this);
}
}
}
@@ -0,0 +1,92 @@
package protect.card_locker;
import com.google.zxing.BarcodeFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CatimaBarcode {
public static final List<BarcodeFormat> barcodeFormats = Collections.unmodifiableList(Arrays.asList(
BarcodeFormat.AZTEC,
BarcodeFormat.CODE_39,
BarcodeFormat.CODE_93,
BarcodeFormat.CODE_128,
BarcodeFormat.CODABAR,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.EAN_8,
BarcodeFormat.EAN_13,
BarcodeFormat.ITF,
BarcodeFormat.PDF_417,
BarcodeFormat.QR_CODE,
BarcodeFormat.UPC_A,
BarcodeFormat.UPC_E
));
public static final List<String> barcodePrettyNames = Collections.unmodifiableList(Arrays.asList(
"Aztec",
"Code 39",
"Code 93",
"Code 128",
"Codabar",
"Data Matrix",
"EAN 8",
"EAN 13",
"ITF",
"PDF 417",
"QR Code",
"UPC A",
"UPC E"
));
private final BarcodeFormat mBarcodeFormat;
private CatimaBarcode(BarcodeFormat barcodeFormat) {
mBarcodeFormat = barcodeFormat;
}
public static CatimaBarcode fromBarcode(BarcodeFormat barcodeFormat) {
return new CatimaBarcode(barcodeFormat);
}
public static CatimaBarcode fromName(String name) {
return new CatimaBarcode(BarcodeFormat.valueOf(name));
}
public static CatimaBarcode fromPrettyName(String prettyName) {
try {
return new CatimaBarcode(barcodeFormats.get(barcodePrettyNames.indexOf(prettyName)));
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException("No barcode type with pretty name " + prettyName + " known!");
}
}
public boolean isSupported() {
return barcodeFormats.contains(mBarcodeFormat);
}
public boolean isSquare() {
return mBarcodeFormat == BarcodeFormat.AZTEC
|| mBarcodeFormat == BarcodeFormat.DATA_MATRIX
|| mBarcodeFormat == BarcodeFormat.MAXICODE
|| mBarcodeFormat == BarcodeFormat.QR_CODE;
}
public BarcodeFormat format() {
return mBarcodeFormat;
}
public String name() {
return mBarcodeFormat.name();
}
public String prettyName() {
int index = barcodeFormats.indexOf(mBarcodeFormat);
if (index == -1 || index >= barcodePrettyNames.size()) {
return mBarcodeFormat.name();
}
return barcodePrettyNames.get(index);
}
}
@@ -0,0 +1,19 @@
package protect.card_locker;
public class CatimaBarcodeWithValue {
private final CatimaBarcode mCatimaBarcode;
private final String mValue;
public CatimaBarcodeWithValue(CatimaBarcode catimaBarcode, String value) {
mCatimaBarcode = catimaBarcode;
mValue = value;
}
public CatimaBarcode catimaBarcode() {
return mCatimaBarcode;
}
public String value() {
return mValue;
}
}
@@ -0,0 +1,25 @@
package protect.card_locker;
import android.app.Activity;
import android.content.Context;
import android.widget.Toast;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
public class CatimaCaptureManager extends CaptureManager {
private final Context mContext;
public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
super(activity, barcodeView);
mContext = activity.getApplicationContext();
}
@Override
protected void displayFrameworkBugMessageAndExit(String message) {
// We don't want to exit, as we also have a enter from card image and add manually button here
// So we show a toast instead
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
}
}
File diff suppressed because it is too large. Load diff
@@ -5,15 +5,12 @@ package protect.card_locker;
* encountered with the format of data being
* imported or exported.
*/
public class FormatException extends Exception
{
public FormatException(String message)
{
public class FormatException extends Exception {
public FormatException(String message) {
super(message);
}
public FormatException(String message, Exception rootCause)
{
public FormatException(String message, Exception rootCause) {
super(message, rootCause);
}
}
@@ -2,19 +2,39 @@ package protect.card_locker;
import android.database.Cursor;
public class Group
{
public final String _id;
import androidx.annotation.Nullable;
public Group(final String _id)
{
public class Group {
public final String _id;
public final int order;
public Group(final String _id, final int order) {
this._id = _id;
this.order = order;
}
public static Group toGroup(Cursor cursor)
{
public static Group toGroup(Cursor cursor) {
String _id = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbGroups.ID));
int order = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbGroups.ORDER));
return new Group(_id);
return new Group(_id, order);
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Group)) {
return false;
}
Group anotherGroup = (Group) obj;
return _id.equals(anotherGroup._id) && order == anotherGroup.order;
}
@Override
public int hashCode() {
String combined = _id + "_" + order;
return combined.hashCode();
}
}
@@ -2,55 +2,84 @@ package protect.card_locker;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageButton;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.Settings;
class GroupCursorAdapter extends CursorAdapter
{
Settings settings;
DBHelper db;
public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder> {
Settings mSettings;
private final Context mContext;
private final GroupAdapterListener mListener;
SQLiteDatabase mDatabase;
public GroupCursorAdapter(Context context, Cursor cursor)
{
super(context, cursor, 0);
settings = new Settings(context);
public GroupCursorAdapter(Context inputContext, Cursor inputCursor, GroupAdapterListener inputListener) {
super(inputCursor, DBHelper.LoyaltyCardDbGroups.ORDER);
setHasStableIds(true);
mSettings = new Settings(inputContext);
mContext = inputContext.getApplicationContext();
mListener = inputListener;
mDatabase = new DBHelper(inputContext).getReadableDatabase();
db = new DBHelper(context);
swapCursor(inputCursor);
}
// The newView method is used to inflate a new view and return it,
// you don't bind any data to the view at this point.
@NonNull
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
return LayoutInflater.from(context).inflate(R.layout.group_layout, parent, false);
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);
}
// The bindView method is used to bind all data to a given view
// such as setting the text on a TextView.
@Override
public void bindView(View view, Context context, Cursor cursor)
{
// Find fields to populate in inflated template
TextView nameField = view.findViewById(R.id.name);
TextView countField = view.findViewById(R.id.cardCount);
public void onBindViewHolder(GroupListItemViewHolder inputHolder, Cursor inputCursor) {
Group group = Group.toGroup(inputCursor);
// Extract properties from cursor
Group group = Group.toGroup(cursor);
inputHolder.mName.setText(group._id);
Integer groupCardCount = db.getGroupCardCount(group._id);
int groupCardCount = DBHelper.getGroupCardCount(mDatabase, group._id);
inputHolder.mCardCount.setText(mContext.getResources().getQuantityString(R.plurals.groupCardCount, groupCardCount, groupCardCount));
// Populate fields with extracted properties
nameField.setText(group._id);
inputHolder.mName.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
inputHolder.mCardCount.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
countField.setText(context.getResources().getQuantityString(R.plurals.groupCardCount, groupCardCount, groupCardCount));
applyClickEvents(inputHolder);
}
nameField.setTextSize(settings.getFontSizeMax(settings.getMediumFont()));
countField.setTextSize(settings.getFontSizeMax(settings.getSmallFont()));
private void applyClickEvents(GroupListItemViewHolder inputHolder) {
inputHolder.mMoveDown.setOnClickListener(view -> mListener.onMoveDownButtonClicked(inputHolder.itemView));
inputHolder.mMoveUp.setOnClickListener(view -> mListener.onMoveUpButtonClicked(inputHolder.itemView));
inputHolder.mEdit.setOnClickListener(view -> mListener.onEditButtonClicked(inputHolder.itemView));
inputHolder.mDelete.setOnClickListener(view -> mListener.onDeleteButtonClicked(inputHolder.itemView));
}
public interface GroupAdapterListener {
void onMoveDownButtonClicked(View view);
void onMoveUpButtonClicked(View view);
void onEditButtonClicked(View view);
void onDeleteButtonClicked(View view);
}
public static class GroupListItemViewHolder extends RecyclerView.ViewHolder {
public TextView mName, mCardCount;
public AppCompatImageButton 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);
}
}
}
@@ -0,0 +1,7 @@
package protect.card_locker;
public enum ImageLocationType {
front,
back,
icon
}
@@ -6,58 +6,63 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Toast;
import java.io.File;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
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 java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import protect.card_locker.async.TaskHandler;
import protect.card_locker.importexport.DataFormat;
import protect.card_locker.importexport.ImportExportResult;
public class ImportExportActivity extends AppCompatActivity
{
public class ImportExportActivity extends CatimaAppCompatActivity {
private static final String TAG = "Catima";
private static final int PERMISSIONS_EXTERNAL_STORAGE = 1;
private static final int CHOOSE_EXPORT_LOCATION = 2;
private static final int IMPORT = 3;
private ImportExportTask importExporter;
private String importAlertTitle;
private String importAlertMessage;
private DataFormat importDataFormat;
private String exportPassword;
private ActivityResultLauncher<Intent> fileCreateLauncher;
private ActivityResultLauncher<String> fileOpenLauncher;
private ActivityResultLauncher<Intent> filePickerLauncher;
final private TaskHandler mTasks = new TaskHandler();
@Override
protected void onCreate(Bundle savedInstanceState)
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.importExport);
setContentView(R.layout.import_export_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
@@ -66,15 +71,57 @@ public class ImportExportActivity extends AppCompatActivity
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)
{
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},
Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSIONS_EXTERNAL_STORAGE);
}
// would use ActivityResultContracts.CreateDocument() but mime type cannot be set
fileCreateLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
Intent intent = result.getData();
if (intent == null) {
Log.e(TAG, "Activity returned NULL data");
return;
}
Uri uri = intent.getData();
if (uri == null) {
Log.e(TAG, "Activity returned NULL uri");
return;
}
try {
OutputStream writer = getContentResolver().openOutputStream(uri);
Log.e(TAG, "Starting file export with: " + result.toString());
startExport(writer, uri, exportPassword.toCharArray(), true);
} catch (IOException e) {
Log.e(TAG, "Failed to export file: " + result.toString(), e);
onExportComplete(ImportExportResult.GenericFailure, uri);
}
});
fileOpenLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), result -> {
if (result == null) {
Log.e(TAG, "Activity returned NULL data");
return;
}
openFileForImport(result, null);
});
filePickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
Intent intent = result.getData();
if (intent == null) {
Log.e(TAG, "Activity returned NULL data");
return;
}
Uri uri = intent.getData();
if (uri == null) {
Log.e(TAG, "Activity returned NULL uri");
return;
}
openFileForImport(intent.getData(), null);
});
// Check that there is a file manager available
final Intent intentCreateDocumentAction = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intentCreateDocumentAction.addCategory(Intent.CATEGORY_OPENABLE);
@@ -82,45 +129,57 @@ public class ImportExportActivity extends AppCompatActivity
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "catima.zip");
Button exportButton = findViewById(R.id.exportButton);
exportButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
chooseFileWithIntent(intentCreateDocumentAction, CHOOSE_EXPORT_LOCATION);
}
exportButton.setOnClickListener(v -> {
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
builder.setTitle(R.string.exportPassword);
FrameLayout container = new FrameLayout(ImportExportActivity.this);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = 50;
params.rightMargin = 50;
final EditText input = new EditText(ImportExportActivity.this);
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
input.setLayoutParams(params);
input.setHint(R.string.exportPasswordHint);
container.addView(input);
builder.setView(container);
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
exportPassword = input.getText().toString();
try {
fileCreateLauncher.launch(intentCreateDocumentAction);
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
Log.e(TAG, "No activity found to handle intent", e);
}
});
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
builder.show();
});
// Check that there is a file manager available
final Intent intentGetContentAction = new Intent(Intent.ACTION_GET_CONTENT);
intentGetContentAction.addCategory(Intent.CATEGORY_OPENABLE);
intentGetContentAction.setType("*/*");
Button importFilesystem = findViewById(R.id.importOptionFilesystemButton);
importFilesystem.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
chooseImportType(intentGetContentAction);
}
});
importFilesystem.setOnClickListener(v -> chooseImportType(false));
// Check that there is an app that data can be imported from
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
Button importApplication = findViewById(R.id.importOptionApplicationButton);
importApplication.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
chooseImportType(intentPickAction);
}
});
importApplication.setOnClickListener(v -> chooseImportType(true));
}
private void chooseImportType(Intent baseIntent) {
private void openFileForImport(Uri uri, char[] password) {
try {
InputStream reader = getContentResolver().openInputStream(uri);
Log.e(TAG, "Starting file import with: " + uri.toString());
startImport(reader, uri, importDataFormat, password, true);
} catch (IOException e) {
Log.e(TAG, "Failed to import file: " + uri.toString(), e);
onImportComplete(ImportExportResult.GenericFailure, uri, importDataFormat);
}
}
private void chooseImportType(boolean choosePicker) {
List<CharSequence> betaImportOptions = new ArrayList<>();
betaImportOptions.add("Fidme");
betaImportOptions.add("Stocard");
@@ -176,47 +235,67 @@ public class ImportExportActivity extends AppCompatActivity
.setTitle(importAlertTitle)
.setMessage(importAlertMessage)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
chooseFileWithIntent(baseIntent, IMPORT);
@Override
public void onClick(DialogInterface dialog, int which) {
try {
if (choosePicker) {
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
filePickerLauncher.launch(intentPickAction);
} else {
fileOpenLauncher.launch("*/*");
}
})
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
Log.e(TAG, "No activity found to handle intent", e);
}
}
})
.setNegativeButton(R.string.cancel, null)
.show();
});
builder.show();
}
private void startImport(final InputStream target, final Uri targetUri, final DataFormat dataFormat, final char[] password)
{
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener()
{
private void startImport(final InputStream target, final Uri targetUri, final DataFormat dataFormat, final char[] password, final boolean closeWhenDone) {
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, true, false, false);
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener() {
@Override
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat)
{
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat) {
onImportComplete(result, targetUri, dataFormat);
if (closeWhenDone) {
try {
target.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
};
importExporter = new ImportExportTask(ImportExportActivity.this,
dataFormat, target, password, listener);
importExporter.execute();
mTasks.executeTask(TaskHandler.TYPE.IMPORT, importExporter);
}
private void startExport(final OutputStream target, final Uri targetUri)
{
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener()
{
private void startExport(final OutputStream target, final Uri targetUri, char[] password, final boolean closeWhenDone) {
mTasks.flushTaskList(TaskHandler.TYPE.EXPORT, true, false, false);
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener() {
@Override
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat)
{
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat) {
onExportComplete(result, targetUri);
if (closeWhenDone) {
try {
target.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
};
importExporter = new ImportExportTask(ImportExportActivity.this,
DataFormat.Catima, target, listener);
importExporter.execute();
DataFormat.Catima, target, password, listener);
mTasks.executeTask(TaskHandler.TYPE.EXPORT, importExporter);
}
@Override
@@ -244,22 +323,17 @@ public class ImportExportActivity extends AppCompatActivity
}
@Override
protected void onDestroy()
{
if(importExporter != null && importExporter.getStatus() != AsyncTask.Status.RUNNING)
{
importExporter.cancel(true);
}
protected void onDestroy() {
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, true, false, false);
mTasks.flushTaskList(TaskHandler.TYPE.EXPORT, true, false, false);
super.onDestroy();
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home)
{
if (id == android.R.id.home) {
finish();
return true;
}
@@ -276,7 +350,7 @@ public class ImportExportActivity extends AppCompatActivity
builder.setView(input);
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
activityResultParser(IMPORT, RESULT_OK, uri, input.getText().toString().toCharArray());
openFileForImport(uri, input.getText().toString().toCharArray());
});
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
@@ -293,13 +367,10 @@ public class ImportExportActivity extends AppCompatActivity
int messageId;
if (result == ImportExportResult.Success)
{
if (result == ImportExportResult.Success) {
builder.setTitle(R.string.importSuccessfulTitle);
messageId = R.string.importSuccessful;
}
else
{
} else {
builder.setTitle(R.string.importFailedTitle);
messageId = R.string.importFailed;
}
@@ -307,11 +378,9 @@ public class ImportExportActivity extends AppCompatActivity
final String message = getResources().getString(messageId);
builder.setMessage(message);
builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener()
{
builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which)
{
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
@@ -319,19 +388,15 @@ public class ImportExportActivity extends AppCompatActivity
builder.create().show();
}
private void onExportComplete(ImportExportResult result, final Uri path)
{
private void onExportComplete(ImportExportResult result, final Uri path) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
int messageId;
if(result == ImportExportResult.Success)
{
if (result == ImportExportResult.Success) {
builder.setTitle(R.string.exportSuccessfulTitle);
messageId = R.string.exportSuccessful;
}
else
{
} else {
builder.setTitle(R.string.exportFailedTitle);
messageId = R.string.exportFailed;
}
@@ -341,8 +406,7 @@ public class ImportExportActivity extends AppCompatActivity
builder.setMessage(message);
builder.setNeutralButton(R.string.ok, (dialog, which) -> dialog.dismiss());
if(result == ImportExportResult.Success)
{
if (result == ImportExportResult.Success) {
final CharSequence sendLabel = ImportExportActivity.this.getResources().getText(R.string.sendLabel);
builder.setPositiveButton(sendLabel, (dialog, which) -> {
@@ -362,92 +426,4 @@ public class ImportExportActivity extends AppCompatActivity
builder.create().show();
}
private void chooseFileWithIntent(Intent intent, int requestCode)
{
try
{
startActivityForResult(intent, requestCode);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
Log.e(TAG, "No activity found to handle intent", e);
}
}
private void activityResultParser(int requestCode, int resultCode, Uri uri, char[] password) {
if (resultCode != RESULT_OK)
{
Log.w(TAG, "Failed onActivityResult(), result=" + resultCode);
return;
}
if(uri == null)
{
Log.e(TAG, "Activity returned a NULL URI");
return;
}
try
{
if (requestCode == CHOOSE_EXPORT_LOCATION)
{
OutputStream writer;
if (uri.getScheme() != null)
{
writer = getContentResolver().openOutputStream(uri);
}
else
{
writer = new FileOutputStream(new File(uri.toString()));
}
Log.e(TAG, "Starting file export with: " + uri.toString());
startExport(writer, uri);
}
else
{
InputStream reader;
if(uri.getScheme() != null)
{
reader = getContentResolver().openInputStream(uri);
}
else
{
reader = new FileInputStream(new File(uri.toString()));
}
Log.e(TAG, "Starting file import with: " + uri.toString());
startImport(reader, uri, importDataFormat, password);
}
}
catch(FileNotFoundException e)
{
Log.e(TAG, "Failed to import/export file: " + uri.toString(), e);
if (requestCode == CHOOSE_EXPORT_LOCATION)
{
onExportComplete(ImportExportResult.GenericFailure, uri);
}
else
{
onImportComplete(ImportExportResult.GenericFailure, uri, importDataFormat);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(data == null)
{
Log.e(TAG, "Activity returned NULL data");
return;
}
activityResultParser(requestCode, resultCode, data.getData(), null);
}
}
@@ -4,7 +4,7 @@ import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.io.IOException;
@@ -13,13 +13,13 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import protect.card_locker.async.CompatCallable;
import protect.card_locker.importexport.DataFormat;
import protect.card_locker.importexport.ImportExportResult;
import protect.card_locker.importexport.MultiFormatExporter;
import protect.card_locker.importexport.MultiFormatImporter;
class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
{
public class ImportExportTask implements CompatCallable<ImportExportResult> {
private static final String TAG = "Catima";
private Activity activity;
@@ -35,14 +35,14 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
/**
* Constructor which will setup a task for exporting to the given file
*/
ImportExportTask(Activity activity, DataFormat format, OutputStream output,
TaskCompleteListener listener)
{
ImportExportTask(Activity activity, DataFormat format, OutputStream output, char[] password,
TaskCompleteListener listener) {
super();
this.activity = activity;
this.doImport = false;
this.format = format;
this.outputStream = output;
this.password = password;
this.listener = listener;
}
@@ -50,8 +50,7 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
* Constructor which will setup a task for importing from the given InputStream.
*/
ImportExportTask(Activity activity, DataFormat format, InputStream input, char[] password,
TaskCompleteListener listener)
{
TaskCompleteListener listener) {
super();
this.activity = activity;
this.doImport = true;
@@ -61,27 +60,22 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
this.listener = listener;
}
private ImportExportResult performImport(Context context, InputStream stream, DBHelper db, char[] password)
{
ImportExportResult importResult = MultiFormatImporter.importData(context, db, stream, format, password);
private ImportExportResult performImport(Context context, InputStream stream, SQLiteDatabase database, char[] password) {
ImportExportResult importResult = MultiFormatImporter.importData(context, database, stream, format, password);
Log.i(TAG, "Import result: " + importResult.name());
return importResult;
}
private ImportExportResult performExport(Context context, OutputStream stream, DBHelper db)
{
private ImportExportResult performExport(Context context, OutputStream stream, SQLiteDatabase database, char[] password) {
ImportExportResult result = ImportExportResult.GenericFailure;
try
{
try {
OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
result = MultiFormatExporter.exportData(context, db, stream, format);
result = MultiFormatExporter.exportData(context, database, stream, format, password);
writer.close();
}
catch (IOException e)
{
} catch (IOException e) {
Log.e(TAG, "Unable to export file", e);
}
@@ -90,55 +84,57 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
return result;
}
protected void onPreExecute()
{
public void onPreExecute() {
progress = new ProgressDialog(activity);
progress.setTitle(doImport ? R.string.importing : R.string.exporting);
progress.setOnDismissListener(new DialogInterface.OnDismissListener()
{
progress.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog)
{
ImportExportTask.this.cancel(true);
public void onDismiss(DialogInterface dialog) {
ImportExportTask.this.stop();
}
});
progress.show();
}
protected ImportExportResult doInBackground(Void... nothing)
{
final DBHelper db = new DBHelper(activity);
protected ImportExportResult doInBackground(Void... nothing) {
final SQLiteDatabase database = new DBHelper(activity).getWritableDatabase();
ImportExportResult result;
if(doImport)
{
result = performImport(activity.getApplicationContext(), inputStream, db, password);
}
else
{
result = performExport(activity.getApplicationContext(), outputStream, db);
if (doImport) {
result = performImport(activity.getApplicationContext(), inputStream, database, password);
} else {
result = performExport(activity.getApplicationContext(), outputStream, database, password);
}
database.close();
return result;
}
protected void onPostExecute(ImportExportResult result)
{
listener.onTaskComplete(result, format);
public void onPostExecute(Object castResult) {
listener.onTaskComplete((ImportExportResult) castResult, format);
progress.dismiss();
Log.i(TAG, (doImport ? "Import" : "Export") + " Complete");
}
protected void onCancelled()
{
protected void onCancelled() {
progress.dismiss();
Log.i(TAG, (doImport ? "Import" : "Export") + " Cancelled");
}
interface TaskCompleteListener
{
protected void stop() {
// Whelp
}
@Override
public ImportExportResult call() {
return doInBackground();
}
interface TaskCompleteListener {
void onTaskComplete(ImportExportResult result, DataFormat format);
}
@@ -4,8 +4,6 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import com.google.zxing.BarcodeFormat;
import java.io.InvalidObjectException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
@@ -35,7 +33,7 @@ public class ImportURIHelper {
private final String shareMultipleText;
public ImportURIHelper(Context context) {
this.context = context;
this.context = context.getApplicationContext();
hosts[0] = context.getResources().getString(R.string.intent_import_card_from_url_host_catima_app);
paths[0] = context.getResources().getString(R.string.intent_import_card_from_url_path_prefix_catima_app);
hosts[1] = context.getResources().getString(R.string.intent_import_card_from_url_host_thelastproject);
@@ -57,13 +55,13 @@ public class ImportURIHelper {
}
public LoyaltyCard parse(Uri uri) throws InvalidObjectException {
if(!isImportUri(uri)) {
if (!isImportUri(uri)) {
throw new InvalidObjectException("Not an import URI");
}
try {
// These values are allowed to be null
BarcodeFormat barcodeType = null;
CatimaBarcode barcodeType = null;
Date expiry = null;
BigDecimal balance = new BigDecimal("0");
Currency balanceType = null;
@@ -92,37 +90,33 @@ public class ImportURIHelper {
String note = kv.get(NOTE);
String cardId = kv.get(CARD_ID);
String barcodeId = kv.get(BARCODE_ID);
if (store == null || note == null || cardId == null) throw new InvalidObjectException("Not a valid import URI: " + uri.toString());
if (store == null || note == null || cardId == null)
throw new InvalidObjectException("Not a valid import URI: " + uri.toString());
String unparsedBarcodeType = kv.get(BARCODE_TYPE);
if(unparsedBarcodeType != null && !unparsedBarcodeType.equals(""))
{
barcodeType = BarcodeFormat.valueOf(unparsedBarcodeType);
if (unparsedBarcodeType != null && !unparsedBarcodeType.equals("")) {
barcodeType = CatimaBarcode.fromName(unparsedBarcodeType);
}
String unparsedBalance = kv.get(BALANCE);
if(unparsedBalance != null && !unparsedBalance.equals(""))
{
if (unparsedBalance != null && !unparsedBalance.equals("")) {
balance = new BigDecimal(unparsedBalance);
}
String unparsedBalanceType = kv.get(BALANCE_TYPE);
if (unparsedBalanceType != null && !unparsedBalanceType.equals(""))
{
if (unparsedBalanceType != null && !unparsedBalanceType.equals("")) {
balanceType = Currency.getInstance(unparsedBalanceType);
}
String unparsedExpiry = kv.get(EXPIRY);
if(unparsedExpiry != null && !unparsedExpiry.equals(""))
{
if (unparsedExpiry != null && !unparsedExpiry.equals("")) {
expiry = new Date(Long.parseLong(unparsedExpiry));
}
String unparsedHeaderColor = kv.get(HEADER_COLOR);
if(unparsedHeaderColor != null)
{
if (unparsedHeaderColor != null) {
headerColor = Integer.parseInt(unparsedHeaderColor);
}
return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0);
return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100);
} catch (NullPointerException | NumberFormatException | UnsupportedEncodingException ex) {
throw new InvalidObjectException("Not a valid import URI");
}
@@ -159,14 +153,14 @@ public class ImportURIHelper {
fragment = appendFragment(fragment, EXPIRY, String.valueOf(loyaltyCard.expiry.getTime()));
}
fragment = appendFragment(fragment, CARD_ID, loyaltyCard.cardId);
if(loyaltyCard.barcodeId != null) {
if (loyaltyCard.barcodeId != null) {
fragment = appendFragment(fragment, BARCODE_ID, loyaltyCard.barcodeId);
}
if(loyaltyCard.barcodeType != null) {
fragment = appendFragment(fragment, BARCODE_TYPE, loyaltyCard.barcodeType.toString());
if (loyaltyCard.barcodeType != null) {
fragment = appendFragment(fragment, BARCODE_TYPE, loyaltyCard.barcodeType.name());
}
if(loyaltyCard.headerColor != null) {
if (loyaltyCard.headerColor != null) {
fragment = appendFragment(fragment, HEADER_COLOR, loyaltyCard.headerColor.toString());
}
// Star status will not be exported
@@ -203,6 +197,7 @@ public class ImportURIHelper {
sendIntent.setType("text/plain");
Intent shareIntent = Intent.createChooser(sendIntent, null);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(shareIntent);
}
}
@@ -18,8 +18,7 @@ import android.text.TextPaint;
* alphabet or digit, if there is no letter or digit available, a default image
* is shown instead.
*/
class LetterBitmap
{
class LetterBitmap {
/**
* The number of available tile colors
@@ -37,39 +36,32 @@ class LetterBitmap
/**
* Constructor for <code>LetterTileProvider</code>
*
* @param context The {@link Context} to use
* @param displayName The name used to create the letter for the tile
* @param key The key used to generate the background color for the tile
* @param context The {@link Context} to use
* @param displayName The name used to create the letter for the tile
* @param key The key used to generate the background color for the tile
* @param tileLetterFontSize The font size used to display the letter
* @param width The desired width of the tile
* @param height The desired height of the tile
* @param backgroundColor (optional) color to use for background.
* @param textColor (optional) color to use for text.
* @param width The desired width of the tile
* @param height The desired height of the tile
* @param backgroundColor (optional) color to use for background.
* @param textColor (optional) color to use for text.
*/
public LetterBitmap(Context context, String displayName, String key, int tileLetterFontSize,
int width, int height, Integer backgroundColor, Integer textColor)
{
int width, int height, Integer backgroundColor, Integer textColor) {
TextPaint paint = new TextPaint();
paint.setTypeface(Typeface.create("sans-serif-light", Typeface.BOLD));
if(textColor != null)
{
if (textColor != null) {
paint.setColor(textColor);
}
else
{
} else {
paint.setColor(Color.WHITE);
}
paint.setTextAlign(Paint.Align.CENTER);
paint.setAntiAlias(true);
if(backgroundColor == null)
{
if (backgroundColor == null) {
mColor = getDefaultColor(context, key);
}
else
{
} else {
mColor = backgroundColor;
}
@@ -80,7 +72,7 @@ class LetterBitmap
c.setBitmap(mBitmap);
c.drawColor(mColor);
char [] firstCharArray = new char[1];
char[] firstCharArray = new char[1];
firstCharArray[0] = firstChar.toUpperCase().charAt(0);
paint.setTextSize(tileLetterFontSize);
@@ -97,16 +89,14 @@ class LetterBitmap
* alphabet or digit, if there is no letter or digit available, a
* default image is shown instead
*/
public Bitmap getLetterTile()
{
public Bitmap getLetterTile() {
return mBitmap;
}
/**
* @return background color used for letter title.
*/
public int getBackgroundColor()
{
public int getBackgroundColor() {
return mColor;
}
@@ -115,8 +105,7 @@ class LetterBitmap
* @return A new or previously chosen color for <code>key</code> used as the
* tile background color
*/
private static int pickColor(String key, TypedArray colors)
{
private static int pickColor(String key, TypedArray colors) {
// String.hashCode() is not supposed to change across java versions, so
// this should guarantee the same key always maps to the same color
final int color = Math.abs(key.hashCode()) % NUM_OF_TILE_COLORS;
@@ -127,8 +116,7 @@ class LetterBitmap
* Determine the color which the letter tile will use if no default
* color is provided.
*/
public static int getDefaultColor(Context context, String key)
{
public static int getDefaultColor(Context context, String key) {
final Resources res = context.getResources();
TypedArray colors = res.obtainTypedArray(R.array.letter_tile_colors);
@@ -1,8 +1,8 @@
package protect.card_locker;
import android.database.Cursor;
import com.google.zxing.BarcodeFormat;
import android.os.Parcel;
import android.os.Parcelable;
import java.math.BigDecimal;
import java.util.Currency;
@@ -10,7 +10,7 @@ import java.util.Date;
import androidx.annotation.Nullable;
public class LoyaltyCard {
public class LoyaltyCard implements Parcelable {
public final int id;
public final String store;
public final String note;
@@ -22,18 +22,20 @@ public class LoyaltyCard {
@Nullable
public final String barcodeId;
public final BarcodeFormat barcodeType;
@Nullable
public final CatimaBarcode barcodeType;
@Nullable
public final Integer headerColor;
public final int starStatus;
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,
final String barcodeId, final BarcodeFormat barcodeType, final Integer headerColor,
final int starStatus)
{
@Nullable final String barcodeId, @Nullable final CatimaBarcode barcodeType,
@Nullable final Integer headerColor, final int starStatus, final long lastUsed, final int zoomLevel) {
this.id = id;
this.store = store;
this.note = note;
@@ -45,10 +47,47 @@ public class LoyaltyCard {
this.barcodeType = barcodeType;
this.headerColor = headerColor;
this.starStatus = starStatus;
this.lastUsed = lastUsed;
this.zoomLevel = zoomLevel;
}
public static LoyaltyCard toLoyaltyCard(Cursor cursor)
{
protected LoyaltyCard(Parcel in) {
id = in.readInt();
store = in.readString();
note = in.readString();
long tmpExpiry = in.readLong();
expiry = tmpExpiry != -1 ? new Date(tmpExpiry) : null;
balance = (BigDecimal) in.readValue(BigDecimal.class.getClassLoader());
balanceType = (Currency) in.readValue(Currency.class.getClassLoader());
cardId = in.readString();
barcodeId = in.readString();
String tmpBarcodeType = in.readString();
barcodeType = !tmpBarcodeType.isEmpty() ? CatimaBarcode.fromName(tmpBarcodeType) : null;
int tmpHeaderColor = in.readInt();
headerColor = tmpHeaderColor != -1 ? tmpHeaderColor : null;
starStatus = in.readInt();
lastUsed = in.readLong();
zoomLevel = in.readInt();
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
parcel.writeString(store);
parcel.writeString(note);
parcel.writeLong(expiry != null ? expiry.getTime() : -1);
parcel.writeValue(balance);
parcel.writeValue(balanceType);
parcel.writeString(cardId);
parcel.writeString(barcodeId);
parcel.writeString(barcodeType != null ? barcodeType.name() : "");
parcel.writeInt(headerColor != null ? headerColor : -1);
parcel.writeInt(starStatus);
parcel.writeLong(lastUsed);
parcel.writeInt(zoomLevel);
}
public static LoyaltyCard toLoyaltyCard(Cursor cursor) {
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));
@@ -57,36 +96,51 @@ public class LoyaltyCard {
String cardId = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID));
String barcodeId = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID));
int starred = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS));
long lastUsed = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.LAST_USED));
int zoomLevel = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ZOOM_LEVEL));
int barcodeTypeColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE);
int balanceTypeColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE);
int headerColorColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR);
BarcodeFormat barcodeType = null;
CatimaBarcode barcodeType = null;
Currency balanceType = null;
Date expiry = null;
Integer headerColor = null;
if (cursor.isNull(barcodeTypeColumn) == false)
{
barcodeType = BarcodeFormat.valueOf(cursor.getString(barcodeTypeColumn));
if (cursor.isNull(barcodeTypeColumn) == false) {
barcodeType = CatimaBarcode.fromName(cursor.getString(barcodeTypeColumn));
}
if (cursor.isNull(balanceTypeColumn) == false)
{
if (cursor.isNull(balanceTypeColumn) == false) {
balanceType = Currency.getInstance(cursor.getString(balanceTypeColumn));
}
if(expiryLong > 0)
{
if (expiryLong > 0) {
expiry = new Date(expiryLong);
}
if(cursor.isNull(headerColorColumn) == false)
{
if (cursor.isNull(headerColorColumn) == false) {
headerColor = cursor.getInt(headerColorColumn);
}
return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred);
return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed, zoomLevel);
}
@Override
public int describeContents() {
return id;
}
public static final Creator<LoyaltyCard> CREATOR = new Creator<LoyaltyCard>() {
@Override
public LoyaltyCard createFromParcel(Parcel in) {
return new LoyaltyCard(in);
}
@Override
public LoyaltyCard[] newArray(int size) {
return new LoyaltyCard[size];
}
};
}
@@ -1,37 +0,0 @@
package protect.card_locker;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.content.Context;
import android.view.View;
public class LoyaltyCardAnimator {
private static AnimatorSet selectedViewIn, defaultViewOut, selectedViewOut, defaultViewIn;
public static void flipView(Context inputContext, final View inputSelectedView, final View inputDefaultView, boolean inputItemSelected) {
selectedViewIn = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_left_in);
defaultViewOut = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_right_out);
selectedViewOut = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_left_out);
defaultViewIn = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_right_in);
final AnimatorSet showFrontAnim = new AnimatorSet();
final AnimatorSet showBackAnim = new AnimatorSet();
selectedViewIn.setTarget(inputSelectedView);
defaultViewOut.setTarget(inputDefaultView);
showFrontAnim.playTogether(selectedViewIn, defaultViewOut);
selectedViewOut.setTarget(inputSelectedView);
defaultViewIn.setTarget(inputDefaultView);
showBackAnim.playTogether(defaultViewIn, selectedViewOut);
if (inputItemSelected) {
showFrontAnim.start();
} else {
showBackAnim.start();
}
}
}
@@ -1,245 +1,198 @@
package protect.card_locker;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.SparseBooleanArray;
import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
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 com.google.android.material.card.MaterialCardView;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Currency;
import java.util.Date;
import androidx.cardview.widget.CardView;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder>
{
private static int mCurrentSelectedIndex = -1;
private Cursor mCursor;
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder> {
private int mCurrentSelectedIndex = -1;
Settings mSettings;
boolean mDarkModeEnabled;
private Context mContext;
private CardAdapterListener mListener;
private SparseBooleanArray mSelectedItems;
private SparseBooleanArray mAnimationItemsIndex;
private final Context mContext;
private final CardAdapterListener mListener;
protected SparseBooleanArray mSelectedItems;
protected SparseBooleanArray mAnimationItemsIndex;
private boolean mReverseAllAnimations = false;
private boolean mShowDetails = true;
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener)
{
super(inputCursor);
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener) {
super(inputCursor, DBHelper.LoyaltyCardDbIds.ID);
setHasStableIds(true);
mSettings = new Settings(inputContext);
mCursor = inputCursor;
mContext = inputContext;
mContext = inputContext.getApplicationContext();
mListener = inputListener;
mSelectedItems = new SparseBooleanArray();
mAnimationItemsIndex = new SparseBooleanArray();
mDarkModeEnabled = MainActivity.isDarkModeEnabled(inputContext);
mDarkModeEnabled = Utils.isDarkModeEnabled(inputContext);
swapCursor(inputCursor);
}
public void showDetails(boolean show) {
mShowDetails = show;
notifyDataSetChanged();
}
public boolean showingDetails() {
return mShowDetails;
}
@Override
public LoyaltyCardListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType)
{
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);
return new LoyaltyCardListItemViewHolder(itemView, mListener);
}
public Cursor getCursor()
{
return mCursor;
public LoyaltyCard getCard(int position) {
mCursor.moveToPosition(position);
return LoyaltyCard.toLoyaltyCard(mCursor);
}
public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor inputCursor) {
if (mDarkModeEnabled) {
inputHolder.mStarIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
}
// Invisible until we want to show something more
inputHolder.mDivider.setVisibility(View.GONE);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(inputCursor);
inputHolder.mStoreField.setText(loyaltyCard.store);
inputHolder.mStoreField.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
if (!loyaltyCard.note.isEmpty()) {
inputHolder.mNoteField.setVisibility(View.VISIBLE);
inputHolder.mNoteField.setText(loyaltyCard.note);
inputHolder.mNoteField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
inputHolder.setStoreField(loyaltyCard.store);
if (mShowDetails && !loyaltyCard.note.isEmpty()) {
inputHolder.setNoteField(loyaltyCard.note);
} else {
inputHolder.mNoteField.setVisibility(View.GONE);
inputHolder.setNoteField(null);
}
if (!loyaltyCard.balance.equals(new BigDecimal("0"))) {
inputHolder.mBalanceField.setVisibility(View.VISIBLE);
inputHolder.mBalanceField.setText(mContext.getString(R.string.balanceSentence, Utils.formatBalance(mContext, loyaltyCard.balance, loyaltyCard.balanceType)));
inputHolder.mBalanceField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
if (mShowDetails && !loyaltyCard.balance.equals(new BigDecimal("0"))) {
inputHolder.setBalanceField(loyaltyCard.balance, loyaltyCard.balanceType);
} else {
inputHolder.mBalanceField.setVisibility(View.GONE);
inputHolder.setBalanceField(null, null);
}
if (loyaltyCard.expiry != null)
{
inputHolder.mExpiryField.setVisibility(View.VISIBLE);
int expiryString = R.string.expiryStateSentence;
if(Utils.hasExpired(loyaltyCard.expiry)) {
expiryString = R.string.expiryStateSentenceExpired;
inputHolder.mExpiryField.setTextColor(mContext.getResources().getColor(R.color.alert));
}
inputHolder.mExpiryField.setText(mContext.getString(expiryString, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry)));
inputHolder.mExpiryField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
if (mShowDetails && loyaltyCard.expiry != null) {
inputHolder.setExpiryField(loyaltyCard.expiry);
} else {
inputHolder.mExpiryField.setVisibility(View.GONE);
inputHolder.setExpiryField(null);
}
inputHolder.mStarIcon.setVisibility((loyaltyCard.starStatus != 0) ? View.VISIBLE : View.GONE);
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
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);
} else {
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
inputHolder.mCardIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
}
inputHolder.setIconBackgroundColor(loyaltyCard.headerColor != null ? loyaltyCard.headerColor : R.attr.colorPrimary);
inputHolder.toggleStar(loyaltyCard.starStatus != 0, itemSelected(inputCursor.getPosition()));
inputHolder.itemView.setActivated(mSelectedItems.get(inputCursor.getPosition(), false));
applyIconAnimation(inputHolder, inputCursor.getPosition());
applyClickEvents(inputHolder, inputCursor.getPosition());
// Force redraw to fix size not shrinking after data change
inputHolder.mRow.requestLayout();
}
private void applyClickEvents(LoyaltyCardListItemViewHolder inputHolder, final int inputPosition)
{
inputHolder.mThumbnailContainer.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View inputView)
{
mListener.onIconClicked(inputPosition);
}
});
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.mRow.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View inputView)
{
mListener.onRowClicked(inputPosition);
}
});
inputHolder.mIconLayout.getLayoutParams().height = expanded ? 0 : iconHeight;
inputHolder.mCardIcon.getLayoutParams().height = iconHeight;
inputHolder.mTickIcon.getLayoutParams().height = iconHeight;
}
inputHolder.mInformationContainer.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View inputView)
{
mListener.onRowClicked(inputPosition);
}
});
private void applyClickEvents(LoyaltyCardListItemViewHolder inputHolder, final int inputPosition) {
inputHolder.mRow.setOnClickListener(inputView -> mListener.onRowClicked(inputPosition));
inputHolder.mRow.setOnLongClickListener(new View.OnLongClickListener()
{
@Override
public boolean onLongClick(View inputView)
{
mListener.onRowLongClicked(inputPosition);
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
}
});
inputHolder.mInformationContainer.setOnLongClickListener(new View.OnLongClickListener()
{
@Override
public boolean onLongClick(View inputView)
{
mListener.onRowLongClicked(inputPosition);
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
}
inputHolder.mRow.setOnLongClickListener(inputView -> {
mListener.onRowLongClicked(inputPosition);
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
});
}
private void applyIconAnimation(LoyaltyCardListItemViewHolder inputHolder, int inputPosition)
{
if (mSelectedItems.get(inputPosition, false))
{
inputHolder.mThumbnailFrontContainer.setVisibility(View.GONE);
resetIconYAxis(inputHolder.mThumbnailBackContainer);
inputHolder.mThumbnailBackContainer.setVisibility(View.VISIBLE);
inputHolder.mThumbnailBackContainer.setAlpha(1);
if (mCurrentSelectedIndex == inputPosition)
{
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, true);
private boolean itemSelected(int inputPosition) {
return mSelectedItems.get(inputPosition, false);
}
private void applyIconAnimation(LoyaltyCardListItemViewHolder inputHolder, int inputPosition) {
if (itemSelected(inputPosition)) {
inputHolder.mCardIcon.setVisibility(View.GONE);
inputHolder.mTickIcon.setVisibility(View.VISIBLE);
if (mCurrentSelectedIndex == inputPosition) {
resetCurrentIndex();
}
}
else
{
inputHolder.mThumbnailBackContainer.setVisibility(View.GONE);
resetIconYAxis(inputHolder.mThumbnailFrontContainer);
inputHolder.mThumbnailFrontContainer.setVisibility(View.VISIBLE);
inputHolder.mThumbnailFrontContainer.setAlpha(1);
if ((mReverseAllAnimations && mAnimationItemsIndex.get(inputPosition, false)) || mCurrentSelectedIndex == inputPosition)
{
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, false);
} else {
inputHolder.mTickIcon.setVisibility(View.GONE);
inputHolder.mCardIcon.setVisibility(View.VISIBLE);
if ((mReverseAllAnimations && mAnimationItemsIndex.get(inputPosition, false)) || mCurrentSelectedIndex == inputPosition) {
resetCurrentIndex();
}
}
}
private void resetIconYAxis(View inputView)
{
if (inputView.getRotationY() != 0)
{
inputView.setRotationY(0);
}
}
public void resetAnimationIndex()
{
mReverseAllAnimations = false;
mAnimationItemsIndex.clear();
}
@SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
public void toggleSelection(int inputPosition)
{
public void toggleSelection(int inputPosition) {
mCurrentSelectedIndex = inputPosition;
if (mSelectedItems.get(inputPosition, false))
{
if (mSelectedItems.get(inputPosition, false)) {
mSelectedItems.delete(inputPosition);
mAnimationItemsIndex.delete(inputPosition);
}
else
{
} else {
mSelectedItems.put(inputPosition, true);
mAnimationItemsIndex.put(inputPosition, true);
}
notifyItemChanged(inputPosition);
notifyDataSetChanged();
}
public void clearSelections()
{
public void clearSelections() {
mReverseAllAnimations = true;
mSelectedItems.clear();
notifyDataSetChanged();
}
public int getSelectedItemCount()
{
public int getSelectedItemCount() {
return mSelectedItems.size();
}
public ArrayList<LoyaltyCard> getSelectedItems()
{
public ArrayList<LoyaltyCard> getSelectedItems() {
ArrayList<LoyaltyCard> result = new ArrayList<>();
int i;
for(i = 0; i < mSelectedItems.size(); i++)
{
for (i = 0; i < mSelectedItems.size(); i++) {
mCursor.moveToPosition(mSelectedItems.keyAt(i));
result.add(LoyaltyCard.toLoyaltyCard(mCursor));
}
@@ -247,51 +200,147 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
return result;
}
private void resetCurrentIndex()
{
private void resetCurrentIndex() {
mCurrentSelectedIndex = -1;
}
public interface CardAdapterListener
{
void onIconClicked(int inputPosition);
public interface CardAdapterListener {
void onRowClicked(int inputPosition);
void onRowLongClicked(int inputPosition);
}
public class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener
{
public class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder {
public TextView mStoreField, mNoteField, mBalanceField, mExpiryField;
public LinearLayout mInformationContainer;
public ImageView mCardIcon, mStarIcon;
public CardView mThumbnailContainer;
public ConstraintLayout mRow;
public RelativeLayout mThumbnailFrontContainer, mThumbnailBackContainer;
public ImageView mCardIcon, mStarBackground, mStarBorder, mTickIcon;
public MaterialCardView mRow, mIconLayout;
public ConstraintLayout mStar;
public View mDivider;
public LoyaltyCardListItemViewHolder(View inputView)
{
private int mIconBackgroundColor;
protected LoyaltyCardListItemViewHolder(View inputView, CardAdapterListener inputListener) {
super(inputView);
mThumbnailContainer = inputView.findViewById(R.id.thumbnail_container);
mRow = inputView.findViewById(R.id.row);
mThumbnailFrontContainer = inputView.findViewById(R.id.thumbnail_front);
mThumbnailBackContainer = inputView.findViewById(R.id.thumbnail_back);
mInformationContainer = inputView.findViewById(R.id.information_container);
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);
mStarIcon = inputView.findViewById(R.id.star);
inputView.setOnLongClickListener(this);
mStar = inputView.findViewById(R.id.star);
mStarBackground = inputView.findViewById(R.id.star_background);
mStarBorder = inputView.findViewById(R.id.star_border);
mTickIcon = inputView.findViewById(R.id.selected_thumbnail);
inputView.setOnLongClickListener(view -> {
inputListener.onRowClicked(getAdapterPosition());
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
});
}
@Override
public boolean onLongClick(View inputView)
{
mListener.onRowLongClicked(getAdapterPosition());
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
public void setStoreField(String text) {
mStoreField.setText(text);
mStoreField.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
mStoreField.requestLayout();
}
public void setNoteField(String text) {
if (text == null) {
mNoteField.setVisibility(View.GONE);
} 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];
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];
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));
mExpiryField.setTextColor(Color.RED);
} else if (mDarkModeEnabled) {
expiryIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
}
mExpiryField.setText(DateFormat.getDateInstance(DateFormat.LONG).format(expiry));
mExpiryField.setTextSize(size);
}
mExpiryField.requestLayout();
}
public void toggleStar(boolean enable, boolean colorByTheme) {
/* the below code does not work in android 5! hence the change of drawable instead
boolean needDarkForeground = Utils.needsDarkForeground(mIconBackgroundColor);
Drawable borderDrawable = mStarBorder.getDrawable().mutate();
Drawable backgroundDrawable = mStarBackground.getDrawable().mutate();
DrawableCompat.setTint(borderDrawable, needsDarkForeground ? Color.BLACK : Color.WHITE);
DrawableCompat.setTint(backgroundDrawable, needsDarkForeground ? Color.BLACK : Color.WHITE);
mStarBorder.setImageDrawable(borderDrawable);
mStarBackground.setImageDrawable(backgroundDrawable);
*/
boolean dark = Utils.needsDarkForeground(mIconBackgroundColor);
if (colorByTheme) {
dark = !mDarkModeEnabled;
}
if (dark) {
mStarBorder.setImageResource(R.drawable.ic_unstarred_white);
mStarBackground.setImageResource(R.drawable.ic_starred_black);
} else {
mStarBorder.setImageResource(R.drawable.ic_unstarred_black);
mStarBackground.setImageResource(R.drawable.ic_starred_white);
}
if (enable) {
mStar.setVisibility(View.VISIBLE);
} else {
mStar.setVisibility(View.GONE);
}
mStarBorder.invalidate();
mStarBackground.invalidate();
}
public void setIconBackgroundColor(int color) {
mIconBackgroundColor = color;
mCardIcon.setBackgroundColor(color);
}
}
}
public int dpToPx(int dp, Context mContext) {
Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
return px;
}
}
File diff suppressed because it is too large. Load diff
@@ -3,13 +3,19 @@ package protect.card_locker;
import android.app.Application;
import androidx.appcompat.app.AppCompatDelegate;
import com.google.android.material.color.DynamicColors;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardLockerApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Settings settings = new Settings(getApplicationContext());
Settings settings = new Settings(this);
AppCompatDelegate.setDefaultNightMode(settings.getTheme());
DynamicColors.applyToActivitiesIfAvailable(this);
}
}
File diff suppressed because it is too large. Load diff
@@ -1,72 +1,82 @@
package protect.card_locker;
import android.app.Activity;
import android.app.SearchManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.database.CursorIndexOutOfBoundsException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
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.List;
import androidx.appcompat.app.AppCompatActivity;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.core.splashscreen.SplashScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.color.DynamicColors;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
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 protect.card_locker.preferences.SettingsActivity;
public class MainActivity extends AppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener
{
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener {
private static final String TAG = "Catima";
public static final String RESTART_ACTIVITY_INTENT = "restart_activity_intent";
private final DBHelper mDB = new DBHelper(this);
private SQLiteDatabase mDatabase;
private LoyaltyCardCursorAdapter mAdapter;
private ActionMode mCurrentActionMode;
private Menu mMenu;
private SearchView mSearchView;
private GestureDetector mGestureDetector;
protected String mFilter = "";
protected Object mGroup = null;
protected DBHelper.LoyaltyCardOrder mOrder = DBHelper.LoyaltyCardOrder.Alpha;
protected DBHelper.LoyaltyCardOrderDirection mOrderDirection = DBHelper.LoyaltyCardOrderDirection.Ascending;
protected int selectedTab = 0;
private RecyclerView mCardList;
private View mHelpText;
private View mNoMatchingCardsText;
private View mNoGroupCardsText;
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback()
{
private ActivityResultLauncher<Intent> mBarcodeScannerLauncher;
private ActivityResultLauncher<Intent> mSettingsLauncher;
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode inputMode, Menu inputMenu)
{
public boolean onCreateActionMode(ActionMode inputMode, Menu inputMenu) {
inputMode.getMenuInflater().inflate(R.menu.card_longclick_menu, inputMenu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode inputMode, Menu inputMenu)
{
public boolean onPrepareActionMode(ActionMode inputMode, Menu inputMenu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode inputMode, MenuItem inputItem)
{
if (inputItem.getItemId() == R.id.action_copy_to_clipboard)
{
public boolean onActionItemClicked(ActionMode inputMode, MenuItem inputItem) {
if (inputItem.getItemId() == R.id.action_copy_to_clipboard) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
String clipboardData;
@@ -94,9 +104,7 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
Toast.makeText(MainActivity.this, cardCount > 1 ? R.string.copy_to_clipboard_multiple_toast : R.string.copy_to_clipboard_toast, Toast.LENGTH_LONG).show();
inputMode.finish();
return true;
}
else if (inputItem.getItemId() == R.id.action_share)
{
} else if (inputItem.getItemId() == R.id.action_share) {
final ImportURIHelper importURIHelper = new ImportURIHelper(MainActivity.this);
try {
importURIHelper.startShareIntent(mAdapter.getSelectedItems());
@@ -106,20 +114,55 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
inputMode.finish();
return true;
}
else if(inputItem.getItemId() == R.id.action_edit)
{
} else if (inputItem.getItemId() == R.id.action_edit) {
if (mAdapter.getSelectedItemCount() != 1) {
throw new IllegalArgumentException("Cannot edit more than 1 card at a time");
}
Intent intent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("id", mAdapter.getSelectedItems().get(0).id);
bundle.putBoolean("update", true);
bundle.putInt(LoyaltyCardEditActivity.BUNDLE_ID, mAdapter.getSelectedItems().get(0).id);
bundle.putBoolean(LoyaltyCardEditActivity.BUNDLE_UPDATE, true);
intent.putExtras(bundle);
startActivity(intent);
inputMode.finish();
return true;
} else if (inputItem.getItemId() == R.id.action_delete) {
AlertDialog.Builder builder = new AlertDialog.Builder(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.
// In here, we use the plain string when meaning exactly 1, and otherwise use the plural forms
if (mAdapter.getSelectedItemCount() == 1) {
builder.setTitle(R.string.deleteTitle);
builder.setMessage(R.string.deleteConfirmation);
} else {
builder.setTitle(getResources().getQuantityString(R.plurals.deleteCardsTitle, mAdapter.getSelectedItemCount(), mAdapter.getSelectedItemCount()));
builder.setMessage(getResources().getQuantityString(R.plurals.deleteCardsConfirmation, mAdapter.getSelectedItemCount(), mAdapter.getSelectedItemCount()));
}
builder.setPositiveButton(R.string.confirm, (dialog, which) -> {
DBHelper db = new DBHelper(MainActivity.this);
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
Log.e(TAG, "Deleting card: " + loyaltyCard.id);
DBHelper.deleteLoyaltyCard(mDatabase, MainActivity.this, loyaltyCard.id);
ShortcutHelper.removeShortcut(MainActivity.this, loyaltyCard.id);
}
TabLayout.Tab tab = ((TabLayout) findViewById(R.id.groups)).getTabAt(selectedTab);
mGroup = tab != null ? tab.getTag() : null;
updateLoyaltyCardList();
dialog.dismiss();
});
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
return true;
}
@@ -127,44 +170,49 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
@Override
public void onDestroyActionMode(ActionMode inputMode)
{
public void onDestroyActionMode(ActionMode inputMode) {
mAdapter.clearSelections();
mCurrentActionMode = null;
mCardList.post(new Runnable()
{
@Override
public void run()
{
mAdapter.resetAnimationIndex();
}
});
}
};
@Override
protected void onCreate(Bundle inputSavedInstanceState)
{
protected void onCreate(Bundle inputSavedInstanceState) {
super.onCreate(inputSavedInstanceState);
SplashScreen.installSplashScreen(this);
// onPreCreate can't tell this activity uses a material theme due to splash screen, force color application here
DynamicColors.applyIfAvailable(this);
Utils.patchOledDarkTheme(this);
setTitle(R.string.app_name);
setContentView(R.layout.main_activity);
// XXX more dynamic color fixing due to splash screen
// without this the background color will get stuck with the old color before dynamic color
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(android.R.attr.colorBackground, typedValue, true);
findViewById(android.R.id.content).setBackgroundColor(typedValue.data);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
updateLoyaltyCardList(mFilter, null);
mDatabase = new DBHelper(this).getWritableDatabase();
TabLayout groupsTabLayout = findViewById(R.id.groups);
groupsTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
selectedTab = tab.getPosition();
updateLoyaltyCardList(mFilter, tab.getTag());
Log.d("onTabSelected", "Tab Position " + tab.getPosition());
mGroup = tab.getTag();
updateLoyaltyCardList();
// Store active tab in Shared Preference to restore next app launch
SharedPreferences activeTabPref = getApplicationContext().getSharedPreferences(
getString(R.string.sharedpreference_active_tab),
Context.MODE_PRIVATE);
SharedPreferences.Editor activeTabPrefEditor = activeTabPref.edit();
activeTabPrefEditor.putInt(getString(R.string.sharedpreference_active_tab), selectedTab);
activeTabPrefEditor.putInt(getString(R.string.sharedpreference_active_tab), tab.getPosition());
activeTabPrefEditor.apply();
}
@@ -181,20 +229,24 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
mGestureDetector = new GestureDetector(this, this);
View.OnTouchListener gestureTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(final View v, final MotionEvent event){
return mGestureDetector.onTouchEvent(event);
}
};
View.OnTouchListener gestureTouchListener = (v, event) -> mGestureDetector.onTouchEvent(event);
final View helpText = findViewById(R.id.helpText);
final View noMatchingCardsText = findViewById(R.id.noMatchingCardsText);
final View list = findViewById(R.id.list);
mHelpText = findViewById(R.id.helpText);
mNoMatchingCardsText = findViewById(R.id.noMatchingCardsText);
mNoGroupCardsText = findViewById(R.id.noGroupCardsText);
mCardList = findViewById(R.id.list);
helpText.setOnTouchListener(gestureTouchListener);
noMatchingCardsText.setOnTouchListener(gestureTouchListener);
list.setOnTouchListener(gestureTouchListener);
mHelpText.setOnTouchListener(gestureTouchListener);
mNoMatchingCardsText.setOnTouchListener(gestureTouchListener);
mCardList.setOnTouchListener(gestureTouchListener);
mNoGroupCardsText.setOnTouchListener(gestureTouchListener);
mAdapter = new LoyaltyCardCursorAdapter(this, null, this);
mCardList.setAdapter(mAdapter);
registerForContextMenu(mCardList);
mGroup = null;
updateLoyaltyCardList();
/*
* This was added for Huawei, but Huawei is just too much of a fucking pain.
@@ -226,40 +278,67 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
.show();
}
*/
mBarcodeScannerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
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);
}
});
mSettingsLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent intent = result.getData();
if (intent != null && intent.getBooleanExtra(RESTART_ACTIVITY_INTENT, false)) {
recreate();
}
}
});
}
@Override
protected void onResume()
{
protected void onResume() {
super.onResume();
if(mCurrentActionMode != null)
{
if (mCurrentActionMode != null) {
mAdapter.clearSelections();
mCurrentActionMode.finish();
}
if (mMenu != null)
{
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
if (!searchView.isIconified())
{
mFilter = searchView.getQuery().toString();
}
if (mSearchView != null && !mSearchView.isIconified()) {
mFilter = mSearchView.getQuery().toString();
}
// Start of active tab logic
TabLayout groupsTabLayout = findViewById(R.id.groups);
updateTabGroups(groupsTabLayout);
// Restore active tab from Shared Preference
// Restore settings 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);
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) {
}
Object group = null;
mGroup = null;
if (groupsTabLayout.getTabCount() != 0) {
TabLayout.Tab tab = groupsTabLayout.getTabAt(selectedTab);
@@ -269,118 +348,88 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
groupsTabLayout.selectTab(tab);
assert tab != null;
group = tab.getTag();
mGroup = tab.getTag();
}
updateLoyaltyCardList(mFilter, group);
updateLoyaltyCardList();
// End of active tab logic
FloatingActionButton addButton = findViewById(R.id.fabAdd);
ExtendedFloatingActionButton addButton = findViewById(R.id.fabAdd);
addButton.setOnClickListener(v -> {
Intent i = new Intent(getApplicationContext(), ScanActivity.class);
startActivityForResult(i, Utils.BARCODE_SCAN);
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
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == Utils.MAIN_REQUEST) {
// We're coming back from another view so clear the search
// We only do this now to prevent a flash of all entries right after picking one
mFilter = "";
if (mMenu != null)
{
MenuItem searchItem = mMenu.findItem(R.id.action_search);
searchItem.collapseActionView();
}
recreate();
public void onBackPressed() {
if (!mSearchView.isIconified()) {
mSearchView.setIconified(true);
return;
}
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
super.onBackPressed();
}
if(!barcodeValues.isEmpty()) {
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
Bundle newBundle = new Bundle();
newBundle.putString("barcodeType", barcodeValues.format());
newBundle.putString("cardId", barcodeValues.content());
newIntent.putExtras(newBundle);
startActivity(newIntent);
private void displayCardSetupOptions(boolean shouldShow) {
View search = findViewById(R.id.action_search);
View folder = findViewById(R.id.action_unfold);
View sort = findViewById(R.id.action_sort);
if (search != null && mSearchView.isIconified()) {
search.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
}
if (folder != null) {
folder.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
}
if (sort != null) {
sort.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
}
}
@Override
public void onBackPressed()
{
if (mMenu == null)
{
super.onBackPressed();
return;
}
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
if (!searchView.isIconified())
{
searchView.setIconified(true);
} else {
TabLayout groupsTabLayout = findViewById(R.id.groups);
if (groupsTabLayout.getVisibility() == View.VISIBLE && selectedTab != 0) {
selectedTab = 0;
groupsTabLayout.selectTab(groupsTabLayout.getTabAt(0));
} else {
super.onBackPressed();
}
}
}
private void updateLoyaltyCardList(String filterText, Object tag)
{
private void updateLoyaltyCardList() {
Group group = null;
if (tag != null) {
group = (Group) tag;
if (mGroup != null) {
group = (Group) mGroup;
}
mCardList = findViewById(R.id.list);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
mCardList.setLayoutManager(mLayoutManager);
mCardList.setItemAnimator(new DefaultItemAnimator());
mAdapter.swapCursor(DBHelper.getLoyaltyCardCursor(mDatabase, mFilter, group, mOrder, mOrderDirection));
final TextView helpText = findViewById(R.id.helpText);
final TextView noMatchingCardsText = findViewById(R.id.noMatchingCardsText);
Cursor cardCursor = mDB.getLoyaltyCardCursor(filterText, group);
mAdapter = new LoyaltyCardCursorAdapter(this, cardCursor, this);
mCardList.setAdapter(mAdapter);
registerForContextMenu(mCardList);
if(mDB.getLoyaltyCardCount() > 0)
{
if (DBHelper.getLoyaltyCardCount(mDatabase) > 0) {
// 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
mCardList.setVisibility(View.VISIBLE);
helpText.setVisibility(View.GONE);
if(mAdapter.getItemCount() > 0)
{
noMatchingCardsText.setVisibility(View.GONE);
mHelpText.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.GONE);
displayCardSetupOptions(true);
if (mAdapter.getItemCount() > 0) {
mCardList.setVisibility(View.VISIBLE);
mNoMatchingCardsText.setVisibility(View.GONE);
} else {
mCardList.setVisibility(View.GONE);
if (!mFilter.isEmpty()) {
// Actual Empty Search Result
mNoMatchingCardsText.setVisibility(View.VISIBLE);
mNoGroupCardsText.setVisibility(View.GONE);
} else {
// Group Tab with no Group Cards
mNoMatchingCardsText.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.VISIBLE);
}
}
else
{
noMatchingCardsText.setVisibility(View.VISIBLE);
}
}
else
{
} else {
mCardList.setVisibility(View.GONE);
helpText.setVisibility(View.VISIBLE);
noMatchingCardsText.setVisibility(View.GONE);
mHelpText.setVisibility(View.VISIBLE);
displayCardSetupOptions(false);
mNoMatchingCardsText.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.GONE);
}
if (mCurrentActionMode != null) {
@@ -388,11 +437,8 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
}
public void updateTabGroups(TabLayout groupsTabLayout)
{
final DBHelper db = new DBHelper(this);
List<Group> newGroups = db.getGroups();
public void updateTabGroups(TabLayout groupsTabLayout) {
List<Group> newGroups = DBHelper.getGroups(mDatabase);
if (newGroups.size() == 0) {
groupsTabLayout.removeAllTabs();
@@ -417,53 +463,36 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
groupsTabLayout.setVisibility(View.VISIBLE);
}
private void openPrivacyPolicy() {
Intent browserIntent = new Intent(
Intent.ACTION_VIEW,
Uri.parse("https://catima.app/privacy-policy")
);
startActivity(browserIntent);
}
@Override
public boolean onCreateOptionsMenu(Menu inputMenu)
{
this.mMenu = inputMenu;
public boolean onCreateOptionsMenu(Menu inputMenu) {
getMenuInflater().inflate(R.menu.main_menu, inputMenu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null)
{
SearchView searchView = (SearchView) inputMenu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(false);
if (searchManager != null) {
mSearchView = (SearchView) inputMenu.findItem(R.id.action_search).getActionView();
mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
mSearchView.setSubmitButtonEnabled(false);
searchView.setOnCloseListener(() -> {
mSearchView.setOnCloseListener(() -> {
invalidateOptionsMenu();
return false;
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query)
{
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText)
{
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;
updateLoyaltyCardList(
mFilter,
currentTab != null ? currentTab.getTag() : null
);
updateLoyaltyCardList();
return true;
}
@@ -473,52 +502,107 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
@Override
public boolean onOptionsItemSelected(MenuItem inputItem)
{
public boolean onOptionsItemSelected(MenuItem inputItem) {
int id = inputItem.getItemId();
if (id == R.id.action_manage_groups)
{
if (id == R.id.action_unfold) {
boolean shouldShow = !mAdapter.showingDetails();
if (shouldShow) {
inputItem.setIcon(R.drawable.ic_baseline_unfold_less_24);
inputItem.setTitle(R.string.action_hide_details);
} else {
inputItem.setIcon(R.drawable.ic_baseline_unfold_more_24);
inputItem.setTitle(R.string.action_show_details);
}
mAdapter.showDetails(shouldShow);
return true;
}
if (id == R.id.action_sort) {
TabLayout.Tab tab = ((TabLayout) findViewById(R.id.groups)).getTabAt(selectedTab);
AtomicInteger currentIndex = new AtomicInteger();
List<DBHelper.LoyaltyCardOrder> loyaltyCardOrders = Arrays.asList(DBHelper.LoyaltyCardOrder.values());
for (int i = 0; i < loyaltyCardOrders.size(); i++) {
if (mOrder == loyaltyCardOrders.get(i)) {
currentIndex.set(i);
break;
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(R.string.sort_by);
final View customLayout = getLayoutInflater().inflate(R.layout.sorting_option, null);
builder.setView(customLayout);
CheckBox ch = (CheckBox) customLayout.findViewById(R.id.checkBox_reverse);
ch.setChecked(mOrderDirection == DBHelper.LoyaltyCardOrderDirection.Descending);
builder.setSingleChoiceItems(R.array.sort_types_array, currentIndex.get(), (dialog, which) -> currentIndex.set(which));
builder.setPositiveButton(R.string.sort, (dialog, which) -> {
if (ch.isChecked()) {
setSort(loyaltyCardOrders.get(currentIndex.get()), DBHelper.LoyaltyCardOrderDirection.Descending);
} else {
setSort(loyaltyCardOrders.get(currentIndex.get()), DBHelper.LoyaltyCardOrderDirection.Ascending);
}
dialog.dismiss();
});
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
return true;
}
if (id == R.id.action_manage_groups) {
Intent i = new Intent(getApplicationContext(), ManageGroupsActivity.class);
startActivityForResult(i, Utils.MAIN_REQUEST);
startActivity(i);
return true;
}
if (id == R.id.action_import_export)
{
if (id == R.id.action_import_export) {
Intent i = new Intent(getApplicationContext(), ImportExportActivity.class);
startActivityForResult(i, Utils.MAIN_REQUEST);
startActivity(i);
return true;
}
if (id == R.id.action_settings)
{
if (id == R.id.action_settings) {
Intent i = new Intent(getApplicationContext(), SettingsActivity.class);
startActivityForResult(i, Utils.MAIN_REQUEST);
mSettingsLauncher.launch(i);
return true;
}
if(id == R.id.action_privacy_policy)
{
openPrivacyPolicy();
return true;
}
if (id == R.id.action_about)
{
if (id == R.id.action_about) {
Intent i = new Intent(getApplicationContext(), AboutActivity.class);
startActivityForResult(i, Utils.MAIN_REQUEST);
startActivity(i);
return true;
}
return super.onOptionsItemSelected(inputItem);
}
protected static boolean isDarkModeEnabled(Context inputContext)
{
Configuration config = inputContext.getResources().getConfiguration();
int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
return (currentNightMode == Configuration.UI_MODE_NIGHT_YES);
private void setSort(DBHelper.LoyaltyCardOrder order, DBHelper.LoyaltyCardOrderDirection direction) {
// Update values
mOrder = order;
mOrderDirection = direction;
// Store in Shared Preference to restore next app launch
SharedPreferences sortPref = getApplicationContext().getSharedPreferences(
getString(R.string.sharedpreference_sort),
Context.MODE_PRIVATE);
SharedPreferences.Editor sortPrefEditor = sortPref.edit();
sortPrefEditor.putString(getString(R.string.sharedpreference_sort_order), order.name());
sortPrefEditor.putString(getString(R.string.sharedpreference_sort_direction), direction.name());
sortPrefEditor.apply();
// Update card list
updateLoyaltyCardList();
}
@Override
@@ -546,6 +630,12 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
@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");
@@ -561,9 +651,10 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
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()) {
@@ -577,6 +668,7 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
// Swipe left
if (velocityX > 150) {
Log.d("onFling", "Left Swipe detected " + velocityX);
Integer nextTab = currentTab - 1;
if (nextTab < 0) {
@@ -592,22 +684,18 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
@Override
public void onRowLongClicked(int inputPosition)
{
public void onRowLongClicked(int inputPosition) {
enableActionMode(inputPosition);
}
private void enableActionMode(int inputPosition)
{
if (mCurrentActionMode == null)
{
private void enableActionMode(int inputPosition) {
if (mCurrentActionMode == null) {
mCurrentActionMode = startSupportActionMode(mCurrentActionModeCallback);
}
toggleSelection(inputPosition);
}
private void toggleSelection(int inputPosition)
{
private void toggleSelection(int inputPosition) {
mAdapter.toggleSelection(inputPosition);
int count = mAdapter.getSelectedItemCount();
@@ -630,29 +718,25 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
@Override
public void onIconClicked(int inputPosition)
{
if (mCurrentActionMode == null)
{
mCurrentActionMode = startSupportActionMode(mCurrentActionModeCallback);
}
toggleSelection(inputPosition);
}
@Override
public void onRowClicked(int inputPosition)
{
if (mAdapter.getSelectedItemCount() > 0)
{
public void onRowClicked(int inputPosition) {
if (mAdapter.getSelectedItemCount() > 0) {
enableActionMode(inputPosition);
}
else
{
Cursor selected = mAdapter.getCursor();
selected.moveToPosition(inputPosition);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
} else {
// FIXME
//
// There is a really nasty edge case that can happen when someone taps a card but right
// after it swipes (very small window, hard to reproduce). The cursor gets replaced and
// may not have a card at the ID number that is returned from onRowClicked.
//
// The proper fix, obviously, would involve makes sure an onFling can't happen while a
// click is being processed. Sadly, I have not yet found a way to make that possible.
LoyaltyCard loyaltyCard;
try {
loyaltyCard = mAdapter.getCard(inputPosition);
} catch (CursorIndexOutOfBoundsException e) {
Log.w(TAG, "Prevented crash from tap + swipe on ID " + inputPosition + ": " + e);
return;
}
Intent i = new Intent(this, LoyaltyCardViewActivity.class);
i.setAction("");
@@ -660,9 +744,9 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
b.putInt("id", loyaltyCard.id);
i.putExtras(b);
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard, i);
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard);
startActivityForResult(i, Utils.MAIN_REQUEST);
startActivity(i);
}
}
}
}
@@ -0,0 +1,219 @@
package protect.card_locker;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
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 {
private SQLiteDatabase mDatabase;
private ManageGroupCursorAdapter mAdapter;
private final String SAVE_INSTANCE_ADAPTER_STATE = "adapterState";
private final String SAVE_INSTANCE_CURRENT_GROUP_NAME = "currentGroupName";
protected Group mGroup = null;
private RecyclerView mCardList;
private TextView mHelpText;
private EditText mGroupNameText;
private boolean mGroupNameNotInUse;
@Override
protected void onCreate(Bundle inputSavedInstanceState) {
super.onCreate(inputSavedInstanceState);
setContentView(R.layout.activity_manage_group);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mDatabase = new DBHelper(this).getWritableDatabase();
mHelpText = findViewById(R.id.helpText);
mCardList = findViewById(R.id.list);
FloatingActionButton saveButton = findViewById(R.id.fabSave);
mGroupNameText = findViewById(R.id.editTextGroupName);
mGroupNameText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
mGroupNameNotInUse = true;
mGroupNameText.setError(null);
String currentGroupName = mGroupNameText.getText().toString().trim();
if (currentGroupName.length() == 0) {
mGroupNameText.setError(getResources().getText(R.string.group_name_is_empty));
return;
}
if (!mGroup._id.equals(currentGroupName)) {
if (DBHelper.getGroup(mDatabase, currentGroupName) != null) {
mGroupNameNotInUse = false;
mGroupNameText.setError(getResources().getText(R.string.group_name_already_in_use));
} else {
mGroupNameNotInUse = true;
}
}
}
});
Intent intent = getIntent();
String groupId = intent.getStringExtra("group");
if (groupId == null) {
throw (new IllegalArgumentException("this activity expects a group loaded into it's intent"));
}
Log.d("groupId", "groupId: " + groupId);
mGroup = DBHelper.getGroup(mDatabase, groupId);
if (mGroup == null) {
throw (new IllegalArgumentException("cannot load group " + groupId + " from database"));
}
mGroupNameText.setText(mGroup._id);
setTitle(getString(R.string.editGroup, mGroup._id));
mAdapter = new ManageGroupCursorAdapter(this, null, this, mGroup);
mCardList.setAdapter(mAdapter);
registerForContextMenu(mCardList);
if (inputSavedInstanceState != null) {
mAdapter.importInGroupState(integerArrayToAdapterState(inputSavedInstanceState.getIntegerArrayList(SAVE_INSTANCE_ADAPTER_STATE)));
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);
saveButton.setOnClickListener(v -> {
String currentGroupName = mGroupNameText.getText().toString().trim();
if (!currentGroupName.equals(mGroup._id)) {
if (currentGroupName.length() == 0) {
Toast.makeText(getApplicationContext(), R.string.group_name_is_empty, Toast.LENGTH_SHORT).show();
return;
}
if (!mGroupNameNotInUse) {
Toast.makeText(getApplicationContext(), R.string.group_name_already_in_use, Toast.LENGTH_SHORT).show();
return;
}
}
mAdapter.commitToDatabase();
if (!currentGroupName.equals(mGroup._id)) {
DBHelper.updateGroup(mDatabase, mGroup._id, currentGroupName);
}
Toast.makeText(getApplicationContext(), R.string.group_updated, Toast.LENGTH_SHORT).show();
finish();
});
// this setText is here because content_main.xml is reused from main activity
mHelpText.setText(getResources().getText(R.string.noGiftCardsGroup));
updateLoyaltyCardList();
}
private ArrayList<Integer> adapterStateToIntegerArray(HashMap<Integer, Boolean> adapterState) {
ArrayList<Integer> ret = new ArrayList<>(adapterState.size() * 2);
for (Map.Entry<Integer, Boolean> entry : adapterState.entrySet()) {
ret.add(entry.getKey());
ret.add(entry.getValue() ? 1 : 0);
}
return ret;
}
private HashMap<Integer, Boolean> integerArrayToAdapterState(ArrayList<Integer> in) {
HashMap<Integer, Boolean> ret = new HashMap<>();
if (in.size() % 2 != 0) {
throw (new RuntimeException("failed restoring adapterState from integer array list"));
}
for (int i = 0; i < in.size(); i += 2) {
ret.put(in.get(i), in.get(i + 1) == 1);
}
return ret;
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putIntegerArrayList(SAVE_INSTANCE_ADAPTER_STATE, adapterStateToIntegerArray(mAdapter.exportInGroupState()));
outState.putString(SAVE_INSTANCE_CURRENT_GROUP_NAME, mGroupNameText.getText().toString());
}
private void updateLoyaltyCardList() {
mAdapter.swapCursor(DBHelper.getLoyaltyCardCursor(mDatabase));
if (mAdapter.getItemCount() == 0) {
mCardList.setVisibility(View.GONE);
mHelpText.setVisibility(View.VISIBLE);
} else {
mCardList.setVisibility(View.VISIBLE);
mHelpText.setVisibility(View.GONE);
}
}
private void leaveWithoutSaving() {
if (hasChanged()) {
AlertDialog.Builder builder = new AlertDialog.Builder(ManageGroupActivity.this);
builder.setTitle(R.string.leaveWithoutSaveTitle);
builder.setMessage(R.string.leaveWithoutSaveConfirmation);
builder.setPositiveButton(R.string.confirm, (dialog, which) -> finish());
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
} else {
finish();
}
}
@Override
public void onBackPressed() {
leaveWithoutSaving();
}
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
private boolean hasChanged() {
return mAdapter.hasChanged() || !mGroup._id.equals(mGroupNameText.getText().toString().trim());
}
@Override
public void onRowLongClicked(int inputPosition) {
mAdapter.toggleSelection(inputPosition);
}
@Override
public void onRowClicked(int inputPosition) {
mAdapter.toggleSelection(inputPosition);
}
}
@@ -0,0 +1,111 @@
package protect.card_locker;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.recyclerview.widget.RecyclerView;
public class ManageGroupCursorAdapter extends LoyaltyCardCursorAdapter {
private HashMap<Integer, Integer> mIndexCardMap;
private HashMap<Integer, Boolean> mInGroupOverlay;
private HashMap<Integer, Boolean> mIsLoyaltyCardInGroupCache;
private HashMap<Integer, List<Group>> mGetGroupCache;
final private Group mGroup;
final private SQLiteDatabase mDatabase;
public ManageGroupCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener, Group group) {
super(inputContext, inputCursor, inputListener);
mGroup = new Group(group._id, group.order);
mInGroupOverlay = new HashMap<>();
mDatabase = new DBHelper(inputContext).getWritableDatabase();
}
@Override
public void swapCursor(Cursor inputCursor) {
super.swapCursor(inputCursor);
mIndexCardMap = new HashMap<>();
mIsLoyaltyCardInGroupCache = new HashMap<>();
mGetGroupCache = new HashMap<>();
}
@Override
public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor inputCursor) {
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(inputCursor);
Boolean overlayValue = mInGroupOverlay.get(loyaltyCard.id);
if ((overlayValue != null ? overlayValue : isLoyaltyCardInGroup(loyaltyCard.id))) {
mAnimationItemsIndex.put(inputCursor.getPosition(), true);
mSelectedItems.put(inputCursor.getPosition(), true);
}
mIndexCardMap.put(inputCursor.getPosition(), loyaltyCard.id);
super.onBindViewHolder(inputHolder, inputCursor);
}
private List<Group> getGroups(int cardId) {
List<Group> cache = mGetGroupCache.get(cardId);
if (cache != null) {
return cache;
}
List<Group> groups = DBHelper.getLoyaltyCardGroups(mDatabase, cardId);
mGetGroupCache.put(cardId, groups);
return groups;
}
private boolean isLoyaltyCardInGroup(int cardId) {
Boolean cache = mIsLoyaltyCardInGroupCache.get(cardId);
if (cache != null) {
return cache;
}
List<Group> groups = getGroups(cardId);
if (groups.contains(mGroup)) {
mIsLoyaltyCardInGroupCache.put(cardId, true);
return true;
}
mIsLoyaltyCardInGroupCache.put(cardId, false);
return false;
}
@Override
public void toggleSelection(int inputPosition) {
super.toggleSelection(inputPosition);
Integer cardId = mIndexCardMap.get(inputPosition);
if (cardId == null) {
throw (new RuntimeException("cardId should not be null here"));
}
Boolean overlayValue = mInGroupOverlay.get(cardId);
if (overlayValue == null) {
mInGroupOverlay.put(cardId, !isLoyaltyCardInGroup(cardId));
} else {
mInGroupOverlay.remove(cardId);
}
}
public boolean hasChanged() {
return mInGroupOverlay.size() > 0;
}
public void commitToDatabase() {
for (Map.Entry<Integer, Boolean> entry : mInGroupOverlay.entrySet()) {
int cardId = entry.getKey();
List<Group> groups = getGroups(cardId);
if (entry.getValue()) {
groups.add(mGroup);
} else {
groups.remove(mGroup);
}
DBHelper.setLoyaltyCardGroups(mDatabase, cardId, groups);
}
}
public void importInGroupState(HashMap<Integer, Boolean> cardIdInGroupMap) {
mInGroupOverlay = new HashMap<>(cardIdInGroupMap);
}
public HashMap<Integer, Boolean> exportInGroupState() {
return new HashMap<>(mInGroupOverlay);
}
}
@@ -1,59 +1,72 @@
package protect.card_locker;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.InputType;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import java.util.List;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class ManageGroupsActivity extends AppCompatActivity
{
public class ManageGroupsActivity extends CatimaAppCompatActivity implements GroupCursorAdapter.GroupAdapterListener {
private static final String TAG = "Catima";
private final DBHelper db = new DBHelper(this);
private SQLiteDatabase mDatabase;
private TextView mHelpText;
private RecyclerView mGroupList;
GroupCursorAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.groups);
setContentView(R.layout.manage_groups_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
updateGroupList();
mDatabase = new DBHelper(this).getWritableDatabase();
}
@Override
protected void onResume() {
super.onResume();
updateGroupList();
FloatingActionButton addButton = findViewById(R.id.fabAdd);
ExtendedFloatingActionButton addButton = findViewById(R.id.fabAdd);
addButton.setOnClickListener(v -> createGroup());
addButton.bringToFront();
mGroupList = findViewById(R.id.list);
mHelpText = findViewById(R.id.helpText);
// Init group list
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
mGroupList.setLayoutManager(mLayoutManager);
mGroupList.setItemAnimator(new DefaultItemAnimator());
mAdapter = new GroupCursorAdapter(this, null, this);
mGroupList.setAdapter(mAdapter);
updateGroupList();
}
@Override
@@ -61,33 +74,21 @@ public class ManageGroupsActivity extends AppCompatActivity
super.onBackPressed();
}
private void updateGroupList()
{
final ListView groupList = findViewById(R.id.list);
final TextView helpText = findViewById(R.id.helpText);
final DBHelper db = new DBHelper(this);
private void updateGroupList() {
mAdapter.swapCursor(DBHelper.getGroupCursor(mDatabase));
if(db.getGroupCount() > 0)
{
groupList.setVisibility(View.VISIBLE);
helpText.setVisibility(View.GONE);
}
else
{
groupList.setVisibility(View.GONE);
helpText.setVisibility(View.VISIBLE);
if (DBHelper.getGroupCount(mDatabase) == 0) {
mGroupList.setVisibility(View.GONE);
mHelpText.setVisibility(View.VISIBLE);
return;
}
Cursor groupCursor = db.getGroupCursor();
final GroupCursorAdapter adapter = new GroupCursorAdapter(this, groupCursor);
groupList.setAdapter(adapter);
registerForContextMenu(groupList);
mGroupList.setVisibility(View.VISIBLE);
mHelpText.setVisibility(View.GONE);
}
private void invalidateHomescreenActiveTab()
{
private void invalidateHomescreenActiveTab() {
SharedPreferences activeTabPref = getApplicationContext().getSharedPreferences(
getString(R.string.sharedpreference_active_tab),
Context.MODE_PRIVATE);
@@ -97,8 +98,7 @@ public class ManageGroupsActivity extends AppCompatActivity
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
@@ -108,69 +108,6 @@ public class ManageGroupsActivity extends AppCompatActivity
return super.onOptionsItemSelected(item);
}
public void moveGroupUp(View view) {
moveGroup(view, true);
}
public void moveGroupDown(View view) {
moveGroup(view, false);
}
public void editGroup(View view) {
final String groupName = getGroupname(view);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.enter_group_name);
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setText(groupName);
builder.setView(input);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
db.updateGroup(groupName, input.getText().toString());
updateGroupList();
}
});
builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog dialog = builder.create();
dialog.show();
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
input.requestFocus();
}
public void deleteGroup(View view) {
final String groupName = getGroupname(view);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.deleteConfirmationGroup);
builder.setMessage(groupName);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
db.deleteGroup(groupName);
updateGroupList();
// Delete may change ordering, so invalidate
invalidateHomescreenActiveTab();
}
});
builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
private void createGroup() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.enter_group_name);
@@ -178,51 +115,37 @@ public class ManageGroupsActivity extends AppCompatActivity
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
db.insertGroup(input.getText().toString());
updateGroupList();
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;
}
});
builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
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);
updateGroupList();
});
builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel());
AlertDialog dialog = builder.create();
dialog.show();
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
input.requestFocus();
}
private String getGroupname(View view) {
LinearLayout parentRow = (LinearLayout) view.getParent().getParent();
TextView groupNameTextView = parentRow.findViewById(R.id.name);
private String getGroupName(View view) {
TextView groupNameTextView = view.findViewById(R.id.name);
return (String) groupNameTextView.getText();
}
private void moveGroup(View view, boolean up) {
final String groupName = getGroupname(view);
List<Group> groups = DBHelper.getGroups(mDatabase);
final String groupName = getGroupName(view);
List<Group> groups = db.getGroups();
int currentIndex = -1;
Integer newIndex;
// Get current index in group list
for (int i = 0; i < groups.size(); i++) {
if (groups.get(i)._id.equals(groupName)) {
currentIndex = i;
break;
}
}
if (currentIndex == -1) {
throw new IndexOutOfBoundsException();
}
int currentIndex = DBHelper.getGroup(mDatabase, groupName).order;
int newIndex;
// Reinsert group in correct position
if (up) {
@@ -240,7 +163,7 @@ public class ManageGroupsActivity extends AppCompatActivity
groups.add(newIndex, group);
// Update database
db.reorderGroups(groups);
DBHelper.reorderGroups(mDatabase, groups);
// Update UI
updateGroupList();
@@ -248,4 +171,40 @@ public class ManageGroupsActivity extends AppCompatActivity
// Ordering may have changed, so invalidate
invalidateHomescreenActiveTab();
}
@Override
public void onMoveDownButtonClicked(View view) {
moveGroup(view, false);
}
@Override
public void onMoveUpButtonClicked(View view) {
moveGroup(view, true);
}
@Override
public void onEditButtonClicked(View view) {
Intent intent = new Intent(this, ManageGroupActivity.class);
intent.putExtra("group", getGroupName(view));
startActivity(intent);
}
@Override
public void onDeleteButtonClicked(View view) {
final String groupName = getGroupName(view);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.deleteConfirmationGroup);
builder.setMessage(groupName);
builder.setPositiveButton(getString(R.string.ok), (dialog, which) -> {
DBHelper.deleteGroup(mDatabase, groupName);
updateGroupList();
// Delete may change ordering, so invalidate
invalidateHomescreenActiveTab();
});
builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel());
AlertDialog dialog = builder.create();
dialog.show();
}
}
@@ -9,6 +9,7 @@ import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.Intents;
@@ -19,50 +20,62 @@ 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.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
/**
* Custom Scannner Activity extending from Activity to display a custom layout form scanner view.
*
* <p>
* Based on https://github.com/journeyapps/zxing-android-embedded/blob/0fdfbce9fb3285e985bad9971c5f7c0a7a334e7b/sample/src/main/java/example/zxing/CustomScannerActivity.java
* originally licensed under Apache 2.0
*/
public class ScanActivity extends AppCompatActivity {
public class ScanActivity extends CatimaAppCompatActivity {
private static final String TAG = "Catima";
private CaptureManager capture;
private DecoratedBarcodeView barcodeScannerView;
private String cardId;
private String addGroup;
private boolean torch = false;
private ActivityResultLauncher<Intent> manualAddLauncher;
// can't use the pre-made contract because that launches the file manager for image type instead of gallery
private ActivityResultLauncher<Intent> photoPickerLauncher;
private void extractIntentFields(Intent intent) {
final Bundle b = intent.getExtras();
cardId = b != null ? b.getString("cardId") : null;
cardId = b != null ? b.getString(LoyaltyCardEditActivity.BUNDLE_CARDID) : null;
addGroup = b != null ? b.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) : null;
Log.d(TAG, "Scan activity: id=" + cardId);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.scanCardBarcode);
setContentView(R.layout.scan_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
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);
barcodeScannerView = findViewById(R.id.zxing_barcode_scanner);
// Even though we do the actual decoding with the barcodeScannerView
// CaptureManager needs to be running to show the camera and scanning bar
capture = new CaptureManager(this, barcodeScannerView);
capture = new CatimaCaptureManager(this, barcodeScannerView);
Intent captureIntent = new Intent();
Bundle captureIntentBundle = new Bundle();
captureIntentBundle.putBoolean(Intents.Scan.BEEP_ENABLED, false);
@@ -75,7 +88,10 @@ public class ScanActivity extends AppCompatActivity {
Intent scanResult = new Intent();
Bundle scanResultBundle = new Bundle();
scanResultBundle.putString(BarcodeSelectorActivity.BARCODE_CONTENTS, result.getText());
scanResultBundle.putString(BarcodeSelectorActivity.BARCODE_FORMAT, result.getBarcodeFormat().toString());
scanResultBundle.putString(BarcodeSelectorActivity.BARCODE_FORMAT, result.getBarcodeFormat().name());
if (addGroup != null) {
scanResultBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, addGroup);
}
scanResult.putExtras(scanResultBundle);
ScanActivity.this.setResult(RESULT_OK, scanResult);
finish();
@@ -118,8 +134,7 @@ public class ScanActivity extends AppCompatActivity {
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
public boolean onCreateOptionsMenu(Menu menu) {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
getMenuInflater().inflate(R.menu.scan_menu, menu);
}
@@ -130,15 +145,12 @@ public class ScanActivity extends AppCompatActivity {
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
if (item.getItemId() == android.R.id.home)
{
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
setResult(Activity.RESULT_CANCELED);
finish();
return true;
} else if (item.getItemId() == R.id.action_toggle_flashlight)
{
} else if (item.getItemId() == R.id.action_toggle_flashlight) {
if (torch) {
torch = false;
barcodeScannerView.setTorchOff();
@@ -155,18 +167,26 @@ public class ScanActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
private void handleActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
BarcodeValues barcodeValues;
try {
barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
} catch (NullPointerException e) {
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
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();
@@ -180,12 +200,12 @@ public class ScanActivity extends AppCompatActivity {
b.putString("initialCardId", cardId);
i.putExtras(b);
}
startActivityForResult(i, Utils.SELECT_BARCODE_REQUEST);
manualAddLauncher.launch(i);
}
public void addFromImage(View view) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, Utils.BARCODE_IMPORT_FROM_IMAGE_FILE);
photoPickerLauncher.launch(photoPickerIntent);
}
}
@@ -1,21 +1,26 @@
package protect.card_locker;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
class ShortcutHelper
{
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.ColorUtils;
import androidx.core.graphics.drawable.IconCompat;
class ShortcutHelper {
// Android documentation says that no more than 5 shortcuts
// are supported. However, that may be too many, as not all
// launcher will show all 5. Instead, the number is limited
@@ -23,6 +28,14 @@ class ShortcutHelper
// chance of being shown.
private static final int MAX_SHORTCUTS = 3;
// https://developer.android.com/reference/android/graphics/drawable/AdaptiveIconDrawable.html
private static final int ADAPTIVE_BITMAP_SCALE = 1;
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);
/**
* Add a card to the app shortcuts, and maintain a list of the most
* recently used cards. If there is already a shortcut for the card,
@@ -30,135 +43,117 @@ class ShortcutHelper
* card exceeds the max number of shortcuts, then the least recently
* used card shortcut is discarded.
*/
@TargetApi(25)
static void updateShortcuts(Context context, LoyaltyCard card, Intent intent)
{
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1)
{
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
LinkedList<ShortcutInfo> list = new LinkedList<>(shortcutManager.getDynamicShortcuts());
static void updateShortcuts(Context context, LoyaltyCard card) {
LinkedList<ShortcutInfoCompat> list = new LinkedList<>(ShortcutManagerCompat.getDynamicShortcuts(context));
DBHelper dbHelper = new DBHelper(context);
SQLiteDatabase database = new DBHelper(context).getReadableDatabase();
String shortcutId = Integer.toString(card.id);
String shortcutId = Integer.toString(card.id);
// Sort the shortcuts by rank, so working with the relative order will be easier.
// This sorts so that the lowest rank is first.
Collections.sort(list, new Comparator<ShortcutInfo>()
{
@Override
public int compare(ShortcutInfo o1, ShortcutInfo o2)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1)
{
return o1.getRank() - o2.getRank();
}
else
{
return 0;
}
}
});
// Sort the shortcuts by rank, so working with the relative order will be easier.
// This sorts so that the lowest rank is first.
Collections.sort(list, Comparator.comparingInt(ShortcutInfoCompat::getRank));
Integer foundIndex = null;
Integer foundIndex = null;
for(int index = 0; index < list.size(); index++)
{
if(list.get(index).getId().equals(shortcutId))
{
// Found the item already
foundIndex = index;
break;
}
for (int index = 0; index < list.size(); index++) {
if (list.get(index).getId().equals(shortcutId)) {
// Found the item already
foundIndex = index;
break;
}
}
if (foundIndex != null) {
// If the item is already found, then the list needs to be
// reordered, so that the selected item now has the lowest
// rank, thus letting it survive longer.
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();
}
if(foundIndex != null)
{
// If the item is already found, then the list needs to be
// reordered, so that the selected item now has the lowest
// rank, thus letting it survive longer.
ShortcutInfo 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();
}
ShortcutInfoCompat shortcut = createShortcutBuilder(context, card).build();
ShortcutInfo shortcut = new ShortcutInfo.Builder(context, Integer.toString(card.id))
.setShortLabel(card.store)
.setLongLabel(card.store)
.setIntent(intent)
list.addFirst(shortcut);
}
LinkedList<ShortcutInfoCompat> finalList = new LinkedList<>();
// The ranks are now updated; the order in the list is the rank.
for (int index = 0; index < list.size(); index++) {
ShortcutInfoCompat prevShortcut = list.get(index);
LoyaltyCard loyaltyCard = DBHelper.getLoyaltyCard(database, Integer.parseInt(prevShortcut.getId()));
ShortcutInfoCompat updatedShortcut = createShortcutBuilder(context, loyaltyCard)
.setRank(index)
.build();
list.addFirst(shortcut);
}
LinkedList<ShortcutInfo> finalList = new LinkedList<>();
// The ranks are now updated; the order in the list is the rank.
for(int index = 0; index < list.size(); index++)
{
ShortcutInfo prevShortcut = list.get(index);
Intent shortcutIntent = prevShortcut.getIntent();
Bitmap iconBitmap = Utils.generateIcon(context, dbHelper.getLoyaltyCard(Integer.parseInt(prevShortcut.getId())), true).getLetterTile();
Icon icon;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
icon = Icon.createWithAdaptiveBitmap(iconBitmap);
} else {
icon = Icon.createWithBitmap(iconBitmap);
}
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
shortcutIntent.setFlags(shortcutIntent.getFlags() | Intent.FLAG_ACTIVITY_SINGLE_TOP);
ShortcutInfo updatedShortcut = new ShortcutInfo.Builder(context, prevShortcut.getId())
.setShortLabel(prevShortcut.getShortLabel())
.setLongLabel(prevShortcut.getLongLabel())
.setIntent(shortcutIntent)
.setIcon(icon)
.setRank(index)
.build();
finalList.addLast(updatedShortcut);
}
shortcutManager.setDynamicShortcuts(finalList);
finalList.addLast(updatedShortcut);
}
ShortcutManagerCompat.setDynamicShortcuts(context, finalList);
}
/**
* Remove the given card id from the app shortcuts, if such a
* shortcut exists.
*/
@TargetApi(25)
static void removeShortcut(Context context, int cardId)
{
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1)
{
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
List<ShortcutInfo> list = shortcutManager.getDynamicShortcuts();
static void removeShortcut(Context context, int cardId) {
List<ShortcutInfoCompat> list = ShortcutManagerCompat.getDynamicShortcuts(context);
String shortcutId = Integer.toString(cardId);
String shortcutId = Integer.toString(cardId);
for(int index = 0; index < list.size(); index++)
{
if(list.get(index).getId().equals(shortcutId))
{
list.remove(index);
break;
}
for (int index = 0; index < list.size(); index++) {
if (list.get(index).getId().equals(shortcutId)) {
list.remove(index);
break;
}
shortcutManager.setDynamicShortcuts(list);
}
ShortcutManagerCompat.setDynamicShortcuts(context, list);
}
static @NotNull
Bitmap createAdaptiveBitmap(@NotNull Bitmap in, int paddingColor) {
Bitmap ret = Bitmap.createBitmap(ADAPTIVE_BITMAP_SIZE, ADAPTIVE_BITMAP_SIZE, Bitmap.Config.ARGB_8888);
Canvas output = new Canvas(ret);
output.drawColor(ColorUtils.compositeColors(PADDING_COLOR_OVERLAY, paddingColor));
Bitmap resized = Utils.resizeBitmap(in, ADAPTIVE_BITMAP_IMAGE_SIZE);
output.drawBitmap(resized, (ADAPTIVE_BITMAP_SIZE - resized.getWidth()) / 2f, (ADAPTIVE_BITMAP_SIZE - resized.getHeight()) / 2f, null);
return ret;
}
static ShortcutInfoCompat.Builder createShortcutBuilder(Context context, LoyaltyCard loyaltyCard) {
Intent intent = new Intent(context, LoyaltyCardViewActivity.class);
intent.setAction(Intent.ACTION_MAIN);
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final Bundle bundle = new Bundle();
bundle.putInt("id", loyaltyCard.id);
bundle.putBoolean("view", true);
intent.putExtras(bundle);
Bitmap iconBitmap = Utils.retrieveCardImage(context, loyaltyCard.id, ImageLocationType.icon);
if (iconBitmap == null) {
iconBitmap = Utils.generateIcon(context, loyaltyCard, true).getLetterTile();
} else {
iconBitmap = createAdaptiveBitmap(iconBitmap, loyaltyCard.headerColor == null ? PADDING_COLOR : loyaltyCard.headerColor);
}
IconCompat icon = IconCompat.createWithAdaptiveBitmap(iconBitmap);
return new ShortcutInfoCompat.Builder(context, Integer.toString(loyaltyCard.id))
.setShortLabel(loyaltyCard.store)
.setLongLabel(loyaltyCard.store)
.setIntent(intent)
.setIcon(icon);
}
}
@@ -0,0 +1,18 @@
package protect.card_locker;
import android.text.Editable;
import android.text.TextWatcher;
public class SimpleTextWatcher implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
}
+165 -27
View File
@@ -3,13 +3,18 @@ package protect.card_locker;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageDecoder;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.Build;
import android.os.LocaleList;
import android.provider.MediaStore;
import android.util.Log;
import android.util.TypedValue;
import android.widget.Toast;
import com.google.zxing.BinaryBitmap;
@@ -21,6 +26,7 @@ import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -31,9 +37,15 @@ import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.graphics.ColorUtils;
import androidx.exifinterface.media.ExifInterface;
import protect.card_locker.preferences.Settings;
public class Utils {
private static final String TAG = "Catima";
@@ -45,12 +57,15 @@ public class Utils {
public static final int BARCODE_IMPORT_FROM_IMAGE_FILE = 4;
public static final int CARD_IMAGE_FROM_CAMERA_FRONT = 5;
public static final int CARD_IMAGE_FROM_CAMERA_BACK = 6;
public static final int CARD_IMAGE_FROM_FILE_FRONT = 7;
public static final int CARD_IMAGE_FROM_FILE_BACK = 8;
public static final int CARD_IMAGE_FROM_CAMERA_ICON = 7;
public static final int CARD_IMAGE_FROM_FILE_FRONT = 8;
public static final int CARD_IMAGE_FROM_FILE_BACK = 9;
public static final int CARD_IMAGE_FROM_FILE_ICON = 10;
static final double LUMINANCE_MIDPOINT = 0.5;
static final int BITMAP_SIZE_BIG = 512;
static final int BITMAP_SIZE_SMALL = 512;
static final int BITMAP_SIZE_BIG = 2048;
static public LetterBitmap generateIcon(Context context, LoyaltyCard loyaltyCard, boolean forShortcut) {
return generateIcon(context, loyaltyCard.store, loyaltyCard.headerColor, forShortcut);
@@ -72,7 +87,7 @@ public class Utils {
tileLetterFontSize = context.getResources().getDimensionPixelSize(R.dimen.tileLetterFontSize);
}
int pixelSize = context.getResources().getDimensionPixelSize(R.dimen.cardThumbnailSize);
int pixelSize = context.getResources().getDimensionPixelSize(R.dimen.tileLetterImageSize);
if (backgroundColor == null) {
backgroundColor = LetterBitmap.getDefaultColor(context, store);
@@ -99,7 +114,12 @@ public class Utils {
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), intent.getData());
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());
}
} catch (IOException e) {
Log.e(TAG, "Error getting data from image file");
e.printStackTrace();
@@ -140,6 +160,21 @@ public class Utils {
}
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++) {
try {
return Utils.getBarcodeFromBitmapReal(bitmap);
} catch (OutOfMemoryError e) {
Log.w(TAG, "Ran OOM in getBarcodeFromBitmap! Trying again with smaller picture! Retry " + i + " of 10.");
bitmap = Bitmap.createScaledBitmap(bitmap, (int) Math.round(0.75 * bitmap.getWidth()), (int) Math.round(0.75 * bitmap.getHeight()), false);
}
}
// Give up
return new BarcodeValues(null, null);
}
static private BarcodeValues getBarcodeFromBitmapReal(Bitmap bitmap) {
// In order to decode it, the Bitmap must first be converted into a pixel array...
int[] intArray = new int[bitmap.getWidth() * bitmap.getHeight()];
bitmap.getPixels(intArray, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
@@ -174,7 +209,7 @@ public class Utils {
if (currency == null) {
numberFormat.setMaximumFractionDigits(0);
return context.getString(R.string.balancePoints, numberFormat.format(value));
return context.getResources().getQuantityString(R.plurals.balancePoints, value.intValue(), numberFormat.format(value));
}
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
@@ -237,22 +272,20 @@ public class Utils {
return bos.toByteArray();
}
static public Bitmap resizeBitmap(Bitmap bitmap) {
static public Bitmap resizeBitmap(Bitmap bitmap, double maxSize) {
if (bitmap == null) {
return null;
}
Integer maxSize = BITMAP_SIZE_BIG;
Integer width = bitmap.getWidth();
Integer height = bitmap.getHeight();
double width = bitmap.getWidth();
double height = bitmap.getHeight();
if (height > width) {
Integer scale = height / maxSize;
double scale = height / maxSize;
height = maxSize;
width = width / scale;
} else if (width > height) {
Integer scale = width / maxSize;
double scale = width / maxSize;
width = maxSize;
height = height / scale;
} else {
@@ -260,7 +293,7 @@ public class Utils {
width = maxSize;
}
return Bitmap.createScaledBitmap(bitmap, width, height, true);
return Bitmap.createScaledBitmap(bitmap, (int) Math.round(width), (int) Math.round(height), true);
}
static public Bitmap rotateBitmap(Bitmap bitmap, ExifInterface exifInterface) {
@@ -286,16 +319,20 @@ public class Utils {
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
static public String getCardImageFileName(int loyaltyCardId, boolean front) {
static public String getCardImageFileName(int loyaltyCardId, ImageLocationType type) {
StringBuilder cardImageFileNameBuilder = new StringBuilder();
cardImageFileNameBuilder.append("card_");
cardImageFileNameBuilder.append(loyaltyCardId);
cardImageFileNameBuilder.append("_");
if (front) {
if (type == ImageLocationType.front) {
cardImageFileNameBuilder.append("front");
} else {
} else if (type == ImageLocationType.back) {
cardImageFileNameBuilder.append("back");
} else if (type == ImageLocationType.icon) {
cardImageFileNameBuilder.append("icon");
} else {
throw new IllegalArgumentException("Unknown image type");
}
cardImageFileNameBuilder.append(".png");
@@ -313,8 +350,8 @@ public class Utils {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
}
static public void saveCardImage(Context context, Bitmap bitmap, int loyaltyCardId, boolean front) throws FileNotFoundException {
saveCardImage(context, bitmap, getCardImageFileName(loyaltyCardId, front));
static public void saveCardImage(Context context, Bitmap bitmap, int loyaltyCardId, ImageLocationType type) throws FileNotFoundException {
saveCardImage(context, bitmap, getCardImageFileName(loyaltyCardId, type));
}
static public Bitmap retrieveCardImage(Context context, String fileName) {
@@ -328,19 +365,120 @@ public class Utils {
return BitmapFactory.decodeStream(in);
}
static public Bitmap retrieveCardImage(Context context, int loyaltyCardId, boolean front) {
return retrieveCardImage(context, getCardImageFileName(loyaltyCardId, front));
static public Bitmap retrieveCardImage(Context context, int loyaltyCardId, ImageLocationType type) {
return retrieveCardImage(context, getCardImageFileName(loyaltyCardId, type));
}
static public Object hashmapGetOrDefault(HashMap hashMap, Object key, Object defaultValue, Class keyType) {
Object value = hashMap.get(keyType.cast(key));
static public <T, U> U mapGetOrDefault(Map<T, U> map, T key, U defaultValue) {
U value = map.get(key);
if (value == null) {
return defaultValue;
}
return value;
}
static public Object hashmapGetOrDefault(HashMap hashMap, String key, Object defaultValue) {
return hashmapGetOrDefault(hashMap, key, defaultValue, String.class);
static public Locale stringToLocale(String localeString) {
String[] localeParts = localeString.split("-");
if (localeParts.length == 1) {
return new Locale(localeParts[0]);
}
if (localeParts[1].startsWith("r")) {
localeParts[1] = localeParts[1].substring(1);
}
return new Locale(localeParts[0], localeParts[1]);
}
static public Context updateBaseContextLocale(Context context) {
Settings settings = new Settings(context);
Locale chosenLocale = settings.getLocale();
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
configuration.locale = chosenLocale != null ? chosenLocale : Locale.getDefault();
res.updateConfiguration(configuration, res.getDisplayMetrics());
return context;
}
LocaleList localeList = chosenLocale != null ? new LocaleList(chosenLocale) : LocaleList.getDefault();
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
return context.createConfigurationContext(configuration);
}
static public long getUnixTime() {
return System.currentTimeMillis() / 1000;
}
static public boolean isDarkModeEnabled(Context inputContext) {
int nightModeSetting = new Settings(inputContext).getTheme();
if (nightModeSetting == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
Configuration config = inputContext.getResources().getConfiguration();
int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
return (currentNightMode == Configuration.UI_MODE_NIGHT_YES);
} else {
return nightModeSetting == AppCompatDelegate.MODE_NIGHT_YES;
}
}
public static File createTempFile(Context context, String name) {
return new File(context.getCacheDir() + "/" + name);
}
public static String saveTempImage(Context context, Bitmap in, String name, Bitmap.CompressFormat format) {
File image = createTempFile(context, name);
try (FileOutputStream out = new FileOutputStream(image)) {
in.compress(format, 100, out);
return image.getAbsolutePath();
} catch (IOException e) {
Log.d("store temp image", "failed writing temp file for temporary image, name: " + name);
return null;
}
}
public static Bitmap loadImage(String path) {
try {
return BitmapFactory.decodeStream(new FileInputStream(path));
} catch (IOException e) {
Log.d("load image", "failed loading image from " + path);
return null;
}
}
public static Bitmap loadTempImage(Context context, String name) {
return loadImage(context.getCacheDir() + "/" + name);
}
// https://stackoverflow.com/a/59324801/8378787
public static int getComplementaryColor(int color) {
int R = color & 255;
int G = (color >> 8) & 255;
int B = (color >> 16) & 255;
int A = (color >> 24) & 255;
R = 255 - R;
G = 255 - G;
B = 255 - B;
return R + (G << 8) + (B << 16) + (A << 24);
}
// replace colors in the current theme
// use before views are inflated, after dynamic color
public static void patchOledDarkTheme(AppCompatActivity activity) {
if (isDarkModeEnabled(activity) && new Settings(activity).getOledDark()) {
activity.getTheme().applyStyle(R.style.DarkBackground, true);
}
}
// XXX android 9 and below has issues with patched theme where the background becomes a
// rendering mess
// use after views are inflated
public static void postPatchOledDarkTheme(AppCompatActivity activity) {
if (isDarkModeEnabled(activity) && new Settings(activity).getOledDark()) {
TypedValue typedValue = new TypedValue();
activity.getTheme().resolveAttribute(android.R.attr.colorBackground, typedValue, true);
activity.findViewById(android.R.id.content).setBackgroundColor(typedValue.data);
}
}
}
@@ -0,0 +1,9 @@
package protect.card_locker.async;
import java.util.concurrent.Callable;
public interface CompatCallable<T> extends Callable<T> {
void onPostExecute(Object result);
void onPreExecute();
}
@@ -0,0 +1,175 @@
package protect.card_locker.async;
import android.os.Handler;
import android.os.Looper;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* AsyncTask has been deprecated so this provides very rudimentary compatibility without
* needing to redo too many Parts.
* <p>
* However this is a much, much more cooperative Behaviour than before so
* the callers need to ensure we do NOT rely on forced cancellation and feed less into the
* ThreadPools so we don't OOM/Overload the Users device
* <p>
* This assumes single-threaded callers.
*/
public class TaskHandler {
public enum TYPE {
BARCODE,
IMPORT,
EXPORT
}
HashMap<TYPE, ThreadPoolExecutor> executors = generateExecutors();
final private HashMap<TYPE, LinkedList<Future<?>>> taskList = new HashMap<>();
private final Handler uiHandler = new Handler(Looper.getMainLooper());
private HashMap<TYPE, ThreadPoolExecutor> generateExecutors() {
HashMap<TYPE, ThreadPoolExecutor> initExecutors = new HashMap<>();
for (TYPE type : TYPE.values()) {
replaceExecutor(initExecutors, type, false, false);
}
return initExecutors;
}
/**
* Replaces (or initializes) an Executor with a clean (new) one
*
* @param executors Map Reference
* @param type Which Queue
* @param flushOld attempt shutdown
* @param waitOnOld wait for Termination
*/
private void replaceExecutor(HashMap<TYPE, ThreadPoolExecutor> executors, TYPE type, Boolean flushOld, Boolean waitOnOld) {
ThreadPoolExecutor oldExecutor = executors.get(type);
if (oldExecutor != null) {
if (flushOld) {
oldExecutor.shutdownNow();
}
if (waitOnOld) {
try {
//noinspection ResultOfMethodCallIgnored
oldExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
executors.put(type, (ThreadPoolExecutor) Executors.newCachedThreadPool());
}
/**
* Queue a Pseudo-AsyncTask for execution
*
* @param type Queue
* @param callable PseudoAsyncTask
*/
public void executeTask(TYPE type, CompatCallable<?> callable) {
Runnable runner = () -> {
try {
// Run on the UI Thread
uiHandler.post(callable::onPreExecute);
// Background
final Object result = callable.call();
// Post results on UI Thread so we can show them
uiHandler.post(() -> {
callable.onPostExecute(result);
});
} catch (Exception e) {
e.printStackTrace();
}
};
LinkedList<Future<?>> list = taskList.get(type);
if (list == null) {
list = new LinkedList<>();
}
ThreadPoolExecutor executor = executors.get(type);
if (executor != null) {
Future<?> task = executor.submit(runner);
// Test Queue Cancellation:
// task.cancel(true);
list.push(task);
taskList.put(type, list);
}
}
/**
* This will attempt to cancel a currently running list of Tasks
* Useful to ignore scheduled tasks - but not able to hard-stop tasks that are running
*
* @param type Which Queue to target
* @param forceCancel attempt to close the Queue and force-replace it after
* @param waitForFinish wait and return after the old executor finished. Times out after 5s
* @param waitForCurrentlyRunning wait before cancelling tasks. Useful for tests.
*/
public void flushTaskList(TYPE type, Boolean forceCancel, Boolean waitForFinish, Boolean waitForCurrentlyRunning) {
// Only used for Testing
if (waitForCurrentlyRunning) {
ThreadPoolExecutor oldExecutor = executors.get(type);
if (oldExecutor != null) {
try {
//noinspection ResultOfMethodCallIgnored
oldExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Attempt to cancel known Tasks and clean the List
LinkedList<Future<?>> tasks = taskList.get(type);
if (tasks != null) {
for (Future<?> task : tasks) {
if (!task.isDone() || !task.isCancelled()) {
// Interrupt any Task we can
task.cancel(true);
}
}
}
tasks = new LinkedList<>();
taskList.put(type, tasks);
if (forceCancel || waitForFinish) {
ThreadPoolExecutor oldExecutor = executors.get(type);
if (oldExecutor != null) {
if (forceCancel) {
if (waitForFinish) {
try {
//noinspection ResultOfMethodCallIgnored
oldExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
oldExecutor.shutdownNow();
replaceExecutor(executors, type, true, false);
} else {
try {
//noinspection ResultOfMethodCallIgnored
oldExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
@@ -12,18 +12,13 @@ public class CSVHelpers {
* if it is not null. Otherwise, a FormatException is thrown.
*/
static String extractString(String key, CSVRecord record, String defaultValue)
throws FormatException
{
throws FormatException {
String toReturn = defaultValue;
if(record.isMapped(key))
{
if (record.isMapped(key)) {
toReturn = record.get(key);
}
else
{
if(defaultValue == null)
{
} else {
if (defaultValue == null) {
throw new FormatException("Field not used but expected: " + key);
}
}
@@ -38,25 +33,19 @@ public class CSVHelpers {
* int, a FormatException is thrown.
*/
static Integer extractInt(String key, CSVRecord record, boolean nullIsOk)
throws FormatException
{
if(record.isMapped(key) == false)
{
throws FormatException {
if (record.isMapped(key) == false) {
throw new FormatException("Field not used but expected: " + key);
}
String value = record.get(key);
if(value.isEmpty() && nullIsOk)
{
if (value.isEmpty() && nullIsOk) {
return null;
}
try
{
try {
return Integer.parseInt(record.get(key));
}
catch(NumberFormatException e)
{
} catch (NumberFormatException e) {
throw new FormatException("Failed to parse field: " + key, e);
}
}
@@ -68,25 +57,19 @@ public class CSVHelpers {
* int, a FormatException is thrown.
*/
static Long extractLong(String key, CSVRecord record, boolean nullIsOk)
throws FormatException
{
if(record.isMapped(key) == false)
{
throws FormatException {
if (record.isMapped(key) == false) {
throw new FormatException("Field not used but expected: " + key);
}
String value = record.get(key);
if(value.isEmpty() && nullIsOk)
{
if (value.isEmpty() && nullIsOk) {
return null;
}
try
{
try {
return Long.parseLong(record.get(key));
}
catch(NumberFormatException e)
{
} catch (NumberFormatException e) {
throw new FormatException("Failed to parse field: " + key, e);
}
}
@@ -2,10 +2,12 @@ package protect.card_locker.importexport;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import org.apache.commons.csv.CSVFormat;
@@ -21,6 +23,7 @@ import java.nio.charset.StandardCharsets;
import protect.card_locker.DBHelper;
import protect.card_locker.Group;
import protect.card_locker.ImageLocationType;
import protect.card_locker.LoyaltyCard;
import protect.card_locker.Utils;
@@ -28,25 +31,28 @@ import protect.card_locker.Utils;
* Class for exporting the database into CSV (Comma Separate Values)
* format.
*/
public class CatimaExporter implements Exporter
{
public void exportData(Context context, DBHelper db, OutputStream output) throws IOException, InterruptedException
{
public class CatimaExporter implements Exporter {
public void exportData(Context context, SQLiteDatabase database, OutputStream output, char[] password) throws IOException, InterruptedException {
// Necessary vars
int readLen;
byte[] readBuffer = new byte[InternalZipConstants.BUFF_SIZE];
// Create zip output stream
ZipOutputStream zipOutputStream = new ZipOutputStream(output);
ZipOutputStream zipOutputStream;
if (password != null && password.length > 0) {
zipOutputStream = new ZipOutputStream(output, password);
} else {
zipOutputStream = new ZipOutputStream(output);
}
// Generate CSV
ByteArrayOutputStream catimaOutputStream = new ByteArrayOutputStream();
OutputStreamWriter catimaOutputStreamWriter = new OutputStreamWriter(catimaOutputStream, StandardCharsets.UTF_8);
writeCSV(db, catimaOutputStreamWriter);
writeCSV(database, catimaOutputStreamWriter);
// Add CSV to zip file
ZipParameters csvZipParameters = new ZipParameters();
csvZipParameters.setFileNameInZip("catima.csv");
ZipParameters csvZipParameters = createZipParameters("catima.csv", password);
zipOutputStream.putNextEntry(csvZipParameters);
InputStream csvInputStream = new ByteArrayInputStream(catimaOutputStream.toByteArray());
while ((readLen = csvInputStream.read(readBuffer)) != -1) {
@@ -55,24 +61,17 @@ public class CatimaExporter implements Exporter
zipOutputStream.closeEntry();
// Loop over all cards again
Cursor cardCursor = db.getLoyaltyCardCursor();
while(cardCursor.moveToNext())
{
Cursor cardCursor = DBHelper.getLoyaltyCardCursor(database);
while (cardCursor.moveToNext()) {
// For each card
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor);
// Prepare looping over both front and back image
boolean[] frontValues = new boolean[2];
frontValues[0] = true;
frontValues[1] = false;
// For each image
for (boolean front : frontValues) {
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
// If it exists, add to the .zip file
Bitmap image = Utils.retrieveCardImage(context, card.id, front);
Bitmap image = Utils.retrieveCardImage(context, card.id, imageLocationType);
if (image != null) {
ZipParameters imageZipParameters = new ZipParameters();
imageZipParameters.setFileNameInZip(Utils.getCardImageFileName(card.id, front));
ZipParameters imageZipParameters = createZipParameters(Utils.getCardImageFileName(card.id, imageLocationType), password);
zipOutputStream.putNextEntry(imageZipParameters);
InputStream imageInputStream = new ByteArrayInputStream(Utils.bitmapToByteArray(image));
while ((readLen = imageInputStream.read(readBuffer)) != -1) {
@@ -86,7 +85,17 @@ public class CatimaExporter implements Exporter
zipOutputStream.close();
}
private void writeCSV(DBHelper db, OutputStreamWriter output) throws IOException, InterruptedException {
private ZipParameters createZipParameters(String fileName, char[] password) {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip(fileName);
if (password != null && password.length > 0) {
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
}
return zipParameters;
}
private void writeCSV(SQLiteDatabase database, OutputStreamWriter output) throws IOException, InterruptedException {
CSVPrinter printer = new CSVPrinter(output, CSVFormat.RFC4180);
// Print the version
@@ -97,16 +106,14 @@ public class CatimaExporter implements Exporter
// Print the header for groups
printer.printRecord(DBHelper.LoyaltyCardDbGroups.ID);
Cursor groupCursor = db.getGroupCursor();
Cursor groupCursor = DBHelper.getGroupCursor(database);
while(groupCursor.moveToNext())
{
while (groupCursor.moveToNext()) {
Group group = Group.toGroup(groupCursor);
printer.printRecord(group._id);
if(Thread.currentThread().isInterrupted())
{
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
}
@@ -127,12 +134,12 @@ public class CatimaExporter implements Exporter
DBHelper.LoyaltyCardDbIds.BARCODE_ID,
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE,
DBHelper.LoyaltyCardDbIds.HEADER_COLOR,
DBHelper.LoyaltyCardDbIds.STAR_STATUS);
DBHelper.LoyaltyCardDbIds.STAR_STATUS,
DBHelper.LoyaltyCardDbIds.LAST_USED);
Cursor cardCursor = db.getLoyaltyCardCursor();
Cursor cardCursor = DBHelper.getLoyaltyCardCursor(database);
while(cardCursor.moveToNext())
{
while (cardCursor.moveToNext()) {
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor);
printer.printRecord(card.id,
@@ -143,12 +150,12 @@ public class CatimaExporter implements Exporter
card.balanceType,
card.cardId,
card.barcodeId,
card.barcodeType,
card.barcodeType != null ? card.barcodeType.name() : "",
card.headerColor,
card.starStatus);
card.starStatus,
card.lastUsed);
if(Thread.currentThread().isInterrupted())
{
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
}
@@ -162,18 +169,16 @@ public class CatimaExporter implements Exporter
printer.printRecord(DBHelper.LoyaltyCardDbIdsGroups.cardID,
DBHelper.LoyaltyCardDbIdsGroups.groupID);
Cursor cardCursor2 = db.getLoyaltyCardCursor();
Cursor cardCursor2 = DBHelper.getLoyaltyCardCursor(database);
while(cardCursor2.moveToNext())
{
while (cardCursor2.moveToNext()) {
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor2);
for (Group group : db.getLoyaltyCardGroups(card.id)) {
for (Group group : DBHelper.getLoyaltyCardGroups(database, card.id)) {
printer.printRecord(card.id, group._id);
}
if(Thread.currentThread().isInterrupted())
{
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
}
@@ -2,8 +2,7 @@ package protect.card_locker.importexport;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import com.google.zxing.BarcodeFormat;
import android.net.Uri;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.LocalFileHeader;
@@ -21,10 +20,12 @@ import java.io.InputStreamReader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Currency;
import java.util.Date;
import java.util.List;
import protect.card_locker.CatimaBarcode;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
import protect.card_locker.Group;
@@ -34,40 +35,42 @@ import protect.card_locker.ZipUtils;
/**
* Class for importing a database from CSV (Comma Separate Values)
* formatted data.
*
* <p>
* The database's loyalty cards are expected to appear in the CSV data.
* A header is expected for the each table showing the names of the columns.
*/
public class CatimaImporter implements Importer
{
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, InterruptedException {
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);
// First, check if this is a zip file
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream);
LocalFileHeader localFileHeader = zipInputStream.getNextEntry();
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream, password);
if (localFileHeader == null) {
boolean isZipFile = false;
LocalFileHeader localFileHeader;
while ((localFileHeader = zipInputStream.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)));
} else if (fileName.endsWith(".png")) {
Utils.saveCardImage(context, ZipUtils.readImage(zipInputStream), fileName);
} else {
throw new FormatException("Unexpected file in import: " + fileName);
}
}
if (!isZipFile) {
// This is not a zip file, try importing as bare CSV
bufferedInputStream.reset();
importCSV(context, db, bufferedInputStream);
return;
}
importZipFile(context, db, zipInputStream, localFileHeader);
}
public void importZipFile(Context context, DBHelper db, ZipInputStream input, LocalFileHeader localFileHeader) throws IOException, FormatException, InterruptedException {
String fileName = localFileHeader.getFileName();
if (fileName.equals("catima.csv")) {
importCSV(context, db, new ByteArrayInputStream(ZipUtils.read(input).getBytes(StandardCharsets.UTF_8)));
} else {
Utils.saveCardImage(context, ZipUtils.readImage(input), fileName);
importCSV(context, database, bufferedInputStream);
}
}
public void importCSV(Context context, DBHelper db, InputStream input) throws IOException, FormatException, InterruptedException {
public void importCSV(Context context, SQLiteDatabase database, InputStream input) throws IOException, FormatException, InterruptedException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
bufferedReader.mark(100);
@@ -84,10 +87,10 @@ public class CatimaImporter implements Importer
switch (version) {
case 1:
parseV1(context, db, bufferedReader);
parseV1(context, database, bufferedReader);
break;
case 2:
parseV2(context, db, bufferedReader);
parseV2(context, database, bufferedReader);
break;
default:
throw new FormatException(String.format("No code to parse version %s", version));
@@ -96,44 +99,25 @@ public class CatimaImporter implements Importer
bufferedReader.close();
}
public void parseV1(Context context, DBHelper db, BufferedReader input) throws IOException, FormatException, InterruptedException
{
final CSVParser parser = new CSVParser(input, CSVFormat.RFC4180.withHeader());
public void parseV1(Context context, SQLiteDatabase database, BufferedReader input) throws IOException, FormatException, InterruptedException {
final CSVParser parser = new CSVParser(input, CSVFormat.RFC4180.builder().setHeader().build());
SQLiteDatabase database = db.getWritableDatabase();
database.beginTransaction();
try {
for (CSVRecord record : parser) {
importLoyaltyCard(context, database, record);
try
{
for (CSVRecord record : parser)
{
importLoyaltyCard(context, database, db, record);
if(Thread.currentThread().isInterrupted())
{
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
}
parser.close();
database.setTransactionSuccessful();
}
catch(IllegalArgumentException|IllegalStateException e)
{
} catch (IllegalArgumentException | IllegalStateException e) {
throw new FormatException("Issue parsing CSV data", e);
}
finally
{
database.endTransaction();
database.close();
}
}
public void parseV2(Context context, DBHelper db, BufferedReader input) throws IOException, FormatException, InterruptedException
{
SQLiteDatabase database = db.getWritableDatabase();
database.beginTransaction();
public void parseV2(Context context, SQLiteDatabase database, BufferedReader input) throws IOException, FormatException, InterruptedException {
Integer part = 0;
String stringPart = "";
@@ -142,18 +126,36 @@ public class CatimaImporter implements Importer
String tmp = input.readLine();
if (tmp == null || tmp.isEmpty()) {
boolean sectionParsed = false;
switch (part) {
case 0:
// This is the version info, ignore
sectionParsed = true;
break;
case 1:
parseV2Groups(db, database, stringPart);
try {
parseV2Groups(database, stringPart);
sectionParsed = true;
} catch (FormatException e) {
// We may have a multiline field, try again
}
break;
case 2:
parseV2Cards(context, db, database, stringPart);
try {
parseV2Cards(context, database, stringPart);
sectionParsed = true;
} catch (FormatException e) {
// We may have a multiline field, try again
}
break;
case 3:
parseV2CardGroups(db, database, stringPart);
try {
parseV2CardGroups(database, stringPart);
sectionParsed = true;
} catch (FormatException e) {
// We may have a multiline field, try again
}
break;
default:
throw new FormatException("Issue parsing CSV data, too many parts for v2 parsing");
@@ -163,29 +165,30 @@ public class CatimaImporter implements Importer
break;
}
part += 1;
stringPart = "";
if (sectionParsed) {
part += 1;
stringPart = "";
} else {
stringPart += tmp + "\n";
}
} else {
stringPart += tmp + "\n";
}
}
database.setTransactionSuccessful();
} catch (FormatException e) {
throw new FormatException("Issue parsing CSV data", e);
} finally {
database.endTransaction();
database.close();
}
}
public void parseV2Groups(DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
{
public void parseV2Groups(SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
// Parse groups
final CSVParser groupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.withHeader());
final CSVParser groupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
List<CSVRecord> records = new ArrayList<>();
try {
for (CSVRecord record : groupParser) {
importGroup(database, db, record);
records.add(record);
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
@@ -196,16 +199,21 @@ public class CatimaImporter implements Importer
} finally {
groupParser.close();
}
for (CSVRecord record : records) {
importGroup(database, record);
}
}
public void parseV2Cards(Context context, DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
{
public void parseV2Cards(Context context, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
// Parse cards
final CSVParser cardParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.withHeader());
final CSVParser cardParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
List<CSVRecord> records = new ArrayList<>();
try {
for (CSVRecord record : cardParser) {
importLoyaltyCard(context, database, db, record);
records.add(record);
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
@@ -216,16 +224,21 @@ public class CatimaImporter implements Importer
} finally {
cardParser.close();
}
for (CSVRecord record : records) {
importLoyaltyCard(context, database, record);
}
}
public void parseV2CardGroups(DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
{
public void parseV2CardGroups(SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
// Parse card group mappings
final CSVParser cardGroupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.withHeader());
final CSVParser cardGroupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
List<CSVRecord> records = new ArrayList<>();
try {
for (CSVRecord record : cardGroupParser) {
importCardGroupMapping(database, db, record);
records.add(record);
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
@@ -236,20 +249,22 @@ public class CatimaImporter implements Importer
} finally {
cardGroupParser.close();
}
for (CSVRecord record : records) {
importCardGroupMapping(database, record);
}
}
/**
* Import a single loyalty card into the database using the given
* session.
*/
private void importLoyaltyCard(Context context, SQLiteDatabase database, DBHelper helper, CSVRecord record)
throws IOException, FormatException
{
private void importLoyaltyCard(Context context, SQLiteDatabase database, CSVRecord record)
throws IOException, FormatException {
int id = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ID, record, false);
String store = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.STORE, record, "");
if(store.isEmpty())
{
if (store.isEmpty()) {
throw new FormatException("No store listed, but is required");
}
@@ -257,12 +272,13 @@ public class CatimaImporter implements Importer
Date expiry = null;
try {
expiry = new Date(CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.EXPIRY, record, true));
} catch (NullPointerException | FormatException e) { }
} catch (NullPointerException | FormatException e) {
}
BigDecimal balance;
try {
balance = new BigDecimal(CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE, record, null));
} catch (FormatException _e ) {
} 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");
@@ -270,72 +286,72 @@ public class CatimaImporter implements Importer
Currency balanceType = null;
String unparsedBalanceType = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE, record, "");
if(!unparsedBalanceType.isEmpty()) {
if (!unparsedBalanceType.isEmpty()) {
balanceType = Currency.getInstance(unparsedBalanceType);
}
String cardId = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.CARD_ID, record, "");
if(cardId.isEmpty())
{
if (cardId.isEmpty()) {
throw new FormatException("No card ID listed, but is required");
}
String barcodeId = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BARCODE_ID, record, "");
if(barcodeId.isEmpty())
{
if (barcodeId.isEmpty()) {
barcodeId = null;
}
BarcodeFormat barcodeType = null;
CatimaBarcode barcodeType = null;
String unparsedBarcodeType = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE, record, "");
if(!unparsedBarcodeType.isEmpty())
{
barcodeType = BarcodeFormat.valueOf(unparsedBarcodeType);
if (!unparsedBarcodeType.isEmpty()) {
barcodeType = CatimaBarcode.fromName(unparsedBarcodeType);
}
Integer headerColor = null;
if(record.isMapped(DBHelper.LoyaltyCardDbIds.HEADER_COLOR))
{
if (record.isMapped(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)) {
headerColor = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.HEADER_COLOR, record, true);
}
int starStatus = 0;
try {
starStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.STAR_STATUS, record, false);
} catch (FormatException _e ) {
// This field did not exist in versions 0.278 and before
} 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
}
if (starStatus != 1) starStatus = 0;
helper.insertLoyaltyCard(database, id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starStatus);
Long lastUsed = 0L;
try {
lastUsed = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.LAST_USED, record, false);
} 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);
}
/**
* Import a single group into the database using the given
* session.
*/
private void importGroup(SQLiteDatabase database, DBHelper helper, CSVRecord record)
throws IOException, FormatException
{
private void importGroup(SQLiteDatabase database, CSVRecord record) throws FormatException {
String id = CSVHelpers.extractString(DBHelper.LoyaltyCardDbGroups.ID, record, null);
helper.insertGroup(database, id);
DBHelper.insertGroup(database, id);
}
/**
* Import a single card to group mapping into the database using the given
* session.
*/
private void importCardGroupMapping(SQLiteDatabase database, DBHelper helper, CSVRecord record)
throws IOException, FormatException
{
private void importCardGroupMapping(SQLiteDatabase database, CSVRecord record) throws FormatException {
Integer cardId = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIdsGroups.cardID, record, false);
String groupId = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIdsGroups.groupID, record, null);
List<Group> cardGroups = helper.getLoyaltyCardGroups(cardId);
cardGroups.add(helper.getGroup(groupId));
helper.setLoyaltyCardGroups(database, cardId, cardGroups);
List<Group> cardGroups = DBHelper.getLoyaltyCardGroups(database, cardId);
cardGroups.add(DBHelper.getGroup(database, groupId));
DBHelper.setLoyaltyCardGroups(database, cardId, cardGroups);
}
}
@@ -1,10 +1,8 @@
package protect.card_locker.importexport;
public enum DataFormat
{
public enum DataFormat {
Catima,
Fidme,
Stocard,
VoucherVault
;
VoucherVault;
}
@@ -1,21 +1,20 @@
package protect.card_locker.importexport;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import java.io.IOException;
import java.io.OutputStream;
import protect.card_locker.DBHelper;
/**
* Interface for a class which can export the contents of the database
* in a given format.
*/
public interface Exporter
{
public interface Exporter {
/**
* Export the database to the output stream in a given format.
*
* @throws IOException
*/
void exportData(Context context, DBHelper db, OutputStream output) throws IOException, InterruptedException;
void exportData(Context context, SQLiteDatabase database, OutputStream output, char[] password) throws IOException, InterruptedException;
}
@@ -3,8 +3,6 @@ package protect.card_locker.importexport;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import com.google.zxing.BarcodeFormat;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.LocalFileHeader;
@@ -20,19 +18,19 @@ import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import protect.card_locker.CatimaBarcode;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
/**
* Class for importing a database from CSV (Comma Separate Values)
* formatted data.
*
* <p>
* The database's loyalty cards are expected to appear in the CSV data.
* A header is expected for the each table showing the names of the columns.
*/
public class FidmeImporter implements Importer
{
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
public class FidmeImporter implements Importer {
public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
// We actually retrieve a .zip file
ZipInputStream zipInputStream = new ZipInputStream(input, password);
@@ -54,14 +52,11 @@ public class FidmeImporter implements Importer
throw new FormatException("Couldn't find loyalty_programs.csv in zip file or it is empty");
}
SQLiteDatabase database = db.getWritableDatabase();
database.beginTransaction();
final CSVParser fidmeParser = new CSVParser(new StringReader(loyaltyCards.toString()), CSVFormat.RFC4180.withDelimiter(';').withHeader());
final CSVParser fidmeParser = new CSVParser(new StringReader(loyaltyCards.toString()), CSVFormat.RFC4180.builder().setDelimiter(';').setHeader().build());
try {
for (CSVRecord record : fidmeParser) {
importLoyaltyCard(database, db, record);
importLoyaltyCard(database, record);
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
@@ -73,10 +68,6 @@ public class FidmeImporter implements Importer
fidmeParser.close();
}
database.setTransactionSuccessful();
database.endTransaction();
database.close();
zipInputStream.close();
}
@@ -84,9 +75,8 @@ public class FidmeImporter implements Importer
* Import a single loyalty card into the database using the given
* session.
*/
private void importLoyaltyCard(SQLiteDatabase database, DBHelper helper, CSVRecord record)
throws IOException, FormatException
{
private void importLoyaltyCard(SQLiteDatabase database, CSVRecord record)
throws FormatException {
// A loyalty card export from Fidme contains the following fields:
// Retailer (store name)
// Program (program name)
@@ -98,8 +88,7 @@ public class FidmeImporter implements Importer
// The store is called Retailer
String store = CSVHelpers.extractString("Retailer", record, "");
if (store.isEmpty())
{
if (store.isEmpty()) {
throw new FormatException("No store listed, but is required");
}
@@ -119,21 +108,20 @@ public class FidmeImporter implements Importer
// The ID is called reference
String cardId = CSVHelpers.extractString("Reference", record, "");
if(cardId.isEmpty())
{
if (cardId.isEmpty()) {
throw new FormatException("No card ID listed, but is required");
}
// Sadly, Fidme exports don't contain the card type
// I guess they have an online DB of all the different companies and what type they use
// TODO: Hook this into our own loyalty card DB if we ever get one
BarcodeFormat barcodeType = null;
CatimaBarcode barcodeType = null;
// No favourite data in the export either
int starStatus = 0;
// TODO: Front and back image
helper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, null, starStatus);
DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, null, starStatus, null);
}
}
@@ -1,9 +1,7 @@
package protect.card_locker.importexport;
public enum ImportExportResult
{
public enum ImportExportResult {
Success,
GenericFailure,
BadPassword
;
BadPassword;
}
@@ -1,6 +1,7 @@
package protect.card_locker.importexport;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import org.json.JSONException;
@@ -8,20 +9,19 @@ import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
/**
* Interface for a class which can import the contents of a stream
* into the database.
*/
public interface Importer
{
public interface Importer {
/**
* Import data from the input stream in a given format into
* the database.
*
* @throws IOException
* @throws FormatException
*/
void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, InterruptedException, JSONException, ParseException;
void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, InterruptedException, JSONException, ParseException;
}
@@ -1,33 +1,29 @@
package protect.card_locker.importexport;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.io.IOException;
import java.io.OutputStream;
import protect.card_locker.DBHelper;
public class MultiFormatExporter
{
public class MultiFormatExporter {
private static final String TAG = "Catima";
/**
* Attempts to export data to the output stream in the
* given format, if possible.
*
* <p>
* The output stream is closed on success.
*
* @return ImportExportResult.Success if the database was successfully exported,
* another ImportExportResult otherwise. If not Success, partial data may have been
* written to the output stream, and it should be discarded.
*/
public static ImportExportResult exportData(Context context, DBHelper db, OutputStream output, DataFormat format)
{
public static ImportExportResult exportData(Context context, SQLiteDatabase database, OutputStream output, DataFormat format, char[] password) {
Exporter exporter = null;
switch(format)
{
switch (format) {
case Catima:
exporter = new CatimaExporter();
break;
@@ -36,26 +32,18 @@ public class MultiFormatExporter
break;
}
if(exporter != null)
{
try
{
exporter.exportData(context, db, output);
if (exporter != null) {
try {
exporter.exportData(context, database, output, password);
return ImportExportResult.Success;
}
catch(IOException e)
{
} catch (IOException e) {
Log.e(TAG, "Failed to export data", e);
}
catch(InterruptedException e)
{
} catch (InterruptedException e) {
Log.e(TAG, "Failed to export data", e);
}
return ImportExportResult.GenericFailure;
}
else
{
} else {
Log.e(TAG, "Unsupported data format exported: " + format.name());
return ImportExportResult.GenericFailure;
}
@@ -1,6 +1,7 @@
package protect.card_locker.importexport;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import net.lingala.zip4j.exception.ZipException;
@@ -11,17 +12,15 @@ import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
public class MultiFormatImporter
{
public class MultiFormatImporter {
private static final String TAG = "Catima";
/**
* Attempts to import data from the input stream of the
* given format into the database.
*
* <p>
* The input stream is not closed, and doing so is the
* responsibility of the caller.
*
@@ -29,12 +28,10 @@ public class MultiFormatImporter
* or another result otherwise. If no Success, no data was written to
* the database.
*/
public static ImportExportResult importData(Context context, DBHelper db, InputStream input, DataFormat format, char[] password)
{
public static ImportExportResult importData(Context context, SQLiteDatabase database, InputStream input, DataFormat format, char[] password) {
Importer importer = null;
switch(format)
{
switch (format) {
case Catima:
importer = new CatimaImporter();
break;
@@ -49,25 +46,20 @@ public class MultiFormatImporter
break;
}
if (importer != null)
{
try
{
importer.importData(context, db, input, password);
if (importer != null) {
database.beginTransaction();
try {
importer.importData(context, database, input, password);
database.setTransactionSuccessful();
return ImportExportResult.Success;
}
catch(ZipException e)
{
} catch (ZipException e) {
return ImportExportResult.BadPassword;
}
catch(IOException | FormatException | InterruptedException | JSONException | ParseException | NullPointerException e)
{
} catch (IOException | FormatException | InterruptedException | JSONException | ParseException | NullPointerException e) {
Log.e(TAG, "Failed to import data", e);
} finally {
database.endTransaction();
}
}
else
{
} else {
Log.e(TAG, "Unsupported data format imported: " + format.name());
}
@@ -9,35 +9,55 @@ import com.google.zxing.BarcodeFormat;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.LocalFileHeader;
import org.json.JSONArray;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.json.JSONException;
import org.json.JSONObject;
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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import protect.card_locker.CatimaBarcode;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
import protect.card_locker.ImageLocationType;
import protect.card_locker.R;
import protect.card_locker.Utils;
import protect.card_locker.ZipUtils;
/**
* Class for importing a database from CSV (Comma Separate Values)
* formatted data.
*
* <p>
* The database's loyalty cards are expected to appear in the CSV data.
* A header is expected for the each table showing the names of the columns.
*/
public class StocardImporter implements Importer
{
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
public class StocardImporter implements Importer {
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, String> providers = new HashMap<>();
HashMap<String, HashMap<String, String>> providers = 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, String> recordData = new HashMap<>();
recordData.put("name", record.get("name"));
recordData.put("barcodeFormat", record.get("barcodeFormat"));
providers.put(record.get("_id"), recordData);
}
parser.close();
} catch (IllegalArgumentException | IllegalStateException e) {
throw new FormatException("Issue parsing CSV data", e);
}
ZipInputStream zipInputStream = new ZipInputStream(input, password);
@@ -50,7 +70,7 @@ public class StocardImporter implements Importer
String[] nameParts = fileName.split("/");
if (providersFileName == null) {
providersFileName = new String[] {
providersFileName = new String[]{
nameParts[0],
"sync",
"data",
@@ -58,7 +78,7 @@ public class StocardImporter implements Importer
nameParts[0],
"analytics-properties.json"
};
cardBaseName = new String[] {
cardBaseName = new String[]{
nameParts[0],
"sync",
"data",
@@ -68,9 +88,7 @@ public class StocardImporter implements Importer
};
}
if (startsWith(nameParts, providersFileName, 0) && !localFileHeader.isDirectory()) {
providers = parseProviders(zipInputStream);
} else if (startsWith(nameParts, cardBaseName, 1)) {
if (startsWith(nameParts, cardBaseName, 1)) {
// Extract cardName
cardName = nameParts[cardBaseName.length].split("\\.", 2)[0];
@@ -91,19 +109,19 @@ public class StocardImporter implements Importer
cardName,
"_providerId",
jsonObject
.getJSONObject("input_provider_reference")
.getString("identifier")
.substring("/loyalty-card-providers/".length())
.getJSONObject("input_provider_reference")
.getString("identifier")
.substring("/loyalty-card-providers/".length())
);
try {
if (jsonObject.has("input_barcode_format")) {
loyaltyCardHashMap = appendToLoyaltyCardHashMap(
loyaltyCardHashMap,
cardName,
"barcodeType",
jsonObject.getString("input_barcode_format")
);
} catch (JSONException ignored) {}
}
}
} else if (fileName.endsWith("notes/default.json")) {
loyaltyCardHashMap = appendToLoyaltyCardHashMap(
@@ -111,7 +129,7 @@ public class StocardImporter implements Importer
cardName,
"note",
ZipUtils.readJSON(zipInputStream)
.getString("content")
.getString("content")
);
} else if (fileName.endsWith("/images/front.png")) {
loyaltyCardHashMap = appendToLoyaltyCardHashMap(
@@ -135,37 +153,33 @@ public class StocardImporter implements Importer
throw new FormatException("Couldn't find any loyalty cards in this Stocard export.");
}
SQLiteDatabase database = db.getWritableDatabase();
database.beginTransaction();
for (HashMap<String, Object> loyaltyCardData : loyaltyCardHashMap.values()) {
String store = providers.get(loyaltyCardData.get("_providerId").toString());
String note = (String) Utils.hashmapGetOrDefault(loyaltyCardData, "note", "");
String providerId = (String) loyaltyCardData.get("_providerId");
HashMap<String, String> providerData = providers.get(providerId);
String store = providerData != null ? providerData.get("name") : providerId;
String note = (String) Utils.mapGetOrDefault(loyaltyCardData, "note", "");
String cardId = (String) loyaltyCardData.get("cardId");
String barcodeTypeString = (String) Utils.hashmapGetOrDefault(loyaltyCardData, "barcodeType", null);
BarcodeFormat barcodeType = null;
String barcodeTypeString = (String) Utils.mapGetOrDefault(loyaltyCardData, "barcodeType", providerData != null ? providerData.get("barcodeFormat") : null);
CatimaBarcode barcodeType = null;
if (barcodeTypeString != null) {
if (barcodeTypeString.equals("RSS_DATABAR_EXPANDED")) {
barcodeType = BarcodeFormat.RSS_EXPANDED;
barcodeType = CatimaBarcode.fromBarcode(BarcodeFormat.RSS_EXPANDED);
} else {
barcodeType = BarcodeFormat.valueOf(barcodeTypeString);
barcodeType = CatimaBarcode.fromName(barcodeTypeString);
}
}
long loyaltyCardInternalId = db.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, null, 0);
long loyaltyCardInternalId = DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, null, 0, null);
if (loyaltyCardData.containsKey("frontImage")) {
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("frontImage"), (int) loyaltyCardInternalId, true);
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("frontImage"), (int) loyaltyCardInternalId, ImageLocationType.front);
}
if (loyaltyCardData.containsKey("backImage")) {
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("backImage"), (int) loyaltyCardInternalId, false);
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("backImage"), (int) loyaltyCardInternalId, ImageLocationType.back);
}
}
database.setTransactionSuccessful();
database.endTransaction();
database.close();
zipInputStream.close();
}
@@ -194,33 +208,4 @@ public class StocardImporter implements Importer
return loyaltyCardHashMap;
}
private HashMap<String, String> parseProviders(ZipInputStream zipInputStream) throws IOException, JSONException {
// FIXME: This is probably completely wrong, but it works for the one and only test file I have
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
JSONArray providerIdList = jsonObject.getJSONArray("provider_id_list");
JSONArray providerList = jsonObject.getJSONArray("provider_list");
// Resort, put IDs with - in them after IDs without any -
List<String> providerIds = new ArrayList<>();
List<String> customProviderIds = new ArrayList<>();
for (int i = 0; i < providerIdList.length(); i++) {
String providerId = providerIdList.get(i).toString();
if (providerId.contains("-")) {
customProviderIds.add(providerId);
} else {
providerIds.add(providerId);
}
}
providerIds.addAll(customProviderIds);
HashMap<String, String> providers = new HashMap<>();
for (int i = 0; i < jsonObject.getInt("number_of_cards"); i++) {
providers.put(providerIds.get(i), providerList.get(i).toString());
}
return providers;
}
}
@@ -23,19 +23,20 @@ import java.util.Currency;
import java.util.Date;
import java.util.TimeZone;
import protect.card_locker.CatimaBarcode;
import protect.card_locker.DBHelper;
import protect.card_locker.FormatException;
import protect.card_locker.Utils;
/**
* Class for importing a database from CSV (Comma Separate Values)
* formatted data.
*
* <p>
* The database's loyalty cards are expected to appear in the CSV data.
* A header is expected for the each table showing the names of the columns.
*/
public class VoucherVaultImporter implements Importer
{
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
public class VoucherVaultImporter implements Importer {
public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
@@ -45,9 +46,6 @@ public class VoucherVaultImporter implements Importer
}
JSONArray jsonArray = new JSONArray(sb.toString());
SQLiteDatabase database = db.getWritableDatabase();
database.beginTransaction();
// 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);
@@ -74,24 +72,24 @@ public class VoucherVaultImporter implements Importer
String cardId = jsonCard.getString("code");
BarcodeFormat barcodeType = null;
CatimaBarcode barcodeType = null;
String codeTypeFromJSON = jsonCard.getString("codeType");
switch (codeTypeFromJSON) {
case "CODE128":
barcodeType = BarcodeFormat.CODE_128;
barcodeType = CatimaBarcode.fromBarcode(BarcodeFormat.CODE_128);
break;
case "CODE39":
barcodeType = BarcodeFormat.CODE_39;
barcodeType = CatimaBarcode.fromBarcode(BarcodeFormat.CODE_39);
break;
case "EAN13":
barcodeType = BarcodeFormat.EAN_13;
barcodeType = CatimaBarcode.fromBarcode(BarcodeFormat.EAN_13);
break;
case "PDF417":
barcodeType = BarcodeFormat.PDF_417;
barcodeType = CatimaBarcode.fromBarcode(BarcodeFormat.PDF_417);
break;
case "QR":
barcodeType = BarcodeFormat.QR_CODE;
barcodeType = CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE);
break;
case "TEXT":
break;
@@ -128,13 +126,9 @@ public class VoucherVaultImporter implements Importer
throw new FormatException("Unknown colour type found: " + colorFromJSON);
}
db.insertLoyaltyCard(store, "", expiry, balance, balanceType, cardId, null, barcodeType, headerColor, 0);
DBHelper.insertLoyaltyCard(database, store, "", expiry, balance, balanceType, cardId, null, barcodeType, headerColor, 0, Utils.getUnixTime());
}
database.setTransactionSuccessful();
database.endTransaction();
database.close();
bufferedReader.close();
}
}
@@ -3,111 +3,108 @@ package protect.card_locker.preferences;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.Locale;
import androidx.annotation.IntegerRes;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.preference.PreferenceManager;
import protect.card_locker.R;
import protect.card_locker.Utils;
public class Settings
{
private Context context;
private SharedPreferences settings;
public class Settings {
private final Context mContext;
private SharedPreferences mSettings;
public Settings(Context context)
{
this.context = context;
this.settings = PreferenceManager.getDefaultSharedPreferences(context);
public Settings(Context context) {
mContext = context.getApplicationContext();
mSettings = PreferenceManager.getDefaultSharedPreferences(context);
}
private String getResString(@StringRes int resId)
{
return context.getString(resId);
private String getResString(@StringRes int resId) {
return mContext.getString(resId);
}
private int getResInt(@IntegerRes int resId)
{
return context.getResources().getInteger(resId);
private int getResInt(@IntegerRes int resId) {
return mContext.getResources().getInteger(resId);
}
private String getString(@StringRes int keyId, String defaultValue)
{
return settings.getString(getResString(keyId), defaultValue);
private String getString(@StringRes int keyId, String defaultValue) {
return mSettings.getString(getResString(keyId), defaultValue);
}
private int getInt(@StringRes int keyId, @IntegerRes int defaultId)
{
return settings.getInt(getResString(keyId), getResInt(defaultId));
private int getInt(@StringRes int keyId, @IntegerRes int defaultId) {
return mSettings.getInt(getResString(keyId), getResInt(defaultId));
}
private boolean getBoolean(@StringRes int keyId, boolean defaultValue)
{
return settings.getBoolean(getResString(keyId), defaultValue);
private boolean getBoolean(@StringRes int keyId, boolean defaultValue) {
return mSettings.getBoolean(getResString(keyId), defaultValue);
}
public int getTheme()
{
public Locale getLocale() {
String value = getString(R.string.settings_key_locale, "");
if (value.length() == 0) {
return null;
}
return Utils.stringToLocale(value);
}
public int getTheme() {
String value = getString(R.string.settings_key_theme, getResString(R.string.settings_key_system_theme));
if(value.equals(getResString(R.string.settings_key_light_theme)))
{
if (value.equals(getResString(R.string.settings_key_light_theme))) {
return AppCompatDelegate.MODE_NIGHT_NO;
}
else if(value.equals(getResString(R.string.settings_key_dark_theme)))
{
} else if (value.equals(getResString(R.string.settings_key_dark_theme))) {
return AppCompatDelegate.MODE_NIGHT_YES;
}
return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
}
public double getFontSizeScale()
{
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()
{
public int getSmallFont() {
return 14;
}
public int getMediumFont()
{
public int getMediumFont() {
return 28;
}
public int getLargeFont()
{
public int getLargeFont() {
return 40;
}
public int getFontSizeMin(int fontSize)
{
public int getFontSizeMin(int fontSize) {
return (int) (Math.round(fontSize / 2.0) - 1);
}
public int getFontSizeMax(int fontSize)
{
public int getFontSizeMax(int fontSize) {
return (int) Math.round(fontSize * getFontSizeScale());
}
public boolean useMaxBrightnessDisplayingBarcode()
{
public boolean useMaxBrightnessDisplayingBarcode() {
return getBoolean(R.string.settings_key_display_barcode_max_brightness, true);
}
public boolean getLockBarcodeScreenOrientation()
{
public boolean getLockBarcodeScreenOrientation() {
return getBoolean(R.string.settings_key_lock_barcode_orientation, false);
}
public boolean getKeepScreenOn()
{
public boolean getKeepScreenOn() {
return getBoolean(R.string.settings_key_keep_screen_on, true);
}
public boolean getDisableLockscreenWhileViewingCard()
{
public boolean getDisableLockscreenWhileViewingCard() {
return getBoolean(R.string.settings_key_disable_lockscreen_while_viewing_card, true);
}
public boolean getOledDark() {
return getBoolean(R.string.settings_key_oled_dark, false);
}
}
@@ -1,96 +1,158 @@
package protect.card_locker.preferences;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
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;
public class SettingsActivity extends CatimaAppCompatActivity {
private final static String RELOAD_MAIN_STATE = "mReloadMain";
private SettingsFragment fragment;
public class SettingsActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.settings);
setContentView(R.layout.settings_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
// Display the fragment as the main content.
fragment = new SettingsFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.settings_container, new SettingsFragment())
.replace(R.id.settings_container, fragment)
.commit();
// restore reload main state
if (savedInstanceState != null) {
fragment.mReloadMain = savedInstanceState.getBoolean(RELOAD_MAIN_STATE);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(RELOAD_MAIN_STATE, fragment.mReloadMain);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home)
{
finish();
if (id == android.R.id.home) {
finishSettingsActivity();
return true;
}
return super.onOptionsItemSelected(item);
}
public static class SettingsFragment extends PreferenceFragmentCompat
{
@Override
public void onBackPressed() {
finishSettingsActivity();
}
private void finishSettingsActivity() {
if (fragment.mReloadMain) {
Intent intent = new Intent();
intent.putExtra(MainActivity.RESTART_ACTIVITY_INTENT, true);
setResult(Activity.RESULT_OK, intent);
} else {
setResult(Activity.RESULT_OK);
}
finish();
}
public static class SettingsFragment extends PreferenceFragmentCompat {
private static final String DIALOG_FRAGMENT_TAG = "SettingsFragment";
public boolean mReloadMain;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey)
{
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// 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));
assert themePreference != null;
themePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{
@Override
public boolean onPreferenceChange(Preference preference, Object o)
{
if(o.toString().equals(getResources().getString(R.string.settings_key_light_theme)))
{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
else if(o.toString().equals(getResources().getString(R.string.settings_key_dark_theme)))
{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
else
{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
FragmentActivity activity = getActivity();
if (activity != null) {
activity.recreate();
}
return true;
themePreference.setOnPreferenceChangeListener((preference, o) -> {
if (o.toString().equals(getResources().getString(R.string.settings_key_light_theme))) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else if (o.toString().equals(getResources().getString(R.string.settings_key_dark_theme))) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
return true;
});
localePreference.setOnPreferenceChangeListener((preference, newValue) -> {
refreshActivity(true);
return true;
});
Preference oledDarkPreference = findPreference(getResources().getString(R.string.settings_key_oled_dark));
assert oledDarkPreference != null;
oledDarkPreference.setOnPreferenceChangeListener((preference, newValue) -> {
refreshActivity(true);
return true;
});
}
private void refreshActivity(boolean reloadMain) {
mReloadMain = reloadMain || mReloadMain;
Activity activity = getActivity();
if (activity != null) {
activity.recreate();
}
}
@Override
public void onDisplayPreferenceDialog(Preference preference)
{
if (preference instanceof NumberDialogPreference)
{
public void onDisplayPreferenceDialog(Preference preference) {
if (preference instanceof NumberDialogPreference) {
NumberDialogPreference dialogPreference = (NumberDialogPreference) preference;
DialogFragment dialogFragment = NumberPickerPreferenceDialogFragment
.newInstance(
@@ -102,9 +164,7 @@ public class SettingsActivity extends AppCompatActivity
);
dialogFragment.setTargetFragment(this, 0);
dialogFragment.show(getParentFragmentManager(), DIALOG_FRAGMENT_TAG);
}
else
{
} else {
super.onDisplayPreferenceDialog(preference);
}
}
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="0"
android:propertyName="alpha"
android:valueFrom="1.0"
android:valueTo="0.0" />
<objectAnimator
android:duration="@integer/full_rotation_duration"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:propertyName="rotationY"
android:valueFrom="-180"
android:valueTo="0" />
<objectAnimator
android:duration="1"
android:propertyName="alpha"
android:startOffset="@integer/half_rotation_duration"
android:valueFrom="0.0"
android:valueTo="1.0" />
</set>
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="@integer/full_rotation_duration"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:propertyName="rotationY"
android:valueFrom="0"
android:valueTo="180" />
<objectAnimator
android:duration="1"
android:propertyName="alpha"
android:startOffset="@integer/half_rotation_duration"
android:valueFrom="1.0"
android:valueTo="0.0" />
</set>
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="0"
android:propertyName="alpha"
android:valueFrom="1.0"
android:valueTo="0.0" />
<objectAnimator
android:duration="@integer/full_rotation_duration"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:propertyName="rotationY"
android:valueFrom="180"
android:valueTo="0" />
<objectAnimator
android:duration="1"
android:propertyName="alpha"
android:startOffset="@integer/half_rotation_duration"
android:valueFrom="0.0"
android:valueTo="1.0" />
</set>
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="@integer/full_rotation_duration"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:propertyName="rotationY"
android:valueFrom="0"
android:valueTo="-180" />
<objectAnimator
android:duration="1"
android:propertyName="alpha"
android:startOffset="@integer/half_rotation_duration"
android:valueFrom="1.0"
android:valueTo="0.0" />
</set>
+9
View File
@@ -0,0 +1,9 @@
<?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,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="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
@@ -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="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
@@ -0,0 +1,13 @@
<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="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
</vector>
@@ -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="M7,10l5,5 5,-5z"/>
@@ -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="M7,14l5,-5 5,5z"/>
@@ -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="M19,14L19,6c0,-1.1 -0.9,-2 -2,-2L3,4c-1.1,0 -2,0.9 -2,2v8c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM10,13c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM23,7v11c0,1.1 -0.9,2 -2,2L4,20v-2h17L21,7h2z"/>
</vector>
@@ -0,0 +1,5 @@
<vector android:autoMirrored="true" 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="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/>
</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.41,18.59L8.83,20 12,16.83 15.17,20l1.41,-1.41L12,14l-4.59,4.59zM16.59,5.41L15.17,4 12,7.17 8.83,4 7.41,5.41 12,10l4.59,-4.59z"/>
</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="M12,5.83L15.17,9l1.41,-1.41L12,3 7.41,7.59 8.83,9 12,5.83zM12,18.17L8.83,15l-1.41,1.41L12,21l4.59,-4.59L15.17,15 12,18.17z"/>
</vector>
+2 -1
View File
@@ -2,7 +2,8 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
@@ -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="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
+2 -2
View File
@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="@color/colorPrimary"
android:viewportWidth="24"
android:viewportHeight="24">
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFFFFF"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
@@ -2,7 +2,8 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:pathData="M18,5l0,-3l-12,0l0,1.17l1.83,1.83z"
android:fillColor="#FFFFFF"/>
@@ -2,7 +2,8 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:pathData="M6,2h12v3h-12z"
android:fillColor="#FFFFFF"/>
@@ -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,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
@@ -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="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z"/>
@@ -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="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"/>
@@ -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="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"/>
@@ -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="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
@@ -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.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
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,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>
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
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="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,9 @@
<?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>
-4
View File
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/listItemHighlight" android:state_activated="true" />
</selector>
+1 -1
View File
@@ -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="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
+327 -14
View File
@@ -10,33 +10,346 @@
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
style="?attr/toolbarStyle" />
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/aboutText"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:linksClickable="true"
android:singleLine="false"
android:focusable="true" />
android:orientation="vertical">
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/version_history"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/version_history_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/version_history"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/version_history_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/version_history_main" />
<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/credits"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/credits_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/credits"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/credits_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/credits_main" />
<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/translate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/translate_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/help_translate_this_app"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/translate_sub"
android:layout_width="match_parent"
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"/>
<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/license"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/license_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/license"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/license_sub"
android:layout_width="match_parent"
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"/>
<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/repo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/repo_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/source_repository"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/repo_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/on_github"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/repo_main" />
<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/privacy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/privacy_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/privacy_policy"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/privacy_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/and_data_usage"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/privacy_main" />
<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"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/rate_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/rate_this_app"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/rate_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/on_google_play"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/rate_main" />
<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:padding="8dp"
android:id="@+id/report_error"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/report_error_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/report_error"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/report_error_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/report_error_main"
app:layout_constraintStart_toStartOf="parent"
android:textSize="16sp"
android:text="@string/on_github"
android:padding="2dp"/>
<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>
</LinearLayout>
</ScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -0,0 +1,64 @@
<?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.ManageGroupActivity">
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/fabSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
app:icon="@drawable/save_24dp"
android:text="@string/save"
android:layout_margin="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<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"
android:visibility="gone"
app:tabMode="scrollable" />
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/storeNameField"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/storeName">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/editTextGroupName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<include
android:id="@+id/include"
layout="@layout/content_main" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:importantForAccessibility="no"
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/barcodeImage"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/barcodeName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
@@ -1,330 +1,89 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<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="fill_parent"
android:layout_height="fill_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
style="?attr/toolbarStyle" />
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/scrollView">
android:orientation="vertical">
<TextView
android:id="@+id/explanationText"
android:textSize="20sp"
android:layout_gravity="center_vertical"
android:paddingStart="20.0dip"
android:paddingEnd="20.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/barcodeIdLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/enterBarcodeInstructions" />
<LinearLayout
android:id="@+id/barcodeIdLayout"
android:orientation="horizontal"
android:padding="10.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/explanationText"
app:layout_constraintBottom_toTopOf="@+id/noBarcode"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<TextView android:textSize="16.0sp"
android:textStyle="bold"
android:layout_gravity="center_vertical"
android:paddingStart="20.0dip"
android:paddingEnd="20.0dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:labelFor="@+id/cardId"
android:text="@string/cardId" />
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout android:orientation="horizontal"
android:padding="10.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:textSize="20sp"
android:layout_gravity="center_vertical"
android:paddingStart="20.0dip"
android:paddingEnd="20.0dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/enterBarcodeInstructions" />
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:padding="10.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/barcodeIdLayout">
<TextView android:textSize="16.0sp"
android:textStyle="bold"
android:layout_gravity="center_vertical"
android:paddingStart="20.0dip"
android:paddingEnd="20.0dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:labelFor="@+id/cardId"
android:text="@string/cardId" />
<EditText android:id="@+id/cardId"
android:hint="AB1234"
android:importantForAutofill="no"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="text"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
<EditText
android:id="@+id/cardId"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/barcodesLayout"/>
<Button
android:id="@+id/noBarcode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/barcodeNoBarcode"
android:textColor="#FFFFFF"
android:enabled="false" />
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/aztecBarcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/aztecBarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/code39Barcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/code39BarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/code128Barcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/code128BarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/codabarBarcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/codabarBarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/datamatrixBarcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/datamatrixBarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/ean8Barcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/ean8BarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/ean13Barcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/ean13BarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/itfBarcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/itfBarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/pdf417Barcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/pdf417BarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/qrcodeBarcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/qrcodeBarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/upcaBarcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/upcaBarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:id="@+id/upceBarcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
<TextView
android:id="@+id/upceBarcodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10.0dip"
android:gravity="center"
android:textSize="@dimen/text_size_medium"
android:textStyle="bold"
android:layout_weight="1.0" />
</LinearLayout>
android:hint="AB1234"
android:importantForAutofill="no"
android:inputType="text"
android:minHeight="48dp"
tools:ignore="ContentDescription" />
</LinearLayout>
</ScrollView>
<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:textColor="#FFFFFF"
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_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:scrollbars="vertical" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
+14 -1
View File
@@ -26,12 +26,25 @@
android:gravity="center"
android:text="@string/noMatchingGiftCards"
android:visibility="gone"/>
<TextView
style="@style/AppTheme.TextView.NoData"
android:id="@+id/noGroupCardsText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/noGroupCards"
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:scrollbars="vertical"
android:visibility="gone" />
android:visibility="gone"/>
</RelativeLayout>
Loaded 100 of 598 files, more files were not shown because too many files have changed in this diff. Show more