Skip to content

Commit

Permalink
Merge pull request #30 from m2049r/feature_qr_amount
Browse files Browse the repository at this point in the history
QR scan of amount
  • Loading branch information
m2049r authored Aug 31, 2017
2 parents 20dbaac + 6822aa8 commit 7eaf17d
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 69 deletions.
2 changes: 1 addition & 1 deletion app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ void replaceFragment(Fragment newFragment, String stackName, Bundle extras) {
}

void popFragmentStack(String name) {
getFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}

//////////////////////////////////////////
Expand Down
37 changes: 9 additions & 28 deletions app/src/main/java/com/m2049r/xmrwallet/ScannerFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@

import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.BarcodeData;

import me.dm7.barcodescanner.zxing.ZXingScannerView;

Expand All @@ -39,9 +38,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
Listener activityCallback;

public interface Listener {
void onAddressScanned(String address, String paymentId);

boolean isPaymentIdValid(String paymentId);
boolean onAddressScanned(String uri);
}

private ZXingScannerView mScannerView;
Expand All @@ -61,32 +58,16 @@ public void onResume() {
mScannerView.startCamera();
}

static final String URI_PREFIX = "monero:";
static final String PAYMENTID_STRING = "?tx_payment_id=";
static final String QR_SCHEME = "monero:";
static final String QR_PAYMENTID = "tx_payment_id";
static final String QR_AMOUNT = "tx_amount";

@Override
public void handleResult(Result rawResult) {
Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
String text = rawResult.getText();
//Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
(text.startsWith(URI_PREFIX))) {
String address = null;
String paymentId = null;
String s = text.substring(URI_PREFIX.length());
if (s.length() == 95) {
address = s;
} else {
int i = s.indexOf(PAYMENTID_STRING);
if ((i == 95) && (s.length() == (95 + PAYMENTID_STRING.length() + 16))) {
address = s.substring(0, 95);
paymentId = s.substring(95 + PAYMENTID_STRING.length());
if (!activityCallback.isPaymentIdValid(paymentId)) {
address = null;
}
}
}
if (Helper.isAddressOk(address, WalletManager.getInstance().isTestNet())) {
activityCallback.onAddressScanned(address, paymentId);
(rawResult.getText().startsWith(QR_SCHEME))) {
if (activityCallback.onAddressScanned(rawResult.getText())) {
return;
} else {
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
Expand Down Expand Up @@ -120,7 +101,7 @@ public void onPause() {
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d(TAG, "attaching scan");
//Log.d(TAG, "attaching scan");
if (context instanceof Listener) {
this.activityCallback = (Listener) context;
} else {
Expand Down
30 changes: 22 additions & 8 deletions app/src/main/java/com/m2049r/xmrwallet/SendFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -373,26 +373,40 @@ public interface Listener {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
BarcodeData data = activityCallback.getScannedData();
if (data != null) {
String scannedAddress = data.address;
if (scannedAddress != null) {
etAddress.setText(scannedAddress);
} else {
etAddress.getText().clear();
}
String scannedPaymenId = data.paymentId;
if (scannedPaymenId != null) {
etPaymentId.setText(scannedPaymenId);
} else {
etPaymentId.getText().clear();
}
if (data.amount >= 0) {
String scannedAmount = Helper.getDisplayAmount(data.amount);
etAmount.setText(scannedAmount);
} else {
etAmount.getText().clear();
}
}
// jump to first empty field
if (etAddress.getText().toString().isEmpty()) {
etAddress.requestFocus();
} else if (etPaymentId.getText().toString().isEmpty()) {
etPaymentId.requestFocus();
} else {
etAmount.requestFocus();
etAmount.setSelection(etAmount.getText().length());
} else { // no scan data
// jump to first empty field
if (etAddress.getText().toString().isEmpty()) {
etAddress.requestFocus();
} else if (etPaymentId.getText().toString().isEmpty()) {
etPaymentId.requestFocus();
} else {
etAmount.requestFocus();
etAmount.setSelection(etAmount.getText().length());
}
}
Log.d(TAG, "onResume");
}

@Override
Expand Down
71 changes: 63 additions & 8 deletions app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.net.UrlQuerySanitizer;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
Expand All @@ -45,6 +47,9 @@
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.TxData;

import java.util.HashMap;
import java.util.Map;

public class WalletActivity extends AppCompatActivity implements WalletFragment.Listener,
WalletService.Observer, SendFragment.Listener, TxFragment.Listener,
GenerateReviewFragment.ListenerWithWallet,
Expand Down Expand Up @@ -563,7 +568,7 @@ public String generatePaymentId() {

@Override
public boolean isPaymentIdValid(String paymentId) {
return getWallet().isPaymentIdValid(paymentId);
return Wallet.isPaymentIdValid(paymentId);
}

@Override
Expand All @@ -573,9 +578,9 @@ public String getWalletAddress() {

void popFragmentStack(String name) {
if (name == null) {
getFragmentManager().popBackStack();
getSupportFragmentManager().popBackStack();
} else {
getFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}

Expand Down Expand Up @@ -626,12 +631,61 @@ public void onScanAddress() {
private BarcodeData scannedData = null;

@Override
public void onAddressScanned(String address, String paymentId) {
// Log.d(TAG, "got " + address);
scannedData = new BarcodeData(address, paymentId);
popFragmentStack(null);
public boolean onAddressScanned(String uri) {
BarcodeData bcData = parseMoneroUri(uri);
if (bcData != null) {
this.scannedData = bcData;
popFragmentStack(null);
return true;
} else {
return false;
}
}

/**
* Parse and decode a monero scheme string. It is here because it needs to validate the data.
*
* @param uri String containing a monero URL
* @return BarcodeData object or null if uri not valid
*/
public BarcodeData parseMoneroUri(String uri) {
if (uri == null) return null;

if (!uri.startsWith(ScannerFragment.QR_SCHEME)) return null;

String noScheme = uri.substring(ScannerFragment.QR_SCHEME.length());
Uri monero = Uri.parse(noScheme);
Map<String, String> parms = new HashMap<>();
String query = monero.getQuery();
if (query != null) {
String[] args = query.split("&");
for (String arg : args) {
String[] namevalue = arg.split("=");
if (namevalue.length == 0) {
continue;
}
parms.put(Uri.decode(namevalue[0]).toLowerCase(),
namevalue.length > 1 ? Uri.decode(namevalue[1]) : null);
}
}
String address = monero.getPath();
String paymentId = parms.get(ScannerFragment.QR_PAYMENTID);
String amountString = parms.get(ScannerFragment.QR_AMOUNT);
long amount = -1;
if (amountString != null) {
amount = Wallet.getAmountFromString(amountString);
}
if ((paymentId != null) && !Wallet.isPaymentIdValid(paymentId)) {
address = null;
}

if (Helper.isAddressOk(address, WalletManager.getInstance().isTestNet())) {
return new BarcodeData(address, paymentId, amount);
}
return null;
}


@Override
public BarcodeData getScannedData() {
BarcodeData data = scannedData;
Expand All @@ -640,7 +694,8 @@ public BarcodeData getScannedData() {
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
@NonNull int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult()");
switch (requestCode) {
case Helper.PERMISSIONS_REQUEST_CAMERA:
Expand Down
26 changes: 5 additions & 21 deletions app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.m2049r.xmrwallet.layout.TransactionInfoAdapter;
import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.util.Helper;

import java.text.NumberFormat;
import java.util.List;
Expand Down Expand Up @@ -62,9 +63,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
clProgress = (ConstraintLayout) view.findViewById(R.id.clProgress);
llUnconfirmedAmount = (LinearLayout) view.findViewById(R.id.llUnconfirmedAmount);
tvBalance = (TextView) view.findViewById(R.id.tvBalance);
tvBalance.setText(getDisplayAmount(0));
tvBalance.setText(Helper.getDisplayAmount(0));
tvUnconfirmedAmount = (TextView) view.findViewById(R.id.tvUnconfirmedAmount);
tvUnconfirmedAmount.setText(getDisplayAmount(0));
tvUnconfirmedAmount.setText(Helper.getDisplayAmount(0));
tvBlockHeightProgress = (TextView) view.findViewById(R.id.tvBlockHeightProgress);

bSend = (Button) view.findViewById(R.id.bSend);
Expand Down Expand Up @@ -168,23 +169,6 @@ String setActivityTitle(Wallet wallet) {
private long firstBlock = 0;
private String walletTitle = null;

private String getDisplayAmount(long amount) {
String s = Wallet.getDisplayAmount(amount);
int lastZero = 0;
int decimal = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if ((lastZero == 0) && (s.charAt(i) != '0')) lastZero = i + 1;
// TODO i18n
if (s.charAt(i) == '.') {
decimal = i;
break;
}
}
//Log.d(TAG, decimal + "/" + lastZero + "/" + s);
int cutoff = Math.max(lastZero, decimal + 2);
return s.substring(0, cutoff);
}

private void updateStatus(Wallet wallet) {
Log.d(TAG, "updateStatus()");
if (walletTitle == null) {
Expand All @@ -193,8 +177,8 @@ private void updateStatus(Wallet wallet) {
}
long balance = wallet.getBalance();
long unlockedBalance = wallet.getUnlockedBalance();
tvBalance.setText(getDisplayAmount(unlockedBalance));
tvUnconfirmedAmount.setText(getDisplayAmount(balance - unlockedBalance));
tvBalance.setText(Helper.getDisplayAmount(unlockedBalance));
tvUnconfirmedAmount.setText(Helper.getDisplayAmount(balance - unlockedBalance));
// balance cannot be less than unlockedBalance
/*if (balance != unlockedBalance) {
llPendingAmount.setVisibility(View.VISIBLE);
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/com/m2049r/xmrwallet/util/BarcodeData.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
public class BarcodeData {
public String address = null;
public String paymentId = null;
//String amount = null:
public long amount = -1;

public BarcodeData(String address, String paymentId) {
public BarcodeData(String address, String paymentId, long amount) {
this.address = address;
this.paymentId = paymentId;
this.amount = amount;
}
}
18 changes: 17 additions & 1 deletion app/src/main/java/com/m2049r/xmrwallet/util/Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import android.view.inputmethod.InputMethodManager;

import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;

import java.io.File;
Expand Down Expand Up @@ -135,5 +136,20 @@ static public boolean isAddressOk(String address, boolean testnet) {
return ((address.length() == 95) && ("4".indexOf(address.charAt(0)) >= 0));
}
}

static public String getDisplayAmount(long amount) {
String s = Wallet.getDisplayAmount(amount);
int lastZero = 0;
int decimal = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if ((lastZero == 0) && (s.charAt(i) != '0')) lastZero = i + 1;
// TODO i18n
if (s.charAt(i) == '.') {
decimal = i;
break;
}
}
//Log.d(TAG, decimal + "/" + lastZero + "/" + s);
int cutoff = Math.max(lastZero, decimal + 2);
return s.substring(0, cutoff);
}
}

0 comments on commit 7eaf17d

Please sign in to comment.