mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-04 17:28:42 +02:00
Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5b38cc438c | ||
![]() |
1eac363102 | ||
![]() |
e51425bc2e | ||
![]() |
f5535dbefa | ||
![]() |
2d42a0287d | ||
![]() |
2ebb9d0650 | ||
![]() |
30792c53c0 | ||
![]() |
3846a0c391 | ||
![]() |
c66ebd654a | ||
![]() |
186ed5cd39 | ||
![]() |
e39cd1c988 | ||
![]() |
39d9c4d0c3 | ||
![]() |
e4562f07a4 | ||
![]() |
b3ea4540a1 | ||
![]() |
ea7c7d2fdb | ||
![]() |
8ff8be6f60 | ||
![]() |
b5ded700fe | ||
![]() |
a5527d4efd | ||
![]() |
a007810824 | ||
![]() |
a634cf18b1 | ||
![]() |
0b2fa08df8 | ||
![]() |
191aa6ac22 | ||
![]() |
a82a90575d | ||
![]() |
2e04046f50 | ||
![]() |
c11d577c5f | ||
![]() |
74b2dd209c | ||
![]() |
cb1d541474 |
10
.idea/libraries/core_1_9_8.xml
generated
Normal file
10
.idea/libraries/core_1_9_8.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="core-1.9.8">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$USER_HOME$/.android/build-cache/db7eb580bfa6467818ef12c5f1fa42273b50aa3a/output/jars/classes.jar!/" />
|
||||||
|
<root url="file://$USER_HOME$/.android/build-cache/db7eb580bfa6467818ef12c5f1fa42273b50aa3a/output/res" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
11
.idea/libraries/core_3_3_0.xml
generated
Normal file
11
.idea/libraries/core_3_3_0.xml
generated
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="core-3.3.0">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.zxing/core/3.3.0/73c49077166faa4c3c0059c5f583d1d7bd1475fe/core-3.3.0.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.zxing/core/3.3.0/39d966e052e28fc7d83793b02e0af97ccf955745/core-3.3.0-sources.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</component>
|
10
.idea/libraries/zxing_1_9_8.xml
generated
Normal file
10
.idea/libraries/zxing_1_9_8.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="zxing-1.9.8">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$USER_HOME$/.android/build-cache/8d8f2e0e10c7af73321454f6fa481e8e5438e654/output/jars/classes.jar!/" />
|
||||||
|
<root url="file://$USER_HOME$/.android/build-cache/8d8f2e0e10c7af73321454f6fa481e8e5438e654/output/res" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
15
README.md
15
README.md
@@ -8,12 +8,11 @@ Another Android Monero Wallet
|
|||||||
- see the [FAQ](doc/FAQ.md)
|
- see the [FAQ](doc/FAQ.md)
|
||||||
|
|
||||||
### Disclaimer
|
### Disclaimer
|
||||||
You may loose all your Moneroj if you use this App.
|
You may loose all your Moneroj if you use this App. Be cautious when spending on mainnet.
|
||||||
|
|
||||||
### Random Notes
|
### Random Notes
|
||||||
- Based off monero v0.10.3.1 with pull requests #2238, #2239 and #2289 applied => so can be used in mainnet!
|
- Based off monero v0.10.3.1 with pull requests #2238, #2239 and #2289 applied => so can be used in mainnet!
|
||||||
- currently only android32
|
- currently only android32 (runs on 64-bit as well)
|
||||||
- ~~currently only use is checking incoming/outgoing transactions~~
|
|
||||||
- works in testnet & mainnet
|
- works in testnet & mainnet
|
||||||
- takes forever to sync due to 32-bit architecture
|
- takes forever to sync due to 32-bit architecture
|
||||||
- use your own daemon - it's easy
|
- use your own daemon - it's easy
|
||||||
@@ -23,15 +22,12 @@ You may loose all your Moneroj if you use this App.
|
|||||||
|
|
||||||
### TODO
|
### TODO
|
||||||
- wallet backup functions
|
- wallet backup functions
|
||||||
- adjust layout so we can use bigger font sizes (maybe show only 5 decimal places instead of 12 in main view)
|
|
||||||
- review visibility of methods/classes
|
- review visibility of methods/classes
|
||||||
- more sensible error dialogs ~~(e.g. when no write permissions granted) instead of just crashing on purpose~~
|
- more sensible error dialogs
|
||||||
- check licenses of included libraries; License Dialog
|
- check licenses of included libraries; License Dialog
|
||||||
- ~~make it pretty~~ (decided to go with "form follows function")
|
|
||||||
- ~~spend monero - not so difficult with wallet api~~
|
|
||||||
|
|
||||||
### Issues
|
### Issues
|
||||||
- Pending incoming transactions disappear after reload
|
- Pending incoming transactions disappear after reload (and appear after being mined)
|
||||||
|
|
||||||
### HOW TO BUILD
|
### HOW TO BUILD
|
||||||
No need to build. Binaries are included:
|
No need to build. Binaries are included:
|
||||||
@@ -45,4 +41,5 @@ If you want to build them yourself (recommended) check out [the instructions](do
|
|||||||
Then, fire up Android Studio and build the APK.
|
Then, fire up Android Studio and build the APK.
|
||||||
|
|
||||||
### Donations
|
### Donations
|
||||||
4AdkPJoxn7JCvAby9szgnt93MSEwdnxdhaASxbTBm6x5dCwmsDep2UYN4FhStDn5i11nsJbpU7oj59ahg8gXb1Mg3viqCuk
|
- Address: 4AdkPJoxn7JCvAby9szgnt93MSEwdnxdhaASxbTBm6x5dCwmsDep2UYN4FhStDn5i11nsJbpU7oj59ahg8gXb1Mg3viqCuk
|
||||||
|
- Viewkey: b1aff2a12191723da0afbe75516f94dd8b068215f6e847d8da57aca5f1f98e0c
|
@@ -7,8 +7,8 @@ android {
|
|||||||
applicationId "com.m2049r.xmrwallet"
|
applicationId "com.m2049r.xmrwallet"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 6
|
versionCode 8
|
||||||
versionName "0.4.2"
|
versionName "0.5.1"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
@@ -46,5 +46,6 @@ dependencies {
|
|||||||
compile 'com.android.support:support-v4:25.3.1'
|
compile 'com.android.support:support-v4:25.3.1'
|
||||||
compile 'com.android.support:recyclerview-v7:25.3.1'
|
compile 'com.android.support:recyclerview-v7:25.3.1'
|
||||||
compile 'com.android.support:cardview-v7:25.3.1'
|
compile 'com.android.support:cardview-v7:25.3.1'
|
||||||
|
compile 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@@ -592,12 +592,16 @@ Java_com_m2049r_xmrwallet_model_Wallet_getFilename(JNIEnv *env, jobject instance
|
|||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
Java_com_m2049r_xmrwallet_model_Wallet_initJ(JNIEnv *env, jobject instance,
|
Java_com_m2049r_xmrwallet_model_Wallet_initJ(JNIEnv *env, jobject instance,
|
||||||
jstring daemon_address,
|
jstring daemon_address,
|
||||||
jlong upper_transaction_size_limit) {
|
jlong upper_transaction_size_limit,
|
||||||
// const std::string &daemon_username = "", const std::string &daemon_password = "") = 0;
|
jstring daemon_username, jstring daemon_password) {
|
||||||
const char *_daemon_address = env->GetStringUTFChars(daemon_address, JNI_FALSE);
|
const char *_daemon_address = env->GetStringUTFChars(daemon_address, JNI_FALSE);
|
||||||
|
const char *_daemon_username = env->GetStringUTFChars(daemon_username, JNI_FALSE);
|
||||||
|
const char *_daemon_password = env->GetStringUTFChars(daemon_password, JNI_FALSE);
|
||||||
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
|
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
|
||||||
bool status = wallet->init(_daemon_address, upper_transaction_size_limit);
|
bool status = wallet->init(_daemon_address, upper_transaction_size_limit, _daemon_username, _daemon_password);
|
||||||
env->ReleaseStringUTFChars(daemon_address, _daemon_address);
|
env->ReleaseStringUTFChars(daemon_address, _daemon_address);
|
||||||
|
env->ReleaseStringUTFChars(daemon_username, _daemon_username);
|
||||||
|
env->ReleaseStringUTFChars(daemon_password, _daemon_password);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@ import android.os.Bundle;
|
|||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -344,6 +345,13 @@ public class GenerateFragment extends Fragment {
|
|||||||
bGenerate.setVisibility(View.VISIBLE);
|
bGenerate.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
Log.d(TAG, "onPause()");
|
||||||
|
activityCallback.setTitle(getString(R.string.generate_title));
|
||||||
|
}
|
||||||
|
|
||||||
GenerateFragment.Listener activityCallback;
|
GenerateFragment.Listener activityCallback;
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
@@ -354,6 +362,9 @@ public class GenerateFragment extends Fragment {
|
|||||||
void onGenerate(String name, String password, String address, String viewKey, String spendKey, long height);
|
void onGenerate(String name, String password, String address, String viewKey, String spendKey, long height);
|
||||||
|
|
||||||
File getStorageRoot();
|
File getStorageRoot();
|
||||||
|
|
||||||
|
void setTitle(String title);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -65,6 +65,7 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
|
|
||||||
boolean testnet = WalletManager.getInstance().isTestNet();
|
boolean testnet = WalletManager.getInstance().isTestNet();
|
||||||
tvWalletMnemonic.setTextIsSelectable(testnet);
|
tvWalletMnemonic.setTextIsSelectable(testnet);
|
||||||
|
tvWalletSpendKey.setTextIsSelectable(testnet);
|
||||||
|
|
||||||
bAccept.setOnClickListener(new View.OnClickListener() {
|
bAccept.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@@ -55,6 +55,8 @@ public class LoginActivity extends AppCompatActivity
|
|||||||
|
|
||||||
static final int DAEMON_TIMEOUT = 500; // deamon must respond in 500ms
|
static final int DAEMON_TIMEOUT = 500; // deamon must respond in 500ms
|
||||||
|
|
||||||
|
Toolbar toolbar;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -63,8 +65,7 @@ public class LoginActivity extends AppCompatActivity
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.tbLogin);
|
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
toolbar.setTitle(R.string.login_activity_name);
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
if (Helper.getWritePermission(this)) {
|
if (Helper.getWritePermission(this)) {
|
||||||
@@ -77,21 +78,17 @@ public class LoginActivity extends AppCompatActivity
|
|||||||
@Override
|
@Override
|
||||||
public void onWalletSelected(final String walletName) {
|
public void onWalletSelected(final String walletName) {
|
||||||
Log.d(TAG, "selected wallet is ." + walletName + ".");
|
Log.d(TAG, "selected wallet is ." + walletName + ".");
|
||||||
if (walletName.equals(':' + getString(R.string.generate_title))) {
|
// now it's getting real, check if wallet exists
|
||||||
startGenerateFragment();
|
String walletPath = Helper.getWalletPath(this, walletName);
|
||||||
} else {
|
if (WalletManager.getInstance().walletExists(walletPath)) {
|
||||||
// now it's getting real, check if wallet exists
|
promptPassword(walletName, new PasswordAction() {
|
||||||
String walletPath = Helper.getWalletPath(this, walletName);
|
@Override
|
||||||
if (WalletManager.getInstance().walletExists(walletPath)) {
|
public void action(String walletName, String password) {
|
||||||
promptPassword(walletName, new PasswordAction() {
|
startWallet(walletName, password);
|
||||||
@Override
|
}
|
||||||
public void action(String walletName, String password) {
|
});
|
||||||
startWallet(walletName, password);
|
} else { // this cannot really happen as we prefilter choices
|
||||||
}
|
Toast.makeText(this, getString(R.string.bad_wallet), Toast.LENGTH_SHORT).show();
|
||||||
});
|
|
||||||
} else { // this cannot really happen as we prefilter choices
|
|
||||||
Toast.makeText(this, getString(R.string.bad_wallet), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +108,11 @@ public class LoginActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAddWallet() {
|
||||||
|
startGenerateFragment();
|
||||||
|
}
|
||||||
|
|
||||||
AlertDialog passwordDialog = null; // for preventing multiple clicks in wallet list
|
AlertDialog passwordDialog = null; // for preventing multiple clicks in wallet list
|
||||||
|
|
||||||
void promptPassword(final String wallet, final PasswordAction action) {
|
void promptPassword(final String wallet, final PasswordAction action) {
|
||||||
@@ -203,9 +205,22 @@ public class LoginActivity extends AppCompatActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
super.setTitle(title);
|
toolbar.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSubtitle(String subtitle) {
|
||||||
|
toolbar.setSubtitle(subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTestNet(boolean testnet) {
|
||||||
|
if (testnet) {
|
||||||
|
toolbar.setBackgroundResource(R.color.colorPrimaryDark);
|
||||||
|
} else {
|
||||||
|
toolbar.setBackgroundResource(R.color.moneroOrange);
|
||||||
|
}
|
||||||
|
}
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
131
app/src/main/java/com/m2049r/xmrwallet/ScannerFragment.java
Normal file
131
app/src/main/java/com/m2049r/xmrwallet/ScannerFragment.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 dm77, 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;
|
||||||
|
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
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 me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||||
|
|
||||||
|
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
|
||||||
|
static final String TAG = "ScannerFragment";
|
||||||
|
|
||||||
|
Listener activityCallback;
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
void onAddressScanned(String address, String paymentId);
|
||||||
|
|
||||||
|
boolean isPaymentIdValid(String paymentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ZXingScannerView mScannerView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
Log.d(TAG, "onCreateView");
|
||||||
|
mScannerView = new ZXingScannerView(getActivity());
|
||||||
|
return mScannerView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
Log.d(TAG, "onResume");
|
||||||
|
mScannerView.setResultHandler(this);
|
||||||
|
mScannerView.startCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
static final String URI_PREFIX = "monero:";
|
||||||
|
static final String PAYMENTID_STRING = "?tx_payment_id=";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleResult(Result rawResult) {
|
||||||
|
Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
|
||||||
|
String text = 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);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.send_qr_invalid), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note from dm77:
|
||||||
|
// * Wait 2 seconds to resume the preview.
|
||||||
|
// * On older devices continuously stopping and resuming camera preview can result in freezing the app.
|
||||||
|
// * I don't know why this is the case but I don't have the time to figure out.
|
||||||
|
Handler handler = new Handler();
|
||||||
|
handler.postDelayed(new
|
||||||
|
|
||||||
|
Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mScannerView.resumeCameraPreview(ScannerFragment.this);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
Log.d(TAG, "onPause");
|
||||||
|
mScannerView.stopCamera();
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
Log.d(TAG, "attaching scan");
|
||||||
|
if (context instanceof Listener) {
|
||||||
|
this.activityCallback = (Listener) context;
|
||||||
|
} else {
|
||||||
|
throw new ClassCastException(context.toString()
|
||||||
|
+ " must implement Listener");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -20,10 +20,12 @@ import android.app.Fragment;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -40,14 +42,16 @@ import com.m2049r.xmrwallet.model.PendingTransaction;
|
|||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
import com.m2049r.xmrwallet.util.BarcodeData;
|
||||||
import com.m2049r.xmrwallet.util.TxData;
|
import com.m2049r.xmrwallet.util.TxData;
|
||||||
|
|
||||||
public class SendFragment extends Fragment {
|
public class SendFragment extends Fragment {
|
||||||
static final String TAG = "GenerateFragment";
|
static final String TAG = "SendFragment";
|
||||||
|
|
||||||
EditText etAddress;
|
EditText etAddress;
|
||||||
EditText etPaymentId;
|
EditText etPaymentId;
|
||||||
EditText etAmount;
|
EditText etAmount;
|
||||||
|
Button bAddress;
|
||||||
Button bSweep;
|
Button bSweep;
|
||||||
Spinner sMixin;
|
Spinner sMixin;
|
||||||
Spinner sPriority;
|
Spinner sPriority;
|
||||||
@@ -60,6 +64,7 @@ public class SendFragment extends Fragment {
|
|||||||
TextView tvTxDust;
|
TextView tvTxDust;
|
||||||
EditText etNotes;
|
EditText etNotes;
|
||||||
Button bSend;
|
Button bSend;
|
||||||
|
Button bReallySend;
|
||||||
ProgressBar pbProgress;
|
ProgressBar pbProgress;
|
||||||
|
|
||||||
final static int Mixins[] = {4, 6, 8, 10, 13}; // must match the layout XML
|
final static int Mixins[] = {4, 6, 8, 10, 13}; // must match the layout XML
|
||||||
@@ -79,6 +84,7 @@ public class SendFragment extends Fragment {
|
|||||||
etAddress = (EditText) view.findViewById(R.id.etAddress);
|
etAddress = (EditText) view.findViewById(R.id.etAddress);
|
||||||
etPaymentId = (EditText) view.findViewById(R.id.etPaymentId);
|
etPaymentId = (EditText) view.findViewById(R.id.etPaymentId);
|
||||||
etAmount = (EditText) view.findViewById(R.id.etAmount);
|
etAmount = (EditText) view.findViewById(R.id.etAmount);
|
||||||
|
bAddress = (Button) view.findViewById(R.id.bAddress);
|
||||||
bSweep = (Button) view.findViewById(R.id.bSweep);
|
bSweep = (Button) view.findViewById(R.id.bSweep);
|
||||||
bPrepareSend = (Button) view.findViewById(R.id.bPrepareSend);
|
bPrepareSend = (Button) view.findViewById(R.id.bPrepareSend);
|
||||||
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
|
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
|
||||||
@@ -90,6 +96,7 @@ public class SendFragment extends Fragment {
|
|||||||
tvTxDust = (TextView) view.findViewById(R.id.tvTxDust);
|
tvTxDust = (TextView) view.findViewById(R.id.tvTxDust);
|
||||||
etNotes = (EditText) view.findViewById(R.id.etNotes);
|
etNotes = (EditText) view.findViewById(R.id.etNotes);
|
||||||
bSend = (Button) view.findViewById(R.id.bSend);
|
bSend = (Button) view.findViewById(R.id.bSend);
|
||||||
|
bReallySend = (Button) view.findViewById(R.id.bReallySend);
|
||||||
|
|
||||||
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
|
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
|
||||||
|
|
||||||
@@ -97,10 +104,6 @@ public class SendFragment extends Fragment {
|
|||||||
etPaymentId.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
etPaymentId.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
etNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
etNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
|
|
||||||
// etAddress.setText("9tDC52GsMjTNt4dpnRCwAF7ekVBkbkgkXGaMKTcSTpBhGpqkPX56jCNRydLq9oGjbbAQBsZhLfgmTKsntmxRd3TaJFYM2f8");
|
|
||||||
boolean testnet = WalletManager.getInstance().isTestNet();
|
|
||||||
if (!testnet) throw new IllegalStateException("Sending TX only on testnet. sorry.");
|
|
||||||
|
|
||||||
Helper.showKeyboard(getActivity());
|
Helper.showKeyboard(getActivity());
|
||||||
etAddress.requestFocus();
|
etAddress.requestFocus();
|
||||||
etAddress.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
etAddress.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||||
@@ -196,6 +199,13 @@ public class SendFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bAddress.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
activityCallback.onScanAddress();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@@ -229,6 +239,26 @@ public class SendFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
bSend.setEnabled(false);
|
bSend.setEnabled(false);
|
||||||
|
boolean testnet = WalletManager.getInstance().isTestNet();
|
||||||
|
if (testnet) {
|
||||||
|
send();
|
||||||
|
} else {
|
||||||
|
etNotes.setEnabled(false);
|
||||||
|
Handler handler = new Handler();
|
||||||
|
handler.postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
bReallySend.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bReallySend.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
bReallySend.setEnabled(false);
|
||||||
send();
|
send();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -245,11 +275,7 @@ public class SendFragment extends Fragment {
|
|||||||
|
|
||||||
private boolean addressOk() {
|
private boolean addressOk() {
|
||||||
String address = etAddress.getText().toString();
|
String address = etAddress.getText().toString();
|
||||||
if (WalletManager.getInstance().isTestNet()) {
|
return Helper.isAddressOk(address, WalletManager.getInstance().isTestNet());
|
||||||
return ((address.length() == 95) && ("9A".indexOf(address.charAt(0)) >= 0));
|
|
||||||
} else {
|
|
||||||
return ((address.length() == 95) && ("4".indexOf(address.charAt(0)) >= 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean amountOk() {
|
private boolean amountOk() {
|
||||||
@@ -310,6 +336,9 @@ public class SendFragment extends Fragment {
|
|||||||
bSweep.setEnabled(true);
|
bSweep.setEnabled(true);
|
||||||
bPrepareSend.setEnabled(true);
|
bPrepareSend.setEnabled(true);
|
||||||
llConfirmSend.setVisibility(View.GONE);
|
llConfirmSend.setVisibility(View.GONE);
|
||||||
|
bSend.setEnabled(true);
|
||||||
|
etNotes.setEnabled(true);
|
||||||
|
bReallySend.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void send() {
|
private void send() {
|
||||||
@@ -335,6 +364,35 @@ public class SendFragment extends Fragment {
|
|||||||
|
|
||||||
void onDisposeRequest();
|
void onDisposeRequest();
|
||||||
|
|
||||||
|
void onScanAddress();
|
||||||
|
|
||||||
|
BarcodeData getScannedData();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
BarcodeData data = activityCallback.getScannedData();
|
||||||
|
if (data != null) {
|
||||||
|
String scannedAddress = data.address;
|
||||||
|
if (scannedAddress != null) {
|
||||||
|
etAddress.setText(scannedAddress);
|
||||||
|
}
|
||||||
|
String scannedPaymenId = data.paymentId;
|
||||||
|
if (scannedPaymenId != null) {
|
||||||
|
etPaymentId.setText(scannedPaymenId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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
|
@Override
|
||||||
|
@@ -50,7 +50,7 @@ public class TxFragment extends Fragment {
|
|||||||
|
|
||||||
static public final String ARG_INFO = "info";
|
static public final String ARG_INFO = "info";
|
||||||
|
|
||||||
private final SimpleDateFormat TS_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
private final SimpleDateFormat TS_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
|
||||||
|
|
||||||
public TxFragment() {
|
public TxFragment() {
|
||||||
super();
|
super();
|
||||||
@@ -146,10 +146,10 @@ public class TxFragment extends Fragment {
|
|||||||
sb.append(getString(R.string.tx_timestamp)).append(": ");
|
sb.append(getString(R.string.tx_timestamp)).append(": ");
|
||||||
sb.append(TS_FORMATTER.format(new Date(info.timestamp * 1000))).append("\n");
|
sb.append(TS_FORMATTER.format(new Date(info.timestamp * 1000))).append("\n");
|
||||||
sb.append(getString(R.string.tx_blockheight)).append(": ");
|
sb.append(getString(R.string.tx_blockheight)).append(": ");
|
||||||
if (info.isPending) {
|
if (info.isFailed) {
|
||||||
sb.append(getString(R.string.tx_pending)).append("\n");
|
|
||||||
} else if (info.isFailed) {
|
|
||||||
sb.append(getString(R.string.tx_failed)).append("\n");
|
sb.append(getString(R.string.tx_failed)).append("\n");
|
||||||
|
} else if (info.isPending) {
|
||||||
|
sb.append(getString(R.string.tx_pending)).append("\n");
|
||||||
} else {
|
} else {
|
||||||
sb.append(info.blockheight).append("\n");
|
sb.append(info.blockheight).append("\n");
|
||||||
}
|
}
|
||||||
@@ -196,10 +196,10 @@ public class TxFragment extends Fragment {
|
|||||||
tvTxId.setText(info.hash);
|
tvTxId.setText(info.hash);
|
||||||
tvTxKey.setText(info.txKey.isEmpty() ? "-" : info.txKey);
|
tvTxKey.setText(info.txKey.isEmpty() ? "-" : info.txKey);
|
||||||
tvTxPaymentId.setText(info.paymentId);
|
tvTxPaymentId.setText(info.paymentId);
|
||||||
if (info.isPending) {
|
if (info.isFailed) {
|
||||||
tvTxBlockheight.setText(getString(R.string.tx_pending));
|
|
||||||
} else if (info.isFailed) {
|
|
||||||
tvTxBlockheight.setText(getString(R.string.tx_failed));
|
tvTxBlockheight.setText(getString(R.string.tx_failed));
|
||||||
|
} else if (info.isPending) {
|
||||||
|
tvTxBlockheight.setText(getString(R.string.tx_pending));
|
||||||
} else {
|
} else {
|
||||||
tvTxBlockheight.setText("" + info.blockheight);
|
tvTxBlockheight.setText("" + info.blockheight);
|
||||||
}
|
}
|
||||||
|
@@ -23,31 +23,38 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.model.PendingTransaction;
|
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||||
import com.m2049r.xmrwallet.model.TransactionInfo;
|
import com.m2049r.xmrwallet.model.TransactionInfo;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.service.WalletService;
|
import com.m2049r.xmrwallet.service.WalletService;
|
||||||
|
import com.m2049r.xmrwallet.util.BarcodeData;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.TxData;
|
import com.m2049r.xmrwallet.util.TxData;
|
||||||
|
|
||||||
public class WalletActivity extends AppCompatActivity implements WalletFragment.Listener,
|
public class WalletActivity extends AppCompatActivity implements WalletFragment.Listener,
|
||||||
WalletService.Observer, SendFragment.Listener, TxFragment.Listener, GenerateReviewFragment.ListenerWithWallet {
|
WalletService.Observer, SendFragment.Listener, TxFragment.Listener,
|
||||||
|
GenerateReviewFragment.ListenerWithWallet,
|
||||||
|
ScannerFragment.Listener {
|
||||||
private static final String TAG = "WalletActivity";
|
private static final String TAG = "WalletActivity";
|
||||||
|
|
||||||
static final int MIN_DAEMON_VERSION = 65544;
|
|
||||||
|
|
||||||
public static final String REQUEST_ID = "id";
|
public static final String REQUEST_ID = "id";
|
||||||
public static final String REQUEST_PW = "pw";
|
public static final String REQUEST_PW = "pw";
|
||||||
|
|
||||||
Toolbar tbWallet;
|
Toolbar toolbar;
|
||||||
|
|
||||||
private boolean synced = false;
|
private boolean synced = false;
|
||||||
|
|
||||||
@@ -107,6 +114,27 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
if (!haveWallet) return true;
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.wallet_menu, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_info:
|
||||||
|
onWalletDetails();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
Log.d(TAG, "onCreate()");
|
Log.d(TAG, "onCreate()");
|
||||||
@@ -116,15 +144,15 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tbWallet = (Toolbar) findViewById(R.id.tbWallet);
|
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
tbWallet.setTitle(R.string.app_name);
|
toolbar.setTitle(R.string.app_name);
|
||||||
setSupportActionBar(tbWallet);
|
setSupportActionBar(toolbar);
|
||||||
tbWallet.setOnClickListener(new View.OnClickListener() {
|
boolean testnet = WalletManager.getInstance().isTestNet();
|
||||||
@Override
|
if (testnet) {
|
||||||
public void onClick(View v) {
|
toolbar.setBackgroundResource(R.color.colorPrimaryDark);
|
||||||
onWalletDetails();
|
} else {
|
||||||
}
|
toolbar.setBackgroundResource(R.color.moneroOrange);
|
||||||
});
|
}
|
||||||
|
|
||||||
Fragment walletFragment = new WalletFragment();
|
Fragment walletFragment = new WalletFragment();
|
||||||
getFragmentManager().beginTransaction()
|
getFragmentManager().beginTransaction()
|
||||||
@@ -158,6 +186,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
String walletId = extras.getString(REQUEST_ID);
|
String walletId = extras.getString(REQUEST_ID);
|
||||||
if (walletId != null) {
|
if (walletId != null) {
|
||||||
setTitle(walletId);
|
setTitle(walletId);
|
||||||
|
setSubtitle("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateProgress();
|
updateProgress();
|
||||||
@@ -172,6 +201,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
// see this happen.
|
// see this happen.
|
||||||
mBoundService = null;
|
mBoundService = null;
|
||||||
setTitle(getString(R.string.wallet_activity_name));
|
setTitle(getString(R.string.wallet_activity_name));
|
||||||
|
setSubtitle("");
|
||||||
Log.d(TAG, "DISCONNECTED");
|
Log.d(TAG, "DISCONNECTED");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -267,7 +297,12 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
tbWallet.setTitle(title);
|
toolbar.setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSubtitle(String subtitle) {
|
||||||
|
toolbar.setSubtitle(subtitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -303,6 +338,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
final WalletFragment walletFragment = (WalletFragment)
|
final WalletFragment walletFragment = (WalletFragment)
|
||||||
getFragmentManager().findFragmentById(R.id.fragment_container);
|
getFragmentManager().findFragmentById(R.id.fragment_container);
|
||||||
if (wallet.isSynchronized()) {
|
if (wallet.isSynchronized()) {
|
||||||
|
Log.d(TAG, "onRefreshed() synced");
|
||||||
releaseWakeLock(); // the idea is to stay awake until synced
|
releaseWakeLock(); // the idea is to stay awake until synced
|
||||||
if (!synced) {
|
if (!synced) {
|
||||||
onProgress(null);
|
onProgress(null);
|
||||||
@@ -342,6 +378,25 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean haveWallet = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWalletStarted(final boolean success) {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (!success) {
|
||||||
|
Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_connect_failed), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!success) {
|
||||||
|
finish();
|
||||||
|
} else {
|
||||||
|
haveWallet = true;
|
||||||
|
invalidateOptionsMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatedTransaction(final PendingTransaction pendingTransaction) {
|
public void onCreatedTransaction(final PendingTransaction pendingTransaction) {
|
||||||
try {
|
try {
|
||||||
@@ -536,7 +591,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
|
|
||||||
private void onWalletDetails() {
|
private void onWalletDetails() {
|
||||||
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container);
|
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container);
|
||||||
if (fragment instanceof WalletFragment) {
|
if (!(fragment instanceof GenerateReviewFragment)) {
|
||||||
Bundle extras = new Bundle();
|
Bundle extras = new Bundle();
|
||||||
extras.putString("type", GenerateReviewFragment.VIEW_WALLET);
|
extras.putString("type", GenerateReviewFragment.VIEW_WALLET);
|
||||||
replaceFragment(new GenerateReviewFragment(), null, extras);
|
replaceFragment(new GenerateReviewFragment(), null, extras);
|
||||||
@@ -547,4 +602,60 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
|||||||
public void onDisposeRequest() {
|
public void onDisposeRequest() {
|
||||||
getWallet().disposePendingTransaction();
|
getWallet().disposePendingTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void startScanFragment() {
|
||||||
|
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container);
|
||||||
|
if (fragment instanceof SendFragment) {
|
||||||
|
Bundle extras = new Bundle();
|
||||||
|
replaceFragment(new ScannerFragment(), null, extras);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// QR scanner callbacks
|
||||||
|
@Override
|
||||||
|
public void onScanAddress() {
|
||||||
|
if (Helper.getCameraPermission(this)) {
|
||||||
|
startScanFragment();
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "Waiting for permissions");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private BarcodeData scannedData = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAddressScanned(String address, String paymentId) {
|
||||||
|
// Log.d(TAG, "got " + address);
|
||||||
|
scannedData = new BarcodeData(address, paymentId);
|
||||||
|
popFragmentStack(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BarcodeData getScannedData() {
|
||||||
|
BarcodeData data = scannedData;
|
||||||
|
scannedData = null;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
||||||
|
Log.d(TAG, "onRequestPermissionsResult()");
|
||||||
|
switch (requestCode) {
|
||||||
|
case Helper.PERMISSIONS_REQUEST_CAMERA:
|
||||||
|
// If request is cancelled, the result arrays are empty.
|
||||||
|
if (grantResults.length > 0
|
||||||
|
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
startScanFragment();
|
||||||
|
} else {
|
||||||
|
String msg = getString(R.string.message_camera_not_permitted);
|
||||||
|
Log.e(TAG, msg);
|
||||||
|
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -22,6 +22,7 @@ import android.content.ClipboardManager;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.constraint.ConstraintLayout;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.widget.DividerItemDecoration;
|
import android.support.v7.widget.DividerItemDecoration;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
@@ -29,6 +30,7 @@ import android.util.Log;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
@@ -49,10 +51,10 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
|||||||
private NumberFormat formatter = NumberFormat.getInstance();
|
private NumberFormat formatter = NumberFormat.getInstance();
|
||||||
|
|
||||||
TextView tvBalance;
|
TextView tvBalance;
|
||||||
TextView tvUnlockedBalance;
|
LinearLayout llUnconfirmedAmount;
|
||||||
|
TextView tvUnconfirmedAmount;
|
||||||
TextView tvBlockHeightProgress;
|
TextView tvBlockHeightProgress;
|
||||||
TextView tvConnectionStatus;
|
ConstraintLayout clProgress;
|
||||||
LinearLayout llProgress;
|
|
||||||
TextView tvProgress;
|
TextView tvProgress;
|
||||||
ProgressBar pbProgress;
|
ProgressBar pbProgress;
|
||||||
Button bSend;
|
Button bSend;
|
||||||
@@ -64,11 +66,13 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
|||||||
|
|
||||||
tvProgress = (TextView) view.findViewById(R.id.tvProgress);
|
tvProgress = (TextView) view.findViewById(R.id.tvProgress);
|
||||||
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
|
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
|
||||||
llProgress = (LinearLayout) view.findViewById(R.id.llProgress);
|
clProgress = (ConstraintLayout) view.findViewById(R.id.clProgress);
|
||||||
|
llUnconfirmedAmount = (LinearLayout) view.findViewById(R.id.llUnconfirmedAmount);
|
||||||
tvBalance = (TextView) view.findViewById(R.id.tvBalance);
|
tvBalance = (TextView) view.findViewById(R.id.tvBalance);
|
||||||
tvUnlockedBalance = (TextView) view.findViewById(R.id.tvUnlockedBalance);
|
tvBalance.setText(getDisplayAmount(0));
|
||||||
|
tvUnconfirmedAmount = (TextView) view.findViewById(R.id.tvUnconfirmedAmount);
|
||||||
|
tvUnconfirmedAmount.setText(getDisplayAmount(0));
|
||||||
tvBlockHeightProgress = (TextView) view.findViewById(R.id.tvBlockHeightProgress);
|
tvBlockHeightProgress = (TextView) view.findViewById(R.id.tvBlockHeightProgress);
|
||||||
tvConnectionStatus = (TextView) view.findViewById(R.id.tvConnectionStatus);
|
|
||||||
|
|
||||||
bSend = (Button) view.findViewById(R.id.bSend);
|
bSend = (Button) view.findViewById(R.id.bSend);
|
||||||
|
|
||||||
@@ -118,7 +122,7 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onSynced() {
|
public void onSynced() {
|
||||||
if (!activityCallback.isWatchOnly() && WalletManager.getInstance().isTestNet()) {
|
if (!activityCallback.isWatchOnly()) {
|
||||||
bSend.setVisibility(View.VISIBLE);
|
bSend.setVisibility(View.VISIBLE);
|
||||||
bSend.setEnabled(true);
|
bSend.setEnabled(true);
|
||||||
}
|
}
|
||||||
@@ -145,11 +149,11 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void showProgress() {
|
public void showProgress() {
|
||||||
llProgress.setVisibility(View.VISIBLE);
|
clProgress.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hideProgress() {
|
public void hideProgress() {
|
||||||
llProgress.setVisibility(View.GONE);
|
clProgress.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
String setActivityTitle(Wallet wallet) {
|
String setActivityTitle(Wallet wallet) {
|
||||||
@@ -158,10 +162,12 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
|||||||
if (shortName.length() > 16) {
|
if (shortName.length() > 16) {
|
||||||
shortName = shortName.substring(0, 14) + "...";
|
shortName = shortName.substring(0, 14) + "...";
|
||||||
}
|
}
|
||||||
String title = "[" + wallet.getAddress().substring(0, 6) + "] "
|
String title = "[" + wallet.getAddress().substring(0, 6) + "] " + shortName;
|
||||||
+ shortName
|
|
||||||
+ (wallet.isWatchOnly() ? " " + getString(R.string.watchonly_label) : "");
|
|
||||||
activityCallback.setTitle(title);
|
activityCallback.setTitle(title);
|
||||||
|
|
||||||
|
String watchOnly = (wallet.isWatchOnly() ? " " + getString(R.string.watchonly_label) : "");
|
||||||
|
String net = (wallet.isTestNet() ? getString(R.string.connect_testnet) : getString(R.string.connect_mainnet));
|
||||||
|
activityCallback.setSubtitle(net + " " + watchOnly);
|
||||||
Log.d(TAG, "wallet title is " + title);
|
Log.d(TAG, "wallet title is " + title);
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
@@ -169,14 +175,39 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
|||||||
private long firstBlock = 0;
|
private long firstBlock = 0;
|
||||||
private String walletTitle = null;
|
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) {
|
private void updateStatus(Wallet wallet) {
|
||||||
Log.d(TAG, "updateStatus()");
|
Log.d(TAG, "updateStatus()");
|
||||||
if (walletTitle == null) {
|
if (walletTitle == null) {
|
||||||
walletTitle = setActivityTitle(wallet);
|
walletTitle = setActivityTitle(wallet);
|
||||||
onProgress(100); // of loading
|
onProgress(100); // of loading
|
||||||
}
|
}
|
||||||
tvBalance.setText(Wallet.getDisplayAmount(wallet.getBalance()));
|
long balance = wallet.getBalance();
|
||||||
tvUnlockedBalance.setText(Wallet.getDisplayAmount(wallet.getUnlockedBalance()));
|
long unlockedBalance = wallet.getUnlockedBalance();
|
||||||
|
tvBalance.setText(getDisplayAmount(unlockedBalance));
|
||||||
|
tvUnconfirmedAmount.setText(getDisplayAmount(balance - unlockedBalance));
|
||||||
|
// balance cannot be less than unlockedBalance
|
||||||
|
/*if (balance != unlockedBalance) {
|
||||||
|
llPendingAmount.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
llPendingAmount.setVisibility(View.INVISIBLE);
|
||||||
|
}*/
|
||||||
String sync = "";
|
String sync = "";
|
||||||
if (!activityCallback.hasBoundService())
|
if (!activityCallback.hasBoundService())
|
||||||
throw new IllegalStateException("WalletService not bound.");
|
throw new IllegalStateException("WalletService not bound.");
|
||||||
@@ -197,9 +228,10 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
|||||||
sync = getString(R.string.status_synced) + ": " + formatter.format(wallet.getBlockChainHeight());
|
sync = getString(R.string.status_synced) + ": " + formatter.format(wallet.getBlockChainHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String net = (wallet.isTestNet() ? getString(R.string.connect_testnet) : getString(R.string.connect_mainnet));
|
|
||||||
tvBlockHeightProgress.setText(sync);
|
tvBlockHeightProgress.setText(sync);
|
||||||
tvConnectionStatus.setText(net + " " + daemonConnected.toString().substring(17));
|
//String net = (wallet.isTestNet() ? getString(R.string.connect_testnet) : getString(R.string.connect_mainnet));
|
||||||
|
//activityCallback.setSubtitle(net + " " + daemonConnected.toString().substring(17));
|
||||||
|
// TODO show connected status somewhere
|
||||||
}
|
}
|
||||||
|
|
||||||
Listener activityCallback;
|
Listener activityCallback;
|
||||||
@@ -216,6 +248,8 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
|||||||
|
|
||||||
void setTitle(String title);
|
void setTitle(String title);
|
||||||
|
|
||||||
|
void setSubtitle(String subtitle);
|
||||||
|
|
||||||
void onSendRequest();
|
void onSendRequest();
|
||||||
|
|
||||||
void onTxDetailsRequest(TransactionInfo info);
|
void onTxDetailsRequest(TransactionInfo info);
|
||||||
|
@@ -40,8 +40,7 @@ import java.util.TimeZone;
|
|||||||
public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfoAdapter.ViewHolder> {
|
public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfoAdapter.ViewHolder> {
|
||||||
private static final String TAG = "TransactionInfoAdapter";
|
private static final String TAG = "TransactionInfoAdapter";
|
||||||
|
|
||||||
private final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
|
private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
private final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("HH:mm:ss");
|
|
||||||
|
|
||||||
static final int TX_RED = Color.rgb(255, 79, 65);
|
static final int TX_RED = Color.rgb(255, 79, 65);
|
||||||
static final int TX_GREEN = Color.rgb(54, 176, 91);
|
static final int TX_GREEN = Color.rgb(54, 176, 91);
|
||||||
@@ -60,8 +59,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
TimeZone tz = cal.getTimeZone(); //get the local time zone.
|
TimeZone tz = cal.getTimeZone(); //get the local time zone.
|
||||||
DATE_FORMATTER.setTimeZone(tz);
|
DATETIME_FORMATTER.setTimeZone(tz);
|
||||||
TIME_FORMATTER.setTimeZone(tz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -91,16 +89,15 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
Collections.sort(data, new Comparator<TransactionInfo>() {
|
Collections.sort(data, new Comparator<TransactionInfo>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(TransactionInfo o1, TransactionInfo o2) {
|
public int compare(TransactionInfo o1, TransactionInfo o2) {
|
||||||
if ((o1.isPending) && (o2.isPending)) {
|
long b1 = o1.timestamp;
|
||||||
long b1 = o1.timestamp;
|
long b2 = o2.timestamp;
|
||||||
long b2 = o2.timestamp;
|
if (b1 > b2) {
|
||||||
return (b1 > b2) ? -1 : (b1 < b2) ? 1 : 0;
|
return -1;
|
||||||
|
} else if (b1 < b2) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return o1.hash.compareTo(o2.hash);
|
||||||
}
|
}
|
||||||
if (o1.isPending) return -1;
|
|
||||||
if (o2.isPending) return 1;
|
|
||||||
long b1 = o1.blockheight;
|
|
||||||
long b2 = o2.blockheight;
|
|
||||||
return (b1 > b2) ? -1 : (b1 < b2) ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.infoItems.addAll(data);
|
this.infoItems.addAll(data);
|
||||||
@@ -114,8 +111,8 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
final TextView tvAmount;
|
final TextView tvAmount;
|
||||||
final TextView tvAmountPoint;
|
final TextView tvAmountPoint;
|
||||||
final TextView tvAmountDecimal;
|
final TextView tvAmountDecimal;
|
||||||
final TextView tvDate;
|
final TextView tvPaymentId;
|
||||||
final TextView tvTime;
|
final TextView tvDateTime;
|
||||||
TransactionInfo infoItem;
|
TransactionInfo infoItem;
|
||||||
|
|
||||||
ViewHolder(View itemView) {
|
ViewHolder(View itemView) {
|
||||||
@@ -124,16 +121,12 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
// I know this is stupid but can't be bothered to align decimals otherwise
|
// I know this is stupid but can't be bothered to align decimals otherwise
|
||||||
this.tvAmountPoint = (TextView) itemView.findViewById(R.id.tx_amount_point);
|
this.tvAmountPoint = (TextView) itemView.findViewById(R.id.tx_amount_point);
|
||||||
this.tvAmountDecimal = (TextView) itemView.findViewById(R.id.tx_amount_decimal);
|
this.tvAmountDecimal = (TextView) itemView.findViewById(R.id.tx_amount_decimal);
|
||||||
this.tvDate = (TextView) itemView.findViewById(R.id.tx_date);
|
this.tvPaymentId = (TextView) itemView.findViewById(R.id.tx_paymentid);
|
||||||
this.tvTime = (TextView) itemView.findViewById(R.id.tx_time);
|
this.tvDateTime = (TextView) itemView.findViewById(R.id.tx_datetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDate(long time) {
|
private String getDateTime(long time) {
|
||||||
return DATE_FORMATTER.format(new Date(time * 1000));
|
return DATETIME_FORMATTER.format(new Date(time * 1000));
|
||||||
}
|
|
||||||
|
|
||||||
private String getTime(long time) {
|
|
||||||
return TIME_FORMATTER.format(new Date(time * 1000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTxColour(int clr) {
|
private void setTxColour(int clr) {
|
||||||
@@ -147,25 +140,26 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
String displayAmount = Wallet.getDisplayAmount(infoItem.amount);
|
String displayAmount = Wallet.getDisplayAmount(infoItem.amount);
|
||||||
// TODO fix this with i8n code but cryptonote::print_money always uses '.' for decimal point
|
// TODO fix this with i8n code but cryptonote::print_money always uses '.' for decimal point
|
||||||
String amountParts[] = displayAmount.split("\\.");
|
String amountParts[] = displayAmount.split("\\.");
|
||||||
|
amountParts[1] = amountParts[1].substring(0,5);
|
||||||
|
|
||||||
this.tvAmount.setText(amountParts[0]);
|
this.tvAmount.setText(amountParts[0]);
|
||||||
this.tvAmountDecimal.setText(amountParts[1]);
|
this.tvAmountDecimal.setText(amountParts[1]);
|
||||||
if (infoItem.isPending) {
|
if (infoItem.isFailed) {
|
||||||
|
this.tvAmount.setText('(' + amountParts[0]);
|
||||||
|
this.tvAmountDecimal.setText(amountParts[1] + ')');
|
||||||
|
setTxColour(TX_FAILED);
|
||||||
|
} else if (infoItem.isPending) {
|
||||||
setTxColour(TX_PENDING);
|
setTxColour(TX_PENDING);
|
||||||
if (infoItem.direction == TransactionInfo.Direction.Direction_Out) {
|
if (infoItem.direction == TransactionInfo.Direction.Direction_Out) {
|
||||||
this.tvAmount.setText('-' + amountParts[0]);
|
this.tvAmount.setText('-' + amountParts[0]);
|
||||||
}
|
}
|
||||||
} else if (infoItem.isFailed) {
|
|
||||||
this.tvAmount.setText('(' + amountParts[0]);
|
|
||||||
this.tvAmountDecimal.setText(amountParts[1] + ')');
|
|
||||||
setTxColour(TX_FAILED);
|
|
||||||
} else if (infoItem.direction == TransactionInfo.Direction.Direction_In) {
|
} else if (infoItem.direction == TransactionInfo.Direction.Direction_In) {
|
||||||
setTxColour(TX_GREEN);
|
setTxColour(TX_GREEN);
|
||||||
} else {
|
} else {
|
||||||
setTxColour(TX_RED);
|
setTxColour(TX_RED);
|
||||||
}
|
}
|
||||||
this.tvDate.setText(getDate(infoItem.timestamp));
|
this.tvPaymentId.setText(infoItem.paymentId.equals("0000000000000000")?"":infoItem.paymentId);
|
||||||
this.tvTime.setText(getTime(infoItem.timestamp));
|
this.tvDateTime.setText(getDateTime(infoItem.timestamp));
|
||||||
|
|
||||||
itemView.setOnClickListener(this);
|
itemView.setOnClickListener(this);
|
||||||
}
|
}
|
||||||
|
@@ -96,10 +96,13 @@ public class Wallet {
|
|||||||
|
|
||||||
// virtual std::string keysFilename() const = 0;
|
// virtual std::string keysFilename() const = 0;
|
||||||
public boolean init(long upper_transaction_size_limit) {
|
public boolean init(long upper_transaction_size_limit) {
|
||||||
return initJ(WalletManager.getInstance().getDaemonAddress(), upper_transaction_size_limit);
|
return initJ(WalletManager.getInstance().getDaemonAddress(), upper_transaction_size_limit,
|
||||||
|
WalletManager.getInstance().getDaemonUsername(),
|
||||||
|
WalletManager.getInstance().getDaemonPassword());
|
||||||
}
|
}
|
||||||
|
|
||||||
private native boolean initJ(String daemon_address, long upper_transaction_size_limit);
|
private native boolean initJ(String daemon_address, long upper_transaction_size_limit,
|
||||||
|
String daemon_username, String daemon_password);
|
||||||
|
|
||||||
// virtual bool createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const = 0;
|
// virtual bool createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const = 0;
|
||||||
// virtual void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) = 0;
|
// virtual void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) = 0;
|
||||||
|
@@ -197,9 +197,12 @@ public class WalletManager {
|
|||||||
return testnet;
|
return testnet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDaemon(String address, boolean testnet) {
|
public void setDaemon(String address, boolean testnet, String username, String password) {
|
||||||
|
//Log.d(TAG, "SETDAEMON " + username + "/" + password + "/" + address);
|
||||||
this.daemonAddress = address;
|
this.daemonAddress = address;
|
||||||
this.testnet = testnet;
|
this.testnet = testnet;
|
||||||
|
this.daemonUsername = username;
|
||||||
|
this.daemonPassword = password;
|
||||||
setDaemonAddressJ(address);
|
setDaemonAddressJ(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +216,18 @@ public class WalletManager {
|
|||||||
|
|
||||||
private native void setDaemonAddressJ(String address);
|
private native void setDaemonAddressJ(String address);
|
||||||
|
|
||||||
|
String daemonUsername = "";
|
||||||
|
|
||||||
|
public String getDaemonUsername() {
|
||||||
|
return daemonUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
String daemonPassword = "";
|
||||||
|
|
||||||
|
public String getDaemonPassword() {
|
||||||
|
return daemonPassword;
|
||||||
|
}
|
||||||
|
|
||||||
public native int getDaemonVersion();
|
public native int getDaemonVersion();
|
||||||
|
|
||||||
public native long getBlockchainHeight();
|
public native long getBlockchainHeight();
|
||||||
|
@@ -127,6 +127,7 @@ public class WalletService extends Service {
|
|||||||
boolean fullRefresh = false;
|
boolean fullRefresh = false;
|
||||||
updateDaemonState(wallet, wallet.isSynchronized() ? height : 0);
|
updateDaemonState(wallet, wallet.isSynchronized() ? height : 0);
|
||||||
if (!wallet.isSynchronized()) {
|
if (!wallet.isSynchronized()) {
|
||||||
|
updated = true;
|
||||||
// we want to see our transactions as they come in
|
// we want to see our transactions as they come in
|
||||||
wallet.getHistory().refresh();
|
wallet.getHistory().refresh();
|
||||||
int txCount = wallet.getHistory().getCount();
|
int txCount = wallet.getHistory().getCount();
|
||||||
@@ -224,6 +225,8 @@ public class WalletService extends Service {
|
|||||||
void onSentTransaction(boolean success);
|
void onSentTransaction(boolean success);
|
||||||
|
|
||||||
void onSetNotes(boolean success);
|
void onSetNotes(boolean success);
|
||||||
|
|
||||||
|
void onWalletStarted(boolean success);
|
||||||
}
|
}
|
||||||
|
|
||||||
String progressText = null;
|
String progressText = null;
|
||||||
@@ -263,6 +266,8 @@ public class WalletService extends Service {
|
|||||||
private Looper mServiceLooper;
|
private Looper mServiceLooper;
|
||||||
private WalletService.ServiceHandler mServiceHandler;
|
private WalletService.ServiceHandler mServiceHandler;
|
||||||
|
|
||||||
|
private boolean errorState = false;
|
||||||
|
|
||||||
// Handler that receives messages from the thread
|
// Handler that receives messages from the thread
|
||||||
private final class ServiceHandler extends Handler {
|
private final class ServiceHandler extends Handler {
|
||||||
ServiceHandler(Looper looper) {
|
ServiceHandler(Looper looper) {
|
||||||
@@ -272,6 +277,11 @@ public class WalletService extends Service {
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
Log.d(TAG, "Handling " + msg.arg2);
|
Log.d(TAG, "Handling " + msg.arg2);
|
||||||
|
if (errorState) {
|
||||||
|
Log.i(TAG, "In error state.");
|
||||||
|
// also, we have already stopped ourselves
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (msg.arg2) {
|
switch (msg.arg2) {
|
||||||
case START_SERVICE: {
|
case START_SERVICE: {
|
||||||
Bundle extras = msg.getData();
|
Bundle extras = msg.getData();
|
||||||
@@ -283,7 +293,12 @@ public class WalletService extends Service {
|
|||||||
if (walletId != null) {
|
if (walletId != null) {
|
||||||
showProgress(getString(R.string.status_wallet_loading));
|
showProgress(getString(R.string.status_wallet_loading));
|
||||||
showProgress(10);
|
showProgress(10);
|
||||||
start(walletId, walletPw); // TODO What if this fails?
|
boolean success = start(walletId, walletPw);
|
||||||
|
if (observer != null) observer.onWalletStarted(success);
|
||||||
|
if (!success) {
|
||||||
|
errorState = true;
|
||||||
|
stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (cmd.equals(REQUEST_CMD_STORE)) {
|
} else if (cmd.equals(REQUEST_CMD_STORE)) {
|
||||||
Wallet myWallet = getWallet();
|
Wallet myWallet = getWallet();
|
||||||
@@ -327,10 +342,6 @@ public class WalletService extends Service {
|
|||||||
} else if (cmd.equals(REQUEST_CMD_SEND)) {
|
} else if (cmd.equals(REQUEST_CMD_SEND)) {
|
||||||
Wallet myWallet = getWallet();
|
Wallet myWallet = getWallet();
|
||||||
Log.d(TAG, "SEND TX for wallet: " + myWallet.getName());
|
Log.d(TAG, "SEND TX for wallet: " + myWallet.getName());
|
||||||
if (!myWallet.isTestNet()) {
|
|
||||||
Log.e(TAG, "Sending transactions only on testnet");
|
|
||||||
throw new IllegalStateException("Sending transactions only in testnet");
|
|
||||||
}
|
|
||||||
PendingTransaction pendingTransaction = myWallet.getPendingTransaction();
|
PendingTransaction pendingTransaction = myWallet.getPendingTransaction();
|
||||||
if (pendingTransaction.getStatus() != PendingTransaction.Status.Status_Ok) {
|
if (pendingTransaction.getStatus() != PendingTransaction.Status.Status_Ok) {
|
||||||
Log.e(TAG, "PendingTransaction is " + pendingTransaction.getStatus());
|
Log.e(TAG, "PendingTransaction is " + pendingTransaction.getStatus());
|
||||||
@@ -461,7 +472,7 @@ public class WalletService extends Service {
|
|||||||
return true; // true is important so that onUnbind is also called next time
|
return true; // true is important so that onUnbind is also called next time
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start(String walletName, String walletPassword) {
|
private boolean start(String walletName, String walletPassword) {
|
||||||
startNotfication();
|
startNotfication();
|
||||||
// if there is an listener it is always started / syncing
|
// if there is an listener it is always started / syncing
|
||||||
Log.d(TAG, "start()");
|
Log.d(TAG, "start()");
|
||||||
@@ -470,7 +481,10 @@ public class WalletService extends Service {
|
|||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
Log.d(TAG, "start() loadWallet");
|
Log.d(TAG, "start() loadWallet");
|
||||||
Wallet aWallet = loadWallet(walletName, walletPassword);
|
Wallet aWallet = loadWallet(walletName, walletPassword);
|
||||||
// TODO check aWallet and die gracefully if neccessary
|
if ((aWallet == null) || (aWallet.getConnectionStatus() != Wallet.ConnectionStatus.ConnectionStatus_Connected)) {
|
||||||
|
if (aWallet != null) aWallet.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
listener = new MyWalletListener(aWallet);
|
listener = new MyWalletListener(aWallet);
|
||||||
listener.start();
|
listener.start();
|
||||||
showProgress(100);
|
showProgress(100);
|
||||||
@@ -480,6 +494,7 @@ public class WalletService extends Service {
|
|||||||
// if we try to refresh the history here we get occasional segfaults!
|
// if we try to refresh the history here we get occasional segfaults!
|
||||||
// doesnt matter since we update as soon as we get a new block anyway
|
// doesnt matter since we update as soon as we get a new block anyway
|
||||||
Log.d(TAG, "start() done");
|
Log.d(TAG, "start() done");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
@@ -512,7 +527,7 @@ public class WalletService extends Service {
|
|||||||
showProgress(55);
|
showProgress(55);
|
||||||
wallet.init(0);
|
wallet.init(0);
|
||||||
showProgress(90);
|
showProgress(90);
|
||||||
Log.d(TAG, wallet.getConnectionStatus().toString());
|
//Log.d(TAG, wallet.getConnectionStatus().toString());
|
||||||
}
|
}
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
|
28
app/src/main/java/com/m2049r/xmrwallet/util/BarcodeData.java
Normal file
28
app/src/main/java/com/m2049r/xmrwallet/util/BarcodeData.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public class BarcodeData {
|
||||||
|
public String address = null;
|
||||||
|
public String paymentId = null;
|
||||||
|
//String amount = null:
|
||||||
|
|
||||||
|
public BarcodeData(String address, String paymentId) {
|
||||||
|
this.address = address;
|
||||||
|
this.paymentId = paymentId;
|
||||||
|
}
|
||||||
|
}
|
@@ -27,6 +27,7 @@ import android.view.WindowManager;
|
|||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.R;
|
import com.m2049r.xmrwallet.R;
|
||||||
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -71,6 +72,24 @@ public class Helper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final int PERMISSIONS_REQUEST_CAMERA = 1;
|
||||||
|
|
||||||
|
static public boolean getCameraPermission(Activity context) {
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||||
|
if (context.checkSelfPermission(Manifest.permission.CAMERA)
|
||||||
|
== PackageManager.PERMISSION_DENIED) {
|
||||||
|
Log.d(TAG, "Permission denied for CAMERA - requesting it");
|
||||||
|
String[] permissions = {Manifest.permission.CAMERA};
|
||||||
|
context.requestPermissions(permissions, PERMISSIONS_REQUEST_CAMERA);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static public String getWalletPath(Context context, String aWalletName) {
|
static public String getWalletPath(Context context, String aWalletName) {
|
||||||
File walletDir = getStorageRoot(context);
|
File walletDir = getStorageRoot(context);
|
||||||
//d(TAG, "walletdir=" + walletDir.getAbsolutePath());
|
//d(TAG, "walletdir=" + walletDir.getAbsolutePath());
|
||||||
@@ -107,4 +126,14 @@ public class Helper {
|
|||||||
static public void hideKeyboardAlways(Activity act) {
|
static public void hideKeyboardAlways(Activity act) {
|
||||||
act.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
act.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public boolean isAddressOk(String address, boolean testnet) {
|
||||||
|
if (address == null) return false;
|
||||||
|
if (testnet) {
|
||||||
|
return ((address.length() == 95) && ("9A".indexOf(address.charAt(0)) >= 0));
|
||||||
|
} else {
|
||||||
|
return ((address.length() == 95) && ("4".indexOf(address.charAt(0)) >= 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -5,5 +5,5 @@
|
|||||||
android:viewportHeight="24.0">
|
android:viewportHeight="24.0">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FF000000"
|
android:fillColor="#FF000000"
|
||||||
android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
|
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||||
</vector>
|
</vector>
|
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportHeight="24.0"
|
|
||||||
android:viewportWidth="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M11.5,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zm6.5,-6v-5.5c0,-3.07 -2.13,-5.64 -5,-6.32V3.5c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,2.67 10,3.5v0.68c-2.87,0.68 -5,3.25 -5,6.32V16l-2,2v1h17v-1l-2,-2z" />
|
|
||||||
</vector>
|
|
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportHeight="24.0"
|
|
||||||
android:viewportWidth="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01,-.25 1.97,-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0,-4.42,-3.58,-8,-8,-8zm0 14c-3.31 0,-6,-2.69,-6,-6 0,-1.01.25,-1.97.7,-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4,-4,-4,-4v3z" />
|
|
||||||
</vector>
|
|
@@ -4,6 +4,20 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
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>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -12,7 +26,7 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvWalletLabel"
|
android:id="@+id/tvWalletLabel"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/generate_wallet_label"
|
android:text="@string/generate_wallet_label"
|
||||||
@@ -22,7 +36,7 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvWalletPasswordLabel"
|
android:id="@+id/tvWalletPasswordLabel"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/generate_password_label"
|
android:text="@string/generate_password_label"
|
||||||
@@ -58,20 +72,6 @@
|
|||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
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>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvWalletMnemonicLabel"
|
android:id="@+id/tvWalletMnemonicLabel"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -103,10 +103,10 @@
|
|||||||
android:id="@+id/tvWalletAddress"
|
android:id="@+id/tvWalletAddress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:selectAllOnFocus="true"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/colorPrimaryDark"
|
android:textColor="@color/colorPrimaryDark"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:selectAllOnFocus="true"
|
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -123,10 +123,10 @@
|
|||||||
android:id="@+id/tvWalletViewKey"
|
android:id="@+id/tvWalletViewKey"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:selectAllOnFocus="true"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/colorPrimaryDark"
|
android:textColor="@color/colorPrimaryDark"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:selectAllOnFocus="true"
|
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -143,10 +143,10 @@
|
|||||||
android:id="@+id/tvWalletSpendKey"
|
android:id="@+id/tvWalletSpendKey"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:selectAllOnFocus="true"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/colorPrimaryDark"
|
android:textColor="@color/colorPrimaryDark"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:selectAllOnFocus="true"
|
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -157,43 +157,4 @@
|
|||||||
android:background="@color/colorPrimary"
|
android:background="@color/colorPrimary"
|
||||||
android:text="@string/generate_button_accept"
|
android:text="@string/generate_button_accept"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/llFunctions"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="2dip"
|
|
||||||
android:background="@color/colorPrimary" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/bBackup"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:background="@color/colorPrimaryDark"
|
|
||||||
android:text="@string/generate_button_backup" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/bExport"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:background="@color/colorPrimaryDark"
|
|
||||||
android:text="@string/generate_button_export" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/bDelete"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="32dp"
|
|
||||||
android:background="@color/colorAccent"
|
|
||||||
android:text="@string/generate_button_delete" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.Toolbar
|
<android.support.v7.widget.Toolbar
|
||||||
android:id="@+id/tbLogin"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorPrimary"
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/fragment_container"
|
android:id="@+id/fragment_container"
|
||||||
|
android:layout_margin="4sp"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
@@ -17,35 +17,49 @@
|
|||||||
android:textOff="@string/connect_testnet"
|
android:textOff="@string/connect_testnet"
|
||||||
android:textOn="@string/connect_mainnet"
|
android:textOn="@string/connect_mainnet"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent"/>
|
||||||
</ToggleButton>
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/etDaemonAddress"
|
android:id="@+id/etDaemonAddress"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:gravity="center"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/prompt_daemon"
|
|
||||||
android:backgroundTint="@color/colorPrimary"
|
android:backgroundTint="@color/colorPrimary"
|
||||||
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:focusableInTouchMode="true"
|
android:focusableInTouchMode="true"
|
||||||
android:clickable="true"
|
android:gravity="center"
|
||||||
android:inputType="text"
|
android:hint="@string/prompt_daemon"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
|
android:inputType="textWebEmailAddress|textNoSuggestions"
|
||||||
|
android:maxLines="1"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="15sp"
|
android:textSize="15sp"
|
||||||
android:maxLines="1"
|
|
||||||
android:imeOptions="actionDone"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/tbMainNet"
|
app:layout_constraintBaseline_toBaselineOf="@+id/tbMainNet"
|
||||||
app:layout_constraintRight_toLeftOf="@+id/tbMainNet"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent" />
|
app:layout_constraintRight_toLeftOf="@+id/tbMainNet" />
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
||||||
<ListView
|
<FrameLayout
|
||||||
android:id="@+id/list"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginTop="4dp">
|
android:layout_height="match_parent">
|
||||||
</ListView>
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"/>
|
||||||
|
|
||||||
|
<android.support.design.widget.FloatingActionButton xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/fabAdd"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16sp"
|
||||||
|
android:src="@drawable/ic_add_black_24dp"
|
||||||
|
app:elevation="6dp"
|
||||||
|
app:fabSize="auto"
|
||||||
|
app:pressedTranslationZ="12dp" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,96 +1,80 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/card"
|
android:id="@+id/card"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
app:cardBackgroundColor="@color/main_background"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="1dp">
|
android:layout_margin="1sp"
|
||||||
|
app:cardBackgroundColor="@color/main_background">
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8sp"
|
||||||
|
android:layout_marginTop="8sp"
|
||||||
|
tools:layout_editor_absoluteX="0sp"
|
||||||
|
tools:layout_editor_absoluteY="0sp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tx_amount"
|
||||||
|
android:layout_width="60sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:layout_editor_absoluteY="0dp"
|
android:gravity="end"
|
||||||
tools:layout_editor_absoluteX="0dp">
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="9999999"
|
||||||
|
android:textColor="@android:color/holo_red_light"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tx_amount"
|
android:id="@+id/tx_amount_point"
|
||||||
android:gravity="end"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="70sp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:textSize="14sp"
|
||||||
android:text="99999999"
|
android:textStyle="bold"
|
||||||
android:textColor="@android:color/holo_red_light"
|
android:text="."
|
||||||
android:textSize="14sp"
|
android:textColor="@android:color/holo_red_light"
|
||||||
android:textStyle="bold"
|
app:layout_constraintBaseline_toBaselineOf="@+id/tx_amount"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toRightOf="@+id/tx_amount"
|
||||||
android:layout_marginLeft="8dp"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:layout_marginBottom="8dp"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tx_amount_point"
|
android:id="@+id/tx_amount_decimal"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="."
|
android:textSize="14sp"
|
||||||
android:textColor="@android:color/holo_red_light"
|
android:text="99999"
|
||||||
android:textSize="14sp"
|
android:textColor="@android:color/holo_red_light"
|
||||||
android:textStyle="bold"
|
app:layout_constraintBaseline_toBaselineOf="@+id/tx_amount"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/tx_amount"
|
app:layout_constraintLeft_toRightOf="@+id/tx_amount_point"
|
||||||
android:layout_marginLeft="0dp"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:layout_marginBottom="8dp"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tx_amount_decimal"
|
android:id="@+id/tx_paymentid"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="999999999999"
|
android:layout_marginRight="8sp"
|
||||||
android:textColor="@android:color/holo_red_light"
|
android:textSize="13sp"
|
||||||
android:textSize="14sp"
|
android:text="0123456789abcdef"
|
||||||
android:textStyle="bold"
|
app:layout_constraintBaseline_toBaselineOf="@+id/tx_amount"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/tx_amount_point"
|
app:layout_constraintRight_toLeftOf="@+id/tx_datetime"
|
||||||
android:layout_marginLeft="0dp"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:layout_marginBottom="8dp"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tx_date"
|
android:id="@+id/tx_datetime"
|
||||||
android:textColor="@android:color/black"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:textSize="14sp"
|
||||||
android:textSize="14sp"
|
android:text="2017-05-22 21:32"
|
||||||
android:text="2017-05-22"
|
android:textColor="@android:color/black"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintBaseline_toBaselineOf="@+id/tx_amount"
|
||||||
android:layout_marginTop="8dp"
|
app:layout_constraintRight_toLeftOf="parent"
|
||||||
android:layout_marginLeft="8dp"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
app:layout_constraintRight_toLeftOf="@+id/tx_time"
|
|
||||||
android:layout_marginRight="8dp"/>
|
|
||||||
|
|
||||||
<TextView
|
</android.support.constraint.ConstraintLayout>
|
||||||
android:id="@+id/tx_time"
|
|
||||||
android:textColor="@android:color/black"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:text="21:32:11"
|
|
||||||
app:layout_constraintRight_toLeftOf="parent"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:layout_marginBottom="8dp"/>
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.v7.widget.CardView>
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.Toolbar
|
<android.support.v7.widget.Toolbar
|
||||||
android:id="@+id/tbWallet"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorPrimary"
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/fragment_container"
|
android:id="@+id/fragment_container"
|
||||||
|
android:layout_margin="4sp"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
@@ -5,111 +5,124 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp">
|
android:layout_marginBottom="4sp"
|
||||||
|
android:layout_marginLeft="4sp"
|
||||||
<TextView
|
android:layout_marginRight="4sp">
|
||||||
android:id="@+id/tvBalanceLabel"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:text="@string/label_balance"
|
|
||||||
android:textSize="10sp"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/tvBalance"
|
|
||||||
app:layout_constraintRight_toLeftOf="@+id/tvBalance" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvBalance"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:text="00000000.000000000000"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvUnlockedBalanceLabel"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:text="@string/label_unlockedBalance"
|
|
||||||
android:textColor="@color/colorAccent"
|
|
||||||
android:textSize="10sp"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/tvUnlockedBalance"
|
|
||||||
app:layout_constraintRight_toLeftOf="@+id/tvUnlockedBalance" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvUnlockedBalance"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="00000000.000000000000"
|
|
||||||
android:textColor="@color/colorAccent"
|
|
||||||
app:layout_constraintRight_toRightOf="@+id/tvBalance"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/tvBalance" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvConnectionStatus"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:text="Loading..."
|
|
||||||
android:textSize="10sp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/tvBalance" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvBlockHeightProgress"
|
android:id="@+id/tvBlockHeightProgress"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:text="Loading..."
|
android:text="Loading..."
|
||||||
android:textSize="10sp"
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<android.support.constraint.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/clProgress"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/tvUnlockedBalance"/>
|
app:layout_constraintRight_toRightOf="parent">
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
<ProgressBar
|
||||||
|
android:id="@+id/pbProgress"
|
||||||
|
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:progress="0"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent" />
|
||||||
|
|
||||||
<LinearLayout
|
<TextView
|
||||||
android:id="@+id/llProgress"
|
android:id="@+id/tvProgress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:text="Loading..."
|
||||||
android:layout_marginTop="8dp"
|
android:textSize="16sp"
|
||||||
android:gravity="center"
|
android:textColor="@color/white"
|
||||||
android:orientation="vertical"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:visibility="gone">
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent" />
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/tvProgress"
|
android:id="@+id/llBalance"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Loading..."
|
android:layout_marginTop="4dp"
|
||||||
android:textSize="16sp" />
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/tvBlockHeightProgress">
|
||||||
|
|
||||||
<ProgressBar
|
<TextView
|
||||||
android:id="@+id/pbProgress"
|
android:id="@+id/tvBalance"
|
||||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
|
android:text="00000000.000000000000"
|
||||||
|
android:textColor="@color/tx_green"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="4sp"
|
||||||
|
android:text="@string/label_xmr"
|
||||||
|
android:textColor="@color/tx_green"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llUnconfirmedAmount"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:progress="0" />
|
android:orientation="horizontal"
|
||||||
</LinearLayout>
|
android:visibility="visible"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/llBalance">
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<TextView
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="4sp"
|
||||||
|
android:textColor="@color/tx_pending"
|
||||||
|
android:text="+"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvUnconfirmedAmount"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="00000000.000000000000"
|
||||||
|
android:textColor="@color/tx_pending"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="4sp"
|
||||||
|
android:text="@string/label_unconfirmed_alance"
|
||||||
|
android:textColor="@color/tx_pending"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
||||||
|
<android.support.constraint.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/list"
|
android:id="@+id/list"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -125,7 +138,6 @@
|
|||||||
android:id="@+id/bSend"
|
android:id="@+id/bSend"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="@color/colorPrimary"
|
android:background="@color/colorPrimary"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:text="@string/wallet_send_hint"
|
android:text="@string/wallet_send_hint"
|
||||||
@@ -133,5 +145,7 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent" />
|
app:layout_constraintRight_toRightOf="parent" />
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user