Compare commits

...

113 Commits

Author SHA1 Message Date
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
bors[bot]
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]
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]
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="9ee00acc93"><code>9ee00ac</code></a> Develop (<a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/issues/14">#14</a>)</li>
<li><a href="1035c87ae1"><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="93a5d495df"><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="300af7866a"><code>300af78</code></a> fix <a href="https://github-redirect.dependabot.com/invissvenska/NumberPickerPreference/issues/9">#9</a></li>
<li><a href="391b8a8593"><code>391b8a8</code></a> increment version, removed commented code from gradle</li>
<li><a href="ef4a9b3a63"><code>ef4a9b3</code></a> set java version to 11 for jitpack by adding the jitpack yml</li>
<li><a href="c28b95e5c8"><code>c28b95e</code></a> set java version to 11</li>
<li><a href="2df1805d82"><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="71f4f5992e"><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]
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
bors[bot]
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]
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]
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="9ed0797525"><code>9ed0797</code></a> Bump version to 4.7.2.</li>
<li><a href="5a8c5def4f"><code>5a8c5de</code></a> Fix theme native object collection in Android S</li>
<li><a href="666a5213a7"><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
bors[bot]
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]
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
bors[bot]
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]
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="c1e4fed866"><code>c1e4fed</code></a> Bump version to 4.7.1.</li>
<li><a href="c9e861d3d7"><code>c9e861d</code></a> Bump to version 3 of preinstrumented jars</li>
<li><a href="434a5347f1"><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]
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="860965237a"><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="9eab02b675"><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="4e5e2d45ff"><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="de9bb5f35d"><code>de9bb5f</code></a> Remove functional interface annotation</li>
<li><a href="ec78cea98c"><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="2ec68db8b7"><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="7a139612ce"><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="3224fb8ef5"><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="9ae5253f4b"><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="14aebe0d05"><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]
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]
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
bors[bot]
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]
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]
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]
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]
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]
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
bors[bot]
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]
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="dc7bcfd314"><code>dc7bcfd</code></a> Bump version to 4.7.</li>
<li><a href="b2706bf5c2"><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="ba989616d5"><code>ba98961</code></a> Add a workflow to build the nativeruntime libraries</li>
<li><a href="a5db353b55"><code>a5db353</code></a> Move clang/clang++ specification to CMakeLists</li>
<li><a href="0388825391"><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="7d44fa13a2"><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="fe3bb98658"><code>fe3bb98</code></a> Disable the universal library for Mac OS</li>
<li><a href="5b1bd881a4"><code>5b1bd88</code></a> Bump asm to 9.2 to support JDK 17 and 18</li>
<li><a href="6a3305348d"><code>6a33053</code></a> Bump AGP to 7.1.0-beta03</li>
<li><a href="4b2ecb9b59"><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
1624d56edb Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker into feature/power_screen_widgets 2021-10-26 21:42:14 +02:00
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
/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
86 changed files with 1267 additions and 1437 deletions

View File

@@ -1,6 +1,22 @@
# Changelog
## Unreleased - 91
## 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

View File

@@ -18,8 +18,8 @@ android {
applicationId "me.hackerchick.catima"
minSdkVersion 21
targetSdkVersion 31
versionCode 91
versionName "2.9.0"
versionCode 94
versionName "2.11.1"
vectorDrawables.useSupportLibrary true
multiDexEnabled true
@@ -49,8 +49,8 @@ android {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
lintOptions {
@@ -80,8 +80,8 @@ android {
dependencies {
// AndroidX
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'androidx.palette:palette:1.0.0'
implementation 'androidx.preference:preference:1.1.1'
@@ -97,8 +97,8 @@ dependencies {
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.github.invissvenska:NumberPickerPreference:1.0.3'
implementation 'net.lingala.zip4j:zip4j:2.9.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'
@@ -106,7 +106,7 @@ dependencies {
// Testing
testImplementation 'androidx.test:core:1.4.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.6.1'
testImplementation 'org.robolectric:robolectric:4.7.2'
}
tasks.withType(SpotBugsTask) {

View File

@@ -37,11 +37,11 @@
<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"
@@ -117,7 +117,7 @@
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"/>
android:theme="@style/AppTheme.NoActionBar" />
<provider
android:name="androidx.core.content.FileProvider"
@@ -128,6 +128,13 @@
android:name="android.support.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>

View File

@@ -6,23 +6,18 @@ import android.os.Bundle;
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.zxing.BarcodeFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import protect.card_locker.async.TaskHandler;
/**
* This activity is callable and will allow a user to enter
@@ -30,20 +25,18 @@ import protect.card_locker.async.TaskHandler;
* the data. The user may then select any barcode, where its
* data and type will be returned to the caller.
*/
public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
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";
private Map<String, Pair<Integer, Integer>> barcodeViewMap;
final private TaskHandler mTasks = new TaskHandler();
private final Handler typingDelayHandler = new Handler(Looper.getMainLooper());
public static final Integer INPUT_DELAY = 250;
private BarcodeSelectorAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -56,21 +49,10 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
actionBar.setDisplayHomeAsUpEnabled(true);
}
barcodeViewMap = new HashMap<>();
barcodeViewMap.put(BarcodeFormat.AZTEC.name(), new Pair<>(R.id.aztecBarcode, R.id.aztecBarcodeText));
barcodeViewMap.put(BarcodeFormat.CODE_39.name(), new Pair<>(R.id.code39Barcode, R.id.code39BarcodeText));
barcodeViewMap.put(BarcodeFormat.CODE_128.name(), new Pair<>(R.id.code128Barcode, R.id.code128BarcodeText));
barcodeViewMap.put(BarcodeFormat.CODABAR.name(), new Pair<>(R.id.codabarBarcode, R.id.codabarBarcodeText));
barcodeViewMap.put(BarcodeFormat.DATA_MATRIX.name(), new Pair<>(R.id.datamatrixBarcode, R.id.datamatrixBarcodeText));
barcodeViewMap.put(BarcodeFormat.EAN_8.name(), new Pair<>(R.id.ean8Barcode, R.id.ean8BarcodeText));
barcodeViewMap.put(BarcodeFormat.EAN_13.name(), new Pair<>(R.id.ean13Barcode, R.id.ean13BarcodeText));
barcodeViewMap.put(BarcodeFormat.ITF.name(), new Pair<>(R.id.itfBarcode, R.id.itfBarcodeText));
barcodeViewMap.put(BarcodeFormat.PDF_417.name(), new Pair<>(R.id.pdf417Barcode, R.id.pdf417BarcodeText));
barcodeViewMap.put(BarcodeFormat.QR_CODE.name(), new Pair<>(R.id.qrcodeBarcode, R.id.qrcodeBarcodeText));
barcodeViewMap.put(BarcodeFormat.UPC_A.name(), new Pair<>(R.id.upcaBarcode, R.id.upcaBarcodeText));
barcodeViewMap.put(BarcodeFormat.UPC_E.name(), new Pair<>(R.id.upceBarcode, R.id.upceBarcodeText));
EditText cardId = findViewById(R.id.cardId);
ListView mBarcodeList = findViewById(R.id.barcodes);
mAdapter = new BarcodeSelectorAdapter(this, new ArrayList<>(), this);
mBarcodeList.setAdapter(mAdapter);
cardId.addTextChangedListener(new SimpleTextWatcher() {
@Override
@@ -103,16 +85,13 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
}
private void generateBarcodes(String value) {
// Attempt to stop any async tasks which may not have been started yet
// TODO this can be very much optimized by only generating Barcodes visible to the User
mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false);
// 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) {
@@ -126,48 +105,6 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
});
}
private void createBarcodeOption(final ImageView image, final String formatType, final String cardId, final TextView text) {
final CatimaBarcode format = CatimaBarcode.fromName(formatType);
image.setImageBitmap(null);
image.setOnClickListener(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 barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), 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(getApplicationContext(), image, cardId, format, text, true, null);
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
@@ -178,4 +115,26 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -5,12 +5,17 @@ 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 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);
}
@@ -58,6 +63,7 @@ public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> exten
if (inputCursor != null) {
mCursor = inputCursor;
mRowIDColumn = mCursor.getColumnIndex(mRowIDColumnName);
mDataValid = true;
notifyDataSetChanged();
} else {

View File

@@ -0,0 +1,159 @@
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.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 final DBHelper dbHelper = new DBHelper(this);
@NonNull
@Override
public Flow.Publisher<Control> createPublisherForAllAvailable() {
Cursor loyaltyCardCursor = dbHelper.getLoyaltyCardCursor();
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(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() {
}
}
}

View File

@@ -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;
}
}

View File

@@ -1,24 +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 Activity activity;
private final Context mContext;
public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
super(activity, barcodeView);
this.activity = activity;
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(activity, message, Toast.LENGTH_LONG).show();
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
}
}

View File

@@ -71,12 +71,8 @@ public class DBHelper extends SQLiteOpenHelper {
Descending
}
private Context mContext;
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
}
@Override
@@ -583,7 +579,7 @@ public class DBHelper extends SQLiteOpenHelper {
}
}
public boolean deleteLoyaltyCard(final int id) {
public boolean deleteLoyaltyCard(Context context, final int id) {
SQLiteDatabase db = getWritableDatabase();
// Delete card
int rowsDeleted = db.delete(LoyaltyCardDbIds.TABLE,
@@ -603,7 +599,7 @@ public class DBHelper extends SQLiteOpenHelper {
// Also wipe card images associated with this card
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
try {
Utils.saveCardImage(mContext, null, id, imageLocationType);
Utils.saveCardImage(context, null, id, imageLocationType);
} catch (FileNotFoundException e) {
e.printStackTrace();
}

View File

@@ -12,28 +12,21 @@ import androidx.appcompat.widget.AppCompatImageButton;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.Settings;
class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder> {
public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder> {
Settings mSettings;
private Cursor mCursor;
private final Context mContext;
private final GroupCursorAdapter.GroupAdapterListener mListener;
private final GroupAdapterListener mListener;
DBHelper mDb;
public GroupCursorAdapter(Context inputContext, Cursor inputCursor, GroupCursorAdapter.GroupAdapterListener inputListener) {
super(inputCursor);
public GroupCursorAdapter(Context inputContext, Cursor inputCursor, GroupAdapterListener inputListener) {
super(inputCursor, DBHelper.LoyaltyCardDbGroups.ORDER);
setHasStableIds(true);
mSettings = new Settings(inputContext);
mContext = inputContext;
mContext = inputContext.getApplicationContext();
mListener = inputListener;
mDb = new DBHelper(inputContext);
swapCursor(mCursor);
}
@Override
public void swapCursor(Cursor inputCursor) {
super.swapCursor(inputCursor);
mCursor = inputCursor;
swapCursor(inputCursor);
}
@NonNull
@@ -43,11 +36,7 @@ class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListI
return new GroupListItemViewHolder(itemView);
}
public Cursor getCursor() {
return mCursor;
}
public void onBindViewHolder(GroupCursorAdapter.GroupListItemViewHolder inputHolder, Cursor inputCursor) {
public void onBindViewHolder(GroupListItemViewHolder inputHolder, Cursor inputCursor) {
Group group = Group.toGroup(inputCursor);
inputHolder.mName.setText(group._id);

View File

@@ -10,14 +10,20 @@ 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.FileOutputStream;
import java.io.IOException;
@@ -26,11 +32,6 @@ 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.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;
@@ -39,8 +40,6 @@ 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;
@@ -49,6 +48,10 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
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
@@ -76,6 +79,49 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
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);
@@ -83,60 +129,57 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "catima.zip");
Button exportButton = findViewById(R.id.exportButton);
exportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
builder.setTitle(R.string.exportPassword);
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;
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);
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();
chooseFileWithIntent(intentCreateDocumentAction, CHOOSE_EXPORT_LOCATION);
});
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
builder.show();
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");
@@ -194,7 +237,17 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
chooseFileWithIntent(baseIntent, IMPORT);
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)
@@ -297,7 +350,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
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());
@@ -373,69 +426,4 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
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, exportPassword.toCharArray(), true);
} 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, true);
}
} catch (IOException 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);
}
}

View File

@@ -33,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);

View File

@@ -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();
}
}
}

View File

@@ -5,7 +5,6 @@ import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.drawable.Drawable;
import android.util.SparseBooleanArray;
import android.util.TypedValue;
@@ -13,52 +12,54 @@ import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
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 androidx.core.graphics.BlendModeColorFilterCompat;
import androidx.core.graphics.BlendModeCompat;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder> {
private int mCurrentSelectedIndex = -1;
private Cursor mCursor;
Settings mSettings;
boolean mDarkModeEnabled;
private Context mContext;
private CardAdapterListener mListener;
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);
super(inputCursor, DBHelper.LoyaltyCardDbIds.ID);
setHasStableIds(true);
mSettings = new Settings(inputContext);
mContext = inputContext;
mContext = inputContext.getApplicationContext();
mListener = inputListener;
mSelectedItems = new SparseBooleanArray();
mAnimationItemsIndex = new SparseBooleanArray();
mDarkModeEnabled = Utils.isDarkModeEnabled(inputContext);
swapCursor(mCursor);
swapCursor(inputCursor);
}
@Override
public void swapCursor(Cursor inputCursor) {
super.swapCursor(inputCursor);
mCursor = inputCursor;
public void showDetails(boolean show) {
mShowDetails = show;
notifyDataSetChanged();
}
public boolean showingDetails() {
return mShowDetails;
}
@Override
@@ -67,23 +68,15 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
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) {
// Invisible until we want to show something more
inputHolder.mDivider.setVisibility(View.GONE);
// remove outline shadow
inputHolder.mThumbnailContainer.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
outline.setAlpha(0f);
}
});
int size = mSettings.getFontSizeMax(mSettings.getSmallFont());
if (mDarkModeEnabled) {
@@ -94,7 +87,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
inputHolder.mStoreField.setText(loyaltyCard.store);
inputHolder.mStoreField.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
if (!loyaltyCard.note.isEmpty()) {
if (mShowDetails && !loyaltyCard.note.isEmpty()) {
inputHolder.mNoteField.setVisibility(View.VISIBLE);
inputHolder.mNoteField.setText(loyaltyCard.note);
inputHolder.mNoteField.setTextSize(size);
@@ -102,7 +95,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
inputHolder.mNoteField.setVisibility(View.GONE);
}
if (!loyaltyCard.balance.equals(new BigDecimal("0"))) {
if (mShowDetails && !loyaltyCard.balance.equals(new BigDecimal("0"))) {
int drawableSize = dpToPx((size * 24) / 14, mContext);
inputHolder.mDivider.setVisibility(View.VISIBLE);
inputHolder.mBalanceField.setVisibility(View.VISIBLE);
@@ -118,7 +111,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
inputHolder.mBalanceField.setVisibility(View.GONE);
}
if (loyaltyCard.expiry != null) {
if (mShowDetails && loyaltyCard.expiry != null) {
int drawableSize = dpToPx((size * 24) / 14, mContext);
inputHolder.mDivider.setVisibility(View.VISIBLE);
inputHolder.mExpiryField.setVisibility(View.VISIBLE);
@@ -140,103 +133,49 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
Bitmap cardIcon = Utils.retrieveCardImage(mContext, loyaltyCard.id, ImageLocationType.icon);
if (cardIcon != null) {
inputHolder.mCardIcon.setImageBitmap(cardIcon);
inputHolder.mCardIcon.setBackgroundColor(Color.TRANSPARENT);
inputHolder.mCardIcon.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
if (loyaltyCard.headerColor != null) {
inputHolder.mCardIcon.setBackgroundColor(loyaltyCard.headerColor);
}
inputHolder.mCardIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
}
inputHolder.mIconLayout.setBackgroundColor(loyaltyCard.headerColor != null ? loyaltyCard.headerColor : ContextCompat.getColor(mContext, R.color.colorPrimary));
inputHolder.mStarIcon.setVisibility(loyaltyCard.starStatus != 0 ? View.VISIBLE : View.GONE);
int imageSize = dpToPx((size * 46) / 14, mContext);
inputHolder.mCardIcon.getLayoutParams().height = imageSize;
inputHolder.mCardIcon.getLayoutParams().width = imageSize;
inputHolder.mStarIcon.getLayoutParams().height = imageSize;
inputHolder.mStarIcon.getLayoutParams().width = imageSize;
inputHolder.mTickIcon.getLayoutParams().height = imageSize;
inputHolder.mTickIcon.getLayoutParams().width = imageSize;
/* Changing Padding and Mragin of different views according to font size
* Views Included:
* a) InformationContainer padding
* b) Store left padding
* c) Divider Margin
* d) note top margin
* e) row margin
* */
int marginPaddingSize = dpToPx((size * 16) / 14, mContext);
inputHolder.mInformationContainer.setPadding(marginPaddingSize, marginPaddingSize, marginPaddingSize, marginPaddingSize);
inputHolder.mStoreField.setPadding(marginPaddingSize, 0, 0, 0);
LinearLayout.LayoutParams lpDivider = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
lpDivider.setMargins(0, marginPaddingSize, 0, marginPaddingSize);
inputHolder.mDivider.setLayoutParams(lpDivider);
LinearLayout.LayoutParams lpNoteField = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
lpNoteField.setMargins(0, marginPaddingSize / 2, 0, 0);
inputHolder.mNoteField.setLayoutParams(lpNoteField);
LinearLayout.LayoutParams lpRow = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
lpRow.setMargins(marginPaddingSize / 2, marginPaddingSize / 2, marginPaddingSize / 2, marginPaddingSize / 2);
inputHolder.mRow.setLayoutParams(lpRow);
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.mRow.setOnClickListener(inputView -> mListener.onRowClicked(inputPosition));
inputHolder.mInformationContainer.setOnClickListener(inputView -> mListener.onRowClicked(inputPosition));
inputHolder.mRow.setOnLongClickListener(inputView -> {
mListener.onRowLongClicked(inputPosition);
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
});
inputHolder.mInformationContainer.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);
inputHolder.mCardIcon.setVisibility(View.GONE);
inputHolder.mTickIcon.setVisibility(View.VISIBLE);
if (mCurrentSelectedIndex == inputPosition) {
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, true);
resetCurrentIndex();
}
} else {
inputHolder.mThumbnailBackContainer.setVisibility(View.GONE);
resetIconYAxis(inputHolder.mThumbnailFrontContainer);
inputHolder.mThumbnailFrontContainer.setVisibility(View.VISIBLE);
inputHolder.mThumbnailFrontContainer.setAlpha(1);
inputHolder.mTickIcon.setVisibility(View.GONE);
inputHolder.mCardIcon.setVisibility(View.VISIBLE);
if ((mReverseAllAnimations && mAnimationItemsIndex.get(inputPosition, false)) || mCurrentSelectedIndex == inputPosition) {
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, false);
resetCurrentIndex();
}
}
}
private void resetIconYAxis(View inputView) {
if (inputView.getRotationY() != 0) {
inputView.setRotationY(0);
}
}
public void resetAnimationIndex() {
mReverseAllAnimations = false;
mAnimationItemsIndex.clear();
}
public void toggleSelection(int inputPosition) {
mCurrentSelectedIndex = inputPosition;
if (mSelectedItems.get(inputPosition, false)) {
@@ -285,25 +224,20 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
public static class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder {
public TextView mStoreField, mNoteField, mBalanceField, mExpiryField;
public LinearLayout mInformationContainer;
public ImageView mCardIcon, mStarIcon, mTickIcon;
public MaterialCardView mRow;
public MaterialCardView mIconLayout, mRow;
public View mDivider;
public RelativeLayout mThumbnailFrontContainer, mThumbnailBackContainer;
public MaterialCardView mThumbnailContainer;
public LoyaltyCardListItemViewHolder(View inputView, CardAdapterListener inputListener) {
super(inputView);
mRow = inputView.findViewById(R.id.row);
mIconLayout = inputView.findViewById(R.id.icon_layout);
mDivider = inputView.findViewById(R.id.info_divider);
mThumbnailContainer = inputView.findViewById(R.id.thumbnail_container);
mThumbnailFrontContainer = inputView.findViewById(R.id.thumbnail_front);
mThumbnailBackContainer = inputView.findViewById(R.id.thumbnail_back);
mInformationContainer = inputView.findViewById(R.id.information_container);
mStoreField = inputView.findViewById(R.id.store);
mNoteField = inputView.findViewById(R.id.note);
mBalanceField = inputView.findViewById(R.id.balance);
mExpiryField = inputView.findViewById(R.id.expiry);
mCardIcon = inputView.findViewById(R.id.thumbnail);
mStarIcon = inputView.findViewById(R.id.star);
mTickIcon = inputView.findViewById(R.id.selected_thumbnail);

View File

@@ -65,10 +65,10 @@ import java.util.concurrent.Callable;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.exifinterface.media.ExifInterface;
import androidx.fragment.app.DialogFragment;
@@ -662,14 +662,14 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
// ucrop 2.2.6 initial aspect ratio is glitched when 0x0 is used as the initial ratio option
// https://github.com/Yalantis/uCrop/blob/281c8e6438d81f464d836fc6b500517144af264a/ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java#L264
// so source width height has to be provided for now, depending on whether future versions of ucrop will support 0x0 as the default option
private void setCropperOptions(boolean oneByOneDefault, float sourceWidth, float sourceHeight) {
private void setCropperOptions(boolean cardShapeDefault, float sourceWidth, float sourceHeight) {
mCropperOptions.setCompressionFormat(TEMP_CROP_IMAGE_FORMAT);
mCropperOptions.setFreeStyleCropEnabled(true);
mCropperOptions.setHideBottomControls(false);
// default aspect ratio workaround
int selectedByDefault = 1;
if (oneByOneDefault) {
selectedByDefault = 0;
if (cardShapeDefault) {
selectedByDefault = 2;
}
mCropperOptions.setAspectRatioOptions(selectedByDefault,
new AspectRatio(null, 1, 1),
@@ -679,10 +679,10 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
}
private void setCropperTheme() {
mCropperOptions.setToolbarColor(getResources().getColor(R.color.colorPrimary));
mCropperOptions.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
mCropperOptions.setToolbarColor(getThemeColor());
mCropperOptions.setStatusBarColor(getThemeColor());
mCropperOptions.setToolbarWidgetColor(Color.WHITE);
mCropperOptions.setActiveControlsWidgetColor(getResources().getColor(R.color.colorPrimary));
mCropperOptions.setActiveControlsWidgetColor(getThemeColor());
}
@Override
@@ -893,11 +893,11 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
onResuming = false;
}
protected void setColorFromIcon(){
protected void setColorFromIcon() {
Object icon = thumbnail.getTag();
if(icon != null && (icon instanceof Bitmap)){
updateTempState(LoyaltyCardField.headerColor, new Palette.Builder((Bitmap)icon).generate().getDominantColor(tempLoyaltyCard.headerColor != null ? tempLoyaltyCard.headerColor : getResources().getColor(R.color.colorPrimary)));
}else{
if (icon != null && (icon instanceof Bitmap)) {
updateTempState(LoyaltyCardField.headerColor, new Palette.Builder((Bitmap) icon).generate().getDominantColor(tempLoyaltyCard.headerColor != null ? tempLoyaltyCard.headerColor : ContextCompat.getColor(this, R.color.colorPrimary)));
} else {
Log.d("setColorFromIcon", "attempting header color change from icon but icon does not exist");
}
}
@@ -1035,8 +1035,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
class ChooseCardImage implements View.OnClickListener {
@Override
public void onClick(View v) throws NoSuchElementException
{
public void onClick(View v) throws NoSuchElementException {
ImageView targetView;
if (v.getId() == R.id.frontImageHolder) {
@@ -1074,11 +1073,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
}
ColorPickerDialog dialog = dialogBuilder.create();
dialog.setColorPickerDialogListener(new ColorPickerDialogListener()
{
dialog.setColorPickerDialogListener(new ColorPickerDialogListener() {
@Override
public void onColorSelected(int dialogId, int color)
{
public void onColorSelected(int dialogId, int color) {
updateTempState(LoyaltyCardField.headerColor, color);
// Unset image if set
@@ -1088,8 +1085,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
}
@Override
public void onDialogDismissed(int dialogId)
{
public void onDialogDismissed(int dialogId) {
// Nothing to do, no change made
}
});
@@ -1317,7 +1313,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
Log.e(TAG, "Deleting card: " + loyaltyCardId);
DBHelper db = new DBHelper(LoyaltyCardEditActivity.this);
db.deleteLoyaltyCard(loyaltyCardId);
db.deleteLoyaltyCard(LoyaltyCardEditActivity.this, loyaltyCardId);
ShortcutHelper.removeShortcut(LoyaltyCardEditActivity.this, loyaltyCardId);
@@ -1352,9 +1348,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
mCropperOptions.setToolbarTitle(getResources().getString(R.string.setIcon));
}
if(requestedIcon()) {
setCropperOptions(true,0f, 0f);
}else{
if (requestedIcon()) {
setCropperOptions(true, 0f, 0f);
} else {
// sniff the input image for width and height to work around a ucrop bug
Bitmap image = null;
try {
@@ -1365,7 +1361,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
}
if (image == null) {
Log.d("cropper", "failed loading bitmap for initial width and height for ucrop " + sourceUri.toString());
setCropperOptions(true,0f, 0f);
setCropperOptions(true, 0f, 0f);
} else {
try {
Bitmap imageRotated = Utils.rotateBitmap(image, new ExifInterface(getContentResolver().openInputStream(sourceUri)));

View File

@@ -48,9 +48,11 @@ import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.Guideline;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.widget.NestedScrollView;
import androidx.core.widget.TextViewCompat;
import protect.card_locker.async.TaskHandler;
import protect.card_locker.preferences.Settings;
@@ -59,6 +61,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
private GestureDetector mGestureDetector;
CoordinatorLayout coordinatorLayout;
TextView cardIdFieldView;
BottomSheetBehavior behavior;
LinearLayout bottomSheet;
@@ -257,6 +260,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
db = new DBHelper(this);
importURIHelper = new ImportURIHelper(this);
coordinatorLayout = findViewById(R.id.coordinator_layout);
cardIdFieldView = findViewById(R.id.cardIdView);
bottomSheet = findViewById(R.id.bottom_sheet);
bottomSheetContentWrapper = findViewById(R.id.bottomSheetContentWrapper);
@@ -369,7 +373,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
mainImage.setOnTouchListener(gestureTouchListener);
}
private void changeUiToBottomSheetState(int newState){
private void changeUiToBottomSheetState(int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
editButton.hide();
} else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
@@ -387,9 +391,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
bottomSheetState = newState;
}
private void adjustLayoutHeights(){
private void adjustLayoutHeights() {
// use getLayoutParams instead of getHeight when heights are pre-determined in xml! getHeight could return 0 if a View is not inflated
if(iconImage.getLayoutParams().height != appBarLayout.getHeight()) {
if (iconImage.getLayoutParams().height != appBarLayout.getHeight()) {
Log.d("adjustLayoutHeights", "setting imageIcon height from: " + iconImage.getLayoutParams().height + " to: " + appBarLayout.getHeight());
iconImage.setLayoutParams(new CoordinatorLayout.LayoutParams(
CoordinatorLayout.LayoutParams.MATCH_PARENT, appBarLayout.getHeight())
@@ -406,17 +410,13 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
// bottomSheetContentWrapper.getChildAt(i).invalidate();
// }
// since it's basically allergic to getting enlarged then shrunk again, and setting it at all when fullscreen makes no sense
if(!isFullscreen){
if (!isFullscreen) {
Log.d("adjustLayoutHeights", "setting bottomSheet height from: " + params.height + " to: " + bottomSheetHeight);
bottomSheetContentWrapper.setLayoutParams(
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, bottomSheetHeight)
);
}
}
// XXX
// from android 5 - 9 a padding magically grows on top of bottomSheet after leaving fullscreen
// I suspect that it's a bug with going into immersive mode then out, along with coordinator layout bottom sheet
Log.d("adjustLayoutHeights", "padding top: " + bottomSheet.getPaddingTop() + " padding bottom: " + bottomSheet.getPaddingBottom());
}
@@ -561,14 +561,14 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
landscapeToolbar.setTitleTextColor(textColor);
Bitmap icon = Utils.retrieveCardImage(this, loyaltyCard.id, ImageLocationType.icon);
if (icon != null){
if (icon != null) {
int backgroundAlphaColor = Utils.needsDarkForeground(backgroundHeaderColor) ? Color.WHITE : Color.BLACK;
Log.d("onResume", "setting icon image");
iconImage.setImageBitmap(icon);
int backgroundWithAlpha = Color.argb(HEADER_FILTER_ALPHA, Color.red(backgroundAlphaColor), Color.green(backgroundAlphaColor), Color.blue(backgroundAlphaColor));
// for images that has alpha
appBarLayout.setBackgroundColor(backgroundWithAlpha);
}else{
} else {
Bitmap plain = Bitmap.createBitmap(new int[]{backgroundHeaderColor}, 1, 1, Bitmap.Config.ARGB_8888);
iconImage.setImageBitmap(plain);
appBarLayout.setBackgroundColor(Color.TRANSPARENT);
@@ -584,8 +584,11 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
// Make notification area light if dark icons are needed
if (Build.VERSION.SDK_INT >= 23) {
window.getDecorView().setSystemUiVisibility(backgroundNeedsDarkIcons ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0);
window.setStatusBarColor(Color.TRANSPARENT);
} else {
// Darken statusbar if icons won't be visible otherwise
window.setStatusBarColor(backgroundNeedsDarkIcons ? ColorUtils.blendARGB(backgroundHeaderColor, Color.BLACK, 0.15f) : Color.TRANSPARENT);
}
window.setStatusBarColor(Color.TRANSPARENT);
// Set shadow colour of store text so even same color on same color would be readable
storeName.setShadowLayer(1, 1, 1, backgroundNeedsDarkIcons ? Color.BLACK : Color.WHITE);
@@ -898,6 +901,8 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
editButton.hide();
// android 5-9, avoid padding growing on top of bottomSheet
coordinatorLayout.removeView(bottomSheet);
// Set Android to fullscreen mode
getWindow().getDecorView().setSystemUiVisibility(
@@ -940,6 +945,11 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
& ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
& ~View.SYSTEM_UI_FLAG_FULLSCREEN
);
// android 5-9, avoid padding growing on top of bottomSheet
if (bottomSheet.getParent() != coordinatorLayout) {
coordinatorLayout.addView(bottomSheet);
}
}
Log.d("setFullScreen", "Is full screen enabled? " + enabled + " Zoom Level = " + barcodeScaler.getProgress());

View File

@@ -26,12 +26,15 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.splashscreen.SplashScreen;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.SettingsActivity;
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener {
@@ -40,7 +43,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
private final DBHelper mDB = new DBHelper(this);
private LoyaltyCardCursorAdapter mAdapter;
private ActionMode mCurrentActionMode;
private Menu mMenu;
private SearchView mSearchView;
private GestureDetector mGestureDetector;
protected String mFilter = "";
protected Object mGroup = null;
@@ -52,6 +55,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
private View mNoMatchingCardsText;
private View mNoGroupCardsText;
private ActivityResultLauncher<Intent> mBarcodeScannerLauncher;
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode inputMode, Menu inputMenu) {
@@ -137,7 +142,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
Log.e(TAG, "Deleting card: " + loyaltyCard.id);
db.deleteLoyaltyCard(loyaltyCard.id);
db.deleteLoyaltyCard(MainActivity.this, loyaltyCard.id);
ShortcutHelper.removeShortcut(MainActivity.this, loyaltyCard.id);
}
@@ -163,12 +168,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
public void onDestroyActionMode(ActionMode inputMode) {
mAdapter.clearSelections();
mCurrentActionMode = null;
mCardList.post(new Runnable() {
@Override
public void run() {
mAdapter.resetAnimationIndex();
}
});
}
};
@@ -260,6 +259,24 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
.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);
}
});
}
@Override
@@ -271,12 +288,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
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
@@ -320,53 +333,16 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
bundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, groupsTabLayout.getTabAt(selectedTab).getText().toString());
}
intent.putExtras(bundle);
startActivityForResult(intent, Utils.BARCODE_SCAN);
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();
}
updateLoyaltyCardList();
return;
}
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, 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);
}
}
@Override
public void onBackPressed() {
if (mMenu != null) {
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
if (!searchView.isIconified()) {
searchView.setIconified(true);
return;
}
if (!mSearchView.isIconified()) {
mSearchView.setIconified(true);
return;
}
super.onBackPressed();
@@ -443,22 +419,20 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
@Override
public boolean onCreateOptionsMenu(Menu inputMenu) {
this.mMenu = 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);
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) {
return false;
@@ -485,6 +459,22 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
public boolean onOptionsItemSelected(MenuItem inputItem) {
int id = inputItem.getItemId();
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();
@@ -526,25 +516,25 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
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) {
Intent i = new Intent(getApplicationContext(), ImportExportActivity.class);
startActivityForResult(i, Utils.MAIN_REQUEST);
startActivity(i);
return true;
}
if (id == R.id.action_settings) {
Intent i = new Intent(getApplicationContext(), SettingsActivity.class);
startActivityForResult(i, Utils.MAIN_REQUEST);
startActivity(i);
return true;
}
if (id == R.id.action_about) {
Intent i = new Intent(getApplicationContext(), AboutActivity.class);
startActivityForResult(i, Utils.MAIN_REQUEST);
startActivity(i);
return true;
}
@@ -681,14 +671,11 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
}
@Override
public void onRowClicked(int inputPosition) {
if (mAdapter.getSelectedItemCount() > 0) {
enableActionMode(inputPosition);
} else {
Cursor selected = mAdapter.getCursor();
selected.moveToPosition(inputPosition);
// FIXME
//
// There is a really nasty edge case that can happen when someone taps a card but right
@@ -699,7 +686,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
// click is being processed. Sadly, I have not yet found a way to make that possible.
LoyaltyCard loyaltyCard;
try {
loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
loyaltyCard = mAdapter.getCard(inputPosition);
} catch (CursorIndexOutOfBoundsException e) {
Log.w(TAG, "Prevented crash from tap + swipe on ID " + inputPosition + ": " + e);
return;
@@ -713,7 +700,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard);
startActivityForResult(i, Utils.MAIN_REQUEST);
startActivity(i);
}
}
}

View File

@@ -165,7 +165,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
private void updateLoyaltyCardList() {
mAdapter.swapCursor(mDB.getLoyaltyCardCursor());
if (mAdapter.getCountFromCursor() == 0) {
if (mAdapter.getItemCount() == 0) {
mCardList.setVisibility(View.GONE);
mHelpText.setVisibility(View.VISIBLE);
} else {

View File

@@ -105,8 +105,4 @@ public class ManageGroupCursorAdapter extends LoyaltyCardCursorAdapter {
public HashMap<Integer, Boolean> exportInGroupState() {
return new HashMap<>(mInGroupOverlay);
}
public int getCountFromCursor() {
return super.getCursor().getCount();
}
}

View File

@@ -20,6 +20,8 @@ import com.journeyapps.barcodescanner.DecoratedBarcodeView;
import java.util.List;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
@@ -39,6 +41,10 @@ public class ScanActivity extends CatimaAppCompatActivity {
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(LoyaltyCardEditActivity.BUNDLE_CARDID) : null;
@@ -60,6 +66,8 @@ public class ScanActivity extends CatimaAppCompatActivity {
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);
@@ -159,8 +167,7 @@ public class ScanActivity extends CatimaAppCompatActivity {
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;
@@ -193,12 +200,12 @@ public class ScanActivity extends CatimaAppCompatActivity {
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);
}
}

View File

@@ -7,7 +7,8 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import java.util.Arrays;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
@@ -18,8 +19,6 @@ import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.ColorUtils;
import androidx.core.graphics.drawable.IconCompat;
import org.jetbrains.annotations.NotNull;
class ShortcutHelper {
// Android documentation says that no more than 5 shortcuts
// are supported. However, that may be too many, as not all
@@ -120,7 +119,8 @@ class ShortcutHelper {
ShortcutManagerCompat.setDynamicShortcuts(context, list);
}
static @NotNull Bitmap createAdaptiveBitmap(@NotNull Bitmap in, int paddingColor){
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));
@@ -143,7 +143,7 @@ class ShortcutHelper {
Bitmap iconBitmap = Utils.retrieveCardImage(context, loyaltyCard.id, ImageLocationType.icon);
if (iconBitmap == null) {
iconBitmap = Utils.generateIcon(context, loyaltyCard, true).getLetterTile();
}else{
} else {
iconBitmap = createAdaptiveBitmap(iconBitmap, loyaltyCard.headerColor == null ? PADDING_COLOR : loyaltyCard.headerColor);
}

View File

@@ -84,7 +84,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);

View File

@@ -70,7 +70,7 @@ public class CatimaExporter implements Exporter {
// If it exists, add to the .zip file
Bitmap image = Utils.retrieveCardImage(context, card.id, imageLocationType);
if (image != null) {
ZipParameters imageZipParameters = createZipParameters(Utils.getCardImageFileName(card.id, imageLocationType) ,password);
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) {

View File

@@ -13,32 +13,32 @@ import protect.card_locker.R;
import protect.card_locker.Utils;
public class Settings {
private Context context;
private SharedPreferences settings;
private final Context mContext;
private SharedPreferences mSettings;
public Settings(Context context) {
this.context = context;
this.settings = PreferenceManager.getDefaultSharedPreferences(context);
mContext = context.getApplicationContext();
mSettings = PreferenceManager.getDefaultSharedPreferences(context);
}
private String getResString(@StringRes int resId) {
return context.getString(resId);
return mContext.getString(resId);
}
private int getResInt(@IntegerRes int resId) {
return context.getResources().getInteger(resId);
return mContext.getResources().getInteger(resId);
}
private String getString(@StringRes int keyId, String defaultValue) {
return settings.getString(getResString(keyId), defaultValue);
return mSettings.getString(getResString(keyId), defaultValue);
}
private int getInt(@StringRes int keyId, @IntegerRes int defaultId) {
return settings.getInt(getResString(keyId), getResInt(defaultId));
return mSettings.getInt(getResString(keyId), getResInt(defaultId));
}
private boolean getBoolean(@StringRes int keyId, boolean defaultValue) {
return settings.getBoolean(getResString(keyId), defaultValue);
return mSettings.getBoolean(getResString(keyId), defaultValue);
}
public Locale getLocale() {

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="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>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="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>

View File

@@ -0,0 +1,22 @@
<?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: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>

View File

@@ -1,318 +1,88 @@
<?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"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</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: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: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: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: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: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: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: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: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: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: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: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: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" />
</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>

View File

@@ -38,7 +38,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="@integer/main_view_card_columns"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -1,146 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
xmlns:android="http://schemas.android.com/apk/res/android"
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/row"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_marginBottom="4dp">
<LinearLayout
android:id="@+id/information_container"
<com.google.android.material.card.MaterialCardView
android:id="@+id/icon_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="85.6f:53.98f"
app:cardCornerRadius="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/store">
<ImageView
android:id="@+id/thumbnail"
android:scaleType="fitCenter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/thumbnailDescription"
android:src="@mipmap/ic_launcher"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/selected_thumbnail"
android:scaleType="fitCenter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/thumbnailDescription"
app:srcCompat="@drawable/ic_done"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<ImageView
android:id="@+id/star"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_gravity="end"
app:srcCompat="@drawable/ic_starred_white"
android:contentDescription="@string/starImage"
app:tint="?attr/colorControlNormal"
android:visibility="gone"
tools:visibility="visible"
android:elevation="4dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/store"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceHeadline1"
app:layout_constraintTop_toBottomOf="@+id/icon_layout"
app:layout_constraintBottom_toTopOf="@+id/note"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text="Example store"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintTop_toBottomOf="@+id/store"
app:layout_constraintBottom_toTopOf="@+id/info_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text="Example note"/>
<com.google.android.material.card.MaterialCardView
android:id="@+id/thumbnail_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
app:cardBackgroundColor="@android:color/transparent">
<View
android:id="@+id/info_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="8dp"
android:background="?android:attr/dividerVertical"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintTop_toBottomOf="@+id/note"
app:layout_constraintBottom_toTopOf="@+id/balance"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<RelativeLayout
android:id="@+id/thumbnail_front"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/storeContainer"
android:layout_alignBottom="@+id/storeContainer"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/balance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
app:drawableLeftCompat="@drawable/ic_baseline_payments_24"
android:drawablePadding="4dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/info_divider"
app:layout_constraintBottom_toTopOf="@+id/expiry"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible"
tools:text="525 points"/>
<ImageView
android:id="@+id/thumbnail"
android:scaleType="fitCenter"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_centerVertical="true"
android:contentDescription="@string/thumbnailDescription"
android:src="@mipmap/ic_launcher" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/thumbnail_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<ImageView
android:id="@+id/selected_thumbnail"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_centerInParent="true"
android:contentDescription="@string/thumbnailDescription"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_done" />
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/store"
android:paddingStart="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_toRightOf="@+id/thumbnail_container"
android:layout_toLeftOf="@+id/star"
android:textAppearance="?attr/textAppearanceHeadline6" />
<ImageView
android:id="@+id/star"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_centerVertical="true"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_starred_white"
android:contentDescription="@string/starImage"
app:tint="?attr/colorControlNormal"
android:layout_alignParentEnd="true"
android:visibility="gone" />
</RelativeLayout>
<TextView
android:id="@+id/note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
android:visibility="gone" />
<View android:id="@+id/info_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="?android:attr/dividerVertical"
android:visibility="gone" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:paddingEnd="8dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
app:drawableLeftCompat="@drawable/ic_baseline_payments_24"
android:drawablePadding="4dp"
android:layout_alignParentStart="true"
android:visibility="gone" />
<TextView
android:id="@+id/expiry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
app:drawableLeftCompat="@drawable/ic_baseline_access_time_24"
android:drawablePadding="4dp"
android:layout_toEndOf="@+id/balance"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/expiry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
app:drawableLeftCompat="@drawable/ic_baseline_access_time_24"
android:drawablePadding="4dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/balance"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible"
tools:text="Tomorrow"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -8,6 +8,11 @@
android:icon="@drawable/ic_search_white"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="always|collapseActionView"/>
<item
android:id="@+id/action_unfold"
android:title="@string/action_hide_details"
android:icon="@drawable/ic_baseline_unfold_less_24"
app:showAsAction="always"/>
<item
android:id="@+id/action_sort"
android:title="@string/sort"

View File

@@ -3,33 +3,34 @@ Branden Archer
J. Lavoie
Allan Nordhøy
Heimen Stoffels
mondstern
solokot
mondstern
Katharine Chui
Oğuz Ersen
IllusiveMan196
Petr Novák
Taco
Gediminas Murauskas
StoyanDimitrov
Joel A
StoyanDimitrov
Nyatsuki
Samantaz Fox
arno-github
Ankit Tiwari
Sergio Paredes
laralem
arshbeerSingh
huuhaa
Miha Frangež
Michael Moroni
Olivia (Zoe)
laralem
betsythefc
waffshappen
K. Herbert
Quentin PAGÈS
String E. Fighter
Yurical
/usr/local/ΕΨΗΕΛΩΝ
Adolfo Jayme-Barrientos
Alessandro Mandelli
KovalevArtem
@@ -56,7 +57,7 @@ Kasina Dheeraj
Flav
Franciszek Stefan
Izzy
krkk
Karol Kosek
bittin
Maciej Błędkowski
Mattia

View File

@@ -217,4 +217,7 @@
<string name="selectColor">Избиране на цвят</string>
<string name="group_name_is_empty">Името на списъка не може да е празно</string>
<string name="group_edit">Редактиране на списък</string>
<string name="action_show_details">Повече детайли</string>
<string name="action_hide_details">По-малко детайли</string>
<string name="noGiftCardsGroup">Няма карти. След като добавите ще можете да ги зачислите към списък от тук.</string>
</resources>

View File

@@ -218,4 +218,6 @@
<string name="noGiftCardsGroup">Sie haben noch keine Kundenkarten. Sobald Sie welche hinzugefügt haben, können Sie sie hier der Gruppe zuordnen.</string>
<string name="setIcon">Symbol einstellen</string>
<string name="selectColor">Farbe auswählen</string>
<string name="action_show_details">Details anzeigen</string>
<string name="action_hide_details">Details ausblenden</string>
</resources>

View File

@@ -218,4 +218,6 @@
<string name="group_name_is_empty">Le nom du groupe ne peut pas être vide</string>
<string name="setIcon">Définir l\'icône</string>
<string name="selectColor">Sélectionnez la couleur</string>
<string name="action_show_details">Afficher les détails</string>
<string name="action_hide_details">Masquer les détails</string>
</resources>

View File

@@ -218,4 +218,6 @@
<string name="group_updated">Gruppo aggiornato</string>
<string name="selectColor">Seleziona il colore</string>
<string name="setIcon">Imposta l\'icona</string>
<string name="action_show_details">Mostra i dettagli</string>
<string name="action_hide_details">Nascondi i dettagli</string>
</resources>

View File

@@ -222,4 +222,6 @@
<string name="noGiftCardsGroup">Dar neturite jokių lojalumo kortelių. Kai kelias pridėsite, galėsite jas priskirti grupei čia.</string>
<string name="setIcon">Nustatyti piktogramą</string>
<string name="selectColor">Pasirinkti spalvą</string>
<string name="action_hide_details">Paslėpti informaciją</string>
<string name="action_show_details">Rodyti išsamią informaciją</string>
</resources>

View File

@@ -216,4 +216,8 @@
<string name="group_name_is_empty">Gruppenavn kan ikke være tomt</string>
<string name="editGroup">Redigerer gruppe: <xliff:g>%s</xliff:g></string>
<string name="noGiftCardsGroup">Du har ingen lojalitetskort enda. Når du først har det kan du legge dem til i en gruppe her.</string>
<string name="action_show_details">Vis detaljer</string>
<string name="action_hide_details">Skjul detaljer</string>
<string name="selectColor">Velg farge</string>
<string name="setIcon">Sett ikon</string>
</resources>

View File

@@ -218,4 +218,6 @@
<string name="group_edit">Groep bewerken</string>
<string name="setIcon">Kies een pictogram</string>
<string name="selectColor">Kies een kleur</string>
<string name="action_show_details">Details tonen</string>
<string name="action_hide_details">Details verbergen</string>
</resources>

View File

@@ -218,4 +218,6 @@
<string name="noGiftCardsGroup">Ainda não tem nenhum cartão de fidelidade. Assim que tenha adicionado alguns, pode atribuí-los ao grupo aqui.</string>
<string name="selectColor">Selecionar cor</string>
<string name="setIcon">Definir ícone</string>
<string name="action_show_details">Mostrar detalhes</string>
<string name="action_hide_details">Ocultar detalhes</string>
</resources>

View File

@@ -154,7 +154,7 @@
<string name="removeImage">Удалить изображение</string>
<string name="backImageDescription">Задняя сторона карты</string>
<string name="frontImageDescription">Лицевая сторона карты</string>
<string name="photos">Фотографии</string>
<string name="photos">Фото</string>
<string name="importStocardMessage">Выберите для импортирования файл <i>***-sync.zip</i>.
\nЭтот файл можно получить по электронной почте от support@stocardapp.com, предварительно запросив экспорт ваших данных.</string>
<string name="passwordRequired">Введите пароль</string>
@@ -225,5 +225,7 @@
<string name="group_name_already_in_use">Такое название группы уже существует</string>
<string name="noGiftCardsGroup">У вас ещё нет ни одной карты. Как только появится несколько карт, вы сможете добавить их в группу здесь.</string>
<string name="setIcon">Выбор значка</string>
<string name="selectColor">Выбор цвета</string>
<string name="selectColor">Выбрать цвет</string>
<string name="action_hide_details">Скрыть детали</string>
<string name="action_show_details">Показать детали</string>
</resources>

View File

@@ -208,4 +208,16 @@
<string name="on_github">på GitHub</string>
<string name="exportPassword">Sätt ett lösenord för att skydda din exporterade data (valfritt)</string>
<string name="exportPasswordHint">Ange lösenord</string>
<string name="group_updated">Gruppen har uppdaterats</string>
<string name="group_edit">Redigera grupp</string>
<string name="group_name_already_in_use">Gruppnamnet är redan upptaget</string>
<string name="group_name_is_empty">Gruppnamn måste anges</string>
<string name="editGroup">Redigerar grupp: <xliff:g>%s</xliff:g></string>
<string name="selectColor">Välj färg</string>
<string name="setIcon">Välj ikon</string>
<string name="action_show_details">Visa detaljer</string>
<string name="action_hide_details">Dölj detaljer</string>
<string name="credits">Bidragsgivare</string>
<string name="source_repository">Källkodslager</string>
<string name="noGiftCardsGroup">Du har inga kundkort än. När du senare lägger till några kan du placera dem i den här gruppen.</string>
</resources>

View File

@@ -218,4 +218,6 @@
<string name="group_updated">Grup güncellendi</string>
<string name="selectColor">Renk seç</string>
<string name="setIcon">Simge ayarla</string>
<string name="action_show_details">Ayrıntıları göster</string>
<string name="action_hide_details">Ayrıntıları gizle</string>
</resources>

View File

@@ -226,4 +226,6 @@
<string name="noGiftCardsGroup">У вас ще немає жодної картки. Коли ви додасте кілька, то зможете призначити їх до групи.</string>
<string name="selectColor">Вибір кольору</string>
<string name="setIcon">Вибір іконки</string>
<string name="action_show_details">Показати деталі</string>
<string name="action_hide_details">Сховати деталі</string>
</resources>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="main_view_card_columns">2</integer>
<integer name="main_view_card_columns">3</integer>
</resources>

View File

@@ -33,7 +33,8 @@
<dimen name="activity_margin">16dp</dimen>
<!-- The default letter tile text size -->
<dimen name="tileLetterFontSize">33sp</dimen>
<dimen name="tileLetterFontSizeForShortcut">24dp</dimen>
<dimen name="tileLetterFontSize">66sp</dimen>
<dimen name="tileLetterFontSizeForShortcut">48dp</dimen>
<dimen name="tileLetterImageSize">92dp</dimen>
<dimen name="cardViewLetterFontSize">100sp</dimen>
</resources>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="main_view_card_columns">1</integer>
<integer name="main_view_card_columns">2</integer>
</resources>

View File

@@ -253,4 +253,6 @@
<string name="rate_this_app">Rate this app</string>
<string name="on_google_play">on Google Play</string>
<string name="report_error">Report Error</string>
<string name="action_show_details">Show details</string>
<string name="action_hide_details">Hide details</string>
</resources>

View File

@@ -28,29 +28,27 @@ import static org.junit.Assert.assertTrue;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 23)
public class DatabaseTest
{
private DBHelper db;
public class DatabaseTest {
private DBHelper mDb;
private Activity mActivity;
private static final Integer DEFAULT_HEADER_COLOR = Color.BLACK;
@Before
public void setUp()
{
Activity activity = Robolectric.setupActivity(MainActivity.class);
db = TestHelpers.getEmptyDb(activity);
public void setUp() {
mActivity = Robolectric.setupActivity(MainActivity.class);
mDb = TestHelpers.getEmptyDb(mActivity);
}
@Test
public void addRemoveOneGiftCard()
{
assertEquals(0, db.getLoyaltyCardCount());
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
public void addRemoveOneGiftCard() {
assertEquals(0, mDb.getLoyaltyCardCount());
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getLoyaltyCardCount());
assertEquals(1, mDb.getLoyaltyCardCount());
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
assertNotNull(loyaltyCard);
assertEquals("store", loyaltyCard.store);
assertEquals("note", loyaltyCard.note);
@@ -63,25 +61,24 @@ public class DatabaseTest
assertEquals(DEFAULT_HEADER_COLOR, loyaltyCard.headerColor);
assertEquals(0, loyaltyCard.starStatus);
result = db.deleteLoyaltyCard(1);
result = mDb.deleteLoyaltyCard(mActivity, 1);
assertTrue(result);
assertEquals(0, db.getLoyaltyCardCount());
assertNull(db.getLoyaltyCard(1));
assertEquals(0, mDb.getLoyaltyCardCount());
assertNull(mDb.getLoyaltyCard(1));
}
@Test
public void updateGiftCard()
{
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
public void updateGiftCard() {
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getLoyaltyCardCount());
assertEquals(1, mDb.getLoyaltyCardCount());
result = db.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("10.00"), Currency.getInstance("EUR"), "cardId1", null, CatimaBarcode.fromBarcode(BarcodeFormat.AZTEC), DEFAULT_HEADER_COLOR);
result = mDb.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("10.00"), Currency.getInstance("EUR"), "cardId1", null, CatimaBarcode.fromBarcode(BarcodeFormat.AZTEC), DEFAULT_HEADER_COLOR);
assertTrue(result);
assertEquals(1, db.getLoyaltyCardCount());
assertEquals(1, mDb.getLoyaltyCardCount());
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
assertNotNull(loyaltyCard);
assertEquals("store1", loyaltyCard.store);
assertEquals("note1", loyaltyCard.note);
@@ -96,18 +93,17 @@ public class DatabaseTest
}
@Test
public void updateGiftCardOnlyStar()
{
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
public void updateGiftCardOnlyStar() {
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getLoyaltyCardCount());
assertEquals(1, mDb.getLoyaltyCardCount());
result = db.updateLoyaltyCardStarStatus(1, 1);
result = mDb.updateLoyaltyCardStarStatus(1, 1);
assertTrue(result);
assertEquals(1, db.getLoyaltyCardCount());
assertEquals(1, mDb.getLoyaltyCardCount());
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
assertNotNull(loyaltyCard);
assertEquals("store", loyaltyCard.store);
assertEquals("note", loyaltyCard.note);
@@ -122,25 +118,23 @@ public class DatabaseTest
}
@Test
public void updateMissingGiftCard()
{
assertEquals(0, db.getLoyaltyCardCount());
public void updateMissingGiftCard() {
assertEquals(0, mDb.getLoyaltyCardCount());
boolean result = db.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("0"), null, "cardId1",
boolean result = mDb.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("0"), null, "cardId1",
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR);
assertEquals(false, result);
assertEquals(0, db.getLoyaltyCardCount());
assertEquals(0, mDb.getLoyaltyCardCount());
}
@Test
public void emptyGiftCardValues()
{
long id = db.insertLoyaltyCard("", "", null, new BigDecimal("0"), null, "", null, null, null, 0, null);
public void emptyGiftCardValues() {
long id = mDb.insertLoyaltyCard("", "", null, new BigDecimal("0"), null, "", null, null, null, 0, null);
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getLoyaltyCardCount());
assertEquals(1, mDb.getLoyaltyCardCount());
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
assertNotNull(loyaltyCard);
assertEquals("", loyaltyCard.store);
assertEquals("", loyaltyCard.note);
@@ -155,37 +149,34 @@ public class DatabaseTest
}
@Test
public void giftCardsViaCursor()
{
public void giftCardsViaCursor() {
final int CARDS_TO_ADD = 10;
// Add the gift cards in reverse order, to ensure
// that they are sorted
for(int index = CARDS_TO_ADD-1; index >= 0; index--)
{
long id = db.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
for (int index = CARDS_TO_ADD - 1; index >= 0; index--) {
long id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 0, null);
boolean result = (id != -1);
assertTrue(result);
}
assertEquals(CARDS_TO_ADD, db.getLoyaltyCardCount());
assertEquals(CARDS_TO_ADD, mDb.getLoyaltyCardCount());
Cursor cursor = db.getLoyaltyCardCursor();
Cursor cursor = mDb.getLoyaltyCardCursor();
assertNotNull(cursor);
assertEquals(CARDS_TO_ADD, cursor.getCount());
cursor.moveToFirst();
for(int index = 0; index < CARDS_TO_ADD; index++)
{
assertEquals("store"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
assertEquals("note"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
for (int index = 0; index < CARDS_TO_ADD; index++) {
assertEquals("store" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
assertEquals("note" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
assertEquals(0, cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY)));
assertEquals("0", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE)));
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE)));
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
assertEquals("cardId" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID)));
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
@@ -206,36 +197,33 @@ public class DatabaseTest
long id;
// Add the gift cards in reverse order and add one with STAR, to ensure
// that they are sorted
for(int index = CARDS_TO_ADD-1; index >= 0; index--)
{
if (index == CARDS_TO_ADD-1) {
id = db.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
for (int index = CARDS_TO_ADD - 1; index >= 0; index--) {
if (index == CARDS_TO_ADD - 1) {
id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 1, null);
}
else {
id = db.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
} else {
id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 0, null);
}
boolean result = (id != -1);
assertTrue(result);
}
assertEquals(CARDS_TO_ADD, db.getLoyaltyCardCount());
assertEquals(CARDS_TO_ADD, mDb.getLoyaltyCardCount());
Cursor cursor = db.getLoyaltyCardCursor();
Cursor cursor = mDb.getLoyaltyCardCursor();
assertNotNull(cursor);
assertEquals(CARDS_TO_ADD, cursor.getCount());
cursor.moveToFirst();
int index = CARDS_TO_ADD-1 ;
assertEquals("store"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
assertEquals("note"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
int index = CARDS_TO_ADD - 1;
assertEquals("store" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
assertEquals("note" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
assertEquals(0, cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY)));
assertEquals("0", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE)));
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE)));
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
assertEquals("cardId" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID)));
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
@@ -243,14 +231,13 @@ public class DatabaseTest
cursor.moveToNext();
for(index = 0; index < CARDS_TO_ADD-1; index++)
{
assertEquals("store"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
assertEquals("note"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
for (index = 0; index < CARDS_TO_ADD - 1; index++) {
assertEquals("store" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
assertEquals("note" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY)));
assertEquals("0", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE)));
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE)));
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
assertEquals("cardId" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID)));
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
@@ -264,8 +251,7 @@ public class DatabaseTest
cursor.close();
}
private void setupDatabaseVersion1(SQLiteDatabase database)
{
private void setupDatabaseVersion1(SQLiteDatabase database) {
// Delete the tables as they exist now
database.execSQL("drop table " + DBHelper.LoyaltyCardDbIds.TABLE);
database.execSQL("drop table " + DBHelper.LoyaltyCardDbGroups.TABLE);
@@ -281,205 +267,196 @@ public class DatabaseTest
}
private int insertCardVersion1(SQLiteDatabase database,
final String store, final String cardId,
final String barcodeType)
{
final String store, final String cardId,
final String barcodeType) {
ContentValues contentValues = new ContentValues();
contentValues.put(DBHelper.LoyaltyCardDbIds.STORE, store);
contentValues.put(DBHelper.LoyaltyCardDbIds.CARD_ID, cardId);
contentValues.put(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
final long newId = database.insert(DBHelper.LoyaltyCardDbIds.TABLE, null, contentValues);
assertTrue(newId != -1);
return (int)newId;
return (int) newId;
}
@Test
public void addRemoveOneGroup()
{
assertEquals(0, db.getGroupCount());
long id = db.insertGroup("group one");
public void addRemoveOneGroup() {
assertEquals(0, mDb.getGroupCount());
long id = mDb.insertGroup("group one");
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getGroupCount());
assertEquals(1, mDb.getGroupCount());
Group group = db.getGroup("group one");
Group group = mDb.getGroup("group one");
assertNotNull(group);
assertEquals("group one", group._id);
result = db.deleteGroup("group one");
result = mDb.deleteGroup("group one");
assertTrue(result);
assertEquals(0, db.getGroupCount());
assertNull(db.getGroup("group one"));
assertEquals(0, mDb.getGroupCount());
assertNull(mDb.getGroup("group one"));
}
@Test
public void updateGroup()
{
public void updateGroup() {
// Create card
assertEquals(0, db.getLoyaltyCardCount());
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
assertEquals(0, mDb.getLoyaltyCardCount());
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getLoyaltyCardCount());
assertEquals(1, mDb.getLoyaltyCardCount());
// Create group
long groupId = db.insertGroup("group one");
long groupId = mDb.insertGroup("group one");
result = (groupId != -1);
assertTrue(result);
assertEquals(1, db.getGroupCount());
assertEquals(1, mDb.getGroupCount());
// Add card to group
Group group = db.getGroup("group one");
Group group = mDb.getGroup("group one");
List<Group> groupList1 = new ArrayList<>();
groupList1.add(group);
db.setLoyaltyCardGroups(1, groupList1);
mDb.setLoyaltyCardGroups(1, groupList1);
// Ensure the card has one group and the group has one card
List<Group> cardGroups = db.getLoyaltyCardGroups((int) id);
List<Group> cardGroups = mDb.getLoyaltyCardGroups((int) id);
assertEquals(1, cardGroups.size());
assertEquals("group one", cardGroups.get(0)._id);
assertEquals(1, db.getGroupCardCount("group one"));
assertEquals(1, mDb.getGroupCardCount("group one"));
// Rename group
result = db.updateGroup("group one", "group one renamed");
result = mDb.updateGroup("group one", "group one renamed");
assertTrue(result);
assertEquals(1, db.getGroupCount());
assertEquals(1, mDb.getGroupCount());
// Group one no longer exists
group = db.getGroup("group one");
group = mDb.getGroup("group one");
assertNull(group);
// But group one renamed does
Group group2 = db.getGroup("group one renamed");
Group group2 = mDb.getGroup("group one renamed");
assertNotNull(group2);
assertEquals("group one renamed", group2._id);
// And card is in "group one renamed"
// Ensure the card has one group and the group has one card
cardGroups = db.getLoyaltyCardGroups((int) id);
cardGroups = mDb.getLoyaltyCardGroups((int) id);
assertEquals(1, cardGroups.size());
assertEquals("group one renamed", cardGroups.get(0)._id);
assertEquals(1, db.getGroupCardCount("group one renamed"));
assertEquals(1, mDb.getGroupCardCount("group one renamed"));
}
@Test
public void updateMissingGroup()
{
assertEquals(0, db.getGroupCount());
public void updateMissingGroup() {
assertEquals(0, mDb.getGroupCount());
boolean result = db.updateGroup("group one", "new name");
boolean result = mDb.updateGroup("group one", "new name");
assertEquals(false, result);
assertEquals(0, db.getGroupCount());
assertEquals(0, mDb.getGroupCount());
}
@Test
public void emptyGroupValues()
{
long id = db.insertGroup("");
public void emptyGroupValues() {
long id = mDb.insertGroup("");
boolean result = (id != -1);
assertFalse(result);
assertEquals(0, db.getLoyaltyCardCount());
assertEquals(0, mDb.getLoyaltyCardCount());
}
@Test
public void duplicateGroupName()
{
assertEquals(0, db.getGroupCount());
long id = db.insertGroup("group one");
public void duplicateGroupName() {
assertEquals(0, mDb.getGroupCount());
long id = mDb.insertGroup("group one");
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getGroupCount());
assertEquals(1, mDb.getGroupCount());
Group group = db.getGroup("group one");
Group group = mDb.getGroup("group one");
assertNotNull(group);
assertEquals("group one", group._id);
// Should fail on duplicate
long id2 = db.insertGroup("group one");
long id2 = mDb.insertGroup("group one");
boolean result2 = (id2 != -1);
assertFalse(result2);
assertEquals(1, db.getGroupCount());
assertEquals(1, mDb.getGroupCount());
}
@Test
public void updateGroupDuplicate()
{
long id = db.insertGroup("group one");
public void updateGroupDuplicate() {
long id = mDb.insertGroup("group one");
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getGroupCount());
assertEquals(1, mDb.getGroupCount());
long id2 = db.insertGroup("group two");
long id2 = mDb.insertGroup("group two");
boolean result2 = (id2 != -1);
assertTrue(result2);
assertEquals(2, db.getGroupCount());
assertEquals(2, mDb.getGroupCount());
// Should fail when trying to rename group two to one
boolean result3 = db.updateGroup("group two", "group one");
boolean result3 = mDb.updateGroup("group two", "group one");
assertFalse(result3);
assertEquals(2, db.getGroupCount());
assertEquals(2, mDb.getGroupCount());
// Rename failed so both should still be the same
Group group = db.getGroup("group one");
Group group = mDb.getGroup("group one");
assertNotNull(group);
assertEquals("group one", group._id);
Group group2 = db.getGroup("group two");
Group group2 = mDb.getGroup("group two");
assertNotNull(group2);
assertEquals("group two", group2._id);
}
@Test
public void cardAddAndRemoveGroups()
{
public void cardAddAndRemoveGroups() {
// Create card
assertEquals(0, db.getLoyaltyCardCount());
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
assertEquals(0, mDb.getLoyaltyCardCount());
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
boolean result = (id != -1);
assertTrue(result);
assertEquals(1, db.getLoyaltyCardCount());
assertEquals(1, mDb.getLoyaltyCardCount());
// Create two groups to only one card
assertEquals(0, db.getGroupCount());
long gid = db.insertGroup("one");
assertEquals(0, mDb.getGroupCount());
long gid = mDb.insertGroup("one");
boolean gresult = (gid != -1);
assertTrue(gresult);
long gid2 = db.insertGroup("two");
long gid2 = mDb.insertGroup("two");
boolean gresult2 = (gid2 != -1);
assertTrue(gresult2);
assertEquals(2, db.getGroupCount());
assertEquals(2, mDb.getGroupCount());
Group group1 = db.getGroup("one");
Group group1 = mDb.getGroup("one");
// Card has no groups by default
List<Group> cardGroups = db.getLoyaltyCardGroups(1);
List<Group> cardGroups = mDb.getLoyaltyCardGroups(1);
assertEquals(0, cardGroups.size());
// Add one groups to card
List<Group> groupList1 = new ArrayList<>();
groupList1.add(group1);
db.setLoyaltyCardGroups(1, groupList1);
mDb.setLoyaltyCardGroups(1, groupList1);
List<Group> cardGroups1 = db.getLoyaltyCardGroups(1);
List<Group> cardGroups1 = mDb.getLoyaltyCardGroups(1);
assertEquals(1, cardGroups1.size());
assertEquals(cardGroups1.get(0)._id, group1._id);
assertEquals(1, db.getGroupCardCount("one"));
assertEquals(0, db.getGroupCardCount("two"));
assertEquals(1, mDb.getGroupCardCount("one"));
assertEquals(0, mDb.getGroupCardCount("two"));
// Remove groups
db.setLoyaltyCardGroups(1, new ArrayList<Group>());
List<Group> cardGroups2 = db.getLoyaltyCardGroups(1);
mDb.setLoyaltyCardGroups(1, new ArrayList<Group>());
List<Group> cardGroups2 = mDb.getLoyaltyCardGroups(1);
assertEquals(0, cardGroups2.size());
assertEquals(0, db.getGroupCardCount("one"));
assertEquals(0, db.getGroupCardCount("two"));
assertEquals(0, mDb.getGroupCardCount("one"));
assertEquals(0, mDb.getGroupCardCount("two"));
}
@Test
public void databaseUpgradeFromVersion1()
{
SQLiteDatabase database = db.getWritableDatabase();
public void databaseUpgradeFromVersion1() {
SQLiteDatabase database = mDb.getWritableDatabase();
// Setup the database as it appeared in revision 1
setupDatabaseVersion1(database);
@@ -489,10 +466,10 @@ public class DatabaseTest
int newCardId2 = insertCardVersion1(database, "store", "cardId", "");
// Upgrade database
db.onUpgrade(database, DBHelper.ORIGINAL_DATABASE_VERSION, DBHelper.DATABASE_VERSION);
mDb.onUpgrade(database, DBHelper.ORIGINAL_DATABASE_VERSION, DBHelper.DATABASE_VERSION);
// Determine that the entries are queryable and the fields are correct
LoyaltyCard card = db.getLoyaltyCard(newCardId);
LoyaltyCard card = mDb.getLoyaltyCard(newCardId);
assertEquals("store", card.store);
assertEquals("", card.note);
assertEquals(null, card.expiry);
@@ -503,11 +480,11 @@ public class DatabaseTest
assertEquals(BarcodeFormat.UPC_A, card.barcodeType.format());
assertEquals(null, card.headerColor);
assertEquals(0, card.starStatus);
assertEquals(0,card.lastUsed);
assertEquals(100,card.zoomLevel);
assertEquals(0, card.lastUsed);
assertEquals(100, card.zoomLevel);
// Determine that the entries are queryable and the fields are correct
LoyaltyCard card2 = db.getLoyaltyCard(newCardId2);
LoyaltyCard card2 = mDb.getLoyaltyCard(newCardId2);
assertEquals("store", card2.store);
assertEquals("", card2.note);
assertEquals(null, card2.expiry);
@@ -518,8 +495,8 @@ public class DatabaseTest
assertEquals(null, card2.barcodeType); // Empty string should've become null
assertEquals(null, card2.headerColor);
assertEquals(0, card2.starStatus);
assertEquals(0,card2.lastUsed);
assertEquals(100,card2.zoomLevel);
assertEquals(0, card2.lastUsed);
assertEquals(100, card2.zoomLevel);
database.close();
}

View File

@@ -20,10 +20,8 @@ import static org.robolectric.Shadows.shadowOf;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 23)
public class ImportExportActivityTest
{
private void registerIntentHandler(String handler)
{
public class ImportExportActivityTest {
private void registerIntentHandler(String handler) {
// Add something that will 'handle' the given intent type
PackageManager packageManager = RuntimeEnvironment.application.getPackageManager();
@@ -39,8 +37,7 @@ public class ImportExportActivityTest
Intent intent = new Intent(handler);
if(handler.equals(Intent.ACTION_GET_CONTENT))
{
if (handler.equals(Intent.ACTION_GET_CONTENT)) {
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
}
@@ -48,8 +45,7 @@ public class ImportExportActivityTest
shadowOf(packageManager).addResolveInfoForIntent(intent, info);
}
private void checkVisibility(Activity activity, int state, int divider, int title, int message, int button)
{
private void checkVisibility(Activity activity, int state, int divider, int title, int message, int button) {
View dividerView = activity.findViewById(divider);
View titleView = activity.findViewById(title);
View messageView = activity.findViewById(message);
@@ -62,8 +58,7 @@ public class ImportExportActivityTest
}
@Test
public void testAllOptionsAvailable()
{
public void testAllOptionsAvailable() {
registerIntentHandler(Intent.ACTION_PICK);
registerIntentHandler(Intent.ACTION_GET_CONTENT);

View File

@@ -45,7 +45,6 @@ import java.util.HashMap;
import java.util.List;
import androidx.core.content.res.ResourcesCompat;
import protect.card_locker.async.TaskHandler;
import protect.card_locker.importexport.DataFormat;
import protect.card_locker.importexport.ImportExportResult;

View File

@@ -30,8 +30,7 @@ public class ImportURITest {
private DBHelper db;
@Before
public void setUp()
{
public void setUp() {
Activity activity = Robolectric.setupActivity(MainActivity.class);
importURIHelper = new ImportURIHelper(activity);
db = TestHelpers.getEmptyDb(activity);
@@ -96,19 +95,17 @@ public class ImportURITest {
}
@Test
public void failToParseInvalidUri()
{
public void failToParseInvalidUri() {
try {
importURIHelper.parse(Uri.parse("https://example.com/test"));
assertTrue(false); // Shouldn't get here
} catch(InvalidObjectException ex) {
} catch (InvalidObjectException ex) {
// Desired behaviour
}
}
@Test
public void failToParseBadData()
{
public void failToParseBadData() {
String[] urls = new String[3];
urls[0] = "https://brarcher.github.io/loyalty-card-locker/share?stare=store&note=note&cardid=12345&barcodetype=ITF&headercolor=-416706";
urls[1] = "https://thelastproject.github.io/Catima/share#stare%3Dstore%26note%3Dnote%26balance%3D0%26cardid%3D12345%26barcodetype%3DITF%26headercolor%3D-416706";

View File

@@ -33,15 +33,13 @@ import static org.junit.Assert.assertTrue;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 23)
public class LoyaltyCardCursorAdapterTest
{
public class LoyaltyCardCursorAdapterTest {
private Activity activity;
private DBHelper db;
private SharedPreferences settings;
@Before
public void setUp()
{
public void setUp() {
ShadowLog.stream = System.out;
activity = Robolectric.setupActivity(MainActivity.class);
@@ -49,15 +47,13 @@ public class LoyaltyCardCursorAdapterTest
settings = PreferenceManager.getDefaultSharedPreferences(activity);
}
private void setFontScale(int fontSizeScale)
{
private void setFontScale(int fontSizeScale) {
settings.edit()
.putInt(activity.getResources().getString(R.string.settings_key_max_font_size_scale), fontSizeScale)
.apply();
.putInt(activity.getResources().getString(R.string.settings_key_max_font_size_scale), fontSizeScale)
.apply();
}
private View createView(Cursor cursor)
{
private View createView(Cursor cursor) {
LoyaltyCardCursorAdapter adapter = new LoyaltyCardCursorAdapter(activity.getApplicationContext(), cursor, (MainActivity) activity);
LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder viewHolder = adapter.createViewHolder(activity.findViewById(R.id.list), 0);
@@ -66,60 +62,48 @@ public class LoyaltyCardCursorAdapterTest
return viewHolder.itemView;
}
private void checkView(final View view, final String store, final String note, final String expiry, final String balance, boolean checkFontSizes)
{
private void checkView(final View view, final String store, final String note, final String expiry, final String balance, boolean checkFontSizes) {
final TextView storeField = view.findViewById(R.id.store);
final TextView noteField = view.findViewById(R.id.note);
final TextView expiryField = view.findViewById(R.id.expiry);
final TextView balanceField = view.findViewById(R.id.balance);
if(checkFontSizes)
{
if (checkFontSizes) {
Settings preferences = new Settings(activity.getApplicationContext());
int mediumFontSize = preferences.getFontSizeMax(preferences.getMediumFont());
int smallFontSize = preferences.getFontSizeMax(preferences.getSmallFont());
assertEquals(mediumFontSize, (int)storeField.getTextSize());
assertEquals(smallFontSize, (int)noteField.getTextSize());
assertEquals(smallFontSize, (int)expiryField.getTextSize());
assertEquals(mediumFontSize, (int) storeField.getTextSize());
assertEquals(smallFontSize, (int) noteField.getTextSize());
assertEquals(smallFontSize, (int) expiryField.getTextSize());
}
assertEquals(store, storeField.getText().toString());
if(!note.isEmpty())
{
if (!note.isEmpty()) {
assertEquals(View.VISIBLE, noteField.getVisibility());
assertEquals(note, noteField.getText().toString());
}
else
{
} else {
assertEquals(View.GONE, noteField.getVisibility());
}
if(!expiry.isEmpty())
{
if (!expiry.isEmpty()) {
assertEquals(View.VISIBLE, expiryField.getVisibility());
assertEquals(expiry, expiryField.getText().toString());
}
else
{
} else {
assertEquals(View.GONE, expiryField.getVisibility());
}
if(!balance.isEmpty())
{
if (!balance.isEmpty()) {
assertEquals(View.VISIBLE, balanceField.getVisibility());
assertEquals(balance, balanceField.getText().toString());
}
else
{
} else {
assertEquals(View.GONE, balanceField.getVisibility());
}
}
@Test
public void TestCursorAdapterEmptyNote()
{
public void TestCursorAdapterEmptyNote() {
db.insertLoyaltyCard("store", "", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
LoyaltyCard card = db.getLoyaltyCard(1);
@@ -128,14 +112,13 @@ public class LoyaltyCardCursorAdapterTest
View view = createView(cursor);
checkView(view, card.store, card.note, "", "",false);
checkView(view, card.store, card.note, "", "", false);
cursor.close();
}
@Test
public void TestCursorAdapterWithNote()
{
public void TestCursorAdapterWithNote() {
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
LoyaltyCard card = db.getLoyaltyCard(1);
@@ -144,14 +127,13 @@ public class LoyaltyCardCursorAdapterTest
View view = createView(cursor);
checkView(view, card.store, card.note, "", "",false);
checkView(view, card.store, card.note, "", "", false);
cursor.close();
}
@Test
public void TestCursorAdapterFontSizes()
{
public void TestCursorAdapterFontSizes() {
final Context context = activity.getApplicationContext();
Date expiryDate = new Date();
String dateString = DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate);
@@ -169,14 +151,13 @@ public class LoyaltyCardCursorAdapterTest
setFontScale(200);
view = createView(cursor);
checkView(view, card.store, card.note, dateString, "",true);
checkView(view, card.store, card.note, dateString, "", true);
cursor.close();
}
@Test
public void TestCursorAdapterStarring()
{
public void TestCursorAdapterStarring() {
assertNotEquals(-1, db.insertLoyaltyCard("storeA", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null));
assertNotEquals(-1, db.insertLoyaltyCard("storeB", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 1, null));
assertNotEquals(-1, db.insertLoyaltyCard("storeC", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 1, null));
@@ -218,8 +199,7 @@ public class LoyaltyCardCursorAdapterTest
}
@Test
public void TestCursorAdapter0Points()
{
public void TestCursorAdapter0Points() {
db.insertLoyaltyCard("store", "", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
LoyaltyCard card = db.getLoyaltyCard(1);
@@ -228,14 +208,13 @@ public class LoyaltyCardCursorAdapterTest
View view = createView(cursor);
checkView(view, card.store, card.note, "", "",false);
checkView(view, card.store, card.note, "", "", false);
cursor.close();
}
@Test
public void TestCursorAdapter0EUR()
{
public void TestCursorAdapter0EUR() {
db.insertLoyaltyCard("store", "", null, new BigDecimal("0"), Currency.getInstance("EUR"), "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
LoyaltyCard card = db.getLoyaltyCard(1);
@@ -244,14 +223,13 @@ public class LoyaltyCardCursorAdapterTest
View view = createView(cursor);
checkView(view, card.store, card.note, "", "",false);
checkView(view, card.store, card.note, "", "", false);
cursor.close();
}
@Test
public void TestCursorAdapter100Points()
{
public void TestCursorAdapter100Points() {
db.insertLoyaltyCard("store", "note", null, new BigDecimal("100"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
LoyaltyCard card = db.getLoyaltyCard(1);
@@ -260,14 +238,13 @@ public class LoyaltyCardCursorAdapterTest
View view = createView(cursor);
checkView(view, card.store, card.note, "", "100 points",false);
checkView(view, card.store, card.note, "", "100 points", false);
cursor.close();
}
@Test
public void TestCursorAdapter10USD()
{
public void TestCursorAdapter10USD() {
db.insertLoyaltyCard("store", "note", null, new BigDecimal("10.00"), Currency.getInstance("USD"), "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
LoyaltyCard card = db.getLoyaltyCard(1);
@@ -276,7 +253,7 @@ public class LoyaltyCardCursorAdapterTest
View view = createView(cursor);
checkView(view, card.store, card.note, "", "$10.00",false);
checkView(view, card.store, card.note, "", "$10.00", false);
cursor.close();
}

View File

@@ -67,32 +67,28 @@ import static org.robolectric.Shadows.shadowOf;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 23)
public class LoyaltyCardViewActivityTest
{
public class LoyaltyCardViewActivityTest {
private final String BARCODE_DATA = "428311627547";
private final CatimaBarcode BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A);
private final String EAN_BARCODE_DATA = "4763705295336";
private final CatimaBarcode EAN_BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.EAN_13);
enum ViewMode
{
enum ViewMode {
ADD_CARD,
VIEW_CARD,
UPDATE_CARD,
;
}
enum FieldTypeView
{
enum FieldTypeView {
TextView,
TextInputLayout,
ImageView
}
@Before
public void setUp()
{
public void setUp() {
// Output logs emitted during tests so they may be accessed
ShadowLog.stream = System.out;
}
@@ -100,8 +96,7 @@ public class LoyaltyCardViewActivityTest
/**
* Register a handler in the package manager for a image capture intent
*/
private void registerMediaStoreIntentHandler()
{
private void registerMediaStoreIntentHandler() {
// Add something that will 'handle' the media capture intent
PackageManager packageManager = RuntimeEnvironment.application.getPackageManager();
@@ -133,12 +128,9 @@ public class LoyaltyCardViewActivityTest
final String barcodeType,
boolean creatingNewCard) throws ParseException {
DBHelper db = new DBHelper(activity);
if(creatingNewCard)
{
if (creatingNewCard) {
assertEquals(0, db.getLoyaltyCardCount());
}
else
{
} else {
assertEquals(1, db.getLoyaltyCardCount());
}
@@ -172,43 +164,31 @@ public class LoyaltyCardViewActivityTest
assertEquals(balance, card.balance);
// The special "Never" string shouldn't actually be written to the loyalty card
if(expiry.equals(activity.getApplicationContext().getString(R.string.never)))
{
if (expiry.equals(activity.getApplicationContext().getString(R.string.never))) {
assertEquals(null, card.expiry);
}
else
{
} else {
assertEquals(DateFormat.getDateInstance().parse(expiry), card.expiry);
}
// The special "Points" string shouldn't actually be written to the loyalty card
if(balanceType.equals(activity.getApplicationContext().getString(R.string.points)))
{
if (balanceType.equals(activity.getApplicationContext().getString(R.string.points))) {
assertEquals(null, card.balanceType);
}
else
{
} else {
assertEquals(Currency.getInstance(balanceType), card.balanceType);
}
assertEquals(cardId, card.cardId);
// The special "Same as barcode ID" string shouldn't actually be written to the loyalty card
if(barcodeId.equals(activity.getApplicationContext().getString(R.string.sameAsCardId)))
{
if (barcodeId.equals(activity.getApplicationContext().getString(R.string.sameAsCardId))) {
assertEquals(null, card.barcodeId);
}
else
{
} else {
assertEquals(barcodeId, card.barcodeId);
}
// The special "No barcode" string shouldn't actually be written to the loyalty card
if(barcodeType.equals(activity.getApplicationContext().getString(R.string.noBarcode)))
{
if (barcodeType.equals(activity.getApplicationContext().getString(R.string.noBarcode))) {
assertEquals(null, card.barcodeType);
}
else
{
} else {
assertEquals(CatimaBarcode.fromName(barcodeType).format(), card.barcodeType.format());
}
assertNotNull(card.headerColor);
@@ -220,8 +200,7 @@ public class LoyaltyCardViewActivityTest
* Initiate and complete a barcode capture, either in success
* or in failure
*/
private void captureBarcodeWithResult(final Activity activity, final boolean success) throws IOException
{
private void captureBarcodeWithResult(final Activity activity, final boolean success) throws IOException {
// Start image capture
final Button startButton = activity.findViewById(R.id.enterButton);
startButton.performClick();
@@ -252,8 +231,7 @@ public class LoyaltyCardViewActivityTest
* Initiate and complete a barcode selection, either in success
* or in failure
*/
private void selectBarcodeWithResult(final Activity activity, final String barcodeData, final String barcodeType, final boolean success) throws IOException
{
private void selectBarcodeWithResult(final Activity activity, final String barcodeData, final String barcodeType, final boolean success) throws IOException {
// Start barcode selector
final Button startButton = activity.findViewById(R.id.enterButton);
startButton.performClick();
@@ -286,8 +264,7 @@ public class LoyaltyCardViewActivityTest
}
private void checkFieldProperties(final Activity activity, final int id, final int visibility,
final Object contents, final FieldTypeView fieldType)
{
final Object contents, final FieldTypeView fieldType) {
final View view = activity.findViewById(id);
assertNotNull(view);
assertEquals(visibility, view.getVisibility());
@@ -315,14 +292,10 @@ public class LoyaltyCardViewActivityTest
final String balanceString, final String balanceTypeString,
final String cardId, final String barcodeId,
final String barcodeType, final Bitmap frontImage,
final Bitmap backImage)
{
if(mode == ViewMode.VIEW_CARD)
{
final Bitmap backImage) {
if (mode == ViewMode.VIEW_CARD) {
checkFieldProperties(activity, R.id.cardIdView, View.VISIBLE, cardId, FieldTypeView.TextView);
}
else
{
} else {
int editVisibility = View.VISIBLE;
checkFieldProperties(activity, R.id.storeNameEdit, editVisibility, store, FieldTypeView.TextView);
@@ -340,11 +313,10 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void noDataLossOnResumeOrRotate()
{
public void noDataLossOnResumeOrRotate() {
registerMediaStoreIntentHandler();
for(boolean newCard : new boolean[] {false, true}) {
for (boolean newCard : new boolean[]{false, true}) {
System.out.println();
System.out.println("=====");
System.out.println("New card? " + newCard);
@@ -437,29 +409,27 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithoutParametersCheckFieldsAvailable()
{
public void startWithoutParametersCheckFieldsAvailable() {
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
activityController.start();
activityController.visible();
activityController.resume();
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never) , "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null);
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
}
@Test
public void startWithoutParametersCannotCreateLoyaltyCard()
{
public void startWithoutParametersCannotCreateLoyaltyCard() {
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
activityController.start();
activityController.visible();
activityController.resume();
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
assertEquals(0, db.getLoyaltyCardCount());
@@ -481,14 +451,13 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithoutParametersBack()
{
public void startWithoutParametersBack() {
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
activityController.start();
activityController.visible();
activityController.resume();
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
assertEquals(false, activity.isFinishing());
shadowOf(activity).clickMenuItem(android.R.id.home);
@@ -504,10 +473,10 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null);
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
// Complete barcode capture successfully
captureBarcodeWithResult(activity, true);
@@ -522,14 +491,13 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithoutParametersCaptureBarcodeFailure() throws IOException
{
public void startWithoutParametersCaptureBarcodeFailure() throws IOException {
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
activityController.start();
activityController.visible();
activityController.resume();
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
@@ -540,12 +508,11 @@ public class LoyaltyCardViewActivityTest
shadowOf(getMainLooper()).idle();
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null);
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
}
@Test
public void startWithoutParametersCaptureBarcodeCancel() throws IOException
{
public void startWithoutParametersCaptureBarcodeCancel() throws IOException {
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
activityController.start();
activityController.visible();
@@ -554,7 +521,7 @@ public class LoyaltyCardViewActivityTest
LoyaltyCardEditActivity activity = (LoyaltyCardEditActivity) activityController.get();
final Context context = activity.getApplicationContext();
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null);
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
// Complete barcode capture successfully
captureBarcodeWithResult(activity, true);
@@ -578,21 +545,17 @@ public class LoyaltyCardViewActivityTest
assertEquals(true, activity.isFinishing());
}
private ActivityController createActivityWithLoyaltyCard(boolean editMode)
{
private ActivityController createActivityWithLoyaltyCard(boolean editMode) {
Intent intent = new Intent();
final Bundle bundle = new Bundle();
bundle.putInt("id", 1);
Class clazz;
if(editMode)
{
if (editMode) {
bundle.putBoolean("update", true);
clazz = LoyaltyCardEditActivity.class;
}
else
{
} else {
bundle.putBoolean("view", true);
clazz = LoyaltyCardViewActivity.class;
}
@@ -603,10 +566,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardEditModeCheckDisplay() throws IOException
{
public void startWithLoyaltyCardEditModeCheckDisplay() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -622,10 +584,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardViewModeCheckDisplay() throws IOException
{
public void startWithLoyaltyCardViewModeCheckDisplay() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -641,10 +602,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardWithBarcodeUpdateBarcode() throws IOException
{
public void startWithLoyaltyCardWithBarcodeUpdateBarcode() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -666,8 +626,7 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardWithReceiptUpdateReceiptCancel() throws IOException
{
public void startWithLoyaltyCardWithReceiptUpdateReceiptCancel() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
LoyaltyCardEditActivity activity = (LoyaltyCardEditActivity) activityController.get();
final Context context = activity.getApplicationContext();
@@ -705,10 +664,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardNoExpirySetExpiry() throws IOException
{
public void startWithLoyaltyCardNoExpirySetExpiry() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -738,10 +696,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardExpirySetNoExpiry() throws IOException
{
public void startWithLoyaltyCardExpirySetNoExpiry() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -763,10 +720,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardNoBalanceSetBalance() throws IOException
{
public void startWithLoyaltyCardNoBalanceSetBalance() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -814,10 +770,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardBalanceSetNoBalance() throws IOException
{
public void startWithLoyaltyCardBalanceSetNoBalance() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -855,10 +810,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardSameAsCardIDUpdateBarcodeID()
{
public void startWithLoyaltyCardSameAsCardIDUpdateBarcodeID() {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -887,10 +841,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardSameAsCardIDUpdateCardID()
{
public void startWithLoyaltyCardSameAsCardIDUpdateCardID() {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -921,10 +874,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDUpdate()
{
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDUpdate() {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -958,10 +910,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDDoNotUpdate()
{
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDDoNotUpdate() {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -995,10 +946,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void checkMenu() throws IOException
{
public void checkMenu() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
@@ -1023,10 +973,9 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithMissingLoyaltyCard() throws IOException
{
public void startWithMissingLoyaltyCard() throws IOException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
activityController.start();
activityController.visible();
@@ -1043,11 +992,10 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithoutParametersViewBack()
{
public void startWithoutParametersViewBack() {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
@@ -1063,11 +1011,10 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startWithoutColors()
{
public void startWithoutColors() {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, null, 0, null);
@@ -1086,7 +1033,7 @@ public class LoyaltyCardViewActivityTest
public void startLoyaltyCardWithoutColorsSave() throws IOException, ParseException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, null, 0, null);
@@ -1104,7 +1051,7 @@ public class LoyaltyCardViewActivityTest
public void startLoyaltyCardWithExplicitNoBarcodeSave() throws IOException, ParseException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, null, Color.BLACK, 0, null);
@@ -1121,7 +1068,7 @@ public class LoyaltyCardViewActivityTest
@Test
public void removeBarcodeFromLoyaltyCard() throws IOException, ParseException {
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
@@ -1149,11 +1096,10 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void startCheckFontSizes()
{
public void startCheckFontSizes() {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
@@ -1161,8 +1107,8 @@ public class LoyaltyCardViewActivityTest
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(activity);
settings.edit()
.putInt(activity.getResources().getString(R.string.settings_key_max_font_size_scale), 100)
.apply();
.putInt(activity.getResources().getString(R.string.settings_key_max_font_size_scale), 100)
.apply();
activityController.start();
activityController.visible();
@@ -1184,13 +1130,11 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void checkScreenOrientationLockSetting()
{
for(boolean locked : new boolean[] {false, true})
{
public void checkScreenOrientationLockSetting() {
for (boolean locked : new boolean[]{false, true}) {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = new DBHelper(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
@@ -1207,12 +1151,9 @@ public class LoyaltyCardViewActivityTest
MenuItem item = shadowOf(activity).getOptionsMenu().findItem(R.id.action_lock_unlock);
if(locked)
{
if (locked) {
assertEquals(item.isVisible(), false);
}
else
{
} else {
assertEquals(item.isVisible(), true);
String title = item.getTitle().toString();
assertEquals(title, activity.getString(R.string.lockScreen));
@@ -1223,8 +1164,7 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void checkPushStarIcon()
{
public void checkPushStarIcon() {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity) activityController.get();
@@ -1258,11 +1198,10 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void checkBarcodeFullscreenWorkflow()
{
public void checkBarcodeFullscreenWorkflow() {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
@@ -1364,11 +1303,10 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void checkNoBarcodeFullscreenWorkflow()
{
public void checkNoBarcodeFullscreenWorkflow() {
ActivityController activityController = createActivityWithLoyaltyCard(false);
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, null, Color.BLACK, 0, null);
@@ -1408,8 +1346,7 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void importCard()
{
public void importCard() {
Date date = new Date();
Uri importUri = Uri.parse("https://catima.app/share#store%3DExample%2BStore%26note%3D%26expiry%3D" + date.getTime() + "%26balance%3D10.00%26balancetype%3DUSD%26cardid%3D123456%26barcodetype%3DAZTEC%26headercolor%3D-416706");
@@ -1423,7 +1360,7 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
shadowOf(getMainLooper()).idle();
@@ -1433,8 +1370,7 @@ public class LoyaltyCardViewActivityTest
}
@Test
public void importCardOldFormat()
{
public void importCardOldFormat() {
Uri importUri = Uri.parse("https://brarcher.github.io/loyalty-card-locker/share?store=Example%20Store&note=&cardid=123456&barcodetype=AZTEC&headercolor=-416706&headertextcolor=-1");
Intent intent = new Intent();
@@ -1446,7 +1382,7 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
Activity activity = (Activity)activityController.get();
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
checkAllFields(activity, ViewMode.ADD_CARD, "Example Store", "", context.getString(R.string.never), "0", context.getString(R.string.points), "123456", context.getString(R.string.sameAsCardId), "Aztec", null, null);

View File

@@ -32,8 +32,7 @@ import static org.robolectric.Shadows.shadowOf;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 23)
public class MainActivityTest
{
public class MainActivityTest {
private SharedPreferences prefs;
@Test
@@ -59,9 +58,10 @@ public class MainActivityTest
assertNotNull(menu);
// The settings, import/export, groups, search and add button should be present
assertEquals(menu.size(), 6);
assertEquals(menu.size(), 7);
assertEquals("Search", menu.findItem(R.id.action_search).getTitle().toString());
assertEquals("Sort", menu.findItem(R.id.action_sort).getTitle().toString());
assertEquals("Hide details", menu.findItem(R.id.action_unfold).getTitle().toString());
assertEquals("Groups", menu.findItem(R.id.action_manage_groups).getTitle().toString());
assertEquals("Import/Export", menu.findItem(R.id.action_import_export).getTitle().toString());
assertEquals("About", menu.findItem(R.id.action_about).getTitle().toString());
@@ -69,8 +69,7 @@ public class MainActivityTest
}
@Test
public void clickAddStartsScan()
{
public void clickAddStartsScan() {
final MainActivity activity = Robolectric.setupActivity(MainActivity.class);
activity.findViewById(R.id.fabAdd).performClick();
@@ -80,11 +79,10 @@ public class MainActivityTest
}
@Test
public void addOneLoyaltyCard()
{
public void addOneLoyaltyCard() {
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
Activity mainActivity = (Activity)activityController.get();
Activity mainActivity = (Activity) activityController.get();
activityController.start();
activityController.resume();
@@ -118,7 +116,7 @@ public class MainActivityTest
{
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
Activity mainActivity = (Activity)activityController.get();
Activity mainActivity = (Activity) activityController.get();
activityController.start();
activityController.resume();
activityController.visible();
@@ -162,11 +160,10 @@ public class MainActivityTest
}
@Test
public void testGroups()
{
public void testGroups() {
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
Activity mainActivity = (Activity)activityController.get();
Activity mainActivity = (Activity) activityController.get();
activityController.start();
activityController.resume();
@@ -212,11 +209,10 @@ public class MainActivityTest
}
@Test
public void testFiltering()
{
public void testFiltering() {
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
MainActivity mainActivity = (MainActivity)activityController.get();
MainActivity mainActivity = (MainActivity) activityController.get();
activityController.start();
activityController.resume();

View File

@@ -19,7 +19,8 @@ public class TestHelpers {
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
try {
Utils.saveCardImage(activity.getApplicationContext(), null, cardID, imageLocationType);
} catch (FileNotFoundException ignored) {}
} catch (FileNotFoundException ignored) {
}
}
cursor.moveToNext();

View File

@@ -12,11 +12,9 @@ import static org.junit.Assert.assertEquals;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 23)
public class UtilsTest
{
public class UtilsTest {
@Test
public void parseBalances()
{
public void parseBalances() {
assertEquals("1", Utils.parseCurrency("1", false).toPlainString());
assertEquals("1", Utils.parseCurrency("1", true).toPlainString());
@@ -67,8 +65,7 @@ public class UtilsTest
}
@Test
public void formatBalances()
{
public void formatBalances() {
Currency euro = Currency.getInstance("EUR");
assertEquals("1", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("1"), null));

View File

@@ -1 +0,0 @@
Catima - Svobodná brašna karet

View File

@@ -0,0 +1,2 @@
- New main screen layout
- Fix bottomsheet sizing issues when switching in and out of fullscreen

View File

@@ -0,0 +1,2 @@
- 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

View File

@@ -0,0 +1,3 @@
- Fix blurriness of main screen letter icons
- Fix icons sometimes disappearing after selection
- Fix status bar icons possibly being invisible on Android 5

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 113 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

@@ -1 +1 @@
Catima — The Libre Card Wallet
Catima — Loyalty Card Wallet

View File

@@ -0,0 +1,2 @@
- Catima lagt til i hurtigtilgang til kontroller for enheter (https://developer.android.com/guide/topics/ui/device-control)
- Grupper vises nå riktig i gruppehåndtering

View File

@@ -1 +1 @@
Catima — for kundekort, billetter og kuponger 🎴
Catima — for kundekort, billetter og kuponger

View File

@@ -0,0 +1,4 @@
- Suporte de gestão de grupos melhorado
- Possibilidade de recortar imagens
- Corrigida a perda de dados da imagem ao guardar após rodar a visualização na edição
- Possibilidade de definir uma imagem personalizada como ícone do cartão

View File

@@ -1 +0,0 @@
Catima gestor de cartões livre

View File

@@ -1 +1 @@
Catima — Open Source кошелёк для карт
Catima — кошелёк для карт

View File

@@ -0,0 +1,2 @@
- Yeni ana ekran düzeni
- Tam ekrana girip çıkarken alt sayfa boyutlandırma sorunlarını düzelt

View File

@@ -0,0 +1,2 @@
- Покращено інтерфейс списку карт. (pull #188 (https://github.com/brarcher/loyalty-card-locker/pull/188))
- Покращено інтерфейс перегляду карти. (pull #190 (https://github.com/brarcher/loyalty-card-locker/pull/190))

View File

@@ -1 +1 @@
- Змінено відображення карт: показ заміток та імені магазину, багаторядкове ID карти та. (pull #197 (https://github.com/brarcher/loyalty-card-locker/pull/197))
- Змінено відображення карт: показ заміток та імені магазину, багаторядкове ID карти. (pull #197 (https://github.com/brarcher/loyalty-card-locker/pull/197))

View File

@@ -0,0 +1,2 @@
- Відкат min SDK з версії 17 до 15. (pull #226 (https://github.com/brarcher/loyalty-card-locker/pull/226))
- Стара бібліотека apache тепер використовується лише для тестів. (pull #225 (https://github.com/brarcher/loyalty-card-locker/pull/225))

View File

@@ -0,0 +1,5 @@
- Додано переклади
- Польська (pull #232 (https://github.com/brarcher/loyalty-card-locker/pull/232))
- Іспанська (pull #232 (https://github.com/brarcher/loyalty-card-locker/pull/232))
- Словацька(pull #232 (https://github.com/brarcher/loyalty-card-locker/pull/232))
- Оновлено переклади (pull #239 (https://github.com/brarcher/loyalty-card-locker/pull/239))

View File

@@ -0,0 +1,2 @@
- Виправлено іспанську локалізацію (pull #244 (https://github.com/brarcher/loyalty-card-locker/pull/244))
- Оновлено переклади (pull #244 (https://github.com/brarcher/loyalty-card-locker/pull/244))

View File

@@ -0,0 +1,14 @@
- Тепер офіційно підтримується наступний список з 1D та 2D штрих-кодів:
- AZTEC
- CODABAR
- CODE_39
- CODE_128
- DATA_MATRIX
- EAN_8
- EAN_13
- ITF
- PDF_417
- QR_CODE
- UPC_A
- Тепер згенеровані штрих-коди більші, тому легше сприймаються сканером

View File

@@ -0,0 +1,4 @@
- Додано налаштування яскравості екрану при перегляді штрих-коду (pull #259 (https://github.com/brarcher/loyalty-card-locker/pull/259))
- Додано грецьку локалізацію (pull #252 (https://github.com/brarcher/loyalty-card-locker/pull/252))
- Додано словенську локалізацію (pull #260 (https://github.com/brarcher/loyalty-card-locker/pull/260))
- Оновлено переклади (pull #260 (https://github.com/brarcher/loyalty-card-locker/pull/260), pull #254 (https://github.com/brarcher/loyalty-card-locker/pull/254))

View File

@@ -0,0 +1,2 @@
- Сортування списку карток ігнорує регістр (pull #266 (https://github.com/brarcher/loyalty-card-locker/pull/266))
- Додано налаштування для блокування орієнтації усіх карток (pull #269 (https://github.com/brarcher/loyalty-card-locker/pull/269)

View File

@@ -0,0 +1 @@
- Виправлено створення нової карти за допомогою вводу штрих-коду вручну (issue #272 (https://github.com/brarcher/loyalty-card-locker/issues/272))

View File

@@ -0,0 +1 @@
- Оновлено та додано переклади

View File

@@ -0,0 +1 @@
- Оновлено російську локалізацію