Compare commits

...

321 Commits

Author SHA1 Message Date
Sylvia van Os
0547fb9949 Fix typo in merge 2020-02-21 16:22:24 +01:00
Sylvia van Os
d092cbe930 Merge branch 'master' into feature/multiple-barcodes 2020-02-21 15:29:26 +01:00
Branden Archer
2f562b432c Merge pull request #357 from brarcher/translations
Update nb_NO translations from Weblate
2020-02-01 16:41:19 -08:00
Branden Archer
b776f90b87 Update translations from Weblate 2020-02-01 16:13:14 -08:00
Branden Archer
7970bb8a40 Merge pull request #350 from brarcher/pre-v0.27
Update for v0.27
2020-01-26 22:41:14 -08:00
Branden Archer
8fa868e99b Update for v0.27 2020-01-26 22:26:40 -08:00
Branden Archer
77a6cca57d Merge pull request #329 from TheLastProject/fix/dark_mode_unscannable
Fix dark mode scanning issues
2020-01-26 22:21:43 -08:00
Branden Archer
5ab3a62e16 Merge branch 'master' into fix/dark_mode_unscannable 2020-01-26 22:15:18 -08:00
Branden Archer
171ec1cd7e Merge pull request #348 from TheLastProject/feature/fullscreenBarcode
Move barcode to top on tap
2020-01-26 09:25:27 -08:00
Branden Archer
54ee93b0cb Merge branch 'master' into feature/fullscreenBarcode 2020-01-25 23:41:11 -08:00
Sylvia van Os
fd6c66a86a Improve documentation 2020-01-21 20:12:15 +01:00
Branden Archer
91044fdc87 Merge pull request #346 from TheLastProject/fix/swap_import_buttons
Fix swapped import buttons
2020-01-20 22:38:08 -08:00
Sylvia van Os
3600065ef8 Robolectric crashes if activity recreates 2020-01-19 19:55:08 +01:00
Sylvia van Os
4a7e8b6eba Reset state on paused to prevent layout glitches 2020-01-19 19:07:06 +01:00
Sylvia van Os
2c12c312e3 Add unit tests 2020-01-19 17:46:50 +01:00
Sylvia van Os
f8943af402 Tap barcode to align to top 2020-01-19 16:45:17 +01:00
Sylvia van Os
3990992f68 Fix swapped import buttons 2020-01-18 13:37:47 +01:00
Branden Archer
d2ac0dacda Merge pull request #344 from brarcher/pre-v0.26.1
Update for v0.26.1
2020-01-09 20:35:20 -08:00
Branden Archer
1a35150677 Update CHANGELOG for v0.26.1 2020-01-09 19:45:08 -08:00
Branden Archer
bf48e394e9 Update app for v0.26.1 2020-01-09 19:45:08 -08:00
Branden Archer
003aba52af Merge pull request #343 from TheLastProject/fix/sharing_npe
Fix NPE when sharing cards without header values
2020-01-09 19:22:00 -08:00
Sylvia van Os
aad98ba55b Fix NPE when sharing cards without header values 2020-01-09 20:16:54 +01:00
Sylvia van Os
67383a7f10 More tabs into header to save some space 2020-01-06 21:54:52 +01:00
Branden Archer
2b50e503da Merge pull request #339 from brarcher/pre-v0.26
Update for v0.26
2020-01-05 20:14:23 -08:00
Branden Archer
ab4c360c37 Update CHANGELOG for v0.26 2020-01-05 20:06:54 -08:00
Branden Archer
c76580d6be Update app version to 0.26 2020-01-05 20:06:54 -08:00
Branden Archer
dc8ac6b574 Merge pull request #338 from brarcher/update-translations
Update translations
2020-01-05 19:45:12 -08:00
Branden Archer
0c23f25aca Update translations
These were pulled from the Transifex project:
transifex.com/na-243/loyalty-card-locker
2020-01-05 19:35:51 -08:00
Sylvia van Os
5b5ade0edc Merge branch 'feature/multiple-barcodes' of ssh://github.com/TheLastProject/loyalty-card-locker into feature/multiple-barcodes 2020-01-05 16:09:49 +01:00
Sylvia van Os
efd0f4ef39 Fix tab state loss on rotation 2020-01-05 16:09:21 +01:00
Sylvia van Os
67ada5c027 Merge branch 'master' into feature/multiple-barcodes 2020-01-05 14:47:58 +01:00
Sylvia van Os
520f0da983 Sanitize long and multiline notes 2020-01-05 14:22:15 +01:00
Sylvia van Os
343d710b2a Swipe between different cards from store 2020-01-05 14:16:13 +01:00
Branden Archer
47b9bbd30d Merge pull request #336 from TheLastProject/fix/convert_to_barcodeless
Fix converting loyalty card to barcodeless
2020-01-04 17:28:39 -08:00
Sylvia van Os
1c71dc964f Rename barcodecount to card count because barcodeless card support 2020-01-05 00:50:08 +01:00
Sylvia van Os
524d649523 Add new tests 2020-01-05 00:36:44 +01:00
Sylvia van Os
e39593228d Fix tests 2020-01-05 00:12:12 +01:00
Sylvia van Os
27d718b461 Also add FAB to edit screen 2020-01-05 00:04:50 +01:00
Sylvia van Os
490281bff9 Fix note not reappearing 2020-01-05 00:00:37 +01:00
Sylvia van Os
5030e4c67a Also add FAB button to main activity 2020-01-04 23:52:36 +01:00
Sylvia van Os
29eac68e3f Group together multiple barcodes of same store 2020-01-04 23:45:28 +01:00
Sylvia van Os
422501da3e Make it easy to add extra barcodes 2020-01-04 23:00:23 +01:00
Sylvia van Os
23bd60b476 Add tab to switch between multiple barcodes of same store 2020-01-04 22:26:00 +01:00
Sylvia van Os
ce81d3afd4 Fix as reviewed and add test 2020-01-02 21:15:06 +01:00
Sylvia van Os
cc99af13e4 Fix tests 2020-01-01 19:43:23 +01:00
Sylvia van Os
ccf3d1f3d6 Fix converting loyalty card to barcodeless
The LoyaltyCardEditActivity assumes on many places that an empty string
means it doesn't know a value yet. This patch ensures that the
BarcodeSelectorActivity returns a special string so that the
LoyaltyCardEditActivity can distinguish explicitly picking no barcode
from a not yet populated field.
2019-12-31 18:23:45 +01:00
Branden Archer
330ded0b5d Merge pull request #334 from TheLastProject/fix/sdk28
Up targetSdk for Google Play
2019-12-30 19:45:46 -08:00
Sylvia van Os
0bcb0a7ab8 Up targetSdk to 29 2019-12-29 13:01:02 +01:00
Sylvia van Os
403c1fca33 Fix last error Travis reported 2019-12-28 21:25:17 +01:00
Sylvia van Os
ca12f8f914 Fix some of the errors Travis reported 2019-12-28 21:19:00 +01:00
Sylvia van Os
d5ba632bb3 Fix unit tests with Robolectric 4 2019-12-28 21:07:47 +01:00
Branden Archer
b9d158583b Update to AndroidX
This is mostly the work of Android Studio's
   Refactor > Migrate to AndroidX...
option. That mostly worked. The two places which were manually updated
were:
  - The reference to AppBarLayout$ScrollingViewBehavior in
    loyalty_card_edit_activity.xml
  - The suggested constraintlayout version, 2.0.0-beta4 caused build
    issues that 1.1.3 avoids
2019-12-28 19:57:27 +01:00
Sylvia van Os
32b4178950 Fix some warnings 2019-12-27 17:40:12 +01:00
Sylvia van Os
d9f97380d9 Fix status bar being white 2019-12-27 17:34:58 +01:00
Sylvia van Os
4e2fe97de5 Merge branch 'fix/sdk28' of ssh://github.com/TheLastProject/loyalty-card-locker into fix/sdk28 2019-12-27 17:27:48 +01:00
Sylvia van Os
1a3dee2c26 Update support libraries 2019-12-27 17:27:40 +01:00
Sylvia van Os
53f3a2109b Merge branch 'master' into fix/sdk28 2019-12-27 17:16:21 +01:00
Sylvia van Os
c5c2f702d0 Up targetSdk for Google Play 2019-12-27 17:14:07 +01:00
Branden Archer
396801ba74 Merge pull request #326 from TheLastProject/feature/multiline_notes
Allow multiline notes
2019-12-24 19:33:31 -08:00
Branden Archer
67163539d5 Merge branch 'master' into feature/multiline_notes 2019-12-24 19:25:59 -08:00
Branden Archer
c1be6f2a88 Merge pull request #330 from TheLastProject/fix/white_on_white_icons
Fix white on white icons
2019-12-20 20:56:50 -08:00
Sylvia van Os
c0d1b446d1 Make same text and header color at least slightly visible 2019-12-16 13:23:16 +01:00
Sylvia van Os
d24a418beb Fix status bar icon colors 2019-12-16 11:36:23 +01:00
Sylvia van Os
1f348295a0 Merge branch 'master' of ssh://github.com/brarcher/loyalty-card-locker into fix/white_on_white_icons 2019-12-15 21:36:56 +01:00
Sylvia van Os
280fe76609 Use DrawableCompat tinting instead 2019-12-15 21:29:34 +01:00
Branden Archer
8a3b623ea6 Merge pull request #324 from TheLastProject/feature/barcodeless_cards
Allow barcodeless cards
2019-12-15 12:01:42 -08:00
Sylvia van Os
e1f66e1917 Implement requested changes 2019-12-15 20:45:12 +01:00
Sylvia van Os
787bda1c77 Add test for empty barcode type 2019-12-15 14:28:48 +01:00
Sylvia van Os
c83b151c08 Revert "Check for empty cardId in BarcodeSelectorActivity instead"
This reverts commit 62f7241bca.
2019-12-15 12:54:51 +01:00
Sylvia van Os
a642b12795 Use a const for luminance halfway point 2019-12-15 12:50:08 +01:00
Sylvia van Os
4e1fb16359 Empty barcodeType is allowed now 2019-12-14 19:03:17 +01:00
Sylvia van Os
0d7d1658d6 Also add padding to edit activity 2019-12-12 19:42:17 +01:00
Sylvia van Os
7b7624a3e0 Fix white on white icons 2019-12-11 17:42:56 +01:00
Sylvia van Os
488125c492 Merge branch 'master' into feature/barcodeless_cards 2019-12-11 14:25:41 +01:00
Sylvia van Os
3aeea02300 Test button state 2019-12-11 14:23:13 +01:00
Sylvia van Os
72227f19e8 Fix comments 2019-12-11 11:38:53 +01:00
Sylvia van Os
62f7241bca Check for empty cardId in BarcodeSelectorActivity instead 2019-12-11 10:44:31 +01:00
Sylvia van Os
80fb7e2cb3 Add 10dp white padding around all QR codes 2019-12-10 20:34:07 +01:00
Branden Archer
ed048e6424 Merge pull request #325 from 532910/master
typo fix
2019-12-09 17:32:31 -08:00
Sylvia van Os
bda8abfe3d Allow multiline notes 2019-12-09 14:44:15 +01:00
Sylvia van Os
19755f4f86 Add test 2019-12-09 13:44:25 +01:00
Sylvia van Os
9a2d195cb2 Don't generate a barcode if id is empty
This prevents a bug with an empty PDF 417 barcode being generated
2019-12-09 13:20:42 +01:00
Sylvia van Os
429309deef UI improvements 2019-12-09 13:10:37 +01:00
sergio
864b82d547 typo fix
URI is an abbreviation, must be URI, not Uri.
2019-12-09 12:38:10 +03:00
Branden Archer
77a2ed29db Merge branch 'master' into feature/barcodeless_cards 2019-12-08 20:15:47 -08:00
Branden Archer
acfb92e9fb Merge pull request #322 from TheLastProject/feature/dark_mode
Dark mode
2019-12-08 18:16:20 -08:00
Sylvia van Os
61c2c0c84a Completely removed rectangle cleanup code, 1D codes seem to need this padding 2019-12-08 18:15:08 +01:00
Sylvia van Os
08afc16d01 Don't remove paddings smaller than 20 pixels 2019-12-08 18:05:09 +01:00
Sylvia van Os
91a4461863 Fix code style 2019-12-05 19:49:45 +01:00
Sylvia van Os
e37288b842 Remove useless null check 2019-12-04 23:10:02 +01:00
Sylvia van Os
fc930f40e4 Merge branch 'master' into feature/barcodeless_cards 2019-12-04 16:36:58 +01:00
Sylvia van Os
33b84ad4c3 Allow barcodeless cards 2019-12-04 15:59:49 +01:00
Sylvia van Os
368a2a30f6 Fix white border in dark theme 2019-12-04 13:27:53 +01:00
Sylvia van Os
5774064da7 Don't draw more than the actual barcode 2019-12-04 13:04:42 +01:00
Sylvia van Os
8673405a50 Merge branch 'master' into feature/dark_mode 2019-12-04 12:45:50 +01:00
Sylvia van Os
4ec4baa53b Fix card title colour issues 2019-12-04 12:45:16 +01:00
Branden Archer
f00be863c2 Merge pull request #323 from TheLastProject/master
Fix GitHub pages
2019-12-03 17:30:18 -08:00
Sylvia van Os
e0d85f9c8d Fix GitHub pages 2019-12-03 17:12:58 +01:00
Branden Archer
3754243748 Merge branch 'master' into feature/dark_mode 2019-12-02 23:30:32 -08:00
Branden Archer
5ef2c4b1da Merge pull request #319 from TheLastProject/fix/improve_note_sizing
Improve note sizing
2019-12-02 23:29:57 -08:00
Branden Archer
8315067caf Merge branch 'master' into fix/improve_note_sizing 2019-12-02 23:19:48 -08:00
Branden Archer
7bbf5b469c Merge pull request #321 from TheLastProject/feature/card_sharing
Add ability to share and receive loyalty cards
2019-12-02 23:13:09 -08:00
Sylvia van Os
0de50e72a6 Fixes, start with right theme 2019-12-02 18:03:36 +01:00
Sylvia van Os
4240fd55ba Style about dialog for dark mode 2019-12-02 17:09:49 +01:00
Sylvia van Os
29e8896059 Remove another unneeded import 2019-12-02 16:33:49 +01:00
Sylvia van Os
a46200f794 Merge branch 'master' into feature/dark_mode 2019-12-02 16:32:58 +01:00
Sylvia van Os
061b1db245 Cleanup 2019-12-02 16:28:16 +01:00
Sylvia van Os
8d3d9a21f7 Allow switching theme 2019-12-02 16:24:24 +01:00
Sylvia van Os
9b5a731d48 Start with dark mode 2019-12-02 15:05:19 +01:00
Sylvia van Os
5e0e8a6f67 Merge branch 'master' into fix/improve_note_sizing 2019-12-02 14:31:13 +01:00
Sylvia van Os
07c74b79f3 Use README as index page, add share page with explanation 2019-12-02 13:14:15 +01:00
Sylvia van Os
5e836758e5 Fix function calls 2019-12-02 12:57:44 +01:00
Sylvia van Os
e314580ac3 Cleanup 2019-12-02 12:56:42 +01:00
Sylvia van Os
2ef739fb4f Fix typo 2019-12-01 22:55:17 +01:00
Sylvia van Os
bae6f746a1 Another import test 2019-12-01 22:38:31 +01:00
Sylvia van Os
22e8d7f699 Fix linter warning 2019-12-01 20:53:37 +01:00
Sylvia van Os
48a1084c40 Fix typo 2019-12-01 20:46:13 +01:00
Sylvia van Os
3d2ad1693a Tests 2019-12-01 20:42:37 +01:00
Sylvia van Os
28b3aa2018 Add ability to share and receive loyalty cards 2019-12-01 18:22:55 +01:00
Branden Archer
ed4adad087 Merge pull request #320 from TheLastProject/feature/card_filter
Add loyalty card filter
2019-11-28 20:22:51 -08:00
Sylvia van Os
5a898b4c4c Address comments 2019-11-28 23:07:27 +01:00
Sylvia van Os
7a78eadabb Remove unneeded imports 2019-11-24 20:08:56 +01:00
Sylvia van Os
d7556b9951 Remove unneeded imports 2019-11-24 19:05:26 +01:00
Sylvia van Os
c936e3c9c0 Switch to SearchView 2019-11-23 20:27:37 +01:00
Sylvia van Os
e33565abdc Add filtering test 2019-11-23 15:27:31 +01:00
Sylvia van Os
30419b5896 Explain focusable change 2019-11-23 14:35:03 +01:00
Sylvia van Os
f0426b98dc Cleanup 2019-11-23 14:29:10 +01:00
Sylvia van Os
bd3d67574e Bump minSdk because of rawQuery usage 2019-11-22 21:03:55 +01:00
Sylvia van Os
52a09056e8 Remove default focus 2019-11-22 20:54:34 +01:00
Sylvia van Os
21a8dc6867 Show warning when no matches 2019-11-22 20:46:06 +01:00
Sylvia van Os
e048fdff59 Fix tests 2019-11-22 20:24:50 +01:00
Sylvia van Os
0a8c85d24c Cleanup 2019-11-22 19:24:03 +01:00
Sylvia van Os
07d938701f Add loyalty card filter 2019-11-22 17:32:40 +01:00
Sylvia van Os
c0c126192f Improve note sizing
Signed-off-by: Sylvia van Os <sylvia@hackerchick.me>
2019-11-22 14:00:21 +01:00
Branden Archer
7cb5eba18f Merge pull request #313 from brarcher/pre-v0.25.4
Update for 0.25.4
2019-10-04 23:05:35 -07:00
Branden Archer
134d7fd824 Update for 0.25.4 2019-10-04 22:47:54 -07:00
Branden Archer
1615bc38bd Merge pull request #312 from brarcher/translations
Update translations
2019-10-04 22:45:19 -07:00
Branden Archer
3ecdf71331 Update translations
These were fetched from Transifex
2019-10-04 22:37:46 -07:00
Branden Archer
66a2cd438c Merge pull request #311 from brarcher/allow-backup
Allow backups of app data
2019-10-04 22:35:12 -07:00
Branden Archer
3fdff3c85a Allow backups of app data
Setting the allowBackup option enables the app to participate
in backup and restore infrastructure.
2019-10-04 22:27:17 -07:00
Branden Archer
56709d40b5 Merge pull request #297 from brarcher/pre-v0.25.3
Update for 0.25.3
2019-03-02 11:59:43 -08:00
Branden Archer
a8c4c73611 Update CHANGELOG 2019-03-02 11:38:21 -08:00
Branden Archer
31dd0e1de2 Update for 0.25.3 2019-03-02 11:37:09 -08:00
Branden Archer
f51e97fdf7 Merge pull request #296 from brarcher/translations
Update Russian translations
2019-03-02 11:36:23 -08:00
Branden Archer
1fcf7101f2 Update Russian translations 2019-03-02 10:19:10 -08:00
Branden Archer
dbb7a4ea62 Merge pull request #292 from brarcher/readme
Update translation instructions in README
2019-01-28 19:26:50 -08:00
Branden Archer
a2fa8edcf5 Update translation instructions in README 2019-01-28 07:08:28 -08:00
Branden Archer
fd71eda561 Merge pull request #290 from brarcher/changelog
Update CHANGELOG
2019-01-05 16:09:09 -08:00
Branden Archer
058676bb0f Update CHANGELOG 2019-01-05 16:01:54 -08:00
Branden Archer
1fb59979f3 Merge pull request #289 from brarcher/pre-v0.25.2
Update for v0.25.2
2019-01-05 16:00:11 -08:00
Branden Archer
9bde7ce4da Update for v0.25.2 2019-01-05 15:40:48 -08:00
Branden Archer
db3d93e1bc Merge pull request #288 from brarcher/translations
Update translations
2019-01-05 15:40:22 -08:00
Branden Archer
4fd7872c87 Update translations 2019-01-05 15:24:47 -08:00
Branden Archer
fc313f0cfa Merge pull request #280 from comradekingu/patch-1
Norwegian Bokmål translation
2018-10-19 21:03:00 -07:00
Allan Nordhøy
03cf97cca7 Added self-referencing "about" tag 2018-10-20 03:22:17 +02:00
Allan Nordhøy
a7204eb9d5 Norwegian Bokmål translation 2018-10-19 15:14:37 +02:00
Branden Archer
81d7250306 Merge pull request #275 from brarcher/pre-v0.25.1
Update for v0.25.1
2018-10-14 11:53:02 -07:00
Branden Archer
580025c99e Update for v0.25.1 2018-10-14 11:46:34 -07:00
Branden Archer
d88bede310 Merge pull request #274 from brarcher/translations
Update translations
2018-10-14 11:46:06 -07:00
Branden Archer
4c9bc911ad Update translations 2018-10-14 11:39:21 -07:00
Branden Archer
38d6d6ccff Merge pull request #273 from brarcher/fix-manual-barcode
Fix manual barcode
2018-10-14 11:38:55 -07:00
Branden Archer
866eaea680 Correct log statement when entering barcode manually 2018-10-14 11:24:42 -07:00
Branden Archer
5619c1c003 Revert "Remove unneeded code"
The log statement here was misleading. This code is responsible for
receiving a barcode that a user typed in manually.

This reverts commit cafa09a86a.
2018-10-14 11:24:42 -07:00
Branden Archer
b8311044db Update class file location for FindBugs
Gradle now places the compiled class file under a different path.
2018-10-14 11:24:42 -07:00
Branden Archer
3679b9a48a Update gradle and android plugin 2018-10-14 11:07:21 -07:00
Branden Archer
727f3f32fe Merge pull request #271 from brarcher/pre-v0.25
Update for v0.25
2018-10-07 15:28:12 -07:00
Branden Archer
6fa70afac5 Update for v0.25 2018-10-07 15:18:08 -07:00
Branden Archer
c5ad261392 Merge pull request #270 from brarcher/translations
Update translations
2018-10-07 15:12:38 -07:00
Branden Archer
28018eb681 Update translations 2018-10-07 15:05:38 -07:00
Branden Archer
28f7b3db02 Merge pull request #269 from brarcher/orientation-setting
Add option to lock orientation state
2018-10-06 18:33:41 -04:00
Branden Archer
10e720de91 Add option to lock orientation state
This new option will control if the screen orientation
lock option is displayed or not. If set, the orientation lock
is forced and the unlock option is hidden.
2018-10-06 15:27:36 -07:00
Branden Archer
4de952ba2d Set rotation state in onCreate()
The menu creation need not change this state
2018-10-06 14:24:50 -07:00
Branden Archer
c5de27abe3 Move orientation locking code to separate method 2018-10-06 14:24:05 -07:00
Branden Archer
cafa09a86a Remove unneeded code
The IntentIntegrator parses out the result, so this
code is not necessary.
2018-09-18 10:53:16 -04:00
Branden Archer
1635737658 Merge pull request #267 from brarcher/translations
Update translations
2018-09-17 10:20:54 -04:00
Branden Archer
6ee60687b6 Update translations 2018-09-17 10:03:05 -04:00
Branden Archer
0afd9358e6 Merge pull request #266 from brarcher/fix-sorting
Sort card list case insensitive
2018-09-15 23:04:35 -04:00
Branden Archer
cad3b492a2 Sort card list case insensitive 2018-09-15 22:50:36 -04:00
Branden Archer
59bde6916c Merge pull request #261 from brarcher/pre-v0.24
Update for v0.24
2018-07-31 21:55:52 -04:00
Branden Archer
eb6364b932 Update CHANGELOG 2018-07-31 21:48:33 -04:00
Branden Archer
ae7ac21785 Update for v0.24 2018-07-31 21:44:28 -04:00
Branden Archer
2dd02f42f5 Merge pull request #260 from brarcher/transifex
Add/update translations
2018-07-27 23:25:37 -04:00
Branden Archer
3b8e38001c Update translations 2018-07-27 23:18:38 -04:00
Branden Archer
fbb0ab27ec Add Slovenian translations 2018-07-27 23:18:38 -04:00
Branden Archer
ceea5182d1 Merge pull request #259 from brarcher/setting-barcode-brightness
Configure brightening screen when display a barcode
2018-07-25 22:43:21 -04:00
Branden Archer
34c07800dd Configure brightening screen when display a barcode
When a barcode is displayed the screen's brightness is set to
the maximum, in an attempt to provide the best chance for a barcode
scanner to capture the barcode. However, it may not always
be desired to increase the brightness, for example when using
the app in low light.

This change adds a setting to control the screen brightening
behavior when a barcode is viewed.
2018-07-25 22:24:27 -04:00
Branden Archer
8c7a3273e8 Merge pull request #256 from brarcher/privacy
Update privacy-policy
2018-07-25 22:07:35 -04:00
Branden Archer
49cd9a28c7 Update privacy-policy 2018-06-26 17:30:38 -04:00
Branden Archer
392024f84f Merge pull request #254 from brarcher/transifex
Transifex config file and translation updates
2018-06-16 18:08:47 -04:00
Branden Archer
165f963f7d Update translations 2018-06-16 17:54:29 -04:00
Branden Archer
aca44c5830 Add Transifex config file 2018-06-16 17:54:29 -04:00
Branden Archer
e2ed5b515a Merge pull request #252 from brarcher/greek
Add Greek translations
2018-06-13 09:33:08 -04:00
Branden Archer
ba6705b96e Add Greek translations 2018-06-13 09:19:38 -04:00
Branden Archer
9f407e5eb0 Merge pull request #246 from brarcher/changelog
Update CHANGELOG
2018-05-12 21:40:56 -04:00
Branden Archer
c00da00be5 Update CHANGELOG 2018-05-12 11:56:48 -04:00
Branden Archer
c2ea640a71 Merge pull request #245 from brarcher/pre-v0.23.4
Update for v0.23.4
2018-05-12 11:48:08 -04:00
Branden Archer
ba5259f0f6 Update for v0.23.4 2018-05-12 11:41:57 -04:00
Branden Archer
b1abfdff2e Merge pull request #244 from brarcher/translations
Translations
2018-05-12 11:41:09 -04:00
Branden Archer
39219531b4 Update translations 2018-05-12 11:33:16 -04:00
Branden Archer
048edf186e Fix Spanish translations
The wrong language was in this file.
2018-05-12 11:32:40 -04:00
Branden Archer
ee6d415d26 Merge pull request #240 from brarcher/pre-v0.23.3
Update for v0.23.3
2018-05-05 20:38:42 -04:00
Branden Archer
5143e3fe45 Update for v0.23.3 2018-05-05 20:26:28 -04:00
Branden Archer
306ee053c1 Merge pull request #239 from brarcher/translations
Update translations
2018-05-05 20:23:40 -04:00
Branden Archer
40871690d5 Update translations 2018-05-05 18:28:33 -04:00
Branden Archer
0bbbabce97 Merge pull request #232 from kRkk/master
Add Polish translation
2018-03-22 22:37:31 -04:00
Karol
f59c485472 Add Polish translation 2018-03-22 22:48:20 +01:00
Branden Archer
d8543f456c Merge pull request #228 from brarcher/changelog
Update CHANGELOG for v0.23.2
2018-03-11 23:51:07 -04:00
Branden Archer
fcf88a1ace Update CHANGELOG for v0.23.2 2018-03-11 23:33:42 -04:00
Branden Archer
a2e99c2b9d Merge pull request #227 from brarcher/pre-v0.23.2
Update for v0.23.2
2018-03-11 23:27:29 -04:00
Branden Archer
607dff03d4 Update for v0.23.2 2018-03-11 23:20:01 -04:00
Branden Archer
73b6c99d9e Merge pull request #226 from brarcher/sdk-15
Add additional layout options to support SDK 15
2018-03-11 23:19:18 -04:00
Branden Archer
036748ee56 Add additional layout options to support SDK<17
Google Play statistics show that the earliest Android version
in use which has installs for this app is 4.0.3, which is SDK 15.
This changes cleans up some layouts so that it will work on
SDK 15.
2018-03-11 23:11:51 -04:00
Branden Archer
5cae97482f Merge pull request #225 from brarcher/test-cleanup
Remove unnecessary apache legacy usage
2018-03-11 22:44:13 -04:00
Branden Archer
f67d27167e Remove unnecessary apache legacy usage
The version of robolectric used no longer requires this.
2018-03-11 22:33:31 -04:00
Branden Archer
0832c7fc97 Merge pull request #222 from brarcher/changelog
Update CHANGELOG
2018-03-08 11:33:32 -05:00
Branden Archer
f5e1a2d732 Update CHANGELOG 2018-03-07 23:29:17 -05:00
Branden Archer
7b799df98a Merge pull request #221 from brarcher/pre-v0.23.1
Update for pre-v0.23.1
2018-03-07 23:25:10 -05:00
Branden Archer
968c3e71a1 Update for pre-v0.23.1 2018-03-07 23:14:53 -05:00
Branden Archer
29d8da99cd Merge pull request #219 from brarcher/barcode-oom
Catch case where barcode rendering runs into an OOM
2018-03-04 14:17:53 -05:00
Branden Archer
79213aa3ec Catch case where barcode rendering runs into an OOM
There are still cases where the barcode could not be rendered
because the process runs out of its memory limit. To avoid
a crash, catch the failure and log it. The barcode will
not be displayed, but at least the app will not crash.
2018-03-04 13:10:12 -05:00
Branden Archer
50fdfe92fa Merge pull request #217 from brarcher/changelog
Update CHANGELOG
2018-02-28 23:13:10 -05:00
Branden Archer
4eab1121b0 Update CHANGELOG 2018-02-28 23:07:15 -05:00
Branden Archer
d3bcd3e273 Merge pull request #215 from brarcher/pre-v0.23
Update for v0.23
2018-02-28 23:05:38 -05:00
Branden Archer
9d1c9c3309 Merge branch 'master' into pre-v0.23 2018-02-28 22:59:37 -05:00
Branden Archer
61e039c456 Merge pull request #216 from brarcher/disable-beep
Disable beep upon successful barcode scan
2018-02-28 22:59:27 -05:00
Branden Archer
0e2d725591 Disable beep upon successful barcode scan 2018-02-28 22:53:05 -05:00
Branden Archer
759d42cfcf Update for v0.23 2018-02-28 22:48:49 -05:00
Branden Archer
2312788a57 Merge pull request #213 from brarcher/header-size
Reduce space used in header for card view
2018-02-26 20:52:44 -05:00
Branden Archer
0820be3986 Reduce space used in header for card view
The landscape view left little room for the barcode and card ID
because the header took up a lot of space. Further, on smaller
phones it would take up a large portion of the screen.

This change reduces the header from 224dp to two action bar sizes
plus the size of the textview for the store name.
2018-02-19 23:21:12 -05:00
Branden Archer
8a11953276 Merge pull request #211 from brarcher/changelog
Update CHANGELOG
2018-02-19 15:30:48 -05:00
Branden Archer
182b3ff3c0 Update CHANGELOG 2018-02-19 10:34:41 -05:00
Branden Archer
79dad1b0a6 Merge pull request #210 from brarcher/pre-v0.22
Update for v0.22
2018-02-19 10:29:16 -05:00
Branden Archer
04466edb01 Update for v0.22 2018-02-18 23:30:04 -05:00
Branden Archer
af3ce5a0ff Merge pull request #209 from brarcher/barcode-rendering
Barcode rendering improvements
2018-02-18 23:24:52 -05:00
Branden Archer
3291185812 Render 1D barcodes with a larger width
For some reason when 1D barcodes are rendered in a smaller width,
they end up scrunched up and not using all available space.
As a result, they do not scale to the entire width of the screen.
In many cases the barcode is not scannable even in landscape.

To resolve this, render the 1D barcodes in a larger space. The space
is still bounded, to prevent OOMs on tablets or really
wide screen devices.
2018-02-18 23:14:51 -05:00
Branden Archer
c9df3bd1d2 Redraw barcode when screen rotates 2018-02-18 23:14:51 -05:00
Branden Archer
057c7923a8 Merge pull request #208 from brarcher/translations
Update translations
2018-02-17 23:49:45 -05:00
Branden Archer
4195d73c53 Update translations 2018-02-17 23:43:21 -05:00
Branden Archer
ed08f0577a Merge pull request #207 from brarcher/changelog-1
Update CHANGELOG
2018-02-17 23:34:21 -05:00
Branden Archer
a1257a1692 Update CHANGELOG 2018-02-17 23:27:26 -05:00
Branden Archer
a51815a172 Merge pull request #206 from brarcher/pre-v0.21
Update for v0.21
2018-02-17 22:56:35 -05:00
Branden Archer
8eee8f6a0f Update for v0.21 2018-02-17 22:44:49 -05:00
Branden Archer
1817c184ae Merge pull request #205 from brarcher/fix-no-color-import
Fix no color import
2018-02-17 22:44:00 -05:00
Branden Archer
773d759ef5 Fix imports with missing colors 2018-02-17 22:37:10 -05:00
Branden Archer
cbc51cfb73 Remove debug toast 2018-02-17 22:37:10 -05:00
Branden Archer
46c3d190d8 Merge pull request #204 from brarcher/custom-font-sizes
Add settings for font sizes
2018-02-17 16:29:54 -05:00
Branden Archer
9951999ca4 Add settings for font sizes 2018-02-17 16:05:10 -05:00
Branden Archer
4843a1093d Merge pull request #203 from brarcher/color-picker
Custom colors
2018-02-17 16:02:54 -05:00
Branden Archer
a4bde722a6 Add config for text and background colors
This adds config options for the colors used for the store text
and background when displaying the store name in the single
card view or the thumbnail for the card list.
2018-02-17 15:50:32 -05:00
Branden Archer
ff5e5d5833 Remove unused code handling adding a card
This case is handled in another acitivity now.
2018-02-12 15:13:23 -05:00
Branden Archer
685eaec8b5 Remove views which are no longer used 2018-02-12 15:13:23 -05:00
Branden Archer
a3556cc66d Merge pull request #200 from brarcher/barcode-space
Add quite space before and after barcode
2018-02-10 22:27:45 -05:00
Branden Archer
13543ea9f6 Add quite space before and after barcode
This is to help barcode scanners determine where the end of
the barcode is.
2018-02-10 22:21:35 -05:00
Branden Archer
d7bf31c308 Merge pull request #199 from brarcher/changelog-1
Update CHANGELOG
2018-02-10 22:13:27 -05:00
Branden Archer
a77a968619 Update CHANGELOG 2018-02-10 22:06:35 -05:00
Branden Archer
70c6ee17cd Merge pull request #198 from brarcher/pre-v0.20
Update for v0.20
2018-02-10 22:02:04 -05:00
Branden Archer
c233f82dc1 Update for v0.20 2018-02-10 13:50:30 -05:00
Branden Archer
be0c2507f2 Merge pull request #197 from brarcher/layout-changes
Layout changes for new card view layout
2018-02-10 13:49:22 -05:00
Branden Archer
abfcf9d6cd Disable MissingPrefix lint
The autosizing TextView, which comes from the support-v4 library,
adds several new attributes to TextViews. These attributes do not
seem to be in the app namespace (as described in the documentation),
as Android Studio and lint complains. However, funtionally the new
attributes work as expected.
2018-02-10 13:43:28 -05:00
Branden Archer
4d565b3b2f Update screenshots and wizard images 2018-02-10 13:37:17 -05:00
Branden Archer
27511a4ccd Make card id and note text selectable 2018-02-10 13:37:17 -05:00
Branden Archer
12440346fa Replace letter icon with store name 2018-02-10 13:37:17 -05:00
Branden Archer
870e4d0c4a Add note text to card view layout 2018-02-10 13:37:17 -05:00
Branden Archer
6e526de087 Auto-size card id text on card view layout 2018-02-10 13:37:16 -05:00
Branden Archer
891636b51f Use ConstraintLayout for card view layout
This way the size of the barcode can be 1/2 the screen.
2018-02-10 13:37:16 -05:00
Branden Archer
017d97d08c Merge pull request #196 from brarcher/feature-graphic
add feature graphic to metadata
2018-02-09 23:30:09 -05:00
Branden Archer
63165ca1a5 add feature graphic to metadata 2018-02-09 23:21:46 -05:00
Branden Archer
48f40a51d1 Merge pull request #192 from brarcher/brarcher-patch-1
Update CHANGELOG
2018-02-01 08:13:51 -05:00
Branden Archer
3940ba5756 Update CHANGELOG 2018-02-01 08:05:10 -05:00
Branden Archer
b8a36e3c45 Merge pull request #191 from brarcher/pre-v0.19
Update for v0.19
2018-02-01 08:02:20 -05:00
Branden Archer
60deaae8d5 Update for v0.19 2018-02-01 07:54:48 -05:00
Branden Archer
a71da8d6dc Merge pull request #190 from brarcher/card-layout
Improve card view layout
2018-01-31 23:39:37 -05:00
Branden Archer
dbbbd128dc Update intro and metadata graphics 2018-01-31 23:19:19 -05:00
Branden Archer
3275279501 Remove unnecessary casts from findViewById 2018-01-31 22:49:31 -05:00
Branden Archer
2f6516ffb9 Display note on separate line, omit card id on card list
The card id was of dubious value, because the main screen
is really for selecting the card. The note may have more value,
as it may specify info about the card.
2018-01-31 22:49:31 -05:00
Branden Archer
41c8b78275 Move store name text size to dimens.xml 2018-01-31 22:49:31 -05:00
Branden Archer
6ed96393d5 Change layout of single card view
This changes the layout when viewing a single card. The new layout
will have a colored area at the top which displays the first letter
of the company, and after that the barcode. The note will be displayed
on the card list screen and is presently omitted here.

As this layout is experimental, the layout for editing a card is
not yet updated. To achieve this the card viewing activity is split
into two separate classes, where one handles viewing and one handles
editing. When the view layout finalizes the edit icon can be updated
as time allows.
2018-01-31 22:49:31 -05:00
Branden Archer
3519e03568 Merge pull request #188 from brarcher/card-list-layout
Improve card list layout
2018-01-28 15:08:03 -05:00
Branden Archer
1aef3f5253 Preserve float result from division
The arguments to drawText for x and y are float, but
dividing two integers truncates the result to an integer.
2018-01-28 14:21:53 -05:00
Branden Archer
c97e80432f Support non-English letters for default card thumbnail 2018-01-28 09:49:21 -05:00
Branden Archer
c6265eb9e3 Add generated icon for cards in card list
This add a thumbnail of a single letter for each card,
consisting of the first letter of the card and a
pastel background.

This was adapted from the andOTP project.
2018-01-27 20:05:57 -05:00
Branden Archer
935cd97f99 Improve layout for card list
This now includes an icon and emphasizes the store name.

This was adapted from the andOTP project.
2018-01-27 20:03:37 -05:00
Branden Archer
e65d096e76 Merge pull request #187 from brarcher/pre-v0.18.1
Update for v0.18.1
2018-01-24 17:39:03 -05:00
Branden Archer
8d38918a12 Update for v0.18.1 2018-01-24 17:28:37 -05:00
Branden Archer
57f2c7acd4 Merge pull request #186 from brarcher/changelog
Update CHANGELOG
2018-01-24 17:28:02 -05:00
Branden Archer
7fb6e4a8d3 Update CHANGELOG 2018-01-24 17:19:10 -05:00
Branden Archer
56d20939be Merge pull request #185 from brarcher/contributing
Create CONTRIBUTING.md
2018-01-24 16:21:42 -05:00
Branden Archer
a3968f8894 Create CONTRIBUTING.md 2018-01-24 16:06:05 -05:00
Branden Archer
74dd292f5a Merge pull request #184 from brarcher/install-crash-workaround
Workaround install crash on Android 5 and below
2018-01-24 13:22:08 -05:00
Branden Archer
d7a7528114 Workaround install crash on Android 5 and below
The aapt2 tool, new to Android Studio 3, creates an APK which fails
to install on Android 5 and below if it contains the following bug:

   https://issuetracker.google.com/issues/64434571

Build tools 27.0.1 has a mitigation. Avoiding aapt2 also avoids hitting
the bug.
2018-01-24 08:37:53 -05:00
Branden Archer
bffeca9033 Merge pull request #182 from brarcher/changelog
Update Changelog
2018-01-19 23:46:15 -05:00
Branden Archer
5a88afb9f3 Update Changelog 2018-01-19 23:39:25 -05:00
Branden Archer
f775f9224b Merge pull request #181 from brarcher/pre-v0.18
Update for v0.18
2018-01-19 23:36:49 -05:00
Branden Archer
17acb8370c Update for v0.18 2018-01-19 23:16:15 -05:00
Branden Archer
23766fe9f0 Merge pull request #180 from brarcher/import-from-filesystem
Import from filesystem
2018-01-19 23:09:28 -05:00
Branden Archer
f1b0a26591 Allow file paths when importing directly from filesystem
The import path directly from the file system may not
result in using a content:// or file:// Uri, but instead
a file system path. If this occurs, attempt to use a FileInputStream
to read the contents.
2018-01-19 22:57:25 -05:00
Branden Archer
f1b2c0d93d Report Uri after import
The filename from Uri code was removed in a previous commit.
To give some feedback about what was imported, the Uri itself
is reported.
2018-01-19 22:57:25 -05:00
Branden Archer
4034997d7f Merge pull request #179 from brarcher/import-crash
Do not bother to show file name after an import
2018-01-19 08:27:36 -05:00
Branden Archer
d3bbaf39f4 Do not bother to show file name after an import
It was observed by one user that the Uri to filename lookup
failed with an IllegalStateException. The code which
converts a Uri to a file path may not be that great,
especially now that the app is expected to not receive
file Uris. Instead of determining the best way to lookup
the file names, as it is not that important it will be
removed.
2018-01-19 00:12:36 -05:00
Branden Archer
ae7684921f Merge pull request #177 from brarcher/csv-crash
Fix crash on some corruption when importing CSV
2018-01-17 08:31:21 -05:00
Branden Archer
e73974536c Update how SDK 27 is acceptd on Travis-CI
There are issues with using the "andorid" tool to accept
some licenses on Travis-CI. The theory from Travis-CI is that
the android binary is out of date. An alternative is using
sdkmanager.
2018-01-17 08:04:26 -05:00
Branden Archer
43072e283f Fix crash on some corruption when importing CSV
Commons-CSV would throw a RuntimeException in some cases of
bad CSV input. This was later changed to throwing an
IllegalStateException. Updating to v1.5 to pick-up the change.
2018-01-16 22:04:36 -05:00
Branden Archer
a3a70d459b Merge pull request #176 from brarcher/readme
Update screenshots in README
2018-01-11 23:06:05 -05:00
Branden Archer
edfc91376f Update screenshots in README
The screenshots now use the images from the metadata
folder in the repo.
2018-01-11 22:35:58 -05:00
Branden Archer
5fb68055ea Merge pull request #175 from brarcher/changelog
Update CHANGELOG
2018-01-11 22:24:43 -05:00
Branden Archer
085a3f10e7 Update CHANGELOG 2018-01-11 22:11:53 -05:00
Branden Archer
4070a6b4e0 Merge pull request #174 from brarcher/transifex
Import translations from Transifex
2018-01-11 22:08:26 -05:00
Branden Archer
bc547a1d2b Import translations from Transifex 2018-01-11 22:01:49 -05:00
Branden Archer
4f9c75da9e Merge pull request #173 from brarcher/pre-v0.17
Update for v0.17
2018-01-11 21:48:52 -05:00
Branden Archer
fde679751a Update for v0.17 2018-01-11 21:36:52 -05:00
Branden Archer
d4720db2e7 Merge pull request #172 from brarcher/update-sdk-27
Update to Android SDK 27
2018-01-03 23:02:12 -05:00
Branden Archer
245935242f Update to Android SDK 27 2018-01-03 22:20:00 -05:00
Branden Archer
e217bd28fb Merge pull request #171 from brarcher/new-icon
New app icon and color scheme
2018-01-03 21:26:32 -05:00
Branden Archer
ad17bc6bf3 Update first start wizard images with new logo and colors
Note that the second slide has been changed. Originally there was
text over the image with an arrow. This text could not be translated
and was part of the instruction. The arrow is really not needed,
so it has been removed with the overlay text.

Also, the originals folder has been removed. The screenshots which
were used to create the wizard images are in the metadata folder.
2018-01-03 21:17:59 -05:00
Branden Archer
17ab1365bf Add metadata in fastlane format
This is for F-Droid to use these for the app's listing.
2018-01-03 21:17:58 -05:00
Branden Archer
7ebbe6413f Update app icons and colors with new design
This icon and feature graphic are contributed under
CC0 1.0 Universal license by Samy, @samymarboy.
2018-01-03 21:17:58 -05:00
Branden Archer
adbc6bf999 Merge pull request #170 from brarcher/file-picker
Remove file:// Uri from backup file picker
2017-12-31 16:24:18 -05:00
Branden Archer
52c41f4c49 Remove file:// Uri from backup file picker
On Android SDK 24+ exposing a file Uri causes a failure.
Picking a file from a file chooser using data of a file://
Uri also hits this. As this is not necessary, removing the
Uri.
2017-12-31 15:53:57 -05:00
Branden Archer
858e317d8f Merge pull request #169 from brarcher/android-studio-3
Update gradle, et al, for Android Studio 3
2017-12-25 21:53:02 -05:00
Branden Archer
898e822a28 Update gradle and gradle android plugin
This is to support Android Studio 3
2017-12-25 19:17:35 -05:00
Branden Archer
6f45f635aa Quote FindBugs dependsOn target
later versions of gradle depend on this
2017-12-25 19:17:04 -05:00
142 changed files with 5221 additions and 1029 deletions

View File

@@ -4,8 +4,8 @@ sudo: true
install:
- echo y | android update sdk -u -a -t tools
- echo y | android update sdk -u -a -t platform-tools
- echo y | android update sdk -u -a -t build-tools-25.0.2
- echo y | android update sdk -u -a -t android-25
- echo y | android update sdk -u -a -t build-tools-26.0.2
- yes | sdkmanager "platforms;android-27"
- echo y | android update sdk -u -a -t extra-google-m2repository
- echo y | android update sdk -u -a -t extra-android-m2repository

10
.tx/config Normal file
View File

@@ -0,0 +1,10 @@
[main]
host = https://www.transifex.com
[loyalty-card-locker.stringsxml]
file_filter = app/src/main/res/values-<lang>/strings.xml
minimum_perc = 0
source_file = app/src/main/res/values/strings.xml
source_lang = en
type = ANDROID

View File

@@ -1,3 +1,144 @@
## v0.27 (2020-01-26)
Changes:
- Tapping on a barcode now moves it to the top of the screen ([#348](https://github.com/brarcher/loyalty-card-locker/pull/348))
- Add white space around barcodes to improve scanning in dark mode ([#328](https://github.com/brarcher/loyalty-card-locker/issues/328))
- Fix swapped import buttons. ([#346](https://github.com/brarcher/loyalty-card-locker/pull/346))
## v0.26.1 (2020-01-09)
Changes:
- Fix issue with sharing cards without background color ([#343](https://github.com/brarcher/loyalty-card-locker/pull/343))
## v0.26 (2020-01-05)
Changes:
- Add ability to search for a card ([#320](https://github.com/brarcher/loyalty-card-locker/pull/320))
- Add ability to share and receive loyalty cards ([#321](https://github.com/brarcher/loyalty-card-locker/pull/321))
- Dark mode support ([#322](https://github.com/brarcher/loyalty-card-locker/pull/322))
- Loyalty cards can now be barcodeless (e.g. not have a barcode) ([#324](https://github.com/brarcher/loyalty-card-locker/pull/324))
- Notes can span multiple lines ([#326](https://github.com/brarcher/loyalty-card-locker/pull/326))
- Improvements with the sizing of notes ([#319](https://github.com/brarcher/loyalty-card-locker/pull/319))
- Improve notification and app icon visibility ([#330](https://github.com/brarcher/loyalty-card-locker/pull/330))
- Update target SDK to Android 10
- Improve the following translations:
* German
* Italian
* Dutch
* Polish
* Russian
## v0.25.4 (2019-10-04)
Changes
- Enable app backups
- Update French and Slovenian translations
## v0.25.3 (2019-03-02)
Changes
- Update Russian translations
## v0.25.2 (2019-01-05)
Changes
- Update and add translations
## v0.25.1 (2018-10-14)
Changes:
- Fix creating new card by manually entering barcode (https://github.com/brarcher/loyalty-card-locker/issues/272)
## v0.25 (2018-10-07)
Changes:
- Sort card list case insensitive (https://github.com/brarcher/loyalty-card-locker/pull/266)
- Add setting to lock orientation for all cards (https://github.com/brarcher/loyalty-card-locker/pull/269)
## v0.24 (2018-07-31)
Changes:
- Add a setting to control screen brightness when displaying a barcode (https://github.com/brarcher/loyalty-card-locker/pull/259)
- Add Greek translations (https://github.com/brarcher/loyalty-card-locker/pull/252)
- Add Slovenian translations (https://github.com/brarcher/loyalty-card-locker/pull/260)
- Update translations (https://github.com/brarcher/loyalty-card-locker/pull/260, https://github.com/brarcher/loyalty-card-locker/pull/254)
## v0.23.4 (2018-05-12)
Changes:
- Fix Spanish translations (https://github.com/brarcher/loyalty-card-locker/pull/244)
- Update translations (https://github.com/brarcher/loyalty-card-locker/pull/244)
## v0.23.3 (2018-05-05)
Changes:
- Added translations
* Polish (https://github.com/brarcher/loyalty-card-locker/pull/232)
* Spanish (https://github.com/brarcher/loyalty-card-locker/pull/232)
* Slovak (https://github.com/brarcher/loyalty-card-locker/pull/232)
- Updated translations (https://github.com/brarcher/loyalty-card-locker/pull/239)
## v0.23.2 (2018-03-11)
Changes:
- Reduce min SDK from 17 to 15. (https://github.com/brarcher/loyalty-card-locker/pull/226)
- Remove usage of legacy apache library, used only in unit tests but no longer needed. (https://github.com/brarcher/loyalty-card-locker/pull/225)
## v0.23.1 (2018-03-07)
Changes:
- Prevent crash when rendering a barcode exhausts the application's memory. (https://github.com/brarcher/loyalty-card-locker/pull/219)
## v0.23 (2018-02-28)
Changes:
- Reduce space in header when viewing a card. (https://github.com/brarcher/loyalty-card-locker/pull/213)
- Disable beep when scanning a barcode. (https://github.com/brarcher/loyalty-card-locker/pull/216)
## v0.22 (2018-02-19)
Changes:
- Update translations. (https://github.com/brarcher/loyalty-card-locker/pull/208)
- Barcode rendering updates: (https://github.com/brarcher/loyalty-card-locker/pull/209)
* Reload card view activity when screen is rotated, so barcode image is correct size.
* Render 1D barcodes in a larger space, allowing them to better fill the screen.
## v0.21 (2018-02-17)
Changes
- Add quiet space at the start/end of barcodes. (https://github.com/brarcher/loyalty-card-locker/pull/200)
- Add options to configure the colors used for the store name font and background. (https://github.com/brarcher/loyalty-card-locker/pull/203)
- Add options to adjust font sizes on the card listing page and single card page. (https://github.com/brarcher/loyalty-card-locker/pull/204)
## v0.20 (2018-02-10)
Changes:
- Changes to Card view to display the note, allow the card ID to take multiple lines, and show the store name. (https://github.com/brarcher/loyalty-card-locker/pull/197)
## v0.19 (2018-02-01)
Changes:
- Improved layout for card list. (https://github.com/brarcher/loyalty-card-locker/pull/188)
- Improved layout when viewing a card. (https://github.com/brarcher/loyalty-card-locker/pull/190)
## v0.18.1 (2018-01-24)
Changes:
- Workaround crash during install on some Android versions (likely Android 5 and below). (https://github.com/brarcher/loyalty-card-locker/pull/184)
## v0.18 (2018-01-19)
Changes:
- Fix crash when importing certain types of corrupted CSV files. (https://github.com/brarcher/loyalty-card-locker/pull/177)
- Fix importing backups directly from the file system. (https://github.com/brarcher/loyalty-card-locker/pull/180)
- Fix importing backups from certain types of content providers. (https://github.com/brarcher/loyalty-card-locker/pull/179)
## v0.17 (2018-01-11)
Changes:
- Fix issue on Android SDK 24+ where using the file chooser import option would cause a crash. (https://github.com/brarcher/loyalty-card-locker/pull/170)
- New icon and color scheme. (https://github.com/brarcher/loyalty-card-locker/pull/171)
## v0.16 (2017-11-29)
Changes:

91
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,91 @@
How to Submit Patches to the Loyalty Card Keychain Project
===============================================================================
https://github.com/brarcher/budget-watch
This document is intended to act as a guide to help you contribute to the
Loyalty Card Keychain project. It is not perfect, and there will always be exceptions
to the rules described here, but by following the instructions below you
should have a much easier time getting your work merged with the upstream
project.
## Test Your Code
There are four possible tests you can run to verify your code. The first
is unit tests, which check the basic functionality of the application, and
can be run by gradle using:
# ./gradlew testReleaseUnitTest
The second and third check for common problems using static analysis.
These are the Android lint checker, run using:
# ./gradlew lintRelease
and FindBugs, run using:
# ./gradlew findbugs
The final check is by testing the application on a live device and verifying
the basic functionality works as expected.
## Make Sure Your Code is Tested
The Loyalty Card Keychain code uses a fair number of unit tests to verify that
the basic functionality is working. Submissions which add functionality
or significantly change the existing code should include additional tests
to verify the proper operation of the proposed changes.
## Explain Your Work
At the top of every patch you should include a description of the problem you
are trying to solve, how you solved it, and why you chose the solution you
implemented. If you are submitting a bug fix, it is also incredibly helpful
if you can describe/include a reproducer for the problem in the description as
well as instructions on how to test for the bug and verify that it has been
fixed.
## Sign Your Work
The sign-off is a simple line at the end of the patch description, which
certifies that you wrote it or otherwise have the right to pass it on as an
open-source patch. The "Developer's Certificate of Origin" pledge is taken
from the Linux Kernel and the rules are pretty simple:
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
... then you just add a line to the bottom of your patch description, with
your real name, saying:
Signed-off-by: Random J Developer <random@developer.example.org>
## Submit Patch(es) for Review
Finally, you will need to submit your patches so that they can be reviewed
and potentially merged into the main Loyalty Card Keychain repository. The preferred
way to do this is to submit a Pull Request to the Loyalty Card Keychain project.
Changes need to apply cleanly onto the master branch and pass all
unit tests and produce no errors during static analysis.

View File

@@ -1,58 +0,0 @@
# Loyalty Card Keychain
[![Build Status](https://travis-ci.org/brarcher/loyalty-card-locker.svg?branch=master)](https://travis-ci.org/brarcher/loyalty-card-locker)
<a href="https://f-droid.org/repository/browse/?fdid=protect.card_locker" target="_blank">
<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="90"/></a>
<a href="https://play.google.com/store/apps/details?id=protect.card_locker" 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>
Stores all of your store loyalty cards on your phone, removing the need to carry them around. Currently the following barcode types are supported:
- AZTEC
- CODABAR
- CODE_39
- CODE_128
- DATA_MATRIX
- EAN_8
- EAN_13
- ITF
- PDF_417
- QR_CODE
- UPC_A
If there is any interest in improving this project, kindly submit a pull request with
proposed changes.
# Screenshots
[<img src="https://user-images.githubusercontent.com/5264535/27416124-79b09162-56d9-11e7-967b-8923177dc228.png" width=250>](https://user-images.githubusercontent.com/5264535/27416124-79b09162-56d9-11e7-967b-8923177dc228.png)
[<img src="https://user-images.githubusercontent.com/5264535/27416127-7baea332-56d9-11e7-8a10-5be90bb02225.png" width=250>](https://user-images.githubusercontent.com/5264535/27416127-7baea332-56d9-11e7-8a10-5be90bb02225.png)
[<img src="https://user-images.githubusercontent.com/5264535/27416128-7d50f7b2-56d9-11e7-9833-1dd962f9cf66.png" width=250>](https://user-images.githubusercontent.com/5264535/27416128-7d50f7b2-56d9-11e7-9833-1dd962f9cf66.png)
[<img src="https://user-images.githubusercontent.com/5264535/27416132-7ea6272c-56d9-11e7-9a52-d73424bf902c.png" width=250>](https://user-images.githubusercontent.com/5264535/27416132-7ea6272c-56d9-11e7-9a52-d73424bf902c.png)
[<img src="https://user-images.githubusercontent.com/5264535/27416137-800aee90-56d9-11e7-9cc9-2a7dc63bb4fb.png" width=250>](https://user-images.githubusercontent.com/5264535/27416137-800aee90-56d9-11e7-9cc9-2a7dc63bb4fb.png)
[<img src="https://user-images.githubusercontent.com/5264535/27416140-82d8211a-56d9-11e7-8031-c71d3077bdc6.png" width=250>](https://user-images.githubusercontent.com/5264535/27416140-82d8211a-56d9-11e7-8031-c71d3077bdc6.png)
# Building
To build, use the gradle wrapper scripts provided in the top level directory of the project. The following will
compile the application and run all unit tests:
GNU/Linux, OSX, UNIX:
```
./gradlew build
```
Windows:
```
./gradlew.bat build
```
# Translating
If you are interested in translating this application to another language, create a pull request with changes or find the project listing on [Transifex](https://www.transifex.com/na-243/loyalty-card-locker).
# Thanks
This application uses the following image:
- [Save](https://thenounproject.com/term/save/716011) by [Bernar Novalyi](https://thenounproject.com/bernar.novalyi)

View File

@@ -7,15 +7,14 @@ findbugs {
}
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
compileSdkVersion 29
defaultConfig {
applicationId "protect.card_locker"
minSdkVersion 17
targetSdkVersion 25
versionCode 17
versionName "0.16"
minSdkVersion 16
targetSdkVersion 29
versionCode 38
versionName "0.27"
}
buildTypes {
release {
@@ -28,31 +27,41 @@ android {
disable "ButtonStyle"
disable "AlwaysShowAction"
disable "MissingTranslation"
disable "MissingPrefix"
}
// This is for Robolectric support for SDK 23
useLibrary 'org.apache.http.legacy'
// Starting with Android Studio 3 Robolectric is unable to find resources.
// The following allows it to find the resources.
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'androidx.appcompat:appcompat:1.2.0-alpha01'
compile 'com.google.android.material:material:1.2.0-alpha03'
compile 'androidx.legacy:legacy-support-v4:1.0.0'
compile 'com.journeyapps:zxing-android-embedded:3.5.0@aar'
compile 'com.google.zxing:core:3.3.0'
compile 'org.apache.commons:commons-csv:1.2'
compile 'org.apache.commons:commons-csv:1.5'
compile 'androidx.constraintlayout:constraintlayout:1.1.3'
compile 'com.jaredrummler:colorpicker:1.0.2'
compile group: 'com.google.guava', name: 'guava', version: '20.0'
compile 'com.github.apl-devs:appintro:v4.2.0'
compile "com.vanniktech:vntnumberpickerpreference:1.0.0"
testCompile 'junit:junit:4.12'
testCompile "org.robolectric:robolectric:3.3.2"
testCompile "org.robolectric:robolectric:4.0.2"
}
task findbugs(type: FindBugs, dependsOn: assembleDebug) {
task findbugs(type: FindBugs, dependsOn: 'assembleDebug') {
description 'Run findbugs'
group 'verification'
classes = fileTree('build/intermediates/classes/debug/')
classes = fileTree('build/intermediates/javac/debug/compileDebugJavaWithJavac/classes')
source = fileTree('src/main/java')
classpath = files()

View File

@@ -17,7 +17,8 @@
android:required="false" />
<application
android:allowBackup="false"
android:name=".LoyaltyCardLockerApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
@@ -35,15 +36,35 @@
<activity
android:name=".LoyaltyCardViewActivity"
android:theme="@style/AppTheme.NoActionBar"
android:configChanges="orientation|screenSize"
android:label=""
android:windowSoftInputMode="stateHidden"
android:exported="true"/>
<activity
android:name=".LoyaltyCardEditActivity"
android:theme="@style/AppTheme.NoActionBar"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateHidden"
android:exported="true">
<intent-filter android:label="@string/intent_import_card_from_url">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "https://github.com/brarcher/loyalty-card-locker/” -->
<data android:scheme="https"
android:host="@string/intent_import_card_from_url_host"
android:pathPrefix="@string/intent_import_card_from_url_path_prefix" />
</intent-filter>
</activity>
<activity
android:name=".BarcodeSelectorActivity"
android:label="@string/selectBarcodeTitle"
android:theme="@style/AppTheme.NoActionBar"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateHidden"/>
<activity
android:name=".preferences.SettingsActivity"
android:label="@string/settings"
android:configChanges="orientation|screenSize"/>
<activity
android:name=".ImportExportActivity"
android:label="@string/importExport"
@@ -65,7 +86,7 @@
</intent-filter>
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:name="androidx.core.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="${applicationId}">

View File

@@ -21,7 +21,11 @@ import java.lang.ref.WeakReference;
class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
{
private static final String TAG = "LoyaltyCardLocker";
private static final int MAX_WIDTH = 500;
// When drawn in a smaller window 1D barcodes for some reason end up
// squished, whereas 2D barcodes look fine.
private static final int MAX_WIDTH_1D = 1500;
private static final int MAX_WIDTH_2D = 500;
private final WeakReference<ImageView> imageViewReference;
private final String cardId;
@@ -38,6 +42,8 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
cardId = cardIdString;
format = barcodeFormat;
final int MAX_WIDTH = getMaxWidth(format);
if(imageView.getWidth() < MAX_WIDTH)
{
imageHeight = imageView.getHeight();
@@ -52,8 +58,43 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
}
}
private int getMaxWidth(BarcodeFormat format)
{
switch(format)
{
// 2D barcodes
case AZTEC:
case DATA_MATRIX:
case MAXICODE:
case PDF_417:
case QR_CODE:
return MAX_WIDTH_2D;
// 1D barcodes:
case CODABAR:
case CODE_39:
case CODE_93:
case CODE_128:
case EAN_8:
case EAN_13:
case ITF:
case UPC_A:
case UPC_E:
case RSS_14:
case RSS_EXPANDED:
case UPC_EAN_EXTENSION:
default:
return MAX_WIDTH_1D;
}
}
public Bitmap doInBackground(Void... params)
{
if (cardId.isEmpty())
{
return null;
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix bitMatrix;
try
@@ -113,6 +154,12 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
{
Log.e(TAG, "Failed to generate barcode of type " + format + ": " + cardId, e);
}
catch(OutOfMemoryError e)
{
Log.w(TAG, "Insufficient memory to render barcode, "
+ imageWidth + "x" + imageHeight + ", " + format.name()
+ ", length=" + cardId.length(), e);
}
return null;
}
@@ -140,4 +187,4 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
imageView.setVisibility(View.GONE);
}
}
}
}

View File

@@ -5,9 +5,9 @@ import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
@@ -67,7 +67,7 @@ public class BarcodeSelectorActivity extends AppCompatActivity
super.onCreate(savedInstanceState);
setContentView(R.layout.barcode_selector_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
@@ -89,7 +89,7 @@ public class BarcodeSelectorActivity extends AppCompatActivity
.put(BarcodeFormat.UPC_A.name(), R.id.upcaBarcode)
.build();
EditText cardId = (EditText) findViewById(R.id.cardId);
EditText cardId = findViewById(R.id.cardId);
cardId.addTextChangedListener(new TextWatcher()
{
@Override
@@ -113,9 +113,13 @@ public class BarcodeSelectorActivity extends AppCompatActivity
// Update barcodes
for(String key : barcodeViewMap.keySet())
{
ImageView image = (ImageView)findViewById(barcodeViewMap.get(key));
ImageView image = findViewById(barcodeViewMap.get(key));
createBarcodeOption(image, key, s.toString());
}
View noBarcodeButtonView = findViewById(R.id.noBarcode);
setButtonListener(noBarcodeButtonView, s.toString());
noBarcodeButtonView.setEnabled(s.length() > 0);
}
@Override
@@ -134,6 +138,21 @@ public class BarcodeSelectorActivity extends AppCompatActivity
}
}
private void setButtonListener(final View button, final String cardId)
{
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "Selected no barcode");
Intent result = new Intent();
result.putExtra(BARCODE_FORMAT, "");
result.putExtra(BARCODE_CONTENTS, cardId);
BarcodeSelectorActivity.this.setResult(RESULT_OK, result);
finish();
}
});
}
private void createBarcodeOption(final ImageView image, final String formatType, final String cardId)
{
final BarcodeFormat format = BarcodeFormat.valueOf(formatType);

View File

@@ -4,8 +4,8 @@ import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
@@ -29,7 +29,7 @@ public class CardShortcutConfigure extends AppCompatActivity
setResult(RESULT_CANCELED);
setContentView(R.layout.main_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setVisibility(View.GONE);
final DBHelper db = new DBHelper(this);
@@ -41,7 +41,7 @@ public class CardShortcutConfigure extends AppCompatActivity
finish();
}
final ListView cardList = (ListView) findViewById(R.id.list);
final ListView cardList = findViewById(R.id.list);
cardList.setVisibility(View.VISIBLE);
Cursor cardCursor = db.getLoyaltyCardCursor();

View File

@@ -23,6 +23,8 @@ public class CsvDatabaseExporter implements DatabaseExporter
DBHelper.LoyaltyCardDbIds.STORE,
DBHelper.LoyaltyCardDbIds.NOTE,
DBHelper.LoyaltyCardDbIds.CARD_ID,
DBHelper.LoyaltyCardDbIds.HEADER_COLOR,
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR,
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE);
Cursor cursor = db.getLoyaltyCardCursor();
@@ -35,6 +37,8 @@ public class CsvDatabaseExporter implements DatabaseExporter
card.store,
card.note,
card.cardId,
card.headerColor,
card.headerTextColor,
card.barcodeType);
if(Thread.currentThread().isInterrupted())

View File

@@ -40,7 +40,7 @@ public class CsvDatabaseImporter implements DatabaseImporter
parser.close();
database.setTransactionSuccessful();
}
catch(IllegalArgumentException e)
catch(IllegalArgumentException|IllegalStateException e)
{
throw new FormatException("Issue parsing CSV data", e);
}
@@ -83,7 +83,7 @@ public class CsvDatabaseImporter implements DatabaseImporter
* "key" as the key. If no such key exists, or the data is not a valid
* int, a FormatException is thrown.
*/
private int extractInt(String key, CSVRecord record)
private Integer extractInt(String key, CSVRecord record, boolean nullIsOk)
throws FormatException
{
if(record.isMapped(key) == false)
@@ -91,6 +91,12 @@ public class CsvDatabaseImporter implements DatabaseImporter
throw new FormatException("Field not used but expected: " + key);
}
String value = record.get(key);
if(value.isEmpty() && nullIsOk)
{
return null;
}
try
{
return Integer.parseInt(record.get(key));
@@ -108,7 +114,7 @@ public class CsvDatabaseImporter implements DatabaseImporter
private void importLoyaltyCard(SQLiteDatabase database, DBHelper helper, CSVRecord record)
throws IOException, FormatException
{
int id = extractInt(DBHelper.LoyaltyCardDbIds.ID, record);
int id = extractInt(DBHelper.LoyaltyCardDbIds.ID, record, false);
String store = extractString(DBHelper.LoyaltyCardDbIds.STORE, record, "");
if(store.isEmpty())
@@ -125,11 +131,17 @@ public class CsvDatabaseImporter implements DatabaseImporter
}
String barcodeType = extractString(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE, record, "");
if(barcodeType.isEmpty())
Integer headerColor = null;
Integer headerTextColor = null;
if(record.isMapped(DBHelper.LoyaltyCardDbIds.HEADER_COLOR) &&
record.isMapped(DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR))
{
throw new FormatException("No barcode type listed, but is required");
headerColor = extractInt(DBHelper.LoyaltyCardDbIds.HEADER_COLOR, record, true);
headerTextColor = extractInt(DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR, record, true);
}
helper.insertLoyaltyCard(database, id, store, note, cardId, barcodeType);
helper.insertLoyaltyCard(database, id, store, note, cardId, barcodeType, headerColor, headerTextColor);
}
}

View File

@@ -7,11 +7,14 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
public class DBHelper extends SQLiteOpenHelper
{
public static final String DATABASE_NAME = "LoyaltyCards.db";
public static final int ORIGINAL_DATABASE_VERSION = 1;
public static final int DATABASE_VERSION = 2;
public static final int DATABASE_VERSION = 3;
static class LoyaltyCardDbIds
{
@@ -19,6 +22,8 @@ public class DBHelper extends SQLiteOpenHelper
public static final String ID = "_id";
public static final String STORE = "store";
public static final String NOTE = "note";
public static final String HEADER_COLOR = "headercolor";
public static final String HEADER_TEXT_COLOR = "headertextcolor";
public static final String CARD_ID = "cardid";
public static final String BARCODE_TYPE = "barcodetype";
}
@@ -36,6 +41,8 @@ public class DBHelper extends SQLiteOpenHelper
LoyaltyCardDbIds.ID + " INTEGER primary key autoincrement," +
LoyaltyCardDbIds.STORE + " TEXT not null," +
LoyaltyCardDbIds.NOTE + " TEXT not null," +
LoyaltyCardDbIds.HEADER_COLOR + " INTEGER," +
LoyaltyCardDbIds.HEADER_TEXT_COLOR + " INTEGER," +
LoyaltyCardDbIds.CARD_ID + " TEXT not null," +
LoyaltyCardDbIds.BARCODE_TYPE + " TEXT not null)");
}
@@ -49,10 +56,20 @@ public class DBHelper extends SQLiteOpenHelper
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.NOTE + " TEXT not null default ''");
}
// Upgrade from version 2 to version 3
if(oldVersion < 3 && newVersion >= 3)
{
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.HEADER_COLOR + " INTEGER");
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.HEADER_TEXT_COLOR + " INTEGER");
}
}
public long insertLoyaltyCard(final String store, final String note, final String cardId,
final String barcodeType)
final String barcodeType, final Integer headerColor,
final Integer headerTextColor)
{
SQLiteDatabase db = getWritableDatabase();
ContentValues contentValues = new ContentValues();
@@ -60,13 +77,16 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.NOTE, note);
contentValues.put(LoyaltyCardDbIds.CARD_ID, cardId);
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.HEADER_TEXT_COLOR, headerTextColor);
final long newId = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
return newId;
}
public boolean insertLoyaltyCard(final SQLiteDatabase db, final int id,
final String store, final String note, final String cardId,
final String barcodeType)
final String barcodeType, final Integer headerColor,
final Integer headerTextColor)
{
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.ID, id);
@@ -74,13 +94,16 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.NOTE, note);
contentValues.put(LoyaltyCardDbIds.CARD_ID, cardId);
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.HEADER_TEXT_COLOR, headerTextColor);
final long newId = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
return (newId != -1);
}
public boolean updateLoyaltyCard(final int id, final String store, final String note,
final String cardId, final String barcodeType)
final String cardId, final String barcodeType,
final Integer headerColor, final Integer headerTextColor)
{
SQLiteDatabase db = getWritableDatabase();
ContentValues contentValues = new ContentValues();
@@ -88,6 +111,8 @@ public class DBHelper extends SQLiteOpenHelper
contentValues.put(LoyaltyCardDbIds.NOTE, note);
contentValues.put(LoyaltyCardDbIds.CARD_ID, cardId);
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
contentValues.put(LoyaltyCardDbIds.HEADER_TEXT_COLOR, headerTextColor);
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE, contentValues,
LoyaltyCardDbIds.ID + "=?",
new String[]{Integer.toString(id)});
@@ -124,16 +149,103 @@ public class DBHelper extends SQLiteOpenHelper
public Cursor getLoyaltyCardCursor()
{
// An empty string will match everything
return getLoyaltyCardCursor("");
}
/**
* Returns a cursor to all loyalty cards with the filter text in either the store or note.
*
* @param filter
* @return Cursor
*/
public Cursor getLoyaltyCardCursor(final String filter)
{
String actualFilter = String.format("%%%s%%", filter);
String[] selectionArgs = { actualFilter, actualFilter };
SQLiteDatabase db = getReadableDatabase();
Cursor res = db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
" ORDER BY " + LoyaltyCardDbIds.STORE, null);
Cursor res = db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
" WHERE " + LoyaltyCardDbIds.STORE + " LIKE ? " +
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? " +
" ORDER BY " + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC", selectionArgs, null);
return res;
}
/**
* Returns a cursor only containing the first loyalty card of the given store.
*
* @param filter
* @return Cursor
*/
public Cursor getOneLoyaltyCardPerStoreCursor(final String filter)
{
String actualFilter = String.format("%%%s%%", filter);
String[] selectionArgs = { actualFilter, actualFilter };
SQLiteDatabase db = getReadableDatabase();
Cursor res = db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
" WHERE " + LoyaltyCardDbIds.STORE + " LIKE ? " +
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? " +
" GROUP BY " + LoyaltyCardDbIds.STORE +
" HAVING MIN(" + LoyaltyCardDbIds.ID + ")" +
" ORDER BY " + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC", selectionArgs, null);
return res;
}
/**
* Returns a list of all loyalty cards of the given store.
*
* @param store
* @return List<LoyaltyCard>
*/
public List<LoyaltyCard> getLoyaltyCardsForStore(String store)
{
List<LoyaltyCard> loyaltyCards = new ArrayList<>();
SQLiteDatabase db = getReadableDatabase();
String[] selectionArgs = { store };
Cursor res = db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
" WHERE " + LoyaltyCardDbIds.STORE + " IS ? " +
" ORDER BY " + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC", selectionArgs, null);
try
{
while (res.moveToNext()) {
loyaltyCards.add(LoyaltyCard.toLoyaltyCard(res));
}
} finally {
res.close();
}
return loyaltyCards;
}
public int getLoyaltyCardCount()
{
// An empty string will match everything
return getLoyaltyCardCount("");
}
/**
* Returns the amount of loyalty cards with the filter text in either the store or note.
*
* @param filter
* @return Integer
*/
public int getLoyaltyCardCount(String filter)
{
String actualFilter = String.format("%%%s%%", filter);
String[] selectionArgs = { actualFilter, actualFilter };
SQLiteDatabase db = getReadableDatabase();
Cursor data = db.rawQuery("SELECT Count(*) FROM " + LoyaltyCardDbIds.TABLE, null);
Cursor data = db.rawQuery("SELECT Count(*) FROM " + LoyaltyCardDbIds.TABLE +
" WHERE " + LoyaltyCardDbIds.STORE + " LIKE ? " +
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? "
, selectionArgs, null);
int numItems = 0;

View File

@@ -7,19 +7,18 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.OpenableColumns;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
@@ -49,7 +48,7 @@ public class ImportExportActivity extends AppCompatActivity
{
super.onCreate(savedInstanceState);
setContentView(R.layout.import_export_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
@@ -72,7 +71,7 @@ public class ImportExportActivity extends AppCompatActivity
}
Button exportButton = (Button)findViewById(R.id.exportButton);
Button exportButton = findViewById(R.id.exportButton);
exportButton.setOnClickListener(new View.OnClickListener()
{
@Override
@@ -82,37 +81,14 @@ public class ImportExportActivity extends AppCompatActivity
}
});
// Check that there is an activity that can bring up a file chooser
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
intentPickAction.setData(Uri.parse("file://"));
Button importFilesystem = (Button) findViewById(R.id.importOptionFilesystemButton);
importFilesystem.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
chooseFileWithIntent(intentPickAction);
}
});
if(isCallable(getApplicationContext(), intentPickAction) == false)
{
findViewById(R.id.dividerImportFilesystem).setVisibility(View.GONE);
findViewById(R.id.importOptionFilesystemTitle).setVisibility(View.GONE);
findViewById(R.id.importOptionFilesystemExplanation).setVisibility(View.GONE);
importFilesystem.setVisibility(View.GONE);
}
// Check that there is an application that can find content
// Check that there is a file manager available
final Intent intentGetContentAction = new Intent(Intent.ACTION_GET_CONTENT);
intentGetContentAction.addCategory(Intent.CATEGORY_OPENABLE);
intentGetContentAction.setType("*/*");
Button importApplication = (Button) findViewById(R.id.importOptionApplicationButton);
importApplication.setOnClickListener(new View.OnClickListener()
Button importFilesystem = findViewById(R.id.importOptionFilesystemButton);
importFilesystem.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
@@ -122,6 +98,27 @@ public class ImportExportActivity extends AppCompatActivity
});
if(isCallable(getApplicationContext(), intentGetContentAction) == false)
{
findViewById(R.id.dividerImportFilesystem).setVisibility(View.GONE);
findViewById(R.id.importOptionFilesystemTitle).setVisibility(View.GONE);
findViewById(R.id.importOptionFilesystemExplanation).setVisibility(View.GONE);
importFilesystem.setVisibility(View.GONE);
}
// Check that there is an app that data can be imported from
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
Button importApplication = findViewById(R.id.importOptionApplicationButton);
importApplication.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
chooseFileWithIntent(intentPickAction);
}
});
if(isCallable(getApplicationContext(), intentPickAction) == false)
{
findViewById(R.id.dividerImportApplication).setVisibility(View.GONE);
findViewById(R.id.importOptionApplicationTitle).setVisibility(View.GONE);
@@ -129,10 +126,9 @@ public class ImportExportActivity extends AppCompatActivity
importApplication.setVisibility(View.GONE);
}
// This option, to import from the fixed location, should always be present
Button importButton = (Button)findViewById(R.id.importOptionFixedButton);
Button importButton = findViewById(R.id.importOptionFixedButton);
importButton.setOnClickListener(new View.OnClickListener()
{
@Override
@@ -236,33 +232,6 @@ public class ImportExportActivity extends AppCompatActivity
return super.onOptionsItemSelected(item);
}
private String fileNameFromUri(Uri uri)
{
if("file".equals(uri.getScheme()))
{
return uri.getPath();
}
Cursor returnCursor =
getContentResolver().query(uri, null, null, null, null);
if(returnCursor == null)
{
return null;
}
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if(returnCursor.moveToFirst() == false)
{
returnCursor.close();
return null;
}
String name = returnCursor.getString(nameIndex);
returnCursor.close();
return name;
}
private void onImportComplete(boolean success, Uri path)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -277,15 +246,10 @@ public class ImportExportActivity extends AppCompatActivity
}
int messageId = success ? R.string.importedFrom : R.string.importFailed;
final String template = getResources().getString(messageId);
// Get the filename of the file being imported
String filename = fileNameFromUri(path);
if(filename == null)
{
filename = "(unknown)";
}
String filename = path.toString();
final String message = String.format(template, filename);
builder.setMessage(message);
@@ -413,13 +377,24 @@ public class ImportExportActivity extends AppCompatActivity
try
{
InputStream reader = getContentResolver().openInputStream(uri);
InputStream reader;
if(uri.getScheme() != null)
{
reader = getContentResolver().openInputStream(uri);
}
else
{
reader = new FileInputStream(new File(uri.toString()));
}
Log.e(TAG, "Starting file import with: " + uri.toString());
startImport(reader, uri);
}
catch (FileNotFoundException e)
catch(FileNotFoundException e)
{
Log.e(TAG, "Failed to import file: " + uri.toString(), e);
onImportComplete(false, uri);
}
}
}

View File

@@ -0,0 +1,97 @@
package protect.card_locker;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import java.io.InvalidObjectException;
public class ImportURIHelper {
private static final String STORE = DBHelper.LoyaltyCardDbIds.STORE;
private static final String NOTE = DBHelper.LoyaltyCardDbIds.NOTE;
private static final String CARD_ID = DBHelper.LoyaltyCardDbIds.CARD_ID;
private static final String BARCODE_TYPE = DBHelper.LoyaltyCardDbIds.BARCODE_TYPE;
private static final String HEADER_COLOR = DBHelper.LoyaltyCardDbIds.HEADER_COLOR;
private static final String HEADER_TEXT_COLOR = DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR;
private final Context context;
private final String host;
private final String path;
private final String shareText;
public ImportURIHelper(Context context) {
this.context = context;
host = context.getResources().getString(R.string.intent_import_card_from_url_host);
path = context.getResources().getString(R.string.intent_import_card_from_url_path_prefix);
shareText = context.getResources().getString(R.string.intent_import_card_from_url_share_text);
}
private boolean isImportUri(Uri uri) {
return uri.getHost().equals(host) && uri.getPath().equals(path);
}
public LoyaltyCard parse(Uri uri) throws InvalidObjectException {
if(!isImportUri(uri)) {
throw new InvalidObjectException("Not an import URI");
}
try {
// These values are allowed to be null
Integer headerColor = null;
Integer headerTextColor = null;
String store = uri.getQueryParameter(STORE);
String note = uri.getQueryParameter(NOTE);
String cardId = uri.getQueryParameter(CARD_ID);
String barcodeType = uri.getQueryParameter(BARCODE_TYPE);
String unparsedHeaderColor = uri.getQueryParameter(HEADER_COLOR);
if(unparsedHeaderColor != null)
{
headerColor = Integer.parseInt(unparsedHeaderColor);
}
String unparsedHeaderTextColor = uri.getQueryParameter(HEADER_TEXT_COLOR);
if(unparsedHeaderTextColor != null)
{
headerTextColor = Integer.parseInt(unparsedHeaderTextColor);
}
return new LoyaltyCard(-1, store, note, cardId, barcodeType, headerColor, headerTextColor);
} catch (NullPointerException | NumberFormatException ex) {
throw new InvalidObjectException("Not a valid import URI");
}
}
// Protected for usage in tests
protected Uri toUri(LoyaltyCard loyaltyCard) {
Uri.Builder uriBuilder = new Uri.Builder();
uriBuilder.scheme("https");
uriBuilder.authority(host);
uriBuilder.path(path);
uriBuilder.appendQueryParameter(STORE, loyaltyCard.store);
uriBuilder.appendQueryParameter(NOTE, loyaltyCard.note);
uriBuilder.appendQueryParameter(CARD_ID, loyaltyCard.cardId);
uriBuilder.appendQueryParameter(BARCODE_TYPE, loyaltyCard.barcodeType);
if(loyaltyCard.headerColor != null)
{
uriBuilder.appendQueryParameter(HEADER_COLOR, loyaltyCard.headerColor.toString());
}
if(loyaltyCard.headerTextColor != null)
{
uriBuilder.appendQueryParameter(HEADER_TEXT_COLOR, loyaltyCard.headerTextColor.toString());
}
return uriBuilder.build();
}
private void startShareIntent(Uri uri) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, shareText + "\n" + uri.toString());
sendIntent.setType("text/plain");
Intent shareIntent = Intent.createChooser(sendIntent, null);
context.startActivity(shareIntent);
}
public void startShareIntent(LoyaltyCard loyaltyCard) {
startShareIntent(toUri(loyaltyCard));
}
}

View File

@@ -0,0 +1,140 @@
package protect.card_locker;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.text.TextPaint;
/**
* Original from https://github.com/andOTP/andOTP/blob/master/app/src/main/java/org/shadowice/flocke/andotp/Utilities/LetterBitmap.java
* which was originally from http://stackoverflow.com/questions/23122088/colored-boxed-with-letters-a-la-gmail
* Used to create a {@link Bitmap} that contains a letter used in the English
* alphabet or digit, if there is no letter or digit available, a default image
* is shown instead.
*/
class LetterBitmap
{
/**
* The number of available tile colors
*/
private static final int NUM_OF_TILE_COLORS = 8;
/**
* The letter bitmap
*/
private final Bitmap mBitmap;
/**
* The background color of the letter bitmap
*/
private final Integer mColor;
/**
* Constructor for <code>LetterTileProvider</code>
*
* @param context The {@link Context} to use
* @param displayName The name used to create the letter for the tile
* @param key The key used to generate the background color for the tile
* @param tileLetterFontSize The font size used to display the letter
* @param width The desired width of the tile
* @param height The desired height of the tile
* @param backgroundColor (optional) color to use for background.
* @param textColor (optional) color to use for text.
*/
public LetterBitmap(Context context, String displayName, String key, int tileLetterFontSize,
int width, int height, Integer backgroundColor, Integer textColor)
{
TextPaint paint = new TextPaint();
paint.setTypeface(Typeface.create("sans-serif-light", Typeface.BOLD));
if(textColor != null)
{
paint.setColor(textColor);
}
else
{
paint.setColor(Color.WHITE);
}
paint.setTextAlign(Paint.Align.CENTER);
paint.setAntiAlias(true);
if(backgroundColor == null)
{
mColor = getDefaultColor(context, key);
}
else
{
mColor = backgroundColor;
}
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
String firstChar = displayName.substring(0, 1);
final Canvas c = new Canvas();
c.setBitmap(mBitmap);
c.drawColor(mColor);
char [] firstCharArray = new char[1];
firstCharArray[0] = firstChar.toUpperCase().charAt(0);
paint.setTextSize(tileLetterFontSize);
// The bounds that enclose the letter
Rect bounds = new Rect();
paint.getTextBounds(firstCharArray, 0, 1, bounds);
c.drawText(firstCharArray, 0, 1, width / 2.0f, height / 2.0f
+ (bounds.bottom - bounds.top) / 2.0f, paint);
}
/**
* @return A {@link Bitmap} that contains a letter used in the English
* alphabet or digit, if there is no letter or digit available, a
* default image is shown instead
*/
public Bitmap getLetterTile()
{
return mBitmap;
}
/**
* @return background color used for letter title.
*/
public int getBackgroundColor()
{
return mColor;
}
/**
* @param key The key used to generate the tile color
* @return A new or previously chosen color for <code>key</code> used as the
* tile background color
*/
private static int pickColor(String key, TypedArray colors)
{
// String.hashCode() is not supposed to change across java versions, so
// this should guarantee the same key always maps to the same color
final int color = Math.abs(key.hashCode()) % NUM_OF_TILE_COLORS;
return colors.getColor(color, Color.BLACK);
}
/**
* Determine the color which the letter tile will use if no default
* color is provided.
*/
public static int getDefaultColor(Context context, String key)
{
final Resources res = context.getResources();
TypedArray colors = res.obtainTypedArray(R.array.letter_tile_colors);
int color = pickColor(key, colors);
colors.recycle();
return color;
}
}

View File

@@ -1,6 +1,7 @@
package protect.card_locker;
import android.database.Cursor;
import androidx.annotation.Nullable;
public class LoyaltyCard
{
@@ -10,13 +11,22 @@ public class LoyaltyCard
public final String cardId;
public final String barcodeType;
public LoyaltyCard(final int id, final String store, final String note, final String cardId, final String barcodeType)
@Nullable
public final Integer headerColor;
@Nullable
public final Integer headerTextColor;
public LoyaltyCard(final int id, final String store, final String note, final String cardId,
final String barcodeType, final Integer headerColor, final Integer headerTextColor)
{
this.id = id;
this.store = store;
this.note = note;
this.cardId = cardId;
this.barcodeType = barcodeType;
this.headerColor = headerColor;
this.headerTextColor = headerTextColor;
}
public static LoyaltyCard toLoyaltyCard(Cursor cursor)
@@ -27,6 +37,22 @@ public class LoyaltyCard
String cardId = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID));
String barcodeType = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE));
return new LoyaltyCard(id, store, note, cardId, barcodeType);
int headerColorColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR);
int headerTextColorColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR);
Integer headerColor = null;
Integer headerTextColor = null;
if(cursor.isNull(headerColorColumn) == false)
{
headerColor = cursor.getInt(headerColorColumn);
}
if(cursor.isNull(headerTextColorColumn) == false)
{
headerTextColor = cursor.getInt(headerTextColorColumn);
}
return new LoyaltyCard(id, store, note, cardId, barcodeType, headerColor, headerTextColor);
}
}

View File

@@ -6,13 +6,21 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import protect.card_locker.preferences.Settings;
class LoyaltyCardCursorAdapter extends CursorAdapter
{
Settings settings;
DBHelper dbHelper;
public LoyaltyCardCursorAdapter(Context context, Cursor cursor)
{
super(context, cursor, 0);
settings = new Settings(context);
dbHelper = new DBHelper(context);
}
// The newView method is used to inflate a new view and return it,
@@ -29,25 +37,46 @@ class LoyaltyCardCursorAdapter extends CursorAdapter
public void bindView(View view, Context context, Cursor cursor)
{
// Find fields to populate in inflated template
ImageView thumbnail = view.findViewById(R.id.thumbnail);
TextView storeField = (TextView) view.findViewById(R.id.store);
TextView cardIdField = (TextView) view.findViewById(R.id.cardId);
TextView noteField = (TextView) view.findViewById(R.id.note);
// Extract properties from cursor
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(cursor);
// Get amount of cards for this store
int cardCount = dbHelper.getLoyaltyCardsForStore(loyaltyCard.store).size();
// Populate fields with extracted properties
String storeAndNote = loyaltyCard.store;
if(loyaltyCard.note.isEmpty() == false)
storeField.setText(loyaltyCard.store);
storeField.setTextSize(settings.getCardTitleListFontSize());
if(cardCount > 1 || !loyaltyCard.note.isEmpty())
{
String storeNameAndNoteFormat = view.getResources().getString(R.string.storeNameAndNoteFormat);
storeAndNote = String.format(storeNameAndNoteFormat, loyaltyCard.store, loyaltyCard.note);
noteField.setVisibility(View.VISIBLE);
if(cardCount > 1)
{
noteField.setText(context.getResources().getString(R.string.cardCount, cardCount));
}
else
{
noteField.setText(loyaltyCard.note);
}
noteField.setTextSize(settings.getCardNoteListFontSize());
}
else
{
noteField.setVisibility(View.GONE);
}
storeField.setText(storeAndNote);
int tileLetterFontSize = context.getResources().getDimensionPixelSize(R.dimen.tileLetterFontSize);
int pixelSize = context.getResources().getDimensionPixelSize(R.dimen.cardThumbnailSize);
String cardIdFormat = view.getResources().getString(R.string.cardIdFormat);
String cardIdLabel = view.getResources().getString(R.string.cardId);
String cardIdText = String.format(cardIdFormat, cardIdLabel, loyaltyCard.cardId);
cardIdField.setText(cardIdText);
Integer letterBackgroundColor = loyaltyCard.headerColor;
Integer letterTextColor = loyaltyCard.headerTextColor;
LetterBitmap letterBitmap = new LetterBitmap(context, loyaltyCard.store, loyaltyCard.store,
tileLetterFontSize, pixelSize, pixelSize, letterBackgroundColor, letterTextColor);
thumbnail.setImageBitmap(letterBitmap.getLetterTile());
}
}

View File

@@ -0,0 +1,528 @@
package protect.card_locker;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.jaredrummler.android.colorpicker.ColorPickerDialog;
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener;
import java.io.InvalidObjectException;
public class LoyaltyCardEditActivity extends AppCompatActivity
{
private static final String TAG = "CardLocker";
protected static final String NO_BARCODE = "_NO_BARCODE_";
protected static final int SELECT_BARCODE_REQUEST = 1;
FloatingActionButton fabSave;
EditText storeFieldEdit;
EditText noteFieldEdit;
ImageView headingColorSample;
Button headingColorSelectButton;
ImageView headingStoreTextColorSample;
Button headingStoreTextColorSelectButton;
TextView cardIdFieldView;
View cardIdDivider;
View cardIdTableRow;
TextView barcodeTypeField;
ImageView barcodeImage;
View barcodeImageLayout;
View barcodeCaptureLayout;
Button captureButton;
Button enterButton;
int loyaltyCardId;
boolean updateLoyaltyCard;
String loyaltyCardStorePrefill = "";
Uri importLoyaltyCardUri = null;
Integer headingColorValue = null;
Integer headingStoreTextColorValue = null;
DBHelper db;
ImportURIHelper importUriHelper;
private void extractIntentFields(Intent intent)
{
final Bundle b = intent.getExtras();
loyaltyCardId = b != null ? b.getInt("id") : 0;
updateLoyaltyCard = b != null && b.getBoolean("update", false);
loyaltyCardStorePrefill = b != null ? b.getString("store", "") : "";
importLoyaltyCardUri = intent.getData();
Log.d(TAG, "View activity: id=" + loyaltyCardId
+ ", updateLoyaltyCard=" + Boolean.toString(updateLoyaltyCard));
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.loyalty_card_edit_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
actionBar.setDisplayHomeAsUpEnabled(true);
}
extractIntentFields(getIntent());
db = new DBHelper(this);
importUriHelper = new ImportURIHelper(this);
fabSave = findViewById(R.id.fabSave);
storeFieldEdit = findViewById(R.id.storeNameEdit);
noteFieldEdit = findViewById(R.id.noteEdit);
headingColorSample = findViewById(R.id.headingColorSample);
headingColorSelectButton = findViewById(R.id.headingColorSelectButton);
headingStoreTextColorSample = findViewById(R.id.headingStoreTextColorSample);
headingStoreTextColorSelectButton = findViewById(R.id.headingStoreTextColorSelectButton);
cardIdFieldView = findViewById(R.id.cardIdView);
cardIdDivider = findViewById(R.id.cardIdDivider);
cardIdTableRow = findViewById(R.id.cardIdTableRow);
barcodeTypeField = findViewById(R.id.barcodeType);
barcodeImage = findViewById(R.id.barcode);
barcodeImageLayout = findViewById(R.id.barcodeLayout);
barcodeCaptureLayout = findViewById(R.id.barcodeCaptureLayout);
captureButton = findViewById(R.id.captureButton);
enterButton = findViewById(R.id.enterButton);
}
@Override
public void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
Log.i(TAG, "Received new intent");
extractIntentFields(intent);
// Reset these fields, so they are re-populated in onResume().
storeFieldEdit.setText("");
noteFieldEdit.setText("");
cardIdFieldView.setText("");
barcodeTypeField.setText("");
}
@Override
public void onResume()
{
super.onResume();
Log.i(TAG, "To view card: " + loyaltyCardId);
fabSave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view) {
doSave();
}
});
if(updateLoyaltyCard)
{
final LoyaltyCard loyaltyCard = db.getLoyaltyCard(loyaltyCardId);
if(loyaltyCard == null)
{
Log.w(TAG, "Could not lookup loyalty card " + loyaltyCardId);
Toast.makeText(this, R.string.noCardExistsError, Toast.LENGTH_LONG).show();
finish();
return;
}
if(storeFieldEdit.getText().length() == 0)
{
storeFieldEdit.setText(loyaltyCard.store);
}
if(noteFieldEdit.getText().length() == 0)
{
noteFieldEdit.setText(loyaltyCard.note);
}
if(cardIdFieldView.getText().length() == 0)
{
cardIdFieldView.setText(loyaltyCard.cardId);
}
if(barcodeTypeField.getText().length() == 0)
{
barcodeTypeField.setText(loyaltyCard.barcodeType);
}
if(headingColorValue == null)
{
headingColorValue = loyaltyCard.headerColor;
if(headingColorValue == null)
{
headingColorValue = LetterBitmap.getDefaultColor(this, loyaltyCard.store);
}
}
if(headingStoreTextColorValue == null)
{
headingStoreTextColorValue = loyaltyCard.headerTextColor;
if(headingStoreTextColorValue == null)
{
headingStoreTextColorValue = Color.WHITE;
}
}
setTitle(R.string.editCardTitle);
}
else if(importLoyaltyCardUri != null)
{
// Try to parse
LoyaltyCard importCard;
try {
importCard = importUriHelper.parse(importLoyaltyCardUri);
} catch (InvalidObjectException ex) {
Toast.makeText(this, R.string.failedParsingImportUriError, Toast.LENGTH_LONG).show();
finish();
return;
}
storeFieldEdit.setText(importCard.store);
noteFieldEdit.setText(importCard.note);
cardIdFieldView.setText(importCard.cardId);
barcodeTypeField.setText(importCard.barcodeType);
headingColorValue = importCard.headerColor;
headingStoreTextColorValue = importCard.headerTextColor;
}
else
{
setTitle(R.string.addCardTitle);
}
// Set prefill values if nothing is set
if(storeFieldEdit.getText().length() == 0 && !loyaltyCardStorePrefill.isEmpty())
{
storeFieldEdit.setText(loyaltyCardStorePrefill);
}
if(headingColorValue == null)
{
// Select a random color to start out with.
TypedArray colors = getResources().obtainTypedArray(R.array.letter_tile_colors);
final int color = (int)(Math.random() * colors.length());
headingColorValue = colors.getColor(color, Color.BLACK);
colors.recycle();
}
if(headingStoreTextColorValue == null) {
headingStoreTextColorValue = Color.WHITE;
}
headingColorSample.setBackgroundColor(headingColorValue);
headingStoreTextColorSample.setBackgroundColor(headingStoreTextColorValue);
headingColorSelectButton.setOnClickListener(new ColorSelectListener(headingColorValue, true));
headingStoreTextColorSelectButton.setOnClickListener(new ColorSelectListener(headingStoreTextColorValue, false));
if(cardIdFieldView.getText().length() > 0 && barcodeTypeField.getText().length() > 0)
{
if(barcodeTypeField.getText().equals(NO_BARCODE))
{
barcodeImageLayout.setVisibility(View.GONE);
}
else
{
String formatString = barcodeTypeField.getText().toString();
final BarcodeFormat format = BarcodeFormat.valueOf(formatString);
final String cardIdString = cardIdFieldView.getText().toString();
if(barcodeImage.getHeight() == 0)
{
Log.d(TAG, "ImageView size is not known known at start, waiting for load");
// The size of the ImageView is not yet available as it has not
// yet been drawn. Wait for it to be drawn so the size is available.
barcodeImage.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
if (Build.VERSION.SDK_INT < 16)
{
barcodeImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
else
{
barcodeImage.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
Log.d(TAG, "ImageView size now known");
new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute();
}
});
}
else
{
Log.d(TAG, "ImageView size known known, creating barcode");
new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute();
}
barcodeImageLayout.setVisibility(View.VISIBLE);
}
}
View.OnClickListener captureCallback = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
IntentIntegrator integrator = new IntentIntegrator(LoyaltyCardEditActivity.this);
integrator.setDesiredBarcodeFormats(BarcodeSelectorActivity.SUPPORTED_BARCODE_TYPES);
String prompt = getResources().getString(R.string.scanCardBarcode);
integrator.setPrompt(prompt);
integrator.setBeepEnabled(false);
integrator.initiateScan();
}
};
captureButton.setOnClickListener(captureCallback);
enterButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent i = new Intent(getApplicationContext(), BarcodeSelectorActivity.class);
String cardId = cardIdFieldView.getText().toString();
if(cardId.length() > 0)
{
final Bundle b = new Bundle();
b.putString("initialCardId", cardId);
i.putExtras(b);
}
startActivityForResult(i, SELECT_BARCODE_REQUEST);
}
});
if(cardIdFieldView.getText().length() > 0)
{
cardIdDivider.setVisibility(View.VISIBLE);
cardIdTableRow.setVisibility(View.VISIBLE);
enterButton.setText(R.string.editCard);
}
else
{
cardIdDivider.setVisibility(View.GONE);
cardIdTableRow.setVisibility(View.GONE);
enterButton.setText(R.string.enterCard);
}
}
class ColorSelectListener implements View.OnClickListener
{
final int defaultColor;
final boolean isBackgroundColor;
ColorSelectListener(int defaultColor, boolean isBackgroundColor)
{
this.defaultColor = defaultColor;
this.isBackgroundColor = isBackgroundColor;
}
@Override
public void onClick(View v)
{
ColorPickerDialog dialog = ColorPickerDialog.newBuilder().setColor(defaultColor).create();
dialog.setColorPickerDialogListener(new ColorPickerDialogListener()
{
@Override
public void onColorSelected(int dialogId, int color)
{
if(isBackgroundColor)
{
headingColorSample.setBackgroundColor(color);
headingColorValue = color;
}
else
{
headingStoreTextColorSample.setBackgroundColor(color);
headingStoreTextColorValue = color;
}
}
@Override
public void onDialogDismissed(int dialogId)
{
// Nothing to do, no change made
}
});
dialog.show(getFragmentManager(), "color-picker-dialog");
}
}
private void doSave()
{
String store = storeFieldEdit.getText().toString();
String note = noteFieldEdit.getText().toString();
String cardId = cardIdFieldView.getText().toString();
String barcodeType = barcodeTypeField.getText().toString();
// We do not want to save the no barcode string to the database
// it is simply an empty there for no barcode
if(barcodeType.equals(NO_BARCODE))
{
barcodeType = "";
}
if(store.isEmpty())
{
Snackbar.make(storeFieldEdit, R.string.noStoreError, Snackbar.LENGTH_LONG).show();
return;
}
if(cardId.isEmpty())
{
Snackbar.make(cardIdFieldView, R.string.noCardIdError, Snackbar.LENGTH_LONG).show();
return;
}
if(updateLoyaltyCard)
{
db.updateLoyaltyCard(loyaltyCardId, store, note, cardId, barcodeType, headingColorValue, headingStoreTextColorValue);
Log.i(TAG, "Updated " + loyaltyCardId + " to " + cardId);
}
else
{
loyaltyCardId = (int)db.insertLoyaltyCard(store, note, cardId, barcodeType, headingColorValue, headingStoreTextColorValue);
}
finish();
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
if(updateLoyaltyCard)
{
getMenuInflater().inflate(R.menu.card_update_menu, menu);
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
switch(id)
{
case android.R.id.home:
finish();
break;
case R.id.action_delete:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.deleteTitle);
builder.setMessage(R.string.deleteConfirmation);
builder.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Log.e(TAG, "Deleting card: " + loyaltyCardId);
DBHelper db = new DBHelper(LoyaltyCardEditActivity.this);
db.deleteLoyaltyCard(loyaltyCardId);
ShortcutHelper.removeShortcut(LoyaltyCardEditActivity.this, loyaltyCardId);
finish();
dialog.dismiss();
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
super.onActivityResult(requestCode, resultCode, intent);
String contents = null;
String format = null;
IntentResult result =
IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (result != null)
{
Log.i(TAG, "Received barcode information from capture");
contents = result.getContents();
format = result.getFormatName();
}
if(requestCode == SELECT_BARCODE_REQUEST && resultCode == Activity.RESULT_OK)
{
Log.i(TAG, "Received barcode information from typing it");
contents = intent.getStringExtra(BarcodeSelectorActivity.BARCODE_CONTENTS);
format = intent.getStringExtra(BarcodeSelectorActivity.BARCODE_FORMAT);
}
if(contents != null && contents.isEmpty() == false &&
format != null)
{
Log.i(TAG, "Read barcode id: " + contents);
Log.i(TAG, "Read format: " + format);
TextView cardIdView = findViewById(R.id.cardIdView);
cardIdView.setText(contents);
final TextView barcodeTypeField = findViewById(R.id.barcodeType);
// Set special NO_BARCODE value to prevent onResume from overwriting it
barcodeTypeField.setText(format.isEmpty() ? LoyaltyCardEditActivity.NO_BARCODE : format);
onResume();
}
}
}

View File

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

View File

@@ -1,77 +1,98 @@
package protect.card_locker;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.graphics.ColorUtils;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.GestureDetectorCompat;
import androidx.core.view.MotionEventCompat;
import androidx.core.widget.TextViewCompat;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import java.util.List;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardViewActivity extends AppCompatActivity
public class LoyaltyCardViewActivity extends AppCompatActivity implements GestureDetector.OnGestureListener
{
private static final String TAG = "CardLocker";
private static final double LUMINANCE_MIDPOINT = 0.5;
private static final int SELECT_BARCODE_REQUEST = 1;
EditText storeFieldEdit;
TextView storeFieldView;
EditText noteFieldEdit;
TextView noteFieldView;
FloatingActionButton FabAdd;
TabLayout tabLayout;
TabLayout.OnTabSelectedListener onTabSelectedListener;
TextView cardIdFieldView;
View cardIdDivider;
View cardIdTableRow;
TextView barcodeTypeField;
TextView noteView;
View noteViewDivider;
TextView storeName;
ImageView barcodeImage;
View barcodeImageLayout;
View barcodeCaptureLayout;
Button captureButton;
Button enterButton;
View collapsingToolbarLayout;
int loyaltyCardId;
boolean updateLoyaltyCard;
boolean viewLoyaltyCard;
LoyaltyCard loyaltyCard;
List<LoyaltyCard> storeCards;
GestureDetectorCompat gestureDetector;
boolean rotationEnabled;
DBHelper db;
ImportURIHelper importURIHelper;
Settings settings;
String cardIdString;
BarcodeFormat format;
boolean backgroundNeedsDarkIcons;
boolean barcodeIsFullscreen = false;
ViewGroup.LayoutParams barcodeImageState;
private void extractIntentFields(Intent intent)
{
final Bundle b = intent.getExtras();
loyaltyCardId = b != null ? b.getInt("id") : 0;
updateLoyaltyCard = b != null && b.getBoolean("update", false);
viewLoyaltyCard = b != null && b.getBoolean("view", false);
Log.d(TAG, "View activity: id=" + loyaltyCardId);
}
Log.d(TAG, "View activity: id=" + loyaltyCardId
+ ", updateLoyaltyCard=" + Boolean.toString(updateLoyaltyCard)
+ ", viewLoyaltyCard=" + Boolean.toString(viewLoyaltyCard));
private Drawable getIcon(int icon, boolean dark)
{
Drawable unwrappedIcon = AppCompatResources.getDrawable(this, icon);
Drawable wrappedIcon = DrawableCompat.wrap(unwrappedIcon);
if(dark)
{
DrawableCompat.setTint(wrappedIcon, Color.BLACK);
}
else
{
DrawableCompat.setTintList(wrappedIcon, null);
}
return wrappedIcon;
}
@Override
@@ -79,8 +100,13 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
{
super.onCreate(savedInstanceState);
setContentView(R.layout.loyalty_card_view_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
settings = new Settings(this);
extractIntentFields(getIntent());
setContentView(R.layout.loyalty_card_view_layout);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
@@ -88,37 +114,85 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
actionBar.setDisplayHomeAsUpEnabled(true);
}
extractIntentFields(getIntent());
db = new DBHelper(this);
importURIHelper = new ImportURIHelper(this);
storeFieldEdit = (EditText) findViewById(R.id.storeNameEdit);
storeFieldView = (TextView) findViewById(R.id.storeNameView);
noteFieldEdit = (EditText) findViewById(R.id.noteEdit);
noteFieldView = (TextView) findViewById(R.id.noteView);
cardIdFieldView = (TextView) findViewById(R.id.cardIdView);
cardIdDivider = findViewById(R.id.cardIdDivider);
cardIdTableRow = findViewById(R.id.cardIdTableRow);
barcodeTypeField = (TextView) findViewById(R.id.barcodeType);
barcodeImage = (ImageView) findViewById(R.id.barcode);
barcodeImageLayout = findViewById(R.id.barcodeLayout);
barcodeCaptureLayout = findViewById(R.id.barcodeCaptureLayout);
FabAdd = findViewById(R.id.fabAdd);
FabAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
Bundle bundle = new Bundle();
bundle.putString("store", loyaltyCard.store);
intent.putExtras(bundle);
startActivity(intent);
finish();
}
});
tabLayout = findViewById(R.id.tabLayout);
onTabSelectedListener = new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
loyaltyCardId = storeCards.get(tab.getPosition()).id;
onResume();
}
captureButton = (Button) findViewById(R.id.captureButton);
enterButton = (Button) findViewById(R.id.enterButton);
@Override
public void onTabUnselected(TabLayout.Tab tab) {}
@Override
public void onTabReselected(TabLayout.Tab tab) {}
};
cardIdFieldView = findViewById(R.id.cardIdView);
noteView = findViewById(R.id.noteView);
noteViewDivider = findViewById(R.id.noteViewDivider);
storeName = findViewById(R.id.storeName);
barcodeImage = findViewById(R.id.barcode);
collapsingToolbarLayout = findViewById(R.id.collapsingToolbarLayout);
rotationEnabled = true;
gestureDetector = new GestureDetectorCompat(this, this);
// Restore active card id after rotation
if(savedInstanceState != null)
{
loyaltyCardId = savedInstanceState.getInt("id");
onResume();
}
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save active card id before rotation
savedInstanceState.putInt("id", loyaltyCardId);
super.onSaveInstanceState(savedInstanceState);
// Allow making barcode fullscreen on tap
barcodeImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(barcodeIsFullscreen)
{
setFullscreen(false);
}
else
{
setFullscreen(true);
}
}
});
}
@Override
public void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
Log.i(TAG, "Received new intent");
extractIntentFields(intent);
// Reset these fields, so they are re-populated in onResume().
storeFieldEdit.setText("");
noteFieldEdit.setText("");
cardIdFieldView.setText("");
barcodeTypeField.setText("");
}
@Override
@@ -128,216 +202,199 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
Log.i(TAG, "To view card: " + loyaltyCardId);
if(viewLoyaltyCard)
if(barcodeIsFullscreen)
{
// The brightness value is on a scale from [0, ..., 1], where
// '1' is the brightest. We attempt to maximize the brightness
// to help barcode readers scan the barcode.
Window window = getWindow();
if(window != null)
{
WindowManager.LayoutParams attributes = window.getAttributes();
attributes.screenBrightness = 1F;
window.setAttributes(attributes);
}
// Completely reset state
//
// This prevents the barcode from taking up the entire screen
// on resume and thus being stretched out of proportion.
recreate();
}
if(updateLoyaltyCard || viewLoyaltyCard)
// The brightness value is on a scale from [0, ..., 1], where
// '1' is the brightest. We attempt to maximize the brightness
// to help barcode readers scan the barcode.
Window window = getWindow();
if(window != null && settings.useMaxBrightnessDisplayingBarcode())
{
final LoyaltyCard loyaltyCard = db.getLoyaltyCard(loyaltyCardId);
if(loyaltyCard == null)
WindowManager.LayoutParams attributes = window.getAttributes();
attributes.screenBrightness = 1F;
window.setAttributes(attributes);
}
loyaltyCard = db.getLoyaltyCard(loyaltyCardId);
if(loyaltyCard == null)
{
Log.w(TAG, "Could not lookup loyalty card " + loyaltyCardId);
Toast.makeText(this, R.string.noCardExistsError, Toast.LENGTH_LONG).show();
finish();
return;
}
storeCards = db.getLoyaltyCardsForStore(loyaltyCard.store);
tabLayout.removeOnTabSelectedListener(onTabSelectedListener);
tabLayout.removeAllTabs();
for(int i = 0; i < storeCards.size(); i++)
{
LoyaltyCard storeCard = storeCards.get(i);
// Use only first line of note
String loyaltyCardText = storeCard.note.split("\\r?\\n")[0].trim();
if(loyaltyCardText.isEmpty())
{
Log.w(TAG, "Could not lookup loyalty card " + loyaltyCardId);
Toast.makeText(this, R.string.noCardExistsError, Toast.LENGTH_LONG).show();
finish();
return;
loyaltyCardText = String.valueOf(i + 1);
}
else if(loyaltyCardText.length() > 15)
{
// Shorten long notes
loyaltyCardText = loyaltyCardText.substring(0, 15).trim() + "";
}
if(storeFieldEdit.getText().length() == 0)
{
storeFieldEdit.setText(loyaltyCard.store);
storeFieldView.setText(loyaltyCard.store);
}
tabLayout.addTab(tabLayout.newTab().setText(loyaltyCardText));
if(noteFieldEdit.getText().length() == 0)
if(storeCard.id == loyaltyCardId)
{
noteFieldEdit.setText(loyaltyCard.note);
noteFieldView.setText(loyaltyCard.note);
tabLayout.getTabAt(i).select();
}
}
tabLayout.addOnTabSelectedListener(onTabSelectedListener);
if(tabLayout.getTabCount() > 1)
{
tabLayout.setVisibility(View.VISIBLE);
}
if(cardIdFieldView.getText().length() == 0)
{
cardIdFieldView.setText(loyaltyCard.cardId);
}
String formatString = loyaltyCard.barcodeType;
format = !formatString.isEmpty() ? BarcodeFormat.valueOf(formatString) : null;
cardIdString = loyaltyCard.cardId;
if(barcodeTypeField.getText().length() == 0)
{
barcodeTypeField.setText(loyaltyCard.barcodeType);
}
cardIdFieldView.setText(loyaltyCard.cardId);
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(cardIdFieldView,
getResources().getInteger(R.integer.settings_card_id_min_font_size_sp)-1, settings.getCardIdFontSize(),
1, TypedValue.COMPLEX_UNIT_SP);
if(updateLoyaltyCard)
{
setTitle(R.string.editCardTitle);
storeFieldView.setVisibility(View.GONE);
noteFieldView.setVisibility(View.GONE);
}
else
{
barcodeCaptureLayout.setVisibility(View.GONE);
captureButton.setVisibility(View.GONE);
setTitle(R.string.viewCardTitle);
storeFieldEdit.setVisibility(View.GONE);
noteFieldEdit.setVisibility(View.GONE);
}
if(loyaltyCard.note.length() > 0)
{
noteView.setText(loyaltyCard.note);
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(noteView,
getResources().getInteger(R.integer.settings_card_note_min_font_size_sp)-1,
settings.getCardNoteFontSize(), 1, TypedValue.COMPLEX_UNIT_SP);
noteView.setVisibility(View.VISIBLE);
noteViewDivider.setVisibility(View.VISIBLE);
}
else
{
setTitle(R.string.addCardTitle);
storeFieldView.setVisibility(View.GONE);
noteFieldView.setVisibility(View.GONE);
noteView.setVisibility(View.GONE);
noteViewDivider.setVisibility(View.GONE);
}
if(cardIdFieldView.getText().length() > 0 && barcodeTypeField.getText().length() > 0)
{
String formatString = barcodeTypeField.getText().toString();
final BarcodeFormat format = BarcodeFormat.valueOf(formatString);
final String cardIdString = cardIdFieldView.getText().toString();
storeName.setText(loyaltyCard.store);
storeName.setTextSize(settings.getCardTitleFontSize());
int textColor;
if(loyaltyCard.headerTextColor != null)
{
textColor = loyaltyCard.headerTextColor;
}
else
{
textColor = Color.WHITE;
}
storeName.setTextColor(textColor);
int backgroundHeaderColor;
if(loyaltyCard.headerColor != null)
{
backgroundHeaderColor = loyaltyCard.headerColor;
}
else
{
backgroundHeaderColor = LetterBitmap.getDefaultColor(this, loyaltyCard.store);
}
collapsingToolbarLayout.setBackgroundColor(backgroundHeaderColor);
// If the background is very bright, we should use dark icons
backgroundNeedsDarkIcons = (ColorUtils.calculateLuminance(backgroundHeaderColor) > LUMINANCE_MIDPOINT);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
actionBar.setHomeAsUpIndicator(getIcon(R.drawable.ic_arrow_back_white, backgroundNeedsDarkIcons));
}
// Make notification area light if dark icons are needed
if(Build.VERSION.SDK_INT >= 23)
{
window.getDecorView().setSystemUiVisibility(backgroundNeedsDarkIcons ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0);
}
if(Build.VERSION.SDK_INT >= 21)
{
window.setStatusBarColor(Color.TRANSPARENT);
}
// Set shadow colour of store text so even same color on same color would be readable
storeName.setShadowLayer(1, 1, 1, backgroundNeedsDarkIcons ? Color.BLACK : Color.WHITE);
if(format != null)
{
findViewById(R.id.barcode).setVisibility(View.VISIBLE);
if(barcodeImage.getHeight() == 0)
{
Log.d(TAG, "ImageView size is not known known at start, waiting for load");
// The size of the ImageView is not yet available as it has not
// yet been drawn. Wait for it to be drawn so the size is available.
barcodeImage.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
new ViewTreeObserver.OnGlobalLayoutListener()
{
if (Build.VERSION.SDK_INT < 16)
{
barcodeImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
else
@Override
public void onGlobalLayout()
{
barcodeImage.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
Log.d(TAG, "ImageView size now known");
new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute();
}
});
Log.d(TAG, "ImageView size now known");
new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute();
}
});
}
else
{
Log.d(TAG, "ImageView size known known, creating barcode");
new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute();
}
barcodeImageLayout.setVisibility(View.VISIBLE);
}
View.OnClickListener captureCallback = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
IntentIntegrator integrator = new IntentIntegrator(LoyaltyCardViewActivity.this);
integrator.setDesiredBarcodeFormats(BarcodeSelectorActivity.SUPPORTED_BARCODE_TYPES);
String prompt = getResources().getString(R.string.scanCardBarcode);
integrator.setPrompt(prompt);
integrator.initiateScan();
}
};
captureButton.setOnClickListener(captureCallback);
enterButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent i = new Intent(getApplicationContext(), BarcodeSelectorActivity.class);
String cardId = cardIdFieldView.getText().toString();
if(cardId.length() > 0)
{
final Bundle b = new Bundle();
b.putString("initialCardId", cardId);
i.putExtras(b);
}
startActivityForResult(i, SELECT_BARCODE_REQUEST);
}
});
if(cardIdFieldView.getText().length() > 0)
{
cardIdDivider.setVisibility(View.VISIBLE);
cardIdTableRow.setVisibility(View.VISIBLE);
enterButton.setText(R.string.editCard);
}
else
{
cardIdDivider.setVisibility(View.GONE);
cardIdTableRow.setVisibility(View.GONE);
enterButton.setText(R.string.enterCard);
findViewById(R.id.barcode).setVisibility(View.INVISIBLE);
}
}
private void doSave()
{
String store = storeFieldEdit.getText().toString();
String note = noteFieldEdit.getText().toString();
String cardId = cardIdFieldView.getText().toString();
String barcodeType = barcodeTypeField.getText().toString();
if(store.isEmpty())
@Override
public void onBackPressed() {
if (barcodeIsFullscreen)
{
Snackbar.make(storeFieldEdit, R.string.noStoreError, Snackbar.LENGTH_LONG).show();
setFullscreen(false);
return;
}
if(cardId.isEmpty() || barcodeType.isEmpty())
{
Snackbar.make(cardIdFieldView, R.string.noCardIdError, Snackbar.LENGTH_LONG).show();
return;
}
if(updateLoyaltyCard)
{
db.updateLoyaltyCard(loyaltyCardId, store, note, cardId, barcodeType);
Log.i(TAG, "Updated " + loyaltyCardId + " to " + cardId);
}
else
{
loyaltyCardId = (int)db.insertLoyaltyCard(store, note, cardId, barcodeType);
}
finish();
super.onBackPressed();
return;
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
if(viewLoyaltyCard)
getMenuInflater().inflate(R.menu.card_view_menu, menu);
// Always calculate lockscreen icon, it may need a black color
boolean lockBarcodeScreenOrientation = settings.getLockBarcodeScreenOrientation();
MenuItem item = menu.findItem(R.id.action_lock_unlock);
setOrientatonLock(item, lockBarcodeScreenOrientation);
if(lockBarcodeScreenOrientation)
{
getMenuInflater().inflate(R.menu.card_view_menu, menu);
}
else if(updateLoyaltyCard)
{
getMenuInflater().inflate(R.menu.card_update_menu, menu);
}
else
{
getMenuInflater().inflate(R.menu.card_add_menu, menu);
item.setVisible(false);
}
rotationEnabled = true;
menu.findItem(R.id.action_share).setIcon(getIcon(R.drawable.ic_share_white, backgroundNeedsDarkIcons));
menu.findItem(R.id.action_edit).setIcon(getIcon(R.drawable.ic_mode_edit_white_24dp, backgroundNeedsDarkIcons));
return super.onCreateOptionsMenu(menu);
}
@@ -353,40 +410,12 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
finish();
break;
case R.id.action_delete:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.deleteTitle);
builder.setMessage(R.string.deleteConfirmation);
builder.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Log.e(TAG, "Deleting card: " + loyaltyCardId);
DBHelper db = new DBHelper(LoyaltyCardViewActivity.this);
db.deleteLoyaltyCard(loyaltyCardId);
ShortcutHelper.removeShortcut(LoyaltyCardViewActivity.this, loyaltyCardId);
finish();
dialog.dismiss();
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
case R.id.action_share:
importURIHelper.startShareIntent(loyaltyCard);
return true;
case R.id.action_edit:
Intent intent = new Intent(getApplicationContext(), LoyaltyCardViewActivity.class);
Intent intent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("id", loyaltyCardId);
bundle.putBoolean("update", true);
@@ -398,62 +427,150 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
case R.id.action_lock_unlock:
if(rotationEnabled)
{
item.setIcon(R.drawable.ic_lock_outline_white_24dp);
item.setTitle(R.string.unlockScreen);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
setOrientatonLock(item, true);
}
else
{
item.setIcon(R.drawable.ic_lock_open_white_24dp);
item.setTitle(R.string.lockScreen);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
setOrientatonLock(item, false);
}
rotationEnabled = !rotationEnabled;
return true;
case R.id.action_save:
doSave();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
private void setOrientatonLock(MenuItem item, boolean lock)
{
String contents = null;
String format = null;
IntentResult result =
IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (result != null)
if(lock)
{
Log.i(TAG, "Received barcode information from capture");
contents = result.getContents();
format = result.getFormatName();
item.setIcon(getIcon(R.drawable.ic_lock_outline_white_24dp, backgroundNeedsDarkIcons));
item.setTitle(R.string.unlockScreen);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}
if(requestCode == SELECT_BARCODE_REQUEST && resultCode == Activity.RESULT_OK)
else
{
Log.i(TAG, "Received barcode information from capture");
contents = intent.getStringExtra(BarcodeSelectorActivity.BARCODE_CONTENTS);
format = intent.getStringExtra(BarcodeSelectorActivity.BARCODE_FORMAT);
}
if(contents != null && contents.isEmpty() == false &&
format != null && format.isEmpty() == false)
{
Log.i(TAG, "Read barcode id: " + contents);
Log.i(TAG, "Read format: " + format);
TextView cardIdView = (TextView)findViewById(R.id.cardIdView);
cardIdView.setText(contents);
final TextView barcodeTypeField = (TextView) findViewById(R.id.barcodeType);
barcodeTypeField.setText(format);
onResume();
item.setIcon(getIcon(R.drawable.ic_lock_open_white_24dp, backgroundNeedsDarkIcons));
item.setTitle(R.string.lockScreen);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
}
}
// Gesture detection
@Override
public boolean onDown(MotionEvent motionEvent) {
return false;
}
@Override
public void onShowPress(MotionEvent motionEvent) {}
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
return false;
}
@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
return false;
}
@Override
public void onLongPress(MotionEvent motionEvent) { }
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
int currentTab = tabLayout.getSelectedTabPosition();
if (motionEvent1.getX() > motionEvent.getX())
{
// Swipe left
int nextTab = currentTab == 0 ? tabLayout.getTabCount() - 1 : currentTab - 1;
tabLayout.getTabAt(nextTab).select();
}
else
{
// Swipe right
int nextTab = currentTab < (tabLayout.getTabCount() - 1) ? currentTab + 1 : 0;
tabLayout.getTabAt(nextTab).select();
}
return true;
}
@Override
public boolean onTouchEvent(MotionEvent motionEvent)
{
gestureDetector.onTouchEvent(motionEvent);
return super.onTouchEvent(motionEvent);
}
/**
* When enabled, hides the status bar and moves the barcode to the top of the screen.
*
* The purpose of this function is to make sure the barcode can be scanned from the phone
* by machines which offer no space to insert the complete device.
*/
private void setFullscreen(boolean enable)
{
ActionBar actionBar = getSupportActionBar();
if(enable && !barcodeIsFullscreen)
{
// Save previous barcodeImage state
barcodeImageState = barcodeImage.getLayoutParams();
// Hide actionbar
if(actionBar != null)
{
actionBar.hide();
}
// Hide collapsingToolbar
collapsingToolbarLayout.setVisibility(View.GONE);
// Set Android to fullscreen mode
getWindow().getDecorView().setSystemUiVisibility(
getWindow().getDecorView().getSystemUiVisibility()
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_FULLSCREEN
);
// Make barcode take all space
barcodeImage.setLayoutParams(new ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.MATCH_PARENT,
ConstraintLayout.LayoutParams.MATCH_PARENT
));
// Move barcode to top
barcodeImage.setScaleType(ImageView.ScaleType.FIT_START);
// Set current state
barcodeIsFullscreen = true;
}
else if(!enable && barcodeIsFullscreen)
{
// Show actionbar
if(actionBar != null)
{
actionBar.show();
}
// Show collapsingToolbar
collapsingToolbarLayout.setVisibility(View.VISIBLE);
// Unset fullscreen mode
getWindow().getDecorView().setSystemUiVisibility(
getWindow().getDecorView().getSystemUiVisibility()
& ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
& ~View.SYSTEM_UI_FLAG_FULLSCREEN
);
// Turn barcode back to normal
barcodeImage.setLayoutParams(barcodeImageState);
// Set current state
barcodeIsFullscreen = false;
}
}
}

View File

@@ -1,17 +1,22 @@
package protect.card_locker;
import android.app.SearchManager;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ClipboardManager;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
@@ -24,26 +29,42 @@ import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.common.collect.ImmutableMap;
import java.util.Calendar;
import java.util.Map;
import protect.card_locker.intro.IntroActivity;
import protect.card_locker.preferences.SettingsActivity;
public class MainActivity extends AppCompatActivity
{
private static final String TAG = "LoyaltyCardLocker";
private static final int MAIN_REQUEST_CODE = 1;
private Menu menu;
private FloatingActionButton fabAdd;
protected String filter = "";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
updateLoyaltyCardList();
fabAdd = findViewById(R.id.fabAdd);
fabAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
startActivityForResult(i, MAIN_REQUEST_CODE);
}
});
updateLoyaltyCardList("");
SharedPreferences prefs = getSharedPreferences("protect.card_locker", MODE_PRIVATE);
if (prefs.getBoolean("firstrun", true)) {
@@ -53,31 +74,89 @@ public class MainActivity extends AppCompatActivity
}
@Override
protected void onResume()
{
protected void onResume() {
super.onResume();
updateLoyaltyCardList();
if (menu != null)
{
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
if (!searchView.isIconified()) {
filter = searchView.getQuery().toString();
}
}
updateLoyaltyCardList(filter);
}
private void updateLoyaltyCardList()
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == MAIN_REQUEST_CODE)
{
// We're coming back from another view so clear the search
// We only do this now to prevent a flash of all entries right after picking one
filter = "";
if (menu != null)
{
MenuItem searchItem = menu.findItem(R.id.action_search);
searchItem.collapseActionView();
}
// In case the theme changed
recreate();
}
}
@Override
public void onBackPressed() {
if (menu == null)
{
super.onBackPressed();
return;
}
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
if (!searchView.isIconified()) {
searchView.setIconified(true);
} else {
super.onBackPressed();
}
}
private void updateLoyaltyCardList(String filterText)
{
final ListView cardList = (ListView) findViewById(R.id.list);
final TextView helpText = (TextView) findViewById(R.id.helpText);
final ListView cardList = findViewById(R.id.list);
final TextView helpText = findViewById(R.id.helpText);
final TextView noMatchingCardsText = findViewById(R.id.noMatchingCardsText);
final DBHelper db = new DBHelper(this);
if(db.getLoyaltyCardCount() > 0)
{
// We want the cardList to be visible regardless of the filtered match count
// to ensure that the noMatchingCardsText doesn't end up being shown below
// the keyboard
cardList.setVisibility(View.VISIBLE);
helpText.setVisibility(View.GONE);
if(db.getLoyaltyCardCount(filterText) > 0)
{
noMatchingCardsText.setVisibility(View.GONE);
}
else
{
noMatchingCardsText.setVisibility(View.VISIBLE);
}
}
else
{
cardList.setVisibility(View.GONE);
helpText.setVisibility(View.VISIBLE);
noMatchingCardsText.setVisibility(View.GONE);
}
Cursor cardCursor = db.getLoyaltyCardCursor();
Cursor cardCursor = db.getOneLoyaltyCardPerStoreCursor(filterText);
final LoyaltyCardCursorAdapter adapter = new LoyaltyCardCursorAdapter(this, cardCursor);
cardList.setAdapter(adapter);
@@ -96,12 +175,11 @@ public class MainActivity extends AppCompatActivity
i.setAction("");
final Bundle b = new Bundle();
b.putInt("id", loyaltyCard.id);
b.putBoolean("view", true);
i.putExtras(b);
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard, i);
startActivity(i);
startActivityForResult(i, MAIN_REQUEST_CODE);
}
});
}
@@ -121,19 +199,28 @@ public class MainActivity extends AppCompatActivity
public boolean onContextItemSelected(MenuItem item)
{
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
ListView listView = (ListView) findViewById(R.id.list);
ListView listView = findViewById(R.id.list);
Cursor cardCursor = (Cursor)listView.getItemAtPosition(info.position);
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor);
if(card != null && item.getItemId() == R.id.action_clipboard)
if(card != null)
{
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(card.store, card.cardId);
clipboard.setPrimaryClip(clip);
if(item.getItemId() == R.id.action_clipboard)
{
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(card.store, card.cardId);
clipboard.setPrimaryClip(clip);
Toast.makeText(this, R.string.copy_to_clipboard_toast, Toast.LENGTH_LONG).show();
return true;
Toast.makeText(this, R.string.copy_to_clipboard_toast, Toast.LENGTH_LONG).show();
return true;
}
else if(item.getItemId() == R.id.action_share)
{
final ImportURIHelper importURIHelper = new ImportURIHelper(this);
importURIHelper.startShareIntent(card);
return true;
}
}
return super.onContextItemSelected(item);
@@ -142,7 +229,39 @@ public class MainActivity extends AppCompatActivity
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
this.menu = menu;
getMenuInflater().inflate(R.menu.main_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null) {
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(false);
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
invalidateOptionsMenu();
return false;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filter = newText;
updateLoyaltyCardList(newText);
return true;
}
});
}
return super.onCreateOptionsMenu(menu);
}
@@ -151,17 +270,17 @@ public class MainActivity extends AppCompatActivity
{
int id = item.getItemId();
if (id == R.id.action_add)
{
Intent i = new Intent(getApplicationContext(), LoyaltyCardViewActivity.class);
startActivity(i);
return true;
}
if(id == R.id.action_import_export)
{
Intent i = new Intent(getApplicationContext(), ImportExportActivity.class);
startActivity(i);
startActivityForResult(i, MAIN_REQUEST_CODE);
return true;
}
if(id == R.id.action_settings)
{
Intent i = new Intent(getApplicationContext(), SettingsActivity.class);
startActivityForResult(i, MAIN_REQUEST_CODE);
return true;
}
@@ -182,14 +301,15 @@ public class MainActivity extends AppCompatActivity
private void displayAboutDialog()
{
final Map<String, String> USED_LIBRARIES = ImmutableMap.of
(
"Commons CSV", "https://commons.apache.org/proper/commons-csv/",
"Guava", "https://github.com/google/guava",
"ZXing", "https://github.com/zxing/zxing",
"ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded",
"AppIntro", "https://github.com/apl-devs/AppIntro"
);
final Map<String, String> USED_LIBRARIES = new ImmutableMap.Builder<String, String>()
.put("Commons CSV", "https://commons.apache.org/proper/commons-csv/")
.put("Guava", "https://github.com/google/guava")
.put("ZXing", "https://github.com/zxing/zxing")
.put("ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded")
.put("AppIntro", "https://github.com/apl-devs/AppIntro")
.put("Color Picker", "https://github.com/jaredrummler/ColorPicker")
.put("VNTNumberPickerPreference", "https://github.com/vanniktech/VNTNumberPickerPreference")
.build();
final Map<String, String> USED_ASSETS = ImmutableMap.of
(
@@ -225,8 +345,19 @@ public class MainActivity extends AppCompatActivity
}
WebView wv = new WebView(this);
// Set CSS for dark mode if dark mode
String css = "";
Configuration config = getResources().getConfiguration();
int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
if(currentNightMode == Configuration.UI_MODE_NIGHT_YES)
{
css = "<style>body {color:white; background-color:black;}</style>";
}
String html =
"<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />" +
css +
"<img src=\"file:///android_res/mipmap/ic_launcher.png\" alt=\"" + appName + "\"/>" +
"<h1>" +
String.format(getString(R.string.about_title_fmt),
@@ -268,6 +399,6 @@ public class MainActivity extends AppCompatActivity
private void startIntro()
{
Intent intent = new Intent(this, IntroActivity.class);
startActivity(intent);
startActivityForResult(intent, MAIN_REQUEST_CODE);
}
}

View File

@@ -1,7 +1,7 @@
package protect.card_locker.intro;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import com.github.paolorotolo.appintro.AppIntro;

View File

@@ -1,7 +1,7 @@
package protect.card_locker.intro;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@@ -1,7 +1,7 @@
package protect.card_locker.intro;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@@ -1,7 +1,7 @@
package protect.card_locker.intro;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@@ -1,7 +1,7 @@
package protect.card_locker.intro;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@@ -1,7 +1,7 @@
package protect.card_locker.intro;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@@ -1,7 +1,7 @@
package protect.card_locker.intro;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@@ -0,0 +1,98 @@
package protect.card_locker.preferences;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import androidx.annotation.IntegerRes;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatDelegate;
import protect.card_locker.R;
public class Settings
{
private Context context;
private SharedPreferences settings;
public Settings(Context context)
{
this.context = context;
this.settings = PreferenceManager.getDefaultSharedPreferences(context);
}
private String getResString(@StringRes int resId)
{
return context.getString(resId);
}
private int getResInt(@IntegerRes int resId)
{
return context.getResources().getInteger(resId);
}
private String getString(@StringRes int keyId, String defaultValue)
{
return settings.getString(getResString(keyId), defaultValue);
}
private int getInt(@StringRes int keyId, @IntegerRes int defaultId)
{
return settings.getInt(getResString(keyId), getResInt(defaultId));
}
private boolean getBoolean(@StringRes int keyId, boolean defaultValue)
{
return settings.getBoolean(getResString(keyId), defaultValue);
}
public int getTheme()
{
String value = getString(R.string.settings_key_theme, getResString(R.string.settings_key_system_theme));
if(value.equals(getResString(R.string.settings_key_light_theme)))
{
return AppCompatDelegate.MODE_NIGHT_NO;
}
else if(value.equals(getResString(R.string.settings_key_dark_theme)))
{
return AppCompatDelegate.MODE_NIGHT_YES;
}
return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
}
public int getCardTitleListFontSize()
{
return getInt(R.string.settings_key_card_title_list_font_size, R.integer.settings_card_title_list_font_size_sp);
}
public int getCardNoteListFontSize()
{
return getInt(R.string.settings_key_card_note_list_font_size, R.integer.settings_card_note_list_font_size_sp);
}
public int getCardTitleFontSize()
{
return getInt(R.string.settings_key_card_title_font_size, R.integer.settings_card_title_font_size_sp);
}
public int getCardIdFontSize()
{
return getInt(R.string.settings_key_card_id_font_size, R.integer.settings_card_id_font_size_sp);
}
public int getCardNoteFontSize()
{
return getInt(R.string.settings_key_card_note_font_size, R.integer.settings_card_note_font_size_sp);
}
public boolean useMaxBrightnessDisplayingBarcode()
{
return getBoolean(R.string.settings_key_display_barcode_max_brightness, true);
}
public boolean getLockBarcodeScreenOrientation()
{
return getBoolean(R.string.settings_key_lock_barcode_orientation, false);
}
}

View File

@@ -0,0 +1,81 @@
package protect.card_locker.preferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import android.view.MenuItem;
import protect.card_locker.R;
public class SettingsActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
{
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if(id == android.R.id.home)
{
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
public static class SettingsFragment extends PreferenceFragment
{
@Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
findPreference(getResources().getString(R.string.settings_key_theme)).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);
}
getActivity().recreate();
return true;
}
});
}
}
}

BIN
app/src/main/res/drawable-hdpi/app_icon_intro.png Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

BIN
app/src/main/res/drawable-mdpi/app_icon_intro.png Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

BIN
app/src/main/res/drawable-xhdpi/app_icon_intro.png Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 758 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

BIN
app/src/main/res/drawable-xxhdpi/app_icon_intro.png Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 75 KiB

BIN
app/src/main/res/drawable-xxxhdpi/app_icon_intro.png Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
<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" />
</android.support.design.widget.AppBarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="fill_parent"
@@ -64,6 +64,12 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/barcodesLayout"/>
<Button
android:id="@+id/noBarcode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/barcodeNoBarcode"
android:enabled="false" />
<LinearLayout android:orientation="horizontal"
android:padding="10.0dp"
android:layout_width="fill_parent"
@@ -198,8 +204,4 @@
</LinearLayout>
</LinearLayout>
</ScrollView>
</android.support.design.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -17,6 +17,14 @@
android:text="@string/noGiftCards"
android:visibility="gone"/>
<TextView
style="@style/AppTheme.TextView.NoData"
android:id="@+id/noMatchingCardsText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/noMatchingGiftCards"
android:visibility="gone"/>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
<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" />
</android.support.design.widget.AppBarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
@@ -163,4 +163,4 @@
</ScrollView>
</android.support.design.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,28 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:src="@drawable/save_24dp"
android:contentDescription="@string/save"
android:layout_margin="16dp" />
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
<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" />
</android.support.design.widget.AppBarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/inputContrastBackground"
app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior">
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -61,7 +70,8 @@
android:layout_width="wrap_content"
android:textSize="@dimen/inputSize"
android:padding="@dimen/inputPadding"
android:layout_alignParentStart="true"/>
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"/>
<EditText
android:id="@+id/storeNameEdit"
@@ -70,16 +80,10 @@
android:layout_width="match_parent"
android:padding="@dimen/inputPadding"
android:textSize="@dimen/inputSize"
android:layout_toEndOf="@id/storeNameField"/>
android:layout_toEndOf="@id/storeNameField"
android:layout_toRightOf="@id/storeNameField"
/>
<TextView
android:id="@+id/storeNameView"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:padding="@dimen/inputPadding"
android:textSize="@dimen/inputSize"
android:textIsSelectable="true"
android:layout_toEndOf="@id/storeNameField"/>
</RelativeLayout>
<View
@@ -118,26 +122,165 @@
android:layout_width="wrap_content"
android:textSize="@dimen/inputSize"
android:padding="@dimen/inputPadding"
android:layout_alignParentStart="true"/>
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
/>
<EditText
android:id="@+id/noteEdit"
android:inputType="textCapSentences"
android:inputType="textMultiLine"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:padding="@dimen/inputPadding"
android:textSize="@dimen/inputSize"
android:layout_toEndOf="@id/noteField"/>
android:layout_toEndOf="@id/noteField"
android:layout_toRightOf="@id/noteField"
/>
</RelativeLayout>
<View
android:gravity="end"
android:layout_height="match_parent"
android:layout_width="@dimen/inputBorderThickness"
android:background="@color/inputBorder" />
</TableRow>
<!-- Store Header Background Color -->
<View
android:layout_height="@dimen/inputBorderThickness"
android:layout_width="match_parent"
android:background="@color/inputBorder" />
<TableRow
android:background="@color/inputBackground"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:gravity="start"
android:layout_height="match_parent"
android:layout_width="@dimen/inputBorderThickness"
android:background="@color/inputBorder" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingRight="@dimen/inputPadding"
android:paddingEnd="@dimen/inputPadding">
<TextView
android:id="@+id/noteView"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:padding="@dimen/inputPadding"
android:id="@+id/headingField"
android:text="@string/storeTextBackgroundColorTitle"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:textSize="@dimen/inputSize"
android:textIsSelectable="true"
android:layout_toEndOf="@id/noteField"/>
</RelativeLayout>
android:padding="@dimen/inputPadding"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/headingColorSampleBorder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="@dimen/colorSamplePadding"
app:layout_constraintStart_toEndOf="@id/headingField"
app:layout_constraintEnd_toStartOf="@+id/headingColorSelectButton"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@android:color/black">
<ImageView
android:id="@+id/headingColorSample"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="1dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@android:color/white"
android:contentDescription="@string/storeNameBackgroundColorDescription"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="@+id/headingColorSelectButton"
android:text="@string/change"
android:padding="@dimen/inputPadding"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toEndOf="@id/headingColorSampleBorder"
android:layout_toRightOf="@id/headingColorSampleBorder"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:gravity="end"
android:layout_height="match_parent"
android:layout_width="@dimen/inputBorderThickness"
android:background="@color/inputBorder" />
</TableRow>
<!-- Store Text Color -->
<View
android:layout_height="@dimen/inputBorderThickness"
android:layout_width="match_parent"
android:background="@color/inputBorder" />
<TableRow
android:background="@color/inputBackground"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:gravity="start"
android:layout_height="match_parent"
android:layout_width="@dimen/inputBorderThickness"
android:background="@color/inputBorder" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingRight="@dimen/inputPadding"
android:paddingEnd="@dimen/inputPadding">
<TextView
android:id="@+id/storeTextField"
android:text="@string/storeTextColorTitle"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:textSize="@dimen/inputSize"
android:padding="@dimen/inputPadding"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/headingStoreTextColorSampleBorder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="@dimen/colorSamplePadding"
app:layout_constraintStart_toEndOf="@id/storeTextField"
app:layout_constraintEnd_toStartOf="@+id/headingStoreTextColorSelectButton"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@android:color/black">
<ImageView
android:id="@+id/headingStoreTextColorSample"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="1dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@android:color/white"
android:contentDescription="@string/storeNameColorDescription"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="@+id/headingStoreTextColorSelectButton"
android:text="@string/change"
android:padding="@dimen/inputPadding"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toEndOf="@id/headingStoreTextColorSampleBorder"
android:layout_toRightOf="@id/headingStoreTextColorSampleBorder"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:gravity="end"
@@ -178,7 +321,9 @@
android:layout_width="wrap_content"
android:textSize="@dimen/inputSize"
android:padding="@dimen/inputPadding"
android:layout_alignParentStart="true"/>
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
/>
<TextView
android:id="@+id/cardIdView"
@@ -187,7 +332,9 @@
android:padding="@dimen/inputPadding"
android:textSize="@dimen/inputSize"
android:textIsSelectable="true"
android:layout_toEndOf="@id/cardIdField"/>
android:layout_toEndOf="@id/cardIdField"
android:layout_toRightOf="@id/cardIdField"
/>
</RelativeLayout>
<View
@@ -217,6 +364,8 @@
android:layout_width="0dp"
android:layout_height="@dimen/barcode_disp_height"
android:layout_gravity="center_horizontal"
android:padding="10.0dp"
android:background="#ffffff"
android:id="@+id/barcode"
android:contentDescription="@string/barcodeImageDescription"
android:layout_weight="1.0"/>
@@ -224,7 +373,8 @@
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:background="@color/inputBackground">
<LinearLayout android:orientation="horizontal"
android:padding="10.0dip"
@@ -248,4 +398,4 @@
</LinearLayout>
</ScrollView>
</android.support.design.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,32 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:orientation="vertical"
android:padding="10.0dp"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:orientation="horizontal"
android:padding="5.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:baselineAligned="true">
<TextView android:textSize="20.0sp"
android:id="@+id/store"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:maxLines="1"/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:baselineAligned="false"
android:padding="@dimen/activity_margin">
<ImageView
android:id="@+id/thumbnail"
android:layout_width="@dimen/cardThumbnailSize"
android:layout_height="@dimen/cardThumbnailSize"
android:layout_marginEnd="@dimen/activity_margin"
android:layout_marginRight="@dimen/activity_margin"
android:src="@mipmap/ic_launcher"
android:contentDescription="@string/thumbnailDescription"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:id="@+id/valueLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible">
<TextView
android:id="@+id/store"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/storeNameTextSize"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="@dimen/noteTextSize"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:padding="5.0dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:baselineAligned="true">
<TextView android:textSize="20.0sp"
android:layout_gravity="start"
android:id="@+id/cardId"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinator_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fitsSystemWindows="true"
>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:src="@drawable/ic_add_white_24dp"
android:contentDescription="@string/action_add"
android:layout_margin="16dp" />
<FrameLayout
android:clipChildren="false"
android:clipToPadding="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/centerGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5"/>
<ImageView
android:id="@+id/barcode"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="20.0dip"
android:layout_marginBottom="10.0dip"
android:layout_marginStart="15.0dip"
android:layout_marginEnd="15.0dip"
app:layout_constraintTop_toTopOf="parent"
android:padding="10.0dp"
android:background="#ffffff"
app:layout_constraintBottom_toTopOf="@+id/centerGuideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:contentDescription="@string/barcodeImageDescription"/>
<TextView
android:id="@+id/cardIdView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="10.0dip"
android:layout_marginRight="10.0dip"
app:layout_constraintTop_toBottomOf="@+id/barcode"
app:layout_constraintBottom_toTopOf="@+id/noteViewDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:textAlignment="center"
app:autoSizeTextType="uniform"
app:autoSizeMinTextSize="@dimen/singleCardCardIdTextSizeMin"
app:autoSizeMaxTextSize="@dimen/singleCardCardIdTextSizeMax"
android:ellipsize="end"
android:textIsSelectable="true"/>
<View
android:id="@id/noteViewDivider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/black"
app:layout_constraintTop_toBottomOf="@id/cardIdView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="@+id/noteView"
/>
<TextView
android:id="@id/noteView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10.0dip"
android:layout_gravity="bottom"
app:layout_constraintTop_toBottomOf="@id/noteViewDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:autoSizeTextType="uniform"
app:autoSizeMinTextSize="@dimen/singleCardNoteTextSizeMin"
app:autoSizeMaxTextSize="@dimen/singleCardNoteTextSizeMax"
android:textIsSelectable="true"
android:scrollbars="vertical"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:id="@+id/drop_shadow_actionbar"
android:layout_width="fill_parent"
android:layout_height="5.0dip"
android:layout_gravity="top"/>
</FrameLayout>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:background="@android:color/transparent"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="56.0dip"
android:layout_weight="1.0"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp"
app:contentScrim="?colorPrimary"
app:expandedTitleGravity="top">
<TextView
android:id="@+id/storeName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@android:color/white"
android:textSize="40sp"
android:textAlignment="center"
android:layout_gravity="center"
android:layout_marginTop="?actionBarSize"
android:layout_marginBottom="?actionBarSize"
app:layout_collapseMode="parallax"
android:fitsSystemWindows="true"/>
<androidx.appcompat.widget.Toolbar
android:id="@id/toolbar"
android:background="@android:color/transparent"
android:theme="@style/CardView.ActionBarTheme"
android:layout_width="fill_parent"
android:layout_height="?actionBarSize"
app:contentInsetStart="72.0dip"
app:layout_collapseMode="pin" />
<com.google.android.material.tabs.TabLayout
android:visibility="gone"
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:tabGravity="fill"
app:tabIndicatorAnimationDuration="0"
app:tabMode="scrollable"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
<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"
@@ -8,20 +8,29 @@
android:fitsSystemWindows="true"
tools:context="protect.card_locker.MainActivity">
<android.support.design.widget.AppBarLayout
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:src="@drawable/ic_add_white_24dp"
android:contentDescription="@string/action_add"
android:layout_margin="16dp" />
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
<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"/>
</android.support.design.widget.AppBarLayout>
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main"/>
</android.support.design.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_save"
android:icon="@drawable/save_24dp"
android:title="@string/save"
app:showAsAction="always"/>
</menu>

View File

@@ -6,4 +6,8 @@
android:id="@+id/action_clipboard"
android:title="@string/copy_to_clipboard"
app:showAsAction="always"/>
<item
android:id="@+id/action_share"
android:title="@string/share"
app:showAsAction="always"/>
</menu>

View File

@@ -2,15 +2,9 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_save"
android:icon="@drawable/save_24dp"
android:title="@string/save"
app:showAsAction="always"/>
<item
android:id="@+id/action_delete"
android:icon="@drawable/ic_delete_white_24dp"
android:title="@string/delete"
app:showAsAction="never"/>
app:showAsAction="always"/>
</menu>

View File

@@ -7,6 +7,11 @@
android:icon="@drawable/ic_lock_open_white_24dp"
android:title="@string/lockScreen"
app:showAsAction="always"/>
<item
android:id="@+id/action_share"
android:icon="@drawable/ic_share_white"
android:title="@string/share"
app:showAsAction="always"/>
<item
android:id="@+id/action_edit"
android:icon="@drawable/ic_mode_edit_white_24dp"

View File

@@ -3,15 +3,20 @@
xmlns:tools="http://schemas.android.com/tools"
tools:context="protect.card_locker.MainActivity">
<item
android:id="@+id/action_add"
android:icon="@drawable/ic_add_white_24dp"
android:title="@string/action_add"
app:showAsAction="always"/>
android:id="@+id/action_search"
android:title="@string/action_search"
android:icon="@drawable/ic_search_white"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="always|collapseActionView"/>
<item
android:id="@+id/action_import_export"
android:icon="@drawable/ic_import_export_white_24dp"
android:title="@string/importExport"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_settings"
android:title="@string/settings"
app:showAsAction="never"/>
<item
android:id="@+id/action_intro"
android:title="@string/startIntro"

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -5,68 +5,47 @@
<string name="action_add">Přidat</string>
<string name="noGiftCards">ZAtím némáte žádné věrnostní karty. Klikněte na tlačítko "+" (plus) nahoře a začněte.\n\nLoyalty Card Locker umožňuje nosit své věrnostní karty v telefonu, takže jsou vždy na dosah.</string>
<string name="storeName">Obchod</string>
<string name="note">Poznámka</string>
<string name="cardId">ID karty</string>
<string name="barcodeType">Typ čárového kódu</string>
<string name="cancel">Zrušit</string>
<string name="save">Uložit</string>
<string name="capture">Naskenovat kartu</string>
<string name="enterCard">Vložit vlastnoručně</string>
<string name="edit">Editovat</string>
<string name="delete">Smazat</string>
<string name="confirm">Potvrdit</string>
<string name="deleteTitle">Odstzranit věrnostní kartu</string>
<string name="deleteConfirmation">Opravdu chcete smazat tuto věrnostní kartu?</string>
<string name="ok">Ano</string>
<string name="copy_to_clipboard">Kopírovat ID do schránky</string>
<string name="sendLabel">Odeslat&#8230;</string>
<string name="editCardTitle">Editovat věrnostní kartu</string>
<string name="addCardTitle">Přidat věrnostní kartu</string>
<string name="viewCardTitle">Zobrazit věrnostní kartu</string>
<string name="scanCardBarcode">Oskenujte kód karty</string>
<string name="barcodeImageDescription">Obrázek kódu karty</string>
<string name="noStoreError">Nebyl zadán Obchod</string>
<string name="noCardIdError">Nebylo zadáno ID karty</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Import/Export</string>
<string name="importName">Import</string>
<string name="exportName">Export</string>
<string name="importExportHelp">Zálohování dat vám umožní přesunout vaše uložené karty na jiné zařízení.</string>
<string name="importedFrom">Importováno z: %1$s</string>
<string name="exportedTo">Exportováno do: %1$s</string>
<string name="fileMissing">Doubor chybí: %1$s</string>
<string name="importSuccessfulTitle">Import proběhl úspěšně</string>
<string name="importFailedTitle">Import selhal</string>
<string name="importFailed">Import selhal: %1$s</string>
<string name="exportSuccessfulTitle">Export proběhl úspěšně</string>
<string name="exportFailedTitle">Export selhal</string>
<string name="exportFailed">Export selhal: %1$s</string>
<string name="importing">Importuji&#8230;</string>
<string name="exporting">Exportuji&#8230;</string>
<string name="noExternalStoragePermissionError">Nelze importovat nebo exportovat karty bez přístupu k externímu uložišti</string>
<string name="about">O aplikaci</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Licensed under the GPLv3.</string>
<string name="about_title_fmt">O aplikaci <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Verze: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Revizní informace: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> používá tyto knihovny třetích stran: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Vyberte čárový kód</string>
<string name="enterBarcodeInstructions">Zadejte hodnotu čárového kódu a potm vyberte kód, který představuje čárový kód, který je na kartě.</string>
<string name="copy_to_clipboard_toast">ID karty zkopírováno do schránky</string>
<string name="importExportHelp">Zálohování dat vám umožní přesunout vaše uložené karty na jiné zařízení.</string>
<string name="importSuccessfulTitle">Import proběhl úspěšně</string>
<string name="importFailedTitle">Import selhal</string>
<string name="exportSuccessfulTitle">Export proběhl úspěšně</string>
<string name="exportFailedTitle">Export selhal</string>
<string name="exportOptionExplanation">Data jsou zapsána do kořenové složky externího uložiště.</string>
<string name="importOptionFilesystemTitle">Import ze souborového systému</string>
<string name="importOptionFilesystemExplanation">Vyberte konkrétní soubor v uložišti.</string>
@@ -77,6 +56,15 @@
<string name="importOptionFixedTitle">Import z umístění exportu</string>
<string name="importOptionFixedExplanation">Import ze stejné složky souborového systému do níž se zapisuje při exportu.</string>
<string name="importOptionFixedButton">Použít složku exportu</string>
<string name="sendLabel">Odeslat&#8230;</string>
</resources>
<string name="about">O aplikaci</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Licensed under the GPLv3.</string>
<string name="about_title_fmt">O aplikaci <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Verze: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Revizní informace: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> používá tyto knihovny třetích stran: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Vyberte čárový kód</string>
<string name="copy_to_clipboard_toast">ID karty zkopírováno do schránky</string>
</resources>

View File

@@ -1,73 +1,87 @@
<?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">
<string name="app_name">Loyalty Card Keychain</string>
<string name="about">Über</string>
<string name="about_title_fmt">Über <xliff:g id="app_name">%s</xliff:g></string>
<string name="action_search">Suche</string>
<string name="action_add">Neu</string>
<string name="addCardTitle">Neue Kundenkarte</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Lizensiert unter der GPLv3.</string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> benutzt die folgenden Fremdbibliotheken: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> verwendet folgenden Dritt-Ressourcen: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="viewCardTitle">Kundenkarte anzeigen</string>
<string name="ok">Ok</string>
<string name="note">Notiz</string>
<string name="save">Speichern</string>
<string name="scanCardBarcode">Barcode scannen</string>
<string name="selectBarcodeTitle">Barcode auswählen</string>
<string name="noGiftCards">Sie haben noch keine Kundenkarte angelegt. Über den \"+\"-Button oben rechts können welche angelegt werden.\n\nDiese App ermöglicht es, Kundenkarten immer mit zu führen.</string>
<string name="noMatchingGiftCards">Es passen keine Kundenkarten zum Suchfilter. Bitte probiere verschiedene Begriffe aus.</string>
<string name="storeName">Geschäft</string>
<string name="note">Notiz</string>
<string name="cardId">Kartennummer</string>
<string name="barcodeType">Barcodeart</string>
<string name="cancel">Abbrechen</string>
<string name="save">Speichern</string>
<string name="capture">Karte scannen</string>
<string name="enterCard">Manuell eingeben</string>
<string name="editCard">Karte bearbeiten</string>
<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="deleteTitle">Karte entfernen</string>
<string name="deleteConfirmation">Bitte bestätigen Sie, dass diese Karte gelöscht werden soll.</string>
<string name="ok">Ok</string>
<string name="copy_to_clipboard">Kopiere die Nummer in die Zwischenablage</string>
<string name="sendLabel">Senden&#8230;</string>
<string name="addedShortcut">Zum Home Screen hinzugefügt</string>
<string name="editCardTitle">Kundenkarte bearbeiten</string>
<string name="addCardTitle">Neue Kundenkarte</string>
<string name="viewCardTitle">Kundenkarte anzeigen</string>
<string name="scanCardBarcode">Barcode scannen</string>
<string name="cardShortcut">Shortcut zu einer Karte</string>
<string name="noCardsMessage">Es ist noch keine Karte vorhanden, bitte zuerst eine hinzufügen</string>
<string name="barcodeImageDescription">Bild des Barcodes</string>
<string name="noStoreError">Kein Geschäft angegeben</string>
<string name="noCardIdError">Keine Kartennummer angegeben</string>
<string name="noCardExistsError">Karte konnte nicht gefunden werden</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Import/Export</string>
<string name="importName">Import</string>
<string name="exportName">Exportieren</string>
<string name="importExportHelp">Gesicherte Daten ermöglichen das Verschieben der Kundenkarten auf ein anderes Gerät.</string>
<string name="importedFrom">Importiert von: %1$s</string>
<string name="exportedTo">Exportiert nach: %1$s</string>
<string name="fileMissing">Datei fehlt: %1$s</string>
<string name="importExport">Import/Export</string>
<string name="importFailed">Import fehlgeschlagen: %1$s</string>
<string name="importName">Import</string>
<string name="importedFrom">Importiert von: %1$s</string>
<string name="noCardIdError">Keine Kartennummer angegeben</string>
<string name="noExternalStoragePermissionError">Ohne die Berechtigung für den externen Speicher kann kein Import oder Export erfolgen.</string>
<string name="noGiftCards">Sie haben noch keine Kundenkarte angelegt. Über den "+" Button oben rechts, können welche angelegt werden.\n\nDiese App ermöglicht es, Kundenkarten immer mit zu führen.</string>
<string name="cancel">Abbrechen</string>
<string name="capture">Karte erfassen</string>
<string name="cardId">Kartennummer</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="confirm">Bestätigen</string>
<string name="copy_to_clipboard">Kopiere die Nummer in die Zwischenablage</string>
<string name="delete">Löschen</string>
<string name="deleteConfirmation">Bitte bestätigen Sie, dass diese Karte gelöscht werden soll.</string>
<string name="edit">Bearbeiten</string>
<string name="editCardTitle">Kundenkarte bearbeiten</string>
<string name="enterCard">Karte einfügen</string>
<string name="editCard">Karte bearbeiten</string>
<string name="exportFailed">Export fehlgeschlagen: %1$s</string>
<string name="barcodeType">Barcodeart</string>
<string name="barcodeImageDescription">Bild des Barcodes</string>
<string name="copy_to_clipboard_toast">Nummer in die Zwischenablage kopiert</string>
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
<string name="enterBarcodeInstructions">Fügen Sie die Kundennummer ein, anschließend wählen Sie die korrekte Barcodeart aus.</string>
<string name="app_revision_fmt">Versions Information: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="importing">Importiere…</string>
<string name="exporting">Exportiere…</string>
<string name="importExportHelp">Gesicherte Daten ermöglichen das Verschieben der Kundenkarten auf ein anderes Gerät.</string>
<string name="importSuccessfulTitle">Import erfolgreich</string>
<string name="importFailedTitle">Import fehlgeschlagen</string>
<string name="importFailed">Import fehlgeschlagen: %1$s</string>
<string name="exportSuccessfulTitle">Export erfolgreich</string>
<string name="exportFailedTitle">Export fehlgeschlagen</string>
<string name="exportFailed">Export fehlgeschlagen: %1$s</string>
<string name="importing">Importiere…</string>
<string name="exporting">Exportiere…</string>
<string name="noExternalStoragePermissionError">Ohne die Berechtigung für den externen Speicher kann kein Import oder Export erfolgen.</string>
<string name="exportOptionExplanation">Die Datei wird ins Rootverzeichnis des externen Speichers geschrieben.</string>
<string name="importOptionFilesystemTitle">Importiere vom Dateisystem</string>
<string name="importOptionFilesystemExplanation">Wähle eine Datei im Speicher aus.</string>
<string name="importOptionFilesystemButton">Vom Dateisystem</string>
<string name="importOptionApplicationTitle">Nutze eine externe App</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">Externe App verwenden</string>
<string name="importOptionApplicationExplanation">Wählen Sie eine Datei aus einer App wie Dropbox, Google Drive, oder Ihrem bevorzugten Dateisystem aus.</string>
<string name="importOptionApplicationButton">Nutze eine externe App</string>
<string name="importOptionFixedTitle">Importiere vom Export-Pfad</string>
<string name="importOptionFixedExplanation">Importiere vom Export-Pfad.</string>
<string name="importOptionFixedButton">Verwende den Export-Pfad.</string>
<string name="sendLabel">Senden&#8230;</string>
<string name="importOptionFixedTitle">Importiere aus Export-Pfad</string>
<string name="importOptionFixedExplanation">Nutze den Export-Pfad, um Karten zu importieren (dies stellt zuvor gesicherte Daten wieder her).</string>
<string name="importOptionFixedButton">Export-Pfad verwenden</string>
<string name="about">Über</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">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="app_libraries"><xliff:g id="app_name">%s</xliff:g> benutzt die folgenden Fremdbibliotheken: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> verwendet folgenden Dritt-Ressourcen: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Barcode auswählen</string>
<string name="copy_to_clipboard_toast">Nummer in die Zwischenablage kopiert</string>
<string name="thumbnailDescription">Vorschaubild für die Karte</string>
<string name="startIntro">Starte Einführung</string>
<string name="intro1Title">Willkommen zu Loyalty Card Keychain\n</string>
@@ -82,4 +96,20 @@
<string name="intro5Description">Sie können selbstverständlich Backups anlegen. Um Karten zu exportieren oder importieren wählen Sie Import/Export im Menü auf dem Hauptbildschirm.\n\n</string>
<string name="intro6Title">Feedback\n</string>
<string name="intro6Description">Diese App enthält keine Werbung, und ist freie und quelloffene Software. Für Details berühren Sie Über im Menü auf der Hauptseite.\n\nHinterlassen Sie uns ein Feedback im App-Store (:</string>
</resources>
<string name="change">Anpassen</string>
<string name="storeTextColorTitle">Textfarbe</string>
<string name="storeTextBackgroundColorTitle">Hintergrundfarbe</string>
<string name="storeNameBackgroundColorDescription">Hintergrundfarbe für den Geschäftsnamen</string>
<string name="storeNameColorDescription">Farbe für den Geschäftsnamen</string>
<string name="settings">Einstellungen</string>
<string name="settings_category_title_ui">Benutzeroberfläche</string>
<string name="settings_card_title_list_font_size">Schriftgröße des Titels in der Listenansicht</string>
<string name="settings_card_note_list_font_size">Schriftgröße der Notiz in der Listenansicht</string>
<string name="settings_card_title_font_size">Schriftgröße des Titels</string>
<string name="settings_card_id_font_size">Schriftgröße der Kartennummer</string>
<string name="settings_card_note_font_size">Schriftgröße der Notiz</string>
<string name="settings_display_barcode_max_brightness">Helligkeit bei Barcode Ansicht erhöhen</string>
<string name="settings_lock_barcode_orientation">Barcodeausrichtung sperren</string>
</resources>

View File

@@ -0,0 +1,110 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Loyalty Card Keychain</string>
<string name="action_add">Προσθήκη</string>
<string name="noGiftCards">Δεν έχετε κάρτες προς το παρόν. Πατήστε το κουμπί \"+\" (συν) στο πάνω μέρος για να ξεκινήσετε.\n\nΤο Loyalty Card Keychain σας δίνει τη δυνατότητα να έχετε τις κάρτες σας στο τηλέφωνο σας, έτσι ώστε να τις έχετε πάντα μαζί σας.</string>
<string name="storeName">Κατάστημα</string>
<string name="note">Σημείωση</string>
<string name="cardId">Κωδικός Κάρτας</string>
<string name="barcodeType">Τύπος Barcode</string>
<string name="cancel">Άκυρο</string>
<string name="save">Αποθήκευση</string>
<string name="capture">Φωτογράφιση Κάρτας</string>
<string name="enterCard">Εισάγετε Κάρτα</string>
<string name="editCard">Επεξεργασία Κάρτας</string>
<string name="edit">Επεξεργασία</string>
<string name="delete">Διαγραφή</string>
<string name="confirm">Επιβεβαίωση</string>
<string name="lockScreen">Αποκλεισμός Περιστροφής</string>
<string name="unlockScreen">Περιστροφή</string>
<string name="deleteTitle">Αφαίρεση Κάρτας</string>
<string name="deleteConfirmation">Παρακαλώ επιβεβαιώστε ότι θέλετε να διαγράψετε αυτή την κάρτα.</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Αντιγραφή κωδικού στο πρόχειρο</string>
<string name="sendLabel">Αποστολή&#8230;</string>
<string name="addedShortcut">Προστέθηκε στην Αρχική Οθόνη</string>
<string name="editCardTitle">Επεξεργασία Κάρτας</string>
<string name="addCardTitle">Προσθήκη Κάρτας</string>
<string name="viewCardTitle">Εμφάνιση Κάρτας</string>
<string name="scanCardBarcode">Σαρώστε τον κωδικό της κάρτας</string>
<string name="cardShortcut">Συντόμευση Κάρτας</string>
<string name="noCardsMessage">Δεν υπάρχουν κάρτες. προσθέστε μία πρώτα</string>
<string name="barcodeImageDescription">Εικόνα του barcode της κάρτας</string>
<string name="noStoreError">Δεν δώσατε κατάστημα</string>
<string name="noCardIdError">Δεν δώσατε κωδικό κάρτας</string>
<string name="noCardExistsError">Δεν ήταν δυνατό να εντοπιστεί κάρτα</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Εισαγωγή/Εξαγωγή</string>
<string name="importName">Εισαγωγή</string>
<string name="exportName">Εξαγωγή</string>
<string name="importExportHelp">Τα εφεδρικά δεδομένα σας δίνουν την δυνατότητα να μεταφέρετε τις κάρτες σας σε μία άλλη συσκευή.</string>
<string name="importedFrom">Εισαγωγή από: %1$s</string>
<string name="exportedTo">Εξαγωγή σε: %1$s</string>
<string name="fileMissing">Το αρχείο λείπει: %1$s</string>
<string name="importSuccessfulTitle">Εισαγωγή επιτυχής</string>
<string name="importFailedTitle">Εισαγωγή ανεπιτυχής</string>
<string name="importFailed">Δεν εισήχθει: %1$s</string>
<string name="exportSuccessfulTitle">Εξαγωγή επιτυχής</string>
<string name="exportFailedTitle">Εξαγωγή ανεπιτυχής</string>
<string name="exportFailed">Δεν εξήχθη: %1$s</string>
<string name="importing">Γίνεται εισαγωγή του&#8230;</string>
<string name="exporting">Γίνεται εξαγωγή του&#8230;</string>
<string name="noExternalStoragePermissionError">Δεν είναι δυνατή η εισαγωγή ή εξαγωγή καρτών χωρίς την άδεια πρόσβασης στον εξωτερικό χώρο αποθήκευσης</string>
<string name="exportOptionExplanation">Τα δεδομένα αποθηκεύονται στον αρχικό φάκελο του εξωτερικού χώρου αποθήκευσης.</string>
<string name="importOptionFilesystemTitle">Εισαγωγή από το σύστημα αρχείων</string>
<string name="importOptionFilesystemExplanation">Επιλέξτε ένα συγκεκριμένο αρχείο από το σύστημα αρχείων.</string>
<string name="importOptionFilesystemButton">Από το σύστημα αρχείων</string>
<string name="importOptionApplicationTitle">Χρήση εξωτερικής εφαρμογής</string>
<string name="importOptionApplicationExplanation">Κάντε χρήση μίας εξωτερικής εφαρμογής όπως είναι τα Dropbox, Google Drive ή ο αγαπημένος σας διαχειριστής αρχείων για να ανοίξετε ένα αρχείο.</string>
<string name="importOptionApplicationButton">Χρήση εξωτερικής εφαρμογής</string>
<string name="importOptionFixedTitle">Εισαγωγή από τοποθεσία εξαγωγής</string>
<string name="importOptionFixedExplanation">Εισαγωγή από την ίδια τοποθεσία στο σύστημα αρχείων, στην οποία γίνεται αποθήκευση κατά την εξαγωγή.</string>
<string name="importOptionFixedButton">Χρήση τοποθεσίας εξαγωγής</string>
<string name="about">Σχετικά</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Άδεια χρήσης υπό το GPLv3.</string>
<string name="about_title_fmt">Σχετικά με <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Έκδοση: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Πληροφορίες Αναθεώρησης: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries">Το <xliff:g id="app_name">%s</xliff:g> χρησιμοποιεί τις ακόλουθες βιβλιοθήκες τρίτων: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources">Το <xliff:g id="app_name">%s</xliff:g> χρησιμοποιεί τους παρακάτω πόρους τρίτων: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Επιλέξτε Barcode</string>
<string name="copy_to_clipboard_toast">Ο κωδικός της κάρτας αντιγράφτηκε στο πρόχειρο</string>
<string name="thumbnailDescription">Μικρογραφία κάρτας</string>
<string name="startIntro">Έναρξη Επεξήγησης</string>
<string name="intro1Title">Καλώς ήλθατε στο Loyalty Card Keychain\n</string>
<string name="intro1Description">Διαχειριστείτε τις κάρτες σας που βασίζονται σε barcodes μέσα από το κινητό σας!\n\n</string>
<string name="intro2Title">Προσθήκη Καρτών\n</string>
<string name="intro2Description">Προσθέστε μία νέα κάρτα πατώντας το συν από την λίστα καρτών.\n\n</string>
<string name="intro3Title">Προσθήκη Καρτών\n</string>
<string name="intro3Description">Για να προσθέσετε το barcode, είτε φωτογραφίστε με την κάμερα είτε γράψτε το χειροκίνητα.\n\n</string>
<string name="intro4Title">Εμφάνιση Κάρτας\n</string>
<string name="intro4Description">Για να εμφανίσετε μία κάρτα, πατήστε πάνω στο όνομα του καταστήματος, στην κεντρική οθόνη της εφαρμογής\n\n</string>
<string name="intro5Title">Αντίγραφα Ασφαλείας\n</string>
<string name="intro5Description">Μπορείτε να δημιουργήσετε αντίγραφα ασφαλείας των καρτών. Για εξαγωγή ή εισαγωγή των δεδομένων των καρτών πατήστε Εισαγωγή/Εξαγωγή στο μενού στην κεντρική οθόνη της εφαρμογής.\n\n</string>
<string name="intro6Title">Σχόλια\n</string>
<string name="intro6Description">Αυτή η εφαρμογή είναι δωρεάν, χωρίς διαφημίσεις και open source. Δείτε λεπτομέρειες πατώντας το Σχετικά στο μενού στην κεντρική οθόνη της εφαρμογής.\n\nΠαρακαλώ αφήστε σχόλια στο app store! (:</string>
<string name="change">Αλλαγή</string>
<string name="storeTextColorTitle">Χρώμα Κειμένου Καταστήματος</string>
<string name="storeTextBackgroundColorTitle">Χρώμα Κεφαλίδας</string>
<string name="storeNameBackgroundColorDescription">Χρώμα για το υπόβαθρο του καταστήματος</string>
<string name="storeNameColorDescription">Χρώμα για το κείμενο του καταστήματος</string>
<string name="settings">Ρυθμίσεις</string>
<string name="settings_category_title_ui">Διεπαφή χρήστη</string>
<string name="settings_card_title_list_font_size">Μέγεθος κειμένου λίστας καρτών</string>
<string name="settings_card_note_list_font_size">Μέγεθος κειμένου λίστας σημειώσεων καρτών</string>
<string name="settings_card_title_font_size">Μέγεθος κειμένου τίτλου κάρτας</string>
<string name="settings_card_id_font_size">Μέγεθος κειμένου κωδικού κάρτας</string>
<string name="settings_card_note_font_size">Μέγεθος κειμένου σημείωσης κάρτας</string>
</resources>

View File

@@ -0,0 +1,4 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
</resources>

View File

@@ -0,0 +1,110 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Cartera para Tarjetas de Fidelización.</string>
<string name="action_add">Añadir</string>
<string name="noGiftCards">Actualmente no tienes ninguna tarjeta guardada. Presiona el botón \"+\" para comenzar.\n\nEsta cartera te permite llevar tus tarjetas de fidelización en tu teléfono para que estén siempre a tu alcance.</string>
<string name="storeName">Tienda</string>
<string name="note">Nota</string>
<string name="cardId">ID de la Tarjeta</string>
<string name="barcodeType">Tipo de Código de Barras</string>
<string name="cancel">Cancelar</string>
<string name="save">Guardar</string>
<string name="capture">Escanear Tarjeta</string>
<string name="enterCard">Introducir Tarjeta</string>
<string name="editCard">Editar Tarjeta</string>
<string name="edit">Editar</string>
<string name="delete">Eliminar</string>
<string name="confirm">Confirmar</string>
<string name="lockScreen">Bloquear Rotación de Pantalla</string>
<string name="unlockScreen">Rotación de Pantalla Automática</string>
<string name="deleteTitle">Eliminar Tarjeta de Fidelización</string>
<string name="deleteConfirmation">Por favor, confirma si quieres eliminar esta tarjeta.</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Copiar ID al portapapeles</string>
<string name="sendLabel">Enviar&#8230;</string>
<string name="addedShortcut">Añadido a la Pantalla de Inicio</string>
<string name="editCardTitle">Editar Tarjeta de Fidelización</string>
<string name="addCardTitle">Añadir Tarjeta de Fidelización</string>
<string name="viewCardTitle">Ver Tarjeta de Fidelización</string>
<string name="scanCardBarcode">Escanear el Código de Barras de la Tarjeta</string>
<string name="cardShortcut">Atajo de Tarjeta</string>
<string name="noCardsMessage">No hay ninguna tarjeta, añade una primero</string>
<string name="barcodeImageDescription">Imagen del código de barras de la tarjeta</string>
<string name="noStoreError">Establecimiento no especificado</string>
<string name="noCardIdError">ID de la Tarjeta no especificado</string>
<string name="noCardExistsError">No se ha podido encontrar la tarjeta de fidelización</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Importar/Exportar</string>
<string name="importName">Importar</string>
<string name="exportName">Exportar</string>
<string name="importExportHelp">La copia de seguridad te permite transferir tus tarjetas a otro dispositivo.</string>
<string name="importedFrom">Importar desde: %1$s</string>
<string name="exportedTo">Exportar a: %1$s</string>
<string name="fileMissing">Archivo perdido: %1$s</string>
<string name="importSuccessfulTitle">Datos importados correctamente</string>
<string name="importFailedTitle">Ha ocurrido un error al importar los datos</string>
<string name="importFailed">Error al importar: %1$s</string>
<string name="exportSuccessfulTitle">Datos exportados correctamente</string>
<string name="exportFailedTitle">Ha ocurrido un error al exportar los datos</string>
<string name="exportFailed">Error al exportar: %1$s</string>
<string name="importing">Importando&#8230;</string>
<string name="exporting">Exportando&#8230;</string>
<string name="noExternalStoragePermissionError">No se pueden importar o exportar tarjetas sin el permiso de almacenamiento</string>
<string name="exportOptionExplanation">Los datos son guardados en la carpeta base del almacenamiento externo.</string>
<string name="importOptionFilesystemTitle">Importar desde el sistema de archivos</string>
<string name="importOptionFilesystemExplanation">Seleccionar un archivo del sistema de archivos</string>
<string name="importOptionFilesystemButton">Desde el sistema de archivos</string>
<string name="importOptionApplicationTitle">Usar una applicación externa</string>
<string name="importOptionApplicationExplanation">Use una aplicación externa como Dropbox, Google Drive o tu gestor de archivos favoritos para abrir un archivo.</string>
<string name="importOptionApplicationButton">Usar aplicación externa</string>
<string name="importOptionFixedTitle">Importar desde el lugar donde los datos son exportados</string>
<string name="importOptionFixedExplanation">Importar desde el mismo lugar en el sistema de archivos donde los datos son exportados.</string>
<string name="importOptionFixedButton">Utilizar el lugar donde los datos son exportados</string>
<string name="about">Acerca de</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Licencia GPLv3</string>
<string name="about_title_fmt">Acerca de <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versión: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Información sobre la Revisión: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> utiliza las siguientes librerías de terceros: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> utiliza los siguientes recursos de terceros: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Selecciona el Código de Barras</string>
<string name="copy_to_clipboard_toast">ID de la Tarjeta copiado al portapapeles</string>
<string name="thumbnailDescription">Miniatura para la tarjeta</string>
<string name="startIntro">Empezar Introducción</string>
<string name="intro1Title">Bienvenido a la Cartera para Tarjetas de Fidelización\n</string>
<string name="intro1Description">Gestiona las tarjetas de fidelización o tarjetas cliente con codigo de barras desde tu teléfono!\n\n</string>
<string name="intro2Title">Añadir Tarjetas\n</string>
<string name="intro2Description">Añade una nueva tarjeta presionando el signo + en la lista de tarjetas.\n\n</string>
<string name="intro3Title">Añadir Tarjetas\n</string>
<string name="intro3Description">Para añadir el código de barras, escanea la tarjeta con tu cámara o introduce el código manualmente.\n\n</string>
<string name="intro4Title">Mostrar Tarjeta\n</string>
<string name="intro4Description">Para mostrar una tarjeta, presiona en el nombre de la tienda desde la pantalla principal\n\n</string>
<string name="intro5Title">Copias de Seguridad\n</string>
<string name="intro5Description">Puedes hacer una copia de seguridad de tus tarjetas. Para exportar o importar los datos presiona Importar/Exportar en el menú de la pagina principal.\n\n</string>
<string name="intro6Title">Tu Opinión\n</string>
<string name="intro6Description">Esta aplicación es gratuita, libre de publicidad y de código libre. Para más detalles presiona en Acerca De en el menu principal.\n\nPor favor deja tu opinión en la tienda de applicaciones! (:</string>
<string name="change">Cambiar</string>
<string name="storeTextColorTitle">Color del Texto de la Tienda</string>
<string name="storeTextBackgroundColorTitle">Color Principal</string>
<string name="storeNameBackgroundColorDescription">Color de fondo para el texto de la tienda</string>
<string name="storeNameColorDescription">Color del texto de la tienda</string>
<string name="settings">Configuración</string>
<string name="settings_category_title_ui">Interfaz de Usuario</string>
<string name="settings_card_title_list_font_size">Tamaño de la letra para el título (lista)</string>
<string name="settings_card_note_list_font_size">Tamaño de la letra para notas (lista)</string>
<string name="settings_card_title_font_size">Tamaño de la letra para el título</string>
<string name="settings_card_id_font_size">Tamaño de la letra para el ID de la tarjeta</string>
<string name="settings_card_note_font_size">Tamaño de la letra para notas</string>
</resources>

View File

@@ -4,50 +4,67 @@
<string name="app_name">Loyalty Card Keychain</string>
<string name="action_add">Ajouter</string>
<string name="noGiftCards">Pas de carte de fidélité enregistrée. Cliquez sur le bouton "+" (plus) pour commencer.\n\nLoyalty Card Locker vous permet d\'enregistrer vos cartes de fidélité sur votre téléphone pour toujours les avoir à portée de main.</string>
<string name="noGiftCards">Aucune carte de fidélité enregistrée. Appuyez sur le bouton \"+\" (plus) pour commencer.\n\nLoyalty Card Locker vous permet d\'enregistrer vos cartes de fidélité sur votre téléphone pour toujours les avoir à portée de main.</string>
<string name="storeName">Nom</string>
<string name="note">Note</string>
<string name="cardId">Numéro</string>
<string name="barcodeType">Type de code-barres</string>
<string name="cancel">Annuler</string>
<string name="save">Enregistrer</string>
<string name="capture">Flasher</string>
<string name="capture">Mode capture</string>
<string name="enterCard">Mode manuel</string>
<string name="editCard">Modifier</string>
<string name="edit">Modifier</string>
<string name="delete">Supprimer</string>
<string name="confirm">Confirmer</string>
<string name="lockScreen">Désactiver la rotation</string>
<string name="unlockScreen">Activer la rotation</string>
<string name="deleteTitle">Supprimer la carte de fidélité</string>
<string name="deleteConfirmation">Confirmez que vous souhaitez supprimer cette carte</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Copier le numéro dans le presse-papier</string>
<string name="sendLabel">Envoyer&#8230;</string>
<string name="addedShortcut">Ajouter à l\'écran d\'accueil</string>
<string name="editCardTitle">Modifier la carte de fidélité</string>
<string name="addCardTitle">Ajouter une carte de fidélité</string>
<string name="viewCardTitle">Voir la carte de fidélité</string>
<string name="scanCardBarcode">Flasher le code-barres de la carte</string>
<string name="cardShortcut">Raccourci de carte</string>
<string name="noCardsMessage">Il n\'y a aucune carte. Ajoutez en une d\'abord.</string>
<string name="barcodeImageDescription">Image du code-barres de la carte</string>
<string name="noStoreError">Aucun nom n\'a été saisi</string>
<string name="noCardIdError">Aucun numéro n\'a été saisi</string>
<string name="noCardExistsError">N\'a pas pu retrouver la carte de fidélité</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Importer/Exporter</string>
<string name="importName">Importer</string>
<string name="exportName">Exporter</string>
<string name="importExportHelp">Exporter vos données vous permet de récupérer vos cartes sur un autre appareil.</string>
<string name="importedFrom">Importé depuis : %1$s</string>
<string name="exportedTo">Exporté vers : %1$s</string>
<string name="fileMissing">Fichier manquant : %1$s</string>
<string name="importSuccessfulTitle">Importé avec succès</string>
<string name="importFailedTitle">Échec de l\'import</string>
<string name="importFailed">Échec de l\'import : %1$s</string>
<string name="exportSuccessfulTitle">Exporté avec succès</string>
<string name="exportFailedTitle">Échec de l\'export</string>
<string name="exportFailed">Échec de l\'export : %1$s</string>
<string name="importing">Import &#8230;</string>
<string name="exporting">Export &#8230;</string>
<string name="noExternalStoragePermissionError">Impossible d\'importer ou d\'exporter les données sans l\'autorisation d\'accès au stockage externe</string>
<string name="exportOptionExplanation">Les données sont sauvegardées à la racine du stockage externe.</string>
<string name="importOptionFilesystemTitle">Importer depuis le système de fichiers.</string>
<string name="importOptionFilesystemExplanation">Choisissez le fichier à importer.</string>
<string name="importOptionFilesystemButton">Système de fichiers</string>
<string name="importOptionApplicationTitle">Application externe</string>
<string name="importOptionApplicationExplanation">Utilisez une application externe comme Dropbox, Google Drive, ou votre gestionnaire de fichiers favori pour ouvrir un fichier.</string>
<string name="importOptionApplicationButton">Application externe</string>
<string name="importOptionFixedTitle">Importer depuis le même emplacement que pour l\'export</string>
<string name="importOptionFixedExplanation">Importe les données depuis le même emplacement que celui défini pour l\'export.</string>
<string name="importOptionFixedButton">Utiliser l\'emplacement de l\'export</string>
<string name="about">À propos</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
@@ -59,38 +76,37 @@
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> utilise les ressources-tierces suivantes : <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Choisissez le code-barre</string>
<string name="enterBarcodeInstructions">Saisissez les chiffres du code-barres et sélectionnez l\'image qui le représente</string>
<string name="copy_to_clipboard_toast">Numéro de carte copié dans le presse-papier</string>
<string name="importExportHelp">Exporter vos données vous permet de récupérer vos cartes sur un autre appareil.</string>
<string name="importSuccessfulTitle">Importé avec succès</string>
<string name="importFailedTitle">Échec de l\'import</string>
<string name="exportSuccessfulTitle">Exporté avec succès</string>
<string name="exportFailedTitle">Échec de l\'export</string>
<string name="exportOptionExplanation">Les données sont sauvegardées à la racine du stockage externe.</string>
<string name="importOptionFilesystemTitle">Importer depuis le système de fichiers.</string>
<string name="importOptionFilesystemExplanation">Choisissez le fichier à importer.</string>
<string name="importOptionFilesystemButton">Système de fichiers</string>
<string name="importOptionApplicationTitle">Application externe</string>
<string name="importOptionApplicationExplanation">Utilisez une application externe comme Dropbox, Google Drive, ou votre gestionnaire de fichiers favori pour ouvrir un fichier.</string>
<string name="importOptionApplicationButton">Application externe</string>
<string name="importOptionFixedTitle">Importer depuis le même emplacement que pour l\'export</string>
<string name="importOptionFixedExplanation">Importe les données depuis le même emplacement que celui défini pour l\'export.</string>
<string name="importOptionFixedButton">Utiliser l\'emplacement de l\'export</string>
<string name="sendLabel">Envoyer&#8230;</string>
<string name="thumbnailDescription">Miniature pour la carte</string>
<string name="startIntro">Présentation</string>
<string name="intro1Title">Bienvenue dans\nLoyalty Card Keychain\n</string>
<string name="intro1Description">Gérez vos cartes de fidélité\nsur votre téléphone !\n\n</string>
<string name="intro2Title">Ajouter une carte\n</string>
<string name="intro2Description">Touchez le signe \'+\' en haut de l\'écran pour ajouter une carte.\n\n</string>
<string name="intro2Description">Ajoutez une nouvelle carte en appuyant sur le bouton \"+\" depuis la liste des cartes.\n\n</string>
<string name="intro3Title">Ajouter une carte\n</string>
<string name="intro3Description">Pour enregistrer le code-barres, utilisez l\'appareil-photo ou entrez-le manuellement.\n\n</string>
<string name="intro4Title">Afficher une carte\n</string>
<string name="intro4Description">Pour afficher une carte, touchez le nom du magasin sur l\'écran principal\n\n</string>
<string name="intro4Description">Pour afficher une carte, appuyez sur le nom du magasin depuis l\'écran principal\n\n</string>
<string name="intro5Title">Sauvegarde\n</string>
<string name="intro5Description">Les cartes peuvent être sauvegardées. Touchez \'Importer/Exporter\' sur l\'écran principal pour restaurer ou sauvegarder les cartes.\n\n</string>
<string name="intro6Title">Votre avis\n</string>
<string name="intro6Description">Cette application est gratuite, sans publicité, et son code est ouvert. Découvrez-en plus en touchant \'à propos\' sur l\'écran principal.\n\nLaissez un commentaire sur votre magasin d\'applications (:</string>
</resources>
<string name="intro5Description">Les cartes peuvent être sauvegardées. Appuyez sur \"Importer/Exporter\" depuis l\'écran principal pour restaurer ou sauvegarder les cartes.\n\n</string>
<string name="intro6Title">Commentaire\n</string>
<string name="intro6Description">Cette application est gratuite, sans pub, et son code est ouvert. Plus de détails en appuyant sur \"À propos\" depuis l\'écran principal.\n\nMerci de laisser un commentaire sur le Play Store (:</string>
<string name="change">Modifier</string>
<string name="storeTextColorTitle">Couleur du texte du magasin</string>
<string name="storeTextBackgroundColorTitle">Couleur du titre</string>
<string name="storeNameBackgroundColorDescription">Couleur de fond du texte du magasin</string>
<string name="storeNameColorDescription">Couleur pour le nom du magasin</string>
<string name="settings">Paramètres</string>
<string name="settings_category_title_ui">Interface</string>
<string name="settings_card_title_list_font_size">Taille de police pour les titres de carte en liste</string>
<string name="settings_card_note_list_font_size">Taille de police pour les notes de carte en liste</string>
<string name="settings_card_title_font_size">Taille de police pour les titres de carte</string>
<string name="settings_card_id_font_size">Taille de police pour les numéros de carte</string>
<string name="settings_card_note_font_size">Taille de police pour les notes de carte</string>
<string name="settings_display_barcode_max_brightness">Augmenter la luminosité du code-barres</string>
<string name="settings_lock_barcode_orientation">Verrouiller l\'orientation du code-barres</string>
</resources>

View File

@@ -0,0 +1,13 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="action_add">הוספה</string>
<string name="cardId">מזהה כרטיס</string>
<string name="barcodeType">סוג ברקוד</string>
<string name="cancel">ביטול</string>
<string name="save">שמור</string>
<string name="capture">צלם כרטיס</string>
<string name="enterCard">הכנס כרטיס</string>
<string name="editCard">עריכת כרטיס</string>
</resources>

View File

@@ -2,70 +2,67 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Carte fedeltà</string>
<string name="action_search">Cerca</string>
<string name="action_add">Aggiungi</string>
<string name="noGiftCards">Non hai ancora alcuna tessera fedeltà al momento. Premi sul bottone "+" (più) in alto per incominciare.\n\nL\'app ti permette di portare con te le tue tessere fedeltà, così da averle sempre a disposizione.</string>
<string name="noGiftCards">Non hai ancora alcuna carta fedeltà. Premi sul bottone +(più) in alto per incominciare.\n\nL\'app ti permette di portare con te le tue carte fedeltà, così da averle sempre a disposizione.</string>
<string name="noMatchingGiftCards">Nessuna carta fedeltà corrisponde al filtro. Riprovare con altri valori</string>
<string name="storeName">Negozio</string>
<string name="note">Note</string>
<string name="cardId">Codice</string>
<string name="barcodeType">Tipo codice a barre</string>
<string name="barcodeNoBarcode">Questa carta non ha un codice a barre</string>
<string name="cancel">Annulla</string>
<string name="save">Salva</string>
<string name="capture">Scansione carta</string>
<string name="edit">Modifica</string>
<string name="delete">Elimina</string>
<string name="editCardTitle">Modifica carta</string>
<string name="addCardTitle">Aggiungi carta</string>
<string name="viewCardTitle">Mostra carta</string>
<string name="scanCardBarcode">Scansiona codice carta</string>
<string name="barcodeImageDescription">Immagine del codice a barre della carta</string>
<string name="noStoreError">Nessun negozio inserito</string>
<string name="noCardIdError">Nessun codice carta inserito</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="note">Note</string>
<string name="importExport">Importa/Esporta</string>
<string name="importName">Importa</string>
<string name="exportName">Esporta</string>
<string name="importedFrom">Importato da: %1$s</string>
<string name="exportedTo">Esportato in: %1$s</string>
<string name="fileMissing">File mancante: %1$s</string>
<string name="importFailed">Impossibile importare: %1$s</string>
<string name="exportFailed">Impossibile esportare: %1$s</string>
<string name="importing">Importazione in corso&#8230;</string>
<string name="exporting">Esportazione in corso&#8230;</string>
<string name="noExternalStoragePermissionError">Impossibile importare o esportare i dati senza il permesso per l\'uso della memoria esterna.</string>
<string name="about">Informazioni</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Pubblicato sotto licenza GPLv3.</string>
<string name="about_title_fmt">Informazioni su <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versione: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Informazione sulla revisione: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> usa le seguenti librerie di terze parti: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> usa le seguenti risorse di terze parti: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="ok">Ok</string>
<string name="enterCard">Inserisci carta</string>
<string name="editCard">Modifica carta</string>
<string name="selectBarcodeTitle">Seleziona codice a barre</string>
<string name="enterBarcodeInstructions">Digita il valore del codice a barre, quindi seleziona l\'immagine che rappresenta il codice a barre che vuoi usare.</string>
<string name="copy_to_clipboard">Copia ID negli appunti</string>
<string name="copy_to_clipboard_toast">ID della carta copiato negli appunti</string>
<string name="edit">Modifica</string>
<string name="delete">Elimina</string>
<string name="confirm">Conferma</string>
<string name="lockScreen">Blocca rotazione</string>
<string name="unlockScreen">Sblocca rotazione</string>
<string name="deleteTitle">Rimuovi carta fedeltà</string>
<string name="deleteConfirmation">Conferma che vuoi eliminare questa carta.</string>
<string name="importExportHelp">Fare il backup dei dati ti permette di spostare le tue tessere da un dispositivo ad un altro.</string>
<string name="ok">Ok</string>
<string name="copy_to_clipboard">Copia ID negli appunti</string>
<string name="share">Condividi</string>
<string name="sendLabel">Invia&#8230;</string>
<string name="addedShortcut">Aggiunto al launcher</string>
<string name="editCardTitle">Modifica carta</string>
<string name="addCardTitle">Aggiungi carta</string>
<string name="viewCardTitle">Mostra carta</string>
<string name="scanCardBarcode">Scansiona codice carta</string>
<string name="cardShortcut">Scorciatoia per la carta</string>
<string name="noCardsMessage">Non ci sono carte. Aggiungine prima una</string>
<string name="barcodeImageDescription">Immagine del codice a barre della carta</string>
<string name="noStoreError">Nessun negozio inserito</string>
<string name="noCardIdError">Nessun codice carta inserito</string>
<string name="noCardExistsError">Impossibile trovare la carta</string>
<string name="failedParsingImportUriError">Impossibile analizzare l\'URI</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Importa/Esporta</string>
<string name="importName">Importa</string>
<string name="exportName">Esporta</string>
<string name="importExportHelp">Fare il backup dei dati ti permette di spostare le tue carte da un dispositivo ad un altro.</string>
<string name="importedFrom">Importato da: %1$s</string>
<string name="exportedTo">Esportato in: %1$s</string>
<string name="fileMissing">File mancante: %1$s</string>
<string name="importSuccessfulTitle">Importazione avvenuta con successo</string>
<string name="importFailedTitle">Importazione fallita</string>
<string name="importFailed">Impossibile importare: %1$s</string>
<string name="exportSuccessfulTitle">Esportazione avvenuta con successo</string>
<string name="exportFailedTitle">Esportazione fallita</string>
<string name="exportFailed">Impossibile esportare: %1$s</string>
<string name="importing">Importazione in corso&#8230;</string>
<string name="exporting">Esportazione in corso&#8230;</string>
<string name="noExternalStoragePermissionError">Impossibile importare o esportare i dati senza il permesso per l\'uso della memoria esterna.</string>
<string name="exportOptionExplanation">I dati sono stati scritti nella cartella principale della memoria esterna.</string>
<string name="importOptionFilesystemTitle">Importa dal file system</string>
<string name="importOptionFilesystemExplanation">Scegli un file dal file system.</string>
@@ -76,11 +73,26 @@
<string name="importOptionFixedTitle">Importa da un altro posto</string>
<string name="importOptionFixedExplanation">Importa dallo stesso posto del file system dove si è esportato.</string>
<string name="importOptionFixedButton">Usa luogo dell\'esportazione</string>
<string name="sendLabel">Invia&#8230;</string>
<string name="startIntro">Incomincia introduzione</string>
<string name="intro1Title">Benvenuto in Carte fedeltà\n</string>
<string name="intro1Description">Gestisci le tue tessere direttamente dal telefono!\n\n</string>
<string name="about">Informazioni</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Pubblicato sotto licenza GPLv3.</string>
<string name="about_title_fmt">Informazioni su <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versione: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Informazione sulla versione: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> usa le seguenti librerie di terze parti: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> usa le seguenti risorse di terze parti: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Seleziona codice a barre</string>
<string name="enterBarcodeInstructions">Immettere l\'ID della carta, quindi selezionare l\'immagine che rappresenta il codice a barre desiderato oppure selezionare &#8220;Questa carta non ha un codice a barre&#8221; per non valorizzare il dato.</string>
<string name="copy_to_clipboard_toast">ID della carta copiato negli appunti</string>
<string name="thumbnailDescription">Miniatura carta</string>
<string name="startIntro">Introduzione</string>
<string name="intro1Title">Benvenuto in Carte Fedeltà\n</string>
<string name="intro1Description">Gestisci le tue carte direttamente dal telefono!\n\n</string>
<string name="intro2Title">Aggiungi carte\n</string>
<string name="intro2Description">Aggiungi una nuova carta premendo il + dall\'elenco delle carte.\n\n</string>
<string name="intro3Title">Aggiungi carte\n</string>
@@ -90,5 +102,27 @@
<string name="intro5Title">Backup\n</string>
<string name="intro5Description">I dati delle tessere possono essere salvati. Per esportare o importare tessere premi Importa/Esporta nel menù nella schermata principale.\n\n</string>
<string name="intro6Title">Feedback\n</string>
<string name="intro6Description">Questa app è gratuita, priva di pubblicità e open source. Guarda i dettagli premendo su Informazioni nella schermata principale.\n\nPer favore, lascia un feedback nell\'app store! (:</string>
</resources>
<string name="intro6Description">Questa app è gratuita, priva di pubblicità e open source. Guarda i dettagli premendo su \"Informazioni\" nella schermata principale.\n\nPer favore, lascia un feedback nell\'app store! (:</string>
<string name="change">Cambia</string>
<string name="storeTextColorTitle">Colore titolo</string>
<string name="storeTextBackgroundColorTitle">Colore scheda</string>
<string name="storeNameBackgroundColorDescription">Colore di sfondo del titolo carta</string>
<string name="storeNameColorDescription">Colore del titolo carta</string>
<string name="settings">Impostazioni</string>
<string name="settings_category_title_ui">Interfaccia utente</string>
<string name="settings_theme">Tema</string>
<string name="settings_system_theme">Tema del sistema</string>
<string name="settings_light_theme">Tema chiaro</string>
<string name="settings_dark_theme">Tema scuro</string>
<string name="settings_card_title_list_font_size">Dimensione testo del titolo carta (in lista carte)</string>
<string name="settings_card_note_list_font_size">Dimensione testo delle note carta (in lista carte)</string>
<string name="settings_card_title_font_size">Dimensione testo del titolo carta</string>
<string name="settings_card_id_font_size">Dimensione testo dell\'ID carta</string>
<string name="settings_card_note_font_size">Dimensione testo delle note carta</string>
<string name="settings_display_barcode_max_brightness">Aumenta luminosità dello schermo quando apro un codice a barre</string>
<string name="settings_lock_barcode_orientation">Blocca orientamento del codice a barre</string>
<string name="intent_import_card_from_url">Importa carte fedeltà</string>
<string name="intent_import_card_from_url_share_text">Voglio condividere una carta fedeltà con te</string>
</resources>

View File

@@ -5,39 +5,30 @@
<string name="action_add">Pridėti</string>
<string name="noGiftCards">Šiuo metu neturite nė vienos įvestos lojalumo kortelės. Paspauskite "+" (pliuso) pliuso mygtuką, kad pradėtumėte.\n\nLoyalty Card Locker leidžia Jums visada nešiotis lojalumo kortelių informaciją savo telefone ar planšetėje, taip jos visada pasiekiamos.</string>
<string name="storeName">Parduotuvė</string>
<string name="note">Užrašas</string>
<string name="cardId">Kortelės ID</string>
<string name="barcodeType">Brūkšninio kodo tipas</string>
<string name="cancel">Atšaukti</string>
<string name="save">Išsaugoti</string>
<string name="capture">Nufotografuoti kortelę</string>
<string name="enterCard">Įvesti kortelę</string>
<string name="edit">Redaguoti</string>
<string name="delete">Ištrinti</string>
<string name="confirm">Patvirtinti</string>
<string name="deleteTitle">Panaikinti lojalumo kortelę</string>
<string name="deleteConfirmation">Prašome patvirtinti jog Jūs norite panaikinti šią lojalumo kortelę.</string>
<string name="ok">Gerai</string>
<string name="copy_to_clipboard">Nukopijuoti ID į iškarpinę</string>
<string name="editCardTitle">Redaguoti lojalumo kortelę</string>
<string name="addCardTitle">Pridėti lojalumo kortelę</string>
<string name="viewCardTitle">Paeržiūrėti lojalumo kortelę</string>
<string name="scanCardBarcode">Nuskanuokite kortelės brūkšninį kodą</string>
<string name="barcodeImageDescription">Kortelės brūkšninio kodo paveikslėlis</string>
<string name="noStoreError">Parduotuvė neįvesta</string>
<string name="noCardIdError">Neįvestas kortelės ID</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Importuoti/Exportuoti</string>
<string name="importName">Importuoti</string>
<string name="exportName">Exportuoti</string>
@@ -49,7 +40,6 @@
<string name="importing">Importuoja&#8230;</string>
<string name="exporting">Eksportuoja&#8230;</string>
<string name="noExternalStoragePermissionError">Negalima importuoti/eksportuoti kortelių be išorinės atminties leidimo</string>
<string name="about">Apie</string>
<string name="app_copyright_fmt">Visos teisės saugomos 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Licenzijuota pagal GPLv3.</string>
@@ -57,10 +47,7 @@
<string name="debug_version_fmt">Versija: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Revizijos informacija: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> naudoja šias trečiosios šalies bibliotekas: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Pasirinkite brūkšninį kodą</string>
<string name="enterBarcodeInstructions">Enter the barcode value then select the image which represents the barcode you want to use</string>
<string name="copy_to_clipboard_toast">Kortelės ID nukopijuota į iškarpinę</string>
</resources>
</resources>

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Kundekortknippe</string>
<string name="action_add">Legg til</string>
<string name="noGiftCards">Du har ingen kundekort for øyeblikket. Klikk på \"+\" (pluss)-knappen øverst for å komme igang.\n\nDa har du dem alltid hendig.</string>
<string name="storeName">Butikk</string>
<string name="note">Merknad</string>
<string name="cardId">Kort-ID</string>
<string name="barcodeType">Strekkodetype</string>
<string name="cancel">Avbryt</string>
<string name="save">Lagre</string>
<string name="capture">Les inn kort</string>
<string name="enterCard">Skriv inn kort</string>
<string name="editCard">Rediger kort</string>
<string name="edit">Rediger</string>
<string name="delete">Slett</string>
<string name="confirm">Bekreft</string>
<string name="lockScreen">Ingen rotering</string>
<string name="unlockScreen">Skru på rotering</string>
<string name="deleteTitle">Fjern kundekort</string>
<string name="deleteConfirmation">Bekreft at du ønsker å slette dette kortet.</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Kopier ID til utklippstavle</string>
<string name="sendLabel">Send…</string>
<string name="addedShortcut">Lagt til på hjemmeskjerm</string>
<string name="editCardTitle">Rediger kundekort</string>
<string name="addCardTitle">Legg til kundekort</string>
<string name="viewCardTitle">Vis kundekort</string>
<string name="scanCardBarcode">Skann kortets strekkode</string>
<string name="cardShortcut">Kort-snarvei</string>
<string name="noCardsMessage">Legg til et kort først</string>
<string name="barcodeImageDescription">Bilde av kortets strekkode</string>
<string name="noStoreError">Ingen butikk angitt</string>
<string name="noCardIdError">Ingen kort-ID innskrevet</string>
<string name="noCardExistsError">Kunne ikke finne kundekort</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Import/eksport</string>
<string name="importName">Importer</string>
<string name="exportName">Eksporter</string>
<string name="importExportHelp">Sikkerhetskopiering av data lar deg flytte kortene til en annen enhet.</string>
<string name="importedFrom">Importert fra: %1$s</string>
<string name="exportedTo">Exportert til: %1$s</string>
<string name="fileMissing">Fil mangler: %1$s</string>
<string name="importSuccessfulTitle">Importert</string>
<string name="importFailedTitle">Kunne ikke importere</string>
<string name="importFailed">Klarte ikke å importere: %1$s</string>
<string name="exportSuccessfulTitle">Eksportert</string>
<string name="exportFailedTitle">Kunne ikke eksportere</string>
<string name="exportFailed">Klarte ikke å eksportere: %1$s</string>
<string name="importing">Importerer…</string>
<string name="exporting">Exporterer…</string>
<string name="noExternalStoragePermissionError">Kan ikke importere eller eksportere kort uten tilgang til ekstern lagring</string>
<string name="exportOptionExplanation">Data skrives til rotmappen i eksternt lagringsområde.</string>
<string name="importOptionFilesystemTitle">Importer fra filsystem</string>
<string name="importOptionFilesystemExplanation">Velg spesifikk fil fra filsystemet.</string>
<string name="importOptionFilesystemButton">Fra filsystem</string>
<string name="importOptionApplicationTitle">Brukt eksternt program</string>
<string name="importOptionApplicationExplanation">Bruk eksternt program som Nextcloud, eller din favorittfilbehandler til å åpne ei fil.</string>
<string name="importOptionApplicationButton">Bruk eksternt program</string>
<string name="importOptionFixedTitle">Importer fra eksporteringsområde</string>
<string name="importOptionFixedExplanation">Importer fra området i filsystemet eksporter skrives til.</string>
<string name="importOptionFixedButton">Bruk eksporteringsplassering</string>
<string name="about">Om</string>
<string name="app_copyright_fmt">Kopirett 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Lisensiert GPLv3+.</string>
<string name="about_title_fmt">Om <xliff:g id="app_name">%s</xliff:g>
</string>
<string name="debug_version_fmt">Versjon: <xliff:g id="version">%s</xliff:g>
</string>
<string name="app_revision_fmt">Utgivelsesinfo: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries">
<xliff:g id="app_name">%s</xliff:g> brukfer følgende tredjepartsbibliotek: <xliff:g id="app_libraries_list">%s</xliff:g>
</string>
<string name="app_resources">
<xliff:g id="app_name">%s</xliff:g> bruker følgende tredjepartsressurser: <xliff:g id="app_resources_list">%s</xliff:g>
</string>
<string name="selectBarcodeTitle">Velg strekkode</string>
<string name="enterBarcodeInstructions">Skriv inn strekkodeverdien og velg så bildet som representerer strekkoden du ønsker å bruke.</string>
<string name="copy_to_clipboard_toast">Kort-ID kopiert til utklippstavle</string>
<string name="thumbnailDescription">Miniatyrbilde for kort</string>
<string name="startIntro">Start intro</string>
<string name="intro1Title">Velkommen til Kundekortknippe\n</string>
<string name="intro1Description">Håndter strekkodekodekundekort på din enhet.\n\n</string>
<string name="intro2Title">Tillegg av kort\n</string>
<string name="intro2Description">Legg til et nytt kort ved å trykke på + i kortlisten.
\n
\n</string>
<string name="intro3Title">Tillegg av kort\n</string>
<string name="intro3Description">Legg til strekkoder med kamera eller skriv dem inn manuelt.
\n
\n</string>
<string name="intro4Title">Vis kort\n</string>
<string name="intro4Description">For å vise et kort, klikk på butikknavnet fra hovedskjermen\n\n</string>
<string name="intro5Title">Sikkerhetskopi\n</string>
<string name="intro5Description">Kortene kan sikkerhetskopieres. For å eksportere eller importere kortdata, trykk på \"Importer/eksporter\" i hovedsidemenyen.
\n
\n</string>
<string name="intro6Title">Tilbakemeldinger\n</string>
<string name="intro6Description">Dette programmet er reklamefri og gratis genenslig fri programvare. Se flere detaljer ved å trykke på \"Om\"-skjermen på hovedsiden.
\n
\nLevn en vurdering i programbutikken. (:</string>
<string name="change">Endre</string>
<string name="storeTextColorTitle">Skriftstørrelse for butikktekst</string>
<string name="storeTextBackgroundColorTitle">Overskriftsfarge</string>
<string name="storeNameBackgroundColorDescription">Farge for butikktekstbakgrunn</string>
<string name="storeNameColorDescription">Butikktekstfarge</string>
<string name="settings">Innstillinger</string>
<string name="settings_category_title_ui">Brukergrensesnitt</string>
<string name="settings_card_title_list_font_size">Korttittelskriftstørrelse</string>
<string name="settings_card_note_list_font_size">Skriftstørrelse for kortmerknadsliste</string>
<string name="settings_card_title_font_size">Skriftstørrelse for korttittel</string>
<string name="settings_card_id_font_size">Skriftstørrelse for kort-ID</string>
<string name="settings_card_note_font_size">Skriftstørrelse for kortmerknad</string>
<string name="settings_display_barcode_max_brightness">Lysere strekkodevisning</string>
<string name="settings_lock_barcode_orientation">Lås strekkodesideretning</string>
</resources>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Palette generated by Material IO https://material.io/color/#!/?view.left=0&view.right=0&primary.color=3F51B5&secondary.color=FFC107 -->
<!-- Colors manually flipped to dark variants -->
<resources>
<color name="colorPrimary">#3f51b5</color>
<color name="colorPrimaryLight">#757de8</color>
<color name="colorPrimaryDark">#002984</color>
<color name="colorSecondary">#ffc107</color>
<color name="colorSecondaryLight">#fff350</color>
<color name="colorSecondaryDark">#c79100</color>
<color name="colorPrimaryText">#000000</color>
<color name="colorSecondaryText">#ffffff</color>
<color name="inputContrastBackground">#070707</color>
<color name="inputBackground">#000000</color>
<color name="inputBorder">#222222</color>
<color name="inputDividerBorder">#666666</color>
</resources>

View File

@@ -1,79 +1,128 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Klantenkaartenkluis</string>
<string name="action_add">Voeg toe</string>
<string name="app_name">Klantenkaartkluis</string>
<string name="action_search">Zoeken</string>
<string name="action_add">Toevoegen</string>
<string name="noGiftCards">Er zijn momenteel geen klantenkaarten toegevoegd. Klik de knop met "+" (plus) om te beginnen.\n\nKlantenkaartenkluis beheert klantenkaarten op een smartphone of tablet, zodat ze altijd binnen handbereik zijn.</string>
<string name="noGiftCards">Je hebt nog geen klantenkaarten toegevoegd. Druk op de knop \'+\' (plus) om te beginnen.\n\nMet Klantenkaartkluis beheer je je klantenkaarten op je smartphone of tablet zodat ze altijd binnen handbereik zijn.</string>
<string name="noMatchingGiftCards">Er zijn geen kaarten die overeenkomen met je zoekopdracht. Probeer het opnieuw.</string>
<string name="storeName">Winkel</string>
<string name="cardId">Kaart-ID</string>
<string name="barcodeType">Barcodetype</string>
<string name="note">Aantekening</string>
<string name="cardId">Kaartnummer</string>
<string name="barcodeType">Soort barcode</string>
<string name="barcodeNoBarcode">Deze kaart heeft geen barcode</string>
<string name="cancel">Annuleer</string>
<string name="save">Sla op</string>
<string name="capture">Scan kaart</string>
<string name="edit">Bewerk</string>
<string name="delete">Verwijder</string>
<string name="cancel">Annuleren</string>
<string name="save">Opslaan</string>
<string name="capture">Scan een kaart</string>
<string name="enterCard">Voer een kaartnummer in</string>
<string name="editCard">Kaart bewerken</string>
<string name="edit">Bewerken</string>
<string name="delete">Verwijderen</string>
<string name="confirm">Bevestigen</string>
<string name="lockScreen">Draaien niet toestaan</string>
<string name="unlockScreen">Draaien toestaan</string>
<string name="deleteTitle">Kaart verwijderen</string>
<string name="deleteConfirmation">Bevestig dat je deze kaart wilt verwijderen.</string>
<string name="ok">Oké</string>
<string name="copy_to_clipboard">Kaartnummer kopiëren naar klembord</string>
<string name="share">Delen</string>
<string name="sendLabel">Versturen&#8230;</string>
<string name="addedShortcut">Toegevoegd aan startscherm</string>
<string name="editCardTitle">Bewerk klantenkaart</string>
<string name="addCardTitle">Voeg klantenkaart toe</string>
<string name="viewCardTitle">Bekijk klantenkaart</string>
<string name="scanCardBarcode">Scan barcode klantenkaart</string>
<string name="editCardTitle">Klantenkaart bewerken</string>
<string name="addCardTitle">Klantenkaart toevoegen</string>
<string name="viewCardTitle">Klantenkaart tonen</string>
<string name="scanCardBarcode">Scan de barcode van de kaart</string>
<string name="cardShortcut">Kaartsnelkoppeling</string>
<string name="noCardsMessage">Je hebt nog geen kaarten toegevoegd.</string>
<string name="barcodeImageDescription">Afbeelding barcode klantenkaart</string>
<string name="barcodeImageDescription">Afbeelding van barcode</string>
<string name="noStoreError">Geen winkel toegevoegd</string>
<string name="noCardIdError">Geen kaart-ID toegevoegd</string>
<string name="noStoreError">Geen winkelnaam ingevoerd</string>
<string name="noCardIdError">Geen kaartnummer ingevoerd</string>
<string name="noCardExistsError">De klantenkaart kan niet worden opgevraagd</string>
<string name="failedParsingImportUriError">Kan de import-uri niet verwerken</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="note">Notitie</string>
<string name="importExport">Importeer/Exporteer</string>
<string name="importName">Importeer</string>
<string name="exportName">Exporteer</string>
<string name="importedFrom">Geïmporteerd van: %1$s</string>
<string name="importExport">Importeren/Exporteren</string>
<string name="importName">Importeren</string>
<string name="exportName">Exporteren</string>
<string name="importExportHelp">Door de gegevens te back-uppen kun je je kaarten overzetten naar een ander apparaat.</string>
<string name="importedFrom">Geïmporteerd uit: %1$s</string>
<string name="exportedTo">Geëxporteerd naar: %1$s</string>
<string name="fileMissing">Bestand niet gevonden: %1$s</string>
<string name="importFailed">Importeren mislukte: %1$s</string>
<string name="exportFailed">Exporteren mislukte: %1$s</string>
<string name="importing">Importerende&#8230;</string>
<string name="exporting">Exporterende&#8230;</string>
<string name="noExternalStoragePermissionError">Niet mogelijk te importeren of exporteren zonder rechten op externe opslag</string>
<string name="fileMissing">Bestand ontbreekt: %1$s</string>
<string name="importSuccessfulTitle">Importeren voltooid</string>
<string name="importFailedTitle">Importeren mislukt</string>
<string name="importFailed">Het importeren is mislukt: %1$s</string>
<string name="exportSuccessfulTitle">Exporteren voltooid</string>
<string name="exportFailedTitle">Exporteren mislukt</string>
<string name="exportFailed">Het exporteren is mislukt: %1$s</string>
<string name="importing">Bezig met importeren&#8230;...</string>
<string name="exporting">Bezig met exporteren&#8230;...</string>
<string name="noExternalStoragePermissionError">Het importeren of exporteren van kaarten is niet mogelijk zonder de machtiging \'externe opslag\'.</string>
<string name="exportOptionExplanation">De gegevens worden weggeschreven naar de hoogste map op de externe opslag.</string>
<string name="importOptionFilesystemTitle">Importeren uit bestandssysteem</string>
<string name="importOptionFilesystemExplanation">Kies een specifiek bestand uit het bestandssysteem.</string>
<string name="importOptionFilesystemButton">Uit bestandssysteem</string>
<string name="importOptionApplicationTitle">Externe app gebruiken</string>
<string name="importOptionApplicationExplanation">Open een bestand middels een externe app, zoals Dropbox, Google Drive of je favoriete bestandsbeheerder.</string>
<string name="importOptionApplicationButton">Externe app gebruiken</string>
<string name="importOptionFixedTitle">Importeren uit exportlocatie</string>
<string name="importOptionFixedExplanation">Importeer uit dezelfde locatie op het bestandssysteem waar tijdens het exporteren naar weggeschreven is.</string>
<string name="importOptionFixedButton">Exportlocatie gebruiken</string>
<string name="about">Over</string>
<string name="app_copyright_fmt">Auteursrecht 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Gelicenseerd met GPLv3.</string>
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Uitgebracht onder de GPLv3-licentie.</string>
<string name="about_title_fmt">Over <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versie: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Revisieïnformatie: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> gebruikt de volgende bibliotheken van derden: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_revision_fmt">Versie-informatie: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> gebruikt de volgende bibliotheken van externe partijen: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> gebruikt de volgende bronnen van externe partijen: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="ok">Oké</string>
<string name="enterCard">Voer kaart in</string>
<string name="selectBarcodeTitle">Barcode toevoegen</string>
<string name="enterBarcodeInstructions">Voer de barcode in en kies daarna de afbeelding van de barcode die je wilt gebruiken., of druk op &#8220;Deze kaart heeft geen barcode&#8221; om geen barcode te gebruiken.</string>
<string name="selectBarcodeTitle">Selecteer barcode</string>
<string name="enterBarcodeInstructions">Voer de waarde van de barcode in en kies daarna de afbeelding die de barcode die je wil gebruiken representeert</string>
<string name="copy_to_clipboard">Kopieer het ID naar het klembord</string>
<string name="copy_to_clipboard_toast">Het ID is naar het klembord gekopieerd</string>
<string name="confirm">Bevestig</string>
<string name="deleteConfirmation">Bevestig deze kaart te verwijderen.</string>
<string name="deleteTitle">Verwijder kaart</string>
<string name="copy_to_clipboard_toast">Kaartnummer is gekopieerd naar het klembord</string>
<string name="importExportHelp">Data die is geback-upt maakt het mogelijk om je klantenkaarten naar een ander apparaat te verplaatsen.</string>
<string name="importSuccessfulTitle">Importeren succesvol</string>
<string name="importFailedTitle">Importeren mislukte</string>
<string name="exportSuccessfulTitle">Exporteren succesvol</string>
<string name="exportFailedTitle">Exporteren mislukt</string>
<string name="exportOptionExplanation">Data is weggeschreven naar de hoogste map in externe opslag.</string>
<string name="importOptionFilesystemTitle">Importeer van filesysteem</string>
<string name="importOptionFilesystemExplanation">Kies een specifiek bestand van het filesysteem.</string>
<string name="importOptionFilesystemButton">Van filesysteem</string>
<string name="importOptionApplicationTitle">Gebruik externe applicatie</string>
<string name="importOptionApplicationExplanation">Gebruik een externe applicatie zoals Dropbox, Google Drive of je favoriete bestandsbeheer om een bestand te openen.</string>
<string name="importOptionApplicationButton">Gebruik externe applicatie</string>
<string name="importOptionFixedTitle">Importeer van exporteerlocatie</string>
<string name="importOptionFixedExplanation">Importeer van zelfde locatie op het filesysteem waar tijdens exporteren naar geschreven is.</string>
<string name="importOptionFixedButton">gebruik exporteerlocaite</string>
<string name="sendLabel">Verzend&#8230;</string>
<string name="thumbnailDescription">Miniatuurvoorbeeld van kaart</string>
</resources>
<string name="startIntro">Rondleiding starten</string>
<string name="intro1Title">Welkom bij Klantenkaartkluis\n</string>
<string name="intro1Description">Beheer je op barcodes gebaseerde klantenkaarten op je telefoon!\n\n</string>
<string name="intro2Title">Kaarten toevoegen\n</string>
<string name="intro2Description">Voeg een kaart toe door in de lijst met kaarten op de plus-knop te drukken.\n\n</string>
<string name="intro3Title">Kaarten toevoegen\n</string>
<string name="intro3Description">De barcode kan worden toegevoegd door deze handmatig in te voeren of te scannen met de camera.\n\n</string>
<string name="intro4Title">Kaart tonen\n</string>
<string name="intro4Description">Toon een kaart door op het kaartoverzicht op de naam van de winkel te drukken.\n\n</string>
<string name="intro5Title">Back-uppen\n</string>
<string name="intro5Description">Je kunt je kaarten back-uppen: druk in het menu op het kaartoverzicht op Importeren/Exporteren.\n\n</string>
<string name="intro6Title">Feedback\n</string>
<string name="intro6Description">Deze app is gratis, reclamevrij en open source. Bekijk alle details door op \'Over\' te drukken in het menu op het kaartoverzicht.\n\nGeef feedback in de app-winkel! (:</string>
<string name="change">Aanpassen</string>
<string name="storeTextColorTitle">Tekstkleur van winkelnaam</string>
<string name="storeTextBackgroundColorTitle">Kopkleur</string>
<string name="storeNameBackgroundColorDescription">Achtergrondkleur van winkeltekst</string>
<string name="storeNameColorDescription">Kleur van winkeltekst</string>
<string name="settings">Instellingen</string>
<string name="settings_category_title_ui">Uiterlijk en bediening</string>
<string name="settings_theme">Thema</string>
<string name="settings_system_theme">Systeemthema</string>
<string name="settings_light_theme">Licht</string>
<string name="settings_dark_theme">Donker</string>
<string name="settings_card_title_list_font_size">Lettergrootte van kaartnamen op de lijst</string>
<string name="settings_card_note_list_font_size">Lettergrootte van aantekeningen op de lijst</string>
<string name="settings_card_title_font_size">Lettergrootte van kaartnamen</string>
<string name="settings_card_id_font_size">Lettergrootte van kaartnummer</string>
<string name="settings_card_note_font_size">Lettergrootte van aantekeningen</string>
<string name="settings_display_barcode_max_brightness">Scherm helderder maken bij tonen van barcode</string>
<string name="settings_lock_barcode_orientation">Barcode-oriëntatie vergrendelen</string>
<string name="intent_import_card_from_url">Klantenkaart importeren</string>
<string name="intent_import_card_from_url_share_text">Ik wil een klantenkaart met je delen</string>
</resources>

View File

@@ -0,0 +1,128 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Loyalty Card Keychain</string>
<string name="action_search">Szukaj</string>
<string name="action_add">Dodaj</string>
<string name="noGiftCards">W tej chwili nie masz żadnych kart lojalnościowych. Kliknij przycisk \"+\" (plus) u góry, aby rozpocząć. \n\nLoyalty Locker Card pozwala nosić karty lojalnościowe w telefonie, dzięki czemu są zawsze w zasięgu ręki.</string>
<string name="noMatchingGiftCards">Żadne karty lojalnościowe nie pasują do filtra wyszukiwania. Spróbuj użyć innych warunków.</string>
<string name="storeName">Sklep</string>
<string name="note">Notatka</string>
<string name="cardId">Identyfikator karty</string>
<string name="barcodeType">Typ kodu kreskowego</string>
<string name="barcodeNoBarcode">Ta karta nie ma kodu kreskowego</string>
<string name="cancel">Anuluj</string>
<string name="save">Zapisz</string>
<string name="capture">Zeskanuj kod</string>
<string name="enterCard">Wprowadź ręcznie</string>
<string name="editCard">Edytuj kartę</string>
<string name="edit">Edytuj</string>
<string name="delete">Usuń</string>
<string name="confirm">Potwierdź</string>
<string name="lockScreen">Zablokuj autoobracanie ekranu</string>
<string name="unlockScreen">Odblokuj autoobracanie ekranu</string>
<string name="deleteTitle">Usuń kartę lojalnościową</string>
<string name="deleteConfirmation">Potwierdź, że chcesz usunąć tę kartę.</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Skopiuj identyfikator do schowka</string>
<string name="share">Udostępnij</string>
<string name="sendLabel">Wyślij&#8230;</string>
<string name="addedShortcut">Dodano do ekranu głównego</string>
<string name="editCardTitle">Edytuj kartę lojalnościową</string>
<string name="addCardTitle">Dodaj kartę lojalnościową</string>
<string name="viewCardTitle">Pokaż kartę lojalnościową</string>
<string name="scanCardBarcode">Zeskanuj kod kreskowy karty lojalnościowej</string>
<string name="cardShortcut">Skrót karty</string>
<string name="noCardsMessage">Nie ma kart, należy dodać pierwszą</string>
<string name="barcodeImageDescription">Obraz kodu kreskowego karty</string>
<string name="noStoreError">Nie wprowadzono nazwy sklepu</string>
<string name="noCardIdError">Nie wprowadzono identyfikatora karty</string>
<string name="noCardExistsError">Nie można wyszukać karty lojalnościowej</string>
<string name="failedParsingImportUriError">Nie można przeanalizować identyfikatora importu URI</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Importuj/Eksportuj</string>
<string name="importName">Importuj</string>
<string name="exportName">Eksportuj</string>
<string name="importExportHelp">Zarchiwizowane dane umożliwiają przeniesienie kart na inne urządzenie.</string>
<string name="importedFrom">Zaimportowano z: %1$s</string>
<string name="exportedTo">Wyeksportowano do: %1$s</string>
<string name="fileMissing">Brak pliku: %1$s</string>
<string name="importSuccessfulTitle">Zaimportowano pomyślnie</string>
<string name="importFailedTitle">Import nie powiódł się</string>
<string name="importFailed">Nie udało się zaimportować: %1$s</string>
<string name="exportSuccessfulTitle">Wyeksportowano pomyślnie</string>
<string name="exportFailedTitle">Eksport nie powiódł się</string>
<string name="exportFailed">Nie udało się wyeksportować: %1$s</string>
<string name="importing">Importowanie&#8230;</string>
<string name="exporting">Eksportowanie&#8230;</string>
<string name="noExternalStoragePermissionError">Nie można importować ani eksportować kart bez uprawnień do pamięci zewnętrznej</string>
<string name="exportOptionExplanation">Dane zapisywane są w głównym katalogu pamięci zewnętrznej.</string>
<string name="importOptionFilesystemTitle">Importuj z systemu plików</string>
<string name="importOptionFilesystemExplanation">Wybierz określony plik z systemu plików.</string>
<string name="importOptionFilesystemButton">Z systemu plików</string>
<string name="importOptionApplicationTitle">Użyj zewnętrznej aplikacji</string>
<string name="importOptionApplicationExplanation">Użyj zewnętrznej aplikacji jak Dropbox, Google Drive, bądź ulubiony menedżer plików, aby otworzyć plik.</string>
<string name="importOptionApplicationButton">Użyj zewnętrznej aplikacji</string>
<string name="importOptionFixedTitle">Importuj z lokalizacji eksportowania</string>
<string name="importOptionFixedExplanation">Importuj z tej samej lokalizacji w systemie plików, do którego zapisano przy eksporcie.</string>
<string name="importOptionFixedButton">Użyj lokalizacji eksportu</string>
<string name="about">O aplikacji</string>
<string name="app_copyright_fmt">© 2016 — <xliff:g>%d</xliff:g> Branden Archer.</string>
<string name="app_license">Licencjonowane na podstawie GNU General Public License, wersji 3.0.</string>
<string name="about_title_fmt">O <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Wersja: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Informacje o wersji: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> wykorzystuje następujące biblioteki osób trzecich: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> wykorzystuje następujące zasoby osób trzecich: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Wybierz kod kreskowy</string>
<string name="enterBarcodeInstructions">Wprowadź identyfikator karty, a następnie wybierz obraz reprezentujący kod kreskowy, którego chcesz użyć, lub wybierz &#8220;Ta karta nie ma kodu kreskowego&#8221;, aby nie używać kodu kreskowego.</string>
<string name="copy_to_clipboard_toast">Skopiowano identyfikator karty do schowka</string>
<string name="thumbnailDescription">Miniaturka karty</string>
<string name="startIntro">Pokaż ekran powitalny</string>
<string name="intro1Title">Witaj w Loyalty Card Keychain\n</string>
<string name="intro1Description">Zarządzaj kartami sklepowymi/lojalnościowymi opartymi na kodzie kreskowym na swoim telefonie!\n\n</string>
<string name="intro2Title">Dodawanie kart\n</string>
<string name="intro2Description">Dodaj nową kartę, dotykając znaku plus z listy kart. \n\n</string>
<string name="intro3Title">Dodawanie kart\n</string>
<string name="intro3Description">Aby dodać kod kreskowy, wykonaj zdjęcie aparatem lub wpisz ręcznie. \n\n</string>
<string name="intro4Title">Pokaż kartę\n</string>
<string name="intro4Description">Aby wyświetlić kartę, na głównym ekranie kliknij nazwę sklepu \n\n</string>
<string name="intro5Title">Kopia zapasowa\n</string>
<string name="intro5Description">Karty można zarchiwizować. Aby wyeksportować lub zaimportować dane karty, dotknij opcji Importuj/eksportuj w menu na stronie głównej. \n\n</string>
<string name="intro6Title">Informacje zwrotne\n</string>
<string name="intro6Description">Ta aplikacja jest darmowa, bez reklam i z otwartym kodem źródłowym. Zobacz szczegóły, klikając Informacje w menu na stronie głównej. \n\n Proszę zostawić opinię o programie w sklepie z aplikacjami! (:</string>
<string name="change">Zmień</string>
<string name="storeTextColorTitle">Kolor tekstu nazwy sklepu</string>
<string name="storeTextBackgroundColorTitle">Kolor nagłówka</string>
<string name="storeNameBackgroundColorDescription">Kolor tła tekstu nazwy sklepu</string>
<string name="storeNameColorDescription">Kolor dla tekstu sklepu</string>
<string name="settings">Ustawienia</string>
<string name="settings_category_title_ui">Interfejs użytkownika</string>
<string name="settings_theme">Motyw</string>
<string name="settings_system_theme">Systemowy</string>
<string name="settings_light_theme">Jasny</string>
<string name="settings_dark_theme">Ciemny</string>
<string name="settings_card_title_list_font_size">Rozmiar czcionki listy tytułów kart</string>
<string name="settings_card_note_list_font_size">Rozmiar czcionki listy kart</string>
<string name="settings_card_title_font_size">Rozmiar czcionki tytułu karty</string>
<string name="settings_card_id_font_size">Rozmiar czcionki identyfikatora karty</string>
<string name="settings_card_note_font_size">Rozmiar czcionki notatki karty</string>
<string name="settings_display_barcode_max_brightness">Rozjaśnij widok kodu kreskowego</string>
<string name="settings_lock_barcode_orientation">Zablokuj autoobracanie kodów kreskowych</string>
<string name="intent_import_card_from_url">Importuj kartę lojalnościową</string>
<string name="intent_import_card_from_url_share_text">Chcę udostępnić Ci kartę lojalnościową</string>
</resources>

View File

@@ -0,0 +1,4 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
</resources>

View File

@@ -0,0 +1,128 @@
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Карты лояльности</string>
<string name="action_search">Поиск</string>
<string name="action_add">Добавить карту</string>
<string name="noGiftCards">Пока нет ни одной карты. Нажмите на кнопку «+» (плюс) сверху для добавления.\n\n«Карты лояльности» позволяют хранить карты скидок в телефоне, так что они всегда будут под рукой.</string>
<string name="noMatchingGiftCards">Карт не найдено, попробуйте поискать по-другому.</string>
<string name="storeName">Магазин</string>
<string name="note">Примечание</string>
<string name="cardId">Номер карты</string>
<string name="barcodeType">Тип штрих-кода</string>
<string name="barcodeNoBarcode">Эта карта без штрихкода</string>
<string name="cancel">Отменить</string>
<string name="save">Сохранить</string>
<string name="capture">Сканировать карту</string>
<string name="enterCard">Ввести номер</string>
<string name="editCard">Редактировать штрих-код</string>
<string name="edit">Редактировать</string>
<string name="delete">Удалить карту</string>
<string name="confirm">Подтвердить</string>
<string name="lockScreen">Блокировать поворот экрана</string>
<string name="unlockScreen">Автоповорот экрана</string>
<string name="deleteTitle">Удаление карты</string>
<string name="deleteConfirmation">Пожалуйста подтвердите удаление карты.</string>
<string name="ok">ОК</string>
<string name="copy_to_clipboard">Скопировать номер карты в буфер обмена</string>
<string name="share">Переслать</string>
<string name="sendLabel">Отправить&#8230;</string>
<string name="addedShortcut">Карта добавлена на главный экран.</string>
<string name="editCardTitle">Редактировать карту</string>
<string name="addCardTitle">Добавить карту</string>
<string name="viewCardTitle">Посмотреть карту</string>
<string name="scanCardBarcode">Отсканируйте штрих-код</string>
<string name="cardShortcut">Ярлык карты</string>
<string name="noCardsMessage">Карт нет, добавьте одну для начала</string>
<string name="barcodeImageDescription">Изображение штрих-кода</string>
<string name="noStoreError">Название магазина не указано</string>
<string name="noCardIdError">Номер карты не указан</string>
<string name="noCardExistsError">Карта не найдена</string>
<string name="failedParsingImportUriError">Не удалось разобрать импортируемый URI</string>
<string name="cardIdFormat">%1$s: %2$s</string>
<string name="importExport">Импорт/Экспорт</string>
<string name="importName">Импорт</string>
<string name="exportName">Экспорт</string>
<string name="importExportHelp">Сохранение карт позволяет перенести их на другое устройство.</string>
<string name="importedFrom">Импортировано из: %1$s</string>
<string name="exportedTo">Экспортировано в: %1$s</string>
<string name="fileMissing">Файл не найден: %1$s</string>
<string name="importSuccessfulTitle">Успешный импорт</string>
<string name="importFailedTitle">Импорт не удался</string>
<string name="importFailed">Не удалось импортировать: %1$s</string>
<string name="exportSuccessfulTitle">Успешный экспорт</string>
<string name="exportFailedTitle">Экспорт не удался</string>
<string name="exportFailed">Не удалось экспортировать: %1$s</string>
<string name="importing">Импорт&#8230;</string>
<string name="exporting">Экспорт&#8230;</string>
<string name="noExternalStoragePermissionError">Импорт или экспорт невозможен без разрешения на доступ к хранилищу</string>
<string name="exportOptionExplanation">Данные сохраняются в корневой каталог хранилища.</string>
<string name="importOptionFilesystemTitle">Импорт из файловой системы</string>
<string name="importOptionFilesystemExplanation">Выберете файл на файловой системе.</string>
<string name="importOptionFilesystemButton">Выбрать файл</string>
<string name="importOptionApplicationTitle">Использование другого приложения</string>
<string name="importOptionApplicationExplanation">Использовать другое приложение такое как Dropbox, Google Drive, или ваш любимый файловый менеджер чтобы открыть файл.</string>
<string name="importOptionApplicationButton">Использовать другое приложение</string>
<string name="importOptionFixedTitle">Импорт из файла экспорта</string>
<string name="importOptionFixedExplanation">Импорт из того же файла, куда сохраняется экспорт.</string>
<string name="importOptionFixedButton">Использовать файл экспорта</string>
<string name="about">О программе</string>
<string name="app_copyright_fmt">Все права защищены 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
<string name="app_license">Лицензия GPLv3.</string>
<string name="about_title_fmt">О программе <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Версия: <xliff:g id="version">%s</xliff:g></string>
<string name="app_revision_fmt">Информация о версиях: <xliff:g id="app_revision_url">%s</xliff:g></string>
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> использует следующие сторонние библиотеки: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> использует следующие сторонние ресурсы: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="selectBarcodeTitle">Выбор штрих-кода</string>
<string name="enterBarcodeInstructions">Введите ID карты и выберите тип штрих-кода.</string>
<string name="copy_to_clipboard_toast">Номер карты скопирован в буфер обмена</string>
<string name="thumbnailDescription">Логотип карты</string>
<string name="startIntro">Введение</string>
<string name="intro1Title">Добро пожаловать в Карты лояльности\n</string>
<string name="intro1Description">Храните все карты лояльности/магазинов со штрих-кодом в телефоне!\n\n</string>
<string name="intro2Title">Добавление карт\n</string>
<string name="intro2Description">Добавьте новую карту, нажав на плюс на экране со списком карт.\n\n</string>
<string name="intro3Title">Добавление карт\n</string>
<string name="intro3Description">Для добавления штрих-кода отсканируйте карту камерой или введите номер вручную.\n\n</string>
<string name="intro4Title">Показ карты\n</string>
<string name="intro4Description">Для показа карты, нажмите на название магазина на главном экране.\n\n</string>
<string name="intro5Title">Резервное копирование\n</string>
<string name="intro5Description">Можно сделать резервную копию карт. Для этого нажмите Импорт/Экспорт в меню на главном экране.\n\n</string>
<string name="intro6Title">Отзыв\n</string>
<string name="intro6Description">Это бесплатное приложение, без рекламы и с открытым исходным кодом. Подробнее в разделе «О программе» в меню на главном экране.\n\nПожалуйста, оставьте отзыв в маркете приложений! (:</string>
<string name="change">Изменить</string>
<string name="storeTextColorTitle">Цвет текста</string>
<string name="storeTextBackgroundColorTitle">Цвет фона</string>
<string name="storeNameBackgroundColorDescription">Цвет фона названия магазина</string>
<string name="storeNameColorDescription">Цвет текста названия магазина</string>
<string name="settings">Настройки</string>
<string name="settings_category_title_ui">Внешний вид</string>
<string name="settings_theme">Тема</string>
<string name="settings_system_theme">Системная тема</string>
<string name="settings_light_theme">Светлая тема</string>
<string name="settings_dark_theme">Тёмная тема</string>
<string name="settings_card_title_list_font_size">Размер шрифта названия карты для списка</string>
<string name="settings_card_note_list_font_size">Размер шрифта примечания для списка</string>
<string name="settings_card_title_font_size">Размер шрифта названия карты</string>
<string name="settings_card_id_font_size">Размер шрифта номера карты</string>
<string name="settings_card_note_font_size">Размер шрифта примечания</string>
<string name="settings_display_barcode_max_brightness">Максимальная яркость при показе карты</string>
<string name="settings_lock_barcode_orientation">Портретная ориентация экрана при показе карты</string>
<string name="intent_import_card_from_url">Импортировать карту</string>
<string name="intent_import_card_from_url_share_text">Я хочу поделиться картой с вами</string>
</resources>

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