Compare commits
24 Commits
feature/pk
...
v0.29
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c988276ced | ||
|
|
67ca1ad505 | ||
|
|
210a0c564a | ||
|
|
0a3df441d3 | ||
|
|
3a97d6b191 | ||
|
|
7f5ba2c133 | ||
|
|
ccb4c3c5a2 | ||
|
|
e8b436a696 | ||
|
|
a160583b30 | ||
|
|
6c24b64837 | ||
|
|
04b824257b | ||
|
|
70251d7ea8 | ||
|
|
fa4ab0ba59 | ||
|
|
8880e35a7a | ||
|
|
c9f3054682 | ||
|
|
537141fd70 | ||
|
|
f027b1f1b8 | ||
|
|
44d7c8520d | ||
|
|
9d9f73fbba | ||
|
|
5c74517e13 | ||
|
|
ded2f003f6 | ||
|
|
fd89caee64 | ||
|
|
3fd7991663 | ||
|
|
565449d17c |
31
.github/workflows/calibreapp-image-actions.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: Compress Images on Push to Master
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**.jpg'
|
||||
- '**.jpeg'
|
||||
- '**.png'
|
||||
- '**.webp'
|
||||
jobs:
|
||||
build:
|
||||
name: calibreapp/image-actions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@master
|
||||
- name: Compress Images
|
||||
id: calibre
|
||||
uses: calibreapp/image-actions@master
|
||||
with:
|
||||
githubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
compressOnly: true
|
||||
- name: Create New Pull Request If Needed
|
||||
if: steps.calibre.outputs.markdown != ''
|
||||
uses: peter-evans/create-pull-request@master
|
||||
with:
|
||||
title: Compressed Images
|
||||
branch-suffix: timestamp
|
||||
commit-message: Compressed Images
|
||||
body: ${{ steps.calibre.outputs.markdown }}
|
||||
10
CHANGELOG.md
@@ -1,3 +1,13 @@
|
||||
## v0.29 (2020-10-29)
|
||||
|
||||
Changes:
|
||||
- Rebrand to Catima
|
||||
- Removed intro
|
||||
- Add floating action buttons
|
||||
- Fix Android 5 crash when opening About screen
|
||||
- Add favourites support
|
||||
- Fix disabled auto-rotate being ignored
|
||||
|
||||
## v0.28 (2020-03-09)
|
||||
|
||||
Changes:
|
||||
|
||||
@@ -13,8 +13,8 @@ android {
|
||||
applicationId "me.hackerchick.catima"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 29
|
||||
versionCode 39
|
||||
versionName "0.28"
|
||||
versionCode 40
|
||||
versionName "0.29"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@@ -32,11 +32,6 @@ android {
|
||||
disable "MissingTranslation"
|
||||
disable "MissingPrefix"
|
||||
}
|
||||
sourceSets {
|
||||
test {
|
||||
resources.srcDirs += ['src/test/resources']
|
||||
}
|
||||
}
|
||||
|
||||
// Starting with Android Studio 3 Robolectric is unable to find resources.
|
||||
// The following allows it to find the resources.
|
||||
@@ -62,6 +57,9 @@ dependencies {
|
||||
compile "com.vanniktech:vntnumberpickerpreference:1.0.0"
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile "org.robolectric:robolectric:4.0.2"
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
task findbugs(type: FindBugs, dependsOn: 'assembleDebug') {
|
||||
|
||||
@@ -12,4 +12,4 @@ public class ApplicationTest extends ApplicationTestCase<Application>
|
||||
{
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,14 +42,13 @@
|
||||
<activity
|
||||
android:name=".LoyaltyCardEditActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:exported="true">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Accepts URIs that begin with "https://thelastproject.github.io/Catima/share" or "https://brarcher.github.io/loyalty-card-locker/share” -->
|
||||
<!-- Accepts URIs that begin with "https://github.com/brarcher/loyalty-card-locker/” -->
|
||||
<data android:scheme="https"
|
||||
android:host="@string/intent_import_card_from_url_host"
|
||||
android:pathPrefix="@string/intent_import_card_from_url_path_prefix" />
|
||||
@@ -57,39 +56,22 @@
|
||||
android:host="@string/intent_import_card_from_url_host_old"
|
||||
android:pathPrefix="@string/intent_import_card_from_url_path_prefix_old" />
|
||||
</intent-filter>
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<!-- Accept pkpass files -->
|
||||
<data android:scheme="content" android:mimeType="application/octet-stream"/>
|
||||
<data android:scheme="content" android:mimeType="application/x-compressed"/>
|
||||
<data android:scheme="content" android:mimeType="application/x-zip-compressed"/>
|
||||
<data android:scheme="content" android:mimeType="application/zip"/>
|
||||
<data android:scheme="content" android:mimeType="application/vnd.apple.pkpass"/>
|
||||
<data android:scheme="content" android:mimeType="application/pkpass"/>
|
||||
<data android:scheme="content" android:mimeType="application/vndapplepkpass"/>
|
||||
<data android:scheme="content" android:mimeType="application/vnd-com.apple.pkpass"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".BarcodeSelectorActivity"
|
||||
android:label="@string/selectBarcodeTitle"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateHidden"/>
|
||||
<activity
|
||||
android:name=".preferences.SettingsActivity"
|
||||
android:label="@string/settings"
|
||||
android:configChanges="orientation|screenSize"/>
|
||||
android:label="@string/settings"/>
|
||||
<activity
|
||||
android:name=".ImportExportActivity"
|
||||
android:label="@string/importExport"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
<activity
|
||||
android:name=".CardShortcutConfigure"
|
||||
android:label="@string/cardShortcut"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
|
||||
|
||||
BIN
app/src/main/ic_launcher-playstore.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
@@ -4,7 +4,6 @@ import android.database.Cursor;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
@@ -27,7 +26,7 @@ public class CsvDatabaseExporter implements DatabaseExporter
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR,
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR,
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE,
|
||||
DBHelper.LoyaltyCardDbIds.EXTRAS);
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS);
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
|
||||
@@ -35,15 +34,6 @@ public class CsvDatabaseExporter implements DatabaseExporter
|
||||
{
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cursor);
|
||||
|
||||
String extras;
|
||||
try {
|
||||
extras = card.extras.toJSON().toString();
|
||||
}
|
||||
catch (JSONException ex)
|
||||
{
|
||||
throw new IOException(ex);
|
||||
}
|
||||
|
||||
printer.printRecord(card.id,
|
||||
card.store,
|
||||
card.note,
|
||||
@@ -51,7 +41,7 @@ public class CsvDatabaseExporter implements DatabaseExporter
|
||||
card.headerColor,
|
||||
card.headerTextColor,
|
||||
card.barcodeType,
|
||||
extras);
|
||||
card.starStatus);
|
||||
|
||||
if(Thread.currentThread().isInterrupted())
|
||||
{
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.text.Normalizer;
|
||||
|
||||
/**
|
||||
* Class for importing a database from CSV (Comma Separate Values)
|
||||
@@ -146,23 +142,14 @@ public class CsvDatabaseImporter implements DatabaseImporter
|
||||
headerTextColor = extractInt(DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR, record, true);
|
||||
}
|
||||
|
||||
Bitmap icon = null;
|
||||
String iconData = extractString(DBHelper.LoyaltyCardDbIds.ICON, record, "");
|
||||
if(!iconData.isEmpty())
|
||||
{
|
||||
icon = DBHelper.convertBitmapBlobToBitmap(iconData.getBytes("UTF-8"));
|
||||
}
|
||||
|
||||
ExtrasHelper extras = new ExtrasHelper();
|
||||
|
||||
try
|
||||
{
|
||||
extras.fromJSON(new JSONObject(extractString(DBHelper.LoyaltyCardDbIds.EXTRAS, record, "{}")));
|
||||
helper.insertLoyaltyCard(database, id, store, note, cardId, barcodeType, headerColor, headerTextColor, icon, extras);
|
||||
}
|
||||
catch (JSONException ex)
|
||||
{
|
||||
throw new FormatException("Invalid JSON in extras field: " + ex);
|
||||
int starStatus = 0;
|
||||
try {
|
||||
starStatus = extractInt(DBHelper.LoyaltyCardDbIds.STAR_STATUS, record, false);
|
||||
} catch (FormatException _ ) {
|
||||
// This field did not exist in versions 0.28 and before
|
||||
// We catch this exception so we can still import old backups
|
||||
}
|
||||
if (starStatus != 1) starStatus = 0;
|
||||
helper.insertLoyaltyCard(database, id, store, note, cardId, barcodeType, headerColor, headerTextColor, starStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,6 @@ import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class DBHelper extends SQLiteOpenHelper
|
||||
{
|
||||
@@ -31,8 +23,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
public static final String HEADER_TEXT_COLOR = "headertextcolor";
|
||||
public static final String CARD_ID = "cardid";
|
||||
public static final String BARCODE_TYPE = "barcodetype";
|
||||
public static final String ICON = "icon";
|
||||
public static final String EXTRAS = "extras";
|
||||
public static final String STAR_STATUS = "starstatus";
|
||||
}
|
||||
|
||||
public DBHelper(Context context)
|
||||
@@ -40,19 +31,6 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
public static byte[] convertBitmapToBlob(Bitmap bitmap)
|
||||
{
|
||||
// https://stackoverflow.com/a/7620610
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 0, byteArrayOutputStream);
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
public static Bitmap convertBitmapBlobToBitmap(byte[] bytes)
|
||||
{
|
||||
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db)
|
||||
{
|
||||
@@ -65,8 +43,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
LoyaltyCardDbIds.HEADER_TEXT_COLOR + " INTEGER," +
|
||||
LoyaltyCardDbIds.CARD_ID + " TEXT not null," +
|
||||
LoyaltyCardDbIds.BARCODE_TYPE + " TEXT not null," +
|
||||
LoyaltyCardDbIds.ICON + " BLOB," +
|
||||
LoyaltyCardDbIds.EXTRAS + " TEXT)");
|
||||
LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0' )");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,21 +64,18 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.HEADER_TEXT_COLOR + " INTEGER");
|
||||
}
|
||||
|
||||
// Upgrade from version 3 to version 4
|
||||
if(oldVersion < 4 && newVersion >= 4)
|
||||
{
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.ICON + " BLOB");
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.EXTRAS + " TEXT");
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0'");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public long insertLoyaltyCard(final String store, final String note, final String cardId,
|
||||
final String barcodeType, final Integer headerColor,
|
||||
final Integer headerTextColor, final Bitmap icon,
|
||||
final ExtrasHelper extras) throws JSONException
|
||||
final Integer headerTextColor, final int starStatus)
|
||||
{
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
@@ -111,8 +85,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_TEXT_COLOR, headerTextColor);
|
||||
contentValues.put(LoyaltyCardDbIds.ICON, icon != null ? convertBitmapToBlob(icon) : null);
|
||||
contentValues.put(LoyaltyCardDbIds.EXTRAS, extras.toJSON().toString());
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
|
||||
final long newId = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
|
||||
return newId;
|
||||
}
|
||||
@@ -120,8 +93,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
public boolean insertLoyaltyCard(final SQLiteDatabase db, final int id,
|
||||
final String store, final String note, final String cardId,
|
||||
final String barcodeType, final Integer headerColor,
|
||||
final Integer headerTextColor, final Bitmap icon,
|
||||
final ExtrasHelper extras) throws JSONException
|
||||
final Integer headerTextColor, final int starStatus)
|
||||
{
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbIds.ID, id);
|
||||
@@ -131,8 +103,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_TEXT_COLOR, headerTextColor);
|
||||
contentValues.put(LoyaltyCardDbIds.ICON, icon != null ? convertBitmapToBlob(icon) : null);
|
||||
contentValues.put(LoyaltyCardDbIds.EXTRAS, extras.toJSON().toString());
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS,starStatus);
|
||||
final long newId = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
|
||||
return (newId != -1);
|
||||
}
|
||||
@@ -140,8 +111,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
|
||||
public boolean updateLoyaltyCard(final int id, final String store, final String note,
|
||||
final String cardId, final String barcodeType,
|
||||
final Integer headerColor, final Integer headerTextColor,
|
||||
final Bitmap icon, final ExtrasHelper extras) throws JSONException
|
||||
final Integer headerColor, final Integer headerTextColor)
|
||||
{
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
@@ -151,8 +121,17 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_TEXT_COLOR, headerTextColor);
|
||||
contentValues.put(LoyaltyCardDbIds.ICON, icon != null ? convertBitmapToBlob(icon) : null);
|
||||
contentValues.put(LoyaltyCardDbIds.EXTRAS, extras.toJSON().toString());
|
||||
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE, contentValues,
|
||||
LoyaltyCardDbIds.ID + "=?",
|
||||
new String[]{Integer.toString(id)});
|
||||
return (rowsUpdated == 1);
|
||||
}
|
||||
|
||||
public boolean updateLoyaltyCardStarStatus(final int id, final int starStatus)
|
||||
{
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS,starStatus);
|
||||
int rowsUpdated = db.update(LoyaltyCardDbIds.TABLE, contentValues,
|
||||
LoyaltyCardDbIds.ID + "=?",
|
||||
new String[]{Integer.toString(id)});
|
||||
@@ -209,7 +188,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
Cursor res = db.rawQuery("select * from " + LoyaltyCardDbIds.TABLE +
|
||||
" WHERE " + LoyaltyCardDbIds.STORE + " LIKE ? " +
|
||||
" OR " + LoyaltyCardDbIds.NOTE + " LIKE ? " +
|
||||
" ORDER BY " + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC", selectionArgs, null);
|
||||
" ORDER BY " + LoyaltyCardDbIds.STAR_STATUS + " DESC," + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC", selectionArgs, null);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class ExtrasHelper {
|
||||
private HashMap<String, LinkedHashMap<String, String>> extras = new HashMap<>();
|
||||
|
||||
public ExtrasHelper fromJSON(JSONObject json) throws JSONException
|
||||
{
|
||||
Iterator<String> languages = json.keys();
|
||||
|
||||
while(languages.hasNext())
|
||||
{
|
||||
String language = languages.next();
|
||||
Iterator<String> keys = json.getJSONObject(language).keys();
|
||||
|
||||
while(keys.hasNext())
|
||||
{
|
||||
String key = keys.next();
|
||||
addLanguageValue(language, key, json.getJSONObject(language).getString(key));
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public JSONObject toJSON() throws JSONException
|
||||
{
|
||||
return new JSONObject(extras);
|
||||
}
|
||||
|
||||
public void addLanguageValue(String language, String key, String value)
|
||||
{
|
||||
if(!extras.containsKey(language))
|
||||
{
|
||||
extras.put(language, new LinkedHashMap<String, String>());
|
||||
}
|
||||
|
||||
LinkedHashMap<String, String> values = extras.get(language);
|
||||
values.put(key, value);
|
||||
|
||||
extras.put(language, values);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public LinkedHashMap<String, String> getAllValues(String language)
|
||||
{
|
||||
return getAllValues(new String[]{language});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public LinkedHashMap<String, String> getAllValues(String[] languages)
|
||||
{
|
||||
LinkedHashMap<String, String> values = new LinkedHashMap<>();
|
||||
|
||||
// Get least preferred language (last in list) first
|
||||
// Then go further and further to the start of the list (preferred language)
|
||||
for(int i = (languages.length - 1); i >= 0; i--)
|
||||
{
|
||||
LinkedHashMap<String, String> languageValues = extras.get(languages[i]);
|
||||
|
||||
if(languageValues != null)
|
||||
{
|
||||
values.putAll(languageValues);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,7 @@ package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.util.Base64;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.InvalidObjectException;
|
||||
|
||||
public class ImportURIHelper {
|
||||
@@ -16,10 +10,11 @@ public class ImportURIHelper {
|
||||
private static final String NOTE = DBHelper.LoyaltyCardDbIds.NOTE;
|
||||
private static final String CARD_ID = DBHelper.LoyaltyCardDbIds.CARD_ID;
|
||||
private static final String BARCODE_TYPE = DBHelper.LoyaltyCardDbIds.BARCODE_TYPE;
|
||||
|
||||
private static final String HEADER_COLOR = DBHelper.LoyaltyCardDbIds.HEADER_COLOR;
|
||||
private static final String HEADER_TEXT_COLOR = DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR;
|
||||
private static final String ICON = DBHelper.LoyaltyCardDbIds.ICON;
|
||||
private static final String EXTRAS = DBHelper.LoyaltyCardDbIds.EXTRAS;
|
||||
|
||||
|
||||
|
||||
private final Context context;
|
||||
private final String host;
|
||||
@@ -32,12 +27,12 @@ public class ImportURIHelper {
|
||||
this.context = context;
|
||||
host = context.getResources().getString(R.string.intent_import_card_from_url_host);
|
||||
path = context.getResources().getString(R.string.intent_import_card_from_url_path_prefix);
|
||||
oldHost = context.getResources().getString(R.string.intent_import_card_from_url_host_old);
|
||||
oldPath = context.getResources().getString(R.string.intent_import_card_from_url_path_prefix_old);
|
||||
oldHost = "brarcher.github.io";
|
||||
oldPath = "/loyalty-card-locker/share";
|
||||
shareText = context.getResources().getString(R.string.intent_import_card_from_url_share_text);
|
||||
}
|
||||
|
||||
public boolean isImportUri(Uri uri) {
|
||||
private boolean isImportUri(Uri uri) {
|
||||
return (uri.getHost().equals(host) && uri.getPath().equals(path)) || (uri.getHost().equals(oldHost) && uri.getPath().equals(oldPath));
|
||||
}
|
||||
|
||||
@@ -55,6 +50,8 @@ public class ImportURIHelper {
|
||||
String note = uri.getQueryParameter(NOTE);
|
||||
String cardId = uri.getQueryParameter(CARD_ID);
|
||||
String barcodeType = uri.getQueryParameter(BARCODE_TYPE);
|
||||
if (store == null || note == null || cardId == null || barcodeType == null) throw new InvalidObjectException("Not a valid import URI");
|
||||
|
||||
String unparsedHeaderColor = uri.getQueryParameter(HEADER_COLOR);
|
||||
if(unparsedHeaderColor != null)
|
||||
{
|
||||
@@ -65,36 +62,15 @@ public class ImportURIHelper {
|
||||
{
|
||||
headerTextColor = Integer.parseInt(unparsedHeaderTextColor);
|
||||
}
|
||||
String iconData = uri.getQueryParameter(ICON);
|
||||
Bitmap icon = null;
|
||||
|
||||
if(iconData != null && !iconData.isEmpty())
|
||||
{
|
||||
byte[] iconBytes = Base64.decode(iconData, Base64.URL_SAFE);
|
||||
icon = DBHelper.convertBitmapBlobToBitmap(iconBytes);
|
||||
}
|
||||
|
||||
String extrasData = uri.getQueryParameter(EXTRAS);
|
||||
ExtrasHelper extras = new ExtrasHelper();
|
||||
if(extrasData != null && !extrasData.isEmpty())
|
||||
{
|
||||
extras.fromJSON(new JSONObject(uri.getQueryParameter(EXTRAS)));
|
||||
}
|
||||
|
||||
return new LoyaltyCard(-1, store, note, cardId, barcodeType, headerColor, headerTextColor, icon, extras);
|
||||
} catch (NullPointerException | NumberFormatException | JSONException ex) {
|
||||
return new LoyaltyCard(-1, store, note, cardId, barcodeType, headerColor, headerTextColor, 0);
|
||||
} catch (NullPointerException | NumberFormatException ex) {
|
||||
throw new InvalidObjectException("Not a valid import URI");
|
||||
}
|
||||
}
|
||||
|
||||
// Protected for usage in tests
|
||||
protected Uri toUri(LoyaltyCard loyaltyCard) throws JSONException {
|
||||
String icon = "";
|
||||
if(loyaltyCard.icon != null)
|
||||
{
|
||||
icon = Base64.encodeToString(DBHelper.convertBitmapToBlob(loyaltyCard.icon), Base64.URL_SAFE);
|
||||
}
|
||||
|
||||
protected Uri toUri(LoyaltyCard loyaltyCard) {
|
||||
Uri.Builder uriBuilder = new Uri.Builder();
|
||||
uriBuilder.scheme("https");
|
||||
uriBuilder.authority(host);
|
||||
@@ -111,9 +87,7 @@ public class ImportURIHelper {
|
||||
{
|
||||
uriBuilder.appendQueryParameter(HEADER_TEXT_COLOR, loyaltyCard.headerTextColor.toString());
|
||||
}
|
||||
uriBuilder.appendQueryParameter(ICON, icon);
|
||||
uriBuilder.appendQueryParameter(EXTRAS, loyaltyCard.extras.toJSON().toString());
|
||||
|
||||
//StarStatus will not be exported
|
||||
return uriBuilder.build();
|
||||
}
|
||||
|
||||
@@ -127,14 +101,7 @@ public class ImportURIHelper {
|
||||
context.startActivity(shareIntent);
|
||||
}
|
||||
|
||||
public boolean startShareIntent(LoyaltyCard loyaltyCard) {
|
||||
try
|
||||
{
|
||||
startShareIntent(toUri(loyaltyCard));
|
||||
return true;
|
||||
}
|
||||
catch (JSONException ex) {}
|
||||
|
||||
return false;
|
||||
public void startShareIntent(LoyaltyCard loyaltyCard) {
|
||||
startShareIntent(toUri(loyaltyCard));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class LoyaltyCard
|
||||
{
|
||||
public final int id;
|
||||
@@ -22,15 +17,10 @@ public class LoyaltyCard
|
||||
@Nullable
|
||||
public final Integer headerTextColor;
|
||||
|
||||
@Nullable
|
||||
public final Bitmap icon;
|
||||
|
||||
@Nullable
|
||||
public final ExtrasHelper extras;
|
||||
public final int starStatus;
|
||||
|
||||
public LoyaltyCard(final int id, final String store, final String note, final String cardId,
|
||||
final String barcodeType, final Integer headerColor, final Integer headerTextColor,
|
||||
final Bitmap icon, final ExtrasHelper extras)
|
||||
final String barcodeType, final Integer headerColor, final Integer headerTextColor,final int starStatus)
|
||||
{
|
||||
this.id = id;
|
||||
this.store = store;
|
||||
@@ -39,8 +29,7 @@ public class LoyaltyCard
|
||||
this.barcodeType = barcodeType;
|
||||
this.headerColor = headerColor;
|
||||
this.headerTextColor = headerTextColor;
|
||||
this.icon = icon;
|
||||
this.extras = extras;
|
||||
this.starStatus = starStatus;
|
||||
}
|
||||
|
||||
public static LoyaltyCard toLoyaltyCard(Cursor cursor)
|
||||
@@ -50,6 +39,8 @@ public class LoyaltyCard
|
||||
String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE));
|
||||
String cardId = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID));
|
||||
String barcodeType = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE));
|
||||
int starred = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS));
|
||||
|
||||
|
||||
int headerColorColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR);
|
||||
int headerTextColorColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR);
|
||||
@@ -67,32 +58,6 @@ public class LoyaltyCard
|
||||
headerTextColor = cursor.getInt(headerTextColorColumn);
|
||||
}
|
||||
|
||||
int iconColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ICON);
|
||||
Bitmap icon = null;
|
||||
|
||||
if(cursor.isNull(iconColumn) == false)
|
||||
{
|
||||
byte[] iconData = cursor.getBlob(iconColumn);
|
||||
icon = BitmapFactory.decodeByteArray(iconData, 0, iconData.length);
|
||||
}
|
||||
|
||||
int extrasColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXTRAS);
|
||||
ExtrasHelper extras = new ExtrasHelper();
|
||||
|
||||
if(cursor.isNull(extrasColumn) == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
extras = extras.fromJSON(new JSONObject(cursor.getString(extrasColumn)));
|
||||
}
|
||||
catch (JSONException ex)
|
||||
{
|
||||
// That this is actually JSON is an implementation detail
|
||||
// The important part is that the DB is in a bad state
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return new LoyaltyCard(id, store, note, cardId, barcodeType, headerColor, headerTextColor, icon, extras);
|
||||
return new LoyaltyCard(id, store, note, cardId, barcodeType, headerColor, headerTextColor, starred);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,27 @@ package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.util.Log;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
class LoyaltyCardCursorAdapter extends CursorAdapter
|
||||
{
|
||||
Settings settings;
|
||||
boolean darkModeEnabled;
|
||||
|
||||
public LoyaltyCardCursorAdapter(Context context, Cursor cursor)
|
||||
{
|
||||
super(context, cursor, 0);
|
||||
settings = new Settings(context);
|
||||
darkModeEnabled= MainActivity.isDarkModeEnabled(context);
|
||||
|
||||
}
|
||||
|
||||
// The newView method is used to inflate a new view and return it,
|
||||
@@ -37,8 +40,14 @@ class LoyaltyCardCursorAdapter extends CursorAdapter
|
||||
{
|
||||
// Find fields to populate in inflated template
|
||||
ImageView thumbnail = view.findViewById(R.id.thumbnail);
|
||||
TextView storeField = (TextView) view.findViewById(R.id.store);
|
||||
TextView noteField = (TextView) view.findViewById(R.id.note);
|
||||
TextView storeField = view.findViewById(R.id.store);
|
||||
TextView noteField = view.findViewById(R.id.note);
|
||||
ImageView star = view.findViewById(R.id.star);
|
||||
|
||||
if(darkModeEnabled)
|
||||
{
|
||||
star.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
|
||||
}
|
||||
|
||||
// Extract properties from cursor
|
||||
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(cursor);
|
||||
@@ -48,7 +57,7 @@ class LoyaltyCardCursorAdapter extends CursorAdapter
|
||||
|
||||
storeField.setTextSize(settings.getCardTitleListFontSize());
|
||||
|
||||
if(loyaltyCard.note.isEmpty() == false)
|
||||
if(!loyaltyCard.note.isEmpty())
|
||||
{
|
||||
noteField.setVisibility(View.VISIBLE);
|
||||
noteField.setText(loyaltyCard.note);
|
||||
@@ -59,21 +68,16 @@ class LoyaltyCardCursorAdapter extends CursorAdapter
|
||||
noteField.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (loyaltyCard.starStatus!=0) star.setVisibility(View.VISIBLE);
|
||||
else star.setVisibility(View.GONE);
|
||||
|
||||
int tileLetterFontSize = context.getResources().getDimensionPixelSize(R.dimen.tileLetterFontSize);
|
||||
int pixelSize = context.getResources().getDimensionPixelSize(R.dimen.cardThumbnailSize);
|
||||
|
||||
|
||||
if(loyaltyCard.icon == null)
|
||||
{
|
||||
Integer letterBackgroundColor = loyaltyCard.headerColor;
|
||||
Integer letterTextColor = loyaltyCard.headerTextColor;
|
||||
LetterBitmap letterBitmap = new LetterBitmap(context, loyaltyCard.store, loyaltyCard.store,
|
||||
tileLetterFontSize, pixelSize, pixelSize, letterBackgroundColor, letterTextColor);
|
||||
thumbnail.setImageBitmap(letterBitmap.getLetterTile());
|
||||
}
|
||||
else
|
||||
{
|
||||
thumbnail.setImageBitmap(loyaltyCard.icon);
|
||||
}
|
||||
Integer letterBackgroundColor = loyaltyCard.headerColor;
|
||||
Integer letterTextColor = loyaltyCard.headerTextColor;
|
||||
LetterBitmap letterBitmap = new LetterBitmap(context, loyaltyCard.store, loyaltyCard.store,
|
||||
tileLetterFontSize, pixelSize, pixelSize, letterBackgroundColor, letterTextColor);
|
||||
thumbnail.setImageBitmap(letterBitmap.getLetterTile());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@@ -33,10 +32,6 @@ import com.google.zxing.integration.android.IntentResult;
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialog;
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
|
||||
public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
@@ -66,53 +61,23 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
int loyaltyCardId;
|
||||
boolean updateLoyaltyCard;
|
||||
Uri importLoyaltyCardUri = null;
|
||||
String importLoyaltyCardType = null;
|
||||
Integer headingColorValue = null;
|
||||
Integer headingStoreTextColorValue = null;
|
||||
Bitmap icon = null;
|
||||
ExtrasHelper extras = new ExtrasHelper();
|
||||
|
||||
DBHelper db;
|
||||
ImportURIHelper importUriHelper;
|
||||
PkpassImporter pkpassImporter;
|
||||
|
||||
private void extractIntentFields(Intent intent)
|
||||
{
|
||||
final Bundle b = intent.getExtras();
|
||||
loyaltyCardId = b != null ? b.getInt("id") : 0;
|
||||
updateLoyaltyCard = b != null && b.getBoolean("update", false);
|
||||
importLoyaltyCardType = intent.getType();
|
||||
importLoyaltyCardUri = intent.getData();
|
||||
|
||||
Log.d(TAG, "View activity: id=" + loyaltyCardId
|
||||
+ ", updateLoyaltyCard=" + Boolean.toString(updateLoyaltyCard));
|
||||
}
|
||||
|
||||
private LoyaltyCard importCard(String type, Uri uri)
|
||||
{
|
||||
// Import URI
|
||||
if(importUriHelper.isImportUri(uri))
|
||||
{
|
||||
try
|
||||
{
|
||||
return importUriHelper.parse(importLoyaltyCardUri);
|
||||
}
|
||||
catch (InvalidObjectException ex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Pkpass
|
||||
try
|
||||
{
|
||||
return pkpassImporter.fromURI(uri);
|
||||
}
|
||||
catch (IOException | JSONException ex) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
@@ -131,7 +96,6 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
|
||||
db = new DBHelper(this);
|
||||
importUriHelper = new ImportURIHelper(this);
|
||||
pkpassImporter = new PkpassImporter(this);
|
||||
|
||||
storeFieldEdit = findViewById(R.id.storeNameEdit);
|
||||
noteFieldEdit = findViewById(R.id.noteEdit);
|
||||
@@ -222,17 +186,15 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
extras = loyaltyCard.extras;
|
||||
|
||||
setTitle(R.string.editCardTitle);
|
||||
}
|
||||
else if(importLoyaltyCardUri != null)
|
||||
{
|
||||
// Try to parse
|
||||
LoyaltyCard importCard = importCard(importLoyaltyCardType, importLoyaltyCardUri);
|
||||
|
||||
if(importCard == null)
|
||||
{
|
||||
LoyaltyCard importCard;
|
||||
try {
|
||||
importCard = importUriHelper.parse(importLoyaltyCardUri);
|
||||
} catch (InvalidObjectException ex) {
|
||||
Toast.makeText(this, R.string.failedParsingImportUriError, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
@@ -244,8 +206,6 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
barcodeTypeField.setText(importCard.barcodeType);
|
||||
headingColorValue = importCard.headerColor;
|
||||
headingStoreTextColorValue = importCard.headerTextColor;
|
||||
icon = importCard.icon;
|
||||
extras = importCard.extras;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -371,11 +331,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
saveButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
doSave();
|
||||
} catch (JSONException ex) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedSavingCard, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
doSave();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -422,7 +378,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void doSave() throws JSONException
|
||||
private void doSave()
|
||||
{
|
||||
String store = storeFieldEdit.getText().toString();
|
||||
String note = noteFieldEdit.getText().toString();
|
||||
@@ -449,13 +405,13 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
if(updateLoyaltyCard)
|
||||
{
|
||||
db.updateLoyaltyCard(loyaltyCardId, store, note, cardId, barcodeType, headingColorValue, headingStoreTextColorValue, icon, extras);
|
||||
{ //update of "starStatus" not necessary, since it cannot be changed in this activity (only in ViewActivity)
|
||||
db.updateLoyaltyCard(loyaltyCardId, store, note, cardId, barcodeType, headingColorValue, headingStoreTextColorValue);
|
||||
Log.i(TAG, "Updated " + loyaltyCardId + " to " + cardId);
|
||||
}
|
||||
else
|
||||
{
|
||||
loyaltyCardId = (int)db.insertLoyaltyCard(store, note, cardId, barcodeType, headingColorValue, headingStoreTextColorValue, icon, extras);
|
||||
loyaltyCardId = (int)db.insertLoyaltyCard(store, note, cardId, barcodeType, headingColorValue, headingStoreTextColorValue, 0);
|
||||
}
|
||||
|
||||
finish();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package protect.card_locker;
|
||||
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Color;
|
||||
@@ -9,7 +8,6 @@ import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
@@ -34,12 +32,6 @@ import android.widget.Toast;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
|
||||
@@ -64,6 +56,7 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
String cardIdString;
|
||||
BarcodeFormat format;
|
||||
|
||||
boolean starred;
|
||||
boolean backgroundNeedsDarkIcons;
|
||||
boolean barcodeIsFullscreen = false;
|
||||
ViewGroup.LayoutParams barcodeImageState;
|
||||
@@ -325,18 +318,29 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
item.setVisible(false);
|
||||
}
|
||||
|
||||
if(loyaltyCard != null && !loyaltyCard.extras.getAllValues(new String[]{Locale.getDefault().getLanguage(), "en", ""}).isEmpty())
|
||||
{
|
||||
MenuItem extraItem = menu.findItem(R.id.action_view_extras);
|
||||
extraItem.setIcon(getIcon(R.drawable.ic_info_outline_white, backgroundNeedsDarkIcons));
|
||||
extraItem.setVisible(true);
|
||||
}
|
||||
loyaltyCard = db.getLoyaltyCard(loyaltyCardId);
|
||||
starred = loyaltyCard.starStatus != 0;
|
||||
|
||||
menu.findItem(R.id.action_share).setIcon(getIcon(R.drawable.ic_share_white, backgroundNeedsDarkIcons));
|
||||
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
if (starred) {
|
||||
menu.findItem(R.id.action_star_unstar).setIcon(getIcon(R.drawable.ic_starred_white, backgroundNeedsDarkIcons));
|
||||
menu.findItem(R.id.action_star_unstar).setTitle(R.string.unstar);
|
||||
}
|
||||
else {
|
||||
menu.findItem(R.id.action_star_unstar).setIcon(getIcon(R.drawable.ic_unstarred_white, backgroundNeedsDarkIcons));
|
||||
menu.findItem(R.id.action_star_unstar).setTitle(R.string.star);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
@@ -364,22 +368,17 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
rotationEnabled = !rotationEnabled;
|
||||
return true;
|
||||
|
||||
case R.id.action_view_extras:
|
||||
try
|
||||
{
|
||||
displayExtrasDialog();
|
||||
}
|
||||
catch (JSONException ex)
|
||||
{
|
||||
Toast.makeText(this, R.string.failedShowingExtras, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
case R.id.action_star_unstar:
|
||||
starred = !starred;
|
||||
db.updateLoyaltyCardStarStatus(loyaltyCardId, starred ? 1 : 0);
|
||||
invalidateOptionsMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
private void setOrientatonLock(MenuItem item, boolean lock)
|
||||
{
|
||||
if(lock)
|
||||
@@ -393,33 +392,10 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
{
|
||||
item.setIcon(getIcon(R.drawable.ic_lock_open_white_24dp, backgroundNeedsDarkIcons));
|
||||
item.setTitle(R.string.lockScreen);
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
private void displayExtrasDialog() throws JSONException
|
||||
{
|
||||
StringBuilder items = new StringBuilder();
|
||||
|
||||
HashMap<String, String> extraValues = loyaltyCard.extras.getAllValues(new String[]{Locale.getDefault().getLanguage(), "en", ""});
|
||||
for(Map.Entry<String, String> entry : extraValues.entrySet())
|
||||
{
|
||||
items.append(entry.getValue() + "\n");
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage(items.toString())
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* When enabled, hides the status bar and moves the barcode to the top of the screen.
|
||||
*
|
||||
|
||||
@@ -2,20 +2,15 @@ package protect.card_locker;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.Menu;
|
||||
@@ -27,13 +22,14 @@ import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Map;
|
||||
|
||||
import protect.card_locker.preferences.SettingsActivity;
|
||||
|
||||
public class MainActivity extends AppCompatActivity
|
||||
@@ -195,26 +191,20 @@ public class MainActivity extends AppCompatActivity
|
||||
Cursor cardCursor = (Cursor)listView.getItemAtPosition(info.position);
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor);
|
||||
|
||||
if(card != null)
|
||||
if(item.getItemId() == R.id.action_clipboard)
|
||||
{
|
||||
if(item.getItemId() == R.id.action_clipboard)
|
||||
{
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(card.store, card.cardId);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(card.store, card.cardId);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
|
||||
Toast.makeText(this, R.string.copy_to_clipboard_toast, Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
else if(item.getItemId() == R.id.action_share)
|
||||
{
|
||||
final ImportURIHelper importURIHelper = new ImportURIHelper(this);
|
||||
if(importURIHelper.startShareIntent(card))
|
||||
{
|
||||
Toast.makeText(this, R.string.failedSharingCard, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Toast.makeText(this, R.string.copy_to_clipboard_toast, Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
else if(item.getItemId() == R.id.action_share)
|
||||
{
|
||||
final ImportURIHelper importURIHelper = new ImportURIHelper(this);
|
||||
importURIHelper.startShareIntent(card);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onContextItemSelected(item);
|
||||
@@ -336,9 +326,7 @@ public class MainActivity extends AppCompatActivity
|
||||
|
||||
// Set CSS for dark mode if dark mode
|
||||
String css = "";
|
||||
Configuration config = getResources().getConfiguration();
|
||||
int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
if(currentNightMode == Configuration.UI_MODE_NIGHT_YES)
|
||||
if(isDarkModeEnabled(this))
|
||||
{
|
||||
css = "<style>body {color:white; background-color:black;}</style>";
|
||||
}
|
||||
@@ -384,4 +372,12 @@ public class MainActivity extends AppCompatActivity
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
protected static boolean isDarkModeEnabled(Context inputContext)
|
||||
{
|
||||
Configuration config = inputContext.getResources().getConfiguration();
|
||||
int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
return (currentNightMode == Configuration.UI_MODE_NIGHT_YES);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,319 +0,0 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class PkpassImporter {
|
||||
private Context context;
|
||||
|
||||
private Bitmap icon = null;
|
||||
|
||||
private HashMap<String, HashMap<String, String>> translations = new HashMap<>();
|
||||
|
||||
public PkpassImporter(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private ByteArrayOutputStream readZipInputStream(ZipInputStream zipInputStream) throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[2048];
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
int size;
|
||||
|
||||
while((size = zipInputStream.read(buffer, 0, buffer.length)) != -1)
|
||||
{
|
||||
byteArrayOutputStream.write(buffer, 0, size);
|
||||
}
|
||||
|
||||
return byteArrayOutputStream;
|
||||
}
|
||||
|
||||
private void loadBitmap(ByteArrayOutputStream byteArrayOutputStream)
|
||||
{
|
||||
byte[] bytes = byteArrayOutputStream.toByteArray();
|
||||
// Only keep the largest icon
|
||||
if(icon != null && bytes.length < icon.getByteCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
icon = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
// FIXME: Probably very fragile
|
||||
private void parseTranslations(String language, String iOSTranslationFileContent)
|
||||
{
|
||||
if(!translations.containsKey(language))
|
||||
{
|
||||
translations.put(language, new HashMap<String, String>());
|
||||
}
|
||||
|
||||
HashMap<String, String> values = translations.get(language);
|
||||
|
||||
for (String entry : iOSTranslationFileContent.trim().split(";"))
|
||||
{
|
||||
String[] parts = entry.split(" = ", 2);
|
||||
|
||||
// Remove all spaces around the key and value
|
||||
String key = parts[0].trim();
|
||||
String value = parts[1].trim();
|
||||
|
||||
// iOS .string files quote everything in double quotes, we don't need to keep those
|
||||
values.put(key.substring(1, key.length()-1), value.substring(1, value.length()-1));
|
||||
}
|
||||
|
||||
translations.put(language, values);
|
||||
}
|
||||
|
||||
private ExtrasHelper appendData(ExtrasHelper extrasHelper, JSONObject pkpassJSON, String styleKey, String arrayName) throws JSONException
|
||||
{
|
||||
// https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/FieldDictionary.html#//apple_ref/doc/uid/TP40012026-CH4-SW1
|
||||
|
||||
JSONArray fields;
|
||||
// These are all optional, so don't throw an exception if they don't exist
|
||||
try
|
||||
{
|
||||
fields = pkpassJSON.getJSONObject(styleKey).getJSONArray(arrayName);
|
||||
}
|
||||
catch (JSONException ex)
|
||||
{
|
||||
return extrasHelper;
|
||||
}
|
||||
|
||||
for(int i = 0; i < fields.length(); i++)
|
||||
{
|
||||
JSONObject fieldObject = fields.getJSONObject(i);
|
||||
String key = fieldObject.getString("key");
|
||||
String label = fieldObject.getString("label");
|
||||
String value = fieldObject.getString("value");
|
||||
|
||||
// Label is optional
|
||||
if(label == null)
|
||||
{
|
||||
label = key;
|
||||
}
|
||||
|
||||
// Add the completely untranslated stuff as fallback
|
||||
String formattedUntranslatedValue = value;
|
||||
if(!label.isEmpty())
|
||||
{
|
||||
formattedUntranslatedValue = label + ": " + value;
|
||||
}
|
||||
extrasHelper.addLanguageValue("", key, formattedUntranslatedValue);
|
||||
|
||||
// Try to find translations
|
||||
for(Map.Entry<String, HashMap<String, String>> language : translations.entrySet())
|
||||
{
|
||||
String translatedLabel = label;
|
||||
if(language.getValue().containsKey(label))
|
||||
{
|
||||
translatedLabel = language.getValue().get(label);
|
||||
}
|
||||
|
||||
String translatedValue = value;
|
||||
if(language.getValue().containsKey(value))
|
||||
{
|
||||
translatedValue = language.getValue().get(value);
|
||||
}
|
||||
|
||||
String formattedValue = translatedValue;
|
||||
|
||||
if(!translatedLabel.isEmpty())
|
||||
{
|
||||
formattedValue = translatedLabel + ": " + translatedValue;
|
||||
}
|
||||
|
||||
extrasHelper.addLanguageValue(language.getKey(), key, formattedValue);
|
||||
}
|
||||
}
|
||||
|
||||
return extrasHelper;
|
||||
}
|
||||
|
||||
public LoyaltyCard fromURI(Uri uri) throws IOException, JSONException {
|
||||
return fromInputStream(context.getContentResolver().openInputStream(uri));
|
||||
}
|
||||
|
||||
public LoyaltyCard fromInputStream(InputStream inputStream) throws IOException, JSONException
|
||||
{
|
||||
String passJSONString = null;
|
||||
|
||||
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
|
||||
|
||||
ZipEntry entry;
|
||||
|
||||
// We first want to parse the translations
|
||||
while((entry = zipInputStream.getNextEntry()) != null) {
|
||||
if(entry.getName().endsWith("pass.strings"))
|
||||
{
|
||||
// Example: en.lproj/pass.strings
|
||||
String language = entry.getName().substring(0, entry.getName().indexOf("."));
|
||||
|
||||
parseTranslations(language, readZipInputStream(zipInputStream).toString("UTF-8"));
|
||||
}
|
||||
else if(entry.getName().equals("pass.json"))
|
||||
{
|
||||
passJSONString = readZipInputStream(zipInputStream).toString("UTF-8");
|
||||
}
|
||||
else if(entry.getName().equals("icon.png") || entry.getName().equals("icon@2x.png"))
|
||||
{
|
||||
loadBitmap(readZipInputStream(zipInputStream));
|
||||
}
|
||||
}
|
||||
|
||||
if(passJSONString == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return fromPassJSON(new JSONObject(passJSONString));
|
||||
}
|
||||
|
||||
public LoyaltyCard fromPassJSON(JSONObject json) throws JSONException
|
||||
{
|
||||
String store = json.getString("organizationName");
|
||||
String note = json.getString("description");
|
||||
|
||||
// https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/TopLevel.html#//apple_ref/doc/uid/TP40012026-CH2-SW1
|
||||
// barcodes is the new field
|
||||
// barcode is deprecated, but used on old iOS versions, so we do fall back to it
|
||||
JSONObject barcode = null;
|
||||
JSONArray barcodes = null;
|
||||
|
||||
try {
|
||||
barcodes = json.getJSONArray("barcodes");
|
||||
} catch (JSONException ex) {
|
||||
}
|
||||
|
||||
if (barcodes != null) {
|
||||
barcode = barcodes.getJSONObject(0);
|
||||
} else {
|
||||
barcode = json.getJSONObject("barcode");
|
||||
}
|
||||
|
||||
if (barcode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String cardId = barcode.getString("message");
|
||||
|
||||
// https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/LowerLevel.html#//apple_ref/doc/uid/TP40012026-CH3-SW3
|
||||
// Required. Barcode format. For the barcode dictionary, you can use only the following values: PKBarcodeFormatQR, PKBarcodeFormatPDF417, or PKBarcodeFormatAztec. For dictionaries in the barcodes array, you may also use PKBarcodeFormatCode128.
|
||||
ImmutableMap<String, String> supportedBarcodeTypes = ImmutableMap.<String, String>builder()
|
||||
.put("PKBarcodeFormatQR", BarcodeFormat.QR_CODE.name())
|
||||
.put("PKBarcodeFormatPDF417", BarcodeFormat.PDF_417.name())
|
||||
.put("PKBarcodeFormatAztec", BarcodeFormat.AZTEC.name())
|
||||
.put("PKBarcodeFormatCode128", BarcodeFormat.CODE_128.name())
|
||||
.build();
|
||||
|
||||
String barcodeType = supportedBarcodeTypes.get(barcode.getString("format"));
|
||||
|
||||
if(barcodeType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Prepare to parse colors
|
||||
Pattern rgbPattern = Pattern.compile("^rgb\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*\\)$");
|
||||
|
||||
// Optional. Background color of the pass, specified as an CSS-style RGB triple. For example, rgb(23, 187, 82).
|
||||
Integer headerColor = null;
|
||||
Matcher headerColorMatcher = rgbPattern.matcher(json.getString("backgroundColor"));
|
||||
if(headerColorMatcher.find())
|
||||
{
|
||||
headerColor = Color.rgb(
|
||||
Integer.parseInt(headerColorMatcher.group(1)),
|
||||
Integer.parseInt(headerColorMatcher.group(2)),
|
||||
Integer.parseInt(headerColorMatcher.group(3)));
|
||||
}
|
||||
if(headerColor == null)
|
||||
{
|
||||
// Maybe they violate the spec, let's parse it in a format Android understands
|
||||
// Necessary for at least Eurowings
|
||||
try
|
||||
{
|
||||
headerColor = Color.parseColor(json.getString("backgroundColor"));
|
||||
}
|
||||
catch (IllegalArgumentException ex) {}
|
||||
}
|
||||
|
||||
|
||||
// Optional. Color of the label text, specified as a CSS-style RGB triple. For example, rgb(255, 255, 255).
|
||||
Integer headerTextColor = null;
|
||||
Matcher headerTextColorMatcher = rgbPattern.matcher(json.getString("labelColor"));
|
||||
if(headerTextColorMatcher.find())
|
||||
{
|
||||
headerTextColor = Color.rgb(
|
||||
Integer.parseInt(headerTextColorMatcher.group(1)),
|
||||
Integer.parseInt(headerTextColorMatcher.group(2)),
|
||||
Integer.parseInt(headerTextColorMatcher.group(3)));
|
||||
}
|
||||
if(headerTextColor == null)
|
||||
{
|
||||
// Maybe they violate the spec, let's parse it in a format Android understands
|
||||
// Necessary for at least Eurowings
|
||||
try
|
||||
{
|
||||
headerTextColor = Color.parseColor(json.getString("labelColor"));
|
||||
}
|
||||
catch (IllegalArgumentException ex) {}
|
||||
}
|
||||
|
||||
// https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/TopLevel.html#//apple_ref/doc/uid/TP40012026-CH2-SW6
|
||||
// There needs to be exactly one style key
|
||||
|
||||
String styleKey = null;
|
||||
ImmutableList<String> possibleStyleKeys = ImmutableList.<String>builder()
|
||||
.add("boardingPass")
|
||||
.add("coupon")
|
||||
.add("eventTicket")
|
||||
.add("generic")
|
||||
.add("storeCard")
|
||||
.build();
|
||||
for(int i = 0; i < possibleStyleKeys.size(); i++)
|
||||
{
|
||||
String possibleStyleKey = possibleStyleKeys.get(i);
|
||||
if(json.has(possibleStyleKey))
|
||||
{
|
||||
styleKey = possibleStyleKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(styleKey == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/LowerLevel.html#//apple_ref/doc/uid/TP40012026-CH3-SW14
|
||||
ExtrasHelper extras = new ExtrasHelper();
|
||||
extras = appendData(extras, json, styleKey, "headerFields");
|
||||
extras = appendData(extras, json, styleKey, "primaryFields");
|
||||
extras = appendData(extras, json, styleKey, "secondaryFields");
|
||||
extras = appendData(extras, json, styleKey, "auxiliaryFields");
|
||||
extras = appendData(extras, json, styleKey, "backFields");
|
||||
|
||||
return new LoyaltyCard(-1, store, note, cardId, barcodeType, headerColor, headerTextColor, icon, extras);
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 582 B |
BIN
app/src/main/res/drawable-hdpi/ic_starred_white.png
Normal file
|
After Width: | Height: | Size: 336 B |
BIN
app/src/main/res/drawable-hdpi/ic_unstarred_white.png
Normal file
|
After Width: | Height: | Size: 439 B |
|
Before Width: | Height: | Size: 519 B After Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 371 B |
BIN
app/src/main/res/drawable-mdpi/ic_starred_white.png
Normal file
|
After Width: | Height: | Size: 234 B |
BIN
app/src/main/res/drawable-mdpi/ic_unstarred_white.png
Normal file
|
After Width: | Height: | Size: 299 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 303 B |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 742 B |
BIN
app/src/main/res/drawable-xhdpi/ic_starred_white.png
Normal file
|
After Width: | Height: | Size: 421 B |
BIN
app/src/main/res/drawable-xhdpi/ic_unstarred_white.png
Normal file
|
After Width: | Height: | Size: 564 B |
|
Before Width: | Height: | Size: 651 B After Width: | Height: | Size: 466 B |
|
Before Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_starred_white.png
Normal file
|
After Width: | Height: | Size: 829 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_unstarred_white.png
Normal file
|
After Width: | Height: | Size: 809 B |
|
Before Width: | Height: | Size: 853 B After Width: | Height: | Size: 606 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 758 B |
66
app/src/main/res/drawable/ic_android_launcher.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="192dp"
|
||||
android:height="192dp"
|
||||
android:viewportWidth="50.8"
|
||||
android:viewportHeight="50.8">
|
||||
<path
|
||||
android:pathData="M14.3354,20.1954l20.7318,-9.2304l5.7612,12.9398l-20.7318,9.2304z"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#f0f0f0"
|
||||
android:strokeColor="#c80000"/>
|
||||
<path
|
||||
android:pathData="M14.8755,10.9648l23.2041,10.3311l-6.8874,15.4694l-23.2041,-10.3311z"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#f0f0f0"
|
||||
android:strokeColor="#c80000"/>
|
||||
<path
|
||||
android:pathData="M16.5599,16.1348l26.5459,7.6119l-4.5489,15.8639l-26.5459,-7.6119z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5875"
|
||||
android:fillColor="#c80000"
|
||||
android:strokeColor="#c80000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M12.011,15.4955h27.6157v16.5032h-27.6157z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5875"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#ff0000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M7.8471,23.7471a4.3659,8.5899 0,1 0,8.7317 0a4.3659,8.5899 0,1 0,-8.7317 0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="0.91078"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#ff0000"/>
|
||||
<path
|
||||
android:pathData="m24.4983,25.781a1.6711,1.6711 0,0 1,-1.3809 1.6457,1.6711 1.6711,0 0,1 -1.8605,-1.0741"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#f0f0f0"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m27.7991,26.333a1.6711,1.6711 0,0 1,-1.8605 1.0741,1.6711 1.6711,0 0,1 -1.3809,-1.6457"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#f0f0f0"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m16.0606,22.271 l2.6458,-2.6458 2.6458,2.6458"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#f0f0f0"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="m27.7023,22.271 l2.6458,-2.6458 2.6458,2.6458"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#f0f0f0"
|
||||
android:strokeLineCap="butt"/>
|
||||
</vector>
|
||||
71
app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<group android:scaleX="1.5307087"
|
||||
android:scaleY="1.5307087"
|
||||
android:translateX="15.12"
|
||||
android:translateY="15.12">
|
||||
<path
|
||||
android:pathData="M14.3354,20.1954l20.7318,-9.2304l5.7612,12.9398l-20.7318,9.2304z"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#f0f0f0"
|
||||
android:strokeColor="#c80000"/>
|
||||
<path
|
||||
android:pathData="M14.8755,10.9648l23.2041,10.3311l-6.8874,15.4694l-23.2041,-10.3311z"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#f0f0f0"
|
||||
android:strokeColor="#c80000"/>
|
||||
<path
|
||||
android:pathData="M16.5599,16.1348l26.5459,7.6119l-4.5489,15.8639l-26.5459,-7.6119z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5875"
|
||||
android:fillColor="#c80000"
|
||||
android:strokeColor="#c80000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M12.011,15.4955h27.6157v16.5032h-27.6157z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5875"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#ff0000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M7.8471,23.7471a4.3659,8.5899 0,1 0,8.7317 0a4.3659,8.5899 0,1 0,-8.7317 0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="0.91078"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#ff0000"/>
|
||||
<path
|
||||
android:pathData="m24.4983,25.781a1.6711,1.6711 0,0 1,-1.3809 1.6457,1.6711 1.6711,0 0,1 -1.8605,-1.0741"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#f0f0f0"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m27.7991,26.333a1.6711,1.6711 0,0 1,-1.8605 1.0741,1.6711 1.6711,0 0,1 -1.3809,-1.6457"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#f0f0f0"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m16.0606,22.271 l2.6458,-2.6458 2.6458,2.6458"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#f0f0f0"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="m27.7023,22.271 l2.6458,-2.6458 2.6458,2.6458"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.529167"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#f0f0f0"
|
||||
android:strokeLineCap="butt"/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -52,5 +52,12 @@
|
||||
android:ellipsize="end"
|
||||
android:textSize="@dimen/noteTextSize"/>
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/star"
|
||||
android:layout_width="@dimen/cardThumbnailSize"
|
||||
android:layout_height="@dimen/cardThumbnailSize"
|
||||
android:layout_marginLeft="@dimen/activity_margin"
|
||||
android:src="@drawable/ic_starred_white"
|
||||
android:tint="#000000"
|
||||
android:contentDescription="@string/starImage"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -13,9 +13,8 @@
|
||||
android:title="@string/share"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_view_extras"
|
||||
android:icon="@drawable/ic_info_outline_white"
|
||||
android:title="@string/moreInfo"
|
||||
app:showAsAction="always"
|
||||
android:visible="false"/>
|
||||
android:id="@+id/action_star_unstar"
|
||||
android:icon="@drawable/ic_unstarred_white"
|
||||
android:title="@string/star"
|
||||
app:showAsAction="always" />
|
||||
</menu>
|
||||
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Executable file → Normal file
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 5.5 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
@@ -47,7 +47,6 @@
|
||||
<string name="importOptionApplicationButton">Použít externí aplikaci</string>
|
||||
|
||||
<string name="about">O aplikaci</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licensed under the GPLv3.</string>
|
||||
<string name="about_title_fmt">O aplikaci <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Verze: <xliff:g id="version">%s</xliff:g></string>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<resources
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="action_search">Suche</string>
|
||||
<string name="action_add">Neu</string>
|
||||
|
||||
<string name="noGiftCards">Sie haben noch keine Kundenkarte angelegt. Über den \"+\"-Button oben rechts können welche angelegt werden.\n\nDiese App ermöglicht es, Kundenkarten immer mit zu führen.</string>
|
||||
<string name="noMatchingGiftCards">Es passen keine Kundenkarten zum Suchfilter. Bitte probiere verschiedene Begriffe aus.</string>
|
||||
|
||||
<string name="storeName">Geschäft</string>
|
||||
<string name="note">Notiz</string>
|
||||
<string name="cardId">Kartennummer</string>
|
||||
@@ -20,19 +17,19 @@
|
||||
<string name="confirm">Bestätigen</string>
|
||||
<string name="lockScreen">Rotation blockieren</string>
|
||||
<string name="unlockScreen">Rotation zulassen</string>
|
||||
<string name="star">Zu den Favoriten hinzufügen</string>
|
||||
<string name="unstar">Aus der Favoritenliste entfernen</string>
|
||||
<string name="deleteTitle">Karte entfernen</string>
|
||||
<string name="deleteConfirmation">Bitte bestätigen Sie, dass diese Karte gelöscht werden soll.</string>
|
||||
<string name="ok">Ok</string>
|
||||
<string name="copy_to_clipboard">Kopiere die Nummer in die Zwischenablage</string>
|
||||
<string name="sendLabel">Senden…</string>
|
||||
<string name="sendLabel">Senden…</string>
|
||||
<string name="editCardTitle">Kundenkarte bearbeiten</string>
|
||||
<string name="addCardTitle">Neue Kundenkarte</string>
|
||||
<string name="scanCardBarcode">Barcode scannen</string>
|
||||
<string name="scanCardBarcode">Strichcode scannen</string>
|
||||
<string name="cardShortcut">Shortcut zu einer Karte</string>
|
||||
<string name="noCardsMessage">Es ist noch keine Karte vorhanden, bitte zuerst eine hinzufügen</string>
|
||||
|
||||
<string name="barcodeImageDescription">Bild des Barcodes</string>
|
||||
|
||||
<string name="barcodeImageDescription">Bild des Strichcodes</string>
|
||||
<string name="noStoreError">Kein Geschäft angegeben</string>
|
||||
<string name="noCardIdError">Keine Kartennummer angegeben</string>
|
||||
<string name="noCardExistsError">Karte konnte nicht gefunden werden</string>
|
||||
@@ -48,34 +45,28 @@
|
||||
<string name="exportFailed">Export fehlgeschlagen</string>
|
||||
<string name="importing">Importiere…</string>
|
||||
<string name="exporting">Exportiere…</string>
|
||||
<string name="noExternalStoragePermissionError">Ohne die Berechtigung für den externen Speicher kann kein Import oder Export erfolgen.</string>
|
||||
<string name="noExternalStoragePermissionError">Ohne die Berechtigung für den externen Speicher kann kein Import oder Export erfolgen</string>
|
||||
<string name="importOptionFilesystemTitle">Importiere aus Dateisystem</string>
|
||||
<string name="importOptionFilesystemExplanation">Wähle eine Datei aus dem Speicher aus.</string>
|
||||
<string name="importOptionFilesystemButton">Aus Dateisystem</string>
|
||||
<string name="importOptionApplicationTitle">Externe App verwenden</string>
|
||||
<string name="importOptionApplicationExplanation">Wählen Sie eine Datei aus einer App wie Dropbox, Google Drive, oder Ihrem bevorzugten Dateisystem aus.</string>
|
||||
<string name="importOptionApplicationButton">Nutze eine externe App</string>
|
||||
|
||||
<string name="about">Über</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Lizensiert unter der GPLv3.</string>
|
||||
<string name="about_title_fmt">Über <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Informationen zu dieser Version: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> benutzt die folgenden Fremdbibliotheken: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> verwendet folgenden Dritt-Ressourcen: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
|
||||
<string name="selectBarcodeTitle">Barcode auswählen</string>
|
||||
<string name="selectBarcodeTitle">Strichcode auswählen</string>
|
||||
<string name="copy_to_clipboard_toast">Nummer in die Zwischenablage kopiert</string>
|
||||
|
||||
<string name="thumbnailDescription">Vorschaubild für die Karte</string>
|
||||
|
||||
<string name="change">Anpassen</string>
|
||||
<string name="storeTextColorTitle">Textfarbe</string>
|
||||
<string name="storeTextBackgroundColorTitle">Hintergrundfarbe</string>
|
||||
<string name="storeNameBackgroundColorDescription">Hintergrundfarbe für den Geschäftsnamen</string>
|
||||
<string name="storeNameColorDescription">Farbe für den Geschäftsnamen</string>
|
||||
|
||||
<string name="settings">Einstellungen</string>
|
||||
<string name="settings_category_title_ui">Benutzeroberfläche</string>
|
||||
<string name="settings_card_title_list_font_size">Schriftgröße des Titels in der Listenansicht</string>
|
||||
@@ -83,6 +74,21 @@
|
||||
<string name="settings_card_title_font_size">Schriftgröße des Titels</string>
|
||||
<string name="settings_card_id_font_size">Schriftgröße der Kartennummer</string>
|
||||
<string name="settings_card_note_font_size">Schriftgröße der Notiz</string>
|
||||
<string name="settings_display_barcode_max_brightness">Helligkeit bei Barcode Ansicht erhöhen</string>
|
||||
<string name="settings_lock_barcode_orientation">Barcodeausrichtung sperren</string>
|
||||
</resources>
|
||||
<string name="settings_display_barcode_max_brightness">Helligkeit bei Strichcode Ansicht erhöhen</string>
|
||||
<string name="settings_lock_barcode_orientation">Strichcodeausrichtung sperren</string>
|
||||
<string name="exportSuccessful">Kundenkartendaten erflogreich exportiert</string>
|
||||
<string name="importSuccessful">Kundenkartendaten erflogreich importiert</string>
|
||||
<string name="intent_import_card_from_url_share_text">Ich will eine Karte mit Ihnen teilen</string>
|
||||
<string name="settings_dark_theme">Dunkel</string>
|
||||
<string name="settings_light_theme">Hell</string>
|
||||
<string name="settings_system_theme">Systemvorgabe</string>
|
||||
<string name="settings_theme">Design</string>
|
||||
<string name="enterBarcodeInstructions">Geben Sie die Karten-ID ein und wählen Sie das Bild aus, das den Strichcode darstellt, den Sie verwenden möchten, oder wählen Sie „Diese Karte hat keinen Strichcode“, um keinen Strichcode zu verwenden.</string>
|
||||
<string name="app_copyright_old">Basiert auf Loyalty Card Keychain, Copyright 2016-2020 Branden Archer.</string>
|
||||
<string name="exportOptionExplanation">Die Daten werden an einen Ort Ihrer Wahl geschrieben.</string>
|
||||
<string name="failedParsingImportUriError">Der Import-URI konnte nicht analysiert werden</string>
|
||||
<string name="addedShortcut">Verknüpfung hinzugefügt</string>
|
||||
<string name="share">Teilen</string>
|
||||
<string name="barcodeNoBarcode">Diese Karte hat keinen Strichcode</string>
|
||||
<string name="barcodeType">Strichcode-Typ</string>
|
||||
</resources>
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
<string name="importOptionApplicationButton">Χρήση εξωτερικής εφαρμογής</string>
|
||||
|
||||
<string name="about">Σχετικά</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Άδεια χρήσης υπό το GPLv3.</string>
|
||||
<string name="about_title_fmt">Σχετικά με <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Έκδοση: <xliff:g id="version">%s</xliff:g></string>
|
||||
|
||||
@@ -1,83 +1,88 @@
|
||||
<resources
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="action_add">Añadir</string>
|
||||
|
||||
<string name="noGiftCards">Actualmente no tienes ninguna tarjeta guardada. Presiona el botón \"+\" para comenzar.\n\nEsta cartera te permite llevar tus tarjetas de fidelización en tu teléfono para que estén siempre a tu alcance.</string>
|
||||
<string name="noGiftCards">Actualmente no tiene ninguna tarjeta guardada. Pulse el botón «+» para comenzar.
|
||||
\n
|
||||
\nCatima le permite llevar sus tarjetas en el teléfono para que estén siempre a su alcance.</string>
|
||||
<string name="storeName">Tienda</string>
|
||||
<string name="note">Nota</string>
|
||||
<string name="cardId">ID de la Tarjeta</string>
|
||||
<string name="cardId">Id. de tarjeta</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="save">Guardar</string>
|
||||
<string name="capture">Escanear Tarjeta</string>
|
||||
<string name="enterCard">Introducir Tarjeta</string>
|
||||
<string name="editCard">Editar Tarjeta</string>
|
||||
<string name="capture">Capturar tarjeta</string>
|
||||
<string name="enterCard">Introducir tarjeta</string>
|
||||
<string name="editCard">Editar tarjeta</string>
|
||||
<string name="edit">Editar</string>
|
||||
<string name="delete">Eliminar</string>
|
||||
<string name="confirm">Confirmar</string>
|
||||
<string name="lockScreen">Bloquear Rotación de Pantalla</string>
|
||||
<string name="unlockScreen">Rotación de Pantalla Automática</string>
|
||||
<string name="deleteTitle">Eliminar Tarjeta de Fidelización</string>
|
||||
<string name="deleteConfirmation">Por favor, confirma si quieres eliminar esta tarjeta.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="copy_to_clipboard">Copiar ID al portapapeles</string>
|
||||
<string name="sendLabel">Enviar…</string>
|
||||
<string name="editCardTitle">Editar Tarjeta de Fidelización</string>
|
||||
<string name="addCardTitle">Añadir Tarjeta de Fidelización</string>
|
||||
<string name="scanCardBarcode">Escanear el Código de Barras de la Tarjeta</string>
|
||||
<string name="cardShortcut">Atajo de Tarjeta</string>
|
||||
<string name="noCardsMessage">No hay ninguna tarjeta, añade una primero</string>
|
||||
|
||||
<string name="lockScreen">Bloquear rotación</string>
|
||||
<string name="unlockScreen">Desbloquear rotación</string>
|
||||
<string name="deleteTitle">Eliminar tarjeta</string>
|
||||
<string name="deleteConfirmation">Confirme que quiere eliminar esta tarjeta.</string>
|
||||
<string name="ok">Aceptar</string>
|
||||
<string name="copy_to_clipboard">Copiar id. en portapapeles</string>
|
||||
<string name="sendLabel">Enviar…</string>
|
||||
<string name="editCardTitle">Editar tarjeta</string>
|
||||
<string name="addCardTitle">Añadir tarjeta</string>
|
||||
<string name="scanCardBarcode">Escanear código de barras de la tarjeta</string>
|
||||
<string name="cardShortcut">Atajo de tarjeta</string>
|
||||
<string name="noCardsMessage">No hay ninguna tarjeta; añada una primero</string>
|
||||
<string name="barcodeImageDescription">Imagen del código de barras de la tarjeta</string>
|
||||
|
||||
<string name="noStoreError">Establecimiento no especificado</string>
|
||||
<string name="noCardIdError">ID de la Tarjeta no especificado</string>
|
||||
<string name="noCardIdError">Id. de tarjeta no especificado</string>
|
||||
<string name="noCardExistsError">No se ha podido encontrar la tarjeta de fidelización</string>
|
||||
<string name="cardIdFormat">%1$s: %2$s</string>
|
||||
<string name="importExport">Importar/Exportar</string>
|
||||
<string name="importExport">Importar/exportar</string>
|
||||
<string name="exportName">Exportar</string>
|
||||
<string name="importExportHelp">La copia de seguridad te permite transferir tus tarjetas a otro dispositivo.</string>
|
||||
<string name="importExportHelp">La copia de respaldo le permite transferir sus tarjetas a otro dispositivo.</string>
|
||||
<string name="importSuccessfulTitle">Datos importados correctamente</string>
|
||||
<string name="importFailedTitle">Ha ocurrido un error al importar los datos</string>
|
||||
<string name="importFailed">Error al importar</string>
|
||||
<string name="importFailedTitle">Falló la importación</string>
|
||||
<string name="importFailed">No se pudo importar</string>
|
||||
<string name="exportSuccessfulTitle">Datos exportados correctamente</string>
|
||||
<string name="exportFailedTitle">Ha ocurrido un error al exportar los datos</string>
|
||||
<string name="exportFailed">Error al exportar</string>
|
||||
<string name="importing">Importando…</string>
|
||||
<string name="exporting">Exportando…</string>
|
||||
<string name="exportFailedTitle">Falló la exportación</string>
|
||||
<string name="exportFailed">No se pudo exportar</string>
|
||||
<string name="importing">Importando…</string>
|
||||
<string name="exporting">Exportando…</string>
|
||||
<string name="noExternalStoragePermissionError">No se pueden importar o exportar tarjetas sin el permiso de almacenamiento</string>
|
||||
<string name="importOptionFilesystemTitle">Importar desde el sistema de archivos</string>
|
||||
<string name="importOptionFilesystemExplanation">Seleccionar un archivo del sistema de archivos</string>
|
||||
<string name="importOptionFilesystemExplanation">Elegir un archivo concreto del sistema de archivos.</string>
|
||||
<string name="importOptionFilesystemButton">Desde el sistema de archivos</string>
|
||||
<string name="importOptionApplicationTitle">Usar una applicación externa</string>
|
||||
<string name="importOptionApplicationTitle">Utilizar aplicación externa</string>
|
||||
<string name="importOptionApplicationExplanation">Use una aplicación externa como Dropbox, Google Drive o tu gestor de archivos favoritos para abrir un archivo.</string>
|
||||
<string name="importOptionApplicationButton">Usar aplicación externa</string>
|
||||
|
||||
<string name="importOptionApplicationButton">Utilizar aplicación externa</string>
|
||||
<string name="about">Acerca de</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licencia GPLv3</string>
|
||||
<string name="app_license">Disponible en virtud de la GPLv3.</string>
|
||||
<string name="about_title_fmt">Acerca de <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versión: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Información sobre la Revisión: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> utiliza las siguientes librerías de terceros: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> utiliza los siguientes recursos de terceros: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
|
||||
<string name="selectBarcodeTitle">Selecciona el Código de Barras</string>
|
||||
<string name="copy_to_clipboard_toast">ID de la Tarjeta copiado al portapapeles</string>
|
||||
|
||||
<string name="thumbnailDescription">Miniatura para la tarjeta</string>
|
||||
|
||||
<string name="change">Cambiar</string>
|
||||
<string name="storeTextColorTitle">Color del Texto de la Tienda</string>
|
||||
<string name="storeTextBackgroundColorTitle">Color Principal</string>
|
||||
<string name="storeTextColorTitle">Color de texto de establecimiento</string>
|
||||
<string name="storeTextBackgroundColorTitle">Color principal</string>
|
||||
<string name="storeNameBackgroundColorDescription">Color de fondo para el texto de la tienda</string>
|
||||
<string name="storeNameColorDescription">Color del texto de la tienda</string>
|
||||
|
||||
<string name="settings">Configuración</string>
|
||||
<string name="settings_category_title_ui">Interfaz de Usuario</string>
|
||||
<string name="settings_category_title_ui">Interfaz de usuario</string>
|
||||
<string name="settings_card_title_list_font_size">Tamaño de la letra para el título (lista)</string>
|
||||
<string name="settings_card_note_list_font_size">Tamaño de la letra para notas (lista)</string>
|
||||
<string name="settings_card_title_font_size">Tamaño de la letra para el título</string>
|
||||
<string name="settings_card_id_font_size">Tamaño de la letra para el ID de la tarjeta</string>
|
||||
<string name="settings_card_note_font_size">Tamaño de la letra para notas</string>
|
||||
</resources>
|
||||
<string name="settings_display_barcode_max_brightness">Iluminar vista de código de barras</string>
|
||||
<string name="exportSuccessful">Se exportaron correctamente los datos de tarjetas de fidelización</string>
|
||||
<string name="importSuccessful">Se importaron correctamente los datos de tarjetas de fidelización</string>
|
||||
<string name="intent_import_card_from_url_share_text">Quiero compartirle una tarjeta</string>
|
||||
<string name="settings_lock_barcode_orientation">Bloquear orientación de código de barras</string>
|
||||
<string name="settings_dark_theme">Tema oscuro</string>
|
||||
<string name="settings_light_theme">Tema claro</string>
|
||||
<string name="settings_system_theme">Tema del sistema</string>
|
||||
<string name="settings_theme">Tema</string>
|
||||
<string name="enterBarcodeInstructions">Introduzca el identificador de tarjeta y seleccione la imagen que represente el código de barras que se utilizará, o bien, elija «Esta tarjeta no tiene código de barras» para no utilizar ninguno.</string>
|
||||
<string name="app_copyright_old">Basado en Loyalty Card Keychain, derechos de autor 2016-2020 de Branden Archer.</string>
|
||||
<string name="exportOptionExplanation">Los datos se guardarán en la ubicación que elija.</string>
|
||||
<string name="failedParsingImportUriError">No se pudo procesar el URI de importación</string>
|
||||
<string name="addedShortcut">Atajo añadido</string>
|
||||
<string name="share">Compartir</string>
|
||||
<string name="barcodeNoBarcode">Esta tarjeta no tiene código de barras</string>
|
||||
<string name="barcodeType">Tipo de código de barras</string>
|
||||
<string name="noMatchingGiftCards">Ninguna tarjeta coincide con el filtro de búsqueda. Pruebe con términos distintos.</string>
|
||||
<string name="action_search">Buscar</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<resources
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="action_add">Ajouter</string>
|
||||
|
||||
<string name="noGiftCards">Aucune carte de fidélité enregistrée. Appuyez sur le bouton \"+\" (plus) pour commencer.\n\nLoyalty Card Locker vous permet d\'enregistrer vos cartes de fidélité sur votre téléphone pour toujours les avoir à portée de main.</string>
|
||||
<string name="storeName">Nom</string>
|
||||
<string name="note">Note</string>
|
||||
@@ -18,18 +16,16 @@
|
||||
<string name="lockScreen">Désactiver la rotation</string>
|
||||
<string name="unlockScreen">Activer la rotation</string>
|
||||
<string name="deleteTitle">Supprimer la carte de fidélité</string>
|
||||
<string name="deleteConfirmation">Confirmez que vous souhaitez supprimer cette carte</string>
|
||||
<string name="deleteConfirmation">Confirmez que vous souhaitez supprimer cette carte.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="copy_to_clipboard">Copier le numéro dans le presse-papier</string>
|
||||
<string name="sendLabel">Envoyer…</string>
|
||||
<string name="sendLabel">Envoyer…</string>
|
||||
<string name="editCardTitle">Modifier la carte de fidélité</string>
|
||||
<string name="addCardTitle">Ajouter une carte de fidélité</string>
|
||||
<string name="scanCardBarcode">Flasher le code-barres de la carte</string>
|
||||
<string name="scanCardBarcode">Scanner le code-barres</string>
|
||||
<string name="cardShortcut">Raccourci de carte</string>
|
||||
<string name="noCardsMessage">Il n\'y a aucune carte. Ajoutez en une d\'abord.</string>
|
||||
|
||||
<string name="noCardsMessage">Il n\'y a aucune carte. Ajoutez-en une d\'abord</string>
|
||||
<string name="barcodeImageDescription">Image du code-barres de la carte</string>
|
||||
|
||||
<string name="noStoreError">Aucun nom n\'a été saisi</string>
|
||||
<string name="noCardIdError">Aucun numéro n\'a été saisi</string>
|
||||
<string name="noCardExistsError">N\'a pas pu retrouver la carte de fidélité</string>
|
||||
@@ -43,38 +39,32 @@
|
||||
<string name="exportSuccessfulTitle">Exporté avec succès</string>
|
||||
<string name="exportFailedTitle">Échec de l\'export</string>
|
||||
<string name="exportFailed">Échec de l\'export </string>
|
||||
<string name="importing">Import …</string>
|
||||
<string name="exporting">Export …</string>
|
||||
<string name="importing">Import …</string>
|
||||
<string name="exporting">Export …</string>
|
||||
<string name="noExternalStoragePermissionError">Impossible d\'importer ou d\'exporter les données sans l\'autorisation d\'accès au stockage externe</string>
|
||||
<string name="importOptionFilesystemTitle">Importer depuis le système de fichiers.</string>
|
||||
<string name="importOptionFilesystemTitle">Importer depuis le système de fichiers</string>
|
||||
<string name="importOptionFilesystemExplanation">Choisissez le fichier à importer.</string>
|
||||
<string name="importOptionFilesystemButton">Système de fichiers</string>
|
||||
<string name="importOptionApplicationTitle">Application externe</string>
|
||||
<string name="importOptionApplicationExplanation">Utilisez une application externe comme Dropbox, Google Drive, ou votre gestionnaire de fichiers favori pour ouvrir un fichier.</string>
|
||||
<string name="importOptionApplicationButton">Application externe</string>
|
||||
|
||||
<string name="about">À propos</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licence GPLv3.</string>
|
||||
<string name="about_title_fmt">À propos de <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Version : <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Notes sur les versions : <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> utilise les bibliothèques-tierces suivantes : <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> utilise les ressources-tierces suivantes : <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
|
||||
<string name="selectBarcodeTitle">Choisissez le code-barre</string>
|
||||
<string name="selectBarcodeTitle">Choisissez le code-barres</string>
|
||||
<string name="copy_to_clipboard_toast">Numéro de carte copié dans le presse-papier</string>
|
||||
|
||||
<string name="thumbnailDescription">Miniature pour la carte</string>
|
||||
|
||||
<string name="change">Modifier</string>
|
||||
<string name="storeTextColorTitle">Couleur du texte du magasin</string>
|
||||
<string name="storeTextBackgroundColorTitle">Couleur du titre</string>
|
||||
<string name="storeNameBackgroundColorDescription">Couleur de fond du texte du magasin</string>
|
||||
<string name="storeNameColorDescription">Couleur pour le nom du magasin</string>
|
||||
|
||||
<string name="settings">Paramètres</string>
|
||||
<string name="settings_category_title_ui">Interface</string>
|
||||
<string name="settings_category_title_ui">Interface utilisateur</string>
|
||||
<string name="settings_card_title_list_font_size">Taille de police pour les titres de carte en liste</string>
|
||||
<string name="settings_card_note_list_font_size">Taille de police pour les notes de carte en liste</string>
|
||||
<string name="settings_card_title_font_size">Taille de police pour les titres de carte</string>
|
||||
@@ -82,4 +72,21 @@
|
||||
<string name="settings_card_note_font_size">Taille de police pour les notes de carte</string>
|
||||
<string name="settings_display_barcode_max_brightness">Augmenter la luminosité du code-barres</string>
|
||||
<string name="settings_lock_barcode_orientation">Verrouiller l\'orientation du code-barres</string>
|
||||
</resources>
|
||||
<string name="exportSuccessful">Carte de fidélité exportée avec succès</string>
|
||||
<string name="importSuccessful">Carte de fidélité importée avec succès</string>
|
||||
<string name="intent_import_card_from_url_share_text">Je veux partager une carte avec toi</string>
|
||||
<string name="settings_dark_theme">Thème sombre</string>
|
||||
<string name="settings_light_theme">Thème clair</string>
|
||||
<string name="settings_system_theme">Thème du système</string>
|
||||
<string name="settings_theme">Thème</string>
|
||||
<string name="enterBarcodeInstructions">Entrez l\'identifiant de la carte puis sélectionnez l\'image qui représente le code-barres que vous souhaitez utiliser, ou sélectionnez « Cette carte n\'a pas de code-barres » pour ne pas utiliser de code-barres.</string>
|
||||
<string name="app_copyright_old">Basé sur Loyalty Card Keychain, copyright 2016-2020 Branden Archer.</string>
|
||||
<string name="exportOptionExplanation">Les données seront écrites à un emplacement de votre choix.</string>
|
||||
<string name="failedParsingImportUriError">Impossible d\'analyser l\'URI d\'importation</string>
|
||||
<string name="addedShortcut">Raccourci ajouté</string>
|
||||
<string name="share">Partager</string>
|
||||
<string name="barcodeNoBarcode">Cette carte n\'a pas de code-barres</string>
|
||||
<string name="barcodeType">Type de code-barres</string>
|
||||
<string name="noMatchingGiftCards">Aucune carte ne correspond au filtre de recherche. Veuillez essayer d\'autres termes.</string>
|
||||
<string name="action_search">Rechercher</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
<resources
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="action_search">Cerca</string>
|
||||
<string name="action_add">Aggiungi</string>
|
||||
|
||||
<string name="noGiftCards">Non hai ancora alcuna carta fedeltà. Premi sul bottone +(più) in alto per incominciare.\n\nL\'app ti permette di portare con te le tue carte fedeltà, così da averle sempre a disposizione.</string>
|
||||
<string name="noMatchingGiftCards">Nessuna carta fedeltà corrisponde al filtro. Riprovare con altri valori</string>
|
||||
|
||||
<string name="noMatchingGiftCards">Nessuna carta fedeltà corrisponde al filtro. Riprovare con altri valori.</string>
|
||||
<string name="storeName">Negozio</string>
|
||||
<string name="note">Note</string>
|
||||
<string name="cardId">Codice</string>
|
||||
<string name="barcodeNoBarcode">Questa carta non ha un codice a barre</string>
|
||||
|
||||
<string name="cancel">Annulla</string>
|
||||
<string name="save">Salva</string>
|
||||
<string name="capture">Scansione carta</string>
|
||||
@@ -27,15 +23,13 @@
|
||||
<string name="ok">Ok</string>
|
||||
<string name="copy_to_clipboard">Copia ID negli appunti</string>
|
||||
<string name="share">Condividi</string>
|
||||
<string name="sendLabel">Invia…</string>
|
||||
<string name="sendLabel">Invia…</string>
|
||||
<string name="editCardTitle">Modifica carta</string>
|
||||
<string name="addCardTitle">Aggiungi carta</string>
|
||||
<string name="scanCardBarcode">Scansiona codice carta</string>
|
||||
<string name="cardShortcut">Scorciatoia per la carta</string>
|
||||
<string name="noCardsMessage">Non ci sono carte. Aggiungine prima una</string>
|
||||
|
||||
<string name="barcodeImageDescription">Immagine del codice a barre della carta</string>
|
||||
|
||||
<string name="noStoreError">Nessun negozio inserito</string>
|
||||
<string name="noCardIdError">Nessun codice carta inserito</string>
|
||||
<string name="noCardExistsError">Impossibile trovare la carta</string>
|
||||
@@ -50,38 +44,31 @@
|
||||
<string name="exportSuccessfulTitle">Esportazione avvenuta con successo</string>
|
||||
<string name="exportFailedTitle">Esportazione fallita</string>
|
||||
<string name="exportFailed">Impossibile esportare</string>
|
||||
<string name="importing">Importazione in corso…</string>
|
||||
<string name="exporting">Esportazione in corso…</string>
|
||||
<string name="noExternalStoragePermissionError">Impossibile importare o esportare i dati senza il permesso per l\'uso della memoria esterna.</string>
|
||||
<string name="importing">Importazione in corso…</string>
|
||||
<string name="exporting">Esportazione in corso…</string>
|
||||
<string name="noExternalStoragePermissionError">Impossibile importare o esportare i dati senza il permesso per l\'uso della memoria esterna</string>
|
||||
<string name="importOptionFilesystemTitle">Importa dal file system</string>
|
||||
<string name="importOptionFilesystemExplanation">Scegli un file dal file system.</string>
|
||||
<string name="importOptionFilesystemButton">Dal file system</string>
|
||||
<string name="importOptionApplicationTitle">Usa un\'applicazione esterna</string>
|
||||
<string name="importOptionApplicationExplanation">Usa un\'applicazione esterna come Dropbox, Google Drive o il tuo file manager preferito per aprire il file.</string>
|
||||
<string name="importOptionApplicationButton">Usa un\'applicazione esterna</string>
|
||||
|
||||
<string name="about">Informazioni</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Pubblicato sotto licenza GPLv3.</string>
|
||||
<string name="about_title_fmt">Informazioni su <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versione: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Informazione sulla versione: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> usa le seguenti librerie di terze parti: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> usa le seguenti risorse di terze parti: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
|
||||
<string name="selectBarcodeTitle">Seleziona codice a barre</string>
|
||||
<string name="enterBarcodeInstructions">Immettere l\'ID della carta, quindi selezionare l\'immagine che rappresenta il codice a barre desiderato oppure selezionare “Questa carta non ha un codice a barre” per non valorizzare il dato.</string>
|
||||
|
||||
<string name="enterBarcodeInstructions">Immettere l\'ID della carta, quindi selezionare l\'immagine che rappresenta il codice a barre desiderato oppure selezionare «Questa carta non ha un codice a barre» per non valorizzare il dato.</string>
|
||||
<string name="copy_to_clipboard_toast">ID della carta copiato negli appunti</string>
|
||||
|
||||
<string name="thumbnailDescription">Miniatura carta</string>
|
||||
|
||||
<string name="change">Cambia</string>
|
||||
<string name="storeTextColorTitle">Colore titolo</string>
|
||||
<string name="storeTextBackgroundColorTitle">Colore scheda</string>
|
||||
<string name="storeNameBackgroundColorDescription">Colore di sfondo del titolo carta</string>
|
||||
<string name="storeNameColorDescription">Colore del titolo carta</string>
|
||||
|
||||
<string name="settings">Impostazioni</string>
|
||||
<string name="settings_category_title_ui">Interfaccia utente</string>
|
||||
<string name="settings_theme">Tema</string>
|
||||
@@ -96,4 +83,10 @@
|
||||
<string name="settings_display_barcode_max_brightness">Aumenta luminosità dello schermo quando apro un codice a barre</string>
|
||||
<string name="settings_lock_barcode_orientation">Blocca orientamento del codice a barre</string>
|
||||
<string name="intent_import_card_from_url_share_text">Voglio condividere una carta fedeltà con te</string>
|
||||
</resources>
|
||||
<string name="exportSuccessful">Dati della carta fedeltà esportati correttamente</string>
|
||||
<string name="importSuccessful">Dati della carta fedeltà importati correttamente</string>
|
||||
<string name="app_copyright_old">Basato su Loyalty Card Keychain, copyright 2016-2020 Branden Archer.</string>
|
||||
<string name="exportOptionExplanation">I dati verranno scritti in una posizione a tua scelta.</string>
|
||||
<string name="addedShortcut">Scorciatoia aggiunta</string>
|
||||
<string name="barcodeType">Tipo di codice a barre</string>
|
||||
</resources>
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
<string name="exporting">Eksportuoja…</string>
|
||||
<string name="noExternalStoragePermissionError">Negalima importuoti/eksportuoti kortelių be išorinės atminties leidimo</string>
|
||||
<string name="about">Apie</string>
|
||||
<string name="app_copyright_fmt">Visos teisės saugomos 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licenzijuota pagal GPLv3.</string>
|
||||
<string name="about_title_fmt">Apie <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versija: <xliff:g id="version">%s</xliff:g></string>
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
<string name="importOptionApplicationExplanation">Bruk eksternt program som Nextcloud, eller din favorittfilbehandler til å åpne ei fil.</string>
|
||||
<string name="importOptionApplicationButton">Bruk eksternt program</string>
|
||||
<string name="about">Om</string>
|
||||
<string name="app_copyright_fmt">Kopirett 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Lisensiert GPLv3+.</string>
|
||||
<string name="about_title_fmt">Om <xliff:g id="app_name">%s</xliff:g>
|
||||
</string>
|
||||
@@ -83,4 +82,17 @@
|
||||
<string name="settings_card_note_font_size">Skriftstørrelse for kortmerknad</string>
|
||||
<string name="settings_display_barcode_max_brightness">Lysere strekkodevisning</string>
|
||||
<string name="settings_lock_barcode_orientation">Lås strekkodesideretning</string>
|
||||
</resources>
|
||||
<string name="exportSuccessful">Eksporterte stamkundekortdata</string>
|
||||
<string name="importSuccessful">Importerte stamkundekortdata</string>
|
||||
<string name="intent_import_card_from_url_share_text">Jeg ønsker å dele et kort med deg</string>
|
||||
<string name="settings_dark_theme">Mørk</string>
|
||||
<string name="settings_light_theme">Lys</string>
|
||||
<string name="settings_system_theme">Systemdrakt</string>
|
||||
<string name="settings_theme">Drakt</string>
|
||||
<string name="app_copyright_old">Basert på Kundekortknippe, opphavsrett 2016-2020 Branden Archer.</string>
|
||||
<string name="failedParsingImportUriError">Kunne ikke tolke importerings-URI</string>
|
||||
<string name="share">Del</string>
|
||||
<string name="barcodeNoBarcode">Dette kortet har ingen strekkode</string>
|
||||
<string name="noMatchingGiftCards">Fant ingen slike kort. Prøv å endre søket.</string>
|
||||
<string name="action_search">Søk</string>
|
||||
</resources>
|
||||
@@ -64,7 +64,6 @@
|
||||
<string name="importOptionApplicationButton">Externe app gebruiken</string>
|
||||
|
||||
<string name="about">Over</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Uitgebracht onder de GPLv3-licentie.</string>
|
||||
<string name="about_title_fmt">Over <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versie: <xliff:g id="version">%s</xliff:g></string>
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
<string name="importOptionApplicationButton">Użyj zewnętrznej aplikacji</string>
|
||||
|
||||
<string name="about">O aplikacji</string>
|
||||
<string name="app_copyright_fmt">© 2016 — <xliff:g>%d</xliff:g> Branden Archer.</string>
|
||||
<string name="app_license">Licencjonowane na podstawie GNU General Public License, wersji 3.0.</string>
|
||||
<string name="about_title_fmt">O <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Wersja: <xliff:g id="version">%s</xliff:g></string>
|
||||
|
||||
@@ -64,7 +64,6 @@
|
||||
<string name="importOptionApplicationButton">Использовать другое приложение</string>
|
||||
|
||||
<string name="about">О программе</string>
|
||||
<string name="app_copyright_fmt">Все права защищены 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Лицензия GPLv3.</string>
|
||||
<string name="about_title_fmt">О программе <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Версия: <xliff:g id="version">%s</xliff:g></string>
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
<string name="importOptionApplicationButton">Použiť externú aplikáciu</string>
|
||||
|
||||
<string name="about">O aplikácii</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licencované GPLv3.</string>
|
||||
<string name="about_title_fmt">O <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Verzia: <xliff:g id="version">%s</xliff:g></string>
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
<string name="importOptionApplicationButton">Uporabi zunanjo aplikacijo</string>
|
||||
|
||||
<string name="about">Več o aplikaciji</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licencirano s skladu z GPLv3.</string>
|
||||
<string name="about_title_fmt">Več o <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Verzija: <xliff:g id="version">%s</xliff:g></string>
|
||||
|
||||
4
app/src/main/res/values/ic_launcher_background.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#223355</color>
|
||||
</resources>
|
||||
@@ -14,13 +14,15 @@
|
||||
<string name="barcodeType">Barcode type</string>
|
||||
<string name="barcodeNoBarcode">This card has no barcode</string>
|
||||
|
||||
<string name="star">Add to favorites</string>
|
||||
<string name="unstar">Remove from favorites</string>
|
||||
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="capture">Capture Card</string>
|
||||
<string name="enterCard">Enter Card</string>
|
||||
<string name="editCard">Edit Card</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="moreInfo">More Info</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="lockScreen">Block Rotation</string>
|
||||
@@ -43,9 +45,6 @@
|
||||
<string name="noStoreError">No Store entered</string>
|
||||
<string name="noCardIdError">No Card ID entered</string>
|
||||
<string name="noCardExistsError">Could not lookup loyalty card</string>
|
||||
<string name="failedSharingCard">Could not share card</string>
|
||||
<string name="failedShowingExtras">Could not show extra information: data not correctly formatted</string>
|
||||
<string name="failedSavingCard">Could not save card</string>
|
||||
<string name="failedParsingImportUriError">Could not parse the import URI</string>
|
||||
<string name="cardIdFormat">%1$s: %2$s</string>
|
||||
<string name="importExport">Import/Export</string>
|
||||
@@ -69,7 +68,7 @@
|
||||
<string name="importOptionApplicationButton">Use external application</string>
|
||||
|
||||
<string name="about">About</string>
|
||||
<string name="app_copyright_fmt">Copyright 2019-<xliff:g>%d</xliff:g> Sylvia van Os.</string>
|
||||
<string name="app_copyright_fmt" translatable="false">Copyright 2019-<xliff:g>%d</xliff:g> Sylvia van Os.</string>
|
||||
<string name="app_copyright_old">Based on Loyalty Card Keychain, copyright 2016-2020 Branden Archer.</string>
|
||||
<string name="app_license">Licensed under the GPLv3.</string>
|
||||
<string name="about_title_fmt">About <xliff:g id="app_name">%s</xliff:g></string>
|
||||
@@ -84,6 +83,7 @@
|
||||
<string name="copy_to_clipboard_toast">Card ID copied to clipboard</string>
|
||||
|
||||
<string name="thumbnailDescription">Thumbnail for card</string>
|
||||
<string name="starImage">Favorite star</string>
|
||||
|
||||
<string name="change">Change</string>
|
||||
<string name="storeTextColorTitle">Store Text Color</string>
|
||||
|
||||
@@ -2,17 +2,12 @@ package protect.card_locker;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentValues;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -33,24 +28,19 @@ public class DatabaseTest
|
||||
|
||||
private static final Integer DEFAULT_HEADER_COLOR = Color.BLACK;
|
||||
private static final Integer DEFAULT_HEADER_TEXT_COLOR = Color.WHITE;
|
||||
private static Bitmap DEFAULT_ICON = BitmapFactory.decodeResource(Resources.getSystem(), R.mipmap.ic_launcher);
|
||||
private static ExtrasHelper DEFAULT_EXTRAS;
|
||||
|
||||
@Before
|
||||
public void setUp() throws JSONException
|
||||
public void setUp()
|
||||
{
|
||||
DEFAULT_EXTRAS = new ExtrasHelper();
|
||||
DEFAULT_EXTRAS.addLanguageValue("en", "key", "value");
|
||||
|
||||
Activity activity = Robolectric.setupActivity(MainActivity.class);
|
||||
db = new DBHelper(activity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addRemoveOneGiftCard() throws JSONException
|
||||
public void addRemoveOneGiftCard()
|
||||
{
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
long id = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR, DEFAULT_ICON, DEFAULT_EXTRAS);
|
||||
long id = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR, 0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
@@ -60,6 +50,7 @@ public class DatabaseTest
|
||||
assertEquals("store", loyaltyCard.store);
|
||||
assertEquals("note", loyaltyCard.note);
|
||||
assertEquals("cardId", loyaltyCard.cardId);
|
||||
assertEquals(0, loyaltyCard.starStatus);
|
||||
assertEquals(BarcodeFormat.UPC_A.toString(), loyaltyCard.barcodeType);
|
||||
|
||||
result = db.deleteLoyaltyCard(1);
|
||||
@@ -69,14 +60,14 @@ public class DatabaseTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGiftCard() throws JSONException
|
||||
public void updateGiftCard()
|
||||
{
|
||||
long id = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR, DEFAULT_ICON, DEFAULT_EXTRAS);
|
||||
long id = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR,0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
result = db.updateLoyaltyCard(1, "store1", "note1", "cardId1", BarcodeFormat.AZTEC.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR, DEFAULT_ICON, DEFAULT_EXTRAS);
|
||||
result = db.updateLoyaltyCard(1, "store1", "note1", "cardId1", BarcodeFormat.AZTEC.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
@@ -85,25 +76,48 @@ public class DatabaseTest
|
||||
assertEquals("store1", loyaltyCard.store);
|
||||
assertEquals("note1", loyaltyCard.note);
|
||||
assertEquals("cardId1", loyaltyCard.cardId);
|
||||
assertEquals(0, loyaltyCard.starStatus);
|
||||
assertEquals(BarcodeFormat.AZTEC.toString(), loyaltyCard.barcodeType);
|
||||
assertEquals(DEFAULT_EXTRAS.toJSON().toString(), loyaltyCard.extras.toJSON().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateMissingGiftCard() throws JSONException
|
||||
public void updateGiftCardOnlyStar()
|
||||
{
|
||||
long id = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR,0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
result = db.updateLoyaltyCardStarStatus(1, 1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("store", loyaltyCard.store);
|
||||
assertEquals("note", loyaltyCard.note);
|
||||
assertEquals("cardId", loyaltyCard.cardId);
|
||||
assertEquals(1, loyaltyCard.starStatus);
|
||||
assertEquals(BarcodeFormat.UPC_A.toString(), loyaltyCard.barcodeType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void updateMissingGiftCard()
|
||||
{
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
|
||||
boolean result = db.updateLoyaltyCard(1, "store1", "note1", "cardId1",
|
||||
BarcodeFormat.UPC_A.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR, DEFAULT_ICON, DEFAULT_EXTRAS);
|
||||
BarcodeFormat.UPC_A.toString(), DEFAULT_HEADER_COLOR, DEFAULT_HEADER_TEXT_COLOR);
|
||||
assertEquals(false, result);
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyGiftCardValues() throws JSONException
|
||||
public void emptyGiftCardValues()
|
||||
{
|
||||
long id = db.insertLoyaltyCard("", "", "", "", null, null, null, new ExtrasHelper());
|
||||
long id = db.insertLoyaltyCard("", "", "", "", null, null, 0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
@@ -114,11 +128,10 @@ public class DatabaseTest
|
||||
assertEquals("", loyaltyCard.note);
|
||||
assertEquals("", loyaltyCard.cardId);
|
||||
assertEquals("", loyaltyCard.barcodeType);
|
||||
assertEquals("{}", loyaltyCard.extras.toJSON().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void giftCardsViaCursor() throws JSONException
|
||||
public void giftCardsViaCursor()
|
||||
{
|
||||
final int CARDS_TO_ADD = 10;
|
||||
|
||||
@@ -127,7 +140,7 @@ public class DatabaseTest
|
||||
for(int index = CARDS_TO_ADD-1; index >= 0; index--)
|
||||
{
|
||||
long id = db.insertLoyaltyCard("store" + index, "note" + index, "cardId" + index,
|
||||
BarcodeFormat.UPC_A.toString(), index, index*2, DEFAULT_ICON, DEFAULT_EXTRAS);
|
||||
BarcodeFormat.UPC_A.toString(), index, index*2, 0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
@@ -148,9 +161,68 @@ public class DatabaseTest
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
|
||||
assertEquals(0, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS)));
|
||||
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
|
||||
assertEquals(index*2, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR)));
|
||||
|
||||
cursor.moveToNext();
|
||||
}
|
||||
|
||||
assertTrue(cursor.isAfterLast());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void giftCardsViaCursorWithOneStarred() //sorting test; stared card should appear first
|
||||
{
|
||||
final int CARDS_TO_ADD = 10;
|
||||
long id;
|
||||
// Add the gift cards in reverse order and add one with STAR, to ensure
|
||||
// that they are sorted
|
||||
for(int index = CARDS_TO_ADD-1; index >= 0; index--)
|
||||
{
|
||||
if (index == CARDS_TO_ADD-1) {
|
||||
id = db.insertLoyaltyCard("store" + index, "note" + index, "cardId" + index,
|
||||
BarcodeFormat.UPC_A.toString(), index, index*2, 1);
|
||||
}
|
||||
|
||||
else {
|
||||
id = db.insertLoyaltyCard("store" + index, "note" + index, "cardId" + index,
|
||||
BarcodeFormat.UPC_A.toString(), index, index*2, 0);
|
||||
}
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(CARDS_TO_ADD, db.getLoyaltyCardCount());
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
assertNotNull(cursor);
|
||||
|
||||
assertEquals(CARDS_TO_ADD, cursor.getCount());
|
||||
|
||||
cursor.moveToFirst();
|
||||
int index = CARDS_TO_ADD-1 ;
|
||||
assertEquals("store"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
|
||||
assertEquals("note"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
|
||||
assertEquals(1, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS)));
|
||||
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
|
||||
assertEquals(index*2, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR)));
|
||||
|
||||
cursor.moveToNext();
|
||||
|
||||
for(index = 0; index < CARDS_TO_ADD-1; index++)
|
||||
{
|
||||
assertEquals("store"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)));
|
||||
assertEquals("note"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)));
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals("cardId"+index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID)));
|
||||
assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE)));
|
||||
assertEquals(0, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS)));
|
||||
assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)));
|
||||
assertEquals(index*2, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR)));
|
||||
assertEquals("{\"en\":{\"key\":\"value\"}}", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXTRAS)));
|
||||
|
||||
cursor.moveToNext();
|
||||
}
|
||||
@@ -185,7 +257,7 @@ public class DatabaseTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void databaseUpgradeFromVersion1() throws JSONException
|
||||
public void databaseUpgradeFromVersion1()
|
||||
{
|
||||
SQLiteDatabase database = db.getWritableDatabase();
|
||||
|
||||
@@ -206,7 +278,6 @@ public class DatabaseTest
|
||||
assertEquals("", card.note);
|
||||
assertEquals(null, card.headerColor);
|
||||
assertEquals(null, card.headerTextColor);
|
||||
assertEquals("{}", card.extras.toJSON().toString());
|
||||
|
||||
database.close();
|
||||
}
|
||||
|
||||
@@ -3,14 +3,10 @@ package protect.card_locker;
|
||||
import android.app.Activity;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.apache.tools.ant.filters.StringInputStream;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -27,7 +23,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Calendar;
|
||||
|
||||
@@ -48,14 +43,10 @@ public class ImportExportTest
|
||||
|
||||
private final String BARCODE_DATA = "428311627547";
|
||||
private final String BARCODE_TYPE = BarcodeFormat.UPC_A.name();
|
||||
private ExtrasHelper EXTRAS;
|
||||
|
||||
@Before
|
||||
public void setUp() throws JSONException
|
||||
public void setUp()
|
||||
{
|
||||
EXTRAS = new ExtrasHelper();
|
||||
EXTRAS.addLanguageValue("en", "key", "value");
|
||||
|
||||
activity = Robolectric.setupActivity(MainActivity.class);
|
||||
db = new DBHelper(activity);
|
||||
nowMs = System.currentTimeMillis();
|
||||
@@ -70,14 +61,14 @@ public class ImportExportTest
|
||||
* an index in the store name.
|
||||
* @param cardsToAdd
|
||||
*/
|
||||
private void addLoyaltyCards(int cardsToAdd) throws JSONException
|
||||
private void addLoyaltyCards(int cardsToAdd)
|
||||
{
|
||||
// Add in reverse order to test sorting
|
||||
for(int index = cardsToAdd; index > 0; index--)
|
||||
{
|
||||
String storeName = String.format("store, \"%4d", index);
|
||||
String note = String.format("note, \"%4d", index);
|
||||
long id = db.insertLoyaltyCard(storeName, note, BARCODE_DATA, BARCODE_TYPE, index, index*2, null, EXTRAS);
|
||||
long id = db.insertLoyaltyCard(storeName, note, BARCODE_DATA, BARCODE_TYPE, index, index*2, 0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
@@ -85,12 +76,36 @@ public class ImportExportTest
|
||||
assertEquals(cardsToAdd, db.getLoyaltyCardCount());
|
||||
}
|
||||
|
||||
private void addLoyaltyCardsFiveStarred()
|
||||
{
|
||||
int cardsToAdd = 9;
|
||||
// Add in reverse order to test sorting
|
||||
for(int index = cardsToAdd; index > 4; index--)
|
||||
{
|
||||
String storeName = String.format("store, \"%4d", index);
|
||||
String note = String.format("note, \"%4d", index);
|
||||
long id = db.insertLoyaltyCard(storeName, note, BARCODE_DATA, BARCODE_TYPE, index, index*2, 1);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
for(int index = cardsToAdd-5; index > 0; index--)
|
||||
{
|
||||
String storeName = String.format("store, \"%4d", index);
|
||||
String note = String.format("note, \"%4d", index);
|
||||
//if index is even
|
||||
long id = db.insertLoyaltyCard(storeName, note, BARCODE_DATA, BARCODE_TYPE, index, index*2, 0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
assertEquals(cardsToAdd, db.getLoyaltyCardCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all of the cards follow the pattern
|
||||
* specified in addLoyaltyCards(), and are in sequential order
|
||||
* where the smallest card's index is 1
|
||||
*/
|
||||
private void checkLoyaltyCards() throws JSONException
|
||||
private void checkLoyaltyCards()
|
||||
{
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
int index = 1;
|
||||
@@ -108,13 +123,64 @@ public class ImportExportTest
|
||||
assertEquals(BARCODE_TYPE, card.barcodeType);
|
||||
assertEquals(Integer.valueOf(index), card.headerColor);
|
||||
assertEquals(Integer.valueOf(index*2), card.headerTextColor);
|
||||
assertEquals("{\"en\":{\"key\":\"value\"}}", card.extras.toJSON().toString());
|
||||
assertEquals(0, card.starStatus);
|
||||
|
||||
index++;
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all of the cards follow the pattern
|
||||
* specified in addLoyaltyCardsSomeStarred(), and are in sequential order
|
||||
* with starred ones first
|
||||
*/
|
||||
private void checkLoyaltyCardsFiveStarred()
|
||||
{
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
int index = 5;
|
||||
|
||||
while(index<10)
|
||||
{
|
||||
cursor.moveToNext();
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cursor);
|
||||
|
||||
String expectedStore = String.format("store, \"%4d", index);
|
||||
String expectedNote = String.format("note, \"%4d", index);
|
||||
|
||||
assertEquals(expectedStore, card.store);
|
||||
assertEquals(expectedNote, card.note);
|
||||
assertEquals(BARCODE_DATA, card.cardId);
|
||||
assertEquals(BARCODE_TYPE, card.barcodeType);
|
||||
assertEquals(Integer.valueOf(index), card.headerColor);
|
||||
assertEquals(Integer.valueOf(index*2), card.headerTextColor);
|
||||
assertEquals(1, card.starStatus);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
index = 1;
|
||||
while(cursor.moveToNext() && index<5)
|
||||
{
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cursor);
|
||||
|
||||
String expectedStore = String.format("store, \"%4d", index);
|
||||
String expectedNote = String.format("note, \"%4d", index);
|
||||
|
||||
assertEquals(expectedStore, card.store);
|
||||
assertEquals(expectedNote, card.note);
|
||||
assertEquals(BARCODE_DATA, card.cardId);
|
||||
assertEquals(BARCODE_TYPE, card.barcodeType);
|
||||
assertEquals(Integer.valueOf(index), card.headerColor);
|
||||
assertEquals(Integer.valueOf(index*2), card.headerTextColor);
|
||||
assertEquals(0, card.starStatus);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the contents of the database
|
||||
*/
|
||||
@@ -128,7 +194,7 @@ public class ImportExportTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleCardsExportImport() throws IOException, JSONException
|
||||
public void multipleCardsExportImport() throws IOException
|
||||
{
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
@@ -163,7 +229,42 @@ public class ImportExportTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importExistingCardsNotReplace() throws IOException, JSONException
|
||||
public void multipleCardsExportImportSomeStarred() throws IOException
|
||||
{
|
||||
final int NUM_CARDS = 9;
|
||||
|
||||
for(DataFormat format : DataFormat.values())
|
||||
{
|
||||
addLoyaltyCardsFiveStarred();
|
||||
|
||||
ByteArrayOutputStream outData = new ByteArrayOutputStream();
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
|
||||
// Export data to CSV format
|
||||
boolean result = MultiFormatExporter.exportData(db, outStream, format);
|
||||
assertTrue(result);
|
||||
outStream.close();
|
||||
|
||||
clearDatabase();
|
||||
|
||||
ByteArrayInputStream inData = new ByteArrayInputStream(outData.toByteArray());
|
||||
InputStreamReader inStream = new InputStreamReader(inData);
|
||||
|
||||
// Import the CSV data
|
||||
result = MultiFormatImporter.importData(db, inStream, DataFormat.CSV);
|
||||
assertTrue(result);
|
||||
|
||||
assertEquals(NUM_CARDS, db.getLoyaltyCardCount());
|
||||
|
||||
checkLoyaltyCardsFiveStarred();
|
||||
|
||||
// Clear the database for the next format under test
|
||||
clearDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importExistingCardsNotReplace() throws IOException
|
||||
{
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
@@ -196,7 +297,7 @@ public class ImportExportTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void corruptedImportNothingSaved() throws IOException, JSONException
|
||||
public void corruptedImportNothingSaved() throws IOException
|
||||
{
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
@@ -241,7 +342,7 @@ public class ImportExportTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useImportExportTask() throws FileNotFoundException, JSONException
|
||||
public void useImportExportTask() throws FileNotFoundException
|
||||
{
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
@@ -298,11 +399,13 @@ public class ImportExportTest
|
||||
{
|
||||
String csvText = "";
|
||||
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STORE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.NOTE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "\n";
|
||||
csvText += "1,store,note,12345,type";
|
||||
DBHelper.LoyaltyCardDbIds.STORE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.NOTE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS + "\n";
|
||||
|
||||
csvText += "1,store,note,12345,type,0";
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(csvText.getBytes(StandardCharsets.UTF_8));
|
||||
InputStreamReader inStream = new InputStreamReader(inputStream);
|
||||
@@ -318,6 +421,7 @@ public class ImportExportTest
|
||||
assertEquals("note", card.note);
|
||||
assertEquals("12345", card.cardId);
|
||||
assertEquals("type", card.barcodeType);
|
||||
assertEquals(0, card.starStatus);
|
||||
assertNull(card.headerColor);
|
||||
assertNull(card.headerTextColor);
|
||||
}
|
||||
@@ -332,8 +436,10 @@ public class ImportExportTest
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "\n";
|
||||
csvText += "1,store,note,12345,type,,";
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS + "\n";
|
||||
|
||||
csvText += "1,store,note,12345,type,,,0";
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(csvText.getBytes(StandardCharsets.UTF_8));
|
||||
InputStreamReader inStream = new InputStreamReader(inputStream);
|
||||
@@ -349,6 +455,7 @@ public class ImportExportTest
|
||||
assertEquals("note", card.note);
|
||||
assertEquals("12345", card.cardId);
|
||||
assertEquals("type", card.barcodeType);
|
||||
assertEquals(0, card.starStatus);
|
||||
assertNull(card.headerColor);
|
||||
assertNull(card.headerTextColor);
|
||||
}
|
||||
@@ -363,8 +470,10 @@ public class ImportExportTest
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "\n";
|
||||
csvText += "1,store,note,12345,type,not a number,invalid";
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS + "\n";
|
||||
|
||||
csvText += "1,store,note,12345,type,not a number,invalid,0";
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(csvText.getBytes(StandardCharsets.UTF_8));
|
||||
InputStreamReader inStream = new InputStreamReader(inputStream);
|
||||
@@ -385,8 +494,10 @@ public class ImportExportTest
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "\n";
|
||||
csvText += "1,store,note,12345,,1,1";
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS + "\n";
|
||||
|
||||
csvText += "1,store,note,12345,,1,1,0";
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(csvText.getBytes(StandardCharsets.UTF_8));
|
||||
InputStreamReader inStream = new InputStreamReader(inputStream);
|
||||
@@ -402,7 +513,132 @@ public class ImportExportTest
|
||||
assertEquals("note", card.note);
|
||||
assertEquals("12345", card.cardId);
|
||||
assertEquals("", card.barcodeType);
|
||||
assertEquals(0, card.starStatus);
|
||||
assertEquals(1, (long) card.headerColor);
|
||||
assertEquals(1, (long) card.headerTextColor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importWithStarredField() throws IOException
|
||||
{
|
||||
String csvText = "";
|
||||
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STORE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.NOTE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS + "\n";
|
||||
|
||||
csvText += "1,store,note,12345,type,1,1,1";
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(csvText.getBytes(StandardCharsets.UTF_8));
|
||||
InputStreamReader inStream = new InputStreamReader(inputStream);
|
||||
|
||||
// Import the CSV data
|
||||
boolean result = MultiFormatImporter.importData(db, inStream, DataFormat.CSV);
|
||||
assertEquals(true, result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
assertEquals("store", card.store);
|
||||
assertEquals("note", card.note);
|
||||
assertEquals("12345", card.cardId);
|
||||
assertEquals("type", card.barcodeType);
|
||||
assertEquals(1, card.starStatus);
|
||||
assertEquals(1, (long) card.headerColor);
|
||||
assertEquals(1, (long) card.headerTextColor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void importWithNoStarredField() throws IOException
|
||||
{
|
||||
String csvText = "";
|
||||
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STORE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.NOTE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS + "\n";
|
||||
|
||||
csvText += "1,store,note,12345,type,1,1,";
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(csvText.getBytes(StandardCharsets.UTF_8));
|
||||
InputStreamReader inStream = new InputStreamReader(inputStream);
|
||||
|
||||
// Import the CSV data
|
||||
boolean result = MultiFormatImporter.importData(db, inStream, DataFormat.CSV);
|
||||
assertEquals(true, result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
assertEquals("store", card.store);
|
||||
assertEquals("note", card.note);
|
||||
assertEquals("12345", card.cardId);
|
||||
assertEquals("type", card.barcodeType);
|
||||
assertEquals(0, card.starStatus);
|
||||
assertEquals(1, (long) card.headerColor);
|
||||
assertEquals(1, (long) card.headerTextColor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importWithInvalidStarField() throws IOException
|
||||
{
|
||||
String csvText = "";
|
||||
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STORE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.NOTE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS + "\n";
|
||||
|
||||
csvText += "1,store,note,12345,type,1,1,2";
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(csvText.getBytes(StandardCharsets.UTF_8));
|
||||
InputStreamReader inStream = new InputStreamReader(inputStream);
|
||||
|
||||
// Import the CSV data
|
||||
boolean result = MultiFormatImporter.importData(db, inStream, DataFormat.CSV);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
csvText = "";
|
||||
csvText += DBHelper.LoyaltyCardDbIds.ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STORE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.NOTE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID + "," +
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_TEXT_COLOR + "," +
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS + "\n";
|
||||
|
||||
csvText += "1,store,note,12345,type,1,1,text";
|
||||
|
||||
inputStream = new ByteArrayInputStream(csvText.getBytes(StandardCharsets.UTF_8));
|
||||
inStream = new InputStreamReader(inputStream);
|
||||
|
||||
// Import the CSV data
|
||||
result = MultiFormatImporter.importData(db, inStream, DataFormat.CSV);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
assertEquals("store", card.store);
|
||||
assertEquals("note", card.note);
|
||||
assertEquals("12345", card.cardId);
|
||||
assertEquals("type", card.barcodeType);
|
||||
assertEquals(0, card.starStatus);
|
||||
assertEquals(1, (long) card.headerColor);
|
||||
assertEquals(1, (long) card.headerTextColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,18 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.io.InvalidObjectException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static protect.card_locker.DBHelper.LoyaltyCardDbIds;
|
||||
@@ -39,18 +32,13 @@ public class ImportURITest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureNoDataLoss() throws InvalidObjectException, JSONException
|
||||
public void ensureNoDataLoss() throws InvalidObjectException
|
||||
{
|
||||
// Generate card
|
||||
Bitmap icon = BitmapFactory.decodeResource(Resources.getSystem(), R.mipmap.ic_launcher);
|
||||
assertNotNull(icon);
|
||||
ExtrasHelper extrasHelper = new ExtrasHelper();
|
||||
extrasHelper.addLanguageValue("en", "key", "value");
|
||||
db.insertLoyaltyCard("store", "note", BarcodeFormat.UPC_A.toString(), LoyaltyCardDbIds.BARCODE_TYPE, Color.BLACK, Color.WHITE, icon, extrasHelper);
|
||||
db.insertLoyaltyCard("store", "note", BarcodeFormat.UPC_A.toString(), LoyaltyCardDbIds.BARCODE_TYPE, Color.BLACK, Color.WHITE, 1);
|
||||
|
||||
// Get card
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
assertNotNull(card.icon);
|
||||
|
||||
// Card to URI
|
||||
Uri cardUri = importURIHelper.toUri(card);
|
||||
@@ -65,23 +53,15 @@ public class ImportURITest {
|
||||
assertEquals(card.headerTextColor, parsedCard.headerTextColor);
|
||||
assertEquals(card.note, parsedCard.note);
|
||||
assertEquals(card.store, parsedCard.store);
|
||||
assertEquals(card.icon.getWidth(), parsedCard.icon.getWidth());
|
||||
assertEquals(card.icon.getHeight(), parsedCard.icon.getHeight());
|
||||
for(int i = 0; i < card.icon.getWidth(); i++)
|
||||
{
|
||||
for(int j = 0; j < card.icon.getHeight(); j++)
|
||||
{
|
||||
assertEquals(card.icon.getPixel(i, j), parsedCard.icon.getPixel(i, j));
|
||||
}
|
||||
}
|
||||
assertEquals(card.extras.toJSON().toString(), parsedCard.extras.toJSON().toString());
|
||||
// No export of starStatus for single cards foreseen therefore 0 will be imported
|
||||
assertEquals(0, parsedCard.starStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureNoCrashOnMissingHeaderFields() throws InvalidObjectException, JSONException
|
||||
public void ensureNoCrashOnMissingHeaderFields() throws InvalidObjectException
|
||||
{
|
||||
// Generate card
|
||||
db.insertLoyaltyCard("store", "note", BarcodeFormat.UPC_A.toString(), LoyaltyCardDbIds.BARCODE_TYPE, null, null, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BarcodeFormat.UPC_A.toString(), LoyaltyCardDbIds.BARCODE_TYPE, null, null, 0);
|
||||
|
||||
// Get card
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
@@ -111,4 +91,36 @@ public class ImportURITest {
|
||||
// Desired behaviour
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failToParseBadData()
|
||||
{
|
||||
try {
|
||||
//"stare" instead of store
|
||||
importURIHelper.parse(Uri.parse("https://brarcher.github.io/loyalty-card-locker/share?stare=store¬e=note&cardid=12345&barcodetype=ITF&headercolor=-416706&headertextcolor=-1"));
|
||||
assertTrue(false); // Shouldn't get here
|
||||
} catch(InvalidObjectException ex) {
|
||||
// Desired behaviour
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseAdditionalUnforeseenData()
|
||||
{
|
||||
LoyaltyCard parsedCard = null;
|
||||
try {
|
||||
parsedCard = importURIHelper.parse(Uri.parse("https://brarcher.github.io/loyalty-card-locker/share?store=store¬e=note&cardid=12345&barcodetype=ITF&headercolor=-416706&headertextcolor=-1¬foreseen=no"));
|
||||
} catch (InvalidObjectException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Compare everything
|
||||
assertEquals("ITF", parsedCard.barcodeType);
|
||||
assertEquals("12345", parsedCard.cardId);
|
||||
assertEquals("note", parsedCard.note);
|
||||
assertEquals("store", parsedCard.store);
|
||||
assertEquals(Integer.valueOf(-416706), parsedCard.headerColor);
|
||||
assertEquals(Integer.valueOf(-1), parsedCard.headerTextColor);
|
||||
assertEquals(0, parsedCard.starStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,11 @@ import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -83,9 +82,9 @@ public class LoyaltyCardCursorAdapterTest
|
||||
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapterEmptyNote() throws JSONException
|
||||
public void TestCursorAdapterEmptyNote()
|
||||
{
|
||||
db.insertLoyaltyCard("store", "", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
@@ -97,9 +96,9 @@ public class LoyaltyCardCursorAdapterTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapterWithNote() throws JSONException
|
||||
public void TestCursorAdapterWithNote()
|
||||
{
|
||||
db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
@@ -111,9 +110,9 @@ public class LoyaltyCardCursorAdapterTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapterFontSizes() throws JSONException
|
||||
public void TestCursorAdapterFontSizes()
|
||||
{
|
||||
db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
@@ -127,4 +126,29 @@ public class LoyaltyCardCursorAdapterTest
|
||||
view = createView(cursor);
|
||||
checkView(view, card.store, card.note, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCursorAdapterStarring()
|
||||
{
|
||||
db.insertLoyaltyCard("storeA", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
db.insertLoyaltyCard("storeB", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 1);
|
||||
db.insertLoyaltyCard("storeC", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 1);
|
||||
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
cursor.moveToFirst();
|
||||
View view = createView(cursor);
|
||||
ImageView star = view.findViewById(R.id.star);
|
||||
assertEquals(View.VISIBLE, star.getVisibility());
|
||||
|
||||
cursor.moveToNext();
|
||||
view = createView(cursor);
|
||||
star = view.findViewById(R.id.star);
|
||||
assertEquals(View.VISIBLE, star.getVisibility());
|
||||
|
||||
cursor.moveToNext();
|
||||
view = createView(cursor);
|
||||
star = view.findViewById(R.id.star);
|
||||
assertEquals(View.GONE, star.getVisibility());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import android.widget.TextView;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.client.android.Intents;
|
||||
import org.json.JSONException;
|
||||
import java.io.IOException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -395,13 +394,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardEditModeCheckDisplay() throws IOException, JSONException
|
||||
public void startWithLoyaltyCardEditModeCheckDisplay() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -411,13 +410,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardViewModeCheckDisplay() throws IOException, JSONException
|
||||
public void startWithLoyaltyCardViewModeCheckDisplay() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -427,13 +426,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardWithBarcodeUpdateBarcode() throws IOException, JSONException
|
||||
public void startWithLoyaltyCardWithBarcodeUpdateBarcode() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
|
||||
db.insertLoyaltyCard("store", "note", EAN_BARCODE_DATA, EAN_BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", EAN_BARCODE_DATA, EAN_BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -448,13 +447,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLoyaltyCardWithReceiptUpdateReceiptCancel() throws IOException, JSONException
|
||||
public void startWithLoyaltyCardWithReceiptUpdateReceiptCancel() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
|
||||
db.insertLoyaltyCard("store", "note", EAN_BARCODE_DATA, EAN_BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", EAN_BARCODE_DATA, EAN_BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -474,13 +473,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkMenu() throws IOException, JSONException
|
||||
public void checkMenu() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -489,12 +488,12 @@ public class LoyaltyCardViewActivityTest
|
||||
final Menu menu = shadowOf(activity).getOptionsMenu();
|
||||
assertTrue(menu != null);
|
||||
|
||||
// The rotation,share and info button should be present
|
||||
// The share, settings, add and star button should be present
|
||||
assertEquals(menu.size(), 3);
|
||||
|
||||
assertEquals("Block Rotation", menu.findItem(R.id.action_lock_unlock).getTitle().toString());
|
||||
assertEquals("Share", menu.findItem(R.id.action_share).getTitle().toString());
|
||||
assertEquals("More Info", menu.findItem(R.id.action_view_extras).getTitle().toString());
|
||||
assertEquals("Add to favorites", menu.findItem(R.id.action_star_unstar).getTitle().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -518,13 +517,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutParametersViewBack() throws JSONException
|
||||
public void startWithoutParametersViewBack()
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -536,13 +535,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutColors() throws JSONException
|
||||
public void startWithoutColors()
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, null, null, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, null, null, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -554,13 +553,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startLoyaltyCardWithoutColorsSave() throws IOException, JSONException
|
||||
public void startLoyaltyCardWithoutColorsSave() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, null, null, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, null, null, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -571,13 +570,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startLoyaltyCardWithExplicitNoBarcodeSave() throws IOException, JSONException
|
||||
public void startLoyaltyCardWithExplicitNoBarcodeSave() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, "", Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, "", Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -588,13 +587,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeBarcodeFromLoyaltyCard() throws IOException, JSONException
|
||||
public void removeBarcodeFromLoyaltyCard() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -615,13 +614,13 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startCheckFontSizes() throws JSONException
|
||||
public void startCheckFontSizes()
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
final int STORE_FONT_SIZE = 50;
|
||||
final int CARD_FONT_SIZE = 40;
|
||||
@@ -655,7 +654,7 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkScreenOrientationLockSetting() throws JSONException
|
||||
public void checkScreenOrientationLockSetting()
|
||||
{
|
||||
for(boolean locked : new boolean[] {false, true})
|
||||
{
|
||||
@@ -663,7 +662,7 @@ public class LoyaltyCardViewActivityTest
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
settings.edit()
|
||||
@@ -692,54 +691,42 @@ public class LoyaltyCardViewActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkMoreInfoNoExtras() throws JSONException
|
||||
public void checkPushStarIcon()
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
Activity activity = (Activity) activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE,0);
|
||||
activityController.start();
|
||||
activityController.resume();
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
assertEquals(false, activity.isFinishing());
|
||||
|
||||
MenuItem item = shadowOf(activity).getOptionsMenu().findItem(R.id.action_view_extras);
|
||||
assertEquals(false, item.isVisible());
|
||||
final Menu menu = shadowOf(activity).getOptionsMenu();
|
||||
assertTrue(menu != null);
|
||||
|
||||
// The share, settings and star button should be present
|
||||
assertEquals(menu.size(), 3);
|
||||
|
||||
assertEquals("Add to favorites", menu.findItem(R.id.action_star_unstar).getTitle().toString());
|
||||
|
||||
shadowOf(activity).clickMenuItem(R.id.action_star_unstar);
|
||||
assertEquals("Remove from favorites", menu.findItem(R.id.action_star_unstar).getTitle().toString());
|
||||
|
||||
shadowOf(activity).clickMenuItem(R.id.action_star_unstar);
|
||||
assertEquals("Add to favorites", menu.findItem(R.id.action_star_unstar).getTitle().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkMoreInfoExtras() throws JSONException
|
||||
public void checkBarcodeFullscreenWorkflow()
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
ExtrasHelper extrasHelper = new ExtrasHelper();
|
||||
extrasHelper.addLanguageValue("en", "key", "value");
|
||||
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, extrasHelper);
|
||||
|
||||
activityController.start();
|
||||
activityController.resume();
|
||||
activityController.visible();
|
||||
|
||||
assertEquals(false, activity.isFinishing());
|
||||
|
||||
MenuItem item = shadowOf(activity).getOptionsMenu().findItem(R.id.action_view_extras);
|
||||
assertEquals(true, item.isVisible());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBarcodeFullscreenWorkflow() throws JSONException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
@@ -798,7 +785,7 @@ public class LoyaltyCardViewActivityTest
|
||||
@Test
|
||||
public void importCard()
|
||||
{
|
||||
Uri importUri = Uri.parse("https://thelastproject.github.io/Catima/share?store=Example%20Store¬e=&cardid=123456&barcodetype=AZTEC&headercolor=-416706&headertextcolor=-1&icon=&extras={}");
|
||||
Uri importUri = Uri.parse("https://thelastproject.github.io/Catima/share?store=Example%20Store¬e=&cardid=123456&barcodetype=AZTEC&headercolor=-416706&headertextcolor=-1");
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setData(importUri);
|
||||
@@ -819,7 +806,7 @@ public class LoyaltyCardViewActivityTest
|
||||
@Test
|
||||
public void importCardOldURL()
|
||||
{
|
||||
Uri importUri = Uri.parse("https://thelastproject.github.io/Catima/share?store=Example%20Store¬e=&cardid=123456&barcodetype=AZTEC&headercolor=-416706&headertextcolor=-1");
|
||||
Uri importUri = Uri.parse("https://brarcher.github.io/loyalty-card-locker/share?store=Example%20Store¬e=&cardid=123456&barcodetype=AZTEC&headercolor=-416706&headertextcolor=-1");
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setData(importUri);
|
||||
|
||||
@@ -15,7 +15,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -83,7 +82,7 @@ public class MainActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addOneLoyaltyCard() throws JSONException
|
||||
public void addOneLoyaltyCard()
|
||||
{
|
||||
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
|
||||
|
||||
@@ -98,7 +97,7 @@ public class MainActivityTest
|
||||
assertEquals(0, list.getCount());
|
||||
|
||||
DBHelper db = new DBHelper(mainActivity);
|
||||
db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
assertEquals(View.VISIBLE, helpText.getVisibility());
|
||||
assertEquals(View.GONE, noMatchingCardsText.getVisibility());
|
||||
@@ -117,7 +116,57 @@ public class MainActivityTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFiltering() throws JSONException
|
||||
public void addFourLoyaltyCardsTwoStarred() // Main screen showing starred cards on top correctly
|
||||
{
|
||||
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
|
||||
|
||||
Activity mainActivity = (Activity)activityController.get();
|
||||
activityController.start();
|
||||
activityController.resume();
|
||||
|
||||
TextView helpText = mainActivity.findViewById(R.id.helpText);
|
||||
TextView noMatchingCardsText = mainActivity.findViewById(R.id.noMatchingCardsText);
|
||||
ListView list = mainActivity.findViewById(R.id.list);
|
||||
|
||||
assertEquals(0, list.getCount());
|
||||
|
||||
DBHelper db = new DBHelper(mainActivity);
|
||||
db.insertLoyaltyCard("storeB", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
db.insertLoyaltyCard("storeA", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
db.insertLoyaltyCard("storeD", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 1);
|
||||
db.insertLoyaltyCard("storeC", "note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 1);
|
||||
|
||||
assertEquals(View.VISIBLE, helpText.getVisibility());
|
||||
assertEquals(View.GONE, noMatchingCardsText.getVisibility());
|
||||
assertEquals(View.GONE, list.getVisibility());
|
||||
|
||||
activityController.pause();
|
||||
activityController.resume();
|
||||
|
||||
assertEquals(View.GONE, helpText.getVisibility());
|
||||
assertEquals(View.GONE, noMatchingCardsText.getVisibility());
|
||||
assertEquals(View.VISIBLE, list.getVisibility());
|
||||
|
||||
assertEquals(4, list.getAdapter().getCount());
|
||||
Cursor cursor = (Cursor)list.getAdapter().getItem(0);
|
||||
assertNotNull(cursor);
|
||||
assertEquals("storeC",cursor.getString(cursor.getColumnIndex("store")));
|
||||
|
||||
cursor = (Cursor)list.getAdapter().getItem(1);
|
||||
assertNotNull(cursor);
|
||||
assertEquals("storeD",cursor.getString(cursor.getColumnIndex("store")));
|
||||
|
||||
cursor = (Cursor)list.getAdapter().getItem(2);
|
||||
assertNotNull(cursor);
|
||||
assertEquals("storeA",cursor.getString(cursor.getColumnIndex("store")));
|
||||
|
||||
cursor = (Cursor)list.getAdapter().getItem(3);
|
||||
assertNotNull(cursor);
|
||||
assertEquals("storeB",cursor.getString(cursor.getColumnIndex("store")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFiltering()
|
||||
{
|
||||
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
|
||||
|
||||
@@ -130,8 +179,8 @@ public class MainActivityTest
|
||||
ListView list = mainActivity.findViewById(R.id.list);
|
||||
|
||||
DBHelper db = new DBHelper(mainActivity);
|
||||
db.insertLoyaltyCard("The First Store", "Initial note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("The Second Store", "Secondary note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, null, new ExtrasHelper());
|
||||
db.insertLoyaltyCard("The First Store", "Initial note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
db.insertLoyaltyCard("The Second Store", "Secondary note", "cardId", BarcodeFormat.UPC_A.toString(), Color.BLACK, Color.WHITE, 0);
|
||||
|
||||
activityController.pause();
|
||||
activityController.resume();
|
||||
|
||||
@@ -1,384 +0,0 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 23)
|
||||
public class PkpassTest {
|
||||
private PkpassImporter pkpassImporter;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
Activity activity = Robolectric.setupActivity(MainActivity.class);
|
||||
pkpassImporter = new PkpassImporter(activity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseGenericExample() throws IOException, JSONException
|
||||
{
|
||||
// https://github.com/keefmoon/Passbook-Example-Code/blob/master/Pass-Example-Generic/Pass-Example-Generic.pkpass
|
||||
InputStream inputStream = getClass().getResourceAsStream("Pass-Example-Generic.pkpass");
|
||||
|
||||
LoyaltyCard card = pkpassImporter.fromInputStream(inputStream);
|
||||
|
||||
// Compare everything
|
||||
assertEquals(BarcodeFormat.QR_CODE.name(), card.barcodeType);
|
||||
assertEquals("0000001", card.cardId);
|
||||
assertEquals("Staff Pass for Employee Number 001", card.note);
|
||||
assertEquals("Passbook Example Company", card.store);
|
||||
assertEquals(String.valueOf(Color.rgb(90, 90, 90)), card.headerColor.toString());
|
||||
assertEquals(String.valueOf(Color.rgb(255, 255, 255)), card.headerTextColor.toString());
|
||||
|
||||
// Check if all the extras got parsed correctly
|
||||
ExtrasHelper extras = card.extras;
|
||||
// Expecting no English entries
|
||||
assertEquals(0, extras.getAllValues("en").keySet().size());
|
||||
// Expecting 7 untranslated entries
|
||||
assertEquals(7, extras.getAllValues("").keySet().size());
|
||||
// Untranslated and English + untranslated fallback should return the same
|
||||
assertEquals(extras.getAllValues(""), extras.getAllValues(new String[]{"en", ""}));
|
||||
|
||||
// Check all 7 values
|
||||
Iterator<Map.Entry<String, String>> extrasKeys = extras.getAllValues("").entrySet().iterator();
|
||||
|
||||
// 1
|
||||
Map.Entry<String, String> entry = extrasKeys.next();
|
||||
assertEquals("staffNumber", entry.getKey());
|
||||
assertEquals("Staff Number: 001", entry.getValue());
|
||||
|
||||
// 2
|
||||
entry = extrasKeys.next();
|
||||
assertEquals("staffName", entry.getKey());
|
||||
assertEquals("Name: Peter Brooke", entry.getValue());
|
||||
|
||||
// 3
|
||||
entry = extrasKeys.next();
|
||||
assertEquals("telephoneExt", entry.getKey());
|
||||
assertEquals("Extension: 9779", entry.getValue());
|
||||
|
||||
// 4
|
||||
entry = extrasKeys.next();
|
||||
assertEquals("jobTitle", entry.getKey());
|
||||
assertEquals("Job Title: Chief Pass Creator", entry.getValue());
|
||||
|
||||
// 5
|
||||
entry = extrasKeys.next();
|
||||
assertEquals("expiryDate", entry.getKey());
|
||||
assertEquals("Expiry Date: 2013-12-31T00:00-23:59", entry.getValue());
|
||||
|
||||
// 6
|
||||
entry = extrasKeys.next();
|
||||
assertEquals("managersName", entry.getKey());
|
||||
assertEquals("Manager's Name: Paul Bailey", entry.getValue());
|
||||
|
||||
// 7
|
||||
entry = extrasKeys.next();
|
||||
assertEquals("managersExt", entry.getKey());
|
||||
assertEquals("Manager's Extension: 9673", entry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseEurowingsTicket() throws IOException, JSONException
|
||||
{
|
||||
// https://github.com/brarcher/loyalty-card-locker/issues/309#issuecomment-563465333
|
||||
InputStream inputStream = getClass().getResourceAsStream("Eurowings.pkpass");
|
||||
|
||||
LoyaltyCard card = pkpassImporter.fromInputStream(inputStream);
|
||||
|
||||
// Compare everything
|
||||
assertEquals(BarcodeFormat.AZTEC.name(), card.barcodeType);
|
||||
assertEquals("M1DOE/JOHN JBZPPP CGNDBVEW 0954 251A016E0073 148>5181W 9250BEW 00000000000002A0000000000000 0 N", card.cardId);
|
||||
assertEquals("Eurowings Boarding Pass", card.note);
|
||||
assertEquals("EUROWINGS", card.store);
|
||||
|
||||
// Violates the spec, but we want to support it anyway...
|
||||
assertEquals(String.valueOf(Color.parseColor("#FFFFFF")), card.headerColor.toString());
|
||||
assertEquals(String.valueOf(Color.parseColor("#AA0061")), card.headerTextColor.toString());
|
||||
|
||||
// Check if all the extras got parsed correctly
|
||||
ExtrasHelper extras = card.extras;
|
||||
|
||||
// Expect 18 English values
|
||||
assertEquals(18, extras.getAllValues("en").size());
|
||||
|
||||
// Expect 18 German values
|
||||
assertEquals(18, extras.getAllValues("de").size());
|
||||
|
||||
// Expect 18 untranslated values
|
||||
assertEquals(18, extras.getAllValues("").size());
|
||||
|
||||
// Expect no French values
|
||||
assertEquals(0, extras.getAllValues("fr").size());
|
||||
|
||||
// Check all 18 English, German and untranslated values
|
||||
Iterator<Map.Entry<String, String>> englishKeys = extras.getAllValues("en").entrySet().iterator();
|
||||
Iterator<Map.Entry<String, String>> germanKeys = extras.getAllValues("de").entrySet().iterator();
|
||||
Iterator<Map.Entry<String, String>> untranslatedKeys = extras.getAllValues("").entrySet().iterator();
|
||||
|
||||
// 1
|
||||
Map.Entry<String, String> englishEntry = englishKeys.next();
|
||||
Map.Entry<String, String> germanEntry = germanKeys.next();
|
||||
Map.Entry<String, String> untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("gate", englishEntry.getKey());
|
||||
assertEquals("gate", germanEntry.getKey());
|
||||
assertEquals("gate", untranslatedEntry.getKey());
|
||||
assertEquals("Gate: B61", englishEntry.getValue());
|
||||
assertEquals("Gate: B61", germanEntry.getValue());
|
||||
assertEquals("gate_str: B61", untranslatedEntry.getValue());
|
||||
|
||||
// 2
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("seat", englishEntry.getKey());
|
||||
assertEquals("seat", germanEntry.getKey());
|
||||
assertEquals("seat", untranslatedEntry.getKey());
|
||||
assertEquals("Seat: 16E", englishEntry.getValue());
|
||||
assertEquals("Sitz: 16E", germanEntry.getValue());
|
||||
assertEquals("seat_str: 16E", untranslatedEntry.getValue());
|
||||
|
||||
// 3
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("origin", englishEntry.getKey());
|
||||
assertEquals("origin", germanEntry.getKey());
|
||||
assertEquals("origin", untranslatedEntry.getKey());
|
||||
assertEquals("Cologne-Bonn: CGN", englishEntry.getValue());
|
||||
assertEquals("Cologne-Bonn: CGN", germanEntry.getValue());
|
||||
assertEquals("Cologne-Bonn: CGN", untranslatedEntry.getValue());
|
||||
|
||||
// 4
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("destination", englishEntry.getKey());
|
||||
assertEquals("destination", germanEntry.getKey());
|
||||
assertEquals("destination", untranslatedEntry.getKey());
|
||||
assertEquals("Dubrovnik: DBV", englishEntry.getValue());
|
||||
assertEquals("Dubrovnik: DBV", germanEntry.getValue());
|
||||
assertEquals("Dubrovnik: DBV", untranslatedEntry.getValue());
|
||||
|
||||
// 5
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("name", englishEntry.getKey());
|
||||
assertEquals("name", germanEntry.getKey());
|
||||
assertEquals("name", untranslatedEntry.getKey());
|
||||
assertEquals("Name: John Doe", englishEntry.getValue());
|
||||
assertEquals("Name: John Doe", germanEntry.getValue());
|
||||
assertEquals("name_str: John Doe", untranslatedEntry.getValue());
|
||||
|
||||
// 6
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("status", englishEntry.getKey());
|
||||
assertEquals("status", germanEntry.getKey());
|
||||
assertEquals("status", untranslatedEntry.getKey());
|
||||
assertEquals("Status: -", englishEntry.getValue());
|
||||
assertEquals("Status: -", germanEntry.getValue());
|
||||
assertEquals("status_str: -", untranslatedEntry.getValue());
|
||||
|
||||
// 7
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("boardinggroup", englishEntry.getKey());
|
||||
assertEquals("boardinggroup", germanEntry.getKey());
|
||||
assertEquals("boardinggroup", untranslatedEntry.getKey());
|
||||
assertEquals("Group: GROUP 1", englishEntry.getValue());
|
||||
assertEquals("Gruppe: GROUP 1", germanEntry.getValue());
|
||||
assertEquals("boardinggroup_str: GROUP 1", untranslatedEntry.getValue());
|
||||
|
||||
// 8
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("tarif", englishEntry.getKey());
|
||||
assertEquals("tarif", germanEntry.getKey());
|
||||
assertEquals("tarif", untranslatedEntry.getKey());
|
||||
assertEquals("Fare: SMART", englishEntry.getValue());
|
||||
assertEquals("Tarif: SMART", germanEntry.getValue());
|
||||
assertEquals("fare_str: SMART", untranslatedEntry.getValue());
|
||||
|
||||
// 9
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("flightNumber", englishEntry.getKey());
|
||||
assertEquals("flightNumber", germanEntry.getKey());
|
||||
assertEquals("flightNumber", untranslatedEntry.getKey());
|
||||
assertEquals("Flight: EW 954", englishEntry.getValue());
|
||||
assertEquals("Flug: EW 954", germanEntry.getValue());
|
||||
assertEquals("flight_str: EW 954", untranslatedEntry.getValue());
|
||||
|
||||
// 10
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("departureDate", englishEntry.getKey());
|
||||
assertEquals("departureDate", germanEntry.getKey());
|
||||
assertEquals("departureDate", untranslatedEntry.getKey());
|
||||
assertEquals("Date: 08/09/2019", englishEntry.getValue());
|
||||
assertEquals("Datum: 08/09/2019", germanEntry.getValue());
|
||||
assertEquals("date_str: 08/09/2019", untranslatedEntry.getValue());
|
||||
|
||||
// 11
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("boarding", englishEntry.getKey());
|
||||
assertEquals("boarding", germanEntry.getKey());
|
||||
assertEquals("boarding", untranslatedEntry.getKey());
|
||||
assertEquals("Boarding: 05:00", englishEntry.getValue());
|
||||
assertEquals("Boarding: 05:00", germanEntry.getValue());
|
||||
assertEquals("boarding_str: 05:00", untranslatedEntry.getValue());
|
||||
|
||||
// 12
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("closure", englishEntry.getKey());
|
||||
assertEquals("closure", germanEntry.getKey());
|
||||
assertEquals("closure", untranslatedEntry.getKey());
|
||||
assertEquals("Gate closure: 05:15", englishEntry.getValue());
|
||||
assertEquals("Gate Schließt: 05:15", germanEntry.getValue());
|
||||
assertEquals("closure_str: 05:15", untranslatedEntry.getValue());
|
||||
|
||||
// 13
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("info", englishEntry.getKey());
|
||||
assertEquals("info", germanEntry.getKey());
|
||||
assertEquals("info", untranslatedEntry.getKey());
|
||||
assertEquals("Eurowings wishes you a pleasant flight .\r\n" +
|
||||
"\r\n" +
|
||||
"We kindly ask you to be present at your departure gate on time.", englishEntry.getValue());
|
||||
assertEquals("Eurowings wünscht Ihnen einen angenehmen Flug.\r\n" +
|
||||
"\r\n" +
|
||||
"Wir bitten Sie, sich zur angegeben Boarding Zeit am Gate einzufinden.", germanEntry.getValue());
|
||||
assertEquals("info_content_str", untranslatedEntry.getValue());
|
||||
|
||||
// 14
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("recordlocator", englishEntry.getKey());
|
||||
assertEquals("recordlocator", germanEntry.getKey());
|
||||
assertEquals("recordlocator", untranslatedEntry.getKey());
|
||||
assertEquals("Booking code: JBZPPP", englishEntry.getValue());
|
||||
assertEquals("Buchungscode: JBZPPP", germanEntry.getValue());
|
||||
assertEquals("recordlocator_str: JBZPPP", untranslatedEntry.getValue());
|
||||
|
||||
// 15
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("sequence", englishEntry.getKey());
|
||||
assertEquals("sequence", germanEntry.getKey());
|
||||
assertEquals("sequence", untranslatedEntry.getKey());
|
||||
assertEquals("Sequence: 73", englishEntry.getValue());
|
||||
assertEquals("Sequenz: 73", germanEntry.getValue());
|
||||
assertEquals("sequence_str: 73", untranslatedEntry.getValue());
|
||||
|
||||
// 16
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("notice", englishEntry.getKey());
|
||||
assertEquals("notice", germanEntry.getKey());
|
||||
assertEquals("notice", untranslatedEntry.getKey());
|
||||
assertEquals("Notice: Please note that although your flight may be delayed, you will still need to check in and go to your departure gate on time as scheduled.\r\n" +
|
||||
"\r\n" +
|
||||
"Carry on one item of hand luggage (8 kg, 55 x 40 x 23 cm) for free.", englishEntry.getValue());
|
||||
assertEquals("Hinweis: Bitte beachten Sie, dass obwohl Ihr Flug verspätet sein mag, Sie dennoch wie geplant pünktlich am Check-in und am Abfluggate erscheinen müssen.\r\n" +
|
||||
"\r\n" +
|
||||
"Kostenlose Mitnahme eines Handgepäckstücks (8 Kg, 55 x 40 x 23cm).", germanEntry.getValue());
|
||||
assertEquals("notice_str: notice_content_str", untranslatedEntry.getValue());
|
||||
|
||||
// 17
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("baggage", englishEntry.getKey());
|
||||
assertEquals("baggage", germanEntry.getKey());
|
||||
assertEquals("baggage", untranslatedEntry.getKey());
|
||||
assertEquals("Carrying liquids in hand luggage: In addition to other restrictions on hand luggage, there are still restrictions on liquids and gels brought by the passenger or purchased before the security control on all departures within the European Union, as well as to many other countries (including Switzerland, Russia, Iceland, Croatia, Israel, Egypt, Morocco, Tunisia and Norway):\r\n" +
|
||||
"\r\n" +
|
||||
"- All liquids (such as toiletries and cosmetics, gels, pastes, creams, lotions, mixtures of liquids and solids, perfumes, pressurised containers, cans, water bottles etc) as well as wax and gel-like substances may only be carried on board in amounts less than 100ml or 100g.\r\n" +
|
||||
"\r\n" +
|
||||
"- These liquids or substances must be packed in closed containers in a transparent, re-sealable plastic bag (max. contents 1 kg).\r\n" +
|
||||
"\r\n" +
|
||||
"- It is the passenger’s responsibility to purchase this bag before departure. They are available in many supermarkets, e.g. as freezer bags. It is currently not possible for passengers to obtain or purchase the required bags from Eurowings check-in.\r\n" +
|
||||
"\r\n" +
|
||||
"- Prescription medicines and baby food may still be carried in hand baggage. The passenger must prove that such medicines and/or baby food are needed during the flight.\r\n" +
|
||||
"\r\n" +
|
||||
"- Products and bags which do not meet the requirements or are only sealed with a rubber band or similar will unfortunately have to be surrendered by passengers\r\n" +
|
||||
"\r\n" +
|
||||
"In order to pass through the airport as quickly as possible, you are strongly advised to pack any liquids or gels which are not essential for your journey on board the aircraft in your checked baggage if possible.\r\n" +
|
||||
"\r\n" +
|
||||
"As a matter of course, liquids from the Travel Value / Duty Free shops which have been purchased after you have passed through security are still allowed on board.\r\n" +
|
||||
"\r\n" +
|
||||
"Eurowings shall not be liable for any items which passengers are prohibited from carrying in their hand baggage for security reasons and are required to surrender at the security checkpoint.", englishEntry.getValue());
|
||||
assertEquals("Mitnahme von Flüssigkeiten im Handgepäck: Neben den sonstigen Beschränkungen für das Handgepäck ist für alle Abflüge innerhalb der Europäischen Union sowie vielen weiteren Ländern (u.a. Schweiz, Russland, Island, Kroatien, Israel, Ägypten, Marokko, Tunesien, Norwegen) die Mitnahme von vor der Fluggastkontrolle erworbenen bzw. mitgebrachten Flüssigkeiten und Gels nur noch eingeschränkt erlaubt:\r\n" +
|
||||
"\r\n" +
|
||||
"- Sämtliche Flüssigkeiten (wie Kosmetik- und Toilettenartikel, Gels, Pasten, Cremes, Lotionen, Gemische aus flüssigen und festen Stoffen, Parfums, Behälter unter Druck, Dosen, Wasserflaschen etc.) sowie wachs- oder gelartige Stoffe dürfen nur noch in Behältnissen bis zu 100 ml bzw. 100 g mit an Bord genommen werden.\r\n" +
|
||||
"\r\n" +
|
||||
"- Diese Flüssigkeiten bzw. Stoffe müssen in einem transparenten, wiederverschließbaren Plastikbeutel (max. 1 kg Inhalt) vollständig geschlossen, verpackt sein.\r\n" +
|
||||
"\r\n" +
|
||||
"- Diese Beutel müssen Fluggäste selbst vor dem Abflug erwerben. Sie sind in vielen Supermärkten z. B. als Gefrierbeutel erhältlich. Es besteht zurzeit keine Möglichkeit, entsprechende Plastikbeutel am Eurowings Check-In zu erwerben bzw. auszugeben.\r\n" +
|
||||
"\r\n" +
|
||||
"- Verschreibungspflichtige Medikamente sowie Babynahrung dürfen weiterhin im Handgepäck transportiert werden. Der Fluggast muss nachweisen, dass die Medikamente und Babynahrung während des Fluges benötigt werden.\r\n" +
|
||||
"\r\n" +
|
||||
"- Produkte und Beutel, die nicht den Maßgaben entsprechen oder die nur mit Gummiband oder ähnlichem verschlossen sind, müssen leider abgegeben werden.\r\n" +
|
||||
"\r\n" +
|
||||
"Flüssigkeiten und Gels, die Sie nicht zwingend während Ihres Aufenthalts an Bord benötigen, sollten zur raschen Fluggastabfertigung nach Möglichkeit im aufzugebenden Gepäck untergebracht werden.\r\n" +
|
||||
"\r\n" +
|
||||
"Selbstverständlich ist die Mitnahme von allen Flüssigkeiten/Gels/Getränken aus Travel-Value oder Duty Free-Shops, die nach der Fluggastkontrolle erworben werden, weiterhin erlaubt.\r\n" +
|
||||
"\r\n" +
|
||||
"Eurowings übernimmt keine Haftung für Gegenstände, die der Fluggast nicht im Handgepäck mitführen darf und deshalb aus Sicherheitsgründen an der Fluggastkontrolle abgeben muss.", germanEntry.getValue());
|
||||
assertEquals("baggage_str: baggage_content_str", untranslatedEntry.getValue());
|
||||
|
||||
// 18
|
||||
englishEntry = englishKeys.next();
|
||||
germanEntry = germanKeys.next();
|
||||
untranslatedEntry = untranslatedKeys.next();
|
||||
assertEquals("contact", englishEntry.getKey());
|
||||
assertEquals("contact", germanEntry.getKey());
|
||||
assertEquals("contact", untranslatedEntry.getKey());
|
||||
assertEquals("Contact: https://mobile.eurowings.com/booking/StaticContactInfo.aspx?culture=en-GB&back=home", englishEntry.getValue());
|
||||
assertEquals("Kontakt: Sie erreichen das deutsche Call Center unter der Telefonnummer\r\n" +
|
||||
"\r\n" +
|
||||
"0180 6 320 320 ( 0:00 Uhr - 24:00 Uhr )\r\n" +
|
||||
"\r\n" +
|
||||
"(0,20 € pro Anruf aus dem Festnetz der Deutschen Telekom - Mobilfunk maximal 0,60 € pro Anruf).", germanEntry.getValue());
|
||||
assertEquals("contact_str: contact_content_str", untranslatedEntry.getValue());
|
||||
}
|
||||
}
|
||||
BIN
banner.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
@@ -6,6 +6,10 @@
|
||||
<a href="https://play.google.com/store/apps/details?id=me.hackerchick.catima" target="_blank">
|
||||
<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" alt="Get it on Google Play" height="90"/></a>
|
||||
|
||||

|
||||
|
||||
*Logo by [Rose (TangentFoxy)](http://github.com/TangentFoxy)*
|
||||
|
||||
Stores all of your store loyalty cards on your phone, removing the need to carry them around. Currently the following barcode types are supported:
|
||||
|
||||
- AZTEC
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 120 KiB |
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,4 +1,4 @@
|
||||
#Wed Jun 27 14:32:00 EDT 2018
|
||||
#Sun Jul 19 15:12:56 CEST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
133
logo.svg
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="192"
|
||||
height="192"
|
||||
viewBox="0 0 50.799999 50.799999"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
|
||||
sodipodi:docname="Catima v1.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="89.145455"
|
||||
inkscape:cy="91.226471"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:snap-object-midpoints="false"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="705"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#f0f0f0;fill-opacity:1;stroke:#c80000;stroke-width:0.529167;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect851"
|
||||
width="22.693819"
|
||||
height="14.164361"
|
||||
x="4.881855"
|
||||
y="24.280193"
|
||||
transform="rotate(-24)" />
|
||||
<rect
|
||||
style="fill:#f0f0f0;fill-opacity:1;stroke:#c80000;stroke-width:0.529167;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect847"
|
||||
width="25.4"
|
||||
height="16.933332"
|
||||
x="18.049208"
|
||||
y="3.9664748"
|
||||
transform="rotate(24)" />
|
||||
<rect
|
||||
style="fill:#c80000;fill-opacity:1;fill-rule:evenodd;stroke:#c80000;stroke-width:1.5875;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect843"
|
||||
width="27.615681"
|
||||
height="16.503178"
|
||||
x="20.365749"
|
||||
y="10.945274"
|
||||
transform="rotate(16)" />
|
||||
<rect
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.5875;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect18"
|
||||
width="27.615681"
|
||||
height="16.503178"
|
||||
x="12.010998"
|
||||
y="15.495529" />
|
||||
<ellipse
|
||||
style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:0.91078;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path845"
|
||||
cx="12.213013"
|
||||
cy="23.747116"
|
||||
rx="4.3658643"
|
||||
ry="8.5899496" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#f0f0f0;stroke-width:0.529167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path853"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="22.827261"
|
||||
sodipodi:cy="25.781031"
|
||||
sodipodi:rx="1.6710632"
|
||||
sodipodi:ry="1.6710632"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="2.7925268"
|
||||
sodipodi:arc-type="arc"
|
||||
d="m 24.498324,25.781031 a 1.6710632,1.6710632 0 0 1 -1.380886,1.645676 1.6710632,1.6710632 0 0 1 -1.860463,-1.074139"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#f0f0f0;stroke-width:0.529167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path855"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="26.228834"
|
||||
sodipodi:cy="25.761429"
|
||||
sodipodi:rx="1.6710632"
|
||||
sodipodi:ry="1.6710632"
|
||||
sodipodi:start="0.34906585"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="arc"
|
||||
d="m 27.79912,26.332966 a 1.6710632,1.6710632 0 0 1 -1.860463,1.074139 1.6710632,1.6710632 0 0 1 -1.380886,-1.645676"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
style="fill:none;stroke:#f0f0f0;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 16.060603,22.270951 2.645833,-2.645833 2.645833,2.645833"
|
||||
id="path859"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#f0f0f0;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 27.702269,22.27095 2.645833,-2.645833 2.645833,2.645833"
|
||||
id="path861"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 102 KiB |