package net.ktnx.mobileledger.ui.templates;
import android.annotation.SuppressLint;
+import android.content.Context;
import android.content.res.Resources;
import android.text.Editable;
import android.text.TextWatcher;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.lifecycle.LifecycleOwner;
import androidx.recyclerview.widget.AsyncListDiffer;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ItemTouchHelper;
import net.ktnx.mobileledger.databinding.TemplateDetailsAccountBinding;
import net.ktnx.mobileledger.databinding.TemplateDetailsHeaderBinding;
import net.ktnx.mobileledger.db.AccountAutocompleteAdapter;
+import net.ktnx.mobileledger.db.DB;
import net.ktnx.mobileledger.model.Data;
import net.ktnx.mobileledger.model.TemplateDetailsItem;
-import net.ktnx.mobileledger.ui.QRScanCapableFragment;
+import net.ktnx.mobileledger.ui.CurrencySelectorFragment;
+import net.ktnx.mobileledger.ui.HelpDialog;
+import net.ktnx.mobileledger.ui.QR;
import net.ktnx.mobileledger.ui.TemplateDetailSourceSelectorFragment;
import net.ktnx.mobileledger.utils.Logger;
import net.ktnx.mobileledger.utils.Misc;
itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public float getMoveThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
- return 0.1f;
+ return 0.5f;
}
@Override
public boolean isLongPressDragEnabled() {
public boolean canDropOver(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder current,
@NonNull RecyclerView.ViewHolder target) {
- final int adapterPosition = target.getAdapterPosition();
+ final int adapterPosition = target.getBindingAdapterPosition();
// first item is immovable
if (adapterPosition == 0)
@NonNull RecyclerView.ViewHolder viewHolder) {
int flags = 0;
// the top item (transaction params) is always there
- final int adapterPosition = viewHolder.getAdapterPosition();
+ final int adapterPosition = viewHolder.getBindingAdapterPosition();
if (adapterPosition > 0)
flags |= makeFlag(ItemTouchHelper.ACTION_STATE_DRAG,
ItemTouchHelper.UP | ItemTouchHelper.DOWN) |
@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull RecyclerView.ViewHolder target) {
- final int fromPosition = viewHolder.getAdapterPosition();
- final int toPosition = target.getAdapterPosition();
+ final int fromPosition = viewHolder.getBindingAdapterPosition();
+ final int toPosition = target.getBindingAdapterPosition();
if (fromPosition == toPosition) {
Logger.debug("drag", String.format(Locale.US,
"Ignoring request to move an account from position %d to %d",
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
- int pos = viewHolder.getAdapterPosition();
+ int pos = viewHolder.getBindingAdapterPosition();
mModel.removeItem(pos);
}
});
for (int i = 1; i < items.size(); i++) {
final TemplateDetailsItem item = items.get(i);
Logger.debug("tmpl",
- String.format(Locale.US, " %d: id %d, pos %d", i, item.getId(), item.getPosition()));
+ String.format(Locale.US, " %d: id %d, pos %d", i, item.getId(),
+ item.getPosition()));
}
}
differ.submitList(items);
private enum HeaderDetail {DESCRIPTION, COMMENT, DATE_YEAR, DATE_MONTH, DATE_DAY}
- private enum AccDetail {ACCOUNT, COMMENT, AMOUNT}
+ private enum AccDetail {ACCOUNT, COMMENT, AMOUNT, CURRENCY}
public abstract static class ViewHolder extends RecyclerView.ViewHolder {
ViewHolder(@NonNull View itemView) {
}
};
b.transactionComment.addTextChangedListener(transactionCommentWatcher);
+
+ b.templateIsFallbackSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (updatePropagationDisabled)
+ return;
+
+ getItem().setFallback(isChecked);
+ b.templateIsFallbackText.setText(isChecked ? R.string.template_is_fallback_yes
+ : R.string.template_is_fallback_no);
+ });
+ final View.OnClickListener fallbackLabelClickListener =
+ (view) -> b.templateIsFallbackSwitch.toggle();
+ b.templateIsFallbackLabel.setOnClickListener(fallbackLabelClickListener);
+ b.templateIsFallbackText.setOnClickListener(fallbackLabelClickListener);
+ b.templateParamsHelpButton.setOnClickListener(v -> HelpDialog.show(b.getRoot()
+ .getContext(),
+ R.string.template_details_template_params_label, R.array.template_params_help));
}
@NotNull
private TemplateDetailsItem.Header getItem() {
- int pos = getAdapterPosition();
+ int pos = getBindingAdapterPosition();
return differ.getCurrentList()
.get(pos)
.asHeaderItem();
}
}
- notifyItemChanged(getAdapterPosition());
+ notifyItemChanged(getBindingAdapterPosition());
});
final AppCompatActivity activity = (AppCompatActivity) v.getContext();
sel.show(activity.getSupportFragmentManager(), "template-details-source-selector");
b.testText.setText(header.getTestText());
if (header.hasLiteralDateYear()) {
- b.templateDetailsYearSource.setText(R.string.template_details_source_literal);
+ b.yearSource.setText(R.string.template_details_source_literal);
final Integer dateYear = header.getDateYear();
b.templateDetailsDateYear.setText(
(dateYear == null) ? null : String.valueOf(dateYear));
- b.templateDetailsDateYearLayout.setVisibility(View.VISIBLE);
+ b.yearLayout.setVisibility(View.VISIBLE);
}
else {
- b.templateDetailsDateYearLayout.setVisibility(View.GONE);
- b.templateDetailsYearSource.setText(
+ b.yearLayout.setVisibility(View.GONE);
+ b.yearSource.setText(
String.format(Locale.US, groupNoText, header.getDateYearMatchGroup(),
getMatchGroupText(header.getDateYearMatchGroup())));
}
- b.templateDetailsYearSourceLabel.setOnClickListener(
+ b.yearSourceLabel.setOnClickListener(
v -> selectHeaderDetailSource(v, HeaderDetail.DATE_YEAR));
- b.templateDetailsYearSource.setOnClickListener(
+ b.yearSource.setOnClickListener(
v -> selectHeaderDetailSource(v, HeaderDetail.DATE_YEAR));
if (header.hasLiteralDateMonth()) {
- b.templateDetailsMonthSource.setText(R.string.template_details_source_literal);
+ b.monthSource.setText(R.string.template_details_source_literal);
final Integer dateMonth = header.getDateMonth();
b.templateDetailsDateMonth.setText(
(dateMonth == null) ? null : String.valueOf(dateMonth));
- b.templateDetailsDateMonthLayout.setVisibility(View.VISIBLE);
+ b.monthLayout.setVisibility(View.VISIBLE);
}
else {
- b.templateDetailsDateMonthLayout.setVisibility(View.GONE);
- b.templateDetailsMonthSource.setText(
+ b.monthLayout.setVisibility(View.GONE);
+ b.monthSource.setText(
String.format(Locale.US, groupNoText, header.getDateMonthMatchGroup(),
getMatchGroupText(header.getDateMonthMatchGroup())));
}
- b.templateDetailsMonthSourceLabel.setOnClickListener(
+ b.monthSourceLabel.setOnClickListener(
v -> selectHeaderDetailSource(v, HeaderDetail.DATE_MONTH));
- b.templateDetailsMonthSource.setOnClickListener(
+ b.monthSource.setOnClickListener(
v -> selectHeaderDetailSource(v, HeaderDetail.DATE_MONTH));
if (header.hasLiteralDateDay()) {
- b.templateDetailsDaySource.setText(R.string.template_details_source_literal);
+ b.daySource.setText(R.string.template_details_source_literal);
final Integer dateDay = header.getDateDay();
b.templateDetailsDateDay.setText(
(dateDay == null) ? null : String.valueOf(dateDay));
- b.templateDetailsDateDayLayout.setVisibility(View.VISIBLE);
+ b.dayLayout.setVisibility(View.VISIBLE);
}
else {
- b.templateDetailsDateDayLayout.setVisibility(View.GONE);
- b.templateDetailsDaySource.setText(
+ b.dayLayout.setVisibility(View.GONE);
+ b.daySource.setText(
String.format(Locale.US, groupNoText, header.getDateDayMatchGroup(),
getMatchGroupText(header.getDateDayMatchGroup())));
}
- b.templateDetailsDaySourceLabel.setOnClickListener(
+ b.daySourceLabel.setOnClickListener(
v -> selectHeaderDetailSource(v, HeaderDetail.DATE_DAY));
- b.templateDetailsDaySource.setOnClickListener(
+ b.daySource.setOnClickListener(
v -> selectHeaderDetailSource(v, HeaderDetail.DATE_DAY));
if (header.hasLiteralTransactionDescription()) {
b.templateDetailsHeadScanQrButton.setOnClickListener(this::scanTestQR);
+ b.templateIsFallbackSwitch.setChecked(header.isFallback());
+ b.templateIsFallbackText.setText(
+ header.isFallback() ? R.string.template_is_fallback_yes
+ : R.string.template_is_fallback_no);
+
checkPatternError(header);
}
finally {
}
private void scanTestQR(View view) {
- QRScanCapableFragment.triggerQRScan();
+ Context ctx = view.getContext();
+ if (ctx instanceof QR.QRScanTrigger)
+ ((QR.QRScanTrigger) ctx).triggerQRScan();
}
}
String groupNoText = resources.getString(R.string.template_item_match_group_source);
Logger.debug("drag", String.format(Locale.US, "Binding account id %d, pos %d at %d",
- item.getId(), item.getPosition(), getAdapterPosition()));
+ item.getId(), item.getPosition(), getBindingAdapterPosition()));
TemplateDetailsItem.AccountRow accRow = item.asAccountRowItem();
b.patternAccountLabel.setText(String.format(Locale.US,
resources.getString(R.string.template_details_account_row_label),
b.templateDetailsNegateAmountText.setVisibility(View.VISIBLE);
}
+ if (accRow.hasLiteralCurrency()) {
+ b.templateDetailsAccountCurrencySource.setText(
+ R.string.template_details_source_literal);
+ net.ktnx.mobileledger.db.Currency c = accRow.getCurrency();
+ if (c == null)
+ b.templateDetailsAccountCurrency.setText(R.string.btn_no_currency);
+ else
+ b.templateDetailsAccountCurrency.setText(c.getName());
+ b.templateDetailsAccountCurrency.setVisibility(View.VISIBLE);
+ }
+ else {
+ b.templateDetailsAccountCurrencySource.setText(
+ String.format(Locale.US, groupNoText, accRow.getCurrencyMatchGroup(),
+ getMatchGroupText(accRow.getCurrencyMatchGroup())));
+ b.templateDetailsAccountCurrency.setVisibility(View.GONE);
+ }
+
b.templateAccountNameSourceLabel.setOnClickListener(
v -> selectAccountRowDetailSource(v, AccDetail.ACCOUNT));
b.templateDetailsAccountNameSource.setOnClickListener(
v -> selectAccountRowDetailSource(v, AccDetail.AMOUNT));
b.templateDetailsAccountAmountSource.setOnClickListener(
v -> selectAccountRowDetailSource(v, AccDetail.AMOUNT));
+ b.templateDetailsAccountCurrencySource.setOnClickListener(
+ v -> selectAccountRowDetailSource(v, AccDetail.CURRENCY));
+ b.templateAccountCurrencySourceLabel.setOnClickListener(
+ v -> selectAccountRowDetailSource(v, AccDetail.CURRENCY));
+ if (accRow.hasLiteralCurrency())
+ b.templateDetailsAccountCurrency.setOnClickListener(v -> {
+ CurrencySelectorFragment cpf = CurrencySelectorFragment.newInstance(
+ CurrencySelectorFragment.DEFAULT_COLUMN_COUNT, false);
+ cpf.setOnCurrencySelectedListener(text -> {
+ if (text == null) {
+ b.templateDetailsAccountCurrency.setText(R.string.btn_no_currency);
+ accRow.setCurrency(null);
+ }
+ else {
+ b.templateDetailsAccountCurrency.setText(text);
+ DB.get()
+ .getCurrencyDAO()
+ .getByName(text)
+ .observe((LifecycleOwner) b.getRoot()
+ .getContext(), accRow::setCurrency);
+ }
+ });
+ cpf.show(
+ ((TemplatesActivity) b.templateDetailsAccountCurrency.getContext()).getSupportFragmentManager(),
+ "currency-selector");
+ });
}
finally {
enableUpdatePropagation();
}
private @NotNull TemplateDetailsItem.AccountRow getItem() {
return differ.getCurrentList()
- .get(getAdapterPosition())
+ .get(getBindingAdapterPosition())
.asAccountRowItem();
}
private void selectAccountRowDetailSource(View v, AccDetail detail) {
case AMOUNT:
accRow.switchToLiteralAmount();
break;
+ case CURRENCY:
+ accRow.switchToLiteralCurrency();
+ break;
default:
throw new IllegalStateException("Unexpected detail " + detail);
}
case AMOUNT:
accRow.setAmountMatchGroup(group);
break;
+ case CURRENCY:
+ accRow.setCurrencyMatchGroup(group);
+ break;
default:
throw new IllegalStateException("Unexpected detail " + detail);
}
}
- notifyItemChanged(getAdapterPosition());
+ notifyItemChanged(getBindingAdapterPosition());
});
final AppCompatActivity activity = (AppCompatActivity) v.getContext();
sel.show(activity.getSupportFragmentManager(), "template-details-source-selector");