Compare commits

..

1 Commits

Author SHA1 Message Date
Sylvia van Os
70cdb18c51 WIP 2023-03-17 17:18:43 +01:00
15 changed files with 3671 additions and 6734 deletions

View File

@@ -1,9 +1,8 @@
# Changelog
## v2.22.0 - 118
## Unreleased - 118
- Support setting start of card validity
- Fix Stocard import (Stocard's export format changed)
## v2.21.2 - 117

View File

@@ -19,8 +19,8 @@ android {
applicationId "me.hackerchick.catima"
minSdk 21
targetSdk 33
versionCode 118
versionName "2.22.0"
versionCode 117
versionName "2.21.2"
vectorDrawables.useSupportLibrary true
multiDexEnabled true

View File

@@ -21,11 +21,12 @@ import java.util.List;
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 = 16;
public static final int DATABASE_VERSION = 17;
public static class LoyaltyCardDbGroups {
public static final String TABLE = "groups";
public static final String ID = "_id";
public static final String NAME = "name";
public static final String ORDER = "orderId";
}
@@ -87,7 +88,8 @@ public class DBHelper extends SQLiteOpenHelper {
public void onCreate(SQLiteDatabase db) {
// create table for card groups
db.execSQL("CREATE TABLE " + LoyaltyCardDbGroups.TABLE + "(" +
LoyaltyCardDbGroups.ID + " TEXT primary key not null," +
LoyaltyCardDbGroups.ID + " INTEGER primary key autoincrement," +
LoyaltyCardDbGroups.NAME + " TEXT not null," +
LoyaltyCardDbGroups.ORDER + " INTEGER DEFAULT '0')");
// create table for cards
@@ -112,7 +114,7 @@ public class DBHelper extends SQLiteOpenHelper {
// create associative table for cards in groups
db.execSQL("CREATE TABLE " + LoyaltyCardDbIdsGroups.TABLE + "(" +
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
LoyaltyCardDbIdsGroups.groupID + " TEXT," +
LoyaltyCardDbIdsGroups.groupID + " INTEGER," +
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID + "))");
// create FTS search table
@@ -321,6 +323,70 @@ public class DBHelper extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
+ " ADD COLUMN " + LoyaltyCardDbIds.VALID_FROM + " INTEGER");
}
if (oldVersion < 17 && newVersion >= 17) {
// SQLite doesn't support modify column
// So we need to create a temp column to change the key of the group table
// https://www.sqlite.org/faq.html#q11
db.beginTransaction();
// Step 1: Migrate LoyaltyCardDbGroups to contain integer ID
db.execSQL("CREATE TEMPORARY TABLE tmp (" +
LoyaltyCardDbGroups.ID + " INTEGER primary key autoincrement," +
LoyaltyCardDbGroups.NAME + " TEXT not null," +
LoyaltyCardDbGroups.ORDER + " INTEGER DEFAULT '0')");
db.execSQL("INSERT INTO tmp (" +
LoyaltyCardDbGroups.NAME + " ," +
LoyaltyCardDbGroups.ORDER + ")" +
" SELECT " +
LoyaltyCardDbGroups.NAME + " ," +
LoyaltyCardDbGroups.ORDER +
" FROM " + LoyaltyCardDbGroups.TABLE);
db.execSQL("DROP TABLE " + LoyaltyCardDbGroups.TABLE);
db.execSQL("CREATE TABLE " + LoyaltyCardDbGroups.TABLE + "(" +
LoyaltyCardDbGroups.ID + " INTEGER primary key autoincrement," +
LoyaltyCardDbGroups.NAME + " TEXT not null," +
LoyaltyCardDbGroups.ORDER + " INTEGER DEFAULT '0')");
db.execSQL("INSERT INTO " + LoyaltyCardDbGroups.TABLE + "(" +
LoyaltyCardDbGroups.ID + " ," +
LoyaltyCardDbGroups.NAME + " ," +
LoyaltyCardDbGroups.ORDER + ")" +
" SELECT " +
LoyaltyCardDbGroups.ID + " ," +
LoyaltyCardDbGroups.NAME + " ," +
LoyaltyCardDbGroups.ORDER +
" FROM tmp");
db.execSQL("DROP TABLE tmp");
// Step 2: Migrate LoyaltyCardDbIdsGroups to link to ID
db.execSQL("CREATE TEMPORARY TABLE tmp (" +
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
LoyaltyCardDbIdsGroups.groupID + " INTEGER," +
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID + "))");
db.execSQL("INSERT INTO tmp (" +
LoyaltyCardDbIdsGroups.cardID + " ," +
LoyaltyCardDbIdsGroups.groupID + ")" +
" SELECT " +
LoyaltyCardDbGroups.NAME + " ," +
LoyaltyCardDbGroups.ORDER +
" FROM " + LoyaltyCardDbGroups.TABLE);
//////////
db.execSQL("CREATE TABLE " + LoyaltyCardDbIdsGroups.TABLE + "(" +
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
LoyaltyCardDbIdsGroups.groupID + " INTEGER," +
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID + "))");
db.setTransactionSuccessful();
db.endTransaction();
}
}
private static ContentValues generateFTSContentValues(final int id, final String store, final String note) {

View File

@@ -74,31 +74,29 @@ public class StocardImporter implements Importer {
String fileName = localFileHeader.getFileName();
String[] nameParts = fileName.split("/");
if (nameParts.length < 2) {
continue;
}
if (providersFileName == null) {
providersFileName = new String[]{
"extracts",
nameParts[1],
nameParts[0],
"sync",
"data",
"users",
nameParts[1],
"analytics-properties",
"content.json"
nameParts[0],
"analytics-properties.json"
};
customProvidersBaseName = new String[]{
"extracts",
nameParts[1],
nameParts[0],
"sync",
"data",
"users",
nameParts[1],
nameParts[0],
"loyalty-card-custom-providers"
};
cardBaseName = new String[]{
"extracts",
nameParts[1],
nameParts[0],
"sync",
"data",
"users",
nameParts[1],
nameParts[0],
"loyalty-cards"
};
}
@@ -108,15 +106,18 @@ public class StocardImporter implements Importer {
customProviderId = nameParts[customProvidersBaseName.length].split("\\.", 2)[0];
// Name file
if (fileName.endsWith(customProviderId + "/content.json")) {
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
if (nameParts.length == customProvidersBaseName.length + 1) {
// Ignore the .txt file
if (fileName.endsWith(".json")) {
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
providers = appendToHashMap(
providers,
customProviderId,
"name",
jsonObject.getString("name")
);
providers = appendToHashMap(
providers,
customProviderId,
"name",
jsonObject.getString("name")
);
}
} else if (fileName.endsWith("logo.png")) {
providers = appendToHashMap(
providers,
@@ -132,43 +133,46 @@ public class StocardImporter implements Importer {
cardName = nameParts[cardBaseName.length].split("\\.", 2)[0];
// This is the card itself
if (fileName.endsWith(cardName + "/content.json")) {
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
if (nameParts.length == cardBaseName.length + 1) {
// Ignore the .txt file
if (fileName.endsWith(".json")) {
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"cardId",
jsonObject.getString("input_id")
);
// Provider ID can be either custom or not, extract whatever version is relevant
String customProviderPrefix = "/users/" + nameParts[1] + "/loyalty-card-custom-providers/";
String providerId = jsonObject
.getJSONObject("input_provider_reference")
.getString("identifier");
if (providerId.startsWith(customProviderPrefix)) {
providerId = providerId.substring(customProviderPrefix.length());
} else {
providerId = providerId.substring("/loyalty-card-providers/".length());
}
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"_providerId",
providerId
);
if (jsonObject.has("input_barcode_format")) {
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"barcodeType",
jsonObject.getString("input_barcode_format")
"cardId",
jsonObject.getString("input_id")
);
// Provider ID can be either custom or not, extract whatever version is relevant
String customProviderPrefix = "/users/" + nameParts[0] + "/loyalty-card-custom-providers/";
String providerId = jsonObject
.getJSONObject("input_provider_reference")
.getString("identifier");
if (providerId.startsWith(customProviderPrefix)) {
providerId = providerId.substring(customProviderPrefix.length());
} else {
providerId = providerId.substring("/loyalty-card-providers/".length());
}
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"_providerId",
providerId
);
if (jsonObject.has("input_barcode_format")) {
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,
"barcodeType",
jsonObject.getString("input_barcode_format")
);
}
}
} else if (fileName.endsWith("notes/default/content.json")) {
} else if (fileName.endsWith("notes/default.json")) {
loyaltyCardHashMap = appendToHashMap(
loyaltyCardHashMap,
cardName,

View File

@@ -2,18 +2,6 @@
stocard_stores.csv was created by extracting /data/data/de.stocard/de.stocard.stocard/databases/stores on a rooted devices and running the following command over it:
```
sqlite3 -header -csv sync_db "select id,content from synced_resources where collection = '/loyalty-card-providers/'" > stocard_providers.csv
while IFS= read -r line; do
if [ "$line" = "id,content" ]; then
echo "_id,name,barcodeFormat" > stocard_stores.csv
else
id="$(echo "$line" | cut -d ',' -f1)"
name="$(echo "$line" | cut -d ',' -f2- | sed 's/""/"/g' | sed 's/^"//g' | sed 's/"$//g' | jq -r .name)"
barcodeFormat="$(echo "$line" | cut -d ',' -f2- | sed 's/""/"/g' | sed 's/^"//g' | sed 's/"$//g' | jq -r .default_barcode_format)"
echo "$id,\"$name\",$barcodeFormat" >> stocard_stores.csv
fi
done < stocard_providers.csv
```
sqlite3 -header -csv stores "select _id,name,barcodeFormat from stores" > stocard_stores.csv
Only used for data portability reasons (ensuring importing works). Do NOT copy this anywhere else or use it for any purpose other than ensuring we can import a GDPR-provided export. We want to make sure this stays under fair use.

View File

File diff suppressed because it is too large Load Diff

View File

@@ -290,5 +290,4 @@
<string name="noCameraPermissionDirectToSystemSetting">لمسح الباركود، ستحتاج Catima إلى الوصول إلى الكاميرا. اضغط هنا لتغيير إعدادات الأذونات.</string>
<string name="updateBalance">تحديث الرصيد</string>
<string name="updateBalanceHint">أدخل المبلغ</string>
<string name="storageReadPermissionRequired">الصلاحيه للوصل للتخزين مطلوبة لهذا الاجراء</string>
</resources>

View File

@@ -1222,10 +1222,6 @@ public class ImportExportTest {
@Test
public void importStocard() throws IOException {
// FIXME: The provided stocard.zip is a very old export (8 July 2021) manually edited to
// look more like the Stocard files provided by users for #1242. It is not an up-to-date
// export and the test is possibly unreliable. This should be replaced by an up-to-date
// export.
InputStream inputStream = getClass().getResourceAsStream("stocard.zip");
// Import the Stocard data
@@ -1275,7 +1271,8 @@ public class ImportExportTest {
card = DBHelper.getLoyaltyCard(mDatabase, 3);
assertEquals("", card.store);
// I don't think we can know this one, but falling back to an unique store name is at least something
assertEquals("63536738-d64b-48ae-aeb8-82761523fa67", card.store);
assertEquals("", card.note);
assertEquals(null, card.validFrom);
assertEquals(null, card.expiry);

View File

Binary file not shown.

View File

@@ -1,2 +1 @@
- Support setting start of card validity
- Fix Stocard import (Stocard's export format changed)
- Support setting start of card validity

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -1,2 +0,0 @@
- Correction de la boîte de dialogue de dépense rapide qui ne permettait pas l'utilisation de la virgule comme séparateur
- Prise en charge du chargement d'images à partir du gestionnaire de fichiers

View File

@@ -1,6 +1,5 @@
- При редактировании номера, поле предварительно заполняется текущим. (№94)
- Ограничена ширина формируемых штрихкодов для уменьшения потребления памяти. (№103)
- Кнопка «Ввести карту» меняется на «Изменить карту», если указанный номер уже используется. (№104)
- Цветовая гамма смягчена и сочетается со значком приложения, упрощена страница просмотра карты. (№107)
- Сделан вводный мастер для первого запуска приложения. (№108)
Все запросы см. в https://github.com/brarcher/loyalty-card-locker/pull/
- При редактировании номера карты, поле предварительно заполняется текущим номером. (запрос №94 (https://github.com/brarcher/loyalty-card-locker/pull/94))
- Ширина формируемых штрихкодов ограничена для уменьшения потребления памяти и ошибок её нехватки. (запрос №103 (https://github.com/brarcher/loyalty-card-locker/pull/103))
- При редактировании карты кнопка ввода карты меняется на кнопку редактирования, если указанный номер уже используется. (запрос №104 (https://github.com/brarcher/loyalty-card-locker/pull/104))
- Цветовая гамма изменена на более мягкую и сочетающуюся с значком приложения, упрощена страница просмотра карты. (запрос №107 (https://github.com/brarcher/loyalty-card-locker/pull/107))
- Добавлен вводный мастер, включающийся при первом запуске приложения. (запрос №108 (https://github.com/brarcher/loyalty-card-locker/pull/108))

View File

@@ -1,4 +1,2 @@
- Förbättrat stöd för skärmläsare
- Kraschar inte vid försök att öppna en video från galleriet
- Svepstöd på lojalitetskortets översiktssida
- Nollställ inte grupp vid klickning på tillbakaknappen
- Kraschar inte när den försöker öppna en video från galleriet