mirror of
https://codeberg.org/anoncontributorxmr/mysu.git
synced 2024-11-22 07:22:26 +00:00
Cleanup/reformat code
This commit is contained in:
parent
68dfd3797c
commit
83c26a0ea3
44 changed files with 338 additions and 215 deletions
|
@ -1,7 +1,6 @@
|
||||||
package net.mynero.wallet
|
package net.mynero.wallet
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.PersistableBundle
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
|
|
@ -33,6 +33,7 @@ class CoinsInfoAdapter(val listener: CoinsInfoAdapterListener?) :
|
||||||
RecyclerView.Adapter<CoinsInfoAdapter.ViewHolder>() {
|
RecyclerView.Adapter<CoinsInfoAdapter.ViewHolder>() {
|
||||||
private var localDataSet // <public-key, coinsinfo>
|
private var localDataSet // <public-key, coinsinfo>
|
||||||
: List<CoinsInfo>
|
: List<CoinsInfo>
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val selectedUtxos // <public-key, coinsinfo>
|
val selectedUtxos // <public-key, coinsinfo>
|
||||||
: HashMap<String?, CoinsInfo>
|
: HashMap<String?, CoinsInfo>
|
||||||
|
|
|
@ -71,9 +71,10 @@ class SubaddressAdapter(val listener: SubaddressAdapterListener?) :
|
||||||
* Provide a reference to the type of views that you are using
|
* Provide a reference to the type of views that you are using
|
||||||
* (custom ViewHolder).
|
* (custom ViewHolder).
|
||||||
*/
|
*/
|
||||||
class ViewHolder(view: View, val listener: SubaddressAdapterListener?) : RecyclerView.ViewHolder(
|
class ViewHolder(view: View, val listener: SubaddressAdapterListener?) :
|
||||||
view
|
RecyclerView.ViewHolder(
|
||||||
) {
|
view
|
||||||
|
) {
|
||||||
|
|
||||||
fun bind(subaddress: Subaddress) {
|
fun bind(subaddress: Subaddress) {
|
||||||
val addressTextView =
|
val addressTextView =
|
||||||
|
|
|
@ -75,7 +75,8 @@ class TransactionInfoAdapter(val listener: TxInfoAdapterListener?) :
|
||||||
* Provide a reference to the type of views that you are using
|
* Provide a reference to the type of views that you are using
|
||||||
* (custom ViewHolder).
|
* (custom ViewHolder).
|
||||||
*/
|
*/
|
||||||
class ViewHolder(val listener: TxInfoAdapterListener?, view: View) : RecyclerView.ViewHolder(view) {
|
class ViewHolder(val listener: TxInfoAdapterListener?, view: View) :
|
||||||
|
RecyclerView.ViewHolder(view) {
|
||||||
private val outboundColour: Int
|
private val outboundColour: Int
|
||||||
private val inboundColour: Int
|
private val inboundColour: Int
|
||||||
private val pendingColour: Int
|
private val pendingColour: Int
|
||||||
|
|
|
@ -19,8 +19,84 @@ import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
// Nodes stolen from https://moneroworld.com/#nodes
|
// Nodes stolen from https://moneroworld.com/#nodes
|
||||||
enum class DefaultNodes(val address: String, private val port: Int, private val network: String, private val nodeName: String) {
|
enum class DefaultNodes(
|
||||||
SAMOURAI("163.172.56.213", 18089, "mainnet", "SamouraiWallet"), MONERUJO("nodex.monerujo.io", 18081, "mainnet", "monerujo"), SUPPORTXMR("node.supportxmr.com", 18081, "mainnet", "SupportXMR"), HASHVAULT("nodes.hashvault.pro", 18081, "mainnet", "Hashvault"), MONEROWORLD("node.moneroworld.com", 18089, "mainnet", "MoneroWorld"), XMRTW("opennode.xmr-tw.org", 18089, "mainnet", "XMRTW"), MYNERO_I2P("ynk3hrwte23asonojqeskoulek2g2cd6tqg4neghnenfyljrvhga.b32.i2p", 0, "mainnet", "node.mysu.i2p"), MYNERO_ONION("tiopyrxseconw73thwlv2pf5hebfcqxj5zdolym7z6pbq6gl4z7xz4ad.onion", 18081, "mainnet", "node.mysu.onion"), SAMOURAI_ONION("446unwib5vc7pfbzflosy6m6vtyuhddnalr3hutyavwe4esfuu5g6ryd.onion", 18089, "mainnet", "SamouraiWallet.onion"), MONERUJO_ONION("monerujods7mbghwe6cobdr6ujih6c22zu5rl7zshmizz2udf7v7fsad.onion", 18081, "mainnet", "monerujo.onion"), Criminales78("56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion", 18089, "mainnet", "Criminales78.onion"), xmrfail("mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion", 18081, "mainnet", "xmrfail.onion"), boldsuck("6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion", 18081, "mainnet", "boldsuck.onion");
|
val address: String,
|
||||||
|
private val port: Int,
|
||||||
|
private val network: String,
|
||||||
|
private val nodeName: String
|
||||||
|
) {
|
||||||
|
SAMOURAI("163.172.56.213", 18089, "mainnet", "SamouraiWallet"), MONERUJO(
|
||||||
|
"nodex.monerujo.io",
|
||||||
|
18081,
|
||||||
|
"mainnet",
|
||||||
|
"monerujo"
|
||||||
|
),
|
||||||
|
SUPPORTXMR(
|
||||||
|
"node.supportxmr.com",
|
||||||
|
18081,
|
||||||
|
"mainnet",
|
||||||
|
"SupportXMR"
|
||||||
|
),
|
||||||
|
HASHVAULT(
|
||||||
|
"nodes.hashvault.pro",
|
||||||
|
18081,
|
||||||
|
"mainnet",
|
||||||
|
"Hashvault"
|
||||||
|
),
|
||||||
|
MONEROWORLD(
|
||||||
|
"node.moneroworld.com",
|
||||||
|
18089,
|
||||||
|
"mainnet",
|
||||||
|
"MoneroWorld"
|
||||||
|
),
|
||||||
|
XMRTW(
|
||||||
|
"opennode.xmr-tw.org",
|
||||||
|
18089,
|
||||||
|
"mainnet",
|
||||||
|
"XMRTW"
|
||||||
|
),
|
||||||
|
MYNERO_I2P(
|
||||||
|
"ynk3hrwte23asonojqeskoulek2g2cd6tqg4neghnenfyljrvhga.b32.i2p",
|
||||||
|
0,
|
||||||
|
"mainnet",
|
||||||
|
"node.mysu.i2p"
|
||||||
|
),
|
||||||
|
MYNERO_ONION(
|
||||||
|
"tiopyrxseconw73thwlv2pf5hebfcqxj5zdolym7z6pbq6gl4z7xz4ad.onion",
|
||||||
|
18081,
|
||||||
|
"mainnet",
|
||||||
|
"node.mysu.onion"
|
||||||
|
),
|
||||||
|
SAMOURAI_ONION(
|
||||||
|
"446unwib5vc7pfbzflosy6m6vtyuhddnalr3hutyavwe4esfuu5g6ryd.onion",
|
||||||
|
18089,
|
||||||
|
"mainnet",
|
||||||
|
"SamouraiWallet.onion"
|
||||||
|
),
|
||||||
|
MONERUJO_ONION(
|
||||||
|
"monerujods7mbghwe6cobdr6ujih6c22zu5rl7zshmizz2udf7v7fsad.onion",
|
||||||
|
18081,
|
||||||
|
"mainnet",
|
||||||
|
"monerujo.onion"
|
||||||
|
),
|
||||||
|
Criminales78(
|
||||||
|
"56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion",
|
||||||
|
18089,
|
||||||
|
"mainnet",
|
||||||
|
"Criminales78.onion"
|
||||||
|
),
|
||||||
|
xmrfail(
|
||||||
|
"mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion",
|
||||||
|
18081,
|
||||||
|
"mainnet",
|
||||||
|
"xmrfail.onion"
|
||||||
|
),
|
||||||
|
boldsuck(
|
||||||
|
"6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion",
|
||||||
|
18081,
|
||||||
|
"mainnet",
|
||||||
|
"boldsuck.onion"
|
||||||
|
);
|
||||||
|
|
||||||
val nodeString: String
|
val nodeString: String
|
||||||
get() = "$address:$port/$network/$nodeName"
|
get() = "$address:$port/$network/$nodeName"
|
||||||
|
|
|
@ -51,8 +51,10 @@ class Node {
|
||||||
this.username = ""
|
this.username = ""
|
||||||
this.password = ""
|
this.password = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
2 -> { // credentials
|
2 -> { // credentials
|
||||||
val userPassword = a[0].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
val userPassword =
|
||||||
|
a[0].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
require(userPassword.size == 2) { "User:Password invalid" }
|
require(userPassword.size == 2) { "User:Password invalid" }
|
||||||
this.username = userPassword[0]
|
this.username = userPassword[0]
|
||||||
this.password = if (this.username.isNotEmpty()) {
|
this.password = if (this.username.isNotEmpty()) {
|
||||||
|
@ -62,11 +64,13 @@ class Node {
|
||||||
}
|
}
|
||||||
daemonAddress = a[1]
|
daemonAddress = a[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
throw IllegalArgumentException("Too many @")
|
throw IllegalArgumentException("Too many @")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val daParts = daemonAddress.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
val daParts =
|
||||||
|
daemonAddress.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
require(!(daParts.size > 3 || daParts.isEmpty())) { "Too many '/' or too few" }
|
require(!(daParts.size > 3 || daParts.isEmpty())) { "Too many '/' or too few" }
|
||||||
daemonAddress = daParts[0]
|
daemonAddress = daParts[0]
|
||||||
val da = daemonAddress.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
val da = daemonAddress.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
@ -240,6 +244,7 @@ class Node {
|
||||||
const val TESTNET = "testnet"
|
const val TESTNET = "testnet"
|
||||||
private var DEFAULT_LEVIN_PORT = 0
|
private var DEFAULT_LEVIN_PORT = 0
|
||||||
private var DEFAULT_RPC_PORT = 0
|
private var DEFAULT_RPC_PORT = 0
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun fromString(nodeString: String?): Node? {
|
fun fromString(nodeString: String?): Node? {
|
||||||
return try {
|
return try {
|
||||||
|
|
|
@ -17,7 +17,12 @@ package net.mynero.wallet.data
|
||||||
|
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
class Subaddress(private val accountIndex: Int, @JvmField val addressIndex: Int, @JvmField val address: String, val label: String) : Comparable<Subaddress> {
|
class Subaddress(
|
||||||
|
private val accountIndex: Int,
|
||||||
|
@JvmField val addressIndex: Int,
|
||||||
|
@JvmField val address: String,
|
||||||
|
val label: String
|
||||||
|
) : Comparable<Subaddress> {
|
||||||
@JvmField
|
@JvmField
|
||||||
var amount: Long = 0
|
var amount: Long = 0
|
||||||
|
|
||||||
|
@ -29,10 +34,13 @@ class Subaddress(private val accountIndex: Int, @JvmField val addressIndex: Int,
|
||||||
val squashedAddress: String
|
val squashedAddress: String
|
||||||
get() = address.substring(0, 8) + "…" + address.substring(address.length - 8)
|
get() = address.substring(0, 8) + "…" + address.substring(address.length - 8)
|
||||||
val displayLabel: String
|
val displayLabel: String
|
||||||
get() = if (label.isEmpty() || DEFAULT_LABEL_FORMATTER.matcher(label).matches()) "#$addressIndex" else label
|
get() = if (label.isEmpty() || DEFAULT_LABEL_FORMATTER.matcher(label)
|
||||||
|
.matches()
|
||||||
|
) "#$addressIndex" else label
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
val DEFAULT_LABEL_FORMATTER: Pattern = Pattern.compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}:[0-9]{2}:[0-9]{2}$")
|
val DEFAULT_LABEL_FORMATTER: Pattern =
|
||||||
|
Pattern.compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}:[0-9]{2}:[0-9]{2}$")
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -41,11 +41,13 @@ class TxData : Parcelable {
|
||||||
preferredInputs = txData.preferredInputs
|
preferredInputs = txData.preferredInputs
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(dstAddr: String?,
|
constructor(
|
||||||
amount: Long,
|
dstAddr: String?,
|
||||||
mixin: Int,
|
amount: Long,
|
||||||
priority: PendingTransaction.Priority?,
|
mixin: Int,
|
||||||
preferredInputs: ArrayList<String>?) {
|
priority: PendingTransaction.Priority?,
|
||||||
|
preferredInputs: ArrayList<String>?
|
||||||
|
) {
|
||||||
destinationAddress = dstAddr
|
destinationAddress = dstAddr
|
||||||
this.amount = amount
|
this.amount = amount
|
||||||
this.mixin = mixin
|
this.mixin = mixin
|
||||||
|
|
|
@ -19,15 +19,20 @@ import java.util.regex.Pattern
|
||||||
|
|
||||||
class UserNotes(txNotes: String?) {
|
class UserNotes(txNotes: String?) {
|
||||||
var txNotes: String? = ""
|
var txNotes: String? = ""
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var note: String? = ""
|
var note: String? = ""
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var xmrtoTag: String? = null
|
var xmrtoTag: String? = null
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var xmrtoKey: String? = null
|
var xmrtoKey: String? = null
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var xmrtoAmount: String? = null // could be a double - but we are not doing any calculations
|
var xmrtoAmount: String? = null // could be a double - but we are not doing any calculations
|
||||||
var xmrtoCurrency: String? = null
|
var xmrtoCurrency: String? = null
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var xmrtoDestination: String? = null
|
var xmrtoDestination: String? = null
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Patterns;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -48,11 +47,17 @@ public class AddNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
ImageButton pastePasswordImageButton = view.findViewById(R.id.paste_password_imagebutton);
|
ImageButton pastePasswordImageButton = view.findViewById(R.id.paste_password_imagebutton);
|
||||||
|
|
||||||
usernameEditText.addTextChangedListener(new TextWatcher() {
|
usernameEditText.addTextChangedListener(new TextWatcher() {
|
||||||
@Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
@Override
|
||||||
@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable editable) {
|
public void afterTextChanged(Editable editable) {
|
||||||
if(editable.toString().isEmpty()) {
|
if (editable.toString().isEmpty()) {
|
||||||
passwordEditText.setText(null);
|
passwordEditText.setText(null);
|
||||||
passwordEditText.setVisibility(View.GONE);
|
passwordEditText.setVisibility(View.GONE);
|
||||||
pastePasswordImageButton.setVisibility(View.GONE);
|
pastePasswordImageButton.setVisibility(View.GONE);
|
||||||
|
@ -73,13 +78,13 @@ public class AddNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
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(nodeAddr.isEmpty() || portString.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()) {
|
||||||
Toast.makeText(getContext(), "Enter password", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Enter password", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,8 @@ import net.mynero.wallet.model.WalletManager;
|
||||||
import net.mynero.wallet.service.AddressService;
|
import net.mynero.wallet.service.AddressService;
|
||||||
import net.mynero.wallet.util.Helper;
|
import net.mynero.wallet.util.Helper;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class EditAddressLabelBottomSheetDialog extends BottomSheetDialogFragment {
|
public class EditAddressLabelBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
|
@ -47,18 +45,19 @@ public class EditAddressLabelBottomSheetDialog extends BottomSheetDialogFragment
|
||||||
try {
|
try {
|
||||||
new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.US).parse(wallet.getSubaddressLabel(addressIndex));
|
new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.US).parse(wallet.getSubaddressLabel(addressIndex));
|
||||||
isDate = true;
|
isDate = true;
|
||||||
} catch (ParseException ignored) { }
|
} catch (ParseException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
labelEditText.setText(isDate ? null : wallet.getSubaddressLabel(addressIndex));
|
labelEditText.setText(isDate ? null : wallet.getSubaddressLabel(addressIndex));
|
||||||
pasteButton.setOnClickListener(view1 -> labelEditText.setText(Helper.getClipBoardText(view.getContext())));
|
pasteButton.setOnClickListener(view1 -> labelEditText.setText(Helper.getClipBoardText(view.getContext())));
|
||||||
saveLabelButton.setOnClickListener(view1 -> {
|
saveLabelButton.setOnClickListener(view1 -> {
|
||||||
String label = labelEditText.getText().toString();
|
String label = labelEditText.getText().toString();
|
||||||
if(addressService.getLatestAddressIndex() == addressIndex) {
|
if (addressService.getLatestAddressIndex() == addressIndex) {
|
||||||
addressService.freshSubaddress();
|
addressService.freshSubaddress();
|
||||||
}
|
}
|
||||||
wallet.setSubaddressLabel(addressIndex, label);
|
wallet.setSubaddressLabel(addressIndex, label);
|
||||||
wallet.store();
|
wallet.store();
|
||||||
if(listener != null) {
|
if (listener != null) {
|
||||||
listener.onDismiss();
|
listener.onDismiss();
|
||||||
}
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
|
|
|
@ -4,7 +4,6 @@ import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Patterns;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -20,19 +19,11 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||||
|
|
||||||
import net.mynero.wallet.R;
|
import net.mynero.wallet.R;
|
||||||
import net.mynero.wallet.data.Node;
|
import net.mynero.wallet.data.Node;
|
||||||
import net.mynero.wallet.service.PrefService;
|
|
||||||
import net.mynero.wallet.util.Constants;
|
|
||||||
import net.mynero.wallet.util.Helper;
|
import net.mynero.wallet.util.Helper;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
public EditNodeListener listener = null;
|
public EditNodeListener listener = null;
|
||||||
public Node node = null;
|
public Node node = null;
|
||||||
|
@ -54,23 +45,29 @@ public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
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);
|
||||||
|
|
||||||
if(node == null) return;
|
if (node == null) return;
|
||||||
addressEditText.setText(node.getHost());
|
addressEditText.setText(node.getHost());
|
||||||
portEditText.setText(""+node.getRpcPort());
|
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()) {
|
||||||
passwordEditText.setText(node.getPassword());
|
passwordEditText.setText(node.getPassword());
|
||||||
passwordEditText.setVisibility(View.VISIBLE);
|
passwordEditText.setVisibility(View.VISIBLE);
|
||||||
pastePasswordImageButton.setVisibility(View.VISIBLE);
|
pastePasswordImageButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
usernameEditText.addTextChangedListener(new TextWatcher() {
|
usernameEditText.addTextChangedListener(new TextWatcher() {
|
||||||
@Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
@Override
|
||||||
@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable editable) {
|
public void afterTextChanged(Editable editable) {
|
||||||
if(editable.toString().isEmpty()) {
|
if (editable.toString().isEmpty()) {
|
||||||
passwordEditText.setText(null);
|
passwordEditText.setText(null);
|
||||||
passwordEditText.setVisibility(View.GONE);
|
passwordEditText.setVisibility(View.GONE);
|
||||||
pastePasswordImageButton.setVisibility(View.GONE);
|
pastePasswordImageButton.setVisibility(View.GONE);
|
||||||
|
@ -96,13 +93,13 @@ public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
String user = usernameEditText.getText().toString();
|
String user = usernameEditText.getText().toString();
|
||||||
String pass = passwordEditText.getText().toString();
|
String pass = passwordEditText.getText().toString();
|
||||||
|
|
||||||
if(nodeName.isEmpty()) {
|
if (nodeName.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(nodeAddr.isEmpty() || portString.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()) {
|
||||||
Toast.makeText(getContext(), "Enter password", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Enter password", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +138,7 @@ public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
|
|
||||||
public interface EditNodeListener {
|
public interface EditNodeListener {
|
||||||
void onNodeDeleted(Node node);
|
void onNodeDeleted(Node node);
|
||||||
|
|
||||||
void onNodeEdited(Node oldNode, Node newNode);
|
void onNodeEdited(Node oldNode, Node newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -60,7 +60,9 @@ public class NodeSelectionBottomSheetDialog extends BottomSheetDialogFragment im
|
||||||
JSONArray jsonArray = null;
|
JSONArray jsonArray = null;
|
||||||
try {
|
try {
|
||||||
jsonArray = new JSONArray(nodesArray);
|
jsonArray = new JSONArray(nodesArray);
|
||||||
} catch (JSONException e) { throw new RuntimeException(e); }
|
} catch (JSONException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < jsonArray.length(); i++) {
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
JSONObject nodeJsonObject = null;
|
JSONObject nodeJsonObject = null;
|
||||||
|
@ -122,7 +124,9 @@ public class NodeSelectionBottomSheetDialog extends BottomSheetDialogFragment im
|
||||||
|
|
||||||
public interface NodeSelectionDialogListener {
|
public interface NodeSelectionDialogListener {
|
||||||
void onNodeSelected();
|
void onNodeSelected();
|
||||||
|
|
||||||
void onClickedEditNode(Node node);
|
void onClickedEditNode(Node node);
|
||||||
|
|
||||||
void onClickedAddNode();
|
void onClickedAddNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -46,7 +46,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
private final MutableLiveData<PendingTransaction> _pendingTransaction = new MutableLiveData<>(null);
|
private final MutableLiveData<PendingTransaction> _pendingTransaction = new MutableLiveData<>(null);
|
||||||
public ArrayList<String> selectedUtxos = new ArrayList<>();
|
public ArrayList<String> selectedUtxos = new ArrayList<>();
|
||||||
public LiveData<Boolean> sendingMax = _sendingMax;
|
public LiveData<Boolean> sendingMax = _sendingMax;
|
||||||
private final ActivityResultLauncher<String> cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(),
|
public LiveData<PendingTransaction> pendingTransaction = _pendingTransaction; private final ActivityResultLauncher<String> cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(),
|
||||||
granted -> {
|
granted -> {
|
||||||
if (granted) {
|
if (granted) {
|
||||||
onScan();
|
onScan();
|
||||||
|
@ -54,7 +54,6 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
Toast.makeText(getActivity(), getString(R.string.no_camera_permission), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.no_camera_permission), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
public LiveData<PendingTransaction> pendingTransaction = _pendingTransaction;
|
|
||||||
public UriData uriData = null;
|
public UriData uriData = null;
|
||||||
public boolean isChurning = false;
|
public boolean isChurning = false;
|
||||||
public Listener listener = null;
|
public Listener listener = null;
|
||||||
|
@ -123,7 +122,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
|
|
||||||
String valueString = Wallet.getDisplayAmount(selectedValue);
|
String valueString = Wallet.getDisplayAmount(selectedValue);
|
||||||
selectedUtxosValueTextView.setVisibility(View.VISIBLE);
|
selectedUtxosValueTextView.setVisibility(View.VISIBLE);
|
||||||
if(isChurning) {
|
if (isChurning) {
|
||||||
_sendingMax.postValue(true);
|
_sendingMax.postValue(true);
|
||||||
sendMaxButton.setEnabled(false);
|
sendMaxButton.setEnabled(false);
|
||||||
selectedUtxosValueTextView.setText(getResources().getString(R.string.selected_utxos_value_churning, valueString));
|
selectedUtxosValueTextView.setText(getResources().getString(R.string.selected_utxos_value_churning, valueString));
|
||||||
|
@ -141,7 +140,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
private void bindObservers() {
|
private void bindObservers() {
|
||||||
BalanceService.getInstance().balanceInfo.observe(getViewLifecycleOwner(), balanceInfo -> {
|
BalanceService.getInstance().balanceInfo.observe(getViewLifecycleOwner(), balanceInfo -> {
|
||||||
createButton.setEnabled(balanceInfo.getRawUnlocked() != 0);
|
createButton.setEnabled(balanceInfo.getRawUnlocked() != 0);
|
||||||
if(!isChurning) {
|
if (!isChurning) {
|
||||||
sendMaxButton.setEnabled(balanceInfo.getRawUnlocked() != 0);
|
sendMaxButton.setEnabled(balanceInfo.getRawUnlocked() != 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -206,7 +205,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
|
|
||||||
createButton.setOnClickListener(view1 -> {
|
createButton.setOnClickListener(view1 -> {
|
||||||
FragmentActivity activity = getActivity();
|
FragmentActivity activity = getActivity();
|
||||||
if(activity != null) {
|
if (activity != null) {
|
||||||
boolean sendAll = sendingMax.getValue() != null ? sendingMax.getValue() : false;
|
boolean sendAll = sendingMax.getValue() != null ? sendingMax.getValue() : false;
|
||||||
String address = addressEditText.getText().toString().trim();
|
String address = addressEditText.getText().toString().trim();
|
||||||
String amount = amountEditText.getText().toString().trim();
|
String amount = amountEditText.getText().toString().trim();
|
||||||
|
@ -274,7 +273,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
private void createTx(String address, String amount, boolean sendAll, PendingTransaction.Priority feePriority) {
|
private void createTx(String address, String amount, boolean sendAll, PendingTransaction.Priority feePriority) {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
((MoneroApplication)activity.getApplication()).getExecutor().execute(() -> {
|
((MoneroApplication) activity.getApplication()).getExecutor().execute(() -> {
|
||||||
try {
|
try {
|
||||||
PendingTransaction pendingTx = TxService.getInstance().createTx(address, amount, sendAll, feePriority, selectedUtxos);
|
PendingTransaction pendingTx = TxService.getInstance().createTx(address, amount, sendAll, feePriority, selectedUtxos);
|
||||||
if (pendingTx != null && pendingTx.getStatus() == PendingTransaction.Status.Status_Ok) {
|
if (pendingTx != null && pendingTx.getStatus() == PendingTransaction.Status.Status_Ok) {
|
||||||
|
@ -282,7 +281,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
} else {
|
} else {
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
createButton.setEnabled(true);
|
createButton.setEnabled(true);
|
||||||
if(pendingTx != null) {
|
if (pendingTx != null) {
|
||||||
Toast.makeText(activity, getString(R.string.error_creating_tx, pendingTx.getErrorString()), Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, getString(R.string.error_creating_tx, pendingTx.getErrorString()), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -350,4 +349,6 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void onSentTransaction();
|
void onSentTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -38,7 +38,7 @@ public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
Wallet wallet = WalletManager.getInstance().getWallet();
|
Wallet wallet = WalletManager.getInstance().getWallet();
|
||||||
String seed = wallet.getSeed("");
|
String seed = wallet.getSeed("");
|
||||||
boolean usesOffset = PrefService.getInstance().getBoolean(Constants.PREF_USES_OFFSET, false);
|
boolean usesOffset = PrefService.getInstance().getBoolean(Constants.PREF_USES_OFFSET, false);
|
||||||
if(usesOffset) {
|
if (usesOffset) {
|
||||||
seed = wallet.getSeed(password);
|
seed = wallet.getSeed(password);
|
||||||
view.findViewById(R.id.wallet_seed_offset_textview).setVisibility(View.VISIBLE);
|
view.findViewById(R.id.wallet_seed_offset_textview).setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment {
|
||||||
|
|
||||||
informationTextView.setText(seed);
|
informationTextView.setText(seed);
|
||||||
viewKeyTextView.setText(privateViewKey);
|
viewKeyTextView.setText(privateViewKey);
|
||||||
restoreHeightTextView.setText(wallet.getRestoreHeight()+"");
|
restoreHeightTextView.setText(wallet.getRestoreHeight() + "");
|
||||||
|
|
||||||
copyViewKeyImageButton.setOnClickListener(view1 -> Helper.clipBoardCopy(getContext(), "private view-key", privateViewKey));
|
copyViewKeyImageButton.setOnClickListener(view1 -> Helper.clipBoardCopy(getContext(), "private view-key", privateViewKey));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
@ -24,7 +23,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
import net.mynero.wallet.MainActivity;
|
import net.mynero.wallet.MainActivity;
|
||||||
import net.mynero.wallet.R;
|
import net.mynero.wallet.R;
|
||||||
import net.mynero.wallet.adapter.TransactionInfoAdapter;
|
import net.mynero.wallet.adapter.TransactionInfoAdapter;
|
||||||
import net.mynero.wallet.fragment.dialog.SendBottomSheetDialog;
|
|
||||||
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.model.WalletManager;
|
||||||
|
@ -91,7 +89,7 @@ public class HomeFragment extends Fragment implements TransactionInfoAdapter.TxI
|
||||||
|
|
||||||
if (balanceService != null) {
|
if (balanceService != null) {
|
||||||
balanceService.balanceInfo.observe(getViewLifecycleOwner(), balanceInfo -> {
|
balanceService.balanceInfo.observe(getViewLifecycleOwner(), balanceInfo -> {
|
||||||
if(balanceInfo != null) {
|
if (balanceInfo != null) {
|
||||||
unlockedBalanceTextView.setText(balanceInfo.getUnlockedDisplay());
|
unlockedBalanceTextView.setText(balanceInfo.getUnlockedDisplay());
|
||||||
|
|
||||||
if (balanceInfo.getLockedDisplay().equals(Constants.STREET_MODE_BALANCE) || balanceInfo.isLockedBalanceZero()) {
|
if (balanceInfo.getLockedDisplay().equals(Constants.STREET_MODE_BALANCE) || balanceInfo.isLockedBalanceZero()) {
|
||||||
|
@ -140,7 +138,7 @@ public class HomeFragment extends Fragment implements TransactionInfoAdapter.TxI
|
||||||
// DISPLAYING EMPTY WALLET HISTORY
|
// DISPLAYING EMPTY WALLET HISTORY
|
||||||
Wallet wallet = WalletManager.getInstance().getWallet();
|
Wallet wallet = WalletManager.getInstance().getWallet();
|
||||||
int textResId, botImgResId = 0;
|
int textResId, botImgResId = 0;
|
||||||
if(wallet != null && wallet.isSynchronized()) {
|
if (wallet != null && wallet.isSynchronized()) {
|
||||||
textResId = R.string.no_history_nget_some_monero_in_here;
|
textResId = R.string.no_history_nget_some_monero_in_here;
|
||||||
botImgResId = R.drawable.xmrchan_empty; // img for synchronized
|
botImgResId = R.drawable.xmrchan_empty; // img for synchronized
|
||||||
} else {
|
} else {
|
||||||
|
@ -189,7 +187,7 @@ public class HomeFragment extends Fragment implements TransactionInfoAdapter.TxI
|
||||||
ImageView botImageView = view.findViewById(R.id.monerochan_imageview);
|
ImageView botImageView = view.findViewById(R.id.monerochan_imageview);
|
||||||
view.findViewById(R.id.no_history_layout).setVisibility(display ? View.VISIBLE : View.GONE);
|
view.findViewById(R.id.no_history_layout).setVisibility(display ? View.VISIBLE : View.GONE);
|
||||||
boolean displayMonerochan = PrefService.getInstance().getBoolean(Constants.PREF_MONEROCHAN, true);
|
boolean displayMonerochan = PrefService.getInstance().getBoolean(Constants.PREF_MONEROCHAN, true);
|
||||||
if(displayMonerochan) {
|
if (displayMonerochan) {
|
||||||
botImageView.setVisibility(View.VISIBLE);
|
botImageView.setVisibility(View.VISIBLE);
|
||||||
mnrjTextView.setVisibility(View.VISIBLE);
|
mnrjTextView.setVisibility(View.VISIBLE);
|
||||||
textView.setVisibility(View.GONE);
|
textView.setVisibility(View.GONE);
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
public void afterTextChanged(Editable editable) {
|
public void afterTextChanged(Editable editable) {
|
||||||
if (mViewModel != null) {
|
if (mViewModel != null) {
|
||||||
mViewModel.setProxyAddress(editable.toString());
|
mViewModel.setProxyAddress(editable.toString());
|
||||||
mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication()));
|
mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -64,7 +64,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
public void afterTextChanged(Editable editable) {
|
public void afterTextChanged(Editable editable) {
|
||||||
if (mViewModel != null) {
|
if (mViewModel != null) {
|
||||||
mViewModel.setProxyPort(editable.toString());
|
mViewModel.setProxyPort(editable.toString());
|
||||||
mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication()));
|
mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -136,7 +136,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
mViewModel.seedType.observe(getViewLifecycleOwner(), seedType -> {
|
mViewModel.seedType.observe(getViewLifecycleOwner(), seedType -> {
|
||||||
seedTypeButton.setText(seedType.toString());
|
seedTypeButton.setText(seedType.toString());
|
||||||
seedTypeDescTextView.setText(getText(seedType.getDescResId()));
|
seedTypeDescTextView.setText(getText(seedType.getDescResId()));
|
||||||
if(seedType == OnboardingViewModel.SeedType.LEGACY) {
|
if (seedType == OnboardingViewModel.SeedType.LEGACY) {
|
||||||
seedOffsetCheckbox.setVisibility(View.VISIBLE);
|
seedOffsetCheckbox.setVisibility(View.VISIBLE);
|
||||||
walletRestoreHeightEditText.setVisibility(View.VISIBLE);
|
walletRestoreHeightEditText.setVisibility(View.VISIBLE);
|
||||||
walletPasswordEditText.setHint(getString(R.string.password_optional));
|
walletPasswordEditText.setHint(getString(R.string.password_optional));
|
||||||
|
@ -151,9 +151,13 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
private void bindListeners() {
|
private void bindListeners() {
|
||||||
seedOffsetCheckbox.setChecked(useOffset);
|
seedOffsetCheckbox.setChecked(useOffset);
|
||||||
// Disable onBack click
|
// Disable onBack click
|
||||||
OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { } };
|
OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
|
||||||
|
@Override
|
||||||
|
public void handleOnBackPressed() {
|
||||||
|
}
|
||||||
|
};
|
||||||
FragmentActivity activity = getActivity();
|
FragmentActivity activity = getActivity();
|
||||||
if(activity != null)
|
if (activity != null)
|
||||||
activity.getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), onBackPressedCallback);
|
activity.getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), onBackPressedCallback);
|
||||||
|
|
||||||
moreOptionsDropdownTextView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked());
|
moreOptionsDropdownTextView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked());
|
||||||
|
@ -163,7 +167,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
createWalletButton.setOnClickListener(view1 -> {
|
createWalletButton.setOnClickListener(view1 -> {
|
||||||
prepareDefaultNode();
|
prepareDefaultNode();
|
||||||
onBackPressedCallback.setEnabled(false);
|
onBackPressedCallback.setEnabled(false);
|
||||||
((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> {
|
((MoneroApplication) getActivity().getApplication()).getExecutor().execute(() -> {
|
||||||
createOrImportWallet(
|
createOrImportWallet(
|
||||||
walletPasswordEditText.getText().toString(),
|
walletPasswordEditText.getText().toString(),
|
||||||
walletPasswordConfirmEditText.getText().toString(),
|
walletPasswordConfirmEditText.getText().toString(),
|
||||||
|
@ -229,13 +233,13 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
addProxyTextListeners();
|
addProxyTextListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication()));
|
mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication()));
|
||||||
});
|
});
|
||||||
|
|
||||||
showXmrchanSwitch.setChecked(PrefService.getInstance().getBoolean(Constants.PREF_MONEROCHAN, true));
|
showXmrchanSwitch.setChecked(PrefService.getInstance().getBoolean(Constants.PREF_MONEROCHAN, true));
|
||||||
showXmrchanSwitch.setOnCheckedChangeListener((compoundButton, b) -> {
|
showXmrchanSwitch.setOnCheckedChangeListener((compoundButton, b) -> {
|
||||||
PrefService.getInstance().edit().putBoolean(Constants.PREF_MONEROCHAN, b).apply();
|
PrefService.getInstance().edit().putBoolean(Constants.PREF_MONEROCHAN, b).apply();
|
||||||
if(b) {
|
if (b) {
|
||||||
xmrchanOnboardingImage.setVisibility(View.VISIBLE);
|
xmrchanOnboardingImage.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
xmrchanOnboardingImage.setVisibility(View.GONE);
|
xmrchanOnboardingImage.setVisibility(View.GONE);
|
||||||
|
@ -253,11 +257,11 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
|
|
||||||
private void toggleSeedType() {
|
private void toggleSeedType() {
|
||||||
OnboardingViewModel.SeedType seedType = mViewModel.seedType.getValue();
|
OnboardingViewModel.SeedType seedType = mViewModel.seedType.getValue();
|
||||||
if(seedType == null) return;
|
if (seedType == null) return;
|
||||||
OnboardingViewModel.SeedType newSeedType = OnboardingViewModel.SeedType.UNKNOWN;
|
OnboardingViewModel.SeedType newSeedType = OnboardingViewModel.SeedType.UNKNOWN;
|
||||||
if(seedType == OnboardingViewModel.SeedType.POLYSEED) {
|
if (seedType == OnboardingViewModel.SeedType.POLYSEED) {
|
||||||
newSeedType = OnboardingViewModel.SeedType.LEGACY;
|
newSeedType = OnboardingViewModel.SeedType.LEGACY;
|
||||||
} else if(seedType == OnboardingViewModel.SeedType.LEGACY) {
|
} else if (seedType == OnboardingViewModel.SeedType.LEGACY) {
|
||||||
newSeedType = OnboardingViewModel.SeedType.POLYSEED;
|
newSeedType = OnboardingViewModel.SeedType.POLYSEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +274,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
|
|
||||||
private void createOrImportWallet(String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText) {
|
private void createOrImportWallet(String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText) {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if(activity != null) {
|
if (activity != null) {
|
||||||
mViewModel.createOrImportWallet(activity, walletPassword, confirmedPassword, walletSeed, restoreHeightText, useOffset);
|
mViewModel.createOrImportWallet(activity, walletPassword, confirmedPassword, walletSeed, restoreHeightText, useOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,11 +303,12 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
|
||||||
public void onNodeSelected() {
|
public void onNodeSelected() {
|
||||||
Node node = PrefService.getInstance().getNode();
|
Node node = PrefService.getInstance().getNode();
|
||||||
selectNodeButton.setText(getString(R.string.node_button_text, node.getAddress()));
|
selectNodeButton.setText(getString(R.string.node_button_text, node.getAddress()));
|
||||||
mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication()));
|
mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClickedEditNode(Node node) { }
|
public void onClickedEditNode(Node node) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClickedAddNode() {
|
public void onClickedAddNode() {
|
||||||
|
|
|
@ -22,10 +22,10 @@ import java.util.Calendar;
|
||||||
|
|
||||||
public class OnboardingViewModel extends ViewModel {
|
public class OnboardingViewModel extends ViewModel {
|
||||||
private final MutableLiveData<Boolean> _showMoreOptions = new MutableLiveData<>(false);
|
private final MutableLiveData<Boolean> _showMoreOptions = new MutableLiveData<>(false);
|
||||||
public LiveData<Boolean> showMoreOptions = _showMoreOptions;
|
|
||||||
private final MutableLiveData<Boolean> _enableCreateButton = new MutableLiveData<>(true);
|
private final MutableLiveData<Boolean> _enableCreateButton = new MutableLiveData<>(true);
|
||||||
public LiveData<Boolean> enableCreateButton = _enableCreateButton;
|
|
||||||
private final MutableLiveData<SeedType> _seedType = new MutableLiveData<>(SeedType.POLYSEED);
|
private final MutableLiveData<SeedType> _seedType = new MutableLiveData<>(SeedType.POLYSEED);
|
||||||
|
public LiveData<Boolean> showMoreOptions = _showMoreOptions;
|
||||||
|
public LiveData<Boolean> enableCreateButton = _enableCreateButton;
|
||||||
public LiveData<SeedType> seedType = _seedType;
|
public LiveData<SeedType> seedType = _seedType;
|
||||||
private String proxyAddress = "";
|
private String proxyAddress = "";
|
||||||
private String proxyPort = "";
|
private String proxyPort = "";
|
||||||
|
@ -69,12 +69,12 @@ public class OnboardingViewModel extends ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createOrImportWallet(Activity mainActivity, String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText, boolean useOffset) {
|
public void createOrImportWallet(Activity mainActivity, String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText, boolean useOffset) {
|
||||||
MoneroApplication application = (MoneroApplication)mainActivity.getApplication();
|
MoneroApplication application = (MoneroApplication) mainActivity.getApplication();
|
||||||
application.getExecutor().execute(() -> {
|
application.getExecutor().execute(() -> {
|
||||||
_enableCreateButton.postValue(false);
|
_enableCreateButton.postValue(false);
|
||||||
String offset = useOffset ? walletPassword : "";
|
String offset = useOffset ? walletPassword : "";
|
||||||
if (!walletPassword.isEmpty()) {
|
if (!walletPassword.isEmpty()) {
|
||||||
if(!walletPassword.equals(confirmedPassword)) {
|
if (!walletPassword.equals(confirmedPassword)) {
|
||||||
_enableCreateButton.postValue(true);
|
_enableCreateButton.postValue(true);
|
||||||
mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, application.getString(R.string.invalid_confirmed_password), Toast.LENGTH_SHORT).show());
|
mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, application.getString(R.string.invalid_confirmed_password), Toast.LENGTH_SHORT).show());
|
||||||
return;
|
return;
|
||||||
|
@ -84,16 +84,16 @@ public class OnboardingViewModel extends ViewModel {
|
||||||
long restoreHeight = getNewRestoreHeight();
|
long restoreHeight = getNewRestoreHeight();
|
||||||
File walletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME);
|
File walletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME);
|
||||||
Wallet wallet = null;
|
Wallet wallet = null;
|
||||||
if(!offset.isEmpty()) {
|
if (!offset.isEmpty()) {
|
||||||
PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_OFFSET, true).apply();
|
PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_OFFSET, true).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (walletSeed.isEmpty()) {
|
if (walletSeed.isEmpty()) {
|
||||||
SeedType seedTypeValue = seedType.getValue();
|
SeedType seedTypeValue = seedType.getValue();
|
||||||
if(seedTypeValue == null) return;
|
if (seedTypeValue == null) return;
|
||||||
|
|
||||||
if(seedTypeValue == SeedType.POLYSEED) {
|
if (seedTypeValue == SeedType.POLYSEED) {
|
||||||
if(offset.isEmpty()) {
|
if (offset.isEmpty()) {
|
||||||
mainActivity.runOnUiThread(() -> {
|
mainActivity.runOnUiThread(() -> {
|
||||||
_enableCreateButton.postValue(true);
|
_enableCreateButton.postValue(true);
|
||||||
Toast.makeText(mainActivity, application.getString(R.string.invalid_empty_passphrase), Toast.LENGTH_SHORT).show();
|
Toast.makeText(mainActivity, application.getString(R.string.invalid_empty_passphrase), Toast.LENGTH_SHORT).show();
|
||||||
|
@ -102,7 +102,7 @@ public class OnboardingViewModel extends ViewModel {
|
||||||
} else {
|
} else {
|
||||||
wallet = WalletManager.getInstance().createWalletPolyseed(walletFile, walletPassword, offset, Constants.MNEMONIC_LANGUAGE);
|
wallet = WalletManager.getInstance().createWalletPolyseed(walletFile, walletPassword, offset, Constants.MNEMONIC_LANGUAGE);
|
||||||
}
|
}
|
||||||
} else if(seedTypeValue == SeedType.LEGACY) {
|
} else if (seedTypeValue == SeedType.LEGACY) {
|
||||||
File tmpWalletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME + "_tmp");
|
File tmpWalletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME + "_tmp");
|
||||||
Wallet tmpWallet = createTempWallet(tmpWalletFile); //we do this to get seed, then recover wallet so we can use seed offset
|
Wallet tmpWallet = createTempWallet(tmpWalletFile); //we do this to get seed, then recover wallet so we can use seed offset
|
||||||
wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, tmpWallet.getSeed(""), offset, restoreHeight);
|
wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, tmpWallet.getSeed(""), offset, restoreHeight);
|
||||||
|
@ -127,7 +127,7 @@ public class OnboardingViewModel extends ViewModel {
|
||||||
walletFile.delete(); // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too.
|
walletFile.delete(); // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too.
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
((MainActivity)mainActivity).init(walletFile, walletPassword);
|
((MainActivity) mainActivity).init(walletFile, walletPassword);
|
||||||
mainActivity.runOnUiThread(mainActivity::onBackPressed);
|
mainActivity.runOnUiThread(mainActivity::onBackPressed);
|
||||||
} else {
|
} else {
|
||||||
mainActivity.runOnUiThread(() -> {
|
mainActivity.runOnUiThread(() -> {
|
||||||
|
@ -147,10 +147,10 @@ public class OnboardingViewModel extends ViewModel {
|
||||||
public SeedType getMnemonicType(String seed) {
|
public SeedType getMnemonicType(String seed) {
|
||||||
String[] words = seed.split("\\s");
|
String[] words = seed.split("\\s");
|
||||||
SeedType seedTypeValue = seedType.getValue();
|
SeedType seedTypeValue = seedType.getValue();
|
||||||
if(seedTypeValue == null) return SeedType.LEGACY;
|
if (seedTypeValue == null) return SeedType.LEGACY;
|
||||||
if(words.length == 16 && seedTypeValue == SeedType.POLYSEED) {
|
if (words.length == 16 && seedTypeValue == SeedType.POLYSEED) {
|
||||||
return SeedType.POLYSEED;
|
return SeedType.POLYSEED;
|
||||||
} else if (words.length == 25 && seedTypeValue == SeedType.LEGACY){
|
} else if (words.length == 25 && seedTypeValue == SeedType.LEGACY) {
|
||||||
return SeedType.LEGACY;
|
return SeedType.LEGACY;
|
||||||
} else {
|
} else {
|
||||||
return SeedType.UNKNOWN;
|
return SeedType.UNKNOWN;
|
||||||
|
@ -166,7 +166,7 @@ public class OnboardingViewModel extends ViewModel {
|
||||||
POLYSEED(R.string.seed_desc_polyseed),
|
POLYSEED(R.string.seed_desc_polyseed),
|
||||||
UNKNOWN(0);
|
UNKNOWN(0);
|
||||||
|
|
||||||
private int descResId;
|
private final int descResId;
|
||||||
|
|
||||||
SeedType(int descResId) {
|
SeedType(int descResId) {
|
||||||
this.descResId = descResId;
|
this.descResId = descResId;
|
||||||
|
|
|
@ -27,9 +27,7 @@ import net.mynero.wallet.R;
|
||||||
import net.mynero.wallet.adapter.SubaddressAdapter;
|
import net.mynero.wallet.adapter.SubaddressAdapter;
|
||||||
import net.mynero.wallet.data.Subaddress;
|
import net.mynero.wallet.data.Subaddress;
|
||||||
import net.mynero.wallet.fragment.dialog.EditAddressLabelBottomSheetDialog;
|
import net.mynero.wallet.fragment.dialog.EditAddressLabelBottomSheetDialog;
|
||||||
import net.mynero.wallet.util.DayNightMode;
|
|
||||||
import net.mynero.wallet.util.Helper;
|
import net.mynero.wallet.util.Helper;
|
||||||
import net.mynero.wallet.util.NightmodeHelper;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
|
@ -15,8 +15,8 @@ import java.util.List;
|
||||||
|
|
||||||
public class ReceiveViewModel extends ViewModel {
|
public class ReceiveViewModel extends ViewModel {
|
||||||
private final MutableLiveData<Subaddress> _address = new MutableLiveData<>();
|
private final MutableLiveData<Subaddress> _address = new MutableLiveData<>();
|
||||||
public LiveData<Subaddress> address = _address;
|
|
||||||
private final MutableLiveData<List<Subaddress>> _addresses = new MutableLiveData<>();
|
private final MutableLiveData<List<Subaddress>> _addresses = new MutableLiveData<>();
|
||||||
|
public LiveData<Subaddress> address = _address;
|
||||||
public LiveData<List<Subaddress>> addresses = _addresses;
|
public LiveData<List<Subaddress>> addresses = _addresses;
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
|
@ -28,7 +28,7 @@ public class ReceiveViewModel extends ViewModel {
|
||||||
Wallet wallet = WalletManager.getInstance().getWallet();
|
Wallet wallet = WalletManager.getInstance().getWallet();
|
||||||
ArrayList<Subaddress> subaddresses = new ArrayList<>();
|
ArrayList<Subaddress> subaddresses = new ArrayList<>();
|
||||||
int addressesSize = AddressService.getInstance().getLatestAddressIndex();
|
int addressesSize = AddressService.getInstance().getLatestAddressIndex();
|
||||||
for(int i = addressesSize - 1; i >= 0; i--) {
|
for (int i = addressesSize - 1; i >= 0; i--) {
|
||||||
subaddresses.add(wallet.getSubaddressObject(i));
|
subaddresses.add(wallet.getSubaddressObject(i));
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(subaddresses);
|
return Collections.unmodifiableList(subaddresses);
|
||||||
|
|
|
@ -2,7 +2,6 @@ package net.mynero.wallet.fragment.send;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
@ -25,8 +24,6 @@ import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.google.zxing.client.android.Intents;
|
import com.google.zxing.client.android.Intents;
|
||||||
import com.journeyapps.barcodescanner.ScanContract;
|
import com.journeyapps.barcodescanner.ScanContract;
|
||||||
|
@ -48,6 +45,7 @@ import java.util.List;
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
|
|
||||||
public class SendFragment extends Fragment {
|
public class SendFragment extends Fragment {
|
||||||
|
public PendingTransaction.Priority priority;
|
||||||
private SendViewModel mViewModel;
|
private SendViewModel mViewModel;
|
||||||
private Button sendMaxButton;
|
private Button sendMaxButton;
|
||||||
private ImageButton addOutputImageView;
|
private ImageButton addOutputImageView;
|
||||||
|
@ -57,22 +55,24 @@ public class SendFragment extends Fragment {
|
||||||
private SlideToActView sendTxSlider;
|
private SlideToActView sendTxSlider;
|
||||||
private RadioGroup feeRadioGroup;
|
private RadioGroup feeRadioGroup;
|
||||||
private TextView feeRadioGroupLabelTextView;
|
private TextView feeRadioGroupLabelTextView;
|
||||||
|
|
||||||
private TextView feeTextView;
|
private TextView feeTextView;
|
||||||
private TextView addressTextView;
|
private TextView addressTextView;
|
||||||
private TextView amountTextView;
|
private TextView amountTextView;
|
||||||
|
|
||||||
public PendingTransaction.Priority priority;
|
|
||||||
private int currentEntryIndex = -1;
|
private int currentEntryIndex = -1;
|
||||||
private final ActivityResultLauncher<ScanOptions> qrCodeLauncher = registerForActivityResult(new ScanContract(), result -> {
|
private final ActivityResultLauncher<ScanOptions> qrCodeLauncher = registerForActivityResult(new ScanContract(), result -> {
|
||||||
if (result.getContents() != null) {
|
if (result.getContents() != null) {
|
||||||
if(currentEntryIndex != -1) {
|
if (currentEntryIndex != -1) {
|
||||||
pasteAddress(getDestView(currentEntryIndex), result.getContents(), false);
|
pasteAddress(getDestView(currentEntryIndex), result.getContents(), false);
|
||||||
currentEntryIndex = -1;
|
currentEntryIndex = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
private final ActivityResultLauncher<String> cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(),
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_send, container, false);
|
||||||
|
} private final ActivityResultLauncher<String> cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(),
|
||||||
granted -> {
|
granted -> {
|
||||||
if (granted) {
|
if (granted) {
|
||||||
onScan(currentEntryIndex);
|
onScan(currentEntryIndex);
|
||||||
|
@ -82,12 +82,6 @@ public class SendFragment extends Fragment {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
return inflater.inflate(R.layout.fragment_send, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
@ -105,7 +99,7 @@ public class SendFragment extends Fragment {
|
||||||
feeRadioGroupLabelTextView = view.findViewById(R.id.tx_fee_radiogroup_label_textview);
|
feeRadioGroupLabelTextView = view.findViewById(R.id.tx_fee_radiogroup_label_textview);
|
||||||
|
|
||||||
FragmentActivity activity = getActivity();
|
FragmentActivity activity = getActivity();
|
||||||
if(activity != null) {
|
if (activity != null) {
|
||||||
inflater = activity.getLayoutInflater();
|
inflater = activity.getLayoutInflater();
|
||||||
}
|
}
|
||||||
bindListeners();
|
bindListeners();
|
||||||
|
@ -133,7 +127,7 @@ public class SendFragment extends Fragment {
|
||||||
addOutputImageView.setOnClickListener(view1 -> {
|
addOutputImageView.setOnClickListener(view1 -> {
|
||||||
sendMaxButton.setVisibility(View.GONE);
|
sendMaxButton.setVisibility(View.GONE);
|
||||||
int outputCount = getDestCount();
|
int outputCount = getDestCount();
|
||||||
if(outputCount < 8) {
|
if (outputCount < 8) {
|
||||||
addOutput(false);
|
addOutput(false);
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(getActivity(), getString(R.string.max_outputs_allowed), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.max_outputs_allowed), Toast.LENGTH_SHORT).show();
|
||||||
|
@ -145,7 +139,7 @@ public class SendFragment extends Fragment {
|
||||||
createButton.setOnClickListener(view1 -> {
|
createButton.setOnClickListener(view1 -> {
|
||||||
boolean outputsValid = checkDestsValidity(isSendAll());
|
boolean outputsValid = checkDestsValidity(isSendAll());
|
||||||
|
|
||||||
if(outputsValid) {
|
if (outputsValid) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.creating_tx), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.creating_tx), Toast.LENGTH_SHORT).show();
|
||||||
createButton.setEnabled(false);
|
createButton.setEnabled(false);
|
||||||
sendMaxButton.setEnabled(false);
|
sendMaxButton.setEnabled(false);
|
||||||
|
@ -166,11 +160,11 @@ public class SendFragment extends Fragment {
|
||||||
|
|
||||||
private boolean checkDestsValidity(boolean sendAll) {
|
private boolean checkDestsValidity(boolean sendAll) {
|
||||||
List<Pair<String, String>> dests = getRawDests();
|
List<Pair<String, String>> dests = getRawDests();
|
||||||
for(Pair<String, String> dest : dests) {
|
for (Pair<String, String> dest : dests) {
|
||||||
String address = dest.component1();
|
String address = dest.component1();
|
||||||
String amount = dest.component2();
|
String amount = dest.component2();
|
||||||
if(!sendAll) {
|
if (!sendAll) {
|
||||||
if(amount.isEmpty()) {
|
if (amount.isEmpty()) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.send_amount_empty), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.send_amount_empty), Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -181,19 +175,19 @@ public class SendFragment extends Fragment {
|
||||||
Toast.makeText(getActivity(), getString(R.string.send_amount_invalid), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.send_amount_invalid), Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if(dests.size() > 1) {
|
} else if (dests.size() > 1) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.send_amount_invalid_sendall_paytomany), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.send_amount_invalid_sendall_paytomany), Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UriData uriData = UriData.parse(address);
|
UriData uriData = UriData.parse(address);
|
||||||
boolean isValidAddress = uriData != null;
|
boolean isValidAddress = uriData != null;
|
||||||
if(!isValidAddress) {
|
if (!isValidAddress) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dests.size() > 1 && uriData.hasPaymentId()) {
|
if (dests.size() > 1 && uriData.hasPaymentId()) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -204,11 +198,11 @@ public class SendFragment extends Fragment {
|
||||||
|
|
||||||
private boolean destsHasPaymentId() {
|
private boolean destsHasPaymentId() {
|
||||||
List<Pair<String, String>> dests = getRawDests();
|
List<Pair<String, String>> dests = getRawDests();
|
||||||
for(Pair<String, String> dest : dests) {
|
for (Pair<String, String> dest : dests) {
|
||||||
String address = dest.component1();
|
String address = dest.component1();
|
||||||
UriData uriData = UriData.parse(address);
|
UriData uriData = UriData.parse(address);
|
||||||
if(uriData == null) return false;
|
if (uriData == null) return false;
|
||||||
if(uriData.hasPaymentId()) return true;
|
if (uriData.hasPaymentId()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -245,28 +239,34 @@ public class SendFragment extends Fragment {
|
||||||
private void addOutput(boolean initial) {
|
private void addOutput(boolean initial) {
|
||||||
if (inflater != null) {
|
if (inflater != null) {
|
||||||
int index = getDestCount();
|
int index = getDestCount();
|
||||||
ConstraintLayout entryView = (ConstraintLayout)inflater.inflate(R.layout.transaction_output_item, null);
|
ConstraintLayout entryView = (ConstraintLayout) inflater.inflate(R.layout.transaction_output_item, null);
|
||||||
ImageButton removeOutputImageButton = entryView.findViewById(R.id.remove_output_imagebutton);
|
ImageButton removeOutputImageButton = entryView.findViewById(R.id.remove_output_imagebutton);
|
||||||
EditText addressField = entryView.findViewById(R.id.address_edittext);
|
EditText addressField = entryView.findViewById(R.id.address_edittext);
|
||||||
addressField.addTextChangedListener(new TextWatcher() {
|
addressField.addTextChangedListener(new TextWatcher() {
|
||||||
@Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
@Override
|
||||||
@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable editable) {
|
public void afterTextChanged(Editable editable) {
|
||||||
int currentOutputs = getDestCount();
|
int currentOutputs = getDestCount();
|
||||||
UriData uriData = UriData.parse(editable.toString());
|
UriData uriData = UriData.parse(editable.toString());
|
||||||
if(uriData != null) {
|
if (uriData != null) {
|
||||||
// we have valid address
|
// we have valid address
|
||||||
boolean hasPaymentId = uriData.hasPaymentId();
|
boolean hasPaymentId = uriData.hasPaymentId();
|
||||||
if(currentOutputs > 1 && hasPaymentId) {
|
if (currentOutputs > 1 && hasPaymentId) {
|
||||||
// multiple outputs when pasting/editing in integrated address. this is not allowed
|
// multiple outputs when pasting/editing in integrated address. this is not allowed
|
||||||
Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show();
|
||||||
addressField.setText(null);
|
addressField.setText(null);
|
||||||
} else if(currentOutputs == 1 && hasPaymentId) {
|
} else if (currentOutputs == 1 && hasPaymentId) {
|
||||||
// show add output button: we are sending to integrated address
|
// show add output button: we are sending to integrated address
|
||||||
mViewModel.setShowAddOutputButton(false);
|
mViewModel.setShowAddOutputButton(false);
|
||||||
}
|
}
|
||||||
} else if(currentOutputs == 1 && !isSendAll()) {
|
} else if (currentOutputs == 1 && !isSendAll()) {
|
||||||
// when send-all is false and this is our only dest and address is invalid, then show add output button
|
// when send-all is false and this is our only dest and address is invalid, then show add output button
|
||||||
mViewModel.setShowAddOutputButton(true);
|
mViewModel.setShowAddOutputButton(true);
|
||||||
}
|
}
|
||||||
|
@ -291,7 +291,7 @@ public class SendFragment extends Fragment {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
entryView.findViewById(R.id.scan_address_imagebutton).setOnClickListener(view -> onScan(index));
|
entryView.findViewById(R.id.scan_address_imagebutton).setOnClickListener(view -> onScan(index));
|
||||||
if(initial) {
|
if (initial) {
|
||||||
removeOutputImageButton.setVisibility(View.INVISIBLE);
|
removeOutputImageButton.setVisibility(View.INVISIBLE);
|
||||||
} else {
|
} else {
|
||||||
removeOutputImageButton.setOnClickListener(view -> {
|
removeOutputImageButton.setOnClickListener(view -> {
|
||||||
|
@ -314,7 +314,7 @@ public class SendFragment extends Fragment {
|
||||||
|
|
||||||
private List<Pair<String, String>> getRawDests() {
|
private List<Pair<String, String>> getRawDests() {
|
||||||
ArrayList<Pair<String, String>> dests = new ArrayList<>();
|
ArrayList<Pair<String, String>> dests = new ArrayList<>();
|
||||||
for(int i = 0; i < getDestCount(); i++) {
|
for (int i = 0; i < getDestCount(); i++) {
|
||||||
ConstraintLayout entryView = getDestView(i);
|
ConstraintLayout entryView = getDestView(i);
|
||||||
EditText amountField = entryView.findViewById(R.id.amount_edittext);
|
EditText amountField = entryView.findViewById(R.id.amount_edittext);
|
||||||
EditText addressField = entryView.findViewById(R.id.address_edittext);
|
EditText addressField = entryView.findViewById(R.id.address_edittext);
|
||||||
|
@ -391,7 +391,7 @@ public class SendFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pasteAddress(ConstraintLayout entryView, String clipboard, boolean pastingAmount) {
|
private void pasteAddress(ConstraintLayout entryView, String clipboard, boolean pastingAmount) {
|
||||||
if(pastingAmount) {
|
if (pastingAmount) {
|
||||||
try {
|
try {
|
||||||
Double.parseDouble(clipboard);
|
Double.parseDouble(clipboard);
|
||||||
setAmount(entryView, clipboard);
|
setAmount(entryView, clipboard);
|
||||||
|
@ -404,10 +404,10 @@ public class SendFragment extends Fragment {
|
||||||
UriData uriData = UriData.parse(clipboard);
|
UriData uriData = UriData.parse(clipboard);
|
||||||
if (uriData != null) {
|
if (uriData != null) {
|
||||||
int currentOutputs = getDestCount();
|
int currentOutputs = getDestCount();
|
||||||
if(currentOutputs > 1 && uriData.hasPaymentId()) {
|
if (currentOutputs > 1 && uriData.hasPaymentId()) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
} else if(currentOutputs == 1 && uriData.hasPaymentId()) {
|
} else if (currentOutputs == 1 && uriData.hasPaymentId()) {
|
||||||
mViewModel.setShowAddOutputButton(false);
|
mViewModel.setShowAddOutputButton(false);
|
||||||
}
|
}
|
||||||
EditText addressField = entryView.findViewById(R.id.address_edittext);
|
EditText addressField = entryView.findViewById(R.id.address_edittext);
|
||||||
|
@ -427,7 +427,7 @@ public class SendFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createTx(List<Pair<String, String>> dests, boolean sendAll, PendingTransaction.Priority feePriority) {
|
private void createTx(List<Pair<String, String>> dests, boolean sendAll, PendingTransaction.Priority feePriority) {
|
||||||
((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> {
|
((MoneroApplication) getActivity().getApplication()).getExecutor().execute(() -> {
|
||||||
try {
|
try {
|
||||||
PendingTransaction pendingTx = TxService.getInstance().createTx(dests, sendAll, feePriority, new ArrayList<>());
|
PendingTransaction pendingTx = TxService.getInstance().createTx(dests, sendAll, feePriority, new ArrayList<>());
|
||||||
if (pendingTx != null && pendingTx.getStatus() == PendingTransaction.Status.Status_Ok) {
|
if (pendingTx != null && pendingTx.getStatus() == PendingTransaction.Status.Status_Ok) {
|
||||||
|
@ -438,7 +438,7 @@ public class SendFragment extends Fragment {
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
createButton.setEnabled(true);
|
createButton.setEnabled(true);
|
||||||
sendMaxButton.setEnabled(true);
|
sendMaxButton.setEnabled(true);
|
||||||
if(pendingTx.getErrorString() != null)
|
if (pendingTx.getErrorString() != null)
|
||||||
Toast.makeText(activity, getString(R.string.error_creating_tx, pendingTx.getErrorString()), Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, getString(R.string.error_creating_tx, pendingTx.getErrorString()), Toast.LENGTH_SHORT).show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ public class SendFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendTx(PendingTransaction pendingTx) {
|
private void sendTx(PendingTransaction pendingTx) {
|
||||||
((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> {
|
((MoneroApplication) getActivity().getApplication()).getExecutor().execute(() -> {
|
||||||
boolean success = TxService.getInstance().sendTx(pendingTx);
|
boolean success = TxService.getInstance().sendTx(pendingTx);
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
|
@ -478,4 +478,6 @@ public class SendFragment extends Fragment {
|
||||||
private void setAddOutputButtonVisibility(int visibility) {
|
private void setAddOutputButtonVisibility(int visibility) {
|
||||||
addOutputImageView.setVisibility(visibility);
|
addOutputImageView.setVisibility(visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,10 +8,10 @@ import net.mynero.wallet.model.PendingTransaction;
|
||||||
|
|
||||||
public class SendViewModel extends ViewModel {
|
public class SendViewModel extends ViewModel {
|
||||||
private final MutableLiveData<Boolean> _sendingMax = new MutableLiveData<>(false);
|
private final MutableLiveData<Boolean> _sendingMax = new MutableLiveData<>(false);
|
||||||
public LiveData<Boolean> sendingMax = _sendingMax;
|
|
||||||
private final MutableLiveData<Boolean> _showAddOutputButton = new MutableLiveData<>(true);
|
private final MutableLiveData<Boolean> _showAddOutputButton = new MutableLiveData<>(true);
|
||||||
public LiveData<Boolean> showAddOutputButton = _showAddOutputButton;
|
|
||||||
private final MutableLiveData<PendingTransaction> _pendingTransaction = new MutableLiveData<>(null);
|
private final MutableLiveData<PendingTransaction> _pendingTransaction = new MutableLiveData<>(null);
|
||||||
|
public LiveData<Boolean> sendingMax = _sendingMax;
|
||||||
|
public LiveData<Boolean> showAddOutputButton = _showAddOutputButton;
|
||||||
public LiveData<PendingTransaction> pendingTransaction = _pendingTransaction;
|
public LiveData<PendingTransaction> pendingTransaction = _pendingTransaction;
|
||||||
|
|
||||||
public void setSendingMax(boolean value) {
|
public void setSendingMax(boolean value) {
|
||||||
|
|
|
@ -24,13 +24,12 @@ import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
|
||||||
import net.mynero.wallet.MoneroApplication;
|
import net.mynero.wallet.MoneroApplication;
|
||||||
import net.mynero.wallet.R;
|
import net.mynero.wallet.R;
|
||||||
import net.mynero.wallet.data.DefaultNodes;
|
|
||||||
import net.mynero.wallet.data.Node;
|
import net.mynero.wallet.data.Node;
|
||||||
import net.mynero.wallet.fragment.dialog.AddNodeBottomSheetDialog;
|
import net.mynero.wallet.fragment.dialog.AddNodeBottomSheetDialog;
|
||||||
import net.mynero.wallet.fragment.dialog.EditNodeBottomSheetDialog;
|
import net.mynero.wallet.fragment.dialog.EditNodeBottomSheetDialog;
|
||||||
import net.mynero.wallet.fragment.dialog.WalletKeysBottomSheetDialog;
|
|
||||||
import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog;
|
import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog;
|
||||||
import net.mynero.wallet.fragment.dialog.PasswordBottomSheetDialog;
|
import net.mynero.wallet.fragment.dialog.PasswordBottomSheetDialog;
|
||||||
|
import net.mynero.wallet.fragment.dialog.WalletKeysBottomSheetDialog;
|
||||||
import net.mynero.wallet.model.Wallet;
|
import net.mynero.wallet.model.Wallet;
|
||||||
import net.mynero.wallet.model.WalletManager;
|
import net.mynero.wallet.model.WalletManager;
|
||||||
import net.mynero.wallet.service.BalanceService;
|
import net.mynero.wallet.service.BalanceService;
|
||||||
|
@ -38,8 +37,6 @@ import net.mynero.wallet.service.BlockchainService;
|
||||||
import net.mynero.wallet.service.HistoryService;
|
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.DayNightMode;
|
|
||||||
import net.mynero.wallet.util.NightmodeHelper;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
@ -60,7 +57,7 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia
|
||||||
public void afterTextChanged(Editable editable) {
|
public void afterTextChanged(Editable editable) {
|
||||||
if (mViewModel != null) {
|
if (mViewModel != null) {
|
||||||
mViewModel.setProxyAddress(editable.toString());
|
mViewModel.setProxyAddress(editable.toString());
|
||||||
mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication()));
|
mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -77,7 +74,7 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia
|
||||||
public void afterTextChanged(Editable editable) {
|
public void afterTextChanged(Editable editable) {
|
||||||
if (mViewModel != null) {
|
if (mViewModel != null) {
|
||||||
mViewModel.setProxyPort(editable.toString());
|
mViewModel.setProxyPort(editable.toString());
|
||||||
mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication()));
|
mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -155,7 +152,7 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia
|
||||||
proxySettingsLayout.setVisibility(View.GONE);
|
proxySettingsLayout.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication()));
|
mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication()));
|
||||||
});
|
});
|
||||||
|
|
||||||
displaySeedButton.setOnClickListener(view1 -> {
|
displaySeedButton.setOnClickListener(view1 -> {
|
||||||
|
@ -233,8 +230,8 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia
|
||||||
public void onNodeSelected() {
|
public void onNodeSelected() {
|
||||||
Node node = PrefService.getInstance().getNode();
|
Node node = PrefService.getInstance().getNode();
|
||||||
selectNodeButton.setText(getString(R.string.node_button_text, node.getAddress()));
|
selectNodeButton.setText(getString(R.string.node_button_text, node.getAddress()));
|
||||||
mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication()));
|
mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication()));
|
||||||
((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> {
|
((MoneroApplication) getActivity().getApplication()).getExecutor().execute(() -> {
|
||||||
WalletManager.getInstance().getWallet().init(0);
|
WalletManager.getInstance().getWallet().init(0);
|
||||||
WalletManager.getInstance().getWallet().startRefresh();
|
WalletManager.getInstance().getWallet().startRefresh();
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,6 @@ import android.util.Patterns;
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import net.mynero.wallet.MoneroApplication;
|
import net.mynero.wallet.MoneroApplication;
|
||||||
import net.mynero.wallet.data.DefaultNodes;
|
|
||||||
import net.mynero.wallet.data.Node;
|
import net.mynero.wallet.data.Node;
|
||||||
import net.mynero.wallet.model.WalletManager;
|
import net.mynero.wallet.model.WalletManager;
|
||||||
import net.mynero.wallet.service.PrefService;
|
import net.mynero.wallet.service.PrefService;
|
||||||
|
|
|
@ -92,16 +92,16 @@ public class TransactionFragment extends Fragment {
|
||||||
|
|
||||||
HistoryService.getInstance().history.observe(getViewLifecycleOwner(), transactionInfos -> {
|
HistoryService.getInstance().history.observe(getViewLifecycleOwner(), transactionInfos -> {
|
||||||
TransactionInfo newTransactionInfo = findNewestVersionOfTransaction(this.transactionInfo, transactionInfos);
|
TransactionInfo newTransactionInfo = findNewestVersionOfTransaction(this.transactionInfo, transactionInfos);
|
||||||
if(newTransactionInfo == null) return;
|
if (newTransactionInfo == null) return;
|
||||||
|
|
||||||
txHashTextView.setText(newTransactionInfo.hash);
|
txHashTextView.setText(newTransactionInfo.hash);
|
||||||
txConfTextView.setText("" + newTransactionInfo.confirmations);
|
txConfTextView.setText("" + newTransactionInfo.confirmations);
|
||||||
txDateTextView.setText(getDateTime(newTransactionInfo.timestamp));
|
txDateTextView.setText(getDateTime(newTransactionInfo.timestamp));
|
||||||
if(newTransactionInfo.confirmations > 1) {
|
if (newTransactionInfo.confirmations > 1) {
|
||||||
confLabel2.setText(getString(R.string.transaction_conf_desc2_confirmed));
|
confLabel2.setText(getString(R.string.transaction_conf_desc2_confirmed));
|
||||||
blockHeightTextView.setText("" + newTransactionInfo.blockheight);
|
blockHeightTextView.setText("" + newTransactionInfo.blockheight);
|
||||||
blockHeightTextView.setVisibility(View.VISIBLE);
|
blockHeightTextView.setVisibility(View.VISIBLE);
|
||||||
} else if(newTransactionInfo.confirmations == 1) {
|
} else if (newTransactionInfo.confirmations == 1) {
|
||||||
confLabel2.setText(getString(R.string.transaction_conf_1_desc2_confirmed));
|
confLabel2.setText(getString(R.string.transaction_conf_1_desc2_confirmed));
|
||||||
blockHeightTextView.setText("" + newTransactionInfo.blockheight);
|
blockHeightTextView.setText("" + newTransactionInfo.blockheight);
|
||||||
blockHeightTextView.setVisibility(View.VISIBLE);
|
blockHeightTextView.setVisibility(View.VISIBLE);
|
||||||
|
@ -111,7 +111,7 @@ public class TransactionFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 : Helper.getDisplayAmount(newTransactionInfo.amount, 12);
|
String balanceString = streetModeEnabled ? Constants.STREET_MODE_BALANCE : Helper.getDisplayAmount(newTransactionInfo.amount, 12);
|
||||||
if (newTransactionInfo.direction == TransactionInfo.Direction.Direction_In) {
|
if (newTransactionInfo.direction == TransactionInfo.Direction.Direction_In) {
|
||||||
|
@ -147,8 +147,8 @@ public class TransactionFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransactionInfo findNewestVersionOfTransaction(TransactionInfo oldTransactionInfo, List<TransactionInfo> transactionInfoList) {
|
private TransactionInfo findNewestVersionOfTransaction(TransactionInfo oldTransactionInfo, List<TransactionInfo> transactionInfoList) {
|
||||||
for(TransactionInfo transactionInfo : transactionInfoList) {
|
for (TransactionInfo transactionInfo : transactionInfoList) {
|
||||||
if(transactionInfo.hash.equals(oldTransactionInfo.hash)) {
|
if (transactionInfo.hash.equals(oldTransactionInfo.hash)) {
|
||||||
this.transactionInfo = transactionInfo;
|
this.transactionInfo = transactionInfo;
|
||||||
return this.transactionInfo;
|
return this.transactionInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
package net.mynero.wallet.fragment.transaction;
|
package net.mynero.wallet.fragment.transaction;
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import androidx.lifecycle.MutableLiveData;
|
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import net.mynero.wallet.model.TransactionInfo;
|
|
||||||
import net.mynero.wallet.model.Wallet;
|
|
||||||
import net.mynero.wallet.model.WalletManager;
|
|
||||||
|
|
||||||
public class TransactionViewModel extends ViewModel {
|
public class TransactionViewModel extends ViewModel {
|
||||||
}
|
}
|
|
@ -24,14 +24,12 @@ import net.mynero.wallet.util.MoneroThreadPoolExecutor;
|
||||||
import net.mynero.wallet.util.UriData;
|
import net.mynero.wallet.util.UriData;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInfoAdapterListener, SendBottomSheetDialog.Listener {
|
public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInfoAdapterListener, SendBottomSheetDialog.Listener {
|
||||||
|
|
||||||
private UtxosViewModel mViewModel;
|
|
||||||
private final CoinsInfoAdapter adapter = new CoinsInfoAdapter(this);
|
private final CoinsInfoAdapter adapter = new CoinsInfoAdapter(this);
|
||||||
|
private UtxosViewModel mViewModel;
|
||||||
private Button sendUtxosButton;
|
private Button sendUtxosButton;
|
||||||
private Button churnUtxosButton;
|
private Button churnUtxosButton;
|
||||||
private Button freezeUtxosButton;
|
private Button freezeUtxosButton;
|
||||||
|
@ -71,7 +69,7 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf
|
||||||
});
|
});
|
||||||
sendUtxosButton.setOnClickListener(view1 -> {
|
sendUtxosButton.setOnClickListener(view1 -> {
|
||||||
ArrayList<String> selectedKeyImages = new ArrayList<>();
|
ArrayList<String> selectedKeyImages = new ArrayList<>();
|
||||||
for(CoinsInfo coinsInfo : adapter.selectedUtxos.values()) {
|
for (CoinsInfo coinsInfo : adapter.selectedUtxos.values()) {
|
||||||
selectedKeyImages.add(coinsInfo.keyImage);
|
selectedKeyImages.add(coinsInfo.keyImage);
|
||||||
}
|
}
|
||||||
SendBottomSheetDialog sendDialog = new SendBottomSheetDialog();
|
SendBottomSheetDialog sendDialog = new SendBottomSheetDialog();
|
||||||
|
@ -81,7 +79,7 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf
|
||||||
});
|
});
|
||||||
churnUtxosButton.setOnClickListener(view1 -> {
|
churnUtxosButton.setOnClickListener(view1 -> {
|
||||||
ArrayList<String> selectedKeyImages = new ArrayList<>();
|
ArrayList<String> selectedKeyImages = new ArrayList<>();
|
||||||
for(CoinsInfo coinsInfo : adapter.selectedUtxos.values()) {
|
for (CoinsInfo coinsInfo : adapter.selectedUtxos.values()) {
|
||||||
selectedKeyImages.add(coinsInfo.keyImage);
|
selectedKeyImages.add(coinsInfo.keyImage);
|
||||||
}
|
}
|
||||||
SendBottomSheetDialog sendDialog = new SendBottomSheetDialog();
|
SendBottomSheetDialog sendDialog = new SendBottomSheetDialog();
|
||||||
|
@ -126,8 +124,8 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean frozenExists = false, unfrozenExists = false, bothExist = false;
|
boolean frozenExists = false, unfrozenExists = false, bothExist = false;
|
||||||
for(CoinsInfo selectedUtxo : adapter.selectedUtxos.values()) {
|
for (CoinsInfo selectedUtxo : adapter.selectedUtxos.values()) {
|
||||||
if(selectedUtxo.isFrozen() || UTXOService.getInstance().isCoinFrozen(selectedUtxo))
|
if (selectedUtxo.isFrozen() || UTXOService.getInstance().isCoinFrozen(selectedUtxo))
|
||||||
frozenExists = true;
|
frozenExists = true;
|
||||||
else {
|
else {
|
||||||
unfrozenExists = true;
|
unfrozenExists = true;
|
||||||
|
@ -141,7 +139,7 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf
|
||||||
freezeUtxosButton.setVisibility(View.GONE);
|
freezeUtxosButton.setVisibility(View.GONE);
|
||||||
freezeUtxosButton.setBackgroundResource(R.drawable.button_bg_left);
|
freezeUtxosButton.setBackgroundResource(R.drawable.button_bg_left);
|
||||||
} else {
|
} else {
|
||||||
if(frozenExists) {
|
if (frozenExists) {
|
||||||
freezeUtxosButton.setBackgroundResource(R.drawable.button_bg);
|
freezeUtxosButton.setBackgroundResource(R.drawable.button_bg);
|
||||||
sendUtxosButton.setVisibility(View.GONE);
|
sendUtxosButton.setVisibility(View.GONE);
|
||||||
churnUtxosButton.setVisibility(View.GONE);
|
churnUtxosButton.setVisibility(View.GONE);
|
||||||
|
@ -153,11 +151,11 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf
|
||||||
freezeUtxosButton.setVisibility(View.VISIBLE);
|
freezeUtxosButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bothExist) {
|
if (bothExist) {
|
||||||
freezeUtxosButton.setText(R.string.toggle_freeze);
|
freezeUtxosButton.setText(R.string.toggle_freeze);
|
||||||
} else if(frozenExists) {
|
} else if (frozenExists) {
|
||||||
freezeUtxosButton.setText(R.string.unfreeze);
|
freezeUtxosButton.setText(R.string.unfreeze);
|
||||||
} else if(unfrozenExists) {
|
} else if (unfrozenExists) {
|
||||||
freezeUtxosButton.setText(R.string.freeze);
|
freezeUtxosButton.setText(R.string.freeze);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||||
*/
|
*/
|
||||||
class SingleLiveEvent<T> : MutableLiveData<T>() {
|
class SingleLiveEvent<T> : MutableLiveData<T>() {
|
||||||
private val mPending = AtomicBoolean(false)
|
private val mPending = AtomicBoolean(false)
|
||||||
|
|
||||||
@MainThread
|
@MainThread
|
||||||
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
|
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
|
||||||
if (hasActiveObservers()) {
|
if (hasActiveObservers()) {
|
||||||
|
|
|
@ -23,18 +23,24 @@ class CoinsInfo : Parcelable, Comparable<CoinsInfo> {
|
||||||
@JvmField
|
@JvmField
|
||||||
var globalOutputIndex: Long
|
var globalOutputIndex: Long
|
||||||
var isSpent = false
|
var isSpent = false
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var keyImage: String? = null
|
var keyImage: String? = null
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var amount: Long = 0
|
var amount: Long = 0
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var hash: String? = null
|
var hash: String? = null
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var pubKey: String? = null
|
var pubKey: String? = null
|
||||||
var isUnlocked = false
|
var isUnlocked = false
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var localOutputIndex: Long = 0
|
var localOutputIndex: Long = 0
|
||||||
var isFrozen = false
|
var isFrozen = false
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var address: String? = null
|
var address: String? = null
|
||||||
|
|
||||||
|
@ -89,7 +95,7 @@ class CoinsInfo : Parcelable, Comparable<CoinsInfo> {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
val CREATOR: Creator<CoinsInfo?> = object : Creator<CoinsInfo?> {
|
val CREATOR: Creator<CoinsInfo?> = object : Creator<CoinsInfo?> {
|
||||||
override fun createFromParcel(`in`: Parcel): CoinsInfo? {
|
override fun createFromParcel(`in`: Parcel): CoinsInfo {
|
||||||
return CoinsInfo(`in`)
|
return CoinsInfo(`in`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package net.mynero.wallet.model
|
||||||
class PendingTransaction internal constructor(var handle: Long) {
|
class PendingTransaction internal constructor(var handle: Long) {
|
||||||
val status: Status
|
val status: Status
|
||||||
get() = Status.values()[getStatusJ()]
|
get() = Status.values()[getStatusJ()]
|
||||||
|
|
||||||
external fun getStatusJ(): Int
|
external fun getStatusJ(): Int
|
||||||
external fun getErrorString(): String?
|
external fun getErrorString(): String?
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ class PendingTransaction internal constructor(var handle: Long) {
|
||||||
external fun getFee(): Long
|
external fun getFee(): Long
|
||||||
val firstTxId: String
|
val firstTxId: String
|
||||||
get() = getFirstTxIdJ() ?: throw IndexOutOfBoundsException()
|
get() = getFirstTxIdJ() ?: throw IndexOutOfBoundsException()
|
||||||
|
|
||||||
external fun getFirstTxIdJ(): String?
|
external fun getFirstTxIdJ(): String?
|
||||||
external fun getTxCount(): Long
|
external fun getTxCount(): Long
|
||||||
|
|
||||||
|
|
|
@ -170,10 +170,6 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Direction fromInteger(int n) {
|
public static Direction fromInteger(int n) {
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -183,5 +179,9 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,6 +21,7 @@ import android.os.Parcelable.Creator
|
||||||
|
|
||||||
class Transfer : Parcelable {
|
class Transfer : Parcelable {
|
||||||
var amount: Long
|
var amount: Long
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var address: String?
|
var address: String?
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,7 @@ class Wallet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private external fun statusWithErrorString(): Status
|
private external fun statusWithErrorString(): Status
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
external fun setPassword(password: String?): Boolean
|
external fun setPassword(password: String?): Boolean
|
||||||
val address: String
|
val address: String
|
||||||
|
@ -126,6 +127,7 @@ class Wallet {
|
||||||
subaddress.amount = amount
|
subaddress.amount = amount
|
||||||
return subaddress
|
return subaddress
|
||||||
}
|
}
|
||||||
|
|
||||||
external fun getPath(): String?
|
external fun getPath(): String?
|
||||||
val networkType: NetworkType?
|
val networkType: NetworkType?
|
||||||
get() = fromInteger(nettype())
|
get() = fromInteger(nettype())
|
||||||
|
@ -217,6 +219,7 @@ class Wallet {
|
||||||
external fun getBalanceAll(): Long
|
external fun getBalanceAll(): Long
|
||||||
val unlockedBalance: Long
|
val unlockedBalance: Long
|
||||||
get() = getUnlockedBalance(accountIndex)
|
get() = getUnlockedBalance(accountIndex)
|
||||||
|
|
||||||
external fun getUnlockedBalanceAll(): Long
|
external fun getUnlockedBalanceAll(): Long
|
||||||
|
|
||||||
external fun getUnlockedBalance(accountIndex: Int): Long
|
external fun getUnlockedBalance(accountIndex: Int): Long
|
||||||
|
@ -349,6 +352,7 @@ class Wallet {
|
||||||
external fun setUserNote(txid: String?, note: String?): Boolean
|
external fun setUserNote(txid: String?, note: String?): Boolean
|
||||||
external fun getUserNote(txid: String?): String?
|
external fun getUserNote(txid: String?): String?
|
||||||
external fun getTxKey(txid: String?): String?
|
external fun getTxKey(txid: String?): String?
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
external fun addAccount(label: String? = NEW_ACCOUNT_NAME)
|
external fun addAccount(label: String? = NEW_ACCOUNT_NAME)
|
||||||
var accountLabel: String?
|
var accountLabel: String?
|
||||||
|
@ -428,6 +432,7 @@ class Wallet {
|
||||||
|
|
||||||
class Status internal constructor(status: Int, @JvmField val errorString: String) {
|
class Status internal constructor(status: Int, @JvmField val errorString: String) {
|
||||||
val status: StatusEnum
|
val status: StatusEnum
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var connectionStatus: ConnectionStatus? = null // optional
|
var connectionStatus: ConnectionStatus? = null // optional
|
||||||
|
|
||||||
|
@ -454,22 +459,30 @@ class Wallet {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun getDisplayAmount(amount: Long): String
|
external fun getDisplayAmount(amount: Long): String
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun getAmountFromString(amount: String?): Long
|
external fun getAmountFromString(amount: String?): Long
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun getAmountFromDouble(amount: Double): Long
|
external fun getAmountFromDouble(amount: Double): Long
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun generatePaymentId(): String
|
external fun generatePaymentId(): String
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun isPaymentIdValid(payment_id: String): Boolean
|
external fun isPaymentIdValid(payment_id: String): Boolean
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isAddressValid(address: String): Boolean {
|
fun isAddressValid(address: String): Boolean {
|
||||||
return instance?.networkType?.value?.let { isAddressValid(address, it) } == true
|
return instance?.networkType?.value?.let { isAddressValid(address, it) } == true
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun isAddressValid(address: String?, networkType: Int): Boolean
|
external fun isAddressValid(address: String?, networkType: Int): Boolean
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun getPaymentIdFromAddress(address: String?, networkType: Int): String?
|
external fun getPaymentIdFromAddress(address: String?, networkType: Int): String?
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun getMaximumAllowedAmount(): Long
|
external fun getMaximumAllowedAmount(): Long
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,7 +245,8 @@ class WalletManager {
|
||||||
fun findWallets(path: File): List<WalletInfo> {
|
fun findWallets(path: File): List<WalletInfo> {
|
||||||
val wallets: MutableList<WalletInfo> = ArrayList()
|
val wallets: MutableList<WalletInfo> = ArrayList()
|
||||||
Timber.d("Scanning: %s", path.absolutePath)
|
Timber.d("Scanning: %s", path.absolutePath)
|
||||||
val found = path.listFiles { dir, filename -> filename.endsWith(".keys") } ?: return emptyList()
|
val found =
|
||||||
|
path.listFiles { dir, filename -> filename.endsWith(".keys") } ?: return emptyList()
|
||||||
for (i in found.indices) {
|
for (i in found.indices) {
|
||||||
val filename = found[i].name
|
val filename = found[i].name
|
||||||
val f = File(
|
val f = File(
|
||||||
|
@ -354,16 +355,22 @@ class WalletManager {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun initLogger(argv0: String?, defaultLogBaseName: String?)
|
external fun initLogger(argv0: String?, defaultLogBaseName: String?)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun setLogLevel(level: Int)
|
external fun setLogLevel(level: Int)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun logDebug(category: String?, message: String?)
|
external fun logDebug(category: String?, message: String?)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun logInfo(category: String?, message: String?)
|
external fun logInfo(category: String?, message: String?)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun logWarning(category: String?, message: String?)
|
external fun logWarning(category: String?, message: String?)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun logError(category: String?, message: String?)
|
external fun logError(category: String?, message: String?)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun moneroVersion(): String?
|
external fun moneroVersion(): String?
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
package net.mynero.wallet.service;
|
package net.mynero.wallet.service;
|
||||||
|
|
||||||
import net.mynero.wallet.MoneroApplication;
|
|
||||||
import net.mynero.wallet.data.Subaddress;
|
import net.mynero.wallet.data.Subaddress;
|
||||||
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.model.WalletManager;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class AddressService extends ServiceBase {
|
public class AddressService extends ServiceBase {
|
||||||
|
|
|
@ -5,9 +5,6 @@ import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import net.mynero.wallet.model.BalanceInfo;
|
import net.mynero.wallet.model.BalanceInfo;
|
||||||
import net.mynero.wallet.model.CoinsInfo;
|
import net.mynero.wallet.model.CoinsInfo;
|
||||||
import net.mynero.wallet.model.Wallet;
|
|
||||||
import net.mynero.wallet.model.WalletManager;
|
|
||||||
import net.mynero.wallet.util.Constants;
|
|
||||||
|
|
||||||
public class BalanceService extends ServiceBase {
|
public class BalanceService extends ServiceBase {
|
||||||
public static BalanceService instance = null;
|
public static BalanceService instance = null;
|
||||||
|
@ -31,8 +28,8 @@ public class BalanceService extends ServiceBase {
|
||||||
|
|
||||||
public long getUnlockedBalanceRaw() {
|
public long getUnlockedBalanceRaw() {
|
||||||
long unlocked = 0;
|
long unlocked = 0;
|
||||||
for(CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) {
|
for (CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) {
|
||||||
if(!coinsInfo.isSpent() && !coinsInfo.isFrozen() && coinsInfo.isUnlocked() && !UTXOService.getInstance().isCoinFrozen(coinsInfo)) {
|
if (!coinsInfo.isSpent() && !coinsInfo.isFrozen() && coinsInfo.isUnlocked() && !UTXOService.getInstance().isCoinFrozen(coinsInfo)) {
|
||||||
unlocked += coinsInfo.amount;
|
unlocked += coinsInfo.amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,8 +38,8 @@ public class BalanceService extends ServiceBase {
|
||||||
|
|
||||||
public long getTotalBalanceRaw() {
|
public long getTotalBalanceRaw() {
|
||||||
long total = 0;
|
long total = 0;
|
||||||
for(CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) {
|
for (CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) {
|
||||||
if(!coinsInfo.isSpent() && !coinsInfo.isFrozen() && !UTXOService.getInstance().isCoinFrozen(coinsInfo)) {
|
if (!coinsInfo.isSpent() && !coinsInfo.isFrozen() && !UTXOService.getInstance().isCoinFrozen(coinsInfo)) {
|
||||||
total += coinsInfo.amount;
|
total += coinsInfo.amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
||||||
|
|
||||||
private void refresh(boolean walletSynced) {
|
private void refresh(boolean walletSynced) {
|
||||||
wallet.refreshHistory();
|
wallet.refreshHistory();
|
||||||
if(walletSynced) {
|
if (walletSynced) {
|
||||||
wallet.refreshCoins();
|
wallet.refreshCoins();
|
||||||
}
|
}
|
||||||
listener.onRefresh(walletSynced);
|
listener.onRefresh(walletSynced);
|
||||||
|
@ -136,7 +136,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
||||||
long totalAmount = 0;
|
long totalAmount = 0;
|
||||||
ArrayList<TransactionOutput> outputs = new ArrayList<>();
|
ArrayList<TransactionOutput> outputs = new ArrayList<>();
|
||||||
|
|
||||||
for(Pair<String, String> dest : dests) {
|
for (Pair<String, String> dest : dests) {
|
||||||
long amount = Wallet.getAmountFromString(dest.component2());
|
long amount = Wallet.getAmountFromString(dest.component2());
|
||||||
totalAmount += amount;
|
totalAmount += amount;
|
||||||
outputs.add(new TransactionOutput(dest.component1(), amount));
|
outputs.add(new TransactionOutput(dest.component1(), amount));
|
||||||
|
@ -150,7 +150,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
||||||
checkSelectedAmounts(preferredInputs, totalAmount, sendAll);
|
checkSelectedAmounts(preferredInputs, totalAmount, sendAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sendAll) {
|
if (sendAll) {
|
||||||
Pair<String, String> dest = dests.get(0);
|
Pair<String, String> dest = dests.get(0);
|
||||||
String address = dest.component1();
|
String address = dest.component1();
|
||||||
return wallet.createSweepTransaction(address, feePriority, preferredInputs);
|
return wallet.createSweepTransaction(address, feePriority, preferredInputs);
|
||||||
|
@ -165,7 +165,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
||||||
String paymentId = Wallet.getPaymentIdFromAddress(mainDestination.destination, WalletManager.getInstance().networkType.value);
|
String paymentId = Wallet.getPaymentIdFromAddress(mainDestination.destination, WalletManager.getInstance().networkType.value);
|
||||||
ArrayList<TransactionOutput> newOutputs = new ArrayList<>(outputs);
|
ArrayList<TransactionOutput> newOutputs = new ArrayList<>(outputs);
|
||||||
boolean donatePerTx = PrefService.getInstance().getBoolean(Constants.PREF_DONATE_PER_TX, false);
|
boolean donatePerTx = PrefService.getInstance().getBoolean(Constants.PREF_DONATE_PER_TX, false);
|
||||||
if(donatePerTx && paymentId.isEmpty()) { // only attach donation when no payment id is needed (i.e. integrated address)
|
if (donatePerTx && paymentId.isEmpty()) { // only attach donation when no payment id is needed (i.e. integrated address)
|
||||||
SecureRandom rand = new SecureRandom();
|
SecureRandom rand = new SecureRandom();
|
||||||
float randomDonatePct = getRandomDonateAmount(0.005f, 0.015f); // occasionally attaches a 0.5% to 1.5% donation. It is random so that not even I know how much exactly you are sending.
|
float randomDonatePct = getRandomDonateAmount(0.005f, 0.015f); // occasionally attaches a 0.5% to 1.5% donation. It is random so that not even I know how much exactly you are sending.
|
||||||
/*
|
/*
|
||||||
|
@ -173,14 +173,14 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
||||||
it will periodically split it up into multiple outputs instead of one.
|
it will periodically split it up into multiple outputs instead of one.
|
||||||
*/
|
*/
|
||||||
int attachDonationRoll = rand.nextInt(100);
|
int attachDonationRoll = rand.nextInt(100);
|
||||||
if(attachDonationRoll > 90) { // 10% chance of being added
|
if (attachDonationRoll > 90) { // 10% chance of being added
|
||||||
int splitDonationRoll = rand.nextInt(100);
|
int splitDonationRoll = rand.nextInt(100);
|
||||||
long donateAmount = (long) (amount*randomDonatePct);
|
long donateAmount = (long) (amount * randomDonatePct);
|
||||||
if(splitDonationRoll > 50) { // 50% chance of being split
|
if (splitDonationRoll > 50) { // 50% chance of being split
|
||||||
// split
|
// split
|
||||||
int split = genRandomDonationSplit(1, 4); // splits into at most 4 outputs, for a total of 6 outputs in the transaction (real dest + change. we don't add donations to send-all/sweep transactions)
|
int split = genRandomDonationSplit(1, 4); // splits into at most 4 outputs, for a total of 6 outputs in the transaction (real dest + change. we don't add donations to send-all/sweep transactions)
|
||||||
long splitAmount = donateAmount / split;
|
long splitAmount = donateAmount / split;
|
||||||
for(int i = 0; i < split; i++) {
|
for (int i = 0; i < split; i++) {
|
||||||
// TODO this can be expanded upon into the future to perform an auto-splitting/auto-churning for the user if their wallet is fresh and has few utxos.
|
// TODO this can be expanded upon into the future to perform an auto-splitting/auto-churning for the user if their wallet is fresh and has few utxos.
|
||||||
// randomly split between multiple wallets
|
// randomly split between multiple wallets
|
||||||
int randomDonationAddress = rand.nextInt(Constants.DONATION_ADDRESSES.length);
|
int randomDonationAddress = rand.nextInt(Constants.DONATION_ADDRESSES.length);
|
||||||
|
@ -232,6 +232,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void onRefresh(boolean walletSynced);
|
void onRefresh(boolean walletSynced);
|
||||||
|
|
||||||
void onConnectionFail();
|
void onConnectionFail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import net.mynero.wallet.data.DefaultNodes;
|
||||||
import net.mynero.wallet.data.Node;
|
import net.mynero.wallet.data.Node;
|
||||||
import net.mynero.wallet.util.Constants;
|
import net.mynero.wallet.util.Constants;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
@ -22,6 +21,10 @@ public class PrefService extends ServiceBase {
|
||||||
instance = this;
|
instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PrefService getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
public SharedPreferences.Editor edit() {
|
public SharedPreferences.Editor edit() {
|
||||||
return preferences.edit();
|
return preferences.edit();
|
||||||
}
|
}
|
||||||
|
@ -29,11 +32,11 @@ public class PrefService extends ServiceBase {
|
||||||
public Node getNode() {
|
public Node getNode() {
|
||||||
boolean usesProxy = getBoolean(Constants.PREF_USES_TOR, false);
|
boolean usesProxy = getBoolean(Constants.PREF_USES_TOR, false);
|
||||||
DefaultNodes defaultNode = DefaultNodes.SAMOURAI;
|
DefaultNodes defaultNode = DefaultNodes.SAMOURAI;
|
||||||
if(usesProxy) {
|
if (usesProxy) {
|
||||||
String proxyPort = getProxyPort();
|
String proxyPort = getProxyPort();
|
||||||
if (!proxyPort.isEmpty()) {
|
if (!proxyPort.isEmpty()) {
|
||||||
int port = Integer.parseInt(proxyPort);
|
int port = Integer.parseInt(proxyPort);
|
||||||
if(port == 4447) {
|
if (port == 4447) {
|
||||||
defaultNode = DefaultNodes.MYNERO_I2P;
|
defaultNode = DefaultNodes.MYNERO_I2P;
|
||||||
} else {
|
} else {
|
||||||
defaultNode = DefaultNodes.MYNERO_ONION;
|
defaultNode = DefaultNodes.MYNERO_ONION;
|
||||||
|
@ -51,9 +54,9 @@ public class PrefService extends ServiceBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node upgradeOldNode(String nodeString) {
|
private Node upgradeOldNode(String nodeString) {
|
||||||
if(!nodeString.isEmpty()) {
|
if (!nodeString.isEmpty()) {
|
||||||
Node node = Node.fromString(nodeString);
|
Node node = Node.fromString(nodeString);
|
||||||
if(node != null) {
|
if (node != null) {
|
||||||
edit().putString(Constants.PREF_NODE_2, node.toJson().toString()).apply();
|
edit().putString(Constants.PREF_NODE_2, node.toJson().toString()).apply();
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +91,7 @@ public class PrefService extends ServiceBase {
|
||||||
|
|
||||||
public String getString(String key, String defaultValue) {
|
public String getString(String key, String defaultValue) {
|
||||||
String value = preferences.getString(key, "");
|
String value = preferences.getString(key, "");
|
||||||
if(value.isEmpty() && !defaultValue.isEmpty()) {
|
if (value.isEmpty() && !defaultValue.isEmpty()) {
|
||||||
edit().putString(key, defaultValue).apply();
|
edit().putString(key, defaultValue).apply();
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
@ -98,14 +101,10 @@ public class PrefService extends ServiceBase {
|
||||||
public boolean getBoolean(String key, boolean defaultValue) {
|
public boolean getBoolean(String key, boolean defaultValue) {
|
||||||
boolean containsKey = preferences.contains(key);
|
boolean containsKey = preferences.contains(key);
|
||||||
boolean value = preferences.getBoolean(key, false);
|
boolean value = preferences.getBoolean(key, false);
|
||||||
if(!value && defaultValue && !containsKey) {
|
if (!value && defaultValue && !containsKey) {
|
||||||
edit().putBoolean(key, true).apply();
|
edit().putBoolean(key, true).apply();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrefService getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ 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 List<CoinsInfo> internalCachedUtxos = new ArrayList<>();
|
||||||
private ArrayList<String> frozenCoins = new ArrayList<>();
|
private ArrayList<String> frozenCoins = new ArrayList<>();
|
||||||
|
|
||||||
public UTXOService(MoneroHandlerThread thread) {
|
public UTXOService(MoneroHandlerThread thread) {
|
||||||
|
@ -56,8 +56,8 @@ public class UTXOService extends ServiceBase {
|
||||||
|
|
||||||
public void toggleFrozen(HashMap<String, CoinsInfo> selectedCoins) {
|
public void toggleFrozen(HashMap<String, CoinsInfo> selectedCoins) {
|
||||||
ArrayList<String> frozenCoinsCopy = new ArrayList<>(frozenCoins);
|
ArrayList<String> frozenCoinsCopy = new ArrayList<>(frozenCoins);
|
||||||
for(CoinsInfo coin : selectedCoins.values()) {
|
for (CoinsInfo coin : selectedCoins.values()) {
|
||||||
if(frozenCoinsCopy.contains(coin.pubKey)) {
|
if (frozenCoinsCopy.contains(coin.pubKey)) {
|
||||||
frozenCoinsCopy.remove(coin.pubKey);
|
frozenCoinsCopy.remove(coin.pubKey);
|
||||||
} else {
|
} else {
|
||||||
frozenCoinsCopy.add(coin.pubKey);
|
frozenCoinsCopy.add(coin.pubKey);
|
||||||
|
@ -77,7 +77,7 @@ public class UTXOService extends ServiceBase {
|
||||||
PrefService prefService = PrefService.getInstance();
|
PrefService prefService = PrefService.getInstance();
|
||||||
String frozenCoinsArrayString = prefService.getString(Constants.PREF_FROZEN_COINS, "[]");
|
String frozenCoinsArrayString = prefService.getString(Constants.PREF_FROZEN_COINS, "[]");
|
||||||
JSONArray frozenCoinsArray = new JSONArray(frozenCoinsArrayString);
|
JSONArray frozenCoinsArray = new JSONArray(frozenCoinsArrayString);
|
||||||
for(int i = 0; i < frozenCoinsArray.length(); i++) {
|
for (int i = 0; i < frozenCoinsArray.length(); i++) {
|
||||||
String pubKey = frozenCoinsArray.getString(i);
|
String pubKey = frozenCoinsArray.getString(i);
|
||||||
frozenCoins.add(pubKey);
|
frozenCoins.add(pubKey);
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ public class UTXOService extends ServiceBase {
|
||||||
PrefService prefService = PrefService.getInstance();
|
PrefService prefService = PrefService.getInstance();
|
||||||
JSONArray jsonArray = new JSONArray();
|
JSONArray jsonArray = new JSONArray();
|
||||||
ArrayList<String> frozenCoinsCopy = new ArrayList<>(frozenCoins);
|
ArrayList<String> frozenCoinsCopy = new ArrayList<>(frozenCoins);
|
||||||
for(String pubKey : frozenCoinsCopy) {
|
for (String pubKey : frozenCoinsCopy) {
|
||||||
jsonArray.put(pubKey);
|
jsonArray.put(pubKey);
|
||||||
}
|
}
|
||||||
prefService.edit().putString(Constants.PREF_FROZEN_COINS, jsonArray.toString()).apply();
|
prefService.edit().putString(Constants.PREF_FROZEN_COINS, jsonArray.toString()).apply();
|
||||||
|
|
|
@ -18,6 +18,7 @@ object Constants {
|
||||||
const val URI_ARG_AMOUNT2 = "amount"
|
const val URI_ARG_AMOUNT2 = "amount"
|
||||||
const val NAV_ARG_TXINFO = "nav_arg_txinfo"
|
const val NAV_ARG_TXINFO = "nav_arg_txinfo"
|
||||||
const val STREET_MODE_BALANCE = "#.############"
|
const val STREET_MODE_BALANCE = "#.############"
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val DONATION_ADDRESSES = arrayOf(
|
val DONATION_ADDRESSES = arrayOf(
|
||||||
"87BqQYkugEzh6Tuyotm2uc3DzJzKM6MuZaC161e6u1TsQxxPmXVPHpdNRyK47JY4d1hhbe25YVz4e9vTXCLDxvHkRXEAeBC", // primary Mysu Donation address
|
"87BqQYkugEzh6Tuyotm2uc3DzJzKM6MuZaC161e6u1TsQxxPmXVPHpdNRyK47JY4d1hhbe25YVz4e9vTXCLDxvHkRXEAeBC", // primary Mysu Donation address
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Date
|
||||||
object DateHelper {
|
object DateHelper {
|
||||||
@JvmField
|
@JvmField
|
||||||
val DATETIME_FORMATTER = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
val DATETIME_FORMATTER = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||||
|
|
||||||
@Throws(ParseException::class)
|
@Throws(ParseException::class)
|
||||||
fun parse(dateString: String): Date {
|
fun parse(dateString: String): Date {
|
||||||
return DATETIME_FORMATTER.parse(dateString.replace("Z$".toRegex(), "+0000"))
|
return DATETIME_FORMATTER.parse(dateString.replace("Z$".toRegex(), "+0000"))
|
||||||
|
|
|
@ -45,7 +45,6 @@ import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.BigInteger
|
|
||||||
import java.net.MalformedURLException
|
import java.net.MalformedURLException
|
||||||
import java.net.SocketTimeoutException
|
import java.net.SocketTimeoutException
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
@ -63,6 +62,7 @@ object Helper {
|
||||||
private const val MONERO_DIR = "monero"
|
private const val MONERO_DIR = "monero"
|
||||||
private val HexArray = "0123456789ABCDEF".toCharArray()
|
private val HexArray = "0123456789ABCDEF".toCharArray()
|
||||||
var ALLOW_SHIFT = false
|
var ALLOW_SHIFT = false
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var DISPLAY_DIGITS_INFO = 5
|
var DISPLAY_DIGITS_INFO = 5
|
||||||
private var ShakeAnimation: Animation? = null
|
private var ShakeAnimation: Animation? = null
|
||||||
|
|
|
@ -194,6 +194,7 @@ class RestoreHeight internal constructor() {
|
||||||
companion object {
|
companion object {
|
||||||
const val DIFFICULTY_TARGET = 120 // seconds
|
const val DIFFICULTY_TARGET = 120 // seconds
|
||||||
private var Singleton: RestoreHeight? = null
|
private var Singleton: RestoreHeight? = null
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val instance: RestoreHeight?
|
val instance: RestoreHeight?
|
||||||
get() {
|
get() {
|
||||||
|
|
|
@ -7,7 +7,8 @@ import net.mynero.wallet.model.WalletManager.Companion.instance
|
||||||
class UriData(@JvmField val address: String, val params: HashMap<String, String>) {
|
class UriData(@JvmField val address: String, val params: HashMap<String, String>) {
|
||||||
|
|
||||||
fun hasPaymentId(): Boolean {
|
fun hasPaymentId(): Boolean {
|
||||||
return instance?.wallet?.nettype()?.let { getPaymentIdFromAddress(address, it) }?.isNotEmpty() == true
|
return instance?.wallet?.nettype()?.let { getPaymentIdFromAddress(address, it) }
|
||||||
|
?.isNotEmpty() == true
|
||||||
}
|
}
|
||||||
|
|
||||||
val amount: String?
|
val amount: String?
|
||||||
|
@ -21,13 +22,13 @@ class UriData(@JvmField val address: String, val params: HashMap<String, String>
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun parse(uri: String): UriData? {
|
fun parse(uri: String): UriData? {
|
||||||
if(uri.isEmpty()) return null
|
if (uri.isEmpty()) return null
|
||||||
val params = HashMap<String, String>()
|
val params = HashMap<String, String>()
|
||||||
val uriParts = uri.replace(Constants.URI_PREFIX, "").split("\\?".toRegex())
|
val uriParts = uri.replace(Constants.URI_PREFIX, "").split("\\?".toRegex())
|
||||||
.dropLastWhile { it.isEmpty() }
|
.dropLastWhile { it.isEmpty() }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
|
|
||||||
if(uriParts.isEmpty()) return null
|
if (uriParts.isEmpty()) return null
|
||||||
val finalAddress = uriParts[0]
|
val finalAddress = uriParts[0]
|
||||||
var queryParams = ""
|
var queryParams = ""
|
||||||
if (uriParts.size > 1) {
|
if (uriParts.size > 1) {
|
||||||
|
|
Loading…
Reference in a new issue