Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions app/src/main/java/protect/card_locker/DBHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,30 @@ public static LoyaltyCard getLoyaltyCard(Context context, SQLiteDatabase databas
return card;
}

public static List<LoyaltyCard> getLoyaltyCardsByCardId(Context context, SQLiteDatabase database, final String cardId) {
List<LoyaltyCard> cards = new ArrayList<>();

Cursor data = database.query(
LoyaltyCardDbIds.TABLE,
null,
whereAttrs(LoyaltyCardDbIds.CARD_ID),
withArgs(cardId),
null,
null,
null
);

if (data.moveToFirst()) {
do {
LoyaltyCard card = LoyaltyCard.fromCursor(context, data);
cards.add(card);
} while (data.moveToNext());
}

data.close();
return cards;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if you confused this with the unique ID before (this is the barcode value basically). If your plan was to limit the amount of loyalty cards to loop over, you could still just use getLoyaltyCardCursor and limit it by the store instead of creating a new function. The DBHelper class is already way too complex, so I'd rather prevent extra complexity there whenever possible.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know it's a barcode. I didn't want to compare the imported card with all the others, so I chose the barcode as a filter.

Previously, the code only compared the card with an existing card with the same ID, which led to duplicates. Since the ID is assigned randomly, it must be removed from the comparison.

This part of the code is therefore essential from a performance perspective.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part of the code is therefore essential from a performance perspective.

I mean, not really, you can also just call one of the existing getLoyaltyCardCursor functions and use the store name as the filter. In fact that would be better, because a cursor lets you loop over the results without loading them all into memory :)

I do agree that removing the database ID from the comparison is correct though.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's think about a reality.
How many users want to have multiple cards with same Barcode?
How many users want to have multiple cards with same store name?

Both of these are very rare, but I think that the first one is absolutely illogical.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reality is that both will be fairly rare, but the second one doesn't need a new function. And thus is cleaner and easier for long-term maintenance of the codebase.

public static List<Group> getLoyaltyCardGroups(SQLiteDatabase database, final int id) {
Cursor data = database.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE + " g " +
" LEFT JOIN " + LoyaltyCardDbIdsGroups.TABLE + " ig ON ig." + LoyaltyCardDbIdsGroups.groupID + " = g." + LoyaltyCardDbGroups.ID +
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/protect/card_locker/LoyaltyCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -582,8 +582,7 @@ public static LoyaltyCard fromCursor(Context context, Cursor cursor) {
public static boolean isDuplicate(Context context, final LoyaltyCard a, final LoyaltyCard b) {
// Note: Bitmap comparing is slow, be careful when calling this method
// Skip lastUsed & zoomLevel*
return a.id == b.id && // non-nullable int
a.store.equals(b.store) && // non-nullable String
return a.store.equals(b.store) && // non-nullable String
a.note.equals(b.note) && // non-nullable String
Utils.equals(a.validFrom, b.validFrom) && // nullable Date
Utils.equals(a.expiry, b.expiry) && // nullable Date
Expand Down
50 changes: 0 additions & 50 deletions app/src/main/java/protect/card_locker/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.DecimalFormat;
Expand All @@ -91,16 +89,13 @@
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import protect.card_locker.preferences.Settings;

public class Utils {
private static final String TAG = "Catima";

// Activity request codes
public static final int MAIN_REQUEST = 1;
public static final int SELECT_BARCODE_REQUEST = 2;
public static final int BARCODE_SCAN = 3;
public static final int BARCODE_IMPORT_FROM_IMAGE_FILE = 4;
Expand All @@ -113,8 +108,6 @@ public class Utils {
public static final int CARD_IMAGE_FROM_FILE_BACK = 11;
public static final int CARD_IMAGE_FROM_FILE_ICON = 12;

public static final String CARD_IMAGE_FILENAME_REGEX = "^(card_)(\\d+)(_(?:front|back|icon)\\.png)$";

static final double LUMINANCE_MIDPOINT = 0.5;

static final int BITMAP_SIZE_SMALL = 512;
Expand Down Expand Up @@ -724,31 +717,6 @@ static public String getCardImageFileName(int loyaltyCardId, ImageLocationType t
return cardImageFileNameBuilder.toString();
}

/**
* Returns a card image filename (string) with the ID replaced according to the map if the input is a valid card image filename (string), otherwise null.
*
* @param fileName e.g. "card_1_front.png"
* @param idMap e.g. Map.of(1, 2)
* @return String e.g. "card_2_front.png"
*/
static public String getRenamedCardImageFileName(final String fileName, final Map<Integer, Integer> idMap) {
Pattern pattern = Pattern.compile(CARD_IMAGE_FILENAME_REGEX);
Matcher matcher = pattern.matcher(fileName);
if (matcher.matches()) {
StringBuilder cardImageFileNameBuilder = new StringBuilder();
cardImageFileNameBuilder.append(matcher.group(1));
try {
int id = Integer.parseInt(matcher.group(2));
cardImageFileNameBuilder.append(idMap.getOrDefault(id, id));
} catch (NumberFormatException _e) {
return null;
}
cardImageFileNameBuilder.append(matcher.group(3));
return cardImageFileNameBuilder.toString();
}
return null;
}

static public void saveCardImage(Context context, Bitmap bitmap, String fileName) throws FileNotFoundException {
if (bitmap == null) {
context.deleteFile(fileName);
Expand Down Expand Up @@ -1132,24 +1100,6 @@ public static int getHeaderColor(Context context, LoyaltyCard loyaltyCard) {
return loyaltyCard.headerColor != null ? loyaltyCard.headerColor : LetterBitmap.getDefaultColor(context, loyaltyCard.store);
}

public static String checksum(InputStream input) throws IOException {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] buf = new byte[4096];
int len;
while ((len = input.read(buf)) != -1) {
md.update(buf, 0, len);
}
StringBuilder sb = new StringBuilder();
for (byte b : md.digest()) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException _e) {
return null;
}
}

public static boolean equals(final Object a, final Object b) {
if (a == null && b == null) {
return true;
Expand Down
Loading