From c6fe580ac5a93cff593d95a0fe34bd6c2c7bddfc Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Thu, 14 Mar 2019 22:05:02 +0200 Subject: [PATCH] put account expansion bracket after the name, fix rotation animation --- .../async/CommitAccountsTask.java | 8 +- .../async/RetrieveTransactionsTask.java | 10 +- .../async/UpdateAccountsTask.java | 23 ++--- .../mobileledger/model/LedgerAccount.java | 87 +++++++++++------ .../model/MobileLedgerProfile.java | 95 ++++++++++++++++--- .../AccountSummaryAdapter.java | 53 +++++++---- .../AccountSummaryFragment.java | 80 ++++++++-------- .../AccountSummaryViewModel.java | 4 +- .../ui/activity/MainActivity.java | 71 +++++++++++++- .../net/ktnx/mobileledger/utils/MLDB.java | 2 +- .../drawable/ic_expand_less_black_24dp.xml | 23 +++++ .../res/layout/account_summary_fragment.xml | 7 +- .../main/res/layout/account_summary_row.xml | 87 ++++++++++++----- app/src/main/res/raw/sql_19.sql | 2 + 14 files changed, 395 insertions(+), 157 deletions(-) create mode 100644 app/src/main/res/drawable/ic_expand_less_black_24dp.xml create mode 100644 app/src/main/res/raw/sql_19.sql diff --git a/app/src/main/java/net/ktnx/mobileledger/async/CommitAccountsTask.java b/app/src/main/java/net/ktnx/mobileledger/async/CommitAccountsTask.java index f038f3aa..7368d712 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/CommitAccountsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/CommitAccountsTask.java @@ -40,12 +40,12 @@ public class CommitAccountsTask try { for (LedgerAccount acc : params[0].accountList) { Log.d("CAT", String.format("Setting %s to %s", acc.getName(), - acc.isHiddenToBe() ? "hidden" : "starred")); + acc.isHiddenByStarToBe() ? "hidden" : "starred")); db.execSQL("UPDATE accounts SET hidden=? WHERE profile=? AND name=?", - new Object[]{acc.isHiddenToBe() ? 1 : 0, profile, acc.getName()}); + new Object[]{acc.isHiddenByStarToBe() ? 1 : 0, profile, acc.getName()}); - acc.setHidden(acc.isHiddenToBe()); - if (!params[0].showOnlyStarred || !acc.isHidden()) newList.add(acc); + acc.setHiddenByStar(acc.isHiddenByStarToBe()); + if (!params[0].showOnlyStarred || !acc.isHiddenByStar()) newList.add(acc); } db.setTransactionSuccessful(); } diff --git a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java index 47154b0b..dfb1f745 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java @@ -169,11 +169,11 @@ public class RetrieveTransactionsTask acct_name = acct_name.replace("\"", ""); L(String.format("found account: %s", acct_name)); - lastAccount = profile.loadAccount(acct_name); + lastAccount = profile.tryLoadAccount(db, acct_name); if (lastAccount == null) { lastAccount = new LedgerAccount(acct_name); - profile.storeAccount(db, lastAccount); } + profile.storeAccount(db, lastAccount); // make sure the parent account(s) are present, // synthesising them if necessary @@ -189,8 +189,8 @@ public class RetrieveTransactionsTask while (!toAppend.isEmpty()) { String aName = toAppend.pop(); LedgerAccount acc = new LedgerAccount(aName); - acc.setHidden(lastAccount.isHidden()); - if (!onlyStarred || !acc.isHidden()) + acc.setHiddenByStar(lastAccount.isHiddenByStar()); + if (!onlyStarred || !acc.isHiddenByStar()) accountList.add(acc); L(String.format("gap-filling with %s", aName)); accountNames.put(aName, null); @@ -198,7 +198,7 @@ public class RetrieveTransactionsTask } } - if (!onlyStarred || !lastAccount.isHidden()) + if (!onlyStarred || !lastAccount.isHiddenByStar()) accountList.add(lastAccount); accountNames.put(acct_name, null); diff --git a/app/src/main/java/net/ktnx/mobileledger/async/UpdateAccountsTask.java b/app/src/main/java/net/ktnx/mobileledger/async/UpdateAccountsTask.java index 8d17a548..ad030ef6 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/UpdateAccountsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/UpdateAccountsTask.java @@ -24,6 +24,7 @@ import android.util.Log; import net.ktnx.mobileledger.model.Data; import net.ktnx.mobileledger.model.LedgerAccount; +import net.ktnx.mobileledger.model.MobileLedgerProfile; import net.ktnx.mobileledger.utils.MLDB; import java.util.ArrayList; @@ -32,13 +33,14 @@ public class UpdateAccountsTask extends AsyncTask doInBackground(Void... params) { Data.backgroundTaskCount.incrementAndGet(); try { - String profileUUID = Data.profile.get().getUuid(); + MobileLedgerProfile profile = Data.profile.get(); + String profileUUID = profile.getUuid(); boolean onlyStarred = Data.optShowOnlyStarred.get(); ArrayList newList = new ArrayList<>(); - String sql = "SELECT name, hidden FROM accounts WHERE profile = ?"; - if (onlyStarred) sql += " AND hidden = 0"; - sql += " ORDER BY name"; + String sql = "SELECT a.name from accounts a WHERE a.profile = ?"; + if (onlyStarred) sql += " AND a.hidden = 0"; + sql += " ORDER BY a.name"; SQLiteDatabase db = MLDB.getReadableDatabase(); try (Cursor cursor = db.rawQuery(sql, new String[]{profileUUID})) { @@ -46,17 +48,8 @@ public class UpdateAccountsTask extends AsyncTask amounts; - static Pattern reHigherAccount = Pattern.compile("^[^:]+:"); + private boolean hasSubAccounts; public LedgerAccount(String name) { this.setName(name); - hidden = false; - } - - public boolean isHidden() { - return hidden; - } - - public void setHidden(boolean hidden) { - this.hidden = hidden; + hiddenByStar = false; } public LedgerAccount(String name, float amount) { this.setName(name); - this.hidden = false; + this.hiddenByStar = false; + this.expanded = true; this.amounts = new ArrayList(); this.addAmount(amount); } + // an account is visible if: + // - it is starred (not hidden by a star) + // - and it has an expanded parent or is a top account + public boolean isVisible() { + if (hiddenByStar) return false; - public void setName(String name) { - this.name = name; - stripName(); - } + if (level == 0) return true; + return isVisible(Data.accounts.get()); + } + public boolean isVisible(ArrayList list) { + for (LedgerAccount acc : list) { + if (acc.isParentOf(this)) { + if (!acc.isExpanded()) return false; + } + } + return true; + } + public boolean isParentOf(LedgerAccount potentialChild) { + return potentialChild.getName().startsWith(name + ":"); + } + public boolean isHiddenByStar() { + return hiddenByStar; + } + public void setHiddenByStar(boolean hiddenByStar) { + this.hiddenByStar = hiddenByStar; + } private void stripName() { level = 0; shortName = name; @@ -76,13 +92,15 @@ public class LedgerAccount { parentName = parentBuilder.substring(0, parentBuilder.length() - 1); else parentName = null; } - public String getName() { return name; } - + public void setName(String name) { + this.name = name; + stripName(); + } public void addAmount(float amount, String currency) { - if (amounts == null ) amounts = new ArrayList<>(); + if (amounts == null) amounts = new ArrayList<>(); amounts.add(new LedgerAmount(amount, currency)); } public void addAmount(float amount) { @@ -93,7 +111,7 @@ public class LedgerAccount { if ((amounts == null) || amounts.isEmpty()) return ""; StringBuilder builder = new StringBuilder(); - for( LedgerAmount amount : amounts ) { + for (LedgerAmount amount : amounts) { String amt = amount.toString(); if (builder.length() > 0) builder.append('\n'); builder.append(amt); @@ -115,16 +133,31 @@ public class LedgerAccount { return parentName; } public void togglehidden() { - hidden = !hidden; + hiddenByStar = !hiddenByStar; } - public boolean isHiddenToBe() { - return hiddenToBe; + public boolean isHiddenByStarToBe() { + return hiddenByStarToBe; } - public void setHiddenToBe(boolean hiddenToBe) { - this.hiddenToBe = hiddenToBe; + public void setHiddenByStarToBe(boolean hiddenByStarToBe) { + this.hiddenByStarToBe = hiddenByStarToBe; } public void toggleHiddenToBe() { - setHiddenToBe(!hiddenToBe); + setHiddenByStarToBe(!hiddenByStarToBe); + } + public boolean hasSubAccounts() { + return hasSubAccounts; + } + public void setHasSubAccounts(boolean hasSubAccounts) { + this.hasSubAccounts = hasSubAccounts; + } + public boolean isExpanded() { + return expanded; + } + public void setExpanded(boolean expanded) { + this.expanded = expanded; + } + public void toggleExpanded() { + expanded = !expanded; } } diff --git a/app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java b/app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java index ec204d9a..17b6ac7a 100644 --- a/app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java +++ b/app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java @@ -29,6 +29,9 @@ import java.util.Date; import java.util.List; import java.util.UUID; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + public final class MobileLedgerProfile { private String uuid; private String name; @@ -185,12 +188,16 @@ public final class MobileLedgerProfile { public void storeAccount(SQLiteDatabase db, LedgerAccount acc) { // replace into is a bad idea because it would reset hidden to its default value // we like the default, but for new accounts only - db.execSQL("update accounts set level = ?, keep = 1 where profile=? and name = ?", - new Object[]{acc.getLevel(), uuid, acc.getName()}); - db.execSQL("insert into accounts(profile, name, name_upper, parent_name, level, keep) " + - "select ?,?,?,?,?,1 where (select changes() = 0)", + db.execSQL("update accounts set level = ?, keep = 1, hidden=?, expanded=? " + + "where profile=? and name = ?", + new Object[]{acc.getLevel(), acc.isHiddenByStar(), acc.isExpanded(), uuid, + acc.getName() + }); + db.execSQL( + "insert into accounts(profile, name, name_upper, parent_name, level, hidden, expanded, keep) " + + "select ?,?,?,?,?,?,?,1 where (select changes() = 0)", new Object[]{uuid, acc.getName(), acc.getName().toUpperCase(), acc.getParentName(), - acc.getLevel() + acc.getLevel(), acc.isHiddenByStar(), acc.isExpanded() }); // Log.d("accounts", String.format("Stored account '%s' in DB [%s]", acc.getName(), uuid)); } @@ -278,20 +285,50 @@ public final class MobileLedgerProfile { Log.d("db", String.format("removing progile %s from DB", uuid)); db.execSQL("delete from profiles where uuid=?", new Object[]{uuid}); } + @NonNull public LedgerAccount loadAccount(String name) { SQLiteDatabase db = MLDB.getReadableDatabase(); - try (Cursor cursor = db.rawQuery("SELECT hidden from accounts where profile=? and name=?", - new String[]{uuid, name})) + return loadAccount(db, name); + } + @Nullable + public LedgerAccount tryLoadAccount(String acct_name) { + SQLiteDatabase db = MLDB.getReadableDatabase(); + return loadAccount(acct_name); + } + @NonNull + public LedgerAccount loadAccount(SQLiteDatabase db, String accName) { + LedgerAccount acc = tryLoadAccount(db, accName); + + if (acc == null) throw new RuntimeException("Unable to load account with name "+accName); + + return acc; + } + @Nullable + public LedgerAccount tryLoadAccount(SQLiteDatabase db, String accName) { + try (Cursor cursor = db.rawQuery( + "SELECT a.hidden, a.expanded, (select 1 from accounts a2 " + + "where a2.profile = a.profile and a2.name like a.name||':%' limit 1) " + + "FROM accounts a WHERE a.profile = ? and a.name=?", new String[]{uuid, accName})) { if (cursor.moveToFirst()) { - LedgerAccount acc = new LedgerAccount(name); - acc.setHidden(cursor.getInt(0) == 1); + LedgerAccount acc = new LedgerAccount(accName); + acc.setHiddenByStar(cursor.getInt(0) == 1); + acc.setExpanded(cursor.getInt(1) == 1); + acc.setHasSubAccounts(cursor.getInt(2) == 1); + + try (Cursor c2 = db.rawQuery( + "SELECT value, currency FROM account_values WHERE profile = ? " + + "AND account = ?", new String[]{uuid, accName})) + { + while (c2.moveToNext()) { + acc.addAmount(c2.getFloat(0), c2.getString(1)); + } + } return acc; } + return null; } - - return null; } public LedgerTransaction loadTransaction(int transactionId) { LedgerTransaction tr = new LedgerTransaction(transactionId, this.uuid); @@ -344,4 +381,40 @@ public final class MobileLedgerProfile { setLongOption(MLDB.OPT_LAST_SCRAPE, now.getTime()); Data.lastUpdateDate.set(now); } + public List loadChildAccountsOf(LedgerAccount acc) { + List result = new ArrayList<>(); + SQLiteDatabase db = MLDB.getReadableDatabase(); + try (Cursor c = db.rawQuery( + "SELECT a.name FROM accounts a WHERE a.profile = ? and a.name like ?||':%'", + new String[]{uuid, acc.getName()})) + { + while (c.moveToNext()) { + LedgerAccount a = loadAccount(db, c.getString(0)); + result.add(a); + } + } + + return result; + } + public List loadVisibleChildAccountsOf(LedgerAccount acc) { + List result = new ArrayList<>(); + ArrayList visibleList = new ArrayList<>(); + visibleList.add(acc); + + SQLiteDatabase db = MLDB.getReadableDatabase(); + try (Cursor c = db.rawQuery( + "SELECT a.name FROM accounts a WHERE a.profile = ? and a.name like ?||':%'", + new String[]{uuid, acc.getName()})) + { + while (c.moveToNext()) { + LedgerAccount a = loadAccount(db, c.getString(0)); + if (a.isVisible(visibleList)) { + result.add(a); + visibleList.add(a); + } + } + } + + return result; + } } diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryAdapter.java b/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryAdapter.java index 086f0cb1..d9df87d5 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryAdapter.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryAdapter.java @@ -24,20 +24,22 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; -import android.widget.LinearLayout; +import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.TextView; import net.ktnx.mobileledger.R; import net.ktnx.mobileledger.model.Data; import net.ktnx.mobileledger.model.LedgerAccount; -import net.ktnx.mobileledger.utils.Colors; import java.util.List; import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; import androidx.recyclerview.widget.RecyclerView; -class AccountSummaryAdapter extends RecyclerView.Adapter { +public class AccountSummaryAdapter + extends RecyclerView.Adapter { private boolean selectionActive; AccountSummaryAdapter() { @@ -51,15 +53,20 @@ class AccountSummaryAdapter extends RecyclerView.Adapter { + int w = right - left; + int h = bottom - top; + if (h > w) { + int p = (h - w) / 2; + v.setPadding(0, p, 0, p); + } + else v.setPadding(0, 0, 0, 0); + }); } } } diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryFragment.java b/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryFragment.java index dd4e4d49..5fd47f14 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryFragment.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryFragment.java @@ -33,17 +33,15 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import net.ktnx.mobileledger.R; import net.ktnx.mobileledger.model.Data; -import net.ktnx.mobileledger.model.LedgerAccount; import net.ktnx.mobileledger.ui.MobileLedgerListFragment; -import net.ktnx.mobileledger.ui.RecyclerItemListener; import net.ktnx.mobileledger.ui.activity.MainActivity; import net.ktnx.mobileledger.utils.Colors; -import java.util.List; import java.util.Observer; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -52,7 +50,7 @@ import static net.ktnx.mobileledger.ui.activity.SettingsActivity.PREF_KEY_SHOW_O public class AccountSummaryFragment extends MobileLedgerListFragment { MenuItem mShowOnlyStarred; - private AccountSummaryAdapter modelAdapter; + public AccountSummaryAdapter modelAdapter; private Menu optMenu; private FloatingActionButton fab; private Observer backgroundTaskCountObserver; @@ -101,48 +99,51 @@ public class AccountSummaryFragment extends MobileLedgerListFragment { modelAdapter = new AccountSummaryAdapter(); + mActivity.mAccountSummaryFragment = this; root = mActivity.findViewById(R.id.account_root); LinearLayoutManager llm = new LinearLayoutManager(mActivity); llm.setOrientation(RecyclerView.VERTICAL); root.setLayoutManager(llm); root.setAdapter(modelAdapter); + DividerItemDecoration did = new DividerItemDecoration(mActivity, DividerItemDecoration.VERTICAL); + root.addItemDecoration(did); fab = mActivity.findViewById(R.id.btn_add_transaction); - root.addOnItemTouchListener(new RecyclerItemListener(mActivity, root, - new RecyclerItemListener.RecyclerTouchListener() { - @Override - public void onClickItem(View v, int position) { - Log.d("value", String.format("item %d clicked", position)); - if (modelAdapter.isSelectionActive()) { - modelAdapter.selectItem(position); - } - else { - List accounts = Data.accounts.get(); - if (accounts != null) { - LedgerAccount account = accounts.get(position); - - mActivity.showAccountTransactions(account); - } - } - } - - @Override - public void onLongClickItem(View v, int position) { - Log.d("value", String.format("item %d long-clicked", position)); - modelAdapter.startSelection(); - if (optMenu != null) { - optMenu.findItem(R.id.menu_acc_summary_cancel_selection) - .setVisible(true); - optMenu.findItem(R.id.menu_acc_summary_confirm_selection) - .setVisible(true); - optMenu.findItem(R.id.menu_acc_summary_only_starred).setVisible(false); - } - { - if (fab != null) fab.hide(); - } - } - })); +// root.addOnItemTouchListener(new RecyclerItemListener(mActivity, root, +// new RecyclerItemListener.RecyclerTouchListener() { +// @Override +// public void onClickItem(View v, int position) { +// Log.d("value", String.format("item %d clicked", position)); +// if (modelAdapter.isSelectionActive()) { +// modelAdapter.selectItem(position); +// } +// else { +// List accounts = Data.accounts.get(); +// if (accounts != null) { +// LedgerAccount account = accounts.get(position); +// +// mActivity.showAccountTransactions(account); +// } +// } +// } +// +// @Override +// public void onLongClickItem(View v, int position) { +// Log.d("value", String.format("item %d long-clicked", position)); +// modelAdapter.startSelection(); +// if (optMenu != null) { +// optMenu.findItem(R.id.menu_acc_summary_cancel_selection) +// .setVisible(true); +// optMenu.findItem(R.id.menu_acc_summary_confirm_selection) +// .setVisible(true); +// optMenu.findItem(R.id.menu_acc_summary_only_starred).setVisible(false); +// } +// { +// if (fab != null) fab.hide(); +// } +// } +// })); mActivity.fabShouldShow(); root.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -155,8 +156,7 @@ public class AccountSummaryFragment extends MobileLedgerListFragment { } }); swiper = mActivity.findViewById(R.id.account_swiper); - Colors.themeWatch.addObserver( - (o, arg) -> swiper.setColorSchemeColors(Colors.primary)); + Colors.themeWatch.addObserver((o, arg) -> swiper.setColorSchemeColors(Colors.primary)); swiper.setColorSchemeColors(Colors.primary); swiper.setOnRefreshListener(() -> { Log.d("ui", "refreshing accounts via swipe"); diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryViewModel.java b/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryViewModel.java index 4d210534..7a7164f3 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryViewModel.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryViewModel.java @@ -31,13 +31,13 @@ import java.util.ArrayList; import androidx.lifecycle.ViewModel; -class AccountSummaryViewModel extends ViewModel { +public class AccountSummaryViewModel extends ViewModel { static void commitSelections(Context context) { CAT task = new CAT(); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new CommitAccountsTaskParams(Data.accounts.get(), Data.optShowOnlyStarred.get())); } - static void scheduleAccountListReload() { + static public void scheduleAccountListReload() { if (Data.profile.get() == null) return; UAT task = new UAT(); diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java b/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java index 4202a84c..87774073 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java @@ -27,6 +27,7 @@ import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.ViewGroup; +import android.view.ViewPropertyAnimator; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.LinearLayout; @@ -52,7 +53,9 @@ import net.ktnx.mobileledger.utils.MLDB; import java.lang.ref.WeakReference; import java.text.DateFormat; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import java.util.Observable; import java.util.Observer; @@ -70,6 +73,7 @@ import androidx.viewpager.widget.ViewPager; public class MainActivity extends ProfileThemedActivity { private static final String STATE_CURRENT_PAGE = "current_page"; private static final String BUNDLE_SAVED_STATE = "bundle_savedState"; + public AccountSummaryFragment mAccountSummaryFragment; DrawerLayout drawer; private LinearLayout profileListContainer; private View profileListHeadArrow, profileListHeadMore, profileListHeadCancel; @@ -86,7 +90,6 @@ public class MainActivity extends ProfileThemedActivity { private boolean profileModificationEnabled = false; private boolean profileListExpanded = false; private ProfilesRecyclerViewAdapter mProfileListAdapter; - @Override protected void onStart() { super.onStart(); @@ -551,6 +554,68 @@ public class MainActivity extends ProfileThemedActivity { // FIXME disable rearranging } + public void onAccountSummaryRowViewClicked(View view) { + ViewGroup row = (ViewGroup) view.getParent(); + if (view.getId() == R.id.account_expander_container) { + Log.d("accounts", "Account expander clicked"); + LedgerAccount acc = (LedgerAccount) row.getTag(); + if (!acc.hasSubAccounts()) return; + + boolean wasExpanded = acc.isExpanded(); + + view.clearAnimation(); + ViewPropertyAnimator animator = view.animate(); + + acc.toggleExpanded(); + Data.profile.get().storeAccount(MLDB.getWritableDatabase(), acc); + + if (wasExpanded) { + Log.d("accounts", String.format("Collapsing account '%s'", acc.getName())); + animator.rotationBy(180); + + // removing all child accounts from the view + int start = -1, count = 0; + int i = 0; + final ArrayList accountList = Data.accounts.get(); + for (LedgerAccount a : accountList) { + if (acc.isParentOf(a)) { + if (start == -1) { + start = i; + } + count++; + } + else { + if (start != -1) { + break; + } + } + i++; + } + + if (start != -1) { + for (int j = 0; j < count; j++) { + Log.d("accounts", String.format("Removing item %d: %s", start + j, + accountList.get(start).getName())); + accountList.remove(start); + } + + mAccountSummaryFragment.modelAdapter.notifyItemRangeRemoved(start, count); + } + } + else { + Log.d("accounts", String.format("Expanding account '%s'", acc.getName())); + animator.rotationBy(-180); + ArrayList accounts = Data.accounts.get(); + List children = Data.profile.get().loadVisibleChildAccountsOf(acc); + int parentPos = accounts.indexOf(acc); + if (parentPos == -1) throw new RuntimeException( + "Can't find index of clicked account " + acc.getName()); + accounts.addAll(parentPos + 1, children); + mAccountSummaryFragment.modelAdapter + .notifyItemRangeInserted(parentPos + 1, children.size()); + } + } + } public class SectionsPagerAdapter extends FragmentPagerAdapter { @@ -563,7 +628,8 @@ public class MainActivity extends ProfileThemedActivity { Log.d("main", String.format("Switching to fragment %d", position)); switch (position) { case 0: - return new AccountSummaryFragment(); +// Log.d("flow", "Creating account summary fragment"); + return mAccountSummaryFragment = new AccountSummaryFragment(); case 1: return new TransactionListFragment(); default: @@ -577,5 +643,4 @@ public class MainActivity extends ProfileThemedActivity { return 2; } } - } diff --git a/app/src/main/java/net/ktnx/mobileledger/utils/MLDB.java b/app/src/main/java/net/ktnx/mobileledger/utils/MLDB.java index 328d8c97..7da81f97 100644 --- a/app/src/main/java/net/ktnx/mobileledger/utils/MLDB.java +++ b/app/src/main/java/net/ktnx/mobileledger/utils/MLDB.java @@ -222,7 +222,7 @@ public final class MLDB { class MobileLedgerDatabase extends SQLiteOpenHelper implements AutoCloseable { public static final String DB_NAME = "MoLe.db"; - public static final int LATEST_REVISION = 18; + public static final int LATEST_REVISION = 19; private final Application mContext; diff --git a/app/src/main/res/drawable/ic_expand_less_black_24dp.xml b/app/src/main/res/drawable/ic_expand_less_black_24dp.xml new file mode 100644 index 00000000..14e4ec1b --- /dev/null +++ b/app/src/main/res/drawable/ic_expand_less_black_24dp.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/app/src/main/res/layout/account_summary_fragment.xml b/app/src/main/res/layout/account_summary_fragment.xml index 4b1e9269..441c60c9 100644 --- a/app/src/main/res/layout/account_summary_fragment.xml +++ b/app/src/main/res/layout/account_summary_fragment.xml @@ -1,5 +1,4 @@ - -