Compare commits

...

260 Commits

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

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



Current translation status:

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


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

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

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

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

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

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

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



Current translation status:

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


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

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

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

# Summary

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

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

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



Current translation status:

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


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

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

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

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



Current translation status:

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


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

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

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

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

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



Current translation status:

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


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

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



Current translation status:

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


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

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

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

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

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

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

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



Current translation status:

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


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

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

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

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

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

Co-authored-by: aditya3901 <2020itb058.aditya@students.iiests.ac.in>
2021-10-18 16:06:10 +00:00
aditya3901
2b22dd4a1f feat/copyable-textview 2021-10-18 14:29:30 +05:30
bors[bot]
a70710ca6a Merge #504
504: Update Fastlane changelogs r=TheLastProject a=github-actions[bot]

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

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

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



Current translation status:

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Remaining - Dialogue Box for entering password.

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

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

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



Current translation status:

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


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

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

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



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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/lt/
2021-10-08 07:04:24 +02:00
Sylvia van Os
fd7e6e4993 Release Catima 2.7.1 2021-10-07 20:04:19 +02:00
Sylvia van Os
b749c79a81 Merge pull request #464 from TheLastProject/create-pull-request/patch-1633550408
Update Fastlane changelogs
2021-10-06 22:01:05 +02:00
TheLastProject
5d019a8e5b Update Fastlane changelogs 2021-10-06 20:00:07 +00:00
Sylvia van Os
4e203aebfe Improve search with spaces 2021-10-06 21:59:45 +02:00
Sylvia van Os
fb2bede135 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-10-06 19:58:44 +02:00
Sylvia van Os
5a88909cd2 Make spotbugs happy 2021-10-06 19:58:29 +02:00
Sylvia van Os
017034a788 Google. Again. 2021-10-06 12:03:09 +02:00
Sylvia van Os
66ff6f8199 Merge branch 'master' of github.com:TheLastProject/Catima 2021-10-06 11:17:38 +02:00
Sylvia van Os
ddccbad020 Fuck you, Google. Fuck you. 2021-10-06 11:17:28 +02:00
Sylvia van Os
578fb068ee Merge pull request #463 from weblate/weblate-catima-catima
Translations update from Weblate
2021-10-06 09:28:31 +02:00
Petr Novák
d624eb3842 Translated using Weblate (Czech)
Currently translated at 98.8% (83 of 84 strings)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-09-20 21:39:11 +02:00
Sylvia van Os
2e648d1062 Remove cat face everywhere 2021-09-19 15:46:00 +02:00
235 changed files with 3443 additions and 1219 deletions

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gradle" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

View File

@@ -2,9 +2,13 @@ name: Android CI
on:
push:
branches: [ master ]
branches:
- master
- staging
- trying
pull_request:
branches: [ master ]
branches:
- master
jobs:
build:

View File

@@ -2,7 +2,7 @@ name: 'Close issues and PRs needing info for too long'
on:
schedule:
- cron: '30 1 * * *'
permissions:
issues: write
pull-requests: write

View File

@@ -1,7 +1,8 @@
name: Convert CHANGELOG to Fastlane
on:
push:
branches: [ master ]
branches:
- master
jobs:
convert_changelog_to_fastlane:

View File

@@ -13,10 +13,12 @@ name: "CodeQL"
on:
push:
branches: [ master ]
branches:
- master
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
branches:
- master
schedule:
- cron: '33 1 * * 4'

View File

@@ -1,11 +1,12 @@
name: Write contributors to file
on:
push:
branches: [ master ]
schedule:
- cron: '3 4 * * 0'
jobs:
contributors_to_file:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
name: Write contributors to file
steps:
- name: Checkout repo

View File

@@ -1,5 +1,37 @@
# Changelog
## Unreleased - 89
- Fix swiping between groups not working on an empty group
- Allow password-protecting exports
- Improve usage of space for QR codes
- Save the last used zoom level per card
- Fix a crash when swiping right after a tap
## v2.7.3 - 88 (2021-10-10)
- Fix incorrect migration making first card become invisible
## v2.7.2 - 87 (2021-10-09)
- Fix regression breaking import/export
## v2.7.1 - 86 (2021-10-07)
- Improve search with spaces
## v2.7.0 - 85 (2021-10-05)
Android 4.4 is no longer supported starting with this release. If you want to use Catima on Android 4.4, please use version 2.6.1.
- Improved Android 12 support
- Improved about screen
- Search now ignores accents
## v2.6.1 - 84 (2021-09-25)
- Minor bugfixes and improvements
## v2.6.0 - 83 (2021-09-19)
- Support for changing the sorting order

View File

@@ -11,15 +11,15 @@ spotbugs {
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
compileSdkVersion 31
buildToolsVersion "31.0.0"
defaultConfig {
applicationId "me.hackerchick.catima"
minSdkVersion 19
targetSdkVersion 30
versionCode 83
versionName "2.6.0"
minSdkVersion 21
targetSdkVersion 31
versionCode 89
versionName "2.8.0"
vectorDrawables.useSupportLibrary true
multiDexEnabled true
@@ -81,20 +81,22 @@ android {
dependencies {
// AndroidX
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.4.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
// Splash Screen
implementation 'androidx.core:core-splashscreen:1.0.0-alpha02'
// Third-party
implementation 'com.journeyapps:zxing-android-embedded:4.1.0@aar'
implementation 'com.journeyapps:zxing-android-embedded:4.2.0@aar'
implementation 'com.google.zxing:core:3.4.1'
implementation 'org.apache.commons:commons-csv:1.8'
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.8.0'
implementation 'net.lingala.zip4j:zip4j:2.9.0'
// SpotBugs
implementation 'io.wcm.tooling.spotbugs:io.wcm.tooling.spotbugs.annotations:1.0.0'

View File

@@ -17,7 +17,7 @@
android:name="android.hardware.camera.autofocus"
android:required="false" />
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android"/>
<application
android:name=".LoyaltyCardLockerApplication"
@@ -29,13 +29,15 @@
<activity
android:name="protect.card_locker.MainActivity"
android:label="@string/app_name"
android:theme="@style/SplashTheme">
android:theme="@style/Theme.App.Starting"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".AboutActivity"
android:label="@string/about"
@@ -56,19 +58,28 @@
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="stateHidden"
android:exported="true">
<intent-filter android:autoVerify="true" android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Main card sharing URIs -->
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="@string/intent_import_card_from_url_host_catima_app"
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_catima_app" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Listen to known card sharing URIs -->
<data android:scheme="https"
android:host="@string/intent_import_card_from_url_host_catima_app"
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_catima_app" />
<data android:scheme="https"
android:host="@string/intent_import_card_from_url_host_thelastproject"
<!-- Old card sharing URIs -->
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="@string/intent_import_card_from_url_host_thelastproject"
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_thelastproject" />
<data android:scheme="https"
android:host="@string/intent_import_card_from_url_host_brarcher"
<data android:host="@string/intent_import_card_from_url_host_brarcher"
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_brarcher" />
</intent-filter>
</activity>
@@ -92,7 +103,8 @@
<activity
android:name=".CardShortcutConfigure"
android:label="@string/cardShortcut"
android:theme="@style/AppTheme.NoActionBar">
android:theme="@style/AppTheme.NoActionBar"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
<category android:name="android.intent.category.DEFAULT"/>

View File

@@ -1,11 +1,13 @@
package protect.card_locker;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import java.io.BufferedReader;
@@ -17,12 +19,15 @@ import java.util.Calendar;
import java.util.List;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.text.HtmlCompat;
public class AboutActivity extends CatimaAppCompatActivity
public class AboutActivity extends CatimaAppCompatActivity implements View.OnClickListener
{
private static final String TAG = "Catima";
ConstraintLayout version_history, translate, license, repo, privacy, error, credits, rate;
@Override
protected void onCreate(Bundle savedInstanceState)
@@ -93,39 +98,82 @@ public class AboutActivity extends CatimaAppCompatActivity
Log.w(TAG, "Package name not found", e);
}
TextView copyright = findViewById(R.id.credits_sub);
copyright.setText(String.format(getString(R.string.app_copyright_fmt), year));
TextView vHistory = findViewById(R.id.version_history_sub);
vHistory.setText(String.format(getString(R.string.debug_version_fmt), version));
setTitle(String.format(getString(R.string.about_title_fmt), appName));
TextView aboutTextView = findViewById(R.id.aboutText);
aboutTextView.setText(HtmlCompat.fromHtml(String.format(getString(R.string.debug_version_fmt), version) +
"<br/><br/>" +
String.format(getString(R.string.app_revision_fmt),
"<a href=\"" + getString(R.string.app_revision_url) + "\">" +
"GitHub" +
"</a>") +
"<br/><br/>" +
String.format(getString(R.string.app_copyright_fmt), year) +
"<br/><br/>" +
getString(R.string.app_copyright_old) +
"<br/><br/>" +
getString(R.string.app_license) +
"<br/><br/>" +
String.format(getString(R.string.app_contributors), contributors.toString()) +
"<br/><br/>" +
String.format(getString(R.string.app_libraries), libs.toString()) +
"<br/><br/>" +
String.format(getString(R.string.app_resources), resources.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
aboutTextView.setMovementMethod(LinkMovementMethod.getInstance());
version_history = findViewById(R.id.version_history);
translate = findViewById(R.id.translate);
license = findViewById(R.id.license);
repo = findViewById(R.id.repo);
privacy = findViewById(R.id.privacy);
error = findViewById(R.id.report_error);
credits = findViewById(R.id.credits);
rate = findViewById(R.id.rate);
version_history.setOnClickListener(this);
translate.setOnClickListener(this);
license.setOnClickListener(this);
repo.setOnClickListener(this);
privacy.setOnClickListener(this);
error.setOnClickListener(this);
rate.setOnClickListener(this);
StringBuilder contributorInfo = new StringBuilder();
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_contributors), contributors.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
contributorInfo.append("\n\n");
contributorInfo.append(getString(R.string.app_copyright_old));
contributorInfo.append("\n\n");
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_libraries), libs.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
contributorInfo.append("\n\n");
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_resources), resources.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
credits.setOnClickListener(view -> new AlertDialog.Builder(this)
.setTitle(R.string.credits)
.setMessage(contributorInfo.toString())
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {})
.show());
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View view) {
int id = view.getId();
String url;
if (id == R.id.version_history) {
url = "https://catima.app/changelog/";
} else if (id == R.id.translate) {
url = "https://hosted.weblate.org/engage/catima/";
} else if (id == R.id.license) {
url = "https://github.com/TheLastProject/Catima/blob/master/LICENSE";
} else if (id == R.id.repo) {
url = "https://github.com/TheLastProject/Catima/";
} else if (id == R.id.privacy) {
url = "https://catima.app/privacy-policy/";
} else if (id == R.id.report_error) {
url = "https://github.com/TheLastProject/Catima/issues";
} else if (id == R.id.rate) {
url = "https://play.google.com/store/apps/details?id=me.hackerchick.catima";
} else {
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
}
}

View File

@@ -4,30 +4,29 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import java.lang.ref.WeakReference;
import protect.card_locker.async.CompatCallable;
/**
* This task will generate a barcode and load it into an ImageView.
* Only a weak reference of the ImageView is kept, so this class will not
* prevent the ImageView from being garbage collected.
*/
class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
{
public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
private static final String TAG = "Catima";
private static final int IS_VALID = 999;
private Context mContext;
private final Context mContext;
private boolean isSuccesful;
// When drawn in a smaller window 1D barcodes for some reason end up
@@ -44,10 +43,11 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
private final boolean showFallback;
private final Runnable callback;
BarcodeImageWriterTask(Context context, ImageView imageView, String cardIdString,
CatimaBarcode barcodeFormat, TextView textView,
boolean showFallback, Runnable callback)
{
BarcodeImageWriterTask(
Context context, ImageView imageView, String cardIdString,
CatimaBarcode barcodeFormat, TextView textView,
boolean showFallback, Runnable callback
) {
mContext = context;
isSuccesful = true;
@@ -62,26 +62,21 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
final int MAX_WIDTH = getMaxWidth(format);
if(imageView.getWidth() < MAX_WIDTH)
{
if (imageView.getWidth() < MAX_WIDTH) {
imageHeight = imageView.getHeight();
imageWidth = imageView.getWidth();
}
else
{
} else {
// Scale down the image to reduce the memory needed to produce it
imageWidth = MAX_WIDTH;
double ratio = (double)MAX_WIDTH / (double)imageView.getWidth();
imageHeight = (int)(imageView.getHeight() * ratio);
double ratio = (double) MAX_WIDTH / (double) imageView.getWidth();
imageHeight = (int) (imageView.getHeight() * ratio);
}
this.showFallback = showFallback;
}
private int getMaxWidth(CatimaBarcode format)
{
switch(format.format())
{
private int getMaxWidth(CatimaBarcode format) {
switch (format.format()) {
// 2D barcodes
case AZTEC:
case DATA_MATRIX:
@@ -108,10 +103,8 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
}
}
private String getFallbackString(CatimaBarcode format)
{
switch(format.format())
{
private String getFallbackString(CatimaBarcode format) {
switch (format.format()) {
// 2D barcodes
case AZTEC:
return "AZTEC";
@@ -144,23 +137,17 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
}
}
private Bitmap generate()
{
if (cardId.isEmpty())
{
private Bitmap generate() {
if (cardId.isEmpty()) {
return null;
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix bitMatrix;
try
{
try
{
try {
try {
bitMatrix = writer.encode(cardId, format.format(), imageWidth, imageHeight, null);
}
catch(Exception e)
{
} catch (Exception e) {
// Cast a wider net here and catch any exception, as there are some
// cases where an encoder may fail if the data is invalid for the
// barcode type. If this happens, we want to fail gracefully.
@@ -175,11 +162,9 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
int[] pixels = new int[bitMatrixWidth * bitMatrixHeight];
for (int y = 0; y < bitMatrixHeight; y++)
{
for (int y = 0; y < bitMatrixHeight; y++) {
int offset = y * bitMatrixWidth;
for (int x = 0; x < bitMatrixWidth; x++)
{
for (int x = 0; x < bitMatrixWidth; x++) {
int color = bitMatrix.get(x, y) ? BLACK : WHITE;
pixels[offset + x] = color;
}
@@ -199,19 +184,14 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
int widthScale = imageWidth / bitMatrixHeight;
int scalingFactor = Math.min(heightScale, widthScale);
if(scalingFactor > 1)
{
if (scalingFactor > 1) {
bitmap = Bitmap.createScaledBitmap(bitmap, bitMatrixWidth * scalingFactor, bitMatrixHeight * scalingFactor, false);
}
return bitmap;
}
catch (WriterException e)
{
} catch (WriterException e) {
Log.e(TAG, "Failed to generate barcode of type " + format + ": " + cardId, e);
}
catch(OutOfMemoryError e)
{
} catch (OutOfMemoryError e) {
Log.w(TAG, "Insufficient memory to render barcode, "
+ imageWidth + "x" + imageHeight + ", " + format.name()
+ ", length=" + cardId.length(), e);
@@ -220,29 +200,36 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
return null;
}
public Bitmap doInBackground(Void... params)
{
Bitmap bitmap = generate();
public Bitmap doInBackground(Void... params) {
// Only do the hard tasks if we've not already been cancelled
if (!Thread.currentThread().isInterrupted()) {
Bitmap bitmap = generate();
if (bitmap == null) {
isSuccesful = false;
if (bitmap == null) {
isSuccesful = false;
if (showFallback) {
Log.i(TAG, "Barcode generation failed, generating fallback...");
cardId = getFallbackString(format);
bitmap = generate();
if (showFallback && !Thread.currentThread().isInterrupted()) {
Log.i(TAG, "Barcode generation failed, generating fallback...");
cardId = getFallbackString(format);
bitmap = generate();
return bitmap;
}
} else {
return bitmap;
}
}
return bitmap;
// We've been interrupted - create a empty fallback
Bitmap.Config config = Bitmap.Config.ARGB_8888;
return Bitmap.createBitmap(imageWidth, imageHeight, config);
}
protected void onPostExecute(Bitmap result)
{
public void onPostExecute(Object castResult) {
Bitmap result = (Bitmap) castResult;
Log.i(TAG, "Finished generating barcode image of type " + format + ": " + cardId);
ImageView imageView = imageViewReference.get();
if(imageView == null)
{
if (imageView == null) {
// The ImageView no longer exists, nothing to do
return;
}
@@ -255,8 +242,7 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
imageView.setContentDescription(mContext.getString(R.string.barcodeImageDescriptionWithType, formatPrettyName));
TextView textView = textViewReference.get();
if(result != null)
{
if (result != null) {
Log.i(TAG, "Displaying barcode");
imageView.setVisibility(View.VISIBLE);
@@ -270,9 +256,7 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
textView.setVisibility(View.VISIBLE);
textView.setText(formatPrettyName);
}
}
else
{
} else {
Log.i(TAG, "Barcode generation failed, removing image from display");
imageView.setVisibility(View.GONE);
if (textView != null) {
@@ -284,4 +268,19 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
callback.run();
}
}
@Override
public void onPreExecute() {
// No Action
}
/**
* Provided to comply with Callable while keeping the original Syntax of AsyncTask
*
* @return generated Bitmap
*/
@Override
public Bitmap call() {
return doInBackground();
}
}

View File

@@ -2,8 +2,9 @@ package protect.card_locker;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.Pair;
import android.view.MenuItem;
@@ -16,24 +17,21 @@ import android.widget.Toast;
import com.google.zxing.BarcodeFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
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
* barcode data and generate all barcodes possible for
* 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 {
private static final String TAG = "Catima";
// Result this activity will return
@@ -41,19 +39,21 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity
public static final String BARCODE_FORMAT = "format";
private Map<String, Pair<Integer, Integer>> barcodeViewMap;
private LinkedList<AsyncTask> barcodeGeneratorTasks = new LinkedList<>();
final private TaskHandler mTasks = new TaskHandler();
private final Handler typingDelayHandler = new Handler(Looper.getMainLooper());
public static final Integer INPUT_DELAY = 250;
@Override
protected void onCreate(Bundle savedInstanceState)
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.selectBarcodeTitle);
setContentView(R.layout.barcode_selector_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
@@ -72,26 +72,31 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity
barcodeViewMap.put(BarcodeFormat.UPC_E.name(), new Pair<>(R.id.upceBarcode, R.id.upceBarcodeText));
EditText cardId = findViewById(R.id.cardId);
cardId.addTextChangedListener(new SimpleTextWatcher()
{
cardId.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
Log.d(TAG, "Entered text: " + s);
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Delay the input processing so we avoid overload
typingDelayHandler.removeCallbacksAndMessages(null);
generateBarcodes(s.toString());
typingDelayHandler.postDelayed(() -> {
Log.d(TAG, "Entered text: " + s);
View noBarcodeButtonView = findViewById(R.id.noBarcode);
setButtonListener(noBarcodeButtonView, s.toString());
noBarcodeButtonView.setEnabled(s.length() > 0);
runOnUiThread(() -> {
generateBarcodes(s.toString());
View noBarcodeButtonView = findViewById(R.id.noBarcode);
setButtonListener(noBarcodeButtonView, s.toString());
noBarcodeButtonView.setEnabled(s.length() > 0);
});
}, INPUT_DELAY);
}
});
final Bundle b = getIntent().getExtras();
final String initialCardId = b != null ? b.getString("initialCardId") : null;
if(initialCardId != null)
{
if (initialCardId != null) {
cardId.setText(initialCardId);
} else {
generateBarcodes("");
@@ -99,24 +104,19 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity
}
private void generateBarcodes(String value) {
// Stop any async tasks which may not have been started yet
for(AsyncTask task : barcodeGeneratorTasks)
{
task.cancel(false);
}
barcodeGeneratorTasks.clear();
// 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())
{
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);
}
}
private void setButtonListener(final View button, final String cardId)
{
private void setButtonListener(final View button, final String cardId) {
button.setOnClickListener(view -> {
Log.d(TAG, "Selected no barcode");
Intent result = new Intent();
@@ -127,8 +127,7 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity
});
}
private void createBarcodeOption(final ImageView image, final String formatType, final String cardId, final TextView text)
{
private void createBarcodeOption(final ImageView image, final String formatType, final String cardId, final TextView text) {
final CatimaBarcode format = CatimaBarcode.fromName(formatType);
image.setImageBitmap(null);
@@ -147,40 +146,32 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity
finish();
});
if(image.getHeight() == 0)
{
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);
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Log.d(TAG, "Global layout finished, type: + " + formatType + ", width: " + image.getWidth());
image.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Log.d(TAG, "Generating barcode for type " + formatType);
BarcodeImageWriterTask task = new BarcodeImageWriterTask(getApplicationContext(), image, cardId, format, text, true, null);
barcodeGeneratorTasks.add(task);
task.execute();
}
});
}
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);
}
});
} else {
Log.d(TAG, "Generating barcode for type " + formatType);
BarcodeImageWriterTask task = new BarcodeImageWriterTask(getApplicationContext(), image, cardId, format, text, true, null);
barcodeGeneratorTasks.add(task);
task.execute();
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)
{
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
setResult(Activity.RESULT_CANCELED);
finish();
return true;

View File

@@ -76,10 +76,6 @@ public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyC
finish();
}
@Override
public void onIconClicked(int inputPosition) {
onClickAction(inputPosition);
}
@Override
public void onRowClicked(int inputPosition) {

View File

@@ -63,6 +63,13 @@ public class CatimaBarcode {
return barcodeFormats.contains(mBarcodeFormat);
}
public boolean isSquare(){
return mBarcodeFormat == BarcodeFormat.AZTEC
|| mBarcodeFormat == BarcodeFormat.DATA_MATRIX
|| mBarcodeFormat == BarcodeFormat.MAXICODE
|| mBarcodeFormat == BarcodeFormat.QR_CODE;
}
public BarcodeFormat format() {
return mBarcodeFormat;
}
@@ -72,6 +79,12 @@ public class CatimaBarcode {
}
public String prettyName() {
return barcodePrettyNames.get(barcodeFormats.indexOf(mBarcodeFormat));
int index = barcodeFormats.indexOf(mBarcodeFormat);
if (index == -1 || index >= barcodePrettyNames.size()) {
return mBarcodeFormat.name();
}
return barcodePrettyNames.get(index);
}
}

View File

@@ -7,6 +7,8 @@ import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;
import android.util.Log;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
@@ -20,7 +22,7 @@ public class DBHelper extends SQLiteOpenHelper
{
public static final String DATABASE_NAME = "Catima.db";
public static final int ORIGINAL_DATABASE_VERSION = 1;
public static final int DATABASE_VERSION = 11;
public static final int DATABASE_VERSION = 14;
public static class LoyaltyCardDbGroups
{
@@ -45,6 +47,7 @@ public class DBHelper extends SQLiteOpenHelper
public static final String BARCODE_TYPE = "barcodetype";
public static final String STAR_STATUS = "starstatus";
public static final String LAST_USED = "lastused";
public static final String ZOOM_LEVEL = "zoomlevel";
}
public static class LoyaltyCardDbIdsGroups
@@ -54,6 +57,14 @@ public class DBHelper extends SQLiteOpenHelper
public static final String groupID = "groupId";
}
public static class LoyaltyCardDbFTS
{
public static final String TABLE = "fts";
public static final String ID = "rowid"; // This should NEVER be changed
public static final String STORE = "store";
public static final String NOTE = "note";
}
public enum LoyaltyCardOrder {
Alpha,
LastUsed,
@@ -78,13 +89,13 @@ public class DBHelper extends SQLiteOpenHelper
public void onCreate(SQLiteDatabase db)
{
// create table for card groups
db.execSQL("create table " + LoyaltyCardDbGroups.TABLE + "(" +
db.execSQL("CREATE TABLE " + LoyaltyCardDbGroups.TABLE + "(" +
LoyaltyCardDbGroups.ID + " TEXT primary key not null," +
LoyaltyCardDbGroups.ORDER + " INTEGER DEFAULT '0')");
// create table for cards
// Balance is TEXT and not REAL to be able to store a BigDecimal without precision loss
db.execSQL("create table " + LoyaltyCardDbIds.TABLE + "(" +
db.execSQL("CREATE TABLE " + LoyaltyCardDbIds.TABLE + "(" +
LoyaltyCardDbIds.ID + " INTEGER primary key autoincrement," +
LoyaltyCardDbIds.STORE + " TEXT not null," +
LoyaltyCardDbIds.NOTE + " TEXT not null," +
@@ -96,26 +107,31 @@ public class DBHelper extends SQLiteOpenHelper
LoyaltyCardDbIds.BARCODE_ID + " TEXT," +
LoyaltyCardDbIds.BARCODE_TYPE + " TEXT," +
LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0'," +
LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0')");
LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0', "+
LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '100' )");
// create associative table for cards in groups
db.execSQL("create table " + LoyaltyCardDbIdsGroups.TABLE + "(" +
db.execSQL("CREATE TABLE " + LoyaltyCardDbIdsGroups.TABLE + "(" +
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
LoyaltyCardDbIdsGroups.groupID + " TEXT," +
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID +"))");
// create FTS search table
db.execSQL("CREATE VIRTUAL TABLE " + LoyaltyCardDbFTS.TABLE + " USING fts4(" +
LoyaltyCardDbFTS.STORE + ", " + LoyaltyCardDbFTS.NOTE + ", " +
"tokenize=unicode61);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// Upgrade from version 1 to version 2
if(oldVersion < 2 && newVersion >= 2)
{
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.NOTE + " TEXT not null default ''");
}
// Upgrade from version 2 to version 3
if(oldVersion < 3 && newVersion >= 3)
{
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
@@ -124,26 +140,23 @@ public class DBHelper extends SQLiteOpenHelper
+ " ADD COLUMN " + LoyaltyCardDbIds.HEADER_TEXT_COLOR + " INTEGER");
}
// Upgrade from version 3 to version 4
if(oldVersion < 4 && newVersion >= 4)
{
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0'");
}
// Upgrade from version 4 to version 5
if(oldVersion < 5 && newVersion >= 5)
{
db.execSQL("create table " + LoyaltyCardDbGroups.TABLE + "(" +
db.execSQL("CREATE TABLE " + LoyaltyCardDbGroups.TABLE + "(" +
LoyaltyCardDbGroups.ID + " TEXT primary key not null)");
db.execSQL("create table " + LoyaltyCardDbIdsGroups.TABLE + "(" +
db.execSQL("CREATE TABLE " + LoyaltyCardDbIdsGroups.TABLE + "(" +
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
LoyaltyCardDbIdsGroups.groupID + " TEXT," +
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID +"))");
}
// Upgrade from version 5 to 6
if(oldVersion < 6 && newVersion >= 6)
{
db.execSQL("ALTER TABLE " + LoyaltyCardDbGroups.TABLE
@@ -219,7 +232,7 @@ public class DBHelper extends SQLiteOpenHelper
db.execSQL("DROP TABLE " + LoyaltyCardDbIds.TABLE);
db.execSQL("create table " + LoyaltyCardDbIds.TABLE + "(" +
db.execSQL("CREATE TABLE " + LoyaltyCardDbIds.TABLE + "(" +
LoyaltyCardDbIds.ID + " INTEGER primary key autoincrement," +
LoyaltyCardDbIds.STORE + " TEXT not null," +
LoyaltyCardDbIds.NOTE + " TEXT not null," +
@@ -269,6 +282,92 @@ public class DBHelper extends SQLiteOpenHelper
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0'");
}
if(oldVersion < 12 && newVersion >= 12)
{
db.execSQL("CREATE VIRTUAL TABLE " + LoyaltyCardDbFTS.TABLE + " USING fts4(" +
LoyaltyCardDbFTS.STORE + ", " + LoyaltyCardDbFTS.NOTE + ", " +
"tokenize=unicode61);");
Cursor cursor = db.rawQuery("SELECT * FROM " + LoyaltyCardDbIds.TABLE + ";", null, null);
cursor.moveToFirst();
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID));
String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE));
String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE));
insertFTS(db, id, store, note);
}
}
if(oldVersion < 13 && newVersion >= 13)
{
db.execSQL("DELETE FROM " + LoyaltyCardDbFTS.TABLE + ";");
Cursor cursor = db.rawQuery("SELECT * FROM " + LoyaltyCardDbIds.TABLE + ";", null, null);
if (cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID));
String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE));
String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE));
insertFTS(db, id, store, note);
while (cursor.moveToNext()) {
id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID));
store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE));
note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE));
insertFTS(db, id, store, note);
}
}
cursor.close();
}
if(oldVersion < 14 && newVersion >= 14){
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '100' ");
}
}
private ContentValues generateFTSContentValues(final int id, final String store, final String note) {
// FTS on Android is severely limited and can only search for word starting with a certain string
// So for each word, we grab every single substring
// This makes it possible to find Décathlon by searching both de and cat, for example
ContentValues ftsContentValues = new ContentValues();
StringBuilder storeString = new StringBuilder();
for (String word : store.split(" ")) {
for (int i = 0; i < word.length(); i++) {
storeString.append(word);
storeString.append(" ");
word = word.substring(1);
}
}
StringBuilder noteString = new StringBuilder();
for (String word : note.split(" ")) {
for (int i = 0; i < word.length(); i++) {
noteString.append(word);
noteString.append(" ");
word = word.substring(1);
}
}
ftsContentValues.put(LoyaltyCardDbFTS.ID, id);
ftsContentValues.put(LoyaltyCardDbFTS.STORE, storeString.toString());
ftsContentValues.put(LoyaltyCardDbFTS.NOTE, noteString.toString());
return ftsContentValues;
}
private void insertFTS(final SQLiteDatabase db, final int id, final String store, final String note) {
db.insert(LoyaltyCardDbFTS.TABLE, null, generateFTSContentValues(id, store, note));
}
private void updateFTS(final SQLiteDatabase db, final int id, final String store, final String note) {
db.update(LoyaltyCardDbFTS.TABLE, generateFTSContentValues(id, store, note),
whereAttrs(LoyaltyCardDbFTS.ID), withArgs(id));
}
public long insertLoyaltyCard(final String store, final String note, final Date expiry,
@@ -278,6 +377,9 @@ public class DBHelper extends SQLiteOpenHelper
final int starStatus, final Long lastUsed)
{
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
// Card
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.STORE, store);
contentValues.put(LoyaltyCardDbIds.NOTE, note);
@@ -290,7 +392,15 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
return db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
long id = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
// FTS
insertFTS(db, (int) id, store, note);
db.setTransactionSuccessful();
db.endTransaction();
return id;
}
public long insertLoyaltyCard(final SQLiteDatabase db, final String store,
@@ -300,6 +410,9 @@ public class DBHelper extends SQLiteOpenHelper
final Integer headerColor, final int starStatus,
final Long lastUsed)
{
db.beginTransaction();
// Card
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.STORE, store);
contentValues.put(LoyaltyCardDbIds.NOTE, note);
@@ -312,7 +425,15 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
return db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
long id = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
// FTS
insertFTS(db, (int) id, store, note);
db.setTransactionSuccessful();
db.endTransaction();
return id;
}
public long insertLoyaltyCard(final SQLiteDatabase db, final int id, final String store,
@@ -322,6 +443,9 @@ public class DBHelper extends SQLiteOpenHelper
final Integer headerColor, final int starStatus,
final Long lastUsed)
{
db.beginTransaction();
// Card
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.ID, id);
contentValues.put(LoyaltyCardDbIds.STORE, store);
@@ -335,7 +459,15 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
return db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
// FTS
insertFTS(db, id, store, note);
db.setTransactionSuccessful();
db.endTransaction();
return id;
}
public boolean updateLoyaltyCard(final int id, final String store, final String note,
@@ -345,6 +477,9 @@ public class DBHelper extends SQLiteOpenHelper
final Integer headerColor)
{
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
// Card
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.STORE, store);
contentValues.put(LoyaltyCardDbIds.NOTE, note);
@@ -357,6 +492,13 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE, contentValues,
whereAttrs(LoyaltyCardDbIds.ID), withArgs(id));
// FTS
updateFTS(db, id, store, note);
db.setTransactionSuccessful();
db.endTransaction();
return (rowsUpdated == 1);
}
@@ -381,6 +523,18 @@ public class DBHelper extends SQLiteOpenHelper
return (rowsUpdated == 1);
}
public boolean updateLoyaltyCardZoomLevel(int loyaltyCardId, int zoomLevel){
SQLiteDatabase db = getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.ZOOM_LEVEL,zoomLevel);
Log.d("updateLoyaltyCardZLevel","Card Id = "+loyaltyCardId+" Zoom level= "+zoomLevel);
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE,contentValues,
whereAttrs(LoyaltyCardDbIds.ID),
withArgs(loyaltyCardId));
Log.d("updateLoyaltyCardZLevel","Rows changed = "+rowsUpdated);
return (rowsUpdated == 1);
}
public LoyaltyCard getLoyaltyCard(final int id)
{
SQLiteDatabase db = getReadableDatabase();
@@ -472,6 +626,11 @@ public class DBHelper extends SQLiteOpenHelper
whereAttrs(LoyaltyCardDbIdsGroups.cardID),
withArgs(id));
// Delete FTS table entries
db.delete(LoyaltyCardDbFTS.TABLE,
whereAttrs(LoyaltyCardDbFTS.ID),
withArgs(id));
// Also wipe card images associated with this card
try {
Utils.saveCardImage(mContext, null, id, true);
@@ -520,9 +679,7 @@ public class DBHelper extends SQLiteOpenHelper
* @param order
* @return Cursor
*/
public Cursor getLoyaltyCardCursor(final String filter, Group group, LoyaltyCardOrder order, LoyaltyCardOrderDirection direction) {
String actualFilter = String.format("%%%s%%", filter);
String[] selectionArgs = { actualFilter, actualFilter };
public Cursor getLoyaltyCardCursor(String filter, Group group, LoyaltyCardOrder order, LoyaltyCardOrderDirection direction) {
StringBuilder groupFilter = new StringBuilder();
String limitString = "";
@@ -536,7 +693,7 @@ public class DBHelper extends SQLiteOpenHelper
groupFilter.append("AND (");
for (int i = 0; i < allowedIds.size(); i++) {
groupFilter.append(LoyaltyCardDbIds.ID + " = ").append(allowedIds.get(i));
groupFilter.append(LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ID + " = ").append(allowedIds.get(i));
if (i != allowedIds.size() - 1) {
groupFilter.append(" OR ");
}
@@ -549,39 +706,29 @@ public class DBHelper extends SQLiteOpenHelper
String orderField = getFieldForOrder(order);
return db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
" WHERE (" + LoyaltyCardDbIds.STORE + " LIKE ? " +
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? )" +
return db.rawQuery("SELECT " + LoyaltyCardDbIds.TABLE + ".* FROM " + LoyaltyCardDbIds.TABLE +
" JOIN " + LoyaltyCardDbFTS.TABLE +
" ON " + LoyaltyCardDbFTS.TABLE + "." + LoyaltyCardDbFTS.ID + " = " + LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ID +
(filter.trim().isEmpty() ? " " : " AND " + LoyaltyCardDbFTS.TABLE + " MATCH ? ") +
groupFilter.toString() +
" ORDER BY " + LoyaltyCardDbIds.STAR_STATUS + " DESC, " +
" (CASE WHEN " + orderField + " IS NULL THEN 1 ELSE 0 END), " +
orderField + " COLLATE NOCASE " + getDbDirection(order, direction) + ", " +
LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC " +
limitString, selectionArgs, null);
" ORDER BY " + LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.STAR_STATUS + " DESC, " +
" (CASE WHEN " + LoyaltyCardDbIds.TABLE + "." + orderField + " IS NULL THEN 1 ELSE 0 END), " +
LoyaltyCardDbIds.TABLE + "." + orderField + " COLLATE NOCASE " + getDbDirection(order, direction) + ", " +
LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC " +
limitString, filter.trim().isEmpty() ? null : new String[] { TextUtils.join("* ", filter.split(" ")) + '*' }, null);
}
/**
* Returns the amount of loyalty cards.
*
* @return Integer
*/
public int getLoyaltyCardCount()
{
SQLiteDatabase db = getReadableDatabase();
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbIds.TABLE);
}
/**
* Returns the amount of loyalty cards with the filter text in either the store or note.
*
* @param filter
* @return Integer
*/
public int getLoyaltyCardCount(String filter)
{
String actualFilter = String.format("%%%s%%", filter);
SQLiteDatabase db = getReadableDatabase();
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbIds.TABLE,
LoyaltyCardDbIds.STORE + " LIKE ? " +
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? ", withArgs(actualFilter, actualFilter));
}
/**
* Returns a cursor to all groups.
*
@@ -596,20 +743,22 @@ public class DBHelper extends SQLiteOpenHelper
}
public List<Group> getGroups() {
try(Cursor data = getGroupCursor()) {
List<Group> groups = new ArrayList<>();
Cursor data = getGroupCursor();
if (!data.moveToFirst()) {
return groups;
}
groups.add(Group.toGroup(data));
while (data.moveToNext()) {
groups.add(Group.toGroup(data));
}
List<Group> groups = new ArrayList<>();
if (!data.moveToFirst()) {
data.close();
return groups;
}
groups.add(Group.toGroup(data));
while (data.moveToNext()) {
groups.add(Group.toGroup(data));
}
data.close();
return groups;
}
public void reorderGroups(final List<Group> groups)

View File

@@ -42,7 +42,7 @@ class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListI
public GroupCursorAdapter.GroupListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType)
{
View itemView = LayoutInflater.from(inputParent.getContext()).inflate(R.layout.group_layout, inputParent, false);
return new GroupCursorAdapter.GroupListItemViewHolder(itemView);
return new GroupListItemViewHolder(itemView);
}
public Cursor getCursor()
@@ -80,7 +80,7 @@ class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListI
void onDeleteButtonClicked(View view);
}
public class GroupListItemViewHolder extends RecyclerView.ViewHolder
public static class GroupListItemViewHolder extends RecyclerView.ViewHolder
{
public TextView mName, mCardCount;
public AppCompatImageButton mMoveUp, mMoveDown, mEdit, mDelete;

View File

@@ -6,20 +6,21 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -30,11 +31,12 @@ 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;
public class ImportExportActivity extends CatimaAppCompatActivity
{
public class ImportExportActivity extends CatimaAppCompatActivity {
private static final String TAG = "Catima";
private static final int PERMISSIONS_EXTERNAL_STORAGE = 1;
@@ -46,18 +48,19 @@ public class ImportExportActivity extends CatimaAppCompatActivity
private String importAlertTitle;
private String importAlertMessage;
private DataFormat importDataFormat;
private String exportPassword;
final private TaskHandler mTasks = new TaskHandler();
@Override
protected void onCreate(Bundle savedInstanceState)
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.importExport);
setContentView(R.layout.import_export_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
@@ -66,12 +69,11 @@ public class ImportExportActivity extends CatimaAppCompatActivity
if (ContextCompat.checkSelfPermission(ImportExportActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(ImportExportActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
{
ContextCompat.checkSelfPermission(ImportExportActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(ImportExportActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSIONS_EXTERNAL_STORAGE);
}
@@ -82,12 +84,31 @@ public class ImportExportActivity extends CatimaAppCompatActivity
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "catima.zip");
Button exportButton = findViewById(R.id.exportButton);
exportButton.setOnClickListener(new View.OnClickListener()
{
exportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
chooseFileWithIntent(intentCreateDocumentAction, CHOOSE_EXPORT_LOCATION);
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
builder.setTitle(R.string.exportPassword);
FrameLayout container = new FrameLayout(ImportExportActivity.this);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = 50;
params.rightMargin = 50;
final EditText input = new EditText(ImportExportActivity.this);
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
input.setLayoutParams(params);
input.setHint(R.string.exportPasswordHint);
container.addView(input);
builder.setView(container);
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
exportPassword = input.getText().toString();
chooseFileWithIntent(intentCreateDocumentAction, CHOOSE_EXPORT_LOCATION);
});
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
builder.show();
}
});
@@ -97,11 +118,9 @@ public class ImportExportActivity extends CatimaAppCompatActivity
intentGetContentAction.setType("*/*");
Button importFilesystem = findViewById(R.id.importOptionFilesystemButton);
importFilesystem.setOnClickListener(new View.OnClickListener()
{
importFilesystem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
public void onClick(View v) {
chooseImportType(intentGetContentAction);
}
});
@@ -110,11 +129,9 @@ public class ImportExportActivity extends CatimaAppCompatActivity
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
Button importApplication = findViewById(R.id.importOptionApplicationButton);
importApplication.setOnClickListener(new View.OnClickListener()
{
importApplication.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
public void onClick(View v) {
chooseImportType(intentPickAction);
}
});
@@ -176,47 +193,57 @@ public class ImportExportActivity extends CatimaAppCompatActivity
.setTitle(importAlertTitle)
.setMessage(importAlertMessage)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
chooseFileWithIntent(baseIntent, IMPORT);
}
})
@Override
public void onClick(DialogInterface dialog, int which) {
chooseFileWithIntent(baseIntent, IMPORT);
}
})
.setNegativeButton(R.string.cancel, null)
.show();
});
builder.show();
}
private void startImport(final InputStream target, final Uri targetUri, final DataFormat dataFormat, final char[] password)
{
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener()
{
private void startImport(final InputStream target, final Uri targetUri, final DataFormat dataFormat, final char[] password, final boolean closeWhenDone) {
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, true, false, false);
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener() {
@Override
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat)
{
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat) {
onImportComplete(result, targetUri, dataFormat);
if (closeWhenDone) {
try {
target.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
};
importExporter = new ImportExportTask(ImportExportActivity.this,
dataFormat, target, password, listener);
importExporter.execute();
mTasks.executeTask(TaskHandler.TYPE.IMPORT, importExporter);
}
private void startExport(final OutputStream target, final Uri targetUri)
{
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener()
{
private void startExport(final OutputStream target, final Uri targetUri, char[] password, final boolean closeWhenDone) {
mTasks.flushTaskList(TaskHandler.TYPE.EXPORT, true, false, false);
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener() {
@Override
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat)
{
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat) {
onExportComplete(result, targetUri);
if (closeWhenDone) {
try {
target.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
};
importExporter = new ImportExportTask(ImportExportActivity.this,
DataFormat.Catima, target, listener);
importExporter.execute();
DataFormat.Catima, target, password, listener);
mTasks.executeTask(TaskHandler.TYPE.EXPORT, importExporter);
}
@Override
@@ -244,22 +271,17 @@ public class ImportExportActivity extends CatimaAppCompatActivity
}
@Override
protected void onDestroy()
{
if(importExporter != null && importExporter.getStatus() != AsyncTask.Status.RUNNING)
{
importExporter.cancel(true);
}
protected void onDestroy() {
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, true, false, false);
mTasks.flushTaskList(TaskHandler.TYPE.EXPORT, true, false, false);
super.onDestroy();
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home)
{
if (id == android.R.id.home) {
finish();
return true;
}
@@ -293,13 +315,10 @@ public class ImportExportActivity extends CatimaAppCompatActivity
int messageId;
if (result == ImportExportResult.Success)
{
if (result == ImportExportResult.Success) {
builder.setTitle(R.string.importSuccessfulTitle);
messageId = R.string.importSuccessful;
}
else
{
} else {
builder.setTitle(R.string.importFailedTitle);
messageId = R.string.importFailed;
}
@@ -307,11 +326,9 @@ public class ImportExportActivity extends CatimaAppCompatActivity
final String message = getResources().getString(messageId);
builder.setMessage(message);
builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener()
{
builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which)
{
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
@@ -319,19 +336,15 @@ public class ImportExportActivity extends CatimaAppCompatActivity
builder.create().show();
}
private void onExportComplete(ImportExportResult result, final Uri path)
{
private void onExportComplete(ImportExportResult result, final Uri path) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
int messageId;
if(result == ImportExportResult.Success)
{
if (result == ImportExportResult.Success) {
builder.setTitle(R.string.exportSuccessfulTitle);
messageId = R.string.exportSuccessful;
}
else
{
} else {
builder.setTitle(R.string.exportFailedTitle);
messageId = R.string.exportFailed;
}
@@ -341,8 +354,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity
builder.setMessage(message);
builder.setNeutralButton(R.string.ok, (dialog, which) -> dialog.dismiss());
if(result == ImportExportResult.Success)
{
if (result == ImportExportResult.Success) {
final CharSequence sendLabel = ImportExportActivity.this.getResources().getText(R.string.sendLabel);
builder.setPositiveButton(sendLabel, (dialog, which) -> {
@@ -363,87 +375,64 @@ public class ImportExportActivity extends CatimaAppCompatActivity
builder.create().show();
}
private void chooseFileWithIntent(Intent intent, int requestCode)
{
try
{
private void chooseFileWithIntent(Intent intent, int requestCode) {
try {
startActivityForResult(intent, requestCode);
}
catch (ActivityNotFoundException e)
{
} 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)
{
if (resultCode != RESULT_OK) {
Log.w(TAG, "Failed onActivityResult(), result=" + resultCode);
return;
}
if(uri == null)
{
if (uri == null) {
Log.e(TAG, "Activity returned a NULL URI");
return;
}
try
{
if (requestCode == CHOOSE_EXPORT_LOCATION)
{
try {
if (requestCode == CHOOSE_EXPORT_LOCATION) {
OutputStream writer;
if (uri.getScheme() != null)
{
if (uri.getScheme() != null) {
writer = getContentResolver().openOutputStream(uri);
}
else
{
} else {
writer = new FileOutputStream(new File(uri.toString()));
}
Log.e(TAG, "Starting file export with: " + uri.toString());
startExport(writer, uri);
}
else
{
startExport(writer, uri, exportPassword.toCharArray(), true);
} else {
InputStream reader;
if(uri.getScheme() != null)
{
if (uri.getScheme() != null) {
reader = getContentResolver().openInputStream(uri);
}
else
{
} else {
reader = new FileInputStream(new File(uri.toString()));
}
Log.e(TAG, "Starting file import with: " + uri.toString());
startImport(reader, uri, importDataFormat, password);
startImport(reader, uri, importDataFormat, password, true);
}
}
catch(FileNotFoundException e)
{
} catch (IOException e) {
Log.e(TAG, "Failed to import/export file: " + uri.toString(), e);
if (requestCode == CHOOSE_EXPORT_LOCATION)
{
if (requestCode == CHOOSE_EXPORT_LOCATION) {
onExportComplete(ImportExportResult.GenericFailure, uri);
}
else
{
} else {
onImportComplete(ImportExportResult.GenericFailure, uri, importDataFormat);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(data == null)
{
if (data == null) {
Log.e(TAG, "Activity returned NULL data");
return;
}

View File

@@ -4,7 +4,6 @@ import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.util.Log;
import java.io.IOException;
@@ -13,13 +12,13 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import protect.card_locker.async.CompatCallable;
import protect.card_locker.importexport.DataFormat;
import protect.card_locker.importexport.ImportExportResult;
import protect.card_locker.importexport.MultiFormatExporter;
import protect.card_locker.importexport.MultiFormatImporter;
class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
{
public class ImportExportTask implements CompatCallable<ImportExportResult> {
private static final String TAG = "Catima";
private Activity activity;
@@ -35,14 +34,14 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
/**
* Constructor which will setup a task for exporting to the given file
*/
ImportExportTask(Activity activity, DataFormat format, OutputStream output,
TaskCompleteListener listener)
{
ImportExportTask(Activity activity, DataFormat format, OutputStream output, char[] password,
TaskCompleteListener listener) {
super();
this.activity = activity;
this.doImport = false;
this.format = format;
this.outputStream = output;
this.password = password;
this.listener = listener;
}
@@ -50,8 +49,7 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
* Constructor which will setup a task for importing from the given InputStream.
*/
ImportExportTask(Activity activity, DataFormat format, InputStream input, char[] password,
TaskCompleteListener listener)
{
TaskCompleteListener listener) {
super();
this.activity = activity;
this.doImport = true;
@@ -61,8 +59,7 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
this.listener = listener;
}
private ImportExportResult performImport(Context context, InputStream stream, DBHelper db, char[] password)
{
private ImportExportResult performImport(Context context, InputStream stream, DBHelper db, char[] password) {
ImportExportResult importResult = MultiFormatImporter.importData(context, db, stream, format, password);
Log.i(TAG, "Import result: " + importResult.name());
@@ -70,18 +67,14 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
return importResult;
}
private ImportExportResult performExport(Context context, OutputStream stream, DBHelper db)
{
private ImportExportResult performExport(Context context, OutputStream stream, DBHelper db, char[] password) {
ImportExportResult result = ImportExportResult.GenericFailure;
try
{
try {
OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
result = MultiFormatExporter.exportData(context, db, stream, format);
result = MultiFormatExporter.exportData(context, db, stream, format, password);
writer.close();
}
catch (IOException e)
{
} catch (IOException e) {
Log.e(TAG, "Unable to export file", e);
}
@@ -90,55 +83,55 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
return result;
}
protected void onPreExecute()
{
public void onPreExecute() {
progress = new ProgressDialog(activity);
progress.setTitle(doImport ? R.string.importing : R.string.exporting);
progress.setOnDismissListener(new DialogInterface.OnDismissListener()
{
progress.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog)
{
ImportExportTask.this.cancel(true);
public void onDismiss(DialogInterface dialog) {
ImportExportTask.this.stop();
}
});
progress.show();
}
protected ImportExportResult doInBackground(Void... nothing)
{
protected ImportExportResult doInBackground(Void... nothing) {
final DBHelper db = new DBHelper(activity);
ImportExportResult result;
if(doImport)
{
if (doImport) {
result = performImport(activity.getApplicationContext(), inputStream, db, password);
}
else
{
result = performExport(activity.getApplicationContext(), outputStream, db);
} else {
result = performExport(activity.getApplicationContext(), outputStream, db, password);
}
return result;
}
protected void onPostExecute(ImportExportResult result)
{
listener.onTaskComplete(result, format);
public void onPostExecute(Object castResult) {
listener.onTaskComplete((ImportExportResult) castResult, format);
progress.dismiss();
Log.i(TAG, (doImport ? "Import" : "Export") + " Complete");
}
protected void onCancelled()
{
protected void onCancelled() {
progress.dismiss();
Log.i(TAG, (doImport ? "Import" : "Export") + " Cancelled");
}
interface TaskCompleteListener
{
protected void stop() {
// Whelp
}
@Override
public ImportExportResult call() {
return doInBackground();
}
interface TaskCompleteListener {
void onTaskComplete(ImportExportResult result, DataFormat format);
}

View File

@@ -122,7 +122,7 @@ public class ImportURIHelper {
headerColor = Integer.parseInt(unparsedHeaderColor);
}
return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime());
return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(),100);
} catch (NullPointerException | NumberFormatException | UnsupportedEncodingException ex) {
throw new InvalidObjectException("Not a valid import URI");
}

View File

@@ -30,11 +30,12 @@ public class LoyaltyCard implements Parcelable {
public final int starStatus;
public final long lastUsed;
public int zoomLevel;
public LoyaltyCard(final int id, final String store, final String note, final Date expiry,
final BigDecimal balance, final Currency balanceType, final String cardId,
@Nullable final String barcodeId, @Nullable final CatimaBarcode barcodeType,
@Nullable final Integer headerColor, final int starStatus, final long lastUsed)
@Nullable final Integer headerColor, final int starStatus, final long lastUsed,final int zoomLevel)
{
this.id = id;
this.store = store;
@@ -48,6 +49,7 @@ public class LoyaltyCard implements Parcelable {
this.headerColor = headerColor;
this.starStatus = starStatus;
this.lastUsed = lastUsed;
this.zoomLevel = zoomLevel;
}
protected LoyaltyCard(Parcel in) {
@@ -66,6 +68,7 @@ public class LoyaltyCard implements Parcelable {
headerColor = tmpHeaderColor != -1 ? tmpHeaderColor : null;
starStatus = in.readInt();
lastUsed = in.readLong();
zoomLevel = in.readInt();
}
@Override
@@ -82,6 +85,7 @@ public class LoyaltyCard implements Parcelable {
parcel.writeInt(headerColor != null ? headerColor : -1);
parcel.writeInt(starStatus);
parcel.writeLong(lastUsed);
parcel.writeInt(zoomLevel);
}
public static LoyaltyCard toLoyaltyCard(Cursor cursor)
@@ -95,6 +99,7 @@ public class LoyaltyCard implements Parcelable {
String barcodeId = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID));
int starred = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS));
long lastUsed = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.LAST_USED));
int zoomLevel = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ZOOM_LEVEL));
int barcodeTypeColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE);
int balanceTypeColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE);
@@ -125,7 +130,7 @@ public class LoyaltyCard implements Parcelable {
headerColor = cursor.getInt(headerColorColumn);
}
return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed);
return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed,zoomLevel);
}
@Override

View File

@@ -1,11 +1,12 @@
package protect.card_locker;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.SparseBooleanArray;
import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.View;
@@ -21,12 +22,13 @@ import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.ArrayList;
import androidx.cardview.widget.CardView;
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>
{
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder> {
private int mCurrentSelectedIndex = -1;
private Cursor mCursor;
Settings mSettings;
@@ -37,8 +39,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
private SparseBooleanArray mAnimationItemsIndex;
private boolean mReverseAllAnimations = false;
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener)
{
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener) {
super(inputCursor);
setHasStableIds(true);
mSettings = new Settings(inputContext);
@@ -59,14 +60,12 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
}
@Override
public LoyaltyCardListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType)
{
public LoyaltyCardListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType) {
View itemView = LayoutInflater.from(inputParent.getContext()).inflate(R.layout.loyalty_card_layout, inputParent, false);
return new LoyaltyCardListItemViewHolder(itemView);
return new LoyaltyCardListItemViewHolder(itemView, mListener);
}
public Cursor getCursor()
{
public Cursor getCursor() {
return mCursor;
}
@@ -74,8 +73,10 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
// Invisible until we want to show something more
inputHolder.mDivider.setVisibility(View.GONE);
int size = mSettings.getFontSizeMax(mSettings.getSmallFont());
if (mDarkModeEnabled) {
inputHolder.mStarIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
inputHolder.mStarIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
}
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(inputCursor);
@@ -85,50 +86,86 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
if (!loyaltyCard.note.isEmpty()) {
inputHolder.mNoteField.setVisibility(View.VISIBLE);
inputHolder.mNoteField.setText(loyaltyCard.note);
inputHolder.mNoteField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
inputHolder.mNoteField.setTextSize(size);
} else {
inputHolder.mNoteField.setVisibility(View.GONE);
}
if (!loyaltyCard.balance.equals(new BigDecimal("0"))) {
int drawableSize = dpToPx((size*24)/14, mContext);
inputHolder.mDivider.setVisibility(View.VISIBLE);
inputHolder.mBalanceField.setVisibility(View.VISIBLE);
Drawable balanceIcon = inputHolder.mBalanceField.getCompoundDrawables()[0];
balanceIcon.setBounds(0,0,drawableSize,drawableSize);
inputHolder.mBalanceField.setCompoundDrawablesRelative(balanceIcon, null, null, null);
if (mDarkModeEnabled) {
inputHolder.mBalanceField.getCompoundDrawables()[0].setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
balanceIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
}
inputHolder.mBalanceField.setText(Utils.formatBalance(mContext, loyaltyCard.balance, loyaltyCard.balanceType));
inputHolder.mBalanceField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
inputHolder.mBalanceField.setTextSize(size);
} else {
inputHolder.mBalanceField.setVisibility(View.GONE);
}
if (loyaltyCard.expiry != null) {
int drawableSize = dpToPx((size*24)/14, mContext);
inputHolder.mDivider.setVisibility(View.VISIBLE);
inputHolder.mExpiryField.setVisibility(View.VISIBLE);
Drawable expiryIcon = inputHolder.mExpiryField.getCompoundDrawables()[0];
expiryIcon.setBounds(0,0, drawableSize, drawableSize);
inputHolder.mExpiryField.setCompoundDrawablesRelative(expiryIcon, null, null, null);
if (Utils.hasExpired(loyaltyCard.expiry)) {
expiryIcon.setColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP);
expiryIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.RED, BlendModeCompat.SRC_ATOP));
inputHolder.mExpiryField.setTextColor(Color.RED);
} else if (mDarkModeEnabled) {
expiryIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
expiryIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
}
inputHolder.mExpiryField.setText(DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry));
inputHolder.mExpiryField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
inputHolder.mExpiryField.setTextSize(size);
} else {
inputHolder.mExpiryField.setVisibility(View.GONE);
}
inputHolder.mStarIcon.setVisibility(loyaltyCard.starStatus != 0 ? View.VISIBLE : View.GONE);
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
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());
}
private void applyClickEvents(LoyaltyCardListItemViewHolder inputHolder, final int inputPosition)
{
inputHolder.mThumbnailContainer.setOnClickListener(inputView -> mListener.onIconClicked(inputPosition));
private void applyClickEvents(LoyaltyCardListItemViewHolder inputHolder, final int inputPosition) {
inputHolder.mRow.setOnClickListener(inputView -> mListener.onRowClicked(inputPosition));
inputHolder.mInformationContainer.setOnClickListener(inputView -> mListener.onRowClicked(inputPosition));
@@ -145,85 +182,68 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
});
}
private void applyIconAnimation(LoyaltyCardListItemViewHolder inputHolder, int inputPosition)
{
if (mSelectedItems.get(inputPosition, false))
{
private void applyIconAnimation(LoyaltyCardListItemViewHolder inputHolder, int inputPosition) {
if (mSelectedItems.get(inputPosition, false)) {
inputHolder.mThumbnailFrontContainer.setVisibility(View.GONE);
resetIconYAxis(inputHolder.mThumbnailBackContainer);
inputHolder.mThumbnailBackContainer.setVisibility(View.VISIBLE);
inputHolder.mThumbnailBackContainer.setAlpha(1);
if (mCurrentSelectedIndex == inputPosition)
{
if (mCurrentSelectedIndex == inputPosition) {
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, true);
resetCurrentIndex();
}
}
else
{
} else {
inputHolder.mThumbnailBackContainer.setVisibility(View.GONE);
resetIconYAxis(inputHolder.mThumbnailFrontContainer);
inputHolder.mThumbnailFrontContainer.setVisibility(View.VISIBLE);
inputHolder.mThumbnailFrontContainer.setAlpha(1);
if ((mReverseAllAnimations && mAnimationItemsIndex.get(inputPosition, false)) || mCurrentSelectedIndex == inputPosition)
{
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)
{
private void resetIconYAxis(View inputView) {
if (inputView.getRotationY() != 0) {
inputView.setRotationY(0);
}
}
public void resetAnimationIndex()
{
public void resetAnimationIndex() {
mReverseAllAnimations = false;
mAnimationItemsIndex.clear();
}
public void toggleSelection(int inputPosition)
{
public void toggleSelection(int inputPosition) {
mCurrentSelectedIndex = inputPosition;
if (mSelectedItems.get(inputPosition, false))
{
if (mSelectedItems.get(inputPosition, false)) {
mSelectedItems.delete(inputPosition);
mAnimationItemsIndex.delete(inputPosition);
}
else
{
} else {
mSelectedItems.put(inputPosition, true);
mAnimationItemsIndex.put(inputPosition, true);
}
notifyDataSetChanged();
}
public void clearSelections()
{
public void clearSelections() {
mReverseAllAnimations = true;
mSelectedItems.clear();
notifyDataSetChanged();
}
public int getSelectedItemCount()
{
public int getSelectedItemCount() {
return mSelectedItems.size();
}
public ArrayList<LoyaltyCard> getSelectedItems()
{
public ArrayList<LoyaltyCard> getSelectedItems() {
ArrayList<LoyaltyCard> result = new ArrayList<>();
int i;
for(i = 0; i < mSelectedItems.size(); i++)
{
for (i = 0; i < mSelectedItems.size(); i++) {
mCursor.moveToPosition(mSelectedItems.keyAt(i));
result.add(LoyaltyCard.toLoyaltyCard(mCursor));
}
@@ -231,33 +251,27 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
return result;
}
private void resetCurrentIndex()
{
private void resetCurrentIndex() {
mCurrentSelectedIndex = -1;
}
public interface CardAdapterListener
{
void onIconClicked(int inputPosition);
public interface CardAdapterListener {
void onRowClicked(int inputPosition);
void onRowLongClicked(int inputPosition);
}
public class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener
{
public static class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder {
public TextView mStoreField, mNoteField, mBalanceField, mExpiryField;
public LinearLayout mInformationContainer;
public ImageView mCardIcon, mStarIcon;
public CardView mThumbnailContainer;
public ImageView mCardIcon, mStarIcon, mTickIcon;
public MaterialCardView mRow;
public View mDivider;
public RelativeLayout mThumbnailFrontContainer, mThumbnailBackContainer;
public LoyaltyCardListItemViewHolder(View inputView)
{
public LoyaltyCardListItemViewHolder(View inputView, CardAdapterListener inputListener) {
super(inputView);
mThumbnailContainer = inputView.findViewById(R.id.thumbnail_container);
mRow = inputView.findViewById(R.id.row);
mDivider = inputView.findViewById(R.id.info_divider);
mThumbnailFrontContainer = inputView.findViewById(R.id.thumbnail_front);
@@ -269,15 +283,18 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
mExpiryField = inputView.findViewById(R.id.expiry);
mCardIcon = inputView.findViewById(R.id.thumbnail);
mStarIcon = inputView.findViewById(R.id.star);
inputView.setOnLongClickListener(this);
}
@Override
public boolean onLongClick(View inputView)
{
mListener.onRowLongClicked(getAdapterPosition());
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
mTickIcon = inputView.findViewById(R.id.selected_thumbnail);
inputView.setOnLongClickListener(view -> {
inputListener.onRowClicked(getAdapterPosition());
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
});
}
}
}
public int dpToPx(int dp, Context mContext){
Resources r = mContext.getResources();
int px = (int)TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
return px;
}
}

View File

@@ -12,6 +12,7 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageDecoder;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -40,7 +41,6 @@ import com.google.android.material.chip.ChipGroup;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import com.google.zxing.BarcodeFormat;
import com.jaredrummler.android.colorpicker.ColorPickerDialog;
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener;
@@ -71,8 +71,9 @@ import androidx.core.content.FileProvider;
import androidx.exifinterface.media.ExifInterface;
import androidx.fragment.app.DialogFragment;
public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
{
import protect.card_locker.async.TaskHandler;
public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
private static final String TAG = "Catima";
private final String STATE_TAB_INDEX = "savedTab";
@@ -140,6 +141,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
LoyaltyCard tempLoyaltyCard;
final private TaskHandler mTasks = new TaskHandler();
private static LoyaltyCard updateTempState(LoyaltyCard loyaltyCard, LoyaltyCardField fieldName, Object value) {
return new LoyaltyCard(
(int) (fieldName == LoyaltyCardField.id ? value : loyaltyCard.id),
@@ -153,7 +156,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
(CatimaBarcode) (fieldName == LoyaltyCardField.barcodeType ? value : loyaltyCard.barcodeType),
(Integer) (fieldName == LoyaltyCardField.headerColor ? value : loyaltyCard.headerColor),
(int) (fieldName == LoyaltyCardField.starStatus ? value : loyaltyCard.starStatus),
Utils.getUnixTime()
Utils.getUnixTime(),100
);
}
@@ -163,8 +166,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
hasChanged = true;
}
private void extractIntentFields(Intent intent)
{
private void extractIntentFields(Intent intent) {
final Bundle b = intent.getExtras();
loyaltyCardId = b != null ? b.getInt(BUNDLE_ID) : 0;
updateLoyaltyCard = b != null && b.getBoolean(BUNDLE_UPDATE, false);
@@ -204,8 +206,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
@@ -415,7 +416,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
} else if (s.toString().equals(getString(R.string.setBarcodeId))) {
if (!lastValue.toString().equals(getString(R.string.setBarcodeId))) {
barcodeIdField.setText(lastValue);
};
}
;
AlertDialog.Builder builder = new AlertDialog.Builder(LoyaltyCardEditActivity.this);
builder.setTitle(R.string.setBarcodeId);
@@ -470,7 +472,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
if (!barcodeFormat.isSupported()) {
Toast.makeText(LoyaltyCardEditActivity.this, getString(R.string.unsupportedBarcodeType), Toast.LENGTH_LONG).show();
}
} catch (IllegalArgumentException e) {}
} catch (IllegalArgumentException e) {
}
}
generateOrHideBarcode();
@@ -509,8 +512,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
}
@Override
public void onNewIntent(Intent intent)
{
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.i(TAG, "Received new intent");
@@ -519,15 +521,14 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
@SuppressLint("DefaultLocale")
@Override
public void onResume()
{
public void onResume() {
super.onResume();
Log.i(TAG, "To view card: " + loyaltyCardId);
onResuming = true;
if(tempLoyaltyCard == null) {
if (tempLoyaltyCard == null) {
if (updateLoyaltyCard) {
tempLoyaltyCard = db.getLoyaltyCard(loyaltyCardId);
if (tempLoyaltyCard == null) {
@@ -550,7 +551,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
setTitle(R.string.addCardTitle);
} else {
// New card, use default values
tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime());
tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime(),100);
setTitle(R.string.addCardTitle);
}
}
@@ -563,8 +564,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
barcodeIdField.setText(tempLoyaltyCard.barcodeId != null ? tempLoyaltyCard.barcodeId : getString(R.string.sameAsCardId));
barcodeTypeField.setText(tempLoyaltyCard.barcodeType != null ? tempLoyaltyCard.barcodeType.prettyName() : getString(R.string.noBarcode));
if(groupsChips.getChildCount() == 0)
{
if (groupsChips.getChildCount() == 0) {
List<Group> existingGroups = db.getGroups();
List<Group> loyaltyCardGroups = db.getLoyaltyCardGroups(loyaltyCardId);
@@ -603,18 +603,17 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
}
// Generate random header color
if(tempLoyaltyCard.headerColor == null)
{
if (tempLoyaltyCard.headerColor == null) {
// Select a random color to start out with.
TypedArray colors = getResources().obtainTypedArray(R.array.letter_tile_colors);
final int color = (int)(Math.random() * colors.length());
final int color = (int) (Math.random() * colors.length());
updateTempState(LoyaltyCardField.headerColor, colors.getColor(color, Color.BLACK));
colors.recycle();
}
// It can't be null because we set it in updateTempState but SpotBugs insists it can be
// NP_NULL_ON_SOME_PATH: Possible null pointer dereference
if(tempLoyaltyCard.headerColor != null) {
if (tempLoyaltyCard.headerColor != null) {
thumbnail.setOnClickListener(new ColorSelectListener());
}
@@ -805,11 +804,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
startActivityForResult(i, type);
}
class EditCardIdAndBarcode implements View.OnClickListener
{
class EditCardIdAndBarcode implements View.OnClickListener {
@Override
public void onClick(View v)
{
public void onClick(View v) {
Intent i = new Intent(getApplicationContext(), ScanActivity.class);
final Bundle b = new Bundle();
b.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, cardIdFieldView.getText().toString());
@@ -818,11 +815,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
}
}
class ChooseCardImage implements View.OnClickListener
{
class ChooseCardImage implements View.OnClickListener {
@Override
public void onClick(View v) throws NoSuchElementException
{
public void onClick(View v) throws NoSuchElementException {
ImageView targetView = v.getId() == ID_IMAGE_FRONT ? cardImageFront : cardImageBack;
LinkedHashMap<String, Callable<Void>> cardOptions = new LinkedHashMap<>();
@@ -869,11 +864,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
}
}
class ColorSelectListener implements View.OnClickListener
{
class ColorSelectListener implements View.OnClickListener {
@Override
public void onClick(View v)
{
public void onClick(View v) {
ColorPickerDialog.Builder dialogBuilder = ColorPickerDialog.newBuilder();
if (tempLoyaltyCard.headerColor != null) {
@@ -881,19 +874,16 @@ 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);
generateIcon(storeFieldEdit.getText().toString());
}
@Override
public void onDialogDismissed(int dialogId)
{
public void onDialogDismissed(int dialogId) {
// Nothing to do, no change made
}
});
@@ -954,20 +944,17 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
return;
}
if(tempLoyaltyCard.store.isEmpty())
{
if (tempLoyaltyCard.store.isEmpty()) {
Snackbar.make(storeFieldEdit, R.string.noStoreError, Snackbar.LENGTH_LONG).show();
return;
}
if(tempLoyaltyCard.cardId.isEmpty())
{
if (tempLoyaltyCard.cardId.isEmpty()) {
Snackbar.make(cardIdFieldView, R.string.noCardIdError, Snackbar.LENGTH_LONG).show();
return;
}
if(!validBalance)
{
if (!validBalance) {
Snackbar.make(balanceField, getString(R.string.parsingBalanceFailed, balanceField.getText().toString()), Snackbar.LENGTH_LONG).show();
return;
}
@@ -979,8 +966,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
selectedGroups.add((Group) chip.getTag());
}
if(updateLoyaltyCard)
{ //update of "starStatus" not necessary, since it cannot be changed in this activity (only in ViewActivity)
if (updateLoyaltyCard) { //update of "starStatus" not necessary, since it cannot be changed in this activity (only in ViewActivity)
db.updateLoyaltyCard(loyaltyCardId, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor);
try {
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, true);
@@ -989,9 +975,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
e.printStackTrace();
}
Log.i(TAG, "Updated " + loyaltyCardId + " to " + cardId);
}
else
{
} else {
loyaltyCardId = (int) db.insertLoyaltyCard(tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, 0, tempLoyaltyCard.lastUsed);
try {
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, true);
@@ -1007,14 +991,10 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
if(updateLoyaltyCard)
{
public boolean onCreateOptionsMenu(Menu menu) {
if (updateLoyaltyCard) {
getMenuInflater().inflate(R.menu.card_update_menu, menu);
}
else
{
} else {
getMenuInflater().inflate(R.menu.card_add_menu, menu);
}
@@ -1022,12 +1002,10 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id)
{
switch (id) {
case android.R.id.home:
askBeforeQuitIfChanged();
break;
@@ -1058,8 +1036,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_OK) {
@@ -1087,7 +1064,12 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
} else if (requestCode == Utils.CARD_IMAGE_FROM_FILE_FRONT || requestCode == Utils.CARD_IMAGE_FROM_FILE_BACK) {
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), intent.getData());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ImageDecoder.Source image_source = ImageDecoder.createSource(getContentResolver(), intent.getData());
bitmap = ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true));
} else {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), intent.getData());
}
} catch (IOException e) {
Log.e(TAG, "Error getting data from image file");
e.printStackTrace();
@@ -1137,6 +1119,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
}
private void generateBarcode(String cardIdString, CatimaBarcode barcodeFormat) {
mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false);
if (barcodeImage.getHeight() == 0) {
Log.d(TAG, "ImageView size is not known known at start, waiting for load");
// The size of the ImageView is not yet available as it has not
@@ -1148,12 +1132,14 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
barcodeImage.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Log.d(TAG, "ImageView size now known");
new BarcodeImageWriterTask(getApplicationContext(), barcodeImage, cardIdString, barcodeFormat, null, false, warnOnInvalidBarcodeType).execute();
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), barcodeImage, cardIdString, barcodeFormat, null, false, warnOnInvalidBarcodeType);
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
}
});
} else {
Log.d(TAG, "ImageView size known known, creating barcode");
new BarcodeImageWriterTask(getApplicationContext(), barcodeImage, cardIdString, barcodeFormat, null, false, warnOnInvalidBarcodeType).execute();
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), barcodeImage, cardIdString, barcodeFormat, null, false, warnOnInvalidBarcodeType);
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
}
showBarcode();

View File

@@ -1,14 +1,18 @@
package protect.card_locker;
import android.app.Application;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.multidex.MultiDexApplication;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardLockerApplication extends MultiDexApplication {
public class LoyaltyCardLockerApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Settings settings = new Settings(getApplicationContext());
Settings settings = new Settings(this);
AppCompatDelegate.setDefaultNightMode(settings.getTheme());
}
}

View File

@@ -30,7 +30,6 @@ import android.widget.Toast;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.zxing.BarcodeFormat;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
@@ -45,12 +44,14 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.Guideline;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.widget.TextViewCompat;
import protect.card_locker.async.TaskHandler;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements GestureDetector.OnGestureListener
{
public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements GestureDetector.OnGestureListener {
private static final String TAG = "Catima";
private GestureDetector mGestureDetector;
@@ -101,6 +102,8 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
static final String STATE_IMAGEINDEX = "imageIndex";
static final String STATE_FULLSCREEN = "isFullscreen";
final private TaskHandler mTasks = new TaskHandler();
@Override
public boolean onDown(MotionEvent e) {
return true;
@@ -181,8 +184,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
IMAGE_BACK
}
private void extractIntentFields(Intent intent)
{
private void extractIntentFields(Intent intent) {
final Bundle b = intent.getExtras();
loyaltyCardId = b != null ? b.getInt("id") : 0;
Log.d(TAG, "View activity: id=" + loyaltyCardId);
@@ -192,22 +194,18 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
Drawable unwrappedIcon = AppCompatResources.getDrawable(this, active ? R.drawable.active_dot : R.drawable.inactive_dot);
assert unwrappedIcon != null;
Drawable wrappedIcon = DrawableCompat.wrap(unwrappedIcon);
DrawableCompat.setTint(wrappedIcon, getResources().getColor(R.color.iconColor));
DrawableCompat.setTint(wrappedIcon, ContextCompat.getColor(getApplicationContext(), R.color.iconColor));
return wrappedIcon;
}
private Drawable getIcon(int icon, boolean dark)
{
private Drawable getIcon(int icon, boolean dark) {
Drawable unwrappedIcon = AppCompatResources.getDrawable(this, icon);
assert unwrappedIcon != null;
Drawable wrappedIcon = DrawableCompat.wrap(unwrappedIcon);
if(dark)
{
if (dark) {
DrawableCompat.setTint(wrappedIcon, Color.BLACK);
}
else
{
} else {
DrawableCompat.setTintList(wrappedIcon, null);
}
@@ -215,8 +213,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
@@ -250,9 +247,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
appBarLayout = findViewById(R.id.app_bar_layout);
centerGuideline = findViewById(R.id.centerGuideline);
centerGuideline.setGuidelinePercent(0.5f);
barcodeScaler = findViewById(R.id.barcodeScaler);
barcodeScaler.setProgress(100);
maximizeButton.setBackgroundColor(getThemeColor());
minimizeButton.setBackgroundColor(getThemeColor());
bottomSheetButton.setBackgroundColor(getThemeColor());
@@ -264,10 +259,18 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
float scale = (float) progress / (float) barcodeScaler.getMax();
Log.d(TAG, "Scaling to " + scale);
if (imageTypes.get(mainImageIndex) == ImageType.BARCODE) {
redrawBarcodeAfterResize();
if(isFullscreen){
loyaltyCard.zoomLevel = progress;
db.updateLoyaltyCardZoomLevel(loyaltyCardId, loyaltyCard.zoomLevel);
}
centerGuideline.setGuidelinePercent(0.5f * scale);
if (format != null && format.isSquare()) {
centerGuideline.setGuidelinePercent(0.75f * scale);
} else {
centerGuideline.setGuidelinePercent(0.5f * scale);
}
drawMainImage(mainImageIndex, true);
}
@Override
@@ -320,7 +323,8 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) { }
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
bottomSheetButton.setOnClickListener(v -> {
@@ -356,8 +360,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
@Override
public void onNewIntent(Intent intent)
{
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.i(TAG, "Received new intent");
@@ -373,8 +376,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
@Override
public void onResume()
{
public void onResume() {
super.onResume();
Log.i(TAG, "To view card: " + loyaltyCardId);
@@ -383,12 +385,10 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
// '1' is the brightest. We attempt to maximize the brightness
// to help barcode readers scan the barcode.
Window window = getWindow();
if(window != null)
{
if (window != null) {
WindowManager.LayoutParams attributes = window.getAttributes();
if (settings.useMaxBrightnessDisplayingBarcode())
{
if (settings.useMaxBrightnessDisplayingBarcode()) {
attributes.screenBrightness = 1F;
}
@@ -397,7 +397,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
if (settings.getDisableLockscreenWhileViewingCard()) {
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
@@ -405,8 +405,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
loyaltyCard = db.getLoyaltyCard(loyaltyCardId);
if(loyaltyCard == null)
{
if (loyaltyCard == null) {
Log.w(TAG, "Could not lookup loyalty card " + loyaltyCardId);
Toast.makeText(this, R.string.noCardExistsError, Toast.LENGTH_LONG).show();
finish();
@@ -424,20 +423,17 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
settings.getFontSizeMin(settings.getLargeFont()), settings.getFontSizeMax(settings.getLargeFont()),
1, TypedValue.COMPLEX_UNIT_SP);
if(loyaltyCard.note.length() > 0)
{
if (loyaltyCard.note.length() > 0) {
noteView.setVisibility(View.VISIBLE);
noteView.setText(loyaltyCard.note);
noteView.setTextSize(settings.getFontSizeMax(settings.getMediumFont()));
}
else
{
} else {
noteView.setVisibility(View.GONE);
}
List<Group> loyaltyCardGroups = db.getLoyaltyCardGroups(loyaltyCardId);
if(loyaltyCardGroups.size() > 0) {
if (loyaltyCardGroups.size() > 0) {
List<String> groupNames = new ArrayList<>();
for (Group group : loyaltyCardGroups) {
groupNames.add(group._id);
@@ -446,35 +442,29 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
groupsView.setVisibility(View.VISIBLE);
groupsView.setText(getString(R.string.groupsList, TextUtils.join(", ", groupNames)));
groupsView.setTextSize(settings.getFontSizeMax(settings.getMediumFont()));
}
else
{
} else {
groupsView.setVisibility(View.GONE);
}
if(!loyaltyCard.balance.equals(new BigDecimal(0))) {
if (!loyaltyCard.balance.equals(new BigDecimal(0))) {
balanceView.setVisibility(View.VISIBLE);
balanceView.setText(getString(R.string.balanceSentence, Utils.formatBalance(this, loyaltyCard.balance, loyaltyCard.balanceType)));
balanceView.setTextSize(settings.getFontSizeMax(settings.getMediumFont()));
}
else
{
} else {
balanceView.setVisibility(View.GONE);
}
if(loyaltyCard.expiry != null) {
if (loyaltyCard.expiry != null) {
expiryView.setVisibility(View.VISIBLE);
int expiryString = R.string.expiryStateSentence;
if(Utils.hasExpired(loyaltyCard.expiry)) {
if (Utils.hasExpired(loyaltyCard.expiry)) {
expiryString = R.string.expiryStateSentenceExpired;
expiryView.setTextColor(getResources().getColor(R.color.alert));
expiryView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.alert));
}
expiryView.setText(getString(expiryString, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry)));
expiryView.setTextSize(settings.getFontSizeMax(settings.getMediumFont()));
}
else
{
} else {
expiryView.setVisibility(View.GONE);
}
expiryView.setTag(loyaltyCard.expiry);
@@ -493,12 +483,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
TypedValue.COMPLEX_UNIT_DIP);
int backgroundHeaderColor;
if(loyaltyCard.headerColor != null)
{
if (loyaltyCard.headerColor != null) {
backgroundHeaderColor = loyaltyCard.headerColor;
}
else
{
} else {
backgroundHeaderColor = LetterBitmap.getDefaultColor(this, loyaltyCard.store);
}
@@ -506,12 +493,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
appBarLayout.setBackgroundColor(backgroundHeaderColor);
int textColor;
if(Utils.needsDarkForeground(backgroundHeaderColor))
{
if (Utils.needsDarkForeground(backgroundHeaderColor)) {
textColor = Color.BLACK;
}
else
{
} else {
textColor = Color.WHITE;
}
storeName.setTextColor(textColor);
@@ -520,20 +504,15 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
// If the background is very bright, we should use dark icons
backgroundNeedsDarkIcons = Utils.needsDarkForeground(backgroundHeaderColor);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setHomeAsUpIndicator(getIcon(R.drawable.ic_arrow_back_white, backgroundNeedsDarkIcons));
}
// Make notification area light if dark icons are needed
if(Build.VERSION.SDK_INT >= 23)
{
if (Build.VERSION.SDK_INT >= 23) {
window.getDecorView().setSystemUiVisibility(backgroundNeedsDarkIcons ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0);
}
if(Build.VERSION.SDK_INT >= 21)
{
window.setStatusBarColor(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);
@@ -587,8 +566,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
@Override
public void onBackPressed() {
if (isFullscreen)
{
if (isFullscreen) {
setFullscreen(false);
return;
}
@@ -597,16 +575,14 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.card_view_menu, menu);
// Always calculate lockscreen icon, it may need a black color
boolean lockBarcodeScreenOrientation = settings.getLockBarcodeScreenOrientation();
MenuItem item = menu.findItem(R.id.action_lock_unlock);
setOrientatonLock(item, lockBarcodeScreenOrientation);
if(lockBarcodeScreenOrientation)
{
if (lockBarcodeScreenOrientation) {
item.setVisible(false);
}
@@ -625,8 +601,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
if (starred) {
menu.findItem(R.id.action_star_unstar).setIcon(getIcon(R.drawable.ic_starred_white, backgroundNeedsDarkIcons));
menu.findItem(R.id.action_star_unstar).setTitle(R.string.unstar);
}
else {
} else {
menu.findItem(R.id.action_star_unstar).setIcon(getIcon(R.drawable.ic_unstarred_white, backgroundNeedsDarkIcons));
menu.findItem(R.id.action_star_unstar).setTitle(R.string.star);
}
@@ -634,12 +609,10 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id)
{
switch (id) {
case android.R.id.home:
finish();
break;
@@ -654,12 +627,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
return true;
case R.id.action_lock_unlock:
if(rotationEnabled)
{
if (rotationEnabled) {
setOrientatonLock(item, true);
}
else
{
} else {
setOrientatonLock(item, false);
}
rotationEnabled = !rotationEnabled;
@@ -675,8 +645,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
return super.onOptionsItemSelected(item);
}
private void setupOrientation()
{
private void setupOrientation() {
Toolbar portraitToolbar = findViewById(R.id.toolbar);
Toolbar landscapeToolbar = findViewById(R.id.toolbar_landscape);
@@ -704,51 +673,44 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
private void setOrientatonLock(MenuItem item, boolean lock)
{
if(lock)
{
private void setOrientatonLock(MenuItem item, boolean lock) {
if (lock) {
item.setIcon(getIcon(R.drawable.ic_lock_outline_white_24dp, backgroundNeedsDarkIcons));
item.setTitle(R.string.unlockScreen);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}
else
{
} else {
item.setIcon(getIcon(R.drawable.ic_lock_open_white_24dp, backgroundNeedsDarkIcons));
item.setTitle(R.string.lockScreen);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
private void makeBottomSheetVisibleIfUseful()
{
private void makeBottomSheetVisibleIfUseful() {
if (noteView.getVisibility() == View.VISIBLE || groupsView.getVisibility() == View.VISIBLE || balanceView.getVisibility() == View.VISIBLE || expiryView.getVisibility() == View.VISIBLE) {
bottomSheet.setVisibility(View.VISIBLE);
}
else
{
} else {
bottomSheet.setVisibility(View.GONE);
}
}
private void drawBarcode() {
mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false);
if (format != null) {
new BarcodeImageWriterTask(
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(
getApplicationContext(),
mainImage,
barcodeIdString != null ? barcodeIdString : cardIdString,
format,
null,
false,
null)
.execute();
null);
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
}
}
@@ -764,7 +726,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
drawBarcode();
}
});
};
}
}
private void drawMainImage(int index, boolean waitForResize) {
@@ -824,6 +786,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
* by machines which offer no space to insert the complete device.
*/
private void setFullscreen(boolean enabled) {
isFullscreen = enabled;
ActionBar actionBar = getSupportActionBar();
if (enabled && !imageTypes.isEmpty()) {
@@ -831,14 +794,15 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
drawMainImage(mainImageIndex, true);
barcodeScaler.setProgress(loyaltyCard.zoomLevel);
// Hide maximize and show minimize button and scaler
maximizeButton.setVisibility(View.GONE);
minimizeButton.setVisibility(View.VISIBLE);
barcodeScaler.setVisibility(View.VISIBLE);
// Hide actionbar
if(actionBar != null)
{
if (actionBar != null) {
actionBar.hide();
}
@@ -863,9 +827,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_FULLSCREEN
);
}
else
{
} else {
Log.d(TAG, "Move out of fullscreen");
// Reset center guideline
@@ -880,8 +842,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
barcodeScaler.setVisibility(View.GONE);
// Show actionbar
if(actionBar != null)
{
if (actionBar != null) {
actionBar.show();
}
@@ -905,6 +866,6 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
);
}
isFullscreen = enabled;
Log.d("setFullScreen","Is full screen enabled? "+enabled+" Zoom Level = "+barcodeScaler.getProgress());
}
}

View File

@@ -8,7 +8,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.database.CursorIndexOutOfBoundsException;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
@@ -16,6 +16,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -31,6 +32,7 @@ import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.splashscreen.SplashScreen;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.SettingsActivity;
@@ -181,8 +183,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
@Override
protected void onCreate(Bundle inputSavedInstanceState)
{
setTheme(R.style.AppTheme_NoActionBar);
super.onCreate(inputSavedInstanceState);
SplashScreen.installSplashScreen(this);
setTitle(R.string.app_name);
setContentView(R.layout.main_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
@@ -193,9 +195,9 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
@Override
public void onTabSelected(TabLayout.Tab tab) {
selectedTab = tab.getPosition();
Log.d("onTabSelected","Tab Position "+tab.getPosition());
mGroup = tab.getTag();
updateLoyaltyCardList();
// Store active tab in Shared Preference to restore next app launch
SharedPreferences activeTabPref = getApplicationContext().getSharedPreferences(
getString(R.string.sharedpreference_active_tab),
@@ -228,6 +230,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
mHelpText.setOnTouchListener(gestureTouchListener);
mNoMatchingCardsText.setOnTouchListener(gestureTouchListener);
mCardList.setOnTouchListener(gestureTouchListener);
mNoGroupCardsText.setOnTouchListener(gestureTouchListener);
mAdapter = new LoyaltyCardCursorAdapter(this, null, this);
mCardList.setAdapter(mAdapter);
@@ -396,16 +399,17 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
// We want the cardList to be visible regardless of the filtered match count
// to ensure that the noMatchingCardsText doesn't end up being shown below
// the keyboard
mCardList.setVisibility(View.VISIBLE);
mHelpText.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.GONE);
if(mAdapter.getItemCount() > 0)
{
mCardList.setVisibility(View.VISIBLE);
mNoMatchingCardsText.setVisibility(View.GONE);
}
else
{
if(!mFilter.isEmpty()) {
mCardList.setVisibility(View.GONE);
if (!mFilter.isEmpty()) {
// Actual Empty Search Result
mNoMatchingCardsText.setVisibility(View.VISIBLE);
mNoGroupCardsText.setVisibility(View.GONE);
@@ -458,14 +462,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
groupsTabLayout.setVisibility(View.VISIBLE);
}
private void openPrivacyPolicy() {
Intent browserIntent = new Intent(
Intent.ACTION_VIEW,
Uri.parse("https://catima.app/privacy-policy")
);
startActivity(browserIntent);
}
@Override
public boolean onCreateOptionsMenu(Menu inputMenu)
{
@@ -519,10 +515,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
if (id == R.id.action_sort)
{
TabLayout.Tab tab = ((TabLayout) findViewById(R.id.groups)).getTabAt(selectedTab);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(R.string.sort_by);
AtomicInteger currentIndex = new AtomicInteger();
List<DBHelper.LoyaltyCardOrder> loyaltyCardOrders = Arrays.asList(DBHelper.LoyaltyCardOrder.values());
for (int i = 0; i < loyaltyCardOrders.size(); i++) {
@@ -532,18 +524,29 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(R.string.sort_by);
final View customLayout = getLayoutInflater().inflate(R.layout.sorting_option, null);
builder.setView(customLayout);
CheckBox ch = (CheckBox) customLayout.findViewById(R.id.checkBox_reverse);
ch.setChecked(mOrderDirection == DBHelper.LoyaltyCardOrderDirection.Descending);
builder.setSingleChoiceItems(R.array.sort_types_array, currentIndex.get(), (dialog, which) -> currentIndex.set(which));
builder.setPositiveButton(R.string.sort, (dialog, which) -> {
setSort(loyaltyCardOrders.get(currentIndex.get()), DBHelper.LoyaltyCardOrderDirection.Ascending);
if(ch.isChecked()) {
setSort(loyaltyCardOrders.get(currentIndex.get()), DBHelper.LoyaltyCardOrderDirection.Descending);
}
else {
setSort(loyaltyCardOrders.get(currentIndex.get()), DBHelper.LoyaltyCardOrderDirection.Ascending);
}
dialog.dismiss();
});
builder.setNeutralButton(R.string.reverse, (dialog, which) -> {
setSort(loyaltyCardOrders.get(currentIndex.get()), DBHelper.LoyaltyCardOrderDirection.Descending);
dialog.dismiss();
});
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
@@ -571,12 +574,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
return true;
}
if(id == R.id.action_privacy_policy)
{
openPrivacyPolicy();
return true;
}
if (id == R.id.action_about)
{
Intent i = new Intent(getApplicationContext(), AboutActivity.class);
@@ -637,6 +634,12 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
mGestureDetector.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.d(TAG, "On fling");
@@ -652,9 +655,10 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
Integer currentTab = groupsTabLayout.getSelectedTabPosition();
Log.d("onFling","Current Tab "+currentTab);
// Swipe right
if (velocityX < -150) {
Log.d("onFling","Right Swipe detected "+velocityX);
Integer nextTab = currentTab + 1;
if (nextTab == groupsTabLayout.getTabCount()) {
@@ -668,6 +672,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
// Swipe left
if (velocityX > 150) {
Log.d("onFling","Left Swipe detected "+velocityX);
Integer nextTab = currentTab - 1;
if (nextTab < 0) {
@@ -720,16 +725,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
}
}
@Override
public void onIconClicked(int inputPosition)
{
if (mCurrentActionMode == null)
{
mCurrentActionMode = startSupportActionMode(mCurrentActionModeCallback);
}
toggleSelection(inputPosition);
}
@Override
public void onRowClicked(int inputPosition)
@@ -742,7 +737,21 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
{
Cursor selected = mAdapter.getCursor();
selected.moveToPosition(inputPosition);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
// FIXME
//
// There is a really nasty edge case that can happen when someone taps a card but right
// after it swipes (very small window, hard to reproduce). The cursor gets replaced and
// may not have a card at the ID number that is returned from onRowClicked.
//
// The proper fix, obviously, would involve makes sure an onFling can't happen while a
// click is being processed. Sadly, I have not yet found a way to make that possible.
LoyaltyCard loyaltyCard;
try {
loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
} catch (CursorIndexOutOfBoundsException e) {
Log.w(TAG, "Prevented crash from tap + swipe on ID " + inputPosition + ": " + e);
return;
}
Intent i = new Intent(this, LoyaltyCardViewActivity.class);
i.setAction("");

View File

@@ -8,6 +8,7 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageDecoder;
import android.graphics.Matrix;
import android.os.Build;
import android.os.LocaleList;
@@ -105,7 +106,12 @@ public class Utils {
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), intent.getData());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ImageDecoder.Source image_source = ImageDecoder.createSource(context.getContentResolver(), intent.getData());
bitmap = ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true));
} else {
bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), intent.getData());
}
} catch (IOException e) {
Log.e(TAG, "Error getting data from image file");
e.printStackTrace();

View File

@@ -0,0 +1,8 @@
package protect.card_locker.async;
import java.util.concurrent.Callable;
public interface CompatCallable<T> extends Callable<T> {
void onPostExecute(Object result);
void onPreExecute();
}

View File

@@ -0,0 +1,174 @@
package protect.card_locker.async;
import android.os.Handler;
import android.os.Looper;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* AsyncTask has been deprecated so this provides very rudimentary compatibility without
* needing to redo too many Parts.
*
* However this is a much, much more cooperative Behaviour than before so
* the callers need to ensure we do NOT rely on forced cancellation and feed less into the
* ThreadPools so we don't OOM/Overload the Users device
*
* This assumes single-threaded callers.
*/
public class TaskHandler {
public enum TYPE {
BARCODE,
IMPORT,
EXPORT
}
HashMap<TYPE, ThreadPoolExecutor> executors = generateExecutors();
final private HashMap<TYPE, LinkedList<Future<?>>> taskList = new HashMap<>();
private final Handler uiHandler = new Handler(Looper.getMainLooper());
private HashMap<TYPE, ThreadPoolExecutor> generateExecutors() {
HashMap<TYPE, ThreadPoolExecutor> initExecutors = new HashMap<>();
for (TYPE type : TYPE.values()) {
replaceExecutor(initExecutors, type, false, false);
}
return initExecutors;
}
/**
* Replaces (or initializes) an Executor with a clean (new) one
* @param executors Map Reference
* @param type Which Queue
* @param flushOld attempt shutdown
* @param waitOnOld wait for Termination
*/
private void replaceExecutor(HashMap<TYPE, ThreadPoolExecutor> executors, TYPE type, Boolean flushOld, Boolean waitOnOld) {
ThreadPoolExecutor oldExecutor = executors.get(type);
if (oldExecutor != null) {
if (flushOld) {
oldExecutor.shutdownNow();
}
if (waitOnOld) {
try {
//noinspection ResultOfMethodCallIgnored
oldExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
executors.put(type, (ThreadPoolExecutor) Executors.newCachedThreadPool());
}
/**
* Queue a Pseudo-AsyncTask for execution
*
* @param type Queue
* @param callable PseudoAsyncTask
*/
public void executeTask(TYPE type, CompatCallable<?> callable) {
Runnable runner = () -> {
try {
// Run on the UI Thread
uiHandler.post(callable::onPreExecute);
// Background
final Object result = callable.call();
// Post results on UI Thread so we can show them
uiHandler.post(() -> {
callable.onPostExecute(result);
});
} catch (Exception e) {
e.printStackTrace();
}
};
LinkedList<Future<?>> list = taskList.get(type);
if (list == null) {
list = new LinkedList<>();
}
ThreadPoolExecutor executor = executors.get(type);
if (executor != null) {
Future<?> task = executor.submit(runner);
// Test Queue Cancellation:
// task.cancel(true);
list.push(task);
taskList.put(type, list);
}
}
/**
* This will attempt to cancel a currently running list of Tasks
* Useful to ignore scheduled tasks - but not able to hard-stop tasks that are running
*
* @param type Which Queue to target
* @param forceCancel attempt to close the Queue and force-replace it after
* @param waitForFinish wait and return after the old executor finished. Times out after 5s
* @param waitForCurrentlyRunning wait before cancelling tasks. Useful for tests.
*/
public void flushTaskList(TYPE type, Boolean forceCancel, Boolean waitForFinish, Boolean waitForCurrentlyRunning) {
// Only used for Testing
if (waitForCurrentlyRunning) {
ThreadPoolExecutor oldExecutor = executors.get(type);
if (oldExecutor != null) {
try {
//noinspection ResultOfMethodCallIgnored
oldExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Attempt to cancel known Tasks and clean the List
LinkedList<Future<?>> tasks = taskList.get(type);
if (tasks != null) {
for (Future<?> task : tasks) {
if (!task.isDone() || !task.isCancelled()) {
// Interrupt any Task we can
task.cancel(true);
}
}
}
tasks = new LinkedList<>();
taskList.put(type, tasks);
if (forceCancel || waitForFinish) {
ThreadPoolExecutor oldExecutor = executors.get(type);
if (oldExecutor != null) {
if (forceCancel) {
if (waitForFinish) {
try {
//noinspection ResultOfMethodCallIgnored
oldExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
oldExecutor.shutdownNow();
replaceExecutor(executors, type, true, false);
} else {
try {
//noinspection ResultOfMethodCallIgnored
oldExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}

View File

@@ -6,6 +6,7 @@ import android.graphics.Bitmap;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import org.apache.commons.csv.CSVFormat;
@@ -30,14 +31,21 @@ import protect.card_locker.Utils;
*/
public class CatimaExporter implements Exporter
{
public void exportData(Context context, DBHelper db, OutputStream output) throws IOException, InterruptedException
public void exportData(Context context, DBHelper db, OutputStream output,char[] password) throws IOException, InterruptedException
{
// Necessary vars
int readLen;
byte[] readBuffer = new byte[InternalZipConstants.BUFF_SIZE];
// Create zip output stream
ZipOutputStream zipOutputStream = new ZipOutputStream(output);
ZipOutputStream zipOutputStream;
if(password!=null && password.length>0){
zipOutputStream = new ZipOutputStream(output,password);
}
else{
zipOutputStream = new ZipOutputStream(output);
}
// Generate CSV
ByteArrayOutputStream catimaOutputStream = new ByteArrayOutputStream();
@@ -45,8 +53,7 @@ public class CatimaExporter implements Exporter
writeCSV(db, catimaOutputStreamWriter);
// Add CSV to zip file
ZipParameters csvZipParameters = new ZipParameters();
csvZipParameters.setFileNameInZip("catima.csv");
ZipParameters csvZipParameters = createZipParameters("catima.csv",password);
zipOutputStream.putNextEntry(csvZipParameters);
InputStream csvInputStream = new ByteArrayInputStream(catimaOutputStream.toByteArray());
while ((readLen = csvInputStream.read(readBuffer)) != -1) {
@@ -71,8 +78,7 @@ public class CatimaExporter implements Exporter
// If it exists, add to the .zip file
Bitmap image = Utils.retrieveCardImage(context, card.id, front);
if (image != null) {
ZipParameters imageZipParameters = new ZipParameters();
imageZipParameters.setFileNameInZip(Utils.getCardImageFileName(card.id, front));
ZipParameters imageZipParameters = createZipParameters(Utils.getCardImageFileName(card.id, front),password);
zipOutputStream.putNextEntry(imageZipParameters);
InputStream imageInputStream = new ByteArrayInputStream(Utils.bitmapToByteArray(image));
while ((readLen = imageInputStream.read(readBuffer)) != -1) {
@@ -86,6 +92,16 @@ public class CatimaExporter implements Exporter
zipOutputStream.close();
}
private ZipParameters createZipParameters(String fileName, char[] password){
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip(fileName);
if(password!=null && password.length>0){
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
}
return zipParameters;
}
private void writeCSV(DBHelper db, OutputStreamWriter output) throws IOException, InterruptedException {
CSVPrinter printer = new CSVPrinter(output, CSVFormat.RFC4180);

View File

@@ -48,7 +48,7 @@ public class CatimaImporter implements Importer
bufferedInputStream.mark(100);
// First, check if this is a zip file
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream);
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream,password);
boolean isZipFile = false;
@@ -104,7 +104,7 @@ public class CatimaImporter implements Importer
public void parseV1(Context context, DBHelper db, BufferedReader input) throws IOException, FormatException, InterruptedException
{
final CSVParser parser = new CSVParser(input, CSVFormat.RFC4180.withHeader());
final CSVParser parser = new CSVParser(input, CSVFormat.RFC4180.builder().setHeader().build());
SQLiteDatabase database = db.getWritableDatabase();
database.beginTransaction();
@@ -209,7 +209,7 @@ public class CatimaImporter implements Importer
public void parseV2Groups(DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
{
// Parse groups
final CSVParser groupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.withHeader());
final CSVParser groupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
List<CSVRecord> records = new ArrayList<>();
@@ -235,7 +235,7 @@ public class CatimaImporter implements Importer
public void parseV2Cards(Context context, DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
{
// Parse cards
final CSVParser cardParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.withHeader());
final CSVParser cardParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
List<CSVRecord> records = new ArrayList<>();
@@ -261,7 +261,7 @@ public class CatimaImporter implements Importer
public void parseV2CardGroups(DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
{
// Parse card group mappings
final CSVParser cardGroupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.withHeader());
final CSVParser cardGroupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
List<CSVRecord> records = new ArrayList<>();

View File

@@ -17,5 +17,5 @@ public interface Exporter
* Export the database to the output stream in a given format.
* @throws IOException
*/
void exportData(Context context, DBHelper db, OutputStream output) throws IOException, InterruptedException;
void exportData(Context context, DBHelper db, OutputStream output,char[] password) throws IOException, InterruptedException;
}

View File

@@ -32,8 +32,7 @@ import protect.card_locker.Utils;
* The database's loyalty cards are expected to appear in the CSV data.
* A header is expected for the each table showing the names of the columns.
*/
public class FidmeImporter implements Importer
{
public class FidmeImporter implements Importer {
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
// We actually retrieve a .zip file
ZipInputStream zipInputStream = new ZipInputStream(input, password);
@@ -59,7 +58,7 @@ public class FidmeImporter implements Importer
SQLiteDatabase database = db.getWritableDatabase();
database.beginTransaction();
final CSVParser fidmeParser = new CSVParser(new StringReader(loyaltyCards.toString()), CSVFormat.RFC4180.withDelimiter(';').withHeader());
final CSVParser fidmeParser = new CSVParser(new StringReader(loyaltyCards.toString()), CSVFormat.RFC4180.builder().setDelimiter(';').setHeader().build());
try {
for (CSVRecord record : fidmeParser) {
@@ -87,8 +86,7 @@ public class FidmeImporter implements Importer
* session.
*/
private void importLoyaltyCard(SQLiteDatabase database, DBHelper helper, CSVRecord record)
throws IOException, FormatException
{
throws IOException, FormatException {
// A loyalty card export from Fidme contains the following fields:
// Retailer (store name)
// Program (program name)
@@ -100,8 +98,7 @@ public class FidmeImporter implements Importer
// The store is called Retailer
String store = CSVHelpers.extractString("Retailer", record, "");
if (store.isEmpty())
{
if (store.isEmpty()) {
throw new FormatException("No store listed, but is required");
}
@@ -121,8 +118,7 @@ public class FidmeImporter implements Importer
// The ID is called reference
String cardId = CSVHelpers.extractString("Reference", record, "");
if(cardId.isEmpty())
{
if (cardId.isEmpty()) {
throw new FormatException("No card ID listed, but is required");
}

View File

@@ -22,7 +22,7 @@ public class MultiFormatExporter
* another ImportExportResult otherwise. If not Success, partial data may have been
* written to the output stream, and it should be discarded.
*/
public static ImportExportResult exportData(Context context, DBHelper db, OutputStream output, DataFormat format)
public static ImportExportResult exportData(Context context, DBHelper db, OutputStream output, DataFormat format,char[] password)
{
Exporter exporter = null;
@@ -40,7 +40,7 @@ public class MultiFormatExporter
{
try
{
exporter.exportData(context, db, output);
exporter.exportData(context, db, output,password);
return ImportExportResult.Success;
}
catch(IOException e)

View File

@@ -43,7 +43,7 @@ public class StocardImporter implements Importer
HashMap<String, HashMap<String, Object>> loyaltyCardHashMap = new HashMap<>();
HashMap<String, HashMap<String, String>> providers = new HashMap<>();
final CSVParser parser = new CSVParser(new InputStreamReader(context.getResources().openRawResource(R.raw.stocard_stores), StandardCharsets.UTF_8), CSVFormat.RFC4180.withHeader());
final CSVParser parser = new CSVParser(new InputStreamReader(context.getResources().openRawResource(R.raw.stocard_stores), StandardCharsets.UTF_8), CSVFormat.RFC4180.builder().setHeader().build());
try
{
@@ -116,14 +116,14 @@ public class StocardImporter implements Importer
.substring("/loyalty-card-providers/".length())
);
try {
if (jsonObject.has("input_barcode_format")) {
loyaltyCardHashMap = appendToLoyaltyCardHashMap(
loyaltyCardHashMap,
cardName,
"barcodeType",
jsonObject.getString("input_barcode_format")
);
} catch (JSONException ignored) {}
}
}
} else if (fileName.endsWith("notes/default.json")) {
loyaltyCardHashMap = appendToLoyaltyCardHashMap(

View File

@@ -1,6 +1,7 @@
package protect.card_locker.preferences;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
@@ -41,7 +42,6 @@ public class SettingsActivity extends CatimaAppCompatActivity
// Display the fragment as the main content.
SettingsFragment fragment = new SettingsFragment();
fragment.setParentReference(this);
getSupportFragmentManager().beginTransaction()
.replace(R.id.settings_container, fragment)
.commit();
@@ -64,11 +64,6 @@ public class SettingsActivity extends CatimaAppCompatActivity
public static class SettingsFragment extends PreferenceFragmentCompat
{
private static final String DIALOG_FRAGMENT_TAG = "SettingsFragment";
private SettingsActivity parent;
public void setParentReference(SettingsActivity settingsActivity) {
parent = settingsActivity;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
@@ -120,8 +115,9 @@ public class SettingsActivity extends CatimaAppCompatActivity
});
localePreference.setOnPreferenceChangeListener((preference, newValue) -> {
// Refresh the activity
parent.finish();
startActivity(parent.getIntent());
Intent intent = new Intent(getContext(), SettingsActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
getContext().startActivity(intent);
return true;
});

View File

@@ -1,7 +0,0 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/ic_launcher_background"/>
<item android:gravity="center"
android:width="256dp"
android:height="256dp"
android:drawable="@drawable/ic_launcher_foreground" />
</layer-list>

View File

@@ -22,21 +22,333 @@
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/aboutText"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:linksClickable="true"
android:singleLine="false"
android:focusable="true" />
android:orientation="vertical">
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/version_history"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/version_history_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/version_history"
android:textColor="@color/colorSecondaryText"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/version_history_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/version_history_main" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textColor="@color/colorSecondaryText"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/credits"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/credits_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/credits"
android:textColor="@color/colorSecondaryText"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/credits_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/credits_main" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textColor="@color/colorSecondaryText"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/translate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/translate_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/help_translate_this_app"
android:textColor="@color/colorSecondaryText"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textColor="@color/colorSecondaryText"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/license"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/license_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/license"
android:textColor="@color/colorSecondaryText"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/license_sub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/app_license"
android:layout_marginEnd="20dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/license_main"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textColor="@color/colorSecondaryText"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/repo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/repo_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/source_repository"
android:textColor="@color/colorSecondaryText"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/repo_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/on_github"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/repo_main" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textColor="@color/colorSecondaryText"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/privacy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/privacy_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/privacy_policy"
android:textColor="@color/colorSecondaryText"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/privacy_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/and_data_usage"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/privacy_main" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textColor="@color/colorSecondaryText"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/rate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/rate_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/rate_this_app"
android:textColor="@color/colorSecondaryText"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/rate_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/on_google_play"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/rate_main" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textColor="@color/colorSecondaryText"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:padding="8dp"
android:id="@+id/report_error"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/report_error_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:padding="2dp"
android:text="@string/report_error"
android:textColor="@color/colorSecondaryText"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/report_error_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/report_error_main"
app:layout_constraintStart_toStartOf="parent"
android:textSize="16sp"
android:text="@string/on_github"
android:padding="2dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:fontFamily="sans-serif-medium"
android:text="@string/arrow"
android:textColor="@color/colorSecondaryText"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</ScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -68,7 +68,7 @@
android:paddingTop="@dimen/inputPadding"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
<com.google.android.material.card.MaterialCardView
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_marginEnd="@dimen/activity_margin"
@@ -84,7 +84,7 @@
android:contentDescription="@string/thumbnailDescription"
android:src="@mipmap/ic_launcher"/>
</androidx.cardview.widget.CardView>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/storeNameField"
@@ -347,7 +347,7 @@
android:paddingTop="@dimen/inputPadding">
<!-- Front image -->
<androidx.cardview.widget.CardView
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@@ -369,7 +369,7 @@
android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_camera_white" />
</androidx.cardview.widget.CardView>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<!-- Back image -->
@@ -382,7 +382,7 @@
android:paddingTop="@dimen/inputPadding">
<!-- Back image -->
<androidx.cardview.widget.CardView
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@@ -404,7 +404,7 @@
android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_camera_white" />
</androidx.cardview.widget.CardView>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</TableLayout>
</TableLayout>

View File

@@ -25,22 +25,29 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
<com.google.android.material.card.MaterialCardView
android:id="@+id/thumbnail_container"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
android:layout_alignParentStart="true">
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
>
<RelativeLayout
android:id="@+id/thumbnail_front"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize">
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">
<ImageView
android:id="@+id/thumbnail"
android:scaleType="centerCrop"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_centerVertical="true"
android:contentDescription="@string/thumbnailDescription"
android:src="@mipmap/ic_launcher" />
@@ -48,25 +55,29 @@
<RelativeLayout
android:id="@+id/thumbnail_back"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize">
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_centerHorizontal="true"
android:layout_centerInParent="true"
android:contentDescription="@string/thumbnailDescription"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_done" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:minHeight="@dimen/cardThumbnailSize"
android:id="@+id/storeContainer"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:layout_toEndOf="@+id/thumbnail_container">
<TextView
@@ -82,6 +93,8 @@
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"
@@ -114,6 +127,8 @@
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"
@@ -125,6 +140,8 @@
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"

View File

@@ -122,6 +122,10 @@
<TextView
android:id="@+id/cardIdView"
android:enabled="true"
android:textIsSelectable="true"
android:focusable="true"
android:longClickable="true"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="10.0dip"
@@ -181,6 +185,10 @@
<TextView
android:id="@+id/noteView"
android:enabled="true"
android:textIsSelectable="true"
android:focusable="true"
android:longClickable="true"
android:autoLink="all"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -190,6 +198,10 @@
<TextView
android:id="@+id/groupsView"
android:enabled="true"
android:textIsSelectable="true"
android:focusable="true"
android:longClickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
@@ -198,6 +210,10 @@
<TextView
android:id="@+id/balanceView"
android:enabled="true"
android:textIsSelectable="true"
android:focusable="true"
android:longClickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
@@ -206,6 +222,10 @@
<TextView
android:id="@+id/expiryView"
android:enabled="true"
android:textIsSelectable="true"
android:focusable="true"
android:longClickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<CheckBox
android:id="@+id/checkBox_reverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:paddingLeft="20dp"
android:text="@string/reverse"
android:textSize="19sp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -27,10 +27,6 @@
android:id="@+id/action_settings"
android:title="@string/settings"
app:showAsAction="never"/>
<item
android:id="@+id/action_privacy_policy"
android:title="@string/privacy_policy"
app:showAsAction="never"/>
<item
android:id="@+id/action_about"
android:title="@string/about"

View File

@@ -6,20 +6,24 @@ Heimen Stoffels
solokot
mondstern
Taco
Gediminas Murauskas
IllusiveMan196
Joel A
Samantaz Fox
arno-github
Sergio Paredes
Nyatsuki
StoyanDimitrov
arshbeerSingh
Petr Novák
Oğuz Ersen
Gediminas Murauskas
Joel A
StoyanDimitrov
Samantaz Fox
Nyatsuki
arno-github
Ankit Tiwari
Sergio Paredes
arshbeerSingh
huuhaa
Michael Moroni
Petr Novák
Olivia (Zoe)
betsythefc
waffshappen
Miha Frangež
K. Herbert
Quentin PAGÈS
String E. Fighter
@@ -34,14 +38,15 @@ Jane Kong
Lukas Grassauer
Michalis
schirinowski
Thomas Bertels
inesre
lgasp
phlostically
waffshappen
Aditya Das
Kevin Sicong Jiang
Miha Frangež
Airat
BMN
Biren
Flav
Franciszek Stefan
Izzy
@@ -49,13 +54,18 @@ Karol Kosek
bittin
Maciej Błędkowski
Mattia
Michael Gangolf
pbeckmann
Peer Beckmann
QuangDNguyen2211
Rohan Babbar
Rose Liverman
Simone Dotto
Still Hsu
Subhashish Anand
Tymofii Lytvynenko
Tjipke van der Heide
avikkundu
opsik
psa-jforestier
Robin

View File

@@ -24,7 +24,7 @@
<item quantity="other"><xliff:g>%d</xliff:g> карти</item>
</plurals>
<string name="failedOpeningFileManager">Инсталирайте приложение за управление на файлове.</string>
<string name="app_license">Свободен софтуер с авторски права, лицензиран под GPLv3+.</string>
<string name="app_license">Свободен софтуер с авторски права, лицензиран под GPLv3+</string>
<string name="frontImageDescription">Снимка на предната страна на карта</string>
<string name="backImageDescription">Снимка на задната страна на карта</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> не изглежда истинска наличност.</string>
@@ -52,7 +52,7 @@
<string name="barcodeId">Стойност на щрихкода</string>
<string name="importLoyaltyCardKeychain">Внасяне от Loyalty Card Keychain</string>
<string name="importFidmeMessage">Изберете файла <i>fidme-export-request-xxxxxx.zip</i>, предварително изнесен от FidMe и ръчно изберете вида на щрихкодовете.
\nИли създайте такъв файл от Data Protection в менюто на профила във FidMe и изберете „Extract my data“.</string>
\nСъздайте такъв файл от Data Protection в менюто на профила във FidMe и изберете „Extract my data“.</string>
<string name="importFidme">Внасяне от FidMe</string>
<string name="exportOptionExplanation">Данните ще бъдат запазени на място по ваш избор.</string>
<string name="accept">Приемане</string>
@@ -116,7 +116,7 @@
<string name="exportName">Изнасяне</string>
<string name="importExport">Внасяне/изнасяне</string>
<string name="sendLabel">Изпращане…</string>
<string name="scanCardBarcode">Сканиране на щрихкод от карта</string>
<string name="scanCardBarcode">Снемане на щрихкод от карта</string>
<string name="editCardTitle">Редактиране на карта</string>
<string name="share">Споделя</string>
<string name="copy_to_clipboard">Копира идентификатора в междинната памет</string>
@@ -124,7 +124,7 @@
<string name="importSuccessful">Картите са внесени успешно</string>
<string name="chooseImportType">От къде ще внесете\?</string>
<string name="importCatimaMessage">Изберете файла <i>catima.zip</i>, предварително изнесен от Catima.
\nИли създайте такъв файл от меню Внасяне/изнасяне от друго устройство със Catima като изберете Изнасяне.</string>
\nСъздайте такъв файл от меню Внасяне/изнасяне от друго устройство с Catima като изберете Изнасяне.</string>
<string name="importOptionApplicationTitle">От друго приложение</string>
<string name="importOptionFilesystemButton">Избиране от файлова система</string>
<string name="importOptionFilesystemExplanation">Изберете определен файл от файловата система.</string>
@@ -133,9 +133,9 @@
<string name="app_revision_fmt">Компилация: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="debug_version_fmt">Издание: <xliff:g id="version">%s</xliff:g></string>
<string name="about_title_fmt">Относно <xliff:g id="app_name">%s</xliff:g></string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Всички права запазени © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Всички права запазени © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="app_copyright_old">На основата на Loyalty Card Keychain
\nвсички права запазени © 20162020 Branden Archer.</string>
\nвсички права запазени © 20162020 Branden Archer</string>
<string name="about">Относно</string>
<string name="importOptionFilesystemTitle">Внасяне от файловата система</string>
<string name="importCatima">Внасяне от Catima</string>
@@ -156,11 +156,11 @@
<string name="importStocard">Внасяне от Stocard</string>
<string name="importVoucherVault">Внасяне от Voucher Vault</string>
<string name="importVoucherVaultMessage">Изберете файла <i>vouchervault.json</i>, предварително изнесен от Voucher Vault.
\nИли създайте такъв файл от меню Изнасяне от Voucher Vault.</string>
<string name="importStocardMessage">Изберете вашия <i>***-sync.zip</i> експорт от Stocard, за да го импортирате.
\nИли го получете, като изпратите имейл на support@stocardapp.com с искане за експорт на вашите данни.</string>
\nСъздайте такъв файл от меню „Export“ във Voucher Vault.</string>
<string name="importStocardMessage">Изберете файла <i>***-sync.zip</i>, предварително изнесен от Stocard.
\nПолучете го като изпратите писмо на support@stocardapp.com с искане за изнасяне вашите данни.</string>
<string name="importLoyaltyCardKeychainMessage">Изберете файла <i>LoyaltyCardKeychain.csv</i>, предварително изнесен от Loyalty Card Keychain.
\nИли създайте такъв файл от меню Внасяне/изнасяне от друго устройство със Loyalty Card Keychain като изберете Изнасяне.</string>
\nСъздайте такъв файл от меню Внасяне/изнасяне от друго устройство с Loyalty Card Keychain като изберете Изнасяне.</string>
<string name="failedParsingImportUriError">Препратката не може да бъде анализирана за внасяне</string>
<string name="card_ids_copied">[не превеждай този низ, https://github.com/TheLastProject/Catima/issues/278]</string>
<string name="failedGeneratingShareURL">Грешка при създаване на адрес за споделяне. Изпратете доклад за дефект.</string>
@@ -190,4 +190,24 @@
<string name="noGroupCards">Тази група не съдържа карти</string>
<string name="toggleMoreInfo">Превключване на повече информация</string>
<string name="barcodeImageDescriptionWithType">Изображение на щрихкод на карта от вида <xliff:g>%s</xliff:g></string>
<string name="swipeToSwitchImages">Плъзване или задържане за смяна на изображения</string>
<string name="sort_by">Сортиране по</string>
<string name="reverse">Наобратно</string>
<string name="sort_by_balance">Наличност</string>
<string name="sort_by_expiry">Валидност</string>
<string name="sort_by_most_recently_used">Последно използване</string>
<string name="sort_by_name">Наименование</string>
<string name="sort">Сортиране</string>
<string name="credits">Заслуги</string>
<string name="license">Лиценз</string>
<string name="source_repository">Хранилище на изходния код</string>
<string name="on_github">в GitHub</string>
<string name="rate_this_app">Оценете приложението</string>
<string name="report_error">Докладване на грешка</string>
<string name="version_history">История на изданията</string>
<string name="on_google_play">в Google Play</string>
<string name="and_data_usage">и използване на данни</string>
<string name="help_translate_this_app">Помогнете за превода на приложението</string>
<string name="exportPasswordHint">Въведете парола</string>
<string name="exportPassword">Задаване на парола за защита на изнесеното (по избор)</string>
</resources>

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="save">সংরক্ষণ</string>
<string name="cancel">বাতিল</string>
<string name="unstar">তারা মুক্ত</string>
<string name="star">তারা</string>
<string name="barcodeNoBarcode">বারকোড না বারকোড</string>
<string name="barcodeType">বারকোড ধরন</string>
<string name="note">বিঃদ্রঃ</string>
<string name="storeName">দোকানের নাম</string>
<string name="noMatchingGiftCards">কোন ম্যাচিং উপহার কার্ড নেই</string>
<string name="noGiftCards">উপহার কার্ড নেই</string>
<string name="action_add">কর্ম যোগ</string>
<string name="all">সব</string>
<string name="noGroupCards">গোষ্ঠী কার্ড নেই</string>
<string name="noGroups">গোষ্ঠীগুলি নেই</string>
<string name="groups">গোষ্ঠীগুলি</string>
<string name="enter_group_name">গোষ্ঠী নাম লিখুন </string>
<string name="exportSuccessful">রপ্তানি সফল</string>
<string name="importSuccessful">আগম সফল</string>
<string name="intent_import_card_from_url_share_text">url শেয়ার টেক্সট থেকে ইন্টেন্ট ইম্পোর্ট কার্ড</string>
<string name="settings_disable_lockscreen_while_viewing_card"> কার্ড দেখা কালিন লকস্ক্রিন নিষ্ক্রিয়</string>
<string name="settings_keep_screen_on">সেটিংস পর্দা খোলা রাখুন</string>
<string name="settings_lock_barcode_orientation"> তালাবদ্ধ বার কোড অভিযোজন</string>
<string name="settings_max_font_size_scale">সর্বোচ্চ হরফ আকার</string>
<string name="settings_light_theme">সাদাটে থিম</string>
<string name="settings_system_theme">যন্ত্রর থিম</string>
<string name="settings_theme">থিম</string>
<string name="settings_category_title_ui">বিভাগ শিরোনাম</string>
<string name="starImage">তারা ছবি</string>
<string name="importCatima">ক্যাতিনা আগম</string>
<string name="importLoyaltyCardKeychain">আমদানি লয়্যালটি কার্ড কীচেন</string>
<string name="importStocard">স্টো কার্ড আমদানি করুন</string>
<string name="importVoucherVault">আমদানি ভাউচার ভল্ট</string>
<string name="barcodeId">বারকোড আইডি</string>
<string name="sameAsCardId">কার্ড আইডির মতো</string>
<string name="setBarcodeId">বারকোড আইডি সেট করুন</string>
<string name="unsupportedBarcodeType">অসমর্থিত বারকোড টাইপ</string>
<string name="wrongValueForBarcodeType">বারকোড টাইপের জন্য ভুল মান</string>
<string name="copy_to_clipboard_multiple_toast">ক্লিপবোর্ড একাধিক টোস্টে অনুলিপি করুন</string>
<string name="intent_import_card_from_url_share_multiple_text">url থেকে ইন্টেন্ট ইম্পোর্ট কার্ড একাধিক টেক্সট শেয়ার করে</string>
<string name="frontImageDescription">সামনের চিত্রের বর্ণনা</string>
<string name="backImageDescription">পিছনের চিত্রের বর্ণনা</string>
<string name="photos">ছবি</string>
<string name="setFrontImage">সদর ছবি স্থাপন</string>
<string name="setBackImage">পিছনের ছবি স্থাপন</string>
<string name="removeImage">ছবি অপসারণ</string>
<string name="takePhoto">ছবি নেত্তয়া</string>
<string name="updateBarcodeQuestionTitle">হালনাগাদ বারকোড প্রশ্ন শিরোনাম</string>
<string name="updateBarcodeQuestionText">হালনাগাদ বারকোড প্রশ্ন টেক্সট </string>
<string name="yes">হাঁ</string>
<string name="no">না</string>
<string name="passwordRequired">পাসওয়ার্ড প্রয়োজন</string>
<string name="failedGeneratingShareURL">শেয়ার ইউআরএল তৈরি করতে ব্যর্থ হয়েছে</string>
<string name="turn_flashlight_on">টর্চলাইট চালু করুন</string>
<string name="turn_flashlight_off">টর্চলাইট বন্ধ করুন</string>
<string name="settings_locale">লোকেল</string>
<string name="settings_system_locale">সিস্টেম লোকেল</string>
<string name="settings_theme_color">থিম রঙ</string>
<string name="settings_catima_theme">কটিমা থিম</string>
<string name="settings_pink_theme">গোলাপী থিম</string>
<string name="settings_magenta_theme">ম্যাজেন্টা থিম</string>
<string name="settings_violet_theme">ভায়োলেট থিম</string>
<string name="settings_blue_theme">নীল থিম</string>
<string name="settings_sky_blue_theme">আকাশী নীল থিম</string>
<string name="settings_green_theme">সবুজ থিম</string>
<string name="settings_brown_theme">বাদামী থিম</string>
<string name="sort">সাজান</string>
<string name="toggleMoreInfo">আরও তথ্য টগল করুন</string>
<string name="swipeToSwitchImages">ছবি পরিবর্তন করতে সোয়াইপ করুন</string>
<string name="sort_by_name">নামের দ্বারা সাজান</string>
<string name="sort_by_most_recently_used">সর্বাধিক সম্প্রতি ব্যবহৃত দ্বারা সাজান</string>
<string name="sort_by_expiry">মেয়াদ শেষ করে সাজান</string>
<string name="reverse">বিপরীত</string>
<string name="sort_by">ক্রমানুসার</string>
<string name="noCardExistsError">কোন কার্ড নেই ত্রুটি</string>
<string name="noStoreError">স্টোরেজ ত্রুটি নেই</string>
<string name="card_ids_copied">কার্ড আইডি কপি করা হয়েছে</string>
<string name="noCardsMessage">কোন কার্ড বার্তা নেই</string>
<string name="addCardTitle">কার্ডের শিরোনাম যোগ করুন</string>
<string name="editCardTitle">কার্ডের শিরোনাম সম্পাদনা করুন</string>
<string name="sendLabel">লেবেল পাঠান</string>
<string name="share">ভাগ</string>
<string name="copy_to_clipboard">নকল করুন ক্লিপবোর্ড এ</string>
<string name="deleteConfirmation">নিশ্চিতকরণ মুছে দিন</string>
<string name="unlockScreen">পর্দা আনলক করুন</string>
<string name="confirm">নিশ্চিত করুন</string>
<string name="delete">মুছে ফেলুন</string>
<string name="edit">সম্পাদনা</string>
</resources>

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="save">Snimi</string>
<string name="cancel">Odustani</string>
<string name="unstar">Ukloni sve omiljene</string>
<string name="star">Omiljene</string>
<string name="barcodeNoBarcode">Ova kartica nema barkode</string>
<string name="barcodeType">Barcode tip</string>
<string name="note">Bilježnica</string>
<string name="storeName">Ime</string>
<string name="noMatchingGiftCards">Nisam našao ništa. Pokušaj promijeniti pretragu.</string>
<string name="noGiftCards">Kliknite + Plus dugme da dodate kartu ili uvozite nešto iz menija prvo.</string>
<string name="action_add">Dodaj</string>
<string name="all">Sve</string>
<string name="noGroupCards">Ova grupa ne sadrži nikakve karte</string>
<string name="noGroups">Kliknite + Plus dugme da dodate grupe za kategorizaciju prvo.</string>
<string name="groups">Grupe</string>
<string name="enter_group_name">Unesite ime grupe</string>
<string name="exportSuccessful">Podaci o kartama izvožen</string>
<string name="importSuccessful">Uvezeni podaci o kartama</string>
<string name="intent_import_card_from_url_share_text">Želim podijeliti čestitku s tobom</string>
<string name="settings_disable_lockscreen_while_viewing_card">Spriječi zaključavanje ekrana</string>
<string name="settings_keep_screen_on">Zadrži ekran</string>
<string name="settings_lock_barcode_orientation">Zaključaj barcode orjentacija</string>
<string name="settings_max_font_size_scale">Max. veliäťina fonta</string>
<string name="settings_light_theme">Svjetlo</string>
<string name="settings_system_theme">Sistem</string>
<string name="settings_theme">Tema</string>
<string name="settings_category_title_ui">Korisničko okruženje</string>
<string name="starImage">Omiljena zvijezda</string>
<string name="importCatima">Uvezi iz Catima</string>
<string name="importLoyaltyCardKeychain">Uvezi iz Loyalty Card Keychain</string>
<string name="importStocard">Uvezi iz Stokarda</string>
<string name="importVoucherVault">Uvezi iz trezora vaučer</string>
<string name="barcodeId">Barcode vrijednost</string>
<string name="sameAsCardId">Isto kao i kartica</string>
<string name="setBarcodeId">Postavi vrijednost za bar kod</string>
<string name="unsupportedBarcodeType">Ovaj bar kod još nije prikazan. Ona može biti podržana u kasnijoj verziji app.</string>
<string name="wrongValueForBarcodeType">Izabrana vrijednost nije izvršna</string>
<string name="copy_to_clipboard_multiple_toast">IDs kartica kopiran u clipboard</string>
<string name="intent_import_card_from_url_share_multiple_text">Želim podijeliti karte s tobom</string>
<string name="frontImageDescription">Slika kartice</string>
<string name="backImageDescription">Slika pozadine kartice</string>
<string name="photos">Slike</string>
<string name="setFrontImage">Postavi naslovnu sliku</string>
<string name="setBackImage">Vrati sliku</string>
<string name="removeImage">Ukloni sliku</string>
<string name="takePhoto">Slikaj</string>
<string name="updateBarcodeQuestionTitle">Ažurirati bar kod vrijednost\?</string>
<string name="updateBarcodeQuestionText">Promijenio si auto. Da li želite ažurirati bar kod koristiti istu vrijednost\?</string>
<string name="yes">Da</string>
<string name="no">Ne.</string>
<string name="passwordRequired">Upišite šifru</string>
<string name="failedGeneratingShareURL">Ne mogu generisati oštriji URL. Molim vas, prijavite ovo.</string>
<string name="turn_flashlight_on">Upali lampu</string>
<string name="turn_flashlight_off">Ugasi lampu</string>
<string name="settings_locale">Jezik</string>
<string name="settings_system_locale">Sistem</string>
<string name="settings_theme_color">Boja teme</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_pink_theme">Ružičasto</string>
<string name="settings_magenta_theme">Ljubičasto</string>
<string name="settings_violet_theme">Ljubičasto</string>
<string name="settings_blue_theme">Plavo</string>
<string name="settings_sky_blue_theme">Nebo plavo</string>
<string name="settings_green_theme">Zeleno</string>
<string name="settings_brown_theme">Braun</string>
<string name="sort">Poništi sortiranje</string>
<string name="toggleMoreInfo">Uključi savjete</string>
<string name="swipeToSwitchImages">Swipe ili long press za prebacivanje slika</string>
<string name="sort_by_name">Ime</string>
<string name="sort_by_most_recently_used">Nedavno Korišten</string>
<string name="sort_by_expiry">Sajam</string>
<string name="reverse">Rikverc</string>
<string name="sort_by">Sortiraj</string>
<string name="noCardExistsError">Nisam mogao pronaći karticu</string>
<string name="noStoreError">Nije uneseno ime</string>
<string name="card_ids_copied">Kopiran ID kartice(s)</string>
<string name="noCardsMessage">Dodaj prvo kartu</string>
<string name="addCardTitle">Dodaj Kartu</string>
<string name="editCardTitle">Izmijeni Karticu</string>
<string name="sendLabel">Pošalji…</string>
<string name="share">Podijeli</string>
<string name="copy_to_clipboard">Kopiraj ID u clipboard</string>
<string name="deleteConfirmation">Izbriši trajno ovu karticu\?</string>
<string name="unlockScreen">Odblokalna Rotacija</string>
<string name="confirm">Potvrdi</string>
<string name="delete">Obriši</string>
<string name="edit">Izmijeni</string>
</resources>

View File

@@ -37,7 +37,7 @@
<string name="importOptionApplicationExplanation">K otevření souboru použijte libovolnou aplikaci nebo svého oblíbeného správce souborů.</string>
<string name="importOptionApplicationButton">Použijte jinou aplikaci</string>
<string name="about">O aplikaci</string>
<string name="app_license">Copylefted libre software, licencovaný GPLv3+.</string>
<string name="app_license">Copylefted libre software, licencovaný GPLv3+</string>
<string name="about_title_fmt">O aplikaci <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Verze: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Informace o revizi: <xliff:g id="app_revision_url">%s</xliff:g></string>
@@ -55,7 +55,7 @@
<string name="app_resources">Zdroje třetích stran Libre: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Libre knihovny třetích stran: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_copyright_old">Na základě Loyalty Card Keychain
\ncopyright © 20162020 Branden Archer.</string>
\ncopyright © 20162020 Branden Archer</string>
<string name="exportOptionExplanation">Data budou zapsána na místo podle vašeho výběru.</string>
<string name="failedParsingImportUriError">Nelze analyzovat import URI</string>
<string name="noCardExistsError">Nelze najít kartu</string>
@@ -138,19 +138,19 @@
<string name="setBarcodeId">Nastavení hodnoty čárového kódu</string>
<string name="sameAsCardId">Stejné jako ID karty</string>
<string name="importVoucherVaultMessage">Vyberte svůj <i>vouchervault.json</i> export z Voucher Vault, který chcete importovat.
\nNebo jej vytvořte tak, že nejprve stisknete tlačítko Exportovat v aplikaci Voucher Vault.</string>
\nVytvořte jej tak, že nejprve stisknete tlačítko Exportovat v aplikaci Voucher Vault.</string>
<string name="importVoucherVault">Import z Voucher Vault</string>
<string name="importStocardMessage">Vyberte svůj <i>***-sync.zip</i> export z aplikace Stocard, který chcete importovat.
\nNebo jej získáte zasláním e-mailu na adresu support@stocardapp.com s žádostí o export vašich dat.</string>
\nZískejte ji zasláním e-mailu na adresu support@stocardapp.com s žádostí o export vašich dat.</string>
<string name="importStocard">Import ze Stocard</string>
<string name="importLoyaltyCardKeychainMessage">Vyberte export <i>LoyaltyCardKeychain.csv</i> z klíčenky věrnostních karet, který chcete importovat.
\nNebo jej vytvořte z nabídky Import/Export v Loyalty Card Keychain tak, že tam nejprve stisknete tlačítko Exportovat.</string>
\nVytvořte jej z nabídky Import/Export v Loyalty Card Keychain tak, že tam nejprve stisknete tlačítko Exportovat.</string>
<string name="importLoyaltyCardKeychain">Import z Loyalty Card Keychain</string>
<string name="importFidmeMessage">Vyberte svůj <i>fidme-export-request-xxxxxx.zip</i> export z FidMe k importu a poté vyberte typy čárových kódů ručně.
\nNebo jej vytvořte ze svého profilu FidMe tak, že nejprve zvolíte možnost Ochrana dat a poté stisknete tlačítko Extract moje data.</string>
<string name="importFidmeMessage">Vyberte svůj <i>fidme-export-request-xxxxxx.zip</i> export z FidMe k importu a poté vyberte typy čárových kódů ručně.
\nVytvořte jej ze svého profilu FidMe tak, že nejprve zvolíte možnost Ochrana dat a poté stisknete tlačítko Extract moje data.</string>
<string name="importFidme">Import z FidMe</string>
<string name="importCatimaMessage">Vyberte export <i>catima.zip</i> z programu Catima, který chcete importovat.
\nNebo jej vytvořte z nabídky Import/Export jiné aplikace Catima tak, že v ní nejprve stisknete tlačítko Exportovat.</string>
\nVytvořte jej z nabídky Import/Export jiné aplikace Catima tak, že v ní nejprve stisknete tlačítko Exportovat.</string>
<string name="importCatima">Import z Catima</string>
<string name="accept">Přijmout</string>
<string name="privacy_policy_popup_text">Oznámení o zásadách ochrany osobních údajů (vyžadováno některými obchody s aplikacemi):
@@ -184,7 +184,7 @@
<string name="exportSuccessful">Data karty exportována</string>
<string name="settings_display_barcode_max_brightness">Rozjasněné zobrazení čárového kódu</string>
<string name="starImage">Oblíbená hvězda</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<plurals name="selectedCardCount">
<item quantity="one">Vybrána <xliff:g>%d</xliff:g> karta</item>
<item quantity="few">Vybrány <xliff:g>%d</xliff:g> karty</item>
@@ -192,4 +192,26 @@
</plurals>
<string name="app_contributors">Přispěli: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="noGroupCards">Tato skupina neobsahuje žádné karty</string>
<string name="sort_by">Seřadit podle</string>
<string name="reverse">Obrátit</string>
<string name="sort_by_balance">Zůstatek</string>
<string name="sort_by_expiry">Vypršení</string>
<string name="sort_by_most_recently_used">Naposledy použité</string>
<string name="sort_by_name">Název</string>
<string name="swipeToSwitchImages">Přejetím nebo dlouhým stisknutím přepínáte obrázky</string>
<string name="toggleMoreInfo">Přepnout zobrazení dalších informací</string>
<string name="sort">Seřadit</string>
<string name="barcodeImageDescriptionWithType">Obrázek čárového kódu karty typu <xliff:g>%s</xliff:g></string>
<string name="version_history">Historie verzí</string>
<string name="rate_this_app">Ohodnoťte tuto aplikaci</string>
<string name="and_data_usage">a využití dat</string>
<string name="credits">Kredity</string>
<string name="on_github">na GitHubu</string>
<string name="source_repository">Úložiště zdrojů</string>
<string name="license">Licence</string>
<string name="help_translate_this_app">Pomozte s překladem této aplikace</string>
<string name="report_error">Nahlásit chybu</string>
<string name="on_google_play">na Google Play</string>
<string name="exportPassword">Nastavení hesla pro ochranu exportu (volitelné)</string>
<string name="exportPasswordHint">Zadejte heslo</string>
</resources>

View File

@@ -36,4 +36,61 @@
</plurals>
<string name="action_add">Tilføj</string>
<string name="action_search">Søg</string>
<string name="importExport">Import/eksport</string>
<string name="exportName">Eksport</string>
<string name="importExportHelp">Hvis du sikkerhedskopierer dine kort, kan du flytte dem til en anden enhed.</string>
<string name="importSuccessfulTitle">Importeret</string>
<string name="importFailedTitle">Import mislykkedes</string>
<string name="importFailed">Kunne ikke importere kort</string>
<string name="exportSuccessfulTitle">Eksporteret</string>
<string name="exportFailedTitle">Eksport mislykkedes</string>
<string name="exportFailed">Kunne ikke eksportere kort</string>
<string name="importing">Importere…</string>
<string name="exporting">Eksportere…</string>
<string name="settings_dark_theme">Mørk</string>
<string name="settings_light_theme">Lys</string>
<string name="settings_theme">Tema</string>
<string name="settings_category_title_ui">Brugergrænseflade</string>
<string name="settings">Indstillinger</string>
<string name="starImage">Favorit stjerne</string>
<string name="thumbnailDescription">Miniaturebillede til kort</string>
<string name="copy_to_clipboard_toast">Kort-ID kopieret til udklipsholderen</string>
<string name="enterBarcodeInstructions">Indtast kortets ID, og vælg enten kortets stregkodetype nedenfor, eller \"Dette kort har ingen stregkode\".</string>
<string name="selectBarcodeTitle">Vælg stregkode</string>
<string name="app_copyright_old">Baseret på Loyalty Card Keychain
\ncopyright © 2016-2020 Branden Archer.</string>
<string name="about">Om</string>
<string name="importOptionApplicationButton">Brug en anden app</string>
<string name="importOptionApplicationExplanation">Brug en hvilken som helst app eller din foretrukne filhåndtering til at åbne en fil.</string>
<string name="importOptionApplicationTitle">Brug en anden app</string>
<string name="noCardsMessage">Tilføj først et kort</string>
<string name="cardShortcut">Kort genvej</string>
<string name="importOptionFilesystemButton">Fra filsystemet</string>
<string name="importOptionFilesystemExplanation">Vælg en bestemt fil fra filsystemet.</string>
<string name="importOptionFilesystemTitle">Import fra filsystem</string>
<string name="exportOptionExplanation">Dataene skrives til en placering efter eget valg.</string>
<string name="noExternalStoragePermissionError">Giv først tilladelse til ekstern lagring til at importere eller eksportere kort</string>
<string name="failedParsingImportUriError">Kunne ikke analysere import-URI\'en</string>
<string name="noCardExistsError">Kunne ikke finde kort</string>
<string name="noCardIdError">Der er ikke angivet noget kort-ID</string>
<string name="noStoreError">Intet navn angivet</string>
<string name="deleteConfirmationGroup">Slet gruppe\?</string>
<string name="all">Alle</string>
<string name="noGroupCards">Denne gruppe indeholder ikke nogen kort</string>
<string name="noGroups">Klik på + plus-knappen for først at tilføje grupper til kategorisering.</string>
<string name="groups">Grupper</string>
<string name="enter_group_name">Indtast gruppenavn</string>
<string name="exportSuccessful">Eksporterede kortdata</string>
<string name="importSuccessful">Kortdata importeret</string>
<string name="intent_import_card_from_url_share_text">Jeg vil dele et kort med jer</string>
<string name="settings_disable_lockscreen_while_viewing_card">Forebyg låseskærm</string>
<string name="settings_keep_screen_on">LHold skærm tændt</string>
<string name="settings_lock_barcode_orientation">Lås stregkode-orientering</string>
<string name="moveUp">Bevæg dig opad</string>
<string name="leaveWithoutSaveConfirmation">Forlade uden at gemme\?</string>
<string name="settings_display_barcode_max_brightness">Lysere stregkodevisning</string>
<string name="failedOpeningFileManager">Installer først en filhåndteringsprogram.</string>
<string name="moveDown">Bevæger sig nedad</string>
<string name="leaveWithoutSaveTitle">Afslut</string>
<string name="addManually">Indtast kort-ID manuelt</string>
</resources>

View File

@@ -46,7 +46,7 @@
<string name="importOptionApplicationExplanation">Beliebige Anwendung oder deinen bevorzugten Dateimanager zur Dateiauswahl verwenden.</string>
<string name="importOptionApplicationButton">Aus anderer Anwendung</string>
<string name="about">Über</string>
<string name="app_license">Freie Software, lizensiert unter der GPLv3+.</string>
<string name="app_license">Freie Software, lizensiert unter der GPLv3+</string>
<string name="about_title_fmt">Über <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Revisionsinfo: <xliff:g id="app_revision_url">%s</xliff:g></string>
@@ -63,10 +63,10 @@
<string name="settings_dark_theme">Dunkel</string>
<string name="settings_light_theme">Hell</string>
<string name="settings_system_theme">System</string>
<string name="settings_theme">Theme</string>
<string name="settings_theme">Farbschema</string>
<string name="enterBarcodeInstructions">Gib die Kartennummer ein und wähle entweder den Barcode-Typ unten oder wähle \"Diese Karte hat keinen Barcode\" aus.</string>
<string name="app_copyright_old">Basierend auf Loyalty Card Keychain
\nCopyright © 2016-2020 Branden Archer.</string>
\nCopyright © 2016-2020 Branden Archer</string>
<string name="exportOptionExplanation">Die Daten werden an einen Ort deiner Wahl geschrieben.</string>
<string name="failedParsingImportUriError">Die Import-URI konnte nicht verarbeitet werden</string>
<string name="share">Teilen</string>
@@ -117,16 +117,16 @@
<string name="accept">Annehmen</string>
<string name="privacy_policy">Datenschutzrichtlinie</string>
<string name="importVoucherVaultMessage">Wählen Sie Ihren <i>vouchervault.json</i>-Export aus Voucher Vault zum Importieren aus.
\nOder erstellen Sie ihn, indem Sie zuerst auf Export in Voucher Vault drücken.</string>
\nErstellen Sie ihn, indem Sie zuerst auf Export in Voucher Vault drücken.</string>
<string name="importVoucherVault">Aus Voucher Vault importieren</string>
<string name="importLoyaltyCardKeychainMessage">Wählen Sie Ihren <i>LoyaltyCardKeychain.csv</i>-Export aus Loyalty Card Keychain zum Importieren aus.
\nOder erstellen Sie ihn über das Menü Import/Export in Loyalty Card Keychain, indem Sie dort zuerst auf Export drücken.</string>
\nErstellen Sie ihn über das Menü Import/Export in Loyalty Card Keychain, indem Sie dort zuerst auf Export drücken.</string>
<string name="importLoyaltyCardKeychain">Aus Loyalty Card Keychain importieren</string>
<string name="importFidmeMessage">Wählen Sie Ihren <i>fidme-export-request-xxxxxx.zip</i>-Export aus FidMe zum Importieren aus und wählen Sie anschließend die Strichcodetypen manuell aus.
\nOder erstellen Sie ihn aus Ihrem FidMe-Profil, indem Sie Datenschutz wählen und dann zuerst auf Meine Daten extrahieren drücken.</string>
<string name="importFidme">Aus FidMe importieren</string>
<string name="importCatimaMessage">Wählen Sie Ihren <i>catima.zip</i>-Export aus Catima zum Importieren aus.
\nOder erstellen Sie ihn aus dem Import/Export-Menü einer anderen Catima-Anwendung, indem Sie dort zuerst Export drücken.</string>
\nErstellen Sie ihn aus dem Import/Export-Menü einer anderen Catima-Anwendung, indem Sie dort zuerst Export drücken.</string>
<string name="importCatima">Aus Catima importieren</string>
<string name="setBarcodeId">Manuell eingeben</string>
<string name="sameAsCardId">Entspricht Kartennummer</string>
@@ -139,7 +139,7 @@
<string name="wrongValueForBarcodeType">Der Wert ist für den gewählten Barcodetyp leider nicht gültig</string>
<string name="app_resources">Freie Ressourcen von Drittanbietern: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Freie Bibliotheken von Drittanbietern: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="intent_import_card_from_url_share_multiple_text">Ich möchte diese Karten mit dir teilen</string>
<string name="copy_to_clipboard_multiple_toast">Kartennummern in die Zwischenablage kopiert</string>
<string name="card_ids_copied">Kartennummer(n) kopiert</string>
@@ -156,7 +156,7 @@
<string name="backImageDescription">Bild der Kartenrückseite</string>
<string name="passwordRequired">Bitte gib das Passwort ein</string>
<string name="importStocardMessage">Wählen Sie Ihren <i>***-sync.zip</i>-Export aus Stocard zum Importieren aus.
\nOder Sie erhalten ihn, indem Sie eine E-Mail an support@stocardapp.com senden und um einen Export Ihrer Daten bitten.</string>
\nSie erhalten ihn, indem Sie eine E-Mail an support@stocardapp.com senden und um einen Export Ihrer Daten bitten.</string>
<string name="importStocard">Von Stocard importieren</string>
<string name="turn_flashlight_off">Licht ausschalten</string>
<string name="turn_flashlight_on">Licht einschalten</string>
@@ -198,4 +198,16 @@
<string name="sort_by_name">Name</string>
<string name="sort">Sortieren</string>
<string name="reverse">Umgekehrt</string>
<string name="version_history">Versionshistorie</string>
<string name="credits">Dank an</string>
<string name="help_translate_this_app">Hilfe bei der Übersetzung</string>
<string name="and_data_usage">und Datennutzung</string>
<string name="rate_this_app">Bewerte die Anwendung</string>
<string name="on_google_play">auf Google Play</string>
<string name="license">Lizenz</string>
<string name="source_repository">Quellcode</string>
<string name="on_github">auf GitHub</string>
<string name="report_error">Fehler melden</string>
<string name="exportPassword">Legen Sie ein Passwort fest, um Ihren Export zu schützen (optional)</string>
<string name="exportPasswordHint">Passwort eingeben</string>
</resources>

View File

@@ -79,4 +79,13 @@
<string name="unlockScreen">Malbloki Rotacio</string>
<string name="lockScreen">Bloko Rotacio</string>
<string name="star">Aldoni al miaj plej ŝatataj</string>
<string name="copy_to_clipboard_toast">Card ID kopiita al la tondujo</string>
<string name="settings_keep_screen_on">Teni sur ekrano</string>
<string name="importSuccessful">Karto datumo importitaj</string>
<string name="enter_group_name">Eniri nomo de la grupo</string>
<string name="noGroups">Klaki la + plus butonon por aldoni grupoj por categorization unua.</string>
<string name="all">Ĉiuj</string>
<string name="intent_import_card_from_url_share_text">Mi deziras dividi karto kun vi</string>
<string name="exportSuccessful">Karto datumo eksportita</string>
<string name="noGroupCards">Ĉi tiu grupo ne enhavas ajnan kartoj</string>
</resources>

View File

@@ -42,7 +42,7 @@
<string name="importOptionApplicationExplanation">Utilisez le gestionnaire de fichiers de votre choix pour importer un fichier.</string>
<string name="importOptionApplicationButton">Utiliser une autre application</string>
<string name="about">À propos</string>
<string name="app_license">Logiciel libre à copyleft, sous licence GPLv3+.</string>
<string name="app_license">Logiciel libre à copyleft, sous licence GPLv3+</string>
<string name="about_title_fmt">À propos de <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Version : <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Notes de version : <xliff:g id="app_revision_url">%s</xliff:g></string>
@@ -62,7 +62,7 @@
<string name="settings_theme">Thème</string>
<string name="enterBarcodeInstructions">Entrez lidentifiant de la carte et choisissez le type de code-barres ci-dessous, ou « Cette carte na pas de code-barres ».</string>
<string name="app_copyright_old">Basé sur Loyalty Card Keychain
\ncopyright © 2016-2020 Branden Archer.</string>
\ncopyright © 2016-2020 Branden Archer</string>
<string name="exportOptionExplanation">Les données seront exportées vers l\'emplacement de votre choix.</string>
<string name="failedParsingImportUriError">Impossible d\'analyser l\'URI d\'importation</string>
<string name="share">Partager</string>
@@ -116,16 +116,16 @@
<string name="settings_disable_lockscreen_while_viewing_card">Empêcher le verrouillage de lécran</string>
<string name="settings_keep_screen_on">Garder lécran allumé</string>
<string name="importVoucherVaultMessage">Sélectionnez votre exportation <i>vouchervault.json</i> de Voucher Vault à importer.
\nOu créez-la en appuyant dabord sur Exporter dans Voucher Vault.</string>
\nCréez-la en appuyant dabord sur Exporter dans Voucher Vault.</string>
<string name="importVoucherVault">Importer depuis Voucher Vault</string>
<string name="importLoyaltyCardKeychainMessage">Sélectionnez votre exportation <i>LoyaltyCardKeychain.csv</i> à partir de Loyalty Card Keychain pour limporter.
\nOu créez-la à partir du menu Importer/Exporter du Loyalty Card Keychain en appuyant dabord sur Exporter.</string>
\nCréez-la à partir du menu Importer/Exporter du Loyalty Card Keychain en appuyant dabord sur Exporter.</string>
<string name="importLoyaltyCardKeychain">Importer depuis Loyalty Card Keychain</string>
<string name="importFidmeMessage">Sélectionnez votre exportation <i>fidme-export-request-xxxxxx.zip</i> de FidMe pour limporter, puis sélectionnez manuellement les types de codes-barres.
\nOu créez-la à partir de votre profil FidMe en choisissant Protection des données, puis en cliquant sur Extraire mes données dabord.</string>
\nCréez-la à partir de votre profil FidMe en choisissant Protection des données, puis en cliquant sur Extraire mes données dabord.</string>
<string name="importFidme">Importer depuis FidMe</string>
<string name="importCatimaMessage">Sélectionnez votre exportation <i>catima.zip</i> depuis Catima à importer.
\nOu créez-la à partir du menu Importer/Exporter dune autre application Catima en appuyant dabord sur Exporter.</string>
\nCréez-la à partir du menu Importer/Exporter dune autre application Catima en appuyant dabord sur Exporter.</string>
<string name="importCatima">Importer depuis Catima</string>
<string name="addFromImage">Sélectionner dans la galerie</string>
<string name="errorReadingImage">Impossible de lire l\'image</string>
@@ -138,7 +138,7 @@
<string name="wrongValueForBarcodeType">La valeur n\'est pas valide pour le type de code-barres sélectionné</string>
<string name="app_resources">Ressources tierces libres : <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Bibliothèques tierces libres : <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="intent_import_card_from_url_share_multiple_text">Je veux partager des cartes avec vous</string>
<string name="copy_to_clipboard_multiple_toast">Identifiants des cartes copiés dans le presse-papiers</string>
<string name="card_ids_copied">Num. de la carte copié(s)</string>
@@ -155,7 +155,7 @@
<string name="frontImageDescription">Image recto de la carte</string>
<string name="passwordRequired">Veuillez entrer le mot de passe</string>
<string name="importStocardMessage">Sélectionnez votre exportation <i>***-sync.zip</i> de Stocard pour limporter.
\nVous pouvez aussi lobtenir en envoyant un courriel à support@stocardapp.com pour demander une exportation de vos données.</string>
\nVous pouvez lobtenir en envoyant un courriel à support@stocardapp.com pour demander une exportation de vos données.</string>
<string name="importStocard">Importer depuis Stocard</string>
<string name="turn_flashlight_off">Éteindre la lampe de poche</string>
<string name="turn_flashlight_on">Allumer la lampe de poche</string>
@@ -198,4 +198,16 @@
<string name="sort_by_most_recently_used">Les plus récemment utilisées</string>
<string name="sort_by_name">Nom</string>
<string name="sort_by_balance">Solde</string>
<string name="report_error">Signaler une erreur</string>
<string name="on_google_play">sur Google Play</string>
<string name="rate_this_app">Notez cette appli</string>
<string name="and_data_usage">utilisation des données</string>
<string name="on_github">sur GitHub</string>
<string name="source_repository">Dépôt source</string>
<string name="license">Licence</string>
<string name="help_translate_this_app">Aidez à traduire cette appli</string>
<string name="credits">Contributeurs</string>
<string name="version_history">Historique des versions</string>
<string name="exportPassword">Définissez un mot de passe pour protéger vos exportations (facultatif)</string>
<string name="exportPasswordHint">Entrez le mot de passe</string>
</resources>

View File

@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
<string name="app_revision_url">https://github.com/TheLastProject/Catima/releases</string>
<string name="storeName">Nama</string>
<string name="note">Keterangan</string>
<string name="delete">Hapus</string>
<string name="edit">Ubah</string>
<string name="save">Simpan</string>
<string name="deleteTitle">Hapus kartu</string>
<string name="cardId">Kartu ID</string>
<string name="barcodeType">Tipe barcode</string>
<string name="star">Tambahkan ke favorit</string>
<string name="unstar">Hapus dari favorit</string>
<string name="action_add">Tambah</string>
<string name="action_search">Cari</string>
<string name="sort_by_name">Nama</string>
<string name="sort_by_balance">Saldo</string>
<string name="sort_by">Sortir dengan</string>
<string name="sort">Sortir</string>
<string name="credits">Kredit</string>
<string name="license">Lisensi</string>
<string name="settings">Pengaturan</string>
<string name="settings_system_theme">Sistem</string>
<string name="selectBarcodeTitle">Pilih Barcode</string>
<string name="deleteConfirmation">Hapus kartu ini secara permanen?</string>
<string name="ok">OK</string>
<string name="share">Bagikan</string>
<string name="editCardTitle">Ubah Kartu</string>
<string name="addCardTitle">Tambah Kartu</string>
<string name="scanCardBarcode">Pindai Kartu Barcode</string>
<string name="barcodeNoBarcode">Kartu ini tidak memiliki barcode</string>
<string name="cancel">Batalkan</string>
<string name="importExport">Import/Ekspor</string>
<string name="settings_category_title_ui">Tampilan Pengguna</string>
<string name="settings_theme">Tema</string>
<string name="all">Semua</string>
<string name="leaveWithoutSaveTitle">Keluar</string>
<string name="card">Kartu</string>
<string name="barcode">Barcode</string>
<string name="chooseExpiryDate">Pilih masa berlaku</string>
<string name="noBarcodeFound">Barcode tidak ditemukan</string>
<string name="errorReadingImage">TIdak dapat membaca gambar</string>
<string name="balance">Saldo</string>
<string name="currency">Mata uang</string>
<string name="chooseImportType">Impor data dari?</string>
<string name="accept">Terima</string>
<string name="importCatima">Impor dari Catima</string>
<string name="importFidme">Impor dari FidMe</string>
<string name="barcodeId">Nilai barcode</string>
<string name="sameAsCardId">Sama denga kartu ID</string>
<string name="setBarcodeId">Tentukan nilai barcode</string>
<string name="photos">Foto</string>
<string name="setFrontImage">Atur gambar bagian depan</string>
<string name="report_error">Lapor Kesalahan</string>
<string name="rate_this_app">Beri nilai pada aplikasi ini</string>
<string name="sort_by_expiry">Masa berlaku</string>
<string name="sort_by_most_recently_used">Paling banyak digunakan</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_pink_theme">Merah Muda</string>
<string name="settings_blue_theme">Biru</string>
<string name="settings_green_theme">Hijau</string>
<string name="settings_sky_blue_theme">Biru Langit</string>
<string name="settings_grey_theme">Abu-abu</string>
<string name="settings_brown_theme">Cokelat</string>
<string name="settings_violet_theme">Ungu</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_theme_color">Warna tema</string>
<string name="settings_system_locale">Sistem</string>
<string name="settings_locale">Bahasa</string>
<string name="turn_flashlight_on">Hidupkan lampu flash</string>
<string name="turn_flashlight_off">Matikan lampu flash</string>
<string name="exportPasswordHint">Masukan kata sandi</string>
<string name="yes">Ya</string>
<string name="no">Tidak</string>
<string name="takePhoto">Ambil foto</string>
<string name="removeImage">Hapus gambar</string>
<string name="setBackImage">Atur gambar bagian belakang</string>
<string name="intent_import_card_from_url_share_multiple_text">Saya ingin berbagi kartu dengan anda</string>
<string name="noGiftCards">Klik tanda + tombol tambah untuk menambahkan kartu, atau mengimpor beberapa kartu melalui menu ⋮ terlebih dahulu.</string>
<string name="noMatchingGiftCards">Tidak menemukan apapun. Coba untuk mengubah pencarian anda.</string>
<string name="noBarcode">Bukan barcode</string>
<string name="confirm">Konfirmasi</string>
<string name="copy_to_clipboard">Salin ID</string>
<string name="sendLabel">Kirim…</string>
<string name="noCardsMessage">Tambah kartu terlebih dahulu</string>
<string name="noStoreError">Nama masih kosong</string>
<string name="noCardIdError">Kartu ID masih kosong</string>
<string name="noCardExistsError">Tidak dapat menemukan kartu</string>
<string name="failedParsingImportUriError">Tidak dapat menguraikan alamat impor situs web</string>
<string name="exportName">Ekspor</string>
<string name="importSuccessfulTitle">Sudah diimpor</string>
<string name="importFailedTitle">Impor gagal</string>
<string name="importFailed">Tidak dapat mengimpor kartu</string>
<string name="exportSuccessfulTitle">Sudah diekspor</string>
<string name="exportFailedTitle">Ekspor gagal</string>
<string name="exportFailed">Tidak dapat mengekspor kartu</string>
<string name="importing">Mengimpor…</string>
<string name="exporting">Mengekspor…</string>
<string name="noExternalStoragePermissionError">Berikan izin penyimpanan eksternal untuk mengimpor atau mengekspor kartu terlebih dahulu</string>
<string name="exportOptionExplanation">The data will be written to a location of your choice.</string>
<string name="importOptionFilesystemTitle">Impor dari sistem</string>
<string name="importOptionFilesystemExplanation">Pilih file dari sistem</string>
<string name="importOptionFilesystemButton">Dari sistem</string>
<string name="importOptionApplicationTitle">Gunakan aplikasi lain</string>
<string name="importOptionApplicationExplanation">Gunakan aplikasi lain atau pengelola file favorit anda untuk membuka file.</string>
<string name="importOptionApplicationButton">Gunakan aplikasi lain</string>
<string name="about">Tentang</string>
<string name="app_copyright_fmt">Hak Cipta © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="app_copyright_old">Berdasarkan Loyalty Card Keychain hak cipta © 20162020 Branden Archer</string>
<string name="app_license">Perangkat lunak bebas copyleft, berlisensi GPLv3+</string>
<string name="about_title_fmt">Tentang <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versi: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Info Revisi: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries">Pustaka pihak ketiga gratis: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources">Sumber daya pihak ketiga gratis: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="enterBarcodeInstructions">Masukkan ID kartu, dan pilih jenis barcodenya di bawah atau \"Kartu ini tidak memiliki barcode\".</string>
<string name="copy_to_clipboard_toast">ID kartu telah disalin</string>
<string name="thumbnailDescription">Gambar tampilan untuk kartu</string>
<string name="starImage">Favorit</string>
<string name="settings_light_theme">Terang</string>
<string name="settings_dark_theme">Gelap</string>
<string name="settings_max_font_size_scale">Ukuran maksimal huruf</string>
<string name="settings_display_barcode_max_brightness">Terangkan tampilan barcode</string>
<string name="settings_lock_barcode_orientation">Kunci orientasi barcode</string>
<string name="settings_keep_screen_on">Biarkan layar menyala</string>
<string name="settings_disable_lockscreen_while_viewing_card">Mencegah layar menyala</string>
<string name="intent_import_card_from_url_share_text">Saya ingin berbagi kartu dengan anda</string>
<string name="importSuccessful">Data kartu terimpor</string>
<string name="exportSuccessful">Data kartu terekspor</string>
<string name="enter_group_name">Masukan nama grup</string>
<string name="groups">Grup</string>
<string name="noGroups">Klik pada tombol tambah + untuk menambahkan grup atau kategori terlebih dahulu.</string>
<string name="noGroupCards">Grup ini tidak memilik kartu</string>
<string name="deleteConfirmationGroup">Hapus grup?</string>
<string name="failedOpeningFileManager">Instal aplikasi pengelola file terlebih dahulu.</string>
<string name="moveUp">Pindah ke atas</string>
<string name="moveDown">Pindah ke bawah</string>
<string name="leaveWithoutSaveConfirmation">Keluar tanpa menyimpan?</string>
<string name="addManually">Masukan ID kartu</string>
<string name="addFromImage">Pilih gambar dari galeri</string>
<string name="groupsList">Grup: <xliff:g>%s</xliff:g></string>
<string name="expiryStateSentence">Masa ber: <xliff:g>%s</xliff:g></string>
<string name="expiryStateSentenceExpired">Kadaluwarsa: <xliff:g>%s</xliff:g></string>
<string name="balanceSentence">Saldo: <xliff:g>%s</xliff:g></string>
<string name="balancePoints"><xliff:g>%s</xliff:g> poin</string>
<string name="editBarcode">Ubah barcode</string>
<string name="expiryDate">Tanggal masa berlaku</string>
<string name="never">Tidak pernah</string>
<string name="moveBarcodeToTopOfScreen">Pindah barcode ke bagian paling depan</string>
<string name="moveBarcodeToCenterOfScreen">Pusatkan barcode pada layar</string>
<string name="points">Poin</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> sepertinya bukan saldo yang valid.</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="privacy_policy">Kebijakan Privasi</string>
<string name="privacy_policy_popup_text">Pemberitahuan kebijakan privasi (diperlukan oleh beberapa toko aplikasi): TIDAK ADA DATA YANG DIKUMPULKAN SAMA SEKALI, yang dapat dikonfirmasi oleh siapa pun karena aplikasi kami adalah perangkat lunak gratis.</string>
<string name="importCatimaMessage">Pilih ekspor <i>catima.zip</i> Anda dari Catima untuk diimpor. Buat dari menu Impor/Ekspor aplikasi Catima lain dengan menekan Ekspor di sana terlebih dahulu.</string>
<string name="importFidmeMessage">Pilih ekspor <i>fidme-export-request-xxxxxx.zip</i> Anda dari FidMe untuk diimpor, dan pilih jenis barcode secara manual setelahnya. Buat dari profil FidMe Anda dengan memilih Perlindungan Data lalu tekan Ekstrak data saya terlebih dahulu.</string>
<string name="importLoyaltyCardKeychain">Impor dari Loyalty Card Keychain</string>
<string name="importLoyaltyCardKeychainMessage">Pilih ekspor <i>LoyaltyCardKeychain.csv</i> Anda dari Loyalty Card Keychain untuk diimpor. Buat dari menu Import/Export di Loyalty Card Keychain dengan menekan Export terlebih dahulu.</string>
<string name="importStocard">Impor dari Stocard</string>
<string name="importStocardMessage">Pilih ekspor <i>***-sync.zip</i> Anda dari Stocard untuk diimpor. Dapatkan dengan mengirim email ke support@stocardapp.com untuk meminta ekspor data Anda.</string>
<string name="importVoucherVault">Impor dari Voucher Vault</string>
<string name="importVoucherVaultMessage">Pilih ekspor <i>vouchervault.json</i> Anda dari Vault Voucher untuk diimpor. Buat dengan menekan Ekspor di Vault Voucher terlebih dahulu.</string>
<string name="unsupportedBarcodeType">Jenis barcode ini belum dapat ditampilkan. Ini mungkin didukung di versi aplikasi yang lebih baru.</string>
<string name="wrongValueForBarcodeType">Nilai tidak berlaku untuk jenis barcode yang dipilih</string>
<string name="copy_to_clipboard_multiple_toast">ID kartu telah disalin</string>
<string name="frontImageDescription">Gambar depan kartu</string>
<string name="backImageDescription">Gambar belakang kartu</string>
<string name="updateBarcodeQuestionTitle">Perbarui barcode?</string>
<string name="updateBarcodeQuestionText">Anda mengubah ID kartu. Apakah Anda juga ingin memperbarui barcode untuk menggunakan nilai yang sama?</string>
<string name="passwordRequired">Silahkan masukan kata sandi</string>
<string name="exportPassword">Tetapkan kata sandi untuk melindungi ekspor anda (opsional)</string>
<string name="failedGeneratingShareURL">Tidak dapat membuat alamat berbagi. Mohon laporkan ini.</string>
<string name="app_contributors">Pengembangan dibantu oleh: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="toggleMoreInfo">Tampilkan info selengkapnya</string>
<string name="swipeToSwitchImages">Geser atau tekan yang lama untuk mengganti gambar</string>
<string name="reverse">Ubah urutan</string>
<string name="version_history">Riwayat Versi</string>
<string name="help_translate_this_app">Bantu terjemahkan aplikasi ini</string>
<string name="source_repository">Sumber Repositori</string>
<string name="on_github">di GitHub</string>
<string name="and_data_usage">dan penggunaan data</string>
<string name="on_google_play">di Google Play</string>
<string name="lockScreen">Blokir rotasi</string>
<string name="unlockScreen">Buka blokir rotasi</string>
<string name="cardShortcut">Pintasan kartu</string>
<string name="card_ids_copied">ID kartu yang tersalin</string>
<string name="barcodeImageDescriptionWithType">Gambar dari jenis barcode <xliff:g>%s</xliff:g></string>
<string name="importExportHelp">Mencadangkan kartu memungkinkan anda memindahkannya ke perangkat lain.</string>
</resources>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="action_add">Bæta</string>
<string name="noBarcode">Nei strikamerkið</string>
<string name="action_search">Leita að</string>
<string name="delete">Eyða</string>
<string name="unlockScreen">Opna Snúningur</string>
<string name="noGiftCards">Smelltu á + plús takka til að bæta kort, eða að flytja inn sumir frá ⋮ matseðill fyrst.</string>
<string name="note">Athugið</string>
<string name="barcodeType">Strikamerkið tegund</string>
<string name="cancel">Hætta</string>
<string name="noMatchingGiftCards">Vissi ekki að finna neitt. Reyna að breyta leita.</string>
<string name="storeName">Nafnið</string>
<string name="barcodeNoBarcode">Þetta kort hefur ekki strikamerkið</string>
<string name="star">Bæta við eftirlæti</string>
<string name="unstar">Fjarlægja frá eftirlæti</string>
<string name="save">Sparaðu</string>
<string name="edit">Breyta</string>
<string name="confirm">Staðfesta</string>
<string name="lockScreen">Blokk Snúningur</string>
<string name="ok">OK</string>
<string name="sendLabel">Sendu…</string>
<string name="deleteConfirmation">Eyða þetta kort til frambúðar\?</string>
<string name="share">Deila</string>
<string name="editCardTitle">Breyta Kort</string>
<string name="addCardTitle">Bæta Kort</string>
<string name="scanCardBarcode">Skanna Kort Strikamerkið</string>
</resources>

View File

@@ -47,7 +47,7 @@
<string name="importOptionApplicationExplanation">Usa qualsiasi app o il tuo gestore di file preferito per aprire un file.</string>
<string name="importOptionApplicationButton">Usa unaltra app</string>
<string name="about">Informazioni</string>
<string name="app_license">Software libero con copyleft, licenza GPLv3+.</string>
<string name="app_license">Software libero con copyleft, licenza GPLv3+</string>
<string name="about_title_fmt">Informazioni su <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versione: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Informazioni sulla revisione: <xliff:g id="app_revision_url"> %s </xliff:g></string>
@@ -67,7 +67,7 @@
<string name="exportSuccessful">Dati della carta importati</string>
<string name="importSuccessful">Dati della carta importati</string>
<string name="app_copyright_old">Basato su Loyalty Card Keychain
\ncopyright © 20162020 Branden Archer.</string>
\ncopyright © 20162020 Branden Archer</string>
<string name="exportOptionExplanation">I dati verranno scritti in una posizione a tua scelta.</string>
<string name="barcodeType">Tipo di codice a barre</string>
<string name="unstar">Rimuovi dai preferiti</string>
@@ -116,16 +116,16 @@
\nNESSUN DATO VIENE RACCOLTO, cosa che chiunque può confermare dato che la nostra applicazione è un software libero.</string>
<string name="privacy_policy">Informativa sulla riservatezza</string>
<string name="importVoucherVaultMessage">Seleziona la tua esportazione <i>vouchervault.json</i> da Voucher Vault da importare.
\nOppure crealo premendo prima Esporta in Voucher Vault.</string>
\nCrealo premendo prima Esporta in Voucher Vault.</string>
<string name="importVoucherVault">Importa da Voucher Vault</string>
<string name="importLoyaltyCardKeychainMessage">Seleziona la tua esportazione <i>LoyaltyCardKeychain.csv</i> da Loyalty Card Keychain per importarla.
\nOppure createlo dal menù Importazione/Esportazione in Loyalty Card Keychain premendo prima su Esporta.</string>
\nCreatelo dal menù Importazione/Esportazione in Loyalty Card Keychain premendo prima su Esporta.</string>
<string name="importLoyaltyCardKeychain">Importa da Loyalty Card Keychain</string>
<string name="importFidmeMessage">Seleziona la tua esportazione <i>fidme-export-request-xxxxxx.zip</i> da FidMe per importare, e seleziona i tipi di codice a barre manualmente dopo.
\nOppure crearlo dal tuo profilo FidMe scegliendo Protezione Dati e poi premendo Estrai i miei dati prima.</string>
\nCrearlo dal tuo profilo FidMe scegliendo Protezione Dati e poi premendo Estrai i miei dati prima.</string>
<string name="importFidme">Importa da FidMe</string>
<string name="importCatimaMessage">Seleziona la tua esportazione <i>catima.zip</i> da Catima per importarla.
\nOppure crealo dal menù Importazione/Esportazione di un\'altra applicazione Catima premendo prima Esporta.</string>
\nCrealo dal menù Importazione/Esportazione di un\'altra applicazione Catima premendo prima Esporta.</string>
<string name="importCatima">Importa da Catima</string>
<string name="setBarcodeId">Imposta il valore del codice a barre</string>
<string name="sameAsCardId">Uguale all\'ID della carta</string>
@@ -138,7 +138,7 @@
<string name="wrongValueForBarcodeType">Il valore non è valido per il tipo di codice a barre selezionato</string>
<string name="app_resources">Risorse libre di terze parti: <xliff:g id="app_resources_list"> %s </xliff:g></string>
<string name="app_libraries">Librerie libre di terze parti: <xliff:g id="app_libraries_list"> %s </xliff:g></string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="intent_import_card_from_url_share_multiple_text">Voglio condividere alcune carte con te</string>
<string name="copy_to_clipboard_multiple_toast">Numeri delle carte copiati negli appunti</string>
<string name="card_ids_copied">Numero/i della carta copiato/i</string>
@@ -155,7 +155,7 @@
<string name="frontImageDescription">Immagine frontale della carta</string>
<string name="passwordRequired">Si prega di inserire la password</string>
<string name="importStocardMessage">Seleziona la tua esportazione <i>***-sync.zip</i> da Stocard per importare.
\nOppure ottenerlo inviando un\'e-mail a support@stocardapp.com chiedendo un\'esportazione dei tuoi dati.</string>
\nOttienilo inviando un\'e-mail a support@stocardapp.com chiedendo un\'esportazione dei tuoi dati.</string>
<string name="importStocard">Importa da Stocard</string>
<string name="turn_flashlight_off">Spegni la torcia</string>
<string name="turn_flashlight_on">Accendi la torcia</string>
@@ -198,4 +198,16 @@
<string name="sort_by_most_recently_used">Usate più di recente</string>
<string name="sort_by_name">Nome</string>
<string name="sort">Ordina</string>
<string name="license">Licenza</string>
<string name="source_repository">Repository fonti</string>
<string name="on_github">su GitHub</string>
<string name="exportPasswordHint">Inserisci la password</string>
<string name="on_google_play">su Google Play</string>
<string name="exportPassword">Imposta una password per proteggere la tua esportazione (opzionale)</string>
<string name="version_history">Cronologia delle versioni</string>
<string name="credits">Crediti</string>
<string name="help_translate_this_app">Aiuta a tradurre questa app</string>
<string name="and_data_usage">e utilizzo dei dati</string>
<string name="rate_this_app">Valuta questa applicazione</string>
<string name="report_error">Segnala un errore</string>
</resources>

View File

@@ -76,10 +76,10 @@
<string name="app_revision_fmt">Revision Info: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
<string name="about_title_fmt">About <xliff:g id="app_name">%s</xliff:g></string>
<string name="app_license">Copylefted libre software, licensed GPLv3+.</string>
<string name="app_license">Copylefted libre software, licensed GPLv3+</string>
<string name="app_copyright_old">Based on Loyalty Card Keychain
\ncopyright © 20162020 Branden Archer.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="app_resources">Libre third-party resources: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="about">Catimaについて</string>
<string name="importOptionApplicationButton">外部のアプリを使う</string>
@@ -95,7 +95,7 @@
<string name="exportFailed">カードをエクスポートできませんでした</string>
<string name="exportFailedTitle">エクスポートに失敗しました</string>
<string name="exportSuccessfulTitle">エクスポートしました</string>
<string name="sameAsCardId">カードの表記と同一</string>
<string name="sameAsCardId">カード番号に合わせる</string>
<string name="barcodeId">バーコード番号</string>
<string name="importVoucherVaultMessage">Voucher Vaultでエクスポートした <i>vouchervault.json</i>ファイルを選択してください。
\nファイルがない場合、Voucher Vaultでファイルをエクスポートしてください。</string>
@@ -152,10 +152,10 @@
<string name="takePhoto">写真を撮影する</string>
<string name="removeImage">画像を削除</string>
<string name="setBackImage">裏面の画像を設定</string>
<string name="setFrontImage">面の画像を設定</string>
<string name="setFrontImage">オモテ面の画像を設定</string>
<string name="photos">フォト</string>
<string name="backImageDescription">裏面</string>
<string name="frontImageDescription"></string>
<string name="backImageDescription">カードの裏面</string>
<string name="frontImageDescription">カードのオモテ</string>
<string name="importStocardMessage">Stocardでエクスポートした<i>***-sync.zip</i>ファイルを選択してください。
\nファイルがない場合、e-mailing support@stocardapp.comにデータのエクスポートを要求してください。</string>
<string name="importStocard">Stocardからインポート</string>
@@ -183,8 +183,27 @@
<string name="settings_pink_theme">Pink</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">テーマカラー</string>
<string name="settings_system_locale">システム</string>
<string name="settings_system_locale">システムに従う</string>
<string name="settings_locale">言語</string>
<string name="noGroupCards">このグループにはカードがありません</string>
<string name="swipeToSwitchImages">画像を切り替えるには長押し、またはスワイプ</string>
<string name="sort_by">並び替え</string>
<string name="sort_by_balance">残高</string>
<string name="sort_by_expiry">期限</string>
<string name="sort_by_most_recently_used">最近使用したカード</string>
<string name="sort_by_name">名前</string>
<string name="sort">並び替え</string>
<string name="rate_this_app">このアプリを評価する</string>
<string name="on_github">GitHub</string>
<string name="source_repository">ソースリポジトリ</string>
<string name="exportPassword">パスワードを設定してエクスポートしたファイルを保護する(任意)</string>
<string name="exportPasswordHint">パスワードを入力してください</string>
<string name="version_history">更新履歴</string>
<string name="credits">貢献者</string>
<string name="help_translate_this_app">このアプリの翻訳を手伝う</string>
<string name="license">ライセンス</string>
<string name="on_google_play">Google Play</string>
<string name="report_error">エラーを報告する</string>
<string name="reverse">逆順</string>
<string name="and_data_usage">and data usage</string>
</resources>

View File

@@ -25,7 +25,7 @@
<string name="exporting">Eksportuoja…</string>
<string name="noExternalStoragePermissionError">Pirmiausia suteikite išorinės saugyklos leidimą, kad galėtumėte importuoti arba eksportuoti korteles</string>
<string name="about">Apie</string>
<string name="app_license">Copylefted libre programinė įranga, licencijuota GPLv3+.</string>
<string name="app_license">Copylefted libre programinė įranga, licencijuota GPLv3+</string>
<string name="about_title_fmt">Apie <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versija: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Revizijos info: <xliff:g id="app_revision_url">%s</xliff:g></string>
@@ -45,10 +45,10 @@
<string name="action_search">Ieškoti</string>
<string name="cardShortcut">Kortelės sparčioji nuoroda</string>
<string name="importVoucherVaultMessage">Pasirinkite savo <i>vouchervault.json</i> eksportą iš Voucher Vault, kurį norite importuoti.
\nArba sukurkite jį pirmiausia paspausdami Eksportuoti Voucher Vault.</string>
\nSukurkite jį pirmiausia paspausdami Eksportuoti Voucher Vault.</string>
<string name="importVoucherVault">Importuoti iš Voucher Vault</string>
<string name="importLoyaltyCardKeychainMessage">Pasirinkite savo <i> LoyaltyCardKeychain.csv</i> eksportą iš Loyalty Card Keychain, kurį norite importuoti.
\nArba sukurkite jį iš Loyalty Card Keychain meniu Importas/Eksportas, pirmiausia paspausdami Eksportuoti.</string>
\nSukurkite jį iš Loyalty Card Keychain meniu Importavimas/Eksportavimas, pirmiausia paspausdami Eksportuoti.</string>
<string name="importLoyaltyCardKeychain">Importuoti iš Loyalty Card Keychain</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="parsingBalanceFailed">Panašu, kad <xliff:g> %s </xliff:g> reikšmė nėra tinkama.</string>
@@ -79,13 +79,13 @@
<string name="sameAsCardId">Tokia pat kaip kortelės ID</string>
<string name="barcodeId">Brūkšninio kodo reikšmė</string>
<string name="importStocardMessage">Pasirinkite <i>***-sync.zip</i> eksportą iš Stocard, kad galėtumėte importuoti.
\nArba gaukite susisiekę el. paštu support@stocardapp.com, prašydami eksportuoti jūsų duomenis.</string>
\nGaukite susisiekę el. paštu support@stocardapp.com, prašydami eksportuoti jūsų duomenis.</string>
<string name="importStocard">Importuoti iš Stocard</string>
<string name="importFidmeMessage">Pasirinkite <i>fidme-export-request-xxxxxx.zip</i> eksportą iš FidMe, kurį norite importuoti, ir po to brūkšninių kodų tipus pasirinkite rankiniu būdu.
\nArba sukurkite jį iš savo FidMe profilio, pasirinkę Duomenų apsauga ir pirmiausia paspaudę Išgauti mano duomenis.</string>
\nSukurkite jį iš savo FidMe profilio, pasirinkę Duomenų apsauga ir pirmiausia paspaudę Išgauti mano duomenis.</string>
<string name="importFidme">Importuoti iš FidMe</string>
<string name="importCatimaMessage">Norėdami importuoti, pasirinkite savo <i> catima.zip </i> eksportą iš Catima.
\nArba sukurkite ją iš kitos Catima programos importavimo / eksportavimo meniu, pirmiausia paspausdami Eksportuoti ten.</string>
<string name="importCatimaMessage">Norėdami importuoti, pasirinkite savo <i> catima.zip </i> eksportavimą iš Catima.
\nSukurkite ją iš kitos Catima programos importavimo / eksportavimo meniu, pirmiausia ten paspausdami Eksportuoti.</string>
<string name="importCatima">Importuoti iš Catima</string>
<string name="accept">Priimti</string>
<string name="privacy_policy_popup_text">Privatumo politikos pranešimas (kurio reikalaujama kai kuriose programėlių parduotuvėse):
@@ -145,8 +145,8 @@
<string name="app_resources">Libre trečiųjų šalių ištekliai: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Libre trečiųjų šalių bibliotekos: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_copyright_old">Paremta Loyalty Card Keychain
\nautorinės teisės © 20162020 Branden Archer.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Autorinės teisės © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
\nautorinės teisės © 20162020 Branden Archer</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Autorinės teisės © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="importOptionApplicationButton">Naudoti kitą programą</string>
<string name="importOptionApplicationExplanation">Norėdami atidaryti failą, naudokite bet kurią programą arba mėgstamą failų tvarkyklę.</string>
<string name="importOptionApplicationTitle">Naudoti kitą programą</string>
@@ -202,4 +202,16 @@
<string name="sort_by_most_recently_used">Vėliausiai naudota</string>
<string name="sort_by_name">Pavadinimas</string>
<string name="sort">Rikiuoti</string>
<string name="credits">Padėkos</string>
<string name="source_repository">Šaltinio repozitorija</string>
<string name="and_data_usage">ir duomenų naudojimas</string>
<string name="rate_this_app">Įvertinkite šią programėlę</string>
<string name="version_history">Versijų istorija</string>
<string name="license">Licencija</string>
<string name="on_github">GitHub</string>
<string name="on_google_play">Google Play</string>
<string name="help_translate_this_app">Padėkite išversti šią programėlę</string>
<string name="report_error">Pranešti apie klaidą</string>
<string name="exportPasswordHint">Įveskite slaptažodį</string>
<string name="exportPassword">Nustatykite slaptažodį, kad apsaugotumėte eksportavimą (neprivaloma)</string>
</resources>

View File

@@ -11,7 +11,7 @@
<string name="edit">Rediger</string>
<string name="delete">Slett</string>
<string name="confirm">Bekreft</string>
<string name="lockScreen">Ingen rotering</string>
<string name="lockScreen">Skru av rotering</string>
<string name="unlockScreen">Skru på rotering</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Kopier ID til utklippstavle</string>
@@ -24,7 +24,7 @@
<string name="noStoreError">Navn ikke angitt</string>
<string name="noCardIdError">Ingen kort-ID innskrevet</string>
<string name="noCardExistsError">Kunne ikke finne kort</string>
<string name="importExport">Import/eksport</string>
<string name="importExport">Importer/eksporter</string>
<string name="exportName">Eksporter</string>
<string name="importExportHelp">Sikkerhetskopiering av kort lar deg flytte dem til en annen enhet.</string>
<string name="importSuccessfulTitle">Importert</string>
@@ -40,11 +40,11 @@
<string name="importOptionFilesystemTitle">Importer fra filsystem</string>
<string name="importOptionFilesystemExplanation">Velg spesifikk fil fra filsystemet.</string>
<string name="importOptionFilesystemButton">Fra filsystem</string>
<string name="importOptionApplicationTitle">Bruk et annet program</string>
<string name="importOptionApplicationExplanation">Bruk hvilket som helst program, eller din favoritt-filutforsker for å åpne en fil.</string>
<string name="importOptionApplicationButton">Bruk et annet program</string>
<string name="importOptionApplicationTitle">Bruk en annen app</string>
<string name="importOptionApplicationExplanation">Bruk en hvilken som helst app, eller din favoritt-filutforsker for å åpne en fil.</string>
<string name="importOptionApplicationButton">Bruk en annen app</string>
<string name="about">Om</string>
<string name="app_license">Gemenhetslig fri programvare, lisensiert GPLv3+.</string>
<string name="app_license">Gemenhetslig fri programvare, lisensiert GPLv3+</string>
<string name="about_title_fmt">Om <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versjon: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Utgivelsesinfo: <xliff:g id="app_revision_url">%s</xliff:g></string>
@@ -64,7 +64,7 @@
<string name="settings_system_theme">System</string>
<string name="settings_theme">Drakt</string>
<string name="app_copyright_old">Basert på Kundekortknippe
\nopphavsrett 20162020 Branden Archer.</string>
\nopphavsrett 20162020 Branden Archer</string>
<string name="failedParsingImportUriError">Kunne ikke tolke importerings-URI</string>
<string name="share">Del</string>
<string name="barcodeNoBarcode">Dette kortet har ingen strekkode</string>
@@ -74,13 +74,13 @@
<string name="unstar">Fjern fra favoritter</string>
<string name="star">Legg til i favoritter</string>
<string name="noGroups">Klikk på «+»- (pluss)-tegnet for å legge til grupper for kategorisering først.</string>
<string name="deleteConfirmationGroup">Slett gruppe\?</string>
<string name="deleteConfirmationGroup">Slett gruppe?</string>
<string name="all">Alle</string>
<string name="groups">Grupper</string>
<string name="enter_group_name">Skriv inn gruppenavn</string>
<string name="noBarcode">Ingen strekkode</string>
<string name="failedOpeningFileManager">Installer en filbehandler først.</string>
<string name="leaveWithoutSaveConfirmation">Forlat uten å lagre\?</string>
<string name="leaveWithoutSaveConfirmation">Forlat uten å lagre?</string>
<string name="leaveWithoutSaveTitle">Avslutt</string>
<string name="addManually">Skriv inn kort-ID manuelt</string>
<string name="moveDown">Flytt nedover</string>
@@ -106,13 +106,13 @@
<string name="balance">Saldo</string>
<string name="balancePoints"><xliff:g>%s</xliff:g> poeng</string>
<string name="balanceSentence">Saldo: <xliff:g>%s</xliff:g></string>
<string name="chooseImportType">Importer data fra\?</string>
<string name="chooseImportType">Importer data fra?</string>
<string name="app_loyalty_card_keychain">Kundekortknippe</string>
<string name="settings_disable_lockscreen_while_viewing_card">Forhindre skjermlås</string>
<string name="settings_keep_screen_on">Behold skjerm påslått</string>
<string name="privacy_policy_popup_text">Personvernspraksis-notis (påkrevd av noen programbutikker):
\n
\nINGEN DATA SAMLES INN, noe alle kan bekreftes siden programmet vårt er fri programvare.</string>
\nINGEN DATA SAMLES INN I DET HELE TATT, noe alle kan bekreftes siden programmet vårt er fri programvare.</string>
<string name="accept">Godta</string>
<string name="privacy_policy">Personvernspraksis</string>
<string name="importFidme">Importer fra FidMe</string>
@@ -124,16 +124,14 @@
<string name="setBarcodeId">Sett strekkodeverdi</string>
<string name="sameAsCardId">Samme som kort-ID</string>
<string name="barcodeId">Strekkodeverdi</string>
<string name="importVoucherVaultMessage">Finn en fil som antagelig heter <i>voucher.vault.json</i> å importere.
\nEller opprett den ved å trykke «Eksport» i Voucher Vault først.</string>
<string name="importVoucherVaultMessage">Velg din <i>vouchervault.json</i>-eksport fra Voucher Vault å importere.
\nOpprett den ved å trykke «Eksport» i Voucher Vault først.</string>
<string name="importVoucherVault">Importer fra Voucher Vault</string>
<string name="importLoyaltyCardKeychainMessage">Velg din <i>LoyaltyCardKeychain.csv - </i> eksporter fra kundekort Nøkkelring til import.
\nEller lage det fra Import/Eksport-menyen i lojalitetskort Nøkkelringen ved å trykke Eksport det første.</string>
<string name="importLoyaltyCardKeychainMessage">Velg din <i>LoyaltyCardKeychain.csv</i>-eksport fra Kundekortknippe å importere.
\nOpprett den i «Import/Eksport»-menyen i Kundekortknippe ved å trykke «Eksporter» der først.</string>
<string name="importLoyaltyCardKeychain">Importer fra Kundekortknippe</string>
<string name="importFidmeMessage">Velg din <i>fidme-eksport-be-xxxxxx.zip</i> eksporter fra FidMe til å importere, og velg strekkode typer manuelt etterpå.
\nEller lage den fra FidMe profil ved å velge Beskyttelse av Data og deretter trykke Trekke ut dataene mine første.</string>
<string name="importCatimaMessage">Finn en fil som antagelig heter <i>Catima.csv</i> å importere.
\nEller opprett den i Import/eksport-menyen i et annet Catima-program ved å trykke «Eksporter» der først.</string>
<string name="importFidmeMessage">Velg din <i>fidme.export-request-xxxxx.zip</i>-eksport fra FidMe å importere, for så å velge strekkodetypene manuelt etterpå-
\nOpprett den i din FidMe-profil ved å velge «Databeskyttelse», for så å trykke «Pakk ut dataen min» først.</string>
<string name="settings_max_font_size_scale">Maks. skriftstørrelse</string>
<string name="wrongValueForBarcodeType">Verdien er ikke gyldig for valgt strekkodetype</string>
<string name="intent_import_card_from_url_share_multiple_text">Jeg vil dele noen kort med deg</string>
@@ -141,11 +139,11 @@
<string name="app_resources">Frie tredjepartsressurser: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Frie tredjepartsbibliotek: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="card_ids_copied">Kopierte kort-ID(er)</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Opphavsrett © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="updateBarcodeQuestionText">Du har endret kortets ID. Ønsker du å også oppdatere strekkoden til samme verdi\?</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Opphavsrett © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="updateBarcodeQuestionText">Du har endret kortets ID. Ønsker du å også oppdatere strekkoden til samme verdi?</string>
<string name="no">Nei</string>
<string name="yes">Ja</string>
<string name="updateBarcodeQuestionTitle">Oppdater strekkodeverdi\?</string>
<string name="updateBarcodeQuestionTitle">Oppdater strekkodeverdi?</string>
<string name="takePhoto">Ta et bilde</string>
<string name="removeImage">Fjern bilde</string>
<string name="setBackImage">Sett bakside</string>
@@ -154,7 +152,7 @@
<string name="backImageDescription">Kortets bakside</string>
<string name="frontImageDescription">Kortets forside</string>
<string name="importStocardMessage">Velg din <i>***-sync.zip</i>-eksport fra Stocard å importere.
\nEller få den ved å sende e-post til support@stocardapp.com der du etterspør eksport av dataen din.</string>
\nSkaff den ved å sende e-post til support@stocardapp.com der du etterspør eksport av dataen din.</string>
<string name="passwordRequired">Skriv inn passordet</string>
<string name="importStocard">Importer fra Stocard</string>
<string name="failedGeneratingShareURL">Klarte ikke å lage delbar nettadresse. Rapporter denne feilen.</string>
@@ -162,10 +160,10 @@
<item quantity="one"><xliff:g>%d</xliff:g> kort valgt</item>
<item quantity="other"><xliff:g>%d</xliff:g> korten valgt</item>
</plurals>
<string name="deleteConfirmation">Slett dette kortet for godt\?</string>
<string name="deleteConfirmation">Slett dette kortet for godt?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Slett dette kortet for godt\?</item>
<item quantity="other">Slett disse <xliff:g xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">%s</xliff:g> kortene for godt\?</item>
<item quantity="other">Slett disse <xliff:g>%d</xliff:g> kortene for godt\?</item>
</plurals>
<string name="turn_flashlight_on">Skru på lommelykten</string>
<string name="turn_flashlight_off">Skru av lommelykten</string>
@@ -191,4 +189,25 @@
<string name="toggleMoreInfo">Veksle visning av mer info</string>
<string name="barcodeImageDescriptionWithType">Bilde av kortstrekkode av typen <xliff:g>%s</xliff:g></string>
<string name="swipeToSwitchImages">Dra eller hold lenge for å bygge bilder</string>
<string name="sort_by">Sorter etter</string>
<string name="reverse">Vend</string>
<string name="sort_by_balance">Saldo</string>
<string name="sort_by_expiry">Utløp</string>
<string name="sort_by_most_recently_used">Nyligst brukt</string>
<string name="sort_by_name">Navn</string>
<string name="sort">Sorter</string>
<string name="help_translate_this_app">Hjelp med å oversette denne appen</string>
<string name="license">Lisens</string>
<string name="version_history">Versjonshistorikk</string>
<string name="importCatimaMessage">Velg din <i>catima.zip</i>-eksport fra Catima å importere.
\nOpprett den fra «Importer/Eksporter»-menyen i en annen Catima-app ved å trykke på «Eksporter» der først</string>
<string name="source_repository">Kildekode</string>
<string name="on_github">på GitHub</string>
<string name="and_data_usage">og bruk av data</string>
<string name="rate_this_app">Vurder denne appen</string>
<string name="on_google_play">på Google Play</string>
<string name="report_error">Rapporter feil</string>
<string name="credits">Bidragsytere</string>
<string name="exportPassword">Sett et passord for å beskytte eksporten din (valgfritt)</string>
<string name="exportPasswordHint">Skriv inn passord</string>
</resources>

View File

@@ -49,7 +49,7 @@
<string name="importOptionApplicationExplanation">Open een bestand middels een app of je favoriete bestandsbeheerder.</string>
<string name="importOptionApplicationButton">Andere app gebruiken</string>
<string name="about">Over</string>
<string name="app_license">Vrije software, uitgebracht onder de GPLv3-licentie.</string>
<string name="app_license">Vrije software, uitgebracht onder de GPLv3+-licentie</string>
<string name="about_title_fmt">Over <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versie: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Versie-informatie: <xliff:g id="app_revision_url">%s</xliff:g></string>
@@ -74,8 +74,8 @@
<string name="groups">Groepen</string>
<string name="enter_group_name">Voer een groepsnaam in</string>
<string name="starImage">Favoriete ster</string>
<string name="app_copyright_old">Gebaseerd op Loyalty Card Keychain,
\ncopyright ©20162020 Branden Archer.</string>
<string name="app_copyright_old">Gebaseerd op Klantenkaartkluis,
\ncopyright ©20162020 Branden Archer</string>
<string name="unstar">Verwijderen uit favorieten</string>
<string name="star">Toevoegen aan favorieten</string>
<string name="addManually">Kaartnummer handmatig invoeren</string>
@@ -116,15 +116,15 @@
<string name="privacy_policy">Privacybeleid</string>
<string name="accept">Accepteren</string>
<string name="importVoucherVaultMessage">Kies het te importeren <i>vouchervault.json</i>-exportbestand.
\nOf ga naar het exportmenu van Voucher Vault om een exportbestand samen te stellen.</string>
\nGa naar het exportmenu van Voucher Vault om een exportbestand samen te stellen.</string>
<string name="importVoucherVault">Importeren uit Voucher Vault</string>
<string name="importLoyaltyCardKeychainMessage">Kies het te importeren genaamd <i>LoyaltyCardKeychain.csv</i>-exportbestand.
\nOf ga naar het import-/exportmenu van Klantenkaartkluis om een exportbestand samen te stellen.</string>
\nGa naar het import-/exportmenu van Klantenkaartkluis om een exportbestand samen te stellen.</string>
<string name="importLoyaltyCardKeychain">Importeren uit Klantenkaartkluis</string>
<string name="importFidmeMessage">Kies het te importeren <i>fidme-export-request-xxxxxx.zip</i>-exportbestand en kies nadien de juiste barcodes.
\nOf ga naar je FidMe-profiel en druk op Gegevensbescherming om een exportbestand samen te stellen.</string>
\nGa naar je FidMe-profiel en druk op Gegevensbescherming om een exportbestand samen te stellen.</string>
<string name="importCatimaMessage">Kies het te importeren <i>Catima.zip</i>-exportbestand.
\nOf ga naar het import-/exportmenu van Catima op een ander apparaat om een exportbestand samen te stellen.</string>
\nGa naar het import-/exportmenu van Catima op een ander apparaat om een exportbestand samen te stellen.</string>
<string name="importFidme">Importeren uit FidMe</string>
<string name="importCatima">Importeren uit Catima</string>
<string name="errorReadingImage">De afbeelding kan niet worden uitgelezen</string>
@@ -138,7 +138,7 @@
<string name="wrongValueForBarcodeType">Deze waarde komt niet overeen met het gekozen barcodetype</string>
<string name="app_resources">Vrije externe bronnen: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Vrije externe bibliotheken: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Auteursrecht © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Auteursrecht © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="intent_import_card_from_url_share_multiple_text">Ik wil kaarten met je delen</string>
<string name="copy_to_clipboard_multiple_toast">De kaart-id\'s zijn gekopieerd naar het klembord</string>
<string name="card_ids_copied">De kaart-ids zijn gekopieerd</string>
@@ -155,7 +155,7 @@
<string name="frontImageDescription">Voorzijde van de kaart</string>
<string name="passwordRequired">Voer het wachtwoord in</string>
<string name="importStocardMessage">Kies het te importeren Stocard-exportbestand genaamd <i>***-sync.zip</i>.
\nOf stuur een e-mail naar support@stocardapp.com waarin je vraagt om een exportbestand.</string>
\nStuur een e-mail naar support@stocardapp.com waarin je vraagt om een exportbestand.</string>
<string name="importStocard">Importeren uit Stocard</string>
<string name="failedGeneratingShareURL">De te delen link kan niet worden gegenereerd. Meld deze fout.</string>
<string name="turn_flashlight_off">Zaklamp uitzetten</string>
@@ -198,4 +198,16 @@
<string name="sort_by_most_recently_used">Op onlangs gebruikt</string>
<string name="sort_by_name">Op naam</string>
<string name="sort">Sorteren</string>
<string name="report_error">Fout melden</string>
<string name="on_google_play">in Google Play</string>
<string name="rate_this_app">Beoordeel deze app</string>
<string name="and_data_usage">en gegevensgebruik</string>
<string name="on_github">op GitHub</string>
<string name="source_repository">Broncode</string>
<string name="license">Licentie</string>
<string name="help_translate_this_app">Help deze app te vertalen</string>
<string name="credits">Met dank aan</string>
<string name="version_history">Versiegeschiedenis</string>
<string name="exportPasswordHint">Voer een wachtwoord in</string>
<string name="exportPassword">Stel een wachtwoord in om je exportbestand te beveiligen (optioneel)</string>
</resources>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="action_add">Acrescentar</string>
<string name="importOptionFilesystemExplanation">Escolha um ficheiro específico a partir do sistema de ficheiros.</string>
<string name="action_search">Pesquisa</string>
<string name="star">Adicionar aos favoritos</string>
<string name="noMatchingGiftCards">Não encontrei nada. Tente alterar a sua pesquisa.</string>
<string name="storeName">Nome</string>
<string name="note">Nota</string>
<string name="barcodeType">Tipo de código de barras</string>
<string name="barcodeNoBarcode">Este cartão não tem código de barras</string>
<string name="cancel">Cancelar</string>
<string name="save">Guardar</string>
<string name="edit">Edição</string>
<string name="noGiftCards">Clique no botão + + para adicionar um cartão, ou importe algum do menu ⋮ primeiro.</string>
<string name="noBarcode">Não há código de barras</string>
<string name="unstar">Retirar dos favoritos</string>
<string name="importOptionFilesystemButton">Do sistema de arquivo</string>
<string name="importOptionApplicationTitle">Use outro aplicativo</string>
<string name="importOptionApplicationExplanation">Utilize qualquer aplicação ou o seu gestor de ficheiros favorito para abrir um ficheiro.</string>
<string name="importOptionApplicationButton">Utilize outro aplicativo</string>
<string name="about">Sobre</string>
<string name="app_license">Copylefted software livre, licenciado GPLv3+</string>
</resources>

View File

@@ -1,4 +1,102 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="barcodeType">Tip cod de bare</string>
<string name="cardId">Cardului ID</string>
<string name="note">Notă</string>
<string name="storeName">Numele</string>
<string name="noMatchingGiftCards">Nu am găsit nimic. Încearcă să schimbi căutarea.</string>
<string name="noGiftCards">Faceți clic pe butonul + plus pentru a adăuga o carte sau importați mai întâi câteva din meniul ⋮.</string>
<string name="action_add">Adăugați</string>
<string name="action_search">Căutare</string>
<string name="sendLabel">Trimiteți…</string>
<string name="share">Împărtășiți</string>
<string name="copy_to_clipboard">Copiați ID-ul în clipboard</string>
<string name="deleteConfirmation">Să șterg definitiv acest card\?</string>
<string name="deleteTitle">Ștergeți cardul</string>
<string name="unlockScreen">Deblocarea rotației</string>
<string name="lockScreen">Rotația blocurilor</string>
<string name="confirm">Confirmați</string>
<string name="delete">Ștergeți</string>
<string name="edit">Editați</string>
<string name="save">Salvați</string>
<string name="cancel">Anulează</string>
<string name="unstar">Eliminați din favorite</string>
<string name="star">Adaugă la favorite</string>
<string name="noBarcode">Fără cod de bare</string>
<string name="barcodeNoBarcode">Acest card nu are cod de bare</string>
<string name="moveDown">Mutarea în jos</string>
<string name="card">Cardul</string>
<string name="settings_theme">Tema</string>
<string name="all">Toate</string>
<string name="noCardsMessage">Adăugați mai întâi o carte</string>
<string name="noCardExistsError">Nu a putut găsi cardul</string>
<string name="failedParsingImportUriError">Nu s-a putut analiza URI-ul de import</string>
<string name="importExport">Importație/Export</string>
<string name="exportName">Exportați</string>
<string name="importSuccessfulTitle">Importat</string>
<string name="importFailedTitle">Importul a eșuat</string>
<string name="importFailed">Nu s-a putut importa carduri</string>
<string name="noCardIdError">Nu s-a introdus niciun ID de card</string>
<string name="exportFailed">Nu s-a putut exporta carduri</string>
<string name="importing">Importul…</string>
<string name="exporting">Exportul…</string>
<string name="noExternalStoragePermissionError">Acordați mai întâi permisiunea de stocare externă pentru a importa sau exporta carduri</string>
<string name="exportOptionExplanation">Datele vor fi scrise într-o locație aleasă de dumneavoastră.</string>
<string name="importOptionFilesystemTitle">Import din sistemul de fișiere</string>
<string name="importOptionApplicationTitle">Utilizați o altă aplicație</string>
<string name="starImage">Steaua preferată</string>
<string name="settings">Setări</string>
<string name="settings_category_title_ui">Interfață utilizator</string>
<string name="intent_import_card_from_url_share_text">Vreau să împărtășesc o carte cu tine</string>
<string name="moveUp">Mutarea în sus</string>
<string name="editCardTitle">Editare card</string>
<string name="addCardTitle">Adaugă card</string>
<string name="importOptionFilesystemButton">Din sistemul de fișiere</string>
<string name="importOptionApplicationExplanation">Utilizați orice aplicație sau managerul de fișiere preferat pentru a deschide un fișier.</string>
<string name="about">Despre</string>
<string name="app_license">Software liber cu copyleft, licențiat GPLv3+</string>
<string name="enterBarcodeInstructions">Introduceți ID-ul cardului și alegeți fie tipul de cod de bare de mai jos, fie \"Acest card nu are cod de bare\".</string>
<string name="settings_system_theme">Sistemul</string>
<string name="settings_light_theme">Lumină</string>
<string name="settings_dark_theme">Întuneric</string>
<string name="noBarcodeFound">Nu a fost găsit niciun cod de bare</string>
<string name="settings_max_font_size_scale">Mărimea maximă a fontului</string>
<string name="settings_display_barcode_max_brightness">Luminați vizualizarea codurilor de bare</string>
<string name="settings_lock_barcode_orientation">Blocare orientare cod de bare</string>
<string name="settings_keep_screen_on">Păstrați ecranul pornit</string>
<string name="settings_disable_lockscreen_while_viewing_card">Evitați ecranul de blocare</string>
<string name="balance">Balanță</string>
<string name="importSuccessful">Date de card importate</string>
<string name="exportSuccessful">Datele cardului exportate</string>
<string name="noGroups">Faceți clic pe butonul + plus pentru a adăuga mai întâi grupuri pentru clasificare.</string>
<string name="deleteConfirmationGroup">Ștergeți grupul\?</string>
<string name="failedOpeningFileManager">Instalați mai întâi un manager de fișiere.</string>
<string name="leaveWithoutSaveTitle">Ieșire</string>
<string name="addManually">Introduceți manual ID-ul cardului</string>
<string name="barcode">Cod de bare</string>
<string name="currency">Monedă</string>
<string name="editBarcode">Editarea codului de bare</string>
<string name="chooseExpiryDate">Alegeți data de expirare</string>
<string name="moveBarcodeToCenterOfScreen">Centrați codul de bare pe ecran</string>
<string name="copy_to_clipboard_toast">ID-ul cardului copiat în clipboard</string>
<string name="noStoreError">Nici un nume introdus</string>
<string name="selectBarcodeTitle">Selectare cod de bare</string>
<string name="noGroupCards">Acest grup nu conține nicio carte</string>
<string name="addFromImage">Selectați imaginea din galerie</string>
<string name="never">Niciodată</string>
<string name="groups">Grupuri</string>
<string name="leaveWithoutSaveConfirmation">Să pleci fără să salvezi\?</string>
<string name="expiryDate">Data expirării</string>
<string name="moveBarcodeToTopOfScreen">Mutați codul de bare în partea de sus a ecranului</string>
<string name="errorReadingImage">Nu s-a putut citi imaginea</string>
<string name="points">Puncte</string>
<string name="cardShortcut">Scurtătură de card</string>
<string name="scanCardBarcode">Scanarea codului de bare al cardului</string>
<string name="importExportHelp">Copierea de rezervă a cardurilor vă permite să le mutați pe un alt dispozitiv.</string>
<string name="exportSuccessfulTitle">Exportată</string>
<string name="exportFailedTitle">Export eșuat</string>
<string name="importOptionFilesystemExplanation">Alegeți un anumit fișier din sistemul de fișiere.</string>
<string name="importOptionApplicationButton">Utilizați o altă aplicație</string>
<string name="thumbnailDescription">Miniatură pentru card</string>
<string name="enter_group_name">Introduceți numele grupului</string>
</resources>

View File

@@ -9,7 +9,7 @@
<string name="cardId">Номер карты</string>
<string name="barcodeType">Тип штрих-кода</string>
<string name="barcodeNoBarcode">Эта карта без штрих-кода</string>
<string name="cancel">Отменить</string>
<string name="cancel">Отмена</string>
<string name="save">Сохранить</string>
<string name="edit">Изменить</string>
<string name="delete">Удалить карту</string>
@@ -49,12 +49,12 @@
<string name="importOptionApplicationExplanation">Используйте любое приложение или ваш любимый файловый менеджер, чтобы открыть файл.</string>
<string name="importOptionApplicationButton">Использовать другое приложение</string>
<string name="about">О приложении</string>
<string name="app_license">Авторское лево свободного программного обеспечения, лицензия GPLv3+.</string>
<string name="app_license">Авторское лево свободного программного обеспечения, лицензия GPLv3+</string>
<string name="about_title_fmt">О приложении <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Версия: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Информация о версиях: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="selectBarcodeTitle">Выбор штрих-кода</string>
<string name="enterBarcodeInstructions">Введите номер карты и выберите тип штрих-кода. Или выберите \"Эта карта без штрих-кода\".</string>
<string name="enterBarcodeInstructions">Введите номер карты и выберите тип штрих-кодали выберите \"Эта карта без штрих-кода\").</string>
<string name="copy_to_clipboard_toast">Номер карты скопирован в буфер обмена</string>
<string name="thumbnailDescription">Логотип карты</string>
<string name="settings">Настройки</string>
@@ -74,7 +74,7 @@
<string name="importSuccessful">Данные карт успешно импортированы</string>
<string name="starImage">Звезда избранного</string>
<string name="app_copyright_old">На основе Loyalty Card Keychain
\nавторские права © 20162020 Branden Archer.</string>
\nавторские права © 20162020 Branden Archer</string>
<string name="unstar">Удалить из избранного</string>
<string name="star">Добавить в избранное</string>
<string name="noBarcode">Нет штрих-кода</string>
@@ -117,16 +117,16 @@
<item quantity="other"><xliff:g>%d</xliff:g> карт</item>
</plurals>
<string name="accept">Принять</string>
<string name="importVoucherVaultMessage">Выберите файл для импортирования, именуемый <i>vouchervault.json</i>.
\nФайл экспорта можно создать в приложении Voucher Vault, нажав кнопку \"Экспорт\".</string>
<string name="importVoucherVaultMessage">Выберите для импортирования файл <i>vouchervault.json</i>.
\nФайл можно создать в приложении Voucher Vault, нажав кнопку \"Экспорт\".</string>
<string name="importVoucherVault">Импорт из Voucher Vault</string>
<string name="importFidmeMessage">Выберите файл для импортирования, именуемый <i>fidme-export-request-xxxxxx.zip</i>, а затем вручную укажите типы штрих-кодов.
\nФайл экспорта можно создать в приложении FidMe, перейдя в свой профиль, выбрав функцию \"Защита данных\", и затем нажав кнопку \"Извлечь мои данные\".</string>
<string name="importLoyaltyCardKeychainMessage">Выберите файл экспорта, именуемый <i>LoyaltyCardKeychain.csv</i>.
\nФайл экспорта можно создать в приложении Loyalty Card Keychain, перейдя в меню \"Импорт/Экспорт\" и нажав кнопку \"Экспорт\".</string>
<string name="importFidmeMessage">Выберите для импортирования файл <i>fidme-export-request-xxxxxx.zip</i>, а затем вручную укажите типы штрих-кодов.
\nФайл можно создать в приложении FidMe, перейдя в свой профиль, выбрав функцию \"Защита данных\", и затем нажав кнопку \"Извлечь мои данные\".</string>
<string name="importLoyaltyCardKeychainMessage">Выберите для импортирования файл <i>LoyaltyCardKeychain.csv</i>.
\nФайл можно создать в приложении Loyalty Card Keychain, перейдя в меню \"Импорт/Экспорт\" и нажав кнопку \"Экспорт\".</string>
<string name="importLoyaltyCardKeychain">Импорт из Loyalty Card Keychain</string>
<string name="importCatimaMessage">Выберите файл для импортирования, именуемый <i>Catima.zip</i>.
\nФайл экспорта можно создать в другой копии Catima, перейдя в меню \"Импорт/Экспорт\" и нажав кнопку \"Экспорт\".</string>
<string name="importCatimaMessage">Выберите для импортирования файл <i>Catima.zip</i>.
\nФайл можно создать в другой копии Catima, перейдя в меню \"Импорт/Экспорт\" и нажав кнопку \"Экспорт\".</string>
<string name="importFidme">Импорт из FidMe</string>
<string name="importCatima">Импорт из Catima</string>
<string name="errorReadingImage">Невозможно считать изображение</string>
@@ -140,7 +140,7 @@
<string name="wrongValueForBarcodeType">Недопустимое значение для выбранного типа штрих-кода</string>
<string name="app_resources">Свободные сторонние ресурсы: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Свободные сторонние библиотеки: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Авторские права © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Авторские права © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="intent_import_card_from_url_share_multiple_text">Поделиться картами</string>
<string name="card_ids_copied">Скопированные номера карт</string>
<string name="copy_to_clipboard_multiple_toast">Номера карт скопированы в буфер обмена</string>
@@ -155,7 +155,7 @@
<string name="backImageDescription">Задняя сторона карты</string>
<string name="frontImageDescription">Лицевая сторона карты</string>
<string name="photos">Фотографии</string>
<string name="importStocardMessage">Выберите файл <i>***-sync.zip</i> для импортирования.
<string name="importStocardMessage">Выберите для импортирования файл <i>***-sync.zip</i>.
\nЭтот файл можно получить по электронной почте от support@stocardapp.com, предварительно запросив экспорт ваших данных.</string>
<string name="passwordRequired">Введите пароль</string>
<string name="importStocard">Импорт из Stocard</string>
@@ -206,4 +206,16 @@
<string name="sort_by_most_recently_used">Частота использования</string>
<string name="sort_by_name">Название</string>
<string name="sort">Сортировка</string>
<string name="credits">Благодарности</string>
<string name="version_history">История версий</string>
<string name="on_github">на GitHub</string>
<string name="rate_this_app">Оценить приложение</string>
<string name="and_data_usage">и использование данных</string>
<string name="report_error">Отчёт об ошибке</string>
<string name="on_google_play">в Google Play</string>
<string name="source_repository">Исходный код</string>
<string name="license">Лицензия</string>
<string name="help_translate_this_app">Помощь в переводе приложения</string>
<string name="exportPassword">Защитить файл экспорта паролем (необязательно)</string>
<string name="exportPasswordHint">Введите пароль</string>
</resources>

View File

@@ -25,7 +25,7 @@
<string name="noCardExistsError">Te kartice zvestobe ni bilo moč najti</string>
<string name="importExport">Uvozi/izvozi</string>
<string name="exportName">Izvozi</string>
<string name="importExportHelp">Varnostna kopija omogoča varen prenos kartic na druge telefonske naprave.</string>
<string name="importExportHelp">Varnostna kopija omogoča varen prenos kartic na druge naprave.</string>
<string name="importSuccessfulTitle">Uvoz je bil uspešen</string>
<string name="importFailedTitle">Uvoz ni uspel</string>
<string name="importFailed">Napaka pri uvozu</string>
@@ -39,7 +39,7 @@
<string name="importOptionFilesystemExplanation">Izberite specifično datoteko iz datotečnega sistema.</string>
<string name="importOptionFilesystemButton">Iz datotečnega sistema</string>
<string name="importOptionApplicationTitle">Uporabi zunanjo aplikacijo</string>
<string name="importOptionApplicationExplanation">Uporabi zunanjo aplikacijo, kot npr. Dropbox, Google Drive ali ostale upravljalnike datotek, za odpiranje datoteko.</string>
<string name="importOptionApplicationExplanation">Uporabi zunanjo aplikacijo, kot npr. Dropbox, Google Drive ali ostale upravljalnike datotek, za odpiranje datoteke.</string>
<string name="importOptionApplicationButton">Uporabi zunanjo aplikacijo</string>
<string name="about">Več o aplikaciji</string>
<string name="app_license">Licencirano s skladu z GPLv3.</string>
@@ -57,7 +57,7 @@
<string name="deleteConfirmation">Prosim potrdite, če želite izbrisati to kartico\?</string>
<string name="card">Kartica</string>
<string name="addFromImage">Izberite sliko iz galerije</string>
<string name="addManually">Ročno vnesite ID kartice</string>
<string name="addManually">Ročno vnesite št. kartice</string>
<string name="leaveWithoutSaveConfirmation">Zapustite brez shranjevanja\?</string>
<string name="leaveWithoutSaveTitle">Izhod</string>
<string name="moveDown">Premikanje navzdol</string>
@@ -71,18 +71,17 @@
<string name="enter_group_name">Vnesite ime skupine</string>
<string name="exportSuccessful">Izvoženi podatki o karticah</string>
<string name="importSuccessful">Uvoženi podatki o karticah</string>
<string name="intent_import_card_from_url_share_text">Želim z vami deliti kartico</string>
<string name="intent_import_card_from_url_share_text">Z vami želim deliti kartico</string>
<string name="settings_disable_lockscreen_while_viewing_card">Preprečitev zaklepanja zaslona</string>
<string name="settings_keep_screen_on">Ohranite zaslon vklopljen</string>
<string name="enterBarcodeInstructions">Vnesite ID kartice in spodaj izberite vrsto črtne kode ali \"Ta kartica nima črtne kode\".</string>
<string name="settings_max_font_size_scale">Največja velikost pisave</string>
<string name="settings_dark_theme">Temno</string>
<string name="settings_light_theme">Luč</string>
<string name="settings_light_theme">Svetlo</string>
<string name="settings_system_theme">Sistem</string>
<string name="settings_theme">Tema</string>
<string name="starImage">Najljubša zvezda</string>
<string name="app_copyright_old">Na podlagi kartice zvestobe obesek za ključe
\ncopyright © 2016-2020 Branden Archer.</string>
<string name="starImage">Zvezdica za priljubljene</string>
<string name="app_copyright_old">Na podlagi aplikacije Loyalty Card Keychain copyright © 2016-2020 Branden Archer.</string>
<string name="exportOptionExplanation">Podatki bodo zapisani na izbrano mesto.</string>
<string name="failedParsingImportUriError">Ni bilo mogoče razčleniti URI uvoza</string>
<string name="card_ids_copied">Kopirana kartica ID(s)</string>
@@ -94,4 +93,72 @@
<string name="barcodeType">Vrsta črtne kode</string>
<string name="noMatchingGiftCards">Ničesar nisem našel. Poskusite spremeniti iskanje.</string>
<string name="action_search">Iskanje</string>
<string name="exportPasswordHint">Vnesite geslo</string>
<string name="exportPassword">Izberite geslo za zaščito izvoza (neobvezno)</string>
<string name="help_translate_this_app">Pomagajte pri prevajanju aplikacije</string>
<string name="version_history">Zgodovina različic</string>
<string name="settings_brown_theme">Rjava</string>
<string name="settings_grey_theme">Siva</string>
<string name="settings_green_theme">Zelena</string>
<string name="settings_sky_blue_theme">Sinje modra</string>
<string name="settings_blue_theme">Modra</string>
<string name="settings_violet_theme">Vijolična</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_pink_theme">Roza</string>
<string name="settings_theme_color">Barva teme</string>
<string name="settings_system_locale">Sistem</string>
<string name="settings_locale">Jezik</string>
<string name="barcodeImageDescriptionWithType">Slika črtne kode tipa <xliff:g>%s</xliff:g></string>
<string name="swipeToSwitchImages">Povlecite ali dolgo pritisnite da zamenjate slike</string>
<string name="sort_by">Razvrsti po</string>
<string name="reverse">Obratno</string>
<string name="sort_by_balance">Stanje</string>
<string name="sort_by_expiry">Potek</string>
<string name="sort_by_most_recently_used">Nazadnje uporabljene</string>
<string name="sort_by_name">Ime</string>
<string name="sort">Razvrsti</string>
<string name="license">Licence</string>
<string name="on_github">na GitHubu</string>
<string name="rate_this_app">Ocenite aplikacijo</string>
<string name="report_error">Prijavite napako</string>
<string name="on_google_play">na Trgovini Google Play</string>
<string name="and_data_usage">in uporaba podatkov</string>
<string name="source_repository">Izvorna koda</string>
<string name="points">Točke</string>
<string name="currency">Valuta</string>
<string name="balance">Stanje na računu</string>
<string name="errorReadingImage">Slike ni bilo mogoče prebrati</string>
<string name="noBarcodeFound">Črtna koda ni bila najdena</string>
<string name="balancePoints"><xliff:g>%s</xliff:g> točk</string>
<string name="balanceSentence">Stanje: <xliff:g>%s</xliff:g></string>
<string name="chooseImportType">Uvoz iz?</string>
<string name="importCatima">Izvoz iz aplikacije Catima</string>
<string name="importStocard">Izvoz iz aplikacije Stocard</string>
<string name="importVoucherVault">Izvoz iz aplikacije Voucher Vault</string>
<string name="privacy_policy">Politika zasebnosti</string>
<string name="turn_flashlight_off">Izklop svetilke</string>
<string name="turn_flashlight_on">Vklop svetilke</string>
<string name="passwordRequired">Vnesite geslo</string>
<string name="accept">Sprejmi</string>
<string name="importLoyaltyCardKeychain">Uvoz iz aplikacije Loyalty Card Keychain</string>
<string name="barcodeId">Vsebina črtne kode</string>
<string name="sameAsCardId">Enaka kot številka kartice</string>
<string name="setBarcodeId">Nastavi vsebino črtne kode</string>
<string name="wrongValueForBarcodeType">Ta vrednost ni veljavna pri izbranem tipu čtne kode</string>
<string name="takePhoto">Naredi fotografijo</string>
<string name="intent_import_card_from_url_share_multiple_text">Z vami želim deliti kartice zvestobe</string>
<string name="copy_to_clipboard_multiple_toast">Številke kartic kopirane v odložišče</string>
<string name="importFidme">Uvoz iz aplikacije FidMe</string>
<string name="no">Ne</string>
<string name="yes">Da</string>
<string name="frontImageDescription">Slika sprednje strani</string>
<string name="backImageDescription">Slika zadnje strani</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> ni veljavno stanje.</string>
<string name="setBackImage">Nastavi sliko sprednje strani</string>
<string name="setFrontImage">Nastavi sliko sprednje strani</string>
<string name="photos">Fotografije</string>
<string name="updateBarcodeQuestionText">Spremenili ste številko kartice. Želite posodobiti tudi črtno kodo na enako vrednost?</string>
<string name="updateBarcodeQuestionTitle">Posodobi črtno kodo?</string>
<string name="removeImage">Odstrani sliko</string>
<string name="unsupportedBarcodeType">Te vrste črtne kode aplikacija ne more prikazati. Morda bo to možno v prihodnosti.</string>
</resources>

View File

@@ -5,8 +5,8 @@
<string name="settings_max_font_size_scale">Max. teckenstorlek</string>
<string name="settings_keep_screen_on">Håll skärmen påslagen</string>
<string name="enterBarcodeInstructions">Ange kortets ID och välj antingen streckkodstyp nedan, eller \"Detta kort har ingen streckkod\".</string>
<string name="importFidmeMessage">Välj den exporterade <i>fidme-export-request-xxxxxx.zip</i> från FidMe som du vill importera och välj streckkodstyper manuellt efteråt,
\neller skapa en från din FidMe-profil först genom att välja \"Data Protection\" och sen trycka på \"Extract my data\".</string>
<string name="importFidmeMessage">Välj den exporterade <i>fidme-export-request-xxxxxx.zip</i> från FidMe som du vill importera och välj streckkodstyper manuellt efteråt.
\nSkapa den från din FidMe-profil först genom att välja \"Data Protection\" och sen trycka på \"Extract my data\".</string>
<string name="importOptionApplicationExplanation">Använd vilken app som helst eller den filhanterare du föredrar för att öppna en fil.</string>
<string name="importOptionApplicationButton">Använd en annan app</string>
<string name="intent_import_card_from_url_share_text">Jag vill dela ett kort med dig</string>
@@ -21,12 +21,12 @@
<item quantity="other"><xliff:g>%d</xliff:g> kort valda</item>
</plurals>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="importLoyaltyCardKeychainMessage">Välj den exporterade <i>LoyaltyCardKeychain.csv</i> från Loyalty Card Keychain som du vill importera,
\neller skapa en från Import/Export-menyn i Loyalty Card Keychain först genom att trycka på Exportera.</string>
<string name="importVoucherVaultMessage">Välj den exporterade <i>vouchervault.json</i> från Voucher Vault som du vill importera,
\neller skapa en först genom att trycka på Exportera i Voucher Vault.</string>
<string name="importStocardMessage">Välj den exporterade <i>***-sync.zip</i> från Stocard som du vill importera,
\neller skaffa en först genom att skicka e-post till support@stocardapp.com och be om att få dina data exporterade.</string>
<string name="importLoyaltyCardKeychainMessage">Välj den exporterade <i>LoyaltyCardKeychain.csv</i> från Loyalty Card Keychain som du vill importera.
\nSkapa den från Import/Export-menyn i Loyalty Card Keychain först genom att trycka på Exportera.</string>
<string name="importVoucherVaultMessage">Välj den exporterade <i>vouchervault.json</i> från Voucher Vault som du vill importera.
\nSkapa den först genom att trycka på Exportera i Voucher Vault.</string>
<string name="importStocardMessage">Välj den exporterade <i>***-sync.zip</i> från Stocard som du vill importera.
\nSkaffa den först genom att skicka e-post till support@stocardapp.com och be om att få dina data exporterade.</string>
<string name="enter_group_name">Ange gruppnamn</string>
<string name="groups">Grupper</string>
<plurals name="groupCardCount">
@@ -90,8 +90,8 @@
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
<string name="about_title_fmt">Om <xliff:g id="app_name">%s</xliff:g></string>
<string name="app_copyright_old">Baserad på Loyalty Card Keychain
\ncopyright © 20162020 Branden Archer.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
\ncopyright © 20162020 Branden Archer</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="about">Om</string>
<string name="importOptionApplicationTitle">Använd en annan app</string>
<string name="importOptionFilesystemButton">Från filsystemet</string>
@@ -158,7 +158,7 @@
<string name="chooseExpiryDate">Välj förfallodatum</string>
<string name="expiryDate">Förfallodatum</string>
<string name="starImage">Favoritstjärna</string>
<string name="app_license">Copyleftad fri programvara, under GPLv3+-licens.</string>
<string name="app_license">Copyleftad fri programvara, under GPLv3+-licens</string>
<string name="app_resources">Fria tredjepartsresurser: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Fria tredjepartsbibliotek: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> verkar inte vara ett giltigt saldo.</string>
@@ -166,8 +166,8 @@
<string name="balanceSentence">Saldo: <xliff:g>%s</xliff:g></string>
<string name="settings_disable_lockscreen_while_viewing_card">Förhindra skärmlåsning</string>
<string name="lockScreen">Förhindra rotation</string>
<string name="importCatimaMessage">Välj den exporterade <i>catima.zip</i> från Catima som du vill importera,
\neller skapa en från Import/Export-menyn i en annan Catima-app genom att trycka på Exportera där först.</string>
<string name="importCatimaMessage">Välj den exporterade <i>catima.zip</i> från Catima som du vill importera.
\nSkapa den från Import/Export-menyn i en annan Catima-app genom att trycka på Exportera där först.</string>
<string name="expiryStateSentence">Giltigt till: <xliff:g>%s</xliff:g></string>
<string name="exportSuccessful">Kortdata exporterad</string>
<string name="importSuccessful">Kortdata importerad</string>
@@ -198,4 +198,12 @@
<string name="sort_by_most_recently_used">Senast använda</string>
<string name="sort_by_name">Namn</string>
<string name="sort">Sortera</string>
<string name="license">Licens</string>
<string name="and_data_usage">och dataanvändning</string>
<string name="rate_this_app">Betygsätt den här appen</string>
<string name="on_google_play">på Google Play</string>
<string name="report_error">Rapportera ett fel</string>
<string name="version_history">Versionshistorik</string>
<string name="help_translate_this_app">Hjälp till med översättningen av appen</string>
<string name="on_github">på GitHub</string>
</resources>

View File

@@ -38,19 +38,19 @@
<string name="sameAsCardId">Kart numarasıyla aynı</string>
<string name="barcodeId">Barkod değeri</string>
<string name="importVoucherVaultMessage">İçe aktarmak için Voucher Vault\'tan dışa aktardığınız <i>vouchervault.json</i> dosyasını seçin.
\nVeya önce Voucher Vault\'ta \"Dışa aktar\" düğmesine basarak bir tane oluşturun.</string>
\nÖnce Voucher Vault\'ta \"Dışa aktar\" düğmesine basarak bir tane oluşturun.</string>
<string name="importVoucherVault">Voucher Vault\'tan içe aktar</string>
<string name="importStocardMessage">İçe aktarmak için Stocard\'dan dışa aktardığınız <i>***-sync.zip</i> dosyasını seçin.
\nVeya support@stocardapp.com adresine e-posta göndererek verilerinizin dışa aktarılmasını isteyerek edinin.</string>
\nsupport@stocardapp.com adresine e-posta göndererek verilerinizin dışa aktarılmasını isteyerek edinin.</string>
<string name="importStocard">Stocard\'dan içe aktar</string>
<string name="importLoyaltyCardKeychainMessage">İçe aktarmak için Loyalty Card Keychain\'den dışa aktardığınız <i>LoyaltyCardKeychain.csv</i> dosyasını seçin.
\nVeya Loyalty Card Keychain uygulamasının İçe/Dışa aktar menüsündeki \"Dışa aktar\" düğmesine basarak bir tane oluşturun.</string>
\nLoyalty Card Keychain uygulamasının İçe/Dışa aktar menüsündeki \"Dışa aktar\" düğmesine basarak bir tane oluşturun.</string>
<string name="importLoyaltyCardKeychain">Loyalty Card Keychain\'den içe aktar</string>
<string name="importFidmeMessage">FidMe\'den içe aktarmak için dışa aktardığınız <i>fidme-export-request-xxxxxx.zip</i> dosyasını seçin ve ardından barkod türlerini elle seçin.
\nVeya FidMe profilinizden Veri Koruma seçeneğini seçip ardından \"Verilerimi çıkar\" düğmesine basarak bir tane oluşturun.</string>
\nFidMe profilinizden Veri Koruma seçeneğini seçip ardından \"Verilerimi çıkar\" düğmesine basarak bir tane oluşturun.</string>
<string name="importFidme">FidMe\'den içe aktar</string>
<string name="importCatimaMessage">İçe aktarmak için Catima\'dan dışa aktardığınız <i>catima.zip</i> dosyasını seçin.
\nVeya başka bir Catima uygulamasının İçe/Dışa aktar menüsündeki \"Dışa aktar\" düğmesine basarak bir tane oluşturun.</string>
\nBaşka bir Catima uygulamasının İçe/Dışa aktar menüsündeki \"Dışa aktar\" düğmesine basarak bir tane oluşturun.</string>
<string name="importCatima">Catima\'dan içe aktar</string>
<string name="accept">Kabul et</string>
<string name="privacy_policy_popup_text">Gizlilik politikası bildirimi (bazı uygulama mağazaları için gerekli):
@@ -119,10 +119,10 @@
<string name="app_revision_fmt">Değişiklik Bilgileri: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="debug_version_fmt">Sürüm: <xliff:g id="version">%s</xliff:g></string>
<string name="about_title_fmt"><xliff:g id="app_name">%s</xliff:g> hakkında</string>
<string name="app_license">GPLv3+ altında lisanslanan copyleft özgür yazılım.</string>
<string name="app_license">GPLv3+ altında lisanslanan copyleft özgür yazılım</string>
<string name="app_copyright_old">Loyalty Card Keychain temel alınmıştır
\nTelif Hakkı © 20162020 Branden Archer.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Telif Hakkı © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
\nTelif Hakkı © 20162020 Branden Archer</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Telif Hakkı © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="about">Hakkında</string>
<string name="importOptionApplicationButton">Başka bir uygulama kullan</string>
<string name="importOptionApplicationExplanation">Bir dosyayı açmak için herhangi bir uygulamayı veya en sevdiğiniz dosya yöneticisini kullanın.</string>
@@ -198,4 +198,16 @@
<string name="sort_by_most_recently_used">En Son Kullanılan</string>
<string name="sort_by_name">Ad</string>
<string name="sort">Sırala</string>
<string name="report_error">Hata Bildir</string>
<string name="on_google_play">Google Play\'de</string>
<string name="rate_this_app">Bu uygulamayı değerlendir</string>
<string name="and_data_usage">ve veri kullanımı</string>
<string name="on_github">GitHub\'da</string>
<string name="source_repository">Kaynak Deposu</string>
<string name="license">Lisans</string>
<string name="help_translate_this_app">Bu uygulamayı çevirmeye yardımcı olun</string>
<string name="credits">Emeği Geçenler</string>
<string name="version_history">Sürüm Geçmişi</string>
<string name="exportPassword">Dışa aktarmanızı korumak için bir parola belirleyin (isteğe bağlı)</string>
<string name="exportPasswordHint">Parola girin</string>
</resources>

View File

@@ -27,20 +27,20 @@
<string name="sameAsCardId">Таке ж як ID картки</string>
<string name="barcodeId">Значення штрих-коду</string>
<string name="importVoucherVaultMessage">Оберіть Voucher Vault експорт-файл названий <i>vouchervault.json</i> для імпортування.
\nЧи створіть його натиснувши \"Експорт\" у Voucher Vault.</string>
\nСтворіть його натиснувши \"Експорт\" у Voucher Vault.</string>
<string name="importVoucherVault">Імпорт з Voucher Vault</string>
<string name="importLoyaltyCardKeychainMessage">Знайдіть файл названий <i>LoyaltyCardKeychain.csv</i> для імпортування.
\nЧи створіть його у меню імпорту/експорту Loyalty Card Keychain натиснувши \"Експорт\".</string>
\nСтворіть його у меню імпорту/експорту Loyalty Card Keychain натиснувши \"Експорт\".</string>
<string name="importCatimaMessage">Оберіть експорт-файл названий <i>catima.zip</i> для імпортування.
\nЧи створіть його з меню імпорту/експорту у іншій Catima, натиснувши \"Експорт\".</string>
\nСтворіть його з меню імпорту/експорту у іншій Catima, натиснувши \"Експорт\".</string>
<string name="importLoyaltyCardKeychain">Імпорт з Loyalty Card Keychain</string>
<string name="importFidmeMessage">Оберіть FidMe експорт-файл названий <i>fidme-export-request-xxxxxx.zip</i> для імпортування і оберіть типи штрих-кодів вручну пізніше.
\nЧи створіть його у вашому FidMe профілі обравши \"Захист даних -&gt; Витяг даних\".</string>
\nСтворіть його у вашому FidMe профілі обравши \"Захист даних -&gt; Витяг даних\".</string>
<string name="importFidme">Імпорт з FidMe</string>
<string name="importCatima">Імпорт з Catima</string>
<string name="accept">Прийняти</string>
<string name="privacy_policy">Політика конфіденційності</string>
<string name="app_loyalty_card_keychain">Брелок картки лояльності</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="chooseImportType">Імпортувати дані з\?</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> здається, не є дійсним залишком.</string>
<string name="points">Бали</string>
@@ -50,7 +50,7 @@
<string name="noBarcodeFound">Жодного штрих-коду не знайдено</string>
<string name="moveBarcodeToCenterOfScreen">Відцентрувати штрих-код на екрані</string>
<string name="moveBarcodeToTopOfScreen">Посунути штрих-код наверх екрану</string>
<string name="chooseExpiryDate">Оберіть дату закінчення терміну дії</string>
<string name="chooseExpiryDate">Оберіть дату</string>
<string name="never">Ніколи</string>
<string name="expiryDate">Дата закінчення терміну дії</string>
<string name="editBarcode">Редагувати штрих-код</string>
@@ -82,7 +82,7 @@
<string name="settings_max_font_size_scale">Макс. розмір шрифту</string>
<string name="settings_dark_theme">Темна</string>
<string name="settings_light_theme">Світла</string>
<string name="settings_system_theme">Система</string>
<string name="settings_system_theme">Системна</string>
<string name="settings_theme">Тема</string>
<string name="settings_category_title_ui">Інтерфейс користувача</string>
<string name="settings">Налаштування</string>
@@ -96,17 +96,17 @@
<string name="app_revision_fmt">Інформація про випуск: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="debug_version_fmt">Версія: <xliff:g id="version">%s</xliff:g></string>
<string name="about_title_fmt">Про <xliff:g id="app_name">%s</xliff:g></string>
<string name="app_license">Копілефт вільне програмне забезпечення, ліцензоване під GPLv3+.</string>
<string name="app_license">Копілефт вільне програмне забезпечення, ліцензоване під GPLv3+</string>
<string name="app_copyright_old">Створено на основі Loyalty Card Keychain
\nавторські права © 20162020 Branden Archer.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Авторські права © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
\nавторські права © 20162020 Branden Archer</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Авторські права © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="about">Про програму</string>
<string name="importOptionApplicationButton">Використайте іншу програму</string>
<string name="importOptionApplicationButton">Вибір програми</string>
<string name="importOptionApplicationExplanation">Використайте іншу програму чи ваш улюблений файл-менеджер для відкриття файлу.</string>
<string name="importOptionApplicationTitle">Використати іншу програму</string>
<string name="importOptionFilesystemButton">З провідника</string>
<string name="importOptionApplicationTitle">З іншої програми</string>
<string name="importOptionFilesystemButton">Обрати файл</string>
<string name="importOptionFilesystemExplanation">Оберіть файл у провіднику.</string>
<string name="importOptionFilesystemTitle">Імпорт з провідника</string>
<string name="importOptionFilesystemTitle">Імпорт з файлу</string>
<string name="exportOptionExplanation">Дані буде записано до локації обраної вами.</string>
<string name="noExternalStoragePermissionError">Надайте дозвіл на доступ до пам\'яті пристрою для імпорту чи експорту карток</string>
<string name="exporting">Експортуємо…</string>
@@ -156,11 +156,11 @@
<string name="removeImage">Видалити зображення</string>
<string name="setBackImage">Встановити зображення тильної сторони</string>
<string name="setFrontImage">Встановити зображення лицьової сторони</string>
<string name="photos">Фотографії</string>
<string name="photos">Фото</string>
<string name="backImageDescription">Тильна сторона карти</string>
<string name="frontImageDescription">Лицьова сторона карти</string>
<string name="importStocardMessage">Виберіть експорт <i> ***-sync.zip </i> зі Stocard для імпорту.
\nАбо отримайте його, надіславши електронною поштою support@stocardapp.com з проханням експортувати ваші дані.</string>
\nОтримайте його, надіславши електронною поштою support@stocardapp.com з проханням експортувати ваші дані.</string>
<string name="importStocard">Імпорт із Stocard</string>
<plurals name="selectedCardCount">
<item quantity="one">Обрано: <xliff:g>%d</xliff:g> карта</item>
@@ -199,4 +199,23 @@
<string name="toggleMoreInfo">Показувати додаткову інформацію</string>
<string name="barcodeImageDescriptionWithType">Зображення штрих-коду карти типу <xliff:g>%s</xliff:g></string>
<string name="swipeToSwitchImages">Свайп чи довге натискання для зміни зображень</string>
<string name="sort_by">Сортувати за</string>
<string name="reverse">Зворотній порядок</string>
<string name="sort_by_balance">Баланс</string>
<string name="sort_by_expiry">Термін дії</string>
<string name="sort_by_most_recently_used">Часто використовувані</string>
<string name="sort_by_name">Назва</string>
<string name="sort">Сортування</string>
<string name="version_history">Історія версій</string>
<string name="help_translate_this_app">Допомогти з перекладом програми</string>
<string name="license">Ліцензія</string>
<string name="source_repository">Вихідний код</string>
<string name="on_github">на GitHub</string>
<string name="and_data_usage">та використання даних</string>
<string name="credits">Подяки</string>
<string name="rate_this_app">Оцінити програму</string>
<string name="on_google_play">у Google Play</string>
<string name="report_error">Повідомити про помилку</string>
<string name="exportPassword">Встановіть пароль для захисту експорту (необов\'язково)</string>
<string name="exportPasswordHint">Введіть пароль</string>
</resources>

View File

@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
<string name="app_revision_url">https://github.com/TheLastProject/Catima/releases</string>
<string name="action_search">搜尋</string>
<string name="action_add">新增</string>
<string name="noGiftCards">點選 + 按鈕以新增卡片\n或從 ⋮ 選單中匯入卡片</string>
<string name="noMatchingGiftCards">沒有找到任何東西。試試其他關鍵字。</string>
<string name="storeName">名稱</string>
<string name="note">註記</string>
<string name="cardId">卡片 ID</string>
<string name="barcodeType">條碼種類</string>
<string name="barcodeNoBarcode">此卡片沒有可用的條碼</string>
<string name="noBarcode">無條碼</string>
<string name="privacy_policy_popup_text">隱私權政策(某些應用程式商店需要此條目): 我們並不會收集任何資料!任何人都可以檢視我們的原始碼並驗證這點。</string>
<string name="star">新增至收藏</string>
<string name="app_license">公共版權 (Copylefted) 的自由軟體,許可 GPLv3+</string>
<string name="unstar">從收藏中移除</string>
<string name="cancel">取消</string>
<string name="save">儲存</string>
<string name="edit">編輯</string>
<string name="delete">刪除</string>
<string name="confirm">確認</string>
<string name="about">關於</string>
<string name="about_title_fmt">關於 <xliff:g id="app_name">%s</xliff:g></string>
<string name="accept">接受</string>
<string name="addCardTitle">新增卡片</string>
<string name="addFromImage">從圖庫中選擇圖片</string>
<string name="addManually">手動輸入卡片 ID</string>
<string name="all">全部</string>
<string name="balance">餘額</string>
<string name="balanceSentence">餘額: <xliff:g>%s</xliff:g></string>
<string name="balancePoints"><xliff:g>%s</xliff:g></string>
<string name="app_copyright_old">基於 Loyalty Card Keychain\n著作權所有 © 20162020 Branden Archer</string>
<string name="barcode">條碼</string>
<string name="barcodeId">條碼內容</string>
<string name="barcodeImageDescriptionWithType">條碼種類 <xliff:g>%s</xliff:g> 的圖片</string>
<string name="card">卡片</string>
<string name="card_ids_copied">已複製卡片 ID(s)</string>
<string name="cardShortcut">卡片捷徑</string>
<string name="chooseExpiryDate">選擇逾期日期</string>
<string name="chooseImportType">從哪裡匯入資料?</string>
<string name="copy_to_clipboard">已複製 ID 至剪貼簿中</string>
<string name="copy_to_clipboard_multiple_toast">已複製多個卡片 ID 至剪貼簿中</string>
<string name="copy_to_clipboard_toast">已複製卡片 ID 至剪貼簿中</string>
<string name="credits">貢獻者</string>
<string name="currency">幣別</string>
<string name="debug_version_fmt">版本:<xliff:g id="version">%s</xliff:g></string>
<string name="deleteConfirmation">永久刪除此卡片?</string>
<string name="deleteConfirmationGroup">刪除此群組?</string>
<string name="deleteTitle">刪除卡片</string>
<string name="editBarcode">編輯條碼</string>
<string name="editCardTitle">編輯圖片</string>
<string name="enter_group_name">輸入群組名稱</string>
<string name="enterBarcodeInstructions">輸入卡片 ID、選擇條碼種類、或選擇「此卡片沒有可用的條碼」。</string>
<string name="errorReadingImage">無法讀取此圖片</string>
<string name="expiryDate">逾期日期</string>
<string name="expiryStateSentence">逾期於:<xliff:g>%s</xliff:g></string>
<string name="expiryStateSentenceExpired">已逾期:<xliff:g>%s</xliff:g></string>
<string name="exportFailed">無法匯出卡片</string>
<string name="exportFailedTitle">匯出失敗</string>
<string name="exporting">匯出中…</string>
<string name="exportName">匯出</string>
<string name="exportOptionExplanation">資料將寫至您所選的位置。</string>
<string name="exportPassword">透過密碼保護您的匯出檔 (選用)</string>
<string name="exportPasswordHint">輸入密碼</string>
<string name="exportSuccessful">已匯出卡片資訊</string>
<string name="exportSuccessfulTitle">已匯出</string>
<string name="failedOpeningFileManager">請先安裝檔案管理員。</string>
<string name="failedParsingImportUriError">無法讀取匯入 URI</string>
<string name="frontImageDescription">卡片 (正面)</string>
<string name="groups">群組</string>
<string name="groupsList">群組:<xliff:g>%s</xliff:g></string>
<string name="help_translate_this_app">幫助翻譯本程式</string>
<string name="importExport">匯入/匯出</string>
<string name="importFailedTitle">匯入失敗</string>
<string name="importFailed">無法匯入卡片</string>
<string name="importing">匯入中…</string>
<string name="importSuccessfulTitle">已匯入</string>
<string name="intent_import_card_from_url_share_multiple_text">我想要分享些卡片給你</string>
<string name="intent_import_card_from_url_share_text">我想要分享張卡片給你</string>
<string name="leaveWithoutSaveConfirmation">不保存就離開?</string>
<string name="leaveWithoutSaveTitle">離開</string>
<string name="license">許可</string>
<string name="never">永不</string>
<string name="no"></string>
<string name="noBarcodeFound">找不到可用的條碼</string>
<string name="noCardExistsError">無法找到卡片</string>
<string name="noCardIdError">尚未輸入卡片 ID</string>
<string name="noCardsMessage">請先新增卡片</string>
<string name="sort">排列</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_pink_theme">粉紅</string>
<string name="settings_magenta_theme">品紅</string>
<string name="settings_violet_theme">紫色</string>
<string name="settings_blue_theme">藍色</string>
<string name="settings_sky_blue_theme">天空藍</string>
<string name="settings_green_theme">綠色</string>
<string name="settings_grey_theme">灰色</string>
<string name="settings_brown_theme">棕色</string>
<string name="sort_by_name">名稱</string>
<string name="sort_by_most_recently_used">最近使用</string>
<string name="sort_by_expiry">逾期日期</string>
<string name="sort_by_balance">餘額</string>
<string name="reverse">反序</string>
<string name="sort_by">排列方式</string>
<string name="version_history">版本歷史</string>
<string name="source_repository">原始碼版本庫</string>
<string name="on_github">於 GitHub</string>
<string name="and_data_usage">及資料使用</string>
<string name="rate_this_app">替本 App 評分</string>
<string name="on_google_play">於 Google Play</string>
<string name="report_error">回報錯誤</string>
<string name="setBarcodeId">設定條碼內容</string>
<string name="sameAsCardId">與卡片 ID 相同</string>
<string name="photos">圖片</string>
<string name="setFrontImage">設定正面圖片</string>
<string name="setBackImage">設定背面圖片</string>
<string name="removeImage">移除圖片</string>
<string name="takePhoto">拍照</string>
<string name="updateBarcodeQuestionTitle">更新條碼內容?</string>
<string name="yes"></string>
<string name="passwordRequired">請輸入密碼</string>
<string name="turn_flashlight_on">開啟手電筒</string>
<string name="turn_flashlight_off">關閉手電筒</string>
<string name="settings_locale">語言</string>
<string name="settings_system_locale">系統語言</string>
<string name="settings_theme_color">主題顏色</string>
<string name="app_contributors">感謝以下貢獻者: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="privacy_policy">隱私權政策</string>
<plurals name="selectedCardCount">
<item quantity="other">已選取 <xliff:g>%d</xliff:g> 張卡片</item>
</plurals>
<plurals name="deleteCardsTitle">
<item quantity="other">刪除 <xliff:g>%d</xliff:g> 張卡片</item>
</plurals>
<plurals name="deleteCardsConfirmation">
<item quantity="other">永久刪除 <xliff:g>%d</xliff:g> 張卡片?</item>
</plurals>
<plurals name="groupCardCount">
<item quantity="other"><xliff:g>%d</xliff:g> 張卡片</item>
</plurals>
<string name="settings">設定</string>
<string name="share">分享</string>
<string name="settings_system_theme">系統主題</string>
<string name="settings_theme">主題</string>
<string name="thumbnailDescription">卡片縮圖</string>
<string name="noGroupCards">此群組中無任何卡片</string>
<string name="settings_category_title_ui">用戶界面</string>
<string name="settings_max_font_size_scale">最大字體大小</string>
<string name="settings_light_theme">淺色</string>
<string name="settings_dark_theme">深色</string>
<string name="settings_display_barcode_max_brightness">調高條碼介面螢幕亮度</string>
<string name="settings_lock_barcode_orientation">鎖定條碼螢幕方向</string>
<string name="settings_keep_screen_on">螢幕恆亮</string>
<string name="settings_disable_lockscreen_while_viewing_card">防止螢幕鎖定</string>
<string name="importSuccessful">已匯入卡片資訊</string>
<string name="moveUp">往上移動</string>
<string name="moveDown">往下移動</string>
<string name="lockScreen">禁止旋轉</string>
<string name="unlockScreen">允許旋轉</string>
<string name="ok">OK</string>
<string name="sendLabel">送出…</string>
<string name="scanCardBarcode">掃描卡片條碼</string>
<string name="noStoreError">尚未輸入卡片名稱</string>
<string name="importExportHelp">備份您的卡片以將這些卡片移至其他裝置中。</string>
<string name="noExternalStoragePermissionError">在匯入及匯出卡片前,請先允許外部儲存裝置存取權限</string>
<string name="importOptionFilesystemTitle">自檔案系統中匯入</string>
<string name="importOptionFilesystemExplanation">自檔案系統中選取檔案。</string>
<string name="importOptionFilesystemButton">自檔案系統</string>
<string name="importOptionApplicationTitle">使用其他應用程式</string>
<string name="importOptionApplicationButton">使用其他應用程式</string>
<string name="importOptionApplicationExplanation">使用任何應用程式選擇您所想要匯入的檔案。</string>
<string name="app_copyright_fmt">著作權所有 © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="importVoucherVault">自 Voucher Vault 中匯入</string>
<string name="importVoucherVaultMessage">選取您自 Voucher Vault 匯出的 <i>vouchervault.json</i> 檔案以進行匯入。
\n請您先透過 Voucher Vault 進行匯出。</string>
<string name="importStocard">自 Stocard 中匯入</string>
<string name="importStocardMessage">>選取您自 Stocard 匯出的 <i>***-sync.zip</i> 檔案以進行匯入。
\n請您寫封 Email 至 support@stocardapp.com 索取您的資料。</string>
<string name="importLoyaltyCardKeychain">自 Loyalty Card Keychain 中匯入</string>
<string name="importLoyaltyCardKeychainMessage">選取您自 Loyalty Card Keychain <i>LoyaltyCardKeychain.csv</i> 檔案以進行匯入。
\n請您先透過 Loyalty Card Keychain 的匯入/匯出選單進行匯出。</string>
<string name="importFidme">自 FidMe 匯入</string>
<string name="importFidmeMessage">選取您自 FidMe 匯出的<i>fidme-export-request-xxxxxx.zip</i> 檔案以進行匯入,並手動選擇條碼種類。
\n請您先透過您的 FidMe 個人檔案選取『Data Protection』並選擇『Extract my data』。</string>
<string name="importCatima">自 Catima 匯入</string>
<string name="importCatimaMessage">選取您自 Catima 匯出的 <i>catima.zip</i> 檔案以進行匯入。
\n您可透過其他裝置的 Catima 程式中的匯入/匯出選單進行匯出。</string>
<string name="points"></string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> 似乎不是個可用的餘額數值。</string>
<string name="app_revision_fmt">修訂版本資訊:<xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries">第三方自由函示庫:<xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources">第三方自由資源:<xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">選擇條碼</string>
<string name="noGroups">請先點選 + 加號按鈕新增群組。</string>
<string name="moveBarcodeToTopOfScreen">將條碼移至螢幕上方</string>
<string name="moveBarcodeToCenterOfScreen">將條碼移至螢幕中央</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="unsupportedBarcodeType">尚支援此條碼種類,但未來版本的應用程式可能會支援此條碼種類。</string>
<string name="wrongValueForBarcodeType">條碼內容不適用於此條碼種類</string>
<string name="backImageDescription">卡片 (背面)</string>
<string name="updateBarcodeQuestionText">您已更新了條碼 ID是否要更新條碼內容以匹配此 ID</string>
<string name="failedGeneratingShareURL">無法建立可分享的 URL請回報此錯誤。</string>
<string name="toggleMoreInfo">切換顯示更多內容</string>
<string name="swipeToSwitchImages">滑動或長按以切換圖片</string>
<string name="starImage">收藏標示</string>
</resources>

View File

@@ -40,15 +40,19 @@
<string-array name="locale_values">
<item />
<item>bg</item>
<item>bn-rIN</item>
<item>bs</item>
<item>cs</item>
<item>da</item>
<item>de</item>
<item>el-rGR</item>
<item>eo</item>
<item>es-rAR</item>
<item>es</item>
<item>es-rAR</item>
<item>fi</item>
<item>fr</item>
<item>he-rIL</item>
<item>in-rID</item>
<item>it</item>
<item>ja</item>
<item>ko</item>
@@ -57,11 +61,15 @@
<item>nl</item>
<item>oc</item>
<item>pl</item>
<item>pt</item>
<item>ro-rRO</item>
<item>ru</item>
<item>sk</item>
<item>sl</item>
<item>sv</item>
<item>tr</item>
<item>uk</item>
<item>zh-TW</item>
<item>zh-rCN</item>
</string-array>
@@ -82,4 +90,4 @@
<!-- Constraints -->
<integer name="settings_max_font_size_scale_pct_min">50</integer>
<integer name="settings_max_font_size_scale_pct_max">200</integer>
</resources>
</resources>

View File

@@ -1,27 +1,21 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"
xmlns:tools="http://schemas.android.com/tools">
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
<string name="action_search">Search</string>
<string name="action_add">Add</string>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> card selected</item>
<item quantity="other"><xliff:g>%d</xliff:g> cards selected</item>
</plurals>
<string name="noGiftCards">Click the + plus button to add a card, or import some from the ⋮ menu first.</string>
<string name="noMatchingGiftCards">Didn\'t find anything. Try changing your search.</string>
<string name="storeName">Name</string>
<string name="note">Note</string>
<string name="cardId">Card ID</string>
<string name="barcodeType">Barcode type</string>
<string name="barcodeNoBarcode">This card has no barcode</string>
<string name="noBarcode">No barcode</string>
<string name="star">Add to favorites</string>
<string name="unstar">Remove from favorites</string>
<string name="cancel">Cancel</string>
<string name="save">Save</string>
<string name="edit">Edit</string>
@@ -48,16 +42,14 @@
<string name="ok">OK</string>
<string name="copy_to_clipboard">Copy ID to clipboard</string>
<string name="share">Share</string>
<string name="sendLabel">Send&#8230;</string>
<string name="sendLabel">Send</string>
<string name="editCardTitle">Edit Card</string>
<string name="addCardTitle">Add Card</string>
<string name="scanCardBarcode">Scan Card Barcode</string>
<string name="cardShortcut">Card Shortcut</string>
<string name="noCardsMessage">Add a card first</string>
<string name="card_ids_copied">Copied Card ID(s)</string>
<string name="barcodeImageDescriptionWithType">Image of card barcode of type <xliff:g>%s</xliff:g></string>
<string name="noStoreError">No name entered</string>
<string name="noCardIdError">No card ID entered</string>
<string name="noCardExistsError">Could not find card</string>
@@ -71,8 +63,8 @@
<string name="exportSuccessfulTitle">Exported</string>
<string name="exportFailedTitle">Export failed</string>
<string name="exportFailed">Could not export cards</string>
<string name="importing">Importing&#8230;</string>
<string name="exporting">Exporting&#8230;</string>
<string name="importing">Importing</string>
<string name="exporting">Exporting</string>
<string name="noExternalStoragePermissionError">Grant external storage permission to import or export cards first</string>
<string name="exportOptionExplanation">The data will be written to a location of your choice.</string>
<string name="importOptionFilesystemTitle">Import from filesystem</string>
@@ -81,25 +73,20 @@
<string name="importOptionApplicationTitle">Use another app</string>
<string name="importOptionApplicationExplanation">Use any app or your favorite file manager to open a file.</string>
<string name="importOptionApplicationButton">Use another app</string>
<string name="about">About</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os.</string>
<string name="app_copyright_old">Based on Loyalty Card Keychain\ncopyright © 20162020 Branden Archer.</string>
<string name="app_license">Copylefted libre software, licensed GPLv3+.</string>
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019<xliff:g>%d</xliff:g> Sylvia van Os</string>
<string name="app_copyright_old">Based on Loyalty Card Keychain\ncopyright © 20162020 Branden Archer</string>
<string name="app_license">Copylefted libre software, licensed GPLv3+</string>
<string name="about_title_fmt">About <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Revision Info: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries">Libre third-party libraries: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources">Libre third-party resources: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Select Barcode</string>
<string name="enterBarcodeInstructions">Enter the card ID, and either pick its barcode type below, or &#8220;This card has no barcode&#8221;.</string>
<string name="enterBarcodeInstructions">Enter the card ID, and either pick its barcode type below, or This card has no barcode.</string>
<string name="copy_to_clipboard_toast">Card ID copied to clipboard</string>
<string name="thumbnailDescription">Thumbnail for card</string>
<string name="starImage">Favorite star</string>
<string name="settings">Settings</string>
<string name="settings_category_title_ui">User interface</string>
<string name="settings_theme">Theme</string>
@@ -112,7 +99,6 @@
<string name="settings_key_dark_theme" translatable="false">dark</string>
<string name="settings_key_max_font_size_scale" translatable="false">pref_max_font_size_scale</string>
<string name="settings_max_font_size_scale">Max. font size</string>
<string name="settings_display_barcode_max_brightness">Brighten barcode view</string>
<string name="settings_key_display_barcode_max_brightness" translatable="false">pref_display_card_max_brightness</string>
<string name="settings_lock_barcode_orientation">Lock barcode orientation</string>
@@ -121,13 +107,11 @@
<string name="settings_key_keep_screen_on" translatable="false">pref_keep_screen_on</string>
<string name="settings_disable_lockscreen_while_viewing_card">Prevent lock screen</string>
<string name="settings_key_disable_lockscreen_while_viewing_card" translatable="false">pref_disable_lockscreen_while_viewing_card</string>
<string name="sharedpreference_active_tab" translatable="false">sharedpreference_active_tab</string>
<string name="sharedpreference_privacy_policy_shown" translatable="false">sharedpreference_privacy_policy_shown</string>
<string name="sharedpreference_sort" translatable="false">sharedpreference_sort</string>
<string name="sharedpreference_sort_order" translatable="false">sharedpreference_sort_order</string>
<string name="sharedpreference_sort_direction" translatable="false">sharedpreference_sort_direction</string>
<string name="intent_import_card_from_url_share_text">I want to share a card with you</string>
<string name="intent_import_card_from_url_host_catima_app" translatable="false">catima.app</string>
<string name="intent_import_card_from_url_path_prefix_catima_app" translatable="false">/share</string>
@@ -137,7 +121,6 @@
<string name="intent_import_card_from_url_path_prefix_brarcher" translatable="false">/loyalty-card-locker/share</string>
<string name="importSuccessful">Card data imported</string>
<string name="exportSuccessful">Card data exported</string>
<string name="enter_group_name">Enter group name</string>
<string name="groups">Groups</string>
<string name="noGroups">Click the + plus button to add groups for categorization first.</string>
@@ -146,7 +129,6 @@
<item quantity="one"><xliff:g>%d</xliff:g> card</item>
<item quantity="other"><xliff:g>%d</xliff:g> cards</item>
</plurals>
<string name="all">All</string>
<string name="deleteConfirmationGroup">Delete group?</string>
<string name="failedOpeningFileManager">Install a file manager first.</string>
@@ -161,7 +143,6 @@
<string name="expiryStateSentenceExpired">Expired: <xliff:g>%s</xliff:g></string>
<string name="balanceSentence">Balance: <xliff:g>%s</xliff:g></string>
<string name="balancePoints"><xliff:g>%s</xliff:g> points</string>
<string name="card">Card</string>
<string name="barcode">Barcode</string>
<string name="editBarcode">Edit barcode</string>
@@ -170,31 +151,32 @@
<string name="chooseExpiryDate">Choose expiry date</string>
<string name="moveBarcodeToTopOfScreen">Move the barcode to the top of the screen</string>
<string name="moveBarcodeToCenterOfScreen">Center the barcode on the screen</string>
<string name="noBarcodeFound">No barcode was found</string>
<string name="errorReadingImage">Could not read the image</string>
<string name="balance">Balance</string>
<string name="currency">Currency</string>
<string name="points">Points</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> does not seem to be a valid balance.</string>
<string name="chooseImportType">Import data from?</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="privacy_policy">Privacy Policy</string>
<string name="privacy_policy_popup_text">Privacy policy notice (required by some app stores):\n\nNO DATA IS COLLECTED AT ALL, which anyone can confirm since our app is libre software.</string>
<string name="accept">Accept</string>
<string name="importCatima">Import from Catima</string>
<string name="importCatimaMessage">Select your <i>catima.zip</i> export from Catima to import.\nOr create it from the "Import/Export" menu of another Catima app by pressing "Export" there first.</string>
<string name="importCatimaMessage">Select your <i>catima.zip</i> export from Catima to import.
\nCreate it from the Import/Export menu of another Catima app by pressing Export there first.</string>
<string name="importFidme">Import from FidMe</string>
<string name="importFidmeMessage">Select your <i>fidme-export-request-xxxxxx.zip</i> export from FidMe to import, and select the barcode types manually afterwards.\nOr create it from your FidMe profile by choosing "Data Protection" and then pressing "Extract my data" first.</string>
<string name="importFidmeMessage">Select your <i>fidme-export-request-xxxxxx.zip</i> export from FidMe to import, and select the barcode types manually afterwards.
\nCreate it from your FidMe profile by choosing Data Protection and then pressing Extract my data first.</string>
<string name="importLoyaltyCardKeychain">Import from Loyalty Card Keychain</string>
<string name="importLoyaltyCardKeychainMessage">Select your <i>LoyaltyCardKeychain.csv</i> export from Loyalty Card Keychain to import.\nOr create it from the "Import/Export" menu in Loyalty Card Keychain by pressing "Export" there first.</string>
<string name="importLoyaltyCardKeychainMessage">Select your <i>LoyaltyCardKeychain.csv</i> export from Loyalty Card Keychain to import.
\nCreate it from the Import/Export menu in Loyalty Card Keychain by pressing Export there first.</string>
<string name="importStocard">Import from Stocard</string>
<string name="importStocardMessage">Select your <i>***-sync.zip</i> export from Stocard to import.\nOr get it by e-mailing support@stocardapp.com asking for an export of your data.</string>
<string name="importStocardMessage">Select your <i>***-sync.zip</i> export from Stocard to import.
\nGet it by e-mailing support@stocardapp.com asking for an export of your data.</string>
<string name="importVoucherVault">Import from Voucher Vault</string>
<string name="importVoucherVaultMessage">Select your <i>vouchervault.json</i> export from Voucher Vault to import.\nOr create it by pressing "Export" in Voucher Vault first.</string>
<string name="importVoucherVaultMessage">Select your <i>vouchervault.json</i> export from Voucher Vault to import.
\nCreate it by pressing Export in Voucher Vault first.</string>
<string name="barcodeId">Barcode value</string>
<string name="sameAsCardId">Same as card ID</string>
<string name="setBarcodeId">Set barcode value</string>
@@ -214,13 +196,14 @@
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="passwordRequired">Please enter the password</string>
<string name="exportPassword">Set a password to protect your export (optional)</string>
<string name="exportPasswordHint">Enter password</string>
<string name="failedGeneratingShareURL">Could not generate sharable URL. Please report this.</string>
<string name="turn_flashlight_on">Turn flashlight on</string>
<string name="turn_flashlight_off">Turn flashlight off</string>
<string name="settings_locale">Language</string>
<string name="settings_key_locale" translatable="false">pref_locale</string>
<string name="settings_system_locale">System</string>
<string name="setting_key_theme_color" translatable="false">pref_theme_color</string>
<string name="settings_theme_color">Theme color</string>
<string name="settings_catima_theme">Catima</string>
@@ -243,7 +226,6 @@
<string name="settings_key_brown_theme" translatable="false">brown_theme</string>
<string name="app_contributors">Made possible by: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="sort">Sort</string>
<string name="toggleMoreInfo">Toggle showing more info</string>
<string name="swipeToSwitchImages">Swipe or long press to switch images</string>
<string name="sort_by_name">Name</string>
@@ -252,4 +234,15 @@
<string name="sort_by_balance">Balance</string>
<string name="reverse">Reverse</string>
<string name="sort_by">Sort by</string>
<string name="version_history">Version History</string>
<string name="arrow" translatable="false"><![CDATA[>]]></string>
<string name="credits">Credits</string>
<string name="help_translate_this_app">Help translate this app</string>
<string name="license">License</string>
<string name="source_repository">Source Repository</string>
<string name="on_github">on GitHub</string>
<string name="and_data_usage">and data usage</string>
<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>
</resources>

View File

@@ -82,8 +82,14 @@
<item name="windowNoTitle">true</item>
</style>
<style name="SplashTheme" parent="@style/AppTheme">
<item name="android:windowBackground">@drawable/background_splash</item>
<!-- Splash Screen Theme-->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/ic_launcher_background</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="postSplashScreenTheme">@style/AppTheme</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.MaterialComponents.Dark.ActionBar"/>

View File

@@ -2,7 +2,6 @@ package protect.card_locker;
import android.app.Activity;
import android.content.Intent;
import android.os.Looper;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
@@ -13,16 +12,19 @@ import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLooper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.robolectric.Shadows.shadowOf;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 23)
public class BarcodeSelectorActivityTest {
@Test
public void emptyStateTest()
{
public void emptyStateTest() {
ActivityController activityController = Robolectric.buildActivity(BarcodeSelectorActivity.class).create();
activityController.start();
activityController.resume();
@@ -41,8 +43,7 @@ public class BarcodeSelectorActivityTest {
}
@Test
public void nonEmptyStateTest() throws InterruptedException
{
public void nonEmptyStateTest() throws InterruptedException {
ActivityController activityController = Robolectric.buildActivity(BarcodeSelectorActivity.class).create();
activityController.start();
activityController.resume();
@@ -54,11 +55,12 @@ public class BarcodeSelectorActivityTest {
cardId.setText("abcdefg");
shadowOf(Looper.getMainLooper()).idle();
// Run the delayed Handler
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
// Button should be visible and enabled
assertEquals(View.VISIBLE, noBarcodeButton.getVisibility());
assertEquals(true, noBarcodeButton.isEnabled());
assertTrue(noBarcodeButton.isEnabled());
// Clicking button should create "empty" barcode
activity.findViewById(R.id.noBarcode).performClick();
@@ -70,8 +72,7 @@ public class BarcodeSelectorActivityTest {
}
@Test
public void nonEmptyToEmptyStateTest() throws InterruptedException
{
public void nonEmptyToEmptyStateTest() throws InterruptedException {
ActivityController activityController = Robolectric.buildActivity(BarcodeSelectorActivity.class).create();
activityController.start();
activityController.resume();
@@ -83,18 +84,20 @@ public class BarcodeSelectorActivityTest {
cardId.setText("abcdefg");
shadowOf(Looper.getMainLooper()).idle();
// Run the delayed Handler
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
// Button should be visible and enabled
assertEquals(View.VISIBLE, noBarcodeButton.getVisibility());
assertEquals(true, noBarcodeButton.isEnabled());
assertTrue(noBarcodeButton.isEnabled());
cardId.setText("");
shadowOf(Looper.getMainLooper()).idle();
// Run the delayed Handler
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
// Button should be visible but disabled
assertEquals(View.VISIBLE, noBarcodeButton.getVisibility());
assertEquals(false, noBarcodeButton.isEnabled());
assertFalse(noBarcodeButton.isEnabled());
}
}

View File

@@ -270,6 +270,7 @@ public class DatabaseTest
database.execSQL("drop table " + DBHelper.LoyaltyCardDbIds.TABLE);
database.execSQL("drop table " + DBHelper.LoyaltyCardDbGroups.TABLE);
database.execSQL("drop table " + DBHelper.LoyaltyCardDbIdsGroups.TABLE);
database.execSQL("drop table " + DBHelper.LoyaltyCardDbFTS.TABLE);
// Create the table as it existed in revision 1
database.execSQL("create table " + DBHelper.LoyaltyCardDbIds.TABLE + "(" +
@@ -502,6 +503,8 @@ 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);
// Determine that the entries are queryable and the fields are correct
LoyaltyCard card2 = db.getLoyaltyCard(newCardId2);
@@ -515,6 +518,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);
database.close();
}

View File

@@ -7,6 +7,7 @@ import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.Environment;
import android.os.Looper;
import android.util.DisplayMetrics;
import com.google.zxing.BarcodeFormat;
@@ -20,6 +21,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.LooperMode;
import org.robolectric.shadows.ShadowLog;
import org.robolectric.shadows.ShadowLooper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -33,6 +35,7 @@ import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -42,6 +45,8 @@ 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;
import protect.card_locker.importexport.MultiFormatExporter;
@@ -51,11 +56,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.robolectric.Shadows.shadowOf;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 23)
public class ImportExportTest
{
public class ImportExportTest {
private Activity activity;
private DBHelper db;
private long nowMs;
@@ -66,8 +71,7 @@ public class ImportExportTest
private final CatimaBarcode BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A);
@Before
public void setUp()
{
public void setUp() {
ShadowLog.stream = System.out;
activity = Robolectric.setupActivity(MainActivity.class);
@@ -75,20 +79,19 @@ public class ImportExportTest
nowMs = System.currentTimeMillis();
Calendar lastYear = Calendar.getInstance();
lastYear.set(Calendar.YEAR, lastYear.get(Calendar.YEAR)-1);
lastYear.set(Calendar.YEAR, lastYear.get(Calendar.YEAR) - 1);
lastYearMs = lastYear.getTimeInMillis();
}
/**
* Add the given number of cards, each with
* an index in the store name.
*
* @param cardsToAdd
*/
private void addLoyaltyCards(int cardsToAdd)
{
private void addLoyaltyCards(int cardsToAdd) {
// Add in reverse order to test sorting
for(int index = cardsToAdd; index > 0; index--)
{
for (int index = cardsToAdd; index > 0; index--) {
String storeName = String.format("store, \"%4d", index);
String note = String.format("note, \"%4d", index);
long id = db.insertLoyaltyCard(storeName, note, null, new BigDecimal(String.valueOf(index)), null, BARCODE_DATA, null, BARCODE_TYPE, index, 0, null);
@@ -99,20 +102,17 @@ public class ImportExportTest
assertEquals(cardsToAdd, db.getLoyaltyCardCount());
}
private void addLoyaltyCardsFiveStarred()
{
private void addLoyaltyCardsFiveStarred() {
int cardsToAdd = 9;
// Add in reverse order to test sorting
for(int index = cardsToAdd; index > 4; index--)
{
for (int index = cardsToAdd; index > 4; index--) {
String storeName = String.format("store, \"%4d", index);
String note = String.format("note, \"%4d", index);
long id = db.insertLoyaltyCard(storeName, note, null, new BigDecimal(String.valueOf(index)), null, BARCODE_DATA, null, BARCODE_TYPE, index, 1, null);
boolean result = (id != -1);
assertTrue(result);
}
for(int index = cardsToAdd-5; index > 0; index--)
{
for (int index = cardsToAdd - 5; index > 0; index--) {
String storeName = String.format("store, \"%4d", index);
String note = String.format("note, \"%4d", index);
//if index is even
@@ -124,8 +124,7 @@ public class ImportExportTest
}
@Test
public void addLoyaltyCardsWithExpiryNeverPastTodayFuture()
{
public void addLoyaltyCardsWithExpiryNeverPastTodayFuture() {
long id = db.insertLoyaltyCard("No Expiry", "", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null);
boolean result = (id != -1);
assertTrue(result);
@@ -165,8 +164,8 @@ public class ImportExportTest
card = db.getLoyaltyCard((int) id);
assertEquals("Today", card.store);
assertEquals("", card.note);
assertTrue(card.expiry.before(new Date(new Date().getTime()+86400)));
assertTrue(card.expiry.after(new Date(new Date().getTime()-86400)));
assertTrue(card.expiry.before(new Date(new Date().getTime() + 86400)));
assertTrue(card.expiry.after(new Date(new Date().getTime() - 86400)));
assertEquals(new BigDecimal("0"), card.balance);
assertEquals(null, card.balanceType);
assertEquals(BARCODE_DATA, card.cardId);
@@ -184,7 +183,7 @@ public class ImportExportTest
card = db.getLoyaltyCard((int) id);
assertEquals("Future", card.store);
assertEquals("", card.note);
assertTrue(card.expiry.after(new Date(new Date().getTime()+86400)));
assertTrue(card.expiry.after(new Date(new Date().getTime() + 86400)));
assertEquals(new BigDecimal("0"), card.balance);
assertEquals(null, card.balanceType);
assertEquals(BARCODE_DATA, card.cardId);
@@ -196,11 +195,9 @@ public class ImportExportTest
assertEquals(4, db.getLoyaltyCardCount());
}
private void addGroups(int groupsToAdd)
{
private void addGroups(int groupsToAdd) {
// Add in reverse order to test sorting
for(int index = groupsToAdd; index > 0; index--)
{
for (int index = groupsToAdd; index > 0; index--) {
String groupName = String.format("group, \"%4d", index);
long id = db.insertGroup(groupName);
boolean result = (id != -1);
@@ -215,13 +212,11 @@ public class ImportExportTest
* specified in addLoyaltyCards(), and are in sequential order
* where the smallest card's index is 1
*/
private void checkLoyaltyCards()
{
private void checkLoyaltyCards() {
Cursor cursor = db.getLoyaltyCardCursor();
int index = 1;
while(cursor.moveToNext())
{
while (cursor.moveToNext()) {
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cursor);
String expectedStore = String.format("store, \"%4d", index);
@@ -248,13 +243,11 @@ public class ImportExportTest
* specified in addLoyaltyCardsSomeStarred(), and are in sequential order
* with starred ones first
*/
private void checkLoyaltyCardsFiveStarred()
{
Cursor cursor = db.getLoyaltyCardCursor();
int index = 5;
private void checkLoyaltyCardsFiveStarred() {
Cursor cursor = db.getLoyaltyCardCursor();
int index = 5;
while(index<10)
{
while (index < 10) {
cursor.moveToNext();
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cursor);
@@ -276,26 +269,25 @@ public class ImportExportTest
}
index = 1;
while(cursor.moveToNext() && index<5)
{
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cursor);
while (cursor.moveToNext() && index < 5) {
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cursor);
String expectedStore = String.format("store, \"%4d", index);
String expectedNote = String.format("note, \"%4d", index);
String expectedStore = String.format("store, \"%4d", index);
String expectedNote = String.format("note, \"%4d", index);
assertEquals(expectedStore, card.store);
assertEquals(expectedNote, card.note);
assertEquals(null, card.expiry);
assertEquals(new BigDecimal(String.valueOf(index)), card.balance);
assertEquals(null, card.balanceType);
assertEquals(BARCODE_DATA, card.cardId);
assertEquals(null, card.barcodeId);
assertEquals(BARCODE_TYPE.format(), card.barcodeType.format());
assertEquals(Integer.valueOf(index), card.headerColor);
assertEquals(0, card.starStatus);
assertEquals(expectedStore, card.store);
assertEquals(expectedNote, card.note);
assertEquals(null, card.expiry);
assertEquals(new BigDecimal(String.valueOf(index)), card.balance);
assertEquals(null, card.balanceType);
assertEquals(BARCODE_DATA, card.cardId);
assertEquals(null, card.barcodeId);
assertEquals(BARCODE_TYPE.format(), card.barcodeType.format());
assertEquals(Integer.valueOf(index), card.headerColor);
assertEquals(0, card.starStatus);
index++;
}
index++;
}
cursor.close();
}
@@ -305,13 +297,11 @@ public class ImportExportTest
* specified in addGroups(), and are in sequential order
* where the smallest group's index is 1
*/
private void checkGroups()
{
private void checkGroups() {
Cursor cursor = db.getGroupCursor();
int index = db.getGroupCount();
while(cursor.moveToNext())
{
while (cursor.moveToNext()) {
Group group = Group.toGroup(cursor);
String expectedGroupName = String.format("group, \"%4d", index);
@@ -324,8 +314,7 @@ public class ImportExportTest
}
@Test
public void multipleCardsExportImport() throws IOException
{
public void multipleCardsExportImport() throws IOException {
final int NUM_CARDS = 10;
addLoyaltyCards(NUM_CARDS);
@@ -334,7 +323,7 @@ public class ImportExportTest
OutputStreamWriter outStream = new OutputStreamWriter(outData);
// Export data to CSV format
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima, null);
assertEquals(ImportExportResult.Success, result);
outStream.close();
@@ -354,9 +343,40 @@ public class ImportExportTest
TestHelpers.getEmptyDb(activity);
}
public void multipleCardsExportImportPasswordProtected() throws IOException {
final int NUM_CARDS = 10;
List<char[]> passwords = Arrays.asList(null, "123456789".toCharArray());
for (char[] password : passwords) {
addLoyaltyCards(NUM_CARDS);
ByteArrayOutputStream outData = new ByteArrayOutputStream();
OutputStreamWriter outStream = new OutputStreamWriter(outData);
// Export data to CSV format
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima, password);
assertEquals(ImportExportResult.Success, result);
outStream.close();
TestHelpers.getEmptyDb(activity);
ByteArrayInputStream inData = new ByteArrayInputStream(outData.toByteArray());
// Import the CSV data
result = MultiFormatImporter.importData(activity.getApplicationContext(), db, inData, DataFormat.Catima, password);
assertEquals(ImportExportResult.Success, result);
assertEquals(NUM_CARDS, db.getLoyaltyCardCount());
checkLoyaltyCards();
// Clear the database for the next format under test
TestHelpers.getEmptyDb(activity);
}
}
@Test
public void multipleCardsExportImportSomeStarred() throws IOException
{
public void multipleCardsExportImportSomeStarred() throws IOException {
final int NUM_CARDS = 9;
addLoyaltyCardsFiveStarred();
@@ -365,7 +385,7 @@ public class ImportExportTest
OutputStreamWriter outStream = new OutputStreamWriter(outData);
// Export data to CSV format
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima, null);
assertEquals(ImportExportResult.Success, result);
outStream.close();
@@ -385,8 +405,7 @@ public class ImportExportTest
TestHelpers.getEmptyDb(activity);
}
private List<String> groupsToGroupNames(List<Group> groups)
{
private List<String> groupsToGroupNames(List<Group> groups) {
List<String> groupNames = new ArrayList<>();
for (Group group : groups) {
@@ -397,8 +416,7 @@ public class ImportExportTest
}
@Test
public void multipleCardsExportImportWithGroups() throws IOException
{
public void multipleCardsExportImportWithGroups() throws IOException {
final int NUM_CARDS = 10;
final int NUM_GROUPS = 3;
@@ -438,7 +456,7 @@ public class ImportExportTest
OutputStreamWriter outStream = new OutputStreamWriter(outData);
// Export data to CSV format
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima, null);
assertEquals(ImportExportResult.Success, result);
outStream.close();
@@ -472,8 +490,7 @@ public class ImportExportTest
}
@Test
public void importExistingCardsNotReplace() throws IOException
{
public void importExistingCardsNotReplace() throws IOException {
final int NUM_CARDS = 10;
addLoyaltyCards(NUM_CARDS);
@@ -482,7 +499,7 @@ public class ImportExportTest
OutputStreamWriter outStream = new OutputStreamWriter(outData);
// Export into CSV data
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima, null);
assertEquals(ImportExportResult.Success, result);
outStream.close();
@@ -501,19 +518,17 @@ public class ImportExportTest
}
@Test
public void corruptedImportNothingSaved() throws IOException
{
public void corruptedImportNothingSaved() throws IOException {
final int NUM_CARDS = 10;
for(DataFormat format : DataFormat.values())
{
for (DataFormat format : DataFormat.values()) {
addLoyaltyCards(NUM_CARDS);
ByteArrayOutputStream outData = new ByteArrayOutputStream();
OutputStreamWriter outStream = new OutputStreamWriter(outData);
// Export data to CSV format
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima);
ImportExportResult result = MultiFormatExporter.exportData(activity.getApplicationContext(), db, outData, DataFormat.Catima, null);
assertEquals(ImportExportResult.Success, result);
TestHelpers.getEmptyDb(activity);
@@ -536,20 +551,17 @@ public class ImportExportTest
}
}
class TestTaskCompleteListener implements ImportExportTask.TaskCompleteListener
{
class TestTaskCompleteListener implements ImportExportTask.TaskCompleteListener {
ImportExportResult result;
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat)
{
public void onTaskComplete(ImportExportResult result, DataFormat dataFormat) {
this.result = result;
}
}
@Test
@LooperMode(LooperMode.Mode.LEGACY)
public void useImportExportTask() throws FileNotFoundException
{
@LooperMode(LooperMode.Mode.PAUSED)
public void useImportExportTask() throws FileNotFoundException {
final int NUM_CARDS = 10;
final File sdcardDir = Environment.getExternalStorageDirectory();
@@ -560,12 +572,17 @@ public class ImportExportTest
TestTaskCompleteListener listener = new TestTaskCompleteListener();
// Export to the file
final String password = "123456789";
FileOutputStream fileOutputStream = new FileOutputStream(exportFile);
ImportExportTask task = new ImportExportTask(activity, DataFormat.Catima, fileOutputStream, listener);
task.execute();
ImportExportTask task = new ImportExportTask(activity, DataFormat.Catima, fileOutputStream, password.toCharArray(), listener);
TaskHandler mTasks = new TaskHandler();
mTasks.executeTask(TaskHandler.TYPE.EXPORT, task);
// Actually run the task to completion
Robolectric.flushBackgroundThreadScheduler();
mTasks.flushTaskList(TaskHandler.TYPE.EXPORT, false, false, true);
shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(5000));
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
// Check that the listener was executed
assertNotNull(listener.result);
@@ -579,11 +596,14 @@ public class ImportExportTest
FileInputStream fileStream = new FileInputStream(exportFile);
task = new ImportExportTask(activity, DataFormat.Catima, fileStream, null, listener);
task.execute();
task = new ImportExportTask(activity, DataFormat.Catima, fileStream, password.toCharArray(), listener);
mTasks.executeTask(TaskHandler.TYPE.IMPORT, task);
// Actually run the task to completion
Robolectric.flushBackgroundThreadScheduler();
// I am CONVINCED there must be a better way than to wait on this Queue with a flush.
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, false, false, true);
shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(5000));
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
// Check that the listener was executed
assertNotNull(listener.result);
@@ -598,8 +618,7 @@ public class ImportExportTest
}
@Test
public void importWithoutColorsV1() throws IOException
{
public void importWithoutColorsV1() throws IOException {
String csvText = "";
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
DBHelper.LoyaltyCardDbIds.STORE + "," +
@@ -634,8 +653,7 @@ public class ImportExportTest
}
@Test
public void importWithoutNullColorsV1() throws IOException
{
public void importWithoutNullColorsV1() throws IOException {
String csvText = "";
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
DBHelper.LoyaltyCardDbIds.STORE + "," +
@@ -672,8 +690,7 @@ public class ImportExportTest
}
@Test
public void importWithoutInvalidColorsV1() throws IOException
{
public void importWithoutInvalidColorsV1() throws IOException {
String csvText = "";
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
DBHelper.LoyaltyCardDbIds.STORE + "," +
@@ -697,8 +714,7 @@ public class ImportExportTest
}
@Test
public void importWithNoBarcodeTypeV1() throws IOException
{
public void importWithNoBarcodeTypeV1() throws IOException {
String csvText = "";
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
DBHelper.LoyaltyCardDbIds.STORE + "," +
@@ -735,8 +751,7 @@ public class ImportExportTest
}
@Test
public void importWithStarredFieldV1() throws IOException
{
public void importWithStarredFieldV1() throws IOException {
String csvText = "";
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
DBHelper.LoyaltyCardDbIds.STORE + "," +
@@ -773,8 +788,7 @@ public class ImportExportTest
}
@Test
public void importWithNoStarredFieldV1() throws IOException
{
public void importWithNoStarredFieldV1() throws IOException {
String csvText = "";
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
DBHelper.LoyaltyCardDbIds.STORE + "," +
@@ -811,8 +825,7 @@ public class ImportExportTest
}
@Test
public void importWithInvalidStarFieldV1() throws IOException
{
public void importWithInvalidStarFieldV1() throws IOException {
String csvText = "";
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
DBHelper.LoyaltyCardDbIds.STORE + "," +
@@ -868,8 +881,7 @@ public class ImportExportTest
}
@Test
public void exportImportV2Zip() throws FileNotFoundException
{
public void exportImportV2Zip() throws FileNotFoundException {
// Prepare images
BitmapDrawable launcher = (BitmapDrawable) ResourcesCompat.getDrawableForDensity(activity.getResources(), R.mipmap.ic_launcher, DisplayMetrics.DENSITY_XXXHIGH, activity.getTheme());
BitmapDrawable roundLauncher = (BitmapDrawable) ResourcesCompat.getDrawableForDensity(activity.getResources(), R.mipmap.ic_launcher_round, DisplayMetrics.DENSITY_XXXHIGH, activity.getTheme());
@@ -901,7 +913,7 @@ public class ImportExportTest
// Export everything
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
MultiFormatExporter.exportData(activity.getApplicationContext(), db, outputStream, DataFormat.Catima);
MultiFormatExporter.exportData(activity.getApplicationContext(), db, outputStream, DataFormat.Catima, null);
// Wipe database
TestHelpers.getEmptyDb(activity);
@@ -925,25 +937,25 @@ public class ImportExportTest
assertEquals(loyaltyCard.cardId, dbLoyaltyCard.cardId);
assertEquals(loyaltyCard.barcodeId, dbLoyaltyCard.barcodeId);
assertEquals(loyaltyCard.starStatus, dbLoyaltyCard.starStatus);
assertEquals(loyaltyCard.barcodeType != null ? loyaltyCard.barcodeType.format() : null, dbLoyaltyCard.barcodeType != null? dbLoyaltyCard.barcodeType.format() : null);
assertEquals(loyaltyCard.barcodeType != null ? loyaltyCard.barcodeType.format() : null, dbLoyaltyCard.barcodeType != null ? dbLoyaltyCard.barcodeType.format() : null);
assertEquals(loyaltyCard.balanceType, dbLoyaltyCard.balanceType);
assertEquals(loyaltyCard.headerColor, dbLoyaltyCard.headerColor);
List<Group> emptyGroup = new ArrayList<>();
assertEquals(
groupsToGroupNames(
(List<Group>) Utils.mapGetOrDefault(
loyaltyCardGroups,
loyaltyCardID,
emptyGroup
groupsToGroupNames(
(List<Group>) Utils.mapGetOrDefault(
loyaltyCardGroups,
loyaltyCardID,
emptyGroup
)
),
groupsToGroupNames(
db.getLoyaltyCardGroups(
loyaltyCardID
)
)
),
groupsToGroupNames(
db.getLoyaltyCardGroups(
loyaltyCardID
)
)
);
Bitmap expectedFrontImage = loyaltyCardFrontImages.get(loyaltyCardID);
@@ -966,8 +978,7 @@ public class ImportExportTest
}
@Test
public void importV2CSV()
{
public void importV2CSV() {
String csvText = "2\n" +
"\n" +
"_id\n" +

View File

@@ -59,12 +59,11 @@ public class MainActivityTest
assertNotNull(menu);
// The settings, import/export, groups, search and add button should be present
assertEquals(menu.size(), 7);
assertEquals(menu.size(), 6);
assertEquals("Search", menu.findItem(R.id.action_search).getTitle().toString());
assertEquals("Sort", menu.findItem(R.id.action_sort).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("Privacy Policy", menu.findItem(R.id.action_privacy_policy).getTitle().toString());
assertEquals("About", menu.findItem(R.id.action_about).getTitle().toString());
assertEquals("Settings", menu.findItem(R.id.action_settings).getTitle().toString());
}
@@ -361,7 +360,7 @@ public class MainActivityTest
assertEquals(View.GONE, helpText.getVisibility());
assertEquals(View.VISIBLE, noMatchingCardsText.getVisibility());
assertEquals(View.VISIBLE, list.getVisibility());
assertEquals(View.GONE, list.getVisibility());
assertEquals(0, list.getAdapter().getItemCount());
@@ -383,7 +382,7 @@ public class MainActivityTest
assertEquals(View.GONE, helpText.getVisibility());
assertEquals(View.VISIBLE, noMatchingCardsText.getVisibility());
assertEquals(View.VISIBLE, list.getVisibility());
assertEquals(View.GONE, list.getVisibility());
assertEquals(0, list.getAdapter().getItemCount());
@@ -397,7 +396,7 @@ public class MainActivityTest
assertEquals(View.GONE, helpText.getVisibility());
assertEquals(View.VISIBLE, noMatchingCardsText.getVisibility());
assertEquals(View.VISIBLE, list.getVisibility());
assertEquals(View.GONE, list.getVisibility());
assertEquals(0, list.getAdapter().getItemCount());
@@ -406,7 +405,7 @@ public class MainActivityTest
assertEquals(View.GONE, helpText.getVisibility());
assertEquals(View.VISIBLE, noMatchingCardsText.getVisibility());
assertEquals(View.VISIBLE, list.getVisibility());
assertEquals(View.GONE, list.getVisibility());
assertEquals(0, list.getAdapter().getItemCount());

2
bors.toml Normal file
View File

@@ -0,0 +1,2 @@
status = [ 'build' ]
delete_merged_branches = true

View File

@@ -9,8 +9,8 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.1'
classpath 'gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.7.0'
classpath 'com.android.tools.build:gradle:7.0.3'
classpath 'gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.7.5'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -24,6 +24,9 @@ allprojects {
maven { url "https://jitpack.io" }
gradlePluginPortal()
}
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:deprecation"
}
}
task clean(type: Delete) {

View File

@@ -4,6 +4,7 @@ Copylefted libre software (GPLv3+) card management app.
[![GitHub Version](https://img.shields.io/github/v/release/TheLastProject/Catima.svg?logo=github&label=GitHub)](https://github.com/TheLastProject/Catima/releases)
[![F-Droid Version](https://img.shields.io/f-droid/v/me.hackerchick.catima.svg?logo=f-droid&label=F-Droid)](https://f-droid.org/packages/me.hackerchick.catima/)
[![IzzyOnDroid Version](https://img.shields.io/endpoint?url=https://apt.izzysoft.de/fdroid/api/v1/shield/me.hackerchick.catima)](https://apt.izzysoft.de/fdroid/index/apk/me.hackerchick.catima)
[![Google Play Store Version](https://img.shields.io/endpoint?color=blue&logo=google-play&url=https%3A%2F%2Fplayshields.herokuapp.com%2Fplay%3Fi%3Dme.hackerchick.catima%26l%3DGoogle%2520Play%26m%3D%24version)](https://play.google.com/store/apps/details?id=me.hackerchick.catima)
![Android CI](https://github.com/TheLastProject/Catima/workflows/Android%20CI/badge.svg)

View File

@@ -0,0 +1 @@
- Подобрено е търсенето, съдържащо знак за интервал

View File

@@ -1,23 +1,22 @@
Спрете да търсите пластмасови карти за възнаграждение по време на плащане в магазин или в интернет магазин.
<b>Сканирайте баркодовете на устройството си с помощта на неговата камера и забравете за картите.</b>
😺
Забравете за портфейла си или го запазете ултралек за ценни вещи.
😺
Спрете да търсите пластмасови карти за възнаграждение докато плащате в магазина или в мрежата.
<b>Сканирайте щрихкодовете на устройството си с помощта на камерата и забравете за пластмасовите карти.</b>
Забравете за портфейла си или го запазете лек за ценни вещи.
С този основен инструмент за ежедневно носене (EDC) можете да замените безполезната пластмаса с пари в брой.
😺
- Избягвайте шпионирането с много малко разрешения. Без достъп до интернет и без реклами.
- Добавете карти или кодове с имена и цветове, които можете да персонализирате.
- Ръчно въвеждане на код, ако няма баркод за съхранение или той не може да се използва.
- Импортиране на карти и кодове от файлове, Catima, FidMe, Loyalty Card Keychain, Stocard и Voucher Vault.
- Направете резервно копие на всичките си карти и ги прехвърлете на ново устройство, ако искате.
- Споделяйте купони, ексклузивни оферти, промоционални кодове или карти и кодове, като използвате всяко приложение.
- Тъмна тема и опции за достъпност за потребители с увредено зрение.
- Добавяйте карти или кодове с имена и цветове, които можете да настройвате по желание.
- Въвеждайте кодове, ако картата е без щрихкод или той не може да се използва.
- Внасяйте карти и кодове от файлове на Catima, FidMe, Loyalty Card Keychain, Stocard и Voucher Vault.
- Изнасяйте резервни копия на всичките си карти и при желание ги прехвърлете на други устройства.
- Споделяйте купони, специални оферти, промоционални кодове или карти и кодове, като използвате всяко приложение.
- Тъмна тема и настройки за достъпност за потребители с намалено зрение.
- Направено за всички от общността на свободния софтуер.
- Локализирани ръчно направени преводи за над 20 езика.
- Локализирани, ръчно направени преводи на над 20 езика.
- Безвъзмездно, подкрепено от приноса на общността.
- Използвайте, изучавайте, променяйте и споделяйте, както желаете; <i>с всички</i>.
- Не само свободен софтуер / отворен код. <i>Copylefted</i> либре софтуер (GPLv3+) за управление на карти.
😺
Опростете живота и пазаруването си и никога повече не губете хартиена касова бележка, карта за подарък за плащане в магазина или самолетен билет.
Вземете всичките си награди и бонуси със себе си и спестявайте, докато пътувате.
😺

View File

@@ -1 +1 @@
За вашите баркодове, членства, програми за лоялност, талони и билети.
За вашите щрихкодове, членства, програми за лоялност, талони и билети.

View File

@@ -0,0 +1,6 @@
- Dodaj opciju da se postavi posebna barcode vrijednost od ID kartice
- Pojednostavi konfiguraciju fonta
- Nekoliko lakših korisničkih funkcija
- Koristi ikonu slova za prečice
- Uvijek Prikaži sve barkode vrste u manuelnom ulazu
- Ukloni Politiku privatnosti prvog početka

View File

@@ -0,0 +1,4 @@
- Podržite novi PDF417 export iz Voucher trezora
- Podržite za kopiranje više barkodova odjednom.
- Podržite dijeljenje više kartica odanosti odjednom
- Pitaj da ažuriraš vrijednost za barcode ako se promijeni ID kartica

View File

@@ -0,0 +1,3 @@
- Dodaj nestali barkod za izvoz
- Nemoj prikazati dijalog o barcodeu ako je vrijednost kao ID kartice
- Dodaj Finski prevod

View File

@@ -0,0 +1,2 @@
- Long-click of a card donosi opciju da kopira ID karticu u clipboard. (vuci broj 49 (https://github.com/brarcher/loyalty-card-locker/issues/49))
- Back button na ulaz/izvoz pogled sada radi, prebacujem korisnika Na main view

View File

@@ -0,0 +1,2 @@
- Nekoliko manjih prijevoda i korisničke funkcije
- Popravi crash u uvoz/dijeljenje lojalnost karticu na Android 6

View File

@@ -0,0 +1 @@
- Popraviti nesposobnost konfiguriranja slika u novoj kartici lojalnosti

View File

@@ -0,0 +1 @@
- Popravi učitavanje slika pri uređivanju postojeće kartice

View File

@@ -0,0 +1,3 @@
- Napravi kraticu
- Generiši kraticu kartice
- Popravi boju kartice

View File

@@ -0,0 +1,4 @@
- Izmijeni izabrani boju u dijalogu za mijenjanje boja
- Podrška za brisanje više kartica odjednom
- Popravi moguću Aritmeticexcepciju pri mijenjanju slike
- Fiksiraj cijeli ekran je zatvoren kada rotirajući uređaj

View File

@@ -0,0 +1,4 @@
- Napravi linkove u bilješkama koje se mogu kliknuti
- Pre-odaberite grupu u kojoj je korisnik trenutno pri kreiranju nove kartice
- Zarez-odvojena grupna imena u lojalnost card view
- Fiksiraj maksimiziraj dugme koje se pojavljuje na barkodeu

View File

@@ -0,0 +1,4 @@
- Poboljšaj uvoznika
- Fix uvoznik Catia export sa više nota
- Titula skale u prihvatljivom opsegu
- Poboljšanja u animaciji

View File

@@ -0,0 +1 @@
- Fix crash na rotaciju u lojalnost kartice editovanje aktivnosti

View File

@@ -0,0 +1,2 @@
- Popravi Kratica tastature za biranje grafičkog elementa
- Zamijeni uobičajeni Android crni ekran prskanjem ekrana

View File

@@ -0,0 +1,2 @@
- Fix slike nisu uvezene iz sigurnosne kopije
- Opcija za prevazilaženje jezika

View File

@@ -0,0 +1,4 @@
- Poboljšaj listu karata za pejzaž i tablicu
- Dodaj mi boju za kosu (hvala, Subhashish Anand!)
- Ne zatvarajte aktivnost na grešci kamere (tako ručni unos je i dalje moguć)
- Dodaj sve doprinosioce dijalogu s obavještenjima

View File

@@ -0,0 +1,4 @@
- Poboljšana podrška čitaocima ekrana
- Nemoj da se slupaš dok pokušavaš da otvoriš video iz galerije
- Provuci podršku na zaslonu sa kartica
- Ne Resetuj grupu na pritiskom dugmeta

View File

@@ -0,0 +1,2 @@
- Podrška za mijenjanje redoslijeda sortiranja
- Sprecite da ne gledate velike slike za barkodeom

View File

@@ -0,0 +1 @@
- Male greške i poboljšanja

View File

@@ -0,0 +1,3 @@
- Změna výchozího názvu importního/exportního souboru. (pull #84 (https://github.com/brarcher/loyalty-card-locker/pull/84))
- Opraven řetězec na stránce import/export. (pull #87 (https://github.com/brarcher/loyalty-card-locker/pull/87))
- Vylepšeno rozvržení stránky se zobrazením karet. Text by měl být lépe čitelný a je možné jej vybrat dlouhým kliknutím. (pull #91 (https://github.com/brarcher/loyalty-card-locker/pull/91))

View File

@@ -0,0 +1,5 @@
- Při úpravě ID karty předvyplňte na začátku existující ID
- Omezte šířku generovaných čárových kódů, abyste snížili spotřebu paměti a chyby mimo paměť
- Při editaci karty změňte tlačítko "Zadat kartu" na "Upravit kartu", pokud ID karty již existuje
- Změňte barevné schéma tak, aby bylo jemnější a kompatibilní s ikonou aplikace, a změňte rozložení při prohlížení karty, aby bylo přehlednější
- Přidejte úvodního průvodce, který se spustí při prvním spuštění aplikace

View File

@@ -0,0 +1 @@
- Zabránění pádu při otáčení obrazovky v úvodním průvodci prvního spuštění.

Some files were not shown because too many files have changed in this diff Show More