mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-06 19:00:30 +02:00
Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7f47307307 | ||
![]() |
165dd3dfd1 | ||
![]() |
171727c9db | ||
![]() |
1492814ec9 | ||
![]() |
9b1225fe4b | ||
![]() |
595d88e42e | ||
![]() |
0e207d7401 | ||
![]() |
5920d6c9e8 | ||
![]() |
44fd3c10fa | ||
![]() |
91ab8a681c | ||
![]() |
d843bdb451 | ||
![]() |
2884fc711c | ||
![]() |
8ea2081270 | ||
![]() |
2296329962 | ||
![]() |
fc1bff2160 | ||
![]() |
e61c2b616e | ||
![]() |
ea1e8ac2c3 | ||
![]() |
1082175089 | ||
![]() |
90d64089a6 | ||
![]() |
b689628975 | ||
![]() |
f8e701aa07 | ||
![]() |
d855328c52 | ||
![]() |
bafe05117b | ||
![]() |
4b7c181040 | ||
![]() |
a3721ae784 | ||
![]() |
ae62c528aa | ||
![]() |
e6522769d0 | ||
![]() |
cab93e8c5e | ||
![]() |
ac78ecb298 | ||
![]() |
51876f788f | ||
![]() |
82c32d4442 | ||
![]() |
22b4905828 | ||
![]() |
0cb8ece336 | ||
![]() |
d2429da044 | ||
![]() |
92d867fbaa | ||
![]() |
a5e3986eb9 | ||
![]() |
8f7f4ee9f9 | ||
![]() |
c23597066a | ||
![]() |
dab5e08910 | ||
![]() |
c35deab283 | ||
![]() |
7c36ccfd9c | ||
![]() |
402d51ec6e | ||
![]() |
ca58211676 | ||
![]() |
97c6ba5334 | ||
![]() |
f1f2f250be | ||
![]() |
7b19e9a2bd | ||
![]() |
ed8010c92c | ||
![]() |
41580e5519 | ||
![]() |
1875e2df62 | ||
![]() |
347123d961 |
11
README.md
11
README.md
@@ -11,22 +11,19 @@ Another Android Monero Wallet
|
|||||||
You may lose all your Moneroj if you use this App. Be cautious when spending on the mainnet.
|
You may lose all your Moneroj if you use this App. Be cautious when spending on the mainnet.
|
||||||
|
|
||||||
### Random Notes
|
### Random Notes
|
||||||
- Based off monero v0.11.0.0 with PR #2289 applied
|
- Based off monero v0.11.1.0
|
||||||
- currently only android32 (runs on 64-bit as well)
|
- currently only android32 (runs on 64-bit as well)
|
||||||
- works on the testnet & mainnet
|
- works on the testnet & mainnet
|
||||||
- sync is slow due to 32-bit architecture
|
- sync is slow due to 32-bit architecture
|
||||||
- use your own daemon - it's easy
|
- use your own daemon - it's easy
|
||||||
- screen stays on until first sync is complete
|
- screen stays on until first sync is complete
|
||||||
- saves wallet only on first sync and when sending transactions or editing notes
|
|
||||||
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
|
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
|
||||||
|
|
||||||
### TODO
|
### TODO
|
||||||
- more sensible error dialogs
|
- see taiga.getmonero.org & issues on github
|
||||||
|
|
||||||
### Issues / Pitfalls
|
### Issues / Pitfalls
|
||||||
- The backups folder is now called "backups" and not ".backups" - which in most file explorers was a hidden folder
|
- You should backup your wallet files in the "monerujo" folder periodically.
|
||||||
- Wallets are now created directly in the "monerujo" folder, and not in the ".new" folder as before
|
|
||||||
- You may want to check the old folders with a file browsing app and delete the ".new" and ".backups" folders AFTER moving neccessary wallet files to the new locations. Or simply make new backups from within Monerujo.
|
|
||||||
- Also note, that on some devices the backups will only be visible on a PC over USB after a reboot of the device (it's an Android bug/feature)
|
- Also note, that on some devices the backups will only be visible on a PC over USB after a reboot of the device (it's an Android bug/feature)
|
||||||
- Created wallets on a private testnet are unusable because the restore height is set to that
|
- Created wallets on a private testnet are unusable because the restore height is set to that
|
||||||
of the "real" testnet. After creating a new wallet, make a **new** one by recovering from the seed.
|
of the "real" testnet. After creating a new wallet, make a **new** one by recovering from the seed.
|
||||||
@@ -36,7 +33,7 @@ The official monero client shows the same behaviour.
|
|||||||
No need to build. Binaries are included:
|
No need to build. Binaries are included:
|
||||||
|
|
||||||
- openssl-1.0.2l
|
- openssl-1.0.2l
|
||||||
- monero-v0.11.0.0 + pull requests #2289
|
- monero-v0.11.1.0
|
||||||
- boost_1_64_0
|
- boost_1_64_0
|
||||||
|
|
||||||
If you want to build them yourself (recommended) check out [the instructions](doc/BUILDING-external-libs.md)
|
If you want to build them yourself (recommended) check out [the instructions](doc/BUILDING-external-libs.md)
|
||||||
|
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "com.m2049r.xmrwallet"
|
applicationId "com.m2049r.xmrwallet"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 42
|
versionCode 67
|
||||||
versionName "1.2.2"
|
versionName "1.3.7 'Satoshis Dream'"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
@@ -27,6 +27,9 @@ android {
|
|||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
|
debug {
|
||||||
|
applicationIdSuffix ".debug"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
@@ -43,28 +46,39 @@ dependencies {
|
|||||||
compile 'com.android.support:cardview-v7:25.4.0'
|
compile 'com.android.support:cardview-v7:25.4.0'
|
||||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||||
compile 'me.dm7.barcodescanner:zxing:1.9.8'
|
compile 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||||
|
|
||||||
|
compile "com.squareup.okhttp3:okhttp:$rootProject.ext.okHttpVersion"
|
||||||
|
compile "com.jakewharton.timber:timber:$rootProject.ext.timberVersion"
|
||||||
|
|
||||||
|
testCompile "junit:junit:$rootProject.ext.junitVersion"
|
||||||
|
testCompile "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
|
||||||
|
testCompile "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion"
|
||||||
|
testCompile 'org.json:json:20140107'
|
||||||
|
testCompile 'net.jodah:concurrentunit:0.4.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'com.android.support:appcompat-v7:70551e62660db15b790c5275f56b9de4dd9407d1494d07c8f3dd5698f3638677',
|
|
||||||
'com.android.support:design:3f409bf2019967ffc344cfaf11e52131fac982468a1707aaeb25bf3c52838966',
|
'com.android.support:design:3f409bf2019967ffc344cfaf11e52131fac982468a1707aaeb25bf3c52838966',
|
||||||
|
'com.android.support:appcompat-v7:70551e62660db15b790c5275f56b9de4dd9407d1494d07c8f3dd5698f3638677',
|
||||||
|
'com.android.support:transition:848270144fb180efd2bf928a00ed176dbbc5290badfd638390ffba90088df8b3',
|
||||||
|
'me.dm7.barcodescanner:zxing:d43973c9527c23fa8e6d338c6a2c458e373ce1ac6bcaa3bc41d11ae49116000d',
|
||||||
|
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
|
||||||
'com.android.support:support-v4:ee44c481a1f4d6978568e223e8125379b52b2ececdd53450e09ebae144bd377d',
|
'com.android.support:support-v4:ee44c481a1f4d6978568e223e8125379b52b2ececdd53450e09ebae144bd377d',
|
||||||
'com.android.support:recyclerview-v7:a2fe121f9d01ed8980e97095b4a3fe9700a0aa0a7d4b0f8c594f765ad8455a0d',
|
'com.android.support:recyclerview-v7:a2fe121f9d01ed8980e97095b4a3fe9700a0aa0a7d4b0f8c594f765ad8455a0d',
|
||||||
'com.android.support:cardview-v7:f3fbbe1fcfdbec7333c6a2c516c5fd511a909d1975271818e268d6fe297d8c70',
|
'com.android.support:cardview-v7:f3fbbe1fcfdbec7333c6a2c516c5fd511a909d1975271818e268d6fe297d8c70',
|
||||||
'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
|
'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
|
||||||
'me.dm7.barcodescanner:zxing:d43973c9527c23fa8e6d338c6a2c458e373ce1ac6bcaa3bc41d11ae49116000d',
|
|
||||||
'com.android.support:support-annotations:a774272036941b4e912eb426d70c848bde7f06a3bf5fb491f75a427dc6595270',
|
|
||||||
'com.android.support:support-vector-drawable:077009d13882ee96f061e4bc2dbe7cce7ae1762d8297592a787ff741afbfb1f2',
|
|
||||||
'com.android.support:animated-vector-drawable:628ab1d56a6ee4cbedf32617af8b2a1fe02964ed0628e8f898cc09ddba6e1835',
|
'com.android.support:animated-vector-drawable:628ab1d56a6ee4cbedf32617af8b2a1fe02964ed0628e8f898cc09ddba6e1835',
|
||||||
'com.android.support:transition:848270144fb180efd2bf928a00ed176dbbc5290badfd638390ffba90088df8b3',
|
'com.android.support:support-vector-drawable:077009d13882ee96f061e4bc2dbe7cce7ae1762d8297592a787ff741afbfb1f2',
|
||||||
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
|
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
|
||||||
|
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
|
||||||
'com.android.support:support-media-compat:566a161d9cb0083ef62a53e46b71ce5b3d455b8635b1a0a4ae28d96d4b583de8',
|
'com.android.support:support-media-compat:566a161d9cb0083ef62a53e46b71ce5b3d455b8635b1a0a4ae28d96d4b583de8',
|
||||||
'com.android.support:support-core-utils:34b8437dfa95ff28d29cf57ffa3b1354a9fa9bfe4059f0fd5ce2f5e4326a1748',
|
'com.android.support:support-core-utils:34b8437dfa95ff28d29cf57ffa3b1354a9fa9bfe4059f0fd5ce2f5e4326a1748',
|
||||||
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
|
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
|
||||||
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
|
'com.android.support:support-annotations:a774272036941b4e912eb426d70c848bde7f06a3bf5fb491f75a427dc6595270',
|
||||||
'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
|
'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
|
||||||
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
|
|
||||||
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
|
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
|
||||||
|
'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
|
||||||
|
'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
BIN
app/src/debug/res/mipmap-hdpi/ic_launcher.png
Executable file
BIN
app/src/debug/res/mipmap-hdpi/ic_launcher.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
BIN
app/src/debug/res/mipmap-mdpi/ic_launcher.png
Executable file
BIN
app/src/debug/res/mipmap-mdpi/ic_launcher.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
BIN
app/src/debug/res/mipmap-xhdpi/ic_launcher.png
Executable file
BIN
app/src/debug/res/mipmap-xhdpi/ic_launcher.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
app/src/debug/res/mipmap-xxhdpi/ic_launcher.png
Executable file
BIN
app/src/debug/res/mipmap-xxhdpi/ic_launcher.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
Executable file
BIN
app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
4
app/src/debug/res/values/strings.xml
Normal file
4
app/src/debug/res/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name" translatable="false">monerujo - Debug</string>
|
||||||
|
</resources>
|
@@ -13,6 +13,7 @@
|
|||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
android:name=".XmrWalletApplication"
|
||||||
android:theme="@style/MyMaterialTheme">
|
android:theme="@style/MyMaterialTheme">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
@@ -22,7 +22,6 @@ import android.support.annotation.Nullable;
|
|||||||
import android.support.design.widget.TextInputLayout;
|
import android.support.design.widget.TextInputLayout;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -33,15 +32,16 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
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 java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class GenerateFragment extends Fragment {
|
public class GenerateFragment extends Fragment {
|
||||||
static final String TAG = "GenerateFragment";
|
|
||||||
|
|
||||||
static final String TYPE = "type";
|
static final String TYPE = "type";
|
||||||
static final String TYPE_NEW = "new";
|
static final String TYPE_NEW = "new";
|
||||||
@@ -366,7 +366,7 @@ public class GenerateFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Timber.d("onResume()");
|
||||||
activityCallback.setTitle(getString(R.string.generate_title) + " - " + getType());
|
activityCallback.setTitle(getString(R.string.generate_title) + " - " + getType());
|
||||||
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
||||||
|
|
||||||
@@ -383,7 +383,7 @@ public class GenerateFragment extends Fragment {
|
|||||||
case TYPE_VIEWONLY:
|
case TYPE_VIEWONLY:
|
||||||
return getString(R.string.generate_wallet_type_view);
|
return getString(R.string.generate_wallet_type_view);
|
||||||
default:
|
default:
|
||||||
Log.e(TAG, "unknown type " + type);
|
Timber.e("unknown type %s", type);
|
||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,6 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -35,14 +34,15 @@ import android.widget.ScrollView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
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.MoneroThreadPoolExecutor;
|
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class GenerateReviewFragment extends Fragment {
|
public class GenerateReviewFragment extends Fragment {
|
||||||
static final String TAG = "GenerateReviewFragment";
|
|
||||||
static final public String VIEW_TYPE_DETAILS = "details";
|
static final public String VIEW_TYPE_DETAILS = "details";
|
||||||
static final public String VIEW_TYPE_ACCEPT = "accept";
|
static final public String VIEW_TYPE_ACCEPT = "accept";
|
||||||
static final public String VIEW_TYPE_WALLET = "wallet";
|
static final public String VIEW_TYPE_WALLET = "wallet";
|
||||||
@@ -103,6 +103,7 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
copyAddress();
|
copyAddress();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
bCopyAddress.setClickable(false);
|
||||||
view.findViewById(R.id.bAdvancedInfo).setOnClickListener(new View.OnClickListener() {
|
view.findViewById(R.id.bAdvancedInfo).setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@@ -213,7 +214,7 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
tvWalletViewKey.setText(viewKey);
|
tvWalletViewKey.setText(viewKey);
|
||||||
tvWalletSpendKey.setText(spendKey);
|
tvWalletSpendKey.setText(spendKey);
|
||||||
bAdvancedInfo.setVisibility(View.VISIBLE);
|
bAdvancedInfo.setVisibility(View.VISIBLE);
|
||||||
bCopyAddress.setEnabled(true);
|
bCopyAddress.setClickable(true);
|
||||||
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
||||||
activityCallback.setTitle(name, getString(R.string.details_title));
|
activityCallback.setTitle(name, getString(R.string.details_title));
|
||||||
activityCallback.setToolbarButton(
|
activityCallback.setToolbarButton(
|
||||||
@@ -264,7 +265,7 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Timber.d("onResume()");
|
||||||
String name = tvWalletName.getText().toString();
|
String name = tvWalletName.getText().toString();
|
||||||
if (name.isEmpty()) name = null;
|
if (name.isEmpty()) name = null;
|
||||||
activityCallback.setTitle(name, getString(R.string.details_title));
|
activityCallback.setTitle(name, getString(R.string.details_title));
|
||||||
@@ -293,5 +294,6 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.wallet_details_menu, menu);
|
inflater.inflate(R.menu.wallet_details_menu, menu);
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,6 @@ import android.support.annotation.Nullable;
|
|||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -44,32 +43,37 @@ import android.widget.RelativeLayout;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.DropDownEditText;
|
import com.m2049r.xmrwallet.dialog.HelpFragment;
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
|
||||||
import com.m2049r.xmrwallet.layout.WalletInfoAdapter;
|
import com.m2049r.xmrwallet.layout.WalletInfoAdapter;
|
||||||
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.NodeList;
|
import com.m2049r.xmrwallet.util.NodeList;
|
||||||
|
import com.m2049r.xmrwallet.widget.DropDownEditText;
|
||||||
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInteractionListener,
|
public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInteractionListener,
|
||||||
View.OnClickListener {
|
View.OnClickListener {
|
||||||
private static final String TAG = "LoginFragment";
|
|
||||||
|
|
||||||
private WalletInfoAdapter adapter;
|
private WalletInfoAdapter adapter;
|
||||||
|
|
||||||
List<WalletManager.WalletInfo> walletList = new ArrayList<>();
|
private List<WalletManager.WalletInfo> walletList = new ArrayList<>();
|
||||||
List<WalletManager.WalletInfo> displayedList = new ArrayList<>();
|
private List<WalletManager.WalletInfo> displayedList = new ArrayList<>();
|
||||||
|
|
||||||
EditText etDummy;
|
private EditText etDummy;
|
||||||
ImageView ivGunther;
|
private ImageView ivGunther;
|
||||||
DropDownEditText etDaemonAddress;
|
private DropDownEditText etDaemonAddress;
|
||||||
ArrayAdapter<String> nodeAdapter;
|
private ArrayAdapter<String> nodeAdapter;
|
||||||
|
|
||||||
Listener activityCallback;
|
private View llXmrToEnabled;
|
||||||
|
private View ibXmrToInfoClose;
|
||||||
|
|
||||||
|
private Listener activityCallback;
|
||||||
|
|
||||||
// Container Activity must implement this interface
|
// Container Activity must implement this interface
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
@@ -112,7 +116,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
Log.d(TAG, "onPause()");
|
Timber.d("onPause()");
|
||||||
savePrefs();
|
savePrefs();
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
@@ -120,7 +124,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Timber.d("onResume()");
|
||||||
activityCallback.setTitle(null);
|
activityCallback.setTitle(null);
|
||||||
activityCallback.setToolbarButton(Toolbar.BUTTON_DONATE);
|
activityCallback.setToolbarButton(Toolbar.BUTTON_DONATE);
|
||||||
activityCallback.showNet(isTestnet());
|
activityCallback.showNet(isTestnet());
|
||||||
@@ -129,7 +133,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
Log.d(TAG, "onCreateView");
|
Timber.d("onCreateView");
|
||||||
View view = inflater.inflate(R.layout.fragment_login, container, false);
|
View view = inflater.inflate(R.layout.fragment_login, container, false);
|
||||||
|
|
||||||
ivGunther = (ImageView) view.findViewById(R.id.ivGunther);
|
ivGunther = (ImageView) view.findViewById(R.id.ivGunther);
|
||||||
@@ -165,6 +169,25 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
etDummy = (EditText) view.findViewById(R.id.etDummy);
|
etDummy = (EditText) view.findViewById(R.id.etDummy);
|
||||||
|
|
||||||
|
llXmrToEnabled = view.findViewById(R.id.llXmrToEnabled);
|
||||||
|
llXmrToEnabled.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
HelpFragment.display(getChildFragmentManager(), R.string.help_xmrto);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ibXmrToInfoClose = view.findViewById(R.id.ibXmrToInfoClose);
|
||||||
|
ibXmrToInfoClose.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
llXmrToEnabled.setVisibility(View.GONE);
|
||||||
|
showXmrtoEnabled = false;
|
||||||
|
saveXmrToPrefs();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
etDaemonAddress = (DropDownEditText) view.findViewById(R.id.etDaemonAddress);
|
etDaemonAddress = (DropDownEditText) view.findViewById(R.id.etDaemonAddress);
|
||||||
nodeAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_dropdown_item_1line);
|
nodeAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_dropdown_item_1line);
|
||||||
etDaemonAddress.setAdapter(nodeAdapter);
|
etDaemonAddress.setAdapter(nodeAdapter);
|
||||||
@@ -211,6 +234,9 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
});
|
});
|
||||||
|
|
||||||
loadPrefs();
|
loadPrefs();
|
||||||
|
if (!showXmrtoEnabled) {
|
||||||
|
llXmrToEnabled.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
@@ -262,7 +288,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadList() {
|
public void loadList() {
|
||||||
Log.d(TAG, "loadList()");
|
Timber.d("loadList()");
|
||||||
WalletManager mgr = WalletManager.getInstance();
|
WalletManager mgr = WalletManager.getInstance();
|
||||||
List<WalletManager.WalletInfo> walletInfos =
|
List<WalletManager.WalletInfo> walletInfos =
|
||||||
mgr.findWallets(activityCallback.getStorageRoot());
|
mgr.findWallets(activityCallback.getStorageRoot());
|
||||||
@@ -290,9 +316,8 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
activityCallback.onWalletDetails(name, isTestnet());
|
activityCallback.onWalletDetails(name, isTestnet());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean showReceive(@NonNull String name) {
|
private void showReceive(@NonNull String name) {
|
||||||
activityCallback.onWalletReceive(name, isTestnet());
|
activityCallback.onWalletReceive(name, isTestnet());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -308,14 +333,14 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean testnet = false;
|
private boolean testnet = BuildConfig.DEBUG;
|
||||||
|
|
||||||
boolean isTestnet() {
|
boolean isTestnet() {
|
||||||
return testnet;
|
return testnet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onTestnetMenuItem() {
|
public boolean onTestnetMenuItem() {
|
||||||
boolean lastState = testnet;//item.isChecked();
|
boolean lastState = testnet;
|
||||||
setNet(!lastState, true); // set and save
|
setNet(!lastState, true); // set and save
|
||||||
return !lastState;
|
return !lastState;
|
||||||
}
|
}
|
||||||
@@ -336,7 +361,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
|
|
||||||
private static final String PREF_DAEMON_TESTNET = "daemon_testnet";
|
private static final String PREF_DAEMON_TESTNET = "daemon_testnet";
|
||||||
private static final String PREF_DAEMON_MAINNET = "daemon_mainnet";
|
private static final String PREF_DAEMON_MAINNET = "daemon_mainnet";
|
||||||
//private static final String PREF_TESTNET = "testnet";
|
private static final String PREF_SHOW_XMRTO_ENABLED = "info_xmrto_enabled_login";
|
||||||
|
|
||||||
private static final String PREF_DAEMONLIST_MAINNET =
|
private static final String PREF_DAEMONLIST_MAINNET =
|
||||||
"node.moneroworld.com:18089;node.xmrbackb.one;node.xmr.be";
|
"node.moneroworld.com:18089;node.xmrbackb.one;node.xmr.be";
|
||||||
@@ -347,22 +372,33 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
private NodeList daemonTestNet;
|
private NodeList daemonTestNet;
|
||||||
private NodeList daemonMainNet;
|
private NodeList daemonMainNet;
|
||||||
|
|
||||||
|
boolean showXmrtoEnabled = true;
|
||||||
|
|
||||||
void loadPrefs() {
|
void loadPrefs() {
|
||||||
SharedPreferences sharedPref = activityCallback.getPrefs();
|
SharedPreferences sharedPref = activityCallback.getPrefs();
|
||||||
|
|
||||||
daemonMainNet = new NodeList(sharedPref.getString(PREF_DAEMON_MAINNET, PREF_DAEMONLIST_MAINNET));
|
daemonMainNet = new NodeList(sharedPref.getString(PREF_DAEMON_MAINNET, PREF_DAEMONLIST_MAINNET));
|
||||||
daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, PREF_DAEMONLIST_TESTNET));
|
daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, PREF_DAEMONLIST_TESTNET));
|
||||||
setNet(isTestnet(), false);
|
setNet(isTestnet(), false);
|
||||||
|
|
||||||
|
showXmrtoEnabled = sharedPref.getBoolean(PREF_SHOW_XMRTO_ENABLED, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveXmrToPrefs() {
|
||||||
|
SharedPreferences sharedPref = activityCallback.getPrefs();
|
||||||
|
SharedPreferences.Editor editor = sharedPref.edit();
|
||||||
|
editor.putBoolean(PREF_SHOW_XMRTO_ENABLED, showXmrtoEnabled);
|
||||||
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
void savePrefs() {
|
void savePrefs() {
|
||||||
savePrefs(false);
|
savePrefs(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void savePrefs(boolean usePreviousState) {
|
void savePrefs(boolean usePreviousTestnetState) {
|
||||||
Log.d(TAG, "SAVE / " + usePreviousState);
|
Timber.d("SAVE / %s", usePreviousTestnetState);
|
||||||
// save the daemon address for the net
|
// save the daemon address for the net
|
||||||
boolean testnet = isTestnet() ^ usePreviousState;
|
boolean testnet = isTestnet() ^ usePreviousTestnetState;
|
||||||
String daemon = getDaemon();
|
String daemon = getDaemon();
|
||||||
if (testnet) {
|
if (testnet) {
|
||||||
daemonTestNet.setRecent(daemon);
|
daemonTestNet.setRecent(daemon);
|
||||||
@@ -372,9 +408,9 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
|
|
||||||
SharedPreferences sharedPref = activityCallback.getPrefs();
|
SharedPreferences sharedPref = activityCallback.getPrefs();
|
||||||
SharedPreferences.Editor editor = sharedPref.edit();
|
SharedPreferences.Editor editor = sharedPref.edit();
|
||||||
//editor.putBoolean(PREF_TESTNET, testnet);
|
|
||||||
editor.putString(PREF_DAEMON_MAINNET, daemonMainNet.toString());
|
editor.putString(PREF_DAEMON_MAINNET, daemonMainNet.toString());
|
||||||
editor.putString(PREF_DAEMON_TESTNET, daemonTestNet.toString());
|
editor.putString(PREF_DAEMON_TESTNET, daemonTestNet.toString());
|
||||||
|
editor.putBoolean(PREF_SHOW_XMRTO_ENABLED, showXmrtoEnabled);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +419,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setDaemon(NodeList nodeList) {
|
void setDaemon(NodeList nodeList) {
|
||||||
Log.d(TAG, "setDaemon() " + nodeList.toString());
|
Timber.d("setDaemon() %s", nodeList.toString());
|
||||||
String[] nodes = nodeList.getNodes().toArray(new String[0]);
|
String[] nodes = nodeList.getNodes().toArray(new String[0]);
|
||||||
nodeAdapter.clear();
|
nodeAdapter.clear();
|
||||||
nodeAdapter.addAll(nodes);
|
nodeAdapter.addAll(nodes);
|
||||||
|
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public interface OnBackPressedListener {
|
||||||
|
boolean onBackPressed();
|
||||||
|
}
|
@@ -19,6 +19,7 @@ package com.m2049r.xmrwallet;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.design.widget.TextInputLayout;
|
import android.support.design.widget.TextInputLayout;
|
||||||
@@ -26,7 +27,6 @@ import android.support.v4.app.Fragment;
|
|||||||
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;
|
||||||
@@ -46,31 +46,32 @@ import com.google.zxing.WriterException;
|
|||||||
import com.google.zxing.common.BitMatrix;
|
import com.google.zxing.common.BitMatrix;
|
||||||
import com.google.zxing.qrcode.QRCodeWriter;
|
import com.google.zxing.qrcode.QRCodeWriter;
|
||||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||||
import com.m2049r.xmrwallet.layout.ExchangeView;
|
import com.m2049r.xmrwallet.data.BarcodeData;
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
|
||||||
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.MoneroThreadPoolExecutor;
|
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||||
|
import com.m2049r.xmrwallet.widget.ExchangeView;
|
||||||
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class ReceiveFragment extends Fragment {
|
public class ReceiveFragment extends Fragment {
|
||||||
static final String TAG = "ReceiveFragment";
|
|
||||||
|
|
||||||
private ProgressBar pbProgress;
|
private ProgressBar pbProgress;
|
||||||
private TextView tvAddress;
|
private TextView tvAddress;
|
||||||
private TextInputLayout etPaymentId;
|
private TextInputLayout etPaymentId;
|
||||||
private ExchangeView evAmount;
|
private ExchangeView evAmount;
|
||||||
private Button bPaymentId;
|
private Button bPaymentId;
|
||||||
private Button bGenerate;
|
private TextView tvQrCode;
|
||||||
private ImageView qrCode;
|
private ImageView qrCode;
|
||||||
|
private ImageView qrCodeFull;
|
||||||
private EditText etDummy;
|
private EditText etDummy;
|
||||||
private ImageButton bCopyAddress;
|
private ImageButton bCopyAddress;
|
||||||
|
|
||||||
//String name;
|
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void setToolbarButton(int type);
|
void setToolbarButton(int type);
|
||||||
|
|
||||||
@@ -91,7 +92,8 @@ public class ReceiveFragment extends Fragment {
|
|||||||
evAmount = (ExchangeView) view.findViewById(R.id.evAmount);
|
evAmount = (ExchangeView) view.findViewById(R.id.evAmount);
|
||||||
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
|
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
|
||||||
qrCode = (ImageView) view.findViewById(R.id.qrCode);
|
qrCode = (ImageView) view.findViewById(R.id.qrCode);
|
||||||
bGenerate = (Button) view.findViewById(R.id.bGenerate);
|
tvQrCode = (TextView) view.findViewById(R.id.tvQrCode);
|
||||||
|
qrCodeFull = (ImageView) view.findViewById(R.id.qrCodeFull);
|
||||||
etDummy = (EditText) view.findViewById(R.id.etDummy);
|
etDummy = (EditText) view.findViewById(R.id.etDummy);
|
||||||
bCopyAddress = (ImageButton) view.findViewById(R.id.bCopyAddress);
|
bCopyAddress = (ImageButton) view.findViewById(R.id.bCopyAddress);
|
||||||
|
|
||||||
@@ -104,11 +106,12 @@ public class ReceiveFragment extends Fragment {
|
|||||||
copyAddress();
|
copyAddress();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
bCopyAddress.setClickable(false);
|
||||||
|
|
||||||
evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() {
|
evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onNewAmount(String xmr) {
|
public void onNewAmount(String xmr) {
|
||||||
Log.d(TAG, "new amount = " + xmr);
|
Timber.d("new amount = %s", xmr);
|
||||||
generateQr();
|
generateQr();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -148,7 +151,6 @@ public class ReceiveFragment extends Fragment {
|
|||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@@ -160,22 +162,33 @@ public class ReceiveFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bGenerate.setOnClickListener(new View.OnClickListener() {
|
qrCode.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (checkPaymentId()) {
|
if (qrValid) {
|
||||||
|
qrCodeFull.setImageBitmap(((BitmapDrawable) qrCode.getDrawable()).getBitmap());
|
||||||
|
qrCodeFull.setVisibility(View.VISIBLE);
|
||||||
|
} else if (checkPaymentId()) {
|
||||||
evAmount.doExchange();
|
evAmount.doExchange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
qrCodeFull.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
qrCodeFull.setImageBitmap(null);
|
||||||
|
qrCodeFull.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
showProgress();
|
showProgress();
|
||||||
clearQR();
|
clearQR();
|
||||||
|
|
||||||
Bundle b = getArguments();
|
Bundle b = getArguments();
|
||||||
String address = b.getString("address");
|
String address = b.getString("address");
|
||||||
String walletName = b.getString("name");
|
String walletName = b.getString("name");
|
||||||
Log.d(TAG, "address=" + address + "/name=" + walletName);
|
Timber.d("%s/%s", address, walletName);
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
String path = b.getString("path");
|
String path = b.getString("path");
|
||||||
String password = b.getString("password");
|
String password = b.getString("password");
|
||||||
@@ -195,14 +208,17 @@ public class ReceiveFragment extends Fragment {
|
|||||||
|
|
||||||
void clearQR() {
|
void clearQR() {
|
||||||
if (qrValid) {
|
if (qrValid) {
|
||||||
qrCode.setImageBitmap(getMoneroLogo());
|
qrCode.setImageBitmap(null);
|
||||||
qrValid = false;
|
qrValid = false;
|
||||||
|
if (isLoaded)
|
||||||
|
tvQrCode.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setQR(Bitmap qr) {
|
void setQR(Bitmap qr) {
|
||||||
qrCode.setImageBitmap(qr);
|
qrCode.setImageBitmap(qr);
|
||||||
qrValid = true;
|
qrValid = true;
|
||||||
|
tvQrCode.setVisibility(View.INVISIBLE);
|
||||||
Helper.hideKeyboard(getActivity());
|
Helper.hideKeyboard(getActivity());
|
||||||
etDummy.requestFocus();
|
etDummy.requestFocus();
|
||||||
}
|
}
|
||||||
@@ -210,21 +226,22 @@ public class ReceiveFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Timber.d("onResume()");
|
||||||
listenerCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
listenerCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
||||||
listenerCallback.setSubtitle(getString(R.string.receive_title));
|
listenerCallback.setSubtitle(getString(R.string.receive_title));
|
||||||
generateQr();
|
generateQr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isLoaded = false;
|
||||||
|
|
||||||
private void show(String name, String address) {
|
private void show(String name, String address) {
|
||||||
Log.d(TAG, "name=" + name);
|
Timber.d("name=%s", name);
|
||||||
|
isLoaded = true;
|
||||||
listenerCallback.setTitle(name);
|
listenerCallback.setTitle(name);
|
||||||
tvAddress.setText(address);
|
tvAddress.setText(address);
|
||||||
etPaymentId.setEnabled(true);
|
etPaymentId.setEnabled(true);
|
||||||
//etAmount.setEnabled(true);
|
|
||||||
bPaymentId.setEnabled(true);
|
bPaymentId.setEnabled(true);
|
||||||
bGenerate.setEnabled(true);
|
bCopyAddress.setClickable(true);
|
||||||
bCopyAddress.setEnabled(true);
|
|
||||||
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
||||||
hideProgress();
|
hideProgress();
|
||||||
generateQr();
|
generateQr();
|
||||||
@@ -278,25 +295,25 @@ public class ReceiveFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateQr() {
|
private void generateQr() {
|
||||||
Log.d(TAG, "GENQR");
|
Timber.d("GENQR");
|
||||||
String address = tvAddress.getText().toString();
|
String address = tvAddress.getText().toString();
|
||||||
String paymentId = etPaymentId.getEditText().getText().toString();
|
String paymentId = etPaymentId.getEditText().getText().toString();
|
||||||
String xmrAmount = evAmount.getAmount();
|
String xmrAmount = evAmount.getAmount();
|
||||||
Log.d(TAG, xmrAmount + "/" + paymentId + "/" + address);
|
Timber.d("%s/%s/%s", xmrAmount, paymentId, address);
|
||||||
if ((xmrAmount == null) || !Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet())) {
|
if ((xmrAmount == null) || !Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet())) {
|
||||||
clearQR();
|
clearQR();
|
||||||
Log.d(TAG, "CLEARQR");
|
Timber.d("CLEARQR");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append(ScannerFragment.QR_SCHEME).append(address);
|
sb.append(BarcodeData.XMR_SCHEME).append(address);
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
if (!paymentId.isEmpty()) {
|
if (!paymentId.isEmpty()) {
|
||||||
if (first) {
|
if (first) {
|
||||||
sb.append("?");
|
sb.append("?");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
sb.append(ScannerFragment.QR_PAYMENTID).append('=').append(paymentId);
|
sb.append(BarcodeData.XMR_PAYMENTID).append('=').append(paymentId);
|
||||||
}
|
}
|
||||||
if (!xmrAmount.isEmpty()) {
|
if (!xmrAmount.isEmpty()) {
|
||||||
if (first) {
|
if (first) {
|
||||||
@@ -304,13 +321,14 @@ public class ReceiveFragment extends Fragment {
|
|||||||
} else {
|
} else {
|
||||||
sb.append("&");
|
sb.append("&");
|
||||||
}
|
}
|
||||||
sb.append(ScannerFragment.QR_AMOUNT).append('=').append(xmrAmount);
|
sb.append(BarcodeData.XMR_AMOUNT).append('=').append(xmrAmount);
|
||||||
}
|
}
|
||||||
String text = sb.toString();
|
String text = sb.toString();
|
||||||
Bitmap qr = generate(text, 500, 500);
|
int size = Math.min(qrCode.getHeight(), qrCode.getWidth());
|
||||||
|
Bitmap qr = generate(text, size, size);
|
||||||
if (qr != null) {
|
if (qr != null) {
|
||||||
setQR(qr);
|
setQR(qr);
|
||||||
Log.d(TAG, "SETQR");
|
Timber.d("SETQR");
|
||||||
etDummy.requestFocus();
|
etDummy.requestFocus();
|
||||||
Helper.hideKeyboard(getActivity());
|
Helper.hideKeyboard(getActivity());
|
||||||
}
|
}
|
||||||
@@ -341,7 +359,6 @@ public class ReceiveFragment extends Fragment {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO check if we can sensibly cache some of this
|
|
||||||
private Bitmap addLogo(Bitmap qrBitmap) {
|
private Bitmap addLogo(Bitmap qrBitmap) {
|
||||||
Bitmap logo = getMoneroLogo();
|
Bitmap logo = getMoneroLogo();
|
||||||
int qrWidth = qrBitmap.getWidth();
|
int qrWidth = qrBitmap.getWidth();
|
||||||
@@ -395,12 +412,9 @@ public class ReceiveFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String PREF_CURRENCY_A = "PREF_CURRENCY_A";
|
|
||||||
static final String PREF_CURRENCY_B = "PREF_CURRENCY_B";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
Log.d(TAG, "onPause()");
|
Timber.d("onPause()");
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,6 @@ import android.content.Context;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
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;
|
||||||
@@ -30,21 +29,21 @@ import com.google.zxing.BarcodeFormat;
|
|||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
|
||||||
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
|
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
|
||||||
static final String TAG = "ScannerFragment";
|
|
||||||
|
|
||||||
private Listener activityCallback;
|
private OnScannedListener onScannedListener;
|
||||||
|
|
||||||
public interface Listener {
|
public interface OnScannedListener {
|
||||||
boolean onAddressScanned(String uri);
|
boolean onScanned(String qrCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZXingScannerView mScannerView;
|
private ZXingScannerView mScannerView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
Log.d(TAG, "onCreateView");
|
Timber.d("onCreateView");
|
||||||
mScannerView = new ZXingScannerView(getActivity());
|
mScannerView = new ZXingScannerView(getActivity());
|
||||||
return mScannerView;
|
return mScannerView;
|
||||||
}
|
}
|
||||||
@@ -52,20 +51,15 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume");
|
Timber.d("onResume");
|
||||||
mScannerView.setResultHandler(this);
|
mScannerView.setResultHandler(this);
|
||||||
mScannerView.startCamera();
|
mScannerView.startCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String QR_SCHEME = "monero:";
|
|
||||||
static final String QR_PAYMENTID = "tx_payment_id";
|
|
||||||
static final String QR_AMOUNT = "tx_amount";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleResult(Result rawResult) {
|
public void handleResult(Result rawResult) {
|
||||||
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
|
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE)) {
|
||||||
(rawResult.getText().startsWith(QR_SCHEME))) {
|
if (onScannedListener.onScanned(rawResult.getText())) {
|
||||||
if (activityCallback.onAddressScanned(rawResult.getText())) {
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
||||||
@@ -91,7 +85,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
Log.d(TAG, "onPause");
|
Timber.d("onPause");
|
||||||
mScannerView.stopCamera();
|
mScannerView.stopCamera();
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
@@ -99,11 +93,11 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
|||||||
@Override
|
@Override
|
||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
if (context instanceof Listener) {
|
if (context instanceof OnScannedListener) {
|
||||||
this.activityCallback = (Listener) context;
|
this.onScannedListener = (OnScannedListener) context;
|
||||||
} else {
|
} else {
|
||||||
throw new ClassCastException(context.toString()
|
throw new ClassCastException(context.toString()
|
||||||
+ " must implement Listener");
|
+ " must implement Listener");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
app/src/main/java/com/m2049r/xmrwallet/SecureActivity.java
Normal file
39
app/src/main/java/com/m2049r/xmrwallet/SecureActivity.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import static android.view.WindowManager.LayoutParams;
|
||||||
|
|
||||||
|
public abstract class SecureActivity extends AppCompatActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// set FLAG_SECURE to prevent screenshots in Release Mode
|
||||||
|
if (!BuildConfig.DEBUG) {
|
||||||
|
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@@ -30,11 +30,14 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
|
||||||
import com.m2049r.xmrwallet.model.TransactionInfo;
|
import com.m2049r.xmrwallet.model.TransactionInfo;
|
||||||
import com.m2049r.xmrwallet.model.Transfer;
|
import com.m2049r.xmrwallet.model.Transfer;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
import com.m2049r.xmrwallet.util.UserNotes;
|
||||||
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@@ -44,7 +47,6 @@ import java.util.Set;
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
public class TxFragment extends Fragment {
|
public class TxFragment extends Fragment {
|
||||||
static final String TAG = "TxFragment";
|
|
||||||
|
|
||||||
static public final String ARG_INFO = "info";
|
static public final String ARG_INFO = "info";
|
||||||
|
|
||||||
@@ -69,12 +71,23 @@ public class TxFragment extends Fragment {
|
|||||||
private TextView etTxNotes;
|
private TextView etTxNotes;
|
||||||
private Button bTxNotes;
|
private Button bTxNotes;
|
||||||
|
|
||||||
|
// XMRTO stuff
|
||||||
|
private View cvXmrTo;
|
||||||
|
private TextView tvTxXmrToKey;
|
||||||
|
private TextView tvDestinationBtc;
|
||||||
|
private TextView tvTxAmountBtc;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.fragment_tx_info, container, false);
|
View view = inflater.inflate(R.layout.fragment_tx_info, container, false);
|
||||||
|
|
||||||
|
cvXmrTo = view.findViewById(R.id.cvXmrTo);
|
||||||
|
tvTxXmrToKey = (TextView) view.findViewById(R.id.tvTxXmrToKey);
|
||||||
|
tvDestinationBtc = (TextView) view.findViewById(R.id.tvDestinationBtc);
|
||||||
|
tvTxAmountBtc = (TextView) view.findViewById(R.id.tvTxAmountBtc);
|
||||||
|
|
||||||
tvTxTimestamp = (TextView) view.findViewById(R.id.tvTxTimestamp);
|
tvTxTimestamp = (TextView) view.findViewById(R.id.tvTxTimestamp);
|
||||||
tvTxId = (TextView) view.findViewById(R.id.tvTxId);
|
tvTxId = (TextView) view.findViewById(R.id.tvTxId);
|
||||||
tvTxKey = (TextView) view.findViewById(R.id.tvTxKey);
|
tvTxKey = (TextView) view.findViewById(R.id.tvTxKey);
|
||||||
@@ -95,7 +108,16 @@ public class TxFragment extends Fragment {
|
|||||||
info.notes = null; // force reload on next view
|
info.notes = null; // force reload on next view
|
||||||
bTxNotes.setEnabled(false);
|
bTxNotes.setEnabled(false);
|
||||||
etTxNotes.setEnabled(false);
|
etTxNotes.setEnabled(false);
|
||||||
activityCallback.onSetNote(info.hash, etTxNotes.getText().toString());
|
userNotes.setNote(etTxNotes.getText().toString());
|
||||||
|
activityCallback.onSetNote(info.hash, userNotes.txNotes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tvTxXmrToKey.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_xmrtokey), tvTxXmrToKey.getText().toString());
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.message_copy_xmrtokey), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -167,8 +189,7 @@ public class TxFragment extends Fragment {
|
|||||||
sb.append("-");
|
sb.append("-");
|
||||||
}
|
}
|
||||||
sb.append("\n\n");
|
sb.append("\n\n");
|
||||||
//Helper.clipBoardCopy(getActivity(), getString(R.string.tx_copy_label), sb.toString());
|
|
||||||
//Toast.makeText(getActivity(), getString(R.string.tx_copy_message), Toast.LENGTH_SHORT).show();
|
|
||||||
Intent sendIntent = new Intent();
|
Intent sendIntent = new Intent();
|
||||||
sendIntent.setAction(Intent.ACTION_SEND);
|
sendIntent.setAction(Intent.ACTION_SEND);
|
||||||
sendIntent.putExtra(Intent.EXTRA_TEXT, sb.toString());
|
sendIntent.putExtra(Intent.EXTRA_TEXT, sb.toString());
|
||||||
@@ -177,12 +198,14 @@ public class TxFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TransactionInfo info = null;
|
TransactionInfo info = null;
|
||||||
|
UserNotes userNotes = null;
|
||||||
|
|
||||||
void loadNotes(TransactionInfo info) {
|
void loadNotes(TransactionInfo info) {
|
||||||
if (info.notes == null) {
|
if ((userNotes == null) || (info.notes == null)) {
|
||||||
info.notes = activityCallback.getTxNotes(info.hash);
|
info.notes = activityCallback.getTxNotes(info.hash);
|
||||||
}
|
}
|
||||||
etTxNotes.setText(info.notes);
|
userNotes = new UserNotes(info.notes);
|
||||||
|
etTxNotes.setText(userNotes.note);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTxColour(int clr) {
|
private void setTxColour(int clr) {
|
||||||
@@ -268,8 +291,21 @@ public class TxFragment extends Fragment {
|
|||||||
tvTxTransfers.setText(sb.toString());
|
tvTxTransfers.setText(sb.toString());
|
||||||
tvDestination.setText(dstSb.toString());
|
tvDestination.setText(dstSb.toString());
|
||||||
this.info = info;
|
this.info = info;
|
||||||
|
showBtcInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showBtcInfo() {
|
||||||
|
if (userNotes.xmrtoKey != null) {
|
||||||
|
cvXmrTo.setVisibility(View.VISIBLE);
|
||||||
|
tvTxXmrToKey.setText(userNotes.xmrtoKey);
|
||||||
|
tvDestinationBtc.setText(userNotes.xmrtoDestination);
|
||||||
|
tvTxAmountBtc.setText(userNotes.xmrtoAmount + " BTC");
|
||||||
|
} else {
|
||||||
|
cvXmrTo.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -309,4 +345,4 @@ public class TxFragment extends Fragment {
|
|||||||
+ " must implement Listener");
|
+ " must implement Listener");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 m2049r et al.
|
||||||
|
*
|
||||||
|
* 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.Application;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class XmrWalletApplication extends Application {
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Timber.plant(new Timber.DebugTree());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
200
app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java
Normal file
200
app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
|
import com.m2049r.xmrwallet.util.BitcoinAddressValidator;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class BarcodeData {
|
||||||
|
public static final String XMR_SCHEME = "monero:";
|
||||||
|
public static final String XMR_PAYMENTID = "tx_payment_id";
|
||||||
|
public static final String XMR_AMOUNT = "tx_amount";
|
||||||
|
|
||||||
|
static final String BTC_SCHEME = "bitcoin:";
|
||||||
|
static final String BTC_AMOUNT = "amount";
|
||||||
|
|
||||||
|
public enum Asset {
|
||||||
|
XMR, BTC
|
||||||
|
}
|
||||||
|
|
||||||
|
public Asset asset = null;
|
||||||
|
public String address = null;
|
||||||
|
public String paymentId = null;
|
||||||
|
public String amount = null;
|
||||||
|
|
||||||
|
public BarcodeData(Asset asset, String address) {
|
||||||
|
this.asset = asset;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BarcodeData(Asset asset, String address, String amount) {
|
||||||
|
this.asset = asset;
|
||||||
|
this.address = address;
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BarcodeData(Asset asset, String address, String paymentId, String amount) {
|
||||||
|
this.asset = asset;
|
||||||
|
this.address = address;
|
||||||
|
this.paymentId = paymentId;
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public BarcodeData fromQrCode(String qrCode) {
|
||||||
|
// check for monero uri
|
||||||
|
BarcodeData bcData = parseMoneroUri(qrCode);
|
||||||
|
// check for naked monero address / integrated address
|
||||||
|
if (bcData == null) {
|
||||||
|
bcData = parseMoneroNaked(qrCode);
|
||||||
|
}
|
||||||
|
// check for btc uri
|
||||||
|
if (bcData == null) {
|
||||||
|
bcData = parseBitcoinUri(qrCode);
|
||||||
|
}
|
||||||
|
// check for naked btc addres
|
||||||
|
if (bcData == null) {
|
||||||
|
bcData = parseBitcoinNaked(qrCode);
|
||||||
|
}
|
||||||
|
return bcData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse and decode a monero scheme string. It is here because it needs to validate the data.
|
||||||
|
*
|
||||||
|
* @param uri String containing a monero URL
|
||||||
|
* @return BarcodeData object or null if uri not valid
|
||||||
|
*/
|
||||||
|
|
||||||
|
static public BarcodeData parseMoneroUri(String uri) {
|
||||||
|
Timber.d("parseMoneroUri=%s", uri);
|
||||||
|
|
||||||
|
if (uri == null) return null;
|
||||||
|
|
||||||
|
if (!uri.startsWith(XMR_SCHEME)) return null;
|
||||||
|
|
||||||
|
String noScheme = uri.substring(XMR_SCHEME.length());
|
||||||
|
Uri monero = Uri.parse(noScheme);
|
||||||
|
Map<String, String> parms = new HashMap<>();
|
||||||
|
String query = monero.getQuery();
|
||||||
|
if (query != null) {
|
||||||
|
String[] args = query.split("&");
|
||||||
|
for (String arg : args) {
|
||||||
|
String[] namevalue = arg.split("=");
|
||||||
|
if (namevalue.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parms.put(Uri.decode(namevalue[0]).toLowerCase(),
|
||||||
|
namevalue.length > 1 ? Uri.decode(namevalue[1]) : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String address = monero.getPath();
|
||||||
|
String paymentId = parms.get(XMR_PAYMENTID);
|
||||||
|
String amount = parms.get(XMR_AMOUNT);
|
||||||
|
if (amount != null) {
|
||||||
|
try {
|
||||||
|
Double.parseDouble(amount);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
Timber.d(ex.getLocalizedMessage());
|
||||||
|
return null; // we have an amount but its not a number!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((paymentId != null) && !Wallet.isPaymentIdValid(paymentId)) {
|
||||||
|
Timber.d("paymentId invalid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Wallet.isAddressValid(address)) {
|
||||||
|
Timber.d("address invalid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new BarcodeData(Asset.XMR, address, paymentId, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public BarcodeData parseMoneroNaked(String address) {
|
||||||
|
Timber.d("parseMoneroNaked=%s", address);
|
||||||
|
|
||||||
|
if (address == null) return null;
|
||||||
|
|
||||||
|
if (!Wallet.isAddressValid(address)) {
|
||||||
|
Timber.d("address invalid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BarcodeData(Asset.XMR, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitcoin:mpQ84J43EURZHkCnXbyQ4PpNDLLBqdsMW2?amount=0.01
|
||||||
|
static public BarcodeData parseBitcoinUri(String uri) {
|
||||||
|
Timber.d("parseBitcoinUri=%s", uri);
|
||||||
|
|
||||||
|
if (uri == null) return null;
|
||||||
|
|
||||||
|
if (!uri.startsWith(BTC_SCHEME)) return null;
|
||||||
|
|
||||||
|
String noScheme = uri.substring(BTC_SCHEME.length());
|
||||||
|
Uri bitcoin = Uri.parse(noScheme);
|
||||||
|
Map<String, String> parms = new HashMap<>();
|
||||||
|
String query = bitcoin.getQuery();
|
||||||
|
if (query != null) {
|
||||||
|
String[] args = query.split("&");
|
||||||
|
for (String arg : args) {
|
||||||
|
String[] namevalue = arg.split("=");
|
||||||
|
if (namevalue.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parms.put(Uri.decode(namevalue[0]).toLowerCase(),
|
||||||
|
namevalue.length > 1 ? Uri.decode(namevalue[1]) : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String address = bitcoin.getPath();
|
||||||
|
String amount = parms.get(BTC_AMOUNT);
|
||||||
|
if (amount != null) {
|
||||||
|
try {
|
||||||
|
Double.parseDouble(amount);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
Timber.d(ex.getLocalizedMessage());
|
||||||
|
return null; // we have an amount but its not a number!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!BitcoinAddressValidator.validate(address, WalletManager.getInstance().isTestNet())) {
|
||||||
|
Timber.d("address invalid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new BarcodeData(BarcodeData.Asset.BTC, address, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public BarcodeData parseBitcoinNaked(String address) {
|
||||||
|
Timber.d("parseBitcoinNaked=%s", address);
|
||||||
|
|
||||||
|
if (address == null) return null;
|
||||||
|
|
||||||
|
if (!BitcoinAddressValidator.validate(address, WalletManager.getInstance().isTestNet())) {
|
||||||
|
Timber.d("address invalid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BarcodeData(BarcodeData.Asset.BTC, address);
|
||||||
|
}
|
||||||
|
}
|
39
app/src/main/java/com/m2049r/xmrwallet/data/PendingTx.java
Normal file
39
app/src/main/java/com/m2049r/xmrwallet/data/PendingTx.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||||
|
|
||||||
|
public class PendingTx {
|
||||||
|
final public PendingTransaction.Status status;
|
||||||
|
final public String error;
|
||||||
|
final public long amount;
|
||||||
|
final public long dust;
|
||||||
|
final public long fee;
|
||||||
|
final public String txId;
|
||||||
|
final public long txCount;
|
||||||
|
|
||||||
|
public PendingTx(PendingTransaction pendingTransaction) {
|
||||||
|
status = pendingTransaction.getStatus();
|
||||||
|
error = pendingTransaction.getErrorString();
|
||||||
|
amount = pendingTransaction.getAmount();
|
||||||
|
dust = pendingTransaction.getDust();
|
||||||
|
fee = pendingTransaction.getFee();
|
||||||
|
txId = pendingTransaction.getFirstTxId();
|
||||||
|
txCount = pendingTransaction.getTxCount();
|
||||||
|
}
|
||||||
|
}
|
@@ -14,36 +14,101 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.m2049r.xmrwallet.util;
|
package com.m2049r.xmrwallet.data;
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.model.PendingTransaction;
|
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||||
|
import com.m2049r.xmrwallet.util.UserNotes;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents
|
// https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents
|
||||||
public class TxData implements Parcelable {
|
public class TxData implements Parcelable {
|
||||||
public TxData(String dst_addr,
|
|
||||||
|
public TxData() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxData(TxData txData) {
|
||||||
|
this.dstAddr = txData.dstAddr;
|
||||||
|
this.paymentId = txData.paymentId;
|
||||||
|
this.amount = txData.amount;
|
||||||
|
this.mixin = txData.mixin;
|
||||||
|
this.priority = txData.priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxData(String dstAddr,
|
||||||
String paymentId,
|
String paymentId,
|
||||||
long amount,
|
long amount,
|
||||||
int mixin,
|
int mixin,
|
||||||
PendingTransaction.Priority priority) {
|
PendingTransaction.Priority priority) {
|
||||||
this.dst_addr = dst_addr;
|
this.dstAddr = dstAddr;
|
||||||
this.paymentId = paymentId;
|
this.paymentId = paymentId;
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
this.mixin = mixin;
|
this.mixin = mixin;
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String dst_addr;
|
public String getDestinationAddress() {
|
||||||
public String paymentId;
|
return dstAddr;
|
||||||
public long amount;
|
}
|
||||||
public int mixin;
|
|
||||||
public PendingTransaction.Priority priority;
|
public String getPaymentId() {
|
||||||
|
return paymentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMixin() {
|
||||||
|
return mixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PendingTransaction.Priority getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestinationAddress(String dstAddr) {
|
||||||
|
this.dstAddr = dstAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPaymentId(String paymentId) {
|
||||||
|
this.paymentId = paymentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(long amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixin(int mixin) {
|
||||||
|
this.mixin = mixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(PendingTransaction.Priority priority) {
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserNotes getUserNotes() {
|
||||||
|
return userNotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserNotes(UserNotes userNotes) {
|
||||||
|
this.userNotes = userNotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String dstAddr;
|
||||||
|
private String paymentId;
|
||||||
|
private long amount;
|
||||||
|
private int mixin;
|
||||||
|
private PendingTransaction.Priority priority;
|
||||||
|
|
||||||
|
private UserNotes userNotes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel out, int flags) {
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
out.writeString(dst_addr);
|
out.writeString(dstAddr);
|
||||||
out.writeString(paymentId);
|
out.writeString(paymentId);
|
||||||
out.writeLong(amount);
|
out.writeLong(amount);
|
||||||
out.writeInt(mixin);
|
out.writeInt(mixin);
|
||||||
@@ -61,8 +126,8 @@ public class TxData implements Parcelable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private TxData(Parcel in) {
|
protected TxData(Parcel in) {
|
||||||
dst_addr = in.readString();
|
dstAddr = in.readString();
|
||||||
paymentId = in.readString();
|
paymentId = in.readString();
|
||||||
amount = in.readLong();
|
amount = in.readLong();
|
||||||
mixin = in.readInt();
|
mixin = in.readInt();
|
||||||
@@ -78,8 +143,8 @@ public class TxData implements Parcelable {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append("dst_addr:");
|
sb.append("dstAddr:");
|
||||||
sb.append(dst_addr);
|
sb.append(dstAddr);
|
||||||
sb.append(",paymentId:");
|
sb.append(",paymentId:");
|
||||||
sb.append(paymentId);
|
sb.append(paymentId);
|
||||||
sb.append(",amount:");
|
sb.append(",amount:");
|
||||||
@@ -87,7 +152,7 @@ public class TxData implements Parcelable {
|
|||||||
sb.append(",mixin:");
|
sb.append(",mixin:");
|
||||||
sb.append(mixin);
|
sb.append(mixin);
|
||||||
sb.append(",priority:");
|
sb.append(",priority:");
|
||||||
sb.append(priority.toString());
|
sb.append(String.valueOf(priority));
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
98
app/src/main/java/com/m2049r/xmrwallet/data/TxDataBtc.java
Normal file
98
app/src/main/java/com/m2049r/xmrwallet/data/TxDataBtc.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||||
|
|
||||||
|
public class TxDataBtc extends TxData {
|
||||||
|
|
||||||
|
private String xmrtoUuid;
|
||||||
|
private String btcAddress;
|
||||||
|
private double btcAmount;
|
||||||
|
|
||||||
|
public TxDataBtc() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxDataBtc(TxDataBtc txDataBtc) {
|
||||||
|
super(txDataBtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getXmrtoUuid() {
|
||||||
|
return xmrtoUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setXmrtoUuid(String xmrtoUuid) {
|
||||||
|
this.xmrtoUuid = xmrtoUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBtcAddress() {
|
||||||
|
return btcAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBtcAddress(String btcAddress) {
|
||||||
|
this.btcAddress = btcAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getBtcAmount() {
|
||||||
|
return btcAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBtcAmount(double btcAmount) {
|
||||||
|
this.btcAmount = btcAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
|
super.writeToParcel(out, flags);
|
||||||
|
out.writeString(xmrtoUuid);
|
||||||
|
out.writeString(btcAddress);
|
||||||
|
out.writeDouble(btcAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
|
||||||
|
public static final Creator<TxDataBtc> CREATOR = new Creator<TxDataBtc>() {
|
||||||
|
public TxDataBtc createFromParcel(Parcel in) {
|
||||||
|
return new TxDataBtc(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxDataBtc[] newArray(int size) {
|
||||||
|
return new TxDataBtc[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected TxDataBtc(Parcel in) {
|
||||||
|
super(in);
|
||||||
|
xmrtoUuid = in.readString();
|
||||||
|
btcAddress = in.readString();
|
||||||
|
btcAmount = in.readDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
sb.append(",xmrtoUuid:");
|
||||||
|
sb.append(xmrtoUuid);
|
||||||
|
sb.append(",btcAddress:");
|
||||||
|
sb.append(btcAddress);
|
||||||
|
sb.append(",btcAmount:");
|
||||||
|
sb.append(btcAmount);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* 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.fragment.send;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.R;
|
||||||
|
import com.m2049r.xmrwallet.data.BarcodeData;
|
||||||
|
import com.m2049r.xmrwallet.data.TxData;
|
||||||
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
import com.m2049r.xmrwallet.widget.ExchangeTextView;
|
||||||
|
import com.m2049r.xmrwallet.widget.NumberPadView;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class SendAmountWizardFragment extends SendWizardFragment {
|
||||||
|
|
||||||
|
public static SendAmountWizardFragment newInstance(Listener listener) {
|
||||||
|
SendAmountWizardFragment instance = new SendAmountWizardFragment();
|
||||||
|
instance.setSendListener(listener);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Listener sendListener;
|
||||||
|
|
||||||
|
public SendAmountWizardFragment setSendListener(Listener listener) {
|
||||||
|
this.sendListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Listener {
|
||||||
|
SendFragment.Listener getActivityCallback();
|
||||||
|
|
||||||
|
TxData getTxData();
|
||||||
|
|
||||||
|
BarcodeData popBarcodeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextView tvFunds;
|
||||||
|
private ExchangeTextView evAmount;
|
||||||
|
//private Button bSendAll;
|
||||||
|
private NumberPadView numberPad;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
Timber.d("onCreateView() %s", (String.valueOf(savedInstanceState)));
|
||||||
|
|
||||||
|
sendListener = (Listener) getParentFragment();
|
||||||
|
|
||||||
|
View view = inflater.inflate(R.layout.fragment_send_amount, container, false);
|
||||||
|
|
||||||
|
tvFunds = (TextView) view.findViewById(R.id.tvFunds);
|
||||||
|
|
||||||
|
evAmount = (ExchangeTextView) view.findViewById(R.id.evAmount);
|
||||||
|
numberPad = (NumberPadView) view.findViewById(R.id.numberPad);
|
||||||
|
numberPad.setListener(evAmount);
|
||||||
|
|
||||||
|
/*
|
||||||
|
bSendAll = (Button) view.findViewById(R.id.bSendAll);
|
||||||
|
bSendAll.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
// TODO: send all - figure out how to display this
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
Helper.hideKeyboard(getActivity());
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onValidateFields() {
|
||||||
|
if (!evAmount.validate(maxFunds)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendListener != null) {
|
||||||
|
String xmr = evAmount.getAmount();
|
||||||
|
if (xmr != null) {
|
||||||
|
sendListener.getTxData().setAmount(Wallet.getAmountFromString(xmr));
|
||||||
|
} else {
|
||||||
|
sendListener.getTxData().setAmount(0L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
double maxFunds = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResumeFragment() {
|
||||||
|
super.onResumeFragment();
|
||||||
|
Timber.d("onResumeFragment()");
|
||||||
|
Helper.hideKeyboard(getActivity());
|
||||||
|
final long funds = getTotalFunds();
|
||||||
|
maxFunds = 1.0 * funds / 1000000000000L;
|
||||||
|
tvFunds.setText(getString(R.string.send_available,
|
||||||
|
Wallet.getDisplayAmount(funds)));
|
||||||
|
// getAmount is null if exchange is in progress
|
||||||
|
if ((evAmount.getAmount() != null) && evAmount.getAmount().isEmpty()) {
|
||||||
|
final BarcodeData data = sendListener.popBarcodeData();
|
||||||
|
if ((data != null) && (data.amount != null)) {
|
||||||
|
evAmount.setAmount(data.amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long getTotalFunds() {
|
||||||
|
return sendListener.getActivityCallback().getTotalFunds();
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -14,16 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.m2049r.xmrwallet.util;
|
package com.m2049r.xmrwallet.fragment.send;
|
||||||
|
|
||||||
public class BarcodeData {
|
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||||
public String address = null;
|
|
||||||
public String paymentId = null;
|
|
||||||
public long amount = -1;
|
|
||||||
|
|
||||||
public BarcodeData(String address, String paymentId, long amount) {
|
interface SendConfirm {
|
||||||
this.address = address;
|
void sendFailed();
|
||||||
this.paymentId = paymentId;
|
|
||||||
this.amount = amount;
|
void createTransactionFailed(String errorText);
|
||||||
}
|
|
||||||
}
|
void transactionCreated(String txTag, PendingTransaction pendingTransaction);
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user