]> git.ktnx.net Git - mobile-ledger.git/commitdiff
last update text also includes transaction count
authorDamyan Ivanov <dam+mobileledger@ktnx.net>
Sat, 19 Sep 2020 07:02:36 +0000 (10:02 +0300)
committerDamyan Ivanov <dam+mobileledger@ktnx.net>
Sat, 19 Sep 2020 09:59:06 +0000 (09:59 +0000)
and is maintained by the main activity, which has access to all the
relevant bits - string resources, live data observation, up to date
transaction count

app/src/main/java/net/ktnx/mobileledger/async/TransactionAccumulator.java
app/src/main/java/net/ktnx/mobileledger/model/Data.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/activity/MainActivity.java
app/src/main/java/net/ktnx/mobileledger/ui/transaction_list/TransactionListAdapter.java
app/src/main/java/net/ktnx/mobileledger/ui/transaction_list/TransactionRowHolder.java
app/src/main/res/layout/last_update_layout.xml
app/src/main/res/values-bg/strings.xml
app/src/main/res/values/strings.xml

index 43d36e1f9af3ba80d48fb533c955023b02f8d1bf..b8c8e6966dca39f92844fc277bec770294699d84 100644 (file)
@@ -30,6 +30,7 @@ public class TransactionAccumulator {
     private SimpleDate earliestDate, latestDate;
     private SimpleDate lastDate = SimpleDate.today();
     private boolean done;
+    private int transactionCount = 0;
     public TransactionAccumulator(MainModel model) {
         this.model = model;
     }
@@ -53,10 +54,11 @@ public class TransactionAccumulator {
         list.add(new TransactionListItem(transaction));
 
         lastDate = date;
+        transactionCount++;
     }
     public void done() {
         done = true;
-        model.setDisplayedTransactions(list);
+        model.setDisplayedTransactions(list, transactionCount);
         model.setFirstTransactionDate(earliestDate);
         model.setLastTransactionDate(latestDate);
     }
index 66738cb0ba3c2d9303dfd1a5533be836dfb56b5e..6d51287f35bfa6a74c138a15d4dbb0f83143b818 100644 (file)
@@ -56,8 +56,10 @@ public final class Data {
     public static final MutableLiveData<Boolean> currencyGap = new MutableLiveData<>(true);
     public static final MutableLiveData<Locale> locale = new MutableLiveData<>();
     public static final MutableLiveData<Boolean> drawerOpen = new MutableLiveData<>(false);
-    public static final MutableLiveData<Date> lastUpdateLiveData = new MutableLiveData<>(null);
-    public static final ObservableValue<Long> lastUpdate = new ObservableValue<>();
+    public static final MutableLiveData<Date> lastUpdateDate = new MutableLiveData<>(null);
+    public static final MutableLiveData<Integer> lastUpdateTransactionCount =
+            new MutableLiveData<>(0);
+    public static final ObservableValue<String> lastUpdateText = new ObservableValue<>();
     private static final MutableLiveData<MobileLedgerProfile> profile =
             new InertMutableLiveData<>();
     private static final AtomicInteger backgroundTaskCount = new AtomicInteger(0);
index 6d640d622d5bca660f578cd14b0b8e212f67fd34..4d232319e0a37bfa6d70230b36d66cbdd28b4b1b 100644 (file)
@@ -124,11 +124,11 @@ public class MainModel extends ViewModel {
 
         return merged;
     }
-    private void setLastUpdateStamp() {
+    private void setLastUpdateStamp(long transactionCount) {
         debug("db", "Updating transaction value stamp");
         Date now = new Date();
         profile.setLongOption(MLDB.OPT_LAST_SCRAPE, now.getTime());
-        Data.lastUpdateLiveData.postValue(now);
+        Data.lastUpdateDate.postValue(now);
     }
     public void scheduleTransactionListReload() {
         UpdateTransactionsTask task = new UpdateTransactionsTask();
@@ -147,8 +147,9 @@ public class MainModel extends ViewModel {
     public LiveData<List<TransactionListItem>> getDisplayedTransactions() {
         return displayedTransactions;
     }
-    public void setDisplayedTransactions(List<TransactionListItem> list) {
+    public void setDisplayedTransactions(List<TransactionListItem> list, int transactionCount) {
         displayedTransactions.postValue(list);
+        Data.lastUpdateTransactionCount.postValue(transactionCount);
     }
     public SimpleDate getFirstTransactionDate() {
         return firstTransactionDate;
@@ -227,7 +228,7 @@ public class MainModel extends ViewModel {
             List<LedgerAccount> accounts, List<LedgerTransaction> transactions) {
         profile.storeAccountAndTransactionListAsync(accounts, transactions);
 
-        setLastUpdateStamp();
+        setLastUpdateStamp(transactions.size());
 
         mergeAccountListFromWeb(accounts);
         updateDisplayedAccounts();
index c6c909152de2b6cb575d4130e58bd6688aee63a9..cc6cff1878a336620ff0df206abf2fc82a1d0d34 100644 (file)
@@ -20,7 +20,6 @@ package net.ktnx.mobileledger.ui.account_summary;
 import android.content.Context;
 import android.content.res.Resources;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -257,32 +256,29 @@ public class AccountSummaryAdapter
 
                     break;
                 case HEADER:
-                    setLastUpdateText(Data.lastUpdate.get());
+                    setLastUpdateText(Data.lastUpdateText.get());
                     break;
                 default:
                     throw new IllegalStateException("Unexpected value: " + newType);
             }
 
         }
-        void setLastUpdateText(long lastUpdate) {
-            final int formatFlags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR |
-                                    DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_NUMERIC_DATE;
-            tvLastUpdate.setText((lastUpdate == 0) ? "----" : DateUtils.formatDateTime(
-                    tvLastUpdate.getContext(), lastUpdate, formatFlags));
+        void setLastUpdateText(String text) {
+            tvLastUpdate.setText(text);
         }
         private void initLastUpdateObserver() {
             if (lastUpdateObserver != null)
                 return;
 
-            lastUpdateObserver = (o, arg) -> setLastUpdateText(Data.lastUpdate.get());
+            lastUpdateObserver = (o, arg) -> setLastUpdateText(Data.lastUpdateText.get());
 
-            Data.lastUpdate.addObserver(lastUpdateObserver);
+            Data.lastUpdateText.addObserver(lastUpdateObserver);
         }
         private void dropLastUpdateObserver() {
             if (lastUpdateObserver == null)
                 return;
 
-            Data.lastUpdate.deleteObserver(lastUpdateObserver);
+            Data.lastUpdateText.deleteObserver(lastUpdateObserver);
             lastUpdateObserver = null;
         }
         private void setType(AccountListItem.Type newType) {
index 9082695fc4973d0adabd0ac38272ec83c381240d..03617c5923c8fe9ef1f431bc35c86e13ebc0e2ac 100644 (file)
@@ -27,6 +27,7 @@ import android.graphics.Color;
 import android.graphics.drawable.Icon;
 import android.os.Build;
 import android.os.Bundle;
+import android.text.format.DateUtils;
 import android.util.Log;
 import android.view.View;
 import android.view.animation.AnimationUtils;
@@ -69,6 +70,7 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
+import java.util.Objects;
 
 /*
  * TODO: reports
@@ -331,6 +333,9 @@ public class MainActivity extends ProfileThemedActivity {
                              .show();
                      mainModel.clearUpdateError();
                  });
+        Data.locale.observe(this, l -> refreshLastUpdateInfo());
+        Data.lastUpdateDate.observe(this, date -> refreshLastUpdateInfo());
+        Data.lastUpdateTransactionCount.observe(this, date -> refreshLastUpdateInfo());
     }
     private void scheduleDataRetrievalIfStale(long lastUpdate) {
         long now = new Date().getTime();
@@ -462,7 +467,8 @@ public class MainActivity extends ProfileThemedActivity {
         // un-hook all observed LiveData
         Data.removeProfileObservers(this);
         Data.profiles.removeObservers(this);
-        Data.lastUpdateLiveData.removeObservers(this);
+        Data.lastUpdateTransactionCount.removeObservers(this);
+        Data.lastUpdateDate.removeObservers(this);
 
         recreate();
     }
@@ -554,26 +560,26 @@ public class MainActivity extends ProfileThemedActivity {
 
         Logger.debug("transactions", String.format(Locale.ENGLISH, "Last update = %d", lastUpdate));
         if (lastUpdate == 0) {
-            Data.lastUpdateLiveData.postValue(null);
+            Data.lastUpdateDate.postValue(null);
         }
         else {
-            Data.lastUpdateLiveData.postValue(new Date(lastUpdate));
+            Data.lastUpdateDate.postValue(new Date(lastUpdate));
         }
 
-        // this is unfortunate, but it appears we need a two-stage rocket to make
-        // a value reach a recycler view item holder. first stage is a regular
-        // LiveData that can be observed by an activity (this).
-        // the second stage forwards the changes, in the UI thread, to the
-        // observable value, observed by the view holders.
-        // view holders can't observe the LiveData because they don't have
-        // access to lifecycle owners. oh, also the value is updated by a thread
-        // so it must be tunnelled by an activity for it to reach the view
-        // holders in the UI thread
-        Data.lastUpdateLiveData.observe(this, date -> runOnUiThread(
-                () -> Data.lastUpdate.set((date == null) ? 0 : date.getTime())));
         scheduleDataRetrievalIfStale(lastUpdate);
 
     }
+    private void refreshLastUpdateInfo() {
+        final int formatFlags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR |
+                                DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_NUMERIC_DATE;
+        String template = getResources().getString(R.string.transaction_count_summary);
+        Integer transactionCount = Data.lastUpdateTransactionCount.getValue();
+        Date lastUpdate = Data.lastUpdateDate.getValue();
+        Data.lastUpdateText.set((lastUpdate == null) ? "----" : String.format(
+                Objects.requireNonNull(Data.locale.getValue()), template,
+                (transactionCount == null) ? 0 : transactionCount,
+                DateUtils.formatDateTime(this, lastUpdate.getTime(), formatFlags)));
+    }
     public void onStopTransactionRefreshClick(View view) {
         Logger.debug("interactive", "Cancelling transactions refresh");
         mainModel.stopTransactionsRetrieval();
index 94712cbdcbac809caa232ceff382f37ddc9fb766..d9f4cf16a53a56a465926078af4964925d0d5fdf 100644 (file)
@@ -166,7 +166,7 @@ public class TransactionListAdapter extends RecyclerView.Adapter<TransactionRowH
                 }
                 break;
             case HEADER:
-                holder.setLastUpdateText(Data.lastUpdate.get());
+                holder.setLastUpdateText(Data.lastUpdateText.get());
 
                 break;
             default:
index ba48d70ca7994ac9bc4575b573016b1b0b853f49..658a338ae3af30c117dc96052e69690aba59f29d 100644 (file)
@@ -17,7 +17,6 @@
 
 package net.ktnx.mobileledger.ui.transaction_list;
 
-import android.text.format.DateUtils;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -64,22 +63,18 @@ class TransactionRowHolder extends RecyclerView.ViewHolder {
         if (lastUpdateObserver != null)
             return;
 
-        lastUpdateObserver = (o, arg) -> setLastUpdateText(Data.lastUpdate.get());
+        lastUpdateObserver = (o, arg) -> setLastUpdateText(Data.lastUpdateText.get());
 
-        Data.lastUpdate.addObserver(lastUpdateObserver);
+        Data.lastUpdateText.addObserver(lastUpdateObserver);
     }
-    void setLastUpdateText(long lastUpdate) {
-        final int formatFlags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR |
-                                DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_NUMERIC_DATE;
-        tvLastUpdate.setText((lastUpdate == 0) ? "----"
-                                               : DateUtils.formatDateTime(tvLastUpdate.getContext(),
-                                                       lastUpdate, formatFlags));
+    void setLastUpdateText(String text) {
+        tvLastUpdate.setText(text);
     }
     private void dropLastUpdateObserver() {
         if (lastUpdateObserver == null)
             return;
 
-        Data.lastUpdate.deleteObserver(lastUpdateObserver);
+        Data.lastUpdateText.deleteObserver(lastUpdateObserver);
         lastUpdateObserver = null;
     }
     void setType(TransactionListItem.Type newType) {
index 2150affe4ebd840fa0adadb661521dbeefcf81b5..b1640f32a2b60705a2929706f5d4a3528f7d1ac3 100644 (file)
     android:layout_height="wrap_content"
     android:paddingTop="4dp"
     >
-    <TextView
-        android:id="@+id/last_update_label"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:paddingStart="8dp"
-        android:paddingEnd="8dp"
-        android:text="@string/transactions_last_update_label"
-        android:textAppearance="@android:style/TextAppearance.Material.Small"
-        app:layout_constraintEnd_toStartOf="@id/last_update_text"
-        app:layout_constraintTop_toTopOf="parent"
-        />
 
     <TextView
         android:id="@+id/last_update_text"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginEnd="@dimen/activity_horizontal_margin"
+        android:layout_marginHorizontal="@dimen/activity_horizontal_margin"
         android:layout_weight="1"
-        android:text="\?"
+        android:gravity="center"
+        android:text="1 123 transactions as of 29.02.2020 13:37"
         android:textAppearance="@android:style/TextAppearance.Material.Small"
         app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         tools:ignore="HardcodedText"
         />
index 0b16b82cc41b56b815dc44f692ac7cd3bda3e91e..193a9faed85bb318e292ec61e811b8f00eadce79 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright © 2019 Damyan Ivanov.
+  ~ 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
     <string name="navigation_drawer_open">Отваряне на страничния панел</string>
     <string name="navigation_drawer_close">Затваряне на страничния панел</string>
     <string name="nav_header_desc">Заглавна част на страничния панел</string>
+    <string name="transaction_count_summary">%,d движения към %s</string>
 </resources>
index d1578be01f6b46a1a30ed1342297afb67d2ae8ba..9272c86a0d768b758fce1bddb55ae6bd277cf4ea 100644 (file)
     <string name="go_to_date_menu_title">Go to date</string>
     <string name="splash_icon_description">Main app icon</string>
     <string name="sub_accounts_expand_collapse_trigger_description">Sub-accounts expand/collapse trigger</string>
+    <string name="transaction_count_summary">%,d transactions as of %s</string>
 </resources>