Compare commits

...

116 Commits

Author SHA1 Message Date
Sylvia van Os
78481516b0 Bump versioncode 2021-08-29 16:38:07 +02:00
Sylvia van Os
423b74273e Release 2.4.0 2021-08-29 16:28:00 +02:00
Sylvia van Os
83e0a988d9 Improve contrast of cards 2021-08-29 16:14:32 +02:00
Sylvia van Os
1adea88ff1 Merge pull request #352 from TheLastProject/feature/cardLayout
Main screen card layout
2021-08-29 01:33:06 +02:00
Sylvia van Os
dda912c8c5 Update CHANGELOG 2021-08-29 01:27:47 +02:00
Sylvia van Os
f3b31bb306 Update screenshots 2021-08-29 01:27:10 +02:00
Sylvia van Os
3b31c4e05a Set min-height for long store names 2021-08-29 01:16:31 +02:00
Sylvia van Os
1155108086 Fix title layout issue 2021-08-29 00:46:36 +02:00
Sylvia van Os
73bb7ded09 Fix recyclerview not rendering all in unit test 2021-08-28 01:51:44 +02:00
Sylvia van Os
d8655eb631 Don't make cards bigger than needed 2021-08-28 01:42:19 +02:00
Sylvia van Os
55cddfef91 Fix incorrect data due to recycling 2021-08-28 01:39:33 +02:00
Sylvia van Os
c35dc736f4 Cleanup buggy code 2021-08-28 01:03:25 +02:00
Sylvia van Os
23b762a500 2 colums in landscape 2021-08-28 00:05:33 +02:00
Sylvia van Os
b9b638de45 Initial card layout 2021-08-27 23:42:03 +02:00
thelastproject/contributors-to-file
5f57507dda Update contributor list 2021-08-27 20:40:38 +00:00
Sylvia van Os
852eb6612c Merge pull request #351 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-27 22:40:04 +02:00
solokot
d96aac7bbf Translated using Weblate (Russian)
Currently translated at 100.0% (197 of 197 strings)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Prevent AppBundle crashes

* Reload activity on language change

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

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

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

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

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

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

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

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

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

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

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-08-11 05:32:35 +02:00
Sylvia van Os
75fdd7390f Merge pull request #325 from recursiveribbons/sql-refactor
Refactored DBHelper
2021-08-09 20:35:55 +02:00
recursiveribbons
7cd6c17b55 Refactored DBHelper 2021-08-09 17:35:25 +02:00
Sylvia van Os
c273d8d17f Fix widget creating different-looking shortcut than app shortcuts 2021-08-08 23:49:10 +02:00
Sylvia van Os
c1b02f58ff Fix indent 2021-08-08 23:04:55 +02:00
Sylvia van Os
0bac2dfb62 Merge pull request #322 from TacoTheDank/master
Some cleanup and compatibility stuff
2021-08-08 23:03:58 +02:00
TacoTheDank
4f0288e396 Use ActivityCompat.recreate 2021-08-08 16:33:55 -04:00
TacoTheDank
55f0399325 Use ShortcutInfoCompat 2021-08-08 16:33:42 -04:00
Sylvia van Os
e756c6e50b Fix dir names 2021-08-08 19:30:37 +02:00
TacoTheDank
5d5b1f0a63 Use AndroidX ExifInterface 2021-08-07 17:08:50 -04:00
TacoTheDank
03e638786b Create TextWatcher stub 2021-08-07 17:08:28 -04:00
TacoTheDank
7d5b2f8dc8 Update NumberPickerPreference library 2021-08-07 16:47:01 -04:00
89 changed files with 1674 additions and 788 deletions

View File

@@ -0,0 +1,23 @@
name: 'Close issues and PRs needing info for too long'
on:
schedule:
- cron: '30 1 * * *'
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
with:
days-before-stale: -1
days-before-close: 90
close-issue-message: 'This issue is missing necessary information and cannot be worked on in its current state. It has therefore been closed to keep the issue tracker clean. If you have more information, feel free to reopen it.'
close-pr-message: 'This PR is missing necessary information and cannot be merged in its current state. It has therefore been closed to keep the issue tracker clean. If you have more information, feel free to reopen it.'
only-labels: 'needs info'
stale-issue-label: 'needs info'
stale-pr-label: 'needs info'
remove-stale-when-updated: false

View File

@@ -10,16 +10,19 @@ on:
- '**.webp'
jobs:
build:
# Only run on Pull Requests within the same repository, and not from forks.
if: github.event.pull_request.head.repo.full_name == github.repository
name: calibreapp/image-actions
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@master
uses: actions/checkout@v2
- name: Compress Images
id: calibre
uses: calibreapp/image-actions@master
uses: calibreapp/image-actions@1.1.0
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
ignorePaths: 'app/src/test'
compressOnly: true
- name: Create New Pull Request If Needed
if: steps.calibre.outputs.markdown != ''

View File

@@ -0,0 +1,17 @@
on:
push:
branches: [ master ]
jobs:
contributors_to_file:
runs-on: ubuntu-latest
name: Write contributors to file
steps:
- name: Checkout repo
id: checkout
uses: actions/checkout@v2
- name: Update contributors
id: update_contributors
uses: TheLastProject/contributors-to-file-action@v1.0.2
with:
file_in_repo: app/src/main/res/raw/contributors.txt

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@ build/
captures/
**/release
**/debug
app/*.log

View File

@@ -1,5 +1,28 @@
# Changelog
## v2.4.0 (2021-08-29)
Changes:
- Improve card list for landscape and tablet display
- Add theming colour support (thanks, Subhashish Anand!)
- Don't close scan activity on camera error (so manual entry is still possible)
- Add all contributors to the about dialog
## v2.3.0 (2021-08-19)
Changes:
- Fix images not imported from backup
- Option to override language
## v2.2.3 (2021-08-13)
Changes:
- Fix widget creating different-looking shortcut than app shortcuts
- Replace default Android black screen with splash screen
## v2.2.2 (2021-08-08)
Changes:

View File

@@ -18,8 +18,8 @@ android {
applicationId "me.hackerchick.catima"
minSdkVersion 19
targetSdkVersion 30
versionCode 78
versionName "2.2.2"
versionCode 81
versionName "2.4.0"
vectorDrawables.useSupportLibrary true
multiDexEnabled true
@@ -37,6 +37,12 @@ android {
}
}
bundle {
language {
enableSplit = false
}
}
compileOptions {
encoding "UTF-8"
@@ -77,6 +83,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
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'
@@ -86,7 +93,7 @@ dependencies {
implementation 'com.google.zxing:core:3.4.1'
implementation 'org.apache.commons:commons-csv:1.8'
implementation 'com.jaredrummler:colorpicker:1.1.0'
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.2'
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.3'
implementation 'net.lingala.zip4j:zip4j:2.8.0'
// SpotBugs

View File

@@ -29,7 +29,7 @@
<activity
android:name="protect.card_locker.MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@@ -83,7 +83,8 @@
android:windowSoftInputMode="stateHidden"/>
<activity
android:name=".preferences.SettingsActivity"
android:label="@string/settings"/>
android:label="@string/settings"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".ImportExportActivity"
android:label="@string/importExport"

View File

@@ -8,16 +8,19 @@ import android.util.Log;
import android.view.MenuItem;
import android.widget.TextView;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import androidx.core.text.HtmlCompat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.text.HtmlCompat;
public class AboutActivity extends AppCompatActivity
public class AboutActivity extends CatimaAppCompatActivity
{
private static final String TAG = "Catima";
@@ -25,6 +28,7 @@ public class AboutActivity extends AppCompatActivity
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setTitle(R.string.about);
setContentView(R.layout.about_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -34,6 +38,24 @@ public class AboutActivity extends AppCompatActivity
actionBar.setDisplayHomeAsUpEnabled(true);
}
StringBuilder contributors = new StringBuilder().append("<br/>");
BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.contributors), StandardCharsets.UTF_8));
try {
while (true) {
String tmp = reader.readLine();
if (tmp == null || tmp.isEmpty()) {
reader.close();
break;
}
contributors.append("<br/>");
contributors.append(tmp);
}
} catch (IOException ignored) {}
final List<ThirdPartyInfo> USED_LIBRARIES = new ArrayList<>();
USED_LIBRARIES.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("Commons CSV", "https://commons.apache.org/proper/commons-csv/", "Apache 2.0"));
@@ -48,13 +70,13 @@ public class AboutActivity extends AppCompatActivity
StringBuilder libs = new StringBuilder().append("<br/>");
for (ThirdPartyInfo entry : USED_LIBRARIES)
{
libs.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")<br/>");
libs.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")");
}
StringBuilder resources = new StringBuilder().append("<br/>");
for (ThirdPartyInfo entry : USED_ASSETS)
{
resources.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")<br/>");
resources.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")");
}
String appName = getString(R.string.app_name);
@@ -87,6 +109,8 @@ public class AboutActivity extends AppCompatActivity
"<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));

View File

@@ -1,11 +1,10 @@
package protect.card_locker;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.Pair;
import android.view.MenuItem;
@@ -16,6 +15,9 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import com.google.zxing.BarcodeFormat;
import java.util.Arrays;
@@ -25,17 +27,13 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
/**
* 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 AppCompatActivity
public class BarcodeSelectorActivity extends CatimaAppCompatActivity
{
private static final String TAG = "Catima";
@@ -69,7 +67,7 @@ public class BarcodeSelectorActivity extends AppCompatActivity
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);
@@ -94,14 +92,8 @@ public class BarcodeSelectorActivity extends AppCompatActivity
barcodeViewMap.put(BarcodeFormat.UPC_E.name(), new Pair<>(R.id.upceBarcode, R.id.upceBarcodeText));
EditText cardId = findViewById(R.id.cardId);
cardId.addTextChangedListener(new TextWatcher()
cardId.addTextChangedListener(new SimpleTextWatcher()
{
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
// Noting to do
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
@@ -113,12 +105,6 @@ public class BarcodeSelectorActivity extends AppCompatActivity
setButtonListener(noBarcodeButtonView, s.toString());
noBarcodeButtonView.setEnabled(s.length() > 0);
}
@Override
public void afterTextChanged(Editable s)
{
// Noting to do
}
});
final Bundle b = getIntent().getExtras();

View File

@@ -1,21 +1,21 @@
package protect.card_locker;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
/**
* The configuration screen for creating a shortcut.
*/
@@ -69,23 +69,9 @@ public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyC
Log.d(TAG, "Creating shortcut for card " + loyaltyCard.store + "," + loyaltyCard.id);
Intent shortcutIntent = new Intent(CardShortcutConfigure.this, LoyaltyCardViewActivity.class);
shortcutIntent.setAction(Intent.ACTION_MAIN);
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle bundle = new Bundle();
bundle.putInt("id", loyaltyCard.id);
bundle.putBoolean("view", true);
shortcutIntent.putExtras(bundle);
ShortcutInfoCompat shortcut = ShortcutHelper.createShortcutBuilder(CardShortcutConfigure.this, loyaltyCard).build();
Bitmap iconBitmap = Utils.generateIcon(CardShortcutConfigure.this, loyaltyCard, true).getLetterTile();
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, loyaltyCard.store);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, iconBitmap);
setResult(RESULT_OK, intent);
setResult(RESULT_OK, ShortcutManagerCompat.createShortcutResultIntent(CardShortcutConfigure.this, shortcut));
finish();
}

View File

@@ -0,0 +1,57 @@
package protect.card_locker;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.util.Log;
import android.util.TypedValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
public class CatimaAppCompatActivity extends AppCompatActivity {
SharedPreferences pref;
HashMap<String, Integer> supportedThemes;
@Override
protected void attachBaseContext(Context base) {
// Apply chosen language
super.attachBaseContext(Utils.updateBaseContextLocale(base));
}
@Override
public Resources.Theme getTheme() {
if (supportedThemes == null) {
supportedThemes = new HashMap<>();
supportedThemes.put(getString(R.string.settings_key_blue_theme), R.style.AppTheme_blue);
supportedThemes.put(getString(R.string.settings_key_brown_theme), R.style.AppTheme_brown);
supportedThemes.put(getString(R.string.settings_key_green_theme), R.style.AppTheme_green);
supportedThemes.put(getString(R.string.settings_key_grey_theme), R.style.AppTheme_grey);
supportedThemes.put(getString(R.string.settings_key_magenta_theme), R.style.AppTheme_magenta);
supportedThemes.put(getString(R.string.settings_key_pink_theme), R.style.AppTheme_pink);
supportedThemes.put(getString(R.string.settings_key_sky_blue_theme), R.style.AppTheme_sky_blue);
supportedThemes.put(getString(R.string.settings_key_violet_theme), R.style.AppTheme_violet);
}
Resources.Theme theme = super.getTheme();
pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String themeName = pref.getString(getString(R.string.setting_key_theme_color), getString(R.string.settings_key_catima_theme));
theme.applyStyle(Utils.mapGetOrDefault(supportedThemes, themeName, R.style.AppTheme_NoActionBar), true);
return theme;
}
public int getThemeColor() {
TypedValue typedValue = new TypedValue();
Resources.Theme theme = getTheme();
theme.resolveAttribute(R.attr.colorPrimary, typedValue, true);
return typedValue.data;
}
}

View File

@@ -0,0 +1,24 @@
package protect.card_locker;
import android.app.Activity;
import android.widget.Toast;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
public class CatimaCaptureManager extends CaptureManager {
private Activity activity;
public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
super(activity, barcodeView);
this.activity = activity;
}
@Override
protected void displayFrameworkBugMessageAndExit(String message) {
// We don't want to exit, as we also have a enter from card image and add manually button here
// So we show a toast instead
Toast.makeText(activity, message, Toast.LENGTH_LONG).show();
}
}

View File

@@ -3,6 +3,7 @@ package protect.card_locker;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
@@ -12,6 +13,7 @@ import com.google.zxing.BarcodeFormat;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Currency;
import java.util.Date;
import java.util.List;
@@ -270,8 +272,7 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.toString() : null);
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
final long newId = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
return newId;
return db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
}
public long insertLoyaltyCard(final SQLiteDatabase db, final String store,
@@ -291,8 +292,7 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.toString() : null);
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.STAR_STATUS,starStatus);
final long newId = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
return newId;
return db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
}
public long insertLoyaltyCard(final SQLiteDatabase db, final int id, final String store,
@@ -313,8 +313,7 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.toString() : null);
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.STAR_STATUS,starStatus);
final long newId = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
return newId;
return db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
}
public boolean updateLoyaltyCard(final int id, final String store, final String note,
@@ -335,8 +334,7 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.toString() : null);
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE, contentValues,
LoyaltyCardDbIds.ID + "=?",
new String[]{Integer.toString(id)});
whereAttrs(LoyaltyCardDbIds.ID), withArgs(id));
return (rowsUpdated == 1);
}
@@ -346,23 +344,21 @@ public class DBHelper extends SQLiteOpenHelper
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.STAR_STATUS,starStatus);
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE, contentValues,
LoyaltyCardDbIds.ID + "=?",
new String[]{Integer.toString(id)});
whereAttrs(LoyaltyCardDbIds.ID),
withArgs(id));
return (rowsUpdated == 1);
}
public LoyaltyCard getLoyaltyCard(final int id)
{
SQLiteDatabase db = getReadableDatabase();
Cursor data = db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
" where " + LoyaltyCardDbIds.ID + "=?", new String[]{String.format("%d", id)});
Cursor data = db.query(LoyaltyCardDbIds.TABLE, null, whereAttrs(LoyaltyCardDbIds.ID), withArgs(id), null, null, null);
LoyaltyCard card = null;
if(data.getCount() == 1)
{
data.moveToFirst();
card = LoyaltyCard.toLoyaltyCard(data);
}
@@ -377,7 +373,7 @@ public class DBHelper extends SQLiteOpenHelper
Cursor data = db.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE + " g " +
" LEFT JOIN " + LoyaltyCardDbIdsGroups.TABLE + " ig ON ig." + LoyaltyCardDbIdsGroups.groupID + " = g." + LoyaltyCardDbGroups.ID +
" where " + LoyaltyCardDbIdsGroups.cardID + "=?" +
" ORDER BY " + LoyaltyCardDbIdsGroups.groupID, new String[]{String.format("%d", id)});
" ORDER BY " + LoyaltyCardDbIdsGroups.groupID, withArgs(id));
List<Group> groups = new ArrayList<>();
@@ -403,8 +399,8 @@ public class DBHelper extends SQLiteOpenHelper
// First delete lookup table entries associated with this card
db.delete(LoyaltyCardDbIdsGroups.TABLE,
LoyaltyCardDbIdsGroups.cardID + " = ? ",
new String[]{String.format("%d", id)});
whereAttrs(LoyaltyCardDbIdsGroups.cardID),
withArgs(id));
// Then create entries for selected values
for (Group group : groups) {
@@ -419,8 +415,8 @@ public class DBHelper extends SQLiteOpenHelper
{
// First delete lookup table entries associated with this card
db.delete(LoyaltyCardDbIdsGroups.TABLE,
LoyaltyCardDbIdsGroups.cardID + " = ? ",
new String[]{String.format("%d", id)});
whereAttrs(LoyaltyCardDbIdsGroups.cardID),
withArgs(id));
// Then create entries for selected values
for (Group group : groups) {
@@ -436,13 +432,13 @@ public class DBHelper extends SQLiteOpenHelper
SQLiteDatabase db = getWritableDatabase();
// Delete card
int rowsDeleted = db.delete(LoyaltyCardDbIds.TABLE,
LoyaltyCardDbIds.ID + " = ? ",
new String[]{String.format("%d", id)});
whereAttrs(LoyaltyCardDbIds.ID),
withArgs(id));
// And delete lookup table entries associated with this card
db.delete(LoyaltyCardDbIdsGroups.TABLE,
LoyaltyCardDbIdsGroups.cardID + " = ? ",
new String[]{String.format("%d", id)});
whereAttrs(LoyaltyCardDbIdsGroups.cardID),
withArgs(id));
// Also wipe card images associated with this card
try {
@@ -492,11 +488,11 @@ public class DBHelper extends SQLiteOpenHelper
List<Integer> allowedIds = getGroupCardIds(group._id);
// Empty group
if (allowedIds.size() > 0) {
if (!allowedIds.isEmpty()) {
groupFilter.append("AND (");
for (int i = 0; i < allowedIds.size(); i++) {
groupFilter.append(LoyaltyCardDbIds.ID + " = " + allowedIds.get(i));
groupFilter.append(LoyaltyCardDbIds.ID + " = ").append(allowedIds.get(i));
if (i != allowedIds.size() - 1) {
groupFilter.append(" OR ");
}
@@ -507,20 +503,18 @@ public class DBHelper extends SQLiteOpenHelper
}
}
Cursor res = db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
return db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
" WHERE (" + LoyaltyCardDbIds.STORE + " LIKE ? " +
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? )" +
groupFilter.toString() +
" ORDER BY " + LoyaltyCardDbIds.STAR_STATUS + " DESC," + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC " +
limitString, selectionArgs, null);
return res;
}
public int getLoyaltyCardCount()
{
// An empty string will match everything
return getLoyaltyCardCount("");
SQLiteDatabase db = getReadableDatabase();
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbIds.TABLE);
}
/**
@@ -532,25 +526,11 @@ public class DBHelper extends SQLiteOpenHelper
public int getLoyaltyCardCount(String filter)
{
String actualFilter = String.format("%%%s%%", filter);
String[] selectionArgs = { actualFilter, actualFilter };
SQLiteDatabase db = getReadableDatabase();
Cursor data = db.rawQuery("SELECT Count(*) FROM " + LoyaltyCardDbIds.TABLE +
" WHERE " + LoyaltyCardDbIds.STORE + " LIKE ? " +
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? "
, selectionArgs, null);
int numItems = 0;
if(data.getCount() == 1)
{
data.moveToFirst();
numItems = data.getInt(0);
}
data.close();
return numItems;
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbIds.TABLE,
LoyaltyCardDbIds.STORE + " LIKE ? " +
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? ", withArgs(actualFilter, actualFilter));
}
/**
@@ -562,47 +542,40 @@ public class DBHelper extends SQLiteOpenHelper
{
SQLiteDatabase db = getReadableDatabase();
Cursor res = db.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE +
return db.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE +
" ORDER BY " + LoyaltyCardDbGroups.ORDER + " ASC," + LoyaltyCardDbGroups.ID + " COLLATE NOCASE ASC", null, null);
return res;
}
public List<Group> getGroups() {
Cursor data = getGroupCursor();
try(Cursor data = getGroupCursor()) {
List<Group> groups = new ArrayList<>();
List<Group> groups = new ArrayList<>();
if (!data.moveToFirst()) {
return groups;
}
groups.add(Group.toGroup(data));
while (data.moveToNext()) {
groups.add(Group.toGroup(data));
}
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)
{
Integer order = 0;
SQLiteDatabase db = getWritableDatabase();
ContentValues contentValues;
for (Group group : groups)
{
contentValues = new ContentValues();
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbGroups.ORDER, order);
db.update(LoyaltyCardDbGroups.TABLE, contentValues,
LoyaltyCardDbGroups.ID + "=?",
new String[]{group._id});
whereAttrs(LoyaltyCardDbGroups.ID),
withArgs(group._id));
order++;
}
@@ -611,18 +584,15 @@ public class DBHelper extends SQLiteOpenHelper
public Group getGroup(final String groupName)
{
SQLiteDatabase db = getReadableDatabase();
Cursor data = db.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE +
" where " + LoyaltyCardDbGroups.ID + "=?", new String[]{groupName});
Cursor data = db.query(LoyaltyCardDbGroups.TABLE, null,
whereAttrs(LoyaltyCardDbGroups.ID), withArgs(groupName), null, null, null);
Group group = null;
if(data.getCount() == 1)
{
data.moveToFirst();
group = Group.toGroup(data);
}
data.close();
return group;
@@ -631,28 +601,14 @@ public class DBHelper extends SQLiteOpenHelper
public int getGroupCount()
{
SQLiteDatabase db = getReadableDatabase();
Cursor data = db.rawQuery("SELECT Count(*) FROM " + LoyaltyCardDbGroups.TABLE, null);
int numItems = 0;
if(data.getCount() == 1)
{
data.moveToFirst();
numItems = data.getInt(0);
}
data.close();
return numItems;
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbGroups.TABLE);
}
public List<Integer> getGroupCardIds(final String groupName)
{
SQLiteDatabase db = getReadableDatabase();
Cursor data = db.rawQuery("SELECT " + LoyaltyCardDbIdsGroups.cardID +
" FROM " + LoyaltyCardDbIdsGroups.TABLE +
" WHERE " + LoyaltyCardDbIdsGroups.groupID + " =? ", new String[]{groupName});
Cursor data = db.query(LoyaltyCardDbIdsGroups.TABLE, withArgs(LoyaltyCardDbIdsGroups.cardID),
whereAttrs(LoyaltyCardDbIdsGroups.groupID), withArgs(groupName), null, null, null);
List<Integer> cardIds = new ArrayList<>();
if (!data.moveToFirst()) {
@@ -678,8 +634,7 @@ public class DBHelper extends SQLiteOpenHelper
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbGroups.ID, name);
contentValues.put(LoyaltyCardDbGroups.ORDER, getGroupCount());
final long newId = db.insert(LoyaltyCardDbGroups.TABLE, null, contentValues);
return newId;
return db.insert(LoyaltyCardDbGroups.TABLE, null, contentValues);
}
public boolean insertGroup(final SQLiteDatabase db, final String name)
@@ -688,7 +643,7 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbGroups.ID, name);
contentValues.put(LoyaltyCardDbGroups.ORDER, getGroupCount());
final long newId = db.insert(LoyaltyCardDbGroups.TABLE, null, contentValues);
return (newId != -1);
return newId != -1;
}
public boolean updateGroup(final String groupName, final String newName)
@@ -708,13 +663,13 @@ public class DBHelper extends SQLiteOpenHelper
try {
// Update group name
int groupsChanged = db.update(LoyaltyCardDbGroups.TABLE, groupContentValues,
LoyaltyCardDbGroups.ID + "=?",
new String[]{groupName});
whereAttrs(LoyaltyCardDbGroups.ID),
withArgs(groupName));
// Also update lookup tables
db.update(LoyaltyCardDbIdsGroups.TABLE, lookupContentValues,
LoyaltyCardDbIdsGroups.groupID + "=?",
new String[]{groupName});
whereAttrs(LoyaltyCardDbIdsGroups.groupID),
withArgs(groupName));
if (groupsChanged == 1) {
db.setTransactionSuccessful();
@@ -738,13 +693,13 @@ public class DBHelper extends SQLiteOpenHelper
try {
// Delete group
int groupsDeleted = db.delete(LoyaltyCardDbGroups.TABLE,
LoyaltyCardDbGroups.ID + " = ? ",
new String[]{groupName});
whereAttrs(LoyaltyCardDbGroups.ID),
withArgs(groupName));
// And delete lookup table entries associated with this group
db.delete(LoyaltyCardDbIdsGroups.TABLE,
LoyaltyCardDbIdsGroups.groupID + " = ? ",
new String[]{groupName});
whereAttrs(LoyaltyCardDbIdsGroups.groupID),
withArgs(groupName));
if (groupsDeleted == 1) {
db.setTransactionSuccessful();
@@ -764,21 +719,24 @@ public class DBHelper extends SQLiteOpenHelper
{
SQLiteDatabase db = getReadableDatabase();
Cursor data = db.rawQuery("SELECT Count(*) FROM " + LoyaltyCardDbIdsGroups.TABLE +
" where " + LoyaltyCardDbIdsGroups.groupID + "=?",
new String[]{groupName});
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbIdsGroups.TABLE,
whereAttrs(LoyaltyCardDbIdsGroups.groupID), withArgs(groupName));
}
int numItems = 0;
if(data.getCount() == 1)
{
data.moveToFirst();
numItems = data.getInt(0);
private String whereAttrs(String... attrs) {
if (attrs.length == 0) {
return null;
}
StringBuilder whereClause = new StringBuilder(attrs[0]).append("=?");
for (int i = 1; i < attrs.length; i++) {
whereClause.append(" AND ").append(attrs[i]).append("=?");
}
return whereClause.toString();
}
data.close();
return numItems;
private String[] withArgs(Object... object) {
return Arrays.stream(object)
.map(String::valueOf)
.toArray(String[]::new);
}
}

View File

@@ -10,6 +10,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageButton;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.Settings;
class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder>

View File

@@ -2,6 +2,7 @@ package protect.card_locker;
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -16,6 +17,12 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -25,16 +32,10 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import protect.card_locker.importexport.DataFormat;
import protect.card_locker.importexport.ImportExportResult;
public class ImportExportActivity extends AppCompatActivity
public class ImportExportActivity extends CatimaAppCompatActivity
{
private static final String TAG = "Catima";
@@ -52,6 +53,7 @@ public class ImportExportActivity extends AppCompatActivity
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);

View File

@@ -4,14 +4,14 @@ import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Nullable;
import com.google.zxing.BarcodeFormat;
import java.math.BigDecimal;
import java.util.Currency;
import java.util.Date;
import androidx.annotation.Nullable;
public class LoyaltyCard implements Parcelable {
public final int id;
public final String store;

View File

@@ -4,6 +4,7 @@ import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.SparseBooleanArray;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
@@ -14,19 +15,22 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.ArrayList;
import com.google.android.material.card.MaterialCardView;
import androidx.cardview.widget.CardView;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.ArrayList;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder>
{
private static int mCurrentSelectedIndex = -1;
private int mCurrentSelectedIndex = -1;
private Cursor mCursor;
Settings mSettings;
boolean mDarkModeEnabled;
@@ -70,6 +74,9 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
}
public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor inputCursor) {
// Invisible until we want to show something more
inputHolder.mDivider.setVisibility(View.GONE);
if (mDarkModeEnabled) {
inputHolder.mStarIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
}
@@ -87,34 +94,39 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
}
if (!loyaltyCard.balance.equals(new BigDecimal("0"))) {
inputHolder.mDivider.setVisibility(View.VISIBLE);
inputHolder.mBalanceField.setVisibility(View.VISIBLE);
inputHolder.mBalanceField.setText(mContext.getString(R.string.balanceSentence, Utils.formatBalance(mContext, loyaltyCard.balance, loyaltyCard.balanceType)));
if (mDarkModeEnabled) {
inputHolder.mBalanceField.getCompoundDrawables()[0].setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
}
inputHolder.mBalanceField.setText(Utils.formatBalance(mContext, loyaltyCard.balance, loyaltyCard.balanceType));
inputHolder.mBalanceField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
} else {
inputHolder.mBalanceField.setVisibility(View.GONE);
}
if (loyaltyCard.expiry != null)
{
if (loyaltyCard.expiry != null) {
inputHolder.mDivider.setVisibility(View.VISIBLE);
inputHolder.mExpiryField.setVisibility(View.VISIBLE);
int expiryString = R.string.expiryStateSentence;
if(Utils.hasExpired(loyaltyCard.expiry)) {
expiryString = R.string.expiryStateSentenceExpired;
inputHolder.mExpiryField.setTextColor(mContext.getResources().getColor(R.color.alert));
Drawable expiryIcon = inputHolder.mExpiryField.getCompoundDrawables()[0];
if (Utils.hasExpired(loyaltyCard.expiry)) {
expiryIcon.setColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP);
inputHolder.mExpiryField.setTextColor(Color.RED);
} else if (mDarkModeEnabled) {
expiryIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
}
inputHolder.mExpiryField.setText(mContext.getString(expiryString, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry)));
inputHolder.mExpiryField.setText(DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry));
inputHolder.mExpiryField.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
} else {
inputHolder.mExpiryField.setVisibility(View.GONE);
}
inputHolder.mStarIcon.setVisibility((loyaltyCard.starStatus != 0) ? View.VISIBLE : View.GONE);
inputHolder.mStarIcon.setVisibility(loyaltyCard.starStatus != 0 ? View.VISIBLE : View.GONE);
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
inputHolder.itemView.setActivated(mSelectedItems.get(inputCursor.getPosition(), false));
applyIconAnimation(inputHolder, inputCursor.getPosition());
applyClickEvents(inputHolder, inputCursor.getPosition());
}
private void applyClickEvents(LoyaltyCardListItemViewHolder inputHolder, final int inputPosition)
@@ -178,7 +190,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
mAnimationItemsIndex.clear();
}
@SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
public void toggleSelection(int inputPosition)
{
mCurrentSelectedIndex = inputPosition;
@@ -192,7 +204,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
mSelectedItems.put(inputPosition, true);
mAnimationItemsIndex.put(inputPosition, true);
}
notifyItemChanged(inputPosition);
notifyDataSetChanged();
}
public void clearSelections()
@@ -241,7 +253,8 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
public LinearLayout mInformationContainer;
public ImageView mCardIcon, mStarIcon;
public CardView mThumbnailContainer;
public ConstraintLayout mRow;
public MaterialCardView mRow;
public View mDivider;
public RelativeLayout mThumbnailFrontContainer, mThumbnailBackContainer;
public LoyaltyCardListItemViewHolder(View inputView)
@@ -249,6 +262,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
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);
mThumbnailBackContainer = inputView.findViewById(R.id.thumbnail_back);
mInformationContainer = inputView.findViewById(R.id.information_container);

View File

@@ -12,7 +12,6 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -21,7 +20,6 @@ import android.os.LocaleList;
import android.provider.MediaStore;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -37,6 +35,14 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.exifinterface.media.ExifInterface;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -65,15 +71,7 @@ import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.fragment.app.DialogFragment;
public class LoyaltyCardEditActivity extends AppCompatActivity
public class LoyaltyCardEditActivity extends CatimaAppCompatActivity
{
private static final String TAG = "Catima";
@@ -241,6 +239,8 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
cardImageBack = findViewById(R.id.backImage);
enterButton = findViewById(R.id.enterButton);
cardImageFront.setBackgroundColor(getThemeColor());
cardImageBack.setBackgroundColor(getThemeColor());
warnOnInvalidBarcodeType = () -> {
if (!(boolean) barcodeImage.getTag()) {
@@ -248,34 +248,22 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
};
storeFieldEdit.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
storeFieldEdit.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
updateTempState(LoyaltyCardField.store, s.toString());
generateIcon(s.toString());
}
@Override
public void afterTextChanged(Editable s) { }
});
noteFieldEdit.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
noteFieldEdit.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
updateTempState(LoyaltyCardField.note, s.toString());
}
@Override
public void afterTextChanged(Editable s) { }
});
expiryField.addTextChangedListener(new TextWatcher() {
expiryField.addTextChangedListener(new SimpleTextWatcher() {
CharSequence lastValue;
@Override
@@ -314,10 +302,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
});
balanceField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
balanceField.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
try {
@@ -330,15 +315,9 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
e.printStackTrace();
}
}
@Override
public void afterTextChanged(Editable s) { }
});
balanceCurrencyField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
balanceCurrencyField.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Currency currency;
@@ -394,7 +373,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
});
cardIdFieldView.addTextChangedListener(new TextWatcher() {
cardIdFieldView.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (initDone && !onResuming) {
@@ -414,12 +393,9 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
public void onTextChanged(CharSequence s, int start, int before, int count) {
updateTempState(LoyaltyCardField.cardId, s.toString());
}
@Override
public void afterTextChanged(Editable s) { }
});
barcodeIdField.addTextChangedListener(new TextWatcher() {
barcodeIdField.addTextChangedListener(new SimpleTextWatcher() {
CharSequence lastValue;
@Override
@@ -478,10 +454,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
});
barcodeTypeField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
barcodeTypeField.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!s.toString().isEmpty()) {

View File

@@ -2,6 +2,7 @@ package protect.card_locker;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.multidex.MultiDexApplication;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardLockerApplication extends MultiDexApplication {

View File

@@ -1,5 +1,6 @@
package protect.card_locker;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -25,6 +26,15 @@ import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.Guideline;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.widget.TextViewCompat;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -37,18 +47,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.Guideline;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.widget.TextViewCompat;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardViewActivity extends AppCompatActivity
public class LoyaltyCardViewActivity extends CatimaAppCompatActivity
{
private static final String TAG = "Catima";
@@ -169,6 +170,9 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
centerGuideline.setGuidelinePercent(0.5f);
barcodeScaler = findViewById(R.id.barcodeScaler);
barcodeScaler.setProgress(100);
minimizeButton.setBackgroundColor(getThemeColor());
maximizeButton.setBackgroundColor(getThemeColor());
bottomSheetButton.setBackgroundColor(getThemeColor());
barcodeScaler.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

View File

@@ -18,23 +18,24 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import java.io.UnsupportedEncodingException;
import java.util.List;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.SettingsActivity;
public class MainActivity extends AppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener
{
private static final String TAG = "Catima";
@@ -48,6 +49,7 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
private RecyclerView mCardList;
private View mHelpText;
private View mNoMatchingCardsText;
private View mNoGroupCardsText;
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback()
{
@@ -176,7 +178,9 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
@Override
protected void onCreate(Bundle inputSavedInstanceState)
{
setTheme(R.style.AppTheme_NoActionBar);
super.onCreate(inputSavedInstanceState);
setTitle(R.string.app_name);
setContentView(R.layout.main_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -219,17 +223,13 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
mHelpText = findViewById(R.id.helpText);
mNoMatchingCardsText = findViewById(R.id.noMatchingCardsText);
mNoGroupCardsText = findViewById(R.id.noGroupCardsText);
mCardList = findViewById(R.id.list);
mHelpText.setOnTouchListener(gestureTouchListener);
mNoMatchingCardsText.setOnTouchListener(gestureTouchListener);
mCardList.setOnTouchListener(gestureTouchListener);
// Init card list
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
mCardList.setLayoutManager(mLayoutManager);
mCardList.setItemAnimator(new DefaultItemAnimator());
mAdapter = new LoyaltyCardCursorAdapter(this, null, this);
mCardList.setAdapter(mAdapter);
registerForContextMenu(mCardList);
@@ -340,7 +340,7 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
MenuItem searchItem = mMenu.findItem(R.id.action_search);
searchItem.collapseActionView();
}
recreate();
ActivityCompat.recreate(this);
return;
}
@@ -403,13 +403,22 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
// the keyboard
mCardList.setVisibility(View.VISIBLE);
mHelpText.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.GONE);
if(mAdapter.getItemCount() > 0)
{
mNoMatchingCardsText.setVisibility(View.GONE);
}
else
{
mNoMatchingCardsText.setVisibility(View.VISIBLE);
if(!filterText.isEmpty()) {
// Actual Empty Search Result
mNoMatchingCardsText.setVisibility(View.VISIBLE);
mNoGroupCardsText.setVisibility(View.GONE);
} else {
// Group Tab with no Group Cards
mNoMatchingCardsText.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.VISIBLE);
}
}
}
else
@@ -417,6 +426,7 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
mCardList.setVisibility(View.GONE);
mHelpText.setVisibility(View.VISIBLE);
mNoMatchingCardsText.setVisibility(View.GONE);
mNoGroupCardsText.setVisibility(View.GONE);
}
if (mCurrentActionMode != null) {
@@ -695,9 +705,9 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
b.putInt("id", loyaltyCard.id);
i.putExtras(b);
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard, i);
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard);
startActivityForResult(i, Utils.MAIN_REQUEST);
}
}
}
}

View File

@@ -2,7 +2,6 @@ package protect.card_locker;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.text.InputType;
import android.view.MenuItem;
@@ -11,19 +10,18 @@ import android.view.WindowManager;
import android.widget.EditText;
import android.widget.TextView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class ManageGroupsActivity extends AppCompatActivity implements GroupCursorAdapter.GroupAdapterListener
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
public class ManageGroupsActivity extends CatimaAppCompatActivity implements GroupCursorAdapter.GroupAdapterListener
{
private static final String TAG = "Catima";
@@ -36,6 +34,7 @@ public class ManageGroupsActivity extends AppCompatActivity implements GroupCurs
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setTitle(R.string.groups);
setContentView(R.layout.manage_groups_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -111,7 +110,7 @@ public class ManageGroupsActivity extends AppCompatActivity implements GroupCurs
}
private void createGroup() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog.Builder builder = new AlertDialog.Builder(this,R.style.AlertDialogTheme);
builder.setTitle(R.string.enter_group_name);
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);

View File

@@ -1,6 +1,7 @@
package protect.card_locker;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
@@ -10,6 +11,9 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.Intents;
import com.journeyapps.barcodescanner.BarcodeCallback;
@@ -19,17 +23,13 @@ import com.journeyapps.barcodescanner.DecoratedBarcodeView;
import java.util.List;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
/**
* Custom Scannner Activity extending from Activity to display a custom layout form scanner view.
*
* Based on https://github.com/journeyapps/zxing-android-embedded/blob/0fdfbce9fb3285e985bad9971c5f7c0a7a334e7b/sample/src/main/java/example/zxing/CustomScannerActivity.java
* originally licensed under Apache 2.0
*/
public class ScanActivity extends AppCompatActivity {
public class ScanActivity extends CatimaAppCompatActivity {
private static final String TAG = "Catima";
private CaptureManager capture;
@@ -49,6 +49,7 @@ public class ScanActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.scanCardBarcode);
setContentView(R.layout.scan_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -67,7 +68,7 @@ public class ScanActivity extends AppCompatActivity {
// Even though we do the actual decoding with the barcodeScannerView
// CaptureManager needs to be running to show the camera and scanning bar
capture = new CaptureManager(this, barcodeScannerView);
capture = new CatimaCaptureManager(this, barcodeScannerView);
Intent captureIntent = new Intent();
Bundle captureIntentBundle = new Bundle();
captureIntentBundle.putBoolean(Intents.Scan.BEEP_ENABLED, false);
@@ -145,8 +146,7 @@ public class ScanActivity extends AppCompatActivity {
setResult(Activity.RESULT_CANCELED);
finish();
return true;
} else if (item.getItemId() == R.id.action_toggle_flashlight)
{
} else if (item.getItemId() == R.id.action_toggle_flashlight) {
if (torch) {
torch = false;
barcodeScannerView.setTorchOff();

View File

@@ -1,13 +1,13 @@
package protect.card_locker;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import java.util.Collections;
import java.util.Comparator;
@@ -30,135 +30,113 @@ class ShortcutHelper
* card exceeds the max number of shortcuts, then the least recently
* used card shortcut is discarded.
*/
@TargetApi(25)
static void updateShortcuts(Context context, LoyaltyCard card, Intent intent)
static void updateShortcuts(Context context, LoyaltyCard card)
{
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1)
LinkedList<ShortcutInfoCompat> list = new LinkedList<>(ShortcutManagerCompat.getDynamicShortcuts(context));
DBHelper dbHelper = new DBHelper(context);
String shortcutId = Integer.toString(card.id);
// Sort the shortcuts by rank, so working with the relative order will be easier.
// This sorts so that the lowest rank is first.
Collections.sort(list, Comparator.comparingInt(ShortcutInfoCompat::getRank));
Integer foundIndex = null;
for(int index = 0; index < list.size(); index++)
{
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
LinkedList<ShortcutInfo> list = new LinkedList<>(shortcutManager.getDynamicShortcuts());
DBHelper dbHelper = new DBHelper(context);
String shortcutId = Integer.toString(card.id);
// Sort the shortcuts by rank, so working with the relative order will be easier.
// This sorts so that the lowest rank is first.
Collections.sort(list, new Comparator<ShortcutInfo>()
if(list.get(index).getId().equals(shortcutId))
{
@Override
public int compare(ShortcutInfo o1, ShortcutInfo o2)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1)
{
return o1.getRank() - o2.getRank();
}
else
{
return 0;
}
}
});
// Found the item already
foundIndex = index;
break;
}
}
Integer foundIndex = null;
for(int index = 0; index < list.size(); index++)
if(foundIndex != null)
{
// If the item is already found, then the list needs to be
// reordered, so that the selected item now has the lowest
// rank, thus letting it survive longer.
ShortcutInfoCompat found = list.remove(foundIndex.intValue());
list.addFirst(found);
}
else
{
// The item is new to the list. First, we need to trim the list
// until it is able to accept a new item, then the item is
// inserted.
while(list.size() >= MAX_SHORTCUTS)
{
if(list.get(index).getId().equals(shortcutId))
{
// Found the item already
foundIndex = index;
break;
}
list.pollLast();
}
if(foundIndex != null)
{
// If the item is already found, then the list needs to be
// reordered, so that the selected item now has the lowest
// rank, thus letting it survive longer.
ShortcutInfo found = list.remove(foundIndex.intValue());
list.addFirst(found);
}
else
{
// The item is new to the list. First, we need to trim the list
// until it is able to accept a new item, then the item is
// inserted.
while(list.size() >= MAX_SHORTCUTS)
{
list.pollLast();
}
ShortcutInfoCompat shortcut = createShortcutBuilder(context, card).build();
ShortcutInfo shortcut = new ShortcutInfo.Builder(context, Integer.toString(card.id))
.setShortLabel(card.store)
.setLongLabel(card.store)
.setIntent(intent)
.build();
list.addFirst(shortcut);
}
list.addFirst(shortcut);
}
LinkedList<ShortcutInfoCompat> finalList = new LinkedList<>();
LinkedList<ShortcutInfo> finalList = new LinkedList<>();
// The ranks are now updated; the order in the list is the rank.
for(int index = 0; index < list.size(); index++)
{
ShortcutInfoCompat prevShortcut = list.get(index);
// The ranks are now updated; the order in the list is the rank.
for(int index = 0; index < list.size(); index++)
{
ShortcutInfo prevShortcut = list.get(index);
LoyaltyCard loyaltyCard = dbHelper.getLoyaltyCard(Integer.parseInt(prevShortcut.getId()));
Intent shortcutIntent = prevShortcut.getIntent();
Bitmap iconBitmap = Utils.generateIcon(context, dbHelper.getLoyaltyCard(Integer.parseInt(prevShortcut.getId())), true).getLetterTile();
Icon icon;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
icon = Icon.createWithAdaptiveBitmap(iconBitmap);
} else {
icon = Icon.createWithBitmap(iconBitmap);
}
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
shortcutIntent.setFlags(shortcutIntent.getFlags() | Intent.FLAG_ACTIVITY_SINGLE_TOP);
ShortcutInfo updatedShortcut = new ShortcutInfo.Builder(context, prevShortcut.getId())
.setShortLabel(prevShortcut.getShortLabel())
.setLongLabel(prevShortcut.getLongLabel())
.setIntent(shortcutIntent)
.setIcon(icon)
ShortcutInfoCompat updatedShortcut = createShortcutBuilder(context, loyaltyCard)
.setRank(index)
.build();
finalList.addLast(updatedShortcut);
}
shortcutManager.setDynamicShortcuts(finalList);
finalList.addLast(updatedShortcut);
}
ShortcutManagerCompat.setDynamicShortcuts(context, finalList);
}
/**
* Remove the given card id from the app shortcuts, if such a
* shortcut exists.
*/
@TargetApi(25)
static void removeShortcut(Context context, int cardId)
{
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1)
List<ShortcutInfoCompat> list = ShortcutManagerCompat.getDynamicShortcuts(context);
String shortcutId = Integer.toString(cardId);
for(int index = 0; index < list.size(); index++)
{
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
List<ShortcutInfo> list = shortcutManager.getDynamicShortcuts();
String shortcutId = Integer.toString(cardId);
for(int index = 0; index < list.size(); index++)
if(list.get(index).getId().equals(shortcutId))
{
if(list.get(index).getId().equals(shortcutId))
{
list.remove(index);
break;
}
list.remove(index);
break;
}
shortcutManager.setDynamicShortcuts(list);
}
ShortcutManagerCompat.setDynamicShortcuts(context, list);
}
static ShortcutInfoCompat.Builder createShortcutBuilder(Context context, LoyaltyCard loyaltyCard) {
Intent intent = new Intent(context, LoyaltyCardViewActivity.class);
intent.setAction(Intent.ACTION_MAIN);
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final Bundle bundle = new Bundle();
bundle.putInt("id", loyaltyCard.id);
bundle.putBoolean("view", true);
intent.putExtras(bundle);
Bitmap iconBitmap = Utils.generateIcon(context, loyaltyCard, true).getLetterTile();
IconCompat icon = IconCompat.createWithAdaptiveBitmap(iconBitmap);
return new ShortcutInfoCompat.Builder(context, Integer.toString(loyaltyCard.id))
.setShortLabel(loyaltyCard.store)
.setLongLabel(loyaltyCard.store)
.setIntent(intent)
.setIcon(icon);
}
}

View File

@@ -0,0 +1,15 @@
package protect.card_locker;
import android.text.Editable;
import android.text.TextWatcher;
public class SimpleTextWatcher implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override
public void afterTextChanged(Editable s) { }
}

View File

@@ -3,15 +3,21 @@ package protect.card_locker;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.Build;
import android.os.LocaleList;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;
import androidx.core.graphics.ColorUtils;
import androidx.exifinterface.media.ExifInterface;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
@@ -32,8 +38,10 @@ import java.util.Currency;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import androidx.core.graphics.ColorUtils;
import protect.card_locker.preferences.Settings;
public class Utils {
private static final String TAG = "Catima";
@@ -332,15 +340,42 @@ public class Utils {
return retrieveCardImage(context, getCardImageFileName(loyaltyCardId, front));
}
static public Object hashmapGetOrDefault(HashMap hashMap, Object key, Object defaultValue, Class keyType) {
Object value = hashMap.get(keyType.cast(key));
static public <T,U> U mapGetOrDefault(Map<T,U> map, T key, U defaultValue) {
U value = map.get(key);
if (value == null) {
return defaultValue;
}
return value;
}
static public Object hashmapGetOrDefault(HashMap hashMap, String key, Object defaultValue) {
return hashmapGetOrDefault(hashMap, key, defaultValue, String.class);
static public Locale stringToLocale(String localeString) {
String[] localeParts = localeString.split("-");
if (localeParts.length == 1) {
return new Locale(localeParts[0]);
}
if (localeParts[1].startsWith("r")) {
localeParts[1] = localeParts[1].substring(1);
}
return new Locale(localeParts[0], localeParts[1]);
}
static public Context updateBaseContextLocale(Context context) {
Settings settings = new Settings(context);
Locale chosenLocale = settings.getLocale();
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
configuration.locale = chosenLocale != null ? chosenLocale : Locale.getDefault();
res.updateConfiguration(configuration, res.getDisplayMetrics());
return context;
}
LocaleList localeList = chosenLocale != null ? new LocaleList(chosenLocale) : LocaleList.getDefault();
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
return context.createConfigurationContext(configuration);
}
}

View File

@@ -2,6 +2,7 @@ package protect.card_locker.importexport;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import com.google.zxing.BarcodeFormat;
@@ -47,24 +48,27 @@ public class CatimaImporter implements Importer
// First, check if this is a zip file
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream);
LocalFileHeader localFileHeader = zipInputStream.getNextEntry();
if (localFileHeader == null) {
boolean isZipFile = false;
LocalFileHeader localFileHeader;
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
isZipFile = true;
String fileName = Uri.parse(localFileHeader.getFileName()).getLastPathSegment();
if (fileName.equals("catima.csv")) {
importCSV(context, db, new ByteArrayInputStream(ZipUtils.read(zipInputStream).getBytes(StandardCharsets.UTF_8)));
} else if (fileName.endsWith(".png")) {
Utils.saveCardImage(context, ZipUtils.readImage(zipInputStream), fileName);
} else {
throw new FormatException("Unexpected file in import: " + fileName);
}
}
if (!isZipFile) {
// This is not a zip file, try importing as bare CSV
bufferedInputStream.reset();
importCSV(context, db, bufferedInputStream);
return;
}
importZipFile(context, db, zipInputStream, localFileHeader);
}
public void importZipFile(Context context, DBHelper db, ZipInputStream input, LocalFileHeader localFileHeader) throws IOException, FormatException, InterruptedException {
String fileName = localFileHeader.getFileName();
if (fileName.equals("catima.csv")) {
importCSV(context, db, new ByteArrayInputStream(ZipUtils.read(input).getBytes(StandardCharsets.UTF_8)));
} else {
Utils.saveCardImage(context, ZipUtils.readImage(input), fileName);
}
}

View File

@@ -162,9 +162,9 @@ public class StocardImporter implements Importer
HashMap<String, String> providerData = providers.get(providerId);
String store = providerData != null ? providerData.get("name") : providerId;
String note = (String) Utils.hashmapGetOrDefault(loyaltyCardData, "note", "");
String note = (String) Utils.mapGetOrDefault(loyaltyCardData, "note", "");
String cardId = (String) loyaltyCardData.get("cardId");
String barcodeTypeString = (String) Utils.hashmapGetOrDefault(loyaltyCardData, "barcodeType", providerData != null ? providerData.get("barcodeFormat") : null);
String barcodeTypeString = (String) Utils.mapGetOrDefault(loyaltyCardData, "barcodeType", providerData != null ? providerData.get("barcodeFormat") : null);
BarcodeFormat barcodeType = null;
if (barcodeTypeString != null) {
if (barcodeTypeString.equals("RSS_DATABAR_EXPANDED")) {

View File

@@ -7,7 +7,11 @@ import androidx.annotation.IntegerRes;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.preference.PreferenceManager;
import java.util.Locale;
import protect.card_locker.R;
import protect.card_locker.Utils;
public class Settings
{
@@ -45,6 +49,17 @@ public class Settings
return settings.getBoolean(getResString(keyId), defaultValue);
}
public Locale getLocale()
{
String value = getString(R.string.settings_key_locale, "");
if (value.length() == 0) {
return null;
}
return Utils.stringToLocale(value);
}
public int getTheme()
{
String value = getString(R.string.settings_key_theme, getResString(R.string.settings_key_system_theme));

View File

@@ -1,27 +1,40 @@
package protect.card_locker.preferences;
import android.content.Context;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import nl.invissvenska.numberpickerpreference.NumberDialogPreference;
import nl.invissvenska.numberpickerpreference.NumberPickerPreferenceDialogFragment;
import protect.card_locker.CatimaAppCompatActivity;
import protect.card_locker.R;
import protect.card_locker.Utils;
public class SettingsActivity extends AppCompatActivity
public class SettingsActivity extends CatimaAppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setTitle(R.string.settings);
setContentView(R.layout.settings_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
@@ -29,8 +42,10 @@ public class SettingsActivity extends AppCompatActivity
}
// Display the fragment as the main content.
SettingsFragment fragment = new SettingsFragment();
fragment.setParentReference(this);
getSupportFragmentManager().beginTransaction()
.replace(R.id.settings_container, new SettingsFragment())
.replace(R.id.settings_container, fragment)
.commit();
}
@@ -51,46 +66,72 @@ public class SettingsActivity extends AppCompatActivity
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)
{
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
// Show pretty names
ListPreference localePreference = findPreference(getResources().getString(R.string.settings_key_locale));
assert localePreference != null;
CharSequence[] entryValues = localePreference.getEntryValues();
List<CharSequence> entries = new ArrayList<>();
for (CharSequence entry : entryValues) {
if (entry.length() == 0) {
entries.add(getResources().getString(R.string.settings_system_locale));
} else {
Locale entryLocale = Utils.stringToLocale(entry.toString());
entries.add(entryLocale.getDisplayName(entryLocale));
}
}
localePreference.setEntries(entries.toArray(new CharSequence[entryValues.length]));
Preference themePreference = findPreference(getResources().getString(R.string.settings_key_theme));
assert themePreference != null;
themePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{
@Override
public boolean onPreferenceChange(Preference preference, Object o)
{
if(o.toString().equals(getResources().getString(R.string.settings_key_light_theme)))
{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
else if(o.toString().equals(getResources().getString(R.string.settings_key_dark_theme)))
{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
else
{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
FragmentActivity activity = getActivity();
if (activity != null) {
activity.recreate();
}
return true;
themePreference.setOnPreferenceChangeListener((preference, o) -> {
if (o.toString().equals(getResources().getString(R.string.settings_key_light_theme))) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else if (o.toString().equals(getResources().getString(R.string.settings_key_dark_theme))) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
FragmentActivity activity = getActivity();
if (activity != null) {
ActivityCompat.recreate(activity);
}
return true;
});
Preference colorPreference = findPreference(getResources().getString(R.string.setting_key_theme_color));
assert colorPreference != null;
colorPreference.setOnPreferenceChangeListener((preference, o) -> {
FragmentActivity activity = getActivity();
if (activity != null) {
ActivityCompat.recreate(activity);
}
return true;
});
localePreference.setOnPreferenceChangeListener((preference, newValue) -> {
// Refresh the activity
parent.finish();
startActivity(parent.getIntent());
return true;
});
}
@Override
public void onDisplayPreferenceDialog(Preference preference)
{
if (preference instanceof NumberDialogPreference)
{
public void onDisplayPreferenceDialog(Preference preference) {
if (preference instanceof NumberDialogPreference) {
NumberDialogPreference dialogPreference = (NumberDialogPreference) preference;
DialogFragment dialogFragment = NumberPickerPreferenceDialogFragment
.newInstance(
@@ -102,9 +143,7 @@ public class SettingsActivity extends AppCompatActivity
);
dialogFragment.setTargetFragment(this, 0);
dialogFragment.show(getParentFragmentManager(), DIALOG_FRAGMENT_TAG);
}
else
{
} else {
super.onDisplayPreferenceDialog(preference);
}
}

View File

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

@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,14L19,6c0,-1.1 -0.9,-2 -2,-2L3,4c-1.1,0 -2,0.9 -2,2v8c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM10,13c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM23,7v11c0,1.1 -0.9,2 -2,2L4,20v-2h17L21,7h2z"/>
</vector>

View File

@@ -26,12 +26,24 @@
android:gravity="center"
android:text="@string/noMatchingGiftCards"
android:visibility="gone"/>
<TextView
style="@style/AppTheme.TextView.NoData"
android:id="@+id/noGroupCardsText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/noGroupCards"
android:visibility="gone"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
app:spanCount="@integer/main_view_card_columns"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:visibility="gone" />
android:background="@color/mainLoyaltyCardBackground"
android:visibility="gone"/>
</RelativeLayout>

View File

@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabSave"
@@ -365,7 +366,6 @@
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:minHeight="50dp"
android:background="@color/colorPrimary"
android:contentDescription="@string/frontImageDescription"
android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_camera_white" />
@@ -401,7 +401,6 @@
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:minHeight="50dp"
android:background="@color/colorPrimary"
android:contentDescription="@string/backImageDescription"
android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_camera_white" />

View File

@@ -1,118 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<com.google.android.material.card.MaterialCardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/row"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="0.5dp"
android:background="@drawable/list_row"
android:clickable="true"
android:focusable="true"
android:padding="@dimen/activity_margin">
android:layout_margin="8dp">
<LinearLayout
android:id="@+id/information_container"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginLeft="@dimen/activity_margin"
android:layout_toEndOf="@+id/thumbnail_container"
android:layout_toRightOf="@+id/thumbnail_container"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="@+id/thumbnail_container"
app:layout_constraintEnd_toStartOf="@+id/star"
app:layout_constraintStart_toEndOf="@+id/thumbnail_container"
app:layout_constraintTop_toTopOf="@+id/thumbnail_container">
android:orientation="vertical">
<TextView
android:id="@+id/store"
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/information_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/storeNameTextSize"
android:textStyle="bold" />
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:textSize="@dimen/noteTextSize" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:textSize="@dimen/noteTextSize" />
<androidx.cardview.widget.CardView
android:id="@+id/thumbnail_container"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
app:cardCornerRadius="4dp"
android:layout_alignParentStart="true">
<TextView
android:id="@+id/expiry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:textSize="@dimen/noteTextSize" />
<RelativeLayout
android:id="@+id/thumbnail_front"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize">
<ImageView
android:id="@+id/thumbnail"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:contentDescription="@string/thumbnailDescription"
android:src="@mipmap/ic_launcher" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/thumbnail_back"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize">
<ImageView
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_centerHorizontal="true"
android:contentDescription="@string/thumbnailDescription"
app:srcCompat="@drawable/ic_done" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
<LinearLayout
android:minHeight="@dimen/cardThumbnailSize"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:layout_toEndOf="@+id/thumbnail_container">
<TextView
android:id="@+id/store"
android:paddingStart="16dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="left"
android:textAppearance="?attr/textAppearanceHeadline6" />
</LinearLayout>
<ImageView
android:id="@+id/star"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
app:srcCompat="@drawable/ic_starred_white"
android:contentDescription="@string/starImage"
app:tint="?attr/colorControlNormal"
android:layout_alignParentEnd="true"
android:visibility="gone" />
</RelativeLayout>
<TextView
android:id="@+id/note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
android:visibility="gone" />
<View android:id="@+id/info_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="?android:attr/dividerVertical"
android:visibility="gone" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="8dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
app:drawableLeftCompat="@drawable/ic_baseline_payments_24"
android:drawablePadding="4dp"
android:layout_alignParentStart="true"
android:visibility="gone" />
<TextView
android:id="@+id/expiry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
app:drawableLeftCompat="@drawable/ic_baseline_access_time_24"
android:drawablePadding="4dp"
android:layout_toEndOf="@+id/balance"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
<androidx.cardview.widget.CardView
android:id="@+id/thumbnail_container"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
app:cardCornerRadius="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:id="@+id/thumbnail_front"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize">
<ImageView
android:id="@+id/thumbnail"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:contentDescription="@string/thumbnailDescription"
android:src="@mipmap/ic_launcher" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/thumbnail_back"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize">
<ImageView
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_centerHorizontal="true"
android:contentDescription="@string/thumbnailDescription"
app:srcCompat="@drawable/ic_done" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
<ImageView
android:id="@+id/star"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_marginLeft="@dimen/activity_margin"
app:srcCompat="@drawable/ic_starred_white"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/activity_margin"
android:contentDescription="@string/starImage"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="#000000" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -55,7 +55,6 @@
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24"
android:contentDescription="@string/moveBarcodeToTopOfScreen"
app:tint="#ffffff"
android:background="@color/colorPrimary"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/barcode"
app:layout_constraintEnd_toEndOf="parent"
@@ -86,7 +85,6 @@
app:srcCompat="@drawable/ic_baseline_arrow_drop_down_24"
android:contentDescription="@string/moveBarcodeToCenterOfScreen"
app:tint="#ffffff"
android:background="@color/colorPrimary"
app:layout_constraintTop_toBottomOf="@+id/barcode"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
@@ -149,7 +147,6 @@
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_gravity="top|start"
android:background="@color/colorPrimary"
android:scaleType="fitCenter"
app:tint="#ffffff"
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24" />

View File

@@ -2,8 +2,23 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/settings_container"
android:layout_width="match_parent"

View File

@@ -0,0 +1,61 @@
Sylvia van Os
Branden Archer
J. Lavoie
Allan Nordhøy
Heimen Stoffels
solokot
Taco
mondstern
Samantaz Fox
Gediminas Murauskas
arno-github
Sergio Paredes
IllusiveMan196
Nyatsuki
StoyanDimitrov
Joel A
arshbeerSingh
huuhaa
Michael Moroni
Petr Novák
betsythefc
K. Herbert
Quentin PAGÈS
Yurical
Adolfo Jayme-Barrientos
Alessandro Mandelli
KovalevArtem
Clonewayx
D. Domig
Diego
Jane Kong
Lukas Grassauer
Michalis
schirinowski
String E. Fighter
inesre
lgasp
phlostically
waffshappen
Kevin Sicong Jiang
Miha Frangež
Airat
BMN
Franciszek Stefan
Izzy
Karol Kosek
bittin
Mattia
pbeckmann
Peer Beckmann
Rose Liverman
Simone Dotto
Subhashish Anand
Tymofii Lytvynenko
Tjipke van der Heide
opsik
psa-jforestier
Robin
sergio
Marcus
techwebpd

View File

@@ -158,21 +158,21 @@
<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>
<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>
<string name="failedParsingImportUriError">Препратката не може да бъде анализирана за внасяне</string>
<string name="card_ids_copied">[не превеждай този низ, https://github.com/TheLastProject/Catima/issues/278]</string>
<string name="failedGeneratingShareURL">Грешка при създаване на адрес за споделяне. Изпратете доклад за дефект.</string>
<string name="deleteTitle">Премахване на карта</string>
<string name="deleteTitle">Изтрийте картата</string>
<plurals name="deleteCardsTitle">
<item quantity="one">Премахване на карта</item>
<item quantity="other">Премахване на карти</item>
<item quantity="one">Изтриване на <xliff:g>%d</xliff:g> карта</item>
<item quantity="other">Изтриване на <xliff:g>%d</xliff:g> карти</item>
</plurals>
<string name="deleteConfirmation">Потвърдете премахване на карта</string>
<string name="deleteConfirmation">Потвърдете премахване на карта\?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Желаете ли картата да бъде премахната\?</item>
<item quantity="other">Желаете ли <xliff:g>%d</xliff:g> картати да бъдат премахнати\?</item>
<item quantity="one">Изтриване на тази <xliff:g>%d</xliff:g> карта завинаги\?</item>
<item quantity="other">Изтриване на тези <xliff:g>%d</xliff:g> карти за постоянно\?</item>
</plurals>
</resources>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
<string name="action_add">Přidat</string>
<string name="noGiftCards">Klepnutím na tlačítko + plus přidáte kartu nebo ji nejprve importujete z nabídky⋮.</string>
<string name="storeName">Název</string>
@@ -72,4 +72,125 @@
<string name="barcodeType">Typ čárového kódu</string>
<string name="noMatchingGiftCards">Nic jsem nenašel. Zkuste změnit vyhledávání.</string>
<string name="action_search">Vyhledávání</string>
<string name="thumbnailDescription">Miniatura karty</string>
<string name="card_ids_copied">Zkopírované ID karty(karet)</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Opravdu chcete kartu <xliff:g>%d</xliff:g> trvale odstranit\?</item>
<item quantity="few">Opravdu chcete karty <xliff:g>%d</xliff:g> trvale odstranit\?</item>
<item quantity="other">Opravdu chcete karty <xliff:g>%d</xliff:g> trvale odstranit\?</item>
</plurals>
<plurals name="deleteCardsTitle">
<item quantity="one">Odstranit kartu <xliff:g>%d</xliff:g></item>
<item quantity="few">Odstranit karty <xliff:g>%d</xliff:g></item>
<item quantity="other">Odstranit karty <xliff:g>%d</xliff:g></item>
</plurals>
<string name="importSuccessful">Data karty importována</string>
<string name="intent_import_card_from_url_share_text">Chci s Vámi sdílet kartu</string>
<string name="settings_disable_lockscreen_while_viewing_card">Bránit uzamykání obrazovky</string>
<string name="settings_keep_screen_on">Udržovat obrazovku zapnutou</string>
<string name="settings_lock_barcode_orientation">Zamknout orientaci čárového kódu</string>
<string name="settings_max_font_size_scale">Maximální velikost písma</string>
<string name="settings_dark_theme">Tmavý</string>
<string name="settings_light_theme">Světlý</string>
<string name="settings_system_theme">Systém</string>
<string name="settings_theme">Vzhled</string>
<string name="settings_category_title_ui">Uživatelské rozhraní</string>
<string name="settings">Nastavení</string>
<string name="card">Karta</string>
<string name="balancePoints"><xliff:g>%s</xliff:g> bodů</string>
<string name="balanceSentence">Zůstatek: <xliff:g>%s</xliff:g></string>
<string name="expiryStateSentenceExpired">Platnost vypršela: <xliff:g>%s</xliff:g></string>
<string name="expiryStateSentence">Platí do: <xliff:g>%s</xliff:g></string>
<string name="moveDown">Přesunout dolů</string>
<string name="moveUp">Přesunout nahoru</string>
<string name="enterBarcodeInstructions">Zadejte ID karty a níže vyberte typ čárového kódu nebo \"Tato karta nemá čárový kód\".</string>
<string name="settings_brown_theme">Hnědá</string>
<string name="settings_grey_theme">Šedá</string>
<string name="settings_green_theme">Zelená</string>
<string name="settings_sky_blue_theme">Azurová</string>
<string name="settings_blue_theme">Modrá</string>
<string name="settings_violet_theme">Fialová</string>
<string name="settings_magenta_theme">Purpurová</string>
<string name="settings_pink_theme">Růžová</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">Barva motivu</string>
<string name="settings_system_locale">Systém</string>
<string name="settings_locale">Jazyk</string>
<string name="turn_flashlight_off">Vypnout světlo</string>
<string name="turn_flashlight_on">Zapnout světlo</string>
<string name="failedGeneratingShareURL">Nepodařilo se vygenerovat sdílenou adresu URL. Nahlaste to prosím.</string>
<string name="passwordRequired">Zadejte prosím heslo</string>
<string name="no">Ne</string>
<string name="yes">Ano</string>
<string name="updateBarcodeQuestionText">Změnili jste ID karty. Chcete také aktualizovat čárový kód, aby používal stejnou hodnotu\?</string>
<string name="updateBarcodeQuestionTitle">Aktualizovat hodnotu čárového kódu\?</string>
<string name="takePhoto">Pořídit fotku</string>
<string name="removeImage">Odstranit obrázek</string>
<string name="setBackImage">Nastavit obrázek zadní strany</string>
<string name="setFrontImage">Nastavit obrázek přední strany</string>
<string name="photos">Fotky</string>
<string name="backImageDescription">Obrázek zadní strany karty</string>
<string name="frontImageDescription">Obrázek přední strany karty</string>
<string name="intent_import_card_from_url_share_multiple_text">Chci s Vámi sdílet kartu</string>
<string name="copy_to_clipboard_multiple_toast">ID karty zkopírováno do schránky</string>
<string name="wrongValueForBarcodeType">Hodnota není platná pro vybraný typ čárového kódu</string>
<string name="unsupportedBarcodeType">Tento typ čárového kódu zatím nelze zobrazit. Možná bude podporován v pozdější verzi aplikace.</string>
<string name="barcodeId">Hodnota čárového kódu</string>
<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>
<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>
<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>
<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="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>
<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):
\n
\nNejsou shromažďovány žádné údaje, což může potvrdit každý, protože naše aplikace je libre software.</string>
<string name="privacy_policy">Zásady soukromí</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="chooseImportType">Importovat data z\?</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> se nezdá být platným zůstatkem.</string>
<string name="points">Body</string>
<string name="currency">Měna</string>
<string name="balance">Zůstatek</string>
<string name="errorReadingImage">Obrázek se nepodařilo přečíst</string>
<string name="noBarcodeFound">Čarový kód nenalezen</string>
<string name="groupsList">Skupiny: <xliff:g>%s</xliff:g></string>
<string name="addFromImage">Výběr obrázku z galerie</string>
<string name="addManually">Ruční zadání ID karty</string>
<string name="leaveWithoutSaveConfirmation">Ukončit bez uložení\?</string>
<string name="leaveWithoutSaveTitle">Ukončit</string>
<string name="failedOpeningFileManager">Nejprve si nainstalujte správce souborů.</string>
<string name="deleteConfirmationGroup">Smazat skupinu\?</string>
<string name="all">Všechny</string>
<plurals name="groupCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> karta</item>
<item quantity="few"><xliff:g>%d</xliff:g> karty</item>
<item quantity="other"><xliff:g>%d</xliff:g> karet</item>
</plurals>
<string name="noGroups">Kliknutím na tlačítko + plus nejprve přidejte skupiny pro kategorizaci.</string>
<string name="groups">Skupiny</string>
<string name="enter_group_name">Zadejte název skupiny</string>
<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>
<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>
<item quantity="other">Vybráno <xliff:g>%d</xliff:g> karet</item>
</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>
</resources>

View File

@@ -2,8 +2,8 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
<string name="action_search">Suchen</string>
<string name="action_add">Hinzufügen</string>
<string name="noGiftCards">Klicken Sie auf das Pluszeichen +, um eine Karte hinzuzufügen, oder importieren Sie zunächst einige aus dem ⋮ Menü.</string>
<string name="noMatchingGiftCards">Nichts gefunden. Versuchen Sie, Ihre Suche zu ändern.</string>
<string name="noGiftCards">Füge eine Karte mit + hinzu oder importiere welche über das ⋮ Menü.</string>
<string name="noMatchingGiftCards">Nichts gefunden. Versuche, deine Suche zu ändern.</string>
<string name="storeName">Name</string>
<string name="note">Notiz</string>
<string name="cardId">Kartennummer</string>
@@ -12,25 +12,25 @@
<string name="edit">Bearbeiten</string>
<string name="delete">Löschen</string>
<string name="confirm">Bestätigen</string>
<string name="lockScreen">Rotation blockieren</string>
<string name="unlockScreen">Rotation zulassen</string>
<string name="lockScreen">Rotation sperren</string>
<string name="unlockScreen">Rotation erlauben</string>
<string name="star">Zu den Favoriten hinzufügen</string>
<string name="unstar">Aus der Favoritenliste entfernen</string>
<string name="unstar">Aus den Favoriten entfernen</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Nummer in die Zwischenablage kopieren</string>
<string name="copy_to_clipboard">Kartennummer in die Zwischenablage kopieren</string>
<string name="sendLabel">Senden </string>
<string name="editCardTitle">Kundenkarte bearbeiten</string>
<string name="addCardTitle">Neue Kundenkarte</string>
<string name="scanCardBarcode">Strichcode scannen</string>
<string name="editCardTitle">Karte bearbeiten</string>
<string name="addCardTitle">Neue Karte</string>
<string name="scanCardBarcode">Barcode scannen</string>
<string name="cardShortcut">Shortcut zu einer Karte</string>
<string name="noCardsMessage">Fügen Sie zuerst eine Karte hinzu</string>
<string name="barcodeImageDescription">Bild des Strichcodes</string>
<string name="noCardsMessage">Füge zuerst eine Karte hinzu</string>
<string name="barcodeImageDescription">Bild des Barcodes</string>
<string name="noStoreError">Kein Name eingegeben</string>
<string name="noCardIdError">Keine Kartennummer angegeben</string>
<string name="noCardExistsError">Karte konnte nicht gefunden werden</string>
<string name="importExport">Import/Export</string>
<string name="exportName">Exportieren</string>
<string name="importExportHelp">Durch das Sichern Ihrer Karten können Sie sie auf ein anderes Gerät verschieben.</string>
<string name="exportName">Export</string>
<string name="importExportHelp">Durch das Sichern deiner Karten kannst du sie auf ein anderes Gerät übertragen.</string>
<string name="importSuccessfulTitle">Importiert</string>
<string name="importFailedTitle">Import fehlgeschlagen</string>
<string name="importFailed">Karten konnten nicht importiert werden</string>
@@ -39,51 +39,52 @@
<string name="exportFailed">Karten konnten nicht exportiert werden</string>
<string name="importing">Importiere…</string>
<string name="exporting">Exportiere…</string>
<string name="noExternalStoragePermissionError">Erteilen Sie zuerst die Erlaubnis zur externen Speicherung, um Karten zu importieren oder zu exportieren</string>
<string name="importOptionFilesystemTitle">Importiere aus Dateisystem</string>
<string name="importOptionFilesystemExplanation">Wähle eine Datei aus dem Speicher aus.</string>
<string name="importOptionFilesystemButton">Aus Dateisystem</string>
<string name="importOptionApplicationTitle">Andere Anwendung verwenden</string>
<string name="importOptionApplicationExplanation">Verwenden Sie eine beliebige Anwendung oder Ihren bevorzugten Dateiverwaltungsprogramm, um eine Datei zu öffnen.</string>
<string name="importOptionApplicationButton">Andere Anwendung verwenden</string>
<string name="noExternalStoragePermissionError">Erlaube Speicherzugriff um Karten zu importieren oder exportieren</string>
<string name="importOptionFilesystemTitle">Importiere aus dem Dateisystem</string>
<string name="importOptionFilesystemExplanation">Wähle eine Datei vom Dateisystem aus.</string>
<string name="importOptionFilesystemButton">Wähle vom Dateisystem</string>
<string name="importOptionApplicationTitle">Andere Anwendungen</string>
<string name="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="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">Informationen zu dieser Version: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="selectBarcodeTitle">Strichcode auswählen</string>
<string name="copy_to_clipboard_toast">Nummer in die Zwischenablage kopiert</string>
<string name="app_revision_fmt">Revisionsinfo: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="selectBarcodeTitle">Barcode auswählen</string>
<string name="copy_to_clipboard_toast">Kartennummer in die Zwischenablage kopiert</string>
<string name="thumbnailDescription">Vorschaubild für die Karte</string>
<string name="settings">Einstellungen</string>
<string name="settings_category_title_ui">Benutzeroberfläche</string>
<string name="settings_display_barcode_max_brightness">Helligkeit bei Strichcode Ansicht erhöhen</string>
<string name="settings_lock_barcode_orientation">Strichcodeausrichtung sperren</string>
<string name="settings_display_barcode_max_brightness">Barcodeansicht aufhellen</string>
<string name="settings_lock_barcode_orientation">Barcoderotation sperren</string>
<string name="exportSuccessful">Kartendaten exportiert</string>
<string name="importSuccessful">Kartendaten importiert</string>
<string name="intent_import_card_from_url_share_text">Ich will eine Karte mit Ihnen teilen</string>
<string name="intent_import_card_from_url_share_text">Ich würde gerne diese Karte mit dir teilen</string>
<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">Design</string>
<string name="enterBarcodeInstructions">Geben Sie die Karten-ID ein und wählen Sie unten entweder den Strichcodetyp oder „Diese Karte hat keinen Strichcode“.</string>
<string name="settings_theme">Theme</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>
<string name="exportOptionExplanation">Die Daten werden an einen Ort Ihrer Wahl geschrieben.</string>
<string name="failedParsingImportUriError">Der Import-URI konnte nicht analysiert werden</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>
<string name="barcodeNoBarcode">Diese Karte hat keinen Strichcode</string>
<string name="barcodeType">Strichcode-Typ</string>
<string name="barcodeNoBarcode">Diese Karte hat keinen Barcode</string>
<string name="barcodeType">Barcodetyp</string>
<string name="starImage">Favoritenstern</string>
<string name="deleteConfirmationGroup">Gruppe löschen\?</string>
<string name="deleteConfirmationGroup">Gruppe löschen?</string>
<string name="all">Alle</string>
<string name="noGroups">Klicken Sie auf das Pluszeichen +, um zunächst Gruppen zur Kategorisierung hinzuzufügen.</string>
<string name="noGroups">Klicke auf das Pluszeichen + um eine Gruppe hinzuzufügen.</string>
<string name="noGroupCards">Diese Gruppe hat noch keine Karten</string>
<string name="groups">Gruppen</string>
<string name="enter_group_name">Geben Sie den Gruppennamen ein</string>
<string name="enter_group_name">Gib einen Gruppennamen ein</string>
<string name="leaveWithoutSaveConfirmation">Beenden ohne zu speichern\?</string>
<string name="leaveWithoutSaveTitle">Beenden</string>
<string name="failedOpeningFileManager">Installieren Sie zunächst ein Dateiverwaltungsprogramm.</string>
<string name="noBarcode">Kein Strichcode</string>
<string name="addManually">Die Karten-ID manuell eingeben</string>
<string name="failedOpeningFileManager">Installiere zuerst einen Dateimanager.</string>
<string name="noBarcode">Kein Barcode</string>
<string name="addManually">Kartennummer manuell eingeben</string>
<string name="moveDown">Nach unten verschieben</string>
<string name="moveUp">Nach oben verschieben</string>
<plurals name="groupCardCount">
@@ -91,18 +92,18 @@
<item quantity="other"><xliff:g>%d</xliff:g> Karten</item>
</plurals>
<string name="groupsList">Gruppen: <xliff:g>%s</xliff:g></string>
<string name="app_loyalty_card_keychain">Bonuskartenschlüsselring</string>
<string name="chooseImportType">Daten importieren aus\?</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="chooseImportType">Daten importieren aus?</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> scheint kein gültiges Guthaben zu sein.</string>
<string name="points">Punkte</string>
<string name="currency">Währung</string>
<string name="balance">Guthaben</string>
<string name="moveBarcodeToCenterOfScreen">Strichcode auf dem Bildschirm zentrieren</string>
<string name="moveBarcodeToTopOfScreen">Strichcode auf dem Bildschirm nach oben schieben</string>
<string name="moveBarcodeToCenterOfScreen">Barcode auf dem Bildschirm zentrieren</string>
<string name="moveBarcodeToTopOfScreen">Barcode auf dem Bildschirm oben fixieren</string>
<string name="chooseExpiryDate">Ablaufdatum wählen</string>
<string name="never">Nie</string>
<string name="expiryDate">Ablaufdatum</string>
<string name="editBarcode">Strichcode bearbeiten</string>
<string name="editBarcode">Barcode ändern</string>
<string name="barcode">Strichcode</string>
<string name="card">Karte</string>
<string name="balancePoints"><xliff:g>%s</xliff:g> Punkte</string>
@@ -110,7 +111,7 @@
<string name="expiryStateSentenceExpired">Abgelaufen: <xliff:g>%s</xliff:g></string>
<string name="expiryStateSentence">Läuft ab: <xliff:g>%s</xliff:g></string>
<string name="settings_disable_lockscreen_while_viewing_card">Sperrbildschirm verhindern</string>
<string name="settings_keep_screen_on">Bildschirm eingeschaltet halten</string>
<string name="settings_keep_screen_on">Bildschirm aktiv halten</string>
<string name="privacy_policy_popup_text">Hinweis zum Datenschutz (oft gefordert):
\n
\nKEINE DATEN WERDEN GESAMMELT, was jeder bestätigen kann, da unsere Anwendung eine freie Software ist.</string>
@@ -128,45 +129,45 @@
<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>
<string name="importCatima">Aus Catima importieren</string>
<string name="setBarcodeId">Strichcodewert setzen</string>
<string name="sameAsCardId">Gleich wie Karten-ID</string>
<string name="barcodeId">Strichcodewert</string>
<string name="errorReadingImage">Das Bild konnte nicht gelesen werden</string>
<string name="noBarcodeFound">Kein Strichcode gefunden</string>
<string name="addFromImage">Bild aus der Galerie auswählen</string>
<string name="settings_max_font_size_scale">Max. Schriftgröße</string>
<string name="unsupportedBarcodeType">Dieser Strichcodetyp kann noch nicht angezeigt werden. Er wird möglicherweise in einer späteren Version der Anwendung unterstützt.</string>
<string name="wrongValueForBarcodeType">Der Wert ist für den gewählten Strichcodetyp nicht gültig</string>
<string name="setBarcodeId">Manuell eingeben</string>
<string name="sameAsCardId">Entspricht Kartennummer</string>
<string name="barcodeId">Barcodewert</string>
<string name="errorReadingImage">Bildverarbeitung fehlgeschlagen</string>
<string name="noBarcodeFound">Kein Barcode erkannt</string>
<string name="addFromImage">Bild aus der Galerie wählen</string>
<string name="settings_max_font_size_scale">Maximale Schriftgröße</string>
<string name="unsupportedBarcodeType">Dieser Barcodetyp kann noch nicht angezeigt werden. Wir hoffen das Format in einer zukünftigen Version zu unterstützen.</string>
<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="intent_import_card_from_url_share_multiple_text">Ich möchte Karten mit dir teilen</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>
<string name="no">Nein</string>
<string name="yes">Ja</string>
<string name="updateBarcodeQuestionText">Sie haben die Karten-ID geändert. Möchten Sie auch den Strichcode aktualisieren, um denselben Wert zu verwenden\?</string>
<string name="updateBarcodeQuestionTitle">Strichcodewert aktualisieren\?</string>
<string name="updateBarcodeQuestionText">Kartennummer geändert. Möchtest du auch den Barcode auf den gleichen Wert ändern?</string>
<string name="updateBarcodeQuestionTitle">Barcodewert aktualisieren?</string>
<string name="takePhoto">Foto aufnehmen</string>
<string name="removeImage">Bild entfernen</string>
<string name="setBackImage">Rückseitenbild einstellen</string>
<string name="setFrontImage">Vorderseitenbild einstellen</string>
<string name="setBackImage">Kartenrückseite</string>
<string name="setFrontImage">Kartenvorderseite</string>
<string name="photos">Fotos</string>
<string name="frontImageDescription">Bild der Kartenvorderseite</string>
<string name="backImageDescription">Bild der Kartenrückseite</string>
<string name="passwordRequired">Bitte geben Sie das Passwort ein</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>
<string name="importStocard">Von Stocard importieren</string>
<string name="turn_flashlight_off">Taschenlampe ausschalten</string>
<string name="turn_flashlight_on">Taschenlampe einschalten</string>
<string name="failedGeneratingShareURL">Keine teilbare URL konnte generiert werden. Bitte melden Sie dies.</string>
<string name="turn_flashlight_off">Licht ausschalten</string>
<string name="turn_flashlight_on">Licht einschalten</string>
<string name="failedGeneratingShareURL">URL konnte nicht erstellt werden. Bitte melde das an uns.</string>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> Karte ausgewählt</item>
<item quantity="other"><xliff:g>%d</xliff:g> Karten ausgewählt</item>
</plurals>
<string name="deleteTitle">Karte entfernen</string>
<string name="deleteConfirmation">Diese Karte löschen\?</string>
<string name="deleteTitle">Karte löschen</string>
<string name="deleteConfirmation">Diese Karte wirklich löschen?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Diese <xliff:g>%d</xliff:g> Karte endgültig löschen\?</item>
<item quantity="other">Diese <xliff:g>%d</xliff:g> Karten endgültig löschen\?</item>
@@ -175,4 +176,17 @@
<item quantity="one"><xliff:g>%d</xliff:g> Karte löschen</item>
<item quantity="other"><xliff:g>%d</xliff:g> Karten löschen</item>
</plurals>
<string name="settings_system_locale">System</string>
<string name="settings_locale">Sprache</string>
<string name="settings_brown_theme">Braun</string>
<string name="settings_grey_theme">Grau</string>
<string name="settings_green_theme">Grün</string>
<string name="settings_sky_blue_theme">Himmelblau</string>
<string name="settings_blue_theme">Blau</string>
<string name="settings_violet_theme">Violett</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_pink_theme">Rosa</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">Designfarbe</string>
<string name="app_contributors">Ermöglicht durch: <xliff:g id="app_contributors">%s</xliff:g></string>
</resources>

View File

@@ -6,30 +6,30 @@
<string name="updateBarcodeQuestionText">Vaihdoit kortin ID-tunnuksen. Haluatko päivittää myös viivakoodin käyttämään samaa arvoa\?</string>
<string name="updateBarcodeQuestionTitle">Päivitä viivakoodin arvo\?</string>
<string name="intent_import_card_from_url_share_multiple_text">Haluan jakaa joitain kortteja kanssasi</string>
<string name="copy_to_clipboard_multiple_toast">Kopioitiin korttitunnukset leikepöydälle</string>
<string name="copy_to_clipboard_multiple_toast">Kortin tunnukset kopioidaan leikepöydälle</string>
<string name="wrongValueForBarcodeType">Arvo ei ole kelvollinen valitulle viivakoodityypille</string>
<string name="unsupportedBarcodeType">Tätä viivakoodityyppiä ei voi vielä näyttää. Sitä saatetaan tukea sovelluksen uudemmassa versiossa.</string>
<string name="unsupportedBarcodeType">Tätä viivakoodityyppiä ei voi vielä näyttää. Sitä saatetaan tukea sovelluksen myöhemmässä versiossa.</string>
<string name="setBarcodeId">Aseta viivakoodin arvo</string>
<string name="sameAsCardId">Sama kuin kortin ID-tunnus</string>
<string name="barcodeId">Viivakoodin arvo</string>
<string name="importVoucherVaultMessage">Etsi tiedostoa joka on todennäköisesti nimetty nimellä <i>vouchervault.json</i> tuotavaksi.
\nTai luo se Vie toiminnolla Voucher Vault sovelluksessa.</string>
<string name="importVoucherVaultMessage">Valitse tuotava <i>vouchervault.json</i>-vienti Voucher Vaultista.
\nTai luo se painamalla ensin Vie Voucher Vaultissa.</string>
<string name="importVoucherVault">Tuo Voucher Vault varmuuskopiotiedostosta</string>
<string name="importLoyaltyCardKeychainMessage">Etsi tiedostoa joka on todennäköisesti nimetty nimellä <i>LoyaltyCardKeychain.csv</i> tuotavaksi.
\nTai luo se Tuo/Vie toiminnolla Loyalty Card Keychain sovelluksessa, valitsemalla valikosta Vie.</string>
<string name="importLoyaltyCardKeychainMessage">Valitse <i>LoyaltyCardKeychain.csv</i>-vientitietosi Loyalty Card Keychainista tuotavaksi.
\nTai luo se Loyalty Card Keychainin Import/Export-valikosta painamalla ensin Export (Vie).</string>
<string name="importLoyaltyCardKeychain">Tuo Loyalty Card Keychain varmuuskopiotiedostosta</string>
<string name="importFidmeMessage">Etsi tiedostoa joka on todennäköisesti nimetty nimellä <i>fidme-export-request-xxxxxx.zip</i> tuotavaksi ja valitse viivakoodityypit manuaalisesti jälkeenpäin.
\nTai luo se Tuo/Vie toiminnolla FidMe profiilistasi, valitsemalla Tietotosuoja ja sitten valitsemalla Vie tietoni.</string>
<string name="importFidmeMessage">Valitse <i>fidme-export-request-xxxxxxxx.zip</i>-vienti FidMe:stä tuotavaksi ja valitse viivakoodityypit manuaalisesti sen jälkeen.
\nTai luo se FidMe-profiilistasi valitsemalla Tietosuoja ja painamalla ensin Extract my data.</string>
<string name="importFidme">Tuo FidMe varmuuskopiotiedostosta</string>
<string name="importCatimaMessage">Etsi tiedostoa joka on todennäköisesti nimetty nimellä <i>Catima.csv</i> tuotavaksi.
\nTai luo se Tuo/Vie toiminnolla Catima sovelluksessa, valitsemalla valikosta Vie.</string>
<string name="importCatimaMessage">Valitse tuotava <i>catima.zip</i>-vienti Catimasta.
\nTai luo se jonkin toisen Catima-sovelluksen Tuo/Vie-valikosta painamalla siellä ensin Vie.</string>
<string name="importCatima">Tuo Catima varmuuskopiotiedostosta</string>
<string name="accept">Hyväksy</string>
<string name="privacy_policy_popup_text">Tietosuojaseloste (joidenkin sovelluskauppojen vaatimus):
\n
\nMITÄÄN TIETOJA EI KERÄTÄ LAINKAAN, minkä kuka tahansa voi vahvistaa, koska sovelluksemma on vapaa ohjelmisto.</string>
<string name="privacy_policy">Tietosuojakäytäntö</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="app_loyalty_card_keychain">Kanta-asiakaskortin avainnippu</string>
<string name="chooseImportType">Tuo tietoja kohteesta\?</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> ei vaikuta olevan kelvollinen saldo.</string>
<string name="points">Pisteet</string>
@@ -85,8 +85,8 @@
<string name="copy_to_clipboard_toast">Kortin ID-tunnus kopioitu leikepöydälle</string>
<string name="enterBarcodeInstructions">Syötä kortin ID-tunnus ja valitse sen viivakoodityyppi, tai valitse \"Tällä kortilla ei ole viivakoodia\".</string>
<string name="selectBarcodeTitle">Valitse viivakoodi</string>
<string name="app_resources">Kolmannen osapuolen vapaat resurssit: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Kolmannen osapuolen vapaat kirjastot: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources">Vapaat kolmannen osapuolen resurssit: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Kolmannen osapuolen Libre-kirjastot: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_revision_fmt">Muutostiedot: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="debug_version_fmt">Versio: <xliff:g id="version">%s</xliff:g></string>
<string name="about_title_fmt">Tietoja <xliff:g id="app_name">%s</xliff:g></string>
@@ -156,4 +156,23 @@
<string name="frontImageDescription">Kortin etukuva</string>
<string name="deleteConfirmation">Poista tämä kortti\?</string>
<string name="deleteTitle">Poista kortti</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Poista tämä <xliff:g>%d</xliff:g> kortti pysyvästi\?</item>
<item quantity="other">Poista tämä <xliff:g>%d</xliff:g> kortit pysyvästi\?</item>
</plurals>
<plurals name="deleteCardsTitle">
<item quantity="one">Poista <xliff:g>%d</xliff:g>kortti</item>
<item quantity="other">Poista <xliff:g>%d</xliff:g>kortit</item>
</plurals>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> Kortti valittu</item>
<item quantity="other"><xliff:g>%d</xliff:g> kortit valitut</item>
</plurals>
<string name="importStocard">Tuo Stocardista</string>
<string name="importStocardMessage">Valitse tuotava <i>***-sync.zip</i>-vienti Stocardista.
\nTai hanki se lähettämällä sähköpostia osoitteeseen support@stocardapp.com ja pyytämällä tietojesi vientiä.</string>
<string name="passwordRequired">Ole hyvä ja syötä salasana</string>
<string name="failedGeneratingShareURL">Ei pystynyt luomaan jaettavaa URL-osoitetta. Ilmoita tästä.</string>
<string name="turn_flashlight_on">Sytytä taskulamppu</string>
<string name="turn_flashlight_off">Sammuta salamavalo</string>
</resources>

View File

@@ -175,4 +175,18 @@
<item quantity="one">Supprimer <xliff:g>%d</xliff:g> carte</item>
<item quantity="other">Supprimer <xliff:g>%d</xliff:g> cartes</item>
</plurals>
<string name="settings_system_locale">Système</string>
<string name="settings_locale">Langue</string>
<string name="settings_brown_theme">Marron</string>
<string name="settings_grey_theme">Gris</string>
<string name="settings_green_theme">Vert</string>
<string name="settings_sky_blue_theme">Bleu ciel</string>
<string name="settings_blue_theme">Bleu</string>
<string name="settings_violet_theme">Violet</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_pink_theme">Rose</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">Couleur du thème</string>
<string name="app_contributors">Rendu possible par : <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="noGroupCards">Ce groupe ne contient pas de cartes</string>
</resources>

View File

@@ -175,4 +175,18 @@
<item quantity="one">Elimina <xliff:g>%d</xliff:g> carta</item>
<item quantity="other">Elimina <xliff:g>%d</xliff:g> carte</item>
</plurals>
<string name="settings_system_locale">Sistema</string>
<string name="settings_locale">Lingua</string>
<string name="settings_brown_theme">Marrone</string>
<string name="settings_grey_theme">Grigio</string>
<string name="settings_green_theme">Verde</string>
<string name="settings_sky_blue_theme">Azzurro</string>
<string name="settings_blue_theme">Blu</string>
<string name="settings_violet_theme">Viola</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_pink_theme">Rosa</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">Colore del tema</string>
<string name="app_contributors">Reso possibile da: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="noGroupCards">Questo gruppo non contiene carte</string>
</resources>

View File

@@ -141,10 +141,10 @@
<string name="action_search">検索</string>
<string name="intent_import_card_from_url_share_multiple_text">カードを共有しましょう</string>
<string name="copy_to_clipboard_multiple_toast">カード番号をクリップボードにコピーしました</string>
<string name="card_ids_copied">コピーしたカード</string>
<string name="card_ids_copied">カード番号をコピーしました</string>
<string name="turn_flashlight_off">ライトをオフにする</string>
<string name="turn_flashlight_on">ライトをオンにする</string>
<string name="failedGeneratingShareURL">共有URLの生成に失敗しました。バグを報告してください。</string>
<string name="failedGeneratingShareURL">共有URLの生成を生成できませんでした。バグを報告してください。</string>
<string name="passwordRequired">パスワードを入力してください</string>
<string name="no">いいえ</string>
<string name="yes">はい</string>
@@ -157,7 +157,7 @@
<string name="photos">フォト</string>
<string name="backImageDescription">裏面</string>
<string name="frontImageDescription">表面</string>
<string name="importStocardMessage">Stocardでエクスポートした<i>***-sync.zip</i>ファイルを選択し、手動でバーコード形式を選択してください。
<string name="importStocardMessage">Stocardでエクスポートした<i>***-sync.zip</i>ファイルを選択してください。
\nファイルがない場合、e-mailing support@stocardapp.comにデータのエクスポートを要求してください。</string>
<string name="importStocard">Stocardからインポート</string>
<plurals name="selectedCardCount">
@@ -165,4 +165,10 @@
</plurals>
<string name="deleteConfirmation">このカードを削除しますか?</string>
<string name="deleteTitle">カードの削除</string>
<plurals name="deleteCardsConfirmation">
<item quantity="other"><xliff:g>%d</xliff:g> 枚のカードを削除しますか?</item>
</plurals>
<plurals name="deleteCardsTitle">
<item quantity="other">削除対象 <xliff:g>%d</xliff:g> cards</item>
</plurals>
</resources>

View File

@@ -179,4 +179,18 @@
<item quantity="few">Ištrinti <xliff:g>%d</xliff:g> korteles</item>
<item quantity="other">Ištrinti <xliff:g>%d</xliff:g> kortelių</item>
</plurals>
<string name="settings_system_locale">Sistemos</string>
<string name="settings_locale">Kalba</string>
<string name="settings_brown_theme">Ruda</string>
<string name="settings_grey_theme">Pilka</string>
<string name="settings_green_theme">Žalia</string>
<string name="settings_sky_blue_theme">Dangaus mėlynumo</string>
<string name="settings_blue_theme">Mėlyna</string>
<string name="settings_violet_theme">Violetinė</string>
<string name="settings_magenta_theme">Rausvai raudona</string>
<string name="settings_pink_theme">Rožinė</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">Temos spalva</string>
<string name="app_contributors">Tapo įmanoma su pagalba: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="noGroupCards">Šioje grupėje nėra jokių kortelių</string>
</resources>

View File

@@ -175,4 +175,18 @@
<item quantity="one">Slett <xliff:g xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">%d</xliff:g> kort</item>
<item quantity="other">Slett <xliff:g xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">%d</xliff:g> kort</item>
</plurals>
</resources>
<string name="settings_system_locale">System</string>
<string name="settings_locale">Språk</string>
<string name="settings_violet_theme">Fiolett</string>
<string name="settings_magenta_theme">Magentarød</string>
<string name="app_contributors">Muliggjort av: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="settings_brown_theme">Brun</string>
<string name="settings_grey_theme">Grå</string>
<string name="settings_green_theme">Grønn</string>
<string name="settings_sky_blue_theme">Himmelblå</string>
<string name="settings_blue_theme">Blå</string>
<string name="settings_pink_theme">Rosa</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">Draktfarge</string>
<string name="noGroupCards">Denne gruppen inneholder ikke noen kort</string>
</resources>

View File

@@ -19,4 +19,6 @@
<color name="inputDividerBorder">#666666</color>
<color name="iconColor">#ffffff</color>
<color name="mainLoyaltyCardBackground">#000000</color>
</resources>

View File

@@ -44,7 +44,7 @@
<string name="noExternalStoragePermissionError">Verleen het recht externe opslag om kaarten te kunnen im- of exporteren</string>
<string name="exportOptionExplanation">De gegevens worden weggeschreven op een locatie naar keuze.</string>
<string name="importOptionFilesystemTitle">Importeren uit bestandssysteem</string>
<string name="importOptionFilesystemExplanation">Kies een specifiek bestand vanop het bestandssysteem.</string>
<string name="importOptionFilesystemExplanation">Kies een specifiek bestand van het bestandssysteem.</string>
<string name="importOptionFilesystemButton">Van bestandssysteem</string>
<string name="importOptionApplicationTitle">Andere app gebruiken</string>
<string name="importOptionApplicationExplanation">Open een bestand middels een app of je favoriete bestandsbeheerder.</string>
@@ -55,7 +55,7 @@
<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>
<string name="selectBarcodeTitle">Barcode toevoegen</string>
<string name="enterBarcodeInstructions">Voer de kaart-id in en kies daarna het soort barcode druk op “Deze kaart heeft geen barcode”.</string>
<string name="enterBarcodeInstructions">Voer de kaart-id in en kies daarna het soort barcode of druk op “Deze kaart heeft geen barcode”.</string>
<string name="copy_to_clipboard_toast">De kaart-id is gekopieerd naar het klembord</string>
<string name="thumbnailDescription">Miniatuurvoorbeeld van kaart</string>
<string name="settings">Instellingen</string>
@@ -175,4 +175,18 @@
<item quantity="one">Weet je zeker dat je deze <xliff:g>%d</xliff:g> kaart wilt verwijderen\?</item>
<item quantity="other">Weet je zeker dat je deze <xliff:g>%d</xliff:g> kaarten wilt verwijderen\?</item>
</plurals>
<string name="settings_system_locale">Systeemtaal</string>
<string name="settings_locale">Taal</string>
<string name="settings_brown_theme">Bruin</string>
<string name="settings_grey_theme">Grijs</string>
<string name="settings_green_theme">Groen</string>
<string name="settings_sky_blue_theme">Hemelsblauw</string>
<string name="settings_blue_theme">Blauw</string>
<string name="settings_violet_theme">Violet</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_pink_theme">Roze</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">Themakleur</string>
<string name="app_contributors">Mede mogelijk gemaakt door: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="noGroupCards">Deze groep bevat geen kaarten</string>
</resources>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="exporting">Exportacion…</string>
<string name="importing">Importacion…</string>
<string name="exportFailed">Exportacion pas possibla</string>
@@ -38,4 +38,17 @@
<string name="storeName">Nom</string>
<string name="action_add">Apondre</string>
<string name="action_search">Recercar</string>
<string name="ok">D\'acòrdi</string>
<string name="deleteConfirmation">Suprimir aquesta carta\?</string>
<plurals name="deleteCardsTitle">
<item quantity="one">Suprimir <xliff:g>%d</xliff:g> carta</item>
<item quantity="other">Suprimir <xliff:g>%d</xliff:g> cartas</item>
</plurals>
<string name="deleteTitle">Suprimir la carta</string>
<string name="noBarcode">Cap de còdi de barras</string>
<string name="barcodeNoBarcode">Aquesta carta a pas cap de còdi de barras</string>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> carta seleccionada</item>
<item quantity="other"><xliff:g>%d</xliff:g> cartas seleccionadas</item>
</plurals>
</resources>

View File

@@ -32,7 +32,7 @@
<string name="failedParsingImportUriError">Невозможно разобрать импортируемый URI</string>
<string name="importExport">Импорт/Экспорт</string>
<string name="exportName">Экспорт</string>
<string name="importExportHelp">Резервное копирование карт позволяет переместить их на другое устройство.</string>
<string name="importExportHelp">Резервное копирование карт позволяет перенести их на другое устройство.</string>
<string name="importSuccessfulTitle">Импортировано</string>
<string name="importFailedTitle">Импорт не выполнен</string>
<string name="importFailed">Невозможно импортировать карты</string>
@@ -183,4 +183,18 @@
<item quantity="many">Удаление <xliff:g>%d</xliff:g> карт</item>
<item quantity="other">Удаление <xliff:g>%d</xliff:g> карт</item>
</plurals>
<string name="settings_system_locale">Системный</string>
<string name="settings_locale">Язык</string>
<string name="settings_sky_blue_theme">Голубой</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_brown_theme">Коричневый</string>
<string name="settings_grey_theme">Серый</string>
<string name="settings_green_theme">Зелёный</string>
<string name="settings_blue_theme">Синий</string>
<string name="settings_violet_theme">Фиолетовый</string>
<string name="settings_magenta_theme">Пурпурный</string>
<string name="settings_pink_theme">Розовый</string>
<string name="settings_theme_color">Цвет темы</string>
<string name="app_contributors">Создано при поддержке: <xliff:g id="app_contributors">%s</xliff:g></string>
<string name="noGroupCards">В группе нет карт</string>
</resources>

View File

@@ -75,7 +75,7 @@
<string name="intent_import_card_from_url_share_multiple_text">Jag vill dela några kort med dig</string>
<string name="copy_to_clipboard_multiple_toast">Kort-ID:n kopierades till Urklipp</string>
<string name="wrongValueForBarcodeType">Värdet är inte giltigt för den valda streckkodstypen</string>
<string name="unsupportedBarcodeType">Denna streckkodstyp kan ännu inte visas. Den ka komma att stödjas i en senare version av appen.</string>
<string name="unsupportedBarcodeType">Denna streckkodstyp kan ännu inte visas. Den kan komma att stödjas i en senare version av appen.</string>
<string name="setBarcodeId">Ange streckkodsvärde</string>
<string name="sameAsCardId">Samma som kort-ID</string>
<string name="turn_flashlight_on">Sätt på ficklampa</string>
@@ -143,4 +143,37 @@
<string name="noGiftCards">Klicka på plus(+)-knappen för att lägga till ett kort, eller importera några från ⋮-menyn först.</string>
<string name="action_add">Lägg till</string>
<string name="action_search">Sök</string>
<string name="exportOptionExplanation">Datan kommer att sparas till en plats som du väljer.</string>
<string name="exportName">Exportera</string>
<string name="exportFailedTitle">Exporten misslyckades</string>
<string name="exportSuccessfulTitle">Exporten lyckades</string>
<string name="scanCardBarcode">Skanna streckkod på kort</string>
<string name="settings_system_theme">Systemtemat</string>
<string name="app_revision_fmt">Ändringsinfo: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="privacy_policy_popup_text">Notis rörande integritetspolicy (krävs av vissa appbutiker):
\n
\nINGEN DATA ALLS SAMLAS IN, vilket vem som helst kan bekräfta eftersom vår app är fri programvara.</string>
<string name="unlockScreen">Tillåt rotation</string>
<string name="privacy_policy">Integritetspolicy</string>
<string name="expiryStateSentenceExpired">Förföll: <xliff:g>%s</xliff:g></string>
<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_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>
<string name="balance">Saldo</string>
<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="expiryStateSentence">Giltigt till: <xliff:g>%s</xliff:g></string>
<string name="exportSuccessful">Kortdata exporterad</string>
<string name="importSuccessful">Kortdata importerad</string>
<string name="failedParsingImportUriError">Kunde inte tolka import-URI:n</string>
<string name="note">Anteckning</string>
<string name="settings_system_locale">System</string>
<string name="settings_locale">Språk</string>
</resources>

View File

@@ -41,7 +41,7 @@
<string name="importCatima">Імпорт з Catima</string>
<string name="accept">Прийняти</string>
<string name="privacy_policy">Політика конфіденційності</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="app_loyalty_card_keychain">Брелок картки лояльності</string>
<string name="chooseImportType">Імпортувати дані з\?</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> здається, не є дійсним залишком.</string>
<string name="points">Бали</string>
@@ -76,7 +76,7 @@
<string name="enter_group_name">Введіть ім\'я групи</string>
<string name="exportSuccessful">Дані картки/карток експортовано</string>
<string name="importSuccessful">Дані картки/карток імпортовано</string>
<string name="intent_import_card_from_url_share_text">Я хочу поділитися картою з тобою</string>
<string name="intent_import_card_from_url_share_text">Я хочу поділитися з тобою картою</string>
<string name="settings_disable_lockscreen_while_viewing_card">Не блокувати екран</string>
<string name="settings_keep_screen_on">Не вимикати екран</string>
<string name="settings_lock_barcode_orientation">Заблокувати орієнтацію штрих-коду</string>
@@ -106,7 +106,7 @@
<string name="importOptionApplicationExplanation">Використайте іншу програму чи ваш улюблений файл-менеджер для відкриття файлу.</string>
<string name="importOptionApplicationTitle">Використати іншу програму</string>
<string name="importOptionFilesystemButton">З провідника</string>
<string name="importOptionFilesystemExplanation">Оберіть конкретний файл у провіднику.</string>
<string name="importOptionFilesystemExplanation">Оберіть файл у провіднику.</string>
<string name="importOptionFilesystemTitle">Імпорт з провідника</string>
<string name="exportOptionExplanation">Дані буде записано до локації обраної вами.</string>
<string name="noExternalStoragePermissionError">Надайте дозвіл на доступ до пам\'яті пристрою для імпорту чи експорту карток</string>
@@ -140,7 +140,7 @@
<string name="delete">Видалити</string>
<string name="edit">Редагувати</string>
<string name="save">Зберегти</string>
<string name="cancel">Відмінити</string>
<string name="cancel">Скасувати</string>
<string name="unstar">Видалити з улюблених</string>
<string name="star">Додати до улюблених</string>
<string name="cardId">ID картки</string>
@@ -160,8 +160,8 @@
<string name="photos">Фотографії</string>
<string name="backImageDescription">Тильна сторона карти</string>
<string name="frontImageDescription">Лицьова сторона карти</string>
<string name="importStocardMessage">Оберіть Stocard експорт-файл, названий <i>***-sync.zip</i> для імпортування і оберіть типи штрих-кодів вручну пізніше.
\nЧи отримайте його надіславши електронного листа із запитом на експортування ваших даних до support@stocardapp.com.</string>
<string name="importStocardMessage">Виберіть експорт <i> ***-sync.zip </i> зі Stocard для імпорту.
\nАбо отримайте його, надіславши електронною поштою support@stocardapp.com з проханням експортувати ваші дані.</string>
<string name="importStocard">Імпорт із Stocard</string>
<plurals name="selectedCardCount">
<item quantity="one">Обрано: <xliff:g>%d</xliff:g> карта</item>
@@ -169,6 +169,30 @@
<item quantity="many">Обрано: <xliff:g>%d</xliff:g> карт</item>
<item quantity="other">Обрано: <xliff:g>%d</xliff:g> карт</item>
</plurals>
<string name="deleteTitle">Видалити карту</string>
<string name="deleteTitle">Видалити картку</string>
<string name="deleteConfirmation">Бажаєте видалити карту\?</string>
</resources>
<plurals name="deleteCardsTitle">
<item quantity="one">Видалити <xliff:g>%d</xliff:g> картку</item>
<item quantity="few">Видалити <xliff:g>%d</xliff:g> картки</item>
<item quantity="many">Видалити <xliff:g>%d</xliff:g> картки</item>
<item quantity="other">Видалити <xliff:g>%d</xliff:g> картки</item>
</plurals>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Видаліть цю <xliff:g>%d</xliff:g> карту назавжди\?</item>
<item quantity="few">Видаліть ці <xliff:g>%d</xliff:g> карти назавжди\?</item>
<item quantity="many">Видаліть ці <xliff:g>%d</xliff:g> карти назавжди\?</item>
<item quantity="other">Видаліть ці <xliff:g>%d</xliff:g> карти назавжди\?</item>
</plurals>
<string name="settings_blue_theme">Синя</string>
<string name="settings_violet_theme">Фіолетова</string>
<string name="settings_magenta_theme">Пурпурова</string>
<string name="settings_pink_theme">Рожева</string>
<string name="settings_catima_theme">Catima</string>
<string name="settings_theme_color">Колір теми</string>
<string name="settings_system_locale">Системна</string>
<string name="settings_locale">Мова</string>
<string name="settings_brown_theme">Коричнева</string>
<string name="settings_grey_theme">Сіра</string>
<string name="settings_green_theme">Зелена</string>
<string name="settings_sky_blue_theme">Небесно-синя</string>
</resources>

View File

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

View File

@@ -1,6 +0,0 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

View File

@@ -24,16 +24,16 @@
<string name="setBarcodeId">设置条形码值</string>
<string name="sameAsCardId">与卡号相同</string>
<string name="barcodeId">条形码值</string>
<string name="importVoucherVaultMessage">找到一个可能名为<i>vouchervault.json</i>的文件进行导入。
<string name="importVoucherVaultMessage">选择从Voucher Vault导出的文件<i>vouchervault.json</i>进行导入。
\n或者先在Voucher Vault中按下导出键来创建导出。</string>
<string name="importVoucherVault">从 Voucher Vault 导入</string>
<string name="importLoyaltyCardKeychainMessage">找到一个很可能名为<i>LoyaltyCardKeychain.csv</i>的文件来导入。
<string name="importLoyaltyCardKeychainMessage">选择从Loyalty Card Keychain导出的文件<i>LoyaltyCardKeychain.csv</i>来导入。
\n或者先从Loyalty Card Keychain的Import/Export菜单中选择Export来导出。</string>
<string name="importLoyaltyCardKeychain">从 Loyalty Card Keychain 导入</string>
<string name="importFidmeMessage">找到一个可能名为<i>fidme-export-request-xxxxxx.zip</i>的文件进行导入,之后再手动选择条码类型。
<string name="importFidmeMessage">选择从Fidme导出的文件<i>fidme-export-request-xxxxxx.zip</i>进行导入,之后再手动选择条码类型。
\n或者从你的FidMe配置文件中选择数据保护然后按提取我的数据来创建导出。</string>
<string name="importFidme">从 FidMe 导入</string>
<string name="importCatimaMessage">找到一个可能名为<i>Catima.csv</i>的文件来导入。
<string name="importCatimaMessage">选择从Catima导出的文件<i>Catima.zip</i>来导入。
\n或者先从另一个Catima应用程序的导入/导出菜单中,来创建导出。</string>
<string name="importCatima">从 Catima 导入</string>
<string name="accept">接受</string>
@@ -143,4 +143,32 @@
<string name="action_search">搜索</string>
<string name="deleteConfirmation">删除此卡?</string>
<string name="deleteTitle">移除卡片</string>
<string name="starImage">最喜欢的星星</string>
<string name="importStocardMessage">选择你从Stocard导出的<i>****-sync.zip</i>来导入。
\n或者发电子邮件给support@stocardapp.com要求导出你的数据从而获得此文件。</string>
<plurals name="deleteCardsConfirmation">
<item quantity="other">确定永久删除 <xliff:g>%d</xliff:g> 这些卡片?</item>
</plurals>
<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>
<string name="turn_flashlight_off">关上手电筒</string>
<string name="turn_flashlight_on">开启手电筒</string>
<string name="failedGeneratingShareURL">无法生成可分享的URL。请向开发者报告。</string>
<string name="passwordRequired">请输入密码</string>
<string name="no"></string>
<string name="yes"></string>
<string name="updateBarcodeQuestionText">您改变了卡片的ID。是否需要同时更新条形码以使用相同的值</string>
<string name="updateBarcodeQuestionTitle">是否要更新条形码的值?</string>
<string name="takePhoto">拍照</string>
<string name="removeImage">移除图像</string>
<string name="setBackImage">设置背面图像</string>
<string name="setFrontImage">设置正面图像</string>
<string name="photos">照片</string>
<string name="backImageDescription">卡片的背面图像</string>
<string name="frontImageDescription">卡片的正面图像</string>
<string name="importStocard">从Stocard导入</string>
</resources>

View File

@@ -20,4 +20,6 @@
<color name="iconColor">#000000</color>
<color name="alert">#FF0000</color>
<color name="mainLoyaltyCardBackground">#F8F8F8</color>
</resources>

View File

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

View File

@@ -12,6 +12,59 @@
<item>@string/settings_dark_theme</item>
</string-array>
<string-array name="color_values">
<item>@string/settings_key_catima_theme</item>
<item>@string/settings_key_pink_theme</item>
<item>@string/settings_key_magenta_theme</item>
<item>@string/settings_key_violet_theme</item>
<item>@string/settings_key_blue_theme</item>
<item>@string/settings_key_sky_blue_theme</item>
<item>@string/settings_key_green_theme</item>
<item>@string/settings_key_grey_theme</item>
<item>@string/settings_key_brown_theme</item>
</string-array>
<string-array name="color_value_strings">
<item>@string/settings_catima_theme</item>
<item>@string/settings_pink_theme</item>
<item>@string/settings_magenta_theme</item>
<item>@string/settings_violet_theme</item>
<item>@string/settings_blue_theme</item>
<item>@string/settings_sky_blue_theme</item>
<item>@string/settings_green_theme</item>
<item>@string/settings_grey_theme</item>
<item>@string/settings_brown_theme</item>
</string-array>
<string-array name="locale_values">
<item />
<item>bg</item>
<item>cs</item>
<item>de</item>
<item>el-rGR</item>
<item>eo</item>
<item>es-rAR</item>
<item>es</item>
<item>fi</item>
<item>fr</item>
<item>he-rIL</item>
<item>it</item>
<item>ja</item>
<item>ko</item>
<item>lt</item>
<item>nb-rNO</item>
<item>nl</item>
<item>oc</item>
<item>pl</item>
<item>ro-rRO</item>
<item>ru</item>
<item>sk</item>
<item>sl</item>
<item>uk</item>
<item>zh-rCN</item>
</string-array>
<array name="letter_tile_colors">
<item>#f16364</item>
<item>#f58559</item>

View File

@@ -138,6 +138,7 @@
<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>
<string name="noGroupCards">This group does not contain any cards</string>
<plurals name="groupCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> card</item>
<item quantity="other"><xliff:g>%d</xliff:g> cards</item>
@@ -213,4 +214,30 @@
<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>
<string name="settings_pink_theme">Pink</string>
<string name="settings_magenta_theme">Magenta</string>
<string name="settings_violet_theme">Violet</string>
<string name="settings_blue_theme">Blue</string>
<string name="settings_sky_blue_theme">Sky blue</string>
<string name="settings_green_theme">Green</string>
<string name="settings_grey_theme">Grey</string>
<string name="settings_brown_theme">Brown</string>
<string name="settings_key_catima_theme" translatable="false">catima_theme</string>
<string name="settings_key_pink_theme" translatable="false">pink_theme</string>
<string name="settings_key_magenta_theme" translatable="false">magenta_theme</string>
<string name="settings_key_violet_theme" translatable="false">violet_theme</string>
<string name="settings_key_blue_theme" translatable="false">blue_theme</string>
<string name="settings_key_sky_blue_theme" translatable="false">sky_blue_theme</string>
<string name="settings_key_green_theme" translatable="false">green_theme</string>
<string name="settings_key_grey_theme" translatable="false">grey_theme</string>
<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>
</resources>

View File

@@ -1,22 +1,90 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorSecondary">@color/colorSecondary</item>
<item name="colorAccent">@color/colorSecondary</item>
<item name="colorAccent">@color/colorPrimary</item>
<item name="actionModeBackground">@color/colorPrimary</item>
<item name="windowActionModeOverlay">true</item>
<item name="actionModeCloseDrawable">@drawable/ic_close</item>
</style>
<style name="AppTheme_pink" parent="AppTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/pink_colorPrimary</item>
<item name="colorPrimaryDark">@color/pink_colorPrimaryDark</item>
<item name="colorAccent">@color/pink_colorPrimary</item>
<item name="actionModeBackground">@color/pink_colorPrimary</item>
</style>
<style name="AppTheme_magenta" parent="AppTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/magenta_colorPrimary</item>
<item name="colorPrimaryDark">@color/magenta_colorPrimaryDark</item>
<item name="colorAccent">@color/magenta_colorPrimary</item>
<item name="actionModeBackground">@color/magenta_colorPrimary</item>
</style>
<style name="AppTheme_violet" parent="AppTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/violet_colorPrimary</item>
<item name="colorPrimaryDark">@color/violet_colorPrimaryDark</item>
<item name="colorAccent">@color/violet_colorPrimary</item>
<item name="actionModeBackground">@color/violet_colorPrimary</item>
</style>
<style name="AppTheme_blue" parent="AppTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/blue_colorPrimary</item>
<item name="colorPrimaryDark">@color/blue_colorPrimaryDark</item>
<item name="colorAccent">@color/blue_colorPrimary</item>
<item name="actionModeBackground">@color/blue_colorPrimary</item>
</style>
<style name="AppTheme_sky_blue" parent="AppTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/skyblue_colorPrimary</item>
<item name="colorPrimaryDark">@color/skyblue_colorPrimaryDark</item>
<item name="colorAccent">@color/skyblue_colorPrimary</item>
<item name="actionModeBackground">@color/skyblue_colorPrimary</item>
</style>
<style name="AppTheme_green" parent="AppTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/green_colorPrimary</item>
<item name="colorPrimaryDark">@color/green_colorPrimaryDark</item>
<item name="colorAccent">@color/green_colorPrimary</item>
<item name="actionModeBackground">@color/green_colorPrimary</item>
</style>
<style name="AppTheme_grey" parent="AppTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/grey_colorPrimary</item>
<item name="colorPrimaryDark">@color/grey_colorPrimaryDark</item>
<item name="colorAccent">@color/grey_colorPrimary</item>
<item name="actionModeBackground">@color/grey_colorPrimary</item>
</style>
<style name="AppTheme_brown" parent="AppTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/brown_colorPrimary</item>
<item name="colorPrimaryDark">@color/brown_colorPrimaryDark</item>
<item name="colorAccent">@color/brown_colorPrimary</item>
<item name="actionModeBackground">@color/brown_colorPrimary</item>
</style>
<style name="AppTheme.NoActionBar" parent="AppTheme">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="SplashTheme" parent="@style/AppTheme">
<item name="android:windowBackground">@drawable/background_splash</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.MaterialComponents.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.MaterialComponents.Light"/>
@@ -32,4 +100,49 @@
<item name="android:padding">@dimen/no_data_padding</item>
<item name="android:textSize">@dimen/no_data_textSize</item>
</style>
<style name="AlertDialogTheme" parent="ThemeOverlay.MaterialComponents.Dialog.Alert">
<item name="buttonBarNegativeButtonStyle">@style/NegativeButtonStyle</item>
<item name="buttonBarPositiveButtonStyle">@style/PositiveButtonStyle</item>
</style>
<style name="NegativeButtonStyle" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">@color/colorSecondaryText</item>
</style>
<style name="PositiveButtonStyle" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">@color/colorSecondaryText</item>
</style>
<color name="red_colorPrimary">#ff0000</color>
<color name="red_colorPrimaryDark">#DF0000</color>
<color name="pink_colorPrimary">#e91e63</color>
<color name="pink_colorPrimaryDark">#CB1755</color>
<color name="magenta_colorPrimary">#9b26af</color>
<color name="magenta_colorPrimaryDark">#7a1ea1</color>
<color name="violet_colorPrimary">#6639b6</color>
<color name="violet_colorPrimaryDark">#502ca7</color>
<color name="blue_colorPrimary">#3F51B5</color>
<color name="blue_colorPrimaryDark">#3445A2</color>
<color name="skyblue_colorPrimary">#03A9F4</color>
<color name="skyblue_colorPrimaryDark">#0094D7</color>
<color name="green_colorPrimary">#4CAF50</color>
<color name="green_colorPrimaryDark">#419744</color>
<!--<color name="colorPrimary">#3F51B5</color>-->
<!--<color name="colorPrimaryDark">#3445A2</color>-->
<color name="grey_colorPrimary">#9d9d9d</color>
<color name="grey_colorPrimaryDark">#606060</color>
<color name="grey_colorAccent">#f90</color>
<color name="brown_colorPrimary">#795548</color>
<color name="brown_colorPrimaryDark">#63453B</color>
<color name="brown_colorAccent">#e81d62</color>
</resources>

View File

@@ -16,6 +16,25 @@
app:iconSpaceReserved="false"
app:singleLineTitle="false" />
<ListPreference
android:key="@string/setting_key_theme_color"
android:title="@string/settings_theme_color"
android:defaultValue="@string/settings_key_catima_theme"
android:entries="@array/color_value_strings"
android:entryValues="@array/color_values"
app:iconSpaceReserved="false"
app:singleLineTitle="false" />
<ListPreference
android:key="@string/settings_key_locale"
android:title="@string/settings_locale"
android:defaultValue=""
android:entries="@array/locale_values"
android:entryValues="@array/locale_values"
app:iconSpaceReserved="false"
app:singleLineTitle="false" />
<nl.invissvenska.numberpickerpreference.NumberDialogPreference
android:key="@string/settings_key_max_font_size_scale"
android:title="@string/settings_max_font_size_scale"

View File

@@ -933,11 +933,10 @@ public class ImportExportTest
assertEquals(
groupsToGroupNames(
(List<Group>) Utils.hashmapGetOrDefault(
(List<Group>) Utils.mapGetOrDefault(
loyaltyCardGroups,
loyaltyCardID,
emptyGroup,
Integer.class
emptyGroup
)
),
groupsToGroupNames(

View File

@@ -25,9 +25,6 @@ import java.util.Currency;
import java.util.Date;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.Settings;
import static org.junit.Assert.assertEquals;
@@ -157,7 +154,7 @@ public class LoyaltyCardCursorAdapterTest
{
final Context context = activity.getApplicationContext();
Date expiryDate = new Date();
String dateString = context.getString(R.string.expiryStateSentence, DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate));
String dateString = DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate);
db.insertLoyaltyCard("store", "note", expiryDate, new BigDecimal("0"), null, "cardId", null, BarcodeFormat.UPC_A, Color.BLACK, 0);
LoyaltyCard card = db.getLoyaltyCard(1);
@@ -263,7 +260,7 @@ public class LoyaltyCardCursorAdapterTest
View view = createView(cursor);
checkView(view, card.store, card.note, "", "Balance: 100 points",false);
checkView(view, card.store, card.note, "", "100 points",false);
cursor.close();
}
@@ -279,7 +276,7 @@ public class LoyaltyCardCursorAdapterTest
View view = createView(cursor);
checkView(view, card.store, card.note, "", "Balance: $10.00",false);
checkView(view, card.store, card.note, "", "$10.00",false);
cursor.close();
}

View File

@@ -148,6 +148,11 @@ public class MainActivityTest
assertEquals(View.VISIBLE, list.getVisibility());
assertEquals(4, list.getAdapter().getItemCount());
// Make sure there is enough space to render all
list.measure(0, 0);
list.layout(0, 0, 100, 1000);
assertEquals("storeC", ((TextView) list.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.store)).getText());
assertEquals("storeD", ((TextView) list.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.store)).getText());
assertEquals("storeA", ((TextView) list.findViewHolderForAdapterPosition(2).itemView.findViewById(R.id.store)).getText());

View File

@@ -3,13 +3,13 @@
buildscript {
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
gradlePluginPortal()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.0'
classpath 'com.android.tools.build:gradle:7.0.1'
classpath 'gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.7.0'
// NOTE: Do not place your application dependencies here; they belong
@@ -20,6 +20,7 @@ buildscript {
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
gradlePluginPortal()
}

View File

@@ -1 +0,0 @@
catima.app

View File

@@ -47,7 +47,7 @@ Supported barcodes:
# Moving data from other apps
Within the app you can import cards and codes from files, Catima, Loyalty Card Keychain, Voucher Vault, and FidMe.
Within the app you can import cards and codes from files, Catima, FidMe, Loyalty Card Keychain, Voucher Vault, and Stocard.
For FidMe you need to select the barcode type for each entry afterwards.
# Building

View File

@@ -1 +0,0 @@
theme: jekyll-theme-cayman

View File

@@ -1 +0,0 @@
README.md

View File

@@ -1,70 +0,0 @@
# PRIVACY POLICY FOR CATIMA
This privacy policy governs your use of the software application Catima (“Application”) for mobile devices
that was created by Sylvia van Os. The Application is designed to store and display barcodes.
# What information does the Application obtain and how is it used?
The Application allows a user to create store entries with a barcode. When a store is later selected the
corresponding barcode is displayed. This user data remains on the device and is not transmitted off of the
device.
If a crash occurs, a dialog may appear with crash details and a suggestion to transmit the details
to the developer. A user has the option to not send the crash details; a user must 'opt-in' to
sending such details.
# User Provided Information
The Application does not have a registration option. The only information which is obtained
is (1) crash details which a user intentionally send to the developer via the app, and
(2) any information provided by the App Store that the application was downloaded from.
# Automatically Collected Information
No information is automatically collected from the Application and transmitted off of the mobile device,
either automatically or manually.
# Does the Application collect precise real time location information of the device?
No.
# Do third parties see and/or have access to information obtained by the Application?
Any crash data which is intentionally submitted by a user to the developer is stored on an email server
which is not owned by the developer. Crash details may be uploaded to a third-party development tool
such as GitHub. In such a case the email address of the user is not uploaded, unless specifically requested
by the user. Besides this, no other data is transmitted off of the mobile device by the Application.
# What are my opt-out rights?
The only data collection is that of crash details, and submitting these to the developer is only opt-in. To
opt-out, a user would have to not submit crash details via the app.
# Data Retention Policy, Managing Your Information
Crash details submitted by a user are stored on a third-party email service, and the retention policy is to
not delete such emails.
# Children
This Application is not used to knowingly solicit data from or market to children under the age of 13. If a parent or
guardian becomes aware that his or her child has provided us with information without their consent, they should
contact us at sylvia+googleplay@hackerchick.me. We will delete such information from our files within a reasonable time.
# Security
We are concerned about safeguarding the confidentiality of your information. The only information which could
be sent to the developer is crash details, and these are opt-in. If a user is presented with the option to
submit details on a crash, all the information which would be submitted is presented to the user. The only
personally identifiable information is the email address of the user which is used to send the crash details.
# Changes
This Privacy Policy may be updated from time to time for any reason. We will notify you of any changes to our
Privacy Policy by posting the new Privacy Policy here. You are advised to consult this Privacy Policy regularly
for any changes, as continued use is deemed approval of all changes. You can check the history of this policy by
checking this history of this file in GitHub.
# Contact us
If you have any questions regarding privacy while using the Application, or have questions about our practices,
please contact us via email at sylvia+googleplay@hackerchick.me.

View File

@@ -1,10 +0,0 @@
# Shared Card
Someone wants to share a card with you. To import this card, you will first need to install the Catima app. It is free, Open Source and contains no ads.
<a href="https://play.google.com/store/apps/details?id=me.hackerchick.catima" target="_blank">
<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" alt="Get it on Google Play" height="90"/></a>
<a href="https://f-droid.org/repository/browse/?fdid=me.hackerchick.catima" target="_blank">
<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" alt="Get it on F-Droid" height="90"/></a>
After installing the app, just click the link you were given again and choose "Import into Catima".

View File

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

View File

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

View File

@@ -0,0 +1 @@
Catima - Портфейлът за карти Libre

View File

@@ -0,0 +1,23 @@
Přestaňte hledat plastové věrnostní karty při placení v obchodě nebo ve webovém obchodě.
<b>Naskenujte si čárové kódy do svého zařízení pomocí jeho fotoaparátu a zapomeňte na karty.</b>
😺
Zapomeňte na peněženku nebo ji mějte ultralehkou na cennosti.
😺
S tímto nezbytným nástrojem pro každodenní nošení (EDC) můžete nahradit zbytečné plasty hotovostí.
😺
- Vyhněte se špehování s velmi malým počtem oprávnění. Žádný přístup k internetu a žádné reklamy.
- Přidejte karty nebo kódy se jmény a přizpůsobitelnými barvami.
- Ruční zadání kódu, pokud není čárový kód k uložení nebo jej nelze použít.
- Import karet a kódů ze souborů, Catima, FidMe, klíčenky věrnostních karet, Stocard a trezoru voucherů.
- Vytvořte si zálohu všech karet a v případě potřeby je přeneste do nového zařízení.
- Sdílejte kupony, exkluzivní nabídky, propagační kódy nebo karty a kódy pomocí libovolné aplikace.
- Tmavé téma a možnosti přístupnosti pro uživatele se zrakovým postižením.
- Vytvořeno pro všechny komunitou svobodného softwaru.
- Lokalizované ruční překlady pro více než 20 jazyků.
- Zdarma, podporováno příspěvky komunity.
- Používejte, studujte, měňte a sdílejte dle libosti; <i>se všemi</i>.
- Nejen svobodný software / open source. <i>Copylefted</i> libre software (GPLv3+) správa karet.
😺
Zjednodušte si život a nakupování a už nikdy neztraťte papírovou účtenku, dárkovou kartu pro platbu v obchodě nebo letenku.
Vezměte si s sebou všechny své odměny a bonusy a šetřete za pochodu.
😺

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -1,23 +1,23 @@
Lopeta muovisten etukorttien etsiminen kaupan tai verkkokaupan kassalla.
Lopeta muovisten palkintokorttien etsiminen kaupan tai verkkokaupan kassalla.
<b>Skannaa viivakoodit laitteeseesi sen kameran avulla, unohda kortit.</b>
😺
Unohda lompakko tai pidä se ultrakevyenä sinulle arvokkaita asioita varten.
Unohda lompakko tai pidä se ultrakevyesti arvoesineitä varten.
😺
Tämän jokapäiväisen (EDC) työkalun avulla, voit korvata turhan muovin käteisellä.
Tämän välttämättömän jokapäiväisen kantamisen (EDC) välineen avulla voit korvata turhan muovin käteisellä.
😺
- Vältä vakoilua hyvin vähäisillä käyttöoikeuksilla. Ei Internet-yhteyttä eikä mainoksia.
- Lisää kortteja tai koodeja nimettynä ja muokattavilla väreillä.
- Koodin syöttäminen manuaalisesti, jos tallennettavaa viivakoodia ei ole tai sitä ei voida käyttää.
- Tuo kortteja ja koodeja varmuuskopiotiedostoista, Catima, Loyalty Card Keychain, Voucher Vault, ja FidMe.
- Vältä vakoilu hyvin vähillä luvilla. Ei Internet-yhteyttä eikä mainoksia.
- Lisää kortteja tai koodeja nimillä ja muokattavilla väreillä.
- Koodin syöttäminen manuaalisesti, jos viivakoodia ei voi tallentaa tai sitä ei voi käyttää.
- Tuo kortteja ja koodeja tiedostoista, Catimasta, FidMe:stä, kanta-asiakaskorttiavaimenperästä, Stocardista ja Voucher Holvista.
- Tee varmuuskopio kaikista korteistasi ja siirrä ne halutessasi uuteen laitteeseen.
- Jaa kuponkeja, erikoistarjouksia, tarjouskoodeja tai kortteja ja koodeja millä tahansa sovelluksella.
- Tumma teema ja esteettömän käytön mahdollisuus näkövammaisille käyttäjille.
- Vapaan ohjelmistoyhteisön kaikkia varten tekemä.
- Jaa kuponkeja, yksinoikeustarjouksia, tarjouskoodeja tai kortteja ja koodeja millä tahansa sovelluksella.
- Tumma teema ja saavutettavuusvaihtoehdot näkövammaisille käyttäjille.
- Libre-ohjelmistoyhteisön kaikille tekemä.
- Lokalisoidut käsintehdyt käännökset yli 20 kielelle.
- Vapaa, yhteisön tukema.
- Käytä, opiskele, muuta ja jaa sitä toiveidesi mukaan; <i>kaikille</i>.
- Ei vain vapaa ohjelma / Avoin lähdekoodi. <i>Copyleft</i> vapaa ohjelma (GPLv3+) korttien hallinta.
- Gratis, yhteisön panoksilla tuettu.
- Käytä, tutki, muuta ja jaa sitä haluamallasi tavalla; <i>kaikkien</i> kanssa.
- Ei vain vapaat ohjelmistot / avoin lähdekoodi. <i>Copylefted</i> libre-ohjelmisto (GPLv3+) kortinhallinta.
😺
Yksinkertaista elämääsi ja ostosten tekemistä, äläkä enää koskaan hukkaa paperikuittia, kaupassa maksettavaa lahjakorttia tai lentolippua.
Ota kaikki edut ja bonukset mukaasi ja säästä missä menetkin.
Yksinkertaista elämääsi ja shoppailuasi, äläkä enää koskaan hukkaa paperikuittia, kaupassa maksettavaa lahjakorttia tai lentolippua.
Ota kaikki palkintosi ja bonuksesi mukaasi ja säästä matkan aikana.
😺

View File

@@ -0,0 +1 @@
Catima — Den fria kortplånboken

View File

@@ -0,0 +1,23 @@
在实体店或网店结账时,再也不用翻找塑料积分卡了。
<b>用摄像头扫描条形码存储到您的设备,就不需要卡片了。</b>
😺
抛开钱包,或者只携带贵重物品给钱包减负。
😺
有了这个必不可少的日常携带EDC工具你可以用现金取代无用的塑料。
😺
- 要求权限极少,避免隐私泄露。无需互联网接入,没有广告。
- 添加卡片或号码,并为其设置名称和颜色。
- 如果没有条码可存储,或条码无法使用,可手动输入号码。
- 可以从本地文件、Catima、FidMe、Loyalty Card Keychain、Stocard和Voucher Vault导入卡片和号码。
- 对所有的卡进行备份。可以把备份转移到新设备上。
- 把优惠券、促销码、卡片和号码等等分享到任何应用程序。
- 为视力受损的用户提供暗色主题和无障碍选项。
- 自由软件社区为大家制作。
- 提供20多种语言的本地化人工翻译。
- 免费的,由社区贡献支持。
- 欢迎<i>与所有人</i>随意使用、研究、改变和分享本软件。
- 不仅是自由软件/开放源码。<i>Copylefted</i>自由软件GPLv3+)卡片管理。
😺
简化你的生活和购物,再也不会丢失纸质收据、店内支付礼品卡或飞机票。
带上你所有的优惠和积分卡,随时随地省钱。
😺

View File

@@ -0,0 +1 @@
适用于您的条形码、会员卡、积分卡、优惠券和门票等。

View File

@@ -0,0 +1 @@
Catima - 自由卡片钱包