From 18cc90fd341614bb30a321a7e790ff089828b76e Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Tue, 19 Mar 2024 04:45:23 +0000 Subject: [PATCH 1/6] release v0.21.7 (56) --- CHANGES.md | 7 +++++++ app/build.gradle | 4 ++-- metadata/bg-BG/changelogs/56.txt | 4 ++++ metadata/en-US/changelogs/56.txt | 4 ++++ 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 metadata/bg-BG/changelogs/56.txt create mode 100644 metadata/en-US/changelogs/56.txt diff --git a/CHANGES.md b/CHANGES.md index e8b5efc7..02f84284 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,12 @@ # Changes +## [0.21.7] = 2024-03-19 + +* FIXES: + + allow user certificates in network security config +* OTHERS: + + bump gradle version + ## [0.21.6] - 2023-06-20 * FIXES diff --git a/app/build.gradle b/app/build.gradle index 7b29013a..71673f6e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -24,8 +24,8 @@ android { minSdkVersion 22 targetSdkVersion 31 vectorDrawables.useSupportLibrary true - versionCode 55 - versionName '0.21.6' + versionCode 56 + versionName '0.21.7' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" javaCompileOptions { annotationProcessorOptions { diff --git a/metadata/bg-BG/changelogs/56.txt b/metadata/bg-BG/changelogs/56.txt new file mode 100644 index 00000000..218ba4a3 --- /dev/null +++ b/metadata/bg-BG/changelogs/56.txt @@ -0,0 +1,4 @@ +* ПОПРАВКИ + + Позволяване на потребителски сертификати в настройките за сигурността на мрежовите връзки +* ДРУГИ + + Обновена версия на gradle diff --git a/metadata/en-US/changelogs/56.txt b/metadata/en-US/changelogs/56.txt new file mode 100644 index 00000000..9b7d3ac4 --- /dev/null +++ b/metadata/en-US/changelogs/56.txt @@ -0,0 +1,4 @@ +* FIXES: + + allow user certificates in network security config +* OTHERS: + + bump gradle version -- 2.39.2 From e687d63b107a215ba3b28e7028b9235cdf645bc0 Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Sun, 31 Mar 2024 10:17:32 +0300 Subject: [PATCH 2/6] add shortcut method for casting and drop the one accessing the underlying account object --- .../mobileledger/model/AccountListItem.java | 23 ++++++++++++++----- .../net/ktnx/mobileledger/ui/MainModel.java | 2 ++ .../AccountSummaryAdapter.java | 17 ++++++++++---- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java b/app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java index dfd3d982..1efe1962 100644 --- a/app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java +++ b/app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java @@ -34,12 +34,19 @@ public abstract class AccountListItem { else throw new RuntimeException("Unsupported sub-class " + this); } - @NotNull - public LedgerAccount getAccount() { - if (this instanceof Account) - return ((Account) this).account; - - throw new IllegalStateException(String.format("Item type is not Account, but %s", this)); + public boolean isAccount() { + return this instanceof Account; + } + public Account toAccount() { + assert isAccount(); + return ((Account) this); + } + public boolean isHeader() { + return this instanceof Header; + } + public Header toHeader() { + assert isHeader(); + return ((Header) this); } public enum Type {ACCOUNT, HEADER} @@ -59,6 +66,10 @@ public abstract class AccountListItem { ((Account) other).account.getAmountsString() .equals(account.getAmountsString()); } + @NotNull + public LedgerAccount getAccount() { + return account; + } } public static class Header extends AccountListItem { diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java b/app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java index 329109fd..dfa6b5c5 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java @@ -38,6 +38,7 @@ import java.util.Locale; public class MainModel extends ViewModel { public final MutableLiveData foundTransactionItemIndex = new MutableLiveData<>(null); private final MutableLiveData updatingFlag = new MutableLiveData<>(false); + private final MutableLiveData showZeroBalanceAccounts = new MutableLiveData<>(true); private final MutableLiveData accountFilter = new MutableLiveData<>(null); private final MutableLiveData> displayedTransactions = new MutableLiveData<>(new ArrayList<>()); @@ -66,6 +67,7 @@ public class MainModel extends ViewModel { public void setFirstTransactionDate(SimpleDate earliestDate) { this.firstTransactionDate = earliestDate; } + public MutableLiveData getShowZeroBalanceAccounts() {return showZeroBalanceAccounts;} public MutableLiveData getAccountFilter() { return accountFilter; } 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 d7da335d..88970641 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 @@ -66,8 +66,10 @@ public class AccountSummaryAdapter extends RecyclerView.Adapter payloads) { - LedgerAccount acc = item.getAccount(); + LedgerAccount acc = item.toAccount() + .getAccount(); Change changes = new Change(); if (payloads != null) { -- 2.39.2 From 20b1574421ee368ca690d1e4de0f666ebfec6520 Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Sun, 31 Mar 2024 10:26:18 +0300 Subject: [PATCH 3/6] add ability to hide all-zero accounts from the account list --- .../net/ktnx/mobileledger/dao/AccountDAO.java | 17 +++- .../mobileledger/model/AccountListItem.java | 5 +- .../mobileledger/model/LedgerAccount.java | 16 +++- .../net/ktnx/mobileledger/ui/MainModel.java | 4 +- .../AccountSummaryAdapter.java | 6 +- .../AccountSummaryFragment.java | 94 +++++++++++++++++-- app/src/main/res/menu/account_list.xml | 32 +++++++ app/src/main/res/values-bg/strings.xml | 4 +- app/src/main/res/values/strings.xml | 4 +- 9 files changed, 158 insertions(+), 24 deletions(-) create mode 100644 app/src/main/res/menu/account_list.xml diff --git a/app/src/main/java/net/ktnx/mobileledger/dao/AccountDAO.java b/app/src/main/java/net/ktnx/mobileledger/dao/AccountDAO.java index 0c581787..5ad4c90f 100644 --- a/app/src/main/java/net/ktnx/mobileledger/dao/AccountDAO.java +++ b/app/src/main/java/net/ktnx/mobileledger/dao/AccountDAO.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Damyan Ivanov. + * Copyright © 2024 Damyan Ivanov. * This file is part of MoLe. * MoLe is free software: you can distribute it and/or modify it * under the term of the GNU General Public License as published by @@ -78,12 +78,19 @@ public abstract class AccountDAO extends BaseDAO { @Query("DELETE FROM accounts") public abstract void deleteAllSync(); - @Query("SELECT * FROM accounts WHERE profile_id=:profileId ORDER BY name") - public abstract LiveData> getAll(long profileId); + @Query("SELECT * FROM accounts WHERE profile_id=:profileId AND IIF(:includeZeroBalances=1, 1," + + " (EXISTS(SELECT 1 FROM account_values av WHERE av.account_id=accounts.id AND av.value" + + " <> 0) OR EXISTS(SELECT 1 FROM accounts a WHERE a.parent_name = accounts.name))) " + + "ORDER BY name") + public abstract LiveData> getAll(long profileId, boolean includeZeroBalances); @Transaction - @Query("SELECT * FROM accounts WHERE profile_id = :profileId ORDER BY name") - public abstract LiveData> getAllWithAmounts(long profileId); + @Query("SELECT * FROM accounts WHERE profile_id = :profileId AND IIF(:includeZeroBalances=1, " + + "1, (EXISTS(SELECT 1 FROM account_values av WHERE av.account_id=accounts.id AND av" + + ".value <> 0) OR EXISTS(SELECT 1 FROM accounts a WHERE a.parent_name = accounts.name))" + + ") ORDER BY name") + public abstract LiveData> getAllWithAmounts(long profileId, + boolean includeZeroBalances); @Query("SELECT * FROM accounts WHERE id=:id") public abstract Account getByIdSync(long id); diff --git a/app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java b/app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java index 1efe1962..807e93d3 100644 --- a/app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java +++ b/app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Damyan Ivanov. + * Copyright © 2024 Damyan Ivanov. * This file is part of MoLe. * MoLe is free software: you can distribute it and/or modify it * under the term of the GNU General Public License as published by @@ -70,6 +70,9 @@ public abstract class AccountListItem { public LedgerAccount getAccount() { return account; } + public boolean allAmountsAreZero() { + return account.allAmountsAreZero(); + } } public static class Header extends AccountListItem { diff --git a/app/src/main/java/net/ktnx/mobileledger/model/LedgerAccount.java b/app/src/main/java/net/ktnx/mobileledger/model/LedgerAccount.java index 1be684cf..c2e62772 100644 --- a/app/src/main/java/net/ktnx/mobileledger/model/LedgerAccount.java +++ b/app/src/main/java/net/ktnx/mobileledger/model/LedgerAccount.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Damyan Ivanov. + * Copyright © 2024 Damyan Ivanov. * This file is part of MoLe. * MoLe is free software: you can distribute it and/or modify it * under the term of the GNU General Public License as published by @@ -201,13 +201,21 @@ public class LedgerAccount { if (amounts != null) amounts.clear(); } - public boolean amountsExpanded() { return amountsExpanded; } - public void setAmountsExpanded(boolean flag) { amountsExpanded = flag; } - public void toggleAmountsExpanded() { amountsExpanded = !amountsExpanded; } + public boolean amountsExpanded() {return amountsExpanded;} + public void setAmountsExpanded(boolean flag) {amountsExpanded = flag;} + public void toggleAmountsExpanded() {amountsExpanded = !amountsExpanded;} public void propagateAmountsTo(LedgerAccount acc) { for (LedgerAmount a : amounts) a.propagateToAccount(acc); } + public boolean allAmountsAreZero() { + for (LedgerAmount a : amounts) { + if (a.getAmount() != 0) + return false; + } + + return true; + } public List getAmounts() { return amounts; } diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java b/app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java index dfa6b5c5..a8b957dc 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Damyan Ivanov. + * Copyright © 2024 Damyan Ivanov. * This file is part of MoLe. * MoLe is free software: you can distribute it and/or modify it * under the term of the GNU General Public License as published by @@ -46,7 +46,6 @@ public class MainModel extends ViewModel { private SimpleDate firstTransactionDate; private SimpleDate lastTransactionDate; transient private RetrieveTransactionsTask retrieveTransactionsTask; - transient private Thread displayedAccountsUpdater; private TransactionsDisplayedFilter displayedTransactionsUpdater; public LiveData getUpdatingFlag() { return updatingFlag; @@ -83,6 +82,7 @@ public class MainModel extends ViewModel { return; } Profile profile = Data.getProfile(); + assert profile != null; retrieveTransactionsTask = new RetrieveTransactionsTask(profile); Logger.debug("db", "Created a background transaction retrieval task"); 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 88970641..dcc16f36 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 @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Damyan Ivanov. + * Copyright © 2024 Damyan Ivanov. * This file is part of MoLe. * MoLe is free software: you can distribute it and/or modify it * under the term of the GNU General Public License as published by @@ -17,6 +17,8 @@ package net.ktnx.mobileledger.ui.account_summary; +import static net.ktnx.mobileledger.utils.Logger.debug; + import android.content.res.Resources; import android.view.LayoutInflater; import android.view.View; @@ -48,8 +50,6 @@ import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Locale; -import static net.ktnx.mobileledger.utils.Logger.debug; - public class AccountSummaryAdapter extends RecyclerView.Adapter { public static final int AMOUNT_LIMIT = 3; private static final int ITEM_TYPE_HEADER = 1; 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 35a9edb7..447e57e7 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 @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Damyan Ivanov. + * Copyright © 2024 Damyan Ivanov. * This file is part of MoLe. * MoLe is free software: you can distribute it and/or modify it * under the term of the GNU General Public License as published by @@ -17,9 +17,14 @@ package net.ktnx.mobileledger.ui.account_summary; +import static net.ktnx.mobileledger.utils.Logger.debug; + import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -31,6 +36,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import net.ktnx.mobileledger.R; import net.ktnx.mobileledger.async.GeneralBackgroundTasks; import net.ktnx.mobileledger.databinding.AccountSummaryFragmentBinding; import net.ktnx.mobileledger.db.AccountWithAmounts; @@ -51,11 +57,11 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import static net.ktnx.mobileledger.utils.Logger.debug; - public class AccountSummaryFragment extends MobileLedgerListFragment { public AccountSummaryAdapter modelAdapter; private AccountSummaryFragmentBinding b; + private MenuItem menuShowZeroBalances; + private MainModel model; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -82,7 +88,7 @@ public class AccountSummaryFragment extends MobileLedgerListFragment { debug("flow", "AccountSummaryFragment.onActivityCreated()"); super.onViewCreated(view, savedInstanceState); - MainModel model = new ViewModelProvider(requireActivity()).get(MainModel.class); + model = new ViewModelProvider(requireActivity()).get(MainModel.class); Data.backgroundTasksRunning.observe(this.getViewLifecycleOwner(), this::onBackgroundTaskRunningChanged); @@ -109,15 +115,40 @@ public class AccountSummaryFragment extends MobileLedgerListFragment { model.scheduleTransactionListRetrieval(); }); - Data.observeProfile(this, this::onProfileChanged); + Data.observeProfile(this, profile -> onProfileChanged(profile, Boolean.TRUE.equals( + model.getShowZeroBalanceAccounts() + .getValue()))); + } + @Override + public void onCreateOptionsMenu(@NotNull Menu menu, @NotNull MenuInflater inflater) { + inflater.inflate(R.menu.account_list, menu); + + menuShowZeroBalances = menu.findItem(R.id.menu_account_list_show_zero_balances); + if ((menuShowZeroBalances == null)) + throw new AssertionError(); + + menuShowZeroBalances.setOnMenuItemClickListener(menuItem -> { + model.getShowZeroBalanceAccounts() + .setValue(Boolean.FALSE.equals(model.getShowZeroBalanceAccounts() + .getValue())); + return true; + }); + + model.getShowZeroBalanceAccounts() + .observe(this, v -> { + menuShowZeroBalances.setChecked(v); + onProfileChanged(Data.getProfile(), v); + }); + + super.onCreateOptionsMenu(menu, inflater); } - private void onProfileChanged(Profile profile) { + private void onProfileChanged(Profile profile, boolean showZeroBalanceAccounts) { if (profile == null) return; DB.get() .getAccountDAO() - .getAllWithAmounts(profile.getId()) + .getAllWithAmounts(profile.getId(), showZeroBalanceAccounts) .observe(getViewLifecycleOwner(), list -> GeneralBackgroundTasks.run(() -> { List adapterList = new ArrayList<>(); adapterList.add(new AccountListItem.Header(Data.lastAccountsUpdateText)); @@ -134,8 +165,57 @@ public class AccountSummaryFragment extends MobileLedgerListFragment { adapterList.add(new AccountListItem.Account(account)); accMap.put(dbAcc.account.getName(), account); } + + if (!showZeroBalanceAccounts) { + removeZeroAccounts(adapterList); + } modelAdapter.setAccounts(adapterList); Data.lastUpdateAccountCount.postValue(adapterList.size() - 1); })); } + private void removeZeroAccounts(List list) { + boolean removed = true; + + while (removed) { + AccountListItem last = null; + removed = false; + List newList = new ArrayList<>(); + + for (AccountListItem item : list) { + if (last == null) { + last = item; + continue; + } + + if (!last.isAccount() || !last.toAccount() + .allAmountsAreZero() || last.toAccount() + .getAccount() + .isParentOf( + item.toAccount() + .getAccount())) + { + newList.add(last); + } + else { + removed = true; + } + + last = item; + } + + if (last != null) { + if (last.getType() != AccountListItem.Type.ACCOUNT || + !((AccountListItem.Account) last).allAmountsAreZero()) + { + newList.add(last); + } + else { + removed = true; + } + } + + list.clear(); + list.addAll(newList); + } + } } diff --git a/app/src/main/res/menu/account_list.xml b/app/src/main/res/menu/account_list.xml new file mode 100644 index 00000000..5a761610 --- /dev/null +++ b/app/src/main/res/menu/account_list.xml @@ -0,0 +1,32 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 4ba6fe38..ccb47516 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -1,6 +1,6 @@