mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2025-12-24 15:47:53 -05:00
Compare commits
280 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b4a01c954 | ||
|
|
aee7728f56 | ||
|
|
6fbbe38542 | ||
|
|
651744b770 | ||
|
|
a189ac22ce | ||
|
|
f4d71e4525 | ||
|
|
45ec062499 | ||
|
|
82d8e84d78 | ||
|
|
fa25bff46f | ||
|
|
5648061a31 | ||
|
|
9cd2f66b40 | ||
|
|
90b7b43faf | ||
|
|
cfe5865d35 | ||
|
|
243898c441 | ||
|
|
0afc6f3976 | ||
|
|
fa95ea6a62 | ||
|
|
abb559afd6 | ||
|
|
61e7d1b154 | ||
|
|
da594a8287 | ||
|
|
15f5c4a67b | ||
|
|
19f7af1e42 | ||
|
|
b5b994642a | ||
|
|
45da445866 | ||
|
|
55b1ad1c55 | ||
|
|
fcd6f075f6 | ||
|
|
3d2f119fdb | ||
|
|
05f4add5cd | ||
|
|
eb71d5f717 | ||
|
|
a64603d64e | ||
|
|
e686bb36ce | ||
|
|
351a805046 | ||
|
|
466ac404bc | ||
|
|
b5c0be8ed5 | ||
|
|
f963b2fd4c | ||
|
|
c26ae45cdc | ||
|
|
addb0896c0 | ||
|
|
c75bef4f01 | ||
|
|
f633fb39aa | ||
|
|
49200fff48 | ||
|
|
f4bd6a3f59 | ||
|
|
18021e7653 | ||
|
|
de364a4cc4 | ||
|
|
3ba42aad6d | ||
|
|
63fad8bae1 | ||
|
|
ad418bc9bd | ||
|
|
b0263d8eb5 | ||
|
|
97d3969f93 | ||
|
|
1c85172206 | ||
|
|
711fa7ef81 | ||
|
|
2220a8e3c6 | ||
|
|
cd1bd31e23 | ||
|
|
f812194b1a | ||
|
|
79c26cfed7 | ||
|
|
85ea10303a | ||
|
|
4196ad8d61 | ||
|
|
90be6a418b | ||
|
|
2e2563cfc0 | ||
|
|
983c207019 | ||
|
|
6a5983b7bf | ||
|
|
b34e69d5d5 | ||
|
|
f1cd9ac935 | ||
|
|
5eb56c934b | ||
|
|
f9b24d4b1b | ||
|
|
537b2cba82 | ||
|
|
d788a274a8 | ||
|
|
57c383c064 | ||
|
|
49a8828007 | ||
|
|
d56a31160a | ||
|
|
bb78f9c12a | ||
|
|
00c005afce | ||
|
|
c008767bd6 | ||
|
|
5e15555ad4 | ||
|
|
916d12c504 | ||
|
|
854958e364 | ||
|
|
d295dd40fd | ||
|
|
069a3c99ef | ||
|
|
f1e7e5494d | ||
|
|
189fe7d101 | ||
|
|
9a9ff77d1c | ||
|
|
b8c1eaf88e | ||
|
|
e525a32511 | ||
|
|
de9f108534 | ||
|
|
c5f0d03a1c | ||
|
|
e592452d02 | ||
|
|
d3d2b37001 | ||
|
|
3dbe4f8327 | ||
|
|
3d81c1be08 | ||
|
|
333874e5e1 | ||
|
|
69a53a8408 | ||
|
|
8dc479793b | ||
|
|
a2d48a236b | ||
|
|
67f390f594 | ||
|
|
1a5109e036 | ||
|
|
ff42ead6b7 | ||
|
|
2f8d8e79c1 | ||
|
|
efa6ac1f6c | ||
|
|
4fc56068e1 | ||
|
|
7a0253ddcd | ||
|
|
ac3647695b | ||
|
|
fc902db170 | ||
|
|
b7230ba2a7 | ||
|
|
f5b71beb4b | ||
|
|
380a12e926 | ||
|
|
f92f84ee5c | ||
|
|
e1eb049d05 | ||
|
|
e03ca71728 | ||
|
|
9f3633b2ef | ||
|
|
0b53bdf6eb | ||
|
|
2536767437 | ||
|
|
2bc7d13d50 | ||
|
|
84fef5a615 | ||
|
|
0993f3180b | ||
|
|
f143e01685 | ||
|
|
cb5a98edad | ||
|
|
74157b2fe5 | ||
|
|
5b7d5599f9 | ||
|
|
cdfcfebd77 | ||
|
|
301fd880f5 | ||
|
|
4a4ef1b148 | ||
|
|
0bc7f4a164 | ||
|
|
5e593d0ded | ||
|
|
e958fff7b4 | ||
|
|
d81b236aa6 | ||
|
|
8be8737459 | ||
|
|
e80238bfcf | ||
|
|
211032c152 | ||
|
|
0bf50fb491 | ||
|
|
6f22e2d185 | ||
|
|
31c341663f | ||
|
|
40a68a55e2 | ||
|
|
1fd0acf6e4 | ||
|
|
127d288ace | ||
|
|
11587631a9 | ||
|
|
466b3d91d3 | ||
|
|
8f4f7524c4 | ||
|
|
f35aa2a064 | ||
|
|
c20206fe28 | ||
|
|
45de3f6616 | ||
|
|
6f42b30790 | ||
|
|
35eab50775 | ||
|
|
19d302e0a4 | ||
|
|
a17ccfa41a | ||
|
|
a22e05284c | ||
|
|
64491a1f7a | ||
|
|
472d8ae18d | ||
|
|
388db6feab | ||
|
|
5833d49fbf | ||
|
|
ffb2fadcfc | ||
|
|
5f534b9646 | ||
|
|
e011324b9f | ||
|
|
21df76a2b6 | ||
|
|
1af9789cf6 | ||
|
|
b891e05fb9 | ||
|
|
55e09b602f | ||
|
|
af4075b9e2 | ||
|
|
da0a221c85 | ||
|
|
191445b822 | ||
|
|
d890b062a9 | ||
|
|
59173443e7 | ||
|
|
5da76c9d9c | ||
|
|
f048566929 | ||
|
|
fe0f4314db | ||
|
|
8d39bd671c | ||
|
|
9ad33a047f | ||
|
|
2a78335607 | ||
|
|
d99c72982d | ||
|
|
79ced018d5 | ||
|
|
f80c79ffb1 | ||
|
|
11970004f0 | ||
|
|
a348ad62a2 | ||
|
|
22d612427f | ||
|
|
a907b28fe8 | ||
|
|
663612dce9 | ||
|
|
a55da89eb2 | ||
|
|
63ceb2589f | ||
|
|
dd981d72d7 | ||
|
|
8940a8ea77 | ||
|
|
57cfac3172 | ||
|
|
f475844bd0 | ||
|
|
4536453fdf | ||
|
|
3ee533b815 | ||
|
|
a744c19cce | ||
|
|
9cc66c5d67 | ||
|
|
3e5b018b55 | ||
|
|
f6fee780ee | ||
|
|
6971f23d0a | ||
|
|
6d33576936 | ||
|
|
b6c9b9059e | ||
|
|
000bd7b734 | ||
|
|
3dde4de775 | ||
|
|
9b867370c2 | ||
|
|
c092a04390 | ||
|
|
50d80c1a9e | ||
|
|
67e2147d33 | ||
|
|
cfe2aaaad8 | ||
|
|
88a91de63b | ||
|
|
2cdeb1af9c | ||
|
|
c815c3908f | ||
|
|
9e831924c6 | ||
|
|
cfc901855b | ||
|
|
a00a69e0c0 | ||
|
|
426acc701e | ||
|
|
d6eccd11a5 | ||
|
|
cb8275771f | ||
|
|
9252c01aa7 | ||
|
|
b4b544e342 | ||
|
|
f667fcbebe | ||
|
|
cc402c39be | ||
|
|
d5d921a1c8 | ||
|
|
d8794811a1 | ||
|
|
e56795307e | ||
|
|
6ad99d47aa | ||
|
|
2998a4d553 | ||
|
|
63db8fa0f3 | ||
|
|
ee14d9e0c5 | ||
|
|
1455265045 | ||
|
|
4f5cd87912 | ||
|
|
d5516c59a6 | ||
|
|
5654abe6e9 | ||
|
|
b17a50f9c2 | ||
|
|
87c9bb590b | ||
|
|
dc9360eb8a | ||
|
|
c8d2aa26f5 | ||
|
|
a5074eb191 | ||
|
|
9df0a8ff57 | ||
|
|
a79cf72ad7 | ||
|
|
db0134a44c | ||
|
|
5f6424778a | ||
|
|
950264105b | ||
|
|
7b2d9eb47f | ||
|
|
088ee66b5a | ||
|
|
2487edf4b2 | ||
|
|
e16d2e22ac | ||
|
|
7b335c69ba | ||
|
|
c1bd7043b1 | ||
|
|
71f3b5bc5f | ||
|
|
e2f33bf4b4 | ||
|
|
b1685ac90e | ||
|
|
394cc6b30f | ||
|
|
75e320e108 | ||
|
|
e8b38b3367 | ||
|
|
ffb24c973a | ||
|
|
d43693b1d8 | ||
|
|
b7f17181f9 | ||
|
|
10dc84820c | ||
|
|
5f0d92470e | ||
|
|
6bb4376e4d | ||
|
|
92da792378 | ||
|
|
81499cd362 | ||
|
|
fc91f1ae63 | ||
|
|
cec7bc880e | ||
|
|
4027df2119 | ||
|
|
93132961d3 | ||
|
|
638528d4fc | ||
|
|
67ef623761 | ||
|
|
cb3afe1878 | ||
|
|
e3f4aec1c5 | ||
|
|
d2f196da21 | ||
|
|
e491a960d7 | ||
|
|
f5c83793bf | ||
|
|
1624d56edb | ||
|
|
e334a5e454 | ||
|
|
cbbd071f4f | ||
|
|
524a6b1ffb | ||
|
|
7954adf7e3 | ||
|
|
0b31a08b9f | ||
|
|
a0884aa81c | ||
|
|
46f64d1a61 | ||
|
|
81cb6ad4fd | ||
|
|
f2f330e3e4 | ||
|
|
5b14670785 | ||
|
|
c5f68aa50f | ||
|
|
5203f89e9d | ||
|
|
8f11d73649 | ||
|
|
3d376e2a90 | ||
|
|
0e814c3359 | ||
|
|
4755cc3f7f | ||
|
|
7f1b1484ac | ||
|
|
ab1e6eed0c | ||
|
|
ba5cf81bb4 |
@@ -24,5 +24,10 @@ with open('CHANGELOG.md') as changelog:
|
||||
text.append(re.sub(r'\[(.*?)\]\((.*?)\)', r'\1 (\2)', line))
|
||||
|
||||
for version, description in changelogs.items():
|
||||
description = "".join(description).strip()
|
||||
|
||||
if not description:
|
||||
continue
|
||||
|
||||
with open(os.path.join("fastlane", "metadata", "android", "en-US", "changelogs", f"{version}.txt"), "w") as fastlane_file:
|
||||
fastlane_file.write("".join(description).strip())
|
||||
fastlane_file.write(description)
|
||||
|
||||
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,6 +1,36 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased - 89
|
||||
## v2.11.1 - 94 (2021-11-30)
|
||||
|
||||
- Fix blurriness of main screen letter icons
|
||||
- Fix icons sometimes disappearing after selection
|
||||
- Fix status bar icons possibly being invisible on Android 5
|
||||
|
||||
## v2.11.0 - 93 (2021-11-28)
|
||||
|
||||
- Add Catima to [Quick Access Device Controls](https://developer.android.com/guide/topics/ui/device-control)
|
||||
- Fix some groups not showing up correctly in group management screen
|
||||
|
||||
## v2.10.0 - 92 (2021-11-20)
|
||||
|
||||
- New main screen layout
|
||||
- Fix bottomsheet sizing issues when switching in and out of fullscreen
|
||||
|
||||
## v2.9.0 - 91 (2021-11-14)
|
||||
|
||||
- Improved group management support
|
||||
- Support cropping images
|
||||
- Fix image data loss when saving after rotating in edit view
|
||||
- Ability to set a custom image as card icon
|
||||
|
||||
## v2.8.1 - 90 (2021-10-27)
|
||||
|
||||
- Fix dots in card view having the wrong colour when changing theme manually
|
||||
- Fix crash in card view on rotation/theme change
|
||||
- Fix flashing of cards list
|
||||
- Fix text overlaying star icon
|
||||
|
||||
## v2.8.0 - 89 (2021-10-25)
|
||||
|
||||
- Fix swiping between groups not working on an empty group
|
||||
- Allow password-protecting exports
|
||||
|
||||
@@ -18,8 +18,8 @@ android {
|
||||
applicationId "me.hackerchick.catima"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
versionCode 89
|
||||
versionName "2.8.0"
|
||||
versionCode 94
|
||||
versionName "2.11.1"
|
||||
|
||||
vectorDrawables.useSupportLibrary true
|
||||
multiDexEnabled true
|
||||
@@ -49,8 +49,8 @@ android {
|
||||
// Flag to enable support for the new language APIs
|
||||
coreLibraryDesugaringEnabled true
|
||||
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
@@ -80,23 +80,25 @@ android {
|
||||
|
||||
dependencies {
|
||||
// AndroidX
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.3'
|
||||
implementation 'androidx.palette:palette:1.0.0'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'com.github.yalantis:ucrop:2.2.7'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
|
||||
// Splash Screen
|
||||
implementation 'androidx.core:core-splashscreen:1.0.0-alpha02'
|
||||
|
||||
// Third-party
|
||||
implementation 'com.journeyapps:zxing-android-embedded:4.2.0@aar'
|
||||
implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
|
||||
implementation 'com.google.zxing:core:3.4.1'
|
||||
implementation 'org.apache.commons:commons-csv:1.9.0'
|
||||
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
||||
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.3'
|
||||
implementation 'net.lingala.zip4j:zip4j:2.9.0'
|
||||
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.4'
|
||||
implementation 'net.lingala.zip4j:zip4j:2.9.1'
|
||||
|
||||
// SpotBugs
|
||||
implementation 'io.wcm.tooling.spotbugs:io.wcm.tooling.spotbugs.annotations:1.0.0'
|
||||
@@ -104,7 +106,7 @@ dependencies {
|
||||
// Testing
|
||||
testImplementation 'androidx.test:core:1.4.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.robolectric:robolectric:4.6.1'
|
||||
testImplementation 'org.robolectric:robolectric:4.7.2'
|
||||
}
|
||||
|
||||
tasks.withType(SpotBugsTask) {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="protect.card_locker"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="protect.card_locker">
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.CAMERA"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
@@ -17,8 +16,6 @@
|
||||
android:name="android.hardware.camera.autofocus"
|
||||
android:required="false" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android"/>
|
||||
|
||||
<application
|
||||
android:name=".LoyaltyCardLockerApplication"
|
||||
android:allowBackup="true"
|
||||
@@ -27,98 +24,117 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name="protect.card_locker.MainActivity"
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.App.Starting"
|
||||
android:exported="true">
|
||||
android:theme="@style/Theme.App.Starting">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".AboutActivity"
|
||||
android:label="@string/about"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
</activity>
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".ManageGroupsActivity"
|
||||
android:label="@string/groups"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
</activity>
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".ManageGroupActivity"
|
||||
android:label="@string/group_edit"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
<activity
|
||||
android:name=".LoyaltyCardViewActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:exported="true"/>
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
<activity
|
||||
android:name=".LoyaltyCardEditActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:exported="true">
|
||||
<intent-filter android:autoVerify="true" android:label="@string/app_name">
|
||||
android:windowSoftInputMode="stateHidden">
|
||||
<intent-filter
|
||||
android:autoVerify="true"
|
||||
android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Main card sharing URIs -->
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
|
||||
<data android:host="@string/intent_import_card_from_url_host_catima_app"
|
||||
<data
|
||||
android:host="@string/intent_import_card_from_url_host_catima_app"
|
||||
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_catima_app" />
|
||||
</intent-filter>
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Old card sharing URIs -->
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
|
||||
<data android:host="@string/intent_import_card_from_url_host_thelastproject"
|
||||
<data
|
||||
android:host="@string/intent_import_card_from_url_host_thelastproject"
|
||||
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_thelastproject" />
|
||||
<data android:host="@string/intent_import_card_from_url_host_brarcher"
|
||||
<data
|
||||
android:host="@string/intent_import_card_from_url_host_brarcher"
|
||||
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_brarcher" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ScanActivity"
|
||||
android:label="@string/scanCardBarcode"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".BarcodeSelectorActivity"
|
||||
android:label="@string/selectBarcodeTitle"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:windowSoftInputMode="stateHidden"/>
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
<activity
|
||||
android:name=".preferences.SettingsActivity"
|
||||
android:label="@string/settings"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".ImportExportActivity"
|
||||
android:label="@string/importExport"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".CardShortcutConfigure"
|
||||
android:exported="true"
|
||||
android:label="@string/cardShortcut"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:exported="true">
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<action android:name="android.intent.action.CREATE_SHORTCUT" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.yalantis.ucrop.UCropActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:grantUriPermissions="true"
|
||||
android:authorities="${applicationId}"
|
||||
android:exported="false"
|
||||
android:authorities="${applicationId}">
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_provider_paths"/>
|
||||
android:resource="@xml/file_provider_paths" />
|
||||
</provider>
|
||||
<service android:name=".CardsOnPowerScreenService" android:label="@string/app_name"
|
||||
android:permission="android.permission.BIND_CONTROLS" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.controls.ControlsProviderService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
</manifest>
|
||||
@@ -24,22 +24,19 @@ import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
|
||||
public class AboutActivity extends CatimaAppCompatActivity implements View.OnClickListener
|
||||
{
|
||||
public class AboutActivity extends CatimaAppCompatActivity implements View.OnClickListener {
|
||||
private static final String TAG = "Catima";
|
||||
ConstraintLayout version_history, translate, license, repo, privacy, error, credits, rate;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setTitle(R.string.about);
|
||||
setContentView(R.layout.about_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if(actionBar != null)
|
||||
{
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@@ -59,7 +56,8 @@ public class AboutActivity extends CatimaAppCompatActivity implements View.OnCli
|
||||
contributors.append("<br/>");
|
||||
contributors.append(tmp);
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
final List<ThirdPartyInfo> USED_LIBRARIES = new ArrayList<>();
|
||||
USED_LIBRARIES.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0"));
|
||||
@@ -73,14 +71,12 @@ public class AboutActivity extends CatimaAppCompatActivity implements View.OnCli
|
||||
USED_ASSETS.add(new ThirdPartyInfo("Android icons", "https://fonts.google.com/icons?selected=Material+Icons", "Apache 2.0"));
|
||||
|
||||
StringBuilder libs = new StringBuilder().append("<br/>");
|
||||
for (ThirdPartyInfo entry : USED_LIBRARIES)
|
||||
{
|
||||
for (ThirdPartyInfo entry : USED_LIBRARIES) {
|
||||
libs.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")");
|
||||
}
|
||||
|
||||
StringBuilder resources = new StringBuilder().append("<br/>");
|
||||
for (ThirdPartyInfo entry : USED_ASSETS)
|
||||
{
|
||||
for (ThirdPartyInfo entry : USED_ASSETS) {
|
||||
resources.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")");
|
||||
}
|
||||
|
||||
@@ -88,13 +84,10 @@ public class AboutActivity extends CatimaAppCompatActivity implements View.OnCli
|
||||
int year = Calendar.getInstance().get(Calendar.YEAR);
|
||||
|
||||
String version = "?";
|
||||
try
|
||||
{
|
||||
try {
|
||||
PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0);
|
||||
version = pi.versionName;
|
||||
}
|
||||
catch (PackageManager.NameNotFoundException e)
|
||||
{
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.w(TAG, "Package name not found", e);
|
||||
}
|
||||
|
||||
@@ -134,13 +127,13 @@ public class AboutActivity extends CatimaAppCompatActivity implements View.OnCli
|
||||
credits.setOnClickListener(view -> new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.credits)
|
||||
.setMessage(contributorInfo.toString())
|
||||
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {})
|
||||
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
})
|
||||
.show());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
finish();
|
||||
|
||||
@@ -6,45 +6,37 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
|
||||
/**
|
||||
* This activity is callable and will allow a user to enter
|
||||
* barcode data and generate all barcodes possible for
|
||||
* the data. The user may then select any barcode, where its
|
||||
* data and type will be returned to the caller.
|
||||
*/
|
||||
public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
|
||||
public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements BarcodeSelectorAdapter.BarcodeSelectorListener {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
// Result this activity will return
|
||||
public static final String BARCODE_CONTENTS = "contents";
|
||||
public static final String BARCODE_FORMAT = "format";
|
||||
|
||||
private Map<String, Pair<Integer, Integer>> barcodeViewMap;
|
||||
|
||||
final private TaskHandler mTasks = new TaskHandler();
|
||||
|
||||
private final Handler typingDelayHandler = new Handler(Looper.getMainLooper());
|
||||
public static final Integer INPUT_DELAY = 250;
|
||||
|
||||
private BarcodeSelectorAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -57,21 +49,10 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
barcodeViewMap = new HashMap<>();
|
||||
barcodeViewMap.put(BarcodeFormat.AZTEC.name(), new Pair<>(R.id.aztecBarcode, R.id.aztecBarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.CODE_39.name(), new Pair<>(R.id.code39Barcode, R.id.code39BarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.CODE_128.name(), new Pair<>(R.id.code128Barcode, R.id.code128BarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.CODABAR.name(), new Pair<>(R.id.codabarBarcode, R.id.codabarBarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.DATA_MATRIX.name(), new Pair<>(R.id.datamatrixBarcode, R.id.datamatrixBarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.EAN_8.name(), new Pair<>(R.id.ean8Barcode, R.id.ean8BarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.EAN_13.name(), new Pair<>(R.id.ean13Barcode, R.id.ean13BarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.ITF.name(), new Pair<>(R.id.itfBarcode, R.id.itfBarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.PDF_417.name(), new Pair<>(R.id.pdf417Barcode, R.id.pdf417BarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.QR_CODE.name(), new Pair<>(R.id.qrcodeBarcode, R.id.qrcodeBarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.UPC_A.name(), new Pair<>(R.id.upcaBarcode, R.id.upcaBarcodeText));
|
||||
barcodeViewMap.put(BarcodeFormat.UPC_E.name(), new Pair<>(R.id.upceBarcode, R.id.upceBarcodeText));
|
||||
|
||||
EditText cardId = findViewById(R.id.cardId);
|
||||
ListView mBarcodeList = findViewById(R.id.barcodes);
|
||||
mAdapter = new BarcodeSelectorAdapter(this, new ArrayList<>(), this);
|
||||
mBarcodeList.setAdapter(mAdapter);
|
||||
|
||||
cardId.addTextChangedListener(new SimpleTextWatcher() {
|
||||
@Override
|
||||
@@ -104,16 +85,13 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
private void generateBarcodes(String value) {
|
||||
// Attempt to stop any async tasks which may not have been started yet
|
||||
// TODO this can be very much optimized by only generating Barcodes visible to the User
|
||||
mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false);
|
||||
|
||||
// Update barcodes
|
||||
for (Map.Entry<String, Pair<Integer, Integer>> entry : barcodeViewMap.entrySet()) {
|
||||
ImageView image = findViewById(entry.getValue().first);
|
||||
TextView text = findViewById(entry.getValue().second);
|
||||
createBarcodeOption(image, entry.getKey(), value, text);
|
||||
ArrayList<CatimaBarcodeWithValue> barcodes = new ArrayList<>();
|
||||
for (BarcodeFormat barcodeFormat : CatimaBarcode.barcodeFormats) {
|
||||
CatimaBarcode catimaBarcode = CatimaBarcode.fromBarcode(barcodeFormat);
|
||||
barcodes.add(new CatimaBarcodeWithValue(catimaBarcode, value));
|
||||
}
|
||||
mAdapter.setBarcodes(barcodes);
|
||||
}
|
||||
|
||||
private void setButtonListener(final View button, final String cardId) {
|
||||
@@ -127,48 +105,6 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void createBarcodeOption(final ImageView image, final String formatType, final String cardId, final TextView text) {
|
||||
final CatimaBarcode format = CatimaBarcode.fromName(formatType);
|
||||
|
||||
image.setImageBitmap(null);
|
||||
image.setOnClickListener(v -> {
|
||||
Log.d(TAG, "Selected barcode type " + formatType);
|
||||
|
||||
if (!((boolean) image.getTag())) {
|
||||
Toast.makeText(BarcodeSelectorActivity.this, getString(R.string.wrongValueForBarcodeType), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Intent result = new Intent();
|
||||
result.putExtra(BARCODE_FORMAT, formatType);
|
||||
result.putExtra(BARCODE_CONTENTS, cardId);
|
||||
BarcodeSelectorActivity.this.setResult(RESULT_OK, result);
|
||||
finish();
|
||||
});
|
||||
|
||||
if (image.getHeight() == 0) {
|
||||
// The size of the ImageView is not yet available as it has not
|
||||
// yet been drawn. Wait for it to be drawn so the size is available.
|
||||
image.getViewTreeObserver().addOnGlobalLayoutListener(
|
||||
new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
Log.d(TAG, "Global layout finished, type: + " + formatType + ", width: " + image.getWidth());
|
||||
image.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
|
||||
Log.d(TAG, "Generating barcode for type " + formatType);
|
||||
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), image, cardId, format, text, true, null);
|
||||
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.d(TAG, "Generating barcode for type " + formatType);
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), image, cardId, format, text, true, null);
|
||||
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
@@ -179,4 +115,26 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity {
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRowClicked(int inputPosition, View view) {
|
||||
CatimaBarcodeWithValue barcodeWithValue = mAdapter.getItem(inputPosition);
|
||||
CatimaBarcode catimaBarcode = barcodeWithValue.catimaBarcode();
|
||||
|
||||
if (!mAdapter.isValid(view)) {
|
||||
Toast.makeText(this, getString(R.string.wrongValueForBarcodeType), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
String barcodeFormat = catimaBarcode.format().name();
|
||||
String value = barcodeWithValue.value();
|
||||
|
||||
Log.d(TAG, "Selected barcode type " + barcodeFormat);
|
||||
|
||||
Intent result = new Intent();
|
||||
result.putExtra(BARCODE_FORMAT, barcodeFormat);
|
||||
result.putExtra(BARCODE_CONTENTS, value);
|
||||
BarcodeSelectorActivity.this.setResult(RESULT_OK, result);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
|
||||
public class BarcodeSelectorAdapter extends ArrayAdapter<CatimaBarcodeWithValue> {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private final TaskHandler mTasks = new TaskHandler();
|
||||
private final BarcodeSelectorListener mListener;
|
||||
|
||||
private static class ViewHolder {
|
||||
ImageView image;
|
||||
TextView text;
|
||||
}
|
||||
|
||||
public interface BarcodeSelectorListener {
|
||||
void onRowClicked(int inputPosition, View view);
|
||||
}
|
||||
|
||||
public BarcodeSelectorAdapter(Context context, ArrayList<CatimaBarcodeWithValue> barcodes, BarcodeSelectorListener barcodeSelectorListener) {
|
||||
super(context, 0, barcodes);
|
||||
mListener = barcodeSelectorListener;
|
||||
}
|
||||
|
||||
public void setBarcodes(ArrayList<CatimaBarcodeWithValue> barcodes) {
|
||||
clear();
|
||||
addAll(barcodes);
|
||||
notifyDataSetChanged();
|
||||
mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
CatimaBarcodeWithValue catimaBarcodeWithValue = getItem(position);
|
||||
CatimaBarcode catimaBarcode = catimaBarcodeWithValue.catimaBarcode();
|
||||
String value = catimaBarcodeWithValue.value();
|
||||
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
viewHolder = new ViewHolder();
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
convertView = inflater.inflate(R.layout.barcode_layout, parent, false);
|
||||
viewHolder.image = convertView.findViewById(R.id.barcodeImage);
|
||||
viewHolder.text = convertView.findViewById(R.id.barcodeName);
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
createBarcodeOption(viewHolder.image, catimaBarcode.format().name(), value, viewHolder.text);
|
||||
|
||||
View finalConvertView = convertView;
|
||||
convertView.setOnClickListener(view -> mListener.onRowClicked(position, finalConvertView));
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
public boolean isValid(View view) {
|
||||
ViewHolder viewHolder = (ViewHolder) view.getTag();
|
||||
return viewHolder.image.getTag() != null && (boolean) viewHolder.image.getTag();
|
||||
}
|
||||
|
||||
private void createBarcodeOption(final ImageView image, final String formatType, final String cardId, final TextView text) {
|
||||
final CatimaBarcode format = CatimaBarcode.fromName(formatType);
|
||||
|
||||
image.setImageBitmap(null);
|
||||
|
||||
if (image.getHeight() == 0) {
|
||||
// The size of the ImageView is not yet available as it has not
|
||||
// yet been drawn. Wait for it to be drawn so the size is available.
|
||||
image.getViewTreeObserver().addOnGlobalLayoutListener(
|
||||
new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
Log.d(TAG, "Global layout finished, type: + " + formatType + ", width: " + image.getWidth());
|
||||
image.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
|
||||
Log.d(TAG, "Generating barcode for type " + formatType);
|
||||
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getContext(), image, cardId, format, text, true, null);
|
||||
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.d(TAG, "Generating barcode for type " + formatType);
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getContext(), image, cardId, format, text, true, null);
|
||||
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,30 +4,30 @@ import android.database.Cursor;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V>
|
||||
{
|
||||
private Cursor mCursor;
|
||||
public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V> {
|
||||
public Cursor mCursor;
|
||||
private boolean mDataValid;
|
||||
private int mRowIDColumn;
|
||||
|
||||
public BaseCursorAdapter(Cursor inputCursor)
|
||||
{
|
||||
private String mRowIDColumnName;
|
||||
|
||||
public BaseCursorAdapter(Cursor inputCursor, String rowIDColumnName) {
|
||||
setHasStableIds(true);
|
||||
|
||||
mRowIDColumnName = rowIDColumnName;
|
||||
|
||||
swapCursor(inputCursor);
|
||||
}
|
||||
|
||||
public abstract void onBindViewHolder(V inputHolder, Cursor inputCursor);
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(V inputHolder, int inputPosition)
|
||||
{
|
||||
if (!mDataValid)
|
||||
{
|
||||
public void onBindViewHolder(V inputHolder, int inputPosition) {
|
||||
if (!mDataValid) {
|
||||
throw new IllegalStateException("Cannot bind view holder when cursor is in invalid state.");
|
||||
}
|
||||
|
||||
if (!mCursor.moveToPosition(inputPosition))
|
||||
{
|
||||
if (!mCursor.moveToPosition(inputPosition)) {
|
||||
throw new IllegalStateException("Could not move cursor to position " + inputPosition + " when trying to bind view holder");
|
||||
}
|
||||
|
||||
@@ -35,49 +35,38 @@ public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> exten
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
if (mDataValid)
|
||||
{
|
||||
public int getItemCount() {
|
||||
if (mDataValid) {
|
||||
return mCursor.getCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int inputPosition)
|
||||
{
|
||||
if (!mDataValid)
|
||||
{
|
||||
public long getItemId(int inputPosition) {
|
||||
if (!mDataValid) {
|
||||
throw new IllegalStateException("Cannot lookup item id when cursor is in invalid state.");
|
||||
}
|
||||
|
||||
if (!mCursor.moveToPosition(inputPosition))
|
||||
{
|
||||
if (!mCursor.moveToPosition(inputPosition)) {
|
||||
throw new IllegalStateException("Could not move cursor to position " + inputPosition + " when trying to get an item id");
|
||||
}
|
||||
|
||||
return mCursor.getLong(mRowIDColumn);
|
||||
}
|
||||
|
||||
public void swapCursor(Cursor inputCursor)
|
||||
{
|
||||
if (inputCursor == mCursor)
|
||||
{
|
||||
public void swapCursor(Cursor inputCursor) {
|
||||
if (inputCursor == mCursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputCursor != null)
|
||||
{
|
||||
if (inputCursor != null) {
|
||||
mCursor = inputCursor;
|
||||
mRowIDColumn = mCursor.getColumnIndex(mRowIDColumnName);
|
||||
mDataValid = true;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
notifyItemRangeRemoved(0, getItemCount());
|
||||
mCursor = null;
|
||||
mRowIDColumn = -1;
|
||||
|
||||
@@ -19,8 +19,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
/**
|
||||
* The configuration screen for creating a shortcut.
|
||||
*/
|
||||
public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener
|
||||
{
|
||||
public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener {
|
||||
static final String TAG = "Catima";
|
||||
final DBHelper mDb = new DBHelper(this);
|
||||
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
import android.service.controls.Control;
|
||||
import android.service.controls.ControlsProviderService;
|
||||
import android.service.controls.DeviceTypes;
|
||||
import android.service.controls.actions.ControlAction;
|
||||
import android.service.controls.templates.StatelessTemplate;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
public class CardsOnPowerScreenService extends ControlsProviderService {
|
||||
|
||||
public static final String PREFIX = "catima-";
|
||||
static final String TAG = "Catima";
|
||||
private final DBHelper dbHelper = new DBHelper(this);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Flow.Publisher<Control> createPublisherForAllAvailable() {
|
||||
Cursor loyaltyCardCursor = dbHelper.getLoyaltyCardCursor();
|
||||
return subscriber -> {
|
||||
while (loyaltyCardCursor.moveToNext()) {
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(loyaltyCardCursor);
|
||||
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra("id", card.id);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), card.id, openIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
subscriber.onNext(
|
||||
new Control.StatelessBuilder(PREFIX + card.id, pendingIntent)
|
||||
.setControlId(PREFIX + card.id)
|
||||
.setTitle(card.store)
|
||||
.setDeviceType(DeviceTypes.TYPE_GENERIC_OPEN_CLOSE)
|
||||
.setSubtitle(card.note)
|
||||
.setCustomIcon(Icon.createWithBitmap(getIcon(this, card)))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
subscriber.onComplete();
|
||||
};
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Flow.Publisher<Control> createPublisherFor(@NonNull List<String> controlIds) {
|
||||
return subscriber -> {
|
||||
subscriber.onSubscribe(new NoOpSubscription());
|
||||
for (String controlId : controlIds) {
|
||||
Control control;
|
||||
|
||||
try {
|
||||
Integer cardId = this.controlIdToCardId(controlId);
|
||||
LoyaltyCard card = dbHelper.getLoyaltyCard(cardId);
|
||||
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra("id", card.id);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), card.id, openIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
control = new Control.StatefulBuilder(controlId, pendingIntent)
|
||||
.setTitle(card.store)
|
||||
.setDeviceType(DeviceTypes.TYPE_GENERIC_OPEN_CLOSE)
|
||||
.setSubtitle(card.note)
|
||||
.setStatus(Control.STATUS_OK)
|
||||
.setControlTemplate(new StatelessTemplate(controlId))
|
||||
.setCustomIcon(Icon.createWithBitmap(getIcon(this, card)))
|
||||
.build();
|
||||
} catch (NullPointerException ignored) {
|
||||
Intent mainScreenIntent = new Intent(this, MainActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), -1, mainScreenIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
control = new Control.StatefulBuilder(controlId, pendingIntent)
|
||||
.setStatus(Control.STATUS_NOT_FOUND)
|
||||
.build();
|
||||
}
|
||||
Log.d(TAG, "Dispatching widget " + controlId);
|
||||
subscriber.onNext(control);
|
||||
}
|
||||
subscriber.onComplete();
|
||||
};
|
||||
}
|
||||
|
||||
private Bitmap getIcon(Context context, LoyaltyCard loyaltyCard) {
|
||||
Bitmap cardIcon = Utils.retrieveCardImage(context, loyaltyCard.id, ImageLocationType.icon);
|
||||
|
||||
if (cardIcon != null) {
|
||||
return cardIcon;
|
||||
}
|
||||
|
||||
return Utils.generateIcon(this, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile();
|
||||
}
|
||||
|
||||
private Integer controlIdToCardId(String controlId) {
|
||||
if (controlId == null)
|
||||
return null;
|
||||
if (!controlId.startsWith(PREFIX)) {
|
||||
Log.w(TAG, "Unsupported control ID format: " + controlId);
|
||||
return null;
|
||||
}
|
||||
controlId = controlId.substring(PREFIX.length());
|
||||
try {
|
||||
return Integer.parseInt(controlId);
|
||||
} catch (RuntimeException ex) {
|
||||
Log.e(TAG, "Unsupported control ID format. Expected numeric after prefix, found: " + controlId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performControlAction(@NonNull String controlId, @NonNull ControlAction action, @NonNull Consumer<Integer> consumer) {
|
||||
consumer.accept(ControlAction.RESPONSE_OK);
|
||||
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra("id", controlIdToCardId(controlId));
|
||||
startActivity(openIntent);
|
||||
|
||||
closePowerScreenOnAndroid11();
|
||||
}
|
||||
|
||||
@SuppressLint({"MissingPermission", "deprecation"})
|
||||
private void closePowerScreenOnAndroid11() {
|
||||
// Android 12 will auto-close the power screen, but earlier versions won't
|
||||
// Lint complains about this but on Android 11 the permission is not needed
|
||||
// On Android 12, we don't need it, and Google will probably get angry if we ask for it
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
||||
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A no-op subscription.
|
||||
* <p>
|
||||
* Flow.Subscriptions are made to last during time and receive periodic updates.
|
||||
* Our app does not require sending periodic updates of loyalty cards, so we are just ignoring anything in the subscription
|
||||
* Also, our db is quick enough to respond that the Publisher is immediately sending and completing data.
|
||||
* This facility is overkill, but if we don't call onSubscribe the service won't work
|
||||
*/
|
||||
private static class NoOpSubscription implements Flow.Subscription {
|
||||
@Override
|
||||
public void request(long l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,33 +8,33 @@ import java.util.List;
|
||||
|
||||
public class CatimaBarcode {
|
||||
public static final List<BarcodeFormat> barcodeFormats = Collections.unmodifiableList(Arrays.asList(
|
||||
BarcodeFormat.AZTEC,
|
||||
BarcodeFormat.CODE_39,
|
||||
BarcodeFormat.CODE_128,
|
||||
BarcodeFormat.CODABAR,
|
||||
BarcodeFormat.DATA_MATRIX,
|
||||
BarcodeFormat.EAN_8,
|
||||
BarcodeFormat.EAN_13,
|
||||
BarcodeFormat.ITF,
|
||||
BarcodeFormat.PDF_417,
|
||||
BarcodeFormat.QR_CODE,
|
||||
BarcodeFormat.UPC_A,
|
||||
BarcodeFormat.UPC_E
|
||||
BarcodeFormat.AZTEC,
|
||||
BarcodeFormat.CODE_39,
|
||||
BarcodeFormat.CODE_128,
|
||||
BarcodeFormat.CODABAR,
|
||||
BarcodeFormat.DATA_MATRIX,
|
||||
BarcodeFormat.EAN_8,
|
||||
BarcodeFormat.EAN_13,
|
||||
BarcodeFormat.ITF,
|
||||
BarcodeFormat.PDF_417,
|
||||
BarcodeFormat.QR_CODE,
|
||||
BarcodeFormat.UPC_A,
|
||||
BarcodeFormat.UPC_E
|
||||
));
|
||||
|
||||
public static final List<String> barcodePrettyNames = Collections.unmodifiableList(Arrays.asList(
|
||||
"Aztec",
|
||||
"Code 39",
|
||||
"Code 128",
|
||||
"Codabar",
|
||||
"Data Matrix",
|
||||
"EAN 8",
|
||||
"EAN 13",
|
||||
"ITF",
|
||||
"PDF 417",
|
||||
"QR Code",
|
||||
"UPC A",
|
||||
"UPC E"
|
||||
"Aztec",
|
||||
"Code 39",
|
||||
"Code 128",
|
||||
"Codabar",
|
||||
"Data Matrix",
|
||||
"EAN 8",
|
||||
"EAN 13",
|
||||
"ITF",
|
||||
"PDF 417",
|
||||
"QR Code",
|
||||
"UPC A",
|
||||
"UPC E"
|
||||
));
|
||||
|
||||
private final BarcodeFormat mBarcodeFormat;
|
||||
@@ -63,7 +63,7 @@ public class CatimaBarcode {
|
||||
return barcodeFormats.contains(mBarcodeFormat);
|
||||
}
|
||||
|
||||
public boolean isSquare(){
|
||||
public boolean isSquare() {
|
||||
return mBarcodeFormat == BarcodeFormat.AZTEC
|
||||
|| mBarcodeFormat == BarcodeFormat.DATA_MATRIX
|
||||
|| mBarcodeFormat == BarcodeFormat.MAXICODE
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package protect.card_locker;
|
||||
|
||||
public class CatimaBarcodeWithValue {
|
||||
private final CatimaBarcode mCatimaBarcode;
|
||||
private final String mValue;
|
||||
|
||||
public CatimaBarcodeWithValue(CatimaBarcode catimaBarcode, String value) {
|
||||
mCatimaBarcode = catimaBarcode;
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public CatimaBarcode catimaBarcode() {
|
||||
return mCatimaBarcode;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return mValue;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,25 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.journeyapps.barcodescanner.CaptureManager;
|
||||
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
|
||||
|
||||
public class CatimaCaptureManager extends CaptureManager {
|
||||
private Activity activity;
|
||||
private final Context mContext;
|
||||
|
||||
public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
|
||||
super(activity, barcodeView);
|
||||
|
||||
this.activity = activity;
|
||||
mContext = activity.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayFrameworkBugMessageAndExit(String message) {
|
||||
// We don't want to exit, as we also have a enter from card image and add manually button here
|
||||
// So we show a toast instead
|
||||
Toast.makeText(activity, message, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,21 +18,18 @@ import java.util.Currency;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class DBHelper extends SQLiteOpenHelper
|
||||
{
|
||||
public class DBHelper extends SQLiteOpenHelper {
|
||||
public static final String DATABASE_NAME = "Catima.db";
|
||||
public static final int ORIGINAL_DATABASE_VERSION = 1;
|
||||
public static final int DATABASE_VERSION = 14;
|
||||
|
||||
public static class LoyaltyCardDbGroups
|
||||
{
|
||||
public static class LoyaltyCardDbGroups {
|
||||
public static final String TABLE = "groups";
|
||||
public static final String ID = "_id";
|
||||
public static final String ORDER = "orderId";
|
||||
}
|
||||
|
||||
public static class LoyaltyCardDbIds
|
||||
{
|
||||
public static class LoyaltyCardDbIds {
|
||||
public static final String TABLE = "cards";
|
||||
public static final String ID = "_id";
|
||||
public static final String STORE = "store";
|
||||
@@ -50,15 +47,13 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
public static final String ZOOM_LEVEL = "zoomlevel";
|
||||
}
|
||||
|
||||
public static class LoyaltyCardDbIdsGroups
|
||||
{
|
||||
public static class LoyaltyCardDbIdsGroups {
|
||||
public static final String TABLE = "cardsGroups";
|
||||
public static final String cardID = "cardId";
|
||||
public static final String groupID = "groupId";
|
||||
}
|
||||
|
||||
public static class LoyaltyCardDbFTS
|
||||
{
|
||||
public static class LoyaltyCardDbFTS {
|
||||
public static final String TABLE = "fts";
|
||||
public static final String ID = "rowid"; // This should NEVER be changed
|
||||
public static final String STORE = "store";
|
||||
@@ -76,18 +71,12 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
Descending
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
|
||||
public DBHelper(Context context)
|
||||
{
|
||||
public DBHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db)
|
||||
{
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
// create table for card groups
|
||||
db.execSQL("CREATE TABLE " + LoyaltyCardDbGroups.TABLE + "(" +
|
||||
LoyaltyCardDbGroups.ID + " TEXT primary key not null," +
|
||||
@@ -107,14 +96,14 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
LoyaltyCardDbIds.BARCODE_ID + " TEXT," +
|
||||
LoyaltyCardDbIds.BARCODE_TYPE + " TEXT," +
|
||||
LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0'," +
|
||||
LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0', "+
|
||||
LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0', " +
|
||||
LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '100' )");
|
||||
|
||||
// create associative table for cards in groups
|
||||
db.execSQL("CREATE TABLE " + LoyaltyCardDbIdsGroups.TABLE + "(" +
|
||||
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
|
||||
LoyaltyCardDbIdsGroups.groupID + " TEXT," +
|
||||
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID +"))");
|
||||
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID + "))");
|
||||
|
||||
// create FTS search table
|
||||
db.execSQL("CREATE VIRTUAL TABLE " + LoyaltyCardDbFTS.TABLE + " USING fts4(" +
|
||||
@@ -124,67 +113,57 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
|
||||
{
|
||||
if(oldVersion < 2 && newVersion >= 2)
|
||||
{
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion < 2 && newVersion >= 2) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.NOTE + " TEXT not null default ''");
|
||||
}
|
||||
|
||||
if(oldVersion < 3 && newVersion >= 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");
|
||||
}
|
||||
|
||||
if(oldVersion < 4 && newVersion >= 4)
|
||||
{
|
||||
if (oldVersion < 4 && newVersion >= 4) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0'");
|
||||
}
|
||||
|
||||
if(oldVersion < 5 && newVersion >= 5)
|
||||
{
|
||||
if (oldVersion < 5 && newVersion >= 5) {
|
||||
db.execSQL("CREATE TABLE " + LoyaltyCardDbGroups.TABLE + "(" +
|
||||
LoyaltyCardDbGroups.ID + " TEXT primary key not null)");
|
||||
|
||||
db.execSQL("CREATE TABLE " + LoyaltyCardDbIdsGroups.TABLE + "(" +
|
||||
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
|
||||
LoyaltyCardDbIdsGroups.groupID + " TEXT," +
|
||||
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID +"))");
|
||||
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID + "))");
|
||||
}
|
||||
|
||||
if(oldVersion < 6 && newVersion >= 6)
|
||||
{
|
||||
if (oldVersion < 6 && newVersion >= 6) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbGroups.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbGroups.ORDER + " INTEGER DEFAULT '0'");
|
||||
}
|
||||
|
||||
if(oldVersion < 7 && newVersion >= 7)
|
||||
{
|
||||
if (oldVersion < 7 && newVersion >= 7) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.EXPIRY + " INTEGER");
|
||||
}
|
||||
|
||||
if(oldVersion < 8 && newVersion >= 8)
|
||||
{
|
||||
if (oldVersion < 8 && newVersion >= 8) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.BALANCE + " TEXT not null DEFAULT '0'");
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.BALANCE_TYPE + " TEXT");
|
||||
}
|
||||
|
||||
if(oldVersion < 9 && newVersion >= 9)
|
||||
{
|
||||
if (oldVersion < 9 && newVersion >= 9) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.BARCODE_ID + " TEXT");
|
||||
}
|
||||
|
||||
if(oldVersion < 10 && newVersion >= 10)
|
||||
{
|
||||
if (oldVersion < 10 && newVersion >= 10) {
|
||||
// SQLite doesn't support modify column
|
||||
// So we need to create a temp column to make barcode type nullable
|
||||
// Let's drop header text colour too while we're at it
|
||||
@@ -277,14 +256,12 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
if(oldVersion < 11 && newVersion >= 11)
|
||||
{
|
||||
if (oldVersion < 11 && newVersion >= 11) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0'");
|
||||
}
|
||||
|
||||
if(oldVersion < 12 && newVersion >= 12)
|
||||
{
|
||||
if (oldVersion < 12 && newVersion >= 12) {
|
||||
db.execSQL("CREATE VIRTUAL TABLE " + LoyaltyCardDbFTS.TABLE + " USING fts4(" +
|
||||
LoyaltyCardDbFTS.STORE + ", " + LoyaltyCardDbFTS.NOTE + ", " +
|
||||
"tokenize=unicode61);");
|
||||
@@ -301,8 +278,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
}
|
||||
}
|
||||
|
||||
if(oldVersion < 13 && newVersion >= 13)
|
||||
{
|
||||
if (oldVersion < 13 && newVersion >= 13) {
|
||||
db.execSQL("DELETE FROM " + LoyaltyCardDbFTS.TABLE + ";");
|
||||
|
||||
Cursor cursor = db.rawQuery("SELECT * FROM " + LoyaltyCardDbIds.TABLE + ";", null, null);
|
||||
@@ -323,7 +299,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
if(oldVersion < 14 && newVersion >= 14){
|
||||
if (oldVersion < 14 && newVersion >= 14) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '100' ");
|
||||
}
|
||||
@@ -374,8 +350,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
final BigDecimal balance, final Currency balanceType,
|
||||
final String cardId, final String barcodeId,
|
||||
final CatimaBarcode barcodeType, final Integer headerColor,
|
||||
final int starStatus, final Long lastUsed)
|
||||
{
|
||||
final int starStatus, final Long lastUsed) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
@@ -408,8 +383,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
final Currency balanceType, final String cardId,
|
||||
final String barcodeId, final CatimaBarcode barcodeType,
|
||||
final Integer headerColor, final int starStatus,
|
||||
final Long lastUsed)
|
||||
{
|
||||
final Long lastUsed) {
|
||||
db.beginTransaction();
|
||||
|
||||
// Card
|
||||
@@ -441,8 +415,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
final Currency balanceType, final String cardId,
|
||||
final String barcodeId, final CatimaBarcode barcodeType,
|
||||
final Integer headerColor, final int starStatus,
|
||||
final Long lastUsed)
|
||||
{
|
||||
final Long lastUsed) {
|
||||
db.beginTransaction();
|
||||
|
||||
// Card
|
||||
@@ -474,8 +447,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
final Date expiry, final BigDecimal balance,
|
||||
final Currency balanceType, final String cardId,
|
||||
final String barcodeId, final CatimaBarcode barcodeType,
|
||||
final Integer headerColor)
|
||||
{
|
||||
final Integer headerColor) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
@@ -502,11 +474,10 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return (rowsUpdated == 1);
|
||||
}
|
||||
|
||||
public boolean updateLoyaltyCardStarStatus(final int id, final int starStatus)
|
||||
{
|
||||
public boolean updateLoyaltyCardStarStatus(final int id, final int starStatus) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS,starStatus);
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
|
||||
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE, contentValues,
|
||||
whereAttrs(LoyaltyCardDbIds.ID),
|
||||
withArgs(id));
|
||||
@@ -523,27 +494,25 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return (rowsUpdated == 1);
|
||||
}
|
||||
|
||||
public boolean updateLoyaltyCardZoomLevel(int loyaltyCardId, int zoomLevel){
|
||||
public boolean updateLoyaltyCardZoomLevel(int loyaltyCardId, int zoomLevel) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbIds.ZOOM_LEVEL,zoomLevel);
|
||||
Log.d("updateLoyaltyCardZLevel","Card Id = "+loyaltyCardId+" Zoom level= "+zoomLevel);
|
||||
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE,contentValues,
|
||||
contentValues.put(LoyaltyCardDbIds.ZOOM_LEVEL, zoomLevel);
|
||||
Log.d("updateLoyaltyCardZLevel", "Card Id = " + loyaltyCardId + " Zoom level= " + zoomLevel);
|
||||
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE, contentValues,
|
||||
whereAttrs(LoyaltyCardDbIds.ID),
|
||||
withArgs(loyaltyCardId));
|
||||
Log.d("updateLoyaltyCardZLevel","Rows changed = "+rowsUpdated);
|
||||
Log.d("updateLoyaltyCardZLevel", "Rows changed = " + rowsUpdated);
|
||||
return (rowsUpdated == 1);
|
||||
}
|
||||
|
||||
public LoyaltyCard getLoyaltyCard(final int id)
|
||||
{
|
||||
public LoyaltyCard getLoyaltyCard(final int id) {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor data = db.query(LoyaltyCardDbIds.TABLE, null, whereAttrs(LoyaltyCardDbIds.ID), withArgs(id), null, null, null);
|
||||
|
||||
LoyaltyCard card = null;
|
||||
|
||||
if(data.getCount() == 1)
|
||||
{
|
||||
if (data.getCount() == 1) {
|
||||
data.moveToFirst();
|
||||
card = LoyaltyCard.toLoyaltyCard(data);
|
||||
}
|
||||
@@ -553,8 +522,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return card;
|
||||
}
|
||||
|
||||
public List<Group> getLoyaltyCardGroups(final int id)
|
||||
{
|
||||
public List<Group> getLoyaltyCardGroups(final int id) {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor data = db.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE + " g " +
|
||||
" LEFT JOIN " + LoyaltyCardDbIdsGroups.TABLE + " ig ON ig." + LoyaltyCardDbIdsGroups.groupID + " = g." + LoyaltyCardDbGroups.ID +
|
||||
@@ -579,8 +547,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return groups;
|
||||
}
|
||||
|
||||
public void setLoyaltyCardGroups(final int id, List<Group> groups)
|
||||
{
|
||||
public void setLoyaltyCardGroups(final int id, List<Group> groups) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
|
||||
// First delete lookup table entries associated with this card
|
||||
@@ -597,8 +564,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
}
|
||||
}
|
||||
|
||||
public void setLoyaltyCardGroups(final SQLiteDatabase db, final int id, List<Group> groups)
|
||||
{
|
||||
public void setLoyaltyCardGroups(final SQLiteDatabase db, final int id, List<Group> groups) {
|
||||
// First delete lookup table entries associated with this card
|
||||
db.delete(LoyaltyCardDbIdsGroups.TABLE,
|
||||
whereAttrs(LoyaltyCardDbIdsGroups.cardID),
|
||||
@@ -613,8 +579,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
}
|
||||
}
|
||||
|
||||
public boolean deleteLoyaltyCard(final int id)
|
||||
{
|
||||
public boolean deleteLoyaltyCard(Context context, final int id) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
// Delete card
|
||||
int rowsDeleted = db.delete(LoyaltyCardDbIds.TABLE,
|
||||
@@ -632,18 +597,18 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
withArgs(id));
|
||||
|
||||
// Also wipe card images associated with this card
|
||||
try {
|
||||
Utils.saveCardImage(mContext, null, id, true);
|
||||
Utils.saveCardImage(mContext, null, id, false);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
|
||||
try {
|
||||
Utils.saveCardImage(context, null, id, imageLocationType);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return (rowsDeleted == 1);
|
||||
}
|
||||
|
||||
public Cursor getLoyaltyCardCursor()
|
||||
{
|
||||
public Cursor getLoyaltyCardCursor() {
|
||||
// An empty string will match everything
|
||||
return getLoyaltyCardCursor("");
|
||||
}
|
||||
@@ -654,8 +619,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
* @param filter
|
||||
* @return Cursor
|
||||
*/
|
||||
public Cursor getLoyaltyCardCursor(final String filter)
|
||||
{
|
||||
public Cursor getLoyaltyCardCursor(final String filter) {
|
||||
return getLoyaltyCardCursor(filter, null);
|
||||
}
|
||||
|
||||
@@ -666,8 +630,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
* @param group
|
||||
* @return Cursor
|
||||
*/
|
||||
public Cursor getLoyaltyCardCursor(final String filter, Group group)
|
||||
{
|
||||
public Cursor getLoyaltyCardCursor(final String filter, Group group) {
|
||||
return getLoyaltyCardCursor(filter, group, LoyaltyCardOrder.Alpha, LoyaltyCardOrderDirection.Ascending);
|
||||
}
|
||||
|
||||
@@ -715,7 +678,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
" (CASE WHEN " + LoyaltyCardDbIds.TABLE + "." + orderField + " IS NULL THEN 1 ELSE 0 END), " +
|
||||
LoyaltyCardDbIds.TABLE + "." + orderField + " COLLATE NOCASE " + getDbDirection(order, direction) + ", " +
|
||||
LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC " +
|
||||
limitString, filter.trim().isEmpty() ? null : new String[] { TextUtils.join("* ", filter.split(" ")) + '*' }, null);
|
||||
limitString, filter.trim().isEmpty() ? null : new String[]{TextUtils.join("* ", filter.split(" ")) + '*'}, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -723,8 +686,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
*
|
||||
* @return Integer
|
||||
*/
|
||||
public int getLoyaltyCardCount()
|
||||
{
|
||||
public int getLoyaltyCardCount() {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbIds.TABLE);
|
||||
}
|
||||
@@ -734,8 +696,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
*
|
||||
* @return Cursor
|
||||
*/
|
||||
public Cursor getGroupCursor()
|
||||
{
|
||||
public Cursor getGroupCursor() {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
|
||||
return db.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE +
|
||||
@@ -761,13 +722,11 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return groups;
|
||||
}
|
||||
|
||||
public void reorderGroups(final List<Group> groups)
|
||||
{
|
||||
public void reorderGroups(final List<Group> groups) {
|
||||
Integer order = 0;
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
|
||||
for (Group group : groups)
|
||||
{
|
||||
for (Group group : groups) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbGroups.ORDER, order);
|
||||
|
||||
@@ -779,15 +738,13 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
}
|
||||
}
|
||||
|
||||
public Group getGroup(final String groupName)
|
||||
{
|
||||
public Group getGroup(final String groupName) {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor data = db.query(LoyaltyCardDbGroups.TABLE, null,
|
||||
whereAttrs(LoyaltyCardDbGroups.ID), withArgs(groupName), null, null, null);
|
||||
|
||||
Group group = null;
|
||||
if(data.getCount() == 1)
|
||||
{
|
||||
if (data.getCount() == 1) {
|
||||
data.moveToFirst();
|
||||
group = Group.toGroup(data);
|
||||
}
|
||||
@@ -796,14 +753,12 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return group;
|
||||
}
|
||||
|
||||
public int getGroupCount()
|
||||
{
|
||||
public int getGroupCount() {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbGroups.TABLE);
|
||||
}
|
||||
|
||||
public List<Integer> getGroupCardIds(final String groupName)
|
||||
{
|
||||
public List<Integer> getGroupCardIds(final String groupName) {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor data = db.query(LoyaltyCardDbIdsGroups.TABLE, withArgs(LoyaltyCardDbIdsGroups.cardID),
|
||||
whereAttrs(LoyaltyCardDbIdsGroups.groupID), withArgs(groupName), null, null, null);
|
||||
@@ -824,8 +779,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return cardIds;
|
||||
}
|
||||
|
||||
public long insertGroup(final String name)
|
||||
{
|
||||
public long insertGroup(final String name) {
|
||||
if (name.isEmpty()) return -1;
|
||||
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
@@ -835,8 +789,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return db.insert(LoyaltyCardDbGroups.TABLE, null, contentValues);
|
||||
}
|
||||
|
||||
public boolean insertGroup(final SQLiteDatabase db, final String name)
|
||||
{
|
||||
public boolean insertGroup(final SQLiteDatabase db, final String name) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbGroups.ID, name);
|
||||
contentValues.put(LoyaltyCardDbGroups.ORDER, getGroupCount());
|
||||
@@ -844,8 +797,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return newId != -1;
|
||||
}
|
||||
|
||||
public boolean updateGroup(final String groupName, final String newName)
|
||||
{
|
||||
public boolean updateGroup(final String groupName, final String newName) {
|
||||
if (newName.isEmpty()) return false;
|
||||
|
||||
boolean success = false;
|
||||
@@ -881,8 +833,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean deleteGroup(final String groupName)
|
||||
{
|
||||
public boolean deleteGroup(final String groupName) {
|
||||
boolean success = false;
|
||||
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
@@ -913,8 +864,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
return success;
|
||||
}
|
||||
|
||||
public int getGroupCardCount(final String groupName)
|
||||
{
|
||||
public int getGroupCardCount(final String groupName) {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
|
||||
return (int) DatabaseUtils.queryNumEntries(db, LoyaltyCardDbIdsGroups.TABLE,
|
||||
|
||||
@@ -5,15 +5,12 @@ package protect.card_locker;
|
||||
* encountered with the format of data being
|
||||
* imported or exported.
|
||||
*/
|
||||
public class FormatException extends Exception
|
||||
{
|
||||
public FormatException(String message)
|
||||
{
|
||||
public class FormatException extends Exception {
|
||||
public FormatException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public FormatException(String message, Exception rootCause)
|
||||
{
|
||||
public FormatException(String message, Exception rootCause) {
|
||||
super(message, rootCause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ package protect.card_locker;
|
||||
|
||||
import android.database.Cursor;
|
||||
|
||||
public class Group
|
||||
{
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class Group {
|
||||
public final String _id;
|
||||
public final int order;
|
||||
|
||||
@@ -12,11 +13,28 @@ public class Group
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public static Group toGroup(Cursor cursor)
|
||||
{
|
||||
public static Group toGroup(Cursor cursor) {
|
||||
String _id = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbGroups.ID));
|
||||
int order = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbGroups.ORDER));
|
||||
|
||||
return new Group(_id, order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof Group)) {
|
||||
return false;
|
||||
}
|
||||
Group anotherGroup = (Group) obj;
|
||||
return _id.equals(anotherGroup._id) && order == anotherGroup.order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
String combined = _id + "_" + order;
|
||||
return combined.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,45 +12,31 @@ import androidx.appcompat.widget.AppCompatImageButton;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder>
|
||||
{
|
||||
public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder> {
|
||||
Settings mSettings;
|
||||
private Cursor mCursor;
|
||||
private final Context mContext;
|
||||
private final GroupCursorAdapter.GroupAdapterListener mListener;
|
||||
private final GroupAdapterListener mListener;
|
||||
DBHelper mDb;
|
||||
|
||||
public GroupCursorAdapter(Context inputContext, Cursor inputCursor, GroupCursorAdapter.GroupAdapterListener inputListener) {
|
||||
super(inputCursor);
|
||||
public GroupCursorAdapter(Context inputContext, Cursor inputCursor, GroupAdapterListener inputListener) {
|
||||
super(inputCursor, DBHelper.LoyaltyCardDbGroups.ORDER);
|
||||
setHasStableIds(true);
|
||||
mSettings = new Settings(inputContext);
|
||||
mContext = inputContext;
|
||||
mContext = inputContext.getApplicationContext();
|
||||
mListener = inputListener;
|
||||
mDb = new DBHelper(inputContext);
|
||||
|
||||
swapCursor(mCursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swapCursor(Cursor inputCursor) {
|
||||
super.swapCursor(inputCursor);
|
||||
mCursor = inputCursor;
|
||||
swapCursor(inputCursor);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public GroupCursorAdapter.GroupListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType)
|
||||
{
|
||||
public GroupCursorAdapter.GroupListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType) {
|
||||
View itemView = LayoutInflater.from(inputParent.getContext()).inflate(R.layout.group_layout, inputParent, false);
|
||||
return new GroupListItemViewHolder(itemView);
|
||||
}
|
||||
|
||||
public Cursor getCursor()
|
||||
{
|
||||
return mCursor;
|
||||
}
|
||||
|
||||
public void onBindViewHolder(GroupCursorAdapter.GroupListItemViewHolder inputHolder, Cursor inputCursor) {
|
||||
public void onBindViewHolder(GroupListItemViewHolder inputHolder, Cursor inputCursor) {
|
||||
Group group = Group.toGroup(inputCursor);
|
||||
|
||||
inputHolder.mName.setText(group._id);
|
||||
@@ -64,24 +50,24 @@ class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListI
|
||||
applyClickEvents(inputHolder);
|
||||
}
|
||||
|
||||
private void applyClickEvents(GroupListItemViewHolder inputHolder)
|
||||
{
|
||||
private void applyClickEvents(GroupListItemViewHolder inputHolder) {
|
||||
inputHolder.mMoveDown.setOnClickListener(view -> mListener.onMoveDownButtonClicked(inputHolder.itemView));
|
||||
inputHolder.mMoveUp.setOnClickListener(view -> mListener.onMoveUpButtonClicked(inputHolder.itemView));
|
||||
inputHolder.mEdit.setOnClickListener(view -> mListener.onEditButtonClicked(inputHolder.itemView));
|
||||
inputHolder.mDelete.setOnClickListener(view -> mListener.onDeleteButtonClicked(inputHolder.itemView));
|
||||
}
|
||||
|
||||
public interface GroupAdapterListener
|
||||
{
|
||||
public interface GroupAdapterListener {
|
||||
void onMoveDownButtonClicked(View view);
|
||||
|
||||
void onMoveUpButtonClicked(View view);
|
||||
|
||||
void onEditButtonClicked(View view);
|
||||
|
||||
void onDeleteButtonClicked(View view);
|
||||
}
|
||||
|
||||
public static class GroupListItemViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
public static class GroupListItemViewHolder extends RecyclerView.ViewHolder {
|
||||
public TextView mName, mCardCount;
|
||||
public AppCompatImageButton mMoveUp, mMoveDown, mEdit, mDelete;
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package protect.card_locker;
|
||||
|
||||
public enum ImageLocationType {
|
||||
front,
|
||||
back,
|
||||
icon
|
||||
}
|
||||
@@ -10,14 +10,20 @@ import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -26,12 +32,6 @@ import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
import protect.card_locker.importexport.DataFormat;
|
||||
import protect.card_locker.importexport.ImportExportResult;
|
||||
@@ -40,8 +40,6 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private static final int PERMISSIONS_EXTERNAL_STORAGE = 1;
|
||||
private static final int CHOOSE_EXPORT_LOCATION = 2;
|
||||
private static final int IMPORT = 3;
|
||||
|
||||
private ImportExportTask importExporter;
|
||||
|
||||
@@ -50,6 +48,10 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
private DataFormat importDataFormat;
|
||||
private String exportPassword;
|
||||
|
||||
private ActivityResultLauncher<Intent> fileCreateLauncher;
|
||||
private ActivityResultLauncher<String> fileOpenLauncher;
|
||||
private ActivityResultLauncher<Intent> filePickerLauncher;
|
||||
|
||||
final private TaskHandler mTasks = new TaskHandler();
|
||||
|
||||
@Override
|
||||
@@ -77,6 +79,49 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
PERMISSIONS_EXTERNAL_STORAGE);
|
||||
}
|
||||
|
||||
// would use ActivityResultContracts.CreateDocument() but mime type cannot be set
|
||||
fileCreateLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
Intent intent = result.getData();
|
||||
if (intent == null) {
|
||||
Log.e(TAG, "Activity returned NULL data");
|
||||
return;
|
||||
}
|
||||
Uri uri = intent.getData();
|
||||
if (uri == null) {
|
||||
Log.e(TAG, "Activity returned NULL uri");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
OutputStream writer = getContentResolver().openOutputStream(uri);
|
||||
Log.e(TAG, "Starting file export with: " + result.toString());
|
||||
startExport(writer, uri, exportPassword.toCharArray(), true);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to export file: " + result.toString(), e);
|
||||
onExportComplete(ImportExportResult.GenericFailure, uri);
|
||||
}
|
||||
|
||||
});
|
||||
fileOpenLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), result -> {
|
||||
if (result == null) {
|
||||
Log.e(TAG, "Activity returned NULL data");
|
||||
return;
|
||||
}
|
||||
openFileForImport(result, null);
|
||||
});
|
||||
filePickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
Intent intent = result.getData();
|
||||
if (intent == null) {
|
||||
Log.e(TAG, "Activity returned NULL data");
|
||||
return;
|
||||
}
|
||||
Uri uri = intent.getData();
|
||||
if (uri == null) {
|
||||
Log.e(TAG, "Activity returned NULL uri");
|
||||
return;
|
||||
}
|
||||
openFileForImport(intent.getData(), null);
|
||||
});
|
||||
|
||||
// Check that there is a file manager available
|
||||
final Intent intentCreateDocumentAction = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intentCreateDocumentAction.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
@@ -84,60 +129,57 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "catima.zip");
|
||||
|
||||
Button exportButton = findViewById(R.id.exportButton);
|
||||
exportButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
|
||||
builder.setTitle(R.string.exportPassword);
|
||||
exportButton.setOnClickListener(v -> {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
|
||||
builder.setTitle(R.string.exportPassword);
|
||||
|
||||
FrameLayout container = new FrameLayout(ImportExportActivity.this);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.leftMargin = 50;
|
||||
params.rightMargin = 50;
|
||||
FrameLayout container = new FrameLayout(ImportExportActivity.this);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.leftMargin = 50;
|
||||
params.rightMargin = 50;
|
||||
|
||||
final EditText input = new EditText(ImportExportActivity.this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
input.setLayoutParams(params);
|
||||
input.setHint(R.string.exportPasswordHint);
|
||||
final EditText input = new EditText(ImportExportActivity.this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
input.setLayoutParams(params);
|
||||
input.setHint(R.string.exportPasswordHint);
|
||||
|
||||
container.addView(input);
|
||||
builder.setView(container);
|
||||
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
exportPassword = input.getText().toString();
|
||||
chooseFileWithIntent(intentCreateDocumentAction, CHOOSE_EXPORT_LOCATION);
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
|
||||
builder.show();
|
||||
container.addView(input);
|
||||
builder.setView(container);
|
||||
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
exportPassword = input.getText().toString();
|
||||
try {
|
||||
fileCreateLauncher.launch(intentCreateDocumentAction);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
|
||||
builder.show();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Check that there is a file manager available
|
||||
final Intent intentGetContentAction = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intentGetContentAction.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intentGetContentAction.setType("*/*");
|
||||
|
||||
Button importFilesystem = findViewById(R.id.importOptionFilesystemButton);
|
||||
importFilesystem.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
chooseImportType(intentGetContentAction);
|
||||
}
|
||||
});
|
||||
importFilesystem.setOnClickListener(v -> chooseImportType(false));
|
||||
|
||||
// Check that there is an app that data can be imported from
|
||||
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
|
||||
|
||||
Button importApplication = findViewById(R.id.importOptionApplicationButton);
|
||||
importApplication.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
chooseImportType(intentPickAction);
|
||||
}
|
||||
});
|
||||
importApplication.setOnClickListener(v -> chooseImportType(true));
|
||||
}
|
||||
|
||||
private void chooseImportType(Intent baseIntent) {
|
||||
private void openFileForImport(Uri uri, char[] password) {
|
||||
try {
|
||||
InputStream reader = getContentResolver().openInputStream(uri);
|
||||
Log.e(TAG, "Starting file import with: " + uri.toString());
|
||||
startImport(reader, uri, importDataFormat, password, true);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to import file: " + uri.toString(), e);
|
||||
onImportComplete(ImportExportResult.GenericFailure, uri, importDataFormat);
|
||||
}
|
||||
}
|
||||
|
||||
private void chooseImportType(boolean choosePicker) {
|
||||
List<CharSequence> betaImportOptions = new ArrayList<>();
|
||||
betaImportOptions.add("Fidme");
|
||||
betaImportOptions.add("Stocard");
|
||||
@@ -195,7 +237,17 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
chooseFileWithIntent(baseIntent, IMPORT);
|
||||
try {
|
||||
if (choosePicker) {
|
||||
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
|
||||
filePickerLauncher.launch(intentPickAction);
|
||||
} else {
|
||||
fileOpenLauncher.launch("*/*");
|
||||
}
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
@@ -298,7 +350,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
activityResultParser(IMPORT, RESULT_OK, uri, input.getText().toString().toCharArray());
|
||||
openFileForImport(uri, input.getText().toString().toCharArray());
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
|
||||
|
||||
@@ -374,69 +426,4 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
private void chooseFileWithIntent(Intent intent, int requestCode) {
|
||||
try {
|
||||
startActivityForResult(intent, requestCode);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void activityResultParser(int requestCode, int resultCode, Uri uri, char[] password) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
Log.w(TAG, "Failed onActivityResult(), result=" + resultCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uri == null) {
|
||||
Log.e(TAG, "Activity returned a NULL URI");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (requestCode == CHOOSE_EXPORT_LOCATION) {
|
||||
|
||||
OutputStream writer;
|
||||
if (uri.getScheme() != null) {
|
||||
writer = getContentResolver().openOutputStream(uri);
|
||||
} else {
|
||||
writer = new FileOutputStream(new File(uri.toString()));
|
||||
}
|
||||
Log.e(TAG, "Starting file export with: " + uri.toString());
|
||||
startExport(writer, uri, exportPassword.toCharArray(), true);
|
||||
} else {
|
||||
InputStream reader;
|
||||
if (uri.getScheme() != null) {
|
||||
reader = getContentResolver().openInputStream(uri);
|
||||
} else {
|
||||
reader = new FileInputStream(new File(uri.toString()));
|
||||
}
|
||||
|
||||
Log.e(TAG, "Starting file import with: " + uri.toString());
|
||||
|
||||
startImport(reader, uri, importDataFormat, password, true);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to import/export file: " + uri.toString(), e);
|
||||
if (requestCode == CHOOSE_EXPORT_LOCATION) {
|
||||
onExportComplete(ImportExportResult.GenericFailure, uri);
|
||||
} else {
|
||||
onImportComplete(ImportExportResult.GenericFailure, uri, importDataFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (data == null) {
|
||||
Log.e(TAG, "Activity returned NULL data");
|
||||
return;
|
||||
}
|
||||
|
||||
activityResultParser(requestCode, resultCode, data.getData(), null);
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
@@ -35,7 +33,7 @@ public class ImportURIHelper {
|
||||
private final String shareMultipleText;
|
||||
|
||||
public ImportURIHelper(Context context) {
|
||||
this.context = context;
|
||||
this.context = context.getApplicationContext();
|
||||
hosts[0] = context.getResources().getString(R.string.intent_import_card_from_url_host_catima_app);
|
||||
paths[0] = context.getResources().getString(R.string.intent_import_card_from_url_path_prefix_catima_app);
|
||||
hosts[1] = context.getResources().getString(R.string.intent_import_card_from_url_host_thelastproject);
|
||||
@@ -57,7 +55,7 @@ public class ImportURIHelper {
|
||||
}
|
||||
|
||||
public LoyaltyCard parse(Uri uri) throws InvalidObjectException {
|
||||
if(!isImportUri(uri)) {
|
||||
if (!isImportUri(uri)) {
|
||||
throw new InvalidObjectException("Not an import URI");
|
||||
}
|
||||
|
||||
@@ -92,37 +90,33 @@ public class ImportURIHelper {
|
||||
String note = kv.get(NOTE);
|
||||
String cardId = kv.get(CARD_ID);
|
||||
String barcodeId = kv.get(BARCODE_ID);
|
||||
if (store == null || note == null || cardId == null) throw new InvalidObjectException("Not a valid import URI: " + uri.toString());
|
||||
if (store == null || note == null || cardId == null)
|
||||
throw new InvalidObjectException("Not a valid import URI: " + uri.toString());
|
||||
|
||||
String unparsedBarcodeType = kv.get(BARCODE_TYPE);
|
||||
if(unparsedBarcodeType != null && !unparsedBarcodeType.equals(""))
|
||||
{
|
||||
if (unparsedBarcodeType != null && !unparsedBarcodeType.equals("")) {
|
||||
barcodeType = CatimaBarcode.fromName(unparsedBarcodeType);
|
||||
}
|
||||
|
||||
String unparsedBalance = kv.get(BALANCE);
|
||||
if(unparsedBalance != null && !unparsedBalance.equals(""))
|
||||
{
|
||||
if (unparsedBalance != null && !unparsedBalance.equals("")) {
|
||||
balance = new BigDecimal(unparsedBalance);
|
||||
}
|
||||
String unparsedBalanceType = kv.get(BALANCE_TYPE);
|
||||
if (unparsedBalanceType != null && !unparsedBalanceType.equals(""))
|
||||
{
|
||||
if (unparsedBalanceType != null && !unparsedBalanceType.equals("")) {
|
||||
balanceType = Currency.getInstance(unparsedBalanceType);
|
||||
}
|
||||
String unparsedExpiry = kv.get(EXPIRY);
|
||||
if(unparsedExpiry != null && !unparsedExpiry.equals(""))
|
||||
{
|
||||
if (unparsedExpiry != null && !unparsedExpiry.equals("")) {
|
||||
expiry = new Date(Long.parseLong(unparsedExpiry));
|
||||
}
|
||||
|
||||
String unparsedHeaderColor = kv.get(HEADER_COLOR);
|
||||
if(unparsedHeaderColor != null)
|
||||
{
|
||||
if (unparsedHeaderColor != null) {
|
||||
headerColor = Integer.parseInt(unparsedHeaderColor);
|
||||
}
|
||||
|
||||
return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(),100);
|
||||
return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100);
|
||||
} catch (NullPointerException | NumberFormatException | UnsupportedEncodingException ex) {
|
||||
throw new InvalidObjectException("Not a valid import URI");
|
||||
}
|
||||
@@ -159,14 +153,14 @@ public class ImportURIHelper {
|
||||
fragment = appendFragment(fragment, EXPIRY, String.valueOf(loyaltyCard.expiry.getTime()));
|
||||
}
|
||||
fragment = appendFragment(fragment, CARD_ID, loyaltyCard.cardId);
|
||||
if(loyaltyCard.barcodeId != null) {
|
||||
if (loyaltyCard.barcodeId != null) {
|
||||
fragment = appendFragment(fragment, BARCODE_ID, loyaltyCard.barcodeId);
|
||||
}
|
||||
|
||||
if(loyaltyCard.barcodeType != null) {
|
||||
if (loyaltyCard.barcodeType != null) {
|
||||
fragment = appendFragment(fragment, BARCODE_TYPE, loyaltyCard.barcodeType.name());
|
||||
}
|
||||
if(loyaltyCard.headerColor != null) {
|
||||
if (loyaltyCard.headerColor != null) {
|
||||
fragment = appendFragment(fragment, HEADER_COLOR, loyaltyCard.headerColor.toString());
|
||||
}
|
||||
// Star status will not be exported
|
||||
|
||||
@@ -18,8 +18,7 @@ import android.text.TextPaint;
|
||||
* alphabet or digit, if there is no letter or digit available, a default image
|
||||
* is shown instead.
|
||||
*/
|
||||
class LetterBitmap
|
||||
{
|
||||
class LetterBitmap {
|
||||
|
||||
/**
|
||||
* The number of available tile colors
|
||||
@@ -37,39 +36,32 @@ class LetterBitmap
|
||||
/**
|
||||
* Constructor for <code>LetterTileProvider</code>
|
||||
*
|
||||
* @param context The {@link Context} to use
|
||||
* @param displayName The name used to create the letter for the tile
|
||||
* @param key The key used to generate the background color for the tile
|
||||
* @param context The {@link Context} to use
|
||||
* @param displayName The name used to create the letter for the tile
|
||||
* @param key The key used to generate the background color for the tile
|
||||
* @param tileLetterFontSize The font size used to display the letter
|
||||
* @param width The desired width of the tile
|
||||
* @param height The desired height of the tile
|
||||
* @param backgroundColor (optional) color to use for background.
|
||||
* @param textColor (optional) color to use for text.
|
||||
* @param width The desired width of the tile
|
||||
* @param height The desired height of the tile
|
||||
* @param backgroundColor (optional) color to use for background.
|
||||
* @param textColor (optional) color to use for text.
|
||||
*/
|
||||
public LetterBitmap(Context context, String displayName, String key, int tileLetterFontSize,
|
||||
int width, int height, Integer backgroundColor, Integer textColor)
|
||||
{
|
||||
int width, int height, Integer backgroundColor, Integer textColor) {
|
||||
TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(Typeface.create("sans-serif-light", Typeface.BOLD));
|
||||
|
||||
if(textColor != null)
|
||||
{
|
||||
if (textColor != null) {
|
||||
paint.setColor(textColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
paint.setColor(Color.WHITE);
|
||||
}
|
||||
|
||||
paint.setTextAlign(Paint.Align.CENTER);
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
if(backgroundColor == null)
|
||||
{
|
||||
if (backgroundColor == null) {
|
||||
mColor = getDefaultColor(context, key);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
mColor = backgroundColor;
|
||||
}
|
||||
|
||||
@@ -80,7 +72,7 @@ class LetterBitmap
|
||||
c.setBitmap(mBitmap);
|
||||
c.drawColor(mColor);
|
||||
|
||||
char [] firstCharArray = new char[1];
|
||||
char[] firstCharArray = new char[1];
|
||||
firstCharArray[0] = firstChar.toUpperCase().charAt(0);
|
||||
paint.setTextSize(tileLetterFontSize);
|
||||
|
||||
@@ -97,16 +89,14 @@ class LetterBitmap
|
||||
* alphabet or digit, if there is no letter or digit available, a
|
||||
* default image is shown instead
|
||||
*/
|
||||
public Bitmap getLetterTile()
|
||||
{
|
||||
public Bitmap getLetterTile() {
|
||||
return mBitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return background color used for letter title.
|
||||
*/
|
||||
public int getBackgroundColor()
|
||||
{
|
||||
public int getBackgroundColor() {
|
||||
return mColor;
|
||||
}
|
||||
|
||||
@@ -115,8 +105,7 @@ class LetterBitmap
|
||||
* @return A new or previously chosen color for <code>key</code> used as the
|
||||
* tile background color
|
||||
*/
|
||||
private static int pickColor(String key, TypedArray colors)
|
||||
{
|
||||
private static int pickColor(String key, TypedArray colors) {
|
||||
// String.hashCode() is not supposed to change across java versions, so
|
||||
// this should guarantee the same key always maps to the same color
|
||||
final int color = Math.abs(key.hashCode()) % NUM_OF_TILE_COLORS;
|
||||
@@ -127,8 +116,7 @@ class LetterBitmap
|
||||
* Determine the color which the letter tile will use if no default
|
||||
* color is provided.
|
||||
*/
|
||||
public static int getDefaultColor(Context context, String key)
|
||||
{
|
||||
public static int getDefaultColor(Context context, String key) {
|
||||
final Resources res = context.getResources();
|
||||
|
||||
TypedArray colors = res.obtainTypedArray(R.array.letter_tile_colors);
|
||||
|
||||
@@ -35,8 +35,7 @@ public class LoyaltyCard implements Parcelable {
|
||||
public LoyaltyCard(final int id, final String store, final String note, final Date expiry,
|
||||
final BigDecimal balance, final Currency balanceType, final String cardId,
|
||||
@Nullable final String barcodeId, @Nullable final CatimaBarcode barcodeType,
|
||||
@Nullable final Integer headerColor, final int starStatus, final long lastUsed,final int zoomLevel)
|
||||
{
|
||||
@Nullable final Integer headerColor, final int starStatus, final long lastUsed, final int zoomLevel) {
|
||||
this.id = id;
|
||||
this.store = store;
|
||||
this.note = note;
|
||||
@@ -88,8 +87,7 @@ public class LoyaltyCard implements Parcelable {
|
||||
parcel.writeInt(zoomLevel);
|
||||
}
|
||||
|
||||
public static LoyaltyCard toLoyaltyCard(Cursor cursor)
|
||||
{
|
||||
public static LoyaltyCard toLoyaltyCard(Cursor cursor) {
|
||||
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID));
|
||||
String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE));
|
||||
String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE));
|
||||
@@ -110,27 +108,23 @@ public class LoyaltyCard implements Parcelable {
|
||||
Date expiry = null;
|
||||
Integer headerColor = null;
|
||||
|
||||
if (cursor.isNull(barcodeTypeColumn) == false)
|
||||
{
|
||||
if (cursor.isNull(barcodeTypeColumn) == false) {
|
||||
barcodeType = CatimaBarcode.fromName(cursor.getString(barcodeTypeColumn));
|
||||
}
|
||||
|
||||
if (cursor.isNull(balanceTypeColumn) == false)
|
||||
{
|
||||
if (cursor.isNull(balanceTypeColumn) == false) {
|
||||
balanceType = Currency.getInstance(cursor.getString(balanceTypeColumn));
|
||||
}
|
||||
|
||||
if(expiryLong > 0)
|
||||
{
|
||||
if (expiryLong > 0) {
|
||||
expiry = new Date(expiryLong);
|
||||
}
|
||||
|
||||
if(cursor.isNull(headerColorColumn) == false)
|
||||
{
|
||||
if (cursor.isNull(headerColorColumn) == false) {
|
||||
headerColor = cursor.getInt(headerColorColumn);
|
||||
}
|
||||
|
||||
return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed,zoomLevel);
|
||||
return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed, zoomLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.animation.AnimatorInflater;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
public class LoyaltyCardAnimator {
|
||||
|
||||
private static AnimatorSet selectedViewIn, defaultViewOut, selectedViewOut, defaultViewIn;
|
||||
|
||||
public static void flipView(Context inputContext, final View inputSelectedView, final View inputDefaultView, boolean inputItemSelected) {
|
||||
|
||||
selectedViewIn = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_left_in);
|
||||
defaultViewOut = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_right_out);
|
||||
selectedViewOut = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_left_out);
|
||||
defaultViewIn = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_right_in);
|
||||
|
||||
final AnimatorSet showFrontAnim = new AnimatorSet();
|
||||
final AnimatorSet showBackAnim = new AnimatorSet();
|
||||
|
||||
selectedViewIn.setTarget(inputSelectedView);
|
||||
defaultViewOut.setTarget(inputDefaultView);
|
||||
showFrontAnim.playTogether(selectedViewIn, defaultViewOut);
|
||||
|
||||
selectedViewOut.setTarget(inputSelectedView);
|
||||
defaultViewIn.setTarget(inputDefaultView);
|
||||
showBackAnim.playTogether(defaultViewIn, selectedViewOut);
|
||||
|
||||
if (inputItemSelected) {
|
||||
showFrontAnim.start();
|
||||
} else {
|
||||
showBackAnim.start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package protect.card_locker;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.SparseBooleanArray;
|
||||
@@ -12,51 +13,53 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.BlendModeColorFilterCompat;
|
||||
import androidx.core.graphics.BlendModeCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.card.MaterialCardView;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.core.graphics.BlendModeColorFilterCompat;
|
||||
import androidx.core.graphics.BlendModeCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder> {
|
||||
private int mCurrentSelectedIndex = -1;
|
||||
private Cursor mCursor;
|
||||
Settings mSettings;
|
||||
boolean mDarkModeEnabled;
|
||||
private Context mContext;
|
||||
private CardAdapterListener mListener;
|
||||
private SparseBooleanArray mSelectedItems;
|
||||
private SparseBooleanArray mAnimationItemsIndex;
|
||||
private final Context mContext;
|
||||
private final CardAdapterListener mListener;
|
||||
protected SparseBooleanArray mSelectedItems;
|
||||
protected SparseBooleanArray mAnimationItemsIndex;
|
||||
private boolean mReverseAllAnimations = false;
|
||||
private boolean mShowDetails = true;
|
||||
|
||||
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener) {
|
||||
super(inputCursor);
|
||||
super(inputCursor, DBHelper.LoyaltyCardDbIds.ID);
|
||||
setHasStableIds(true);
|
||||
mSettings = new Settings(inputContext);
|
||||
mContext = inputContext;
|
||||
mContext = inputContext.getApplicationContext();
|
||||
mListener = inputListener;
|
||||
mSelectedItems = new SparseBooleanArray();
|
||||
mAnimationItemsIndex = new SparseBooleanArray();
|
||||
|
||||
mDarkModeEnabled = MainActivity.isDarkModeEnabled(inputContext);
|
||||
mDarkModeEnabled = Utils.isDarkModeEnabled(inputContext);
|
||||
|
||||
swapCursor(mCursor);
|
||||
swapCursor(inputCursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swapCursor(Cursor inputCursor) {
|
||||
super.swapCursor(inputCursor);
|
||||
mCursor = inputCursor;
|
||||
public void showDetails(boolean show) {
|
||||
mShowDetails = show;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean showingDetails() {
|
||||
return mShowDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,8 +68,9 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
return new LoyaltyCardListItemViewHolder(itemView, mListener);
|
||||
}
|
||||
|
||||
public Cursor getCursor() {
|
||||
return mCursor;
|
||||
public LoyaltyCard getCard(int position) {
|
||||
mCursor.moveToPosition(position);
|
||||
return LoyaltyCard.toLoyaltyCard(mCursor);
|
||||
}
|
||||
|
||||
public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor inputCursor) {
|
||||
@@ -83,7 +87,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
|
||||
inputHolder.mStoreField.setText(loyaltyCard.store);
|
||||
inputHolder.mStoreField.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
|
||||
if (!loyaltyCard.note.isEmpty()) {
|
||||
if (mShowDetails && !loyaltyCard.note.isEmpty()) {
|
||||
inputHolder.mNoteField.setVisibility(View.VISIBLE);
|
||||
inputHolder.mNoteField.setText(loyaltyCard.note);
|
||||
inputHolder.mNoteField.setTextSize(size);
|
||||
@@ -91,12 +95,12 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
inputHolder.mNoteField.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (!loyaltyCard.balance.equals(new BigDecimal("0"))) {
|
||||
int drawableSize = dpToPx((size*24)/14, mContext);
|
||||
if (mShowDetails && !loyaltyCard.balance.equals(new BigDecimal("0"))) {
|
||||
int drawableSize = dpToPx((size * 24) / 14, mContext);
|
||||
inputHolder.mDivider.setVisibility(View.VISIBLE);
|
||||
inputHolder.mBalanceField.setVisibility(View.VISIBLE);
|
||||
Drawable balanceIcon = inputHolder.mBalanceField.getCompoundDrawables()[0];
|
||||
balanceIcon.setBounds(0,0,drawableSize,drawableSize);
|
||||
balanceIcon.setBounds(0, 0, drawableSize, drawableSize);
|
||||
inputHolder.mBalanceField.setCompoundDrawablesRelative(balanceIcon, null, null, null);
|
||||
if (mDarkModeEnabled) {
|
||||
balanceIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
|
||||
@@ -107,12 +111,12 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
inputHolder.mBalanceField.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (loyaltyCard.expiry != null) {
|
||||
int drawableSize = dpToPx((size*24)/14, mContext);
|
||||
if (mShowDetails && loyaltyCard.expiry != null) {
|
||||
int drawableSize = dpToPx((size * 24) / 14, mContext);
|
||||
inputHolder.mDivider.setVisibility(View.VISIBLE);
|
||||
inputHolder.mExpiryField.setVisibility(View.VISIBLE);
|
||||
Drawable expiryIcon = inputHolder.mExpiryField.getCompoundDrawables()[0];
|
||||
expiryIcon.setBounds(0,0, drawableSize, drawableSize);
|
||||
expiryIcon.setBounds(0, 0, drawableSize, drawableSize);
|
||||
inputHolder.mExpiryField.setCompoundDrawablesRelative(expiryIcon, null, null, null);
|
||||
if (Utils.hasExpired(loyaltyCard.expiry)) {
|
||||
expiryIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.RED, BlendModeCompat.SRC_ATOP));
|
||||
@@ -126,96 +130,52 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
inputHolder.mExpiryField.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
inputHolder.mStarIcon.setVisibility(loyaltyCard.starStatus != 0 ? View.VISIBLE : View.GONE);
|
||||
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
|
||||
int imageSize = dpToPx( (size*46)/14, mContext);
|
||||
inputHolder.mCardIcon.getLayoutParams().height = imageSize;
|
||||
inputHolder.mCardIcon.getLayoutParams().width = imageSize;
|
||||
inputHolder.mStarIcon.getLayoutParams().height = imageSize;
|
||||
inputHolder.mStarIcon.getLayoutParams().width = imageSize;
|
||||
inputHolder.mTickIcon.getLayoutParams().height = imageSize;
|
||||
inputHolder.mTickIcon.getLayoutParams().width = imageSize;
|
||||
Bitmap cardIcon = Utils.retrieveCardImage(mContext, loyaltyCard.id, ImageLocationType.icon);
|
||||
if (cardIcon != null) {
|
||||
inputHolder.mCardIcon.setImageBitmap(cardIcon);
|
||||
inputHolder.mCardIcon.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
} else {
|
||||
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
|
||||
inputHolder.mCardIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||
}
|
||||
inputHolder.mIconLayout.setBackgroundColor(loyaltyCard.headerColor != null ? loyaltyCard.headerColor : ContextCompat.getColor(mContext, R.color.colorPrimary));
|
||||
|
||||
/* Changing Padding and Mragin of different views according to font size
|
||||
* Views Included:
|
||||
* a) InformationContainer padding
|
||||
* b) Store left padding
|
||||
* c) Divider Margin
|
||||
* d) note top margin
|
||||
* e) row margin
|
||||
* */
|
||||
int marginPaddingSize = dpToPx((size*16)/14, mContext );
|
||||
inputHolder.mInformationContainer.setPadding(marginPaddingSize, marginPaddingSize, marginPaddingSize, marginPaddingSize);
|
||||
inputHolder.mStoreField.setPadding(marginPaddingSize, 0, 0, 0);
|
||||
LinearLayout.LayoutParams lpDivider = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT );
|
||||
lpDivider.setMargins(0, marginPaddingSize, 0, marginPaddingSize);
|
||||
inputHolder.mDivider.setLayoutParams(lpDivider);
|
||||
LinearLayout.LayoutParams lpNoteField = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT );
|
||||
lpNoteField.setMargins(0, marginPaddingSize/2, 0, 0);
|
||||
inputHolder.mNoteField.setLayoutParams(lpNoteField);
|
||||
LinearLayout.LayoutParams lpRow = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT );
|
||||
lpRow.setMargins(marginPaddingSize/2, marginPaddingSize/2, marginPaddingSize/2, marginPaddingSize/2);
|
||||
inputHolder.mRow.setLayoutParams(lpRow);
|
||||
inputHolder.mStarIcon.setVisibility(loyaltyCard.starStatus != 0 ? View.VISIBLE : View.GONE);
|
||||
|
||||
inputHolder.itemView.setActivated(mSelectedItems.get(inputCursor.getPosition(), false));
|
||||
applyIconAnimation(inputHolder, inputCursor.getPosition());
|
||||
applyClickEvents(inputHolder, inputCursor.getPosition());
|
||||
|
||||
// Force redraw to fix size not shrinking after data change
|
||||
inputHolder.mRow.requestLayout();
|
||||
}
|
||||
|
||||
private void applyClickEvents(LoyaltyCardListItemViewHolder inputHolder, final int inputPosition) {
|
||||
inputHolder.mRow.setOnClickListener(inputView -> mListener.onRowClicked(inputPosition));
|
||||
inputHolder.mInformationContainer.setOnClickListener(inputView -> mListener.onRowClicked(inputPosition));
|
||||
|
||||
inputHolder.mRow.setOnLongClickListener(inputView -> {
|
||||
mListener.onRowLongClicked(inputPosition);
|
||||
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
return true;
|
||||
});
|
||||
|
||||
inputHolder.mInformationContainer.setOnLongClickListener(inputView -> {
|
||||
mListener.onRowLongClicked(inputPosition);
|
||||
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void applyIconAnimation(LoyaltyCardListItemViewHolder inputHolder, int inputPosition) {
|
||||
if (mSelectedItems.get(inputPosition, false)) {
|
||||
inputHolder.mThumbnailFrontContainer.setVisibility(View.GONE);
|
||||
resetIconYAxis(inputHolder.mThumbnailBackContainer);
|
||||
inputHolder.mThumbnailBackContainer.setVisibility(View.VISIBLE);
|
||||
inputHolder.mThumbnailBackContainer.setAlpha(1);
|
||||
inputHolder.mCardIcon.setVisibility(View.GONE);
|
||||
inputHolder.mTickIcon.setVisibility(View.VISIBLE);
|
||||
if (mCurrentSelectedIndex == inputPosition) {
|
||||
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, true);
|
||||
resetCurrentIndex();
|
||||
}
|
||||
} else {
|
||||
inputHolder.mThumbnailBackContainer.setVisibility(View.GONE);
|
||||
resetIconYAxis(inputHolder.mThumbnailFrontContainer);
|
||||
inputHolder.mThumbnailFrontContainer.setVisibility(View.VISIBLE);
|
||||
inputHolder.mThumbnailFrontContainer.setAlpha(1);
|
||||
inputHolder.mTickIcon.setVisibility(View.GONE);
|
||||
inputHolder.mCardIcon.setVisibility(View.VISIBLE);
|
||||
if ((mReverseAllAnimations && mAnimationItemsIndex.get(inputPosition, false)) || mCurrentSelectedIndex == inputPosition) {
|
||||
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, false);
|
||||
resetCurrentIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetIconYAxis(View inputView) {
|
||||
if (inputView.getRotationY() != 0) {
|
||||
inputView.setRotationY(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void resetAnimationIndex() {
|
||||
mReverseAllAnimations = false;
|
||||
mAnimationItemsIndex.clear();
|
||||
}
|
||||
|
||||
|
||||
public void toggleSelection(int inputPosition) {
|
||||
mCurrentSelectedIndex = inputPosition;
|
||||
if (mSelectedItems.get(inputPosition, false)) {
|
||||
@@ -264,23 +224,20 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
public static class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public TextView mStoreField, mNoteField, mBalanceField, mExpiryField;
|
||||
public LinearLayout mInformationContainer;
|
||||
public ImageView mCardIcon, mStarIcon, mTickIcon;
|
||||
public MaterialCardView mRow;
|
||||
public MaterialCardView mIconLayout, mRow;
|
||||
public View mDivider;
|
||||
public RelativeLayout mThumbnailFrontContainer, mThumbnailBackContainer;
|
||||
|
||||
public LoyaltyCardListItemViewHolder(View inputView, CardAdapterListener inputListener) {
|
||||
super(inputView);
|
||||
mRow = inputView.findViewById(R.id.row);
|
||||
mIconLayout = inputView.findViewById(R.id.icon_layout);
|
||||
mDivider = inputView.findViewById(R.id.info_divider);
|
||||
mThumbnailFrontContainer = inputView.findViewById(R.id.thumbnail_front);
|
||||
mThumbnailBackContainer = inputView.findViewById(R.id.thumbnail_back);
|
||||
mInformationContainer = inputView.findViewById(R.id.information_container);
|
||||
mStoreField = inputView.findViewById(R.id.store);
|
||||
mNoteField = inputView.findViewById(R.id.note);
|
||||
mBalanceField = inputView.findViewById(R.id.balance);
|
||||
mExpiryField = inputView.findViewById(R.id.expiry);
|
||||
|
||||
mCardIcon = inputView.findViewById(R.id.thumbnail);
|
||||
mStarIcon = inputView.findViewById(R.id.star);
|
||||
mTickIcon = inputView.findViewById(R.id.selected_thumbnail);
|
||||
@@ -292,9 +249,9 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
}
|
||||
}
|
||||
|
||||
public int dpToPx(int dp, Context mContext){
|
||||
public int dpToPx(int dp, Context mContext) {
|
||||
Resources r = mContext.getResources();
|
||||
int px = (int)TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
|
||||
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
|
||||
return px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,20 @@ package protect.card_locker;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ImageDecoder;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.LocaleList;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
@@ -43,6 +40,8 @@ import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialog;
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener;
|
||||
import com.yalantis.ucrop.UCrop;
|
||||
import com.yalantis.ucrop.model.AspectRatio;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -63,14 +62,17 @@ import java.util.Locale;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
||||
import androidx.palette.graphics.Palette;
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
|
||||
public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
@@ -78,12 +80,28 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
private final String STATE_TAB_INDEX = "savedTab";
|
||||
private final String STATE_TEMP_CARD = "tempLoyaltyCard";
|
||||
private final String STATE_REQUESTED_IMAGE = "requestedImage";
|
||||
private final String STATE_FRONT_IMAGE_UNSAVED = "frontImageUnsaved";
|
||||
private final String STATE_BACK_IMAGE_UNSAVED = "backImageUnsaved";
|
||||
private final String STATE_ICON_UNSAVED = "iconUnsaved";
|
||||
private final String STATE_UPDATE_LOYALTY_CARD = "updateLoyaltyCard";
|
||||
private final String STATE_HAS_CHANGED = "hasChange";
|
||||
private final String STATE_FRONT_IMAGE_REMOVED = "frontImageRemoved";
|
||||
private final String STATE_BACK_IMAGE_REMOVED = "backImageRemoved";
|
||||
private final String STATE_ICON_REMOVED = "iconRemoved";
|
||||
|
||||
private static final int ID_IMAGE_FRONT = 0;
|
||||
private static final int ID_IMAGE_BACK = 1;
|
||||
private final String TEMP_CAMERA_IMAGE_NAME = LoyaltyCardEditActivity.class.getSimpleName() + "_camera_image.jpg";
|
||||
private final String TEMP_CROP_IMAGE_NAME = LoyaltyCardEditActivity.class.getSimpleName() + "_crop_image.png";
|
||||
private final Bitmap.CompressFormat TEMP_CROP_IMAGE_FORMAT = Bitmap.CompressFormat.PNG;
|
||||
|
||||
private final String TEMP_UNSAVED_FRONT_IMAGE_NAME = LoyaltyCardEditActivity.class.getSimpleName() + "_front_image.png";
|
||||
private final String TEMP_UNSAVED_BACK_IMAGE_NAME = LoyaltyCardEditActivity.class.getSimpleName() + "_back_image.png";
|
||||
private final String TEMP_UNSAVED_ICON_NAME = LoyaltyCardEditActivity.class.getSimpleName() + "_icon.png";
|
||||
private final Bitmap.CompressFormat TEMP_UNSAVED_IMAGE_FORMAT = Bitmap.CompressFormat.PNG;
|
||||
|
||||
private static final int PERMISSION_REQUEST_CAMERA_IMAGE_FRONT = 100;
|
||||
private static final int PERMISSION_REQUEST_CAMERA_IMAGE_BACK = 101;
|
||||
private static final int PERMISSION_REQUEST_CAMERA_IMAGE_ICON = 102;
|
||||
|
||||
public static final String BUNDLE_ID = "id";
|
||||
public static final String BUNDLE_UPDATE = "update";
|
||||
@@ -137,10 +155,25 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
HashMap<String, Currency> currencies = new HashMap<>();
|
||||
|
||||
String tempCameraPicturePath;
|
||||
|
||||
LoyaltyCard tempLoyaltyCard;
|
||||
|
||||
ActivityResultLauncher<Uri> mPhotoTakerLauncher;
|
||||
ActivityResultLauncher<Intent> mPhotoPickerLauncher;
|
||||
ActivityResultLauncher<Intent> mCardIdAndBarCodeEditorLauncher;
|
||||
|
||||
ActivityResultLauncher<Intent> mCropperLauncher;
|
||||
int mRequestedImage = 0;
|
||||
int mCropperFinishedType = 0;
|
||||
UCrop.Options mCropperOptions;
|
||||
|
||||
boolean mFrontImageUnsaved = false;
|
||||
boolean mBackImageUnsaved = false;
|
||||
boolean mIconUnsaved = false;
|
||||
|
||||
boolean mFrontImageRemoved = false;
|
||||
boolean mBackImageRemoved = false;
|
||||
boolean mIconRemoved = false;
|
||||
|
||||
final private TaskHandler mTasks = new TaskHandler();
|
||||
|
||||
private static LoyaltyCard updateTempState(LoyaltyCard loyaltyCard, LoyaltyCardField fieldName, Object value) {
|
||||
@@ -156,7 +189,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
(CatimaBarcode) (fieldName == LoyaltyCardField.barcodeType ? value : loyaltyCard.barcodeType),
|
||||
(Integer) (fieldName == LoyaltyCardField.headerColor ? value : loyaltyCard.headerColor),
|
||||
(int) (fieldName == LoyaltyCardField.starStatus ? value : loyaltyCard.starStatus),
|
||||
Utils.getUnixTime(),100
|
||||
Utils.getUnixTime(), 100
|
||||
);
|
||||
}
|
||||
|
||||
@@ -182,12 +215,41 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
+ ", updateLoyaltyCard=" + updateLoyaltyCard);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
|
||||
super.onSaveInstanceState(savedInstanceState);
|
||||
tabs = findViewById(R.id.tabs);
|
||||
savedInstanceState.putInt(STATE_TAB_INDEX, tabs.getSelectedTabPosition());
|
||||
savedInstanceState.putParcelable(STATE_TEMP_CARD, tempLoyaltyCard);
|
||||
savedInstanceState.putInt(STATE_REQUESTED_IMAGE, mRequestedImage);
|
||||
|
||||
Object cardImageFrontObj = cardImageFront.getTag();
|
||||
if (mFrontImageUnsaved && (cardImageFrontObj instanceof Bitmap) && Utils.saveTempImage(this, (Bitmap) cardImageFrontObj, TEMP_UNSAVED_FRONT_IMAGE_NAME, TEMP_UNSAVED_IMAGE_FORMAT) != null) {
|
||||
savedInstanceState.putInt(STATE_FRONT_IMAGE_UNSAVED, 1);
|
||||
} else {
|
||||
savedInstanceState.putInt(STATE_FRONT_IMAGE_UNSAVED, 0);
|
||||
}
|
||||
|
||||
Object cardImageBackObj = cardImageBack.getTag();
|
||||
if (mBackImageUnsaved && (cardImageBackObj instanceof Bitmap) && Utils.saveTempImage(this, (Bitmap) cardImageBackObj, TEMP_UNSAVED_BACK_IMAGE_NAME, TEMP_UNSAVED_IMAGE_FORMAT) != null) {
|
||||
savedInstanceState.putInt(STATE_BACK_IMAGE_UNSAVED, 1);
|
||||
} else {
|
||||
savedInstanceState.putInt(STATE_BACK_IMAGE_UNSAVED, 0);
|
||||
}
|
||||
|
||||
Object thumbnailObj = thumbnail.getTag();
|
||||
if (mIconUnsaved && (thumbnailObj instanceof Bitmap) && Utils.saveTempImage(this, (Bitmap) thumbnailObj, TEMP_UNSAVED_ICON_NAME, TEMP_UNSAVED_IMAGE_FORMAT) != null) {
|
||||
savedInstanceState.putInt(STATE_ICON_UNSAVED, 1);
|
||||
} else {
|
||||
savedInstanceState.putInt(STATE_ICON_UNSAVED, 0);
|
||||
}
|
||||
|
||||
savedInstanceState.putInt(STATE_UPDATE_LOYALTY_CARD, updateLoyaltyCard ? 1 : 0);
|
||||
savedInstanceState.putInt(STATE_HAS_CHANGED, hasChanged ? 1 : 0);
|
||||
savedInstanceState.putInt(STATE_FRONT_IMAGE_REMOVED, mFrontImageRemoved ? 1 : 0);
|
||||
savedInstanceState.putInt(STATE_BACK_IMAGE_REMOVED, mBackImageRemoved ? 1 : 0);
|
||||
savedInstanceState.putInt(STATE_ICON_REMOVED, mIconRemoved ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -196,6 +258,15 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
tabs = findViewById(R.id.tabs);
|
||||
tabs.selectTab(tabs.getTabAt(savedInstanceState.getInt(STATE_TAB_INDEX)));
|
||||
mRequestedImage = savedInstanceState.getInt(STATE_REQUESTED_IMAGE);
|
||||
mFrontImageUnsaved = savedInstanceState.getInt(STATE_FRONT_IMAGE_UNSAVED) == 1;
|
||||
mBackImageUnsaved = savedInstanceState.getInt(STATE_BACK_IMAGE_UNSAVED) == 1;
|
||||
mIconUnsaved = savedInstanceState.getInt(STATE_ICON_UNSAVED) == 1;
|
||||
updateLoyaltyCard = savedInstanceState.getInt(STATE_UPDATE_LOYALTY_CARD) == 1;
|
||||
hasChanged = savedInstanceState.getInt(STATE_HAS_CHANGED) == 1;
|
||||
mFrontImageRemoved = savedInstanceState.getInt(STATE_FRONT_IMAGE_REMOVED) == 1;
|
||||
mBackImageRemoved = savedInstanceState.getInt(STATE_BACK_IMAGE_REMOVED) == 1;
|
||||
mIconRemoved = savedInstanceState.getInt(STATE_ICON_REMOVED) == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -235,8 +306,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
barcodeCaptureLayout = findViewById(R.id.barcodeCaptureLayout);
|
||||
cardImageFrontHolder = findViewById(R.id.frontImageHolder);
|
||||
cardImageBackHolder = findViewById(R.id.backImageHolder);
|
||||
cardImageFrontHolder.setId(ID_IMAGE_FRONT);
|
||||
cardImageBackHolder.setId(ID_IMAGE_BACK);
|
||||
cardImageFront = findViewById(R.id.frontImage);
|
||||
cardImageBack = findViewById(R.id.backImage);
|
||||
|
||||
@@ -417,7 +486,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
if (!lastValue.toString().equals(getString(R.string.setBarcodeId))) {
|
||||
barcodeIdField.setText(lastValue);
|
||||
}
|
||||
;
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(LoyaltyCardEditActivity.this);
|
||||
builder.setTitle(R.string.setBarcodeId);
|
||||
@@ -509,6 +577,112 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
});
|
||||
|
||||
tabs.selectTab(tabs.getTabAt(0));
|
||||
|
||||
|
||||
mPhotoTakerLauncher = registerForActivityResult(new ActivityResultContracts.TakePicture(), result -> {
|
||||
if (result) {
|
||||
startCropper(getCacheDir() + "/" + TEMP_CAMERA_IMAGE_NAME);
|
||||
}
|
||||
});
|
||||
|
||||
// android 11: wanted to swap it to ActivityResultContracts.GetContent but then it shows a file browsers that shows image mime types, offering gallery in the file browser
|
||||
mPhotoPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
if (result.getResultCode() == RESULT_OK) {
|
||||
Intent intent = result.getData();
|
||||
if (intent == null) {
|
||||
Log.d("photo picker", "photo picker returned without an intent");
|
||||
return;
|
||||
}
|
||||
Uri uri = intent.getData();
|
||||
startCropperUri(uri);
|
||||
}
|
||||
});
|
||||
|
||||
mCardIdAndBarCodeEditorLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
if (result.getResultCode() == RESULT_OK) {
|
||||
Intent intent = result.getData();
|
||||
if (intent == null) {
|
||||
Log.d("barcode card id editor", "barcode and card id editor picker returned without an intent");
|
||||
return;
|
||||
}
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(Utils.BARCODE_SCAN, result.getResultCode(), intent, getApplicationContext());
|
||||
|
||||
cardId = barcodeValues.content();
|
||||
barcodeType = barcodeValues.format();
|
||||
barcodeId = "";
|
||||
}
|
||||
});
|
||||
|
||||
mCropperLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
Intent intent = result.getData();
|
||||
if (intent == null) {
|
||||
Log.d("cropper", "ucrop returned a null intent");
|
||||
return;
|
||||
}
|
||||
if (result.getResultCode() == Activity.RESULT_OK) {
|
||||
Uri debugUri = UCrop.getOutput(intent);
|
||||
if (debugUri == null) {
|
||||
throw new RuntimeException("ucrop returned success but not destination uri!");
|
||||
}
|
||||
Log.d("cropper", "ucrop produced image at " + debugUri);
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(getCacheDir() + "/" + TEMP_CROP_IMAGE_NAME);
|
||||
|
||||
if (bitmap != null) {
|
||||
if (requestedFrontImage()) {
|
||||
mFrontImageUnsaved = true;
|
||||
setCardImage(cardImageFront, Utils.resizeBitmap(bitmap, Utils.BITMAP_SIZE_BIG), true);
|
||||
} else if (requestedBackImage()) {
|
||||
mBackImageUnsaved = true;
|
||||
setCardImage(cardImageBack, Utils.resizeBitmap(bitmap, Utils.BITMAP_SIZE_BIG), true);
|
||||
} else {
|
||||
mIconUnsaved = true;
|
||||
setCardImage(thumbnail, Utils.resizeBitmap(bitmap, Utils.BITMAP_SIZE_SMALL), false);
|
||||
thumbnail.setBackgroundColor(Color.TRANSPARENT);
|
||||
setColorFromIcon();
|
||||
}
|
||||
Log.d("cropper", "mRequestedImage: " + mRequestedImage);
|
||||
mCropperFinishedType = mRequestedImage;
|
||||
hasChanged = true;
|
||||
} else {
|
||||
Toast.makeText(LoyaltyCardEditActivity.this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (result.getResultCode() == UCrop.RESULT_ERROR) {
|
||||
Throwable e = UCrop.getError(intent);
|
||||
if (e == null) {
|
||||
throw new RuntimeException("ucrop returned error state but not an error!");
|
||||
}
|
||||
Log.e("cropper error", e.toString());
|
||||
}
|
||||
});
|
||||
|
||||
mCropperOptions = new UCrop.Options();
|
||||
setCropperTheme();
|
||||
}
|
||||
|
||||
// ucrop 2.2.6 initial aspect ratio is glitched when 0x0 is used as the initial ratio option
|
||||
// https://github.com/Yalantis/uCrop/blob/281c8e6438d81f464d836fc6b500517144af264a/ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java#L264
|
||||
// so source width height has to be provided for now, depending on whether future versions of ucrop will support 0x0 as the default option
|
||||
private void setCropperOptions(boolean cardShapeDefault, float sourceWidth, float sourceHeight) {
|
||||
mCropperOptions.setCompressionFormat(TEMP_CROP_IMAGE_FORMAT);
|
||||
mCropperOptions.setFreeStyleCropEnabled(true);
|
||||
mCropperOptions.setHideBottomControls(false);
|
||||
// default aspect ratio workaround
|
||||
int selectedByDefault = 1;
|
||||
if (cardShapeDefault) {
|
||||
selectedByDefault = 2;
|
||||
}
|
||||
mCropperOptions.setAspectRatioOptions(selectedByDefault,
|
||||
new AspectRatio(null, 1, 1),
|
||||
new AspectRatio(getResources().getString(R.string.ucrop_label_original).toUpperCase(), sourceWidth, sourceHeight),
|
||||
new AspectRatio(getResources().getString(R.string.card).toUpperCase(), 85.6f, 53.98f)
|
||||
);
|
||||
}
|
||||
|
||||
private void setCropperTheme() {
|
||||
mCropperOptions.setToolbarColor(getThemeColor());
|
||||
mCropperOptions.setStatusBarColor(getThemeColor());
|
||||
mCropperOptions.setToolbarWidgetColor(Color.WHITE);
|
||||
mCropperOptions.setActiveControlsWidgetColor(getThemeColor());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -519,6 +693,30 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
extractIntentFields(intent);
|
||||
}
|
||||
|
||||
private boolean requestedFrontImage() {
|
||||
return mRequestedImage == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || mRequestedImage == Utils.CARD_IMAGE_FROM_FILE_FRONT;
|
||||
}
|
||||
|
||||
private boolean croppedFrontImage() {
|
||||
return mCropperFinishedType == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || mCropperFinishedType == Utils.CARD_IMAGE_FROM_FILE_FRONT;
|
||||
}
|
||||
|
||||
private boolean requestedBackImage() {
|
||||
return mRequestedImage == Utils.CARD_IMAGE_FROM_CAMERA_BACK || mRequestedImage == Utils.CARD_IMAGE_FROM_FILE_BACK;
|
||||
}
|
||||
|
||||
private boolean croppedBackImage() {
|
||||
return mCropperFinishedType == Utils.CARD_IMAGE_FROM_CAMERA_BACK || mCropperFinishedType == Utils.CARD_IMAGE_FROM_FILE_BACK;
|
||||
}
|
||||
|
||||
private boolean requestedIcon() {
|
||||
return mRequestedImage == Utils.CARD_IMAGE_FROM_CAMERA_ICON || mRequestedImage == Utils.CARD_IMAGE_FROM_FILE_ICON;
|
||||
}
|
||||
|
||||
private boolean croppedIcon() {
|
||||
return mCropperFinishedType == Utils.CARD_IMAGE_FROM_CAMERA_ICON || mCropperFinishedType == Utils.CARD_IMAGE_FROM_FILE_ICON;
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
@Override
|
||||
public void onResume() {
|
||||
@@ -528,6 +726,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
onResuming = true;
|
||||
|
||||
|
||||
if (tempLoyaltyCard == null) {
|
||||
if (updateLoyaltyCard) {
|
||||
tempLoyaltyCard = db.getLoyaltyCard(loyaltyCardId);
|
||||
@@ -537,9 +736,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
setTitle(R.string.editCardTitle);
|
||||
setCardImage(cardImageFront, Utils.retrieveCardImage(this, tempLoyaltyCard.id, true));
|
||||
setCardImage(cardImageBack, Utils.retrieveCardImage(this, tempLoyaltyCard.id, false));
|
||||
} else if (importLoyaltyCardUri != null) {
|
||||
try {
|
||||
tempLoyaltyCard = importUriHelper.parse(importLoyaltyCardUri);
|
||||
@@ -548,14 +744,45 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
setTitle(R.string.addCardTitle);
|
||||
} else {
|
||||
// New card, use default values
|
||||
tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime(),100);
|
||||
setTitle(R.string.addCardTitle);
|
||||
tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime(), 100);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!initDone) {
|
||||
if (updateLoyaltyCard) {
|
||||
setTitle(R.string.editCardTitle);
|
||||
|
||||
if (!mFrontImageUnsaved && !croppedFrontImage() && !mFrontImageRemoved) {
|
||||
setCardImage(cardImageFront, Utils.retrieveCardImage(this, tempLoyaltyCard.id, ImageLocationType.front), true);
|
||||
}
|
||||
if (!mBackImageUnsaved && !croppedBackImage() && !mBackImageRemoved) {
|
||||
setCardImage(cardImageBack, Utils.retrieveCardImage(this, tempLoyaltyCard.id, ImageLocationType.back), true);
|
||||
}
|
||||
if (!mIconUnsaved && !croppedIcon() && !mIconRemoved) {
|
||||
setCardImage(thumbnail, Utils.retrieveCardImage(this, tempLoyaltyCard.id, ImageLocationType.icon), false);
|
||||
}
|
||||
} else {
|
||||
setTitle(R.string.addCardTitle);
|
||||
}
|
||||
|
||||
if (mFrontImageUnsaved && !croppedFrontImage()) {
|
||||
setCardImage(cardImageFront, Utils.loadTempImage(this, TEMP_UNSAVED_FRONT_IMAGE_NAME), true);
|
||||
}
|
||||
if (mBackImageUnsaved && !croppedBackImage()) {
|
||||
setCardImage(cardImageBack, Utils.loadTempImage(this, TEMP_UNSAVED_BACK_IMAGE_NAME), true);
|
||||
}
|
||||
if (mIconUnsaved && !croppedIcon()) {
|
||||
setCardImage(thumbnail, Utils.loadTempImage(this, TEMP_UNSAVED_ICON_NAME), false);
|
||||
}
|
||||
}
|
||||
|
||||
mCropperFinishedType = 0;
|
||||
|
||||
boolean hadChanges = hasChanged;
|
||||
|
||||
storeFieldEdit.setText(tempLoyaltyCard.store);
|
||||
noteFieldEdit.setText(tempLoyaltyCard.note);
|
||||
formatExpiryField(this, expiryField, tempLoyaltyCard.expiry);
|
||||
@@ -614,7 +841,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
// It can't be null because we set it in updateTempState but SpotBugs insists it can be
|
||||
// NP_NULL_ON_SOME_PATH: Possible null pointer dereference
|
||||
if (tempLoyaltyCard.headerColor != null) {
|
||||
thumbnail.setOnClickListener(new ColorSelectListener());
|
||||
thumbnail.setOnClickListener(new ChooseCardImage());
|
||||
}
|
||||
|
||||
// Update from intent
|
||||
@@ -645,8 +872,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
// Initialization has finished
|
||||
if (!initDone) {
|
||||
hasChanged = false;
|
||||
initDone = true;
|
||||
hasChanged = hadChanges;
|
||||
}
|
||||
|
||||
generateOrHideBarcode();
|
||||
@@ -666,12 +893,21 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
onResuming = false;
|
||||
}
|
||||
|
||||
protected static void setCardImage(ImageView imageView, Bitmap bitmap) {
|
||||
protected void setColorFromIcon() {
|
||||
Object icon = thumbnail.getTag();
|
||||
if (icon != null && (icon instanceof Bitmap)) {
|
||||
updateTempState(LoyaltyCardField.headerColor, new Palette.Builder((Bitmap) icon).generate().getDominantColor(tempLoyaltyCard.headerColor != null ? tempLoyaltyCard.headerColor : ContextCompat.getColor(this, R.color.colorPrimary)));
|
||||
} else {
|
||||
Log.d("setColorFromIcon", "attempting header color change from icon but icon does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
protected void setCardImage(ImageView imageView, Bitmap bitmap, boolean applyFallback) {
|
||||
imageView.setTag(bitmap);
|
||||
|
||||
if (bitmap != null) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
} else {
|
||||
} else if (applyFallback) {
|
||||
imageView.setImageResource(R.drawable.ic_camera_white);
|
||||
}
|
||||
}
|
||||
@@ -707,8 +943,10 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
try {
|
||||
if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_FRONT) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_FRONT);
|
||||
} else {
|
||||
} else if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_BACK) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_BACK);
|
||||
} else if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_ICON) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_ICON);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -737,9 +975,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(R.string.no, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss())
|
||||
.setOnDismissListener(dialogInterface -> {
|
||||
if (tempStoredOldBarcodeValue != null) {
|
||||
barcodeIdField.setText(tempStoredOldBarcodeValue);
|
||||
@@ -768,40 +1004,22 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.leaveWithoutSaveTitle);
|
||||
builder.setMessage(R.string.leaveWithoutSaveConfirmation);
|
||||
builder.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
builder.setPositiveButton(R.string.confirm, (dialog, which) -> {
|
||||
finish();
|
||||
dialog.dismiss();
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
|
||||
confirmExitDialog = builder.create();
|
||||
}
|
||||
confirmExitDialog.show();
|
||||
}
|
||||
|
||||
private void takePhotoForCard(int type) throws IOException {
|
||||
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
|
||||
String imageFileName = "CATIMA_" + new Date().getTime();
|
||||
File image = File.createTempFile(
|
||||
imageFileName,
|
||||
".jpg",
|
||||
getExternalFilesDir(Environment.DIRECTORY_PICTURES)
|
||||
);
|
||||
private void takePhotoForCard(int type) {
|
||||
Uri photoURI = FileProvider.getUriForFile(LoyaltyCardEditActivity.this, BuildConfig.APPLICATION_ID, Utils.createTempFile(this, TEMP_CAMERA_IMAGE_NAME));
|
||||
mRequestedImage = type;
|
||||
|
||||
tempCameraPicturePath = image.getAbsolutePath();
|
||||
|
||||
Uri photoURI = FileProvider.getUriForFile(LoyaltyCardEditActivity.this, BuildConfig.APPLICATION_ID, image);
|
||||
i.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
|
||||
|
||||
startActivityForResult(i, type);
|
||||
mPhotoTakerLauncher.launch(photoURI);
|
||||
}
|
||||
|
||||
class EditCardIdAndBarcode implements View.OnClickListener {
|
||||
@@ -811,41 +1029,140 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
final Bundle b = new Bundle();
|
||||
b.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, cardIdFieldView.getText().toString());
|
||||
i.putExtras(b);
|
||||
startActivityForResult(i, Utils.BARCODE_SCAN);
|
||||
mCardIdAndBarCodeEditorLauncher.launch(i);
|
||||
}
|
||||
}
|
||||
|
||||
class ChooseCardImage implements View.OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) throws NoSuchElementException {
|
||||
ImageView targetView = v.getId() == ID_IMAGE_FRONT ? cardImageFront : cardImageBack;
|
||||
ImageView targetView;
|
||||
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
targetView = cardImageFront;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
targetView = cardImageBack;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
targetView = thumbnail;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid IMAGE ID " + v.getId());
|
||||
}
|
||||
|
||||
LinkedHashMap<String, Callable<Void>> cardOptions = new LinkedHashMap<>();
|
||||
if (targetView.getTag() != null) {
|
||||
if (targetView.getTag() != null && v.getId() != R.id.thumbnail) {
|
||||
cardOptions.put(getString(R.string.removeImage), () -> {
|
||||
setCardImage(targetView, null);
|
||||
if (targetView == cardImageFront) {
|
||||
mFrontImageRemoved = true;
|
||||
mFrontImageUnsaved = false;
|
||||
} else {
|
||||
mBackImageRemoved = true;
|
||||
mBackImageUnsaved = false;
|
||||
}
|
||||
|
||||
setCardImage(targetView, null, true);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
if (v.getId() == R.id.thumbnail) {
|
||||
cardOptions.put(getString(R.string.selectColor), () -> {
|
||||
ColorPickerDialog.Builder dialogBuilder = ColorPickerDialog.newBuilder();
|
||||
|
||||
if (tempLoyaltyCard.headerColor != null) {
|
||||
dialogBuilder.setColor(tempLoyaltyCard.headerColor);
|
||||
}
|
||||
|
||||
ColorPickerDialog dialog = dialogBuilder.create();
|
||||
dialog.setColorPickerDialogListener(new ColorPickerDialogListener() {
|
||||
@Override
|
||||
public void onColorSelected(int dialogId, int color) {
|
||||
updateTempState(LoyaltyCardField.headerColor, color);
|
||||
|
||||
// Unset image if set
|
||||
thumbnail.setTag(null);
|
||||
|
||||
generateIcon(storeFieldEdit.getText().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDialogDismissed(int dialogId) {
|
||||
// Nothing to do, no change made
|
||||
}
|
||||
});
|
||||
dialog.show(getSupportFragmentManager(), "color-picker-dialog");
|
||||
|
||||
setCardImage(targetView, null, false);
|
||||
mIconRemoved = true;
|
||||
mIconUnsaved = false;
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
cardOptions.put(getString(R.string.takePhoto), () -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
requestPermissions(new String[]{Manifest.permission.CAMERA}, v.getId() == ID_IMAGE_FRONT ? PERMISSION_REQUEST_CAMERA_IMAGE_FRONT : PERMISSION_REQUEST_CAMERA_IMAGE_BACK);
|
||||
int permissionRequestType;
|
||||
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_FRONT;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_BACK;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_ICON;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
requestPermissions(new String[]{Manifest.permission.CAMERA}, permissionRequestType);
|
||||
} else {
|
||||
takePhotoForCard(v.getId() == ID_IMAGE_FRONT ? Utils.CARD_IMAGE_FROM_CAMERA_FRONT : Utils.CARD_IMAGE_FROM_CAMERA_BACK);
|
||||
int cardImageType;
|
||||
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
cardImageType = Utils.CARD_IMAGE_FROM_CAMERA_FRONT;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
cardImageType = Utils.CARD_IMAGE_FROM_CAMERA_BACK;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
cardImageType = Utils.CARD_IMAGE_FROM_CAMERA_ICON;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
takePhotoForCard(cardImageType);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
cardOptions.put(getString(R.string.addFromImage), () -> {
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
mRequestedImage = Utils.CARD_IMAGE_FROM_FILE_FRONT;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
mRequestedImage = Utils.CARD_IMAGE_FROM_FILE_BACK;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
mRequestedImage = Utils.CARD_IMAGE_FROM_FILE_ICON;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
Intent i = new Intent(Intent.ACTION_PICK);
|
||||
i.setType("image/*");
|
||||
startActivityForResult(i, v.getId() == ID_IMAGE_FRONT ? Utils.CARD_IMAGE_FROM_FILE_FRONT : Utils.CARD_IMAGE_FROM_FILE_BACK);
|
||||
mPhotoPickerLauncher.launch(i);
|
||||
return null;
|
||||
});
|
||||
|
||||
int titleResource;
|
||||
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
titleResource = R.string.setFrontImage;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
titleResource = R.string.setBackImage;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
titleResource = R.string.setIcon;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(LoyaltyCardEditActivity.this)
|
||||
.setTitle(v.getId() == ID_IMAGE_FRONT ? getString(R.string.setFrontImage) : getString(R.string.setBackImage))
|
||||
.setTitle(getString(titleResource))
|
||||
.setItems(cardOptions.keySet().toArray(new CharSequence[cardOptions.size()]), (dialog, which) -> {
|
||||
Iterator<Callable<Void>> callables = cardOptions.values().iterator();
|
||||
Callable<Void> callable = callables.next();
|
||||
@@ -864,33 +1181,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
class ColorSelectListener implements View.OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ColorPickerDialog.Builder dialogBuilder = ColorPickerDialog.newBuilder();
|
||||
|
||||
if (tempLoyaltyCard.headerColor != null) {
|
||||
dialogBuilder.setColor(tempLoyaltyCard.headerColor);
|
||||
}
|
||||
|
||||
ColorPickerDialog dialog = dialogBuilder.create();
|
||||
dialog.setColorPickerDialogListener(new ColorPickerDialogListener() {
|
||||
@Override
|
||||
public void onColorSelected(int dialogId, int color) {
|
||||
updateTempState(LoyaltyCardField.headerColor, color);
|
||||
|
||||
generateIcon(storeFieldEdit.getText().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDialogDismissed(int dialogId) {
|
||||
// Nothing to do, no change made
|
||||
}
|
||||
});
|
||||
dialog.show(getSupportFragmentManager(), "color-picker-dialog");
|
||||
}
|
||||
}
|
||||
|
||||
public static class DatePickerFragment extends DialogFragment
|
||||
implements DatePickerDialog.OnDateSetListener {
|
||||
|
||||
@@ -902,6 +1192,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
this.expiryFieldEdit = expiryFieldEdit;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
// Use the current date as the default date in the picker
|
||||
@@ -969,8 +1260,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
if (updateLoyaltyCard) { //update of "starStatus" not necessary, since it cannot be changed in this activity (only in ViewActivity)
|
||||
db.updateLoyaltyCard(loyaltyCardId, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor);
|
||||
try {
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, true);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageBack.getTag(), loyaltyCardId, false);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, ImageLocationType.front);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageBack.getTag(), loyaltyCardId, ImageLocationType.back);
|
||||
Utils.saveCardImage(this, (Bitmap) thumbnail.getTag(), loyaltyCardId, ImageLocationType.icon);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -978,8 +1270,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
} else {
|
||||
loyaltyCardId = (int) db.insertLoyaltyCard(tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, 0, tempLoyaltyCard.lastUsed);
|
||||
try {
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, true);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageBack.getTag(), loyaltyCardId, false);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, ImageLocationType.front);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageBack.getTag(), loyaltyCardId, ImageLocationType.back);
|
||||
Utils.saveCardImage(this, (Bitmap) thumbnail.getTag(), loyaltyCardId, ImageLocationType.icon);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -987,6 +1280,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
db.setLoyaltyCardGroups(loyaltyCardId, selectedGroups);
|
||||
|
||||
ShortcutHelper.updateShortcuts(this, db.getLoyaltyCard(loyaltyCardId));
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -1018,7 +1313,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
Log.e(TAG, "Deleting card: " + loyaltyCardId);
|
||||
|
||||
DBHelper db = new DBHelper(LoyaltyCardEditActivity.this);
|
||||
db.deleteLoyaltyCard(loyaltyCardId);
|
||||
db.deleteLoyaltyCard(LoyaltyCardEditActivity.this, loyaltyCardId);
|
||||
|
||||
ShortcutHelper.removeShortcut(LoyaltyCardEditActivity.this, loyaltyCardId);
|
||||
|
||||
@@ -1035,68 +1330,60 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
public void startCropper(String sourceImagePath) {
|
||||
startCropperUri(Uri.parse("file://" + sourceImagePath));
|
||||
}
|
||||
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (requestCode == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || requestCode == Utils.CARD_IMAGE_FROM_CAMERA_BACK) {
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(tempCameraPicturePath);
|
||||
public void startCropperUri(Uri sourceUri) {
|
||||
Log.d("cropper", "launching cropper with image " + sourceUri.getPath());
|
||||
File cropOutput = Utils.createTempFile(this, TEMP_CROP_IMAGE_NAME);
|
||||
Uri destUri = Uri.parse("file://" + cropOutput.getAbsolutePath());
|
||||
Log.d("cropper", "asking cropper to output to " + destUri.toString());
|
||||
|
||||
if (bitmap != null) {
|
||||
bitmap = Utils.resizeBitmap(bitmap);
|
||||
try {
|
||||
bitmap = Utils.rotateBitmap(bitmap, new ExifInterface(tempCameraPicturePath));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (requestCode == Utils.CARD_IMAGE_FROM_CAMERA_FRONT) {
|
||||
setCardImage(cardImageFront, bitmap);
|
||||
} else {
|
||||
setCardImage(cardImageBack, bitmap);
|
||||
}
|
||||
|
||||
hasChanged = true;
|
||||
} else {
|
||||
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (requestCode == Utils.CARD_IMAGE_FROM_FILE_FRONT || requestCode == Utils.CARD_IMAGE_FROM_FILE_BACK) {
|
||||
Bitmap bitmap = null;
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ImageDecoder.Source image_source = ImageDecoder.createSource(getContentResolver(), intent.getData());
|
||||
bitmap = ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true));
|
||||
} else {
|
||||
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), intent.getData());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error getting data from image file");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (bitmap != null) {
|
||||
bitmap = Utils.resizeBitmap(bitmap);
|
||||
if (requestCode == Utils.CARD_IMAGE_FROM_FILE_FRONT) {
|
||||
setCardImage(cardImageFront, bitmap);
|
||||
} else {
|
||||
setCardImage(cardImageBack, bitmap);
|
||||
}
|
||||
|
||||
hasChanged = true;
|
||||
} else {
|
||||
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else {
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
|
||||
|
||||
cardId = barcodeValues.content();
|
||||
barcodeType = barcodeValues.format();
|
||||
barcodeId = "";
|
||||
}
|
||||
if (requestedFrontImage()) {
|
||||
mCropperOptions.setToolbarTitle(getResources().getString(R.string.setFrontImage));
|
||||
} else if (requestedBackImage()) {
|
||||
mCropperOptions.setToolbarTitle(getResources().getString(R.string.setBackImage));
|
||||
} else if (requestedIcon()) {
|
||||
mCropperOptions.setToolbarTitle(getResources().getString(R.string.setIcon));
|
||||
}
|
||||
|
||||
onResume();
|
||||
if (requestedIcon()) {
|
||||
setCropperOptions(true, 0f, 0f);
|
||||
} else {
|
||||
// sniff the input image for width and height to work around a ucrop bug
|
||||
Bitmap image = null;
|
||||
try {
|
||||
image = BitmapFactory.decodeStream(getContentResolver().openInputStream(sourceUri));
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Log.d("cropper", "failed opening bitmap for initial width and height for ucrop " + sourceUri.toString());
|
||||
}
|
||||
if (image == null) {
|
||||
Log.d("cropper", "failed loading bitmap for initial width and height for ucrop " + sourceUri.toString());
|
||||
setCropperOptions(true, 0f, 0f);
|
||||
} else {
|
||||
try {
|
||||
Bitmap imageRotated = Utils.rotateBitmap(image, new ExifInterface(getContentResolver().openInputStream(sourceUri)));
|
||||
setCropperOptions(false, imageRotated.getWidth(), imageRotated.getHeight());
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Log.d("cropper", "failed opening image for exif reading before setting initial width and height for ucrop");
|
||||
setCropperOptions(false, image.getWidth(), image.getHeight());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.d("cropper", "exif reading failed before setting initial width and height for ucrop");
|
||||
setCropperOptions(false, image.getWidth(), image.getHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
mCropperLauncher.launch(
|
||||
UCrop.of(
|
||||
sourceUri,
|
||||
destUri
|
||||
).withOptions(mCropperOptions)
|
||||
.getIntent(this)
|
||||
);
|
||||
}
|
||||
|
||||
private void showBarcode() {
|
||||
@@ -1120,7 +1407,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
private void generateBarcode(String cardIdString, CatimaBarcode barcodeFormat) {
|
||||
mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false);
|
||||
|
||||
|
||||
if (barcodeImage.getHeight() == 0) {
|
||||
Log.d(TAG, "ImageView size is not known known at start, waiting for load");
|
||||
// The size of the ImageView is not yet available as it has not
|
||||
@@ -1150,14 +1437,16 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
thumbnail.setBackgroundColor(tempLoyaltyCard.headerColor);
|
||||
if (thumbnail.getTag() == null) {
|
||||
thumbnail.setBackgroundColor(tempLoyaltyCard.headerColor);
|
||||
|
||||
LetterBitmap letterBitmap = Utils.generateIcon(this, store, tempLoyaltyCard.headerColor);
|
||||
LetterBitmap letterBitmap = Utils.generateIcon(this, store, tempLoyaltyCard.headerColor);
|
||||
|
||||
if (letterBitmap != null) {
|
||||
thumbnail.setImageBitmap(letterBitmap.getLetterTile());
|
||||
} else {
|
||||
thumbnail.setImageBitmap(null);
|
||||
if (letterBitmap != null) {
|
||||
thumbnail.setImageBitmap(letterBitmap.getLetterTile());
|
||||
} else {
|
||||
thumbnail.setImageBitmap(null);
|
||||
}
|
||||
}
|
||||
|
||||
thumbnail.setMinimumWidth(thumbnail.getHeight());
|
||||
|
||||
@@ -3,7 +3,6 @@ package protect.card_locker;
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
public class LoyaltyCardLockerApplication extends Application {
|
||||
|
||||
@@ -5,11 +5,11 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.GestureDetector;
|
||||
@@ -17,6 +17,8 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
@@ -44,8 +46,11 @@ import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.constraintlayout.widget.Guideline;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
import androidx.core.widget.NestedScrollView;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
@@ -56,10 +61,11 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
|
||||
private GestureDetector mGestureDetector;
|
||||
|
||||
CoordinatorLayout coordinatorLayout;
|
||||
TextView cardIdFieldView;
|
||||
BottomSheetBehavior behavior;
|
||||
View bottomSheet;
|
||||
View bottomSheetContentWrapper;
|
||||
LinearLayout bottomSheet;
|
||||
NestedScrollView bottomSheetContentWrapper;
|
||||
ImageView bottomSheetButton;
|
||||
TextView noteView;
|
||||
TextView groupsView;
|
||||
@@ -72,6 +78,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
ImageButton minimizeButton;
|
||||
View collapsingToolbarLayout;
|
||||
AppBarLayout appBarLayout;
|
||||
ImageView iconImage;
|
||||
Toolbar landscapeToolbar;
|
||||
|
||||
int loyaltyCardId;
|
||||
LoyaltyCard loyaltyCard;
|
||||
boolean rotationEnabled;
|
||||
@@ -99,8 +108,13 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
private ImageView[] dots;
|
||||
boolean isBarcodeSupported = true;
|
||||
|
||||
int bottomSheetState;
|
||||
|
||||
static final String STATE_IMAGEINDEX = "imageIndex";
|
||||
static final String STATE_FULLSCREEN = "isFullscreen";
|
||||
static final String STATE_BOTTOMSHEET = "bottomSheetState";
|
||||
|
||||
private final int HEADER_FILTER_ALPHA = 127;
|
||||
|
||||
final private TaskHandler mTasks = new TaskHandler();
|
||||
|
||||
@@ -190,11 +204,15 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
Log.d(TAG, "View activity: id=" + loyaltyCardId);
|
||||
}
|
||||
|
||||
private Drawable getDotIcon(boolean active) {
|
||||
private Drawable getDotIcon(boolean active, boolean darkMode) {
|
||||
Drawable unwrappedIcon = AppCompatResources.getDrawable(this, active ? R.drawable.active_dot : R.drawable.inactive_dot);
|
||||
assert unwrappedIcon != null;
|
||||
Drawable wrappedIcon = DrawableCompat.wrap(unwrappedIcon);
|
||||
DrawableCompat.setTint(wrappedIcon, ContextCompat.getColor(getApplicationContext(), R.color.iconColor));
|
||||
if (darkMode) {
|
||||
DrawableCompat.setTint(wrappedIcon, Color.WHITE);
|
||||
} else {
|
||||
DrawableCompat.setTint(wrappedIcon, Color.BLACK);
|
||||
}
|
||||
|
||||
return wrappedIcon;
|
||||
}
|
||||
@@ -212,6 +230,17 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
return wrappedIcon;
|
||||
}
|
||||
|
||||
private void setCenterGuideline(int zoomLevel) {
|
||||
float scale = zoomLevel / 100f;
|
||||
|
||||
if (format != null && format.isSquare()) {
|
||||
centerGuideline.setGuidelinePercent(0.75f * scale);
|
||||
} else {
|
||||
centerGuideline.setGuidelinePercent(0.5f * scale);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -219,6 +248,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
if (savedInstanceState != null) {
|
||||
mainImageIndex = savedInstanceState.getInt(STATE_IMAGEINDEX);
|
||||
isFullscreen = savedInstanceState.getBoolean(STATE_FULLSCREEN);
|
||||
bottomSheetState = savedInstanceState.getInt(STATE_BOTTOMSHEET);
|
||||
}
|
||||
|
||||
settings = new Settings(this);
|
||||
@@ -230,6 +260,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
db = new DBHelper(this);
|
||||
importURIHelper = new ImportURIHelper(this);
|
||||
|
||||
coordinatorLayout = findViewById(R.id.coordinator_layout);
|
||||
cardIdFieldView = findViewById(R.id.cardIdView);
|
||||
bottomSheet = findViewById(R.id.bottom_sheet);
|
||||
bottomSheetContentWrapper = findViewById(R.id.bottomSheetContentWrapper);
|
||||
@@ -245,6 +276,8 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
minimizeButton = findViewById(R.id.minimizeButton);
|
||||
collapsingToolbarLayout = findViewById(R.id.collapsingToolbarLayout);
|
||||
appBarLayout = findViewById(R.id.app_bar_layout);
|
||||
iconImage = findViewById(R.id.icon_image);
|
||||
landscapeToolbar = findViewById(R.id.toolbar_landscape);
|
||||
|
||||
centerGuideline = findViewById(R.id.centerGuideline);
|
||||
barcodeScaler = findViewById(R.id.barcodeScaler);
|
||||
@@ -254,21 +287,19 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
barcodeScaler.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (!fromUser) {
|
||||
Log.d(TAG, "non user triggered onProgressChanged, ignoring, progress is " + progress);
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "Progress is " + progress);
|
||||
Log.d(TAG, "Max is " + barcodeScaler.getMax());
|
||||
float scale = (float) progress / (float) barcodeScaler.getMax();
|
||||
Log.d(TAG, "Scaling to " + scale);
|
||||
|
||||
if(isFullscreen){
|
||||
loyaltyCard.zoomLevel = progress;
|
||||
db.updateLoyaltyCardZoomLevel(loyaltyCardId, loyaltyCard.zoomLevel);
|
||||
}
|
||||
loyaltyCard.zoomLevel = progress;
|
||||
db.updateLoyaltyCardZoomLevel(loyaltyCardId, loyaltyCard.zoomLevel);
|
||||
|
||||
if (format != null && format.isSquare()) {
|
||||
centerGuideline.setGuidelinePercent(0.75f * scale);
|
||||
} else {
|
||||
centerGuideline.setGuidelinePercent(0.5f * scale);
|
||||
}
|
||||
setCenterGuideline(loyaltyCard.zoomLevel);
|
||||
|
||||
drawMainImage(mainImageIndex, true);
|
||||
}
|
||||
@@ -306,20 +337,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
behavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
|
||||
@Override
|
||||
public void onStateChanged(@NonNull View bottomSheet, int newState) {
|
||||
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
|
||||
editButton.hide();
|
||||
} else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
|
||||
bottomSheetButton.setImageResource(R.drawable.ic_baseline_arrow_drop_down_24);
|
||||
editButton.hide();
|
||||
} else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
|
||||
bottomSheetButton.setImageResource(R.drawable.ic_baseline_arrow_drop_up_24);
|
||||
if (!isFullscreen) {
|
||||
editButton.show();
|
||||
}
|
||||
|
||||
// Scroll bottomsheet content back to top
|
||||
bottomSheetContentWrapper.setScrollY(0);
|
||||
}
|
||||
changeUiToBottomSheetState(newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,22 +353,18 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
}
|
||||
});
|
||||
|
||||
// Fix bottom sheet content sizing
|
||||
ViewTreeObserver viewTreeObserver = bottomSheet.getViewTreeObserver();
|
||||
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
appBarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
bottomSheet.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
|
||||
int height = displayMetrics.heightPixels;
|
||||
int maxHeight = height - appBarLayout.getHeight() - bottomSheetButton.getHeight();
|
||||
Log.d(TAG, "Button sheet should be " + maxHeight + " pixels high");
|
||||
bottomSheetContentWrapper.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
maxHeight
|
||||
)
|
||||
);
|
||||
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
||||
adjustLayoutHeights();
|
||||
}
|
||||
});
|
||||
|
||||
appBarLayout.setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
|
||||
outline.setAlpha(0f);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -359,6 +373,53 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
mainImage.setOnTouchListener(gestureTouchListener);
|
||||
}
|
||||
|
||||
private void changeUiToBottomSheetState(int newState) {
|
||||
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
|
||||
editButton.hide();
|
||||
} else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
|
||||
bottomSheetButton.setImageResource(R.drawable.ic_baseline_arrow_drop_down_24);
|
||||
editButton.hide();
|
||||
} else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
|
||||
bottomSheetButton.setImageResource(R.drawable.ic_baseline_arrow_drop_up_24);
|
||||
if (!isFullscreen) {
|
||||
editButton.show();
|
||||
}
|
||||
|
||||
// Scroll bottomsheet content back to top
|
||||
bottomSheetContentWrapper.setScrollY(0);
|
||||
}
|
||||
bottomSheetState = newState;
|
||||
}
|
||||
|
||||
private void adjustLayoutHeights() {
|
||||
// use getLayoutParams instead of getHeight when heights are pre-determined in xml! getHeight could return 0 if a View is not inflated
|
||||
if (iconImage.getLayoutParams().height != appBarLayout.getHeight()) {
|
||||
Log.d("adjustLayoutHeights", "setting imageIcon height from: " + iconImage.getLayoutParams().height + " to: " + appBarLayout.getHeight());
|
||||
iconImage.setLayoutParams(new CoordinatorLayout.LayoutParams(
|
||||
CoordinatorLayout.LayoutParams.MATCH_PARENT, appBarLayout.getHeight())
|
||||
);
|
||||
}
|
||||
int bottomSheetHeight = getResources().getDisplayMetrics().heightPixels - appBarLayout.getHeight() - bottomSheetButton.getLayoutParams().height;
|
||||
ViewGroup.LayoutParams params = bottomSheetContentWrapper.getLayoutParams();
|
||||
if (params.height != bottomSheetHeight || params.width != LinearLayout.LayoutParams.MATCH_PARENT) {
|
||||
// XXX android 5 - 9 has so much quirks with setting bottomSheetContent height
|
||||
// just invalidate the wrapper works on 10 onward
|
||||
// bottomSheetContentWrapper.invalidate();
|
||||
// The below worked on android 5 but not 6, reloading the card then it breaks again on 6, entirely random :(
|
||||
// for (int i = 0; i < bottomSheetContentWrapper.getChildCount(); i++) {
|
||||
// bottomSheetContentWrapper.getChildAt(i).invalidate();
|
||||
// }
|
||||
// since it's basically allergic to getting enlarged then shrunk again, and setting it at all when fullscreen makes no sense
|
||||
if (!isFullscreen) {
|
||||
Log.d("adjustLayoutHeights", "setting bottomSheet height from: " + params.height + " to: " + bottomSheetHeight);
|
||||
bottomSheetContentWrapper.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, bottomSheetHeight)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
@@ -371,6 +432,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
public void onSaveInstanceState(Bundle savedInstanceState) {
|
||||
savedInstanceState.putInt(STATE_IMAGEINDEX, mainImageIndex);
|
||||
savedInstanceState.putBoolean(STATE_FULLSCREEN, isFullscreen);
|
||||
savedInstanceState.putInt(STATE_BOTTOMSHEET, bottomSheetState);
|
||||
super.onSaveInstanceState(savedInstanceState);
|
||||
}
|
||||
|
||||
@@ -489,9 +551,6 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
backgroundHeaderColor = LetterBitmap.getDefaultColor(this, loyaltyCard.store);
|
||||
}
|
||||
|
||||
collapsingToolbarLayout.setBackgroundColor(backgroundHeaderColor);
|
||||
appBarLayout.setBackgroundColor(backgroundHeaderColor);
|
||||
|
||||
int textColor;
|
||||
if (Utils.needsDarkForeground(backgroundHeaderColor)) {
|
||||
textColor = Color.BLACK;
|
||||
@@ -499,7 +558,21 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
textColor = Color.WHITE;
|
||||
}
|
||||
storeName.setTextColor(textColor);
|
||||
((Toolbar) findViewById(R.id.toolbar_landscape)).setTitleTextColor(textColor);
|
||||
landscapeToolbar.setTitleTextColor(textColor);
|
||||
|
||||
Bitmap icon = Utils.retrieveCardImage(this, loyaltyCard.id, ImageLocationType.icon);
|
||||
if (icon != null) {
|
||||
int backgroundAlphaColor = Utils.needsDarkForeground(backgroundHeaderColor) ? Color.WHITE : Color.BLACK;
|
||||
Log.d("onResume", "setting icon image");
|
||||
iconImage.setImageBitmap(icon);
|
||||
int backgroundWithAlpha = Color.argb(HEADER_FILTER_ALPHA, Color.red(backgroundAlphaColor), Color.green(backgroundAlphaColor), Color.blue(backgroundAlphaColor));
|
||||
// for images that has alpha
|
||||
appBarLayout.setBackgroundColor(backgroundWithAlpha);
|
||||
} else {
|
||||
Bitmap plain = Bitmap.createBitmap(new int[]{backgroundHeaderColor}, 1, 1, Bitmap.Config.ARGB_8888);
|
||||
iconImage.setImageBitmap(plain);
|
||||
appBarLayout.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
// If the background is very bright, we should use dark icons
|
||||
backgroundNeedsDarkIcons = Utils.needsDarkForeground(backgroundHeaderColor);
|
||||
@@ -511,8 +584,11 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
// Make notification area light if dark icons are needed
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
window.getDecorView().setSystemUiVisibility(backgroundNeedsDarkIcons ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0);
|
||||
window.setStatusBarColor(Color.TRANSPARENT);
|
||||
} else {
|
||||
// Darken statusbar if icons won't be visible otherwise
|
||||
window.setStatusBarColor(backgroundNeedsDarkIcons ? ColorUtils.blendARGB(backgroundHeaderColor, Color.BLACK, 0.15f) : Color.TRANSPARENT);
|
||||
}
|
||||
window.setStatusBarColor(Color.TRANSPARENT);
|
||||
|
||||
// Set shadow colour of store text so even same color on same color would be readable
|
||||
storeName.setShadowLayer(1, 1, 1, backgroundNeedsDarkIcons ? Color.BLACK : Color.WHITE);
|
||||
@@ -531,13 +607,12 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
imageTypes.add(ImageType.BARCODE);
|
||||
}
|
||||
|
||||
frontImageBitmap = Utils.retrieveCardImage(this, loyaltyCard.id, true);
|
||||
backImageBitmap = Utils.retrieveCardImage(this, loyaltyCard.id, false);
|
||||
|
||||
frontImageBitmap = Utils.retrieveCardImage(this, loyaltyCard.id, ImageLocationType.front);
|
||||
if (frontImageBitmap != null) {
|
||||
imageTypes.add(ImageType.IMAGE_FRONT);
|
||||
}
|
||||
|
||||
backImageBitmap = Utils.retrieveCardImage(this, loyaltyCard.id, ImageLocationType.back);
|
||||
if (backImageBitmap != null) {
|
||||
imageTypes.add(ImageType.IMAGE_BACK);
|
||||
}
|
||||
@@ -545,10 +620,11 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
dotIndicator.removeAllViews();
|
||||
if (imageTypes.size() >= 2) {
|
||||
dots = new ImageView[imageTypes.size()];
|
||||
boolean darkMode = Utils.isDarkModeEnabled(getApplicationContext());
|
||||
|
||||
for (int i = 0; i < imageTypes.size(); i++) {
|
||||
dots[i] = new ImageView(this);
|
||||
dots[i].setImageDrawable(getDotIcon(false));
|
||||
dots[i].setImageDrawable(getDotIcon(false, darkMode));
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
params.setMargins(8, 0, 8, 0);
|
||||
@@ -561,6 +637,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
|
||||
setFullscreen(isFullscreen);
|
||||
|
||||
// restore bottomSheet UI states from changing orientation
|
||||
changeUiToBottomSheetState(bottomSheetState);
|
||||
|
||||
db.updateLoyaltyCardLastUsed(loyaltyCard.id);
|
||||
}
|
||||
|
||||
@@ -647,7 +726,6 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
|
||||
private void setupOrientation() {
|
||||
Toolbar portraitToolbar = findViewById(R.id.toolbar);
|
||||
Toolbar landscapeToolbar = findViewById(R.id.toolbar_landscape);
|
||||
|
||||
int orientation = getResources().getConfiguration().orientation;
|
||||
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
@@ -736,8 +814,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
}
|
||||
|
||||
if (dots != null) {
|
||||
boolean darkMode = Utils.isDarkModeEnabled(getApplicationContext());
|
||||
for (int i = 0; i < dots.length; i++) {
|
||||
dots[i].setImageDrawable(getDotIcon(i == index));
|
||||
dots[i].setImageDrawable(getDotIcon(i == index, darkMode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,7 +860,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
|
||||
/**
|
||||
* When enabled, hides the status bar and moves the barcode to the top of the screen.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*/
|
||||
@@ -795,6 +874,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
drawMainImage(mainImageIndex, true);
|
||||
|
||||
barcodeScaler.setProgress(loyaltyCard.zoomLevel);
|
||||
setCenterGuideline(loyaltyCard.zoomLevel);
|
||||
|
||||
// Hide maximize and show minimize button and scaler
|
||||
maximizeButton.setVisibility(View.GONE);
|
||||
@@ -813,7 +893,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
// Don't ask me why...
|
||||
appBarLayout.setVisibility(View.INVISIBLE);
|
||||
collapsingToolbarLayout.setVisibility(View.GONE);
|
||||
findViewById(R.id.toolbar_landscape).setVisibility(View.GONE);
|
||||
landscapeToolbar.setVisibility(View.GONE);
|
||||
|
||||
// Hide other UI elements
|
||||
cardIdFieldView.setVisibility(View.GONE);
|
||||
@@ -821,6 +901,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
editButton.hide();
|
||||
|
||||
// android 5-9, avoid padding growing on top of bottomSheet
|
||||
coordinatorLayout.removeView(bottomSheet);
|
||||
|
||||
// Set Android to fullscreen mode
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
getWindow().getDecorView().getSystemUiVisibility()
|
||||
@@ -831,7 +914,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
Log.d(TAG, "Move out of fullscreen");
|
||||
|
||||
// Reset center guideline
|
||||
barcodeScaler.setProgress(100);
|
||||
setCenterGuideline(100);
|
||||
|
||||
drawMainImage(mainImageIndex, true);
|
||||
|
||||
@@ -849,8 +932,6 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
// Show appropriate toolbar
|
||||
// And restore 24dp paddingTop for appBarLayout
|
||||
appBarLayout.setVisibility(View.VISIBLE);
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
setupOrientation();
|
||||
|
||||
// Show other UI elements
|
||||
@@ -864,8 +945,13 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
& ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
& ~View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
);
|
||||
|
||||
// android 5-9, avoid padding growing on top of bottomSheet
|
||||
if (bottomSheet.getParent() != coordinatorLayout) {
|
||||
coordinatorLayout.addView(bottomSheet);
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("setFullScreen","Is full screen enabled? "+enabled+" Zoom Level = "+barcodeScaler.getProgress());
|
||||
Log.d("setFullScreen", "Is full screen enabled? " + enabled + " Zoom Level = " + barcodeScaler.getProgress());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorIndexOutOfBoundsException;
|
||||
import android.os.Bundle;
|
||||
@@ -27,23 +26,24 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.view.ActionMode;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.splashscreen.SplashScreen;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import protect.card_locker.preferences.SettingsActivity;
|
||||
|
||||
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener
|
||||
{
|
||||
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private final DBHelper mDB = new DBHelper(this);
|
||||
private LoyaltyCardCursorAdapter mAdapter;
|
||||
private ActionMode mCurrentActionMode;
|
||||
private Menu mMenu;
|
||||
private SearchView mSearchView;
|
||||
private GestureDetector mGestureDetector;
|
||||
protected String mFilter = "";
|
||||
protected Object mGroup = null;
|
||||
@@ -55,8 +55,9 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
private View mNoMatchingCardsText;
|
||||
private View mNoGroupCardsText;
|
||||
|
||||
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback()
|
||||
{
|
||||
private ActivityResultLauncher<Intent> mBarcodeScannerLauncher;
|
||||
|
||||
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback() {
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode inputMode, Menu inputMenu) {
|
||||
inputMode.getMenuInflater().inflate(R.menu.card_longclick_menu, inputMenu);
|
||||
@@ -64,8 +65,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode inputMode, Menu inputMenu)
|
||||
{
|
||||
public boolean onPrepareActionMode(ActionMode inputMode, Menu inputMenu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
inputMode.finish();
|
||||
return true;
|
||||
} else if(inputItem.getItemId() == R.id.action_edit) {
|
||||
} else if (inputItem.getItemId() == R.id.action_edit) {
|
||||
if (mAdapter.getSelectedItemCount() != 1) {
|
||||
throw new IllegalArgumentException("Cannot edit more than 1 card at a time");
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
startActivity(intent);
|
||||
inputMode.finish();
|
||||
return true;
|
||||
} else if(inputItem.getItemId() == R.id.action_delete) {
|
||||
} else if (inputItem.getItemId() == R.id.action_delete) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
|
||||
// The following may seem weird, but it is necessary to give translators enough flexibility.
|
||||
// For example, in Russian, Android's plural quantity "one" actually refers to "any number ending on 1 but not ending in 11".
|
||||
@@ -142,7 +142,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
|
||||
Log.e(TAG, "Deleting card: " + loyaltyCard.id);
|
||||
|
||||
db.deleteLoyaltyCard(loyaltyCard.id);
|
||||
db.deleteLoyaltyCard(MainActivity.this, loyaltyCard.id);
|
||||
|
||||
ShortcutHelper.removeShortcut(MainActivity.this, loyaltyCard.id);
|
||||
}
|
||||
@@ -165,24 +165,14 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode inputMode)
|
||||
{
|
||||
public void onDestroyActionMode(ActionMode inputMode) {
|
||||
mAdapter.clearSelections();
|
||||
mCurrentActionMode = null;
|
||||
mCardList.post(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mAdapter.resetAnimationIndex();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle inputSavedInstanceState)
|
||||
{
|
||||
protected void onCreate(Bundle inputSavedInstanceState) {
|
||||
super.onCreate(inputSavedInstanceState);
|
||||
SplashScreen.installSplashScreen(this);
|
||||
setTitle(R.string.app_name);
|
||||
@@ -195,7 +185,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
selectedTab = tab.getPosition();
|
||||
Log.d("onTabSelected","Tab Position "+tab.getPosition());
|
||||
Log.d("onTabSelected", "Tab Position " + tab.getPosition());
|
||||
mGroup = tab.getTag();
|
||||
updateLoyaltyCardList();
|
||||
// Store active tab in Shared Preference to restore next app launch
|
||||
@@ -269,27 +259,37 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
.show();
|
||||
}
|
||||
*/
|
||||
|
||||
mBarcodeScannerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
Intent intent = result.getData();
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(Utils.BARCODE_SCAN, result.getResultCode(), intent, this);
|
||||
|
||||
if (!barcodeValues.isEmpty()) {
|
||||
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
|
||||
Bundle newBundle = new Bundle();
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_BARCODETYPE, barcodeValues.format());
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, barcodeValues.content());
|
||||
Bundle inputBundle = intent.getExtras();
|
||||
if (inputBundle != null && inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) != null) {
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP));
|
||||
}
|
||||
newIntent.putExtras(newBundle);
|
||||
startActivity(newIntent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if(mCurrentActionMode != null)
|
||||
{
|
||||
if (mCurrentActionMode != null) {
|
||||
mAdapter.clearSelections();
|
||||
mCurrentActionMode.finish();
|
||||
}
|
||||
|
||||
if (mMenu != null)
|
||||
{
|
||||
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
|
||||
|
||||
if (!searchView.isIconified())
|
||||
{
|
||||
mFilter = searchView.getQuery().toString();
|
||||
}
|
||||
if (mSearchView != null && !mSearchView.isIconified()) {
|
||||
mFilter = mSearchView.getQuery().toString();
|
||||
}
|
||||
|
||||
// Start of active tab logic
|
||||
@@ -307,7 +307,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
try {
|
||||
mOrder = DBHelper.LoyaltyCardOrder.valueOf(sortPref.getString(getString(R.string.sharedpreference_sort_order), null));
|
||||
mOrderDirection = DBHelper.LoyaltyCardOrderDirection.valueOf(sortPref.getString(getString(R.string.sharedpreference_sort_direction), null));
|
||||
} catch (IllegalArgumentException | NullPointerException ignored) {}
|
||||
} catch (IllegalArgumentException | NullPointerException ignored) {
|
||||
}
|
||||
|
||||
mGroup = null;
|
||||
|
||||
@@ -332,57 +333,18 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
bundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, groupsTabLayout.getTabAt(selectedTab).getText().toString());
|
||||
}
|
||||
intent.putExtras(bundle);
|
||||
startActivityForResult(intent, Utils.BARCODE_SCAN);
|
||||
mBarcodeScannerLauncher.launch(intent);
|
||||
});
|
||||
addButton.bringToFront();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
if (requestCode == Utils.MAIN_REQUEST) {
|
||||
// We're coming back from another view so clear the search
|
||||
// We only do this now to prevent a flash of all entries right after picking one
|
||||
mFilter = "";
|
||||
if (mMenu != null)
|
||||
{
|
||||
MenuItem searchItem = mMenu.findItem(R.id.action_search);
|
||||
searchItem.collapseActionView();
|
||||
}
|
||||
ActivityCompat.recreate(this);
|
||||
|
||||
public void onBackPressed() {
|
||||
if (!mSearchView.isIconified()) {
|
||||
mSearchView.setIconified(true);
|
||||
return;
|
||||
}
|
||||
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
|
||||
|
||||
if(!barcodeValues.isEmpty()) {
|
||||
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
|
||||
Bundle newBundle = new Bundle();
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_BARCODETYPE, barcodeValues.format());
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, barcodeValues.content());
|
||||
Bundle inputBundle = intent.getExtras();
|
||||
if (inputBundle != null && inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) != null) {
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP));
|
||||
}
|
||||
newIntent.putExtras(newBundle);
|
||||
startActivity(newIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed()
|
||||
{
|
||||
if (mMenu != null) {
|
||||
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
|
||||
|
||||
if (!searchView.isIconified()) {
|
||||
searchView.setIconified(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@@ -394,20 +356,16 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
mAdapter.swapCursor(mDB.getLoyaltyCardCursor(mFilter, group, mOrder, mOrderDirection));
|
||||
|
||||
if(mDB.getLoyaltyCardCount() > 0)
|
||||
{
|
||||
if (mDB.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
|
||||
mHelpText.setVisibility(View.GONE);
|
||||
mNoGroupCardsText.setVisibility(View.GONE);
|
||||
if(mAdapter.getItemCount() > 0)
|
||||
{
|
||||
if (mAdapter.getItemCount() > 0) {
|
||||
mCardList.setVisibility(View.VISIBLE);
|
||||
mNoMatchingCardsText.setVisibility(View.GONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
mCardList.setVisibility(View.GONE);
|
||||
if (!mFilter.isEmpty()) {
|
||||
// Actual Empty Search Result
|
||||
@@ -419,9 +377,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
mNoGroupCardsText.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
mCardList.setVisibility(View.GONE);
|
||||
mHelpText.setVisibility(View.VISIBLE);
|
||||
mNoMatchingCardsText.setVisibility(View.GONE);
|
||||
@@ -433,8 +389,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTabGroups(TabLayout groupsTabLayout)
|
||||
{
|
||||
public void updateTabGroups(TabLayout groupsTabLayout) {
|
||||
final DBHelper db = new DBHelper(this);
|
||||
|
||||
List<Group> newGroups = db.getGroups();
|
||||
@@ -463,35 +418,28 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu inputMenu)
|
||||
{
|
||||
this.mMenu = inputMenu;
|
||||
|
||||
public boolean onCreateOptionsMenu(Menu inputMenu) {
|
||||
getMenuInflater().inflate(R.menu.main_menu, inputMenu);
|
||||
|
||||
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
|
||||
if (searchManager != null)
|
||||
{
|
||||
SearchView searchView = (SearchView) inputMenu.findItem(R.id.action_search).getActionView();
|
||||
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
|
||||
searchView.setSubmitButtonEnabled(false);
|
||||
if (searchManager != null) {
|
||||
mSearchView = (SearchView) inputMenu.findItem(R.id.action_search).getActionView();
|
||||
mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
|
||||
mSearchView.setSubmitButtonEnabled(false);
|
||||
|
||||
searchView.setOnCloseListener(() -> {
|
||||
mSearchView.setOnCloseListener(() -> {
|
||||
invalidateOptionsMenu();
|
||||
return false;
|
||||
});
|
||||
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
|
||||
{
|
||||
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query)
|
||||
{
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText)
|
||||
{
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
mFilter = newText;
|
||||
|
||||
TabLayout groupsTabLayout = findViewById(R.id.groups);
|
||||
@@ -508,12 +456,26 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem inputItem)
|
||||
{
|
||||
public boolean onOptionsItemSelected(MenuItem inputItem) {
|
||||
int id = inputItem.getItemId();
|
||||
|
||||
if (id == R.id.action_sort)
|
||||
{
|
||||
if (id == R.id.action_unfold) {
|
||||
boolean shouldShow = !mAdapter.showingDetails();
|
||||
|
||||
if (shouldShow) {
|
||||
inputItem.setIcon(R.drawable.ic_baseline_unfold_less_24);
|
||||
inputItem.setTitle(R.string.action_hide_details);
|
||||
} else {
|
||||
inputItem.setIcon(R.drawable.ic_baseline_unfold_more_24);
|
||||
inputItem.setTitle(R.string.action_show_details);
|
||||
}
|
||||
|
||||
mAdapter.showDetails(shouldShow);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_sort) {
|
||||
TabLayout.Tab tab = ((TabLayout) findViewById(R.id.groups)).getTabAt(selectedTab);
|
||||
AtomicInteger currentIndex = new AtomicInteger();
|
||||
List<DBHelper.LoyaltyCardOrder> loyaltyCardOrders = Arrays.asList(DBHelper.LoyaltyCardOrder.values());
|
||||
@@ -536,10 +498,9 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
builder.setSingleChoiceItems(R.array.sort_types_array, currentIndex.get(), (dialog, which) -> currentIndex.set(which));
|
||||
|
||||
builder.setPositiveButton(R.string.sort, (dialog, which) -> {
|
||||
if(ch.isChecked()) {
|
||||
if (ch.isChecked()) {
|
||||
setSort(loyaltyCardOrders.get(currentIndex.get()), DBHelper.LoyaltyCardOrderDirection.Descending);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
setSort(loyaltyCardOrders.get(currentIndex.get()), DBHelper.LoyaltyCardOrderDirection.Ascending);
|
||||
}
|
||||
dialog.dismiss();
|
||||
@@ -553,31 +514,27 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_manage_groups)
|
||||
{
|
||||
if (id == R.id.action_manage_groups) {
|
||||
Intent i = new Intent(getApplicationContext(), ManageGroupsActivity.class);
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_import_export)
|
||||
{
|
||||
if (id == R.id.action_import_export) {
|
||||
Intent i = new Intent(getApplicationContext(), ImportExportActivity.class);
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_settings)
|
||||
{
|
||||
if (id == R.id.action_settings) {
|
||||
Intent i = new Intent(getApplicationContext(), SettingsActivity.class);
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_about)
|
||||
{
|
||||
if (id == R.id.action_about) {
|
||||
Intent i = new Intent(getApplicationContext(), AboutActivity.class);
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -602,13 +559,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
updateLoyaltyCardList();
|
||||
}
|
||||
|
||||
protected static boolean isDarkModeEnabled(Context inputContext)
|
||||
{
|
||||
Configuration config = inputContext.getResources().getConfiguration();
|
||||
int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
return (currentNightMode == Configuration.UI_MODE_NIGHT_YES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent e) {
|
||||
return false;
|
||||
@@ -655,10 +605,10 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
|
||||
Integer currentTab = groupsTabLayout.getSelectedTabPosition();
|
||||
Log.d("onFling","Current Tab "+currentTab);
|
||||
Log.d("onFling", "Current Tab " + currentTab);
|
||||
// Swipe right
|
||||
if (velocityX < -150) {
|
||||
Log.d("onFling","Right Swipe detected "+velocityX);
|
||||
Log.d("onFling", "Right Swipe detected " + velocityX);
|
||||
Integer nextTab = currentTab + 1;
|
||||
|
||||
if (nextTab == groupsTabLayout.getTabCount()) {
|
||||
@@ -672,7 +622,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
// Swipe left
|
||||
if (velocityX > 150) {
|
||||
Log.d("onFling","Left Swipe detected "+velocityX);
|
||||
Log.d("onFling", "Left Swipe detected " + velocityX);
|
||||
Integer nextTab = currentTab - 1;
|
||||
|
||||
if (nextTab < 0) {
|
||||
@@ -688,22 +638,18 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRowLongClicked(int inputPosition)
|
||||
{
|
||||
public void onRowLongClicked(int inputPosition) {
|
||||
enableActionMode(inputPosition);
|
||||
}
|
||||
|
||||
private void enableActionMode(int inputPosition)
|
||||
{
|
||||
if (mCurrentActionMode == null)
|
||||
{
|
||||
private void enableActionMode(int inputPosition) {
|
||||
if (mCurrentActionMode == null) {
|
||||
mCurrentActionMode = startSupportActionMode(mCurrentActionModeCallback);
|
||||
}
|
||||
toggleSelection(inputPosition);
|
||||
}
|
||||
|
||||
private void toggleSelection(int inputPosition)
|
||||
{
|
||||
private void toggleSelection(int inputPosition) {
|
||||
mAdapter.toggleSelection(inputPosition);
|
||||
int count = mAdapter.getSelectedItemCount();
|
||||
|
||||
@@ -725,18 +671,11 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRowClicked(int inputPosition)
|
||||
{
|
||||
if (mAdapter.getSelectedItemCount() > 0)
|
||||
{
|
||||
public void onRowClicked(int inputPosition) {
|
||||
if (mAdapter.getSelectedItemCount() > 0) {
|
||||
enableActionMode(inputPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
Cursor selected = mAdapter.getCursor();
|
||||
selected.moveToPosition(inputPosition);
|
||||
} else {
|
||||
// FIXME
|
||||
//
|
||||
// There is a really nasty edge case that can happen when someone taps a card but right
|
||||
@@ -747,7 +686,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
// click is being processed. Sadly, I have not yet found a way to make that possible.
|
||||
LoyaltyCard loyaltyCard;
|
||||
try {
|
||||
loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
|
||||
loyaltyCard = mAdapter.getCard(inputPosition);
|
||||
} catch (CursorIndexOutOfBoundsException e) {
|
||||
Log.w(TAG, "Prevented crash from tap + swipe on ID " + inputPosition + ": " + e);
|
||||
return;
|
||||
@@ -761,7 +700,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard);
|
||||
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
216
app/src/main/java/protect/card_locker/ManageGroupActivity.java
Normal file
216
app/src/main/java/protect/card_locker/ManageGroupActivity.java
Normal file
@@ -0,0 +1,216 @@
|
||||
package protect.card_locker;
|
||||
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class ManageGroupActivity extends CatimaAppCompatActivity implements ManageGroupCursorAdapter.CardAdapterListener {
|
||||
|
||||
private final DBHelper mDB = new DBHelper(this);
|
||||
private ManageGroupCursorAdapter mAdapter;
|
||||
|
||||
private final String SAVE_INSTANCE_ADAPTER_STATE = "adapterState";
|
||||
private final String SAVE_INSTANCE_CURRENT_GROUP_NAME = "currentGroupName";
|
||||
|
||||
protected Group mGroup = null;
|
||||
private RecyclerView mCardList;
|
||||
private TextView mHelpText;
|
||||
private EditText mGroupNameText;
|
||||
|
||||
private boolean mGroupNameNotInUse;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle inputSavedInstanceState) {
|
||||
super.onCreate(inputSavedInstanceState);
|
||||
setContentView(R.layout.activity_manage_group);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
mHelpText = findViewById(R.id.helpText);
|
||||
mCardList = findViewById(R.id.list);
|
||||
FloatingActionButton saveButton = findViewById(R.id.fabSave);
|
||||
|
||||
mGroupNameText = findViewById(R.id.editTextGroupName);
|
||||
|
||||
mGroupNameText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
mGroupNameNotInUse = true;
|
||||
mGroupNameText.setError(null);
|
||||
String currentGroupName = mGroupNameText.getText().toString().trim();
|
||||
if (currentGroupName.length() == 0) {
|
||||
mGroupNameText.setError(getResources().getText(R.string.group_name_is_empty));
|
||||
return;
|
||||
}
|
||||
if (!mGroup._id.equals(currentGroupName)) {
|
||||
if (mDB.getGroup(currentGroupName) != null) {
|
||||
mGroupNameNotInUse = false;
|
||||
mGroupNameText.setError(getResources().getText(R.string.group_name_already_in_use));
|
||||
} else {
|
||||
mGroupNameNotInUse = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Intent intent = getIntent();
|
||||
String groupId = intent.getStringExtra("group");
|
||||
if (groupId == null) {
|
||||
throw (new IllegalArgumentException("this activity expects a group loaded into it's intent"));
|
||||
}
|
||||
Log.d("groupId", "groupId: " + groupId);
|
||||
mGroup = mDB.getGroup(groupId);
|
||||
if (mGroup == null) {
|
||||
throw (new IllegalArgumentException("cannot load group " + groupId + " from database"));
|
||||
}
|
||||
mGroupNameText.setText(mGroup._id);
|
||||
setTitle(getString(R.string.editGroup, mGroup._id));
|
||||
mAdapter = new ManageGroupCursorAdapter(this, null, this, mGroup);
|
||||
mCardList.setAdapter(mAdapter);
|
||||
registerForContextMenu(mCardList);
|
||||
|
||||
if (inputSavedInstanceState != null) {
|
||||
mAdapter.importInGroupState(integerArrayToAdapterState(inputSavedInstanceState.getIntegerArrayList(SAVE_INSTANCE_ADAPTER_STATE)));
|
||||
mGroupNameText.setText(inputSavedInstanceState.getString(SAVE_INSTANCE_CURRENT_GROUP_NAME));
|
||||
}
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar == null) {
|
||||
throw (new RuntimeException("mActionBar is not expected to be null here"));
|
||||
}
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
|
||||
saveButton.setOnClickListener(v -> {
|
||||
String currentGroupName = mGroupNameText.getText().toString().trim();
|
||||
if (!currentGroupName.equals(mGroup._id)) {
|
||||
if (currentGroupName.length() == 0) {
|
||||
Toast.makeText(getApplicationContext(), R.string.group_name_is_empty, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if (!mGroupNameNotInUse) {
|
||||
Toast.makeText(getApplicationContext(), R.string.group_name_already_in_use, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mAdapter.commitToDatabase();
|
||||
if (!currentGroupName.equals(mGroup._id)) {
|
||||
mDB.updateGroup(mGroup._id, currentGroupName);
|
||||
}
|
||||
Toast.makeText(getApplicationContext(), R.string.group_updated, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
});
|
||||
// this setText is here because content_main.xml is reused from main activity
|
||||
mHelpText.setText(getResources().getText(R.string.noGiftCardsGroup));
|
||||
updateLoyaltyCardList();
|
||||
}
|
||||
|
||||
private ArrayList<Integer> adapterStateToIntegerArray(HashMap<Integer, Boolean> adapterState) {
|
||||
ArrayList<Integer> ret = new ArrayList<>(adapterState.size() * 2);
|
||||
for (Map.Entry<Integer, Boolean> entry : adapterState.entrySet()) {
|
||||
ret.add(entry.getKey());
|
||||
ret.add(entry.getValue() ? 1 : 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private HashMap<Integer, Boolean> integerArrayToAdapterState(ArrayList<Integer> in) {
|
||||
HashMap<Integer, Boolean> ret = new HashMap<>();
|
||||
if (in.size() % 2 != 0) {
|
||||
throw (new RuntimeException("failed restoring adapterState from integer array list"));
|
||||
}
|
||||
for (int i = 0; i < in.size(); i += 2) {
|
||||
ret.put(in.get(i), in.get(i + 1) == 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putIntegerArrayList(SAVE_INSTANCE_ADAPTER_STATE, adapterStateToIntegerArray(mAdapter.exportInGroupState()));
|
||||
outState.putString(SAVE_INSTANCE_CURRENT_GROUP_NAME, mGroupNameText.getText().toString());
|
||||
}
|
||||
|
||||
private void updateLoyaltyCardList() {
|
||||
mAdapter.swapCursor(mDB.getLoyaltyCardCursor());
|
||||
|
||||
if (mAdapter.getItemCount() == 0) {
|
||||
mCardList.setVisibility(View.GONE);
|
||||
mHelpText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mCardList.setVisibility(View.VISIBLE);
|
||||
mHelpText.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void leaveWithoutSaving() {
|
||||
if (hasChanged()) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ManageGroupActivity.this);
|
||||
builder.setTitle(R.string.leaveWithoutSaveTitle);
|
||||
builder.setMessage(R.string.leaveWithoutSaveConfirmation);
|
||||
builder.setPositiveButton(R.string.confirm, (dialog, which) -> finish());
|
||||
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
leaveWithoutSaving();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasChanged() {
|
||||
return mAdapter.hasChanged() || !mGroup._id.equals(mGroupNameText.getText().toString().trim());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRowLongClicked(int inputPosition) {
|
||||
// do nothing for now
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRowClicked(int inputPosition) {
|
||||
mAdapter.toggleSelection(inputPosition);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ManageGroupCursorAdapter extends LoyaltyCardCursorAdapter {
|
||||
private HashMap<Integer, Integer> mIndexCardMap;
|
||||
private HashMap<Integer, Boolean> mInGroupOverlay;
|
||||
private HashMap<Integer, Boolean> mIsLoyaltyCardInGroupCache;
|
||||
private HashMap<Integer, List<Group>> mGetGroupCache;
|
||||
final private Group mGroup;
|
||||
final private DBHelper mDb;
|
||||
|
||||
public ManageGroupCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener, Group group) {
|
||||
super(inputContext, inputCursor, inputListener);
|
||||
mGroup = new Group(group._id, group.order);
|
||||
mInGroupOverlay = new HashMap<>();
|
||||
mDb = new DBHelper(inputContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swapCursor(Cursor inputCursor) {
|
||||
super.swapCursor(inputCursor);
|
||||
mIndexCardMap = new HashMap<>();
|
||||
mIsLoyaltyCardInGroupCache = new HashMap<>();
|
||||
mGetGroupCache = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor inputCursor) {
|
||||
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(inputCursor);
|
||||
Boolean overlayValue = mInGroupOverlay.get(loyaltyCard.id);
|
||||
if ((overlayValue != null ? overlayValue : isLoyaltyCardInGroup(loyaltyCard.id))) {
|
||||
mAnimationItemsIndex.put(inputCursor.getPosition(), true);
|
||||
mSelectedItems.put(inputCursor.getPosition(), true);
|
||||
}
|
||||
mIndexCardMap.put(inputCursor.getPosition(), loyaltyCard.id);
|
||||
super.onBindViewHolder(inputHolder, inputCursor);
|
||||
}
|
||||
|
||||
private List<Group> getGroups(int cardId) {
|
||||
List<Group> cache = mGetGroupCache.get(cardId);
|
||||
if (cache != null) {
|
||||
return cache;
|
||||
}
|
||||
List<Group> groups = mDb.getLoyaltyCardGroups(cardId);
|
||||
mGetGroupCache.put(cardId, groups);
|
||||
return groups;
|
||||
}
|
||||
|
||||
private boolean isLoyaltyCardInGroup(int cardId) {
|
||||
Boolean cache = mIsLoyaltyCardInGroupCache.get(cardId);
|
||||
if (cache != null) {
|
||||
return cache;
|
||||
}
|
||||
List<Group> groups = getGroups(cardId);
|
||||
if (groups.contains(mGroup)) {
|
||||
mIsLoyaltyCardInGroupCache.put(cardId, true);
|
||||
return true;
|
||||
}
|
||||
mIsLoyaltyCardInGroupCache.put(cardId, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleSelection(int inputPosition) {
|
||||
super.toggleSelection(inputPosition);
|
||||
Integer cardId = mIndexCardMap.get(inputPosition);
|
||||
if (cardId == null) {
|
||||
throw (new RuntimeException("cardId should not be null here"));
|
||||
}
|
||||
Boolean overlayValue = mInGroupOverlay.get(cardId);
|
||||
if (overlayValue == null) {
|
||||
mInGroupOverlay.put(cardId, !isLoyaltyCardInGroup(cardId));
|
||||
} else {
|
||||
mInGroupOverlay.remove(cardId);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasChanged() {
|
||||
return mInGroupOverlay.size() > 0;
|
||||
}
|
||||
|
||||
public void commitToDatabase() {
|
||||
for (Map.Entry<Integer, Boolean> entry : mInGroupOverlay.entrySet()) {
|
||||
int cardId = entry.getKey();
|
||||
List<Group> groups = getGroups(cardId);
|
||||
if (entry.getValue()) {
|
||||
groups.add(mGroup);
|
||||
} else {
|
||||
groups.remove(mGroup);
|
||||
}
|
||||
mDb.setLoyaltyCardGroups(cardId, groups);
|
||||
}
|
||||
}
|
||||
|
||||
public void importInGroupState(HashMap<Integer, Boolean> cardIdInGroupMap) {
|
||||
mInGroupOverlay = new HashMap<>(cardIdInGroupMap);
|
||||
}
|
||||
|
||||
public HashMap<Integer, Boolean> exportInGroupState() {
|
||||
return new HashMap<>(mInGroupOverlay);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
@@ -9,6 +10,7 @@ import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
@@ -21,8 +23,7 @@ import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class ManageGroupsActivity extends CatimaAppCompatActivity implements GroupCursorAdapter.GroupAdapterListener
|
||||
{
|
||||
public class ManageGroupsActivity extends CatimaAppCompatActivity implements GroupCursorAdapter.GroupAdapterListener {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private final DBHelper mDb = new DBHelper(this);
|
||||
@@ -31,16 +32,14 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
GroupCursorAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setTitle(R.string.groups);
|
||||
setContentView(R.layout.manage_groups_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if(actionBar != null)
|
||||
{
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
}
|
||||
@@ -72,8 +71,7 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
private void updateGroupList()
|
||||
{
|
||||
private void updateGroupList() {
|
||||
mAdapter.swapCursor(mDb.getGroupCursor());
|
||||
|
||||
if (mDb.getGroupCount() == 0) {
|
||||
@@ -87,8 +85,7 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
mHelpText.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void invalidateHomescreenActiveTab()
|
||||
{
|
||||
private void invalidateHomescreenActiveTab() {
|
||||
SharedPreferences activeTabPref = getApplicationContext().getSharedPreferences(
|
||||
getString(R.string.sharedpreference_active_tab),
|
||||
Context.MODE_PRIVATE);
|
||||
@@ -98,8 +95,7 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
if (id == android.R.id.home) {
|
||||
@@ -110,14 +106,23 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
}
|
||||
|
||||
private void createGroup() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this,R.style.AlertDialogTheme);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AlertDialogTheme);
|
||||
builder.setTitle(R.string.enter_group_name);
|
||||
final EditText input = new EditText(this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton(getString(R.string.ok), (dialog, which) -> {
|
||||
mDb.insertGroup(input.getText().toString());
|
||||
String inputString = input.getText().toString().trim();
|
||||
if (inputString.length() == 0) {
|
||||
Toast.makeText(getApplicationContext(), R.string.group_name_is_empty, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if (mDb.getGroup(inputString) != null) {
|
||||
Toast.makeText(getApplicationContext(), R.string.group_name_already_in_use, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
mDb.insertGroup(inputString);
|
||||
updateGroupList();
|
||||
});
|
||||
builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel());
|
||||
@@ -176,25 +181,9 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
|
||||
@Override
|
||||
public void onEditButtonClicked(View view) {
|
||||
final String groupName = getGroupName(view);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.enter_group_name);
|
||||
final EditText input = new EditText(this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
input.setText(groupName);
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton(getString(R.string.ok), (dialog, which) -> {
|
||||
String newGroupName = input.getText().toString();
|
||||
mDb.updateGroup(groupName, newGroupName);
|
||||
updateGroupList();
|
||||
});
|
||||
builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel());
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
|
||||
input.requestFocus();
|
||||
Intent intent = new Intent(this, ManageGroupActivity.class);
|
||||
intent.putExtra("group", getGroupName(view));
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,12 +20,14 @@ import com.journeyapps.barcodescanner.DecoratedBarcodeView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
/**
|
||||
* Custom Scannner Activity extending from Activity to display a custom layout form scanner view.
|
||||
*
|
||||
* <p>
|
||||
* Based on https://github.com/journeyapps/zxing-android-embedded/blob/0fdfbce9fb3285e985bad9971c5f7c0a7a334e7b/sample/src/main/java/example/zxing/CustomScannerActivity.java
|
||||
* originally licensed under Apache 2.0
|
||||
*/
|
||||
@@ -39,6 +41,10 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
private String addGroup;
|
||||
private boolean torch = false;
|
||||
|
||||
private ActivityResultLauncher<Intent> manualAddLauncher;
|
||||
// can't use the pre-made contract because that launches the file manager for image type instead of gallery
|
||||
private ActivityResultLauncher<Intent> photoPickerLauncher;
|
||||
|
||||
private void extractIntentFields(Intent intent) {
|
||||
final Bundle b = intent.getExtras();
|
||||
cardId = b != null ? b.getString(LoyaltyCardEditActivity.BUNDLE_CARDID) : null;
|
||||
@@ -54,13 +60,14 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if(actionBar != null)
|
||||
{
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
extractIntentFields(getIntent());
|
||||
|
||||
manualAddLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.SELECT_BARCODE_REQUEST, result.getResultCode(), result.getData()));
|
||||
photoPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_IMAGE_FILE, result.getResultCode(), result.getData()));
|
||||
findViewById(R.id.add_from_image).setOnClickListener(this::addFromImage);
|
||||
findViewById(R.id.add_manually).setOnClickListener(this::addManually);
|
||||
|
||||
@@ -127,8 +134,7 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
|
||||
getMenuInflater().inflate(R.menu.scan_menu, menu);
|
||||
}
|
||||
@@ -139,10 +145,8 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
if (item.getItemId() == android.R.id.home)
|
||||
{
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
setResult(Activity.RESULT_CANCELED);
|
||||
finish();
|
||||
return true;
|
||||
@@ -163,9 +167,7 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent)
|
||||
{
|
||||
private void handleActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
BarcodeValues barcodeValues;
|
||||
@@ -198,12 +200,12 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
b.putString("initialCardId", cardId);
|
||||
i.putExtras(b);
|
||||
}
|
||||
startActivityForResult(i, Utils.SELECT_BARCODE_REQUEST);
|
||||
manualAddLauncher.launch(i);
|
||||
}
|
||||
|
||||
public void addFromImage(View view) {
|
||||
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
|
||||
photoPickerIntent.setType("image/*");
|
||||
startActivityForResult(photoPickerIntent, Utils.BARCODE_IMPORT_FROM_IMAGE_FILE);
|
||||
photoPickerLauncher.launch(photoPickerIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,12 @@ package protect.card_locker;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
@@ -12,10 +16,10 @@ import java.util.List;
|
||||
|
||||
import androidx.core.content.pm.ShortcutInfoCompat;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
|
||||
class ShortcutHelper
|
||||
{
|
||||
class ShortcutHelper {
|
||||
// Android documentation says that no more than 5 shortcuts
|
||||
// are supported. However, that may be too many, as not all
|
||||
// launcher will show all 5. Instead, the number is limited
|
||||
@@ -23,6 +27,14 @@ class ShortcutHelper
|
||||
// chance of being shown.
|
||||
private static final int MAX_SHORTCUTS = 3;
|
||||
|
||||
// https://developer.android.com/reference/android/graphics/drawable/AdaptiveIconDrawable.html
|
||||
private static final int ADAPTIVE_BITMAP_SCALE = 1;
|
||||
private static final int ADAPTIVE_BITMAP_SIZE = 108 * ADAPTIVE_BITMAP_SCALE;
|
||||
private static final int ADAPTIVE_BITMAP_VISIBLE_SIZE = 72 * ADAPTIVE_BITMAP_SCALE;
|
||||
private static final int ADAPTIVE_BITMAP_IMAGE_SIZE = ADAPTIVE_BITMAP_VISIBLE_SIZE + 5 * ADAPTIVE_BITMAP_SCALE;
|
||||
private static final int PADDING_COLOR = Color.argb(255, 255, 255, 255);
|
||||
private static final int PADDING_COLOR_OVERLAY = Color.argb(127, 0, 0, 0);
|
||||
|
||||
/**
|
||||
* Add a card to the app shortcuts, and maintain a list of the most
|
||||
* recently used cards. If there is already a shortcut for the card,
|
||||
@@ -30,8 +42,7 @@ class ShortcutHelper
|
||||
* card exceeds the max number of shortcuts, then the least recently
|
||||
* used card shortcut is discarded.
|
||||
*/
|
||||
static void updateShortcuts(Context context, LoyaltyCard card)
|
||||
{
|
||||
static void updateShortcuts(Context context, LoyaltyCard card) {
|
||||
LinkedList<ShortcutInfoCompat> list = new LinkedList<>(ShortcutManagerCompat.getDynamicShortcuts(context));
|
||||
|
||||
DBHelper dbHelper = new DBHelper(context);
|
||||
@@ -44,31 +55,25 @@ class ShortcutHelper
|
||||
|
||||
Integer foundIndex = null;
|
||||
|
||||
for(int index = 0; index < list.size(); index++)
|
||||
{
|
||||
if(list.get(index).getId().equals(shortcutId))
|
||||
{
|
||||
for (int index = 0; index < list.size(); index++) {
|
||||
if (list.get(index).getId().equals(shortcutId)) {
|
||||
// Found the item already
|
||||
foundIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(foundIndex != null)
|
||||
{
|
||||
if (foundIndex != null) {
|
||||
// If the item is already found, then the list needs to be
|
||||
// reordered, so that the selected item now has the lowest
|
||||
// rank, thus letting it survive longer.
|
||||
ShortcutInfoCompat found = list.remove(foundIndex.intValue());
|
||||
list.addFirst(found);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// The item is new to the list. First, we need to trim the list
|
||||
// until it is able to accept a new item, then the item is
|
||||
// inserted.
|
||||
while(list.size() >= MAX_SHORTCUTS)
|
||||
{
|
||||
while (list.size() >= MAX_SHORTCUTS) {
|
||||
list.pollLast();
|
||||
}
|
||||
|
||||
@@ -80,15 +85,14 @@ class ShortcutHelper
|
||||
LinkedList<ShortcutInfoCompat> finalList = new LinkedList<>();
|
||||
|
||||
// The ranks are now updated; the order in the list is the rank.
|
||||
for(int index = 0; index < list.size(); index++)
|
||||
{
|
||||
for (int index = 0; index < list.size(); index++) {
|
||||
ShortcutInfoCompat prevShortcut = list.get(index);
|
||||
|
||||
LoyaltyCard loyaltyCard = dbHelper.getLoyaltyCard(Integer.parseInt(prevShortcut.getId()));
|
||||
|
||||
ShortcutInfoCompat updatedShortcut = createShortcutBuilder(context, loyaltyCard)
|
||||
.setRank(index)
|
||||
.build();
|
||||
.setRank(index)
|
||||
.build();
|
||||
|
||||
finalList.addLast(updatedShortcut);
|
||||
}
|
||||
@@ -100,16 +104,13 @@ class ShortcutHelper
|
||||
* Remove the given card id from the app shortcuts, if such a
|
||||
* shortcut exists.
|
||||
*/
|
||||
static void removeShortcut(Context context, int cardId)
|
||||
{
|
||||
static void removeShortcut(Context context, int cardId) {
|
||||
List<ShortcutInfoCompat> list = ShortcutManagerCompat.getDynamicShortcuts(context);
|
||||
|
||||
String shortcutId = Integer.toString(cardId);
|
||||
|
||||
for(int index = 0; index < list.size(); index++)
|
||||
{
|
||||
if(list.get(index).getId().equals(shortcutId))
|
||||
{
|
||||
for (int index = 0; index < list.size(); index++) {
|
||||
if (list.get(index).getId().equals(shortcutId)) {
|
||||
list.remove(index);
|
||||
break;
|
||||
}
|
||||
@@ -118,6 +119,16 @@ class ShortcutHelper
|
||||
ShortcutManagerCompat.setDynamicShortcuts(context, list);
|
||||
}
|
||||
|
||||
static @NotNull
|
||||
Bitmap createAdaptiveBitmap(@NotNull Bitmap in, int paddingColor) {
|
||||
Bitmap ret = Bitmap.createBitmap(ADAPTIVE_BITMAP_SIZE, ADAPTIVE_BITMAP_SIZE, Bitmap.Config.ARGB_8888);
|
||||
Canvas output = new Canvas(ret);
|
||||
output.drawColor(ColorUtils.compositeColors(PADDING_COLOR_OVERLAY, paddingColor));
|
||||
Bitmap resized = Utils.resizeBitmap(in, ADAPTIVE_BITMAP_IMAGE_SIZE);
|
||||
output.drawBitmap(resized, (ADAPTIVE_BITMAP_SIZE - resized.getWidth()) / 2f, (ADAPTIVE_BITMAP_SIZE - resized.getHeight()) / 2f, null);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ShortcutInfoCompat.Builder createShortcutBuilder(Context context, LoyaltyCard loyaltyCard) {
|
||||
Intent intent = new Intent(context, LoyaltyCardViewActivity.class);
|
||||
intent.setAction(Intent.ACTION_MAIN);
|
||||
@@ -129,7 +140,12 @@ class ShortcutHelper
|
||||
bundle.putBoolean("view", true);
|
||||
intent.putExtras(bundle);
|
||||
|
||||
Bitmap iconBitmap = Utils.generateIcon(context, loyaltyCard, true).getLetterTile();
|
||||
Bitmap iconBitmap = Utils.retrieveCardImage(context, loyaltyCard.id, ImageLocationType.icon);
|
||||
if (iconBitmap == null) {
|
||||
iconBitmap = Utils.generateIcon(context, loyaltyCard, true).getLetterTile();
|
||||
} else {
|
||||
iconBitmap = createAdaptiveBitmap(iconBitmap, loyaltyCard.headerColor == null ? PADDING_COLOR : loyaltyCard.headerColor);
|
||||
}
|
||||
|
||||
IconCompat icon = IconCompat.createWithAdaptiveBitmap(iconBitmap);
|
||||
|
||||
|
||||
@@ -5,11 +5,14 @@ import android.text.TextWatcher;
|
||||
|
||||
public class SimpleTextWatcher implements TextWatcher {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) { }
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) { }
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.google.zxing.Result;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -38,6 +39,7 @@ import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import protect.card_locker.preferences.Settings;
|
||||
@@ -52,12 +54,15 @@ public class Utils {
|
||||
public static final int BARCODE_IMPORT_FROM_IMAGE_FILE = 4;
|
||||
public static final int CARD_IMAGE_FROM_CAMERA_FRONT = 5;
|
||||
public static final int CARD_IMAGE_FROM_CAMERA_BACK = 6;
|
||||
public static final int CARD_IMAGE_FROM_FILE_FRONT = 7;
|
||||
public static final int CARD_IMAGE_FROM_FILE_BACK = 8;
|
||||
public static final int CARD_IMAGE_FROM_CAMERA_ICON = 7;
|
||||
public static final int CARD_IMAGE_FROM_FILE_FRONT = 8;
|
||||
public static final int CARD_IMAGE_FROM_FILE_BACK = 9;
|
||||
public static final int CARD_IMAGE_FROM_FILE_ICON = 10;
|
||||
|
||||
static final double LUMINANCE_MIDPOINT = 0.5;
|
||||
|
||||
static final int BITMAP_SIZE_BIG = 512;
|
||||
static final int BITMAP_SIZE_SMALL = 512;
|
||||
static final int BITMAP_SIZE_BIG = 2048;
|
||||
|
||||
static public LetterBitmap generateIcon(Context context, LoyaltyCard loyaltyCard, boolean forShortcut) {
|
||||
return generateIcon(context, loyaltyCard.store, loyaltyCard.headerColor, forShortcut);
|
||||
@@ -79,7 +84,7 @@ public class Utils {
|
||||
tileLetterFontSize = context.getResources().getDimensionPixelSize(R.dimen.tileLetterFontSize);
|
||||
}
|
||||
|
||||
int pixelSize = context.getResources().getDimensionPixelSize(R.dimen.cardThumbnailSize);
|
||||
int pixelSize = context.getResources().getDimensionPixelSize(R.dimen.tileLetterImageSize);
|
||||
|
||||
if (backgroundColor == null) {
|
||||
backgroundColor = LetterBitmap.getDefaultColor(context, store);
|
||||
@@ -264,13 +269,11 @@ public class Utils {
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
static public Bitmap resizeBitmap(Bitmap bitmap) {
|
||||
static public Bitmap resizeBitmap(Bitmap bitmap, double maxSize) {
|
||||
if (bitmap == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
double maxSize = BITMAP_SIZE_BIG;
|
||||
|
||||
double width = bitmap.getWidth();
|
||||
double height = bitmap.getHeight();
|
||||
|
||||
@@ -313,16 +316,20 @@ public class Utils {
|
||||
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
}
|
||||
|
||||
static public String getCardImageFileName(int loyaltyCardId, boolean front) {
|
||||
static public String getCardImageFileName(int loyaltyCardId, ImageLocationType type) {
|
||||
StringBuilder cardImageFileNameBuilder = new StringBuilder();
|
||||
|
||||
cardImageFileNameBuilder.append("card_");
|
||||
cardImageFileNameBuilder.append(loyaltyCardId);
|
||||
cardImageFileNameBuilder.append("_");
|
||||
if (front) {
|
||||
if (type == ImageLocationType.front) {
|
||||
cardImageFileNameBuilder.append("front");
|
||||
} else {
|
||||
} else if (type == ImageLocationType.back) {
|
||||
cardImageFileNameBuilder.append("back");
|
||||
} else if (type == ImageLocationType.icon) {
|
||||
cardImageFileNameBuilder.append("icon");
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown image type");
|
||||
}
|
||||
cardImageFileNameBuilder.append(".png");
|
||||
|
||||
@@ -340,8 +347,8 @@ public class Utils {
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
}
|
||||
|
||||
static public void saveCardImage(Context context, Bitmap bitmap, int loyaltyCardId, boolean front) throws FileNotFoundException {
|
||||
saveCardImage(context, bitmap, getCardImageFileName(loyaltyCardId, front));
|
||||
static public void saveCardImage(Context context, Bitmap bitmap, int loyaltyCardId, ImageLocationType type) throws FileNotFoundException {
|
||||
saveCardImage(context, bitmap, getCardImageFileName(loyaltyCardId, type));
|
||||
}
|
||||
|
||||
static public Bitmap retrieveCardImage(Context context, String fileName) {
|
||||
@@ -355,11 +362,11 @@ public class Utils {
|
||||
return BitmapFactory.decodeStream(in);
|
||||
}
|
||||
|
||||
static public Bitmap retrieveCardImage(Context context, int loyaltyCardId, boolean front) {
|
||||
return retrieveCardImage(context, getCardImageFileName(loyaltyCardId, front));
|
||||
static public Bitmap retrieveCardImage(Context context, int loyaltyCardId, ImageLocationType type) {
|
||||
return retrieveCardImage(context, getCardImageFileName(loyaltyCardId, type));
|
||||
}
|
||||
|
||||
static public <T,U> U mapGetOrDefault(Map<T,U> map, T key, U defaultValue) {
|
||||
static public <T, U> U mapGetOrDefault(Map<T, U> map, T key, U defaultValue) {
|
||||
U value = map.get(key);
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
@@ -401,4 +408,44 @@ public class Utils {
|
||||
static public long getUnixTime() {
|
||||
return System.currentTimeMillis() / 1000;
|
||||
}
|
||||
|
||||
static public boolean isDarkModeEnabled(Context inputContext) {
|
||||
int nightModeSetting = new Settings(inputContext).getTheme();
|
||||
if (nightModeSetting == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
|
||||
Configuration config = inputContext.getResources().getConfiguration();
|
||||
int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
return (currentNightMode == Configuration.UI_MODE_NIGHT_YES);
|
||||
} else {
|
||||
return nightModeSetting == AppCompatDelegate.MODE_NIGHT_YES;
|
||||
}
|
||||
}
|
||||
|
||||
public static File createTempFile(Context context, String name) {
|
||||
return new File(context.getCacheDir() + "/" + name);
|
||||
}
|
||||
|
||||
public static String saveTempImage(Context context, Bitmap in, String name, Bitmap.CompressFormat format) {
|
||||
File image = createTempFile(context, name);
|
||||
try (FileOutputStream out = new FileOutputStream(image)) {
|
||||
in.compress(format, 100, out);
|
||||
return image.getAbsolutePath();
|
||||
} catch (IOException e) {
|
||||
Log.d("store temp image", "failed writing temp file for temporary image, name: " + name);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap loadImage(String path) {
|
||||
try {
|
||||
return BitmapFactory.decodeStream(new FileInputStream(path));
|
||||
} catch (IOException e) {
|
||||
Log.d("load image", "failed loading image from " + path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap loadTempImage(Context context, String name) {
|
||||
return loadImage(context.getCacheDir() + "/" + name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@ import java.util.concurrent.Callable;
|
||||
|
||||
public interface CompatCallable<T> extends Callable<T> {
|
||||
void onPostExecute(Object result);
|
||||
|
||||
void onPreExecute();
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* AsyncTask has been deprecated so this provides very rudimentary compatibility without
|
||||
* needing to redo too many Parts.
|
||||
*
|
||||
* <p>
|
||||
* However this is a much, much more cooperative Behaviour than before so
|
||||
* the callers need to ensure we do NOT rely on forced cancellation and feed less into the
|
||||
* ThreadPools so we don't OOM/Overload the Users device
|
||||
*
|
||||
* <p>
|
||||
* This assumes single-threaded callers.
|
||||
*/
|
||||
public class TaskHandler {
|
||||
@@ -44,9 +44,10 @@ public class TaskHandler {
|
||||
|
||||
/**
|
||||
* Replaces (or initializes) an Executor with a clean (new) one
|
||||
*
|
||||
* @param executors Map Reference
|
||||
* @param type Which Queue
|
||||
* @param flushOld attempt shutdown
|
||||
* @param type Which Queue
|
||||
* @param flushOld attempt shutdown
|
||||
* @param waitOnOld wait for Termination
|
||||
*/
|
||||
private void replaceExecutor(HashMap<TYPE, ThreadPoolExecutor> executors, TYPE type, Boolean flushOld, Boolean waitOnOld) {
|
||||
|
||||
@@ -12,18 +12,13 @@ public class CSVHelpers {
|
||||
* if it is not null. Otherwise, a FormatException is thrown.
|
||||
*/
|
||||
static String extractString(String key, CSVRecord record, String defaultValue)
|
||||
throws FormatException
|
||||
{
|
||||
throws FormatException {
|
||||
String toReturn = defaultValue;
|
||||
|
||||
if(record.isMapped(key))
|
||||
{
|
||||
if (record.isMapped(key)) {
|
||||
toReturn = record.get(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(defaultValue == null)
|
||||
{
|
||||
} else {
|
||||
if (defaultValue == null) {
|
||||
throw new FormatException("Field not used but expected: " + key);
|
||||
}
|
||||
}
|
||||
@@ -38,25 +33,19 @@ public class CSVHelpers {
|
||||
* int, a FormatException is thrown.
|
||||
*/
|
||||
static Integer extractInt(String key, CSVRecord record, boolean nullIsOk)
|
||||
throws FormatException
|
||||
{
|
||||
if(record.isMapped(key) == false)
|
||||
{
|
||||
throws FormatException {
|
||||
if (record.isMapped(key) == false) {
|
||||
throw new FormatException("Field not used but expected: " + key);
|
||||
}
|
||||
|
||||
String value = record.get(key);
|
||||
if(value.isEmpty() && nullIsOk)
|
||||
{
|
||||
if (value.isEmpty() && nullIsOk) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
return Integer.parseInt(record.get(key));
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
} catch (NumberFormatException e) {
|
||||
throw new FormatException("Failed to parse field: " + key, e);
|
||||
}
|
||||
}
|
||||
@@ -68,25 +57,19 @@ public class CSVHelpers {
|
||||
* int, a FormatException is thrown.
|
||||
*/
|
||||
static Long extractLong(String key, CSVRecord record, boolean nullIsOk)
|
||||
throws FormatException
|
||||
{
|
||||
if(record.isMapped(key) == false)
|
||||
{
|
||||
throws FormatException {
|
||||
if (record.isMapped(key) == false) {
|
||||
throw new FormatException("Field not used but expected: " + key);
|
||||
}
|
||||
|
||||
String value = record.get(key);
|
||||
if(value.isEmpty() && nullIsOk)
|
||||
{
|
||||
if (value.isEmpty() && nullIsOk) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
return Long.parseLong(record.get(key));
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
} catch (NumberFormatException e) {
|
||||
throw new FormatException("Failed to parse field: " + key, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
import protect.card_locker.DBHelper;
|
||||
import protect.card_locker.Group;
|
||||
import protect.card_locker.ImageLocationType;
|
||||
import protect.card_locker.LoyaltyCard;
|
||||
import protect.card_locker.Utils;
|
||||
|
||||
@@ -29,10 +30,8 @@ import protect.card_locker.Utils;
|
||||
* Class for exporting the database into CSV (Comma Separate Values)
|
||||
* format.
|
||||
*/
|
||||
public class CatimaExporter implements Exporter
|
||||
{
|
||||
public void exportData(Context context, DBHelper db, OutputStream output,char[] password) throws IOException, InterruptedException
|
||||
{
|
||||
public class CatimaExporter implements Exporter {
|
||||
public void exportData(Context context, DBHelper db, OutputStream output, char[] password) throws IOException, InterruptedException {
|
||||
// Necessary vars
|
||||
int readLen;
|
||||
byte[] readBuffer = new byte[InternalZipConstants.BUFF_SIZE];
|
||||
@@ -40,10 +39,9 @@ public class CatimaExporter implements Exporter
|
||||
// Create zip output stream
|
||||
ZipOutputStream zipOutputStream;
|
||||
|
||||
if(password!=null && password.length>0){
|
||||
zipOutputStream = new ZipOutputStream(output,password);
|
||||
}
|
||||
else{
|
||||
if (password != null && password.length > 0) {
|
||||
zipOutputStream = new ZipOutputStream(output, password);
|
||||
} else {
|
||||
zipOutputStream = new ZipOutputStream(output);
|
||||
}
|
||||
|
||||
@@ -53,7 +51,7 @@ public class CatimaExporter implements Exporter
|
||||
writeCSV(db, catimaOutputStreamWriter);
|
||||
|
||||
// Add CSV to zip file
|
||||
ZipParameters csvZipParameters = createZipParameters("catima.csv",password);
|
||||
ZipParameters csvZipParameters = createZipParameters("catima.csv", password);
|
||||
zipOutputStream.putNextEntry(csvZipParameters);
|
||||
InputStream csvInputStream = new ByteArrayInputStream(catimaOutputStream.toByteArray());
|
||||
while ((readLen = csvInputStream.read(readBuffer)) != -1) {
|
||||
@@ -63,22 +61,16 @@ public class CatimaExporter implements Exporter
|
||||
|
||||
// Loop over all cards again
|
||||
Cursor cardCursor = db.getLoyaltyCardCursor();
|
||||
while(cardCursor.moveToNext())
|
||||
{
|
||||
while (cardCursor.moveToNext()) {
|
||||
// For each card
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor);
|
||||
|
||||
// Prepare looping over both front and back image
|
||||
boolean[] frontValues = new boolean[2];
|
||||
frontValues[0] = true;
|
||||
frontValues[1] = false;
|
||||
|
||||
// For each image
|
||||
for (boolean front : frontValues) {
|
||||
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
|
||||
// If it exists, add to the .zip file
|
||||
Bitmap image = Utils.retrieveCardImage(context, card.id, front);
|
||||
Bitmap image = Utils.retrieveCardImage(context, card.id, imageLocationType);
|
||||
if (image != null) {
|
||||
ZipParameters imageZipParameters = createZipParameters(Utils.getCardImageFileName(card.id, front),password);
|
||||
ZipParameters imageZipParameters = createZipParameters(Utils.getCardImageFileName(card.id, imageLocationType), password);
|
||||
zipOutputStream.putNextEntry(imageZipParameters);
|
||||
InputStream imageInputStream = new ByteArrayInputStream(Utils.bitmapToByteArray(image));
|
||||
while ((readLen = imageInputStream.read(readBuffer)) != -1) {
|
||||
@@ -92,10 +84,10 @@ public class CatimaExporter implements Exporter
|
||||
zipOutputStream.close();
|
||||
}
|
||||
|
||||
private ZipParameters createZipParameters(String fileName, char[] password){
|
||||
private ZipParameters createZipParameters(String fileName, char[] password) {
|
||||
ZipParameters zipParameters = new ZipParameters();
|
||||
zipParameters.setFileNameInZip(fileName);
|
||||
if(password!=null && password.length>0){
|
||||
if (password != null && password.length > 0) {
|
||||
zipParameters.setEncryptFiles(true);
|
||||
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
|
||||
}
|
||||
@@ -115,14 +107,12 @@ public class CatimaExporter implements Exporter
|
||||
|
||||
Cursor groupCursor = db.getGroupCursor();
|
||||
|
||||
while(groupCursor.moveToNext())
|
||||
{
|
||||
while (groupCursor.moveToNext()) {
|
||||
Group group = Group.toGroup(groupCursor);
|
||||
|
||||
printer.printRecord(group._id);
|
||||
|
||||
if(Thread.currentThread().isInterrupted())
|
||||
{
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
@@ -148,8 +138,7 @@ public class CatimaExporter implements Exporter
|
||||
|
||||
Cursor cardCursor = db.getLoyaltyCardCursor();
|
||||
|
||||
while(cardCursor.moveToNext())
|
||||
{
|
||||
while (cardCursor.moveToNext()) {
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor);
|
||||
|
||||
printer.printRecord(card.id,
|
||||
@@ -165,8 +154,7 @@ public class CatimaExporter implements Exporter
|
||||
card.starStatus,
|
||||
card.lastUsed);
|
||||
|
||||
if(Thread.currentThread().isInterrupted())
|
||||
{
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
@@ -182,16 +170,14 @@ public class CatimaExporter implements Exporter
|
||||
|
||||
Cursor cardCursor2 = db.getLoyaltyCardCursor();
|
||||
|
||||
while(cardCursor2.moveToNext())
|
||||
{
|
||||
while (cardCursor2.moveToNext()) {
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor2);
|
||||
|
||||
for (Group group : db.getLoyaltyCardGroups(card.id)) {
|
||||
printer.printRecord(card.id, group._id);
|
||||
}
|
||||
|
||||
if(Thread.currentThread().isInterrupted())
|
||||
{
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import net.lingala.zip4j.io.inputstream.ZipInputStream;
|
||||
import net.lingala.zip4j.model.LocalFileHeader;
|
||||
|
||||
@@ -37,18 +35,17 @@ import protect.card_locker.ZipUtils;
|
||||
/**
|
||||
* Class for importing a database from CSV (Comma Separate Values)
|
||||
* formatted data.
|
||||
*
|
||||
* <p>
|
||||
* The database's loyalty cards are expected to appear in the CSV data.
|
||||
* A header is expected for the each table showing the names of the columns.
|
||||
*/
|
||||
public class CatimaImporter implements Importer
|
||||
{
|
||||
public class CatimaImporter implements Importer {
|
||||
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, InterruptedException {
|
||||
InputStream bufferedInputStream = new BufferedInputStream(input);
|
||||
bufferedInputStream.mark(100);
|
||||
|
||||
// First, check if this is a zip file
|
||||
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream,password);
|
||||
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream, password);
|
||||
|
||||
boolean isZipFile = false;
|
||||
|
||||
@@ -102,41 +99,32 @@ public class CatimaImporter implements Importer
|
||||
bufferedReader.close();
|
||||
}
|
||||
|
||||
public void parseV1(Context context, DBHelper db, BufferedReader input) throws IOException, FormatException, InterruptedException
|
||||
{
|
||||
public void parseV1(Context context, DBHelper db, BufferedReader input) throws IOException, FormatException, InterruptedException {
|
||||
final CSVParser parser = new CSVParser(input, CSVFormat.RFC4180.builder().setHeader().build());
|
||||
|
||||
SQLiteDatabase database = db.getWritableDatabase();
|
||||
database.beginTransaction();
|
||||
|
||||
try
|
||||
{
|
||||
for (CSVRecord record : parser)
|
||||
{
|
||||
try {
|
||||
for (CSVRecord record : parser) {
|
||||
importLoyaltyCard(context, database, db, record);
|
||||
|
||||
if(Thread.currentThread().isInterrupted())
|
||||
{
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
|
||||
parser.close();
|
||||
database.setTransactionSuccessful();
|
||||
}
|
||||
catch(IllegalArgumentException|IllegalStateException e)
|
||||
{
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
throw new FormatException("Issue parsing CSV data", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
} finally {
|
||||
database.endTransaction();
|
||||
database.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void parseV2(Context context, DBHelper db, BufferedReader input) throws IOException, FormatException, InterruptedException
|
||||
{
|
||||
public void parseV2(Context context, DBHelper db, BufferedReader input) throws IOException, FormatException, InterruptedException {
|
||||
SQLiteDatabase database = db.getWritableDatabase();
|
||||
database.beginTransaction();
|
||||
|
||||
@@ -206,8 +194,7 @@ public class CatimaImporter implements Importer
|
||||
}
|
||||
}
|
||||
|
||||
public void parseV2Groups(DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
|
||||
{
|
||||
public void parseV2Groups(DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
|
||||
// Parse groups
|
||||
final CSVParser groupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
|
||||
|
||||
@@ -232,8 +219,7 @@ public class CatimaImporter implements Importer
|
||||
}
|
||||
}
|
||||
|
||||
public void parseV2Cards(Context context, DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
|
||||
{
|
||||
public void parseV2Cards(Context context, DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
|
||||
// Parse cards
|
||||
final CSVParser cardParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
|
||||
|
||||
@@ -258,8 +244,7 @@ public class CatimaImporter implements Importer
|
||||
}
|
||||
}
|
||||
|
||||
public void parseV2CardGroups(DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException
|
||||
{
|
||||
public void parseV2CardGroups(DBHelper db, SQLiteDatabase database, String data) throws IOException, FormatException, InterruptedException {
|
||||
// Parse card group mappings
|
||||
final CSVParser cardGroupParser = new CSVParser(new StringReader(data), CSVFormat.RFC4180.builder().setHeader().build());
|
||||
|
||||
@@ -289,13 +274,11 @@ public class CatimaImporter implements Importer
|
||||
* session.
|
||||
*/
|
||||
private void importLoyaltyCard(Context context, SQLiteDatabase database, DBHelper helper, CSVRecord record)
|
||||
throws IOException, FormatException
|
||||
{
|
||||
throws IOException, FormatException {
|
||||
int id = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ID, record, false);
|
||||
|
||||
String store = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.STORE, record, "");
|
||||
if(store.isEmpty())
|
||||
{
|
||||
if (store.isEmpty()) {
|
||||
throw new FormatException("No store listed, but is required");
|
||||
}
|
||||
|
||||
@@ -303,12 +286,13 @@ public class CatimaImporter implements Importer
|
||||
Date expiry = null;
|
||||
try {
|
||||
expiry = new Date(CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.EXPIRY, record, true));
|
||||
} catch (NullPointerException | FormatException e) { }
|
||||
} catch (NullPointerException | FormatException e) {
|
||||
}
|
||||
|
||||
BigDecimal balance;
|
||||
try {
|
||||
balance = new BigDecimal(CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE, record, null));
|
||||
} catch (FormatException _e ) {
|
||||
} catch (FormatException _e) {
|
||||
// These fields did not exist in versions 1.8.1 and before
|
||||
// We catch this exception so we can still import old backups
|
||||
balance = new BigDecimal("0");
|
||||
@@ -316,33 +300,29 @@ public class CatimaImporter implements Importer
|
||||
|
||||
Currency balanceType = null;
|
||||
String unparsedBalanceType = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE, record, "");
|
||||
if(!unparsedBalanceType.isEmpty()) {
|
||||
if (!unparsedBalanceType.isEmpty()) {
|
||||
balanceType = Currency.getInstance(unparsedBalanceType);
|
||||
}
|
||||
|
||||
String cardId = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.CARD_ID, record, "");
|
||||
if(cardId.isEmpty())
|
||||
{
|
||||
if (cardId.isEmpty()) {
|
||||
throw new FormatException("No card ID listed, but is required");
|
||||
}
|
||||
|
||||
String barcodeId = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BARCODE_ID, record, "");
|
||||
if(barcodeId.isEmpty())
|
||||
{
|
||||
if (barcodeId.isEmpty()) {
|
||||
barcodeId = null;
|
||||
}
|
||||
|
||||
CatimaBarcode barcodeType = null;
|
||||
String unparsedBarcodeType = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE, record, "");
|
||||
if(!unparsedBarcodeType.isEmpty())
|
||||
{
|
||||
if (!unparsedBarcodeType.isEmpty()) {
|
||||
barcodeType = CatimaBarcode.fromName(unparsedBarcodeType);
|
||||
}
|
||||
|
||||
Integer headerColor = null;
|
||||
|
||||
if(record.isMapped(DBHelper.LoyaltyCardDbIds.HEADER_COLOR))
|
||||
{
|
||||
if (record.isMapped(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)) {
|
||||
headerColor = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.HEADER_COLOR, record, true);
|
||||
}
|
||||
|
||||
@@ -371,8 +351,7 @@ public class CatimaImporter implements Importer
|
||||
* session.
|
||||
*/
|
||||
private void importGroup(SQLiteDatabase database, DBHelper helper, CSVRecord record)
|
||||
throws IOException, FormatException
|
||||
{
|
||||
throws IOException, FormatException {
|
||||
String id = CSVHelpers.extractString(DBHelper.LoyaltyCardDbGroups.ID, record, null);
|
||||
|
||||
helper.insertGroup(database, id);
|
||||
@@ -383,8 +362,7 @@ public class CatimaImporter implements Importer
|
||||
* session.
|
||||
*/
|
||||
private void importCardGroupMapping(SQLiteDatabase database, DBHelper helper, CSVRecord record)
|
||||
throws IOException, FormatException
|
||||
{
|
||||
throws IOException, FormatException {
|
||||
Integer cardId = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIdsGroups.cardID, record, false);
|
||||
String groupId = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIdsGroups.groupID, record, null);
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package protect.card_locker.importexport;
|
||||
|
||||
public enum DataFormat
|
||||
{
|
||||
public enum DataFormat {
|
||||
Catima,
|
||||
Fidme,
|
||||
Stocard,
|
||||
VoucherVault
|
||||
;
|
||||
VoucherVault;
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ import protect.card_locker.DBHelper;
|
||||
* Interface for a class which can export the contents of the database
|
||||
* in a given format.
|
||||
*/
|
||||
public interface Exporter
|
||||
{
|
||||
public interface Exporter {
|
||||
/**
|
||||
* Export the database to the output stream in a given format.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
void exportData(Context context, DBHelper db, OutputStream output,char[] password) throws IOException, InterruptedException;
|
||||
void exportData(Context context, DBHelper db, OutputStream output, char[] password) throws IOException, InterruptedException;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package protect.card_locker.importexport;
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import net.lingala.zip4j.io.inputstream.ZipInputStream;
|
||||
import net.lingala.zip4j.model.LocalFileHeader;
|
||||
|
||||
@@ -23,12 +21,11 @@ import java.text.ParseException;
|
||||
import protect.card_locker.CatimaBarcode;
|
||||
import protect.card_locker.DBHelper;
|
||||
import protect.card_locker.FormatException;
|
||||
import protect.card_locker.Utils;
|
||||
|
||||
/**
|
||||
* Class for importing a database from CSV (Comma Separate Values)
|
||||
* formatted data.
|
||||
*
|
||||
* <p>
|
||||
* The database's loyalty cards are expected to appear in the CSV data.
|
||||
* A header is expected for the each table showing the names of the columns.
|
||||
*/
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package protect.card_locker.importexport;
|
||||
|
||||
public enum ImportExportResult
|
||||
{
|
||||
public enum ImportExportResult {
|
||||
Success,
|
||||
GenericFailure,
|
||||
BadPassword
|
||||
;
|
||||
BadPassword;
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ import protect.card_locker.FormatException;
|
||||
* Interface for a class which can import the contents of a stream
|
||||
* into the database.
|
||||
*/
|
||||
public interface Importer
|
||||
{
|
||||
public interface Importer {
|
||||
/**
|
||||
* Import data from the input stream in a given format into
|
||||
* the database.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws FormatException
|
||||
*/
|
||||
|
||||
@@ -8,26 +8,23 @@ import java.io.OutputStream;
|
||||
|
||||
import protect.card_locker.DBHelper;
|
||||
|
||||
public class MultiFormatExporter
|
||||
{
|
||||
public class MultiFormatExporter {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
/**
|
||||
* Attempts to export data to the output stream in the
|
||||
* given format, if possible.
|
||||
*
|
||||
* <p>
|
||||
* The output stream is closed on success.
|
||||
*
|
||||
* @return ImportExportResult.Success if the database was successfully exported,
|
||||
* another ImportExportResult otherwise. If not Success, partial data may have been
|
||||
* written to the output stream, and it should be discarded.
|
||||
*/
|
||||
public static ImportExportResult exportData(Context context, DBHelper db, OutputStream output, DataFormat format,char[] password)
|
||||
{
|
||||
public static ImportExportResult exportData(Context context, DBHelper db, OutputStream output, DataFormat format, char[] password) {
|
||||
Exporter exporter = null;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
switch (format) {
|
||||
case Catima:
|
||||
exporter = new CatimaExporter();
|
||||
break;
|
||||
@@ -36,26 +33,18 @@ public class MultiFormatExporter
|
||||
break;
|
||||
}
|
||||
|
||||
if(exporter != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
exporter.exportData(context, db, output,password);
|
||||
if (exporter != null) {
|
||||
try {
|
||||
exporter.exportData(context, db, output, password);
|
||||
return ImportExportResult.Success;
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to export data", e);
|
||||
}
|
||||
catch(InterruptedException e)
|
||||
{
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Failed to export data", e);
|
||||
}
|
||||
|
||||
return ImportExportResult.GenericFailure;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Log.e(TAG, "Unsupported data format exported: " + format.name());
|
||||
return ImportExportResult.GenericFailure;
|
||||
}
|
||||
|
||||
@@ -14,14 +14,13 @@ import java.text.ParseException;
|
||||
import protect.card_locker.DBHelper;
|
||||
import protect.card_locker.FormatException;
|
||||
|
||||
public class MultiFormatImporter
|
||||
{
|
||||
public class MultiFormatImporter {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
/**
|
||||
* Attempts to import data from the input stream of the
|
||||
* given format into the database.
|
||||
*
|
||||
* <p>
|
||||
* The input stream is not closed, and doing so is the
|
||||
* responsibility of the caller.
|
||||
*
|
||||
@@ -29,12 +28,10 @@ public class MultiFormatImporter
|
||||
* or another result otherwise. If no Success, no data was written to
|
||||
* the database.
|
||||
*/
|
||||
public static ImportExportResult importData(Context context, DBHelper db, InputStream input, DataFormat format, char[] password)
|
||||
{
|
||||
public static ImportExportResult importData(Context context, DBHelper db, InputStream input, DataFormat format, char[] password) {
|
||||
Importer importer = null;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
switch (format) {
|
||||
case Catima:
|
||||
importer = new CatimaImporter();
|
||||
break;
|
||||
@@ -49,25 +46,17 @@ public class MultiFormatImporter
|
||||
break;
|
||||
}
|
||||
|
||||
if (importer != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (importer != null) {
|
||||
try {
|
||||
importer.importData(context, db, input, password);
|
||||
return ImportExportResult.Success;
|
||||
}
|
||||
catch(ZipException e)
|
||||
{
|
||||
} catch (ZipException e) {
|
||||
return ImportExportResult.BadPassword;
|
||||
}
|
||||
catch(IOException | FormatException | InterruptedException | JSONException | ParseException | NullPointerException e)
|
||||
{
|
||||
} catch (IOException | FormatException | InterruptedException | JSONException | ParseException | NullPointerException e) {
|
||||
Log.e(TAG, "Failed to import data", e);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Log.e(TAG, "Unsupported data format imported: " + format.name());
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.HashMap;
|
||||
import protect.card_locker.CatimaBarcode;
|
||||
import protect.card_locker.DBHelper;
|
||||
import protect.card_locker.FormatException;
|
||||
import protect.card_locker.ImageLocationType;
|
||||
import protect.card_locker.R;
|
||||
import protect.card_locker.Utils;
|
||||
import protect.card_locker.ZipUtils;
|
||||
@@ -33,22 +34,19 @@ import protect.card_locker.ZipUtils;
|
||||
/**
|
||||
* Class for importing a database from CSV (Comma Separate Values)
|
||||
* formatted data.
|
||||
*
|
||||
* <p>
|
||||
* The database's loyalty cards are expected to appear in the CSV data.
|
||||
* A header is expected for the each table showing the names of the columns.
|
||||
*/
|
||||
public class StocardImporter implements Importer
|
||||
{
|
||||
public class StocardImporter implements Importer {
|
||||
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
|
||||
HashMap<String, HashMap<String, Object>> loyaltyCardHashMap = new HashMap<>();
|
||||
HashMap<String, HashMap<String, String>> providers = new HashMap<>();
|
||||
|
||||
final CSVParser parser = new CSVParser(new InputStreamReader(context.getResources().openRawResource(R.raw.stocard_stores), StandardCharsets.UTF_8), CSVFormat.RFC4180.builder().setHeader().build());
|
||||
|
||||
try
|
||||
{
|
||||
for (CSVRecord record : parser)
|
||||
{
|
||||
try {
|
||||
for (CSVRecord record : parser) {
|
||||
HashMap<String, String> recordData = new HashMap<>();
|
||||
recordData.put("name", record.get("name"));
|
||||
recordData.put("barcodeFormat", record.get("barcodeFormat"));
|
||||
@@ -57,7 +55,7 @@ public class StocardImporter implements Importer
|
||||
}
|
||||
|
||||
parser.close();
|
||||
} catch(IllegalArgumentException|IllegalStateException e) {
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
throw new FormatException("Issue parsing CSV data", e);
|
||||
}
|
||||
|
||||
@@ -72,7 +70,7 @@ public class StocardImporter implements Importer
|
||||
String[] nameParts = fileName.split("/");
|
||||
|
||||
if (providersFileName == null) {
|
||||
providersFileName = new String[] {
|
||||
providersFileName = new String[]{
|
||||
nameParts[0],
|
||||
"sync",
|
||||
"data",
|
||||
@@ -80,7 +78,7 @@ public class StocardImporter implements Importer
|
||||
nameParts[0],
|
||||
"analytics-properties.json"
|
||||
};
|
||||
cardBaseName = new String[] {
|
||||
cardBaseName = new String[]{
|
||||
nameParts[0],
|
||||
"sync",
|
||||
"data",
|
||||
@@ -111,9 +109,9 @@ public class StocardImporter implements Importer
|
||||
cardName,
|
||||
"_providerId",
|
||||
jsonObject
|
||||
.getJSONObject("input_provider_reference")
|
||||
.getString("identifier")
|
||||
.substring("/loyalty-card-providers/".length())
|
||||
.getJSONObject("input_provider_reference")
|
||||
.getString("identifier")
|
||||
.substring("/loyalty-card-providers/".length())
|
||||
);
|
||||
|
||||
if (jsonObject.has("input_barcode_format")) {
|
||||
@@ -131,7 +129,7 @@ public class StocardImporter implements Importer
|
||||
cardName,
|
||||
"note",
|
||||
ZipUtils.readJSON(zipInputStream)
|
||||
.getString("content")
|
||||
.getString("content")
|
||||
);
|
||||
} else if (fileName.endsWith("/images/front.png")) {
|
||||
loyaltyCardHashMap = appendToLoyaltyCardHashMap(
|
||||
@@ -178,10 +176,10 @@ public class StocardImporter implements Importer
|
||||
long loyaltyCardInternalId = db.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, null, 0, null);
|
||||
|
||||
if (loyaltyCardData.containsKey("frontImage")) {
|
||||
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("frontImage"), (int) loyaltyCardInternalId, true);
|
||||
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("frontImage"), (int) loyaltyCardInternalId, ImageLocationType.front);
|
||||
}
|
||||
if (loyaltyCardData.containsKey("backImage")) {
|
||||
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("backImage"), (int) loyaltyCardInternalId, false);
|
||||
Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("backImage"), (int) loyaltyCardInternalId, ImageLocationType.back);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,11 @@ import protect.card_locker.Utils;
|
||||
/**
|
||||
* Class for importing a database from CSV (Comma Separate Values)
|
||||
* formatted data.
|
||||
*
|
||||
* <p>
|
||||
* The database's loyalty cards are expected to appear in the CSV data.
|
||||
* A header is expected for the each table showing the names of the columns.
|
||||
*/
|
||||
public class VoucherVaultImporter implements Importer
|
||||
{
|
||||
public class VoucherVaultImporter implements Importer {
|
||||
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException {
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||
|
||||
|
||||
@@ -12,44 +12,36 @@ import androidx.preference.PreferenceManager;
|
||||
import protect.card_locker.R;
|
||||
import protect.card_locker.Utils;
|
||||
|
||||
public class Settings
|
||||
{
|
||||
private Context context;
|
||||
private SharedPreferences settings;
|
||||
public class Settings {
|
||||
private final Context mContext;
|
||||
private SharedPreferences mSettings;
|
||||
|
||||
public Settings(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
this.settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
public Settings(Context context) {
|
||||
mContext = context.getApplicationContext();
|
||||
mSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
}
|
||||
|
||||
private String getResString(@StringRes int resId)
|
||||
{
|
||||
return context.getString(resId);
|
||||
private String getResString(@StringRes int resId) {
|
||||
return mContext.getString(resId);
|
||||
}
|
||||
|
||||
private int getResInt(@IntegerRes int resId)
|
||||
{
|
||||
return context.getResources().getInteger(resId);
|
||||
private int getResInt(@IntegerRes int resId) {
|
||||
return mContext.getResources().getInteger(resId);
|
||||
}
|
||||
|
||||
private String getString(@StringRes int keyId, String defaultValue)
|
||||
{
|
||||
return settings.getString(getResString(keyId), defaultValue);
|
||||
private String getString(@StringRes int keyId, String defaultValue) {
|
||||
return mSettings.getString(getResString(keyId), defaultValue);
|
||||
}
|
||||
|
||||
private int getInt(@StringRes int keyId, @IntegerRes int defaultId)
|
||||
{
|
||||
return settings.getInt(getResString(keyId), getResInt(defaultId));
|
||||
private int getInt(@StringRes int keyId, @IntegerRes int defaultId) {
|
||||
return mSettings.getInt(getResString(keyId), getResInt(defaultId));
|
||||
}
|
||||
|
||||
private boolean getBoolean(@StringRes int keyId, boolean defaultValue)
|
||||
{
|
||||
return settings.getBoolean(getResString(keyId), defaultValue);
|
||||
private boolean getBoolean(@StringRes int keyId, boolean defaultValue) {
|
||||
return mSettings.getBoolean(getResString(keyId), defaultValue);
|
||||
}
|
||||
|
||||
public Locale getLocale()
|
||||
{
|
||||
public Locale getLocale() {
|
||||
String value = getString(R.string.settings_key_locale, "");
|
||||
|
||||
if (value.length() == 0) {
|
||||
@@ -59,69 +51,55 @@ public class Settings
|
||||
return Utils.stringToLocale(value);
|
||||
}
|
||||
|
||||
public int getTheme()
|
||||
{
|
||||
public int getTheme() {
|
||||
String value = getString(R.string.settings_key_theme, getResString(R.string.settings_key_system_theme));
|
||||
|
||||
if(value.equals(getResString(R.string.settings_key_light_theme)))
|
||||
{
|
||||
if (value.equals(getResString(R.string.settings_key_light_theme))) {
|
||||
return AppCompatDelegate.MODE_NIGHT_NO;
|
||||
}
|
||||
else if(value.equals(getResString(R.string.settings_key_dark_theme)))
|
||||
{
|
||||
} else if (value.equals(getResString(R.string.settings_key_dark_theme))) {
|
||||
return AppCompatDelegate.MODE_NIGHT_YES;
|
||||
}
|
||||
|
||||
return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
|
||||
}
|
||||
|
||||
public double getFontSizeScale()
|
||||
{
|
||||
public double getFontSizeScale() {
|
||||
return getInt(R.string.settings_key_max_font_size_scale, R.integer.settings_max_font_size_scale_pct) / 100.0;
|
||||
}
|
||||
|
||||
public int getSmallFont()
|
||||
{
|
||||
public int getSmallFont() {
|
||||
return 14;
|
||||
}
|
||||
|
||||
public int getMediumFont()
|
||||
{
|
||||
public int getMediumFont() {
|
||||
return 28;
|
||||
}
|
||||
|
||||
public int getLargeFont()
|
||||
{
|
||||
public int getLargeFont() {
|
||||
return 40;
|
||||
}
|
||||
|
||||
public int getFontSizeMin(int fontSize)
|
||||
{
|
||||
public int getFontSizeMin(int fontSize) {
|
||||
return (int) (Math.round(fontSize / 2.0) - 1);
|
||||
}
|
||||
|
||||
public int getFontSizeMax(int fontSize)
|
||||
{
|
||||
public int getFontSizeMax(int fontSize) {
|
||||
return (int) Math.round(fontSize * getFontSizeScale());
|
||||
}
|
||||
|
||||
public boolean useMaxBrightnessDisplayingBarcode()
|
||||
{
|
||||
public boolean useMaxBrightnessDisplayingBarcode() {
|
||||
return getBoolean(R.string.settings_key_display_barcode_max_brightness, true);
|
||||
}
|
||||
|
||||
public boolean getLockBarcodeScreenOrientation()
|
||||
{
|
||||
public boolean getLockBarcodeScreenOrientation() {
|
||||
return getBoolean(R.string.settings_key_lock_barcode_orientation, false);
|
||||
}
|
||||
|
||||
public boolean getKeepScreenOn()
|
||||
{
|
||||
public boolean getKeepScreenOn() {
|
||||
return getBoolean(R.string.settings_key_keep_screen_on, true);
|
||||
}
|
||||
|
||||
public boolean getDisableLockscreenWhileViewingCard()
|
||||
{
|
||||
public boolean getDisableLockscreenWhileViewingCard() {
|
||||
return getBoolean(R.string.settings_key_disable_lockscreen_while_viewing_card, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,19 +24,16 @@ import protect.card_locker.CatimaAppCompatActivity;
|
||||
import protect.card_locker.R;
|
||||
import protect.card_locker.Utils;
|
||||
|
||||
public class SettingsActivity extends CatimaAppCompatActivity
|
||||
{
|
||||
public class SettingsActivity extends CatimaAppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setTitle(R.string.settings);
|
||||
setContentView(R.layout.settings_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if(actionBar != null)
|
||||
{
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@@ -48,12 +45,10 @@ public class SettingsActivity extends CatimaAppCompatActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
if(id == android.R.id.home)
|
||||
{
|
||||
if (id == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
@@ -61,8 +56,7 @@ public class SettingsActivity extends CatimaAppCompatActivity
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
public static class SettingsFragment extends PreferenceFragmentCompat
|
||||
{
|
||||
public static class SettingsFragment extends PreferenceFragmentCompat {
|
||||
private static final String DIALOG_FRAGMENT_TAG = "SettingsFragment";
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="0"
|
||||
android:propertyName="alpha"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.0" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="@integer/full_rotation_duration"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:propertyName="rotationY"
|
||||
android:valueFrom="-180"
|
||||
android:valueTo="0" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="1"
|
||||
android:propertyName="alpha"
|
||||
android:startOffset="@integer/half_rotation_duration"
|
||||
android:valueFrom="0.0"
|
||||
android:valueTo="1.0" />
|
||||
</set>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="@integer/full_rotation_duration"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:propertyName="rotationY"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="180" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="1"
|
||||
android:propertyName="alpha"
|
||||
android:startOffset="@integer/half_rotation_duration"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.0" />
|
||||
</set>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="0"
|
||||
android:propertyName="alpha"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.0" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="@integer/full_rotation_duration"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:propertyName="rotationY"
|
||||
android:valueFrom="180"
|
||||
android:valueTo="0" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="1"
|
||||
android:propertyName="alpha"
|
||||
android:startOffset="@integer/half_rotation_duration"
|
||||
android:valueFrom="0.0"
|
||||
android:valueTo="1.0" />
|
||||
</set>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="@integer/full_rotation_duration"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:propertyName="rotationY"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="-180" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="1"
|
||||
android:propertyName="alpha"
|
||||
android:startOffset="@integer/half_rotation_duration"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.0" />
|
||||
</set>
|
||||
5
app/src/main/res/drawable/ic_baseline_unfold_less_24.xml
Normal file
5
app/src/main/res/drawable/ic_baseline_unfold_less_24.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M7.41,18.59L8.83,20 12,16.83 15.17,20l1.41,-1.41L12,14l-4.59,4.59zM16.59,5.41L15.17,4 12,7.17 8.83,4 7.41,5.41 12,10l4.59,-4.59z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/ic_baseline_unfold_more_24.xml
Normal file
5
app/src/main/res/drawable/ic_baseline_unfold_more_24.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,5.83L15.17,9l1.41,-1.41L12,3 7.41,7.59 8.83,9 12,5.83zM12,18.17L8.83,15l-1.41,1.41L12,21l4.59,-4.59L15.17,15 12,18.17z"/>
|
||||
</vector>
|
||||
65
app/src/main/res/layout/activity_manage_group.xml
Normal file
65
app/src/main/res/layout/activity_manage_group.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="protect.card_locker.ManageGroupActivity">
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fabSave"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
app:srcCompat="@drawable/save_24dp"
|
||||
android:contentDescription="@string/save"
|
||||
android:layout_margin="16dp" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/groups"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:tabMode="scrollable" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/storeNameField"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/storeName">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editTextGroupName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
<include
|
||||
android:id="@+id/include"
|
||||
layout="@layout/content_main" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
22
app/src/main/res/layout/barcode_layout.xml
Normal file
22
app/src/main/res/layout/barcode_layout.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/barcodeImage"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/barcodeName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
@@ -1,318 +1,88 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ScrollView
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:id="@+id/scrollView">
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/explanationText"
|
||||
android:textSize="20sp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingStart="20.0dip"
|
||||
android:paddingEnd="20.0dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/barcodeIdLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:text="@string/enterBarcodeInstructions" />
|
||||
<LinearLayout
|
||||
android:id="@+id/barcodeIdLayout"
|
||||
android:orientation="horizontal"
|
||||
android:padding="10.0dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/explanationText"
|
||||
app:layout_constraintBottom_toTopOf="@+id/noBarcode"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
<TextView android:textSize="16.0sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingStart="20.0dip"
|
||||
android:paddingEnd="20.0dip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:labelFor="@+id/cardId"
|
||||
android:text="@string/cardId" />
|
||||
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:padding="10.0dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView android:textSize="20sp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingStart="20.0dip"
|
||||
android:paddingEnd="20.0dip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enterBarcodeInstructions" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:padding="10.0dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/barcodeIdLayout">
|
||||
<TextView android:textSize="16.0sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingStart="20.0dip"
|
||||
android:paddingEnd="20.0dip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:labelFor="@+id/cardId"
|
||||
android:text="@string/cardId" />
|
||||
<EditText android:id="@+id/cardId"
|
||||
android:hint="AB1234"
|
||||
android:importantForAutofill="no"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
<EditText
|
||||
android:id="@+id/cardId"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/barcodesLayout"/>
|
||||
<Button
|
||||
android:id="@+id/noBarcode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/barcodeNoBarcode"
|
||||
android:textColor="#FFFFFF"
|
||||
android:enabled="false" />
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/aztecBarcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/aztecBarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/code39Barcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/code39BarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/code128Barcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/code128BarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/codabarBarcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/codabarBarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/datamatrixBarcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/datamatrixBarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/ean8Barcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/ean8BarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/ean13Barcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/ean13BarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/itfBarcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/itfBarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/pdf417Barcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/pdf417BarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/qrcodeBarcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/qrcodeBarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/upcaBarcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/upcaBarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/barcode_disp_height"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/upceBarcode"
|
||||
android:layout_weight="1.0"/>
|
||||
<TextView
|
||||
android:id="@+id/upceBarcodeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10.0dip"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1.0" />
|
||||
</LinearLayout>
|
||||
android:hint="AB1234"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text"
|
||||
android:minHeight="48dp" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
<Button
|
||||
android:id="@+id/noBarcode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/barcodeIdLayout"
|
||||
app:layout_constraintBottom_toTopOf="@+id/barcodes"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:text="@string/barcodeNoBarcode"
|
||||
android:textColor="#FFFFFF"
|
||||
android:enabled="false" />
|
||||
<ListView
|
||||
android:id="@+id/barcodes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/noBarcode"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:scrollbars="vertical" />
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:spanCount="@integer/main_view_card_columns"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -75,7 +75,9 @@
|
||||
android:layout_gravity="center_vertical"
|
||||
app:cardCornerRadius="4dp"
|
||||
android:paddingHorizontal="@dimen/inputPadding"
|
||||
app:cardElevation="0dp">
|
||||
app:cardElevation="0dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
android:outlineProvider="none">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/thumbnail"
|
||||
@@ -97,7 +99,7 @@
|
||||
android:id="@+id/storeNameEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
android:singleLine="true" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
@@ -121,7 +123,7 @@
|
||||
android:id="@+id/cardIdView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
android:singleLine="true" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,154 +1,147 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/row"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp">
|
||||
|
||||
<LinearLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/information_container"
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/icon_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintDimensionRatio="85.6f:53.98f"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/store">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/thumbnail"
|
||||
android:scaleType="fitCenter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/thumbnailDescription"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/selected_thumbnail"
|
||||
android:scaleType="fitCenter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/thumbnailDescription"
|
||||
app:srcCompat="@drawable/ic_done"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/star"
|
||||
android:layout_width="@dimen/cardThumbnailSize"
|
||||
android:layout_height="@dimen/cardThumbnailSize"
|
||||
android:layout_gravity="end"
|
||||
app:srcCompat="@drawable/ic_starred_white"
|
||||
android:contentDescription="@string/starImage"
|
||||
app:tint="?attr/colorControlNormal"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/store"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textAppearance="?attr/textAppearanceHeadline1"
|
||||
app:layout_constraintTop_toBottomOf="@+id/icon_layout"
|
||||
app:layout_constraintBottom_toTopOf="@+id/note"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Example store"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:id="@+id/note"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:layout_constraintTop_toBottomOf="@+id/store"
|
||||
app:layout_constraintBottom_toTopOf="@+id/info_divider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Example note"/>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/thumbnail_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="4dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
>
|
||||
<View
|
||||
android:id="@+id/info_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="?android:attr/dividerVertical"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:layout_constraintTop_toBottomOf="@+id/note"
|
||||
app:layout_constraintBottom_toTopOf="@+id/balance"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/thumbnail_front"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@+id/storeContainer"
|
||||
android:layout_alignBottom="@+id/storeContainer"
|
||||
android:layout_gravity="center_vertical">
|
||||
<TextView
|
||||
android:id="@+id/balance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:drawableLeftCompat="@drawable/ic_baseline_payments_24"
|
||||
android:drawablePadding="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@+id/info_divider"
|
||||
app:layout_constraintBottom_toTopOf="@+id/expiry"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible"
|
||||
tools:text="525 points"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/thumbnail"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_width="@dimen/cardThumbnailSize"
|
||||
android:layout_height="@dimen/cardThumbnailSize"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@string/thumbnailDescription"
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/thumbnail_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/selected_thumbnail"
|
||||
android:layout_width="@dimen/cardThumbnailSize"
|
||||
android:layout_height="@dimen/cardThumbnailSize"
|
||||
android:layout_centerInParent="true"
|
||||
android:contentDescription="@string/thumbnailDescription"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@drawable/ic_done" />
|
||||
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/storeContainer"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_toEndOf="@+id/thumbnail_container">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/store"
|
||||
android:paddingStart="16dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="left"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/star"
|
||||
android:layout_width="@dimen/cardThumbnailSize"
|
||||
android:layout_height="@dimen/cardThumbnailSize"
|
||||
android:layout_centerVertical="true"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@drawable/ic_starred_white"
|
||||
android:contentDescription="@string/starImage"
|
||||
app:tint="?attr/colorControlNormal"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/note"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:visibility="gone" />
|
||||
|
||||
<View android:id="@+id/info_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="?android:attr/dividerVertical"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:id="@+id/balance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingEnd="8dp"
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:drawableLeftCompat="@drawable/ic_baseline_payments_24"
|
||||
android:drawablePadding="4dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:visibility="gone" />
|
||||
<TextView
|
||||
android:id="@+id/expiry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:drawableLeftCompat="@drawable/ic_baseline_access_time_24"
|
||||
android:drawablePadding="4dp"
|
||||
android:layout_toEndOf="@+id/balance"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/expiry"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:drawableLeftCompat="@drawable/ic_baseline_access_time_24"
|
||||
android:drawablePadding="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@+id/balance"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible"
|
||||
tools:text="Tomorrow"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -155,8 +155,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/inputBackground"
|
||||
android:fitsSystemWindows="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="0px"
|
||||
android:visibility="gone"
|
||||
app:behavior_hideable="false"
|
||||
app:behavior_peekHeight="80dp"
|
||||
@@ -168,10 +168,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_gravity="top|start"
|
||||
android:scaleType="fitCenter"
|
||||
android:contentDescription="@string/toggleMoreInfo"
|
||||
app:tint="#ffffff"
|
||||
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24" />
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24"
|
||||
app:tint="#ffffff" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/bottomSheetContentWrapper"
|
||||
@@ -185,109 +185,127 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noteView"
|
||||
android:enabled="true"
|
||||
android:textIsSelectable="true"
|
||||
android:focusable="true"
|
||||
android:longClickable="true"
|
||||
android:autoLink="all"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="all"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:longClickable="true"
|
||||
android:padding="20dp"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/singleCardNoteTextSizeMin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/groupsView"
|
||||
android:enabled="true"
|
||||
android:textIsSelectable="true"
|
||||
android:focusable="true"
|
||||
android:longClickable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:longClickable="true"
|
||||
android:padding="20dp"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/singleCardNoteTextSizeMin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/balanceView"
|
||||
android:enabled="true"
|
||||
android:textIsSelectable="true"
|
||||
android:focusable="true"
|
||||
android:longClickable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:longClickable="true"
|
||||
android:padding="20dp"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/singleCardNoteTextSizeMin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/expiryView"
|
||||
android:enabled="true"
|
||||
android:textIsSelectable="true"
|
||||
android:focusable="true"
|
||||
android:longClickable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:longClickable="true"
|
||||
android:padding="20dp"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/singleCardNoteTextSizeMin" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar_layout"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:weightSum="1.0"
|
||||
android:fitsSystemWindows="true">
|
||||
>
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar_landscape"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:background="@android:color/transparent"
|
||||
android:fitsSystemWindows="false"
|
||||
android:paddingTop="0dp"
|
||||
android:theme="@style/CardView.ActionBarTheme"
|
||||
android:visibility="gone"
|
||||
app:contentInsetStart="72.0dip"
|
||||
app:layout_collapseMode="pin" />
|
||||
|
||||
<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:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:minHeight="56.0dip"
|
||||
android:layout_weight="1.0"
|
||||
app:expandedTitleMarginStart="48dp"
|
||||
app:expandedTitleMarginEnd="64dp"
|
||||
app:contentScrim="?colorPrimary"
|
||||
app:expandedTitleGravity="top">
|
||||
app:expandedTitleGravity="top"
|
||||
app:expandedTitleMarginEnd="64dp"
|
||||
app:expandedTitleMarginStart="48dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
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"/>
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="40sp"
|
||||
app:layout_collapseMode="parallax" />
|
||||
|
||||
<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"
|
||||
android:background="@android:color/transparent"
|
||||
android:theme="@style/CardView.ActionBarTheme"
|
||||
app:contentInsetStart="72.0dip"
|
||||
app:layout_collapseMode="pin" />
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar_landscape"
|
||||
android:visibility="gone"
|
||||
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"
|
||||
android:paddingTop="6dp" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:fitsSystemWindows="true"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@drawable/ic_launcher_foreground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
android:icon="@drawable/ic_search_white"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||
app:showAsAction="always|collapseActionView"/>
|
||||
<item
|
||||
android:id="@+id/action_unfold"
|
||||
android:title="@string/action_hide_details"
|
||||
android:icon="@drawable/ic_baseline_unfold_less_24"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_sort"
|
||||
android:title="@string/sort"
|
||||
|
||||
@@ -5,38 +5,44 @@ Allan Nordhøy
|
||||
Heimen Stoffels
|
||||
solokot
|
||||
mondstern
|
||||
Taco
|
||||
Katharine Chui
|
||||
Oğuz Ersen
|
||||
IllusiveMan196
|
||||
Petr Novák
|
||||
Oğuz Ersen
|
||||
Taco
|
||||
Gediminas Murauskas
|
||||
Joel A
|
||||
StoyanDimitrov
|
||||
Samantaz Fox
|
||||
Nyatsuki
|
||||
Samantaz Fox
|
||||
arno-github
|
||||
Ankit Tiwari
|
||||
Sergio Paredes
|
||||
laralem
|
||||
arshbeerSingh
|
||||
huuhaa
|
||||
Miha Frangež
|
||||
Michael Moroni
|
||||
Olivia (Zoe)
|
||||
betsythefc
|
||||
waffshappen
|
||||
Miha Frangež
|
||||
K. Herbert
|
||||
Quentin PAGÈS
|
||||
String E. Fighter
|
||||
Yurical
|
||||
/usr/local/ΕΨΗΕΛΩΝ
|
||||
Adolfo Jayme-Barrientos
|
||||
Alessandro Mandelli
|
||||
KovalevArtem
|
||||
Clonewayx
|
||||
D. Domig
|
||||
Diego
|
||||
sr093906
|
||||
Jane Kong
|
||||
Lukas Grassauer
|
||||
Marnick L'Eau
|
||||
Michalis
|
||||
Rosdyana Kusuma
|
||||
schirinowski
|
||||
Thomas Bertels
|
||||
inesre
|
||||
@@ -47,6 +53,7 @@ Kevin Sicong Jiang
|
||||
Airat
|
||||
BMN
|
||||
Biren
|
||||
Kasina Dheeraj
|
||||
Flav
|
||||
Franciszek Stefan
|
||||
Izzy
|
||||
@@ -58,7 +65,9 @@ Michael Gangolf
|
||||
pbeckmann
|
||||
Peer Beckmann
|
||||
QuangDNguyen2211
|
||||
Reza
|
||||
Rohan Babbar
|
||||
Ronak Upadhyay
|
||||
Rose Liverman
|
||||
Simone Dotto
|
||||
Still Hsu
|
||||
|
||||
@@ -85,10 +85,10 @@
|
||||
<string name="noGroups">Докоснете бутона +, за да добавите списък.</string>
|
||||
<string name="noStoreError">Не е въведено наименование</string>
|
||||
<string name="groups">Списъци</string>
|
||||
<string name="enter_group_name">Въведете име на списък</string>
|
||||
<string name="enter_group_name">Въведете име на списъка</string>
|
||||
<string name="intent_import_card_from_url_share_text">Искам да споделя тази карта с вас</string>
|
||||
<string name="settings_display_barcode_max_brightness">Увеличаване на яркостта при видим щрихкод</string>
|
||||
<string name="settings_lock_barcode_orientation">Спиране на завъртането на щрихкода</string>
|
||||
<string name="settings_lock_barcode_orientation">Без на завъртане на щрихкода</string>
|
||||
<string name="settings_keep_screen_on">Поддържане на екрана включен</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Предотвратяване на заключване на екрана</string>
|
||||
<string name="settings_max_font_size_scale">Максимален размер на шрифта</string>
|
||||
@@ -164,30 +164,30 @@
|
||||
<string name="failedParsingImportUriError">Препратката не може да бъде анализирана за внасяне</string>
|
||||
<string name="card_ids_copied">[не превеждай този низ, https://github.com/TheLastProject/Catima/issues/278]</string>
|
||||
<string name="failedGeneratingShareURL">Грешка при създаване на адрес за споделяне. Изпратете доклад за дефект.</string>
|
||||
<string name="deleteTitle">Изтрийте картата</string>
|
||||
<string name="deleteTitle">Премахване на карта</string>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">Изтриване на <xliff:g>%d</xliff:g> карта</item>
|
||||
<item quantity="other">Изтриване на <xliff:g>%d</xliff:g> карти</item>
|
||||
</plurals>
|
||||
<string name="deleteConfirmation">Потвърдете премахване на карта\?</string>
|
||||
<string name="deleteConfirmation">Потвърдете премахване на картата.</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">Изтриване на тази <xliff:g>%d</xliff:g> карта завинаги\?</item>
|
||||
<item quantity="other">Изтриване на тези <xliff:g>%d</xliff:g> карти за постоянно\?</item>
|
||||
<item quantity="one">Желаете ли <xliff:g>%d</xliff:g> карта да бъде премахната\?</item>
|
||||
<item quantity="other">Желаете ли тези <xliff:g>%d</xliff:g> карти да бъдат премахнати\?</item>
|
||||
</plurals>
|
||||
<string name="app_contributors">Осъществено от: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="settings_brown_theme">Браун</string>
|
||||
<string name="settings_grey_theme">Сив</string>
|
||||
<string name="settings_green_theme">Зелен</string>
|
||||
<string name="settings_sky_blue_theme">Небесно синьо</string>
|
||||
<string name="settings_brown_theme">Кафяво</string>
|
||||
<string name="settings_grey_theme">Сиво</string>
|
||||
<string name="settings_green_theme">Зелено</string>
|
||||
<string name="settings_sky_blue_theme">Небесносиньо</string>
|
||||
<string name="settings_blue_theme">Синьо</string>
|
||||
<string name="settings_violet_theme">Виолет</string>
|
||||
<string name="settings_magenta_theme">Магента</string>
|
||||
<string name="settings_pink_theme">Розов</string>
|
||||
<string name="settings_violet_theme">Виолетово</string>
|
||||
<string name="settings_magenta_theme">Цикламено</string>
|
||||
<string name="settings_pink_theme">Розово</string>
|
||||
<string name="settings_catima_theme">Catima</string>
|
||||
<string name="settings_theme_color">Цвят на темата</string>
|
||||
<string name="settings_system_locale">Система</string>
|
||||
<string name="settings_locale">Език</string>
|
||||
<string name="noGroupCards">Тази група не съдържа карти</string>
|
||||
<string name="noGroupCards">Групата не съдържа карти</string>
|
||||
<string name="toggleMoreInfo">Превключване на повече информация</string>
|
||||
<string name="barcodeImageDescriptionWithType">Изображение на щрихкод на карта от вида <xliff:g>%s</xliff:g></string>
|
||||
<string name="swipeToSwitchImages">Плъзване или задържане за смяна на изображения</string>
|
||||
@@ -210,4 +210,14 @@
|
||||
<string name="help_translate_this_app">Помогнете за превода на приложението</string>
|
||||
<string name="exportPasswordHint">Въведете парола</string>
|
||||
<string name="exportPassword">Задаване на парола за защита на изнесеното (по избор)</string>
|
||||
<string name="setIcon">Задаване на пиктограма</string>
|
||||
<string name="editGroup">Променяне на списъка: <xliff:g>%s</xliff:g></string>
|
||||
<string name="group_name_already_in_use">Има списък с това име</string>
|
||||
<string name="group_updated">Промените са запазени</string>
|
||||
<string name="selectColor">Избиране на цвят</string>
|
||||
<string name="group_name_is_empty">Името на списъка не може да е празно</string>
|
||||
<string name="group_edit">Редактиране на списък</string>
|
||||
<string name="action_show_details">Повече детайли</string>
|
||||
<string name="action_hide_details">По-малко детайли</string>
|
||||
<string name="noGiftCardsGroup">Няма карти. След като добавите ще можете да ги зачислите към списък от тук.</string>
|
||||
</resources>
|
||||
@@ -21,7 +21,7 @@
|
||||
<string name="importExport">Import/Export</string>
|
||||
<string name="exportName">Export</string>
|
||||
<string name="importExportHelp">Zálohování karet vám umožní přesunout je do jiného zařízení.</string>
|
||||
<string name="importSuccessfulTitle">Dovážit</string>
|
||||
<string name="importSuccessfulTitle">Importováno</string>
|
||||
<string name="importFailedTitle">Import selhal</string>
|
||||
<string name="importFailed">Nelze importovat karty</string>
|
||||
<string name="exportSuccessfulTitle">Exportovat</string>
|
||||
@@ -37,7 +37,7 @@
|
||||
<string name="importOptionApplicationExplanation">K otevření souboru použijte libovolnou aplikaci nebo svého oblíbeného správce souborů.</string>
|
||||
<string name="importOptionApplicationButton">Použijte jinou aplikaci</string>
|
||||
<string name="about">O aplikaci</string>
|
||||
<string name="app_license">Copylefted libre software, licencovaný GPLv3+</string>
|
||||
<string name="app_license">Copyleftovaný svobodný software s licencí GPLv3+</string>
|
||||
<string name="about_title_fmt">O aplikaci <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Verze: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Informace o revizi: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
@@ -52,8 +52,8 @@
|
||||
<string name="expiryDate">Platnost</string>
|
||||
<string name="editBarcode">Upravit čárový kód</string>
|
||||
<string name="barcode">Kód</string>
|
||||
<string name="app_resources">Zdroje třetích stran Libre: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Libre knihovny třetích stran: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources">Svobodné zdroje třetích stran: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Svobodné knihovny třetích stran: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_copyright_old">Na základě Loyalty Card Keychain
|
||||
\ncopyright © 2016–2020 Branden Archer</string>
|
||||
<string name="exportOptionExplanation">Data budou zapsána na místo podle vašeho výběru.</string>
|
||||
@@ -155,7 +155,7 @@
|
||||
<string name="accept">Přijmout</string>
|
||||
<string name="privacy_policy_popup_text">Oznámení o zásadách ochrany osobních údajů (vyžadováno některými obchody s aplikacemi):
|
||||
\n
|
||||
\nNejsou shromažďovány žádné údaje, což může potvrdit každý, protože naše aplikace je libre software.</string>
|
||||
\nNejsou shromažďovány žádné údaje, což může potvrdit každý, protože naše aplikace je svobodný software.</string>
|
||||
<string name="privacy_policy">Zásady soukromí</string>
|
||||
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
|
||||
<string name="chooseImportType">Importovat data z\?</string>
|
||||
@@ -214,4 +214,12 @@
|
||||
<string name="on_google_play">na Google Play</string>
|
||||
<string name="exportPassword">Nastavení hesla pro ochranu exportu (volitelné)</string>
|
||||
<string name="exportPasswordHint">Zadejte heslo</string>
|
||||
<string name="selectColor">Vyberte barvu</string>
|
||||
<string name="setIcon">Nastavit ikonu</string>
|
||||
<string name="group_edit">Upravit skupinu</string>
|
||||
<string name="group_name_already_in_use">Již použitý název skupiny</string>
|
||||
<string name="group_name_is_empty">Název skupiny nemůže být prázdný</string>
|
||||
<string name="group_updated">Skupina aktualizována</string>
|
||||
<string name="editGroup">Úprava skupiny: <xliff:g>%s</xliff:g></string>
|
||||
<string name="noGiftCardsGroup">Zatím nemáte žádné věrnostní karty. Jakmile nějaké přidáte, můžete je přiřadit do skupiny zde.</string>
|
||||
</resources>
|
||||
7
app/src/main/res/values-cy/strings.xml
Normal file
7
app/src/main/res/values-cy/strings.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="noGiftCards">Cliciwch y + plws botwm i ychwanegu cerdyn, neu mewnforio rhai o\'r ⋮ ddewislen cyntaf.</string>
|
||||
<string name="action_add">Ychwanegu</string>
|
||||
<string name="action_search">Chwilio</string>
|
||||
<string name="noMatchingGiftCards">Nid oedd hyd i unrhyw beth. Ceisiwch newid eich chwiliad.</string>
|
||||
</resources>
|
||||
@@ -210,4 +210,14 @@
|
||||
<string name="report_error">Fehler melden</string>
|
||||
<string name="exportPassword">Legen Sie ein Passwort fest, um Ihren Export zu schützen (optional)</string>
|
||||
<string name="exportPasswordHint">Passwort eingeben</string>
|
||||
<string name="group_name_already_in_use">Der Gruppenname wird bereits verwendet</string>
|
||||
<string name="group_name_is_empty">Gruppenname darf nicht leer sein</string>
|
||||
<string name="group_updated">Gruppe aktualisiert</string>
|
||||
<string name="editGroup">Gruppe wird bearbeitet: <xliff:g>%s</xliff:g></string>
|
||||
<string name="group_edit">Gruppe bearbeiten</string>
|
||||
<string name="noGiftCardsGroup">Sie haben noch keine Kundenkarten. Sobald Sie welche hinzugefügt haben, können Sie sie hier der Gruppe zuordnen.</string>
|
||||
<string name="setIcon">Symbol einstellen</string>
|
||||
<string name="selectColor">Farbe auswählen</string>
|
||||
<string name="action_show_details">Details anzeigen</string>
|
||||
<string name="action_hide_details">Details ausblenden</string>
|
||||
</resources>
|
||||
@@ -210,4 +210,14 @@
|
||||
<string name="version_history">Historique des versions</string>
|
||||
<string name="exportPassword">Définissez un mot de passe pour protéger vos exportations (facultatif)</string>
|
||||
<string name="exportPasswordHint">Entrez le mot de passe</string>
|
||||
<string name="editGroup">Modification du groupe : <xliff:g> %s </xliff:g></string>
|
||||
<string name="noGiftCardsGroup">Vous n\'avez pas encore de cartes de fidélité. Une fois que vous en aurez ajouté, vous pourrez les affecter au groupe ici.</string>
|
||||
<string name="group_edit">Modifier le groupe</string>
|
||||
<string name="group_name_already_in_use">Nom de groupe déjà utilisé</string>
|
||||
<string name="group_updated">Groupe mis à jour</string>
|
||||
<string name="group_name_is_empty">Le nom du groupe ne peut pas être vide</string>
|
||||
<string name="setIcon">Définir l\'icône</string>
|
||||
<string name="selectColor">Sélectionnez la couleur</string>
|
||||
<string name="action_show_details">Afficher les détails</string>
|
||||
<string name="action_hide_details">Masquer les détails</string>
|
||||
</resources>
|
||||
86
app/src/main/res/values-hr/strings.xml
Normal file
86
app/src/main/res/values-hr/strings.xml
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="unstar">Ukloni iz favorita</string>
|
||||
<string name="action_search">Pretraživanje</string>
|
||||
<string name="save">Spremi</string>
|
||||
<string name="edit">Uredi</string>
|
||||
<string name="delete">Ukloni</string>
|
||||
<string name="confirm">Potvrdi</string>
|
||||
<string name="lockScreen">Rotacija bloka</string>
|
||||
<string name="unlockScreen">Otključaj Rotaciju</string>
|
||||
<string name="deleteTitle">Ukloni kartu</string>
|
||||
<string name="deleteConfirmation">Izbrisati ovu karticu zauvijek\?</string>
|
||||
<string name="copy_to_clipboard">Kopiraj ID u međuspremnik</string>
|
||||
<string name="share">Podijeli</string>
|
||||
<string name="sendLabel">Pošalji…</string>
|
||||
<string name="editCardTitle">Uredi karticu</string>
|
||||
<string name="addCardTitle">Dodaj Kartu</string>
|
||||
<string name="scanCardBarcode">Skeniranje crtičnog koda kartice</string>
|
||||
<string name="cardShortcut">Oznaka karte</string>
|
||||
<string name="noCardsMessage">Najprije dodajte karticu</string>
|
||||
<string name="card_ids_copied">Kopirani ID kartice</string>
|
||||
<string name="noBarcode">Nema crtičnog koda</string>
|
||||
<string name="star">Dodaj u favorite</string>
|
||||
<string name="action_add">Dodaj</string>
|
||||
<string name="storeName">Ime</string>
|
||||
<string name="note">Napomena</string>
|
||||
<string name="noMatchingGiftCards">Ništa nisam našao. Pokušajte promijeniti pretraživanje.</string>
|
||||
<string name="cardId">ID kartice</string>
|
||||
<string name="barcodeType">Vrsta crtičnog koda</string>
|
||||
<string name="barcodeNoBarcode">Na ovoj kartici nema crtičnog koda</string>
|
||||
<string name="cancel">Poništi</string>
|
||||
<string name="noGiftCards">Pritisnite gumb + plus da biste dodali karticu ili ga najprije uvezite iz izbornika ⋮.</string>
|
||||
<string name="noStoreError">Ime nije uneseno</string>
|
||||
<string name="noCardExistsError">Nije moguće pronaći karticu</string>
|
||||
<string name="failedParsingImportUriError">Nije moguće analizirati uvoz URI</string>
|
||||
<string name="importExport">Uvoz / Izvoz</string>
|
||||
<string name="exportName">Izvoz</string>
|
||||
<string name="importExportHelp">Sigurnosno kopiranje kartica omogućuje vam da ih premjestite na drugi uređaj.</string>
|
||||
<string name="importSuccessfulTitle">Uvezeno</string>
|
||||
<string name="importFailedTitle">Nije moguće uvesti</string>
|
||||
<string name="importFailed">Nije moguće uvesti karte</string>
|
||||
<string name="exportSuccessfulTitle">Izvezeno</string>
|
||||
<string name="about">Oh</string>
|
||||
<string name="importOptionApplicationButton">Koristite drugu aplikaciju</string>
|
||||
<string name="barcode">Barkod</string>
|
||||
<string name="exportOptionExplanation">Podaci će biti zabilježeni na odabranom mjestu.</string>
|
||||
<string name="exportFailedTitle">Izvoz nije uspio</string>
|
||||
<string name="exporting">Opskrba…</string>
|
||||
<string name="noExternalStoragePermissionError">Najprije odobrite dopuštenje za vanjsku pohranu za uvoz ili izvoz kartica</string>
|
||||
<string name="importOptionFilesystemExplanation">Odaberite određenu datoteku iz datotečnog sustava.</string>
|
||||
<string name="importOptionApplicationTitle">Koristite drugu aplikaciju</string>
|
||||
<string name="settings">Postavke</string>
|
||||
<string name="settings_dark_theme">Tamno</string>
|
||||
<string name="exportFailed">Nije moguće izvesti karte</string>
|
||||
<string name="importing">Uvoz…</string>
|
||||
<string name="importOptionFilesystemTitle">Uvoz iz datotečnog sustava</string>
|
||||
<string name="importOptionFilesystemButton">Iz datotečnog sustava</string>
|
||||
<string name="importOptionApplicationExplanation">Koristite bilo koju aplikaciju ili omiljeni upravitelj datoteka za otvaranje datoteke.</string>
|
||||
<string name="settings_theme">Tema</string>
|
||||
<string name="settings_system_theme">Sustav</string>
|
||||
<string name="settings_light_theme">Svjetlo</string>
|
||||
<string name="settings_max_font_size_scale">Maksimalna veličina fonta</string>
|
||||
<string name="settings_display_barcode_max_brightness">Osvijetlite izgled crtičnog koda</string>
|
||||
<string name="moveDown">Pomicanje prema dolje</string>
|
||||
<string name="addManually">Ručno unesite ID kartice</string>
|
||||
<string name="thumbnailDescription">Sličica za karticu</string>
|
||||
<string name="starImage">Omiljena zvijezda</string>
|
||||
<string name="settings_category_title_ui">Korisničko sučelje</string>
|
||||
<string name="settings_lock_barcode_orientation">Zaključavanje orijentacije crtičnog koda</string>
|
||||
<string name="exportSuccessful">Izvezeni podaci o karti</string>
|
||||
<string name="settings_keep_screen_on">Držite zaslon uključen</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Spriječiti zaključavanje zaslona</string>
|
||||
<string name="intent_import_card_from_url_share_text">Želim podijeliti razglednicu s vama</string>
|
||||
<string name="importSuccessful">Uvezeni podaci o karti</string>
|
||||
<string name="enter_group_name">Unesite naziv grupe</string>
|
||||
<string name="groups">Grupe</string>
|
||||
<string name="noGroups">Pritisnite gumb + plus da biste najprije dodali grupe za klasifikaciju.</string>
|
||||
<string name="noGroupCards">Ova grupa ne sadrži nikakve kartice</string>
|
||||
<string name="addFromImage">Odaberite sliku iz galerije</string>
|
||||
<string name="deleteConfirmationGroup">Izbriši grupu\?</string>
|
||||
<string name="failedOpeningFileManager">Najprije instalirajte upravitelj datoteka.</string>
|
||||
<string name="moveUp">Pomicanje gore</string>
|
||||
<string name="leaveWithoutSaveTitle">Izlaz</string>
|
||||
<string name="card">Karta</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Otići bez očuvanja\?</string>
|
||||
</resources>
|
||||
@@ -97,16 +97,17 @@
|
||||
<string name="importing">Mengimpor…</string>
|
||||
<string name="exporting">Mengekspor…</string>
|
||||
<string name="noExternalStoragePermissionError">Berikan izin penyimpanan eksternal untuk mengimpor atau mengekspor kartu terlebih dahulu</string>
|
||||
<string name="exportOptionExplanation">The data will be written to a location of your choice.</string>
|
||||
<string name="exportOptionExplanation">Data akan ditulis ke lokasi pilihan Anda.</string>
|
||||
<string name="importOptionFilesystemTitle">Impor dari sistem</string>
|
||||
<string name="importOptionFilesystemExplanation">Pilih file dari sistem</string>
|
||||
<string name="importOptionFilesystemExplanation">Pilih file dari sistem.</string>
|
||||
<string name="importOptionFilesystemButton">Dari sistem</string>
|
||||
<string name="importOptionApplicationTitle">Gunakan aplikasi lain</string>
|
||||
<string name="importOptionApplicationExplanation">Gunakan aplikasi lain atau pengelola file favorit anda untuk membuka file.</string>
|
||||
<string name="importOptionApplicationButton">Gunakan aplikasi lain</string>
|
||||
<string name="about">Tentang</string>
|
||||
<string name="app_copyright_fmt">Hak Cipta © 2019–<xliff:g>%d</xliff:g> Sylvia van Os</string>
|
||||
<string name="app_copyright_old">Berdasarkan Loyalty Card Keychain hak cipta © 2016–2020 Branden Archer</string>
|
||||
<string name="app_copyright_old">Berdasarkan Loyalty Card Keychain
|
||||
\nhak cipta © 2016–2020 Branden Archer</string>
|
||||
<string name="app_license">Perangkat lunak bebas copyleft, berlisensi GPLv3+</string>
|
||||
<string name="about_title_fmt">Tentang <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versi: <xliff:g id="version">%s</xliff:g></string>
|
||||
@@ -152,15 +153,22 @@
|
||||
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> sepertinya bukan saldo yang valid.</string>
|
||||
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
|
||||
<string name="privacy_policy">Kebijakan Privasi</string>
|
||||
<string name="privacy_policy_popup_text">Pemberitahuan kebijakan privasi (diperlukan oleh beberapa toko aplikasi): TIDAK ADA DATA YANG DIKUMPULKAN SAMA SEKALI, yang dapat dikonfirmasi oleh siapa pun karena aplikasi kami adalah perangkat lunak gratis.</string>
|
||||
<string name="importCatimaMessage">Pilih ekspor <i>catima.zip</i> Anda dari Catima untuk diimpor. Buat dari menu Impor/Ekspor aplikasi Catima lain dengan menekan Ekspor di sana terlebih dahulu.</string>
|
||||
<string name="importFidmeMessage">Pilih ekspor <i>fidme-export-request-xxxxxx.zip</i> Anda dari FidMe untuk diimpor, dan pilih jenis barcode secara manual setelahnya. Buat dari profil FidMe Anda dengan memilih Perlindungan Data lalu tekan Ekstrak data saya terlebih dahulu.</string>
|
||||
<string name="privacy_policy_popup_text">Pemberitahuan kebijakan privasi (diperlukan oleh beberapa toko aplikasi):
|
||||
\n
|
||||
\nTIDAK ADA DATA YANG DIKUMPULKAN SAMA SEKALI, yang dapat dikonfirmasi oleh siapa pun karena aplikasi kami adalah libre software.</string>
|
||||
<string name="importCatimaMessage">Pilih ekspor <i>catima.zip</i> Anda dari Catima untuk diimpor.
|
||||
\nBuat dari menu Impor/Ekspor aplikasi Catima lain dengan menekan Ekspor di sana terlebih dahulu.</string>
|
||||
<string name="importFidmeMessage">Pilih ekspor <i>fidme-export-request-xxxxxx.zip</i> Anda dari FidMe untuk diimpor, dan pilih jenis barcode secara manual setelahnya.
|
||||
\nBuat dari profil FidMe Anda dengan memilih Perlindungan Data lalu tekan Ekstrak data saya terlebih dahulu.</string>
|
||||
<string name="importLoyaltyCardKeychain">Impor dari Loyalty Card Keychain</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">Pilih ekspor <i>LoyaltyCardKeychain.csv</i> Anda dari Loyalty Card Keychain untuk diimpor. Buat dari menu Import/Export di Loyalty Card Keychain dengan menekan Export terlebih dahulu.</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">Pilih ekspor <i>LoyaltyCardKeychain.csv</i> Anda dari Loyalty Card Keychain untuk diimpor.
|
||||
\nBuat dari menu Import/Export di Loyalty Card Keychain dengan menekan Export terlebih dahulu.</string>
|
||||
<string name="importStocard">Impor dari Stocard</string>
|
||||
<string name="importStocardMessage">Pilih ekspor <i>***-sync.zip</i> Anda dari Stocard untuk diimpor. Dapatkan dengan mengirim email ke support@stocardapp.com untuk meminta ekspor data Anda.</string>
|
||||
<string name="importStocardMessage">Pilih ekspor <i>***-sync.zip</i> Anda dari Stocard untuk diimpor.
|
||||
\nDapatkan dengan mengirim email ke support@stocardapp.com untuk meminta ekspor data Anda.</string>
|
||||
<string name="importVoucherVault">Impor dari Voucher Vault</string>
|
||||
<string name="importVoucherVaultMessage">Pilih ekspor <i>vouchervault.json</i> Anda dari Vault Voucher untuk diimpor. Buat dengan menekan Ekspor di Vault Voucher terlebih dahulu.</string>
|
||||
<string name="importVoucherVaultMessage">Pilih ekspor <i>vouchervault.json</i> Anda dari Vault Voucher untuk diimpor.
|
||||
\nBuat dengan menekan Ekspor di Vault Voucher terlebih dahulu.</string>
|
||||
<string name="unsupportedBarcodeType">Jenis barcode ini belum dapat ditampilkan. Ini mungkin didukung di versi aplikasi yang lebih baru.</string>
|
||||
<string name="wrongValueForBarcodeType">Nilai tidak berlaku untuk jenis barcode yang dipilih</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">ID kartu telah disalin</string>
|
||||
@@ -187,4 +195,16 @@
|
||||
<string name="card_ids_copied">ID kartu yang tersalin</string>
|
||||
<string name="barcodeImageDescriptionWithType">Gambar dari jenis barcode <xliff:g>%s</xliff:g></string>
|
||||
<string name="importExportHelp">Mencadangkan kartu memungkinkan anda memindahkannya ke perangkat lain.</string>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> kartu dipilih</item>
|
||||
</plurals>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> kartu</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="other">Hapus kartu <xliff:g>%d</xliff:g> ini secara permanen\?</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="other">Hapus <xliff:g>%d</xliff:g> kartu</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
@@ -25,4 +25,63 @@
|
||||
<string name="editCardTitle">Breyta Kort</string>
|
||||
<string name="addCardTitle">Bæta Kort</string>
|
||||
<string name="scanCardBarcode">Skanna Kort Strikamerkið</string>
|
||||
<string name="noCardsMessage">Bæta kort fyrstu</string>
|
||||
<string name="exportFailedTitle">Flytja mistókst</string>
|
||||
<string name="exportSuccessfulTitle">Flutt</string>
|
||||
<string name="noStoreError">Ekkert nafn slegið</string>
|
||||
<string name="noCardExistsError">Gæti ekki fundið kort</string>
|
||||
<string name="failedParsingImportUriError">Get ekki lesið inn URI</string>
|
||||
<string name="exportName">Flytja</string>
|
||||
<string name="importExportHelp">Stuðningur upp spil gerir þér kleift að færa þá til annar tæki.</string>
|
||||
<string name="importSuccessfulTitle">Flutt</string>
|
||||
<string name="importFailedTitle">Innflutningur mistókst</string>
|
||||
<string name="noExternalStoragePermissionError">Grant ytri geymslu leyfi til að flytja eða flytja spil fyrstu</string>
|
||||
<string name="exportOptionExplanation">Gögnum verður skrifað á stað af eigin vali.</string>
|
||||
<string name="importOptionFilesystemTitle">Innflutningur frá möppuna</string>
|
||||
<string name="importOptionFilesystemExplanation">Velja ákveðna skrá frá möppuna.</string>
|
||||
<string name="starImage">Uppáhalds stjörnu</string>
|
||||
<string name="never">Aldrei</string>
|
||||
<string name="currency">Mynt</string>
|
||||
<string name="moveBarcodeToTopOfScreen">Færa strikamerkið að efst á skjánum</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">Miðju strikamerkið á skjánum</string>
|
||||
<string name="errorReadingImage">Gat ekki lesið ímynd</string>
|
||||
<string name="importOptionApplicationButton">Notaðu annan app</string>
|
||||
<string name="about">Um</string>
|
||||
<string name="settings">Stillingar</string>
|
||||
<string name="settings_max_font_size_scale">Max. letrið</string>
|
||||
<string name="settings_lock_barcode_orientation">Læsa strikamerkið stefnumörkun</string>
|
||||
<string name="settings_keep_screen_on">Halda á skjánum</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Að koma í veg fyrir að læsa skjánum</string>
|
||||
<string name="editBarcode">Breyta strikamerkið</string>
|
||||
<string name="settings_light_theme">Ljós</string>
|
||||
<string name="importOptionFilesystemButton">Frá möppuna</string>
|
||||
<string name="chooseImportType">Flytja gögn úr\?</string>
|
||||
<string name="balance">Jafnvægi</string>
|
||||
<string name="points">Stig</string>
|
||||
<string name="importOptionApplicationTitle">Notaðu annan app</string>
|
||||
<string name="importOptionApplicationExplanation">Nota allir app eða uppáhalds skráasafn að opna skrá.</string>
|
||||
<string name="selectBarcodeTitle">Veldu Strikamerkið</string>
|
||||
<string name="thumbnailDescription">Þumalinn fyrir kort</string>
|
||||
<string name="settings_theme">Þema</string>
|
||||
<string name="app_license">Copylefted frítt hugbúnaður, leyfi GPLv3+</string>
|
||||
<string name="noBarcodeFound">Nei strikamerkið var komist</string>
|
||||
<string name="settings_category_title_ui">Notandi tengi</string>
|
||||
<string name="settings_system_theme">Kerfi</string>
|
||||
<string name="settings_dark_theme">Dökk</string>
|
||||
<string name="settings_display_barcode_max_brightness">Bjartari strikamerkið skoða</string>
|
||||
<string name="enter_group_name">Inn nafn hópur</string>
|
||||
<string name="intent_import_card_from_url_share_text">Ég vil deila kort með þér</string>
|
||||
<string name="importSuccessful">Kortið gögn flutt</string>
|
||||
<string name="groups">Tekur</string>
|
||||
<string name="exportSuccessful">Kortagögn flutt út</string>
|
||||
<string name="failedOpeningFileManager">Setja skráasafn fyrst.</string>
|
||||
<string name="moveUp">Fara upp</string>
|
||||
<string name="leaveWithoutSaveTitle">Brottför</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Fara án þess að bjarga\?</string>
|
||||
<string name="addFromImage">Veldu mynd frá gallerí</string>
|
||||
<string name="card">Kort</string>
|
||||
<string name="barcode">Strikamerkið</string>
|
||||
<string name="expiryDate">Fyrningu</string>
|
||||
<string name="moveDown">Fara neðar</string>
|
||||
<string name="chooseExpiryDate">Velja rennur</string>
|
||||
</resources>
|
||||
@@ -210,4 +210,14 @@
|
||||
<string name="and_data_usage">e utilizzo dei dati</string>
|
||||
<string name="rate_this_app">Valuta questa applicazione</string>
|
||||
<string name="report_error">Segnala un errore</string>
|
||||
<string name="editGroup">Gruppo di modifica: <xliff:g>%s</xliff:g></string>
|
||||
<string name="group_name_is_empty">Il nome del gruppo non può essere vuoto</string>
|
||||
<string name="noGiftCardsGroup">Non hai ancora nessuna carta fedeltà. Una volta che ne hai aggiunte, puoi assegnarle al gruppo qui.</string>
|
||||
<string name="group_edit">Modifica il gruppo</string>
|
||||
<string name="group_name_already_in_use">Nome del gruppo già in uso</string>
|
||||
<string name="group_updated">Gruppo aggiornato</string>
|
||||
<string name="selectColor">Seleziona il colore</string>
|
||||
<string name="setIcon">Imposta l\'icona</string>
|
||||
<string name="action_show_details">Mostra i dettagli</string>
|
||||
<string name="action_hide_details">Nascondi i dettagli</string>
|
||||
</resources>
|
||||
89
app/src/main/res/values-lb/strings.xml
Normal file
89
app/src/main/res/values-lb/strings.xml
Normal file
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="deleteTitle">Kaart läschen</string>
|
||||
<string name="action_search">Sichen</string>
|
||||
<string name="action_add">Derbäisetzen</string>
|
||||
<string name="noBarcode">Kee barcode</string>
|
||||
<string name="star">An meng Favoriten bäisetzen</string>
|
||||
<string name="unstar">Aus Favoriten ewechhuelen</string>
|
||||
<string name="cancel">Stornieren</string>
|
||||
<string name="save">Späicheren</string>
|
||||
<string name="edit">Änneren</string>
|
||||
<string name="delete">Läschen</string>
|
||||
<string name="confirm">Bestätegen</string>
|
||||
<string name="lockScreen">Blockrotation</string>
|
||||
<string name="unlockScreen">Déblockéieren Rotatioun</string>
|
||||
<string name="deleteConfirmation">Dës Kaart dauerhaft läschen\?</string>
|
||||
<string name="ok">Okay</string>
|
||||
<string name="share">Aktie</string>
|
||||
<string name="sendLabel">Schécken…</string>
|
||||
<string name="editCardTitle">Kaart änneren</string>
|
||||
<string name="addCardTitle">Kaart derbäisetzen</string>
|
||||
<string name="cardShortcut">Kaart Bréck</string>
|
||||
<string name="exportSuccessfulTitle">Exportéieren</string>
|
||||
<string name="exportFailedTitle">Export fehlgeschlagen</string>
|
||||
<string name="exportFailed">Kaarten konnten net exportéiert ginn</string>
|
||||
<string name="importing">Importéieren…</string>
|
||||
<string name="importOptionFilesystemTitle">Import aus dem Dateisystem</string>
|
||||
<string name="importOptionFilesystemExplanation">Wielt eng bestëmmte Datei aus dem Dateisystem.</string>
|
||||
<string name="importOptionFilesystemButton">Aus dem Dateisystem</string>
|
||||
<string name="importOptionApplicationTitle">Benotzt eng aner app</string>
|
||||
<string name="importOptionApplicationButton">Benotzt eng aner app</string>
|
||||
<string name="app_license">Ënner Copyleft stehende fräi software, lizenséiert GPLv3+</string>
|
||||
<string name="groups">Gruppen</string>
|
||||
<string name="importCatima">Import aus Catima</string>
|
||||
<string name="importFidme">Import aus FidMe</string>
|
||||
<string name="importVoucherVault">Import aus Voucher Vault</string>
|
||||
<string name="barcodeId">Barcode-Wäert</string>
|
||||
<string name="sameAsCardId">Déiselwecht wéi kaart ID</string>
|
||||
<string name="frontImageDescription">Vorderes Bild vun der Kaart</string>
|
||||
<string name="backImageDescription">D \' hënnescht Bild vun der Kaart</string>
|
||||
<string name="photos">Fotoen</string>
|
||||
<string name="setFrontImage">Vorderes Bild einstellen</string>
|
||||
<string name="setBackImage">Bild zerécksetzen</string>
|
||||
<string name="removeImage">Bild ewechhuelen</string>
|
||||
<string name="takePhoto">Mach eng Foto</string>
|
||||
<string name="no">Neen</string>
|
||||
<string name="exportPassword">Leeë Si e Passwuert fir de Schutz vun Hirem Exports fest (optional)</string>
|
||||
<string name="exportPasswordHint">Passwuert aginn</string>
|
||||
<string name="noMatchingGiftCards">Ech hunn näischt fonnt. Probéieren Iech, Är Sich ze änneren.</string>
|
||||
<string name="note">Beuechten</string>
|
||||
<string name="barcodeNoBarcode">Dës Kaart huet kee Barcode</string>
|
||||
<string name="importExportHelp">Wann Dir Är Kaarten sécheren, kënnen Si se op een anert Instrument réckelen.</string>
|
||||
<string name="about">Iwwer</string>
|
||||
<string name="selectBarcodeTitle">Wielt Barcode</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Ech wëll e puer Kaarten mat Iech deelen</string>
|
||||
<string name="updateBarcodeQuestionTitle">Aktualiséiert barcode-Wäert\?</string>
|
||||
<string name="intent_import_card_from_url_share_text">Ech wëll eng Kaart mat dir deelen</string>
|
||||
<string name="importSuccessfulTitle">Anere sproochen</string>
|
||||
<string name="unsupportedBarcodeType">Dee barcode-Typ kann net ugewise ginn. Et kann zu enger spéiderer Versioun vun der App ënnerstëtzt ginn.</string>
|
||||
<string name="yes">Jo</string>
|
||||
<string name="importFailedTitle">Import fehlgeschlagen</string>
|
||||
<string name="importFailed">Kaarten konnten net anere sproochen ginn</string>
|
||||
<string name="exporting">Ausführende…</string>
|
||||
<string name="exportOptionExplanation">D \' Donnéeë ginn op eng Plaz vun Hirer Wal geschriwwen.</string>
|
||||
<string name="importOptionApplicationExplanation">Benotzen Se eng beliebige App oder Hire bevorzugten Dateimanager, fir eng Datei ze opmaachen.</string>
|
||||
<string name="accept">Averstane</string>
|
||||
<string name="settings_display_barcode_max_brightness">Erhellen barcode-Usiicht</string>
|
||||
<string name="enterBarcodeInstructions">Gitt d \' Kaarten-ID en an wielen Se entweder den Barcode-Typ ënnen oder \"Dës Kaart huet kee Barcode\".</string>
|
||||
<string name="importStocard">Importéieren vun Stocard</string>
|
||||
<string name="importLoyaltyCardKeychain">Import vun Loyalty Card Keychain</string>
|
||||
<string name="setBarcodeId">Leeë Si barcode-Wäert</string>
|
||||
<string name="wrongValueForBarcodeType">De Wäert ass fir de ausgewielt Barcode-Typ net gëllt</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">Kaarten-IDs an d \' Tëschentablag inspiréiere</string>
|
||||
<string name="updateBarcodeQuestionText">Si hunn d \' Kaarten-ID geännert. Wëllt Dir och de Barcode aktualiséieren, fir deselwechte Wäert ze benotzen\?</string>
|
||||
<string name="settings_dark_theme">Donkel</string>
|
||||
<string name="settings_lock_barcode_orientation">Barcode-Ausriichtung spären</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Bildschierm spären verhënneren</string>
|
||||
<string name="settings_light_theme">Liicht</string>
|
||||
<string name="settings_max_font_size_scale">Max. Schrëftgréisst</string>
|
||||
<string name="settings_keep_screen_on">Hale Si op Bildschierm</string>
|
||||
<string name="importSuccessful">Kartendaten anere sproochen</string>
|
||||
<string name="exportSuccessful">Exportierte Kartendaten</string>
|
||||
<string name="enter_group_name">Gruppenname aginn</string>
|
||||
<string name="noGroupCards">Dës Grupp ass keng Kaarten</string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> Kaart</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> Netzwerkkarten</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
@@ -25,7 +25,7 @@
|
||||
<string name="exporting">Eksportuoja…</string>
|
||||
<string name="noExternalStoragePermissionError">Pirmiausia suteikite išorinės saugyklos leidimą, kad galėtumėte importuoti arba eksportuoti korteles</string>
|
||||
<string name="about">Apie</string>
|
||||
<string name="app_license">Copylefted libre programinė įranga, licencijuota GPLv3+</string>
|
||||
<string name="app_license">Copylefted laisvoji programinė įranga, licencijuota GPLv3+</string>
|
||||
<string name="about_title_fmt">Apie <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versija: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Revizijos info: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
@@ -90,7 +90,7 @@
|
||||
<string name="accept">Priimti</string>
|
||||
<string name="privacy_policy_popup_text">Privatumo politikos pranešimas (kurio reikalaujama kai kuriose programėlių parduotuvėse):
|
||||
\n
|
||||
\nJOKIE DUOMENYS NĖRA RENKAMI, o tai gali patvirtinti bet kas, nes mūsų programėlė yra libre programinė įranga.</string>
|
||||
\nJOKIE DUOMENYS NĖRA RENKAMI, o tai gali patvirtinti bet kas, nes mūsų programėlė yra laisvoji programinė įranga.</string>
|
||||
<string name="privacy_policy">Privatumo politika</string>
|
||||
<string name="chooseImportType">Importuoti duomenis iš\?</string>
|
||||
<string name="points">Taškai</string>
|
||||
@@ -142,8 +142,8 @@
|
||||
<string name="starImage">Mėgstamiausia žvaigždė</string>
|
||||
<string name="thumbnailDescription">Kortelės miniatiūra</string>
|
||||
<string name="enterBarcodeInstructions">Įveskite kortelės ID ir toliau pasirinkite jos brūkšninio kodo tipą arba \"Ši kortelė neturi brūkšninio kodo\".</string>
|
||||
<string name="app_resources">Libre trečiųjų šalių ištekliai: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Libre trečiųjų šalių bibliotekos: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources">Laisvosios trečiųjų šalių ištekliai: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Laisvosios trečiųjų šalių bibliotekos: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_copyright_old">Paremta Loyalty Card Keychain
|
||||
\nautorinės teisės © 2016–2020 Branden Archer</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Autorinės teisės © 2019–<xliff:g>%d</xliff:g> Sylvia van Os</string>
|
||||
@@ -214,4 +214,14 @@
|
||||
<string name="report_error">Pranešti apie klaidą</string>
|
||||
<string name="exportPasswordHint">Įveskite slaptažodį</string>
|
||||
<string name="exportPassword">Nustatykite slaptažodį, kad apsaugotumėte eksportavimą (neprivaloma)</string>
|
||||
<string name="group_name_already_in_use">Toks grupės pavadinimas jau naudojamas</string>
|
||||
<string name="group_name_is_empty">Grupės pavadinimas negali būti tuščias</string>
|
||||
<string name="editGroup">Redaguojama grupė: <xliff:g>%s</xliff:g></string>
|
||||
<string name="group_updated">Grupė atnaujinta</string>
|
||||
<string name="group_edit">Redaguoti grupę</string>
|
||||
<string name="noGiftCardsGroup">Dar neturite jokių lojalumo kortelių. Kai kelias pridėsite, galėsite jas priskirti grupei čia.</string>
|
||||
<string name="setIcon">Nustatyti piktogramą</string>
|
||||
<string name="selectColor">Pasirinkti spalvą</string>
|
||||
<string name="action_hide_details">Paslėpti informaciją</string>
|
||||
<string name="action_show_details">Rodyti išsamią informaciją</string>
|
||||
</resources>
|
||||
96
app/src/main/res/values-lv/strings.xml
Normal file
96
app/src/main/res/values-lv/strings.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="action_search">Meklēšana</string>
|
||||
<string name="action_add">Pievienot</string>
|
||||
<string name="noGiftCards">Noklikšķiniet uz pogas + plus, lai pievienotu karti, vai vispirms importējiet dažus no ⋮ izvēlnes.</string>
|
||||
<string name="noMatchingGiftCards">Neko neatradu. Mēģiniet mainīt meklēšanu.</string>
|
||||
<string name="storeName">Nosaukums</string>
|
||||
<string name="note">Piezīme</string>
|
||||
<string name="barcodeType">Svītrkoda Tips</string>
|
||||
<string name="barcodeNoBarcode">Šai kartei nav svītrkoda</string>
|
||||
<string name="noBarcode">Nav svītrkoda</string>
|
||||
<string name="star">Pievienot izlasei</string>
|
||||
<string name="unstar">Noņemt no izlases</string>
|
||||
<string name="cancel">Atcelt</string>
|
||||
<string name="save">Saglabāt</string>
|
||||
<string name="edit">Rediģēt</string>
|
||||
<string name="delete">Dzēst</string>
|
||||
<string name="moveBarcodeToTopOfScreen">Pārvietojiet svītrkodu uz ekrāna augšdaļu</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">Centrējiet svītrkodu uz ekrāna</string>
|
||||
<string name="errorReadingImage">Nevarēja nolasīt attēlu</string>
|
||||
<string name="balance">Bilance</string>
|
||||
<string name="noBarcodeFound">Svītrkods netika atrasts</string>
|
||||
<string name="currency">Valūta</string>
|
||||
<string name="points">Punkts</string>
|
||||
<string name="chooseImportType">Importēt datus no\?</string>
|
||||
<string name="sendLabel">Nosūtīt…</string>
|
||||
<string name="editCardTitle">Rediģēt Karti</string>
|
||||
<string name="share">Daļa</string>
|
||||
<string name="confirm">Apstiprināt</string>
|
||||
<string name="lockScreen">Bloķēt Rotāciju</string>
|
||||
<string name="unlockScreen">Atbloķēt Rotāciju</string>
|
||||
<string name="deleteTitle">Dzēst karti</string>
|
||||
<string name="deleteConfirmation">Dzēst šo karti pastāvīgi\?</string>
|
||||
<string name="ok">LABI</string>
|
||||
<string name="addCardTitle">Pievienot Karti</string>
|
||||
<string name="scanCardBarcode">Skenēšanas Kartes Svītrkods</string>
|
||||
<string name="cardShortcut">Kartes Saīsne</string>
|
||||
<string name="noCardsMessage">Vispirms pievienojiet karti</string>
|
||||
<string name="noStoreError">Vārds nav ievadīts</string>
|
||||
<string name="noCardExistsError">Nevarēja atrast karti</string>
|
||||
<string name="failedParsingImportUriError">Nevarēja parsēt importa URI</string>
|
||||
<string name="importExport">Imports/Eksports</string>
|
||||
<string name="exportName">Eksports</string>
|
||||
<string name="importExportHelp">Jūsu Karšu dublēšana ļauj pārvietot tās uz citu ierīci.</string>
|
||||
<string name="importSuccessfulTitle">Importēts</string>
|
||||
<string name="importFailedTitle">Neizdevās importēt</string>
|
||||
<string name="importFailed">Nevarēja importēt kartes</string>
|
||||
<string name="exportSuccessfulTitle">Eksports</string>
|
||||
<string name="exportFailedTitle">Eksports neizdevās</string>
|
||||
<string name="exportFailed">Nevarēja eksportēt kartes</string>
|
||||
<string name="importing">Imports…</string>
|
||||
<string name="exporting">Eksports…</string>
|
||||
<string name="noExternalStoragePermissionError">Piešķiriet ārējai atmiņai atļauju vispirms importēt vai eksportēt kartes</string>
|
||||
<string name="exportOptionExplanation">Dati tiks rakstīts uz vietu, pēc jūsu izvēles.</string>
|
||||
<string name="importOptionFilesystemTitle">Importēt no failu sistēmas</string>
|
||||
<string name="importOptionFilesystemExplanation">Izvēlieties konkrētu failu no failu sistēmas.</string>
|
||||
<string name="importOptionFilesystemButton">No failu sistēmas</string>
|
||||
<string name="importOptionApplicationTitle">Izmantojiet citu lietotni</string>
|
||||
<string name="importOptionApplicationExplanation">Izmantojiet jebkuru lietotni vai savu iecienītāko failu pārvaldnieku, lai atvērtu failu.</string>
|
||||
<string name="importOptionApplicationButton">Izmantojiet citu lietotni</string>
|
||||
<string name="about">Par</string>
|
||||
<string name="app_license">Copylefted libre programmatūra, licencēta GPLv3+</string>
|
||||
<string name="selectBarcodeTitle">Izvēlieties Svītrkodu</string>
|
||||
<string name="copy_to_clipboard_toast">Kartes ID kopēts starpliktuvē</string>
|
||||
<string name="thumbnailDescription">Sīktēls kartei</string>
|
||||
<string name="starImage">Mīļākā zvaigzne</string>
|
||||
<string name="settings">Iestatījums</string>
|
||||
<string name="settings_category_title_ui">Interfeiss</string>
|
||||
<string name="settings_theme">Tēma</string>
|
||||
<string name="settings_system_theme">Sistēma</string>
|
||||
<string name="settings_light_theme">Gaisma</string>
|
||||
<string name="settings_dark_theme">Tumšs</string>
|
||||
<string name="settings_max_font_size_scale">Max. fonts</string>
|
||||
<string name="settings_display_barcode_max_brightness">Izgaismojiet svītrkoda skatu</string>
|
||||
<string name="settings_lock_barcode_orientation">Lock svītrkoda orientācija</string>
|
||||
<string name="settings_keep_screen_on">Saglabāt ekrānu</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Novērst bloķēšanas ekrānu</string>
|
||||
<string name="intent_import_card_from_url_share_text">Es vēlos dalīties ar jums karti</string>
|
||||
<string name="importSuccessful">Importētie kartes dati</string>
|
||||
<string name="exportSuccessful">Kartes dati eksportēti</string>
|
||||
<string name="noGroups">Noklikšķiniet uz pogas + plus, lai vispirms pievienotu grupas kategorizēšanai.</string>
|
||||
<string name="noGroupCards">Šajā grupā nav nevienas kartes</string>
|
||||
<string name="all">Visi</string>
|
||||
<string name="deleteConfirmationGroup">Dzēst grupu\?</string>
|
||||
<string name="failedOpeningFileManager">Vispirms instalējiet failu pārvaldnieku.</string>
|
||||
<string name="moveUp">Pārvietot uz augšu</string>
|
||||
<string name="moveDown">Pārvietot uz leju</string>
|
||||
<string name="leaveWithoutSaveTitle">Izeja</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Atstāt bez taupīšanas\?</string>
|
||||
<string name="addFromImage">Izvēlieties attēlu no galerijas</string>
|
||||
<string name="card">Karte</string>
|
||||
<string name="barcode">Svītrkods</string>
|
||||
<string name="expiryDate">Derīguma termiņš</string>
|
||||
<string name="never">Nekad</string>
|
||||
<string name="chooseExpiryDate">Izvēlieties derīguma termiņu</string>
|
||||
</resources>
|
||||
@@ -162,7 +162,7 @@
|
||||
</plurals>
|
||||
<string name="deleteConfirmation">Slett dette kortet for godt?</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">Slett dette kortet for godt\?</item>
|
||||
<item quantity="one">Slett dette <xliff:g>%d</xliff:g> kortet for godt\?</item>
|
||||
<item quantity="other">Slett disse <xliff:g>%d</xliff:g> kortene for godt\?</item>
|
||||
</plurals>
|
||||
<string name="turn_flashlight_on">Skru på lommelykten</string>
|
||||
@@ -196,7 +196,7 @@
|
||||
<string name="sort_by_most_recently_used">Nyligst brukt</string>
|
||||
<string name="sort_by_name">Navn</string>
|
||||
<string name="sort">Sorter</string>
|
||||
<string name="help_translate_this_app">Hjelp med å oversette denne appen</string>
|
||||
<string name="help_translate_this_app">Bistå oversettelsen av programmet</string>
|
||||
<string name="license">Lisens</string>
|
||||
<string name="version_history">Versjonshistorikk</string>
|
||||
<string name="importCatimaMessage">Velg din <i>catima.zip</i>-eksport fra Catima å importere.
|
||||
@@ -204,10 +204,20 @@
|
||||
<string name="source_repository">Kildekode</string>
|
||||
<string name="on_github">på GitHub</string>
|
||||
<string name="and_data_usage">og bruk av data</string>
|
||||
<string name="rate_this_app">Vurder denne appen</string>
|
||||
<string name="rate_this_app">Vurder dette programmet</string>
|
||||
<string name="on_google_play">på Google Play</string>
|
||||
<string name="report_error">Rapporter feil</string>
|
||||
<string name="credits">Bidragsytere</string>
|
||||
<string name="exportPassword">Sett et passord for å beskytte eksporten din (valgfritt)</string>
|
||||
<string name="exportPasswordHint">Skriv inn passord</string>
|
||||
<string name="group_edit">Rediger gruppe</string>
|
||||
<string name="group_name_already_in_use">Gruppenavn allerede i bruk</string>
|
||||
<string name="group_updated">Gruppe oppdatert</string>
|
||||
<string name="group_name_is_empty">Gruppenavn kan ikke være tomt</string>
|
||||
<string name="editGroup">Redigerer gruppe: <xliff:g>%s</xliff:g></string>
|
||||
<string name="noGiftCardsGroup">Du har ingen lojalitetskort enda. Når du først har det kan du legge dem til i en gruppe her.</string>
|
||||
<string name="action_show_details">Vis detaljer</string>
|
||||
<string name="action_hide_details">Skjul detaljer</string>
|
||||
<string name="selectColor">Velg farge</string>
|
||||
<string name="setIcon">Sett ikon</string>
|
||||
</resources>
|
||||
@@ -210,4 +210,14 @@
|
||||
<string name="version_history">Versiegeschiedenis</string>
|
||||
<string name="exportPasswordHint">Voer een wachtwoord in</string>
|
||||
<string name="exportPassword">Stel een wachtwoord in om je exportbestand te beveiligen (optioneel)</string>
|
||||
<string name="group_name_already_in_use">Er is al een groep met deze naam</string>
|
||||
<string name="group_updated">De groep is bijgewerkt</string>
|
||||
<string name="group_name_is_empty">Voer een groepsnaam in</string>
|
||||
<string name="editGroup">Groep bewerken: <xliff:g>%s</xliff:g></string>
|
||||
<string name="noGiftCardsGroup">Je hebt nog geen klantenkaarten toegevoegd. Voeg kaarten toe om ze hier te kunnen groeperen.</string>
|
||||
<string name="group_edit">Groep bewerken</string>
|
||||
<string name="setIcon">Kies een pictogram</string>
|
||||
<string name="selectColor">Kies een kleur</string>
|
||||
<string name="action_show_details">Details tonen</string>
|
||||
<string name="action_hide_details">Details verbergen</string>
|
||||
</resources>
|
||||
2
app/src/main/res/values-pt-rPT/strings.xml
Normal file
2
app/src/main/res/values-pt-rPT/strings.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -1,24 +1,223 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="action_add">Acrescentar</string>
|
||||
<string name="importOptionFilesystemExplanation">Escolha um ficheiro específico a partir do sistema de ficheiros.</string>
|
||||
<string name="action_search">Pesquisa</string>
|
||||
<string name="star">Adicionar aos favoritos</string>
|
||||
<string name="noMatchingGiftCards">Não encontrei nada. Tente alterar a sua pesquisa.</string>
|
||||
<string name="noMatchingGiftCards">Não foi encontrado nada. Tente alterar a sua pesquisa.</string>
|
||||
<string name="storeName">Nome</string>
|
||||
<string name="note">Nota</string>
|
||||
<string name="barcodeType">Tipo de código de barras</string>
|
||||
<string name="barcodeNoBarcode">Este cartão não tem código de barras</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="save">Guardar</string>
|
||||
<string name="edit">Edição</string>
|
||||
<string name="noGiftCards">Clique no botão + + para adicionar um cartão, ou importe algum do menu ⋮ primeiro.</string>
|
||||
<string name="noBarcode">Não há código de barras</string>
|
||||
<string name="edit">Editar</string>
|
||||
<string name="noGiftCards">Clique no botão + para adicionar um cartão ou importe um no botão do menu ⋮</string>
|
||||
<string name="noBarcode">Sem código de barras</string>
|
||||
<string name="unstar">Retirar dos favoritos</string>
|
||||
<string name="importOptionFilesystemButton">Do sistema de arquivo</string>
|
||||
<string name="importOptionApplicationTitle">Use outro aplicativo</string>
|
||||
<string name="importOptionFilesystemButton">Do sistema de ficheiros</string>
|
||||
<string name="importOptionApplicationTitle">Usar outra aplicação</string>
|
||||
<string name="importOptionApplicationExplanation">Utilize qualquer aplicação ou o seu gestor de ficheiros favorito para abrir um ficheiro.</string>
|
||||
<string name="importOptionApplicationButton">Utilize outro aplicativo</string>
|
||||
<string name="importOptionApplicationButton">Utilizar outra aplicação</string>
|
||||
<string name="about">Sobre</string>
|
||||
<string name="app_license">Copylefted software livre, licenciado GPLv3+</string>
|
||||
<string name="app_license">Software livre de partilha sob a mesma licença e segundo a licença GPLv3+</string>
|
||||
<string name="addCardTitle">Adicionar cartão</string>
|
||||
<string name="lockScreen">Bloquear rotação</string>
|
||||
<string name="editCardTitle">Editar cartão</string>
|
||||
<string name="unlockScreen">Desbloquear rotação</string>
|
||||
<string name="deleteTitle">Eliminar cartão</string>
|
||||
<string name="copy_to_clipboard">Copiar identificador para a área de transferência</string>
|
||||
<string name="sendLabel">Enviar…</string>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> cartão selecionado</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> cartões selecionados</item>
|
||||
</plurals>
|
||||
<string name="deleteConfirmation">Eliminar este cartão permanentemente\?</string>
|
||||
<string name="share">Partilhar</string>
|
||||
<string name="scanCardBarcode">Digitalizar código de barras</string>
|
||||
<string name="confirm">Confirmar</string>
|
||||
<string name="delete">Eliminar</string>
|
||||
<string name="cardId">Identificador do cartão</string>
|
||||
<string name="cardShortcut">Atalho do cartão</string>
|
||||
<string name="noCardsMessage">Adicione primeiro um cartão</string>
|
||||
<string name="noStoreError">Nenhum nome inserido</string>
|
||||
<string name="noCardExistsError">Não foi possível encontrar o cartão</string>
|
||||
<string name="failedParsingImportUriError">Não foi possível analisar o URI de importação</string>
|
||||
<string name="importExport">Importar / exportar</string>
|
||||
<string name="exportName">Exportar</string>
|
||||
<string name="importSuccessful">Dados do cartão importados</string>
|
||||
<string name="noGroups">Primeiro clique no botão + para adicionar grupos para categorização.</string>
|
||||
<string name="noGroupCards">Este grupo não contém cartões</string>
|
||||
<string name="intent_import_card_from_url_share_text">Quero partilhar um cartão</string>
|
||||
<string name="settings_display_barcode_max_brightness">Iluminar o código de barras</string>
|
||||
<string name="settings_keep_screen_on">Manter ecrã ligado</string>
|
||||
<string name="enter_group_name">Introduza o nome do grupo</string>
|
||||
<string name="groups">Grupos</string>
|
||||
<string name="settings_lock_barcode_orientation">Bloquear orientação do código de barras</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Desativar bloqueio do ecrã</string>
|
||||
<string name="exportSuccessful">Dados do cartão exportados</string>
|
||||
<string name="all">Todos</string>
|
||||
<string name="deleteConfirmationGroup">Eliminar o grupo\?</string>
|
||||
<string name="settings">Configurações</string>
|
||||
<string name="settings_category_title_ui">Interface do utilizador</string>
|
||||
<string name="settings_theme">Tema</string>
|
||||
<string name="settings_system_theme">Sistema</string>
|
||||
<string name="settings_light_theme">Claro</string>
|
||||
<string name="settings_dark_theme">Escuro</string>
|
||||
<string name="settings_max_font_size_scale">Tamanho máximo da fonte</string>
|
||||
<string name="selectBarcodeTitle">Selecionar código de barras</string>
|
||||
<string name="enterBarcodeInstructions">Introduza o identificador do cartão e depois escolha o tipo de código de barras abaixo ou \"Este cartão não tem código de barras\".</string>
|
||||
<string name="copy_to_clipboard_toast">Identificador do cartão copiado para a área de transferência</string>
|
||||
<string name="thumbnailDescription">Miniatura do cartão</string>
|
||||
<string name="starImage">Favorito</string>
|
||||
<string name="failedOpeningFileManager">Instalar primeiro um gestor de ficheiros.</string>
|
||||
<string name="moveUp">Subir</string>
|
||||
<string name="moveDown">Descer</string>
|
||||
<string name="leaveWithoutSaveTitle">Sair</string>
|
||||
<string name="noExternalStoragePermissionError">Conceda primeiro a autorização de acesso ao armazenamento externo para importar ou exportar cartões</string>
|
||||
<string name="importExportHelp">A cópia de segurança dos seus cartões permite-lhe movê-los para outro dispositivo.</string>
|
||||
<string name="importSuccessfulTitle">Importado</string>
|
||||
<string name="importFailedTitle">A importação falhou</string>
|
||||
<string name="importFailed">Não foi possível importar os cartões</string>
|
||||
<string name="exportSuccessfulTitle">Exportado</string>
|
||||
<string name="exportFailedTitle">A exportação falhou</string>
|
||||
<string name="exportFailed">Não foi possível exportar os cartões</string>
|
||||
<string name="importing">A importar…</string>
|
||||
<string name="exporting">A exportar…</string>
|
||||
<string name="settings_sky_blue_theme">Azul céu</string>
|
||||
<string name="report_error">Reportar erro</string>
|
||||
<string name="balancePoints"><xliff:g>%s</xliff:g> pontos</string>
|
||||
<string name="barcode">Código de barras</string>
|
||||
<string name="chooseImportType">De onde importar os dados\?</string>
|
||||
<string name="card">Cartão</string>
|
||||
<string name="expiryStateSentence">Expiram: <xliff:g>%s</xliff:g></string>
|
||||
<string name="app_resources">Recursos livres de terceiros: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Bibliotecas livres de terceiros: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="takePhoto">Tirar uma fotografia</string>
|
||||
<string name="yes">Sim</string>
|
||||
<string name="exportPassword">Defina uma palavra-passe para proteger a exportação (opcional)</string>
|
||||
<string name="exportPasswordHint">Digite a palavra-passe</string>
|
||||
<string name="setBarcodeId">Definir o valor do código de barras</string>
|
||||
<string name="sameAsCardId">Igual ao identificador do cartão</string>
|
||||
<string name="importFidmeMessage">Selecione a exportação <i>fidme-export-request-xxxxxx.zip</i> do FidMe para importar e depois selecione os tipos de código de barras manualmente.
|
||||
\nPrimeiro crie a exportação no seu perfil do FidMe escolhendo a opção \"Proteção de dados\" e em seguida pressionando \"Extrair os meus dados\".</string>
|
||||
<string name="importStocardMessage">Selecione a exportação <i>***-sync.zip</i> do Stocard para importar.
|
||||
\nObtenha-o através do e-mail support@stocardapp.com solicitando uma exportação dos seus dados.</string>
|
||||
<string name="barcodeId">Valor do código de barras</string>
|
||||
<string name="wrongValueForBarcodeType">O valor não é válido para o tipo de código de barras selecionado</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Quero partilhar alguns cartões</string>
|
||||
<string name="removeImage">Remover imagem</string>
|
||||
<string name="backImageDescription">Imagem de trás do cartão</string>
|
||||
<string name="frontImageDescription">Imagem frontal do cartão</string>
|
||||
<string name="photos">Fotografias</string>
|
||||
<string name="passwordRequired">Introduza a palavra-passe</string>
|
||||
<string name="settings_green_theme">Verde</string>
|
||||
<string name="settings_grey_theme">Cinza</string>
|
||||
<string name="settings_brown_theme">Castanho</string>
|
||||
<string name="updateBarcodeQuestionTitle">Atualizar o valor do código de barras\?</string>
|
||||
<string name="updateBarcodeQuestionText">Alterou a identificação do cartão. Também quer atualizar o código de barras para usar o mesmo valor\?</string>
|
||||
<string name="no">Não</string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> cartão</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> cartões</item>
|
||||
</plurals>
|
||||
<string name="importOptionFilesystemTitle">Importar do sistema de ficheiros</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Direitos de autor © 2019–<xliff:g>%d</xliff:g> Sylvia van Os</string>
|
||||
<string name="app_copyright_old">Baseado no Loyalty Card Keychain
|
||||
\ndireitos de autor © 2016–2020 Branden Archer</string>
|
||||
<string name="about_title_fmt">Sobre o <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versão: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Informação da revisão: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="expiryStateSentenceExpired">Expirados: <xliff:g>%s</xliff:g></string>
|
||||
<string name="leaveWithoutSaveConfirmation">Sair sem guardar\?</string>
|
||||
<string name="addManually">Introduzir manualmente o identificador do cartão</string>
|
||||
<string name="addFromImage">Selecionar imagem da galeria</string>
|
||||
<string name="groupsList">Grupos: <xliff:g>%s</xliff:g></string>
|
||||
<string name="balanceSentence">Saldo: <xliff:g>%s</xliff:g></string>
|
||||
<string name="editBarcode">Editar código de barras</string>
|
||||
<string name="expiryDate">Validade</string>
|
||||
<string name="never">Nunca</string>
|
||||
<string name="chooseExpiryDate">Escolher validade</string>
|
||||
<string name="moveBarcodeToTopOfScreen">Mover o código de barras para o topo do ecrã</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">Centrar o código de barras no ecrã</string>
|
||||
<string name="noBarcodeFound">Não foi encontrado nenhum código de barras</string>
|
||||
<string name="errorReadingImage">Não foi possível ler a imagem</string>
|
||||
<string name="balance">Saldo</string>
|
||||
<string name="currency">Moeda</string>
|
||||
<string name="points">Pontos</string>
|
||||
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> não parece ser um saldo válido.</string>
|
||||
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
|
||||
<string name="privacy_policy">Política de privacidade</string>
|
||||
<string name="privacy_policy_popup_text">Aviso de política de privacidade (exigido por algumas lojas de aplicações):
|
||||
\n
|
||||
\nNENHUM DADO É RECOLHIDO DE FORMA ALGUMA, o que qualquer pessoa pode confirmar, já que a nossa aplicação é um software livre de código-fonte aberto.</string>
|
||||
<string name="accept">Aceitar</string>
|
||||
<string name="importCatima">Importar do Catima</string>
|
||||
<string name="importCatimaMessage">Selecione a exportação <i>catima.zip</i> do Catima a importar.
|
||||
\nPrimeiro crie a exportação no menu \"Importar / exportar\" de outra aplicação Catima pressionando \"Exportar\" nesse menu.</string>
|
||||
<string name="importFidme">Importar do FidMe</string>
|
||||
<string name="importLoyaltyCardKeychain">Importar do Loyalty Card Keychain</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">Selecione a exportação <i>LoyaltyCardKeychain.csv</i> do Loyalty Card Keychain para importar.
|
||||
\nPrimeiro crie a exportação no menu \"Importar / exportar\" no Loyalty Card Keychain pressionando \"Exportar\".</string>
|
||||
<string name="importStocard">Importar do Stocard</string>
|
||||
<string name="importVoucherVault">Importar do Voucher Vault</string>
|
||||
<string name="importVoucherVaultMessage">Selecione a exportação <i>vouchervault.json</i> do Voucher Vault para importar.
|
||||
\nCrie-a primeiro pressionando a opção \"Exportar\" no Voucher Vault.</string>
|
||||
<string name="unsupportedBarcodeType">Este tipo de código de barras ainda não pode ser mostrado. Pode vir a ser suportado numa versão posterior da aplicação.</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">Identificação do cartão copiado para a área de transferência</string>
|
||||
<string name="setFrontImage">Definir imagem frontal</string>
|
||||
<string name="setBackImage">Definir imagem de trás</string>
|
||||
<string name="failedGeneratingShareURL">Não foi possível gerar uma URL partilhável. Por favor reporte isto aos programadores.</string>
|
||||
<string name="turn_flashlight_on">Ligar lanterna</string>
|
||||
<string name="turn_flashlight_off">Desligar lanterna</string>
|
||||
<string name="settings_locale">Idioma</string>
|
||||
<string name="settings_system_locale">Sistema</string>
|
||||
<string name="settings_theme_color">Cor do tema</string>
|
||||
<string name="settings_catima_theme">Catima</string>
|
||||
<string name="settings_pink_theme">Rosa</string>
|
||||
<string name="settings_magenta_theme">Magenta</string>
|
||||
<string name="settings_violet_theme">Violeta</string>
|
||||
<string name="settings_blue_theme">Azul</string>
|
||||
<string name="app_contributors">Tornado possível por: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="sort">Ordenar</string>
|
||||
<string name="toggleMoreInfo">Alternar mostrar mais informação</string>
|
||||
<string name="swipeToSwitchImages">Deslize ou pressione prolongadamente para mudar as imagens</string>
|
||||
<string name="sort_by_name">Nome</string>
|
||||
<string name="sort_by_most_recently_used">Mais usados recentemente</string>
|
||||
<string name="sort_by_expiry">Validade</string>
|
||||
<string name="sort_by_balance">Saldo</string>
|
||||
<string name="reverse">Inverter</string>
|
||||
<string name="sort_by">Ordenar por</string>
|
||||
<string name="version_history">Histórico de versões</string>
|
||||
<string name="credits">Créditos</string>
|
||||
<string name="help_translate_this_app">Ajude a traduzir esta aplicação</string>
|
||||
<string name="license">Licença</string>
|
||||
<string name="source_repository">Repositório do código-fonte</string>
|
||||
<string name="on_github">no GitHub</string>
|
||||
<string name="and_data_usage">e utilização de dados</string>
|
||||
<string name="rate_this_app">Avalie esta aplicação</string>
|
||||
<string name="on_google_play">no Google Play</string>
|
||||
<string name="exportOptionExplanation">Os dados serão guardados num local à sua escolha.</string>
|
||||
<string name="noCardIdError">Nenhum identificador inserido</string>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">Eliminar <xliff:g>%d</xliff:g> cartão</item>
|
||||
<item quantity="other">Eliminar <xliff:g>%d</xliff:g> cartões</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">Eliminar o cartão <xliff:g>%d</xliff:g> permanentemente\?</item>
|
||||
<item quantity="other">Eliminar os cartões <xliff:g>%d</xliff:g> permanentemente\?</item>
|
||||
</plurals>
|
||||
<string name="ok">OK</string>
|
||||
<string name="card_ids_copied">Identificadores dos cartões copiados</string>
|
||||
<string name="barcodeImageDescriptionWithType">Imagem do código de barras do cartão do tipo <xliff:g>%s</xliff:g></string>
|
||||
<string name="group_edit">Editar grupo</string>
|
||||
<string name="group_name_already_in_use">O nome do grupo já está a ser usado</string>
|
||||
<string name="group_name_is_empty">O nome do grupo não pode estar vazio</string>
|
||||
<string name="group_updated">Grupo atualizado</string>
|
||||
<string name="editGroup">A editar grupo: <xliff:g>%s</xliff:g></string>
|
||||
<string name="noGiftCardsGroup">Ainda não tem nenhum cartão de fidelidade. Assim que tenha adicionado alguns, pode atribuí-los ao grupo aqui.</string>
|
||||
<string name="selectColor">Selecionar cor</string>
|
||||
<string name="setIcon">Definir ícone</string>
|
||||
<string name="action_show_details">Mostrar detalhes</string>
|
||||
<string name="action_hide_details">Ocultar detalhes</string>
|
||||
</resources>
|
||||
@@ -154,7 +154,7 @@
|
||||
<string name="removeImage">Удалить изображение</string>
|
||||
<string name="backImageDescription">Задняя сторона карты</string>
|
||||
<string name="frontImageDescription">Лицевая сторона карты</string>
|
||||
<string name="photos">Фотографии</string>
|
||||
<string name="photos">Фото</string>
|
||||
<string name="importStocardMessage">Выберите для импортирования файл <i>***-sync.zip</i>.
|
||||
\nЭтот файл можно получить по электронной почте от support@stocardapp.com, предварительно запросив экспорт ваших данных.</string>
|
||||
<string name="passwordRequired">Введите пароль</string>
|
||||
@@ -218,4 +218,14 @@
|
||||
<string name="help_translate_this_app">Помощь в переводе приложения</string>
|
||||
<string name="exportPassword">Защитить файл экспорта паролем (необязательно)</string>
|
||||
<string name="exportPasswordHint">Введите пароль</string>
|
||||
<string name="group_name_is_empty">Название группы не может быть пустым</string>
|
||||
<string name="group_updated">Группа обновлена</string>
|
||||
<string name="editGroup">Редактирование группы: <xliff:g>%s</xliff:g></string>
|
||||
<string name="group_edit">Изменить группу</string>
|
||||
<string name="group_name_already_in_use">Такое название группы уже существует</string>
|
||||
<string name="noGiftCardsGroup">У вас ещё нет ни одной карты. Как только появится несколько карт, вы сможете добавить их в группу здесь.</string>
|
||||
<string name="setIcon">Выбор значка</string>
|
||||
<string name="selectColor">Выбрать цвет</string>
|
||||
<string name="action_hide_details">Скрыть детали</string>
|
||||
<string name="action_show_details">Показать детали</string>
|
||||
</resources>
|
||||
@@ -206,4 +206,18 @@
|
||||
<string name="version_history">Versionshistorik</string>
|
||||
<string name="help_translate_this_app">Hjälp till med översättningen av appen</string>
|
||||
<string name="on_github">på GitHub</string>
|
||||
<string name="exportPassword">Sätt ett lösenord för att skydda din exporterade data (valfritt)</string>
|
||||
<string name="exportPasswordHint">Ange lösenord</string>
|
||||
<string name="group_updated">Gruppen har uppdaterats</string>
|
||||
<string name="group_edit">Redigera grupp</string>
|
||||
<string name="group_name_already_in_use">Gruppnamnet är redan upptaget</string>
|
||||
<string name="group_name_is_empty">Gruppnamn måste anges</string>
|
||||
<string name="editGroup">Redigerar grupp: <xliff:g>%s</xliff:g></string>
|
||||
<string name="selectColor">Välj färg</string>
|
||||
<string name="setIcon">Välj ikon</string>
|
||||
<string name="action_show_details">Visa detaljer</string>
|
||||
<string name="action_hide_details">Dölj detaljer</string>
|
||||
<string name="credits">Bidragsgivare</string>
|
||||
<string name="source_repository">Källkodslager</string>
|
||||
<string name="noGiftCardsGroup">Du har inga kundkort än. När du senare lägger till några kan du placera dem i den här gruppen.</string>
|
||||
</resources>
|
||||
@@ -210,4 +210,14 @@
|
||||
<string name="version_history">Sürüm Geçmişi</string>
|
||||
<string name="exportPassword">Dışa aktarmanızı korumak için bir parola belirleyin (isteğe bağlı)</string>
|
||||
<string name="exportPasswordHint">Parola girin</string>
|
||||
<string name="noGiftCardsGroup">Henüz sadakat kartınız yok. Birkaç tane ekledikten sonra, onları burada gruba atayabilirsiniz.</string>
|
||||
<string name="group_name_already_in_use">Grup adı zaten kullanılıyor</string>
|
||||
<string name="editGroup">Grup Düzenleniyor: <xliff:g>%s</xliff:g></string>
|
||||
<string name="group_edit">Grubu Düzenle</string>
|
||||
<string name="group_name_is_empty">Grup adı boş olamaz</string>
|
||||
<string name="group_updated">Grup güncellendi</string>
|
||||
<string name="selectColor">Renk seç</string>
|
||||
<string name="setIcon">Simge ayarla</string>
|
||||
<string name="action_show_details">Ayrıntıları göster</string>
|
||||
<string name="action_hide_details">Ayrıntıları gizle</string>
|
||||
</resources>
|
||||
@@ -218,4 +218,14 @@
|
||||
<string name="report_error">Повідомити про помилку</string>
|
||||
<string name="exportPassword">Встановіть пароль для захисту експорту (необов\'язково)</string>
|
||||
<string name="exportPasswordHint">Введіть пароль</string>
|
||||
<string name="group_name_is_empty">Назва групи не може бути пустою</string>
|
||||
<string name="group_updated">Групу оновлено</string>
|
||||
<string name="editGroup">Редагування групи: <xliff:g>%s</xliff:g></string>
|
||||
<string name="group_edit">Змінити групу</string>
|
||||
<string name="group_name_already_in_use">Група з такою назвою вже існує</string>
|
||||
<string name="noGiftCardsGroup">У вас ще немає жодної картки. Коли ви додасте кілька, то зможете призначити їх до групи.</string>
|
||||
<string name="selectColor">Вибір кольору</string>
|
||||
<string name="setIcon">Вибір іконки</string>
|
||||
<string name="action_show_details">Показати деталі</string>
|
||||
<string name="action_hide_details">Сховати деталі</string>
|
||||
</resources>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<integer name="main_view_card_columns">2</integer>
|
||||
<integer name="main_view_card_columns">3</integer>
|
||||
</resources>
|
||||
@@ -12,7 +12,7 @@
|
||||
<string name="card">卡片</string>
|
||||
<string name="addManually">手动输入卡号</string>
|
||||
<string name="settings_system_theme">系统设置</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019–<xliff:g>%d</xliff:g> Sylvia van Os.</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">版权所有 © 2019–<xliff:g>%d</xliff:g> Sylvia van Os</string>
|
||||
<string name="importOptionApplicationButton">使用其他应用</string>
|
||||
<string name="importOptionFilesystemButton">从文件系统</string>
|
||||
<string name="unstar">从收藏中删除</string>
|
||||
@@ -23,17 +23,17 @@
|
||||
<string name="setBarcodeId">设置条形码值</string>
|
||||
<string name="sameAsCardId">与卡号相同</string>
|
||||
<string name="barcodeId">条形码值</string>
|
||||
<string name="importVoucherVaultMessage">选择从Voucher Vault导出的文件:<i>vouchervault.json</i>进行导入。
|
||||
\n或者先在Voucher Vault中按下导出键来创建导出。</string>
|
||||
<string name="importVoucherVaultMessage">选择 Voucher Vault 导出文件 <i>vouchervault.json</i> 进行导入。
|
||||
\n先在 Voucher Vault 中按下“导出”来创建此文件。</string>
|
||||
<string name="importVoucherVault">从 Voucher Vault 导入</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">选择从Loyalty Card Keychain导出的文件:<i>LoyaltyCardKeychain.csv</i>来导入。
|
||||
\n或者先从Loyalty Card Keychain的Import/Export菜单中选择Export来导出。</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">选择 Loyalty Card Keychain 导出文件 <i>LoyaltyCardKeychain.csv</i>来导入。
|
||||
\n先在 Loyalty Card Keychain 的 “导入/导出” 菜单中按“导出”。</string>
|
||||
<string name="importLoyaltyCardKeychain">从 Loyalty Card Keychain 导入</string>
|
||||
<string name="importFidmeMessage">选择从Fidme导出的文件:<i>fidme-export-request-xxxxxx.zip</i>进行导入,之后再手动选择条码类型。
|
||||
\n或者从你的FidMe配置文件中选择数据保护,然后按提取我的数据来创建导出。</string>
|
||||
<string name="importFidmeMessage">选择 Fidme 导出文件 <i>fidme-export-request-xxxxxx.zip</i>进行导入,之后再手动选择条码类型。
|
||||
\n创建 Fidme 配置的导出文件,方法是选择“数据保护”,然后按“提取我的数据”。</string>
|
||||
<string name="importFidme">从 FidMe 导入</string>
|
||||
<string name="importCatimaMessage">选择从Catima导出的文件:<i>Catima.zip</i>来导入。
|
||||
\n或者先从另一个Catima应用程序的导入/导出菜单中,来创建导出。</string>
|
||||
<string name="importCatimaMessage">选择 Catima 导出文件 <i>Catima.zip</i>来导入。
|
||||
\n先按另一个 Catima 应用程序导入/导出菜单中“导出”创建文件。</string>
|
||||
<string name="importCatima">从 Catima 导入</string>
|
||||
<string name="accept">接受</string>
|
||||
<string name="privacy_policy_popup_text">隐私政策通知(一些应用程序商店要求)。
|
||||
@@ -87,9 +87,9 @@
|
||||
<string name="enterBarcodeInstructions">输入卡号,并从下面选择其条码类型,或选择\"此卡片没有条码\"。</string>
|
||||
<string name="selectBarcodeTitle">选择条码</string>
|
||||
<string name="app_resources">第三方自由资源:<xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_license">本软件为自由软件,使用 GPLv3+ 许可.</string>
|
||||
<string name="app_license">本软件为自由软件,使用 GPLv3+ 许可证</string>
|
||||
<string name="app_copyright_old">基于 Loyalty Card Keychain
|
||||
\ncopyright © 2016–2020 Branden Archer.</string>
|
||||
\n版权所有 © 2016–2020 Branden Archer</string>
|
||||
<string name="about">关于</string>
|
||||
<string name="importOptionApplicationExplanation">使用任何应用程序或您喜欢的文件管理器打开文件。</string>
|
||||
<string name="importOptionApplicationTitle">使用其他应用</string>
|
||||
@@ -143,8 +143,8 @@
|
||||
<string name="deleteConfirmation">删除此卡?</string>
|
||||
<string name="deleteTitle">移除卡片</string>
|
||||
<string name="starImage">最喜欢的星星</string>
|
||||
<string name="importStocardMessage">选择你从Stocard导出的<i>****-sync.zip</i>来导入。
|
||||
\n或者发电子邮件给support@stocardapp.com,要求导出你的数据,从而获得此文件。</string>
|
||||
<string name="importStocardMessage">选择 Stocard 导出文件 <i>****-sync.zip</i>来导入。
|
||||
\n发电子邮件给 support@stocardapp.com 请求获得数据导出文件。</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="other">确定永久删除 <xliff:g>%d</xliff:g> 这些卡片?</item>
|
||||
</plurals>
|
||||
@@ -170,4 +170,7 @@
|
||||
<string name="backImageDescription">卡片的背面图像</string>
|
||||
<string name="frontImageDescription">卡片的正面图像</string>
|
||||
<string name="importStocard">从Stocard导入</string>
|
||||
<string name="noGiftCardsGroup">你还没有会员卡。一旦添加了一些卡,你可以将它们分配到这里的组。</string>
|
||||
<string name="barcodeImageDescriptionWithType"><xliff:g>%s</xliff:g>型卡片条码图像</string>
|
||||
<string name="group_edit">编辑组</string>
|
||||
</resources>
|
||||
@@ -33,7 +33,8 @@
|
||||
<dimen name="activity_margin">16dp</dimen>
|
||||
|
||||
<!-- The default letter tile text size -->
|
||||
<dimen name="tileLetterFontSize">33sp</dimen>
|
||||
<dimen name="tileLetterFontSizeForShortcut">24dp</dimen>
|
||||
<dimen name="tileLetterFontSize">66sp</dimen>
|
||||
<dimen name="tileLetterFontSizeForShortcut">48dp</dimen>
|
||||
<dimen name="tileLetterImageSize">92dp</dimen>
|
||||
<dimen name="cardViewLetterFontSize">100sp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<integer name="main_view_card_columns">1</integer>
|
||||
<integer name="main_view_card_columns">2</integer>
|
||||
</resources>
|
||||
@@ -43,6 +43,7 @@
|
||||
<item>bn-rIN</item>
|
||||
<item>bs</item>
|
||||
<item>cs</item>
|
||||
<item>cy</item>
|
||||
<item>da</item>
|
||||
<item>de</item>
|
||||
<item>el-rGR</item>
|
||||
@@ -52,11 +53,13 @@
|
||||
<item>fi</item>
|
||||
<item>fr</item>
|
||||
<item>he-rIL</item>
|
||||
<item>hr</item>
|
||||
<item>in-rID</item>
|
||||
<item>it</item>
|
||||
<item>ja</item>
|
||||
<item>ko</item>
|
||||
<item>lt</item>
|
||||
<item>lv</item>
|
||||
<item>nb-rNO</item>
|
||||
<item>nl</item>
|
||||
<item>oc</item>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="action_search">Search</string>
|
||||
<string name="action_add">Add</string>
|
||||
<plurals name="selectedCardCount">
|
||||
@@ -7,6 +7,7 @@
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> cards selected</item>
|
||||
</plurals>
|
||||
<string name="noGiftCards">Click the + plus button to add a card, or import some from the ⋮ menu first.</string>
|
||||
<string name="noGiftCardsGroup">You don\'t have any loyalty cards yet. Once you\'ve added some you can assign them to the group here.</string>
|
||||
<string name="noMatchingGiftCards">Didn\'t find anything. Try changing your search.</string>
|
||||
<string name="storeName">Name</string>
|
||||
<string name="note">Note</string>
|
||||
@@ -123,12 +124,16 @@
|
||||
<string name="exportSuccessful">Card data exported</string>
|
||||
<string name="enter_group_name">Enter group name</string>
|
||||
<string name="groups">Groups</string>
|
||||
<string name="group_edit">Edit Group</string>
|
||||
<string name="noGroups">Click the + plus button to add groups for categorization first.</string>
|
||||
<string name="noGroupCards">This group does not contain any cards</string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> card</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> cards</item>
|
||||
</plurals>
|
||||
<string name="group_name_already_in_use">Group name already in use</string>
|
||||
<string name="group_name_is_empty">Group name cannot be empty</string>
|
||||
<string name="group_updated">Group updated</string>
|
||||
<string name="all">All</string>
|
||||
<string name="deleteConfirmationGroup">Delete group?</string>
|
||||
<string name="failedOpeningFileManager">Install a file manager first.</string>
|
||||
@@ -139,6 +144,7 @@
|
||||
<string name="addManually">Manually enter card ID</string>
|
||||
<string name="addFromImage">Select image from gallery</string>
|
||||
<string name="groupsList">Groups: <xliff:g>%s</xliff:g></string>
|
||||
<string name="editGroup">Editing Group: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentence">Expires: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentenceExpired">Expired: <xliff:g>%s</xliff:g></string>
|
||||
<string name="balanceSentence">Balance: <xliff:g>%s</xliff:g></string>
|
||||
@@ -204,6 +210,8 @@
|
||||
<string name="settings_locale">Language</string>
|
||||
<string name="settings_key_locale" translatable="false">pref_locale</string>
|
||||
<string name="settings_system_locale">System</string>
|
||||
<string name="selectColor">Select color</string>
|
||||
<string name="setIcon">Set icon</string>
|
||||
<string name="setting_key_theme_color" translatable="false">pref_theme_color</string>
|
||||
<string name="settings_theme_color">Theme color</string>
|
||||
<string name="settings_catima_theme">Catima</string>
|
||||
@@ -245,4 +253,6 @@
|
||||
<string name="rate_this_app">Rate this app</string>
|
||||
<string name="on_google_play">on Google Play</string>
|
||||
<string name="report_error">Report Error</string>
|
||||
</resources>
|
||||
<string name="action_show_details">Show details</string>
|
||||
<string name="action_hide_details">Hide details</string>
|
||||
</resources>
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.MaterialComponents.Dark.ActionBar"/>
|
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.MaterialComponents.Light"/>
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.DayNight"/>
|
||||
|
||||
<style name="CardView.ActionBarTheme" parent="@style/ThemeOverlay.MaterialComponents.ActionBar">
|
||||
<!-- THIS is where you can color the arrow! -->
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<paths>
|
||||
<external-path name="exportPath" path="/" />
|
||||
<cache-path name="cachePath" path="/" />
|
||||
</paths>
|
||||
@@ -28,29 +28,27 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 23)
|
||||
public class DatabaseTest
|
||||
{
|
||||
private DBHelper db;
|
||||
public class DatabaseTest {
|
||||
private DBHelper mDb;
|
||||
private Activity mActivity;
|
||||
|
||||
private static final Integer DEFAULT_HEADER_COLOR = Color.BLACK;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
Activity activity = Robolectric.setupActivity(MainActivity.class);
|
||||
db = TestHelpers.getEmptyDb(activity);
|
||||
public void setUp() {
|
||||
mActivity = Robolectric.setupActivity(MainActivity.class);
|
||||
mDb = TestHelpers.getEmptyDb(mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addRemoveOneGiftCard()
|
||||
{
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
public void addRemoveOneGiftCard() {
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("store", loyaltyCard.store);
|
||||
assertEquals("note", loyaltyCard.note);
|
||||
@@ -63,25 +61,24 @@ public class DatabaseTest
|
||||
assertEquals(DEFAULT_HEADER_COLOR, loyaltyCard.headerColor);
|
||||
assertEquals(0, loyaltyCard.starStatus);
|
||||
|
||||
result = db.deleteLoyaltyCard(1);
|
||||
result = mDb.deleteLoyaltyCard(mActivity, 1);
|
||||
assertTrue(result);
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
assertNull(db.getLoyaltyCard(1));
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
assertNull(mDb.getLoyaltyCard(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGiftCard()
|
||||
{
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
public void updateGiftCard() {
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
result = db.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("10.00"), Currency.getInstance("EUR"), "cardId1", null, CatimaBarcode.fromBarcode(BarcodeFormat.AZTEC), DEFAULT_HEADER_COLOR);
|
||||
result = mDb.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("10.00"), Currency.getInstance("EUR"), "cardId1", null, CatimaBarcode.fromBarcode(BarcodeFormat.AZTEC), DEFAULT_HEADER_COLOR);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("store1", loyaltyCard.store);
|
||||
assertEquals("note1", loyaltyCard.note);
|
||||
@@ -96,18 +93,17 @@ public class DatabaseTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGiftCardOnlyStar()
|
||||
{
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
public void updateGiftCardOnlyStar() {
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
result = db.updateLoyaltyCardStarStatus(1, 1);
|
||||
result = mDb.updateLoyaltyCardStarStatus(1, 1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("store", loyaltyCard.store);
|
||||
assertEquals("note", loyaltyCard.note);
|
||||
@@ -122,25 +118,23 @@ public class DatabaseTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateMissingGiftCard()
|
||||
{
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
public void updateMissingGiftCard() {
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
|
||||
boolean result = db.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("0"), null, "cardId1",
|
||||
boolean result = mDb.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("0"), null, "cardId1",
|
||||
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR);
|
||||
assertEquals(false, result);
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyGiftCardValues()
|
||||
{
|
||||
long id = db.insertLoyaltyCard("", "", null, new BigDecimal("0"), null, "", null, null, null, 0, null);
|
||||
public void emptyGiftCardValues() {
|
||||
long id = mDb.insertLoyaltyCard("", "", null, new BigDecimal("0"), null, "", null, null, null, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("", loyaltyCard.store);
|
||||
assertEquals("", loyaltyCard.note);
|
||||
@@ -155,37 +149,34 @@ public class DatabaseTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void giftCardsViaCursor()
|
||||
{
|
||||
public void giftCardsViaCursor() {
|
||||
final int CARDS_TO_ADD = 10;
|
||||
|
||||
// Add the gift cards in reverse order, to ensure
|
||||
// that they are sorted
|
||||
for(int index = CARDS_TO_ADD-1; index >= 0; index--)
|
||||
{
|
||||
long id = db.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
for (int index = CARDS_TO_ADD - 1; index >= 0; index--) {
|
||||
long id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(CARDS_TO_ADD, db.getLoyaltyCardCount());
|
||||
assertEquals(CARDS_TO_ADD, mDb.getLoyaltyCardCount());
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
Cursor cursor = mDb.getLoyaltyCardCursor();
|
||||
assertNotNull(cursor);
|
||||
|
||||
assertEquals(CARDS_TO_ADD, cursor.getCount());
|
||||
|
||||
cursor.moveToFirst();
|
||||
|
||||
for(int index = 0; index < CARDS_TO_ADD; index++)
|
||||
{
|
||||
assertEquals("store"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
|
||||
assertEquals("note"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
|
||||
for (int index = 0; index < CARDS_TO_ADD; index++) {
|
||||
assertEquals("store" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
|
||||
assertEquals("note" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
|
||||
assertEquals(0, cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY)));
|
||||
assertEquals("0", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE)));
|
||||
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE)));
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals("cardId" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID)));
|
||||
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
|
||||
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
|
||||
@@ -206,36 +197,33 @@ public class DatabaseTest
|
||||
long id;
|
||||
// Add the gift cards in reverse order and add one with STAR, to ensure
|
||||
// that they are sorted
|
||||
for(int index = CARDS_TO_ADD-1; index >= 0; index--)
|
||||
{
|
||||
if (index == CARDS_TO_ADD-1) {
|
||||
id = db.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
for (int index = CARDS_TO_ADD - 1; index >= 0; index--) {
|
||||
if (index == CARDS_TO_ADD - 1) {
|
||||
id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 1, null);
|
||||
}
|
||||
|
||||
else {
|
||||
id = db.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
} else {
|
||||
id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 0, null);
|
||||
}
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(CARDS_TO_ADD, db.getLoyaltyCardCount());
|
||||
assertEquals(CARDS_TO_ADD, mDb.getLoyaltyCardCount());
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
Cursor cursor = mDb.getLoyaltyCardCursor();
|
||||
assertNotNull(cursor);
|
||||
|
||||
assertEquals(CARDS_TO_ADD, cursor.getCount());
|
||||
|
||||
cursor.moveToFirst();
|
||||
int index = CARDS_TO_ADD-1 ;
|
||||
assertEquals("store"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
|
||||
assertEquals("note"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
|
||||
int index = CARDS_TO_ADD - 1;
|
||||
assertEquals("store" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
|
||||
assertEquals("note" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
|
||||
assertEquals(0, cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY)));
|
||||
assertEquals("0", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE)));
|
||||
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE)));
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals("cardId" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID)));
|
||||
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
|
||||
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
|
||||
@@ -243,14 +231,13 @@ public class DatabaseTest
|
||||
|
||||
cursor.moveToNext();
|
||||
|
||||
for(index = 0; index < CARDS_TO_ADD-1; index++)
|
||||
{
|
||||
assertEquals("store"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
|
||||
assertEquals("note"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
|
||||
for (index = 0; index < CARDS_TO_ADD - 1; index++) {
|
||||
assertEquals("store" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
|
||||
assertEquals("note" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
|
||||
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY)));
|
||||
assertEquals("0", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE)));
|
||||
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE)));
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals("cardId" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID)));
|
||||
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
|
||||
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
|
||||
@@ -264,8 +251,7 @@ public class DatabaseTest
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
private void setupDatabaseVersion1(SQLiteDatabase database)
|
||||
{
|
||||
private void setupDatabaseVersion1(SQLiteDatabase database) {
|
||||
// Delete the tables as they exist now
|
||||
database.execSQL("drop table " + DBHelper.LoyaltyCardDbIds.TABLE);
|
||||
database.execSQL("drop table " + DBHelper.LoyaltyCardDbGroups.TABLE);
|
||||
@@ -281,205 +267,196 @@ public class DatabaseTest
|
||||
}
|
||||
|
||||
private int insertCardVersion1(SQLiteDatabase database,
|
||||
final String store, final String cardId,
|
||||
final String barcodeType)
|
||||
{
|
||||
final String store, final String cardId,
|
||||
final String barcodeType) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(DBHelper.LoyaltyCardDbIds.STORE, store);
|
||||
contentValues.put(DBHelper.LoyaltyCardDbIds.CARD_ID, cardId);
|
||||
contentValues.put(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
|
||||
final long newId = database.insert(DBHelper.LoyaltyCardDbIds.TABLE, null, contentValues);
|
||||
assertTrue(newId != -1);
|
||||
return (int)newId;
|
||||
return (int) newId;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addRemoveOneGroup()
|
||||
{
|
||||
assertEquals(0, db.getGroupCount());
|
||||
long id = db.insertGroup("group one");
|
||||
public void addRemoveOneGroup() {
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
long id = mDb.insertGroup("group one");
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
Group group = db.getGroup("group one");
|
||||
Group group = mDb.getGroup("group one");
|
||||
assertNotNull(group);
|
||||
assertEquals("group one", group._id);
|
||||
|
||||
result = db.deleteGroup("group one");
|
||||
result = mDb.deleteGroup("group one");
|
||||
assertTrue(result);
|
||||
assertEquals(0, db.getGroupCount());
|
||||
assertNull(db.getGroup("group one"));
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
assertNull(mDb.getGroup("group one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGroup()
|
||||
{
|
||||
public void updateGroup() {
|
||||
// Create card
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
// Create group
|
||||
long groupId = db.insertGroup("group one");
|
||||
long groupId = mDb.insertGroup("group one");
|
||||
result = (groupId != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
// Add card to group
|
||||
Group group = db.getGroup("group one");
|
||||
Group group = mDb.getGroup("group one");
|
||||
List<Group> groupList1 = new ArrayList<>();
|
||||
groupList1.add(group);
|
||||
db.setLoyaltyCardGroups(1, groupList1);
|
||||
mDb.setLoyaltyCardGroups(1, groupList1);
|
||||
|
||||
// Ensure the card has one group and the group has one card
|
||||
List<Group> cardGroups = db.getLoyaltyCardGroups((int) id);
|
||||
List<Group> cardGroups = mDb.getLoyaltyCardGroups((int) id);
|
||||
assertEquals(1, cardGroups.size());
|
||||
assertEquals("group one", cardGroups.get(0)._id);
|
||||
assertEquals(1, db.getGroupCardCount("group one"));
|
||||
assertEquals(1, mDb.getGroupCardCount("group one"));
|
||||
|
||||
// Rename group
|
||||
result = db.updateGroup("group one", "group one renamed");
|
||||
result = mDb.updateGroup("group one", "group one renamed");
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
// Group one no longer exists
|
||||
group = db.getGroup("group one");
|
||||
group = mDb.getGroup("group one");
|
||||
assertNull(group);
|
||||
|
||||
// But group one renamed does
|
||||
Group group2 = db.getGroup("group one renamed");
|
||||
Group group2 = mDb.getGroup("group one renamed");
|
||||
assertNotNull(group2);
|
||||
assertEquals("group one renamed", group2._id);
|
||||
|
||||
// And card is in "group one renamed"
|
||||
// Ensure the card has one group and the group has one card
|
||||
cardGroups = db.getLoyaltyCardGroups((int) id);
|
||||
cardGroups = mDb.getLoyaltyCardGroups((int) id);
|
||||
assertEquals(1, cardGroups.size());
|
||||
assertEquals("group one renamed", cardGroups.get(0)._id);
|
||||
assertEquals(1, db.getGroupCardCount("group one renamed"));
|
||||
assertEquals(1, mDb.getGroupCardCount("group one renamed"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateMissingGroup()
|
||||
{
|
||||
assertEquals(0, db.getGroupCount());
|
||||
public void updateMissingGroup() {
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
|
||||
boolean result = db.updateGroup("group one", "new name");
|
||||
boolean result = mDb.updateGroup("group one", "new name");
|
||||
assertEquals(false, result);
|
||||
assertEquals(0, db.getGroupCount());
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyGroupValues()
|
||||
{
|
||||
long id = db.insertGroup("");
|
||||
public void emptyGroupValues() {
|
||||
long id = mDb.insertGroup("");
|
||||
boolean result = (id != -1);
|
||||
assertFalse(result);
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicateGroupName()
|
||||
{
|
||||
assertEquals(0, db.getGroupCount());
|
||||
long id = db.insertGroup("group one");
|
||||
public void duplicateGroupName() {
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
long id = mDb.insertGroup("group one");
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
Group group = db.getGroup("group one");
|
||||
Group group = mDb.getGroup("group one");
|
||||
assertNotNull(group);
|
||||
assertEquals("group one", group._id);
|
||||
|
||||
// Should fail on duplicate
|
||||
long id2 = db.insertGroup("group one");
|
||||
long id2 = mDb.insertGroup("group one");
|
||||
boolean result2 = (id2 != -1);
|
||||
assertFalse(result2);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGroupDuplicate()
|
||||
{
|
||||
long id = db.insertGroup("group one");
|
||||
public void updateGroupDuplicate() {
|
||||
long id = mDb.insertGroup("group one");
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
long id2 = db.insertGroup("group two");
|
||||
long id2 = mDb.insertGroup("group two");
|
||||
boolean result2 = (id2 != -1);
|
||||
assertTrue(result2);
|
||||
assertEquals(2, db.getGroupCount());
|
||||
assertEquals(2, mDb.getGroupCount());
|
||||
|
||||
// Should fail when trying to rename group two to one
|
||||
boolean result3 = db.updateGroup("group two", "group one");
|
||||
boolean result3 = mDb.updateGroup("group two", "group one");
|
||||
assertFalse(result3);
|
||||
assertEquals(2, db.getGroupCount());
|
||||
assertEquals(2, mDb.getGroupCount());
|
||||
|
||||
// Rename failed so both should still be the same
|
||||
Group group = db.getGroup("group one");
|
||||
Group group = mDb.getGroup("group one");
|
||||
assertNotNull(group);
|
||||
assertEquals("group one", group._id);
|
||||
|
||||
Group group2 = db.getGroup("group two");
|
||||
Group group2 = mDb.getGroup("group two");
|
||||
assertNotNull(group2);
|
||||
assertEquals("group two", group2._id);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cardAddAndRemoveGroups()
|
||||
{
|
||||
public void cardAddAndRemoveGroups() {
|
||||
// Create card
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
// Create two groups to only one card
|
||||
assertEquals(0, db.getGroupCount());
|
||||
long gid = db.insertGroup("one");
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
long gid = mDb.insertGroup("one");
|
||||
boolean gresult = (gid != -1);
|
||||
assertTrue(gresult);
|
||||
|
||||
long gid2 = db.insertGroup("two");
|
||||
long gid2 = mDb.insertGroup("two");
|
||||
boolean gresult2 = (gid2 != -1);
|
||||
assertTrue(gresult2);
|
||||
|
||||
assertEquals(2, db.getGroupCount());
|
||||
assertEquals(2, mDb.getGroupCount());
|
||||
|
||||
Group group1 = db.getGroup("one");
|
||||
Group group1 = mDb.getGroup("one");
|
||||
|
||||
// Card has no groups by default
|
||||
List<Group> cardGroups = db.getLoyaltyCardGroups(1);
|
||||
List<Group> cardGroups = mDb.getLoyaltyCardGroups(1);
|
||||
assertEquals(0, cardGroups.size());
|
||||
|
||||
// Add one groups to card
|
||||
List<Group> groupList1 = new ArrayList<>();
|
||||
groupList1.add(group1);
|
||||
db.setLoyaltyCardGroups(1, groupList1);
|
||||
mDb.setLoyaltyCardGroups(1, groupList1);
|
||||
|
||||
List<Group> cardGroups1 = db.getLoyaltyCardGroups(1);
|
||||
List<Group> cardGroups1 = mDb.getLoyaltyCardGroups(1);
|
||||
assertEquals(1, cardGroups1.size());
|
||||
assertEquals(cardGroups1.get(0)._id, group1._id);
|
||||
assertEquals(1, db.getGroupCardCount("one"));
|
||||
assertEquals(0, db.getGroupCardCount("two"));
|
||||
assertEquals(1, mDb.getGroupCardCount("one"));
|
||||
assertEquals(0, mDb.getGroupCardCount("two"));
|
||||
|
||||
// Remove groups
|
||||
db.setLoyaltyCardGroups(1, new ArrayList<Group>());
|
||||
List<Group> cardGroups2 = db.getLoyaltyCardGroups(1);
|
||||
mDb.setLoyaltyCardGroups(1, new ArrayList<Group>());
|
||||
List<Group> cardGroups2 = mDb.getLoyaltyCardGroups(1);
|
||||
assertEquals(0, cardGroups2.size());
|
||||
assertEquals(0, db.getGroupCardCount("one"));
|
||||
assertEquals(0, db.getGroupCardCount("two"));
|
||||
assertEquals(0, mDb.getGroupCardCount("one"));
|
||||
assertEquals(0, mDb.getGroupCardCount("two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void databaseUpgradeFromVersion1()
|
||||
{
|
||||
SQLiteDatabase database = db.getWritableDatabase();
|
||||
public void databaseUpgradeFromVersion1() {
|
||||
SQLiteDatabase database = mDb.getWritableDatabase();
|
||||
|
||||
// Setup the database as it appeared in revision 1
|
||||
setupDatabaseVersion1(database);
|
||||
@@ -489,10 +466,10 @@ public class DatabaseTest
|
||||
int newCardId2 = insertCardVersion1(database, "store", "cardId", "");
|
||||
|
||||
// Upgrade database
|
||||
db.onUpgrade(database, DBHelper.ORIGINAL_DATABASE_VERSION, DBHelper.DATABASE_VERSION);
|
||||
mDb.onUpgrade(database, DBHelper.ORIGINAL_DATABASE_VERSION, DBHelper.DATABASE_VERSION);
|
||||
|
||||
// Determine that the entries are queryable and the fields are correct
|
||||
LoyaltyCard card = db.getLoyaltyCard(newCardId);
|
||||
LoyaltyCard card = mDb.getLoyaltyCard(newCardId);
|
||||
assertEquals("store", card.store);
|
||||
assertEquals("", card.note);
|
||||
assertEquals(null, card.expiry);
|
||||
@@ -503,11 +480,11 @@ public class DatabaseTest
|
||||
assertEquals(BarcodeFormat.UPC_A, card.barcodeType.format());
|
||||
assertEquals(null, card.headerColor);
|
||||
assertEquals(0, card.starStatus);
|
||||
assertEquals(0,card.lastUsed);
|
||||
assertEquals(100,card.zoomLevel);
|
||||
assertEquals(0, card.lastUsed);
|
||||
assertEquals(100, card.zoomLevel);
|
||||
|
||||
// Determine that the entries are queryable and the fields are correct
|
||||
LoyaltyCard card2 = db.getLoyaltyCard(newCardId2);
|
||||
LoyaltyCard card2 = mDb.getLoyaltyCard(newCardId2);
|
||||
assertEquals("store", card2.store);
|
||||
assertEquals("", card2.note);
|
||||
assertEquals(null, card2.expiry);
|
||||
@@ -518,8 +495,8 @@ public class DatabaseTest
|
||||
assertEquals(null, card2.barcodeType); // Empty string should've become null
|
||||
assertEquals(null, card2.headerColor);
|
||||
assertEquals(0, card2.starStatus);
|
||||
assertEquals(0,card2.lastUsed);
|
||||
assertEquals(100,card2.zoomLevel);
|
||||
assertEquals(0, card2.lastUsed);
|
||||
assertEquals(100, card2.zoomLevel);
|
||||
|
||||
database.close();
|
||||
}
|
||||
|
||||
@@ -20,10 +20,8 @@ import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 23)
|
||||
public class ImportExportActivityTest
|
||||
{
|
||||
private void registerIntentHandler(String handler)
|
||||
{
|
||||
public class ImportExportActivityTest {
|
||||
private void registerIntentHandler(String handler) {
|
||||
// Add something that will 'handle' the given intent type
|
||||
PackageManager packageManager = RuntimeEnvironment.application.getPackageManager();
|
||||
|
||||
@@ -39,8 +37,7 @@ public class ImportExportActivityTest
|
||||
|
||||
Intent intent = new Intent(handler);
|
||||
|
||||
if(handler.equals(Intent.ACTION_GET_CONTENT))
|
||||
{
|
||||
if (handler.equals(Intent.ACTION_GET_CONTENT)) {
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
}
|
||||
@@ -48,8 +45,7 @@ public class ImportExportActivityTest
|
||||
shadowOf(packageManager).addResolveInfoForIntent(intent, info);
|
||||
}
|
||||
|
||||
private void checkVisibility(Activity activity, int state, int divider, int title, int message, int button)
|
||||
{
|
||||
private void checkVisibility(Activity activity, int state, int divider, int title, int message, int button) {
|
||||
View dividerView = activity.findViewById(divider);
|
||||
View titleView = activity.findViewById(title);
|
||||
View messageView = activity.findViewById(message);
|
||||
@@ -62,8 +58,7 @@ public class ImportExportActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllOptionsAvailable()
|
||||
{
|
||||
public void testAllOptionsAvailable() {
|
||||
registerIntentHandler(Intent.ACTION_PICK);
|
||||
registerIntentHandler(Intent.ACTION_GET_CONTENT);
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.core.content.res.ResourcesCompat;
|
||||
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
import protect.card_locker.importexport.DataFormat;
|
||||
import protect.card_locker.importexport.ImportExportResult;
|
||||
@@ -894,6 +893,7 @@ public class ImportExportTest {
|
||||
HashMap<Integer, List<Group>> loyaltyCardGroups = new HashMap<>();
|
||||
HashMap<Integer, Bitmap> loyaltyCardFrontImages = new HashMap<>();
|
||||
HashMap<Integer, Bitmap> loyaltyCardBackImages = new HashMap<>();
|
||||
HashMap<Integer, Bitmap> loyaltyCardIconImages = new HashMap<>();
|
||||
|
||||
// Create card 1
|
||||
int loyaltyCardId = (int) db.insertLoyaltyCard("Card 1", "Note 1", new Date(1618053234), new BigDecimal("100"), Currency.getInstance("USD"), "1234", "5432", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE), 1, 0, null);
|
||||
@@ -902,10 +902,12 @@ public class ImportExportTest {
|
||||
List<Group> groups = Arrays.asList(db.getGroup("One"));
|
||||
db.setLoyaltyCardGroups(loyaltyCardId, groups);
|
||||
loyaltyCardGroups.put(loyaltyCardId, groups);
|
||||
Utils.saveCardImage(activity.getApplicationContext(), launcherBitmap, loyaltyCardId, true);
|
||||
Utils.saveCardImage(activity.getApplicationContext(), roundLauncherBitmap, loyaltyCardId, false);
|
||||
Utils.saveCardImage(activity.getApplicationContext(), launcherBitmap, loyaltyCardId, ImageLocationType.front);
|
||||
Utils.saveCardImage(activity.getApplicationContext(), roundLauncherBitmap, loyaltyCardId, ImageLocationType.back);
|
||||
Utils.saveCardImage(activity.getApplicationContext(), launcherBitmap, loyaltyCardId, ImageLocationType.icon);
|
||||
loyaltyCardFrontImages.put(loyaltyCardId, launcherBitmap);
|
||||
loyaltyCardBackImages.put(loyaltyCardId, roundLauncherBitmap);
|
||||
loyaltyCardIconImages.put(loyaltyCardId, launcherBitmap);
|
||||
|
||||
// Create card 2
|
||||
loyaltyCardId = (int) db.insertLoyaltyCard("Card 2", "", null, new BigDecimal(0), null, "123456", null, null, 2, 1, null);
|
||||
@@ -960,8 +962,10 @@ public class ImportExportTest {
|
||||
|
||||
Bitmap expectedFrontImage = loyaltyCardFrontImages.get(loyaltyCardID);
|
||||
Bitmap expectedBackImage = loyaltyCardBackImages.get(loyaltyCardID);
|
||||
Bitmap actualFrontImage = Utils.retrieveCardImage(activity.getApplicationContext(), Utils.getCardImageFileName(loyaltyCardID, true));
|
||||
Bitmap actualBackImage = Utils.retrieveCardImage(activity.getApplicationContext(), Utils.getCardImageFileName(loyaltyCardID, false));
|
||||
Bitmap expectedIconImage = loyaltyCardIconImages.get(loyaltyCardID);
|
||||
Bitmap actualFrontImage = Utils.retrieveCardImage(activity.getApplicationContext(), Utils.getCardImageFileName(loyaltyCardID, ImageLocationType.front));
|
||||
Bitmap actualBackImage = Utils.retrieveCardImage(activity.getApplicationContext(), Utils.getCardImageFileName(loyaltyCardID, ImageLocationType.back));
|
||||
Bitmap actualIconImage = Utils.retrieveCardImage(activity.getApplicationContext(), Utils.getCardImageFileName(loyaltyCardID, ImageLocationType.icon));
|
||||
|
||||
if (expectedFrontImage != null) {
|
||||
assertTrue(expectedFrontImage.sameAs(actualFrontImage));
|
||||
@@ -974,6 +978,12 @@ public class ImportExportTest {
|
||||
} else {
|
||||
assertNull(actualBackImage);
|
||||
}
|
||||
|
||||
if (expectedIconImage != null) {
|
||||
assertTrue(expectedIconImage.sameAs(actualIconImage));
|
||||
} else {
|
||||
assertNull(actualIconImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1041,8 +1051,9 @@ public class ImportExportTest {
|
||||
assertEquals(BarcodeFormat.QR_CODE, card1.barcodeType.format());
|
||||
assertEquals(1, (long) card1.headerColor);
|
||||
assertEquals(0, card1.starStatus);
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card1.id, true));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card1.id, false));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card1.id, ImageLocationType.front));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card1.id, ImageLocationType.back));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card1.id, ImageLocationType.icon));
|
||||
|
||||
LoyaltyCard card8 = db.getLoyaltyCard(8);
|
||||
|
||||
@@ -1056,8 +1067,9 @@ public class ImportExportTest {
|
||||
assertEquals(null, card8.barcodeType);
|
||||
assertEquals(-5317, (long) card8.headerColor);
|
||||
assertEquals(0, card8.starStatus);
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card8.id, true));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card8.id, false));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card8.id, ImageLocationType.front));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card8.id, ImageLocationType.back));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card8.id, ImageLocationType.icon));
|
||||
|
||||
LoyaltyCard card2 = db.getLoyaltyCard(2);
|
||||
|
||||
@@ -1071,8 +1083,9 @@ public class ImportExportTest {
|
||||
assertEquals(null, card2.barcodeType);
|
||||
assertEquals(-9977996, (long) card2.headerColor);
|
||||
assertEquals(0, card2.starStatus);
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card2.id, true));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card2.id, false));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card2.id, ImageLocationType.front));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card2.id, ImageLocationType.back));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card2.id, ImageLocationType.icon));
|
||||
|
||||
LoyaltyCard card3 = db.getLoyaltyCard(3);
|
||||
|
||||
@@ -1086,8 +1099,9 @@ public class ImportExportTest {
|
||||
assertEquals(null, card3.barcodeType);
|
||||
assertEquals(-9977996, (long) card3.headerColor);
|
||||
assertEquals(0, card3.starStatus);
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card3.id, true));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card3.id, false));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card3.id, ImageLocationType.front));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card3.id, ImageLocationType.back));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card3.id, ImageLocationType.icon));
|
||||
|
||||
LoyaltyCard card4 = db.getLoyaltyCard(4);
|
||||
|
||||
@@ -1101,8 +1115,9 @@ public class ImportExportTest {
|
||||
assertEquals(null, card4.barcodeType);
|
||||
assertEquals(-10902850, (long) card4.headerColor);
|
||||
assertEquals(1, card4.starStatus);
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card4.id, true));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card4.id, false));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card4.id, ImageLocationType.front));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card4.id, ImageLocationType.back));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card4.id, ImageLocationType.icon));
|
||||
|
||||
LoyaltyCard card5 = db.getLoyaltyCard(5);
|
||||
|
||||
@@ -1116,8 +1131,9 @@ public class ImportExportTest {
|
||||
assertEquals(BarcodeFormat.CODE_128, card5.barcodeType.format());
|
||||
assertEquals(-10902850, (long) card5.headerColor);
|
||||
assertEquals(0, card5.starStatus);
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card5.id, true));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card5.id, false));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card5.id, ImageLocationType.front));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card5.id, ImageLocationType.back));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card5.id, ImageLocationType.icon));
|
||||
|
||||
LoyaltyCard card6 = db.getLoyaltyCard(6);
|
||||
|
||||
@@ -1131,8 +1147,9 @@ public class ImportExportTest {
|
||||
assertEquals(BarcodeFormat.AZTEC, card6.barcodeType.format());
|
||||
assertEquals(null, card6.headerColor);
|
||||
assertEquals(0, card6.starStatus);
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card6.id, true));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card6.id, false));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card6.id, ImageLocationType.front));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card6.id, ImageLocationType.back));
|
||||
assertEquals(null, Utils.retrieveCardImage(activity.getApplicationContext(), card6.id, ImageLocationType.icon));
|
||||
|
||||
TestHelpers.getEmptyDb(activity);
|
||||
}
|
||||
@@ -1212,8 +1229,9 @@ public class ImportExportTest {
|
||||
assertEquals(BarcodeFormat.EAN_13, card.barcodeType.format());
|
||||
assertEquals(0, card.starStatus);
|
||||
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 1, true));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 1, false));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 1, ImageLocationType.front));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 1, ImageLocationType.back));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 1, ImageLocationType.icon));
|
||||
|
||||
card = db.getLoyaltyCard(2);
|
||||
|
||||
@@ -1227,8 +1245,9 @@ public class ImportExportTest {
|
||||
assertEquals(BarcodeFormat.EAN_13, card.barcodeType.format());
|
||||
assertEquals(0, card.starStatus);
|
||||
|
||||
assertTrue(BitmapFactory.decodeStream(getClass().getResourceAsStream("stocard-front.jpg")).sameAs(Utils.retrieveCardImage(activity.getApplicationContext(), 2, true)));
|
||||
assertTrue(BitmapFactory.decodeStream(getClass().getResourceAsStream("stocard-back.jpg")).sameAs(Utils.retrieveCardImage(activity.getApplicationContext(), 2, false)));
|
||||
assertTrue(BitmapFactory.decodeStream(getClass().getResourceAsStream("stocard-front.jpg")).sameAs(Utils.retrieveCardImage(activity.getApplicationContext(), 2, ImageLocationType.front)));
|
||||
assertTrue(BitmapFactory.decodeStream(getClass().getResourceAsStream("stocard-back.jpg")).sameAs(Utils.retrieveCardImage(activity.getApplicationContext(), 2, ImageLocationType.back)));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 2, ImageLocationType.icon));
|
||||
|
||||
card = db.getLoyaltyCard(3);
|
||||
|
||||
@@ -1243,8 +1262,9 @@ public class ImportExportTest {
|
||||
assertEquals(BarcodeFormat.RSS_EXPANDED, card.barcodeType.format());
|
||||
assertEquals(0, card.starStatus);
|
||||
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 3, true));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 3, false));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 3, ImageLocationType.front));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 3, ImageLocationType.back));
|
||||
assertNull(Utils.retrieveCardImage(activity.getApplicationContext(), 3, ImageLocationType.icon));
|
||||
|
||||
TestHelpers.getEmptyDb(activity);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,7 @@ public class ImportURITest {
|
||||
private DBHelper db;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
public void setUp() {
|
||||
Activity activity = Robolectric.setupActivity(MainActivity.class);
|
||||
importURIHelper = new ImportURIHelper(activity);
|
||||
db = TestHelpers.getEmptyDb(activity);
|
||||
@@ -96,19 +95,17 @@ public class ImportURITest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failToParseInvalidUri()
|
||||
{
|
||||
public void failToParseInvalidUri() {
|
||||
try {
|
||||
importURIHelper.parse(Uri.parse("https://example.com/test"));
|
||||
assertTrue(false); // Shouldn't get here
|
||||
} catch(InvalidObjectException ex) {
|
||||
} catch (InvalidObjectException ex) {
|
||||
// Desired behaviour
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failToParseBadData()
|
||||
{
|
||||
public void failToParseBadData() {
|
||||
String[] urls = new String[3];
|
||||
urls[0] = "https://brarcher.github.io/loyalty-card-locker/share?stare=store¬e=note&cardid=12345&barcodetype=ITF&headercolor=-416706";
|
||||
urls[1] = "https://thelastproject.github.io/Catima/share#stare%3Dstore%26note%3Dnote%26balance%3D0%26cardid%3D12345%26barcodetype%3DITF%26headercolor%3D-416706";
|
||||
|
||||
@@ -33,15 +33,13 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 23)
|
||||
public class LoyaltyCardCursorAdapterTest
|
||||
{
|
||||
public class LoyaltyCardCursorAdapterTest {
|
||||
private Activity activity;
|
||||
private DBHelper db;
|
||||
private SharedPreferences settings;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
public void setUp() {
|
||||
ShadowLog.stream = System.out;
|
||||
|
||||
activity = Robolectric.setupActivity(MainActivity.class);
|
||||
@@ -49,15 +47,13 @@ public class LoyaltyCardCursorAdapterTest
|
||||
settings = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
}
|
||||
|
||||
private void setFontScale(int fontSizeScale)
|
||||
{
|
||||
private void setFontScale(int fontSizeScale) {
|
||||
settings.edit()
|
||||
.putInt(activity.getResources().getString(R.string.settings_key_max_font_size_scale), fontSizeScale)
|
||||
.apply();
|
||||
.putInt(activity.getResources().getString(R.string.settings_key_max_font_size_scale), fontSizeScale)
|
||||
.apply();
|
||||
}
|
||||
|
||||
private View createView(Cursor cursor)
|
||||
{
|
||||
private View createView(Cursor cursor) {
|
||||
LoyaltyCardCursorAdapter adapter = new LoyaltyCardCursorAdapter(activity.getApplicationContext(), cursor, (MainActivity) activity);
|
||||
|
||||
LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder viewHolder = adapter.createViewHolder(activity.findViewById(R.id.list), 0);
|
||||
@@ -66,60 +62,48 @@ public class LoyaltyCardCursorAdapterTest
|
||||
return viewHolder.itemView;
|
||||
}
|
||||
|
||||
private void checkView(final View view, final String store, final String note, final String expiry, final String balance, boolean checkFontSizes)
|
||||
{
|
||||
private void checkView(final View view, final String store, final String note, final String expiry, final String balance, boolean checkFontSizes) {
|
||||
final TextView storeField = view.findViewById(R.id.store);
|
||||
final TextView noteField = view.findViewById(R.id.note);
|
||||
final TextView expiryField = view.findViewById(R.id.expiry);
|
||||
final TextView balanceField = view.findViewById(R.id.balance);
|
||||
|
||||
if(checkFontSizes)
|
||||
{
|
||||
if (checkFontSizes) {
|
||||
Settings preferences = new Settings(activity.getApplicationContext());
|
||||
int mediumFontSize = preferences.getFontSizeMax(preferences.getMediumFont());
|
||||
int smallFontSize = preferences.getFontSizeMax(preferences.getSmallFont());
|
||||
|
||||
assertEquals(mediumFontSize, (int)storeField.getTextSize());
|
||||
assertEquals(smallFontSize, (int)noteField.getTextSize());
|
||||
assertEquals(smallFontSize, (int)expiryField.getTextSize());
|
||||
assertEquals(mediumFontSize, (int) storeField.getTextSize());
|
||||
assertEquals(smallFontSize, (int) noteField.getTextSize());
|
||||
assertEquals(smallFontSize, (int) expiryField.getTextSize());
|
||||
}
|
||||
|
||||
assertEquals(store, storeField.getText().toString());
|
||||
if(!note.isEmpty())
|
||||
{
|
||||
if (!note.isEmpty()) {
|
||||
assertEquals(View.VISIBLE, noteField.getVisibility());
|
||||
assertEquals(note, noteField.getText().toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(View.GONE, noteField.getVisibility());
|
||||
}
|
||||
|
||||
if(!expiry.isEmpty())
|
||||
{
|
||||
if (!expiry.isEmpty()) {
|
||||
assertEquals(View.VISIBLE, expiryField.getVisibility());
|
||||
assertEquals(expiry, expiryField.getText().toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(View.GONE, expiryField.getVisibility());
|
||||
}
|
||||
|
||||
if(!balance.isEmpty())
|
||||
{
|
||||
if (!balance.isEmpty()) {
|
||||
assertEquals(View.VISIBLE, balanceField.getVisibility());
|
||||
assertEquals(balance, balanceField.getText().toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(View.GONE, balanceField.getVisibility());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapterEmptyNote()
|
||||
{
|
||||
public void TestCursorAdapterEmptyNote() {
|
||||
db.insertLoyaltyCard("store", "", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
@@ -128,14 +112,13 @@ public class LoyaltyCardCursorAdapterTest
|
||||
|
||||
View view = createView(cursor);
|
||||
|
||||
checkView(view, card.store, card.note, "", "",false);
|
||||
checkView(view, card.store, card.note, "", "", false);
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapterWithNote()
|
||||
{
|
||||
public void TestCursorAdapterWithNote() {
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
@@ -144,14 +127,13 @@ public class LoyaltyCardCursorAdapterTest
|
||||
|
||||
View view = createView(cursor);
|
||||
|
||||
checkView(view, card.store, card.note, "", "",false);
|
||||
checkView(view, card.store, card.note, "", "", false);
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapterFontSizes()
|
||||
{
|
||||
public void TestCursorAdapterFontSizes() {
|
||||
final Context context = activity.getApplicationContext();
|
||||
Date expiryDate = new Date();
|
||||
String dateString = DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate);
|
||||
@@ -169,14 +151,13 @@ public class LoyaltyCardCursorAdapterTest
|
||||
|
||||
setFontScale(200);
|
||||
view = createView(cursor);
|
||||
checkView(view, card.store, card.note, dateString, "",true);
|
||||
checkView(view, card.store, card.note, dateString, "", true);
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapterStarring()
|
||||
{
|
||||
public void TestCursorAdapterStarring() {
|
||||
assertNotEquals(-1, db.insertLoyaltyCard("storeA", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null));
|
||||
assertNotEquals(-1, db.insertLoyaltyCard("storeB", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 1, null));
|
||||
assertNotEquals(-1, db.insertLoyaltyCard("storeC", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 1, null));
|
||||
@@ -218,8 +199,7 @@ public class LoyaltyCardCursorAdapterTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapter0Points()
|
||||
{
|
||||
public void TestCursorAdapter0Points() {
|
||||
db.insertLoyaltyCard("store", "", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
@@ -228,14 +208,13 @@ public class LoyaltyCardCursorAdapterTest
|
||||
|
||||
View view = createView(cursor);
|
||||
|
||||
checkView(view, card.store, card.note, "", "",false);
|
||||
checkView(view, card.store, card.note, "", "", false);
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapter0EUR()
|
||||
{
|
||||
public void TestCursorAdapter0EUR() {
|
||||
db.insertLoyaltyCard("store", "", null, new BigDecimal("0"), Currency.getInstance("EUR"), "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
@@ -244,14 +223,13 @@ public class LoyaltyCardCursorAdapterTest
|
||||
|
||||
View view = createView(cursor);
|
||||
|
||||
checkView(view, card.store, card.note, "", "",false);
|
||||
checkView(view, card.store, card.note, "", "", false);
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapter100Points()
|
||||
{
|
||||
public void TestCursorAdapter100Points() {
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("100"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
@@ -260,14 +238,13 @@ public class LoyaltyCardCursorAdapterTest
|
||||
|
||||
View view = createView(cursor);
|
||||
|
||||
checkView(view, card.store, card.note, "", "100 points",false);
|
||||
checkView(view, card.store, card.note, "", "100 points", false);
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapter10USD()
|
||||
{
|
||||
public void TestCursorAdapter10USD() {
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("10.00"), Currency.getInstance("USD"), "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), Color.BLACK, 0, null);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
@@ -276,7 +253,7 @@ public class LoyaltyCardCursorAdapterTest
|
||||
|
||||
View view = createView(cursor);
|
||||
|
||||
checkView(view, card.store, card.note, "", "$10.00",false);
|
||||
checkView(view, card.store, card.note, "", "$10.00", false);
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@@ -67,32 +67,28 @@ import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 23)
|
||||
public class LoyaltyCardViewActivityTest
|
||||
{
|
||||
public class LoyaltyCardViewActivityTest {
|
||||
private final String BARCODE_DATA = "428311627547";
|
||||
private final CatimaBarcode BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A);
|
||||
|
||||
private final String EAN_BARCODE_DATA = "4763705295336";
|
||||
private final CatimaBarcode EAN_BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.EAN_13);
|
||||
|
||||
enum ViewMode
|
||||
{
|
||||
enum ViewMode {
|
||||
ADD_CARD,
|
||||
VIEW_CARD,
|
||||
UPDATE_CARD,
|
||||
;
|
||||
}
|
||||
|
||||
enum FieldTypeView
|
||||
{
|
||||
enum FieldTypeView {
|
||||
TextView,
|
||||
TextInputLayout,
|
||||
ImageView
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
public void setUp() {
|
||||
// Output logs emitted during tests so they may be accessed
|
||||
ShadowLog.stream = System.out;
|
||||
}
|
||||
@@ -100,8 +96,7 @@ public class LoyaltyCardViewActivityTest
|
||||
/**
|
||||
* Register a handler in the package manager for a image capture intent
|
||||
*/
|
||||
private void registerMediaStoreIntentHandler()
|
||||
{
|
||||
private void registerMediaStoreIntentHandler() {
|
||||
// Add something that will 'handle' the media capture intent
|
||||
PackageManager packageManager = RuntimeEnvironment.application.getPackageManager();
|
||||
|
||||
@@ -133,12 +128,9 @@ public class LoyaltyCardViewActivityTest
|
||||
final String barcodeType,
|
||||
boolean creatingNewCard) throws ParseException {
|
||||
DBHelper db = new DBHelper(activity);
|
||||
if(creatingNewCard)
|
||||
{
|
||||
if (creatingNewCard) {
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
}
|
||||
|
||||
@@ -172,43 +164,31 @@ public class LoyaltyCardViewActivityTest
|
||||
assertEquals(balance, card.balance);
|
||||
|
||||
// The special "Never" string shouldn't actually be written to the loyalty card
|
||||
if(expiry.equals(activity.getApplicationContext().getString(R.string.never)))
|
||||
{
|
||||
if (expiry.equals(activity.getApplicationContext().getString(R.string.never))) {
|
||||
assertEquals(null, card.expiry);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(DateFormat.getDateInstance().parse(expiry), card.expiry);
|
||||
}
|
||||
|
||||
// The special "Points" string shouldn't actually be written to the loyalty card
|
||||
if(balanceType.equals(activity.getApplicationContext().getString(R.string.points)))
|
||||
{
|
||||
if (balanceType.equals(activity.getApplicationContext().getString(R.string.points))) {
|
||||
assertEquals(null, card.balanceType);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(Currency.getInstance(balanceType), card.balanceType);
|
||||
}
|
||||
assertEquals(cardId, card.cardId);
|
||||
|
||||
// The special "Same as barcode ID" string shouldn't actually be written to the loyalty card
|
||||
if(barcodeId.equals(activity.getApplicationContext().getString(R.string.sameAsCardId)))
|
||||
{
|
||||
if (barcodeId.equals(activity.getApplicationContext().getString(R.string.sameAsCardId))) {
|
||||
assertEquals(null, card.barcodeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(barcodeId, card.barcodeId);
|
||||
}
|
||||
|
||||
// The special "No barcode" string shouldn't actually be written to the loyalty card
|
||||
if(barcodeType.equals(activity.getApplicationContext().getString(R.string.noBarcode)))
|
||||
{
|
||||
if (barcodeType.equals(activity.getApplicationContext().getString(R.string.noBarcode))) {
|
||||
assertEquals(null, card.barcodeType);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(CatimaBarcode.fromName(barcodeType).format(), card.barcodeType.format());
|
||||
}
|
||||
assertNotNull(card.headerColor);
|
||||
@@ -220,8 +200,7 @@ public class LoyaltyCardViewActivityTest
|
||||
* Initiate and complete a barcode capture, either in success
|
||||
* or in failure
|
||||
*/
|
||||
private void captureBarcodeWithResult(final Activity activity, final boolean success) throws IOException
|
||||
{
|
||||
private void captureBarcodeWithResult(final Activity activity, final boolean success) throws IOException {
|
||||
// Start image capture
|
||||
final Button startButton = activity.findViewById(R.id.enterButton);
|
||||
startButton.performClick();
|
||||
@@ -252,8 +231,7 @@ public class LoyaltyCardViewActivityTest
|
||||
* Initiate and complete a barcode selection, either in success
|
||||
* or in failure
|
||||
*/
|
||||
private void selectBarcodeWithResult(final Activity activity, final String barcodeData, final String barcodeType, final boolean success) throws IOException
|
||||
{
|
||||
private void selectBarcodeWithResult(final Activity activity, final String barcodeData, final String barcodeType, final boolean success) throws IOException {
|
||||
// Start barcode selector
|
||||
final Button startButton = activity.findViewById(R.id.enterButton);
|
||||
startButton.performClick();
|
||||
@@ -263,11 +241,6 @@ public class LoyaltyCardViewActivityTest
|
||||
assertNotNull(intent);
|
||||
assertEquals(intent.getComponent().getClassName(), ScanActivity.class.getCanonicalName());
|
||||
|
||||
Activity newActivity = Robolectric.buildActivity(ScanActivity.class, intent).create().get();
|
||||
|
||||
final Button manualButton = newActivity.findViewById(R.id.add_manually);
|
||||
manualButton.performClick();
|
||||
|
||||
intentForResult = shadowOf(activity).peekNextStartedActivityForResult();
|
||||
assertNotNull(intentForResult);
|
||||
|
||||
@@ -291,8 +264,7 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
private void checkFieldProperties(final Activity activity, final int id, final int visibility,
|
||||
final Object contents, final FieldTypeView fieldType)
|
||||
{
|
||||
final Object contents, final FieldTypeView fieldType) {
|
||||
final View view = activity.findViewById(id);
|
||||
assertNotNull(view);
|
||||
assertEquals(visibility, view.getVisibility());
|
||||
@@ -320,14 +292,10 @@ public class LoyaltyCardViewActivityTest
|
||||
final String balanceString, final String balanceTypeString,
|
||||
final String cardId, final String barcodeId,
|
||||
final String barcodeType, final Bitmap frontImage,
|
||||
final Bitmap backImage)
|
||||
{
|
||||
if(mode == ViewMode.VIEW_CARD)
|
||||
{
|
||||
final Bitmap backImage) {
|
||||
if (mode == ViewMode.VIEW_CARD) {
|
||||
checkFieldProperties(activity, R.id.cardIdView, View.VISIBLE, cardId, FieldTypeView.TextView);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
int editVisibility = View.VISIBLE;
|
||||
|
||||
checkFieldProperties(activity, R.id.storeNameEdit, editVisibility, store, FieldTypeView.TextView);
|
||||
@@ -345,11 +313,10 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noDataLossOnResumeOrRotate()
|
||||
{
|
||||
public void noDataLossOnResumeOrRotate() {
|
||||
registerMediaStoreIntentHandler();
|
||||
|
||||
for(boolean newCard : new boolean[] {false, true}) {
|
||||
for (boolean newCard : new boolean[]{false, true}) {
|
||||
System.out.println();
|
||||
System.out.println("=====");
|
||||
System.out.println("New card? " + newCard);
|
||||
@@ -364,7 +331,7 @@ public class LoyaltyCardViewActivityTest
|
||||
activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
|
||||
}
|
||||
|
||||
Activity activity = (Activity) activityController.get();
|
||||
LoyaltyCardEditActivity activity = (LoyaltyCardEditActivity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -406,8 +373,8 @@ public class LoyaltyCardViewActivityTest
|
||||
cardIdField.setText("12345678");
|
||||
barcodeField.setText("87654321");
|
||||
barcodeTypeField.setText(CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName());
|
||||
LoyaltyCardEditActivity.setCardImage(frontImageView, frontBitmap);
|
||||
LoyaltyCardEditActivity.setCardImage(backImageView, backBitmap);
|
||||
activity.setCardImage(frontImageView, frontBitmap, true);
|
||||
activity.setCardImage(backImageView, backBitmap, true);
|
||||
|
||||
shadowOf(getMainLooper()).idle();
|
||||
|
||||
@@ -442,29 +409,27 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutParametersCheckFieldsAvailable()
|
||||
{
|
||||
public void startWithoutParametersCheckFieldsAvailable() {
|
||||
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never) , "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null);
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutParametersCannotCreateLoyaltyCard()
|
||||
{
|
||||
public void startWithoutParametersCannotCreateLoyaltyCard() {
|
||||
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
|
||||
Activity activity = (Activity) activityController.get();
|
||||
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
|
||||
@@ -486,14 +451,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutParametersBack()
|
||||
{
|
||||
public void startWithoutParametersBack() {
|
||||
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
|
||||
assertEquals(false, activity.isFinishing());
|
||||
shadowOf(activity).clickMenuItem(android.R.id.home);
|
||||
@@ -509,13 +473,14 @@ public class LoyaltyCardViewActivityTest
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null);
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
|
||||
|
||||
// Complete barcode capture successfully
|
||||
captureBarcodeWithResult(activity, true);
|
||||
activityController.resume();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), BARCODE_TYPE.prettyName(), null, null);
|
||||
|
||||
@@ -526,29 +491,28 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutParametersCaptureBarcodeFailure() throws IOException
|
||||
{
|
||||
public void startWithoutParametersCaptureBarcodeFailure() throws IOException {
|
||||
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
|
||||
|
||||
// Complete barcode capture in failure
|
||||
captureBarcodeWithResult(activity, false);
|
||||
activityController.resume();
|
||||
|
||||
shadowOf(getMainLooper()).idle();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null);
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutParametersCaptureBarcodeCancel() throws IOException
|
||||
{
|
||||
public void startWithoutParametersCaptureBarcodeCancel() throws IOException {
|
||||
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -557,10 +521,11 @@ public class LoyaltyCardViewActivityTest
|
||||
LoyaltyCardEditActivity activity = (LoyaltyCardEditActivity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null);
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
|
||||
|
||||
// Complete barcode capture successfully
|
||||
captureBarcodeWithResult(activity, true);
|
||||
activityController.resume();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), BARCODE_TYPE.prettyName(), null, null);
|
||||
|
||||
@@ -580,21 +545,17 @@ public class LoyaltyCardViewActivityTest
|
||||
assertEquals(true, activity.isFinishing());
|
||||
}
|
||||
|
||||
private ActivityController createActivityWithLoyaltyCard(boolean editMode)
|
||||
{
|
||||
private ActivityController createActivityWithLoyaltyCard(boolean editMode) {
|
||||
Intent intent = new Intent();
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putInt("id", 1);
|
||||
|
||||
Class clazz;
|
||||
|
||||
if(editMode)
|
||||
{
|
||||
if (editMode) {
|
||||
bundle.putBoolean("update", true);
|
||||
clazz = LoyaltyCardEditActivity.class;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
bundle.putBoolean("view", true);
|
||||
clazz = LoyaltyCardViewActivity.class;
|
||||
}
|
||||
@@ -605,10 +566,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardEditModeCheckDisplay() throws IOException
|
||||
{
|
||||
public void startWithLoyaltyCardEditModeCheckDisplay() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -624,10 +584,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardViewModeCheckDisplay() throws IOException
|
||||
{
|
||||
public void startWithLoyaltyCardViewModeCheckDisplay() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -643,10 +602,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardWithBarcodeUpdateBarcode() throws IOException
|
||||
{
|
||||
public void startWithLoyaltyCardWithBarcodeUpdateBarcode() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -660,6 +618,7 @@ public class LoyaltyCardViewActivityTest
|
||||
|
||||
// Complete barcode capture successfully
|
||||
captureBarcodeWithResult(activity, true);
|
||||
activityController.resume();
|
||||
|
||||
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), BARCODE_TYPE.prettyName(), null, null);
|
||||
|
||||
@@ -667,8 +626,7 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardWithReceiptUpdateReceiptCancel() throws IOException
|
||||
{
|
||||
public void startWithLoyaltyCardWithReceiptUpdateReceiptCancel() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
LoyaltyCardEditActivity activity = (LoyaltyCardEditActivity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
@@ -684,6 +642,7 @@ public class LoyaltyCardViewActivityTest
|
||||
|
||||
// Complete barcode capture successfully
|
||||
captureBarcodeWithResult(activity, true);
|
||||
activityController.resume();
|
||||
|
||||
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), BARCODE_TYPE.prettyName(), null, null);
|
||||
|
||||
@@ -705,10 +664,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardNoExpirySetExpiry() throws IOException
|
||||
{
|
||||
public void startWithLoyaltyCardNoExpirySetExpiry() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -738,10 +696,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardExpirySetNoExpiry() throws IOException
|
||||
{
|
||||
public void startWithLoyaltyCardExpirySetNoExpiry() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -763,10 +720,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardNoBalanceSetBalance() throws IOException
|
||||
{
|
||||
public void startWithLoyaltyCardNoBalanceSetBalance() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -814,10 +770,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardBalanceSetNoBalance() throws IOException
|
||||
{
|
||||
public void startWithLoyaltyCardBalanceSetNoBalance() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -855,10 +810,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardSameAsCardIDUpdateBarcodeID()
|
||||
{
|
||||
public void startWithLoyaltyCardSameAsCardIDUpdateBarcodeID() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -887,10 +841,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardSameAsCardIDUpdateCardID()
|
||||
{
|
||||
public void startWithLoyaltyCardSameAsCardIDUpdateCardID() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -921,10 +874,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDUpdate()
|
||||
{
|
||||
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDUpdate() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -958,10 +910,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDDoNotUpdate()
|
||||
{
|
||||
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDDoNotUpdate() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -995,10 +946,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkMenu() throws IOException
|
||||
{
|
||||
public void checkMenu() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
|
||||
@@ -1023,10 +973,9 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithMissingLoyaltyCard() throws IOException
|
||||
{
|
||||
public void startWithMissingLoyaltyCard() throws IOException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -1043,11 +992,10 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutParametersViewBack()
|
||||
{
|
||||
public void startWithoutParametersViewBack() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
|
||||
|
||||
@@ -1063,11 +1011,10 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutColors()
|
||||
{
|
||||
public void startWithoutColors() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, null, 0, null);
|
||||
|
||||
@@ -1086,7 +1033,7 @@ public class LoyaltyCardViewActivityTest
|
||||
public void startLoyaltyCardWithoutColorsSave() throws IOException, ParseException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, null, 0, null);
|
||||
|
||||
@@ -1104,7 +1051,7 @@ public class LoyaltyCardViewActivityTest
|
||||
public void startLoyaltyCardWithExplicitNoBarcodeSave() throws IOException, ParseException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, null, Color.BLACK, 0, null);
|
||||
|
||||
@@ -1121,7 +1068,7 @@ public class LoyaltyCardViewActivityTest
|
||||
@Test
|
||||
public void removeBarcodeFromLoyaltyCard() throws IOException, ParseException {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
|
||||
@@ -1136,6 +1083,7 @@ public class LoyaltyCardViewActivityTest
|
||||
|
||||
// Complete empty barcode selection successfully
|
||||
selectBarcodeWithResult(activity, BARCODE_DATA, "", true);
|
||||
activityController.resume();
|
||||
|
||||
// Check if the barcode type is NO_BARCODE as expected
|
||||
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);
|
||||
@@ -1148,11 +1096,10 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startCheckFontSizes()
|
||||
{
|
||||
public void startCheckFontSizes() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
|
||||
|
||||
@@ -1160,8 +1107,8 @@ public class LoyaltyCardViewActivityTest
|
||||
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
settings.edit()
|
||||
.putInt(activity.getResources().getString(R.string.settings_key_max_font_size_scale), 100)
|
||||
.apply();
|
||||
.putInt(activity.getResources().getString(R.string.settings_key_max_font_size_scale), 100)
|
||||
.apply();
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -1183,13 +1130,11 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkScreenOrientationLockSetting()
|
||||
{
|
||||
for(boolean locked : new boolean[] {false, true})
|
||||
{
|
||||
public void checkScreenOrientationLockSetting() {
|
||||
for (boolean locked : new boolean[]{false, true}) {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
|
||||
|
||||
@@ -1206,12 +1151,9 @@ public class LoyaltyCardViewActivityTest
|
||||
|
||||
MenuItem item = shadowOf(activity).getOptionsMenu().findItem(R.id.action_lock_unlock);
|
||||
|
||||
if(locked)
|
||||
{
|
||||
if (locked) {
|
||||
assertEquals(item.isVisible(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assertEquals(item.isVisible(), true);
|
||||
String title = item.getTitle().toString();
|
||||
assertEquals(title, activity.getString(R.string.lockScreen));
|
||||
@@ -1222,8 +1164,7 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkPushStarIcon()
|
||||
{
|
||||
public void checkPushStarIcon() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity) activityController.get();
|
||||
@@ -1257,11 +1198,10 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBarcodeFullscreenWorkflow()
|
||||
{
|
||||
public void checkBarcodeFullscreenWorkflow() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null);
|
||||
|
||||
@@ -1363,11 +1303,10 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkNoBarcodeFullscreenWorkflow()
|
||||
{
|
||||
public void checkNoBarcodeFullscreenWorkflow() {
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = TestHelpers.getEmptyDb(activity);
|
||||
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, BARCODE_DATA, null, null, Color.BLACK, 0, null);
|
||||
|
||||
@@ -1407,11 +1346,10 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importCard()
|
||||
{
|
||||
public void importCard() {
|
||||
Date date = new Date();
|
||||
|
||||
Uri importUri = Uri.parse("https://thelastproject.github.io/Catima/share?store=Example%20Store¬e=&expiry=" + date.getTime() + "&balance=10&balancetype=USD&cardid=123456&barcodetype=AZTEC&headercolor=-416706&headertextcolor=-1");
|
||||
Uri importUri = Uri.parse("https://catima.app/share#store%3DExample%2BStore%26note%3D%26expiry%3D" + date.getTime() + "%26balance%3D10.00%26balancetype%3DUSD%26cardid%3D123456%26barcodetype%3DAZTEC%26headercolor%3D-416706");
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setData(importUri);
|
||||
@@ -1422,7 +1360,7 @@ public class LoyaltyCardViewActivityTest
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
|
||||
shadowOf(getMainLooper()).idle();
|
||||
@@ -1432,8 +1370,7 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importCardOldURL()
|
||||
{
|
||||
public void importCardOldFormat() {
|
||||
Uri importUri = Uri.parse("https://brarcher.github.io/loyalty-card-locker/share?store=Example%20Store¬e=&cardid=123456&barcodetype=AZTEC&headercolor=-416706&headertextcolor=-1");
|
||||
|
||||
Intent intent = new Intent();
|
||||
@@ -1445,7 +1382,7 @@ public class LoyaltyCardViewActivityTest
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
final Context context = activity.getApplicationContext();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "Example Store", "", context.getString(R.string.never), "0", context.getString(R.string.points), "123456", context.getString(R.string.sameAsCardId), "Aztec", null, null);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user