mirror of
https://codeberg.org/r4v3r23/mysu.git
synced 2024-11-09 20:53:47 +01:00
0.4.7
Transaction screen redesign. Now auto-updates as well. Tx builder fee calculation fixes (thanks to Monero C++ bug fixes). Wallet balance now displays immediately once synced, fixing a recent bug where it was delayed by a few seconds.
This commit is contained in:
parent
eb8d0b0b46
commit
bc004857ee
@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "net.mynero.wallet"
|
applicationId "net.mynero.wallet"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 34
|
targetSdkVersion 34
|
||||||
versionCode 40600
|
versionCode 40700
|
||||||
versionName "0.4.6 'Fluorine Fermi'"
|
versionName "0.4.7 'Fluorine Fermi'"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
|
@ -108,8 +108,10 @@ public class MainActivity extends AppCompatActivity implements MoneroHandlerThre
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRefresh() {
|
public void onRefresh(boolean walletSynced) {
|
||||||
|
if(walletSynced)
|
||||||
this.utxoService.refreshUtxos();
|
this.utxoService.refreshUtxos();
|
||||||
|
|
||||||
this.historyService.refreshHistory();
|
this.historyService.refreshHistory();
|
||||||
this.balanceService.refreshBalance();
|
this.balanceService.refreshBalance();
|
||||||
this.blockchainService.refreshBlockchain();
|
this.blockchainService.refreshBlockchain();
|
||||||
|
@ -351,13 +351,17 @@ public class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getAddress() {
|
public String getAddress() {
|
||||||
return getHost() + ":" + rpcPort;
|
return getHost() + ":" + getRpcPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRpcPort() {
|
||||||
|
return rpcPort;
|
||||||
|
}
|
||||||
|
|
||||||
public void setHost(String host) throws UnknownHostException {
|
public void setHost(String host) throws UnknownHostException {
|
||||||
if ((host == null) || (host.isEmpty()))
|
if ((host == null) || (host.isEmpty()))
|
||||||
throw new UnknownHostException("loopback not supported (yet?)");
|
throw new UnknownHostException("loopback not supported (yet?)");
|
||||||
|
@ -41,6 +41,7 @@ public class AddNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
|||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
Button addNodeButton = view.findViewById(R.id.add_node_button);
|
Button addNodeButton = view.findViewById(R.id.add_node_button);
|
||||||
EditText addressEditText = view.findViewById(R.id.address_edittext);
|
EditText addressEditText = view.findViewById(R.id.address_edittext);
|
||||||
|
EditText portEditText = view.findViewById(R.id.node_port_edittext);
|
||||||
EditText nodeNameEditText = view.findViewById(R.id.node_name_edittext);
|
EditText nodeNameEditText = view.findViewById(R.id.node_name_edittext);
|
||||||
EditText usernameEditText = view.findViewById(R.id.username_edittext);
|
EditText usernameEditText = view.findViewById(R.id.username_edittext);
|
||||||
EditText passwordEditText = view.findViewById(R.id.password_edittext);
|
EditText passwordEditText = view.findViewById(R.id.password_edittext);
|
||||||
@ -67,14 +68,15 @@ public class AddNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
|||||||
addPasteListener(view, passwordEditText, R.id.paste_password_imagebutton);
|
addPasteListener(view, passwordEditText, R.id.paste_password_imagebutton);
|
||||||
|
|
||||||
addNodeButton.setOnClickListener(view1 -> {
|
addNodeButton.setOnClickListener(view1 -> {
|
||||||
String node = addressEditText.getText().toString();
|
String nodeAddr = addressEditText.getText().toString();
|
||||||
|
String portString = portEditText.getText().toString();
|
||||||
String name = nodeNameEditText.getText().toString();
|
String name = nodeNameEditText.getText().toString();
|
||||||
String user = usernameEditText.getText().toString();
|
String user = usernameEditText.getText().toString();
|
||||||
String pass = passwordEditText.getText().toString();
|
String pass = passwordEditText.getText().toString();
|
||||||
if(name.isEmpty()) {
|
if(name.isEmpty()) {
|
||||||
Toast.makeText(getContext(), "Enter node name", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Enter node name", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
} else if(node.isEmpty()) {
|
} else if(nodeAddr.isEmpty() || portString.isEmpty()) {
|
||||||
Toast.makeText(getContext(), "Enter node address", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Enter node address", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
} else if(!user.isEmpty() && pass.isEmpty()) {
|
} else if(!user.isEmpty() && pass.isEmpty()) {
|
||||||
@ -88,10 +90,9 @@ public class AddNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
|||||||
jsonObject.put("username", user);
|
jsonObject.put("username", user);
|
||||||
jsonObject.put("password", pass);
|
jsonObject.put("password", pass);
|
||||||
}
|
}
|
||||||
String[] nodeParts = node.split(":");
|
|
||||||
|
|
||||||
jsonObject.put("host", nodeParts[0]);
|
jsonObject.put("host", nodeAddr);
|
||||||
jsonObject.put("rpcPort", nodeParts[1]);
|
jsonObject.put("rpcPort", Integer.parseInt(portString));
|
||||||
jsonObject.put("network", "mainnet");
|
jsonObject.put("network", "mainnet");
|
||||||
jsonObject.put("name", name);
|
jsonObject.put("name", name);
|
||||||
|
|
||||||
|
@ -48,13 +48,16 @@ public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
|||||||
Button deleteNodeButton = view.findViewById(R.id.delete_node_button);
|
Button deleteNodeButton = view.findViewById(R.id.delete_node_button);
|
||||||
Button doneEditingButton = view.findViewById(R.id.done_editing_button);
|
Button doneEditingButton = view.findViewById(R.id.done_editing_button);
|
||||||
EditText addressEditText = view.findViewById(R.id.address_edittext);
|
EditText addressEditText = view.findViewById(R.id.address_edittext);
|
||||||
|
EditText portEditText = view.findViewById(R.id.node_port_edittext);
|
||||||
EditText nodeNameEditText = view.findViewById(R.id.node_name_edittext);
|
EditText nodeNameEditText = view.findViewById(R.id.node_name_edittext);
|
||||||
EditText usernameEditText = view.findViewById(R.id.username_edittext);
|
EditText usernameEditText = view.findViewById(R.id.username_edittext);
|
||||||
EditText passwordEditText = view.findViewById(R.id.password_edittext);
|
EditText passwordEditText = view.findViewById(R.id.password_edittext);
|
||||||
ImageButton pastePasswordImageButton = view.findViewById(R.id.paste_password_imagebutton);
|
ImageButton pastePasswordImageButton = view.findViewById(R.id.paste_password_imagebutton);
|
||||||
|
|
||||||
Node node = Node.fromJson(nodeJson);
|
Node node = Node.fromJson(nodeJson);
|
||||||
addressEditText.setText(node.getAddress());
|
if(node == null) return;
|
||||||
|
addressEditText.setText(node.getHost());
|
||||||
|
portEditText.setText(node.getRpcPort());
|
||||||
nodeNameEditText.setText(node.getName());
|
nodeNameEditText.setText(node.getName());
|
||||||
usernameEditText.setText(node.getUsername());
|
usernameEditText.setText(node.getUsername());
|
||||||
if(!node.getPassword().isEmpty()) {
|
if(!node.getPassword().isEmpty()) {
|
||||||
|
@ -120,7 +120,7 @@ public class HomeFragment extends Fragment implements TransactionInfoAdapter.TxI
|
|||||||
if (height > 1 && daemonHeight > 1) {
|
if (height > 1 && daemonHeight > 1) {
|
||||||
progressBar.setProgress(x);
|
progressBar.setProgress(x);
|
||||||
progressBarText.setVisibility(View.VISIBLE);
|
progressBarText.setVisibility(View.VISIBLE);
|
||||||
progressBarText.setText("Syncing... " + height + " / " + daemonHeight);
|
progressBarText.setText("Syncing... " + n + " blocks remaining");
|
||||||
} else {
|
} else {
|
||||||
progressBarText.setVisibility(View.GONE);
|
progressBarText.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
@ -434,21 +434,23 @@ public class SendFragment extends Fragment {
|
|||||||
mViewModel.setPendingTransaction(pendingTx);
|
mViewModel.setPendingTransaction(pendingTx);
|
||||||
} else {
|
} else {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if (activity != null) {
|
if (activity != null && pendingTx != null) {
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
createButton.setEnabled(true);
|
createButton.setEnabled(true);
|
||||||
sendMaxButton.setEnabled(true);
|
sendMaxButton.setEnabled(true);
|
||||||
Toast.makeText(getActivity(), getString(R.string.error_creating_tx), Toast.LENGTH_SHORT).show();
|
if(pendingTx.getErrorString() != null)
|
||||||
|
Toast.makeText(activity, getString(R.string.error_creating_tx, pendingTx.getErrorString()), Toast.LENGTH_SHORT).show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
createButton.setEnabled(true);
|
createButton.setEnabled(true);
|
||||||
sendMaxButton.setEnabled(true);
|
sendMaxButton.setEnabled(true);
|
||||||
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, getString(R.string.error_creating_tx, e.getMessage()), Toast.LENGTH_SHORT).show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,18 +19,22 @@ import androidx.lifecycle.ViewModelProvider;
|
|||||||
import net.mynero.wallet.R;
|
import net.mynero.wallet.R;
|
||||||
import net.mynero.wallet.model.TransactionInfo;
|
import net.mynero.wallet.model.TransactionInfo;
|
||||||
import net.mynero.wallet.model.Wallet;
|
import net.mynero.wallet.model.Wallet;
|
||||||
|
import net.mynero.wallet.model.WalletManager;
|
||||||
|
import net.mynero.wallet.service.HistoryService;
|
||||||
import net.mynero.wallet.service.PrefService;
|
import net.mynero.wallet.service.PrefService;
|
||||||
import net.mynero.wallet.util.Constants;
|
import net.mynero.wallet.util.Constants;
|
||||||
import net.mynero.wallet.util.Helper;
|
import net.mynero.wallet.util.Helper;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
public class TransactionFragment extends Fragment {
|
public class TransactionFragment extends Fragment {
|
||||||
|
|
||||||
private TransactionViewModel mViewModel;
|
private TransactionViewModel mViewModel;
|
||||||
|
private TransactionInfo transactionInfo = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
@ -48,8 +52,7 @@ public class TransactionFragment extends Fragment {
|
|||||||
mViewModel = new ViewModelProvider(this).get(TransactionViewModel.class);
|
mViewModel = new ViewModelProvider(this).get(TransactionViewModel.class);
|
||||||
Bundle args = getArguments();
|
Bundle args = getArguments();
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
TransactionInfo txInfo = getArguments().getParcelable(Constants.NAV_ARG_TXINFO);
|
this.transactionInfo = getArguments().getParcelable(Constants.NAV_ARG_TXINFO);
|
||||||
mViewModel.init(txInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bindObservers(view);
|
bindObservers(view);
|
||||||
@ -59,25 +62,26 @@ public class TransactionFragment extends Fragment {
|
|||||||
private void bindListeners(View view) {
|
private void bindListeners(View view) {
|
||||||
ImageButton copyTxHashImageButton = view.findViewById(R.id.copy_txhash_imagebutton);
|
ImageButton copyTxHashImageButton = view.findViewById(R.id.copy_txhash_imagebutton);
|
||||||
copyTxHashImageButton.setOnClickListener(view1 -> {
|
copyTxHashImageButton.setOnClickListener(view1 -> {
|
||||||
TransactionInfo txInfo = mViewModel.transaction.getValue();
|
TransactionInfo txInfo = this.transactionInfo;
|
||||||
if (txInfo != null) {
|
if (txInfo != null) {
|
||||||
Helper.clipBoardCopy(getContext(), "transaction_hash", txInfo.hash);
|
Helper.clipBoardCopy(getContext(), "transaction_hash", txInfo.hash);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ImageButton copyTxAddressImageButton = view.findViewById(R.id.copy_txaddress_imagebutton);
|
ImageButton copyTxAddressImageButton = view.findViewById(R.id.copy_txaddress_imagebutton);
|
||||||
|
TextView addressTextView = view.findViewById(R.id.transaction_address_textview);
|
||||||
copyTxAddressImageButton.setOnClickListener(view1 -> {
|
copyTxAddressImageButton.setOnClickListener(view1 -> {
|
||||||
TransactionInfo txInfo = mViewModel.transaction.getValue();
|
TransactionInfo txInfo = this.transactionInfo;
|
||||||
if (txInfo != null) {
|
if (txInfo != null) {
|
||||||
String destination = mViewModel.destination.getValue();
|
String destination = addressTextView.getText().toString();
|
||||||
if (destination != null) {
|
|
||||||
Helper.clipBoardCopy(getContext(), "transaction_address", destination);
|
Helper.clipBoardCopy(getContext(), "transaction_address", destination);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindObservers(View view) {
|
private void bindObservers(View view) {
|
||||||
|
TextView txActionTextView = view.findViewById(R.id.transaction_action_textview);
|
||||||
|
TextView confLabel2 = view.findViewById(R.id.transaction_conf_label2_textview);
|
||||||
TextView txHashTextView = view.findViewById(R.id.transaction_hash_textview);
|
TextView txHashTextView = view.findViewById(R.id.transaction_hash_textview);
|
||||||
TextView txConfTextView = view.findViewById(R.id.transaction_conf_textview);
|
TextView txConfTextView = view.findViewById(R.id.transaction_conf_textview);
|
||||||
TextView txAddressTextView = view.findViewById(R.id.transaction_address_textview);
|
TextView txAddressTextView = view.findViewById(R.id.transaction_address_textview);
|
||||||
@ -85,43 +89,73 @@ public class TransactionFragment extends Fragment {
|
|||||||
TextView txDateTextView = view.findViewById(R.id.transaction_date_textview);
|
TextView txDateTextView = view.findViewById(R.id.transaction_date_textview);
|
||||||
TextView txAmountTextView = view.findViewById(R.id.transaction_amount_textview);
|
TextView txAmountTextView = view.findViewById(R.id.transaction_amount_textview);
|
||||||
TextView blockHeightTextView = view.findViewById(R.id.tx_block_height_textview);
|
TextView blockHeightTextView = view.findViewById(R.id.tx_block_height_textview);
|
||||||
TextView blockHeightLabelTextView = view.findViewById(R.id.transaction_block_height_label_textview);
|
|
||||||
|
|
||||||
mViewModel.transaction.observe(getViewLifecycleOwner(), transactionInfo -> {
|
HistoryService.getInstance().history.observe(getViewLifecycleOwner(), transactionInfos -> {
|
||||||
txHashTextView.setText(transactionInfo.hash);
|
TransactionInfo newTransactionInfo = findNewestVersionOfTransaction(this.transactionInfo, transactionInfos);
|
||||||
txConfTextView.setText("" + transactionInfo.confirmations);
|
if(newTransactionInfo == null) return;
|
||||||
txDateTextView.setText(getDateTime(transactionInfo.timestamp));
|
|
||||||
if(transactionInfo.confirmations > 0) {
|
txHashTextView.setText(newTransactionInfo.hash);
|
||||||
blockHeightTextView.setText("" + transactionInfo.blockheight);
|
txConfTextView.setText("" + newTransactionInfo.confirmations);
|
||||||
|
txDateTextView.setText(getDateTime(newTransactionInfo.timestamp));
|
||||||
|
if(newTransactionInfo.confirmations > 1) {
|
||||||
|
confLabel2.setText(getString(R.string.transaction_conf_desc2_confirmed));
|
||||||
|
blockHeightTextView.setText("" + newTransactionInfo.blockheight);
|
||||||
|
blockHeightTextView.setVisibility(View.VISIBLE);
|
||||||
|
} else if(newTransactionInfo.confirmations == 1) {
|
||||||
|
confLabel2.setText(getString(R.string.transaction_conf_1_desc2_confirmed));
|
||||||
|
blockHeightTextView.setText("" + newTransactionInfo.blockheight);
|
||||||
blockHeightTextView.setVisibility(View.VISIBLE);
|
blockHeightTextView.setVisibility(View.VISIBLE);
|
||||||
blockHeightLabelTextView.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
} else {
|
||||||
blockHeightTextView.setVisibility(View.GONE);
|
blockHeightTextView.setVisibility(View.GONE);
|
||||||
blockHeightLabelTextView.setVisibility(View.GONE);
|
confLabel2.setText(getString(R.string.transaction_conf_desc2_unconfirmed));
|
||||||
}
|
}
|
||||||
|
|
||||||
Context ctx = getContext();
|
Context ctx = getContext();
|
||||||
if(ctx != null) {
|
if(ctx != null) {
|
||||||
boolean streetModeEnabled = PrefService.getInstance().getBoolean(Constants.PREF_STREET_MODE, false);
|
boolean streetModeEnabled = PrefService.getInstance().getBoolean(Constants.PREF_STREET_MODE, false);
|
||||||
String balanceString = streetModeEnabled ? Constants.STREET_MODE_BALANCE : Wallet.getDisplayAmount(transactionInfo.amount);
|
String balanceString = streetModeEnabled ? Constants.STREET_MODE_BALANCE : Helper.getDisplayAmount(newTransactionInfo.amount, 12);
|
||||||
if (transactionInfo.direction == TransactionInfo.Direction.Direction_In) {
|
if (newTransactionInfo.direction == TransactionInfo.Direction.Direction_In) {
|
||||||
|
txActionTextView.setText(getString(R.string.transaction_action_recv));
|
||||||
txAmountTextView.setTextColor(ContextCompat.getColor(ctx, R.color.oled_positiveColor));
|
txAmountTextView.setTextColor(ContextCompat.getColor(ctx, R.color.oled_positiveColor));
|
||||||
txAmountTextView.setText(getString(R.string.tx_list_amount_positive, balanceString));
|
|
||||||
} else {
|
} else {
|
||||||
|
txActionTextView.setText(getString(R.string.transaction_action_sent));
|
||||||
txAmountTextView.setTextColor(ContextCompat.getColor(ctx, R.color.oled_negativeColor));
|
txAmountTextView.setTextColor(ContextCompat.getColor(ctx, R.color.oled_negativeColor));
|
||||||
txAmountTextView.setText(getString(R.string.tx_list_amount_negative, balanceString));
|
|
||||||
}
|
}
|
||||||
|
txAmountTextView.setText(balanceString);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
mViewModel.destination.observe(getViewLifecycleOwner(), s -> {
|
String destination = "-";
|
||||||
txAddressTextView.setText(Objects.requireNonNullElse(s, "-"));
|
Wallet wallet = WalletManager.getInstance().getWallet();
|
||||||
if (s == null) {
|
if (newTransactionInfo.txKey == null) {
|
||||||
|
newTransactionInfo.txKey = wallet.getTxKey(newTransactionInfo.hash);
|
||||||
|
}
|
||||||
|
if (newTransactionInfo.address == null && newTransactionInfo.direction == TransactionInfo.Direction.Direction_In) {
|
||||||
|
destination = wallet.getSubaddress(newTransactionInfo.accountIndex, newTransactionInfo.addressIndex);
|
||||||
|
} else if (newTransactionInfo.address != null && newTransactionInfo.direction == TransactionInfo.Direction.Direction_In) {
|
||||||
|
destination = newTransactionInfo.address;
|
||||||
|
} else if (newTransactionInfo.transfers != null && newTransactionInfo.direction == TransactionInfo.Direction.Direction_Out) {
|
||||||
|
if (newTransactionInfo.transfers.size() == 1) {
|
||||||
|
destination = newTransactionInfo.transfers.get(0).address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
txAddressTextView.setText(Objects.requireNonNullElse(destination, "-"));
|
||||||
|
if (destination == null) {
|
||||||
copyTxAddressImageButton.setVisibility(View.INVISIBLE);
|
copyTxAddressImageButton.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TransactionInfo findNewestVersionOfTransaction(TransactionInfo oldTransactionInfo, List<TransactionInfo> transactionInfoList) {
|
||||||
|
for(TransactionInfo transactionInfo : transactionInfoList) {
|
||||||
|
if(transactionInfo.hash.equals(oldTransactionInfo.hash)) {
|
||||||
|
this.transactionInfo = transactionInfo;
|
||||||
|
return this.transactionInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private String getDateTime(long time) {
|
private String getDateTime(long time) {
|
||||||
return DATETIME_FORMATTER.format(new Date(time * 1000));
|
return DATETIME_FORMATTER.format(new Date(time * 1000));
|
||||||
}
|
}
|
||||||
|
@ -9,25 +9,4 @@ import net.mynero.wallet.model.Wallet;
|
|||||||
import net.mynero.wallet.model.WalletManager;
|
import net.mynero.wallet.model.WalletManager;
|
||||||
|
|
||||||
public class TransactionViewModel extends ViewModel {
|
public class TransactionViewModel extends ViewModel {
|
||||||
private final MutableLiveData<TransactionInfo> _transaction = new MutableLiveData<>(null);
|
|
||||||
private final MutableLiveData<String> _destination = new MutableLiveData<>(null);
|
|
||||||
public LiveData<TransactionInfo> transaction = _transaction;
|
|
||||||
public LiveData<String> destination = _destination;
|
|
||||||
|
|
||||||
public void init(TransactionInfo info) {
|
|
||||||
Wallet wallet = WalletManager.getInstance().getWallet();
|
|
||||||
if (info.txKey == null) {
|
|
||||||
info.txKey = wallet.getTxKey(info.hash);
|
|
||||||
}
|
|
||||||
if (info.address == null && info.direction == TransactionInfo.Direction.Direction_In) {
|
|
||||||
_destination.setValue(wallet.getSubaddress(info.accountIndex, info.addressIndex));
|
|
||||||
} else if (info.address != null && info.direction == TransactionInfo.Direction.Direction_In) {
|
|
||||||
_destination.setValue(info.address);
|
|
||||||
} else if (info.transfers != null && info.direction == TransactionInfo.Direction.Direction_Out) {
|
|
||||||
if (info.transfers.size() == 1) {
|
|
||||||
_destination.setValue(info.transfers.get(0).address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._transaction.setValue(info);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ import net.mynero.wallet.model.WalletManager;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HistoryService extends ServiceBase {
|
public class HistoryService extends ServiceBase {
|
||||||
public static HistoryService instance = null;
|
private static HistoryService instance = null;
|
||||||
private final MutableLiveData<List<TransactionInfo>> _history = new MutableLiveData<>();
|
private final MutableLiveData<List<TransactionInfo>> _history = new MutableLiveData<>();
|
||||||
public LiveData<List<TransactionInfo>> history = _history;
|
public LiveData<List<TransactionInfo>> history = _history;
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ public class HistoryService extends ServiceBase {
|
|||||||
_history.postValue(getHistory());
|
_history.postValue(getHistory());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TransactionInfo> getHistory() {
|
private List<TransactionInfo> getHistory() {
|
||||||
return WalletManager.getInstance().getWallet().getHistory().getAll();
|
return WalletManager.getInstance().getWallet().getHistory().getAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
|
|
||||||
package net.mynero.wallet.service;
|
package net.mynero.wallet.service;
|
||||||
|
|
||||||
import net.mynero.wallet.data.DefaultNodes;
|
|
||||||
import net.mynero.wallet.data.Node;
|
import net.mynero.wallet.data.Node;
|
||||||
import net.mynero.wallet.data.TxData;
|
|
||||||
import net.mynero.wallet.model.CoinsInfo;
|
import net.mynero.wallet.model.CoinsInfo;
|
||||||
import net.mynero.wallet.model.PendingTransaction;
|
import net.mynero.wallet.model.PendingTransaction;
|
||||||
import net.mynero.wallet.model.TransactionOutput;
|
import net.mynero.wallet.model.TransactionOutput;
|
||||||
@ -57,7 +55,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
|||||||
@Override
|
@Override
|
||||||
public synchronized void start() {
|
public synchronized void start() {
|
||||||
super.start();
|
super.start();
|
||||||
this.listener.onRefresh();
|
this.listener.onRefresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -120,12 +118,12 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
|||||||
BlockchainService.getInstance().setConnectionStatus(status);
|
BlockchainService.getInstance().setConnectionStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refresh(boolean refreshCoins) {
|
private void refresh(boolean walletSynced) {
|
||||||
wallet.refreshHistory();
|
wallet.refreshHistory();
|
||||||
if(refreshCoins) {
|
if(walletSynced) {
|
||||||
wallet.refreshCoins();
|
wallet.refreshCoins();
|
||||||
}
|
}
|
||||||
listener.onRefresh();
|
listener.onRefresh(walletSynced);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PendingTransaction createTx(String address, String amountStr, boolean sendAll, PendingTransaction.Priority feePriority, ArrayList<String> selectedUtxos) throws Exception {
|
public PendingTransaction createTx(String address, String amountStr, boolean sendAll, PendingTransaction.Priority feePriority, ArrayList<String> selectedUtxos) throws Exception {
|
||||||
@ -146,7 +144,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
|||||||
ArrayList<String> preferredInputs;
|
ArrayList<String> preferredInputs;
|
||||||
if (selectedUtxos.isEmpty()) {
|
if (selectedUtxos.isEmpty()) {
|
||||||
// no inputs manually selected, we are sending from home screen most likely, or user somehow broke the app
|
// no inputs manually selected, we are sending from home screen most likely, or user somehow broke the app
|
||||||
preferredInputs = UTXOService.getInstance().selectUtxos(totalAmount, sendAll);
|
preferredInputs = UTXOService.getInstance().selectUtxos(totalAmount, sendAll, feePriority);
|
||||||
} else {
|
} else {
|
||||||
preferredInputs = selectedUtxos;
|
preferredInputs = selectedUtxos;
|
||||||
checkSelectedAmounts(preferredInputs, totalAmount, sendAll);
|
checkSelectedAmounts(preferredInputs, totalAmount, sendAll);
|
||||||
@ -233,7 +231,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void onRefresh();
|
void onRefresh(boolean walletSynced);
|
||||||
void onConnectionFail();
|
void onConnectionFail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import android.util.Pair;
|
|||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import net.mynero.wallet.model.Coins;
|
|
||||||
import net.mynero.wallet.model.CoinsInfo;
|
import net.mynero.wallet.model.CoinsInfo;
|
||||||
import net.mynero.wallet.model.PendingTransaction;
|
import net.mynero.wallet.model.PendingTransaction;
|
||||||
import net.mynero.wallet.model.Wallet;
|
import net.mynero.wallet.model.Wallet;
|
||||||
@ -22,6 +21,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public class UTXOService extends ServiceBase {
|
public class UTXOService extends ServiceBase {
|
||||||
public static UTXOService instance = null;
|
public static UTXOService instance = null;
|
||||||
|
private List<CoinsInfo> internalCachedUtxos = new ArrayList<>();
|
||||||
private final MutableLiveData<List<CoinsInfo>> _utxos = new MutableLiveData<>();
|
private final MutableLiveData<List<CoinsInfo>> _utxos = new MutableLiveData<>();
|
||||||
public LiveData<List<CoinsInfo>> utxos = _utxos;
|
public LiveData<List<CoinsInfo>> utxos = _utxos;
|
||||||
private ArrayList<String> frozenCoins = new ArrayList<>();
|
private ArrayList<String> frozenCoins = new ArrayList<>();
|
||||||
@ -41,12 +41,13 @@ public class UTXOService extends ServiceBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void refreshUtxos() {
|
public void refreshUtxos() {
|
||||||
_utxos.postValue(getUtxosInternal());
|
List<CoinsInfo> coinsInfos = getUtxosInternal();
|
||||||
|
_utxos.postValue(coinsInfos);
|
||||||
|
internalCachedUtxos = coinsInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CoinsInfo> getUtxos() {
|
public List<CoinsInfo> getUtxos() {
|
||||||
List<CoinsInfo> value = utxos.getValue();
|
return Collections.unmodifiableList(internalCachedUtxos);
|
||||||
return value != null ? value : List.of();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<CoinsInfo> getUtxosInternal() {
|
private List<CoinsInfo> getUtxosInternal() {
|
||||||
@ -93,12 +94,12 @@ public class UTXOService extends ServiceBase {
|
|||||||
prefService.edit().putString(Constants.PREF_FROZEN_COINS, jsonArray.toString()).apply();
|
prefService.edit().putString(Constants.PREF_FROZEN_COINS, jsonArray.toString()).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> selectUtxos(long amount, boolean sendAll) throws Exception {
|
public ArrayList<String> selectUtxos(long amount, boolean sendAll, PendingTransaction.Priority feePriority) throws Exception {
|
||||||
final long basicFeeEstimate = calculateBasicFee(amount);
|
final long basicFeeEstimate = calculateBasicFee(amount, feePriority);
|
||||||
final long amountWithBasicFee = amount + basicFeeEstimate;
|
final long amountWithBasicFee = amount + basicFeeEstimate;
|
||||||
ArrayList<String> selectedUtxos = new ArrayList<>();
|
ArrayList<String> selectedUtxos = new ArrayList<>();
|
||||||
ArrayList<String> seenTxs = new ArrayList<>();
|
ArrayList<String> seenTxs = new ArrayList<>();
|
||||||
List<CoinsInfo> utxos = getUtxos();
|
List<CoinsInfo> utxos = new ArrayList<>(getUtxos());
|
||||||
long amountSelected = 0;
|
long amountSelected = 0;
|
||||||
Collections.sort(utxos);
|
Collections.sort(utxos);
|
||||||
//loop through each utxo
|
//loop through each utxo
|
||||||
@ -127,11 +128,10 @@ public class UTXOService extends ServiceBase {
|
|||||||
return selectedUtxos;
|
return selectedUtxos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long calculateBasicFee(long amount) {
|
private long calculateBasicFee(long amount, PendingTransaction.Priority feePriority) {
|
||||||
ArrayList<Pair<String, Long>> destinations = new ArrayList<>();
|
ArrayList<Pair<String, Long>> destinations = new ArrayList<>();
|
||||||
destinations.add(new Pair<>("87MRtZPrWUCVUgcFHdsVb5MoZUcLtqfD3FvQVGwftFb8eSdMnE39JhAJcbuSW8X2vRaRsB9RQfuCpFciybJFHaz3QYPhCLw", amount));
|
destinations.add(new Pair<>("87MRtZPrWUCVUgcFHdsVb5MoZUcLtqfD3FvQVGwftFb8eSdMnE39JhAJcbuSW8X2vRaRsB9RQfuCpFciybJFHaz3QYPhCLw", amount));
|
||||||
// destination string doesn't actually matter here, so i'm using the donation address. amount also technically doesn't matter
|
// destination string doesn't actually matter here, so i'm using the donation address. amount also technically doesn't matter
|
||||||
// priority also isn't accounted for in the Monero C++ code. maybe this is a bug by the core Monero team, or i'm using an outdated method.
|
return WalletManager.getInstance().getWallet().estimateTransactionFee(destinations, feePriority);
|
||||||
return WalletManager.getInstance().getWallet().estimateTransactionFee(destinations, PendingTransaction.Priority.Priority_Low);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,15 +45,13 @@
|
|||||||
android:id="@+id/paste_address_imagebutton"
|
android:id="@+id/paste_address_imagebutton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:minWidth="48dp"
|
android:minWidth="48dp"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
android:src="@drawable/ic_content_paste_24dp"
|
android:src="@drawable/ic_content_paste_24dp"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/address_edittext"
|
app:layout_constraintBottom_toBottomOf="@id/address_edittext"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/address_edittext"
|
app:layout_constraintStart_toEndOf="@id/node_port_edittext"
|
||||||
app:layout_constraintTop_toTopOf="@id/address_edittext"
|
app:layout_constraintTop_toTopOf="@id/address_edittext"
|
||||||
tools:ignore="SpeakableTextPresentCheck" />
|
tools:ignore="SpeakableTextPresentCheck" />
|
||||||
|
|
||||||
@ -61,16 +59,30 @@
|
|||||||
android:id="@+id/address_edittext"
|
android:id="@+id/address_edittext"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:background="@drawable/edittext_bg"
|
android:background="@drawable/edittext_bg"
|
||||||
android:hint="@string/node_address_hint"
|
android:hint="@string/node_address_hint"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:digits="-QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890.:"
|
android:digits="-QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890.:"
|
||||||
app:layout_constraintBottom_toTopOf="@id/username_edittext"
|
app:layout_constraintBottom_toTopOf="@id/username_edittext"
|
||||||
app:layout_constraintEnd_toStartOf="@id/paste_address_imagebutton"
|
app:layout_constraintEnd_toStartOf="@id/node_port_edittext"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/node_port_edittext"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="@drawable/edittext_bg"
|
||||||
|
android:hint="@string/node_port_hint"
|
||||||
|
android:inputType="number"
|
||||||
|
android:digits="-QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890.:"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/address_edittext"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/address_edittext"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/paste_address_imagebutton"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/address_edittext" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/add_node_button"
|
android:id="@+id/add_node_button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -85,7 +97,6 @@
|
|||||||
android:id="@+id/username_edittext"
|
android:id="@+id/username_edittext"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:background="@drawable/edittext_bg"
|
android:background="@drawable/edittext_bg"
|
||||||
android:hint="@string/node_username_hint"
|
android:hint="@string/node_username_hint"
|
||||||
@ -98,8 +109,6 @@
|
|||||||
android:id="@+id/paste_username_imagebutton"
|
android:id="@+id/paste_username_imagebutton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:minWidth="48dp"
|
android:minWidth="48dp"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
|
@ -45,15 +45,13 @@
|
|||||||
android:id="@+id/paste_address_imagebutton"
|
android:id="@+id/paste_address_imagebutton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:minWidth="48dp"
|
android:minWidth="48dp"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
android:src="@drawable/ic_content_paste_24dp"
|
android:src="@drawable/ic_content_paste_24dp"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/address_edittext"
|
app:layout_constraintBottom_toBottomOf="@id/address_edittext"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/address_edittext"
|
app:layout_constraintStart_toEndOf="@id/node_port_edittext"
|
||||||
app:layout_constraintTop_toTopOf="@id/address_edittext"
|
app:layout_constraintTop_toTopOf="@id/address_edittext"
|
||||||
tools:ignore="SpeakableTextPresentCheck" />
|
tools:ignore="SpeakableTextPresentCheck" />
|
||||||
|
|
||||||
@ -61,20 +59,34 @@
|
|||||||
android:id="@+id/address_edittext"
|
android:id="@+id/address_edittext"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:background="@drawable/edittext_bg"
|
android:background="@drawable/edittext_bg"
|
||||||
android:hint="@string/node_address_hint"
|
android:hint="@string/node_address_hint"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:digits="-QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890.:"
|
android:digits="-QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890.:"
|
||||||
app:layout_constraintBottom_toTopOf="@id/username_edittext"
|
app:layout_constraintBottom_toTopOf="@id/username_edittext"
|
||||||
app:layout_constraintEnd_toStartOf="@id/paste_address_imagebutton"
|
app:layout_constraintEnd_toStartOf="@id/node_port_edittext"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/node_port_edittext"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="@drawable/edittext_bg"
|
||||||
|
android:hint="@string/node_port_hint"
|
||||||
|
android:inputType="number"
|
||||||
|
android:digits="-QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890.:"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/address_edittext"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/address_edittext"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/paste_address_imagebutton"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/address_edittext" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/username_edittext"
|
android:id="@+id/username_edittext"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:background="@drawable/edittext_bg"
|
android:background="@drawable/edittext_bg"
|
||||||
android:hint="@string/node_username_hint"
|
android:hint="@string/node_username_hint"
|
||||||
@ -87,8 +99,6 @@
|
|||||||
android:id="@+id/paste_username_imagebutton"
|
android:id="@+id/paste_username_imagebutton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:minWidth="48dp"
|
android:minWidth="48dp"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
@ -136,7 +146,7 @@
|
|||||||
android:id="@+id/delete_node_button"
|
android:id="@+id/delete_node_button"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="32dp"
|
||||||
android:layout_marginEnd="1dp"
|
android:layout_marginEnd="1dp"
|
||||||
android:background="@drawable/button_bg_left"
|
android:background="@drawable/button_bg_left"
|
||||||
android:text="@string/delete"
|
android:text="@string/delete"
|
||||||
@ -147,7 +157,7 @@
|
|||||||
android:id="@+id/done_editing_button"
|
android:id="@+id/done_editing_button"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="32dp"
|
||||||
android:layout_marginStart="1dp"
|
android:layout_marginStart="1dp"
|
||||||
android:background="@drawable/button_bg_right"
|
android:background="@drawable/button_bg_right"
|
||||||
android:text="@string/done"
|
android:text="@string/done"
|
||||||
|
@ -8,143 +8,54 @@
|
|||||||
tools:context="net.mynero.wallet.fragment.settings.SettingsFragment">
|
tools:context="net.mynero.wallet.fragment.settings.SettingsFragment">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/transaction_title_textview"
|
android:id="@+id/transaction_action_textview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="32dp"
|
android:layout_marginBottom="32dp"
|
||||||
android:text="@string/transaction"
|
android:text="@string/transaction_action_recv"
|
||||||
android:textSize="32sp"
|
android:textSize="42sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@id/transaction_hash_label_textview"
|
android:textColor="@color/oled_addressListColor"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/transaction_amount_textview"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/transaction_hash_label_textview"
|
android:id="@+id/transaction_amount_textview"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/transaction_hash"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/transaction_title_textview"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/transaction_hash_textview"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/transaction_hash"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="middle"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/copy_txhash_imagebutton"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/copy_txhash_imagebutton"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/copy_txhash_imagebutton"/>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/copy_txhash_imagebutton"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@android:color/transparent"
|
android:text="@string/tx_amount_no_prefix2"
|
||||||
android:minWidth="48dp"
|
android:textSize="24sp"
|
||||||
android:minHeight="48dp"
|
|
||||||
android:src="@drawable/ic_content_copy_24dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/transaction_hash_textview"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/transaction_hash_label_textview" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/transaction_conf_label_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/confirmations"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/copy_txhash_imagebutton"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/transaction_conf_textview"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="0"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="middle"
|
android:ellipsize="middle"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintTop_toBottomOf="@id/transaction_action_textview"/>
|
||||||
app:layout_constraintTop_toBottomOf="@id/transaction_conf_label_textview"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/transaction_block_height_label_textview"
|
android:id="@+id/transaction_amount_units_textview"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/block_height"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/transaction_conf_textview"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tx_block_height_textview"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="0"
|
android:text="XMR"
|
||||||
android:textSize="14sp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginTop="8dp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="middle"
|
android:ellipsize="middle"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toEndOf="@id/transaction_amount_textview"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/transaction_block_height_label_textview"/>
|
app:layout_constraintTop_toBottomOf="@id/transaction_action_textview"/>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/transaction_amount_label_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/amount_label"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/tx_block_height_textview"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/transaction_amount_textview"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/tx_amount_no_prefix"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="middle"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/transaction_amount_label_textview"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/transaction_address_label_textview"
|
android:id="@+id/transaction_address_label_textview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/transaction_destination"
|
android:text="@string/transaction_destination_desc"
|
||||||
android:textSize="18sp"
|
android:textSize="28sp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/oled_addressListColor"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/transaction_amount_textview"/>
|
app:layout_constraintTop_toBottomOf="@id/transaction_amount_textview"/>
|
||||||
@ -153,9 +64,8 @@
|
|||||||
android:id="@+id/transaction_address_textview"
|
android:id="@+id/transaction_address_textview"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/transaction_hash"
|
android:text="@string/transaction_destination"
|
||||||
android:textSize="14sp"
|
android:textSize="24sp"
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="middle"
|
android:ellipsize="middle"
|
||||||
@ -177,24 +87,63 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/transaction_address_label_textview" />
|
app:layout_constraintTop_toBottomOf="@id/transaction_address_label_textview" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/transaction_date_label_textview"
|
android:id="@+id/transaction_hash_label_textview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/date"
|
android:text="@string/transaction_hash_desc"
|
||||||
android:textSize="18sp"
|
android:textSize="28sp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="8dp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/oled_addressListColor"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/copy_txaddress_imagebutton"/>
|
app:layout_constraintTop_toBottomOf="@id/copy_txaddress_imagebutton"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/transaction_hash_textview"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/transaction_hash"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/copy_txhash_imagebutton"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/copy_txhash_imagebutton"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/copy_txhash_imagebutton"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/copy_txhash_imagebutton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:minWidth="48dp"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:src="@drawable/ic_content_copy_24dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/transaction_hash_textview"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/transaction_hash_label_textview" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/transaction_date_label_textview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/transaction_on_date_label"
|
||||||
|
android:textSize="28sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/oled_addressListColor"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/copy_txhash_imagebutton"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/transaction_date_textview"
|
android:id="@+id/transaction_date_textview"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="0"
|
android:text="0"
|
||||||
android:textSize="14sp"
|
android:textSize="24sp"
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="middle"
|
android:ellipsize="middle"
|
||||||
@ -202,4 +151,55 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/transaction_date_label_textview"/>
|
app:layout_constraintTop_toBottomOf="@id/transaction_date_label_textview"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/transaction_conf_label_textview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/transaction_conf_desc"
|
||||||
|
android:textSize="28sp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/oled_addressListColor"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/transaction_date_textview"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/transaction_conf_textview"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="0"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/transaction_conf_label_textview"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/transaction_conf_label2_textview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/transaction_conf_desc2_confirmed"
|
||||||
|
android:textSize="28sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/oled_addressListColor"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/transaction_conf_textview"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tx_block_height_textview"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="0"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/transaction_conf_label2_textview"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -73,13 +73,16 @@
|
|||||||
<string name="add_node">Add Node</string>
|
<string name="add_node">Add Node</string>
|
||||||
<string name="nodes">Nodes</string>
|
<string name="nodes">Nodes</string>
|
||||||
<string name="node_name_hint">My Monero Node</string>
|
<string name="node_name_hint">My Monero Node</string>
|
||||||
<string name="node_address_hint">127.0.0.1:18081</string>
|
<string name="node_address_hint">127.0.0.1</string>
|
||||||
|
<string name="node_port_hint">18081</string>
|
||||||
<string name="node_username_hint">Username (optional)</string>
|
<string name="node_username_hint">Username (optional)</string>
|
||||||
<string name="node_password_hint">Password</string>
|
<string name="node_password_hint">Password</string>
|
||||||
<string name="transaction">Transaction</string>
|
<string name="transaction">Transaction</string>
|
||||||
|
<string name="transaction_action_sent">You sent</string>
|
||||||
|
<string name="transaction_action_recv">You received</string>
|
||||||
<string name="amount_label">Amount</string>
|
<string name="amount_label">Amount</string>
|
||||||
<string name="tx_amount_no_prefix">%1$s XMR</string>
|
<string name="tx_amount_no_prefix">%1$s XMR</string>
|
||||||
|
<string name="tx_amount_no_prefix2">999.99999999999</string>
|
||||||
<string name="wallet_proxy_address_hint">127.0.0.1</string>
|
<string name="wallet_proxy_address_hint">127.0.0.1</string>
|
||||||
<string name="wallet_proxy_port_hint">9050</string>
|
<string name="wallet_proxy_port_hint">9050</string>
|
||||||
<string name="no_history_loading">Loading your wallet…</string>
|
<string name="no_history_loading">Loading your wallet…</string>
|
||||||
@ -89,9 +92,16 @@
|
|||||||
<string name="disconnected">Disconnected</string>
|
<string name="disconnected">Disconnected</string>
|
||||||
<string name="version_mismatch">Version mismatch</string>
|
<string name="version_mismatch">Version mismatch</string>
|
||||||
<string name="transaction_hash">Transaction Hash</string>
|
<string name="transaction_hash">Transaction Hash</string>
|
||||||
|
<string name="transaction_hash_desc">in a transaction with id</string>
|
||||||
<string name="transaction_destination">Destination</string>
|
<string name="transaction_destination">Destination</string>
|
||||||
|
<string name="transaction_destination_desc">to address</string>
|
||||||
<string name="confirmations">Confirmations</string>
|
<string name="confirmations">Confirmations</string>
|
||||||
|
<string name="transaction_conf_desc">It has been confirmed</string>
|
||||||
|
<string name="transaction_conf_desc2_confirmed">times, and was mined in block</string>
|
||||||
|
<string name="transaction_conf_desc2_unconfirmed">times, and is currently in the mempool</string>
|
||||||
|
<string name="transaction_conf_1_desc2_confirmed">time, and was mined in block</string>
|
||||||
<string name="date">Date</string>
|
<string name="date">Date</string>
|
||||||
|
<string name="transaction_on_date_label">on</string>
|
||||||
<string name="node_selected">Node has been selected</string>
|
<string name="node_selected">Node has been selected</string>
|
||||||
<string name="fee_priority">Fee priority:</string>
|
<string name="fee_priority">Fee priority:</string>
|
||||||
<string name="low">Low</string>
|
<string name="low">Low</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user