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

Compare commits

...

60 Commits
v0.5.1 ... v0.7

Author SHA1 Message Date
m2049r
4918f44048 Docs updated for 0.7 and bugfixes (#55)
* docs and version

* wallet failed message moved to UI thread

* display balance in pure white
2017-09-10 20:04:21 +02:00
m2049r
924c3fa260 allow back only if not accepting (#54) 2017-09-10 10:40:13 +02:00
m2049r
eb2b3b5675 use MoneroThreadPoolExecutor for wallet creation (#53) 2017-09-10 09:49:21 +02:00
Benedict
7a9bb22da7 Added more files and directories to gitignore (#47)
* added files and directories to gitignore we don't need to change and push

* correct gitignore level for .idea folder
2017-09-09 22:16:58 +02:00
m2049r
c7e745cbc3 Merge pull request #52 from m2049r/feature_kraken
Add support for USD/EUR on receive
2017-09-09 22:16:02 +02:00
m2049r
654caaed22 Merge branch 'master' into feature_kraken 2017-09-09 22:15:37 +02:00
m2049r
b8c287b763 cleanup 2017-09-09 22:02:17 +02:00
m2049r
5c1fa097a9 show alternative currency (USD/EUR) on receive
uses https://www.kraken.com/help/api#get-ticker-info
2017-09-09 19:31:37 +02:00
m2049r
80531740dd Update strings.xml 2017-09-09 12:24:01 +02:00
m2049r
08a62cabab Bugfix: Display of unconfirmed amount (#51)
* fix unconfirmed display

* fix unconfirmed display
2017-09-09 12:22:24 +02:00
m2049r
cf4d8bdbf0 fix unconfirmed display 2017-09-09 09:34:44 +02:00
m2049r
7b690a5086 fix merge conflict in gradle-witness.jar 2017-09-09 01:11:17 +02:00
m2049r
e8e5be35b3 Merge branch 'master' of https://github.com/m2049r/xmrwallet 2017-09-09 01:02:56 +02:00
Benedict
5dbf84d5d6 verify checksum from dependencies 2017-09-09 01:01:47 +02:00
m2049r
bf64f77b10 Upgrade to monero v0.11.0.0 (#50) 2017-09-09 01:01:28 +02:00
m2049r
9b82023a9f UI facelift (#49) 2017-09-09 01:01:27 +02:00
KeeJef
be54900e1f Making a few small changes to the readme
Added a link to the release page 
corrected a few small spelling and grammatical errors
2017-09-09 01:01:27 +02:00
KeeJef
033032639a Revert "Update README.md"
This reverts commit 466fd3bf26.
2017-09-09 01:01:27 +02:00
KeeJef
ab8567692f Update README.md 2017-09-09 01:01:27 +02:00
m2049r
65894664a1 Upgrade to monero v0.11.0.0 (#50) 2017-09-09 00:37:12 +02:00
m2049r
e8f53a5a2f UI facelift (#49) 2017-09-08 23:59:50 +02:00
Benedict
22e0a225b0 verify checksum from dependencies 2017-09-08 22:14:09 +02:00
m2049r
e769f1a472 Merge pull request #46 from KeeJef/master
Small changes to the readme
2017-09-07 15:44:13 +02:00
KeeJef
b447df9ef9 Making a few small changes to the readme
Added a link to the release page 
corrected a few small spelling and grammatical errors
2017-09-07 14:27:49 +10:00
KeeJef
42f4e4a0e9 Revert "Update README.md"
This reverts commit 466fd3bf26.
2017-09-07 14:17:12 +10:00
KeeJef
466fd3bf26 Update README.md 2017-09-07 14:15:07 +10:00
KeeJef
c9bbe1db3f Merge pull request #1 from m2049r/master
Merging Up to date
2017-09-07 14:08:27 +10:00
m2049r
dec67e0675 Revert "Upgrade to monero v0.11.0.0 (#44)" (#45)
This reverts commit 9cbeaa7942.
2017-09-06 21:14:38 +02:00
m2049r
9cbeaa7942 Upgrade to monero v0.11.0.0 (#44)
and minor changes
2017-09-06 21:03:31 +02:00
m2049r
093e4bda1d Doc & Version update (#43)
* added hint that amount is in XMR

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

9
.gitignore vendored
View File

@@ -1,2 +1,9 @@
.gradle
build
/build
*.iml
/.idea/libraries
/.idea/workspace.xml
/local.properties
/captures
.externalNativeBuild
.DS_Store

2
.idea/.gitignore generated vendored
View File

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

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="espresso-core-2.2.2">
<CLASSES>
<root url="file://$USER_HOME$/.android/build-cache/d505abdc89cc7d1b938ec3f95e87d4323360fa14/output/res" />
<root url="jar://$USER_HOME$/.android/build-cache/d505abdc89cc7d1b938ec3f95e87d4323360fa14/output/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/espresso/espresso-core/2.2.2/espresso-core-2.2.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="espresso-idling-resource-2.2.2">
<CLASSES>
<root url="jar://$USER_HOME$/.android/build-cache/0dcbbeb3c862ffabe5d9f3c1f70b25bfdf6c739e/output/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.android/build-cache/0dcbbeb3c862ffabe5d9f3c1f70b25bfdf6c739e/output/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/espresso/espresso-idling-resource/2.2.2/espresso-idling-resource-2.2.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="exposed-instrumentation-api-publish-0.5">
<CLASSES>
<root url="jar://$USER_HOME$/.android/build-cache/c11e9f250159df473b4fbff8b80f455f0be2e5b5/output/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.android/build-cache/c11e9f250159df473b4fbff8b80f455f0be2e5b5/output/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/exposed-instrumentation-api-publish/0.5/exposed-instrumentation-api-publish-0.5-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="hamcrest-core-1.3">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a25dc3219429f0e5d060061f71acb49bf010a0/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b/hamcrest-core-1.3-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="hamcrest-integration-1.3">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-integration/1.3/5de0c73fef18917cd85d0ab70bb23818685e4dfd/hamcrest-integration-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="hamcrest-library-1.3">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-library/1.3/4785a3c21320980282f9f33d0d1264a69040538f/hamcrest-library-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="javawriter-2.1.1">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javawriter/2.1.1/67ff45d9ae02e583d0f9b3432a5ebbe05c30c966/javawriter-2.1.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="javax.annotation-api-1.2">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.annotation/javax.annotation-api/1.2/479c1e06db31c432330183f5cae684163f186146/javax.annotation-api-1.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="javax.inject-1">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.inject/javax.inject/1/6975da39a7040257bd51d21a231b76c915872d38/javax.inject-1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="jsr305-2.0.1">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/2.0.1/516c03b21d50a644d538de0f0369c620989cd8f0/jsr305-2.0.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="junit-4.12">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/2973d150c0dc1fefe998f834810d68f278ea58ec/junit-4.12.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/a6c32b40bf3d76eca54e3c601e5d1470c86fcdfa/junit-4.12-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="rules-0.5">
<CLASSES>
<root url="jar://$USER_HOME$/.android/build-cache/8f8d46a3318b85241b55e25415619e9017c0aef1/output/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.android/build-cache/8f8d46a3318b85241b55e25415619e9017c0aef1/output/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/rules/0.5/rules-0.5-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="runner-0.5">
<CLASSES>
<root url="jar://$USER_HOME$/.android/build-cache/a3a29c4e90c979d7576a0a7d8450261e0065a0a8/output/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.android/build-cache/a3a29c4e90c979d7576a0a7d8450261e0065a0a8/output/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/runner/0.5/runner-0.5-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -2,18 +2,18 @@
Another Android Monero Wallet
### QUICKSTART
- Download APK (Release) and install it
- Download the APK for the most current release [here](https://github.com/m2049r/xmrwallet/releases) and install it
- Run the App and select "Generate Wallet" to create a new wallet or recover a wallet
- Advanced users could copy over synced wallet files (all files) onto sdcard in directory Monerujo (created first time App is started)
- see the [FAQ](doc/FAQ.md)
- Advanced users can copy over synced wallet files (all files) onto sdcard in directory Monerujo (created first time App is started)
- See the [FAQ](doc/FAQ.md)
### Disclaimer
You may loose all your Moneroj if you use this App. Be cautious when spending on mainnet.
You may lose all your Moneroj if you use this App. Be cautious when spending on the mainnet.
### 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.11.0.0 with PR #2289 applied
- currently only android32 (runs on 64-bit as well)
- works in testnet & mainnet
- works on the testnet & mainnet
- takes forever to sync due to 32-bit architecture
- use your own daemon - it's easy
- screen stays on until first sync is complete
@@ -21,13 +21,14 @@ You may loose all your Moneroj if you use this App. Be cautious when spending on
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
### TODO
- wallet backup functions
- review visibility of methods/classes
- more sensible error dialogs
- check licenses of included libraries; License Dialog
### Issues
- Pending incoming transactions disappear after reload (and appear after being mined)
### Issues / Pitfalls
- 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.
The official monero client shows the same behaviour.
### HOW TO BUILD
No need to build. Binaries are included:
@@ -42,4 +43,4 @@ Then, fire up Android Studio and build the APK.
### Donations
- Address: 4AdkPJoxn7JCvAby9szgnt93MSEwdnxdhaASxbTBm6x5dCwmsDep2UYN4FhStDn5i11nsJbpU7oj59ahg8gXb1Mg3viqCuk
- Viewkey: b1aff2a12191723da0afbe75516f94dd8b068215f6e847d8da57aca5f1f98e0c
- Viewkey: b1aff2a12191723da0afbe75516f94dd8b068215f6e847d8da57aca5f1f98e0c

View File

@@ -147,7 +147,7 @@ target_link_libraries( monerujo
blockchain_db
lmdb
#easylogging # not for 0.10.3.1
easylogging
unbound
p2p

View File

@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'witness'
android {
compileSdkVersion 25
@@ -7,8 +8,8 @@ android {
applicationId "com.m2049r.xmrwallet"
minSdkVersion 21
targetSdkVersion 25
versionCode 8
versionName "0.5.1"
versionCode 12
versionName "0.7"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
@@ -35,11 +36,6 @@ android {
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
@@ -47,5 +43,29 @@ dependencies {
compile 'com.android.support:recyclerview-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'
}
dependencyVerification {
verify = [
'com.android.support:design:a3e83064fe99d0a4369f9b46d8bfbe77d0c3022fffdee4be3ac3857b87cc89e3',
'com.android.support:appcompat-v7:ac1ebbc46589195dda3e0b1becfe410bafd75bdf3edd1cd9acf04850f3895830',
'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
'com.android.support:transition:36c688825a8c0e6e879e18886de83dc90673322822d5b606ee302f70fb558e16',
'me.dm7.barcodescanner:zxing:d43973c9527c23fa8e6d338c6a2c458e373ce1ac6bcaa3bc41d11ae49116000d',
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
'com.android.support:support-v4:07d389154bcf73b47e514964df1578136b26cba78257b8a577a3ccb54beff0ae',
'com.android.support:recyclerview-v7:375974a8724e359d97d77fa8522c614f813a3ac4583c1807f154a3f9a054b0a1',
'com.android.support:cardview-v7:defc17032ffa600a82e1c7d96bb574aa5ed64e2b57e28414a245da7d6db0c666',
'com.android.support:animated-vector-drawable:4bc46edf1946b32d518b41416d1734e915e0cbb28021de3b340527419b070691',
'com.android.support:support-vector-drawable:13728f337f36d1c02d52198a6c20724edb447a0875454d829f95cb9eb4aa293b',
'com.android.support:support-fragment:541d6393c1e024453aca2a14f31bea0c7270ff4e2a02783f3528aa426367444d',
'com.android.support:support-media-compat:cbed07d07e0e84fdb4b75712f5fd946229a8af155933c9a92e41db64d00791e0',
'com.android.support:support-core-utils:32fac02eb2c20a77fa3e3bc3ede62392a19613f72b8f8e10f5dfa84bb4c89ea1',
'com.android.support:support-core-ui:6182278a6653e6c111c888963626cbb16f2d0022571cb239760475119e0b92a8',
'com.android.support:support-compat:e02d781268dc60aab6638d8dc20156ea11ca20b962d294b85e6f1e8418cabfa7',
'com.android.support:support-annotations:aedf76962584adfaed2bd3fcaa22406461c4310237fc27e301128edaa2dba2fa',
'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
]
}

View File

@@ -11,10 +11,10 @@
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="@drawable/ic_monero_32dp"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:theme="@style/MyMaterialTheme">
<activity
android:name=".WalletActivity"

View File

@@ -461,12 +461,11 @@ Java_com_m2049r_xmrwallet_model_WalletManager_resolveOpenAlias(JNIEnv *env, jobj
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
// actually a WalletManager function, but logically in onWalletSelected
JNIEXPORT jboolean JNICALL
Java_com_m2049r_xmrwallet_model_WalletManager_closeJ(JNIEnv *env, jobject instance,
jobject walletInstance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, walletInstance);
bool closeSuccess = Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(wallet);
bool closeSuccess = Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(wallet, false);
if (closeSuccess) {
MyWalletListener *walletListener = getHandle<MyWalletListener>(env, walletInstance,
"listenerHandle");
@@ -564,8 +563,13 @@ Java_com_m2049r_xmrwallet_model_Wallet_getIntegratedAddress(JNIEnv *env, jobject
JNIEXPORT jstring JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getSecretViewKey(JNIEnv *env, jobject instance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
//return env->NewStringUTF(wallet->secretViewKey().c_str()); // changed in head
return env->NewStringUTF(wallet->privateViewKey().c_str());
return env->NewStringUTF(wallet->secretViewKey().c_str());
}
JNIEXPORT jstring JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getSecretSpendKey(JNIEnv *env, jobject instance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return env->NewStringUTF(wallet->secretSpendKey().c_str());
}
JNIEXPORT jboolean JNICALL

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -16,12 +16,13 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
@@ -82,9 +83,17 @@ public class LoginFragment extends Fragment {
File getStorageRoot();
void onWalletSelected(final String wallet);
void onWalletSelected(String wallet);
void onWalletDetails(final String wallet);
void onWalletDetails(String wallet);
void onWalletReceive(String wallet);
void onWalletRename(String name);
void onWalletBackup(String name);
void onWalletArchive(String walletName);
void onAddWallet();
@@ -117,14 +126,14 @@ public class LoginFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onPause()");
Log.d(TAG, "onResume()");
activityCallback.setTitle(getString(R.string.login_activity_name));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.login_fragment, container, false);
tbMainNet = (ToggleButton) view.findViewById(R.id.tbMainNet);
@@ -222,31 +231,6 @@ public class LoginFragment extends Fragment {
}
});
/* listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// Difference to opening wallet is that we don't need a daemon set
String itemValue = (String) listView.getItemAtPosition(position);
if (itemValue.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
return true;
}
String wallet = itemValue.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = isMainNet() ? "4" : "9A";
if (x.indexOf(itemValue.charAt(1)) < 0) {
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
return true;
}
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(wallet);
return true;
}
});
*/
loadList();
return view;
}
@@ -255,24 +239,26 @@ public class LoginFragment extends Fragment {
displayedList.clear();
String x = isMainNet() ? "4" : "9A";
for (String s : walletList) {
// Log.d(TAG, "filtering " + s);
if (x.indexOf(s.charAt(1)) >= 0) displayedList.add(s);
}
}
private void loadList() {
public void loadList() {
Log.d(TAG, "loadList()");
WalletManager mgr = WalletManager.getInstance();
List<WalletManager.WalletInfo> walletInfos =
mgr.findWallets(activityCallback.getStorageRoot());
walletList.clear();
for (WalletManager.WalletInfo walletInfo : walletInfos) {
// Log.d(TAG, walletInfo.address);
// ONCE the walletInfo.address was null - because the address.txt was empty
// this was before the wallet generation was in its own therad with huge stack
// TODO: keep an eye on Wallet.getAddress() returning empty
String displayAddress = walletInfo.address;
if (displayAddress.length() == 95) {
if ((displayAddress != null) && displayAddress.length() == 95) {
displayAddress = walletInfo.address.substring(0, 6);
walletList.add("[" + displayAddress + "] " + walletInfo.name);
}
walletList.add("[" + displayAddress + "] " + walletInfo.name);
}
filterList();
((BaseAdapter) listView.getAdapter()).notifyDataSetChanged();
@@ -408,32 +394,52 @@ public class LoginFragment extends Fragment {
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
String listItem = (String) listView.getItemAtPosition(info.position);
String name = nameFromListItem(listItem, !isMainNet());
if (name == null) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
}
switch (item.getItemId()) {
case R.id.action_info:
String listItem = (String) listView.getItemAtPosition(info.position);
return showInfo(listItem);
showInfo(name);
break;
case R.id.action_receive:
showReceive(name);
break;
case R.id.action_rename:
activityCallback.onWalletRename(name);
break;
case R.id.action_backup:
activityCallback.onWalletBackup(name);
break;
case R.id.action_archive:
activityCallback.onWalletArchive(name);
break;
default:
return super.onContextItemSelected(item);
}
}
private boolean showInfo(String listItem) {
if (listItem.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
return true;
}
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = isMainNet() ? "4" : "9A";
if (x.indexOf(listItem.charAt(1)) < 0) {
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
return true;
}
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(wallet);
return true;
}
private void showInfo(@NonNull String name) {
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(name);
}
private boolean showReceive(@NonNull String name) {
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletReceive(name);
return true;
}
private String nameFromListItem(String listItem, boolean testnet) {
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = testnet ? "9A" : "4";
if (x.indexOf(listItem.charAt(1)) < 0) {
return null;
}
return wallet;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,10 +16,10 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -28,8 +28,7 @@ import android.widget.Toast;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.BarcodeData;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
@@ -39,9 +38,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
Listener activityCallback;
public interface Listener {
void onAddressScanned(String address, String paymentId);
boolean isPaymentIdValid(String paymentId);
boolean onAddressScanned(String uri);
}
private ZXingScannerView mScannerView;
@@ -61,32 +58,16 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
mScannerView.startCamera();
}
static final String URI_PREFIX = "monero:";
static final String PAYMENTID_STRING = "?tx_payment_id=";
static final String QR_SCHEME = "monero:";
static final String QR_PAYMENTID = "tx_payment_id";
static final String QR_AMOUNT = "tx_amount";
@Override
public void handleResult(Result rawResult) {
Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
String text = rawResult.getText();
//Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
(text.startsWith(URI_PREFIX))) {
String address = null;
String paymentId = null;
String s = text.substring(URI_PREFIX.length());
if (s.length() == 95) {
address = s;
} else {
int i = s.indexOf(PAYMENTID_STRING);
if ((i == 95) && (s.length() == (95 + PAYMENTID_STRING.length() + 16))) {
address = s.substring(0, 95);
paymentId = s.substring(95 + PAYMENTID_STRING.length());
if (!activityCallback.isPaymentIdValid(paymentId)) {
address = null;
}
}
}
if (Helper.isAddressOk(address, WalletManager.getInstance().isTestNet())) {
activityCallback.onAddressScanned(address, paymentId);
(rawResult.getText().startsWith(QR_SCHEME))) {
if (activityCallback.onAddressScanned(rawResult.getText())) {
return;
} else {
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
@@ -120,7 +101,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d(TAG, "attaching scan");
//Log.d(TAG, "attaching scan");
if (context instanceof Listener) {
this.activityCallback = (Listener) context;
} else {

View File

@@ -16,11 +16,11 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.InputType;
@@ -51,7 +51,7 @@ public class SendFragment extends Fragment {
EditText etAddress;
EditText etPaymentId;
EditText etAmount;
Button bAddress;
Button bScan;
Button bSweep;
Spinner sMixin;
Spinner sPriority;
@@ -67,9 +67,10 @@ public class SendFragment extends Fragment {
Button bReallySend;
ProgressBar pbProgress;
final static int Mixins[] = {4, 6, 8, 10, 13}; // must match the layout XML
final static int Mixins[] = {4, 7, 12, 25}; // must match the layout XML
final static PendingTransaction.Priority Priorities[] =
{PendingTransaction.Priority.Priority_Low,
{PendingTransaction.Priority.Priority_Default,
PendingTransaction.Priority.Priority_Low,
PendingTransaction.Priority.Priority_Medium,
PendingTransaction.Priority.Priority_High}; // must match the layout XML
@@ -84,7 +85,7 @@ public class SendFragment extends Fragment {
etAddress = (EditText) view.findViewById(R.id.etAddress);
etPaymentId = (EditText) view.findViewById(R.id.etPaymentId);
etAmount = (EditText) view.findViewById(R.id.etAmount);
bAddress = (Button) view.findViewById(R.id.bAddress);
bScan = (Button) view.findViewById(R.id.bScan);
bSweep = (Button) view.findViewById(R.id.bSweep);
bPrepareSend = (Button) view.findViewById(R.id.bPrepareSend);
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
@@ -100,8 +101,8 @@ public class SendFragment extends Fragment {
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
etAddress.setRawInputType(InputType.TYPE_CLASS_TEXT);
etPaymentId.setRawInputType(InputType.TYPE_CLASS_TEXT);
etAddress.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etPaymentId.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
Helper.showKeyboard(getActivity());
@@ -199,7 +200,7 @@ public class SendFragment extends Fragment {
}
});
bAddress.setOnClickListener(new View.OnClickListener() {
bScan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
activityCallback.onScanAddress();
@@ -209,7 +210,8 @@ public class SendFragment extends Fragment {
bPaymentId.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
etPaymentId.setText((activityCallback.generatePaymentId()));
etPaymentId.setText((Wallet.generatePaymentId()));
etPaymentId.setSelection(etPaymentId.getText().length());
}
});
@@ -285,7 +287,7 @@ public class SendFragment extends Fragment {
private boolean paymentIdOk() {
String paymentId = etPaymentId.getText().toString();
return paymentId.isEmpty() || activityCallback.isPaymentIdValid(paymentId);
return paymentId.isEmpty() || Wallet.isPaymentIdValid(paymentId);
}
private void prepareSend() {
@@ -321,6 +323,7 @@ public class SendFragment extends Fragment {
etAddress.setEnabled(false);
etPaymentId.setEnabled(false);
etAmount.setEnabled(false);
bScan.setEnabled(false);
bPaymentId.setEnabled(false);
bSweep.setEnabled(false);
bPrepareSend.setEnabled(false);
@@ -332,6 +335,7 @@ public class SendFragment extends Fragment {
etAddress.setEnabled(true);
etPaymentId.setEnabled(true);
etAmount.setEnabled(true);
bScan.setEnabled(true);
bPaymentId.setEnabled(true);
bSweep.setEnabled(true);
bPrepareSend.setEnabled(true);
@@ -356,10 +360,6 @@ public class SendFragment extends Fragment {
void onSend(String notes);
String generatePaymentId();
boolean isPaymentIdValid(String paymentId);
String getWalletAddress();
void onDisposeRequest();
@@ -373,26 +373,40 @@ public class SendFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
BarcodeData data = activityCallback.getScannedData();
if (data != null) {
String scannedAddress = data.address;
if (scannedAddress != null) {
etAddress.setText(scannedAddress);
} else {
etAddress.getText().clear();
}
String scannedPaymenId = data.paymentId;
if (scannedPaymenId != null) {
etPaymentId.setText(scannedPaymenId);
} else {
etPaymentId.getText().clear();
}
if (data.amount >= 0) {
String scannedAmount = Helper.getDisplayAmount(data.amount);
etAmount.setText(scannedAmount);
} else {
etAmount.getText().clear();
}
etAmount.requestFocus();
etAmount.setSelection(etAmount.getText().length());
} else { // no scan data
// jump to first empty field
if (etAddress.getText().toString().isEmpty()) {
etAddress.requestFocus();
} else if (etPaymentId.getText().toString().isEmpty()) {
etPaymentId.requestFocus();
} else {
etAmount.requestFocus();
etAmount.setSelection(etAmount.getText().length());
}
}
// jump to first empty field
if (etAddress.getText().toString().isEmpty()) {
etAddress.requestFocus();
} else if (etPaymentId.getText().toString().isEmpty()) {
etPaymentId.requestFocus();
} else {
etAmount.requestFocus();
}
Log.d(TAG, "onResume");
}
@Override
@@ -430,6 +444,7 @@ public class SendFragment extends Fragment {
}
});
builder.setMessage(errorText);
builder.setCancelable(false);
builder.create().show();
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -16,21 +16,20 @@
package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.v7.app.AlertDialog;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -38,9 +37,8 @@ import android.widget.TextView;
import com.m2049r.xmrwallet.layout.TransactionInfoAdapter;
import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Transfer;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import java.text.NumberFormat;
import java.util.List;
@@ -51,7 +49,6 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
private NumberFormat formatter = NumberFormat.getInstance();
TextView tvBalance;
LinearLayout llUnconfirmedAmount;
TextView tvUnconfirmedAmount;
TextView tvBlockHeightProgress;
ConstraintLayout clProgress;
@@ -59,6 +56,19 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
ProgressBar pbProgress;
Button bSend;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (activityCallback.hasWallet())
inflater.inflate(R.menu.wallet_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -67,21 +77,17 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
tvProgress = (TextView) view.findViewById(R.id.tvProgress);
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
clProgress = (ConstraintLayout) view.findViewById(R.id.clProgress);
llUnconfirmedAmount = (LinearLayout) view.findViewById(R.id.llUnconfirmedAmount);
tvBalance = (TextView) view.findViewById(R.id.tvBalance);
tvBalance.setText(getDisplayAmount(0));
tvBalance.setText(getResources().getString(R.string.xmr_balance, Helper.getDisplayAmount(0)));
tvUnconfirmedAmount = (TextView) view.findViewById(R.id.tvUnconfirmedAmount);
tvUnconfirmedAmount.setText(getDisplayAmount(0));
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, Helper.getDisplayAmount(0)));
tvBlockHeightProgress = (TextView) view.findViewById(R.id.tvBlockHeightProgress);
bSend = (Button) view.findViewById(R.id.bSend);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list);
RecyclerView.ItemDecoration itemDecoration = new
DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(itemDecoration);
this.adapter = new TransactionInfoAdapter(this);
this.adapter = new TransactionInfoAdapter(getActivity(), this);
recyclerView.setAdapter(adapter);
bSend.setOnClickListener(new View.OnClickListener()
@@ -150,10 +156,12 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
public void showProgress() {
clProgress.setVisibility(View.VISIBLE);
tvBlockHeightProgress.setVisibility(View.GONE);
}
public void hideProgress() {
clProgress.setVisibility(View.GONE);
tvBlockHeightProgress.setVisibility(View.VISIBLE);
}
String setActivityTitle(Wallet wallet) {
@@ -162,6 +170,8 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
if (shortName.length() > 16) {
shortName = shortName.substring(0, 14) + "...";
}
// TODO very very rarely this craches because getAddress returns "" or so ...
// maybe because this runs in the ui thread and not in a 5MB thread
String title = "[" + wallet.getAddress().substring(0, 6) + "] " + shortName;
activityCallback.setTitle(title);
@@ -175,23 +185,6 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
private long firstBlock = 0;
private String walletTitle = null;
private String getDisplayAmount(long amount) {
String s = Wallet.getDisplayAmount(amount);
int lastZero = 0;
int decimal = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if ((lastZero == 0) && (s.charAt(i) != '0')) lastZero = i + 1;
// TODO i18n
if (s.charAt(i) == '.') {
decimal = i;
break;
}
}
//Log.d(TAG, decimal + "/" + lastZero + "/" + s);
int cutoff = Math.max(lastZero, decimal + 2);
return s.substring(0, cutoff);
}
private void updateStatus(Wallet wallet) {
Log.d(TAG, "updateStatus()");
if (walletTitle == null) {
@@ -200,14 +193,8 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
}
long balance = wallet.getBalance();
long unlockedBalance = wallet.getUnlockedBalance();
tvBalance.setText(getDisplayAmount(unlockedBalance));
tvUnconfirmedAmount.setText(getDisplayAmount(balance - unlockedBalance));
// balance cannot be less than unlockedBalance
/*if (balance != unlockedBalance) {
llPendingAmount.setVisibility(View.VISIBLE);
} else {
llPendingAmount.setVisibility(View.INVISIBLE);
}*/
tvBalance.setText(getResources().getString(R.string.xmr_balance, Helper.getDisplayAmount(unlockedBalance)));
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, Helper.getDisplayAmount(balance - unlockedBalance)));
String sync = "";
if (!activityCallback.hasBoundService())
throw new IllegalStateException("WalletService not bound.");
@@ -259,6 +246,10 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
boolean isWatchOnly();
String getTxKey(String txId);
void onWalletReceive();
boolean hasWallet();
}
@Override

View File

@@ -16,7 +16,9 @@
package com.m2049r.xmrwallet.layout;
import android.content.Context;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
@@ -42,10 +44,15 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
static final int TX_RED = Color.rgb(255, 79, 65);
static final int TX_GREEN = Color.rgb(54, 176, 91);
static final int TX_PENDING = Color.rgb(72, 53, 176);
static final int TX_FAILED = Color.rgb(208, 0, 255);
//static final int TX_RED = Color.rgb(255, 79, 65);
//static final int TX_GREEN = Color.rgb(54, 176, 91);
//static final int TX_PENDING = Color.rgb(72, 53, 176);
//static final int TX_FAILED = Color.rgb(208, 0, 255);
int outboundColour;
int inboundColour;
int pendingColour;
int failedColour;
public interface OnInteractionListener {
void onInteraction(View view, TransactionInfo item);
@@ -54,7 +61,14 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
private final List<TransactionInfo> infoItems;
private final OnInteractionListener listener;
public TransactionInfoAdapter(OnInteractionListener listener) {
Context context;
public TransactionInfoAdapter(Context context, OnInteractionListener listener) {
this.context = context;
inboundColour = ContextCompat.getColor(context, R.color.tx_green);
outboundColour = ContextCompat.getColor(context, R.color.tx_red);
pendingColour = ContextCompat.getColor(context, R.color.tx_pending);
failedColour = ContextCompat.getColor(context, R.color.tx_failed);
this.infoItems = new ArrayList<>();
this.listener = listener;
Calendar cal = Calendar.getInstance();
@@ -109,8 +123,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
final TextView tvAmount;
final TextView tvAmountPoint;
final TextView tvAmountDecimal;
final TextView tvFee;
final TextView tvPaymentId;
final TextView tvDateTime;
TransactionInfo infoItem;
@@ -118,9 +131,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
ViewHolder(View itemView) {
super(itemView);
this.tvAmount = (TextView) itemView.findViewById(R.id.tx_amount);
// 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.tvAmountDecimal = (TextView) itemView.findViewById(R.id.tx_amount_decimal);
this.tvFee = (TextView) itemView.findViewById(R.id.tx_fee);
this.tvPaymentId = (TextView) itemView.findViewById(R.id.tx_paymentid);
this.tvDateTime = (TextView) itemView.findViewById(R.id.tx_datetime);
}
@@ -131,34 +142,41 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
private void setTxColour(int clr) {
tvAmount.setTextColor(clr);
tvAmountDecimal.setTextColor(clr);
tvAmountPoint.setTextColor(clr);
tvFee.setTextColor(clr);
}
void bind(int position) {
this.infoItem = infoItems.get(position);
String displayAmount = Wallet.getDisplayAmount(infoItem.amount);
// TODO fix this with i8n code but cryptonote::print_money always uses '.' for decimal point
String amountParts[] = displayAmount.split("\\.");
amountParts[1] = amountParts[1].substring(0,5);
String amount = displayAmount.substring(0, displayAmount.length() - (12 - 5));
this.tvAmount.setText(amount);
this.tvAmount.setText(amountParts[0]);
this.tvAmountDecimal.setText(amountParts[1]);
if ((infoItem.fee > 0)) {
String feeAmount = Wallet.getDisplayAmount(infoItem.fee);
String fee = feeAmount.substring(0, feeAmount.length() - (12 - 5));
if (infoItem.isPending) {
this.tvFee.setText(context.getString(R.string.tx_list_fee_pending, fee));
} else {
this.tvFee.setText(context.getString(R.string.tx_list_fee, fee));
}
} else {
this.tvFee.setText("");
}
if (infoItem.isFailed) {
this.tvAmount.setText('(' + amountParts[0]);
this.tvAmountDecimal.setText(amountParts[1] + ')');
setTxColour(TX_FAILED);
this.tvAmount.setText(context.getString(R.string.tx_list_amount_failed, amount));
setTxColour(failedColour);
} else if (infoItem.isPending) {
setTxColour(TX_PENDING);
setTxColour(pendingColour);
if (infoItem.direction == TransactionInfo.Direction.Direction_Out) {
this.tvAmount.setText('-' + amountParts[0]);
this.tvAmount.setText(context.getString(R.string.tx_list_amount_negative, amount));
}
} else if (infoItem.direction == TransactionInfo.Direction.Direction_In) {
setTxColour(TX_GREEN);
setTxColour(inboundColour);
} else {
setTxColour(TX_RED);
setTxColour(outboundColour);
}
this.tvPaymentId.setText(infoItem.paymentId.equals("0000000000000000")?"":infoItem.paymentId);
this.tvPaymentId.setText(infoItem.paymentId.equals("0000000000000000") ? "" : infoItem.paymentId);
this.tvDateTime.setText(getDateTime(infoItem.timestamp));
itemView.setOnClickListener(this);

View File

@@ -34,6 +34,7 @@ public class PendingTransaction {
}
public enum Priority {
Priority_Default(0),
Priority_Low(1),
Priority_Medium(2),
Priority_High(3),
@@ -41,6 +42,8 @@ public class PendingTransaction {
public static Priority fromInteger(int n) {
switch (n) {
case 0:
return Priority_Default;
case 1:
return Priority_Low;
case 2:

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