]> git.ktnx.net Git - mobile-ledger.git/commitdiff
more pronounced day/month delimiters in the transaction list master
authorDamyan Ivanov <dam+mobileledger@ktnx.net>
Sun, 31 Mar 2024 11:13:26 +0000 (14:13 +0300)
committerDamyan Ivanov <dam+mobileledger@ktnx.net>
Sun, 31 Mar 2024 11:13:26 +0000 (14:13 +0300)
40 files changed:
CHANGES.md
TODO.txt [new file with mode: 0644]
app/build.gradle
app/src/main/AndroidManifest.xml
app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java
app/src/main/java/net/ktnx/mobileledger/backup/MobileLedgerBackupAgent.java
app/src/main/java/net/ktnx/mobileledger/backup/RawConfigReader.java
app/src/main/java/net/ktnx/mobileledger/dao/AccountDAO.java
app/src/main/java/net/ktnx/mobileledger/json/v1_23/ParsedLedgerTransaction.java
app/src/main/java/net/ktnx/mobileledger/json/v1_23/ParsedPosting.java
app/src/main/java/net/ktnx/mobileledger/json/v1_23/ParsedPrecision.java [deleted file]
app/src/main/java/net/ktnx/mobileledger/json/v1_23/ParsedSourcePos.java
app/src/main/java/net/ktnx/mobileledger/json/v1_23/ParsedStyle.java
app/src/main/java/net/ktnx/mobileledger/model/AccountListItem.java
app/src/main/java/net/ktnx/mobileledger/model/LedgerAccount.java
app/src/main/java/net/ktnx/mobileledger/ui/MainModel.java
app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryAdapter.java
app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryFragment.java
app/src/main/java/net/ktnx/mobileledger/ui/new_transaction/NewTransactionModel.java
app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListDivider.java
app/src/main/java/net/ktnx/mobileledger/ui/transaction_list/TransactionListDelimiterRowHolder.java
app/src/main/java/net/ktnx/mobileledger/utils/Colors.java
app/src/main/res/menu/account_list.xml [new file with mode: 0644]
app/src/main/res/values-bg/strings.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/backup_descriptor.xml [deleted file]
app/src/main/res/xml/network_security_config.xml
build.gradle
gradle.properties
gradle/wrapper/gradle-wrapper.properties
metadata/bg-BG/changelogs/52.txt [new file with mode: 0644]
metadata/bg-BG/changelogs/53.txt [new file with mode: 0644]
metadata/bg-BG/changelogs/54.txt [new file with mode: 0644]
metadata/bg-BG/changelogs/55.txt [new file with mode: 0644]
metadata/bg-BG/changelogs/56.txt [new file with mode: 0644]
metadata/en-US/changelogs/52.txt [new file with mode: 0644]
metadata/en-US/changelogs/53.txt [new file with mode: 0644]
metadata/en-US/changelogs/54.txt [new file with mode: 0644]
metadata/en-US/changelogs/55.txt [new file with mode: 0644]
metadata/en-US/changelogs/56.txt [new file with mode: 0644]

index c7dc45dbdf6dfedb0b448dbfc46b8ea97ef8caf1..02f84284cacf6943424f157b78ec8e114eb5dd6f 100644 (file)
@@ -1,6 +1,39 @@
 # Changes
 
-## [0.21.2] = 2022-04-04
+## [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
+    + fix sending transations to hledger-web 1.23+
+
+## [0.21.5] - 2022-09-03
+
+* FIXES
+    + fix cloud backup
+
+## [0.21.4] - 2022-06-18
+
+* FIXES
+    + fix compatibility wuth hledger-web 1.23+ when submitting new transactions. Thanks to Faye Duxovni for the patch!
+    + fix a crash when deleting templates
+    + fix a rare crash when submitting transactions with multiple accounts with no amounts with zero remaining balance
+
+## [0.21.3] - 2022-04-06
+
+* FIXES
+    + sync gradle version requirements
+* OTHERS
+    + bump version of several dependent libraries
+    + bump SDK version to 31
+    + adjust deprecated constructor usage
+
+## [0.21.2] - 2022-04-04
 
 * FIXES
     + fix crash when auto-balancing multi currency transaction
diff --git a/TODO.txt b/TODO.txt
new file mode 100644 (file)
index 0000000..e229e17
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,7 @@
+* Easy way to add tag:value pairs to transactions and transaction accounts
+
+* Filter by tag:value pairs
+
+* Refresh button in account/transaction list
+
+* Top button in account/transaction list
index 58dfbabf22f6ce93b2f03e9206ca537a8d7fceec..71673f6eb8dca03508bc0f12f40580f9893fda37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2022 Damyan Ivanov.
+ * Copyright © 2023 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
@@ -24,8 +24,8 @@ android {
         minSdkVersion 22
         targetSdkVersion 31
         vectorDrawables.useSupportLibrary true
-        versionCode 51
-        versionName '0.21.2'
+        versionCode 56
+        versionName '0.21.7'
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         javaCompileOptions {
             annotationProcessorOptions {
@@ -62,6 +62,7 @@ android {
     }
     buildFeatures.viewBinding = true
     buildToolsVersion '30.0.3'
+    namespace 'net.ktnx.mobileledger'
 }
 
 dependencies {
index 47f9b1d4f5276e21aa8795f91453e598fda8b76b..b17a1ecfcacfaec410eee37f6be145c34c967ac7 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?><!--
-  ~ Copyright © 2022 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
@@ -15,8 +15,7 @@
   ~ along with MoLe. If not, see <https://www.gnu.org/licenses/>.
   -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    package="net.ktnx.mobileledger">
+    xmlns:tools="http://schemas.android.com/tools">
 
     <uses-permission android:name="android.permission.INTERNET" />
 
         android:name=".App"
         android:allowBackup="true"
         android:appCategory="productivity"
-        android:fullBackupContent="@xml/backup_descriptor"
         android:icon="@drawable/app_icon"
         android:label="@string/app_name"
         android:networkSecurityConfig="@xml/network_security_config"
         android:roundIcon="@drawable/app_icon_round"
         android:supportsRtl="true"
-        android:backupAgent="net.ktnx.mobileledger.backup.MobileLedgerBackupAgent"
+        android:backupAgent=".backup.MobileLedgerBackupAgent"
         tools:ignore="GoogleAppIndexingWarning">
         <activity
             android:name=".BackupsActivity"
index 79a58173f10e502d11dfbd752fcfdef355aeb4b3..0e700cca9a510be8e210fafccbe548b88c2a427a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2021 Damyan Ivanov.
+ * Copyright © 2023 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.async;
 
+import static net.ktnx.mobileledger.utils.Logger.debug;
+
 import android.util.Log;
 
 import net.ktnx.mobileledger.db.Profile;
@@ -45,8 +47,6 @@ import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static net.ktnx.mobileledger.utils.Logger.debug;
-
 /* TODO: get rid of the custom session/cookie and auth code?
  *       (the last problem with the POST was the missing content-length header)
  *       This will resolve itself when hledger-web 1.14+ is released with Debian/stable,
@@ -275,6 +275,7 @@ public class SendTransactionTask extends Thread {
                 case v1_14:
                 case v1_15:
                 case v1_19_1:
+                case v1_23:
                     sendOK(profileApiVersion);
                     break;
                 default:
@@ -286,9 +287,7 @@ public class SendTransactionTask extends Thread {
             error = e.getMessage();
         }
 
-        Misc.onMainThread(()->{
-            taskCallback.onTransactionSaveDone(error, transaction);
-        });
+        Misc.onMainThread(() -> taskCallback.onTransactionSaveDone(error, transaction));
     }
     private void legacySendOkWithRetry() throws IOException {
         int tried = 0;
index ea09e51417d68735d281c30fa6213303f5425183..6653843594ce2bbc5b275784ef4c1818588bbcfc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2021 Damyan Ivanov.
+ * Copyright © 2022 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,7 +17,7 @@
 
 package net.ktnx.mobileledger.backup;
 
-import android.app.backup.BackupAgentHelper;
+import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
 import android.os.ParcelFileDescriptor;
@@ -29,13 +29,13 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
-class MobileLedgerBackupAgent extends BackupAgentHelper {
+public class MobileLedgerBackupAgent extends BackupAgent {
     private static final int READ_BUF_LEN = 10;
     public static String SETTINGS_KEY = "settings";
     @Override
     public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
                          ParcelFileDescriptor newState) throws IOException {
-        super.onBackup(oldState, data, newState);
+        Logger.debug("backup", "onBackup()");
         backupSettings(data);
         newState.close();
     }
index 45a593d7add390a4898f191d1a1b49d15de62232..95b27b32ed85a2975799b64e11855e8f17ead7ed 100644 (file)
@@ -20,6 +20,7 @@ package net.ktnx.mobileledger.backup;
 import android.util.JsonReader;
 import android.util.JsonToken;
 
+import net.ktnx.mobileledger.App;
 import net.ktnx.mobileledger.backup.ConfigIO.Keys;
 import net.ktnx.mobileledger.dao.CurrencyDAO;
 import net.ktnx.mobileledger.dao.ProfileDAO;
@@ -30,6 +31,8 @@ import net.ktnx.mobileledger.db.Profile;
 import net.ktnx.mobileledger.db.TemplateAccount;
 import net.ktnx.mobileledger.db.TemplateHeader;
 import net.ktnx.mobileledger.db.TemplateWithAccounts;
+import net.ktnx.mobileledger.model.Data;
+import net.ktnx.mobileledger.utils.Logger;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -337,6 +340,7 @@ public class RawConfigReader {
         restoreCommodities();
         restoreProfiles();
         restoreTemplates();
+        restoreCurrentProfile();
     }
     private void restoreTemplates() {
         if (templates == null)
@@ -374,4 +378,24 @@ public class RawConfigReader {
                 dao.insert(c);
         }
     }
+    private void restoreCurrentProfile() {
+        if (currentProfile == null) {
+            Logger.debug("backup", "Not restoring current profile (not present in backup)");
+            return;
+        }
+
+        ProfileDAO dao = DB.get()
+                           .getProfileDAO();
+
+        Profile p = dao.getByUuidSync(currentProfile);
+
+        if (p != null) {
+            Logger.debug("backup", "Restoring current profile "+p.getName());
+            Data.postCurrentProfile(p);
+            App.storeStartupProfileAndTheme(p.getId(), p.getTheme());
+        }
+        else {
+            Logger.debug("backup", "Not restoring profile "+currentProfile+": not found in DB");
+        }
+    }
 }
index 0c581787a30a2fac55c605674904eebdd7441995..5ad4c90fb4138487b9626648dd9b1191d19c188b 100644 (file)
@@ -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<Account> {
     @Query("DELETE FROM accounts")
     public abstract void deleteAllSync();
 
-    @Query("SELECT * FROM accounts WHERE profile_id=:profileId ORDER BY name")
-    public abstract LiveData<List<Account>> 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<List<Account>> getAll(long profileId, boolean includeZeroBalances);
 
     @Transaction
-    @Query("SELECT * FROM accounts WHERE profile_id = :profileId ORDER BY name")
-    public abstract LiveData<List<AccountWithAmounts>> 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<List<AccountWithAmounts>> getAllWithAmounts(long profileId,
+                                                                         boolean includeZeroBalances);
 
     @Query("SELECT * FROM accounts WHERE id=:id")
     public abstract Account getByIdSync(long id);
index fe0a280907dfa90c4d273b75be6c176789170dde..59d1763522c5b4b97d8fe1fd64a6e6997f4dd3ff 100644 (file)
@@ -43,6 +43,12 @@ public class ParsedLedgerTransaction implements net.ktnx.mobileledger.json.Parse
     private List<List<String>> ttags = new ArrayList<>();
     private List<ParsedSourcePos> tsourcepos = new ArrayList<>();
     public ParsedLedgerTransaction() {
+        ParsedSourcePos startPos = new ParsedSourcePos();
+        ParsedSourcePos endPos = new ParsedSourcePos();
+        endPos.setSourceLine(2);
+
+        tsourcepos.add(startPos);
+        tsourcepos.add(endPos);
     }
     public static ParsedLedgerTransaction fromLedgerTransaction(LedgerTransaction tr) {
         ParsedLedgerTransaction result = new ParsedLedgerTransaction();
index 8f0cdbcdfe17e22227e05348f11c14e8e8f3ef5a..e60bd193c3989a2f44042b9a412c0d072608a952 100644 (file)
@@ -59,7 +59,7 @@ public class ParsedPosting extends net.ktnx.mobileledger.json.ParsedPosting {
         ParsedStyle style = new ParsedStyle();
         style.setAscommodityside(getCommoditySide());
         style.setAscommodityspaced(getCommoditySpaced());
-        style.setAsprecision(new ParsedPrecision(2));
+        style.setAsprecision(2);
         style.setAsdecimalpoint('.');
         amt.setAstyle(style);
         if (acc.getCurrency() != null)
diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_23/ParsedPrecision.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_23/ParsedPrecision.java
deleted file mode 100644 (file)
index ffaac7d..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright © 2020 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your opinion), any later version.
- *
- * MoLe is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License terms for details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package net.ktnx.mobileledger.json.v1_23;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-class ParsedPrecision {
-    private int contents;
-    private String tag;
-    ParsedPrecision() {
-        tag = "NaturalPrecision";
-    }
-    ParsedPrecision(int contents) {
-        this.contents = contents;
-        tag = "Precision";
-    }
-    public int getContents() {
-        return contents;
-    }
-    public void setContents(int contents) {
-        this.contents = contents;
-    }
-    public String getTag() {
-        return tag;
-    }
-    public void setTag(String tag) {
-        this.tag = tag;
-    }
-}
index 6a62f8dd015c598d9df472664b95fd8f783e8fdb..b3ea5db6a033ab5a31eaa58053485ebd7b5f1a94 100644 (file)
@@ -18,9 +18,9 @@
 package net.ktnx.mobileledger.json.v1_23;
 
 class ParsedSourcePos {
-    private String sourceName;
-    private int sourceLine;
-    private int sourceColumn;
+    private String sourceName = "";
+    private int sourceLine = 1;
+    private int sourceColumn = 1;
     public ParsedSourcePos() {
     }
     public String getSourceName() {
index c9bf8bef70dbbb89761acef2a1b0bef52e4facd5..d3a0a133bb49b24ecbb856fd82965048deeb3060 100644 (file)
@@ -21,13 +21,13 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class ParsedStyle extends net.ktnx.mobileledger.json.ParsedStyle {
-    private ParsedPrecision asprecision;
+    private int asprecision;
     public ParsedStyle() {
     }
-    public ParsedPrecision getAsprecision() {
+    public int getAsprecision() {
         return asprecision;
     }
-    public void setAsprecision(ParsedPrecision asprecision) {
+    public void setAsprecision(int asprecision) {
         this.asprecision = asprecision;
     }
 }
index dfd3d982011a105191f5e801bea2fcc5e276c4d6..807e93d348b1e182d81090d94fc097b32cd4be8f 100644 (file)
@@ -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
@@ -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,13 @@ public abstract class AccountListItem {
                    ((Account) other).account.getAmountsString()
                                             .equals(account.getAmountsString());
         }
+        @NotNull
+        public LedgerAccount getAccount() {
+            return account;
+        }
+        public boolean allAmountsAreZero() {
+            return account.allAmountsAreZero();
+        }
     }
 
     public static class Header extends AccountListItem {
index 1be684cf1b0d1bcb700485384a3a068963576610..c2e62772f5990ef911854c838218edde70e50f82 100644 (file)
@@ -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<LedgerAmount> getAmounts() {
         return amounts;
     }
index 329109fdccf3947f578e0eb2ac20a6abd58fcb14..a8b957dc330be48f6a304cce50bd5f5012468b11 100644 (file)
@@ -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
@@ -38,6 +38,7 @@ import java.util.Locale;
 public class MainModel extends ViewModel {
     public final MutableLiveData<Integer> foundTransactionItemIndex = new MutableLiveData<>(null);
     private final MutableLiveData<Boolean> updatingFlag = new MutableLiveData<>(false);
+    private final MutableLiveData<Boolean> showZeroBalanceAccounts = new MutableLiveData<>(true);
     private final MutableLiveData<String> accountFilter = new MutableLiveData<>(null);
     private final MutableLiveData<List<TransactionListItem>> displayedTransactions =
             new MutableLiveData<>(new ArrayList<>());
@@ -45,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<Boolean> getUpdatingFlag() {
         return updatingFlag;
@@ -66,6 +66,7 @@ public class MainModel extends ViewModel {
     public void setFirstTransactionDate(SimpleDate earliestDate) {
         this.firstTransactionDate = earliestDate;
     }
+    public MutableLiveData<Boolean> getShowZeroBalanceAccounts() {return showZeroBalanceAccounts;}
     public MutableLiveData<String> getAccountFilter() {
         return accountFilter;
     }
@@ -81,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");
index d7da335d675a19da8e1c273f717badb72488ce0c..dcc16f3678ed3885605d4b85de77653f1f957b9c 100644 (file)
@@ -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<AccountSummaryAdapter.RowHolder> {
     public static final int AMOUNT_LIMIT = 3;
     private static final int ITEM_TYPE_HEADER = 1;
@@ -66,8 +66,10 @@ public class AccountSummaryAdapter extends RecyclerView.Adapter<AccountSummaryAd
                                            @NonNull AccountListItem newItem) {
                 Change changes = new Change();
 
-                final LedgerAccount oldAcc = oldItem.getAccount();
-                final LedgerAccount newAcc = newItem.getAccount();
+                final LedgerAccount oldAcc = oldItem.toAccount()
+                                                    .getAccount();
+                final LedgerAccount newAcc = newItem.toAccount()
+                                                    .getAccount();
 
                 if (!Misc.equalStrings(oldAcc.getName(), newAcc.getName()))
                     changes.add(Change.NAME);
@@ -97,8 +99,10 @@ public class AccountSummaryAdapter extends RecyclerView.Adapter<AccountSummaryAd
                 if (oldType == AccountListItem.Type.HEADER)
                     return true;
 
-                return oldItem.getAccount()
-                              .getId() == newItem.getAccount()
+                return oldItem.toAccount()
+                              .getAccount()
+                              .getId() == newItem.toAccount()
+                                                 .getAccount()
                                                  .getId();
             }
             @Override
@@ -114,6 +118,7 @@ public class AccountSummaryAdapter extends RecyclerView.Adapter<AccountSummaryAd
             return 0;
         return listDiffer.getCurrentList()
                          .get(position)
+                         .toAccount()
                          .getAccount()
                          .getId();
     }
@@ -258,6 +263,7 @@ public class AccountSummaryAdapter extends RecyclerView.Adapter<AccountSummaryAd
         private LedgerAccount getAccount() {
             return listDiffer.getCurrentList()
                              .get(getBindingAdapterPosition())
+                             .toAccount()
                              .getAccount();
         }
         private void toggleAmountsExpanded() {
@@ -301,7 +307,8 @@ public class AccountSummaryAdapter extends RecyclerView.Adapter<AccountSummaryAd
         }
         @Override
         public void bind(AccountListItem item, @Nullable List<Object> payloads) {
-            LedgerAccount acc = item.getAccount();
+            LedgerAccount acc = item.toAccount()
+                                    .getAccount();
 
             Change changes = new Change();
             if (payloads != null) {
index 35a9edb7205c84bd16889468d90416b6018d547b..807c16daf8540af877827e2729d0e848f733d3c3 100644 (file)
@@ -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
 
 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<AccountListItem> 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<AccountListItem> list) {
+        boolean removed = true;
+
+        while (removed) {
+            AccountListItem last = null;
+            removed = false;
+            List<AccountListItem> 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.isAccount() || !last.toAccount()
+                                              .allAmountsAreZero())
+                {
+                    newList.add(last);
+                }
+                else {
+                    removed = true;
+                }
+            }
+
+            list.clear();
+            list.addAll(newList);
+        }
+    }
 }
index d8f387b72696983f1fe9f87d0ae12e0a5b4d1be8..51bcd306b2da3e6fb50223ecc5f61e7f5dd357dc 100644 (file)
@@ -482,27 +482,28 @@ public class NewTransactionModel extends ViewModel {
         if (emptyAmountAccounts.size() > 0) {
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                 emptyAmountAccounts.forEach((currency, accounts) -> {
-                    if (accounts.size() != 1)
+                    final Float balance = emptyAmountAccountBalance.get(currency);
+
+                    if (balance != null && !Misc.isZero(balance) && accounts.size() != 1) {
                         throw new RuntimeException(String.format(Locale.US,
-                                "Should not happen: approved transaction has %d accounts for " +
-                                "currency %s", accounts.size(), currency));
-                    accounts.get(0)
-                            .setAmount(-Objects.requireNonNull(
-                                    emptyAmountAccountBalance.get(currency)));
+                                "Should not happen: approved transaction has %d accounts " +
+                                "without amounts for currency '%s'", accounts.size(), currency));
+                    }
+                    accounts.forEach(acc -> acc.setAmount(balance == null ? 0 : -balance));
                 });
             }
             else {
                 for (String currency : emptyAmountAccounts.keySet()) {
                     List<LedgerTransactionAccount> accounts =
                             Objects.requireNonNull(emptyAmountAccounts.get(currency));
-
-                    if (accounts.size() != 1)
+                    final Float balance = emptyAmountAccountBalance.get(currency);
+                    if (balance != null && !Misc.isZero(balance) && accounts.size() != 1)
                         throw new RuntimeException(String.format(Locale.US,
                                 "Should not happen: approved transaction has %d accounts for " +
                                 "currency %s", accounts.size(), currency));
-                    accounts.get(0)
-                            .setAmount(-Objects.requireNonNull(
-                                    emptyAmountAccountBalance.get(currency)));
+                    for (LedgerTransactionAccount acc : accounts) {
+                        acc.setAmount(balance == null ? 0 : -balance);
+                    }
                 }
             }
         }
index 9860e80490946d3316bc2b4147ffcaab62a54f31..f841ad76db445cb76e375bbb9ccb83912e14fa79 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2021 Damyan Ivanov.
+ * Copyright © 2022 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
  * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
  */
 
-//
-// Substantial portions taken from DividerItemDecoration subject to the following license terms:
-//
-// Copyright 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
 package net.ktnx.mobileledger.ui.templates;
 
 import android.content.Context;
@@ -94,7 +77,8 @@ class TemplateListDivider extends DividerItemDecoration {
         for (int i = 0; i < childCount; i++) {
             final View child = parent.getChildAt(i);
             final int childAdapterPosition = parent.getChildAdapterPosition(child);
-            if (adapter.getItemViewType(childAdapterPosition) ==
+            if (childAdapterPosition == RecyclerView.NO_POSITION ||
+                adapter.getItemViewType(childAdapterPosition) ==
                 TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER ||
                 childAdapterPosition + 1 < itemCount &&
                 adapter.getItemViewType(childAdapterPosition + 1) ==
@@ -110,6 +94,10 @@ class TemplateListDivider extends DividerItemDecoration {
     }
 
     private void drawHorizontal(Canvas canvas, RecyclerView parent) {
+        final RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
+        if (layoutManager == null)
+            return;
+
         canvas.save();
         final int top;
         final int bottom;
@@ -133,14 +121,16 @@ class TemplateListDivider extends DividerItemDecoration {
         for (int i = 0; i < childCount; i++) {
             final View child = parent.getChildAt(i);
             final int childAdapterPosition = parent.getChildAdapterPosition(child);
-            if (adapter.getItemViewType(childAdapterPosition) ==
+            if (childAdapterPosition == RecyclerView.NO_POSITION ||
+                adapter.getItemViewType(childAdapterPosition) ==
                 TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER ||
                 childAdapterPosition + 1 < itemCount &&
                 adapter.getItemViewType(childAdapterPosition + 1) ==
                 TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER)
+            {
                 continue;
-            parent.getLayoutManager()
-                  .getDecoratedBoundsWithMargins(child, mBounds);
+            }
+            layoutManager.getDecoratedBoundsWithMargins(child, mBounds);
             final int right = mBounds.right + Math.round(child.getTranslationX());
             final int left = right - divider.getIntrinsicWidth();
             divider.setBounds(left, top, right, bottom);
@@ -156,7 +146,8 @@ class TemplateListDivider extends DividerItemDecoration {
                 (TemplatesRecyclerViewAdapter) Objects.requireNonNull(parent.getAdapter());
         final int itemCount = adapter.getItemCount();
 
-        if (adapter.getItemViewType(childAdapterPosition) ==
+        if (childAdapterPosition == RecyclerView.NO_POSITION ||
+            adapter.getItemViewType(childAdapterPosition) ==
             TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER ||
             childAdapterPosition + 1 < itemCount &&
             adapter.getItemViewType(childAdapterPosition + 1) ==
index 390b4941719c2eca9b5d4c4e992086131ac3525e..b5fe883d14a74cc2d92cf308d6382838155b3bb0 100644 (file)
@@ -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
@@ -19,9 +19,12 @@ package net.ktnx.mobileledger.ui.transaction_list;
 
 import android.view.View;
 
+import androidx.constraintlayout.widget.ConstraintLayout;
+
 import net.ktnx.mobileledger.App;
 import net.ktnx.mobileledger.databinding.TransactionDelimiterBinding;
 import net.ktnx.mobileledger.model.TransactionListItem;
+import net.ktnx.mobileledger.utils.DimensionUtils;
 import net.ktnx.mobileledger.utils.Globals;
 import net.ktnx.mobileledger.utils.SimpleDate;
 
@@ -46,15 +49,21 @@ class TransactionListDelimiterRowHolder extends TransactionRowHolderBase {
             b.transactionDelimiterMonth.setText(
                     Globals.monthNames[cal.get(GregorianCalendar.MONTH)]);
             b.transactionDelimiterMonth.setVisibility(View.VISIBLE);
-            //                holder.vDelimiterLine.setBackgroundResource(R.drawable
-            //                .dashed_border_8dp);
             b.transactionDelimiterThick.setVisibility(View.VISIBLE);
+            ConstraintLayout.LayoutParams lp =
+                    (ConstraintLayout.LayoutParams) b.transactionDelimiterThick.getLayoutParams();
+            lp.height = DimensionUtils.dp2px(b.getRoot()
+                                              .getContext(), 4);
+            b.transactionDelimiterThick.setLayoutParams(lp);
         }
         else {
             b.transactionDelimiterMonth.setVisibility(View.GONE);
-            //                holder.vDelimiterLine.setBackgroundResource(R.drawable
-            //                .dashed_border_1dp);
-            b.transactionDelimiterThick.setVisibility(View.GONE);
+            ConstraintLayout.LayoutParams lp =
+                    (ConstraintLayout.LayoutParams) b.transactionDelimiterThick.getLayoutParams();
+            lp.height = DimensionUtils.dp2px(b.getRoot()
+                                              .getContext(), 1.3f);
+            b.transactionDelimiterThick.setLayoutParams(lp);
+            b.transactionDelimiterThick.setVisibility(View.VISIBLE);
         }
 
     }
index 7cf710ac0067b3b90319190c4f5524679beb38b6..348a5598a324073ea2415f353cd32a1019b72542 100644 (file)
@@ -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.utils;
 
+import static net.ktnx.mobileledger.utils.Logger.debug;
+
 import android.app.Activity;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -38,8 +40,6 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
 
-import static net.ktnx.mobileledger.utils.Logger.debug;
-
 public class Colors {
     public static final int DEFAULT_HUE_DEG = 261;
     public static final MutableLiveData<Integer> themeWatch = new MutableLiveData<>(0);
@@ -76,7 +76,7 @@ public class Colors {
         TypedValue tv = new TypedValue();
         theme.resolveAttribute(R.attr.table_row_dark_bg, tv, true);
         tableRowDarkBG = tv.data;
-        theme.resolveAttribute(R.attr.colorPrimary, tv, true);
+        theme.resolveAttribute(androidx.appcompat.R.attr.colorPrimary, tv, true);
         primary = tv.data;
 
         if (themePrimaryColor.size() == 0) {
@@ -84,7 +84,7 @@ public class Colors {
                 Resources.Theme tmpTheme = theme.getResources()
                                                 .newTheme();
                 tmpTheme.applyStyle(themeId, true);
-                tmpTheme.resolveAttribute(R.attr.colorPrimary, tv, false);
+                tmpTheme.resolveAttribute(androidx.appcompat.R.attr.colorPrimary, tv, false);
                 themePrimaryColor.put(themeId, tv.data);
             }
         }
@@ -180,7 +180,7 @@ public class Colors {
                         huesSB.append(", ");
                     huesSB.append(h);
                 }
-                debug("profiles", String.format("used hues: %s", huesSB.toString()));
+                debug("profiles", String.format("used hues: %s", huesSB));
             }
             hues.add(hues.get(0));
 
diff --git a/app/src/main/res/menu/account_list.xml b/app/src/main/res/menu/account_list.xml
new file mode 100644 (file)
index 0000000..5a76161
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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
+  ~ the Free Software Foundation, either version 3 of the License, or
+  ~ (at your opinion), any later version.
+  ~
+  ~ MoLe is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  ~ GNU General Public License terms for details.
+  ~
+  ~ You should have received a copy of the GNU General Public License
+  ~ along with MoLe. If not, see <https://www.gnu.org/licenses/>.
+  -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    >
+
+    <item
+        android:id="@+id/menu_account_list_show_zero_balances"
+        android:checkable="true"
+        android:enabled="true"
+        android:menuCategory="container"
+        android:title="@string/accounts_menu_show_zero"
+        android:titleCondensed="@string/accounts_menu_show_zero_condensed"
+        android:visible="true"
+        app:showAsAction="withText"
+        />
+</menu>
\ No newline at end of file
index 4ba6fe385256fd8800789ee1d432d21e7861b36a..ccb47516c7ce94db047f23881c99479810dc84c8 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ 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
     <string name="no_profile_restore_hint">… а може и да възстановите настройките от резервно копие</string>
     <string name="profile_not_available">Недостъпен профил</string>
     <string name="api_1_23">Версия 1.23</string>
+    <string name="accounts_menu_show_zero">Сметки с нулев баланс</string>
+    <string name="accounts_menu_show_zero_condensed">Нулеви сметки</string>
 </resources>
index d4fec3ac4f274ac8f9043784ab829101603aebc8..52d84690005411a968feef747c3b8d94bf881da9 100644 (file)
@@ -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
     <string name="no_profile_restore_hint">… or, you may restore from backup</string>
     <string name="profile_not_available">Profile not available</string>
     <string name="api_1_23">Version 1.23</string>
+    <string name="accounts_menu_show_zero">Show zero balances</string>
+    <string name="accounts_menu_show_zero_condensed">Zero balances</string>
 </resources>
diff --git a/app/src/main/res/xml/backup_descriptor.xml b/app/src/main/res/xml/backup_descriptor.xml
deleted file mode 100644 (file)
index 93cbcae..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright © 2019 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
-  ~ the Free Software Foundation, either version 3 of the License, or
-  ~ (at your opinion), any later version.
-  ~
-  ~ MoLe is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-  ~ GNU General Public License terms for details.
-  ~
-  ~ You should have received a copy of the GNU General Public License
-  ~ along with MoLe. If not, see <https://www.gnu.org/licenses/>.
-  -->
-
-<full-backup-content>
-    <!-- Exclude specific shared preferences that contain GCM registration Id -->
-</full-backup-content>
index 223e12e8fbcb0f28f1559e621f1ebf197a23dbc2..c1da32275828ef31c0ccca046348a72b5a50e47f 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?><!--
-  ~ Copyright © 2019 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
   -->
 
 <network-security-config>
-    <base-config cleartextTrafficPermitted="true" />
+    <base-config cleartextTrafficPermitted="true">
+        <trust-anchors>
+            <certificates src="system" />
+            <certificates src="user" />
+        </trust-anchors>
+    </base-config>
 </network-security-config>
\ No newline at end of file
index acc8190a2f325dc1294955ee400cfe018b3b5776..e9d71576e71beaaba39d96d67f402a45e9f63e69 100644 (file)
@@ -24,7 +24,7 @@ buildscript {
         mavenCentral()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:7.1.2'
+        classpath 'com.android.tools.build:gradle:8.0.2'
         
 
         // NOTE: Do not place your application dependencies here; they belong
index 048e816edeb7bd5d8292f38228ae641cf4edf448..db96c7725ba87fd8ea2d7a50722e54fe5ebacccf 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright © 2019 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
 # along with MoLe. If not, see <https://www.gnu.org/licenses/>.
 #
 
-# Project-wide Gradle settings.
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-# For more details on how to configure your build environment visit
+## For more details on how to configure your build environment visit
 # http://www.gradle.org/docs/current/userguide/build_environment.html
+#
 # Specifies the JVM arguments used for the daemon process.
 # The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx1536m
+# Default value: -Xmx1024m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+#
 # When configured, Gradle will run in incubating parallel mode.
 # This option should only be used with decoupled projects. More details, visit
 # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
 # org.gradle.parallel=true
+#Sun Mar 17 11:29:00 EET 2024
 android.debug.obsoleteApi=true
+android.defaults.buildfeatures.buildconfig=true
+android.enableJetifier=false
+android.enableR8.fullMode=false
+android.nonFinalResIds=false
+android.nonTransitiveRClass=true
 android.useAndroidX=true
-android.enableJetifier=true
\ No newline at end of file
+org.gradle.jvmargs=-Xmx1024M -Dkotlin.daemon.jvm.options\="-Xmx1536M"
+org.gradle.unsafe.configuration-cache=true
index 08b1a0c0f020a68d20ab5b7322042a95c70ebdbb..855f89cc8328ec83f5f1cf99a034a4c0aa8cd550 100644 (file)
@@ -1,6 +1,21 @@
-#Sat Nov 28 08:24:27 EET 2020
+#
+# 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
+# the Free Software Foundation, either version 3 of the License, or
+# (at your opinion), any later version.
+#
+# MoLe is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License terms for details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MoLe. If not, see <https://www.gnu.org/licenses/>.
+#
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
diff --git a/metadata/bg-BG/changelogs/52.txt b/metadata/bg-BG/changelogs/52.txt
new file mode 100644 (file)
index 0000000..9c8c8db
--- /dev/null
@@ -0,0 +1,5 @@
+* ПОПРАВКИ
+    + коригирани версии на gradle
+* ДРУГИ
+    + обновени версии на множество библиотеки
+    + прицелване във версия 31 на платформата
diff --git a/metadata/bg-BG/changelogs/53.txt b/metadata/bg-BG/changelogs/53.txt
new file mode 100644 (file)
index 0000000..427dbb3
--- /dev/null
@@ -0,0 +1,4 @@
+* ПОПРАВКИ
+    + отстранен проблем със съвместимостта с hledger-web 1.23+ при изпращане на нови транзакции. Благодарности на Faye Duxovni за поправката!
+    + поправен срив при изтриване на шаблони
+    + поправен рядък срив при изпращане на транзакции, съдържащи повече от една сметка без сума и нулев остатъчен баланс
diff --git a/metadata/bg-BG/changelogs/54.txt b/metadata/bg-BG/changelogs/54.txt
new file mode 100644 (file)
index 0000000..2e1dace
--- /dev/null
@@ -0,0 +1,2 @@
+* ПОПРАВКИ
+    + отстранен проблем с централизираното резервно копие на настройките
diff --git a/metadata/bg-BG/changelogs/55.txt b/metadata/bg-BG/changelogs/55.txt
new file mode 100644 (file)
index 0000000..208db92
--- /dev/null
@@ -0,0 +1,2 @@
+* ПОПРАВКИ
+    + отстранен проблем при изпращане на транзакции към hledger-web 1.23+
diff --git a/metadata/bg-BG/changelogs/56.txt b/metadata/bg-BG/changelogs/56.txt
new file mode 100644 (file)
index 0000000..218ba4a
--- /dev/null
@@ -0,0 +1,4 @@
+* ПОПРАВКИ
+    + Позволяване на потребителски сертификати в настройките за сигурността на мрежовите връзки
+* ДРУГИ
+    + Обновена версия на gradle
diff --git a/metadata/en-US/changelogs/52.txt b/metadata/en-US/changelogs/52.txt
new file mode 100644 (file)
index 0000000..13f6c20
--- /dev/null
@@ -0,0 +1,6 @@
+* FIXES
+    + sync gradle version requirements
+* OTHERS
+    + bump version of several dependent libraries
+    + bump SDK version to 31
+    + adjust deprecated constructor usage
diff --git a/metadata/en-US/changelogs/53.txt b/metadata/en-US/changelogs/53.txt
new file mode 100644 (file)
index 0000000..8e8601b
--- /dev/null
@@ -0,0 +1,4 @@
+* FIXES
+    + fix compatibility wuth hledger-web 1.23+ when submitting new transactions. Thanks to Faye Duxovni for the patch!
+    + fix a crash when deleting templates
+    + fix a rare crash when submitting transactions with multiple accounts with no amounts with zero remaining balance
diff --git a/metadata/en-US/changelogs/54.txt b/metadata/en-US/changelogs/54.txt
new file mode 100644 (file)
index 0000000..a2e3a20
--- /dev/null
@@ -0,0 +1,2 @@
+* FIXES
+    + fix cloud backup
diff --git a/metadata/en-US/changelogs/55.txt b/metadata/en-US/changelogs/55.txt
new file mode 100644 (file)
index 0000000..3697ab5
--- /dev/null
@@ -0,0 +1,2 @@
+* FIXES:
+    + fixed sending of transactions to hledger-web 1.23+
diff --git a/metadata/en-US/changelogs/56.txt b/metadata/en-US/changelogs/56.txt
new file mode 100644 (file)
index 0000000..9b7d3ac
--- /dev/null
@@ -0,0 +1,4 @@
+* FIXES:
+    + allow user certificates in network security config
+* OTHERS:
+    + bump gradle version