X-Git-Url: https://git.ktnx.net/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2Fui%2Fnew_transaction%2FNewTransactionActivity.java;h=50b8c63ea508513dac4aafc5161d2f1920c77b4a;hb=5eadaa3fd9348a396f541ee96a8608dd200e8a7f;hp=ab28ca16d05a2ff43d5d57404692c17a8f021177;hpb=346b3c8e74a12b1822239481f807479fa81fc706;p=mobile-ledger.git diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/new_transaction/NewTransactionActivity.java b/app/src/main/java/net/ktnx/mobileledger/ui/new_transaction/NewTransactionActivity.java index ab28ca16..50b8c63e 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/new_transaction/NewTransactionActivity.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/new_transaction/NewTransactionActivity.java @@ -17,44 +17,46 @@ package net.ktnx.mobileledger.ui.new_transaction; +import android.content.Context; import android.content.Intent; import android.database.AbstractCursor; -import android.database.Cursor; +import android.os.AsyncTask; import android.os.Bundle; import android.os.ParcelFormatException; -import android.text.TextUtils; import android.util.TypedValue; import android.view.Menu; import android.view.MenuItem; import android.view.View; import androidx.activity.result.ActivityResultLauncher; -import androidx.annotation.NonNull; +import androidx.core.view.MenuCompat; import androidx.lifecycle.LiveData; import androidx.lifecycle.ViewModelProvider; import androidx.navigation.NavController; import androidx.navigation.fragment.NavHostFragment; import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.snackbar.Snackbar; import net.ktnx.mobileledger.BuildConfig; import net.ktnx.mobileledger.R; -import net.ktnx.mobileledger.async.AsyncCrasher; import net.ktnx.mobileledger.async.DescriptionSelectedCallback; +import net.ktnx.mobileledger.async.GeneralBackgroundTasks; import net.ktnx.mobileledger.async.SendTransactionTask; import net.ktnx.mobileledger.async.TaskCallback; +import net.ktnx.mobileledger.dao.TransactionDAO; import net.ktnx.mobileledger.databinding.ActivityNewTransactionBinding; import net.ktnx.mobileledger.db.DB; import net.ktnx.mobileledger.db.TemplateHeader; +import net.ktnx.mobileledger.db.TransactionWithAccounts; import net.ktnx.mobileledger.model.Data; import net.ktnx.mobileledger.model.LedgerTransaction; import net.ktnx.mobileledger.model.MatchedTemplate; +import net.ktnx.mobileledger.ui.FabManager; import net.ktnx.mobileledger.ui.QR; import net.ktnx.mobileledger.ui.activity.ProfileThemedActivity; +import net.ktnx.mobileledger.ui.activity.SplashActivity; import net.ktnx.mobileledger.ui.templates.TemplatesActivity; import net.ktnx.mobileledger.utils.Logger; -import net.ktnx.mobileledger.utils.MLDB; import net.ktnx.mobileledger.utils.Misc; import java.util.ArrayList; @@ -67,11 +69,14 @@ import static net.ktnx.mobileledger.utils.Logger.debug; public class NewTransactionActivity extends ProfileThemedActivity implements TaskCallback, NewTransactionFragment.OnNewTransactionFragmentInteractionListener, - QR.QRScanTrigger, QR.QRScanResultReceiver, DescriptionSelectedCallback { + QR.QRScanTrigger, QR.QRScanResultReceiver, DescriptionSelectedCallback, + FabManager.FabHandler { + final String TAG = "new-t-a"; private NavController navController; private NewTransactionModel model; private ActivityResultLauncher qrScanLauncher; private ActivityNewTransactionBinding b; + private FabManager fabManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -79,8 +84,17 @@ public class NewTransactionActivity extends ProfileThemedActivity b = ActivityNewTransactionBinding.inflate(getLayoutInflater(), null, false); setContentView(b.getRoot()); setSupportActionBar(b.toolbar); - Data.observeProfile(this, - mobileLedgerProfile -> b.toolbar.setSubtitle(mobileLedgerProfile.getName())); + Data.observeProfile(this, profile -> { + if (profile == null) { + Logger.debug("new-t-act", "no active profile. Redirecting to SplashActivity"); + Intent intent = new Intent(this, SplashActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); + } + else + b.toolbar.setSubtitle(profile.getName()); + }); NavHostFragment navHostFragment = (NavHostFragment) Objects.requireNonNull( getSupportFragmentManager().findFragmentById(R.id.new_transaction_nav)); @@ -93,33 +107,40 @@ public class NewTransactionActivity extends ProfileThemedActivity qrScanLauncher = QR.registerLauncher(this, this); + fabManager = new FabManager(b.fabAdd); + model.isSubmittable() .observe(this, isSubmittable -> { if (isSubmittable) { - b.fabAdd.show(); + fabManager.showFab(); } else { - b.fabAdd.hide(); + fabManager.hideFab(); } }); // viewModel.checkTransactionSubmittable(listAdapter); b.fabAdd.setOnClickListener(v -> onFabPressed()); - - } @Override protected void initProfile() { - String profileUUID = getIntent().getStringExtra("profile_uuid"); + long profileId = getIntent().getLongExtra(PARAM_PROFILE_ID, 0); + int profileHue = getIntent().getIntExtra(PARAM_THEME, -1); - if (profileUUID != null) { - mProfile = Data.getProfile(profileUUID); - if (mProfile == null) - finish(); - Data.setCurrentProfile(mProfile); + if (profileHue < 0) { + Logger.debug(TAG, "Started with invalid/missing theme; quitting"); + finish(); + return; + } + + if (profileId <= 0) { + Logger.debug(TAG, "Started with invalid/missing profile_id; quitting"); + finish(); + return; } - else - super.initProfile(); + + setupProfileColors(profileHue); + initProfile(profileId); } @Override public void finish() { @@ -143,27 +164,33 @@ public class NewTransactionActivity extends ProfileThemedActivity saver.execute(tr); } catch (Exception e) { - debug("new-transaction", "Unknown error", e); + debug("new-transaction", "Unknown error: " + e); Bundle b = new Bundle(); b.putString("error", "unknown error"); navController.navigate(R.id.newTransactionFragment, b); } } - public void simulateCrash(MenuItem item) { + public boolean onSimulateCrashMenuItemClicked(MenuItem item) { debug("crash", "Will crash intentionally"); - new AsyncCrasher().execute(); + GeneralBackgroundTasks.run(() -> { throw new RuntimeException("Simulated crash");}); + return true; } public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + + if (!BuildConfig.DEBUG) + return true; + // 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); - menu.findItem(R.id.action_simulate_save) - .setVisible(true); - } + MenuCompat.setGroupDividerEnabled(menu, true); + + menu.findItem(R.id.action_simulate_save) + .setOnMenuItemClickListener(this::onToggleSimulateSaveMenuItemClicked); + menu.findItem(R.id.action_simulate_crash) + .setOnMenuItemClickListener(this::onSimulateCrashMenuItemClicked); model.getSimulateSave() .observe(this, state -> { @@ -181,17 +208,27 @@ public class NewTransactionActivity extends ProfileThemedActivity getResources().getDisplayMetrics())); } @Override - public void done(String error) { + public void onTransactionSaveDone(String error, Object arg) { Bundle b = new Bundle(); if (error != null) { b.putString("error", error); navController.navigate(R.id.action_newTransactionSavingFragment_Failure, b); } - else + else { navController.navigate(R.id.action_newTransactionSavingFragment_Success, b); + + AsyncTask.execute(() -> commitToDb((LedgerTransaction) arg)); + } + } + public void commitToDb(LedgerTransaction tr) { + TransactionWithAccounts dbTransaction = tr.toDBO(); + DB.get() + .getTransactionDAO() + .appendSync(dbTransaction); } - public void toggleSimulateSave(MenuItem item) { + public boolean onToggleSimulateSaveMenuItemClicked(MenuItem item) { model.toggleSimulateSave(); + return true; } @Override @@ -324,99 +361,48 @@ public class NewTransactionActivity extends ProfileThemedActivity .create() .show(); } - public void descriptionSelected(String description) { + public void onDescriptionSelected(String description) { debug("description selected", description); if (!model.accountListIsEmpty()) return; - String accFilter = mProfile.getPreferredAccountsFilter(); + AsyncTask.execute(() -> { + String accFilter = mProfile.getPreferredAccountsFilter(); - ArrayList params = new ArrayList<>(); - StringBuilder sb = new StringBuilder("select t.profile, t.id from transactions t"); + TransactionDAO trDao = DB.get() + .getTransactionDAO(); - if (!TextUtils.isEmpty(accFilter)) { - sb.append(" JOIN transaction_accounts ta") - .append(" ON ta.profile = t.profile") - .append(" AND ta.transaction_id = t.id"); - } - - sb.append(" WHERE t.description=?"); - params.add(description); + TransactionWithAccounts tr = null; - if (!TextUtils.isEmpty(accFilter)) { - sb.append(" AND ta.account_name LIKE '%'||?||'%'"); - params.add(accFilter); - } + if (Misc.emptyIsNull(accFilter) != null) + tr = trDao.getFirstByDescriptionHavingAccountSync(description, accFilter); + if (tr == null) + tr = trDao.getFirstByDescriptionSync(description); - sb.append(" ORDER BY t.year desc, t.month desc, t.day desc LIMIT 1"); - - final String sql = sb.toString(); - debug("description", sql); - debug("description", params.toString()); - - // FIXME: handle exceptions? - MLDB.queryInBackground(sql, params.toArray(new String[]{}), new MLDB.CallbackHelper() { - @Override - public void onStart() { - model.incrementBusyCounter(); - } - @Override - public void onDone() { - model.decrementBusyCounter(); - } - @Override - public boolean onRow(@NonNull Cursor cursor) { - final String profileUUID = cursor.getString(0); - final int transactionId = cursor.getInt(1); - runOnUiThread(() -> model.loadTransactionIntoModel(profileUUID, transactionId)); - return false; // limit 1, by the way - } - @Override - public void onNoRows() { - if (TextUtils.isEmpty(accFilter)) - return; - - debug("description", "Trying transaction search without preferred account filter"); - - final String broaderSql = - "select t.profile, t.id from transactions t where t.description=?" + - " ORDER BY year desc, month desc, day desc LIMIT 1"; - params.remove(1); - debug("description", broaderSql); - debug("description", description); - - runOnUiThread(() -> Snackbar.make(b.newTransactionNav, - R.string.ignoring_preferred_account, Snackbar.LENGTH_INDEFINITE) - .show()); - - MLDB.queryInBackground(broaderSql, new String[]{description}, - new MLDB.CallbackHelper() { - @Override - public void onStart() { - model.incrementBusyCounter(); - } - @Override - public boolean onRow(@NonNull Cursor cursor) { - final String profileUUID = cursor.getString(0); - final int transactionId = cursor.getInt(1); - runOnUiThread(() -> model.loadTransactionIntoModel(profileUUID, - transactionId)); - return false; - } - @Override - public void onDone() { - model.decrementBusyCounter(); - } - }); - } + if (tr != null) + model.loadTransactionIntoModel(tr); }); } private void onFabPressed() { - b.fabAdd.hide(); + fabManager.hideFab(); Misc.hideSoftKeyboard(this); LedgerTransaction tr = model.constructLedgerTransaction(); onTransactionSave(tr); } + @Override + public Context getContext() { + return this; + } + @Override + public void showManagedFab() { + if (Objects.requireNonNull(model.isSubmittable() + .getValue())) + fabManager.showFab(); + } + @Override + public void hideManagedFab() { + fabManager.hideFab(); + } }