diff --git a/app/src/main/java/protect/card_locker/DBHelper.java b/app/src/main/java/protect/card_locker/DBHelper.java index 90e4270ddc..485207ea56 100644 --- a/app/src/main/java/protect/card_locker/DBHelper.java +++ b/app/src/main/java/protect/card_locker/DBHelper.java @@ -21,7 +21,7 @@ public class DBHelper extends SQLiteOpenHelper { public static final String DATABASE_NAME = "Catima.db"; public static final int ORIGINAL_DATABASE_VERSION = 1; - public static final int DATABASE_VERSION = 15; + public static final int DATABASE_VERSION = 16; public static class LoyaltyCardDbGroups { public static final String TABLE = "groups"; @@ -45,6 +45,7 @@ public static class LoyaltyCardDbIds { public static final String STAR_STATUS = "starstatus"; public static final String LAST_USED = "lastused"; public static final String ZOOM_LEVEL = "zoomlevel"; + public static final String ZOOM_WIDTH = "zoomwidth"; public static final String ARCHIVE_STATUS = "archive"; } @@ -105,6 +106,7 @@ public void onCreate(SQLiteDatabase db) { LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0'," + LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0', " + LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '100', " + + LoyaltyCardDbIds.ZOOM_WIDTH + " INTEGER DEFAULT '100', " + LoyaltyCardDbIds.ARCHIVE_STATUS + " INTEGER DEFAULT '0' )"); // create associative table for cards in groups @@ -310,10 +312,17 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE + " ADD COLUMN " + LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '100' "); } + + if (oldVersion < 16 && newVersion >= 16) { + db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE + + " ADD COLUMN " + LoyaltyCardDbIds.ZOOM_WIDTH + " INTEGER DEFAULT '100' "); + } + if (oldVersion < 15 && newVersion >= 15) { db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE + " ADD COLUMN " + LoyaltyCardDbIds.ARCHIVE_STATUS + " INTEGER DEFAULT '0' "); } + } private static ContentValues generateFTSContentValues(final int id, final String store, final String note) { @@ -494,6 +503,24 @@ public static boolean updateLoyaltyCardZoomLevel(SQLiteDatabase database, int lo return (rowsUpdated == 1); } + /** + * Updates the zoom width of a card. + * @param database database where the card is located + * @param loyaltyCardId id of the card + * @param zoomWidth new zoom width of the card + * @return whether exactly 1 row was updated + */ + public static boolean updateLoyaltyCardZoomWidth(SQLiteDatabase database, int loyaltyCardId, int zoomWidth) { + ContentValues contentValues = new ContentValues(); + contentValues.put(LoyaltyCardDbIds.ZOOM_WIDTH, zoomWidth); + Log.d("updateLoyaltyCardZWidth", "Card Id = " + loyaltyCardId + " Zoom width= " + zoomWidth); + int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues, + whereAttrs(LoyaltyCardDbIds.ID), + withArgs(loyaltyCardId)); + Log.d("updateLoyaltyCardZWidth", "Rows changed = " + rowsUpdated); + return (rowsUpdated == 1); + } + public static boolean updateLoyaltyCardBalance(SQLiteDatabase database, final int id, final BigDecimal newBalance) { ContentValues contentValues = new ContentValues(); contentValues.put(LoyaltyCardDbIds.BALANCE, newBalance.toString()); @@ -899,4 +926,9 @@ private static String getDbDirection(LoyaltyCardOrder order, LoyaltyCardOrderDir return direction == LoyaltyCardOrderDirection.Ascending ? "ASC" : "DESC"; } + + public static int getColumnCount(SQLiteDatabase db) { + Cursor cursor = db.rawQuery("SELECT * FROM " + LoyaltyCardDbIds.TABLE + ";", null, null); + return cursor.getColumnCount(); + } } diff --git a/app/src/main/java/protect/card_locker/ImportURIHelper.java b/app/src/main/java/protect/card_locker/ImportURIHelper.java index 1549ed9cd5..7a240d0b9b 100644 --- a/app/src/main/java/protect/card_locker/ImportURIHelper.java +++ b/app/src/main/java/protect/card_locker/ImportURIHelper.java @@ -116,7 +116,7 @@ public LoyaltyCard parse(Uri uri) throws InvalidObjectException { headerColor = Integer.parseInt(unparsedHeaderColor); } - return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100,0); + return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100, 100, 0); } catch (NullPointerException | NumberFormatException | UnsupportedEncodingException ex) { throw new InvalidObjectException("Not a valid import URI"); } diff --git a/app/src/main/java/protect/card_locker/LoyaltyCard.java b/app/src/main/java/protect/card_locker/LoyaltyCard.java index 31255a0431..5458e3baeb 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCard.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCard.java @@ -32,12 +32,14 @@ public class LoyaltyCard implements Parcelable { public final int archiveStatus; public final long lastUsed; public int zoomLevel; + public int zoomWidth; + // Another constructor, with zoomWidth as an extra parameter public LoyaltyCard(final int id, final String store, final String note, final Date expiry, final BigDecimal balance, final Currency balanceType, final String cardId, @Nullable final String barcodeId, @Nullable final CatimaBarcode barcodeType, @Nullable final Integer headerColor, final int starStatus, - final long lastUsed, final int zoomLevel, final int archiveStatus) { + final long lastUsed, final int zoomLevel, final int zoomWidth, final int archiveStatus) { this.id = id; this.store = store; this.note = note; @@ -51,6 +53,7 @@ public LoyaltyCard(final int id, final String store, final String note, final Da this.starStatus = starStatus; this.lastUsed = lastUsed; this.zoomLevel = zoomLevel; + this.zoomWidth = zoomWidth; this.archiveStatus = archiveStatus; } @@ -71,6 +74,7 @@ protected LoyaltyCard(Parcel in) { starStatus = in.readInt(); lastUsed = in.readLong(); zoomLevel = in.readInt(); + zoomWidth = in.readInt(); archiveStatus = in.readInt(); } @@ -89,6 +93,7 @@ public void writeToParcel(Parcel parcel, int i) { parcel.writeInt(starStatus); parcel.writeLong(lastUsed); parcel.writeInt(zoomLevel); + parcel.writeInt(zoomWidth); parcel.writeInt(archiveStatus); } @@ -103,6 +108,7 @@ public static LoyaltyCard toLoyaltyCard(Cursor cursor) { int starred = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS)); long lastUsed = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.LAST_USED)); int zoomLevel = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ZOOM_LEVEL)); + int zoomWidth = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ZOOM_WIDTH)); int archived = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ARCHIVE_STATUS)); int barcodeTypeColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE); @@ -130,7 +136,7 @@ public static LoyaltyCard toLoyaltyCard(Cursor cursor) { headerColor = cursor.getInt(headerColorColumn); } - return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed, zoomLevel,archived); + return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed, zoomLevel, zoomWidth, archived); } @Override diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java index d909808fd8..e83f3c3494 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java @@ -215,6 +215,7 @@ private static LoyaltyCard updateTempState(LoyaltyCard loyaltyCard, LoyaltyCardF (int) (fieldName == LoyaltyCardField.starStatus ? value : loyaltyCard.starStatus), 0, // Unimportant, always set to null in doSave so the DB updates it to the current timestamp 100, // Unimportant, not updated in doSave, defaults to 100 for new cards + 100, (int) (fieldName == LoyaltyCardField.archiveStatus ? value : loyaltyCard.archiveStatus) ); } @@ -779,7 +780,7 @@ public void onResume() { } } else { // New card, use default values - tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime(), 100,0); + tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime(), 100, 100, 0); } } diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java index 6019a3953e..850dfa65e4 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java @@ -2,7 +2,6 @@ import android.content.ActivityNotFoundException; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.ColorStateList; @@ -15,7 +14,6 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.text.Editable; import android.text.InputType; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -58,7 +56,6 @@ import androidx.core.graphics.BlendModeCompat; import androidx.core.graphics.ColorUtils; import androidx.core.graphics.drawable.DrawableCompat; -import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsControllerCompat; import androidx.core.widget.TextViewCompat; @@ -123,7 +120,12 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements FloatingActionButton editButton; Guideline centerGuideline; - SeekBar barcodeScaler; + SeekBar barcodeHeightScaler; + SeekBar barcodeWidthScaler; + TextView zoomHeightText; + TextView zoomWidthText; + LinearLayout widthScalerLayout; + LinearLayout heightScalerLayout; Bitmap frontImageBitmap; Bitmap backImageBitmap; @@ -369,6 +371,8 @@ protected void onCreate(Bundle savedInstanceState) { iconImage = binding.iconImage; portraitToolbar = binding.toolbar; landscapeToolbar = binding.toolbarLandscape; + zoomHeightText = binding.zoomHeightText; + zoomWidthText = binding.zoomWidthText; bottomAppBarInfoButton = binding.buttonShowInfo; bottomAppBarPreviousButton = binding.buttonPrevious; @@ -388,38 +392,19 @@ protected void onCreate(Bundle savedInstanceState) { } }; + widthScalerLayout = binding.widthScalerLayout; + heightScalerLayout = binding.heightScalerLayout; centerGuideline = binding.centerGuideline; - barcodeScaler = binding.barcodeScaler; - barcodeScaler.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (!fromUser) { - Log.d(TAG, "non user triggered onProgressChanged, ignoring, progress is " + progress); - return; - } - Log.d(TAG, "Progress is " + progress); - Log.d(TAG, "Max is " + barcodeScaler.getMax()); - float scale = (float) progress / (float) barcodeScaler.getMax(); - Log.d(TAG, "Scaling to " + scale); + barcodeHeightScaler = binding.barcodeHeightScaler; - loyaltyCard.zoomLevel = progress; - DBHelper.updateLoyaltyCardZoomLevel(database, loyaltyCardId, loyaltyCard.zoomLevel); + SeekBarListener heightScalerListener = new SeekBarListener(barcodeHeightScaler); + barcodeHeightScaler.setOnSeekBarChangeListener(heightScalerListener); - setCenterGuideline(loyaltyCard.zoomLevel); - - drawMainImage(mainImageIndex, true, isFullscreen); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - - } - }); + // set zoom width of barcode + barcodeWidthScaler = binding.barcodeWidthScaler; + zoomWidthText = binding.zoomWidthText; + SeekBarListener widthScalerListener = new SeekBarListener(barcodeWidthScaler); + barcodeWidthScaler.setOnSeekBarChangeListener(widthScalerListener); rotationEnabled = true; @@ -758,8 +743,10 @@ public void onResume() { // Also apply colours to UI elements int darkenedColor = ColorUtils.blendARGB(backgroundHeaderColor, Color.BLACK, 0.1f); - barcodeScaler.setProgressTintList(ColorStateList.valueOf(darkenedColor)); - barcodeScaler.setThumbTintList(ColorStateList.valueOf(darkenedColor)); + barcodeHeightScaler.setProgressTintList(ColorStateList.valueOf(darkenedColor)); + barcodeHeightScaler.setThumbTintList(ColorStateList.valueOf(darkenedColor)); + barcodeWidthScaler.setProgressTintList(ColorStateList.valueOf(darkenedColor)); + barcodeWidthScaler.setThumbTintList(ColorStateList.valueOf(darkenedColor)); maximizeButton.setBackgroundColor(darkenedColor); minimizeButton.setBackgroundColor(darkenedColor); bottomAppBar.setBackgroundColor(darkenedColor); @@ -1124,13 +1111,21 @@ private void setFullscreen(boolean enabled) { drawMainImage(mainImageIndex, true, isFullscreen); - barcodeScaler.setProgress(loyaltyCard.zoomLevel); + barcodeHeightScaler.setProgress(loyaltyCard.zoomLevel); + barcodeWidthScaler.setProgress(loyaltyCard.zoomWidth); setCenterGuideline(loyaltyCard.zoomLevel); // Hide maximize and show minimize button and scaler + widthScalerLayout.setVisibility(View.VISIBLE); + heightScalerLayout.setVisibility(View.VISIBLE); maximizeButton.setVisibility(View.GONE); minimizeButton.setVisibility(View.VISIBLE); - barcodeScaler.setVisibility(View.VISIBLE); + barcodeHeightScaler.setVisibility(View.VISIBLE); + barcodeWidthScaler.setVisibility(View.VISIBLE); + zoomWidthText.setText("Width"); + zoomHeightText.setText("Height"); + zoomWidthText.setVisibility(View.VISIBLE); + zoomHeightText.setVisibility(View.VISIBLE); // Hide actionbar if (actionBar != null) { @@ -1170,7 +1165,16 @@ private void setFullscreen(boolean enabled) { maximizeButton.setVisibility(imageTypes.isEmpty() ? View.GONE : View.VISIBLE); minimizeButton.setVisibility(View.GONE); - barcodeScaler.setVisibility(View.GONE); + widthScalerLayout.setVisibility(View.GONE); + heightScalerLayout.setVisibility(View.GONE); + barcodeHeightScaler.setVisibility(View.GONE); + barcodeWidthScaler.setVisibility(View.GONE); + zoomWidthText.setVisibility(View.GONE); + zoomHeightText.setVisibility(View.GONE); + + // reset displaying width after exiting maximize mode + mainImage.getLayoutParams().width = mainLayout.getWidth(); + mainImage.requestLayout(); // Show actionbar if (actionBar != null) { @@ -1198,7 +1202,8 @@ private void setFullscreen(boolean enabled) { } } - Log.d("setFullScreen", "Is full screen enabled? " + enabled + " Zoom Level = " + barcodeScaler.getProgress()); + Log.d("setFullScreen", "Is full screen enabled? " + enabled + " Zoom Level = " + barcodeHeightScaler.getProgress() + ", Width level = " + barcodeWidthScaler.getProgress()); + } @SuppressWarnings("deprecation") @@ -1218,4 +1223,47 @@ private void setFullscreenModeSdkLessThan30() { | View.SYSTEM_UI_FLAG_FULLSCREEN ); } + + /** + * Helper class for the barcode zoom scalers. + */ + public class SeekBarListener implements SeekBar.OnSeekBarChangeListener { + private SeekBar seekBar; + + public SeekBarListener(SeekBar sb) { + seekBar = sb; + } + + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (!fromUser) { + Log.d(TAG, "non user triggered onProgressChanged, ignoring, progress is " + progress); + return; + } + Log.d(TAG, "Progress is " + progress); + Log.d(TAG, "Max is " + seekBar.getMax()); + float scale = (float) progress / (float) seekBar.getMax(); + Log.d(TAG, "Scaling to " + scale); + + if (seekBar == barcodeHeightScaler) { + loyaltyCard.zoomLevel = progress; + DBHelper.updateLoyaltyCardZoomLevel(database, loyaltyCardId, loyaltyCard.zoomLevel); + setCenterGuideline(loyaltyCard.zoomLevel); + } else if (seekBar == barcodeWidthScaler) { + loyaltyCard.zoomWidth = progress; + DBHelper.updateLoyaltyCardZoomWidth(database, loyaltyCardId, loyaltyCard.zoomWidth); + mainImage.getLayoutParams().width = mainLayout.getWidth() * loyaltyCard.zoomWidth / 100; + mainImage.requestLayout(); + } + + drawMainImage(mainImageIndex, true, isFullscreen); + } + + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + public void onStopTrackingTouch(SeekBar seekBar) { + + } + } } diff --git a/app/src/main/res/layout/loyalty_card_view_layout.xml b/app/src/main/res/layout/loyalty_card_view_layout.xml index af280f19fc..6be47c36ad 100644 --- a/app/src/main/res/layout/loyalty_card_view_layout.xml +++ b/app/src/main/res/layout/loyalty_card_view_layout.xml @@ -97,11 +97,25 @@ android:orientation="horizontal" app:layout_constraintGuide_percent="0.5"/> + + + + - + + + + + + + + + app:layout_constraintTop_toBottomOf="@+id/scalerGuideline" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" + android:gravity="center" + android:orientation="horizontal" > + + + + + + Select a card Options Starred - Set scale + Set height + Set width If you want to request support, include the following info: Duplicate Archive diff --git a/app/src/test/java/protect/card_locker/DatabaseTest.java b/app/src/test/java/protect/card_locker/DatabaseTest.java index 78e9429c74..1c1c387152 100644 --- a/app/src/test/java/protect/card_locker/DatabaseTest.java +++ b/app/src/test/java/protect/card_locker/DatabaseTest.java @@ -488,6 +488,7 @@ public void databaseUpgradeFromVersion1() { assertEquals(0, card.starStatus); assertEquals(0, card.lastUsed); assertEquals(100, card.zoomLevel); + assertEquals(100, card.zoomWidth); // Determine that the entries are queryable and the fields are correct LoyaltyCard card2 = DBHelper.getLoyaltyCard(database, newCardId2); @@ -503,6 +504,7 @@ public void databaseUpgradeFromVersion1() { assertEquals(0, card2.starStatus); assertEquals(0, card2.lastUsed); assertEquals(100, card2.zoomLevel); + assertEquals(100, card.zoomWidth); } @Test