mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2025-12-24 23:57:53 -05:00
Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2a500824a | ||
|
|
6a91d59050 | ||
|
|
451c49d05f | ||
|
|
b4ec4b74ca | ||
|
|
6c254315af | ||
|
|
dfaf61722f | ||
|
|
2dbebea884 | ||
|
|
d7da942481 | ||
|
|
6b4a01c954 | ||
|
|
aee7728f56 | ||
|
|
6fbbe38542 | ||
|
|
651744b770 | ||
|
|
a189ac22ce | ||
|
|
f4d71e4525 | ||
|
|
45ec062499 | ||
|
|
82d8e84d78 | ||
|
|
fa25bff46f | ||
|
|
5648061a31 | ||
|
|
9cd2f66b40 | ||
|
|
90b7b43faf | ||
|
|
cfe5865d35 | ||
|
|
243898c441 | ||
|
|
0afc6f3976 | ||
|
|
fa95ea6a62 | ||
|
|
abb559afd6 | ||
|
|
61e7d1b154 | ||
|
|
da594a8287 | ||
|
|
15f5c4a67b | ||
|
|
19f7af1e42 | ||
|
|
b5b994642a | ||
|
|
45da445866 | ||
|
|
55b1ad1c55 | ||
|
|
fcd6f075f6 | ||
|
|
3d2f119fdb | ||
|
|
05f4add5cd | ||
|
|
eb71d5f717 | ||
|
|
a64603d64e | ||
|
|
e686bb36ce | ||
|
|
351a805046 | ||
|
|
466ac404bc | ||
|
|
b5c0be8ed5 | ||
|
|
f963b2fd4c | ||
|
|
c26ae45cdc | ||
|
|
addb0896c0 | ||
|
|
c75bef4f01 | ||
|
|
f633fb39aa | ||
|
|
49200fff48 | ||
|
|
f4bd6a3f59 | ||
|
|
18021e7653 | ||
|
|
de364a4cc4 | ||
|
|
3ba42aad6d | ||
|
|
63fad8bae1 | ||
|
|
ad418bc9bd | ||
|
|
b0263d8eb5 | ||
|
|
97d3969f93 | ||
|
|
1c85172206 | ||
|
|
711fa7ef81 | ||
|
|
2220a8e3c6 | ||
|
|
cd1bd31e23 | ||
|
|
f812194b1a | ||
|
|
79c26cfed7 | ||
|
|
85ea10303a | ||
|
|
4196ad8d61 | ||
|
|
90be6a418b | ||
|
|
2e2563cfc0 | ||
|
|
983c207019 | ||
|
|
6a5983b7bf | ||
|
|
b34e69d5d5 | ||
|
|
f1cd9ac935 | ||
|
|
5eb56c934b | ||
|
|
f9b24d4b1b | ||
|
|
537b2cba82 | ||
|
|
d788a274a8 | ||
|
|
57c383c064 | ||
|
|
49a8828007 | ||
|
|
d56a31160a | ||
|
|
bb78f9c12a | ||
|
|
1624d56edb | ||
|
|
7f1b1484ac | ||
|
|
ab1e6eed0c | ||
|
|
ba5cf81bb4 |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,5 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
## v2.11.2 - 95 (2021-12-04)
|
||||
|
||||
- Fix crash on sharing card
|
||||
|
||||
## v2.11.1 - 94 (2021-11-30)
|
||||
|
||||
- Fix blurriness of main screen letter icons
|
||||
- Fix icons sometimes disappearing after selection
|
||||
- Fix status bar icons possibly being invisible on Android 5
|
||||
|
||||
## v2.11.0 - 93 (2021-11-28)
|
||||
|
||||
- Add Catima to [Quick Access Device Controls](https://developer.android.com/guide/topics/ui/device-control)
|
||||
- Fix some groups not showing up correctly in group management screen
|
||||
|
||||
## v2.10.0 - 92 (2021-11-20)
|
||||
|
||||
- New main screen layout
|
||||
|
||||
@@ -18,8 +18,8 @@ android {
|
||||
applicationId "me.hackerchick.catima"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
versionCode 92
|
||||
versionName "2.10.0"
|
||||
versionCode 95
|
||||
versionName "2.11.2"
|
||||
|
||||
vectorDrawables.useSupportLibrary true
|
||||
multiDexEnabled true
|
||||
@@ -49,8 +49,8 @@ android {
|
||||
// Flag to enable support for the new language APIs
|
||||
coreLibraryDesugaringEnabled true
|
||||
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
@@ -97,7 +97,7 @@ dependencies {
|
||||
implementation 'com.google.zxing:core:3.4.1'
|
||||
implementation 'org.apache.commons:commons-csv:1.9.0'
|
||||
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
||||
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.3'
|
||||
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.4'
|
||||
implementation 'net.lingala.zip4j:zip4j:2.9.1'
|
||||
|
||||
// SpotBugs
|
||||
@@ -106,7 +106,7 @@ dependencies {
|
||||
// Testing
|
||||
testImplementation 'androidx.test:core:1.4.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.robolectric:robolectric:4.7.1'
|
||||
testImplementation 'org.robolectric:robolectric:4.7.3'
|
||||
}
|
||||
|
||||
tasks.withType(SpotBugsTask) {
|
||||
|
||||
@@ -37,11 +37,11 @@
|
||||
<activity
|
||||
android:name=".AboutActivity"
|
||||
android:label="@string/about"
|
||||
android:theme="@style/AppTheme.NoActionBar"></activity>
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".ManageGroupsActivity"
|
||||
android:label="@string/groups"
|
||||
android:theme="@style/AppTheme.NoActionBar"></activity>
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".ManageGroupActivity"
|
||||
android:label="@string/group_edit"
|
||||
@@ -117,7 +117,7 @@
|
||||
|
||||
<activity
|
||||
android:name="com.yalantis.ucrop.UCropActivity"
|
||||
android:theme="@style/Theme.AppCompat.NoActionBar"/>
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
@@ -128,6 +128,13 @@
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_provider_paths" />
|
||||
</provider>
|
||||
<service android:name=".CardsOnPowerScreenService" android:label="@string/app_name"
|
||||
android:permission="android.permission.BIND_CONTROLS" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.controls.ControlsProviderService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -5,12 +5,17 @@ import android.database.Cursor;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V> {
|
||||
private Cursor mCursor;
|
||||
public Cursor mCursor;
|
||||
private boolean mDataValid;
|
||||
private int mRowIDColumn;
|
||||
|
||||
public BaseCursorAdapter(Cursor inputCursor) {
|
||||
private String mRowIDColumnName;
|
||||
|
||||
public BaseCursorAdapter(Cursor inputCursor, String rowIDColumnName) {
|
||||
setHasStableIds(true);
|
||||
|
||||
mRowIDColumnName = rowIDColumnName;
|
||||
|
||||
swapCursor(inputCursor);
|
||||
}
|
||||
|
||||
@@ -58,6 +63,7 @@ public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> exten
|
||||
|
||||
if (inputCursor != null) {
|
||||
mCursor = inputCursor;
|
||||
mRowIDColumn = mCursor.getColumnIndex(mRowIDColumnName);
|
||||
mDataValid = true;
|
||||
notifyDataSetChanged();
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
import android.service.controls.Control;
|
||||
import android.service.controls.ControlsProviderService;
|
||||
import android.service.controls.DeviceTypes;
|
||||
import android.service.controls.actions.ControlAction;
|
||||
import android.service.controls.templates.StatelessTemplate;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
public class CardsOnPowerScreenService extends ControlsProviderService {
|
||||
|
||||
public static final String PREFIX = "catima-";
|
||||
static final String TAG = "Catima";
|
||||
private final DBHelper dbHelper = new DBHelper(this);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Flow.Publisher<Control> createPublisherForAllAvailable() {
|
||||
Cursor loyaltyCardCursor = dbHelper.getLoyaltyCardCursor();
|
||||
return subscriber -> {
|
||||
while (loyaltyCardCursor.moveToNext()) {
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(loyaltyCardCursor);
|
||||
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra("id", card.id);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), card.id, openIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
subscriber.onNext(
|
||||
new Control.StatelessBuilder(PREFIX + card.id, pendingIntent)
|
||||
.setControlId(PREFIX + card.id)
|
||||
.setTitle(card.store)
|
||||
.setDeviceType(DeviceTypes.TYPE_GENERIC_OPEN_CLOSE)
|
||||
.setSubtitle(card.note)
|
||||
.setCustomIcon(Icon.createWithBitmap(getIcon(this, card)))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
subscriber.onComplete();
|
||||
};
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Flow.Publisher<Control> createPublisherFor(@NonNull List<String> controlIds) {
|
||||
return subscriber -> {
|
||||
subscriber.onSubscribe(new NoOpSubscription());
|
||||
for (String controlId : controlIds) {
|
||||
Control control;
|
||||
|
||||
try {
|
||||
Integer cardId = this.controlIdToCardId(controlId);
|
||||
LoyaltyCard card = dbHelper.getLoyaltyCard(cardId);
|
||||
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra("id", card.id);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), card.id, openIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
control = new Control.StatefulBuilder(controlId, pendingIntent)
|
||||
.setTitle(card.store)
|
||||
.setDeviceType(DeviceTypes.TYPE_GENERIC_OPEN_CLOSE)
|
||||
.setSubtitle(card.note)
|
||||
.setStatus(Control.STATUS_OK)
|
||||
.setControlTemplate(new StatelessTemplate(controlId))
|
||||
.setCustomIcon(Icon.createWithBitmap(getIcon(this, card)))
|
||||
.build();
|
||||
} catch (NullPointerException ignored) {
|
||||
Intent mainScreenIntent = new Intent(this, MainActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), -1, mainScreenIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
control = new Control.StatefulBuilder(controlId, pendingIntent)
|
||||
.setStatus(Control.STATUS_NOT_FOUND)
|
||||
.build();
|
||||
}
|
||||
Log.d(TAG, "Dispatching widget " + controlId);
|
||||
subscriber.onNext(control);
|
||||
}
|
||||
subscriber.onComplete();
|
||||
};
|
||||
}
|
||||
|
||||
private Bitmap getIcon(Context context, LoyaltyCard loyaltyCard) {
|
||||
Bitmap cardIcon = Utils.retrieveCardImage(context, loyaltyCard.id, ImageLocationType.icon);
|
||||
|
||||
if (cardIcon != null) {
|
||||
return cardIcon;
|
||||
}
|
||||
|
||||
return Utils.generateIcon(this, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile();
|
||||
}
|
||||
|
||||
private Integer controlIdToCardId(String controlId) {
|
||||
if (controlId == null)
|
||||
return null;
|
||||
if (!controlId.startsWith(PREFIX)) {
|
||||
Log.w(TAG, "Unsupported control ID format: " + controlId);
|
||||
return null;
|
||||
}
|
||||
controlId = controlId.substring(PREFIX.length());
|
||||
try {
|
||||
return Integer.parseInt(controlId);
|
||||
} catch (RuntimeException ex) {
|
||||
Log.e(TAG, "Unsupported control ID format. Expected numeric after prefix, found: " + controlId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performControlAction(@NonNull String controlId, @NonNull ControlAction action, @NonNull Consumer<Integer> consumer) {
|
||||
consumer.accept(ControlAction.RESPONSE_OK);
|
||||
Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra("id", controlIdToCardId(controlId));
|
||||
startActivity(openIntent);
|
||||
|
||||
closePowerScreenOnAndroid11();
|
||||
}
|
||||
|
||||
@SuppressLint({"MissingPermission", "deprecation"})
|
||||
private void closePowerScreenOnAndroid11() {
|
||||
// Android 12 will auto-close the power screen, but earlier versions won't
|
||||
// Lint complains about this but on Android 11 the permission is not needed
|
||||
// On Android 12, we don't need it, and Google will probably get angry if we ask for it
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
||||
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A no-op subscription.
|
||||
* <p>
|
||||
* Flow.Subscriptions are made to last during time and receive periodic updates.
|
||||
* Our app does not require sending periodic updates of loyalty cards, so we are just ignoring anything in the subscription
|
||||
* Also, our db is quick enough to respond that the Publisher is immediately sending and completing data.
|
||||
* This facility is overkill, but if we don't call onSubscribe the service won't work
|
||||
*/
|
||||
private static class NoOpSubscription implements Flow.Subscription {
|
||||
@Override
|
||||
public void request(long l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,25 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.journeyapps.barcodescanner.CaptureManager;
|
||||
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
|
||||
|
||||
public class CatimaCaptureManager extends CaptureManager {
|
||||
private Activity activity;
|
||||
private final Context mContext;
|
||||
|
||||
public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
|
||||
super(activity, barcodeView);
|
||||
|
||||
this.activity = activity;
|
||||
mContext = activity.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayFrameworkBugMessageAndExit(String message) {
|
||||
// We don't want to exit, as we also have a enter from card image and add manually button here
|
||||
// So we show a toast instead
|
||||
Toast.makeText(activity, message, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,12 +71,8 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
Descending
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
|
||||
public DBHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -583,7 +579,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean deleteLoyaltyCard(final int id) {
|
||||
public boolean deleteLoyaltyCard(Context context, final int id) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
// Delete card
|
||||
int rowsDeleted = db.delete(LoyaltyCardDbIds.TABLE,
|
||||
@@ -603,7 +599,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
// Also wipe card images associated with this card
|
||||
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
|
||||
try {
|
||||
Utils.saveCardImage(mContext, null, id, imageLocationType);
|
||||
Utils.saveCardImage(context, null, id, imageLocationType);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -12,28 +12,21 @@ import androidx.appcompat.widget.AppCompatImageButton;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder> {
|
||||
public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder> {
|
||||
Settings mSettings;
|
||||
private Cursor mCursor;
|
||||
private final Context mContext;
|
||||
private final GroupCursorAdapter.GroupAdapterListener mListener;
|
||||
private final GroupAdapterListener mListener;
|
||||
DBHelper mDb;
|
||||
|
||||
public GroupCursorAdapter(Context inputContext, Cursor inputCursor, GroupCursorAdapter.GroupAdapterListener inputListener) {
|
||||
super(inputCursor);
|
||||
public GroupCursorAdapter(Context inputContext, Cursor inputCursor, GroupAdapterListener inputListener) {
|
||||
super(inputCursor, DBHelper.LoyaltyCardDbGroups.ORDER);
|
||||
setHasStableIds(true);
|
||||
mSettings = new Settings(inputContext);
|
||||
mContext = inputContext;
|
||||
mContext = inputContext.getApplicationContext();
|
||||
mListener = inputListener;
|
||||
mDb = new DBHelper(inputContext);
|
||||
|
||||
swapCursor(mCursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swapCursor(Cursor inputCursor) {
|
||||
super.swapCursor(inputCursor);
|
||||
mCursor = inputCursor;
|
||||
swapCursor(inputCursor);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -43,11 +36,7 @@ class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListI
|
||||
return new GroupListItemViewHolder(itemView);
|
||||
}
|
||||
|
||||
public Cursor getCursor() {
|
||||
return mCursor;
|
||||
}
|
||||
|
||||
public void onBindViewHolder(GroupCursorAdapter.GroupListItemViewHolder inputHolder, Cursor inputCursor) {
|
||||
public void onBindViewHolder(GroupListItemViewHolder inputHolder, Cursor inputCursor) {
|
||||
Group group = Group.toGroup(inputCursor);
|
||||
|
||||
inputHolder.mName.setText(group._id);
|
||||
|
||||
@@ -10,14 +10,20 @@ import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -26,11 +32,6 @@ import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
import protect.card_locker.importexport.DataFormat;
|
||||
import protect.card_locker.importexport.ImportExportResult;
|
||||
@@ -39,8 +40,6 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private static final int PERMISSIONS_EXTERNAL_STORAGE = 1;
|
||||
private static final int CHOOSE_EXPORT_LOCATION = 2;
|
||||
private static final int IMPORT = 3;
|
||||
|
||||
private ImportExportTask importExporter;
|
||||
|
||||
@@ -49,6 +48,10 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
private DataFormat importDataFormat;
|
||||
private String exportPassword;
|
||||
|
||||
private ActivityResultLauncher<Intent> fileCreateLauncher;
|
||||
private ActivityResultLauncher<String> fileOpenLauncher;
|
||||
private ActivityResultLauncher<Intent> filePickerLauncher;
|
||||
|
||||
final private TaskHandler mTasks = new TaskHandler();
|
||||
|
||||
@Override
|
||||
@@ -76,6 +79,49 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
PERMISSIONS_EXTERNAL_STORAGE);
|
||||
}
|
||||
|
||||
// would use ActivityResultContracts.CreateDocument() but mime type cannot be set
|
||||
fileCreateLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
Intent intent = result.getData();
|
||||
if (intent == null) {
|
||||
Log.e(TAG, "Activity returned NULL data");
|
||||
return;
|
||||
}
|
||||
Uri uri = intent.getData();
|
||||
if (uri == null) {
|
||||
Log.e(TAG, "Activity returned NULL uri");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
OutputStream writer = getContentResolver().openOutputStream(uri);
|
||||
Log.e(TAG, "Starting file export with: " + result.toString());
|
||||
startExport(writer, uri, exportPassword.toCharArray(), true);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to export file: " + result.toString(), e);
|
||||
onExportComplete(ImportExportResult.GenericFailure, uri);
|
||||
}
|
||||
|
||||
});
|
||||
fileOpenLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), result -> {
|
||||
if (result == null) {
|
||||
Log.e(TAG, "Activity returned NULL data");
|
||||
return;
|
||||
}
|
||||
openFileForImport(result, null);
|
||||
});
|
||||
filePickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
Intent intent = result.getData();
|
||||
if (intent == null) {
|
||||
Log.e(TAG, "Activity returned NULL data");
|
||||
return;
|
||||
}
|
||||
Uri uri = intent.getData();
|
||||
if (uri == null) {
|
||||
Log.e(TAG, "Activity returned NULL uri");
|
||||
return;
|
||||
}
|
||||
openFileForImport(intent.getData(), null);
|
||||
});
|
||||
|
||||
// Check that there is a file manager available
|
||||
final Intent intentCreateDocumentAction = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intentCreateDocumentAction.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
@@ -83,60 +129,57 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "catima.zip");
|
||||
|
||||
Button exportButton = findViewById(R.id.exportButton);
|
||||
exportButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
|
||||
builder.setTitle(R.string.exportPassword);
|
||||
exportButton.setOnClickListener(v -> {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
|
||||
builder.setTitle(R.string.exportPassword);
|
||||
|
||||
FrameLayout container = new FrameLayout(ImportExportActivity.this);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.leftMargin = 50;
|
||||
params.rightMargin = 50;
|
||||
FrameLayout container = new FrameLayout(ImportExportActivity.this);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.leftMargin = 50;
|
||||
params.rightMargin = 50;
|
||||
|
||||
final EditText input = new EditText(ImportExportActivity.this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
input.setLayoutParams(params);
|
||||
input.setHint(R.string.exportPasswordHint);
|
||||
final EditText input = new EditText(ImportExportActivity.this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
input.setLayoutParams(params);
|
||||
input.setHint(R.string.exportPasswordHint);
|
||||
|
||||
container.addView(input);
|
||||
builder.setView(container);
|
||||
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
exportPassword = input.getText().toString();
|
||||
chooseFileWithIntent(intentCreateDocumentAction, CHOOSE_EXPORT_LOCATION);
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
|
||||
builder.show();
|
||||
container.addView(input);
|
||||
builder.setView(container);
|
||||
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
exportPassword = input.getText().toString();
|
||||
try {
|
||||
fileCreateLauncher.launch(intentCreateDocumentAction);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
|
||||
builder.show();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Check that there is a file manager available
|
||||
final Intent intentGetContentAction = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intentGetContentAction.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intentGetContentAction.setType("*/*");
|
||||
|
||||
Button importFilesystem = findViewById(R.id.importOptionFilesystemButton);
|
||||
importFilesystem.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
chooseImportType(intentGetContentAction);
|
||||
}
|
||||
});
|
||||
importFilesystem.setOnClickListener(v -> chooseImportType(false));
|
||||
|
||||
// Check that there is an app that data can be imported from
|
||||
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
|
||||
|
||||
Button importApplication = findViewById(R.id.importOptionApplicationButton);
|
||||
importApplication.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
chooseImportType(intentPickAction);
|
||||
}
|
||||
});
|
||||
importApplication.setOnClickListener(v -> chooseImportType(true));
|
||||
}
|
||||
|
||||
private void chooseImportType(Intent baseIntent) {
|
||||
private void openFileForImport(Uri uri, char[] password) {
|
||||
try {
|
||||
InputStream reader = getContentResolver().openInputStream(uri);
|
||||
Log.e(TAG, "Starting file import with: " + uri.toString());
|
||||
startImport(reader, uri, importDataFormat, password, true);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to import file: " + uri.toString(), e);
|
||||
onImportComplete(ImportExportResult.GenericFailure, uri, importDataFormat);
|
||||
}
|
||||
}
|
||||
|
||||
private void chooseImportType(boolean choosePicker) {
|
||||
List<CharSequence> betaImportOptions = new ArrayList<>();
|
||||
betaImportOptions.add("Fidme");
|
||||
betaImportOptions.add("Stocard");
|
||||
@@ -194,7 +237,17 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
chooseFileWithIntent(baseIntent, IMPORT);
|
||||
try {
|
||||
if (choosePicker) {
|
||||
final Intent intentPickAction = new Intent(Intent.ACTION_PICK);
|
||||
filePickerLauncher.launch(intentPickAction);
|
||||
} else {
|
||||
fileOpenLauncher.launch("*/*");
|
||||
}
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
@@ -297,7 +350,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
activityResultParser(IMPORT, RESULT_OK, uri, input.getText().toString().toCharArray());
|
||||
openFileForImport(uri, input.getText().toString().toCharArray());
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel());
|
||||
|
||||
@@ -373,69 +426,4 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
private void chooseFileWithIntent(Intent intent, int requestCode) {
|
||||
try {
|
||||
startActivityForResult(intent, requestCode);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedOpeningFileManager, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void activityResultParser(int requestCode, int resultCode, Uri uri, char[] password) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
Log.w(TAG, "Failed onActivityResult(), result=" + resultCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uri == null) {
|
||||
Log.e(TAG, "Activity returned a NULL URI");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (requestCode == CHOOSE_EXPORT_LOCATION) {
|
||||
|
||||
OutputStream writer;
|
||||
if (uri.getScheme() != null) {
|
||||
writer = getContentResolver().openOutputStream(uri);
|
||||
} else {
|
||||
writer = new FileOutputStream(new File(uri.toString()));
|
||||
}
|
||||
Log.e(TAG, "Starting file export with: " + uri.toString());
|
||||
startExport(writer, uri, exportPassword.toCharArray(), true);
|
||||
} else {
|
||||
InputStream reader;
|
||||
if (uri.getScheme() != null) {
|
||||
reader = getContentResolver().openInputStream(uri);
|
||||
} else {
|
||||
reader = new FileInputStream(new File(uri.toString()));
|
||||
}
|
||||
|
||||
Log.e(TAG, "Starting file import with: " + uri.toString());
|
||||
|
||||
startImport(reader, uri, importDataFormat, password, true);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to import/export file: " + uri.toString(), e);
|
||||
if (requestCode == CHOOSE_EXPORT_LOCATION) {
|
||||
onExportComplete(ImportExportResult.GenericFailure, uri);
|
||||
} else {
|
||||
onImportComplete(ImportExportResult.GenericFailure, uri, importDataFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (data == null) {
|
||||
Log.e(TAG, "Activity returned NULL data");
|
||||
return;
|
||||
}
|
||||
|
||||
activityResultParser(requestCode, resultCode, data.getData(), null);
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public class ImportURIHelper {
|
||||
private final String shareMultipleText;
|
||||
|
||||
public ImportURIHelper(Context context) {
|
||||
this.context = context;
|
||||
this.context = context.getApplicationContext();
|
||||
hosts[0] = context.getResources().getString(R.string.intent_import_card_from_url_host_catima_app);
|
||||
paths[0] = context.getResources().getString(R.string.intent_import_card_from_url_path_prefix_catima_app);
|
||||
hosts[1] = context.getResources().getString(R.string.intent_import_card_from_url_host_thelastproject);
|
||||
@@ -197,6 +197,7 @@ public class ImportURIHelper {
|
||||
sendIntent.setType("text/plain");
|
||||
|
||||
Intent shareIntent = Intent.createChooser(sendIntent, null);
|
||||
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(shareIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.animation.AnimatorInflater;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
public class LoyaltyCardAnimator {
|
||||
|
||||
private static AnimatorSet selectedViewIn, defaultViewOut, selectedViewOut, defaultViewIn;
|
||||
|
||||
public static void flipView(Context inputContext, final View inputSelectedView, final View inputDefaultView, boolean inputItemSelected) {
|
||||
|
||||
selectedViewIn = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_left_in);
|
||||
defaultViewOut = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_right_out);
|
||||
selectedViewOut = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_left_out);
|
||||
defaultViewIn = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_right_in);
|
||||
|
||||
final AnimatorSet showFrontAnim = new AnimatorSet();
|
||||
final AnimatorSet showBackAnim = new AnimatorSet();
|
||||
|
||||
selectedViewIn.setTarget(inputSelectedView);
|
||||
defaultViewOut.setTarget(inputDefaultView);
|
||||
showFrontAnim.playTogether(selectedViewIn, defaultViewOut);
|
||||
|
||||
selectedViewOut.setTarget(inputSelectedView);
|
||||
defaultViewIn.setTarget(inputDefaultView);
|
||||
showBackAnim.playTogether(defaultViewIn, selectedViewOut);
|
||||
|
||||
if (inputItemSelected) {
|
||||
showFrontAnim.start();
|
||||
} else {
|
||||
showBackAnim.start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import protect.card_locker.preferences.Settings;
|
||||
|
||||
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder> {
|
||||
private int mCurrentSelectedIndex = -1;
|
||||
private Cursor mCursor;
|
||||
Settings mSettings;
|
||||
boolean mDarkModeEnabled;
|
||||
private final Context mContext;
|
||||
@@ -41,23 +40,17 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
private boolean mShowDetails = true;
|
||||
|
||||
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, CardAdapterListener inputListener) {
|
||||
super(inputCursor);
|
||||
super(inputCursor, DBHelper.LoyaltyCardDbIds.ID);
|
||||
setHasStableIds(true);
|
||||
mSettings = new Settings(inputContext);
|
||||
mContext = inputContext;
|
||||
mContext = inputContext.getApplicationContext();
|
||||
mListener = inputListener;
|
||||
mSelectedItems = new SparseBooleanArray();
|
||||
mAnimationItemsIndex = new SparseBooleanArray();
|
||||
|
||||
mDarkModeEnabled = Utils.isDarkModeEnabled(inputContext);
|
||||
|
||||
swapCursor(mCursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swapCursor(Cursor inputCursor) {
|
||||
super.swapCursor(inputCursor);
|
||||
mCursor = inputCursor;
|
||||
swapCursor(inputCursor);
|
||||
}
|
||||
|
||||
public void showDetails(boolean show) {
|
||||
@@ -75,8 +68,9 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
return new LoyaltyCardListItemViewHolder(itemView, mListener);
|
||||
}
|
||||
|
||||
public Cursor getCursor() {
|
||||
return mCursor;
|
||||
public LoyaltyCard getCard(int position) {
|
||||
mCursor.moveToPosition(position);
|
||||
return LoyaltyCard.toLoyaltyCard(mCursor);
|
||||
}
|
||||
|
||||
public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor inputCursor) {
|
||||
@@ -169,35 +163,19 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
private void applyIconAnimation(LoyaltyCardListItemViewHolder inputHolder, int inputPosition) {
|
||||
if (mSelectedItems.get(inputPosition, false)) {
|
||||
inputHolder.mCardIcon.setVisibility(View.GONE);
|
||||
resetIconYAxis(inputHolder.mTickIcon);
|
||||
inputHolder.mTickIcon.setVisibility(View.VISIBLE);
|
||||
if (mCurrentSelectedIndex == inputPosition) {
|
||||
LoyaltyCardAnimator.flipView(mContext, inputHolder.mTickIcon, inputHolder.mCardIcon, true);
|
||||
resetCurrentIndex();
|
||||
}
|
||||
} else {
|
||||
inputHolder.mTickIcon.setVisibility(View.GONE);
|
||||
resetIconYAxis(inputHolder.mCardIcon);
|
||||
inputHolder.mCardIcon.setVisibility(View.VISIBLE);
|
||||
if ((mReverseAllAnimations && mAnimationItemsIndex.get(inputPosition, false)) || mCurrentSelectedIndex == inputPosition) {
|
||||
LoyaltyCardAnimator.flipView(mContext, inputHolder.mTickIcon, inputHolder.mCardIcon, false);
|
||||
resetCurrentIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetIconYAxis(View inputView) {
|
||||
if (inputView.getRotationY() != 0) {
|
||||
inputView.setRotationY(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void resetAnimationIndex() {
|
||||
mReverseAllAnimations = false;
|
||||
mAnimationItemsIndex.clear();
|
||||
}
|
||||
|
||||
|
||||
public void toggleSelection(int inputPosition) {
|
||||
mCurrentSelectedIndex = inputPosition;
|
||||
if (mSelectedItems.get(inputPosition, false)) {
|
||||
|
||||
@@ -679,10 +679,10 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
private void setCropperTheme() {
|
||||
mCropperOptions.setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary));
|
||||
mCropperOptions.setStatusBarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark));
|
||||
mCropperOptions.setToolbarColor(getThemeColor());
|
||||
mCropperOptions.setStatusBarColor(getThemeColor());
|
||||
mCropperOptions.setToolbarWidgetColor(Color.WHITE);
|
||||
mCropperOptions.setActiveControlsWidgetColor(ContextCompat.getColor(this, R.color.colorPrimary));
|
||||
mCropperOptions.setActiveControlsWidgetColor(getThemeColor());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1313,7 +1313,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
Log.e(TAG, "Deleting card: " + loyaltyCardId);
|
||||
|
||||
DBHelper db = new DBHelper(LoyaltyCardEditActivity.this);
|
||||
db.deleteLoyaltyCard(loyaltyCardId);
|
||||
db.deleteLoyaltyCard(LoyaltyCardEditActivity.this, loyaltyCardId);
|
||||
|
||||
ShortcutHelper.removeShortcut(LoyaltyCardEditActivity.this, loyaltyCardId);
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.constraintlayout.widget.Guideline;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
import androidx.core.widget.NestedScrollView;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
@@ -583,8 +584,11 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
// Make notification area light if dark icons are needed
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
window.getDecorView().setSystemUiVisibility(backgroundNeedsDarkIcons ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0);
|
||||
window.setStatusBarColor(Color.TRANSPARENT);
|
||||
} else {
|
||||
// Darken statusbar if icons won't be visible otherwise
|
||||
window.setStatusBarColor(backgroundNeedsDarkIcons ? ColorUtils.blendARGB(backgroundHeaderColor, Color.BLACK, 0.15f) : Color.TRANSPARENT);
|
||||
}
|
||||
window.setStatusBarColor(Color.TRANSPARENT);
|
||||
|
||||
// Set shadow colour of store text so even same color on same color would be readable
|
||||
storeName.setShadowLayer(1, 1, 1, backgroundNeedsDarkIcons ? Color.BLACK : Color.WHITE);
|
||||
|
||||
@@ -26,12 +26,15 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.view.ActionMode;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.splashscreen.SplashScreen;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import protect.card_locker.preferences.SettingsActivity;
|
||||
|
||||
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener {
|
||||
@@ -40,7 +43,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
private final DBHelper mDB = new DBHelper(this);
|
||||
private LoyaltyCardCursorAdapter mAdapter;
|
||||
private ActionMode mCurrentActionMode;
|
||||
private Menu mMenu;
|
||||
private SearchView mSearchView;
|
||||
private GestureDetector mGestureDetector;
|
||||
protected String mFilter = "";
|
||||
protected Object mGroup = null;
|
||||
@@ -52,6 +55,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
private View mNoMatchingCardsText;
|
||||
private View mNoGroupCardsText;
|
||||
|
||||
private ActivityResultLauncher<Intent> mBarcodeScannerLauncher;
|
||||
|
||||
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback() {
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode inputMode, Menu inputMenu) {
|
||||
@@ -137,7 +142,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
|
||||
Log.e(TAG, "Deleting card: " + loyaltyCard.id);
|
||||
|
||||
db.deleteLoyaltyCard(loyaltyCard.id);
|
||||
db.deleteLoyaltyCard(MainActivity.this, loyaltyCard.id);
|
||||
|
||||
ShortcutHelper.removeShortcut(MainActivity.this, loyaltyCard.id);
|
||||
}
|
||||
@@ -163,12 +168,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
public void onDestroyActionMode(ActionMode inputMode) {
|
||||
mAdapter.clearSelections();
|
||||
mCurrentActionMode = null;
|
||||
mCardList.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAdapter.resetAnimationIndex();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -260,6 +259,24 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
.show();
|
||||
}
|
||||
*/
|
||||
|
||||
mBarcodeScannerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
Intent intent = result.getData();
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(Utils.BARCODE_SCAN, result.getResultCode(), intent, this);
|
||||
|
||||
if (!barcodeValues.isEmpty()) {
|
||||
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
|
||||
Bundle newBundle = new Bundle();
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_BARCODETYPE, barcodeValues.format());
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, barcodeValues.content());
|
||||
Bundle inputBundle = intent.getExtras();
|
||||
if (inputBundle != null && inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) != null) {
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP));
|
||||
}
|
||||
newIntent.putExtras(newBundle);
|
||||
startActivity(newIntent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -271,12 +288,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
mCurrentActionMode.finish();
|
||||
}
|
||||
|
||||
if (mMenu != null) {
|
||||
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
|
||||
|
||||
if (!searchView.isIconified()) {
|
||||
mFilter = searchView.getQuery().toString();
|
||||
}
|
||||
if (mSearchView != null && !mSearchView.isIconified()) {
|
||||
mFilter = mSearchView.getQuery().toString();
|
||||
}
|
||||
|
||||
// Start of active tab logic
|
||||
@@ -320,53 +333,16 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
bundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, groupsTabLayout.getTabAt(selectedTab).getText().toString());
|
||||
}
|
||||
intent.putExtras(bundle);
|
||||
startActivityForResult(intent, Utils.BARCODE_SCAN);
|
||||
mBarcodeScannerLauncher.launch(intent);
|
||||
});
|
||||
addButton.bringToFront();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
if (requestCode == Utils.MAIN_REQUEST) {
|
||||
// We're coming back from another view so clear the search
|
||||
// We only do this now to prevent a flash of all entries right after picking one
|
||||
mFilter = "";
|
||||
if (mMenu != null) {
|
||||
MenuItem searchItem = mMenu.findItem(R.id.action_search);
|
||||
searchItem.collapseActionView();
|
||||
}
|
||||
updateLoyaltyCardList();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
|
||||
|
||||
if (!barcodeValues.isEmpty()) {
|
||||
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
|
||||
Bundle newBundle = new Bundle();
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_BARCODETYPE, barcodeValues.format());
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, barcodeValues.content());
|
||||
Bundle inputBundle = intent.getExtras();
|
||||
if (inputBundle != null && inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) != null) {
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP));
|
||||
}
|
||||
newIntent.putExtras(newBundle);
|
||||
startActivity(newIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mMenu != null) {
|
||||
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
|
||||
|
||||
if (!searchView.isIconified()) {
|
||||
searchView.setIconified(true);
|
||||
return;
|
||||
}
|
||||
if (!mSearchView.isIconified()) {
|
||||
mSearchView.setIconified(true);
|
||||
return;
|
||||
}
|
||||
|
||||
super.onBackPressed();
|
||||
@@ -443,22 +419,20 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu inputMenu) {
|
||||
this.mMenu = inputMenu;
|
||||
|
||||
getMenuInflater().inflate(R.menu.main_menu, inputMenu);
|
||||
|
||||
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
|
||||
if (searchManager != null) {
|
||||
SearchView searchView = (SearchView) inputMenu.findItem(R.id.action_search).getActionView();
|
||||
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
|
||||
searchView.setSubmitButtonEnabled(false);
|
||||
mSearchView = (SearchView) inputMenu.findItem(R.id.action_search).getActionView();
|
||||
mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
|
||||
mSearchView.setSubmitButtonEnabled(false);
|
||||
|
||||
searchView.setOnCloseListener(() -> {
|
||||
mSearchView.setOnCloseListener(() -> {
|
||||
invalidateOptionsMenu();
|
||||
return false;
|
||||
});
|
||||
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
return false;
|
||||
@@ -542,25 +516,25 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
if (id == R.id.action_manage_groups) {
|
||||
Intent i = new Intent(getApplicationContext(), ManageGroupsActivity.class);
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_import_export) {
|
||||
Intent i = new Intent(getApplicationContext(), ImportExportActivity.class);
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_settings) {
|
||||
Intent i = new Intent(getApplicationContext(), SettingsActivity.class);
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_about) {
|
||||
Intent i = new Intent(getApplicationContext(), AboutActivity.class);
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -702,8 +676,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
if (mAdapter.getSelectedItemCount() > 0) {
|
||||
enableActionMode(inputPosition);
|
||||
} else {
|
||||
Cursor selected = mAdapter.getCursor();
|
||||
selected.moveToPosition(inputPosition);
|
||||
// FIXME
|
||||
//
|
||||
// There is a really nasty edge case that can happen when someone taps a card but right
|
||||
@@ -714,7 +686,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
// click is being processed. Sadly, I have not yet found a way to make that possible.
|
||||
LoyaltyCard loyaltyCard;
|
||||
try {
|
||||
loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
|
||||
loyaltyCard = mAdapter.getCard(inputPosition);
|
||||
} catch (CursorIndexOutOfBoundsException e) {
|
||||
Log.w(TAG, "Prevented crash from tap + swipe on ID " + inputPosition + ": " + e);
|
||||
return;
|
||||
@@ -728,7 +700,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard);
|
||||
|
||||
startActivityForResult(i, Utils.MAIN_REQUEST);
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
|
||||
private void updateLoyaltyCardList() {
|
||||
mAdapter.swapCursor(mDB.getLoyaltyCardCursor());
|
||||
|
||||
if (mAdapter.getCountFromCursor() == 0) {
|
||||
if (mAdapter.getItemCount() == 0) {
|
||||
mCardList.setVisibility(View.GONE);
|
||||
mHelpText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
|
||||
@@ -105,8 +105,4 @@ public class ManageGroupCursorAdapter extends LoyaltyCardCursorAdapter {
|
||||
public HashMap<Integer, Boolean> exportInGroupState() {
|
||||
return new HashMap<>(mInGroupOverlay);
|
||||
}
|
||||
|
||||
public int getCountFromCursor() {
|
||||
return super.getCursor().getCount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.journeyapps.barcodescanner.DecoratedBarcodeView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
@@ -39,6 +41,10 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
private String addGroup;
|
||||
private boolean torch = false;
|
||||
|
||||
private ActivityResultLauncher<Intent> manualAddLauncher;
|
||||
// can't use the pre-made contract because that launches the file manager for image type instead of gallery
|
||||
private ActivityResultLauncher<Intent> photoPickerLauncher;
|
||||
|
||||
private void extractIntentFields(Intent intent) {
|
||||
final Bundle b = intent.getExtras();
|
||||
cardId = b != null ? b.getString(LoyaltyCardEditActivity.BUNDLE_CARDID) : null;
|
||||
@@ -60,6 +66,8 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
|
||||
extractIntentFields(getIntent());
|
||||
|
||||
manualAddLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.SELECT_BARCODE_REQUEST, result.getResultCode(), result.getData()));
|
||||
photoPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_IMAGE_FILE, result.getResultCode(), result.getData()));
|
||||
findViewById(R.id.add_from_image).setOnClickListener(this::addFromImage);
|
||||
findViewById(R.id.add_manually).setOnClickListener(this::addManually);
|
||||
|
||||
@@ -159,8 +167,7 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
private void handleActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
BarcodeValues barcodeValues;
|
||||
@@ -193,12 +200,12 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
b.putString("initialCardId", cardId);
|
||||
i.putExtras(b);
|
||||
}
|
||||
startActivityForResult(i, Utils.SELECT_BARCODE_REQUEST);
|
||||
manualAddLauncher.launch(i);
|
||||
}
|
||||
|
||||
public void addFromImage(View view) {
|
||||
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
|
||||
photoPickerIntent.setType("image/*");
|
||||
startActivityForResult(photoPickerIntent, Utils.BARCODE_IMPORT_FROM_IMAGE_FILE);
|
||||
photoPickerLauncher.launch(photoPickerIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class Utils {
|
||||
tileLetterFontSize = context.getResources().getDimensionPixelSize(R.dimen.tileLetterFontSize);
|
||||
}
|
||||
|
||||
int pixelSize = context.getResources().getDimensionPixelSize(R.dimen.cardThumbnailSize);
|
||||
int pixelSize = context.getResources().getDimensionPixelSize(R.dimen.tileLetterImageSize);
|
||||
|
||||
if (backgroundColor == null) {
|
||||
backgroundColor = LetterBitmap.getDefaultColor(context, store);
|
||||
|
||||
@@ -13,32 +13,32 @@ import protect.card_locker.R;
|
||||
import protect.card_locker.Utils;
|
||||
|
||||
public class Settings {
|
||||
private Context context;
|
||||
private SharedPreferences settings;
|
||||
private final Context mContext;
|
||||
private SharedPreferences mSettings;
|
||||
|
||||
public Settings(Context context) {
|
||||
this.context = context;
|
||||
this.settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
mContext = context.getApplicationContext();
|
||||
mSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
}
|
||||
|
||||
private String getResString(@StringRes int resId) {
|
||||
return context.getString(resId);
|
||||
return mContext.getString(resId);
|
||||
}
|
||||
|
||||
private int getResInt(@IntegerRes int resId) {
|
||||
return context.getResources().getInteger(resId);
|
||||
return mContext.getResources().getInteger(resId);
|
||||
}
|
||||
|
||||
private String getString(@StringRes int keyId, String defaultValue) {
|
||||
return settings.getString(getResString(keyId), defaultValue);
|
||||
return mSettings.getString(getResString(keyId), defaultValue);
|
||||
}
|
||||
|
||||
private int getInt(@StringRes int keyId, @IntegerRes int defaultId) {
|
||||
return settings.getInt(getResString(keyId), getResInt(defaultId));
|
||||
return mSettings.getInt(getResString(keyId), getResInt(defaultId));
|
||||
}
|
||||
|
||||
private boolean getBoolean(@StringRes int keyId, boolean defaultValue) {
|
||||
return settings.getBoolean(getResString(keyId), defaultValue);
|
||||
return mSettings.getBoolean(getResString(keyId), defaultValue);
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="0"
|
||||
android:propertyName="alpha"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.0" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="@integer/full_rotation_duration"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:propertyName="rotationY"
|
||||
android:valueFrom="-180"
|
||||
android:valueTo="0" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="1"
|
||||
android:propertyName="alpha"
|
||||
android:startOffset="@integer/half_rotation_duration"
|
||||
android:valueFrom="0.0"
|
||||
android:valueTo="1.0" />
|
||||
</set>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="@integer/full_rotation_duration"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:propertyName="rotationY"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="180" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="1"
|
||||
android:propertyName="alpha"
|
||||
android:startOffset="@integer/half_rotation_duration"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.0" />
|
||||
</set>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="0"
|
||||
android:propertyName="alpha"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.0" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="@integer/full_rotation_duration"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:propertyName="rotationY"
|
||||
android:valueFrom="180"
|
||||
android:valueTo="0" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="1"
|
||||
android:propertyName="alpha"
|
||||
android:startOffset="@integer/half_rotation_duration"
|
||||
android:valueFrom="0.0"
|
||||
android:valueTo="1.0" />
|
||||
</set>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="@integer/full_rotation_duration"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:propertyName="rotationY"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="-180" />
|
||||
|
||||
<objectAnimator
|
||||
android:duration="1"
|
||||
android:propertyName="alpha"
|
||||
android:startOffset="@integer/half_rotation_duration"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.0" />
|
||||
</set>
|
||||
@@ -16,7 +16,7 @@
|
||||
android:id="@+id/icon_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintDimensionRatio="2:1"
|
||||
app:layout_constraintDimensionRatio="85.6f:53.98f"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/store">
|
||||
|
||||
@@ -3,33 +3,34 @@ Branden Archer
|
||||
J. Lavoie
|
||||
Allan Nordhøy
|
||||
Heimen Stoffels
|
||||
mondstern
|
||||
solokot
|
||||
mondstern
|
||||
Katharine Chui
|
||||
Oğuz Ersen
|
||||
IllusiveMan196
|
||||
Petr Novák
|
||||
Taco
|
||||
Gediminas Murauskas
|
||||
StoyanDimitrov
|
||||
Joel A
|
||||
StoyanDimitrov
|
||||
Nyatsuki
|
||||
Samantaz Fox
|
||||
arno-github
|
||||
Ankit Tiwari
|
||||
Sergio Paredes
|
||||
laralem
|
||||
arshbeerSingh
|
||||
huuhaa
|
||||
Miha Frangež
|
||||
Michael Moroni
|
||||
Olivia (Zoe)
|
||||
laralem
|
||||
betsythefc
|
||||
waffshappen
|
||||
K. Herbert
|
||||
Quentin PAGÈS
|
||||
String E. Fighter
|
||||
Yurical
|
||||
/usr/local/ΕΨΗΕΛΩΝ
|
||||
Adolfo Jayme-Barrientos
|
||||
Alessandro Mandelli
|
||||
KovalevArtem
|
||||
@@ -56,7 +57,7 @@ Kasina Dheeraj
|
||||
Flav
|
||||
Franciszek Stefan
|
||||
Izzy
|
||||
krkk
|
||||
Karol Kosek
|
||||
bittin
|
||||
Maciej Błędkowski
|
||||
Mattia
|
||||
|
||||
@@ -217,4 +217,7 @@
|
||||
<string name="selectColor">Избиране на цвят</string>
|
||||
<string name="group_name_is_empty">Името на списъка не може да е празно</string>
|
||||
<string name="group_edit">Редактиране на списък</string>
|
||||
<string name="action_show_details">Повече детайли</string>
|
||||
<string name="action_hide_details">По-малко детайли</string>
|
||||
<string name="noGiftCardsGroup">Няма карти. След като добавите ще можете да ги зачислите към списък от тук.</string>
|
||||
</resources>
|
||||
@@ -218,4 +218,6 @@
|
||||
<string name="noGiftCardsGroup">Sie haben noch keine Kundenkarten. Sobald Sie welche hinzugefügt haben, können Sie sie hier der Gruppe zuordnen.</string>
|
||||
<string name="setIcon">Symbol einstellen</string>
|
||||
<string name="selectColor">Farbe auswählen</string>
|
||||
<string name="action_show_details">Details anzeigen</string>
|
||||
<string name="action_hide_details">Details ausblenden</string>
|
||||
</resources>
|
||||
@@ -218,4 +218,6 @@
|
||||
<string name="group_name_is_empty">Le nom du groupe ne peut pas être vide</string>
|
||||
<string name="setIcon">Définir l\'icône</string>
|
||||
<string name="selectColor">Sélectionnez la couleur</string>
|
||||
<string name="action_show_details">Afficher les détails</string>
|
||||
<string name="action_hide_details">Masquer les détails</string>
|
||||
</resources>
|
||||
@@ -218,4 +218,6 @@
|
||||
<string name="group_updated">Gruppo aggiornato</string>
|
||||
<string name="selectColor">Seleziona il colore</string>
|
||||
<string name="setIcon">Imposta l\'icona</string>
|
||||
<string name="action_show_details">Mostra i dettagli</string>
|
||||
<string name="action_hide_details">Nascondi i dettagli</string>
|
||||
</resources>
|
||||
@@ -196,7 +196,7 @@
|
||||
<string name="rate_this_app">このアプリを評価する</string>
|
||||
<string name="on_github">GitHub</string>
|
||||
<string name="source_repository">ソースリポジトリ</string>
|
||||
<string name="exportPassword">パスワードを設定してエクスポートしたファイルを保護する(任意)</string>
|
||||
<string name="exportPassword">パスワードを設定する(不要なら空欄)</string>
|
||||
<string name="exportPasswordHint">パスワードを入力してください</string>
|
||||
<string name="version_history">更新履歴</string>
|
||||
<string name="credits">貢献者</string>
|
||||
@@ -206,4 +206,13 @@
|
||||
<string name="report_error">エラーを報告する</string>
|
||||
<string name="reverse">逆順</string>
|
||||
<string name="and_data_usage">and data usage</string>
|
||||
<string name="group_updated">グループを更新しました</string>
|
||||
<string name="editGroup">グループ編集: <xliff:g>%s</xliff:g></string>
|
||||
<string name="action_show_details">詳細を表示</string>
|
||||
<string name="action_hide_details">詳細を非表示</string>
|
||||
<string name="selectColor">色を選択</string>
|
||||
<string name="setIcon">アイコン設定</string>
|
||||
<string name="group_edit">グループ編集</string>
|
||||
<string name="group_name_already_in_use">このグループ名は既に使用されています</string>
|
||||
<string name="group_name_is_empty">グループ名を入力してください</string>
|
||||
</resources>
|
||||
@@ -222,4 +222,6 @@
|
||||
<string name="noGiftCardsGroup">Dar neturite jokių lojalumo kortelių. Kai kelias pridėsite, galėsite jas priskirti grupei čia.</string>
|
||||
<string name="setIcon">Nustatyti piktogramą</string>
|
||||
<string name="selectColor">Pasirinkti spalvą</string>
|
||||
<string name="action_hide_details">Paslėpti informaciją</string>
|
||||
<string name="action_show_details">Rodyti išsamią informaciją</string>
|
||||
</resources>
|
||||
@@ -216,4 +216,8 @@
|
||||
<string name="group_name_is_empty">Gruppenavn kan ikke være tomt</string>
|
||||
<string name="editGroup">Redigerer gruppe: <xliff:g>%s</xliff:g></string>
|
||||
<string name="noGiftCardsGroup">Du har ingen lojalitetskort enda. Når du først har det kan du legge dem til i en gruppe her.</string>
|
||||
<string name="action_show_details">Vis detaljer</string>
|
||||
<string name="action_hide_details">Skjul detaljer</string>
|
||||
<string name="selectColor">Velg farge</string>
|
||||
<string name="setIcon">Sett ikon</string>
|
||||
</resources>
|
||||
@@ -218,4 +218,6 @@
|
||||
<string name="group_edit">Groep bewerken</string>
|
||||
<string name="setIcon">Kies een pictogram</string>
|
||||
<string name="selectColor">Kies een kleur</string>
|
||||
<string name="action_show_details">Details tonen</string>
|
||||
<string name="action_hide_details">Details verbergen</string>
|
||||
</resources>
|
||||
@@ -218,4 +218,6 @@
|
||||
<string name="noGiftCardsGroup">Ainda não tem nenhum cartão de fidelidade. Assim que tenha adicionado alguns, pode atribuí-los ao grupo aqui.</string>
|
||||
<string name="selectColor">Selecionar cor</string>
|
||||
<string name="setIcon">Definir ícone</string>
|
||||
<string name="action_show_details">Mostrar detalhes</string>
|
||||
<string name="action_hide_details">Ocultar detalhes</string>
|
||||
</resources>
|
||||
@@ -226,4 +226,6 @@
|
||||
<string name="noGiftCardsGroup">У вас ещё нет ни одной карты. Как только появится несколько карт, вы сможете добавить их в группу здесь.</string>
|
||||
<string name="setIcon">Выбор значка</string>
|
||||
<string name="selectColor">Выбрать цвет</string>
|
||||
<string name="action_hide_details">Скрыть детали</string>
|
||||
<string name="action_show_details">Показать детали</string>
|
||||
</resources>
|
||||
@@ -215,4 +215,9 @@
|
||||
<string name="editGroup">Redigerar grupp: <xliff:g>%s</xliff:g></string>
|
||||
<string name="selectColor">Välj färg</string>
|
||||
<string name="setIcon">Välj ikon</string>
|
||||
<string name="action_show_details">Visa detaljer</string>
|
||||
<string name="action_hide_details">Dölj detaljer</string>
|
||||
<string name="credits">Bidragsgivare</string>
|
||||
<string name="source_repository">Källkodslager</string>
|
||||
<string name="noGiftCardsGroup">Du har inga kundkort än. När du senare lägger till några kan du placera dem i den här gruppen.</string>
|
||||
</resources>
|
||||
@@ -226,4 +226,6 @@
|
||||
<string name="noGiftCardsGroup">У вас ще немає жодної картки. Коли ви додасте кілька, то зможете призначити їх до групи.</string>
|
||||
<string name="selectColor">Вибір кольору</string>
|
||||
<string name="setIcon">Вибір іконки</string>
|
||||
<string name="action_show_details">Показати деталі</string>
|
||||
<string name="action_hide_details">Сховати деталі</string>
|
||||
</resources>
|
||||
@@ -33,7 +33,8 @@
|
||||
<dimen name="activity_margin">16dp</dimen>
|
||||
|
||||
<!-- The default letter tile text size -->
|
||||
<dimen name="tileLetterFontSize">33sp</dimen>
|
||||
<dimen name="tileLetterFontSizeForShortcut">24dp</dimen>
|
||||
<dimen name="tileLetterFontSize">66sp</dimen>
|
||||
<dimen name="tileLetterFontSizeForShortcut">48dp</dimen>
|
||||
<dimen name="tileLetterImageSize">92dp</dimen>
|
||||
<dimen name="cardViewLetterFontSize">100sp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -29,25 +29,26 @@ import static org.junit.Assert.assertTrue;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 23)
|
||||
public class DatabaseTest {
|
||||
private DBHelper db;
|
||||
private DBHelper mDb;
|
||||
private Activity mActivity;
|
||||
|
||||
private static final Integer DEFAULT_HEADER_COLOR = Color.BLACK;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Activity activity = Robolectric.setupActivity(MainActivity.class);
|
||||
db = TestHelpers.getEmptyDb(activity);
|
||||
mActivity = Robolectric.setupActivity(MainActivity.class);
|
||||
mDb = TestHelpers.getEmptyDb(mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addRemoveOneGiftCard() {
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("store", loyaltyCard.store);
|
||||
assertEquals("note", loyaltyCard.note);
|
||||
@@ -60,24 +61,24 @@ public class DatabaseTest {
|
||||
assertEquals(DEFAULT_HEADER_COLOR, loyaltyCard.headerColor);
|
||||
assertEquals(0, loyaltyCard.starStatus);
|
||||
|
||||
result = db.deleteLoyaltyCard(1);
|
||||
result = mDb.deleteLoyaltyCard(mActivity, 1);
|
||||
assertTrue(result);
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
assertNull(db.getLoyaltyCard(1));
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
assertNull(mDb.getLoyaltyCard(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGiftCard() {
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
result = db.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("10.00"), Currency.getInstance("EUR"), "cardId1", null, CatimaBarcode.fromBarcode(BarcodeFormat.AZTEC), DEFAULT_HEADER_COLOR);
|
||||
result = mDb.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("10.00"), Currency.getInstance("EUR"), "cardId1", null, CatimaBarcode.fromBarcode(BarcodeFormat.AZTEC), DEFAULT_HEADER_COLOR);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("store1", loyaltyCard.store);
|
||||
assertEquals("note1", loyaltyCard.note);
|
||||
@@ -93,16 +94,16 @@ public class DatabaseTest {
|
||||
|
||||
@Test
|
||||
public void updateGiftCardOnlyStar() {
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
result = db.updateLoyaltyCardStarStatus(1, 1);
|
||||
result = mDb.updateLoyaltyCardStarStatus(1, 1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("store", loyaltyCard.store);
|
||||
assertEquals("note", loyaltyCard.note);
|
||||
@@ -118,22 +119,22 @@ public class DatabaseTest {
|
||||
|
||||
@Test
|
||||
public void updateMissingGiftCard() {
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
|
||||
boolean result = db.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("0"), null, "cardId1",
|
||||
boolean result = mDb.updateLoyaltyCard(1, "store1", "note1", null, new BigDecimal("0"), null, "cardId1",
|
||||
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR);
|
||||
assertEquals(false, result);
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyGiftCardValues() {
|
||||
long id = db.insertLoyaltyCard("", "", null, new BigDecimal("0"), null, "", null, null, null, 0, null);
|
||||
long id = mDb.insertLoyaltyCard("", "", null, new BigDecimal("0"), null, "", null, null, null, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard loyaltyCard = db.getLoyaltyCard(1);
|
||||
LoyaltyCard loyaltyCard = mDb.getLoyaltyCard(1);
|
||||
assertNotNull(loyaltyCard);
|
||||
assertEquals("", loyaltyCard.store);
|
||||
assertEquals("", loyaltyCard.note);
|
||||
@@ -154,15 +155,15 @@ public class DatabaseTest {
|
||||
// Add the gift cards in reverse order, to ensure
|
||||
// that they are sorted
|
||||
for (int index = CARDS_TO_ADD - 1; index >= 0; index--) {
|
||||
long id = db.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
long id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(CARDS_TO_ADD, db.getLoyaltyCardCount());
|
||||
assertEquals(CARDS_TO_ADD, mDb.getLoyaltyCardCount());
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
Cursor cursor = mDb.getLoyaltyCardCursor();
|
||||
assertNotNull(cursor);
|
||||
|
||||
assertEquals(CARDS_TO_ADD, cursor.getCount());
|
||||
@@ -198,19 +199,19 @@ public class DatabaseTest {
|
||||
// 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, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 1, null);
|
||||
} else {
|
||||
id = db.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
id = mDb.insertLoyaltyCard("store" + index, "note" + index, null, new BigDecimal("0"), null, "cardId" + index,
|
||||
null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), index, 0, null);
|
||||
}
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(CARDS_TO_ADD, db.getLoyaltyCardCount());
|
||||
assertEquals(CARDS_TO_ADD, mDb.getLoyaltyCardCount());
|
||||
|
||||
Cursor cursor = db.getLoyaltyCardCursor();
|
||||
Cursor cursor = mDb.getLoyaltyCardCursor();
|
||||
assertNotNull(cursor);
|
||||
|
||||
assertEquals(CARDS_TO_ADD, cursor.getCount());
|
||||
@@ -279,130 +280,130 @@ public class DatabaseTest {
|
||||
|
||||
@Test
|
||||
public void addRemoveOneGroup() {
|
||||
assertEquals(0, db.getGroupCount());
|
||||
long id = db.insertGroup("group one");
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
long id = mDb.insertGroup("group one");
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
Group group = db.getGroup("group one");
|
||||
Group group = mDb.getGroup("group one");
|
||||
assertNotNull(group);
|
||||
assertEquals("group one", group._id);
|
||||
|
||||
result = db.deleteGroup("group one");
|
||||
result = mDb.deleteGroup("group one");
|
||||
assertTrue(result);
|
||||
assertEquals(0, db.getGroupCount());
|
||||
assertNull(db.getGroup("group one"));
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
assertNull(mDb.getGroup("group one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGroup() {
|
||||
// Create card
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
// Create group
|
||||
long groupId = db.insertGroup("group one");
|
||||
long groupId = mDb.insertGroup("group one");
|
||||
result = (groupId != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
// Add card to group
|
||||
Group group = db.getGroup("group one");
|
||||
Group group = mDb.getGroup("group one");
|
||||
List<Group> groupList1 = new ArrayList<>();
|
||||
groupList1.add(group);
|
||||
db.setLoyaltyCardGroups(1, groupList1);
|
||||
mDb.setLoyaltyCardGroups(1, groupList1);
|
||||
|
||||
// Ensure the card has one group and the group has one card
|
||||
List<Group> cardGroups = db.getLoyaltyCardGroups((int) id);
|
||||
List<Group> cardGroups = mDb.getLoyaltyCardGroups((int) id);
|
||||
assertEquals(1, cardGroups.size());
|
||||
assertEquals("group one", cardGroups.get(0)._id);
|
||||
assertEquals(1, db.getGroupCardCount("group one"));
|
||||
assertEquals(1, mDb.getGroupCardCount("group one"));
|
||||
|
||||
// Rename group
|
||||
result = db.updateGroup("group one", "group one renamed");
|
||||
result = mDb.updateGroup("group one", "group one renamed");
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
// Group one no longer exists
|
||||
group = db.getGroup("group one");
|
||||
group = mDb.getGroup("group one");
|
||||
assertNull(group);
|
||||
|
||||
// But group one renamed does
|
||||
Group group2 = db.getGroup("group one renamed");
|
||||
Group group2 = mDb.getGroup("group one renamed");
|
||||
assertNotNull(group2);
|
||||
assertEquals("group one renamed", group2._id);
|
||||
|
||||
// And card is in "group one renamed"
|
||||
// Ensure the card has one group and the group has one card
|
||||
cardGroups = db.getLoyaltyCardGroups((int) id);
|
||||
cardGroups = mDb.getLoyaltyCardGroups((int) id);
|
||||
assertEquals(1, cardGroups.size());
|
||||
assertEquals("group one renamed", cardGroups.get(0)._id);
|
||||
assertEquals(1, db.getGroupCardCount("group one renamed"));
|
||||
assertEquals(1, mDb.getGroupCardCount("group one renamed"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateMissingGroup() {
|
||||
assertEquals(0, db.getGroupCount());
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
|
||||
boolean result = db.updateGroup("group one", "new name");
|
||||
boolean result = mDb.updateGroup("group one", "new name");
|
||||
assertEquals(false, result);
|
||||
assertEquals(0, db.getGroupCount());
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyGroupValues() {
|
||||
long id = db.insertGroup("");
|
||||
long id = mDb.insertGroup("");
|
||||
boolean result = (id != -1);
|
||||
assertFalse(result);
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicateGroupName() {
|
||||
assertEquals(0, db.getGroupCount());
|
||||
long id = db.insertGroup("group one");
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
long id = mDb.insertGroup("group one");
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
Group group = db.getGroup("group one");
|
||||
Group group = mDb.getGroup("group one");
|
||||
assertNotNull(group);
|
||||
assertEquals("group one", group._id);
|
||||
|
||||
// Should fail on duplicate
|
||||
long id2 = db.insertGroup("group one");
|
||||
long id2 = mDb.insertGroup("group one");
|
||||
boolean result2 = (id2 != -1);
|
||||
assertFalse(result2);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGroupDuplicate() {
|
||||
long id = db.insertGroup("group one");
|
||||
long id = mDb.insertGroup("group one");
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getGroupCount());
|
||||
assertEquals(1, mDb.getGroupCount());
|
||||
|
||||
long id2 = db.insertGroup("group two");
|
||||
long id2 = mDb.insertGroup("group two");
|
||||
boolean result2 = (id2 != -1);
|
||||
assertTrue(result2);
|
||||
assertEquals(2, db.getGroupCount());
|
||||
assertEquals(2, mDb.getGroupCount());
|
||||
|
||||
// Should fail when trying to rename group two to one
|
||||
boolean result3 = db.updateGroup("group two", "group one");
|
||||
boolean result3 = mDb.updateGroup("group two", "group one");
|
||||
assertFalse(result3);
|
||||
assertEquals(2, db.getGroupCount());
|
||||
assertEquals(2, mDb.getGroupCount());
|
||||
|
||||
// Rename failed so both should still be the same
|
||||
Group group = db.getGroup("group one");
|
||||
Group group = mDb.getGroup("group one");
|
||||
assertNotNull(group);
|
||||
assertEquals("group one", group._id);
|
||||
|
||||
Group group2 = db.getGroup("group two");
|
||||
Group group2 = mDb.getGroup("group two");
|
||||
assertNotNull(group2);
|
||||
assertEquals("group two", group2._id);
|
||||
}
|
||||
@@ -410,52 +411,52 @@ public class DatabaseTest {
|
||||
@Test
|
||||
public void cardAddAndRemoveGroups() {
|
||||
// Create card
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
long id = db.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
assertEquals(0, mDb.getLoyaltyCardCount());
|
||||
long id = mDb.insertLoyaltyCard("store", "note", null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
assertEquals(1, mDb.getLoyaltyCardCount());
|
||||
|
||||
// Create two groups to only one card
|
||||
assertEquals(0, db.getGroupCount());
|
||||
long gid = db.insertGroup("one");
|
||||
assertEquals(0, mDb.getGroupCount());
|
||||
long gid = mDb.insertGroup("one");
|
||||
boolean gresult = (gid != -1);
|
||||
assertTrue(gresult);
|
||||
|
||||
long gid2 = db.insertGroup("two");
|
||||
long gid2 = mDb.insertGroup("two");
|
||||
boolean gresult2 = (gid2 != -1);
|
||||
assertTrue(gresult2);
|
||||
|
||||
assertEquals(2, db.getGroupCount());
|
||||
assertEquals(2, mDb.getGroupCount());
|
||||
|
||||
Group group1 = db.getGroup("one");
|
||||
Group group1 = mDb.getGroup("one");
|
||||
|
||||
// Card has no groups by default
|
||||
List<Group> cardGroups = db.getLoyaltyCardGroups(1);
|
||||
List<Group> cardGroups = mDb.getLoyaltyCardGroups(1);
|
||||
assertEquals(0, cardGroups.size());
|
||||
|
||||
// Add one groups to card
|
||||
List<Group> groupList1 = new ArrayList<>();
|
||||
groupList1.add(group1);
|
||||
db.setLoyaltyCardGroups(1, groupList1);
|
||||
mDb.setLoyaltyCardGroups(1, groupList1);
|
||||
|
||||
List<Group> cardGroups1 = db.getLoyaltyCardGroups(1);
|
||||
List<Group> cardGroups1 = mDb.getLoyaltyCardGroups(1);
|
||||
assertEquals(1, cardGroups1.size());
|
||||
assertEquals(cardGroups1.get(0)._id, group1._id);
|
||||
assertEquals(1, db.getGroupCardCount("one"));
|
||||
assertEquals(0, db.getGroupCardCount("two"));
|
||||
assertEquals(1, mDb.getGroupCardCount("one"));
|
||||
assertEquals(0, mDb.getGroupCardCount("two"));
|
||||
|
||||
// Remove groups
|
||||
db.setLoyaltyCardGroups(1, new ArrayList<Group>());
|
||||
List<Group> cardGroups2 = db.getLoyaltyCardGroups(1);
|
||||
mDb.setLoyaltyCardGroups(1, new ArrayList<Group>());
|
||||
List<Group> cardGroups2 = mDb.getLoyaltyCardGroups(1);
|
||||
assertEquals(0, cardGroups2.size());
|
||||
assertEquals(0, db.getGroupCardCount("one"));
|
||||
assertEquals(0, db.getGroupCardCount("two"));
|
||||
assertEquals(0, mDb.getGroupCardCount("one"));
|
||||
assertEquals(0, mDb.getGroupCardCount("two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void databaseUpgradeFromVersion1() {
|
||||
SQLiteDatabase database = db.getWritableDatabase();
|
||||
SQLiteDatabase database = mDb.getWritableDatabase();
|
||||
|
||||
// Setup the database as it appeared in revision 1
|
||||
setupDatabaseVersion1(database);
|
||||
@@ -465,10 +466,10 @@ public class DatabaseTest {
|
||||
int newCardId2 = insertCardVersion1(database, "store", "cardId", "");
|
||||
|
||||
// Upgrade database
|
||||
db.onUpgrade(database, DBHelper.ORIGINAL_DATABASE_VERSION, DBHelper.DATABASE_VERSION);
|
||||
mDb.onUpgrade(database, DBHelper.ORIGINAL_DATABASE_VERSION, DBHelper.DATABASE_VERSION);
|
||||
|
||||
// Determine that the entries are queryable and the fields are correct
|
||||
LoyaltyCard card = db.getLoyaltyCard(newCardId);
|
||||
LoyaltyCard card = mDb.getLoyaltyCard(newCardId);
|
||||
assertEquals("store", card.store);
|
||||
assertEquals("", card.note);
|
||||
assertEquals(null, card.expiry);
|
||||
@@ -483,7 +484,7 @@ public class DatabaseTest {
|
||||
assertEquals(100, card.zoomLevel);
|
||||
|
||||
// Determine that the entries are queryable and the fields are correct
|
||||
LoyaltyCard card2 = db.getLoyaltyCard(newCardId2);
|
||||
LoyaltyCard card2 = mDb.getLoyaltyCard(newCardId2);
|
||||
assertEquals("store", card2.store);
|
||||
assertEquals("", card2.note);
|
||||
assertEquals(null, card2.expiry);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Catima - Svobodná brašna karet
|
||||
2
fastlane/metadata/android/en-US/changelogs/93.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/93.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Add Catima to Quick Access Device Controls (https://developer.android.com/guide/topics/ui/device-control)
|
||||
- Fix some groups not showing up correctly in group management screen
|
||||
3
fastlane/metadata/android/en-US/changelogs/94.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/94.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Fix blurriness of main screen letter icons
|
||||
- Fix icons sometimes disappearing after selection
|
||||
- Fix status bar icons possibly being invisible on Android 5
|
||||
@@ -1 +1 @@
|
||||
Catima — The Libre Card Wallet
|
||||
Catima — Loyalty Card Wallet
|
||||
|
||||
2
fastlane/metadata/android/nb-NO/changelogs/93.txt
Normal file
2
fastlane/metadata/android/nb-NO/changelogs/93.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Catima lagt til i hurtigtilgang til kontroller for enheter (https://developer.android.com/guide/topics/ui/device-control)
|
||||
- Grupper vises nå riktig i gruppehåndtering
|
||||
@@ -8,7 +8,7 @@ Med dette essensielle verktøyet kan du erstatte unyttig plast med kontanter.
|
||||
- Unngå spionasje med veldig få tilganger. Ingen tilgang til Internett, og ingen reklame.
|
||||
- Legg til kort eller koder med navn og egne farger.
|
||||
- Manuell kodeinnskriving hvis det ikke er noen strekkode å lagre, eller den ikke kan brukes.
|
||||
- Importer kort og koder fra filer ,Catima, FidMe, Kundekortknippe, Stocard og Voucher Vault.
|
||||
- Importer kort og koder fra filer, Catima, FidMe, Kundekortknippe, Stocard og Voucher Vault.
|
||||
- Lag en sikkerhetskopi av alle kortene dine og overfør dem til en ny enhet hvis du ønsker det.
|
||||
- Del kupponger, eksklusive tilbud, promokoder eller kort og koder ved bruk av ethvert program.
|
||||
- Mørk drakt og tilgjengelighetsvalg for synshemmede brukere.
|
||||
|
||||
@@ -1 +1 @@
|
||||
Catima — for kundekort, billetter og kuponger 🎴
|
||||
Catima — for kundekort, billetter og kuponger
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Catima gestor de cartões livre
|
||||
@@ -1,3 +0,0 @@
|
||||
- Foi alterado o nome de ficheiro padrão de importar/exportar. (pull #84 (https://github.com/brarcher/loyalty-card-locker/pull/84))
|
||||
- Corrigida a sequência na página de importação/exportação. (pull #87 (https://github.com/brarcher/loyalty-card-locker/pull/87))
|
||||
- Disposição da página de visualização do cartão melhorada. O texto deve ser mais fácil de ler e selecionável com um toque longo. (pull #91 (https://github.com/brarcher/loyalty-card-locker/pull/91))
|
||||
@@ -1,5 +0,0 @@
|
||||
- Ao editar um identificador de um cartão, pré-preencher o identificador existente.
|
||||
- Limitada a largura dos códigos de barras gerados para reduzir o uso de memória e erros.
|
||||
- Alterado o botão "Introduzir cartão" para "Editar cartão" se já existir um identificador.
|
||||
- Alterado o esquema de cores para ser mais suave e compatível com o ícone da aplicação e disposição alterada ao visualizar um cartão.
|
||||
- Acrescentado um assistente de introdução que será lançado no primeiro lançamento da aplicação.
|
||||
@@ -1 +0,0 @@
|
||||
- Evitar uma falha de sistema ao rodar o ecrã no primeiro assistente de introdução.
|
||||
@@ -1,2 +0,0 @@
|
||||
- Uma alteração na v0.11 reduziu o uso de memória do desenho do código de barras, mas afetou as dimensões do código de barras. Isto agora é alterado para manter as dimensões do código de barras enquanto reduz o uso de memória. (pull #126 (https://github.com/brarcher/loyalty-card-locker/pull/126))
|
||||
- Atualização das traduções em alemão e francês. (pull #122, pull #124, pull #125)
|
||||
@@ -1,3 +0,0 @@
|
||||
- Adicionada a opção de bloqueio da rotação do ecrã ao mostrar um cartão. Se bloqueado, o ecrã passará para a sua orientação "natural" e a rotação posterior do ecrã será bloqueada. (pull #128)
|
||||
- Se um cartão for selecionado no ecrã principal mas não puder ser carregado, a aplicação falha graciosamente e lança uma mensagem. (pull #132)
|
||||
- Corrigidos casos em que não foi possível encontrar identificadores de layout para o assistente de introdução. (pull #128)
|
||||
@@ -1,5 +0,0 @@
|
||||
O Android 4.4 já não é suportado a partir desta versão. Se quiser usar o Catima no Android 4.4, use a versão 2.6.1.
|
||||
|
||||
- Suporte melhorado ao Android 12
|
||||
- Ecrã "sobre" melhorado
|
||||
- A pesquisa agora ignora acentos
|
||||
@@ -1 +0,0 @@
|
||||
- Melhorada a pesquisa com espaços
|
||||
@@ -1 +0,0 @@
|
||||
- Corrigir a regressão que quebra importação/exportação
|
||||
@@ -1 +0,0 @@
|
||||
- Corrigir migração incorreta fazendo com que o primeiro cartão se torne invisível
|
||||
@@ -1,5 +0,0 @@
|
||||
- Corrigir deslizar entre grupos que não trabalham num grupo vazio
|
||||
- Permitir proteção por palavra-passe de exportações
|
||||
- Melhorar o uso do espaço para códigos QR
|
||||
- Memorizar o último nível de ampliação usado por cartão
|
||||
- Corrigir uma falha de sistema ao deslizar logo após um toque
|
||||
@@ -1,6 +0,0 @@
|
||||
A parte "Bloqueador" do nome não era intuitiva. Para ajudar a remediar isso, foi criado por betsythefc um novo ícone da aplicação que representa melhor o propósito da aplicação: armazenar cartões de fidelização que utilizam códigos de barras. Junto com este novo ícone o nome da aplicação foi alterado para "Loyalty Card Keychain".
|
||||
|
||||
Recursos adicionais/melhorias:
|
||||
|
||||
- A importação/exportação de cartões foi alterada para ser mais flexível.
|
||||
- Adicionada tradução para lituano e francês.
|
||||
@@ -1,4 +0,0 @@
|
||||
- Corrigir pontos na visualização do cartão tendo a cor errada ao mudar o tema manualmente
|
||||
- Corrigir falha na visualização do cartão na mudança de rotação/tema
|
||||
- Corrigir piscar da lista de cartões
|
||||
- Corrigir o ícone de favorito sobreposto ao texto
|
||||
@@ -1,22 +0,0 @@
|
||||
Não procure mais os cartões plástico na caixa de pagamento das lojas.
|
||||
<b>Digitalize os códigos de barras para o seu dispositivo usando a câmara fotográfica e esqueça os cartões. </b>
|
||||
|
||||
Esqueça a sua carteira ou guarde-a para outras coisas mais úteis.
|
||||
|
||||
Com esta ferramenta essencial de transporte diário pode substituir o plástico inútil por dinheiro.
|
||||
|
||||
- Evite quebra de privacidade, a aplicação usa poucas permissões. Não precisa de acesso à Internet e não tem anúncios.
|
||||
- Adicione cartões ou códigos com nomes e cores personalizáveis.
|
||||
- Introduza manualmente códigos se não houver um código de barras no cartão físico ou se este estiver danificado.
|
||||
- Importe cartões e códigos a partir de ficheiros de outras aplicações como Catima, FidMe, Loyalty Card Keychain, Stocard e Voucher Vault.
|
||||
- Faça uma cópia de segurança de todos os seus cartões e transfira-os para um novo dispositivo, se quiser.
|
||||
- Partilhe cupões, ofertas exclusivas, códigos promocionais ou cartões e códigos usando qualquer outra aplicação.
|
||||
- Com tema escuro e opções de acessibilidade para utilizadores com deficiência visual.
|
||||
- Feito para todos pela comunidade do software livre.
|
||||
- Traduções localizadas feitas manualmente em mais de 20 idiomas.
|
||||
- Aplicação gratuita, suportada por contribuições da comunidade.
|
||||
- Use, estude, altere e partilhe o código-fonte da aplicação como quiser; <i>com toda a gente</i>.
|
||||
- Não é apenas um Software Livre / Código Aberto. É uma aplicação de gestão de cartões de partilha <i>sob a mesma licença</i> segundo a licença (GPLv3+).
|
||||
|
||||
Simplifique a sua vida e as suas compras e nunca mais perca um recibo em papel, um cartão de oferta de pagamento na loja ou um bilhete de avião.
|
||||
Leve todas as suas recompensas e bónus consigo e poupe.
|
||||
@@ -1 +0,0 @@
|
||||
Para os seus cartões de afiliações, programas de fidelidade, cupões e bilhetes.
|
||||
@@ -1 +0,0 @@
|
||||
Catima gestor de cartões livre
|
||||
3
fastlane/metadata/android/tr-TR/changelogs/10.txt
Normal file
3
fastlane/metadata/android/tr-TR/changelogs/10.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Öntanımlı içe/dışa aktarma dosya adı değiştirildi. (https://github.com/brarcher/loyalty-card-locker/pull/84)
|
||||
- İçe/dışa aktarma sayfasındaki dizge düzeltildi. (https://github.com/brarcher/loyalty-card-locker/pull/87)
|
||||
- Kart görünümü sayfasının düzeni iyileştirildi. Metnin okunması daha kolay olmalı ve uzun bir tıklama ile seçilebilir olmalıdır. https://github.com/brarcher/loyalty-card-locker/pull/91)
|
||||
1
fastlane/metadata/android/tr-TR/changelogs/12.txt
Normal file
1
fastlane/metadata/android/tr-TR/changelogs/12.txt
Normal file
@@ -0,0 +1 @@
|
||||
- İlk çalıştırma giriş sihirbazında ekranı döndürürken oluşan çökmeyi önle.
|
||||
3
fastlane/metadata/android/tr-TR/changelogs/19.txt
Normal file
3
fastlane/metadata/android/tr-TR/changelogs/19.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Belirli türdeki bozuk CSV dosyalarını içe aktarırken oluşan çökme düzeltildi. (https://github.com/brarcher/loyalty-card-locker/pull/177)
|
||||
- Yedekleri doğrudan dosya sisteminden içe aktarma düzeltildi. (https://github.com/brarcher/loyalty-card-locker/pull/180)
|
||||
- Belirli içerik sağlayıcı türlerinden yedekleri içe aktarma düzeltildi. (https://github.com/brarcher/loyalty-card-locker/pull/179)
|
||||
3
fastlane/metadata/android/tr-TR/changelogs/2.txt
Normal file
3
fastlane/metadata/android/tr-TR/changelogs/2.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- İtalyanca çeviri
|
||||
- Tüm 1B barkod türleri için destek. (Başlangıçta yalnızca ürün 1B barkodları destekleniyordu)
|
||||
- Başlangıçta eksik olan gerekli kamera izni eklendi.
|
||||
2
fastlane/metadata/android/tr-TR/changelogs/21.txt
Normal file
2
fastlane/metadata/android/tr-TR/changelogs/21.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Kart listesi düzeni iyileştirildi. (https://github.com/brarcher/loyalty-card-locker/pull/188)
|
||||
- Kartı görüntüleme düzeni iyileştirildi. (https://github.com/brarcher/loyalty-card-locker/pull/190)
|
||||
2
fastlane/metadata/android/tr-TR/changelogs/93.txt
Normal file
2
fastlane/metadata/android/tr-TR/changelogs/93.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Catima'yı Hızlı Erişim Aygıt Denetimlerine ekle (https://developer.android.com/guide/topics/ui/device-control)
|
||||
- Grup yönetimi ekranında bazı grupların doğru görünmemesini düzelt
|
||||
3
fastlane/metadata/android/tr-TR/changelogs/94.txt
Normal file
3
fastlane/metadata/android/tr-TR/changelogs/94.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Ana ekran harf simgelerinin bulanıklığını düzelt
|
||||
- Simgelerin seçtikten sonra bazen kaybolmasını düzelt
|
||||
- Android 5'te bazen görünmez olan durum çubuğu simgelerini düzelt
|
||||
2
fastlane/metadata/android/uk/changelogs/21.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/21.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Покращено інтерфейс списку карт. (pull #188 (https://github.com/brarcher/loyalty-card-locker/pull/188))
|
||||
- Покращено інтерфейс перегляду карти. (pull #190 (https://github.com/brarcher/loyalty-card-locker/pull/190))
|
||||
@@ -1 +1 @@
|
||||
- Змінено відображення карт: показ заміток та імені магазину, багаторядкове ID карти та. (pull #197 (https://github.com/brarcher/loyalty-card-locker/pull/197))
|
||||
- Змінено відображення карт: показ заміток та імені магазину, багаторядкове ID карти. (pull #197 (https://github.com/brarcher/loyalty-card-locker/pull/197))
|
||||
|
||||
2
fastlane/metadata/android/uk/changelogs/27.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/27.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Відкат min SDK з версії 17 до 15. (pull #226 (https://github.com/brarcher/loyalty-card-locker/pull/226))
|
||||
- Стара бібліотека apache тепер використовується лише для тестів. (pull #225 (https://github.com/brarcher/loyalty-card-locker/pull/225))
|
||||
5
fastlane/metadata/android/uk/changelogs/28.txt
Normal file
5
fastlane/metadata/android/uk/changelogs/28.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
- Додано переклади
|
||||
- Польська (pull #232 (https://github.com/brarcher/loyalty-card-locker/pull/232))
|
||||
- Іспанська (pull #232 (https://github.com/brarcher/loyalty-card-locker/pull/232))
|
||||
- Словацька(pull #232 (https://github.com/brarcher/loyalty-card-locker/pull/232))
|
||||
- Оновлено переклади (pull #239 (https://github.com/brarcher/loyalty-card-locker/pull/239))
|
||||
2
fastlane/metadata/android/uk/changelogs/29.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/29.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Виправлено іспанську локалізацію (pull #244 (https://github.com/brarcher/loyalty-card-locker/pull/244))
|
||||
- Оновлено переклади (pull #244 (https://github.com/brarcher/loyalty-card-locker/pull/244))
|
||||
14
fastlane/metadata/android/uk/changelogs/3.txt
Normal file
14
fastlane/metadata/android/uk/changelogs/3.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
- Тепер офіційно підтримується наступний список з 1D та 2D штрих-кодів:
|
||||
- AZTEC
|
||||
- CODABAR
|
||||
- CODE_39
|
||||
- CODE_128
|
||||
- DATA_MATRIX
|
||||
- EAN_8
|
||||
- EAN_13
|
||||
- ITF
|
||||
- PDF_417
|
||||
- QR_CODE
|
||||
- UPC_A
|
||||
|
||||
- Тепер згенеровані штрих-коди більші, тому легше сприймаються сканером
|
||||
4
fastlane/metadata/android/uk/changelogs/30.txt
Normal file
4
fastlane/metadata/android/uk/changelogs/30.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
- Додано налаштування яскравості екрану при перегляді штрих-коду (pull #259 (https://github.com/brarcher/loyalty-card-locker/pull/259))
|
||||
- Додано грецьку локалізацію (pull #252 (https://github.com/brarcher/loyalty-card-locker/pull/252))
|
||||
- Додано словенську локалізацію (pull #260 (https://github.com/brarcher/loyalty-card-locker/pull/260))
|
||||
- Оновлено переклади (pull #260 (https://github.com/brarcher/loyalty-card-locker/pull/260), pull #254 (https://github.com/brarcher/loyalty-card-locker/pull/254))
|
||||
2
fastlane/metadata/android/uk/changelogs/31.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/31.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Сортування списку карток ігнорує регістр (pull #266 (https://github.com/brarcher/loyalty-card-locker/pull/266))
|
||||
- Додано налаштування для блокування орієнтації усіх карток (pull #269 (https://github.com/brarcher/loyalty-card-locker/pull/269)
|
||||
1
fastlane/metadata/android/uk/changelogs/32.txt
Normal file
1
fastlane/metadata/android/uk/changelogs/32.txt
Normal file
@@ -0,0 +1 @@
|
||||
- Виправлено створення нової карти за допомогою вводу штрих-коду вручну (issue #272 (https://github.com/brarcher/loyalty-card-locker/issues/272))
|
||||
1
fastlane/metadata/android/uk/changelogs/33.txt
Normal file
1
fastlane/metadata/android/uk/changelogs/33.txt
Normal file
@@ -0,0 +1 @@
|
||||
- Оновлено та додано переклади
|
||||
1
fastlane/metadata/android/uk/changelogs/34.txt
Normal file
1
fastlane/metadata/android/uk/changelogs/34.txt
Normal file
@@ -0,0 +1 @@
|
||||
- Оновлено російську локалізацію
|
||||
Reference in New Issue
Block a user