diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java
index 47c977925..965000277 100644
--- a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java
+++ b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java
@@ -1,6 +1,7 @@
package protect.card_locker;
import android.content.ActivityNotFoundException;
+import android.content.ClipboardManager;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.ColorStateList;
@@ -146,6 +147,21 @@ public void onMainImageTap() {
openImageInGallery(imageType);
}
+ private boolean copyBarcodeToClipBoard(){
+ if (imageTypes.get(mainImageIndex) == ImageType.BARCODE) {
+ String barcodeString = barcodeIdString != null ? barcodeIdString : cardIdString;
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
+ if (clipboard != null) {
+ android.content.ClipData clip = android.content.ClipData.newPlainText("Barcode", barcodeString);
+ clipboard.setPrimaryClip(clip);
+ Toast.makeText(this, R.string.copy_success, Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(this, R.string.copy_failed, Toast.LENGTH_SHORT).show();
+ }
+ }
+ return true;
+ }
+
private void openImageInGallery(ImageType imageType) {
File file = null;
@@ -350,12 +366,16 @@ public void onStopTrackingTouch(SeekBar seekBar) {
});
binding.mainImage.setOnClickListener(view -> onMainImageTap());
+
// This long-press was originally only intended for when Talkback was used but sadly limiting
// this doesn't seem to work well
binding.mainImage.setOnLongClickListener(view -> {
setMainImage(true, true);
return true;
});
+
+ binding.mainImageDescription.setOnLongClickListener(view -> copyBarcodeToClipBoard());
+
binding.fullscreenImage.setOnClickListener(view -> onMainImageTap());
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@@ -698,6 +718,7 @@ protected void onResume() {
builder.setTitle(R.string.cardId);
builder.setView(cardIdView);
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> dialogInterface.dismiss());
+ builder.setNeutralButton(R.string.copy, (dialogInterface, i) -> copyBarcodeToClipBoard());
AlertDialog dialog = builder.create();
dialog.show();
});
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e782652fd..bf5bec02f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -361,4 +361,7 @@
Select a Passbook file (.pkpass)
This file is not supported
Sorry, something went wrong, please try again...
+ Copy
+ Copied to clipboard
+ Failed to copy to clipboard
diff --git a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java
index 2fc8d6121..831a822b4 100644
--- a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java
+++ b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java
@@ -12,6 +12,8 @@
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -1389,4 +1391,51 @@ public void importCardOldFormat() {
checkAllFields(activity, ViewMode.ADD_CARD, "Example Store", "", context.getString(R.string.anyDate), context.getString(R.string.never), "0", context.getString(R.string.points), "123456", context.getString(R.string.sameAsCardId), "Aztec", null, null);
assertEquals(-416706, ((ColorDrawable) activity.findViewById(R.id.thumbnail).getBackground()).getColor());
}
+
+
+ @Test
+ public void longPressOnBarcodeShouldCopyTheBarcodeValue() {
+ final Context context = ApplicationProvider.getApplicationContext();
+ SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+
+ long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, Color.BLACK, 0, null, 0);
+
+ ActivityController activityController = createActivityWithLoyaltyCard(false, (int) cardId);
+ Activity activity = (Activity) activityController.get();
+
+ activityController.start();
+ activityController.visible();
+ activityController.resume();
+
+ // Short press on description to open the modal
+ TextView barcodeTextView = activity.findViewById(R.id.main_image_description);
+ barcodeTextView.performClick();
+ shadowOf(getMainLooper()).idle();
+
+ // click on the copy neutral button
+ AlertDialog barcodeDialog = (AlertDialog) (ShadowDialog.getLatestDialog());
+ assertNotNull(barcodeDialog);
+ barcodeDialog.getButton(AlertDialog.BUTTON_NEUTRAL).performClick();
+ shadowOf(getMainLooper()).idle();
+
+ // Check if the barcode value is copied to the clipboard
+ ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clipData = clipboard.getPrimaryClip();
+ assertNotNull(clipData);
+ assertEquals(BARCODE_DATA, clipData.getItemAt(0).getText().toString());
+
+ //clear the clipboard
+ clipboard.setPrimaryClip(ClipData.newPlainText("", ""));
+
+ //quit the dialog
+ barcodeDialog.dismiss();
+
+ // Long press on the barcode description should copy the barcode value
+ barcodeTextView.performLongClick();
+ shadowOf(getMainLooper()).idle();
+ // Check if the barcode value is copied to the clipboard
+ clipData = clipboard.getPrimaryClip();
+ assertNotNull(clipData);
+ assertEquals(BARCODE_DATA, clipData.getItemAt(0).getText().toString());
+ }
}