mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-04 17:28:42 +02:00
Compare commits
60 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4918f44048 | ||
![]() |
924c3fa260 | ||
![]() |
eb2b3b5675 | ||
![]() |
7a9bb22da7 | ||
![]() |
c7e745cbc3 | ||
![]() |
654caaed22 | ||
![]() |
b8c287b763 | ||
![]() |
5c1fa097a9 | ||
![]() |
80531740dd | ||
![]() |
08a62cabab | ||
![]() |
cf4d8bdbf0 | ||
![]() |
7b690a5086 | ||
![]() |
e8e5be35b3 | ||
![]() |
5dbf84d5d6 | ||
![]() |
bf64f77b10 | ||
![]() |
9b82023a9f | ||
![]() |
be54900e1f | ||
![]() |
033032639a | ||
![]() |
ab8567692f | ||
![]() |
65894664a1 | ||
![]() |
e8f53a5a2f | ||
![]() |
22e0a225b0 | ||
![]() |
e769f1a472 | ||
![]() |
b447df9ef9 | ||
![]() |
42f4e4a0e9 | ||
![]() |
466fd3bf26 | ||
![]() |
c9bbe1db3f | ||
![]() |
dec67e0675 | ||
![]() |
9cbeaa7942 | ||
![]() |
093e4bda1d | ||
![]() |
4aa7000cb3 | ||
![]() |
62844192df | ||
![]() |
855b35a6b7 | ||
![]() |
88110b702f | ||
![]() |
0013caa05f | ||
![]() |
5b3e92e91a | ||
![]() |
f8ea3cc77f | ||
![]() |
59ef2a1f8e | ||
![]() |
fae07ed716 | ||
![]() |
e662d5a9c0 | ||
![]() |
4b2d52fbe6 | ||
![]() |
ec7798cb34 | ||
![]() |
20e7d6d065 | ||
![]() |
89ada5b294 | ||
![]() |
fe80fef36e | ||
![]() |
e8331dda7a | ||
![]() |
68abaec6cb | ||
![]() |
fe84bae9ed | ||
![]() |
1289a0ada4 | ||
![]() |
93025c5e1b | ||
![]() |
e0439a1359 | ||
![]() |
93ec3865da | ||
![]() |
49e338e80d | ||
![]() |
075ddff226 | ||
![]() |
7eaf17d48e | ||
![]() |
6822aa83d8 | ||
![]() |
20dbaac4fa | ||
![]() |
726887af2e | ||
![]() |
03da2880ac | ||
![]() |
78c053f4e8 |
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,2 +1,9 @@
|
||||
.gradle
|
||||
build
|
||||
/build
|
||||
*.iml
|
||||
/.idea/libraries
|
||||
/.idea/workspace.xml
|
||||
/local.properties
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.DS_Store
|
||||
|
2
.idea/.gitignore
generated
vendored
2
.idea/.gitignore
generated
vendored
@@ -1,2 +1,2 @@
|
||||
workspace.xml
|
||||
markdown-navigator*
|
||||
markdown-*
|
||||
|
12
.idea/libraries/espresso_core_2_2_2.xml
generated
12
.idea/libraries/espresso_core_2_2_2.xml
generated
@@ -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>
|
12
.idea/libraries/espresso_idling_resource_2_2_2.xml
generated
12
.idea/libraries/espresso_idling_resource_2_2_2.xml
generated
@@ -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>
|
@@ -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>
|
11
.idea/libraries/hamcrest_core_1_3.xml
generated
11
.idea/libraries/hamcrest_core_1_3.xml
generated
@@ -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>
|
9
.idea/libraries/hamcrest_integration_1_3.xml
generated
9
.idea/libraries/hamcrest_integration_1_3.xml
generated
@@ -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>
|
9
.idea/libraries/hamcrest_library_1_3.xml
generated
9
.idea/libraries/hamcrest_library_1_3.xml
generated
@@ -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>
|
9
.idea/libraries/javawriter_2_1_1.xml
generated
9
.idea/libraries/javawriter_2_1_1.xml
generated
@@ -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>
|
9
.idea/libraries/javax_annotation_api_1_2.xml
generated
9
.idea/libraries/javax_annotation_api_1_2.xml
generated
@@ -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>
|
9
.idea/libraries/javax_inject_1.xml
generated
9
.idea/libraries/javax_inject_1.xml
generated
@@ -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>
|
9
.idea/libraries/jsr305_2_0_1.xml
generated
9
.idea/libraries/jsr305_2_0_1.xml
generated
@@ -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>
|
11
.idea/libraries/junit_4_12.xml
generated
11
.idea/libraries/junit_4_12.xml
generated
@@ -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>
|
12
.idea/libraries/rules_0_5.xml
generated
12
.idea/libraries/rules_0_5.xml
generated
@@ -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>
|
12
.idea/libraries/runner_0_5.xml
generated
12
.idea/libraries/runner_0_5.xml
generated
@@ -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>
|
21
README.md
21
README.md
@@ -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
|
||||
|
@@ -147,7 +147,7 @@ target_link_libraries( monerujo
|
||||
|
||||
blockchain_db
|
||||
lmdb
|
||||
#easylogging # not for 0.10.3.1
|
||||
easylogging
|
||||
unbound
|
||||
p2p
|
||||
|
||||
|
@@ -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',
|
||||
]
|
||||
}
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
|
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
498
app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java
Normal file
498
app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 {
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
Reference in New Issue
Block a user