diff --git a/CHANGELOG.md b/CHANGELOG.md index 4296e278..d1d25fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v2.0.2 (2021-07-25) + +Changes: + +- Fix inability to configure photos in new loyalty card + ## v2.0.1 (2021-07-21) Changes: diff --git a/app/src/main/java/protect/card_locker/LoyaltyCard.java b/app/src/main/java/protect/card_locker/LoyaltyCard.java index e2fc9847..3968c091 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCard.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCard.java @@ -7,11 +7,12 @@ import com.google.zxing.BarcodeFormat; import java.math.BigDecimal; import java.util.Currency; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import androidx.annotation.Nullable; -public class LoyaltyCard -{ +public class LoyaltyCard { public final int id; public final String store; public final String note; diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java index b5ba115d..2c453ed1 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java @@ -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,43 @@ public class LoyaltyCardEditActivity extends AppCompatActivity String tempCameraPicturePath; + LoyaltyCard tempLoyaltyCard; + + private static LoyaltyCard updateTempState(LoyaltyCard loyaltyCard, LoyaltyCardField fieldName, Object value) { + Map cardData = new HashMap<>(); + for (LoyaltyCardField existingFieldName : LoyaltyCardField.values()) { + try { + Field field = LoyaltyCard.class.getField(existingFieldName.name()); + cardData.put(existingFieldName, field.get(loyaltyCard)); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + return null; + } + } + + cardData.put(fieldName, value); + + return new LoyaltyCard( + (int) cardData.get(LoyaltyCardField.id), + (String) cardData.get(LoyaltyCardField.store), + (String) cardData.get(LoyaltyCardField.note), + (Date) cardData.get(LoyaltyCardField.expiry), + (BigDecimal) cardData.get(LoyaltyCardField.balance), + (Currency) cardData.get(LoyaltyCardField.balanceType), + (String) cardData.get(LoyaltyCardField.cardId), + (String) cardData.get(LoyaltyCardField.barcodeId), + (BarcodeFormat) cardData.get(LoyaltyCardField.barcodeType), + (Integer) cardData.get(LoyaltyCardField.headerColor), + (int) cardData.get(LoyaltyCardField.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 +202,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 +258,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 +266,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 +289,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 +314,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 +324,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 +345,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 +353,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 +401,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 +433,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 +448,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 +458,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 +465,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 +488,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 +545,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 +555,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); + } 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)); + setCardImage(cardImageFront, (Bitmap) cardImageFront.getTag()); + setCardImage(cardImageBack, (Bitmap) cardImageBack.getTag()); if(groupsChips.getChildCount() == 0) { @@ -685,16 +627,17 @@ 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)); + thumbnail.setOnClickListener(new ColorSelectListener(tempLoyaltyCard.headerColor)); // Update from intent if (barcodeType != null) { @@ -717,6 +660,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,6 +684,8 @@ public class LoyaltyCardEditActivity extends AppCompatActivity saveButton.bringToFront(); generateIcon(storeFieldEdit.getText().toString()); + + onResuming = false; } protected static void setCardImage(ImageView imageView, Bitmap bitmap) { @@ -747,9 +698,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 +756,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(); @@ -981,9 +928,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 +968,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 +978,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 +1005,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 +1016,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); @@ -1159,8 +1098,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 +1118,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 +1138,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 +1159,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 +1193,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()); diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardField.java b/app/src/main/java/protect/card_locker/LoyaltyCardField.java new file mode 100644 index 00000000..6971b9be --- /dev/null +++ b/app/src/main/java/protect/card_locker/LoyaltyCardField.java @@ -0,0 +1,15 @@ +package protect.card_locker; + +public enum LoyaltyCardField { + id, + store, + note, + expiry, + balance, + balanceType, + cardId, + barcodeId, + barcodeType, + headerColor, + starStatus +} diff --git a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java index ac0a4a4f..c6cf3dd1 100644 --- a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java +++ b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java @@ -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; @@ -27,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; @@ -41,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; @@ -58,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; @@ -346,6 +350,12 @@ public class LoyaltyCardViewActivityTest 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) { @@ -369,7 +379,7 @@ public class LoyaltyCardViewActivityTest shadowOf(getMainLooper()).idle(); // Check default settings - checkAllFields(activity, ViewMode.ADD_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 ? "" : EAN_BARCODE_TYPE.name(), null, null); + 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); @@ -377,22 +387,23 @@ public class LoyaltyCardViewActivityTest 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 TextInputLayout cardIdField = activity.findViewById(R.id.cardIdField); + 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"); - expiryField.setText(expiryDate.toString()); + LoyaltyCardEditActivity.formatExpiryField(context, expiryField, expiryDate); balanceField.setText("100"); - balanceTypeField.setText("EUR"); - cardIdField.getEditText().setText("12345678"); + balanceTypeField.setText(currency.getSymbol()); + cardIdField.setText("12345678"); barcodeField.setText("87654321"); barcodeTypeField.setText(BarcodeFormat.QR_CODE.name()); LoyaltyCardEditActivity.setCardImage(frontImageView, frontBitmap); @@ -401,16 +412,16 @@ public class LoyaltyCardViewActivityTest shadowOf(getMainLooper()).idle(); // Check if changed - checkAllFields(activity, ViewMode.ADD_CARD, "correct store", "correct note", expiryDate.toString(), "100", "EUR", "12345678", "87654321", BarcodeFormat.QR_CODE.name(), frontBitmap, backBitmap); + 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.stop(); + activityController.pause(); activityController.resume(); shadowOf(getMainLooper()).idle(); // Check if no changes lost - checkAllFields(activity, ViewMode.ADD_CARD, "correct store", "correct note", expiryDate.toString(), "100", "EUR", "12345678", "87654321", BarcodeFormat.QR_CODE.name(), frontBitmap, backBitmap); + 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); } } @@ -425,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),"", null, null); + checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never) , "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null); } @Test @@ -485,7 +496,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),"", null, null); + checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null); // Complete barcode capture successfully captureBarcodeWithResult(activity, true); @@ -509,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), "", null, null); + checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null); // Complete barcode capture 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),"", null, null); + 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 @@ -528,7 +541,7 @@ 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),"", null, null); + checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), "", context.getString(R.string.sameAsCardId),context.getString(R.string.noBarcode), null, null); // Complete barcode capture successfully captureBarcodeWithResult(activity, true); @@ -825,6 +838,146 @@ public class LoyaltyCardViewActivityTest 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(); + } + @Test public void checkMenu() throws IOException { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8cf6eb5a..2d04a6aa 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -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