confirmations indicator (#775)

This commit is contained in:
m2049r 2021-08-07 11:17:13 +02:00 committed by GitHub
parent 002dfd5d58
commit 9cd8a75dc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 35 deletions

View File

@ -58,7 +58,6 @@ import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects;
import timber.log.Timber; import timber.log.Timber;
@ -128,7 +127,7 @@ public class WalletFragment extends Fragment
currencies.add(Helper.BASE_CRYPTO); currencies.add(Helper.BASE_CRYPTO);
if (Helper.SHOW_EXCHANGERATES) if (Helper.SHOW_EXCHANGERATES)
currencies.addAll(Arrays.asList(getResources().getStringArray(R.array.currency))); currencies.addAll(Arrays.asList(getResources().getStringArray(R.array.currency)));
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(Objects.requireNonNull(getContext()), R.layout.item_spinner_balance, currencies); ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(requireContext(), R.layout.item_spinner_balance, currencies);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sCurrency.setAdapter(spinnerAdapter); sCurrency.setAdapter(spinnerAdapter);
@ -346,13 +345,18 @@ public class WalletFragment extends Fragment
// if account index has changed scroll to top? // if account index has changed scroll to top?
private int accountIndex = 0; private int accountIndex = 0;
public void onRefreshed(final Wallet wallet, final boolean full) { public void onRefreshed(final Wallet wallet, boolean full) {
Timber.d("onRefreshed(%b)", full); Timber.d("onRefreshed(%b)", full);
if (adapter.needsTransactionUpdateOnNewBlock()) {
wallet.getHistory().refresh();
full = true;
}
if (full) { if (full) {
List<TransactionInfo> list = new ArrayList<>(); List<TransactionInfo> list = new ArrayList<>();
final long streetHeight = activityCallback.getStreetModeHeight(); final long streetHeight = activityCallback.getStreetModeHeight();
Timber.d("StreetHeight=%d", streetHeight); Timber.d("StreetHeight=%d", streetHeight);
wallet.getHistory().refresh();
for (TransactionInfo info : wallet.getHistory().getAll()) { for (TransactionInfo info : wallet.getHistory().getAll()) {
Timber.d("TxHeight=%d, Label=%s", info.blockheight, info.subaddressLabel); Timber.d("TxHeight=%d, Label=%s", info.blockheight, info.subaddressLabel);
if ((info.isPending || (info.blockheight >= streetHeight)) if ((info.isPending || (info.blockheight >= streetHeight))
@ -561,7 +565,7 @@ public class WalletFragment extends Fragment
//TODO figure out why gunther disappears on return from send although he is still set //TODO figure out why gunther disappears on return from send although he is still set
if (enable) { if (enable) {
if (streetGunther == null) if (streetGunther == null)
streetGunther = ContextCompat.getDrawable(Objects.requireNonNull(getContext()), R.drawable.ic_gunther_streetmode); streetGunther = ContextCompat.getDrawable(requireContext(), R.drawable.ic_gunther_streetmode);
ivStreetGunther.setImageDrawable(streetGunther); ivStreetGunther.setImageDrawable(streetGunther);
} else } else
ivStreetGunther.setImageDrawable(null); ivStreetGunther.setImageDrawable(null);

View File

@ -30,6 +30,7 @@ import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.progressindicator.CircularProgressIndicator;
import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.data.Crypto; import com.m2049r.xmrwallet.data.Crypto;
import com.m2049r.xmrwallet.data.UserNotes; import com.m2049r.xmrwallet.data.UserNotes;
@ -48,7 +49,9 @@ import java.util.TimeZone;
import timber.log.Timber; import timber.log.Timber;
public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfoAdapter.ViewHolder> { public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfoAdapter.ViewHolder> {
private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm"); private final static int MAX_CONFIRMATIONS = 10;
private final static SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
private final int outboundColour; private final int outboundColour;
private final int inboundColour; private final int inboundColour;
@ -77,6 +80,10 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
DATETIME_FORMATTER.setTimeZone(tz); DATETIME_FORMATTER.setTimeZone(tz);
} }
public boolean needsTransactionUpdateOnNewBlock() {
return (infoItems.size() > 0) && (infoItems.get(0).confirmations < MAX_CONFIRMATIONS);
}
private static class TransactionInfoDiff extends DiffCallback<TransactionInfo> { private static class TransactionInfoDiff extends DiffCallback<TransactionInfo> {
public TransactionInfoDiff(List<TransactionInfo> oldList, List<TransactionInfo> newList) { public TransactionInfoDiff(List<TransactionInfo> oldList, List<TransactionInfo> newList) {
@ -95,6 +102,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
return (oldItem.direction == newItem.direction) return (oldItem.direction == newItem.direction)
&& (oldItem.isPending == newItem.isPending) && (oldItem.isPending == newItem.isPending)
&& (oldItem.isFailed == newItem.isFailed) && (oldItem.isFailed == newItem.isFailed)
&& (oldItem.confirmations == newItem.confirmations)
&& (oldItem.subaddressLabel.equals(newItem.subaddressLabel)) && (oldItem.subaddressLabel.equals(newItem.subaddressLabel))
&& (Objects.equals(oldItem.notes, newItem.notes)); && (Objects.equals(oldItem.notes, newItem.notes));
} }
@ -149,6 +157,8 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
final TextView tvFee; final TextView tvFee;
final TextView tvPaymentId; final TextView tvPaymentId;
final TextView tvDateTime; final TextView tvDateTime;
final CircularProgressIndicator pbConfirmations;
final TextView tvConfirmations;
TransactionInfo infoItem; TransactionInfo infoItem;
ViewHolder(View itemView) { ViewHolder(View itemView) {
@ -158,6 +168,9 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
tvFee = itemView.findViewById(R.id.tx_fee); tvFee = itemView.findViewById(R.id.tx_fee);
tvPaymentId = itemView.findViewById(R.id.tx_paymentid); tvPaymentId = itemView.findViewById(R.id.tx_paymentid);
tvDateTime = itemView.findViewById(R.id.tx_datetime); tvDateTime = itemView.findViewById(R.id.tx_datetime);
pbConfirmations = itemView.findViewById(R.id.pbConfirmations);
pbConfirmations.setMax(MAX_CONFIRMATIONS);
tvConfirmations = itemView.findViewById(R.id.tvConfirmations);
} }
private String getDateTime(long time) { private String getDateTime(long time) {
@ -182,7 +195,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
ivTxType.setVisibility(View.GONE); ivTxType.setVisibility(View.GONE);
} }
} else { } else {
ivTxType.setVisibility(View.GONE); // gives us more space for the amount ivTxType.setVisibility(View.GONE);
} }
String displayAmount = Helper.getDisplayAmount(infoItem.amount, Helper.DISPLAY_DIGITS_INFO); String displayAmount = Helper.getDisplayAmount(infoItem.amount, Helper.DISPLAY_DIGITS_INFO);
@ -205,12 +218,34 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
this.tvFee.setText(context.getString(R.string.tx_list_failed_text)); this.tvFee.setText(context.getString(R.string.tx_list_failed_text));
tvFee.setVisibility(View.VISIBLE); tvFee.setVisibility(View.VISIBLE);
setTxColour(failedColour); setTxColour(failedColour);
pbConfirmations.setVisibility(View.GONE);
tvConfirmations.setVisibility(View.GONE);
} else if (infoItem.isPending) { } else if (infoItem.isPending) {
setTxColour(pendingColour); setTxColour(pendingColour);
pbConfirmations.setVisibility(View.GONE);
pbConfirmations.setIndeterminate(true);
pbConfirmations.setVisibility(View.VISIBLE);
tvConfirmations.setVisibility(View.GONE);
} else if (infoItem.direction == TransactionInfo.Direction.Direction_In) { } else if (infoItem.direction == TransactionInfo.Direction.Direction_In) {
setTxColour(inboundColour); setTxColour(inboundColour);
final int confirmations = (int) infoItem.confirmations;
if (confirmations <= MAX_CONFIRMATIONS) {
pbConfirmations.setVisibility(View.VISIBLE);
pbConfirmations.setProgressCompat(confirmations, true);
final String confCount = Integer.toString(confirmations);
tvConfirmations.setText(confCount);
if (confCount.length() == 1) // we only have space for character in the progress circle
tvConfirmations.setVisibility(View.VISIBLE);
else
tvConfirmations.setVisibility(View.GONE);
} else {
pbConfirmations.setVisibility(View.GONE);
tvConfirmations.setVisibility(View.GONE);
}
} else { } else {
setTxColour(outboundColour); setTxColour(outboundColour);
pbConfirmations.setVisibility(View.GONE);
tvConfirmations.setVisibility(View.GONE);
} }
String tag = null; String tag = null;

View File

@ -108,16 +108,12 @@ public class WalletService extends Service {
Timber.d("unconfirmedMoneyReceived() %d @ %s", amount, txId); Timber.d("unconfirmedMoneyReceived() %d @ %s", amount, txId);
} }
long lastBlockTime = 0;
int lastTxCount = 0; int lastTxCount = 0;
public void newBlock(long height) { public void newBlock(long height) {
final Wallet wallet = getWallet(); final Wallet wallet = getWallet();
if (wallet == null) throw new IllegalStateException("No wallet!"); if (wallet == null) throw new IllegalStateException("No wallet!");
// don't flood with an update for every block ...
if (lastBlockTime < System.currentTimeMillis() - 2000) {
Timber.d("newBlock() @ %d with observer %s", height, observer); Timber.d("newBlock() @ %d with observer %s", height, observer);
lastBlockTime = System.currentTimeMillis();
if (observer != null) { if (observer != null) {
boolean fullRefresh = false; boolean fullRefresh = false;
updateDaemonState(wallet, wallet.isSynchronized() ? height : 0); updateDaemonState(wallet, wallet.isSynchronized() ? height : 0);
@ -136,7 +132,6 @@ public class WalletService extends Service {
observer.onRefreshed(wallet, fullRefresh); observer.onRefreshed(wallet, fullRefresh);
} }
} }
}
public void updated() { public void updated() {
Timber.d("updated()"); Timber.d("updated()");

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -19,6 +20,11 @@
android:layout_weight="9" android:layout_weight="9"
android:orientation="horizontal"> android:orientation="horizontal">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageView <ImageView
android:id="@+id/ivTxType" android:id="@+id/ivTxType"
android:layout_width="16dp" android:layout_width="16dp"
@ -27,6 +33,31 @@
android:src="@drawable/ic_xmrto_btc" android:src="@drawable/ic_xmrto_btc"
android:visibility="visible" /> android:visibility="visible" />
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/pbConfirmations"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:indeterminate="false"
android:max="10"
android:progress="8"
android:visibility="visible"
app:indicatorInset="0dp"
app:indicatorSize="30dp"
app:trackThickness="4dp" />
<TextView
android:id="@+id/tvConfirmations"
style="@style/MoneroText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingBottom="1dp"
android:text="8"
android:visibility="visible" />
</FrameLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -57,8 +88,8 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_weight="13" android:layout_weight="13"
android:gravity="start" android:gravity="start"
tools:text="0123456789abcdef" /> tools:text="0123456789abcdef" />

View File

@ -6,7 +6,7 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.2.0' classpath 'com.android.tools.build:gradle:4.2.2'
} }
} }