diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java index 4ed0b2524..1320b9da6 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java @@ -45,6 +45,7 @@ import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import androidx.exifinterface.media.ExifInterface; +import androidx.lifecycle.ViewModelProvider; import com.google.android.material.chip.Chip; import com.google.android.material.chip.ChipGroup; @@ -85,17 +86,12 @@ import java.util.concurrent.Callable; import protect.card_locker.async.TaskHandler; import protect.card_locker.databinding.LayoutChipChoiceBinding; import protect.card_locker.databinding.LoyaltyCardEditActivityBinding; +import protect.card_locker.viewmodels.LoyaltyCardEditActivityViewModel; public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements BarcodeImageWriterResultCallback, ColorPickerDialogListener { - private LoyaltyCardEditActivityBinding binding; private static final String TAG = "Catima"; - - private final String STATE_TAB_INDEX = "savedTab"; - private final String STATE_TEMP_CARD = "tempLoyaltyCard"; - private final String STATE_TEMP_CARD_FIELD = "tempLoyaltyCardField"; - private final String STATE_UPDATE_LOYALTY_CARD = "updateLoyaltyCard"; - private final String STATE_HAS_CHANGED = "hasChange"; - private final String STATE_OPEN_SET_ICON_MENU = "openSetIconMenu"; + protected LoyaltyCardEditActivityViewModel viewModel; + private LoyaltyCardEditActivityBinding binding; private static final String PICK_DATE_REQUEST_KEY = "pick_date_request"; private static final String NEWLY_PICKED_DATE_ARGUMENT_KEY = "newly_picked_date"; @@ -117,8 +113,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements public static final String BUNDLE_OPEN_SET_ICON_MENU = "openSetIconMenu"; public static final String BUNDLE_ADDGROUP = "addGroup"; - TabLayout tabs; - ImageView thumbnail; ImageView thumbnailEditIcon; EditText storeFieldEdit; @@ -143,17 +137,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements Toolbar toolbar; - int loyaltyCardId; - boolean updateLoyaltyCard; - boolean duplicateFromLoyaltyCardId; - boolean openSetIconMenu; - String addGroup; - - Uri importLoyaltyCardUri = null; - SQLiteDatabase mDatabase; - boolean hasChanged = false; String tempStoredOldBarcodeValue = null; boolean initDone = false; boolean onResuming = false; @@ -164,15 +149,11 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements HashMap currencies = new HashMap<>(); HashMap currencySymbols = new HashMap<>(); - LoyaltyCard tempLoyaltyCard = new LoyaltyCard(); - LoyaltyCardField tempLoyaltyCardField; - ActivityResultLauncher mPhotoTakerLauncher; ActivityResultLauncher mPhotoPickerLauncher; ActivityResultLauncher mCardIdAndBarCodeEditorLauncher; ActivityResultLauncher mCropperLauncher; - int mRequestedImage = 0; UCrop.Options mCropperOptions; final private TaskHandler mTasks = new TaskHandler(); @@ -188,95 +169,100 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } protected void setLoyaltyCardStore(@NonNull String store) { - tempLoyaltyCard.setStore(store); + viewModel.getLoyaltyCard().setStore(store); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardNote(@NonNull String note) { - tempLoyaltyCard.setNote(note); + viewModel.getLoyaltyCard().setNote(note); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardValidFrom(@Nullable Date validFrom) { - tempLoyaltyCard.setValidFrom(validFrom); + viewModel.getLoyaltyCard().setValidFrom(validFrom); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardExpiry(@Nullable Date expiry) { - tempLoyaltyCard.setExpiry(expiry); + viewModel.getLoyaltyCard().setExpiry(expiry); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardBalance(@NonNull BigDecimal balance) { - tempLoyaltyCard.setBalance(balance); + viewModel.getLoyaltyCard().setBalance(balance); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardBalanceType(@Nullable Currency balanceType) { - tempLoyaltyCard.setBalanceType(balanceType); + viewModel.getLoyaltyCard().setBalanceType(balanceType); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardCardId(@NonNull String cardId) { - tempLoyaltyCard.setCardId(cardId); + viewModel.getLoyaltyCard().setCardId(cardId); generateBarcode(); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardBarcodeId(@Nullable String barcodeId) { - tempLoyaltyCard.setBarcodeId(barcodeId); + viewModel.getLoyaltyCard().setBarcodeId(barcodeId); generateBarcode(); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardBarcodeType(@Nullable CatimaBarcode barcodeType) { - tempLoyaltyCard.setBarcodeType(barcodeType); + viewModel.getLoyaltyCard().setBarcodeType(barcodeType); generateBarcode(); - hasChanged = true; + viewModel.setHasChanged(true); } protected void setLoyaltyCardHeaderColor(@Nullable Integer headerColor) { - tempLoyaltyCard.setHeaderColor(headerColor); + viewModel.getLoyaltyCard().setHeaderColor(headerColor); - hasChanged = true; + viewModel.setHasChanged(true); } /* Extract intent fields and return if code should keep running */ private boolean extractIntentFields(Intent intent) { final Bundle b = intent.getExtras(); - addGroup = b != null ? b.getString(BUNDLE_ADDGROUP) : null; - openSetIconMenu = b != null && b.getBoolean(BUNDLE_OPEN_SET_ICON_MENU, false); + viewModel.setAddGroup(b != null ? b.getString(BUNDLE_ADDGROUP) : null); + viewModel.setOpenSetIconMenu(b != null && b.getBoolean(BUNDLE_OPEN_SET_ICON_MENU, false)); - loyaltyCardId = b != null ? b.getInt(BUNDLE_ID) : 0; - updateLoyaltyCard = b != null && b.getBoolean(BUNDLE_UPDATE, false); - duplicateFromLoyaltyCardId = b != null && b.getBoolean(BUNDLE_DUPLICATE_ID, false); - importLoyaltyCardUri = intent.getData(); + viewModel.setLoyaltyCardId(b != null ? b.getInt(BUNDLE_ID) : 0); + viewModel.setUpdateLoyaltyCard(b != null && b.getBoolean(BUNDLE_UPDATE, false)); + viewModel.setDuplicateFromLoyaltyCardId(b != null && b.getBoolean(BUNDLE_DUPLICATE_ID, false)); + viewModel.setImportLoyaltyCardUri(intent.getData()); + + Uri importLoyaltyCardUri = viewModel.getImportLoyaltyCardUri(); // If we have to import a loyalty card, do so - if (updateLoyaltyCard || duplicateFromLoyaltyCardId) { - tempLoyaltyCard = DBHelper.getLoyaltyCard(this, mDatabase, loyaltyCardId); - if (tempLoyaltyCard == null) { - Log.w(TAG, "Could not lookup loyalty card " + loyaltyCardId); + if (viewModel.getUpdateLoyaltyCard() || viewModel.getDuplicateFromLoyaltyCardId()) { + // Retrieve from database + LoyaltyCard loyaltyCard = DBHelper.getLoyaltyCard(this, mDatabase, viewModel.getLoyaltyCardId()); + if (loyaltyCard == null) { + Log.w(TAG, "Could not lookup loyalty card " + viewModel.getLoyaltyCardId()); Toast.makeText(this, R.string.noCardExistsError, Toast.LENGTH_LONG).show(); finish(); return false; } + viewModel.setLoyaltyCard(loyaltyCard); } else if (importLoyaltyCardUri != null) { + // Load from URI try { - tempLoyaltyCard = new ImportURIHelper(this).parse(importLoyaltyCardUri); + viewModel.setLoyaltyCard(new ImportURIHelper(this).parse(importLoyaltyCardUri)); } catch (InvalidObjectException ex) { Toast.makeText(this, R.string.failedParsingImportUriError, Toast.LENGTH_LONG).show(); finish(); @@ -286,11 +272,13 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements // If the intent contains any loyalty card fields, override those fields in our current temp card if (b != null) { - tempLoyaltyCard.updateFromBundle(this, b, false); + LoyaltyCard loyaltyCard = viewModel.getLoyaltyCard(); + loyaltyCard.updateFromBundle(this, b, false); + viewModel.setLoyaltyCard(loyaltyCard); } - Log.d(TAG, "Edit activity: id=" + loyaltyCardId - + ", updateLoyaltyCard=" + updateLoyaltyCard); + Log.d(TAG, "Edit activity: id=" + viewModel.getLoyaltyCardId() + + ", updateLoyaltyCard=" + viewModel.getUpdateLoyaltyCard()); return true; } @@ -298,31 +286,12 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements @Override public void onSaveInstanceState(@NonNull Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); - tabs = binding.tabs; - savedInstanceState.putInt(STATE_TAB_INDEX, tabs.getSelectedTabPosition()); - savedInstanceState.putBundle(STATE_TEMP_CARD, tempLoyaltyCard.toBundle(this, new ArrayList<>())); - savedInstanceState.putSerializable(STATE_TEMP_CARD_FIELD, tempLoyaltyCardField); - - savedInstanceState.putInt(STATE_UPDATE_LOYALTY_CARD, updateLoyaltyCard ? 1 : 0); - savedInstanceState.putInt(STATE_HAS_CHANGED, hasChanged ? 1 : 0); - savedInstanceState.putInt(STATE_OPEN_SET_ICON_MENU, openSetIconMenu ? 1 : 0); } @Override public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { onRestoring = true; - tempLoyaltyCard = new LoyaltyCard(); - Bundle tempCardBundle = savedInstanceState.getBundle(STATE_TEMP_CARD); - if (tempCardBundle != null) { - tempLoyaltyCard.updateFromBundle(this, tempCardBundle, true); - } - tempLoyaltyCardField = (LoyaltyCardField) savedInstanceState.getSerializable(STATE_TEMP_CARD_FIELD); super.onRestoreInstanceState(savedInstanceState); - tabs = binding.tabs; - tabs.selectTab(tabs.getTabAt(savedInstanceState.getInt(STATE_TAB_INDEX))); - updateLoyaltyCard = savedInstanceState.getInt(STATE_UPDATE_LOYALTY_CARD) == 1; - hasChanged = savedInstanceState.getInt(STATE_HAS_CHANGED) == 1; - openSetIconMenu = savedInstanceState.getInt(STATE_OPEN_SET_ICON_MENU) == 1; } @Override @@ -330,14 +299,20 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements super.onCreate(savedInstanceState); binding = LoyaltyCardEditActivityBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); + + viewModel = new ViewModelProvider(this).get(LoyaltyCardEditActivityViewModel.class); + toolbar = binding.toolbar; setSupportActionBar(toolbar); enableToolbarBackButton(); mDatabase = new DBHelper(this).getWritableDatabase(); - if (!extractIntentFields(getIntent())) { - return; + if (!viewModel.getInitialized()) { + if (!extractIntentFields(getIntent())) { + return; + } + viewModel.setInitialized(true); } for (Currency currency : Currency.getAvailableCurrencies()) { @@ -345,7 +320,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements currencySymbols.put(currency.getCurrencyCode(), currency.getSymbol()); } - tabs = binding.tabs; thumbnail = binding.thumbnail; thumbnailEditIcon = binding.thumbnailEditIcon; storeFieldEdit = binding.storeNameEdit; @@ -403,7 +377,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements setLoyaltyCardBalance(BigDecimal.valueOf(0)); } - balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(tempLoyaltyCard.balance, tempLoyaltyCard.balanceType)); + balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(viewModel.getLoyaltyCard().balance, viewModel.getLoyaltyCard().balanceType)); } }); @@ -412,7 +386,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements public void onTextChanged(CharSequence s, int start, int before, int count) { if (onResuming || onRestoring) return; try { - BigDecimal balance = Utils.parseBalance(s.toString(), tempLoyaltyCard.balanceType); + BigDecimal balance = Utils.parseBalance(s.toString(), viewModel.getLoyaltyCard().balanceType); setLoyaltyCardBalance(balance); balanceField.setError(null); validBalance = true; @@ -437,8 +411,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements setLoyaltyCardBalanceType(currency); - if (tempLoyaltyCard.balance != null && !onResuming && !onRestoring) { - balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(tempLoyaltyCard.balance, currency)); + if (viewModel.getLoyaltyCard().balance != null && !onResuming && !onRestoring) { + balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(viewModel.getLoyaltyCard().balance, currency)); } } @@ -484,7 +458,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements // 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 (tempLoyaltyCard.barcodeId != null) { + if (viewModel.getLoyaltyCard().barcodeId != null) { // If it is not set to "same as Card ID", save as tempStoredOldBarcodeValue tempStoredOldBarcodeValue = barcodeIdField.getText().toString(); } @@ -539,8 +513,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements input.setLayoutParams(params); container.addView(input); - if (tempLoyaltyCard.barcodeId != null) { - input.setText(tempLoyaltyCard.barcodeId); + if (viewModel.getLoyaltyCard().barcodeId != null) { + input.setText(viewModel.getLoyaltyCard().barcodeId); } builder.setView(container); @@ -601,10 +575,11 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } }); - tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + binding.tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override @edu.umd.cs.findbugs.annotations.SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") public void onTabSelected(TabLayout.Tab tab) { + viewModel.setTabIndex(tab.getPosition()); showPart(tab.getText().toString()); } @@ -616,12 +591,12 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements @Override @edu.umd.cs.findbugs.annotations.SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") public void onTabReselected(TabLayout.Tab tab) { + viewModel.setTabIndex(tab.getPosition()); showPart(tab.getText().toString()); } }); - tabs.selectTab(tabs.getTabAt(0)); - + selectTab(viewModel.getTabIndex()); mPhotoTakerLauncher = registerForActivityResult(new ActivityResultContracts.TakePicture(), result -> { if (result) { @@ -656,9 +631,11 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements return; } - tempLoyaltyCard.updateFromBundle(this, resultIntentBundle, false); + LoyaltyCard loyaltyCard = viewModel.getLoyaltyCard(); + loyaltyCard.updateFromBundle(this, resultIntentBundle, false); + viewModel.setLoyaltyCard(loyaltyCard); generateBarcode(); - hasChanged = true; + viewModel.setHasChanged(true); } }); @@ -681,11 +658,14 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements setCardImage(ImageLocationType.front, cardImageFront, Utils.resizeBitmap(bitmap, Utils.BITMAP_SIZE_BIG), true); } else if (requestedBackImage()) { setCardImage(ImageLocationType.back, cardImageBack, Utils.resizeBitmap(bitmap, Utils.BITMAP_SIZE_BIG), true); - } else { + } else if (requestedIcon()) { setThumbnailImage(Utils.resizeBitmap(bitmap, Utils.BITMAP_SIZE_SMALL)); + } else { + Toast.makeText(this, R.string.generic_error_please_retry, Toast.LENGTH_LONG).show(); + return; } - Log.d("cropper", "mRequestedImage: " + mRequestedImage); - hasChanged = true; + Log.d("cropper", "requestedImageType: " + viewModel.getRequestedImageType()); + viewModel.setHasChanged(true); } else { Toast.makeText(LoyaltyCardEditActivity.this, R.string.errorReadingImage, Toast.LENGTH_LONG).show(); } @@ -708,6 +688,11 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements }); } + private void selectTab(int index) { + binding.tabs.selectTab(binding.tabs.getTabAt(index)); + viewModel.setTabIndex(index); + } + // ucrop 2.2.6 initial aspect ratio is glitched when 0x0 is used as the initial ratio option // https://github.com/Yalantis/uCrop/blob/281c8e6438d81f464d836fc6b500517144af264a/ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java#L264 // so source width height has to be provided for now, depending on whether future versions of ucrop will support 0x0 as the default option @@ -745,24 +730,22 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } } - @Override - public void onNewIntent(Intent intent) { - super.onNewIntent(intent); - - Log.i(TAG, "Received new intent"); - extractIntentFields(intent); - } - private boolean requestedFrontImage() { - return mRequestedImage == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || mRequestedImage == Utils.CARD_IMAGE_FROM_FILE_FRONT; + int requestedImageType = viewModel.getRequestedImageType(); + + return requestedImageType == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || requestedImageType == Utils.CARD_IMAGE_FROM_FILE_FRONT; } private boolean requestedBackImage() { - return mRequestedImage == Utils.CARD_IMAGE_FROM_CAMERA_BACK || mRequestedImage == Utils.CARD_IMAGE_FROM_FILE_BACK; + int requestedImageType = viewModel.getRequestedImageType(); + + return requestedImageType == Utils.CARD_IMAGE_FROM_CAMERA_BACK || requestedImageType == Utils.CARD_IMAGE_FROM_FILE_BACK; } private boolean requestedIcon() { - return mRequestedImage == Utils.CARD_IMAGE_FROM_CAMERA_ICON || mRequestedImage == Utils.CARD_IMAGE_FROM_FILE_ICON; + int requestedImageType = viewModel.getRequestedImageType(); + + return requestedImageType == Utils.CARD_IMAGE_FROM_CAMERA_ICON || requestedImageType == Utils.CARD_IMAGE_FROM_FILE_ICON; } @SuppressLint("DefaultLocale") @@ -770,39 +753,41 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements protected void onResume() { super.onResume(); - Log.i(TAG, "To view card: " + loyaltyCardId); + Log.i(TAG, "To view card: " + viewModel.getLoyaltyCardId()); onResuming = true; - if (updateLoyaltyCard) { + if (viewModel.getUpdateLoyaltyCard()) { setTitle(R.string.editCardTitle); } else { setTitle(R.string.addCardTitle); } - boolean hadChanges = hasChanged; + boolean hadChanges = viewModel.getHasChanged(); - storeFieldEdit.setText(tempLoyaltyCard.store); - noteFieldEdit.setText(tempLoyaltyCard.note); - formatDateField(this, validFromField, tempLoyaltyCard.validFrom); - formatDateField(this, expiryField, tempLoyaltyCard.expiry); - cardIdFieldView.setText(tempLoyaltyCard.cardId); - barcodeIdField.setText(tempLoyaltyCard.barcodeId != null ? tempLoyaltyCard.barcodeId : getString(R.string.sameAsCardId)); - barcodeTypeField.setText(tempLoyaltyCard.barcodeType != null ? tempLoyaltyCard.barcodeType.prettyName() : getString(R.string.noBarcode)); + storeFieldEdit.setText(viewModel.getLoyaltyCard().store); + noteFieldEdit.setText(viewModel.getLoyaltyCard().note); + formatDateField(this, validFromField, viewModel.getLoyaltyCard().validFrom); + formatDateField(this, expiryField, viewModel.getLoyaltyCard().expiry); + cardIdFieldView.setText(viewModel.getLoyaltyCard().cardId); + String barcodeId = viewModel.getLoyaltyCard().barcodeId; + barcodeIdField.setText(barcodeId != null && !barcodeId.isEmpty() ? barcodeId : getString(R.string.sameAsCardId)); + CatimaBarcode barcodeType = viewModel.getLoyaltyCard().barcodeType; + barcodeTypeField.setText(barcodeType != null ? barcodeType.prettyName() : getString(R.string.noBarcode)); // We set the balance here (with onResuming/onRestoring == true) to prevent formatBalanceCurrencyField() from setting it (via onTextChanged), // which can cause issues when switching locale because it parses the balance and e.g. the decimal separator may have changed. - formatBalanceCurrencyField(tempLoyaltyCard.balanceType); - BigDecimal balance = tempLoyaltyCard.balance == null ? new BigDecimal("0") : tempLoyaltyCard.balance; + formatBalanceCurrencyField(viewModel.getLoyaltyCard().balanceType); + BigDecimal balance = viewModel.getLoyaltyCard().balance == null ? new BigDecimal("0") : viewModel.getLoyaltyCard().balance; setLoyaltyCardBalance(balance); - balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(tempLoyaltyCard.balance, tempLoyaltyCard.balanceType)); + balanceField.setText(Utils.formatBalanceWithoutCurrencySymbol(viewModel.getLoyaltyCard().balance, viewModel.getLoyaltyCard().balanceType)); validBalance = true; Log.d(TAG, "Setting balance to " + balance); if (groupsChips.getChildCount() == 0) { List existingGroups = DBHelper.getGroups(mDatabase); - List loyaltyCardGroups = DBHelper.getLoyaltyCardGroups(mDatabase, loyaltyCardId); + List loyaltyCardGroups = DBHelper.getLoyaltyCardGroups(mDatabase, viewModel.getLoyaltyCardId()); if (existingGroups.isEmpty()) { groupsChips.setVisibility(View.GONE); @@ -817,7 +802,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements chip.setText(group._id); chip.setTag(group); - if (group._id.equals(addGroup)) { + if (group._id.equals(viewModel.getAddGroup())) { chip.setChecked(true); } else { chip.setChecked(false); @@ -830,7 +815,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } chip.setOnTouchListener((v, event) -> { - hasChanged = true; + viewModel.setHasChanged(true); return false; }); @@ -839,40 +824,19 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } } - if (tempLoyaltyCard.headerColor == null) { + if (viewModel.getLoyaltyCard().headerColor == null) { // If name is set, pick colour relevant for name. Otherwise pick randomly - setLoyaltyCardHeaderColor(tempLoyaltyCard.store.isEmpty() ? Utils.getRandomHeaderColor(this) : Utils.getHeaderColor(this, tempLoyaltyCard)); + setLoyaltyCardHeaderColor(viewModel.getLoyaltyCard().store.isEmpty() ? Utils.getRandomHeaderColor(this) : Utils.getHeaderColor(this, viewModel.getLoyaltyCard())); } - // Fix up some fields - if (tempLoyaltyCard.barcodeType != null) { - try { - barcodeTypeField.setText(tempLoyaltyCard.barcodeType.prettyName()); - } catch (IllegalArgumentException e) { - barcodeTypeField.setText(getString(R.string.noBarcode)); - } - } - - if (tempLoyaltyCard.cardId != null) { - cardIdFieldView.setText(tempLoyaltyCard.cardId); - } - - if (tempLoyaltyCard.barcodeId != null) { - if (!tempLoyaltyCard.barcodeId.isEmpty()) { - barcodeIdField.setText(tempLoyaltyCard.barcodeId); - } else { - barcodeIdField.setText(getString(R.string.sameAsCardId)); - } - } - - setThumbnailImage(tempLoyaltyCard.imageThumbnail); - setCardImage(ImageLocationType.front, cardImageFront, tempLoyaltyCard.imageFront, true); - setCardImage(ImageLocationType.back, cardImageBack, tempLoyaltyCard.imageBack, true); + setThumbnailImage(viewModel.getLoyaltyCard().imageThumbnail); + setCardImage(ImageLocationType.front, cardImageFront, viewModel.getLoyaltyCard().imageFront, true); + setCardImage(ImageLocationType.back, cardImageBack, viewModel.getLoyaltyCard().imageBack, true); // Initialization has finished if (!initDone) { initDone = true; - hasChanged = hadChanges; + viewModel.setHasChanged(hadChanges); } generateBarcode(); @@ -889,7 +853,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements generateIcon(storeFieldEdit.getText().toString().trim()); - Integer headerColor = tempLoyaltyCard.headerColor; + Integer headerColor = viewModel.getLoyaltyCard().headerColor; if (headerColor != null) { thumbnail.setOnClickListener(new ChooseCardImage()); thumbnailEditIcon.setBackgroundColor(Utils.needsDarkForeground(headerColor) ? Color.BLACK : Color.WHITE); @@ -901,8 +865,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements // Fake click on the edit icon to cause the set icon option to pop up if the icon was // long-pressed in the view activity - if (openSetIconMenu) { - openSetIconMenu = false; + if (viewModel.getOpenSetIconMenu()) { + viewModel.setOpenSetIconMenu(false); thumbnail.callOnClick(); } } @@ -911,7 +875,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements setCardImage(ImageLocationType.icon, thumbnail, bitmap, false); if (bitmap != null) { - int headerColor = Utils.getHeaderColorFromImage(bitmap, Utils.getHeaderColor(this, tempLoyaltyCard)); + int headerColor = Utils.getHeaderColorFromImage(bitmap, Utils.getHeaderColor(this, viewModel.getLoyaltyCard())); setLoyaltyCardHeaderColor(headerColor); @@ -922,20 +886,22 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } else { generateIcon(storeFieldEdit.getText().toString().trim()); - if (tempLoyaltyCard.headerColor != null) { - thumbnailEditIcon.setBackgroundColor(Utils.needsDarkForeground(tempLoyaltyCard.headerColor) ? Color.BLACK : Color.WHITE); - thumbnailEditIcon.setColorFilter(Utils.needsDarkForeground(tempLoyaltyCard.headerColor) ? Color.WHITE : Color.BLACK); + Integer headerColor = viewModel.getLoyaltyCard().headerColor; + + if (headerColor != null) { + thumbnailEditIcon.setBackgroundColor(Utils.needsDarkForeground(headerColor) ? Color.BLACK : Color.WHITE); + thumbnailEditIcon.setColorFilter(Utils.needsDarkForeground(headerColor) ? Color.WHITE : Color.BLACK); } } } protected void setCardImage(ImageLocationType imageLocationType, ImageView imageView, Bitmap bitmap, boolean applyFallback) { if (imageLocationType == ImageLocationType.icon) { - tempLoyaltyCard.setImageThumbnail(bitmap); + viewModel.getLoyaltyCard().setImageThumbnail(bitmap); } else if (imageLocationType == ImageLocationType.front) { - tempLoyaltyCard.setImageFront(bitmap); + viewModel.getLoyaltyCard().setImageFront(bitmap); } else if (imageLocationType == ImageLocationType.back) { - tempLoyaltyCard.setImageBack(bitmap); + viewModel.getLoyaltyCard().setImageBack(bitmap); } else { throw new IllegalArgumentException("Unknown image type"); } @@ -1118,7 +1084,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } private void askBeforeQuitIfChanged() { - if (!hasChanged) { + if (!viewModel.getHasChanged()) { if (tempStoredOldBarcodeValue != null) { askBarcodeChange(this::askBeforeQuitIfChanged); return; @@ -1145,7 +1111,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements private void takePhotoForCard(int type) { Uri photoURI = FileProvider.getUriForFile(LoyaltyCardEditActivity.this, BuildConfig.APPLICATION_ID, Utils.createTempFile(this, TEMP_CAMERA_IMAGE_NAME)); - mRequestedImage = type; + viewModel.setRequestedImageType(type); try { mPhotoTakerLauncher.launch(photoURI); @@ -1156,7 +1122,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } private void selectImageFromGallery(int type) { - mRequestedImage = type; + viewModel.setRequestedImageType(type); Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); @@ -1200,15 +1166,15 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements ImageView targetView; if (v.getId() == R.id.frontImageHolder) { - currentImage = tempLoyaltyCard.imageFront; + currentImage = viewModel.getLoyaltyCard().imageFront; imageLocationType = ImageLocationType.front; targetView = cardImageFront; } else if (v.getId() == R.id.backImageHolder) { - currentImage = tempLoyaltyCard.imageBack; + currentImage = viewModel.getLoyaltyCard().imageBack; imageLocationType = ImageLocationType.back; targetView = cardImageBack; } else if (v.getId() == R.id.thumbnail) { - currentImage = tempLoyaltyCard.imageThumbnail; + currentImage = viewModel.getLoyaltyCard().imageThumbnail; imageLocationType = ImageLocationType.icon; targetView = thumbnail; } else { @@ -1227,8 +1193,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements cardOptions.put(getString(R.string.selectColor), () -> { ColorPickerDialog.Builder dialogBuilder = ColorPickerDialog.newBuilder(); - if (tempLoyaltyCard.headerColor != null) { - dialogBuilder.setColor(tempLoyaltyCard.headerColor); + if (viewModel.getLoyaltyCard().headerColor != null) { + dialogBuilder.setColor(viewModel.getLoyaltyCard().headerColor); } ColorPickerDialog dialog = dialogBuilder.create(); @@ -1274,17 +1240,17 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements }); if (v.getId() == R.id.thumbnail) { - if (tempLoyaltyCard.imageFront != null) { + if (viewModel.getLoyaltyCard().imageFront != null) { cardOptions.put(getString(R.string.useFrontImage), () -> { - setThumbnailImage(Utils.resizeBitmap(tempLoyaltyCard.imageFront, Utils.BITMAP_SIZE_SMALL)); + setThumbnailImage(Utils.resizeBitmap(viewModel.getLoyaltyCard().imageFront, Utils.BITMAP_SIZE_SMALL)); return null; }); } - if (tempLoyaltyCard.imageBack != null) { + if (viewModel.getLoyaltyCard().imageBack != null) { cardOptions.put(getString(R.string.useBackImage), () -> { - setThumbnailImage(Utils.resizeBitmap(tempLoyaltyCard.imageBack, Utils.BITMAP_SIZE_SMALL)); + setThumbnailImage(Utils.resizeBitmap(viewModel.getLoyaltyCard().imageBack, Utils.BITMAP_SIZE_SMALL)); return null; }); @@ -1385,7 +1351,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements // Required to handle configuration changes // See https://github.com/material-components/material-components-android/issues/1688 - tempLoyaltyCardField = loyaltyCardField; + viewModel.setTempLoyaltyCardField(loyaltyCardField); getSupportFragmentManager().addFragmentOnAttachListener((fragmentManager, fragment) -> { if (fragment instanceof MaterialDatePicker && Objects.equals(fragment.getTag(), PICK_DATE_REQUEST_KEY)) { ((MaterialDatePicker) fragment).addOnPositiveButtonClickListener(selection -> { @@ -1418,6 +1384,12 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements long selection = result.getLong(NEWLY_PICKED_DATE_ARGUMENT_KEY); Date newDate = new Date(selection); + + LoyaltyCardField tempLoyaltyCardField = viewModel.getTempLoyaltyCardField(); + if (tempLoyaltyCardField == null) { + throw new AssertionError("tempLoyaltyCardField is null unexpectedly!"); + } + switch (tempLoyaltyCardField) { case validFrom: formatDateField(LoyaltyCardEditActivity.this, validFromField, newDate); @@ -1459,22 +1431,22 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements boolean hasError = false; - if (tempLoyaltyCard.store.isEmpty()) { + if (viewModel.getLoyaltyCard().store.isEmpty()) { storeFieldEdit.setError(getString(R.string.field_must_not_be_empty)); // Focus element - tabs.selectTab(tabs.getTabAt(0)); + selectTab(0); storeFieldEdit.requestFocus(); hasError = true; } - if (tempLoyaltyCard.cardId.isEmpty()) { + if (viewModel.getLoyaltyCard().cardId.isEmpty()) { cardIdFieldView.setError(getString(R.string.field_must_not_be_empty)); // Focus element if first error element if (!hasError) { - tabs.selectTab(tabs.getTabAt(0)); + selectTab(0); cardIdFieldView.requestFocus(); hasError = true; } @@ -1485,7 +1457,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements // Focus element if first error element if (!hasError) { - tabs.selectTab(tabs.getTabAt(1)); + selectTab(1); balanceField.requestFocus(); hasError = true; } @@ -1505,25 +1477,25 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements // Both update and new card save with lastUsed set to null // This makes the DBHelper set it to the current date // So that new and edited card are always on top when sorting by recently used - if (updateLoyaltyCard) { - DBHelper.updateLoyaltyCard(mDatabase, loyaltyCardId, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.validFrom, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, tempLoyaltyCard.starStatus, null, tempLoyaltyCard.archiveStatus); + if (viewModel.getUpdateLoyaltyCard()) { + DBHelper.updateLoyaltyCard(mDatabase, viewModel.getLoyaltyCardId(), viewModel.getLoyaltyCard().store, viewModel.getLoyaltyCard().note, viewModel.getLoyaltyCard().validFrom, viewModel.getLoyaltyCard().expiry, viewModel.getLoyaltyCard().balance, viewModel.getLoyaltyCard().balanceType, viewModel.getLoyaltyCard().cardId, viewModel.getLoyaltyCard().barcodeId, viewModel.getLoyaltyCard().barcodeType, viewModel.getLoyaltyCard().headerColor, viewModel.getLoyaltyCard().starStatus, null, viewModel.getLoyaltyCard().archiveStatus); } else { - loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.validFrom, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, 0, null, 0); + viewModel.setLoyaltyCardId((int) DBHelper.insertLoyaltyCard(mDatabase, viewModel.getLoyaltyCard().store, viewModel.getLoyaltyCard().note, viewModel.getLoyaltyCard().validFrom, viewModel.getLoyaltyCard().expiry, viewModel.getLoyaltyCard().balance, viewModel.getLoyaltyCard().balanceType, viewModel.getLoyaltyCard().cardId, viewModel.getLoyaltyCard().barcodeId, viewModel.getLoyaltyCard().barcodeType, viewModel.getLoyaltyCard().headerColor, 0, null, 0)); } try { - Utils.saveCardImage(this, tempLoyaltyCard.imageFront, loyaltyCardId, ImageLocationType.front); - Utils.saveCardImage(this, tempLoyaltyCard.imageBack, loyaltyCardId, ImageLocationType.back); - Utils.saveCardImage(this, tempLoyaltyCard.imageThumbnail, loyaltyCardId, ImageLocationType.icon); + Utils.saveCardImage(this, viewModel.getLoyaltyCard().imageFront, viewModel.getLoyaltyCardId(), ImageLocationType.front); + Utils.saveCardImage(this, viewModel.getLoyaltyCard().imageBack, viewModel.getLoyaltyCardId(), ImageLocationType.back); + Utils.saveCardImage(this, viewModel.getLoyaltyCard().imageThumbnail, viewModel.getLoyaltyCardId(), ImageLocationType.icon); } catch (FileNotFoundException e) { e.printStackTrace(); } - DBHelper.setLoyaltyCardGroups(mDatabase, loyaltyCardId, selectedGroups); + DBHelper.setLoyaltyCardGroups(mDatabase, viewModel.getLoyaltyCardId(), selectedGroups); - ShortcutHelper.updateShortcuts(this, DBHelper.getLoyaltyCard(this, mDatabase, loyaltyCardId)); + ShortcutHelper.updateShortcuts(this, DBHelper.getLoyaltyCard(this, mDatabase, viewModel.getLoyaltyCardId())); - if (duplicateFromLoyaltyCardId) { + if (viewModel.getDuplicateFromLoyaltyCardId()) { Intent intent = new Intent(getApplicationContext(), MainActivity.class); startActivity(intent); } @@ -1566,6 +1538,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements mCropperOptions.setToolbarTitle(getResources().getString(R.string.setBackImage)); } else if (requestedIcon()) { mCropperOptions.setToolbarTitle(getResources().getString(R.string.setIcon)); + } else { + Toast.makeText(this, R.string.generic_error_please_retry, Toast.LENGTH_LONG).show(); + return; } if (requestedIcon()) { @@ -1618,8 +1593,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements private void generateBarcode() { mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false); - String cardIdString = tempLoyaltyCard.barcodeId != null ? tempLoyaltyCard.barcodeId : tempLoyaltyCard.cardId; - CatimaBarcode barcodeFormat = tempLoyaltyCard.barcodeType; + String cardIdString = viewModel.getLoyaltyCard().barcodeId != null ? viewModel.getLoyaltyCard().barcodeId : viewModel.getLoyaltyCard().cardId; + CatimaBarcode barcodeFormat = viewModel.getLoyaltyCard().barcodeType; if (cardIdString == null || cardIdString.isEmpty() || barcodeFormat == null) { barcodeImageLayout.setVisibility(View.GONE); @@ -1651,14 +1626,16 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements } private void generateIcon(String store) { - if (tempLoyaltyCard.headerColor == null) { + Integer headerColor = viewModel.getLoyaltyCard().headerColor; + + if (headerColor == null) { return; } - if (tempLoyaltyCard.imageThumbnail == null) { - thumbnail.setBackgroundColor(tempLoyaltyCard.headerColor); + if (viewModel.getLoyaltyCard().imageThumbnail == null) { + thumbnail.setBackgroundColor(headerColor); - LetterBitmap letterBitmap = Utils.generateIcon(this, store, tempLoyaltyCard.headerColor); + LetterBitmap letterBitmap = Utils.generateIcon(this, store, headerColor); if (letterBitmap != null) { thumbnail.setImageBitmap(letterBitmap.getLetterTile()); diff --git a/app/src/main/java/protect/card_locker/viewmodels/LoyaltyCardEditActivityViewModel.kt b/app/src/main/java/protect/card_locker/viewmodels/LoyaltyCardEditActivityViewModel.kt new file mode 100644 index 000000000..1faeb0f53 --- /dev/null +++ b/app/src/main/java/protect/card_locker/viewmodels/LoyaltyCardEditActivityViewModel.kt @@ -0,0 +1,24 @@ +package protect.card_locker.viewmodels + +import android.net.Uri +import androidx.lifecycle.ViewModel +import protect.card_locker.LoyaltyCard +import protect.card_locker.LoyaltyCardField + +class LoyaltyCardEditActivityViewModel : ViewModel() { + var initialized: Boolean = false + var hasChanged: Boolean = false + + var addGroup: String? = null + var openSetIconMenu: Boolean = false + var loyaltyCardId: Int = 0 + var updateLoyaltyCard: Boolean = false + var duplicateFromLoyaltyCardId: Boolean = false + var importLoyaltyCardUri: Uri? = null + + var tabIndex: Int = 0 + var requestedImageType: Int = 0 + var tempLoyaltyCardField: LoyaltyCardField? = null + + var loyaltyCard: LoyaltyCard = LoyaltyCard() +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 881eccf1f..4f09ac5aa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -362,4 +362,5 @@ Use back image Select a Passbook file (.pkpass) This file is not supported + Sorry, something went wrong, please try again... diff --git a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java index ad8a5bc73..07f9af1bd 100644 --- a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java +++ b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java @@ -585,13 +585,13 @@ public class LoyaltyCardViewActivityTest { // A change was made shadowOf(activity).clickMenuItem(android.R.id.home); assertEquals(true, activity.confirmExitDialog.isShowing()); - assertEquals(true, activity.hasChanged); + assertEquals(true, activity.viewModel.getHasChanged()); assertEquals(false, activity.isFinishing()); // Exit after setting hasChanged to false - activity.hasChanged = false; + activity.viewModel.setHasChanged(false); shadowOf(activity).clickMenuItem(android.R.id.home); - assertEquals(false, activity.hasChanged); + assertEquals(false, activity.viewModel.getHasChanged()); assertEquals(true, activity.isFinishing()); } @@ -708,13 +708,13 @@ public class LoyaltyCardViewActivityTest { // A change was made shadowOf(activity).clickMenuItem(android.R.id.home); assertEquals(true, activity.confirmExitDialog.isShowing()); - assertEquals(true, activity.hasChanged); + assertEquals(true, activity.viewModel.getHasChanged()); assertEquals(false, activity.isFinishing()); // Exit after setting hasChanged to false - activity.hasChanged = false; + activity.viewModel.setHasChanged(false); shadowOf(activity).clickMenuItem(android.R.id.home); - assertEquals(false, activity.hasChanged); + assertEquals(false, activity.viewModel.getHasChanged()); assertEquals(true, activity.isFinishing()); database.close();