From 26bbea737773e5f252f34a74be2d58a8c739b61c Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Tue, 22 Mar 2022 20:25:39 +0100 Subject: [PATCH 1/5] Fix Stocard import getting stuck --- .../protect/card_locker/importexport/StocardImporter.java | 2 +- .../test/java/protect/card_locker/ImportExportTest.java | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/main/java/protect/card_locker/importexport/StocardImporter.java b/app/src/main/java/protect/card_locker/importexport/StocardImporter.java index d51091986..d3ac1103a 100644 --- a/app/src/main/java/protect/card_locker/importexport/StocardImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/StocardImporter.java @@ -162,7 +162,7 @@ public class StocardImporter implements Importer { String cardId = (String) loyaltyCardData.get("cardId"); String barcodeTypeString = (String) Utils.mapGetOrDefault(loyaltyCardData, "barcodeType", providerData != null ? providerData.get("barcodeFormat") : null); CatimaBarcode barcodeType = null; - if (barcodeTypeString != null) { + if (barcodeTypeString != null && !barcodeTypeString.isEmpty()) { if (barcodeTypeString.equals("RSS_DATABAR_EXPANDED")) { barcodeType = CatimaBarcode.fromBarcode(BarcodeFormat.RSS_EXPANDED); } else { diff --git a/app/src/test/java/protect/card_locker/ImportExportTest.java b/app/src/test/java/protect/card_locker/ImportExportTest.java index f5e3085f5..8627c0af0 100644 --- a/app/src/test/java/protect/card_locker/ImportExportTest.java +++ b/app/src/test/java/protect/card_locker/ImportExportTest.java @@ -64,9 +64,6 @@ import static org.robolectric.Shadows.shadowOf; public class ImportExportTest { private Activity activity; private SQLiteDatabase mDatabase; - private long nowMs; - private long lastYearMs; - private final int MONTHS_PER_YEAR = 12; private final String BARCODE_DATA = "428311627547"; private final CatimaBarcode BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A); @@ -77,11 +74,6 @@ public class ImportExportTest { activity = Robolectric.setupActivity(MainActivity.class); mDatabase = TestHelpers.getEmptyDb(activity).getWritableDatabase(); - nowMs = System.currentTimeMillis(); - - Calendar lastYear = Calendar.getInstance(); - lastYear.set(Calendar.YEAR, lastYear.get(Calendar.YEAR) - 1); - lastYearMs = lastYear.getTimeInMillis(); } /** From 329293fa7c26f95efff207d4b33e40938090c253 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Tue, 22 Mar 2022 21:26:36 +0100 Subject: [PATCH 2/5] Support custom providers in Stocard import --- .../importexport/StocardImporter.java | 80 +++++++++++++++---- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/protect/card_locker/importexport/StocardImporter.java b/app/src/main/java/protect/card_locker/importexport/StocardImporter.java index d3ac1103a..33595b084 100644 --- a/app/src/main/java/protect/card_locker/importexport/StocardImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/StocardImporter.java @@ -41,13 +41,13 @@ import protect.card_locker.ZipUtils; public class StocardImporter implements Importer { public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException { HashMap> loyaltyCardHashMap = new HashMap<>(); - HashMap> providers = new HashMap<>(); + HashMap> providers = new HashMap<>(); final CSVParser parser = new CSVParser(new InputStreamReader(context.getResources().openRawResource(R.raw.stocard_stores), StandardCharsets.UTF_8), CSVFormat.RFC4180.builder().setHeader().build()); try { for (CSVRecord record : parser) { - HashMap recordData = new HashMap<>(); + HashMap recordData = new HashMap<>(); recordData.put("name", record.get("name")); recordData.put("barcodeFormat", record.get("barcodeFormat")); @@ -62,6 +62,8 @@ public class StocardImporter implements Importer { ZipInputStream zipInputStream = new ZipInputStream(input, password); String[] providersFileName = null; + String[] customProvidersBaseName = null; + String customProviderId = ""; String[] cardBaseName = null; String cardName = ""; LocalFileHeader localFileHeader; @@ -78,6 +80,14 @@ public class StocardImporter implements Importer { nameParts[0], "analytics-properties.json" }; + customProvidersBaseName = new String[]{ + nameParts[0], + "sync", + "data", + "users", + nameParts[0], + "loyalty-card-custom-providers" + }; cardBaseName = new String[]{ nameParts[0], "sync", @@ -88,6 +98,33 @@ public class StocardImporter implements Importer { }; } + if (startsWith(nameParts, customProvidersBaseName, 1)) { + // Extract providerId + customProviderId = nameParts[customProvidersBaseName.length].split("\\.", 2)[0]; + + // Name file + if (nameParts.length == customProvidersBaseName.length + 1) { + // Ignore the .txt file + if (fileName.endsWith(".json")) { + JSONObject jsonObject = ZipUtils.readJSON(zipInputStream); + + providers = appendToHashMap( + providers, + customProviderId, + "name", + jsonObject.getString("name") + ); + } + } else if (fileName.endsWith("logo.png")) { + providers = appendToHashMap( + providers, + customProviderId, + "logo", + ZipUtils.readImage(zipInputStream) + ); + } + } + if (startsWith(nameParts, cardBaseName, 1)) { // Extract cardName cardName = nameParts[cardBaseName.length].split("\\.", 2)[0]; @@ -98,24 +135,33 @@ public class StocardImporter implements Importer { if (fileName.endsWith(".json")) { JSONObject jsonObject = ZipUtils.readJSON(zipInputStream); - loyaltyCardHashMap = appendToLoyaltyCardHashMap( + loyaltyCardHashMap = appendToHashMap( loyaltyCardHashMap, cardName, "cardId", jsonObject.getString("input_id") ); - loyaltyCardHashMap = appendToLoyaltyCardHashMap( + + // Provider ID can be either custom or not, extract whatever version is relevant + String customProviderPrefix = "/users/" + nameParts[0] + "/loyalty-card-custom-providers/"; + String providerId = jsonObject + .getJSONObject("input_provider_reference") + .getString("identifier"); + if (providerId.startsWith(customProviderPrefix)) { + providerId = providerId.substring(customProviderPrefix.length()); + } else { + providerId = providerId.substring("/loyalty-card-providers/".length()); + } + + loyaltyCardHashMap = appendToHashMap( loyaltyCardHashMap, cardName, "_providerId", - jsonObject - .getJSONObject("input_provider_reference") - .getString("identifier") - .substring("/loyalty-card-providers/".length()) + providerId ); if (jsonObject.has("input_barcode_format")) { - loyaltyCardHashMap = appendToLoyaltyCardHashMap( + loyaltyCardHashMap = appendToHashMap( loyaltyCardHashMap, cardName, "barcodeType", @@ -124,7 +170,7 @@ public class StocardImporter implements Importer { } } } else if (fileName.endsWith("notes/default.json")) { - loyaltyCardHashMap = appendToLoyaltyCardHashMap( + loyaltyCardHashMap = appendToHashMap( loyaltyCardHashMap, cardName, "note", @@ -132,14 +178,14 @@ public class StocardImporter implements Importer { .getString("content") ); } else if (fileName.endsWith("/images/front.png")) { - loyaltyCardHashMap = appendToLoyaltyCardHashMap( + loyaltyCardHashMap = appendToHashMap( loyaltyCardHashMap, cardName, "frontImage", ZipUtils.readImage(zipInputStream) ); } else if (fileName.endsWith("/images/back.png")) { - loyaltyCardHashMap = appendToLoyaltyCardHashMap( + loyaltyCardHashMap = appendToHashMap( loyaltyCardHashMap, cardName, "backImage", @@ -155,9 +201,9 @@ public class StocardImporter implements Importer { for (HashMap loyaltyCardData : loyaltyCardHashMap.values()) { String providerId = (String) loyaltyCardData.get("_providerId"); - HashMap providerData = providers.get(providerId); + HashMap providerData = providers.get(providerId); - String store = providerData != null ? providerData.get("name") : providerId; + String store = providerData != null ? providerData.get("name").toString() : providerId; String note = (String) Utils.mapGetOrDefault(loyaltyCardData, "note", ""); String cardId = (String) loyaltyCardData.get("cardId"); String barcodeTypeString = (String) Utils.mapGetOrDefault(loyaltyCardData, "barcodeType", providerData != null ? providerData.get("barcodeFormat") : null); @@ -172,6 +218,10 @@ public class StocardImporter implements Importer { long loyaltyCardInternalId = DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, null, 0, null); + if (providerData != null && providerData.containsKey("logo")) { + Utils.saveCardImage(context, (Bitmap) providerData.get("logo"), (int) loyaltyCardInternalId, ImageLocationType.icon); + } + if (loyaltyCardData.containsKey("frontImage")) { Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("frontImage"), (int) loyaltyCardInternalId, ImageLocationType.front); } @@ -197,7 +247,7 @@ public class StocardImporter implements Importer { return true; } - private HashMap> appendToLoyaltyCardHashMap(HashMap> loyaltyCardHashMap, String cardID, String key, Object value) { + private HashMap> appendToHashMap(HashMap> loyaltyCardHashMap, String cardID, String key, Object value) { HashMap loyaltyCardData = loyaltyCardHashMap.get(cardID); if (loyaltyCardData == null) { loyaltyCardData = new HashMap<>(); From 86a01d36db8337f8463ebc154529d8392a3dab83 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Tue, 22 Mar 2022 21:46:37 +0100 Subject: [PATCH 3/5] Fix background color generation --- .../card_locker/LoyaltyCardEditActivity.java | 7 ++----- app/src/main/java/protect/card_locker/Utils.java | 16 ++++++++++++++++ .../importexport/StocardImporter.java | 13 ++++++++++--- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java index 7cd6ed737..f80a782bb 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java @@ -855,10 +855,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity { // 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()); - updateTempState(LoyaltyCardField.headerColor, colors.getColor(color, Color.BLACK)); - colors.recycle(); + updateTempState(LoyaltyCardField.headerColor, Utils.getRandomHeaderColor(this)); } // It can't be null because we set it in updateTempState but SpotBugs insists it can be @@ -919,7 +916,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity { protected void setColorFromIcon() { Object icon = thumbnail.getTag(); if (icon != null && (icon instanceof Bitmap)) { - updateTempState(LoyaltyCardField.headerColor, new Palette.Builder((Bitmap) icon).generate().getDominantColor(tempLoyaltyCard.headerColor != null ? tempLoyaltyCard.headerColor : R.attr.colorPrimary)); + updateTempState(LoyaltyCardField.headerColor, Utils.getHeaderColorFromImage((Bitmap) icon, tempLoyaltyCard.headerColor)); } else { Log.d("setColorFromIcon", "attempting header color change from icon but icon does not exist"); } diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java index 55e9d86d0..43175783d 100644 --- a/app/src/main/java/protect/card_locker/Utils.java +++ b/app/src/main/java/protect/card_locker/Utils.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; @@ -48,6 +49,7 @@ import androidx.appcompat.app.AppCompatDelegate; import androidx.core.graphics.ColorUtils; import androidx.exifinterface.media.ExifInterface; +import androidx.palette.graphics.Palette; import protect.card_locker.preferences.Settings; public class Utils { @@ -518,4 +520,18 @@ public class Utils { item.setTitle(R.string.action_show_details); } } + + public static int getHeaderColorFromImage(Bitmap image, int fallback) { + if (image == null) { + return fallback; + } + + return new Palette.Builder(image).generate().getDominantColor(R.attr.colorPrimary); + } + + public static int getRandomHeaderColor(Context context) { + TypedArray colors = context.getResources().obtainTypedArray(R.array.letter_tile_colors); + final int color = (int) (Math.random() * colors.length()); + return colors.getColor(color, Color.BLACK); + } } diff --git a/app/src/main/java/protect/card_locker/importexport/StocardImporter.java b/app/src/main/java/protect/card_locker/importexport/StocardImporter.java index 33595b084..6a5ae3c33 100644 --- a/app/src/main/java/protect/card_locker/importexport/StocardImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/StocardImporter.java @@ -216,10 +216,17 @@ public class StocardImporter implements Importer { } } - long loyaltyCardInternalId = DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, null, 0, null); - + int headerColor = Utils.getRandomHeaderColor(context); + Bitmap cardIcon = null; if (providerData != null && providerData.containsKey("logo")) { - Utils.saveCardImage(context, (Bitmap) providerData.get("logo"), (int) loyaltyCardInternalId, ImageLocationType.icon); + cardIcon = (Bitmap) providerData.get("logo"); + headerColor = Utils.getHeaderColorFromImage(cardIcon, headerColor); + } + + long loyaltyCardInternalId = DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, 0, null); + + if (cardIcon != null) { + Utils.saveCardImage(context, cardIcon, (int) loyaltyCardInternalId, ImageLocationType.icon); } if (loyaltyCardData.containsKey("frontImage")) { From 420886bc3f6556747dd6b0f999e31938c872e880 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Tue, 22 Mar 2022 21:59:35 +0100 Subject: [PATCH 4/5] Make SpotBugs happy --- .../main/java/protect/card_locker/LoyaltyCardEditActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java index f80a782bb..15cc1c2e5 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java @@ -916,7 +916,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity { protected void setColorFromIcon() { Object icon = thumbnail.getTag(); if (icon != null && (icon instanceof Bitmap)) { - updateTempState(LoyaltyCardField.headerColor, Utils.getHeaderColorFromImage((Bitmap) icon, tempLoyaltyCard.headerColor)); + updateTempState(LoyaltyCardField.headerColor, Utils.getHeaderColorFromImage((Bitmap) icon, tempLoyaltyCard.headerColor != null ? tempLoyaltyCard.headerColor : R.attr.colorPrimary)); } else { Log.d("setColorFromIcon", "attempting header color change from icon but icon does not exist"); } From 27443db9457fcdd98c6ef20eab77fdd8e4c00ed7 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Wed, 23 Mar 2022 17:31:11 +0100 Subject: [PATCH 5/5] Import fix --- app/src/main/res/raw/stocard_stores.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/raw/stocard_stores.csv b/app/src/main/res/raw/stocard_stores.csv index f0732895e..0a9a687c2 100644 --- a/app/src/main/res/raw/stocard_stores.csv +++ b/app/src/main/res/raw/stocard_stores.csv @@ -440,7 +440,7 @@ _id,name,barcodeFormat 450,CAD,EAN_13 451,Camomilla,EAN_13 452,"Carpisa Yamamay",EAN_13 -453,Carrefour,EAN_13 +453,Carrefour,CODE_128 454,"Cisalfa Sport",EAN_13 455,Coin,ITF 456,Comet,EAN_13