X-Git-Url: https://git.ktnx.net/?p=mobile-ledger.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2Fui%2Factivity%2FNewTransactionActivity.java;h=b7770dcc5310f2366ee9a0bb628392f989e8a42e;hp=82fa12d075aedf5ab6ed81174298c86c3c5e9e6b;hb=83cac114e375728080194fb09758b49c50a8119b;hpb=b7f7df30bf96a995f165b3f7e4321655aac0132a diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionActivity.java b/app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionActivity.java index 82fa12d0..b7770dcc 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionActivity.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionActivity.java @@ -18,13 +18,9 @@ package net.ktnx.mobileledger.ui.activity; import android.annotation.SuppressLint; +import android.database.Cursor; +import android.os.AsyncTask; import android.os.Bundle; -import android.support.design.widget.BaseTransientBottomBar; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; @@ -44,32 +40,44 @@ import android.widget.TableRow; import android.widget.TextView; import android.widget.Toast; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.BaseTransientBottomBar; +import com.google.android.material.snackbar.Snackbar; + +import net.ktnx.mobileledger.BuildConfig; import net.ktnx.mobileledger.R; +import net.ktnx.mobileledger.async.DescriptionSelectedCallback; import net.ktnx.mobileledger.async.SaveTransactionTask; import net.ktnx.mobileledger.async.TaskCallback; import net.ktnx.mobileledger.model.Data; import net.ktnx.mobileledger.model.LedgerTransaction; import net.ktnx.mobileledger.model.LedgerTransactionAccount; +import net.ktnx.mobileledger.model.MobileLedgerProfile; import net.ktnx.mobileledger.ui.DatePickerFragment; import net.ktnx.mobileledger.ui.OnSwipeTouchListener; import net.ktnx.mobileledger.utils.Globals; import net.ktnx.mobileledger.utils.MLDB; import java.text.ParseException; +import java.util.ArrayList; import java.util.Date; +import java.util.List; +import java.util.Locale; import java.util.Objects; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.DialogFragment; + /* * TODO: nicer progress while transaction is submitted * TODO: reports * TODO: get rid of the custom session/cookie and auth code? * (the last problem with the POST was the missing content-length header) * TODO: nicer swiping removal with visual feedback - * TODO: setup wizard - * TODO: update accounts/check settings upon change of backend settings * */ -public class NewTransactionActivity extends AppCompatActivity implements TaskCallback { +public class NewTransactionActivity extends ProfileThemedActivity + implements TaskCallback, DescriptionSelectedCallback { private static SaveTransactionTask saver; private TableLayout table; private ProgressBar progress; @@ -82,6 +90,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_transaction); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); @@ -93,7 +102,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal }); tvDescription = findViewById(R.id.new_transaction_description); MLDB.hookAutocompletionAdapter(this, tvDescription, MLDB.DESCRIPTION_HISTORY_TABLE, - "description", false, findViewById(R.id.new_transaction_acc_1)); + "description", false, findViewById(R.id.new_transaction_acc_1), this); hookTextChangeListener(tvDescription); progress = findViewById(R.id.save_transaction_progress); @@ -108,7 +117,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal TextView tvAmount = (TextView) row.getChildAt(1); hookSwipeListener(row); MLDB.hookAutocompletionAdapter(this, tvAccountName, MLDB.ACCOUNTS_TABLE, "name", true, - tvAmount); + tvAmount, null); hookTextChangeListener(tvAccountName); hookTextChangeListener(tvAmount); // Log.d("swipe", "hooked to row "+i); @@ -133,7 +142,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal @Override protected void onStart() { super.onStart(); - if (tvDate.getText().toString().isEmpty()) tvDate.requestFocus(); + if (tvDescription.getText().toString().isEmpty()) tvDescription.requestFocus(); } public void saveTransaction() { if (fab != null) fab.setEnabled(false); @@ -238,10 +247,18 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal }); } + public boolean simulateCrash(MenuItem item) { + Log.d("crash", "Will crash intentionally"); + new AsyncCrasher().execute(); + return true; + } public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.new_transaction, menu); + if (BuildConfig.DEBUG) { + menu.findItem(R.id.action_simulate_crash).setVisible(true); + } check_transaction_submittable(); return true; @@ -276,7 +293,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal }); } - private void doAddAccountRow(boolean focus) { + private TableRow doAddAccountRow(boolean focus) { final AutoCompleteTextView acc = new AutoCompleteTextView(this); acc.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT, 9f)); @@ -296,6 +313,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal amt.setMinWidth(dp2px(40)); amt.setTextAlignment(EditText.TEXT_ALIGNMENT_VIEW_END); amt.setImeOptions(EditorInfo.IME_ACTION_DONE); + amt.setSelectAllOnFocus(true); // forward navigation support final TableRow last_row = (TableRow) table.getChildAt(table.getChildCount() - 1); @@ -317,9 +335,11 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal if (focus) acc.requestFocus(); hookSwipeListener(row); - MLDB.hookAutocompletionAdapter(this, acc, MLDB.ACCOUNTS_TABLE, "name", true, amt); + MLDB.hookAutocompletionAdapter(this, acc, MLDB.ACCOUNTS_TABLE, "name", true, amt, null); hookTextChangeListener(acc); hookTextChangeListener(amt); + + return row; } public void addTransactionAccountFromMenu(MenuItem item) { doAddAccountRow(true); @@ -458,4 +478,84 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal ((TextView) tr.getChildAt(1)).setText(""); } } + @Override + public void descriptionSelected(String description) { + Log.d("descr selected", description); + if (!inputStateIsInitial()) return; + + try (Cursor c = MLDB.getDatabase().rawQuery( + "select profile, id from transactions where description=? order by date desc " + + "limit 1", new String[]{description})) + { + if (!c.moveToNext()) return; + + String profileUUID = c.getString(0); + int transactionId = c.getInt(1); + LedgerTransaction tr; + MobileLedgerProfile profile = null; + for (int i = 0; i < Data.profiles.size(); i++) { + MobileLedgerProfile p = Data.profiles.get(i); + if (p.getUuid().equals(profileUUID)) { + profile = p; + break; + } + } + if (profile == null) throw new RuntimeException(String.format( + "Unable to find profile %s, which is supposed to contain " + + "transaction %d with description %s", profileUUID, transactionId, + description)); + + tr = profile.loadTransaction(transactionId); + int i = 0; + table = findViewById(R.id.new_transaction_accounts_table); + ArrayList accounts = tr.getAccounts(); + TableRow firstNegative = null; + int negativeCount = 0; + for (i = 0; i < accounts.size(); i++) { + LedgerTransactionAccount acc = accounts.get(i); + TableRow row = (TableRow) table.getChildAt(i); + if (row == null) row = doAddAccountRow(false); + + ((TextView) row.getChildAt(0)).setText(acc.getAccountName()); + ((TextView) row.getChildAt(1)) + .setText(String.format(Locale.US, "%1.2f", acc.getAmount())); + + if (acc.getAmount() < 0.005) { + if (firstNegative == null) firstNegative = row; + negativeCount++; + } + } + + if (negativeCount == 1) { + ((TextView) firstNegative.getChildAt(1)).setText(null); + } + + check_transaction_submittable(); + + EditText firstAmount = (EditText) ((TableRow) table.getChildAt(0)).getChildAt(1); + String amtString = String.valueOf(firstAmount.getText()); + firstAmount.requestFocus(); + firstAmount.setSelection(0, amtString.length()); + } + + } + private boolean inputStateIsInitial() { + table = findViewById(R.id.new_transaction_accounts_table); + + if (table.getChildCount() != 2) return false; + + for (int i = 0; i < 2; i++) { + TableRow row = (TableRow) table.getChildAt(i); + if (((TextView) row.getChildAt(0)).getText().length() > 0) return false; + if (((TextView) row.getChildAt(1)).getText().length() > 0) return false; + } + + return true; + } + private class AsyncCrasher extends AsyncTask{ + @Override + protected Void doInBackground(Void... voids) { + throw new RuntimeException("Simulated crash"); + } + } }