Compare commits

...

53 Commits

Author SHA1 Message Date
Sylvia van Os
c86cc22a93 Release v2.1.0 2021-08-01 21:00:12 +02:00
Sylvia van Os
765577ae9e Merge pull request #306 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-01 20:50:42 +02:00
Heimen Stoffels
d1d15644b5 Translated using Weblate (Dutch)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-01 20:36:29 +02:00
Sylvia van Os
5d41b213db Remove translations to break lint 2021-08-01 20:36:17 +02:00
Sylvia van Os
aa515b1192 Be more explicit in quantity
Translators still keep triggering the linter with errors such as the
following:
Error: The quantity 'one' matches more than one specific number in this locale (1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …), but the message did not include a formatting argument (such as %d). This is usually an internationalization error. See full issue explanation for more. [ImpliedQuantity]
2021-08-01 12:50:56 +02:00
Sylvia van Os
068660fe3f Merge pull request #305 from weblate/weblate-catima-catima
Translations update from Weblate
2021-08-01 12:42:14 +02:00
solokot
99ffaf97d1 Translated using Weblate (Russian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-08-01 12:32:51 +02:00
Heimen Stoffels
b53999c1cf Translated using Weblate (Dutch)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-08-01 12:32:51 +02:00
Allan Nordhøy
57f87d7dc0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 90.6% (156 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-08-01 12:32:50 +02:00
J. Lavoie
760f6a873d Translated using Weblate (Italian)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/it/
2021-08-01 12:32:50 +02:00
J. Lavoie
675bd43ff8 Translated using Weblate (French)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/fr/
2021-08-01 12:32:50 +02:00
J. Lavoie
07532ce001 Translated using Weblate (Spanish)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2021-08-01 12:32:50 +02:00
J. Lavoie
908a7055c7 Translated using Weblate (German)
Currently translated at 100.0% (172 of 172 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/de/
2021-08-01 12:32:49 +02:00
Sylvia van Os
2be371caed Forgot number 2021-07-30 19:46:10 +02:00
Sylvia van Os
f4f3f2e307 Increase i18n flexibility
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". So while in English the extra non-plural form seems unnecessary duplication, it is necessary to give translators enough flexibility. Therefore, we use the plain string when meaning exactly 1, and otherwise use the plural forms.
2021-07-30 19:40:43 +02:00
Sylvia van Os
edbf76c7dc Merge pull request #303 from weblate/weblate-catima-catima
Translations update from Weblate
2021-07-30 19:02:48 +02:00
109247019824
f8615f45f0 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/bg/
2021-07-30 18:18:55 +02:00
IllusiveMan196
c3bc3e9911 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/uk/
2021-07-30 18:18:55 +02:00
solokot
8adcca1df2 Translated using Weblate (Russian)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-07-30 18:18:55 +02:00
Heimen Stoffels
bdde8669ac Translated using Weblate (Dutch)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-07-30 18:18:55 +02:00
solokot
59db2df525 Translated using Weblate (Russian)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/ru/
2021-07-30 18:18:55 +02:00
Sylvia van Os
3b83ff5b0e Fix syntax 2021-07-30 18:18:32 +02:00
Heimen Stoffels
19fb290a51 Translated using Weblate (Dutch)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nl/
2021-07-30 18:15:39 +02:00
Allan Nordhøy
e1e823d9e0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 90.0% (153 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/nb_NO/
2021-07-30 18:15:30 +02:00
Sylvia van Os
7ed477b670 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-07-29 22:16:47 +02:00
Sylvia van Os
1960fb0b6a Fix fullscreen loss on rotation 2021-07-29 22:16:36 +02:00
Sylvia van Os
e913482790 Merge pull request #299 from comradekingu/patch-7
New strings reworked
2021-07-29 21:54:43 +02:00
Allan Nordhøy
2e5bd76d31 New strings reworked 2021-07-29 19:47:10 +00:00
Sylvia van Os
876ae979da Simplify updateTempState
Hopefully fixes the few weird crashes on Google Play
2021-07-29 21:42:21 +02:00
Sylvia van Os
d918c15ad6 Prevent ArithmeticException 2021-07-29 21:18:21 +02:00
Sylvia van Os
d57cb307c3 Support multi-deleting cards 2021-07-29 20:38:37 +02:00
Sylvia van Os
cbcf1bcd99 Use desugaring to upgrade zxing without having to increase minSdk
As documented by the zxing team on https://github.com/zxing/zxing/wiki/Frequently-Asked-Questions#it-doesnt-work-with-java-7--no-interface-method-sortljavautilcomparator
2021-07-28 23:05:27 +02:00
Sylvia van Os
96bc10583f Fix colour dialog selected colour 2021-07-27 22:04:09 +02:00
Sylvia van Os
5ca4d29a36 Release Catima 2.0.4 2021-07-27 21:42:04 +02:00
Sylvia van Os
2efb666fae Fix loyalty card colour changing 2021-07-27 21:38:54 +02:00
Sylvia van Os
89dce1068f Shortcut fixes 2021-07-27 21:26:24 +02:00
Sylvia van Os
9854125af9 Make lint happy 2021-07-26 23:37:17 +02:00
Sylvia van Os
6e307ab1f0 Update dependencies 2021-07-26 23:10:51 +02:00
Sylvia van Os
c4f0d1bef6 Release Catima 2.0.3 2021-07-25 22:32:40 +02:00
Sylvia van Os
5201788818 Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-07-25 21:52:10 +02:00
Sylvia van Os
8472bc9755 Make SpotBugs happy 2021-07-25 21:51:46 +02:00
Sylvia van Os
ce0f531831 Merge pull request #289 from weblate/weblate-catima-catima
Translations update from Weblate
2021-07-25 21:41:26 +02:00
Quentin PAGÈS
18e9c3ccb5 Translated using Weblate (Occitan)
Currently translated at 32.3% (55 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/oc/
2021-07-25 21:40:25 +02:00
Sylvia van Os
19afe8e69c Simplify edit activity and fix some status bugs 2021-07-25 21:40:15 +02:00
Sylvia van Os
8e5bace7cc Merge branch 'master' of github.com:TheLastProject/loyalty-card-locker 2021-07-23 23:52:58 +02:00
Sylvia van Os
1ca85e9d7b Create unit test for broken onResume behaviour 2021-07-23 23:52:45 +02:00
Sylvia van Os
eb24af8266 Add Zip4j to used libraries list 2021-07-22 12:14:39 +02:00
Sylvia van Os
12ba01eb87 Merge pull request #287 from weblate/weblate-catima-catima
Translations update from Weblate
2021-07-21 23:32:51 +02:00
Quentin PAGÈS
a0e30bdccc Added translation using Weblate (Occitan) 2021-07-21 23:26:38 +02:00
Sylvia van Os
4663e22128 Rename Spanish metadata to something fastlane supply can push to Google Play 2021-07-21 18:42:27 +02:00
Sylvia van Os
7bd1d16d24 Merge pull request #286 from weblate/weblate-catima-catima
Translations update from Weblate
2021-07-21 18:37:32 +02:00
Diego
fd838cfd43 Translated using Weblate (Spanish)
Currently translated at 100.0% (3 of 3 strings)

Translation: Catima/Fastlane
Translate-URL: https://hosted.weblate.org/projects/catima/fastlane/es/
2021-07-21 18:32:48 +02:00
Diego
1eca79b4cb Translated using Weblate (Spanish)
Currently translated at 100.0% (170 of 170 strings)

Translation: Catima/Catima
Translate-URL: https://hosted.weblate.org/projects/catima/catima/es/
2021-07-21 18:32:48 +02:00
49 changed files with 876 additions and 457 deletions

View File

@@ -1,5 +1,34 @@
# Changelog
## v2.1.0 (2021-08-01)
Changes:
- Fix selected colour in colour changing dialog
- Support for deleting multiple cards at once
- Fix possible ArithmeticException when resizing image
- Fix fullscreen is closed when rotating device
## v2.0.4 (2021-07-27)
Changes:
- Fix shortcut creation
- Generate card-specific shortcut icon
- Fix ability to change loyalty card colour
## v2.0.3 (2021-07-25)
Changes:
- Fix loading photos when editing existing card
## v2.0.2 (2021-07-25)
Changes:
- Fix inability to configure photos in new loyalty card
## v2.0.1 (2021-07-21)
Changes:

View File

@@ -18,10 +18,11 @@ android {
applicationId "me.hackerchick.catima"
minSdkVersion 19
targetSdkVersion 30
versionCode 71
versionName "2.0.1"
versionCode 75
versionName "2.1.0"
vectorDrawables.useSupportLibrary true
multiDexEnabled true
}
buildTypes {
@@ -38,6 +39,10 @@ android {
compileOptions {
encoding "UTF-8"
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
@@ -69,17 +74,16 @@ android {
dependencies {
// AndroidX
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
// Third-party
implementation 'com.journeyapps:zxing-android-embedded:4.1.0@aar'
// Do not upgrade past 3.3.3! Causes a crash on versions before Android Nougat
//noinspection GradleDependency
implementation 'com.google.zxing:core:3.3.3'
implementation 'com.google.zxing:core:3.4.1'
implementation 'org.apache.commons:commons-csv:1.8'
implementation 'com.jaredrummler:colorpicker:1.1.0'
implementation 'com.google.guava:guava:30.1.1-jre'
@@ -90,7 +94,7 @@ dependencies {
implementation 'io.wcm.tooling.spotbugs:io.wcm.tooling.spotbugs.annotations:1.0.0'
// Testing
testImplementation 'androidx.test:core:1.3.0'
testImplementation 'androidx.test:core:1.4.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.4'
}

View File

@@ -35,12 +35,13 @@ public class AboutActivity extends AppCompatActivity
}
final List<ThirdPartyInfo> USED_LIBRARIES = new ArrayList<>();
USED_LIBRARIES.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("Commons CSV", "https://commons.apache.org/proper/commons-csv/", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("Guava", "https://github.com/google/guava", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("NumberPickerPreference", "https://github.com/invissvenska/NumberPickerPreference", "GNU LGPL 3.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("Zip4j", "https://github.com/srikanth-lingala/zip4j", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("ZXing", "https://github.com/zxing/zxing", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0"));
USED_LIBRARIES.add(new ThirdPartyInfo("NumberPickerPreference", "https://github.com/invissvenska/NumberPickerPreference", "GNU LGPL 3.0"));
final List<ThirdPartyInfo> USED_ASSETS = new ArrayList<>();
USED_ASSETS.add(new ThirdPartyInfo("Android icons", "https://fonts.google.com/icons?selected=Material+Icons", "Apache 2.0"));
@@ -104,4 +105,4 @@ public class AboutActivity extends AppCompatActivity
return super.onOptionsItemSelected(item);
}
}
}

View File

@@ -2,8 +2,8 @@ package protect.card_locker;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
@@ -12,6 +12,8 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
@@ -47,6 +49,11 @@ public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyC
}
final RecyclerView cardList = findViewById(R.id.list);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
cardList.setLayoutManager(mLayoutManager);
cardList.setItemAnimator(new DefaultItemAnimator());
cardList.setVisibility(View.VISIBLE);
Cursor cardCursor = db.getLoyaltyCardCursor();
@@ -72,11 +79,12 @@ public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyC
bundle.putBoolean("view", true);
shortcutIntent.putExtras(bundle);
Parcelable icon = Intent.ShortcutIconResource.fromContext(CardShortcutConfigure.this, R.mipmap.ic_launcher);
Bitmap iconBitmap = Utils.generateIcon(CardShortcutConfigure.this, loyaltyCard, true).getLetterTile();
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, loyaltyCard.store);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, iconBitmap);
setResult(RESULT_OK, intent);
finish();

View File

@@ -220,23 +220,20 @@ public class ImportExportActivity extends AppCompatActivity
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
{
if(requestCode == PERMISSIONS_EXTERNAL_STORAGE)
{
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_EXTERNAL_STORAGE) {
// If request is cancelled, the result arrays are empty.
boolean success = grantResults.length > 0;
for(int grant : grantResults)
{
if(grant != PackageManager.PERMISSION_GRANTED)
{
for (int grant : grantResults) {
if (grant != PackageManager.PERMISSION_GRANTED) {
success = false;
}
}
if(!success)
{
if (!success) {
// External storage permission rejected, inform user that
// import/export is prevented
Toast.makeText(getApplicationContext(), R.string.noExternalStoragePermissionError,

View File

@@ -11,7 +11,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import protect.card_locker.importexport.DataFormat;

View File

@@ -10,8 +10,7 @@ import java.util.Date;
import androidx.annotation.Nullable;
public class LoyaltyCard
{
public class LoyaltyCard {
public final int id;
public final String store;
public final String note;

View File

@@ -4,6 +4,7 @@ import android.Manifest;
import android.annotation.SuppressLint;
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;
@@ -49,6 +50,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.ArrayList;
@@ -61,6 +63,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
@@ -121,6 +124,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
boolean hasChanged = false;
String tempStoredOldBarcodeValue = null;
boolean initDone = false;
boolean onResuming = false;
AlertDialog confirmExitDialog = null;
boolean validBalance = true;
@@ -130,6 +134,30 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
String tempCameraPicturePath;
LoyaltyCard tempLoyaltyCard;
private static LoyaltyCard updateTempState(LoyaltyCard loyaltyCard, LoyaltyCardField fieldName, Object value) {
return new LoyaltyCard(
(int) (fieldName == LoyaltyCardField.id ? value : loyaltyCard.id),
(String) (fieldName == LoyaltyCardField.store ? value : loyaltyCard.store),
(String) (fieldName == LoyaltyCardField.note ? value : loyaltyCard.note),
(Date) (fieldName == LoyaltyCardField.expiry ? value : loyaltyCard.expiry),
(BigDecimal) (fieldName == LoyaltyCardField.balance ? value : loyaltyCard.balance),
(Currency) (fieldName == LoyaltyCardField.balanceType ? value : loyaltyCard.balanceType),
(String) (fieldName == LoyaltyCardField.cardId ? value : loyaltyCard.cardId),
(String) (fieldName == LoyaltyCardField.barcodeId ? value : loyaltyCard.barcodeId),
(BarcodeFormat) (fieldName == LoyaltyCardField.barcodeType ? value : loyaltyCard.barcodeType),
(Integer) (fieldName == LoyaltyCardField.headerColor ? value : loyaltyCard.headerColor),
(int) (fieldName == LoyaltyCardField.starStatus ? value : loyaltyCard.starStatus)
);
}
private void updateTempState(LoyaltyCardField fieldName, Object value) {
tempLoyaltyCard = updateTempState(tempLoyaltyCard, fieldName, value);
hasChanged = true;
}
private void extractIntentFields(Intent intent)
{
final Bundle b = intent.getExtras();
@@ -161,8 +189,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loyalty_card_edit_activity);
@@ -218,8 +245,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasChanged = true;
updateTempState(LoyaltyCardField.store, s.toString());
generateIcon(s.toString());
}
@@ -227,6 +253,19 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
public void afterTextChanged(Editable s) { }
});
noteFieldEdit.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) {
updateTempState(LoyaltyCardField.note, s.toString());
}
@Override
public void afterTextChanged(Editable s) { }
});
expiryField.addTextChangedListener(new TextWatcher() {
CharSequence lastValue;
@@ -237,17 +276,17 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasChanged = true;
if (s.toString().equals(getString(R.string.never))) {
expiryField.setTag(null);
} else if (s.toString().equals(getString(R.string.chooseExpiryDate))) {
if (!lastValue.toString().equals(getString(R.string.chooseExpiryDate))) {
expiryField.setText(lastValue);
};
DialogFragment datePickerFragment = new DatePickerFragment(expiryField);
}
DialogFragment datePickerFragment = new DatePickerFragment(LoyaltyCardEditActivity.this, expiryField);
datePickerFragment.show(getSupportFragmentManager(), "datePicker");
}
updateTempState(LoyaltyCardField.expiry, expiryField.getTag());
}
@Override
@@ -262,7 +301,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
balanceField.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol((BigDecimal) balanceField.getTag(), (Currency) balanceCurrencyField.getTag()));
balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(tempLoyaltyCard.balance, tempLoyaltyCard.balanceType));
}
});
@@ -272,13 +311,11 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasChanged = true;
try {
BigDecimal balance = Utils.parseCurrency(s.toString(), Utils.currencyHasDecimals((Currency) balanceCurrencyField.getTag()));
BigDecimal balance = Utils.parseCurrency(s.toString(), Utils.currencyHasDecimals(tempLoyaltyCard.balanceType));
updateTempState(LoyaltyCardField.balance, balance);
validBalance = true;
balanceField.setTag(balance);
} catch (NumberFormatException e) {
validBalance = false;
e.printStackTrace();
@@ -295,8 +332,6 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasChanged = true;
Currency currency;
if (s.toString().equals(getString(R.string.points))) {
@@ -305,12 +340,10 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
currency = currencies.get(s.toString());
}
balanceCurrencyField.setTag(currency);
updateTempState(LoyaltyCardField.balanceType, currency);
BigDecimal balance = (BigDecimal) balanceField.getTag();
if (balance != null) {
balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(balance, currency));
if (tempLoyaltyCard.balance != null) {
balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(tempLoyaltyCard.balance, currency));
}
}
@@ -355,29 +388,22 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
cardIdFieldView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (initDone) {
if (initDone && !onResuming) {
if (tempStoredOldBarcodeValue == null) {
// We changed the card ID, save the current barcode ID in a temp
// variable and make sure to ask the user later if they also want to
// update the barcode ID
if (barcodeIdField.getTag() == null) {
// If it is set to "same as Card ID", temp-save the value before the
// Card ID change
tempStoredOldBarcodeValue = s.toString();
} else {
// Otherwise, set the temp value to the current field value
if (tempLoyaltyCard.barcodeId != null) {
// If it is not set to "same as Card ID", save as tempStoredOldBarcodeValue
tempStoredOldBarcodeValue = barcodeIdField.getText().toString();
}
barcodeIdField.setText(tempStoredOldBarcodeValue);
barcodeIdField.setTag(tempStoredOldBarcodeValue);
}
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasChanged = true;
updateTempState(LoyaltyCardField.cardId, s.toString());
}
@Override
@@ -394,14 +420,12 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasChanged = true;
if (s.toString().equals(getString(R.string.sameAsCardId))) {
// If the user manually changes the barcode again make sure we disable the
// request to update it to match the card id (if changed)
tempStoredOldBarcodeValue = null;
barcodeIdField.setTag(null);
updateTempState(LoyaltyCardField.barcodeId, null);
} else if (s.toString().equals(getString(R.string.setBarcodeId))) {
if (!lastValue.toString().equals(getString(R.string.setBarcodeId))) {
barcodeIdField.setText(lastValue);
@@ -411,8 +435,8 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
builder.setTitle(R.string.setBarcodeId);
final EditText input = new EditText(LoyaltyCardEditActivity.this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
if (barcodeIdField.getTag() != null) {
input.setText((String) barcodeIdField.getTag());
if (tempLoyaltyCard.barcodeId != null) {
input.setText(tempLoyaltyCard.barcodeId);
}
builder.setView(input);
@@ -421,7 +445,6 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
// request to update it to match the card id (if changed)
tempStoredOldBarcodeValue = null;
barcodeIdField.setTag(input.getText().toString());
barcodeIdField.setText(input.getText());
});
builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel());
@@ -429,6 +452,8 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
dialog.show();
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
input.requestFocus();
} else {
updateTempState(LoyaltyCardField.barcodeId, s.toString());
}
generateOrHideBarcode();
@@ -450,16 +475,14 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasChanged = true;
if (!s.toString().isEmpty()) {
if (s.toString().equals(getString(R.string.noBarcode))) {
barcodeTypeField.setTag(null);
updateTempState(LoyaltyCardField.barcodeType, null);
} else {
try {
BarcodeFormat barcodeFormat = BarcodeFormat.valueOf(s.toString());
barcodeTypeField.setTag(barcodeFormat);
updateTempState(LoyaltyCardField.barcodeType, barcodeFormat);
if (!BarcodeSelectorActivity.SUPPORTED_BARCODE_TYPES.contains(barcodeFormat.name())) {
Toast.makeText(LoyaltyCardEditActivity.this, getString(R.string.unsupportedBarcodeType), Toast.LENGTH_LONG).show();
@@ -509,22 +532,6 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
Log.i(TAG, "Received new intent");
extractIntentFields(intent);
// Reset these fields, so they are re-populated in onResume().
storeFieldEdit.setText("");
noteFieldEdit.setText("");
expiryField.setTag(null);
expiryField.setText("");
balanceCurrencyField.setTag(null);
balanceCurrencyField.setText("");
balanceField.setTag(null);
balanceField.setText("");
cardIdFieldView.setText("");
barcodeIdField.setTag(null);
barcodeIdField.setText("");
barcodeTypeField.setText("");
cardImageFront.setTag(null);
cardImageBack.setTag(null);
}
@SuppressLint("DefaultLocale")
@@ -535,121 +542,43 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
Log.i(TAG, "To view card: " + loyaltyCardId);
if(updateLoyaltyCard)
{
final LoyaltyCard loyaltyCard = db.getLoyaltyCard(loyaltyCardId);
if(loyaltyCard == null)
{
Log.w(TAG, "Could not lookup loyalty card " + loyaltyCardId);
Toast.makeText(this, R.string.noCardExistsError, Toast.LENGTH_LONG).show();
finish();
return;
}
onResuming = true;
if(storeFieldEdit.getText().length() == 0)
{
storeFieldEdit.setText(loyaltyCard.store);
}
if(noteFieldEdit.getText().length() == 0)
{
noteFieldEdit.setText(loyaltyCard.note);
}
if(expiryField.getText().length() == 0)
{
expiryField.setTag(loyaltyCard.expiry);
formatExpiryField(loyaltyCard.expiry);
}
if(balanceCurrencyField.getText().length() == 0)
{
balanceCurrencyField.setTag(loyaltyCard.balanceType);
formatBalanceCurrencyField(loyaltyCard.balanceType);
}
if(balanceField.getText().length() == 0)
{
balanceField.setTag(loyaltyCard.balance);
balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(loyaltyCard.balance, loyaltyCard.balanceType));
}
if(cardIdFieldView.getText().length() == 0)
{
cardIdFieldView.setText(loyaltyCard.cardId);
}
if(barcodeIdField.getText().length() == 0)
{
barcodeIdField.setTag(loyaltyCard.barcodeId);
barcodeIdField.setText(loyaltyCard.barcodeId != null ? loyaltyCard.barcodeId : getString(R.string.sameAsCardId));
}
if(barcodeTypeField.getText().length() == 0)
{
barcodeTypeField.setText(loyaltyCard.barcodeType != null ? loyaltyCard.barcodeType.toString() : getString(R.string.noBarcode));
}
if(headingColorValue == null)
{
headingColorValue = loyaltyCard.headerColor;
if(headingColorValue == null)
{
headingColorValue = LetterBitmap.getDefaultColor(this, loyaltyCard.store);
if(tempLoyaltyCard == null) {
if (updateLoyaltyCard) {
tempLoyaltyCard = db.getLoyaltyCard(loyaltyCardId);
if (tempLoyaltyCard == null) {
Log.w(TAG, "Could not lookup loyalty card " + loyaltyCardId);
Toast.makeText(this, R.string.noCardExistsError, Toast.LENGTH_LONG).show();
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);
} catch (InvalidObjectException ex) {
Toast.makeText(this, R.string.failedParsingImportUriError, Toast.LENGTH_LONG).show();
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);
setTitle(R.string.addCardTitle);
}
if(cardImageFront.getTag() == null)
{
setCardImage(cardImageFront, Utils.retrieveCardImage(this, loyaltyCard.id, true));
}
if(cardImageBack.getTag() == null)
{
setCardImage(cardImageBack, Utils.retrieveCardImage(this, loyaltyCard.id, false));
}
setTitle(R.string.editCardTitle);
}
else if(importLoyaltyCardUri != null)
{
// Try to parse
LoyaltyCard importCard;
try {
importCard = importUriHelper.parse(importLoyaltyCardUri);
} catch (InvalidObjectException ex) {
Toast.makeText(this, R.string.failedParsingImportUriError, Toast.LENGTH_LONG).show();
finish();
return;
}
storeFieldEdit.setText(importCard.store);
noteFieldEdit.setText(importCard.note);
expiryField.setTag(importCard.expiry);
formatExpiryField(importCard.expiry);
balanceField.setTag(importCard.balance);
balanceCurrencyField.setTag(importCard.balanceType);
formatBalanceCurrencyField(importCard.balanceType);
cardIdFieldView.setText(importCard.cardId);
barcodeIdField.setTag(importCard.barcodeId);
barcodeIdField.setText(importCard.barcodeId != null ? importCard.barcodeId : getString(R.string.sameAsCardId));
barcodeTypeField.setText(importCard.barcodeType != null ? importCard.barcodeType.toString() : getString(R.string.noBarcode));
headingColorValue = importCard.headerColor;
}
else
{
setTitle(R.string.addCardTitle);
expiryField.setTag(null);
expiryField.setText(getString(R.string.never));
barcodeIdField.setTag(null);
barcodeIdField.setText(getString(R.string.sameAsCardId));
balanceField.setTag(new BigDecimal("0"));
balanceCurrencyField.setTag(null);
formatBalanceCurrencyField(null);
hideBarcode();
setCardImage(cardImageFront, null);
setCardImage(cardImageBack, null);
}
storeFieldEdit.setText(tempLoyaltyCard.store);
noteFieldEdit.setText(tempLoyaltyCard.note);
formatExpiryField(this, expiryField, tempLoyaltyCard.expiry);
formatBalanceCurrencyField(tempLoyaltyCard.balanceType);
cardIdFieldView.setText(tempLoyaltyCard.cardId);
barcodeIdField.setText(tempLoyaltyCard.barcodeId != null ? tempLoyaltyCard.barcodeId : getString(R.string.sameAsCardId));
barcodeTypeField.setText(tempLoyaltyCard.barcodeType != null ? tempLoyaltyCard.barcodeType.name() : getString(R.string.noBarcode));
if(groupsChips.getChildCount() == 0)
{
@@ -685,16 +614,21 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
}
if(headingColorValue == null)
// Generate random header color
if(tempLoyaltyCard.headerColor == null)
{
// Select a random color to start out with.
TypedArray colors = getResources().obtainTypedArray(R.array.letter_tile_colors);
final int color = (int)(Math.random() * colors.length());
headingColorValue = colors.getColor(color, Color.BLACK);
updateTempState(LoyaltyCardField.headerColor, colors.getColor(color, Color.BLACK));
colors.recycle();
}
thumbnail.setOnClickListener(new ColorSelectListener(headingColorValue));
// 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());
}
// Update from intent
if (barcodeType != null) {
@@ -717,6 +651,12 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
}
// Empty intent values
barcodeType = null;
cardId = null;
barcodeId = null;
// Initialization has finished
if (!initDone) {
hasChanged = false;
initDone = true;
@@ -735,9 +675,11 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
saveButton.bringToFront();
generateIcon(storeFieldEdit.getText().toString());
onResuming = false;
}
private void setCardImage(ImageView imageView, Bitmap bitmap) {
protected static void setCardImage(ImageView imageView, Bitmap bitmap) {
imageView.setTag(bitmap);
if (bitmap != null) {
@@ -747,9 +689,11 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
}
private void formatExpiryField(Date expiry) {
protected static void formatExpiryField(Context context, EditText expiryField, Date expiry) {
expiryField.setTag(expiry);
if (expiry == null) {
expiryField.setText(getString(R.string.never));
expiryField.setText(context.getString(R.string.never));
} else {
expiryField.setText(DateFormat.getDateInstance(DateFormat.LONG).format(expiry));
}
@@ -803,23 +747,17 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
.setMessage(R.string.updateBarcodeQuestionText)
.setPositiveButton(R.string.yes, (dialog, which) -> {
barcodeIdField.setText(R.string.sameAsCardId);
tempStoredOldBarcodeValue = null;
if (callback != null) {
callback.run();
}
dialog.dismiss();
})
.setNegativeButton(R.string.no, (dialog, which) -> {
barcodeIdField.setText(tempStoredOldBarcodeValue);
tempStoredOldBarcodeValue = null;
if (callback != null) {
callback.run();
}
dialog.dismiss();
})
.setOnDismissListener(dialogInterface -> {
barcodeIdField.setText(tempStoredOldBarcodeValue);
tempStoredOldBarcodeValue = null;
if (tempStoredOldBarcodeValue != null) {
barcodeIdField.setText(tempStoredOldBarcodeValue);
tempStoredOldBarcodeValue = null;
}
if (callback != null) {
callback.run();
@@ -945,25 +883,22 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
class ColorSelectListener implements View.OnClickListener
{
final int defaultColor;
ColorSelectListener(int defaultColor)
{
this.defaultColor = defaultColor;
}
@Override
public void onClick(View v)
{
ColorPickerDialog dialog = ColorPickerDialog.newBuilder().setColor(defaultColor).create();
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)
{
hasChanged = true;
headingColorValue = color;
updateTempState(LoyaltyCardField.headerColor, color);
generateIcon(storeFieldEdit.getText().toString());
}
@@ -981,9 +916,11 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
public static class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener {
final Context context;
final EditText expiryFieldEdit;
DatePickerFragment(EditText expiryFieldEdit) {
DatePickerFragment(Context context, EditText expiryFieldEdit) {
this.context = context;
this.expiryFieldEdit = expiryFieldEdit;
}
@@ -1019,8 +956,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
Date date = new Date(unixTime);
expiryFieldEdit.setTag(date);
expiryFieldEdit.setText(DateFormat.getDateInstance(DateFormat.LONG).format(date));
formatExpiryField(context, expiryFieldEdit, date);
}
}
@@ -1030,22 +966,13 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
return;
}
String store = storeFieldEdit.getText().toString();
String note = noteFieldEdit.getText().toString();
Date expiry = (Date) expiryField.getTag();
BigDecimal balance = (BigDecimal) balanceField.getTag();
Currency balanceType = balanceCurrencyField.getTag() != null ? ((Currency) balanceCurrencyField.getTag()) : null;
String cardId = cardIdFieldView.getText().toString();
String barcodeId = (String) barcodeIdField.getTag();
BarcodeFormat barcodeType = (BarcodeFormat) barcodeTypeField.getTag();
if(store.isEmpty())
if(tempLoyaltyCard.store.isEmpty())
{
Snackbar.make(storeFieldEdit, R.string.noStoreError, Snackbar.LENGTH_LONG).show();
return;
}
if(cardId.isEmpty())
if(tempLoyaltyCard.cardId.isEmpty())
{
Snackbar.make(cardIdFieldView, R.string.noCardIdError, Snackbar.LENGTH_LONG).show();
return;
@@ -1066,7 +993,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
if(updateLoyaltyCard)
{ //update of "starStatus" not necessary, since it cannot be changed in this activity (only in ViewActivity)
db.updateLoyaltyCard(loyaltyCardId, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headingColorValue);
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);
@@ -1077,7 +1004,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
else
{
loyaltyCardId = (int)db.insertLoyaltyCard(store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headingColorValue, 0);
loyaltyCardId = (int)db.insertLoyaltyCard(tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, 0);
try {
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, true);
Utils.saveCardImage(this, (Bitmap) cardImageBack.getTag(), loyaltyCardId, false);
@@ -1121,30 +1048,18 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.deleteTitle);
builder.setMessage(R.string.deleteConfirmation);
builder.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Log.e(TAG, "Deleting card: " + loyaltyCardId);
builder.setPositiveButton(R.string.confirm, (dialog, which) -> {
Log.e(TAG, "Deleting card: " + loyaltyCardId);
DBHelper db = new DBHelper(LoyaltyCardEditActivity.this);
db.deleteLoyaltyCard(loyaltyCardId);
DBHelper db = new DBHelper(LoyaltyCardEditActivity.this);
db.deleteLoyaltyCard(loyaltyCardId);
ShortcutHelper.removeShortcut(LoyaltyCardEditActivity.this, loyaltyCardId);
ShortcutHelper.removeShortcut(LoyaltyCardEditActivity.this, loyaltyCardId);
finish();
dialog.dismiss();
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
}
finish();
dialog.dismiss();
});
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
@@ -1159,8 +1074,8 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
{
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || requestCode == Utils.CARD_IMAGE_FROM_CAMERA_BACK) {
if (resultCode == RESULT_OK) {
if (resultCode == RESULT_OK) {
if (requestCode == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || requestCode == Utils.CARD_IMAGE_FROM_CAMERA_BACK) {
Bitmap bitmap = BitmapFactory.decodeFile(tempCameraPicturePath);
if (bitmap != null) {
@@ -1179,9 +1094,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
hasChanged = true;
}
}
} else if (requestCode == Utils.CARD_IMAGE_FROM_FILE_FRONT || requestCode == Utils.CARD_IMAGE_FROM_FILE_BACK) {
if (resultCode == RESULT_OK) {
} else if (requestCode == Utils.CARD_IMAGE_FROM_FILE_FRONT || requestCode == Utils.CARD_IMAGE_FROM_FILE_BACK) {
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), intent.getData());
@@ -1201,11 +1114,9 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
hasChanged = true;
}
}
} else {
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
} else {
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
if (resultCode == RESULT_OK) {
cardId = barcodeValues.content();
barcodeType = barcodeValues.format();
barcodeId = "";
@@ -1224,8 +1135,8 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
private void generateOrHideBarcode() {
String cardIdString = barcodeIdField.getTag() != null ? barcodeIdField.getTag().toString() : cardIdFieldView.getText().toString();
BarcodeFormat barcodeFormat = (BarcodeFormat) barcodeTypeField.getTag();
String cardIdString = tempLoyaltyCard.barcodeId != null ? tempLoyaltyCard.barcodeId : tempLoyaltyCard.cardId;
BarcodeFormat barcodeFormat = tempLoyaltyCard.barcodeType;
if (barcodeFormat == null || cardIdString.isEmpty() || !BarcodeSelectorActivity.SUPPORTED_BARCODE_TYPES.contains(barcodeFormat.name())) {
hideBarcode();
@@ -1258,13 +1169,13 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
}
private void generateIcon(String store) {
if (headingColorValue == null) {
if (tempLoyaltyCard.headerColor == null) {
return;
}
thumbnail.setBackgroundColor(headingColorValue);
thumbnail.setBackgroundColor(tempLoyaltyCard.headerColor);
LetterBitmap letterBitmap = Utils.generateIcon(this, store, headingColorValue);
LetterBitmap letterBitmap = Utils.generateIcon(this, store, tempLoyaltyCard.headerColor);
if (letterBitmap != null) {
thumbnail.setImageBitmap(letterBitmap.getLetterTile());

View File

@@ -0,0 +1,15 @@
package protect.card_locker;
public enum LoyaltyCardField {
id,
store,
note,
expiry,
balance,
balanceType,
cardId,
barcodeId,
barcodeType,
headerColor,
starStatus
}

View File

@@ -1,11 +1,10 @@
package protect.card_locker;
import android.app.Application;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.multidex.MultiDexApplication;
import protect.card_locker.preferences.Settings;
public class LoyaltyCardLockerApplication extends Application {
public class LoyaltyCardLockerApplication extends MultiDexApplication {
public void onCreate() {
super.onCreate();

View File

@@ -92,6 +92,8 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
FullscreenType fullscreenType = FullscreenType.NONE;
boolean isBarcodeSupported = true;
static final String STATE_FULLSCREENTYPE = "fullscreenType";
enum FullscreenType {
NONE,
BARCODE,
@@ -128,6 +130,10 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
fullscreenType = FullscreenType.valueOf(savedInstanceState.getString(STATE_FULLSCREENTYPE));
}
settings = new Settings(this);
extractIntentFields(getIntent());
@@ -285,6 +291,13 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
extractIntentFields(intent);
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString(STATE_FULLSCREENTYPE, String.valueOf(fullscreenType));
super.onSaveInstanceState(savedInstanceState);
}
@Override
public void onResume()
{
@@ -468,40 +481,7 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
Toast.makeText(this, getString(R.string.unsupportedBarcodeType), Toast.LENGTH_LONG).show();
}
if(format != null && isBarcodeSupported)
{
if (fullscreenType == FullscreenType.NONE) {
maximizeButton.setVisibility(View.VISIBLE);
}
barcodeImage.setVisibility(View.VISIBLE);
if(barcodeImage.getHeight() == 0)
{
Log.d(TAG, "ImageView size is not known known at start, waiting for load");
// The size of the ImageView is not yet available as it has not
// yet been drawn. Wait for it to be drawn so the size is available.
redrawBarcodeAfterResize();
}
else
{
Log.d(TAG, "ImageView size known known, creating barcode");
new BarcodeImageWriterTask(
barcodeImage,
barcodeIdString != null ? barcodeIdString : cardIdString,
format,
null,
false,
null)
.execute();
}
// Force redraw fullscreen state
setFullscreen(fullscreenType);
}
else
{
maximizeButton.setVisibility(View.GONE);
barcodeImage.setVisibility(View.GONE);
}
setFullscreen(fullscreenType);
}
@Override

View File

@@ -25,6 +25,7 @@ import com.google.android.material.tabs.TabLayout;
import java.io.UnsupportedEncodingException;
import java.util.List;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
@@ -50,8 +51,7 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback()
{
@Override
public boolean onCreateActionMode(ActionMode inputMode, Menu inputMenu)
{
public boolean onCreateActionMode(ActionMode inputMode, Menu inputMenu) {
inputMode.getMenuInflater().inflate(R.menu.card_longclick_menu, inputMenu);
return true;
}
@@ -63,10 +63,8 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
@Override
public boolean onActionItemClicked(ActionMode inputMode, MenuItem inputItem)
{
if (inputItem.getItemId() == R.id.action_copy_to_clipboard)
{
public boolean onActionItemClicked(ActionMode inputMode, MenuItem inputItem) {
if (inputItem.getItemId() == R.id.action_copy_to_clipboard) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
String clipboardData;
@@ -94,9 +92,7 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
Toast.makeText(MainActivity.this, cardCount > 1 ? R.string.copy_to_clipboard_multiple_toast : R.string.copy_to_clipboard_toast, Toast.LENGTH_LONG).show();
inputMode.finish();
return true;
}
else if (inputItem.getItemId() == R.id.action_share)
{
} else if (inputItem.getItemId() == R.id.action_share) {
final ImportURIHelper importURIHelper = new ImportURIHelper(MainActivity.this);
try {
importURIHelper.startShareIntent(mAdapter.getSelectedItems());
@@ -106,9 +102,7 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
}
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");
}
@@ -120,6 +114,42 @@ public class MainActivity extends AppCompatActivity implements LoyaltyCardCursor
intent.putExtras(bundle);
startActivity(intent);
inputMode.finish();
return true;
} 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".
// So while in English the extra non-plural form seems unnecessary duplication, it is necessary to give translators enough flexibility.
// In here, we use the plain string when meaning exactly 1, and otherwise use the plural forms
if (mAdapter.getSelectedItemCount() == 1) {
builder.setTitle(R.string.deleteTitle);
builder.setMessage(R.string.deleteConfirmation);
} else {
builder.setTitle(getResources().getQuantityString(R.plurals.deleteCardsTitle, mAdapter.getSelectedItemCount(), mAdapter.getSelectedItemCount()));
builder.setMessage(getResources().getQuantityString(R.plurals.deleteCardsConfirmation, mAdapter.getSelectedItemCount(), mAdapter.getSelectedItemCount()));
}
builder.setPositiveButton(R.string.confirm, (dialog, which) -> {
DBHelper db = new DBHelper(MainActivity.this);
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
Log.e(TAG, "Deleting card: " + loyaltyCard.id);
db.deleteLoyaltyCard(loyaltyCard.id);
ShortcutHelper.removeShortcut(MainActivity.this, loyaltyCard.id);
}
TabLayout.Tab tab = ((TabLayout) findViewById(R.id.groups)).getTabAt(selectedTab);
updateLoyaltyCardList(mFilter, tab != null ? tab.getTag() : null);
dialog.dismiss();
});
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
return true;
}

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.os.Build;
@@ -37,6 +38,8 @@ class ShortcutHelper
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
LinkedList<ShortcutInfo> list = new LinkedList<>(shortcutManager.getDynamicShortcuts());
DBHelper dbHelper = new DBHelper(context);
String shortcutId = Integer.toString(card.id);
// Sort the shortcuts by rank, so working with the relative order will be easier.
@@ -105,6 +108,14 @@ class ShortcutHelper
Intent shortcutIntent = prevShortcut.getIntent();
Bitmap iconBitmap = Utils.generateIcon(context, dbHelper.getLoyaltyCard(Integer.parseInt(prevShortcut.getId())), true).getLetterTile();
Icon icon;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
icon = Icon.createWithAdaptiveBitmap(iconBitmap);
} else {
icon = Icon.createWithBitmap(iconBitmap);
}
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
shortcutIntent.setFlags(shortcutIntent.getFlags() | Intent.FLAG_ACTIVITY_SINGLE_TOP);
@@ -113,7 +124,7 @@ class ShortcutHelper
.setShortLabel(prevShortcut.getShortLabel())
.setLongLabel(prevShortcut.getLongLabel())
.setIntent(shortcutIntent)
.setIcon(Icon.createWithResource(context, R.drawable.circle))
.setIcon(icon)
.setRank(index)
.build();

View File

@@ -9,7 +9,6 @@ import android.graphics.Color;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
@@ -33,7 +32,6 @@ import java.util.Currency;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import androidx.core.graphics.ColorUtils;
@@ -54,6 +52,10 @@ public class Utils {
static final int BITMAP_SIZE_BIG = 512;
static public LetterBitmap generateIcon(Context context, LoyaltyCard loyaltyCard, boolean forShortcut) {
return generateIcon(context, loyaltyCard.store, loyaltyCard.headerColor, forShortcut);
}
static public LetterBitmap generateIcon(Context context, String store, Integer backgroundColor) {
return generateIcon(context, store, backgroundColor, false);
}
@@ -240,17 +242,17 @@ public class Utils {
return null;
}
Integer maxSize = BITMAP_SIZE_BIG;
double maxSize = BITMAP_SIZE_BIG;
Integer width = bitmap.getWidth();
Integer height = bitmap.getHeight();
double width = bitmap.getWidth();
double height = bitmap.getHeight();
if (height > width) {
Integer scale = height / maxSize;
double scale = height / maxSize;
height = maxSize;
width = width / scale;
} else if (width > height) {
Integer scale = width / maxSize;
double scale = width / maxSize;
width = maxSize;
height = height / scale;
} else {
@@ -258,7 +260,7 @@ public class Utils {
width = maxSize;
}
return Bitmap.createScaledBitmap(bitmap, width, height, true);
return Bitmap.createScaledBitmap(bitmap, (int) Math.round(width), (int) Math.round(height), true);
}
static public Bitmap rotateBitmap(Bitmap bitmap, ExifInterface exifInterface) {

View File

@@ -12,7 +12,6 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class ZipUtils {

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.InternalZipConstants;
@@ -12,16 +11,13 @@ import net.lingala.zip4j.util.InternalZipConstants;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.zip.ZipEntry;
import protect.card_locker.DBHelper;
import protect.card_locker.Group;

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import protect.card_locker.DBHelper;

View File

@@ -5,7 +5,6 @@ import android.util.Log;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import protect.card_locker.DBHelper;

View File

@@ -3,7 +3,6 @@ package protect.card_locker.importexport;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.google.zxing.BarcodeFormat;
@@ -14,14 +13,9 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;

View File

@@ -113,6 +113,6 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="@android:color/black" />
app:tint="#000000" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -53,7 +53,7 @@
android:padding="0dp"
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24"
android:contentDescription="@string/moveBarcodeToTopOfScreen"
android:tint="@android:color/white"
app:tint="#ffffff"
android:background="@color/colorPrimary"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/barcode"
@@ -84,7 +84,7 @@
android:padding="0dp"
app:srcCompat="@drawable/ic_baseline_arrow_drop_down_24"
android:contentDescription="@string/moveBarcodeToCenterOfScreen"
android:tint="@android:color/white"
app:tint="#ffffff"
android:background="@color/colorPrimary"
app:layout_constraintTop_toBottomOf="@+id/barcode"
app:layout_constraintEnd_toEndOf="parent"
@@ -150,7 +150,7 @@
android:layout_gravity="top|start"
android:background="@color/colorPrimary"
android:scaleType="fitCenter"
android:tint="@android:color/white"
app:tint="#ffffff"
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24" />
<androidx.core.widget.NestedScrollView

View File

@@ -7,20 +7,27 @@
android:title="@string/copy_to_clipboard"
android:icon="@drawable/ic_copy"
android:titleCondensed="@string/copy_to_clipboard"
app:showAsAction="always"/>
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_share"
android:title="@string/share"
android:icon="@drawable/ic_share"
android:titleCondensed="@string/share"
app:showAsAction="always"/>
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_edit"
android:icon="@drawable/ic_edit"
android:title="@string/editCardTitle"
android:titleCondensed="@string/editCardTitle"
app:showAsAction="always"/>
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_delete"
android:icon="@drawable/ic_delete_white_24dp"
android:title="@string/delete"
android:titleCondensed="@string/delete"
app:showAsAction="ifRoom"/>
</menu>

View File

@@ -122,8 +122,6 @@
<string name="share">Споделя</string>
<string name="copy_to_clipboard">Копира идентификатора в междинната памет</string>
<string name="ok">Добре</string>
<string name="deleteConfirmation">Потвърдете премахване на карта</string>
<string name="deleteTitle">Премахване на карта</string>
<string name="importSuccessful">Картите са внесени успешно</string>
<string name="chooseImportType">От къде ще внесете\?</string>
<string name="importCatimaMessage">Изберете файла <i>catima.zip</i>, предварително изнесен от Catima.
@@ -146,8 +144,8 @@
<string name="unlockScreen">Разрешава автоматичното завъртане</string>
<string name="lockScreen">Спира автоматичното завъртане</string>
<plurals name="selectedCardCount">
<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="deleteConfirmationGroup">Изтриване на група\?</string>
<string name="moveDown">Преместване надолу</string>
@@ -166,5 +164,15 @@
\nИли създайте такъв файл от меню Внасяне/изнасяне от друго устройство със Loyalty Card Keychain като изберете Изнасяне.</string>
<string name="failedParsingImportUriError">Препратката не може да бъде анализирана за внасяне</string>
<string name="card_ids_copied">[не превеждай този низ, https://github.com/TheLastProject/Catima/issues/278]</string>
<string name="failedGeneratingShareURL">Неуспешно генериране на адрес за споделяне. Докладвайте за тази грешка!</string>
<string name="failedGeneratingShareURL">Грешка при създаване на адрес за споделяне. Изпратете доклад за дефект.</string>
<string name="deleteTitle">Премахване на карта</string>
<plurals name="deleteCardsTitle">
<item quantity="one">Премахване на карта</item>
<item quantity="other">Премахване на карти</item>
</plurals>
<string name="deleteConfirmation">Потвърдете премахване на карта</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Желаете ли картата да бъде премахната\?</item>
<item quantity="other">Желаете ли <xliff:g>%d</xliff:g> картати да бъдат премахнати\?</item>
</plurals>
</resources>

View File

@@ -12,8 +12,6 @@
<string name="edit">Editovat</string>
<string name="delete">Smazat</string>
<string name="confirm">Potvrdit</string>
<string name="deleteTitle">Odstzranit věrnostní kartu</string>
<string name="deleteConfirmation">Opravdu chcete smazat tuto věrnostní kartu?</string>
<string name="ok">Ano</string>
<string name="copy_to_clipboard">Kopírovat ID do schránky</string>
<string name="sendLabel">Odeslat&#8230;</string>
@@ -51,4 +49,7 @@
<string name="selectBarcodeTitle">Vyberte čárový kód</string>
<string name="copy_to_clipboard_toast">ID karty zkopírováno do schránky</string>
<string name="deleteTitle">Odstzranit věrnostní kartu</string>
<string name="deleteConfirmation">Opravdu chcete smazat tuto věrnostní kartu?</string>
</resources>

View File

@@ -16,8 +16,6 @@
<string name="unlockScreen">Rotation zulassen</string>
<string name="star">Zu den Favoriten hinzufügen</string>
<string name="unstar">Aus der Favoritenliste entfernen</string>
<string name="deleteTitle">Karte entfernen</string>
<string name="deleteConfirmation">Diese Karte löschen\?</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Nummer in die Zwischenablage kopieren</string>
<string name="sendLabel">Senden </string>
@@ -162,9 +160,19 @@
<string name="importStocard">Von Stocard importieren</string>
<string name="turn_flashlight_off">Taschenlampe ausschalten</string>
<string name="turn_flashlight_on">Taschenlampe einschalten</string>
<string name="failedGeneratingShareURL">Fehler beim Generieren der Freigabe-URL. Bitte melden Sie diesen Fehler!</string>
<string name="failedGeneratingShareURL">Keine teilbare URL konnte generiert werden. Bitte melden Sie dies.</string>
<plurals name="selectedCardCount">
<item quantity="one">Ausgewählt: <xliff:g>%d</xliff:g> Karte</item>
<item quantity="other">Ausgewählt: <xliff:g>%d</xliff:g> Karten</item>
<item quantity="one"><xliff:g>%d</xliff:g> Karte ausgewählt</item>
<item quantity="other"><xliff:g>%d</xliff:g> Karten ausgewählt</item>
</plurals>
<string name="deleteTitle">Karte entfernen</string>
<string name="deleteConfirmation">Diese Karte löschen\?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Diese <xliff:g>%d</xliff:g> Karte endgültig löschen\?</item>
<item quantity="other">Diese <xliff:g>%d</xliff:g> Karten endgültig löschen\?</item>
</plurals>
<plurals name="deleteCardsTitle">
<item quantity="one">Karte löschen</item>
<item quantity="other">Karten löschen</item>
</plurals>
</resources>

View File

@@ -12,8 +12,6 @@
<string name="confirm">Επιβεβαίωση</string>
<string name="lockScreen">Αποκλεισμός Περιστροφής</string>
<string name="unlockScreen">Περιστροφή</string>
<string name="deleteTitle">Αφαίρεση Κάρτας</string>
<string name="deleteConfirmation">Παρακαλώ επιβεβαιώστε ότι θέλετε να διαγράψετε αυτή την κάρτα.</string>
<string name="ok">Εντάξει</string>
<string name="copy_to_clipboard">Αντιγραφή κωδικού στο πρόχειρο</string>
<string name="sendLabel">Αποστολή…</string>
@@ -58,4 +56,6 @@
<string name="settings_light_theme">Φωτεινό</string>
<string name="settings_system_theme">Σύστημα</string>
<string name="barcode">Γραμμικός κώδικας</string>
<string name="deleteTitle">Αφαίρεση Κάρτας</string>
<string name="deleteConfirmation">Παρακαλώ επιβεβαιώστε ότι θέλετε να διαγράψετε αυτή την κάρτα.</string>
</resources>

View File

@@ -1,7 +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">
<string name="deleteConfirmation">Ĉu forigi ĉi tiun karton\?</string>
<string name="deleteTitle">Forigi karton</string>
<string name="barcodeNoBarcode">Strekokodo mankas al karto</string>
<string name="delete">Forigi</string>
<string name="noBarcode">Sen strekokodo</string>
@@ -52,4 +50,6 @@
<string name="cancel">Nuligi</string>
<string name="action_add">Aldoni</string>
<string name="action_search">Serĉi</string>
<string name="deleteConfirmation">Ĉu forigi ĉi tiun karton\?</string>
<string name="deleteTitle">Forigi karton</string>
</resources>

View File

@@ -12,8 +12,6 @@
<string name="confirm">Confirmar</string>
<string name="lockScreen">Bloquear giro</string>
<string name="unlockScreen">Desbloquear giro</string>
<string name="deleteTitle">Eliminar tarjeta</string>
<string name="deleteConfirmation">¿Quiere eliminar esta tarjeta\?</string>
<string name="ok">Aceptar</string>
<string name="copy_to_clipboard">Copiar id. en portapapeles</string>
<string name="sendLabel">Enviar…</string>
@@ -28,7 +26,7 @@
<string name="noCardExistsError">No se ha podido encontrar la tarjeta</string>
<string name="importExport">Importar/exportar</string>
<string name="exportName">Exportar</string>
<string name="importExportHelp">La copia de respaldo le permite transferir sus tarjetas a otro dispositivo.</string>
<string name="importExportHelp">El respaldo le permite transferir sus tarjetas a otro dispositivo.</string>
<string name="importSuccessfulTitle">Importado</string>
<string name="importFailedTitle">Falló la importación</string>
<string name="importFailed">No se han podido importar tarjetas</string>
@@ -48,18 +46,18 @@
<string name="app_license">Programa libre con «copyleft», disponible en virtud de la licencia GPLv3+.</string>
<string name="about_title_fmt">Acerca de <xliff:g id="app_name">%s</xliff:g></string>
<string name="debug_version_fmt">Versión: <xliff:g id="version">%s</xliff:g></string>
<string name="settings">Configuración</string>
<string name="settings">Ajustes</string>
<string name="settings_category_title_ui">Interfaz de usuario</string>
<string name="settings_display_barcode_max_brightness">Iluminar vista del código de barras</string>
<string name="exportSuccessful">Datos de las tarjetas exportados</string>
<string name="importSuccessful">Datos de las tarjetas importados</string>
<string name="intent_import_card_from_url_share_text">Quiero compartirle una tarjeta</string>
<string name="settings_lock_barcode_orientation">Bloquear orientación del código de barras</string>
<string name="intent_import_card_from_url_share_text">Quiero compartirte una tarjeta</string>
<string name="settings_lock_barcode_orientation">Bloquear giro en el código de barras</string>
<string name="settings_dark_theme">Oscuro</string>
<string name="settings_light_theme">Claro</string>
<string name="settings_system_theme">Sistema</string>
<string name="settings_theme">Tema</string>
<string name="enterBarcodeInstructions">Introduzca el identificador de tarjeta y seleccione la imagen que represente el código de barras que se utilizará, o bien, elija «Esta tarjeta no tiene código de barras» para no utilizar ninguno.</string>
<string name="enterBarcodeInstructions">Introduzca el identificador de tarjeta y seleccione el código de barras que se utilizará, o de lo contrario, elija «Esta tarjeta no tiene código de barras».</string>
<string name="app_copyright_old">Basado en Loyalty Card Keychain
\nderechos de autor © 2016-2020 de Branden Archer.</string>
<string name="exportOptionExplanation">Los datos se guardarán en la ubicación que elija.</string>
@@ -73,7 +71,7 @@
<string name="noGroups">Primero pulse en el botón «+» para añadir grupos de categorización.</string>
<string name="starImage">Favorito</string>
<string name="thumbnailDescription">Miniatura de la tarjeta</string>
<string name="copy_to_clipboard_toast">Se copió el identificador de tarjeta en el portapapeles</string>
<string name="copy_to_clipboard_toast">Se copió la id. de tarjeta en el portapapeles</string>
<string name="selectBarcodeTitle">Seleccionar el código de barras</string>
<string name="unstar">Eliminar de favoritos</string>
<string name="noBarcode">Sin código de barras</string>
@@ -94,8 +92,8 @@
<item quantity="other"><xliff:g>%d</xliff:g> tarjetas</item>
</plurals>
<string name="points">Puntos</string>
<string name="moveBarcodeToCenterOfScreen">Centrar el código de barras en la pantalla</string>
<string name="moveBarcodeToTopOfScreen">Mover el código de barras a la zona superior de la pantalla</string>
<string name="moveBarcodeToCenterOfScreen">Centre el código de barras en la pantalla</string>
<string name="moveBarcodeToTopOfScreen">Mueva el código de barras a la zona superior de la pantalla</string>
<string name="chooseExpiryDate">Elegir fecha de caducidad</string>
<string name="never">Nunca</string>
<string name="expiryDate">Fecha de caducidad</string>
@@ -108,4 +106,73 @@
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Derechos de autor © 2019-<xliff:g>%d</xliff:g> de Sylvia van Os.</string>
<string name="app_resources">Recursos de terceros libres: <xliff:g id="app_resources_list">%s</xliff:g></string>
<string name="app_libraries">Bibliotecas de terceros libres: <xliff:g id="app_libraries_list">%s</xliff:g></string>
<string name="settings_max_font_size_scale">Tam. de fuente máximo</string>
<string name="importCatimaMessage">Seleccione su <i>catima.zip</i> exportado desde Catima para importarlo.
\nO créalo primero desde el menú Importar/Exportar de otra app de Catima al presionar Exportar desde allí.</string>
<string name="importFidmeMessage">Seleccione su <i>fidme-export-request-xxxxxx.zip</i> exportado desde FidMe para importar, y luego escoja los tipos de códigos de barras manualmente.
\nO créalo primero desde tu perfil de FidMe eligiendo Protección de datos y pulsa Extraer mis datos.</string>
<string name="importLoyaltyCardKeychainMessage">Seleccione su <i>LoyaltyCardKeychain.csv</i> exportado desde Loyalty Card Keychain para importarlo.
\nO créalo primero desde el menú Importar/Exportar en Loyalty Card Keychain pulsando Exportar desde allí.</string>
<string name="importStocardMessage">Seleccione su <i>*-sync.zip</i> exportado de Stocard para importarla, y selecciona los tipos de códigos de barras manualmente después.
\nO consígalo enviando un correo electrónico a support@stocardapp.com solicitando una exportación de sus datos.</string>
<string name="importVoucherVaultMessage">Seleccione su <i>vouchervault.json</i> exportado desde Voucher Vault para importarlo.
\nO créalo pulsando primero Exportar en Voucher Vault.</string>
<string name="failedGeneratingShareURL">No se ha podido generar una URL compartible. Por favor, informe de ello.</string>
<string name="passwordRequired">Por favor, introduzca la contraseña</string>
<string name="updateBarcodeQuestionText">Ha cambiado la Id. de la tarjeta. ¿Desea actualizar también el código de barras para usar el mismo valor\?</string>
<string name="intent_import_card_from_url_share_multiple_text">Quiero compartirte algunas tarjetas</string>
<string name="setBackImage">Establecer imagen anversa</string>
<string name="card_ids_copied">Id. de tarjetas copiadas</string>
<string name="turn_flashlight_off">Apagar linterna</string>
<string name="turn_flashlight_on">Encender linterna</string>
<string name="no">No</string>
<string name="yes"></string>
<string name="updateBarcodeQuestionTitle">¿Actualizar valor de código de barras\?</string>
<string name="takePhoto">Tomar una foto</string>
<string name="removeImage">Quitar imagen</string>
<string name="setFrontImage">Establecer imagen frontal</string>
<string name="photos">Fotos</string>
<string name="backImageDescription">Imagen del reverso de la tarjeta</string>
<string name="frontImageDescription">Imagen frontal de la tarjeta</string>
<string name="copy_to_clipboard_multiple_toast">ID de tarjetas copiadas al portapapeles</string>
<string name="wrongValueForBarcodeType">El valor no es válido para el tipo de código de barras seleccionado</string>
<string name="unsupportedBarcodeType">Este tipo de código de barras todavía no se puede visualizar. Es posible que se admita en una futura versión de la aplicación.</string>
<string name="setBarcodeId">Establecer valor de código de barra</string>
<string name="sameAsCardId">Igual que la ID de tarjeta</string>
<string name="barcodeId">Valor de código de barra</string>
<string name="importVoucherVault">Importar desde Voucher Vault</string>
<string name="importStocard">Importar desde Stocard</string>
<string name="importLoyaltyCardKeychain">Importar desde Loyalty Card Keychain</string>
<string name="importFidme">Importar desde FidMe</string>
<string name="importCatima">Importar desde Catima</string>
<string name="accept">Aceptar</string>
<string name="privacy_policy_popup_text">Aviso de política de privacidad (requerido por algunas tiendas de apps):
\n
\nNINGÚN DATO SE RECOPILA, cualquiera puede confirmar ya que nuestra aplicación es software libre.</string>
<string name="privacy_policy">Política de privacidad</string>
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
<string name="chooseImportType">¿De dónde importar datos\?</string>
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> no tendría un saldo válido.</string>
<string name="currency">Moneda</string>
<string name="balance">Saldo</string>
<string name="errorReadingImage">No se pudo leer la imagen</string>
<string name="noBarcodeFound">No se encontró código de barras</string>
<string name="balanceSentence">Saldo: <xliff:g>%s</xliff:g></string>
<string name="addFromImage">Selecciona imagen desde galería</string>
<string name="settings_disable_lockscreen_while_viewing_card">Evitar bloqueo de pantalla</string>
<string name="settings_keep_screen_on">Mantener pantalla encendida</string>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> tarjeta seleccionada</item>
<item quantity="other"><xliff:g>%d</xliff:g> tarjetas seleccionadas</item>
</plurals>
<string name="deleteTitle">Eliminar tarjeta</string>
<string name="deleteConfirmation">¿Quiere eliminar esta tarjeta\?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">¿Borrar esta tarjeta <xliff:g>%d</xliff:g> permanentemente\?</item>
<item quantity="other">¿Borrar estas tarjetas <xliff:g>%d</xliff:g> permanentemente\?</item>
</plurals>
<plurals name="deleteCardsTitle">
<item quantity="one">Borrar la tarjeta</item>
<item quantity="other">Borrar las tarjetas</item>
</plurals>
</resources>

View File

@@ -128,8 +128,6 @@
<string name="share">Jaa</string>
<string name="copy_to_clipboard">Kopioi ID-tunnus leikepöydälle</string>
<string name="ok">OK</string>
<string name="deleteConfirmation">Poista tämä kortti\?</string>
<string name="deleteTitle">Poista kortti</string>
<string name="unlockScreen">Poista kierron esto</string>
<string name="lockScreen">Estä kierto</string>
<string name="confirm">Vahvista</string>
@@ -156,4 +154,6 @@
<string name="photos">Valokuvat</string>
<string name="backImageDescription">Kortin takakuva</string>
<string name="frontImageDescription">Kortin etukuva</string>
<string name="deleteConfirmation">Poista tämä kortti\?</string>
<string name="deleteTitle">Poista kortti</string>
</resources>

View File

@@ -12,8 +12,6 @@
<string name="confirm">Confirmer</string>
<string name="lockScreen">Désactiver la rotation</string>
<string name="unlockScreen">Activer la rotation</string>
<string name="deleteTitle">Supprimer la carte de fidélité</string>
<string name="deleteConfirmation">Supprimer cette carte \?</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Copier le numéro dans le presse-papier</string>
<string name="sendLabel">Envoyer…</string>
@@ -162,9 +160,15 @@
<string name="importStocard">Importer depuis Stocard</string>
<string name="turn_flashlight_off">Éteindre la lampe de poche</string>
<string name="turn_flashlight_on">Allumer la lampe de poche</string>
<string name="failedGeneratingShareURL">Échec de la génération de lURL de partage. Veuillez signaler ce problème !</string>
<string name="failedGeneratingShareURL">Impossible de générer une URL partageable. Veuillez signaler ceci.</string>
<plurals name="selectedCardCount">
<item quantity="one">Sélectionnée : <xliff:g>%d</xliff:g> carte</item>
<item quantity="other">Sélectionnées : <xliff:g>%d</xliff:g> cartes</item>
<item quantity="one"><xliff:g>%d</xliff:g> carte sélectionnée</item>
<item quantity="other"><xliff:g>%d</xliff:g> cartes sélectionnées</item>
</plurals>
</resources>
<string name="deleteTitle">Supprimer la carte de fidélité</string>
<string name="deleteConfirmation">Supprimer cette carte \?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Supprimer cette <xliff:g>%d</xliff:g> carte définitivement \?</item>
<item quantity="other">Supprimer ces <xliff:g>%d</xliff:g> cartes définitivement \?</item>
</plurals>
</resources>

View File

@@ -15,8 +15,6 @@
<string name="confirm">Conferma</string>
<string name="lockScreen">Blocca rotazione</string>
<string name="unlockScreen">Sblocca rotazione</string>
<string name="deleteTitle">Rimuovi carta fedeltà</string>
<string name="deleteConfirmation">Eliminare questa carta\?</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Copia ID negli appunti</string>
<string name="share">Condividi</string>
@@ -162,9 +160,19 @@
<string name="importStocard">Importa da Stocard</string>
<string name="turn_flashlight_off">Spegni la torcia</string>
<string name="turn_flashlight_on">Accendi la torcia</string>
<string name="failedGeneratingShareURL">Impossibile generare l\'URL di condivisione. Si prega di segnalare questo errore!</string>
<string name="failedGeneratingShareURL">Impossibile generare un URL condivisibile. Si prega di segnalarlo.</string>
<plurals name="selectedCardCount">
<item quantity="one">Selezionata: <xliff:g>%d</xliff:g> carta</item>
<item quantity="other">Selezionate: <xliff:g>%d</xliff:g> carte</item>
<item quantity="one"><xliff:g>%d</xliff:g> carta selezionata</item>
<item quantity="other"><xliff:g>%d</xliff:g> carte selezionate</item>
</plurals>
<string name="deleteTitle">Rimuovi carta fedeltà</string>
<string name="deleteConfirmation">Eliminare questa carta\?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Eliminare definitivamente questa scheda <xliff:g>%d</xliff:g>\?</item>
<item quantity="other">Eliminare definitivamente queste schede <xliff:g>%d</xliff:g>\?</item>
</plurals>
<plurals name="deleteCardsTitle">
<item quantity="one">Elimina la carta</item>
<item quantity="other">Elimina le carte</item>
</plurals>
</resources>

View File

@@ -120,8 +120,6 @@
<string name="share">共有</string>
<string name="copy_to_clipboard">カード番号をクリップボードにコピーする</string>
<string name="ok">確定</string>
<string name="deleteConfirmation">このカードを削除しますか?</string>
<string name="deleteTitle">カードの削除</string>
<string name="unlockScreen">自動回転を無効にしない</string>
<string name="lockScreen">自動回転を無効にする</string>
<string name="confirm">確認</string>
@@ -165,4 +163,6 @@
<plurals name="selectedCardCount">
<item quantity="other">選択済み: <xliff:g>%d</xliff:g></item>
</plurals>
<string name="deleteConfirmation">このカードを削除しますか?</string>
<string name="deleteTitle">カードの削除</string>
</resources>

View File

@@ -31,8 +31,6 @@
<string name="share">공유</string>
<string name="copy_to_clipboard">ID를 클립보드에 복사</string>
<string name="ok">확인</string>
<string name="deleteConfirmation">정말 이 카드를 삭제하시겠습니까\?</string>
<string name="deleteTitle">카드 제거</string>
<string name="unlockScreen">회전 잠금 해제</string>
<string name="lockScreen">회전 잠금</string>
<string name="confirm">확인</string>
@@ -78,4 +76,6 @@
<string name="starImage">즐겨찾기 별</string>
<string name="settings_display_barcode_max_brightness">바코드를 표시할 때 화면 밝기 높이기</string>
<string name="barcode">바코드</string>
<string name="deleteConfirmation">정말 이 카드를 삭제하시겠습니까\?</string>
<string name="deleteTitle">카드 제거</string>
</resources>

View File

@@ -10,8 +10,6 @@
<string name="edit">Redaguoti</string>
<string name="delete">Ištrinti</string>
<string name="confirm">Patvirtinti</string>
<string name="deleteTitle">Panaikinti lojalumo kortelę</string>
<string name="deleteConfirmation">Ištrinti šią kortelę\?</string>
<string name="ok">Gerai</string>
<string name="copy_to_clipboard">Nukopijuoti ID į iškarpinę</string>
<string name="editCardTitle">Redaguoti lojalumo kortelę</string>
@@ -169,4 +167,6 @@
<item quantity="few">Pasirinktos: <xliff:g>%d</xliff:g> kortelės</item>
<item quantity="other">Pasirinkta: <xliff:g>%d</xliff:g> kortelių</item>
</plurals>
<string name="deleteTitle">Panaikinti lojalumo kortelę</string>
<string name="deleteConfirmation">Ištrinti šią kortelę\?</string>
</resources>

View File

@@ -13,8 +13,6 @@
<string name="confirm">Bekreft</string>
<string name="lockScreen">Ingen rotering</string>
<string name="unlockScreen">Skru på rotering</string>
<string name="deleteTitle">Fjern kundekort</string>
<string name="deleteConfirmation">Slett dette kortet\?</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Kopier ID til utklippstavle</string>
<string name="sendLabel">Send…</string>
@@ -156,9 +154,25 @@
<string name="photos">Bilder</string>
<string name="backImageDescription">Kortets bakside</string>
<string name="frontImageDescription">Kortets forside</string>
<string name="importStocardMessage">Finn din Stocard.zip-fil å importere, og velg strekkodetypene manuelt etterpå.
<string name="importStocardMessage">Velg din <i>***-sync.zip</i>-eksport fra Stocard å importere, og velg strekkodetypene manuelt etterpå.
\nEller få den ved å sende e-post til support@stocardapp.com der du etterspør eksport av dataen din.</string>
<string name="passwordRequired">Skriv inn passordet</string>
<string name="importStocard">Importer fra Stocard</string>
<string name="failedGeneratingShareURL">Klarte ikke å lage delingsnettadresse. Rapporter denne feilen.</string>
<string name="failedGeneratingShareURL">Klarte ikke å lage delbar nettadresse. Rapporter denne feilen.</string>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> kort valgt</item>
<item quantity="other"><xliff:g>%d</xliff:g> kort valgt</item>
</plurals>
<string name="deleteConfirmation">Slett dette kortet\?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Slett dette kortet for godt\?</item>
<item quantity="other">Slett disse <xliff:g xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">%d</xliff:g> kortene for godt\?</item>
</plurals>
<string name="turn_flashlight_on">Skru på lommelykten</string>
<string name="turn_flashlight_off">Skru av lommelykten</string>
<string name="deleteTitle">Fjern kundekort</string>
<plurals name="deleteCardsTitle">
<item quantity="one">Slett kort</item>
<item quantity="other">Slett kort</item>
</plurals>
</resources>

View File

@@ -16,8 +16,6 @@
<string name="confirm">Bevestigen</string>
<string name="lockScreen">Draaien niet toestaan</string>
<string name="unlockScreen">Draaien toestaan</string>
<string name="deleteTitle">Kaart verwijderen</string>
<string name="deleteConfirmation">Kaart verwijderen\?</string>
<string name="ok">Oké</string>
<string name="copy_to_clipboard">Kaartnummer kopiëren naar klembord</string>
<string name="share">Delen</string>
@@ -160,11 +158,21 @@
<string name="importStocardMessage">Kies het te importeren Stocard-exportbestand genaamd <i>***-sync.zip</i> en kies nadien de juiste barcodes.
\nOf stuur een e-mail naar support@stocardapp.com waarin je vraagt om een exportbestand.</string>
<string name="importStocard">Importeren uit Stocard</string>
<string name="failedGeneratingShareURL">De te delen link kan niet worden gegenereerd. Meld deze bug!</string>
<string name="failedGeneratingShareURL">De te delen link kan niet worden gegenereerd. Meld deze fout.</string>
<string name="turn_flashlight_off">Zaklamp uitzetten</string>
<string name="turn_flashlight_on">Zaklamp aanzetten</string>
<plurals name="selectedCardCount">
<item quantity="one"><xliff:g>%d</xliff:g> kaart geselecteerd</item>
<item quantity="other"><xliff:g>%d</xliff:g> kaarten geselecteerd</item>
</plurals>
<string name="deleteTitle">Kaart verwijderen</string>
<plurals name="deleteCardsTitle">
<item quantity="one"><xliff:g>%d</xliff:g> kaart verwijderen</item>
<item quantity="other"><xliff:g>%d</xliff:g> kaarten verwijderen</item>
</plurals>
<string name="deleteConfirmation">Kaart verwijderen\?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Weet je zeker dat je deze <xliff:g>%d</xliff:g> kaart wilt verwijderen\?</item>
<item quantity="other">Weet je zeker dat je deze <xliff:g>%d</xliff:g> kaarten wilt verwijderen\?</item>
</plurals>
</resources>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="exporting">Exportacion…</string>
<string name="importing">Importacion…</string>
<string name="exportFailed">Exportacion pas possibla</string>
<string name="exportSuccessfulTitle">Exportat</string>
<string name="importFailed">Importacion de vòstras cartas impossibla</string>
<string name="importFailedTitle">Fracàs de limportacion</string>
<string name="importSuccessfulTitle">Importat</string>
<string name="importExportHelp">Exportar vòstras cartas vos permet de las recuperar sus un autre aparelh.</string>
<string name="exportName">Exportar</string>
<string name="importExport">Importar/Exportar</string>
<string name="failedParsingImportUriError">Analisi impossibla lURI dimportacion</string>
<string name="noCardExistsError">Cap de carta pas trobada</string>
<string name="noCardIdError">Cap de numèro de carta pas picat</string>
<string name="noStoreError">Cap de nom pas picat</string>
<string name="barcodeImageDescription">Imatge del còdi de barras</string>
<string name="card_ids_copied">Num. de la carta copiada</string>
<string name="noCardsMessage">Apondètz den primièr una carta</string>
<string name="cardShortcut">Acorchi de carta</string>
<string name="scanCardBarcode">Numerizar lo còdi de barras</string>
<string name="addCardTitle">Apondre una carta</string>
<string name="editCardTitle">Modificar la carta</string>
<string name="sendLabel">Enviar…</string>
<string name="share">Partejar</string>
<string name="unlockScreen">Activar la rotacion</string>
<string name="lockScreen">Desactivar la rotacion</string>
<string name="confirm">Confirmar</string>
<string name="delete">Suprimir</string>
<string name="edit">Modificar</string>
<string name="save">Enregistrar</string>
<string name="cancel">Anullar</string>
<string name="unstar">Tirar dels favorits</string>
<string name="star">Apondre als favorits</string>
<string name="barcodeType">Tipe còdi de barras</string>
<string name="cardId">Numèro</string>
<string name="note">Nòta</string>
<string name="storeName">Nom</string>
<string name="action_add">Apondre</string>
<string name="action_search">Recercar</string>
</resources>

View File

@@ -15,8 +15,6 @@
<string name="confirm">Potwierdź</string>
<string name="lockScreen">Zablokuj autoobracanie ekranu</string>
<string name="unlockScreen">Odblokuj autoobracanie ekranu</string>
<string name="deleteTitle">Usuń kartę lojalnościową</string>
<string name="deleteConfirmation">Potwierdź, że chcesz usunąć tę kartę.</string>
<string name="ok">OK</string>
<string name="copy_to_clipboard">Skopiuj identyfikator do schowka</string>
<string name="share">Udostępnij</string>
@@ -83,4 +81,6 @@
<string name="star">Dodaj do ulubionych</string>
<string name="noBarcode">Brak kodu kreskowego</string>
<string name="barcodeType">Typ kodu kreskowego</string>
<string name="deleteTitle">Usuń kartę lojalnościową</string>
<string name="deleteConfirmation">Potwierdź, że chcesz usunąć tę kartę.</string>
</resources>

View File

@@ -16,8 +16,6 @@
<string name="confirm">Подтвердить</string>
<string name="lockScreen">Блокировать поворот экрана</string>
<string name="unlockScreen">Автоповорот экрана</string>
<string name="deleteTitle">Удаление карты</string>
<string name="deleteConfirmation">Удалить карту\?</string>
<string name="ok">ОК</string>
<string name="copy_to_clipboard">Копировать номер карты</string>
<string name="share">Переслать</string>
@@ -162,7 +160,7 @@
\nЭтот файл можно получить по электронной почте от support@stocardapp.com, предварительно запросив экспорт ваших данных.</string>
<string name="passwordRequired">Введите пароль</string>
<string name="importStocard">Импорт из Stocard</string>
<string name="failedGeneratingShareURL">Невозможно создать URL для обмена. Пожалуйста, сообщите об ошибке!</string>
<string name="failedGeneratingShareURL">Невозможно создать URL для обмена. Пожалуйста, сообщите об этом.</string>
<string name="turn_flashlight_off">Отключить вспышку</string>
<string name="turn_flashlight_on">Включить вспышку</string>
<plurals name="selectedCardCount">
@@ -171,4 +169,12 @@
<item quantity="many">Выбрано: <xliff:g>%d</xliff:g> карт</item>
<item quantity="other">Выбрано: <xliff:g>%d</xliff:g> карт</item>
</plurals>
</resources>
<string name="deleteTitle">Удаление карты</string>
<string name="deleteConfirmation">Удалить карту\?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Удалить эту <xliff:g>%d</xliff:g> карту безвозвратно\?</item>
<item quantity="few">Удалить эти <xliff:g>%d</xliff:g> карты безвозвратно\?</item>
<item quantity="many">Удалить эти <xliff:g>%d</xliff:g> карт безвозвратно\?</item>
<item quantity="other">Удалить эти <xliff:g>%d</xliff:g> карт безвозвратно\?</item>
</plurals>
</resources>

View File

@@ -14,8 +14,6 @@
<string name="confirm">Potvrdiť</string>
<string name="lockScreen">Zakázať rotáciu</string>
<string name="unlockScreen">Povoliť rotáciu</string>
<string name="deleteTitle">Odstrániť kartu</string>
<string name="deleteConfirmation">Naozaj chcete túto kartu odstrániť?</string>
<string name="ok">Áno</string>
<string name="copy_to_clipboard">Kopírovať ID do schránky</string>
<string name="sendLabel">Odoslať&#8230;</string>
@@ -64,4 +62,6 @@
<string name="settings_category_title_ui">Používateľské prostredie</string>
<string name="settings_display_barcode_max_brightness">Zvýšiť jas pri zobrazení čiarového kódu </string>
<string name="settings_lock_barcode_orientation">Uzamkni orientáciu čiarového kódu</string>
</resources>
<string name="deleteTitle">Odstrániť kartu</string>
<string name="deleteConfirmation">Naozaj chcete túto kartu odstrániť?</string>
</resources>

View File

@@ -12,8 +12,6 @@
<string name="confirm">Potrdi</string>
<string name="lockScreen">Onemogoči obračanje zaslona</string>
<string name="unlockScreen">Omogoči obračanje zaslona</string>
<string name="deleteTitle">Odstrani kartico zvestobe</string>
<string name="deleteConfirmation">Prosim potrdite, če želite izbrisati to kartico.</string>
<string name="ok">Vredu</string>
<string name="copy_to_clipboard">Kopirajte številko kartice</string>
<string name="sendLabel">Pošlji…</string>
@@ -56,4 +54,6 @@
<string name="settings_category_title_ui">Uporabniški vmesnik</string>
<string name="settings_display_barcode_max_brightness">Povečaj osvetljenost prikaza črtne kode</string>
<string name="settings_lock_barcode_orientation">Zakleni orientacijo črtne kode</string>
<string name="deleteTitle">Odstrani kartico zvestobe</string>
<string name="deleteConfirmation">Prosim potrdite, če želite izbrisati to kartico.</string>
</resources>

View File

@@ -134,8 +134,6 @@
<string name="share">Поділитися</string>
<string name="copy_to_clipboard">Копіювати ID до буферу обміну</string>
<string name="ok">ОК</string>
<string name="deleteConfirmation">Бажаєте видалити карту\?</string>
<string name="deleteTitle">Видалити карту</string>
<string name="unlockScreen">Розблокувати обертання</string>
<string name="lockScreen">Блокувати обертання</string>
<string name="confirm">Підтвердити</string>
@@ -153,7 +151,7 @@
<string name="action_search">Пошук</string>
<string name="turn_flashlight_off">Вимкнути спалах</string>
<string name="turn_flashlight_on">Увімкнути спалах</string>
<string name="failedGeneratingShareURL">Збій створення URL обміну. Будь ласка повідомте про цю помилку!</string>
<string name="failedGeneratingShareURL">Збій створення URL обміну. Будь ласка повідомте про цю помилку.</string>
<string name="passwordRequired">Будь ласка введіть пароль</string>
<string name="takePhoto">Зробити фото</string>
<string name="removeImage">Видалити зображення</string>
@@ -171,4 +169,6 @@
<item quantity="many">Обрано: <xliff:g>%d</xliff:g> карт</item>
<item quantity="other">Обрано: <xliff:g>%d</xliff:g> карт</item>
</plurals>
</resources>
<string name="deleteTitle">Видалити карту</string>
<string name="deleteConfirmation">Бажаєте видалити карту\?</string>
</resources>

View File

@@ -123,8 +123,6 @@
<string name="share">分享</string>
<string name="copy_to_clipboard">复制卡号到剪贴板</string>
<string name="ok">确定</string>
<string name="deleteConfirmation">删除此卡?</string>
<string name="deleteTitle">移除卡片</string>
<string name="unlockScreen">解除旋转锁定</string>
<string name="lockScreen">锁定旋转</string>
<string name="confirm">确认</string>
@@ -143,4 +141,6 @@
<string name="noGiftCards">点击 \"+\"加号按钮来添加卡片,或者先从⋮菜单中导入一些。</string>
<string name="action_add">添加</string>
<string name="action_search">搜索</string>
<string name="deleteConfirmation">删除此卡?</string>
<string name="deleteTitle">移除卡片</string>
</resources>

View File

@@ -5,8 +5,8 @@
<string name="action_search">Search</string>
<string name="action_add">Add</string>
<plurals name="selectedCardCount">
<item quantity="one">Selected: <xliff:g>%d</xliff:g> card</item>
<item quantity="other">Selected: <xliff:g>%d</xliff:g> cards</item>
<item quantity="one"><xliff:g>%d</xliff:g> card selected</item>
<item quantity="other"><xliff:g>%d</xliff:g> cards selected</item>
</plurals>
<string name="noGiftCards">Click the + plus button to add a card, or import some from the ⋮ menu first.</string>
@@ -29,8 +29,22 @@
<string name="confirm">Confirm</string>
<string name="lockScreen">Block Rotation</string>
<string name="unlockScreen">Unblock Rotation</string>
<string name="deleteTitle">Remove Card</string>
<string name="deleteConfirmation">Delete this card?</string>
<!-- START NOTE: i18n oddness -->
<!-- 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".
So while in English the extra non-plural form seems unnecessary duplication, it is necessary to give translators enough flexibility.
In Catima, we use the plain string when meaning exactly 1, and otherwise use the plural forms -->
<string name="deleteTitle">Delete card</string>
<plurals name="deleteCardsTitle">
<item quantity="one">Delete <xliff:g>%d</xliff:g> card</item>
<item quantity="other">Delete <xliff:g>%d</xliff:g> cards</item>
</plurals>
<string name="deleteConfirmation">Delete this card permanently?</string>
<plurals name="deleteCardsConfirmation">
<item quantity="one">Delete this <xliff:g>%d</xliff:g> card permanently?</item>
<item quantity="other">Delete these <xliff:g>%d</xliff:g> cards permanently?</item>
</plurals>
<!-- END NOTE: i18n oddness -->
<string name="ok">OK</string>
<string name="copy_to_clipboard">Copy ID to clipboard</string>
<string name="share">Share</string>
@@ -196,7 +210,7 @@
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="passwordRequired">Please enter the password</string>
<string name="failedGeneratingShareURL">Failed generating share URL. Please report this bug!</string>
<string name="failedGeneratingShareURL">Could not generate sharable URL. Please report this.</string>
<string name="turn_flashlight_on">Turn flashlight on</string>
<string name="turn_flashlight_off">Turn flashlight off</string>
</resources>

View File

@@ -1,6 +1,7 @@
package protect.card_locker;
import android.app.Activity;
import androidx.appcompat.app.AlertDialog;
import android.app.DatePickerDialog;
import android.content.Context;
import android.content.Intent;
@@ -9,7 +10,10 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
@@ -24,6 +28,7 @@ import android.widget.SeekBar;
import android.widget.TextView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.textfield.MaterialAutoCompleteTextView;
import com.google.android.material.textfield.TextInputLayout;
import com.google.zxing.BarcodeFormat;
@@ -38,6 +43,7 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.ShadowDialog;
import org.robolectric.shadows.ShadowLog;
@@ -55,6 +61,7 @@ import static android.os.Looper.getMainLooper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.robolectric.Shadows.shadowOf;
@@ -298,7 +305,11 @@ public class LoyaltyCardViewActivityTest
assertEquals(contents, textView.getEditText().getText().toString());
} else if (fieldType == FieldTypeView.ImageView) {
ImageView imageView = (ImageView) view;
// TODO: implement
Bitmap image = null;
if (imageView.getTag() != null) {
image = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
}
assertEquals(contents, image);
} else {
throw new UnsupportedOperationException();
}
@@ -308,7 +319,8 @@ public class LoyaltyCardViewActivityTest
final String store, final String note, final String expiryString,
final String balanceString, final String balanceTypeString,
final String cardId, final String barcodeId,
final String barcodeType)
final String barcodeType, final Bitmap frontImage,
final Bitmap backImage)
{
if(mode == ViewMode.VIEW_CARD)
{
@@ -326,9 +338,90 @@ public class LoyaltyCardViewActivityTest
checkFieldProperties(activity, R.id.cardIdView, View.VISIBLE, cardId, FieldTypeView.TextView);
checkFieldProperties(activity, R.id.barcodeIdField, View.VISIBLE, barcodeId, FieldTypeView.TextView);
checkFieldProperties(activity, R.id.barcodeTypeField, View.VISIBLE, barcodeType, FieldTypeView.TextView);
checkFieldProperties(activity, R.id.barcode, View.VISIBLE, null, FieldTypeView.ImageView);
checkFieldProperties(activity, R.id.frontImage, View.VISIBLE, null, FieldTypeView.ImageView);
checkFieldProperties(activity, R.id.backImage, View.VISIBLE, null, FieldTypeView.ImageView);
//checkFieldProperties(activity, R.id.barcode, View.VISIBLE, null, FieldTypeView.ImageView);
checkFieldProperties(activity, R.id.frontImage, View.VISIBLE, frontImage, FieldTypeView.ImageView);
checkFieldProperties(activity, R.id.backImage, View.VISIBLE, backImage, FieldTypeView.ImageView);
}
}
@Test
public void noDataLossOnResume()
{
registerMediaStoreIntentHandler();
for(boolean newCard : new boolean[] {false, true}) {
System.out.println();
System.out.println("=====");
System.out.println("New card? " + newCard);
System.out.println("=====");
System.out.println();
ActivityController activityController;
if (!newCard) {
activityController = createActivityWithLoyaltyCard(true);
} else {
activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
}
Activity activity = (Activity) activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
if (!newCard) {
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, Color.BLACK, 0);
}
activityController.start();
activityController.visible();
activityController.resume();
shadowOf(getMainLooper()).idle();
// Check default settings
checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, newCard ? "" : "store", newCard ? "" : "note", context.getString(R.string.never), "0", context.getString(R.string.points), newCard ? "" : EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), newCard ? context.getString(R.string.noBarcode) : EAN_BARCODE_TYPE.name(), null, null);
// Change everything
final EditText storeField = activity.findViewById(R.id.storeNameEdit);
final EditText noteField = activity.findViewById(R.id.noteEdit);
final EditText expiryField = activity.findViewById(R.id.expiryField);
final EditText balanceField = activity.findViewById(R.id.balanceField);
final EditText balanceTypeField = activity.findViewById(R.id.balanceCurrencyField);
final EditText cardIdField = activity.findViewById(R.id.cardIdView);
final EditText barcodeField = activity.findViewById(R.id.barcodeIdField);
final EditText barcodeTypeField = activity.findViewById(R.id.barcodeTypeField);
final ImageView frontImageView = activity.findViewById(R.id.frontImage);
final ImageView backImageView = activity.findViewById(R.id.backImage);
Currency currency = Currency.getInstance("EUR");
Date expiryDate = new Date();
Bitmap frontBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.circle);
Bitmap backBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.save_24dp);
storeField.setText("correct store");
noteField.setText("correct note");
LoyaltyCardEditActivity.formatExpiryField(context, expiryField, expiryDate);
balanceField.setText("100");
balanceTypeField.setText(currency.getSymbol());
cardIdField.setText("12345678");
barcodeField.setText("87654321");
barcodeTypeField.setText(BarcodeFormat.QR_CODE.name());
LoyaltyCardEditActivity.setCardImage(frontImageView, frontBitmap);
LoyaltyCardEditActivity.setCardImage(backImageView, backBitmap);
shadowOf(getMainLooper()).idle();
// Check if changed
checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", BarcodeFormat.QR_CODE.name(), frontBitmap, backBitmap);
// Resume
activityController.pause();
activityController.resume();
shadowOf(getMainLooper()).idle();
// Check if no changes lost
checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", BarcodeFormat.QR_CODE.name(), frontBitmap, backBitmap);
}
}
@@ -343,7 +436,7 @@ public class LoyaltyCardViewActivityTest
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),"");
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
@@ -403,12 +496,12 @@ public class LoyaltyCardViewActivityTest
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),"");
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);
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.toString());
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.toString(), null, null);
shadowOf(getMainLooper()).idle();
@@ -427,12 +520,14 @@ public class LoyaltyCardViewActivityTest
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), "");
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);
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),"");
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);
}
@Test
@@ -446,12 +541,12 @@ 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),"");
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);
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.toString());
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.toString(), null, null);
// Cancel the loyalty card creation
assertEquals(false, activity.isFinishing());
@@ -507,7 +602,7 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
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.toString());
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.toString(), null, null);
db.close();
}
@@ -526,7 +621,7 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.VIEW_CARD, "store", "note", null, "0", context.getString(R.string.points), BARCODE_DATA, null, BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.VIEW_CARD, "store", "note", null, "0", context.getString(R.string.points), BARCODE_DATA, null, BARCODE_TYPE.toString(), null, null);
db.close();
}
@@ -545,12 +640,12 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
// Complete barcode capture successfully
captureBarcodeWithResult(activity, true);
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.toString());
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.toString(), null, null);
db.close();
}
@@ -569,12 +664,12 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
// Complete barcode capture successfully
captureBarcodeWithResult(activity, true);
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.toString());
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.toString(), null, null);
// Cancel the loyalty card creation
assertEquals(false, activity.isFinishing());
@@ -607,7 +702,7 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
// Set date to today
MaterialAutoCompleteTextView expiryField = activity.findViewById(R.id.expiryField);
@@ -621,7 +716,7 @@ public class LoyaltyCardViewActivityTest
shadowOf(getMainLooper()).idle();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", DateFormat.getDateInstance(DateFormat.LONG).format(new Date()), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", DateFormat.getDateInstance(DateFormat.LONG).format(new Date()), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
db.close();
}
@@ -640,13 +735,13 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", DateFormat.getDateInstance(DateFormat.LONG).format(new Date()), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", DateFormat.getDateInstance(DateFormat.LONG).format(new Date()), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
// Set date to never
MaterialAutoCompleteTextView expiryField = activity.findViewById(R.id.expiryField);
expiryField.setText(expiryField.getAdapter().getItem(0).toString(), false);
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
db.close();
}
@@ -665,7 +760,7 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
// Set balance to 10 points
EditText balanceField = activity.findViewById(R.id.balanceField);
@@ -694,7 +789,7 @@ public class LoyaltyCardViewActivityTest
shadowOf(getMainLooper()).idle();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", DateFormat.getDateInstance(DateFormat.LONG).format(new Date()), "10.00", "", EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", DateFormat.getDateInstance(DateFormat.LONG).format(new Date()), "10.00", "", EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE.toString(), null, null);
db.close();
}
@@ -716,7 +811,7 @@ public class LoyaltyCardViewActivityTest
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "10.00", "$", EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "10.00", "$", EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
shadowOf(getMainLooper()).idle();
@@ -738,7 +833,147 @@ public class LoyaltyCardViewActivityTest
shadowOf(getMainLooper()).idle();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", "", EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString());
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", "", EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
db.close();
}
@Test
public void startWithLoyaltyCardSameAsCardIDUpdateBarcodeID()
{
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, Color.BLACK, 0);
activityController.start();
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
// Change barcode ID
EditText barcodeField = activity.findViewById(R.id.barcodeIdField);
barcodeField.setText("123456");
// Switch away from card ID and ensure no dialog appears
TabLayout tabs = activity.findViewById(R.id.tabs);
tabs.getTabAt(2).select();
shadowOf(getMainLooper()).idle();
AlertDialog updateBarcodeIdDialog = (AlertDialog) (ShadowDialog.getLatestDialog());
assertNull(updateBarcodeIdDialog);
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, "123456", EAN_BARCODE_TYPE.toString(), null, null);
db.close();
}
@Test
public void startWithLoyaltyCardSameAsCardIDUpdateCardID()
{
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, Color.BLACK, 0);
activityController.start();
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
// Change card ID
EditText cardIdField = activity.findViewById(R.id.cardIdView);
cardIdField.setText("123456");
// Switch away from card ID and ensure no dialog appears
TabLayout tabs = activity.findViewById(R.id.tabs);
tabs.getTabAt(2).select();
shadowOf(getMainLooper()).idle();
AlertDialog updateBarcodeIdDialog = (AlertDialog) (ShadowDialog.getLatestDialog());
assertNull(updateBarcodeIdDialog);
shadowOf(getMainLooper()).idle();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), "123456", context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
db.close();
}
@Test
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDUpdate()
{
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, EAN_BARCODE_DATA, "123456", EAN_BARCODE_TYPE, Color.BLACK, 0);
activityController.start();
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, "123456", EAN_BARCODE_TYPE.toString(), null, null);
// Change card ID
EditText cardIdField = activity.findViewById(R.id.cardIdView);
cardIdField.setText("654321");
shadowOf(getMainLooper()).idle();
// Switch away from card ID and ensure the dialog appears
TabLayout tabs = activity.findViewById(R.id.tabs);
tabs.getTabAt(2).select();
shadowOf(getMainLooper()).idle();
AlertDialog updateBarcodeIdDialog = (AlertDialog) ShadowDialog.getLatestDialog();
assertNotNull(updateBarcodeIdDialog);
updateBarcodeIdDialog.getButton(DatePickerDialog.BUTTON_POSITIVE).performClick();
shadowOf(getMainLooper()).idle();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), "654321", context.getString(R.string.sameAsCardId), EAN_BARCODE_TYPE.toString(), null, null);
db.close();
}
@Test
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDDoNotUpdate()
{
ActivityController activityController = createActivityWithLoyaltyCard(true);
Activity activity = (Activity)activityController.get();
final Context context = activity.getApplicationContext();
DBHelper db = TestHelpers.getEmptyDb(activity);
db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, EAN_BARCODE_DATA, "123456", EAN_BARCODE_TYPE, Color.BLACK, 0);
activityController.start();
activityController.visible();
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), EAN_BARCODE_DATA, "123456", EAN_BARCODE_TYPE.toString(), null, null);
// Change card ID
EditText cardIdField = activity.findViewById(R.id.cardIdView);
cardIdField.setText("654321");
shadowOf(getMainLooper()).idle();
// Switch away from card ID and ensure the dialog appears
TabLayout tabs = activity.findViewById(R.id.tabs);
tabs.getTabAt(2).select();
shadowOf(getMainLooper()).idle();
AlertDialog updateBarcodeIdDialog = (AlertDialog) (ShadowDialog.getLatestDialog());
assertNotNull(updateBarcodeIdDialog);
updateBarcodeIdDialog.getButton(DatePickerDialog.BUTTON_NEGATIVE).performClick();
shadowOf(getMainLooper()).idle();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), "654321", "123456", EAN_BARCODE_TYPE.toString(), null, null);
db.close();
}
@@ -881,13 +1116,13 @@ public class LoyaltyCardViewActivityTest
activityController.resume();
// First check if the card is 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), BARCODE_TYPE.toString());
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.toString(), null, null);
// Complete empty barcode selection successfully
selectBarcodeWithResult(activity, BARCODE_DATA, "", true);
// 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));
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);
assertEquals(View.GONE, activity.findViewById(R.id.barcodeLayout).getVisibility());
// Check if the special NO_BARCODE string doesn't get saved
@@ -1127,7 +1362,7 @@ public class LoyaltyCardViewActivityTest
shadowOf(getMainLooper()).idle();
checkAllFields(activity, ViewMode.ADD_CARD, "Example Store", "", DateFormat.getDateInstance(DateFormat.LONG).format(date), "10.00", "$", "123456", context.getString(R.string.sameAsCardId), "AZTEC");
checkAllFields(activity, ViewMode.ADD_CARD, "Example Store", "", DateFormat.getDateInstance(DateFormat.LONG).format(date), "10.00", "$", "123456", context.getString(R.string.sameAsCardId), "AZTEC", null, null);
assertEquals(-416706, ((ColorDrawable) activity.findViewById(R.id.thumbnail).getBackground()).getColor());
}
@@ -1148,7 +1383,7 @@ public class LoyaltyCardViewActivityTest
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");
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);
assertEquals(-416706, ((ColorDrawable) activity.findViewById(R.id.thumbnail).getBackground()).getColor());
}
}

View File

@@ -0,0 +1,23 @@
Deja de buscar tarjetas de recompensa de plástico durante la compra en la tienda o en la web.
<b>Escanea los códigos de barras en tu dispositivo usando su cámara, olvídate de las tarjetas.</b>
😺
Olvídate de la cartera, o téngala ultraligera para los objetos de valor.
😺
Con esta herramienta esencial para llevar a diario (EDC) puedes sustituir el plástico inútil por el dinero en efectivo.
😺
- Evita el espionaje con muy pocos permisos. Sin acceso a Internet y sin anuncios.
- Añade tarjetas o códigos con nombres y colores personalizables.
- Introduce manual de códigos si no hay código de barras que almacenar, o no se puede utilizar.
- Importe tarjetas y códigos desde archivos, Catima, FidMe, Llavero de tarjetas de fidelidad, Stocard y Voucher Vault.
- Haz respaldos de todas tus tarjetas y mígralas a un nuevo dispositivo si lo necesita.
- Comparte cupones, ofertas exclusivas, códigos promocionales o tarjetas y códigos utilizando cualquier aplicación.
- Tema oscuro y opciones de accesibilidad para usuarios con problemas de visión.
- Hecho para todos por la comunidad del software libre.
- Traducciones localizadas a mano para más de 20 idiomas.
- Gratis, apoyado por las contribuciones de la comunidad.
- Utiliza, estudia, cambia y comparte como quieras; <i>con quien quieras</i>.
- No sólo Software Libre / Open Source. Es un software de gestión de tarjetas libre y <i>copyleft</i> (GPLv3+).
😺
Simplifica tu vida y tus compras, y no vuelvas a perder un recibo de papel, una tarjeta regalo de pago en tienda o un billete de avión.
Lleva contigo todas tus recompensas y bonos, y ahorra sobre la marcha.
😺

View File

@@ -0,0 +1 @@
Para códigos de barras, membresías, sistema de fidelidad, cupones y tickets.

View File

@@ -0,0 +1 @@
Catima — La Billetera Libre para Tarjetas

View File

@@ -1,5 +1,6 @@
#Sun Jul 25 20:59:51 CEST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME