1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-04 17:28:42 +02:00

Compare commits

...

31 Commits
v0.5.1 ... v0.6

Author SHA1 Message Date
m2049r
093e4bda1d Doc & Version update (#43)
* added hint that amount is in XMR

* update FAQ and version
2017-09-04 23:29:48 +02:00
m2049r
4aa7000cb3 added hint that amount is in XMR (#42)
added hint that amount is in XMR when receiving
2017-09-04 23:27:04 +02:00
m2049r
62844192df Merge pull request #41 from m2049r/bugfix_logo
fixed logo svg
2017-09-04 23:21:29 +02:00
m2049r
855b35a6b7 added l in svg path 2017-09-04 22:52:10 +02:00
m2049r
88110b702f Merge pull request #40 from m2049r/bugfix_issue_37
request and respond to permissions marshmallow style
2017-09-04 22:32:30 +02:00
m2049r
0013caa05f request and respond to permissions marshmallow style 2017-09-04 22:30:37 +02:00
m2049r
5b3e92e91a Merge pull request #39 from m2049r/bugfix_issue_36
Use AsyncTask with 5MB stack in lots of places
2017-09-04 20:51:21 +02:00
m2049r
f8ea3cc77f use AsyncTask with 5MB stack in lots of places 2017-09-04 20:43:05 +02:00
m2049r
59ef2a1f8e Merge pull request #33 from KeeJef/master
Clarifying some Strings
2017-09-04 18:26:30 +02:00
m2049r
fae07ed716 Merge pull request #38 from m2049r/feature_rename_wallet
Rename/Backup/Archive Wallet FIles
2017-09-04 07:34:48 +02:00
m2049r
e662d5a9c0 wallet rename + tweaks 2017-09-04 07:26:04 +02:00
m2049r
4b2d52fbe6 wallet archive/backup progress dialogs 2017-09-03 21:29:15 +02:00
m2049r
ec7798cb34 wallet archive/backup 2017-09-03 14:09:27 +02:00
m2049r
20e7d6d065 rename option in wallet list + tweaks 2017-09-03 11:55:42 +02:00
m2049r
89ada5b294 Merge pull request #35 from m2049r/feature_info_alert
Alert before showing wallet details
2017-09-03 09:44:37 +02:00
m2049r
fe80fef36e alert before showing wallet details 2017-09-03 09:43:52 +02:00
m2049r
e8331dda7a Merge pull request #34 from m2049r/feature_qr_receive
QR Code for receiving
2017-09-02 12:56:17 +02:00
m2049r
68abaec6cb tweaks + get address from wallet (and not from file) 2017-09-02 12:51:57 +02:00
m2049r
fe84bae9ed rework options menus 2017-09-02 10:05:50 +02:00
KeeJef
1289a0ada4 Clarifying some Strings
Just for new people i think the amount when sending should indicate that the values are XMR not USD or something
2017-09-02 13:08:09 +10:00
m2049r
93025c5e1b Receive QR code 2017-09-02 00:00:54 +02:00
m2049r
e0439a1359 Merge pull request #32 from m2049r/bugfix_scanbutton
fix scan button enable/disable
2017-08-31 18:48:27 +02:00
m2049r
93ec3865da fix scan button enable/disable 2017-08-31 18:43:51 +02:00
m2049r
49e338e80d Merge pull request #31 from m2049r/doc
Update FAQ + version
2017-08-31 18:22:02 +02:00
m2049r
075ddff226 update FAQ + version 2017-08-31 18:19:59 +02:00
m2049r
7eaf17d48e Merge pull request #30 from m2049r/feature_qr_amount
QR scan of amount
2017-08-31 09:58:21 +02:00
m2049r
6822aa83d8 QR scan of amount as well
bugfix: use getSupportFragmentManager everywhere
2017-08-31 09:57:14 +02:00
m2049r
20dbaac4fa Merge pull request #29 from m2049r/bugfix_fragment_v4
use v4 fragment support library to cater for android 5.1
2017-08-31 01:00:52 +02:00
m2049r
726887af2e use v4 fragment support library to cater for android 5.1 2017-08-31 01:00:27 +02:00
m2049r
03da2880ac Merge pull request #28 from m2049r/bugfix_service_timing
make user wait for service to finish
2017-08-30 23:36:01 +02:00
m2049r
78c053f4e8 make user wait for service to finish 2017-08-30 23:35:16 +02:00
36 changed files with 1598 additions and 376 deletions

2
.idea/.gitignore generated vendored
View File

@@ -1,2 +1,2 @@
workspace.xml
markdown-navigator*
markdown-*

View File

@@ -21,7 +21,6 @@ You may loose all your Moneroj if you use this App. Be cautious when spending on
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
### TODO
- wallet backup functions
- review visibility of methods/classes
- more sensible error dialogs
- check licenses of included libraries; License Dialog

View File

@@ -7,8 +7,8 @@ android {
applicationId "com.m2049r.xmrwallet"
minSdkVersion 21
targetSdkVersion 25
versionCode 8
versionName "0.5.1"
versionCode 11
versionName "0.6"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {

View File

@@ -11,7 +11,7 @@
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="@drawable/ic_monero_32dp"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">

View File

@@ -461,7 +461,6 @@ Java_com_m2049r_xmrwallet_model_WalletManager_resolveOpenAlias(JNIEnv *env, jobj
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
// actually a WalletManager function, but logically in onWalletSelected
JNIEXPORT jboolean JNICALL
Java_com_m2049r_xmrwallet_model_WalletManager_closeJ(JNIEnv *env, jobject instance,
jobject walletInstance) {

View File

@@ -16,9 +16,9 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
@@ -69,12 +69,9 @@ public class GenerateFragment extends Fragment {
bGenerate = (Button) view.findViewById(R.id.bGenerate);
etWalletMnemonic.setRawInputType(InputType.TYPE_CLASS_TEXT);
etWalletAddress.setRawInputType(InputType.TYPE_CLASS_TEXT);
etWalletViewKey.setRawInputType(InputType.TYPE_CLASS_TEXT);
etWalletSpendKey.setRawInputType(InputType.TYPE_CLASS_TEXT);
boolean testnet = WalletManager.getInstance().isTestNet();
//etWalletMnemonic.setTextIsSelectable(testnet);
etWalletAddress.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etWalletViewKey.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etWalletSpendKey.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
Helper.showKeyboard(getActivity());
etWalletName.addTextChangedListener(new TextWatcher() {
@@ -298,8 +295,12 @@ public class GenerateFragment extends Fragment {
private void generateWallet() {
String name = etWalletName.getText().toString();
if (name.length() == 0) return;
String walletPath = Helper.getWalletPath(getActivity(), name);
if (WalletManager.getInstance().walletExists(walletPath)) {
if (name.charAt(0)=='.') {
Toast.makeText(getActivity(), getString(R.string.generate_wallet_dot), Toast.LENGTH_LONG).show();
etWalletName.requestFocus();
}
File walletFile = Helper.getWalletFile(getActivity(), name);
if (WalletManager.getInstance().walletExists(walletFile)) {
Toast.makeText(getActivity(), getString(R.string.generate_wallet_exists), Toast.LENGTH_LONG).show();
etWalletName.requestFocus();
return;
@@ -348,7 +349,7 @@ public class GenerateFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onPause()");
Log.d(TAG, "onResume()");
activityCallback.setTitle(getString(R.string.generate_title));
}

View File

@@ -16,9 +16,11 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -28,15 +30,13 @@ import android.widget.TextView;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.MoneroHandlerThread;
import java.io.File;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
public class GenerateReviewFragment extends Fragment {
static final String TAG = "GenerateReviewFragment";
static final public String VIEW_DETAILS = "details";
static final public String VIEW_ACCEPT = "accept";
static final public String VIEW_WALLET = "wallet";
static final public String VIEW_TYPE_DETAILS = "details";
static final public String VIEW_TYPE_ACCEPT = "accept";
static final public String VIEW_TYPE_WALLET = "wallet";
ProgressBar pbProgress;
TextView tvWalletName;
@@ -76,16 +76,12 @@ public class GenerateReviewFragment extends Fragment {
showProgress();
Bundle b = getArguments();
String type = b.getString("type");
if (!type.equals(VIEW_WALLET)) {
String name = b.getString("name");
String password = b.getString("password");
tvWalletName.setText(new File(name).getName());
show(name, password, type);
} else {
show(walletCallback.getWallet(), null, type);
}
Bundle args = getArguments();
String path = args.getString("path");
String password = args.getString("password");
String type = args.getString("type");
new AsyncShow().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR,
path, password, type);
return view;
}
@@ -96,40 +92,64 @@ public class GenerateReviewFragment extends Fragment {
acceptCallback.onAccept(name, password);
}
private void show(final String walletPath, final String password, final String type) {
new Thread(null,
new Runnable() {
@Override
public void run() {
final Wallet wallet = WalletManager.getInstance().openWallet(walletPath, password);
getActivity().runOnUiThread(new Runnable() {
public void run() {
show(wallet, password, type);
wallet.close();
}
});
}
}
, "DetailsReview", MoneroHandlerThread.THREAD_STACK_SIZE).start();
}
private class AsyncShow extends AsyncTask<String, Void, Boolean> {
String type;
String password;
private void show(final Wallet wallet, final String password, final String type) {
if (type.equals(GenerateReviewFragment.VIEW_ACCEPT)) {
tvWalletPassword.setText(password);
bAccept.setVisibility(View.VISIBLE);
bAccept.setEnabled(true);
String name;
String address;
String seed;
String viewKey;
boolean isWatchOnly;
@Override
protected Boolean doInBackground(String... params) {
if (params.length != 3) return false;
String walletPath = params[0];
password = params[1];
type = params[2];
Wallet wallet;
boolean closeWallet;
if (type.equals(GenerateReviewFragment.VIEW_TYPE_WALLET)) {
wallet = GenerateReviewFragment.this.walletCallback.getWallet();
closeWallet = false;
} else {
wallet = WalletManager.getInstance().openWallet(walletPath, password);
closeWallet = true;
}
if (wallet.getStatus() != Wallet.Status.Status_Ok) return false;
name = wallet.getName();
address = wallet.getAddress();
seed = wallet.getSeed();
viewKey = wallet.getSecretViewKey();
isWatchOnly = wallet.isWatchOnly();
if (closeWallet) wallet.close();
return true;
}
tvWalletName.setText(wallet.getName());
tvWalletAddress.setText(wallet.getAddress());
tvWalletMnemonic.setText(wallet.getSeed());
tvWalletViewKey.setText(wallet.getSecretViewKey());
String spend = wallet.isWatchOnly() ? "" : "not available - use seed for recovery";
if (spend.length() > 0) { //TODO should be == 64, but spendkey is not in the API yet
tvWalletSpendKey.setText(spend);
} else {
tvWalletSpendKey.setText(getString(R.string.generate_wallet_watchonly));
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result) {
if (type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT)) {
tvWalletPassword.setText(password);
bAccept.setVisibility(View.VISIBLE);
bAccept.setEnabled(true);
}
tvWalletName.setText(name);
tvWalletAddress.setText(address);
tvWalletMnemonic.setText(seed);
tvWalletViewKey.setText(viewKey);
String spend = isWatchOnly ? "" : "not available - use seed for recovery";
if (spend.length() > 0) { //TODO should be == 64, but spendkey is not in the API yet
tvWalletSpendKey.setText(spend);
} else {
tvWalletSpendKey.setText(getString(R.string.generate_wallet_watchonly));
}
}
hideProgress();
}
hideProgress();
}
GenerateReviewFragment.Listener acceptCallback = null;
@@ -141,6 +161,7 @@ public class GenerateReviewFragment extends Fragment {
public interface ListenerWithWallet {
Wallet getWallet();
}
@Override

File diff suppressed because it is too large Load Diff

View File

@@ -16,12 +16,13 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
@@ -82,9 +83,17 @@ public class LoginFragment extends Fragment {
File getStorageRoot();
void onWalletSelected(final String wallet);
void onWalletSelected(String wallet);
void onWalletDetails(final String wallet);
void onWalletDetails(String wallet);
void onWalletReceive(String wallet);
void onWalletRename(String name);
void onWalletBackup(String name);
void onWalletArchive(String walletName);
void onAddWallet();
@@ -117,14 +126,14 @@ public class LoginFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onPause()");
Log.d(TAG, "onResume()");
activityCallback.setTitle(getString(R.string.login_activity_name));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.login_fragment, container, false);
tbMainNet = (ToggleButton) view.findViewById(R.id.tbMainNet);
@@ -222,31 +231,6 @@ public class LoginFragment extends Fragment {
}
});
/* listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// Difference to opening wallet is that we don't need a daemon set
String itemValue = (String) listView.getItemAtPosition(position);
if (itemValue.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
return true;
}
String wallet = itemValue.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = isMainNet() ? "4" : "9A";
if (x.indexOf(itemValue.charAt(1)) < 0) {
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
return true;
}
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(wallet);
return true;
}
});
*/
loadList();
return view;
}
@@ -260,7 +244,8 @@ public class LoginFragment extends Fragment {
}
}
private void loadList() {
public void loadList() {
Log.d(TAG, "loadList()");
WalletManager mgr = WalletManager.getInstance();
List<WalletManager.WalletInfo> walletInfos =
mgr.findWallets(activityCallback.getStorageRoot());
@@ -408,32 +393,52 @@ public class LoginFragment extends Fragment {
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
String listItem = (String) listView.getItemAtPosition(info.position);
String name = nameFromListItem(listItem, !isMainNet());
if (name == null) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
}
switch (item.getItemId()) {
case R.id.action_info:
String listItem = (String) listView.getItemAtPosition(info.position);
return showInfo(listItem);
showInfo(name);
break;
case R.id.action_receive:
showReceive(name);
break;
case R.id.action_rename:
activityCallback.onWalletRename(name);
break;
case R.id.action_backup:
activityCallback.onWalletBackup(name);
break;
case R.id.action_archive:
activityCallback.onWalletArchive(name);
break;
default:
return super.onContextItemSelected(item);
}
}
private boolean showInfo(String listItem) {
if (listItem.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
return true;
}
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = isMainNet() ? "4" : "9A";
if (x.indexOf(listItem.charAt(1)) < 0) {
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
return true;
}
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(wallet);
return true;
}
private void showInfo(@NonNull String name) {
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(name);
}
private boolean showReceive(@NonNull String name) {
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletReceive(name);
return true;
}
private String nameFromListItem(String listItem, boolean testnet) {
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = testnet ? "9A" : "4";
if (x.indexOf(listItem.charAt(1)) < 0) {
return null;
}
return wallet;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,10 +16,10 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -28,8 +28,7 @@ import android.widget.Toast;
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;
@@ -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;
@@ -61,32 +58,16 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
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();
@@ -120,7 +101,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
@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 {

View File

@@ -16,11 +16,11 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.InputType;
@@ -51,7 +51,7 @@ public class SendFragment extends Fragment {
EditText etAddress;
EditText etPaymentId;
EditText etAmount;
Button bAddress;
Button bScan;
Button bSweep;
Spinner sMixin;
Spinner sPriority;
@@ -84,7 +84,7 @@ public class SendFragment extends Fragment {
etAddress = (EditText) view.findViewById(R.id.etAddress);
etPaymentId = (EditText) view.findViewById(R.id.etPaymentId);
etAmount = (EditText) view.findViewById(R.id.etAmount);
bAddress = (Button) view.findViewById(R.id.bAddress);
bScan = (Button) view.findViewById(R.id.bScan);
bSweep = (Button) view.findViewById(R.id.bSweep);
bPrepareSend = (Button) view.findViewById(R.id.bPrepareSend);
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
@@ -100,8 +100,8 @@ public class SendFragment extends Fragment {
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
etAddress.setRawInputType(InputType.TYPE_CLASS_TEXT);
etPaymentId.setRawInputType(InputType.TYPE_CLASS_TEXT);
etAddress.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etPaymentId.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
Helper.showKeyboard(getActivity());
@@ -199,7 +199,7 @@ public class SendFragment extends Fragment {
}
});
bAddress.setOnClickListener(new View.OnClickListener() {
bScan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
activityCallback.onScanAddress();
@@ -209,7 +209,8 @@ public class SendFragment extends Fragment {
bPaymentId.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
etPaymentId.setText((activityCallback.generatePaymentId()));
etPaymentId.setText((Wallet.generatePaymentId()));
etPaymentId.setSelection(etPaymentId.getText().length());
}
});
@@ -285,7 +286,7 @@ public class SendFragment extends Fragment {
private boolean paymentIdOk() {
String paymentId = etPaymentId.getText().toString();
return paymentId.isEmpty() || activityCallback.isPaymentIdValid(paymentId);
return paymentId.isEmpty() || Wallet.isPaymentIdValid(paymentId);
}
private void prepareSend() {
@@ -321,6 +322,7 @@ public class SendFragment extends Fragment {
etAddress.setEnabled(false);
etPaymentId.setEnabled(false);
etAmount.setEnabled(false);
bScan.setEnabled(false);
bPaymentId.setEnabled(false);
bSweep.setEnabled(false);
bPrepareSend.setEnabled(false);
@@ -332,6 +334,7 @@ public class SendFragment extends Fragment {
etAddress.setEnabled(true);
etPaymentId.setEnabled(true);
etAmount.setEnabled(true);
bScan.setEnabled(true);
bPaymentId.setEnabled(true);
bSweep.setEnabled(true);
bPrepareSend.setEnabled(true);
@@ -356,10 +359,6 @@ public class SendFragment extends Fragment {
void onSend(String notes);
String generatePaymentId();
boolean isPaymentIdValid(String paymentId);
String getWalletAddress();
void onDisposeRequest();
@@ -373,26 +372,40 @@ public class SendFragment extends Fragment {
@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();
}
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());
}
}
// jump to first empty field
if (etAddress.getText().toString().isEmpty()) {
etAddress.requestFocus();
} else if (etPaymentId.getText().toString().isEmpty()) {
etPaymentId.requestFocus();
} else {
etAmount.requestFocus();
}
Log.d(TAG, "onResume");
}
@Override

View File

@@ -16,28 +16,23 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Transfer;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.MoneroHandlerThread;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

File diff suppressed because it is too large Load Diff

View File

@@ -16,21 +16,20 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.v7.app.AlertDialog;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -38,9 +37,8 @@ import android.widget.TextView;
import com.m2049r.xmrwallet.layout.TransactionInfoAdapter;
import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Transfer;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import java.text.NumberFormat;
import java.util.List;
@@ -59,6 +57,19 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
ProgressBar pbProgress;
Button bSend;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (activityCallback.hasWallet())
inflater.inflate(R.menu.wallet_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -69,9 +80,9 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
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);
@@ -175,23 +186,6 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
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) {
@@ -200,8 +194,8 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
}
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);
@@ -259,6 +253,10 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
boolean isWatchOnly();
String getTxKey(String txId);
void onWalletReceive();
boolean hasWallet();
}
@Override

View File

@@ -238,6 +238,7 @@ public class Wallet {
public native void setDefaultMixin(int mixin);
public native boolean setUserNote(String txid, String note);
public native String getUserNote(String txid);
public native String getTxKey(String txid);

View File

@@ -71,8 +71,8 @@ public class WalletManager {
managedWallets.remove(walletId);
}
public Wallet createWallet(String path, String password, String language) {
long walletHandle = createWalletJ(path, password, language, isTestNet());
public Wallet createWallet(File aFile, String password, String language) {
long walletHandle = createWalletJ(aFile.getAbsolutePath(), password, language, isTestNet());
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet.getName(), wallet);
return wallet;
@@ -89,14 +89,14 @@ public class WalletManager {
private native long openWalletJ(String path, String password, boolean isTestNet);
public Wallet recoveryWallet(String path, String mnemonic) {
Wallet wallet = recoveryWallet(path, mnemonic, 0);
public Wallet recoveryWallet(File aFile, String mnemonic) {
Wallet wallet = recoveryWallet(aFile, mnemonic, 0);
manageWallet(wallet.getName(), wallet);
return wallet;
}
public Wallet recoveryWallet(String path, String mnemonic, long restoreHeight) {
long walletHandle = recoveryWalletJ(path, mnemonic, isTestNet(), restoreHeight);
public Wallet recoveryWallet(File aFile, String mnemonic, long restoreHeight) {
long walletHandle = recoveryWalletJ(aFile.getAbsolutePath(), mnemonic, isTestNet(), restoreHeight);
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet.getName(), wallet);
return wallet;
@@ -104,9 +104,9 @@ public class WalletManager {
private native long recoveryWalletJ(String path, String mnemonic, boolean isTestNet, long restoreHeight);
public Wallet createWalletFromKeys(String path, String language, long restoreHeight,
public Wallet createWalletFromKeys(File aFile, String language, long restoreHeight,
String addressString, String viewKeyString, String spendKeyString) {
long walletHandle = createWalletFromKeysJ(path, language, isTestNet(), restoreHeight,
long walletHandle = createWalletFromKeysJ(aFile.getAbsolutePath(), language, isTestNet(), restoreHeight,
addressString, viewKeyString, spendKeyString);
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet.getName(), wallet);
@@ -134,6 +134,10 @@ public class WalletManager {
return closed;
}
public boolean walletExists(File aFile) {
return walletExists(aFile.getAbsolutePath());
}
public native boolean walletExists(String path);
public native boolean verifyWalletPassword(String keys_file_name, String password, boolean watch_only);
@@ -146,6 +150,31 @@ public class WalletManager {
public String address;
}
public WalletInfo getWalletInfo(File wallet) {
WalletInfo info = new WalletInfo();
info.path = wallet.getParentFile();
info.name = wallet.getName();
File addressFile = new File(info.path, info.name + ".address.txt");
//Log.d(TAG, addressFile.getAbsolutePath());
info.address = "??????";
BufferedReader addressReader = null;
try {
addressReader = new BufferedReader(new FileReader(addressFile));
info.address = addressReader.readLine();
} catch (IOException ex) {
Log.d(TAG, ex.getLocalizedMessage());
} finally {
if (addressReader != null) {
try {
addressReader.close();
} catch (IOException ex) {
// that's just too bad
}
}
}
return info;
}
public List<WalletInfo> findWallets(File path) {
List<WalletInfo> wallets = new ArrayList<>();
Log.d(TAG, "Scanning: " + path.getAbsolutePath());
@@ -155,29 +184,9 @@ public class WalletManager {
}
});
for (int i = 0; i < found.length; i++) {
WalletInfo info = new WalletInfo();
info.path = path;
String filename = found[i].getName();
info.name = filename.substring(0, filename.length() - 5); // 5 is length of ".keys"+1
File addressFile = new File(path, info.name + ".address.txt");
//Log.d(TAG, addressFile.getAbsolutePath());
info.address = "??????";
BufferedReader addressReader = null;
try {
addressReader = new BufferedReader(new FileReader(addressFile));
info.address = addressReader.readLine();
} catch (IOException ex) {
Log.d(TAG, ex.getLocalizedMessage());
} finally {
if (addressReader != null) {
try {
addressReader.close();
} catch (IOException ex) {
// that's just too bad
}
}
}
wallets.add(info);
File f = new File(found[i].getParent(), filename.substring(0, filename.length() - 5)); // 5 is length of ".keys"+1
wallets.add(getWalletInfo(f));
}
return wallets;
}

View File

@@ -19,10 +19,7 @@ package com.m2049r.xmrwallet.service;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -30,13 +27,11 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.WalletActivity;
import com.m2049r.xmrwallet.model.PendingTransaction;
import com.m2049r.xmrwallet.model.TransactionHistory;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletListener;
import com.m2049r.xmrwallet.model.WalletManager;
@@ -44,6 +39,8 @@ import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.TxData;
public class WalletService extends Service {
public static boolean Running = false;
final static String TAG = "WalletService";
final static int NOTIFICATION_ID = 2049;
@@ -400,9 +397,6 @@ public class WalletService extends Service {
@Override
public void onCreate() {
//mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//showNotification();
// We are using a HandlerThread and a Looper to avoid loading and closing
// concurrency
MoneroHandlerThread thread = new MoneroHandlerThread("WalletService",
@@ -419,8 +413,6 @@ public class WalletService extends Service {
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
// Cancel the persistent notification.
//mNM.cancel(NOTIFICATION);
if (this.listener != null) {
Log.w(TAG, "onDestroy() with active listener");
// no need to stop() here because the wallet closing should have been triggered
@@ -438,7 +430,8 @@ public class WalletService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// when the activity satrts the service, it expects to start it for a new wallet
Running = true;
// when the activity starts the service, it expects to start it for a new wallet
// the service is possibly still occupied with saving the last opened wallet
// so we queue the open request
// this should not matter since the old activity is not getting updates
@@ -514,6 +507,7 @@ public class WalletService extends Service {
}
stopForeground(true);
stopSelf();
Running = false;
}
private Wallet loadWallet(String walletName, String walletPassword) {
@@ -533,7 +527,7 @@ public class WalletService extends Service {
}
private Wallet openWallet(String walletName, String walletPassword) {
String path = Helper.getWalletPath(getApplicationContext(), walletName);
String path = Helper.getWalletFile(getApplicationContext(), walletName).getAbsolutePath();
showProgress(20);
Wallet wallet = null;
WalletManager walletMgr = WalletManager.getInstance();
@@ -563,7 +557,7 @@ public class WalletService extends Service {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new Notification.Builder(this)
.setContentTitle(getString(R.string.service_description))
.setSmallIcon(R.drawable.ic_notification_sync_32_32)
.setSmallIcon(R.drawable.ic_monero_32dp)
.setContentIntent(pendingIntent)
.build();
startForeground(NOTIFICATION_ID, notification);

View File

@@ -19,10 +19,11 @@ package com.m2049r.xmrwallet.util;
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;
}
}

View File

@@ -21,12 +21,20 @@ import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.os.Environment;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.WindowManager;
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;
@@ -90,12 +98,16 @@ public class Helper {
}
}
static public String getWalletPath(Context context, String aWalletName) {
// static public String getWalletPath(Context context, String aWalletName) {
// return getWalletFile(context, aWalletName).getAbsolutePath();
// }
static public File getWalletFile(Context context, String aWalletName) {
File walletDir = getStorageRoot(context);
//d(TAG, "walletdir=" + walletDir.getAbsolutePath());
File f = new File(walletDir, aWalletName);
Log.d(TAG, "wallet = " + f.getAbsolutePath() + " size=" + f.length());
return f.getAbsolutePath();
return f;
}
/* Checks if external storage is available for read and write */
@@ -136,4 +148,41 @@ public class Helper {
}
}
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);
}
public static Bitmap getBitmap(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (drawable instanceof BitmapDrawable) {
return BitmapFactory.decodeResource(context.getResources(), drawableId);
} else if (drawable instanceof VectorDrawable) {
return getBitmap((VectorDrawable) drawable);
} else {
throw new IllegalArgumentException("unsupported drawable type");
}
}
private static Bitmap getBitmap(VectorDrawable vectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
return bitmap;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2017 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet.util;
import com.m2049r.xmrwallet.service.MoneroHandlerThread;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class MoneroThreadPoolExecutor {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(null, r, "MoneroTask #" + mCount.getAndIncrement(), MoneroHandlerThread.THREAD_STACK_SIZE);
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<>(128);
public static final Executor MONERO_THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
MONERO_THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
}

View File

@@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="75.0"
android:viewportWidth="75.0">
<path
android:fillColor="#ff6600"
android:pathData="M 37.3,0.35329395 c -20.377,0 -36.903,16.524 -36.903,36.902 0,4.074 0.66,7.992 1.88,11.657 l 11.036,0 0,-31.049 23.987,23.987 23.987,-23.987 0,31.049 11.037,0 c 1.22,-3.665 1.88,-7.583 1.88,-11.657 0,-20.378 -16.526,-36.902 -36.904,-36.902" />
<path
android:fillColor="#4c4c4c"
android:pathData="M 21.3164,36.895994 l 0,19.537 -15.55,0 c 6.478,10.628 18.178,17.726 31.533,17.726 13.355,0 25.056,-7.098 31.533,-17.726 l -15.549,0 0,-19.537 -15.984,15.984 z" />
</vector>

View File

@@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportHeight="75.0"
android:viewportWidth="75.0">
<path
android:fillColor="#ffffff"
android:pathData=" M 37.3, 37.3
m -36.9, 0
a 36.9,36.9 0 1,0 73.8,0
a 36.9,36.9 0 1,0 -73.8,0" />
<path
android:fillColor="#ff6600"
android:pathData="M 37.3,0.35329395 c -20.377,0 -36.903,16.524 -36.903,36.902 0,4.074 0.66,7.992 1.88,11.657 l 11.036,0 0,-31.049 23.987,23.987 23.987,-23.987 0,31.049 11.037,0 c 1.22,-3.665 1.88,-7.583 1.88,-11.657 0,-20.378 -16.526,-36.902 -36.904,-36.902" />
<path
android:fillColor="#4c4c4c"
android:pathData="M 21.3164,36.895994 l 0,19.537 -15.55,0 c 6.478,10.628 18.178,17.726 31.533,17.726 13.355,0 25.056,-7.098 31.533,-17.726 l -15.549,0 0,-19.537 -15.984,15.984 z" />
</vector>

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -4,19 +4,13 @@
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
<ProgressBar
android:id="@+id/pbProgress"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8sp"
android:orientation="vertical">
<ProgressBar
android:id="@+id/pbProgress"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible" />
</LinearLayout>
android:visibility="invisible" />
<LinearLayout
android:layout_width="match_parent"
@@ -143,7 +137,6 @@
android:id="@+id/tvWalletSpendKey"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:selectAllOnFocus="true"
android:textAlignment="center"
android:textColor="@color/colorPrimaryDark"
android:textIsSelectable="true"

View File

@@ -4,14 +4,14 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp" >
android:padding="10dp">
<TextView
android:id="@+id/tvPasswordLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wallet Password"
android:labelFor="@+id/etPassword"
android:text="@string/prompt_password"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
@@ -19,7 +19,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="normal"
android:inputType="textPassword" >
android:inputType="textPassword">
</EditText>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="@+id/tvRenameLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/prompt_rename"
android:labelFor="@+id/etRename"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="@+id/etRename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="normal"
android:inputType="text" />
</LinearLayout>

View File

@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ProgressBar
android:id="@+id/pbProgress"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8sp"
android:visibility="gone" />
<TextView
android:id="@+id/tvAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4sp"
android:layout_marginTop="4sp"
android:textIsSelectable="true"
android:selectAllOnFocus="true"
android:hint="@string/send_address_hint"
android:textAlignment="center"
android:textSize="16sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4sp"
android:layout_marginTop="4sp"
android:orientation="horizontal"
android:weightSum="10">
<TextView
android:layout_width="0sp"
android:layout_height="wrap_content"
android:layout_marginRight="8sp"
android:layout_weight="3"
android:text="@string/receive_paymentid_label"
android:textAlignment="textEnd"
android:textSize="16sp" />
<EditText
android:id="@+id/etPaymentId"
android:layout_width="0sp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:enabled="false"
android:hint="@string/receive_paymentid_hint"
android:imeOptions="actionNext"
android:inputType="textMultiLine"
android:textAlignment="textStart"
android:textSize="16sp" />
<Button
android:id="@+id/bPaymentId"
android:layout_width="0sp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="2"
android:background="@color/colorPrimary"
android:enabled="false"
android:minHeight="36sp"
android:text="@string/receive_paymentid_button"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4sp"
android:layout_marginTop="4sp"
android:orientation="horizontal"
android:weightSum="10">
<TextView
android:layout_width="0sp"
android:layout_height="wrap_content"
android:layout_marginRight="8sp"
android:layout_weight="3"
android:text="@string/send_amount_label"
android:textAlignment="textEnd"
android:textSize="24sp" />
<EditText
android:id="@+id/etAmount"
android:layout_width="0sp"
android:layout_height="wrap_content"
android:layout_weight="7"
android:enabled="false"
android:hint="@string/receive_amount_hint"
android:imeOptions="actionDone"
android:inputType="numberDecimal"
android:textAlignment="textStart"
android:textSize="24sp" />
</LinearLayout>
<Button
android:id="@+id/bGenerate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4sp"
android:layout_marginTop="4sp"
android:background="@color/colorPrimary"
android:enabled="false"
android:minHeight="36sp"
android:text="@string/receive_generate_hint" />
<ImageView
android:id="@+id/qrCode"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="16sp"
android:adjustViewBounds="true" />
<EditText
android:id="@+id/etDummy"
android:layout_width="0sp"
android:layout_height="0sp" />
</LinearLayout>

View File

@@ -52,7 +52,7 @@
android:textSize="16sp" />
<Button
android:id="@+id/bAddress"
android:id="@+id/bScan"
android:layout_width="0sp"
android:layout_height="wrap_content"
android:layout_gravity="center"

View File

@@ -3,6 +3,24 @@
<item
android:id="@+id/action_info"
android:icon="@drawable/ic_info_black_24dp"
android:title="@string/menu_info" />
<item
android:id="@+id/action_receive"
android:icon="@drawable/ic_monero_qr_24dp"
android:title="@string/menu_receive" />
<item
android:id="@+id/action_rename"
android:title="@string/menu_rename" />
<item
android:id="@+id/action_backup"
android:title="@string/menu_backup" />
<item
android:id="@+id/action_archive"
android:title="@string/menu_archive" />
</menu>

Some files were not shown because too many files have changed in this diff Show More