1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-02 15:53:04 +02:00

Compare commits

...

95 Commits

Author SHA1 Message Date
m2049r
4ebcda2b14 bump version 2024-10-17 13:39:16 +02:00
m2049r
c49351a8a9 own orbothelper & fix receiver visibility (#961) 2024-10-17 13:01:12 +02:00
m2049r
41e84f2e29 fix receiver visibility 2024-10-17 12:42:26 +02:00
m2049r
f08ddf93c8 bump version 2024-10-16 21:31:09 +02:00
m2049r
4bfc9c1bdd fix RECEIVER_NOT_EXPORTED crash 2024-10-16 20:18:12 +02:00
m2049r
1a13bdde91 add some default nodes 2024-10-07 23:42:23 +02:00
m2049r
3e56d5a54b update default nodes (#959) 2024-09-24 09:00:22 +02:00
m2049r
c64fb1a769 Merge pull request #954 from m2049r/feature/show_connected
show when sidekick is connected
2024-09-19 22:44:00 +02:00
m2049r
2d2a7d2db0 show when sidekick is connected 2024-09-15 20:46:00 +02:00
m2049r
ac9e24ee9f Merge pull request #952 from m2049r/feature/sidekick_v
Support for Sidekick device
2024-09-06 00:45:48 +02:00
m2049r
059438a09e targetSdkVersion 35 2024-09-05 23:13:11 +02:00
m2049r
d22fdfe2dc Sidekick Support for Monerokon 2024-09-05 23:12:42 +02:00
m2049r
48577e46aa lock in background (#936) 2024-04-05 16:03:30 +02:00
m2049r
451371cd92 refactor onBackPressed to use the callback dispatcher (#937) 2024-04-05 15:57:37 +02:00
m2049r
cd6f646b63 bump version 2024-03-17 14:10:14 +01:00
m2049r
aa530caa28 improve german transaltion. remove permissions translations 2024-03-17 14:04:49 +01:00
m2049r
5df43f1274 fix translation errors 2024-03-17 13:38:36 +01:00
m2049r
3b0cb3ffdb upgrade gradle 2024-03-17 13:28:22 +01:00
m2049r
300551dbe4 update zlib to 1.3.1 2024-03-17 13:06:05 +01:00
m2049r
942519adb7 ignore monero native stuff 2024-03-17 12:53:51 +01:00
m2049r
0652a8ba14 upgrade dnsjava (#924) 2024-01-13 17:33:23 +01:00
m2049r
04d0bd2ffb fix tests 2024-01-13 16:14:05 +01:00
m2049r
8473e66c69 upgrade dependencies 2024-01-13 15:58:00 +01:00
m2049r
2218ff615c fix unescaped quotes 2024-01-13 15:41:23 +01:00
m2049r
54b55b9f8f optimize build time 2024-01-13 15:33:21 +01:00
m2049r
5abf84f62b optimize build time 2024-01-13 15:31:14 +01:00
m2049r
6ff75d221f add RSD (#923) 2024-01-13 14:28:30 +01:00
audioz
c90f107c3c Hebrew Translation (#895) 2024-01-13 14:13:56 +01:00
Digitale Souveränität - JETZT!
a3db18032e add ds-jetzt node (#905)
add ds-jetzt node as clear & onion
2024-01-13 14:13:18 +01:00
anhdres
9db2c10679 updated texts for eng and spa (#911)
Co-authored-by: m2049r <m2049r@monerujo.io>
2024-01-13 14:11:41 +01:00
XD22
eab85c7f0a Fix Docker libs Builds (#918)
Co-authored-by: m2049r <m2049r@monerujo.io>
2024-01-13 14:08:02 +01:00
kuznetsovgm
6bf3229e77 fixed a translation error (#912) 2024-01-13 14:05:52 +01:00
audioz
9f4f626acb Docker build fix. (#896)
* Hebrew Translation

* ~~ https://zlib.net/
Version 1.2.13 has these key updates from 1.2.12:

    Fix a bug when getting a gzip header extra field with inflateGetHeader(). This remedies CVE-2022-37434.
    Fix a bug in block type selection when Z_FIXED used. Now the smallest block type is selected, for better compression.
    Fix a configure issue that discarded the provided CC definition.
    Correct incorrect inputs provided to the CRC functions. This mitigates a bug in Java.
    Repair prototypes and exporting of the new CRC functions.
    Fix inflateBack to detect invalid input with distances too far.

Due to the first bug fix, any installations of 1.2.12 or earlier should be replaced with 1.2.13.

* Delete app/src/main/res/values-he directory
2024-01-13 14:05:22 +01:00
XD22
434dab55ba Fix TalkBack Screen reader (#917)
* Fixing TalkBack p1

* Fix TalkBack español translate p2

* Fix TalkBack français translate p3

* Escape some apostrophe, Fix wrong Locale codes
2024-01-13 14:03:31 +01:00
m2049r
59cc6b1864 upgrade dependencies 2024-01-13 13:59:38 +01:00
m2049r
a6e9d0e77c use yadio for pricing "exotic" fiat (#921)
* yadio api

* add more currencies

* fix es typo

* bump version & fix cicleci build
2023-12-10 14:24:35 +01:00
m2049r
17df7c3faf Pocket Change V2 (#914)
* show PC on btc confirm
* random slots to refill
2023-08-28 19:24:45 +02:00
m2049r
bf1829f775 PocketChange (#901) 2023-06-05 05:03:51 +02:00
m2049r
bc4aa0f772 Feature v0.18.2.2 (#900)
* add Ledger Stax

* update block heights

* reestimate restore height only for mainnet

* upgrade to gradle 8.0.1

* upgrade dependencies
2023-05-29 17:01:07 +02:00
m2049r
3f09e73df7 Merge pull request #898 from m2049r/feature_tweaks
UI tweaks
2023-05-03 23:13:21 +02:00
m2049r
11b7e23ad2 remove RUB as currency as we don't get an exchange rate for it 2023-05-03 22:49:18 +02:00
m2049r
ae48027689 new qr code logo 2023-05-03 22:43:42 +02:00
m2049r
a42f750fc4 center sync status 2023-05-03 08:22:23 +02:00
m2049r
3406f585f2 organize all imports 2023-04-30 17:46:58 +02:00
m2049r
7546637c89 remove NFC support 2023-04-30 17:43:51 +02:00
m2049r
4da2106f04 show active account in drawer 2023-04-30 17:16:20 +02:00
m2049r
93c11fb90e update build tools version 2023-04-30 17:04:05 +02:00
m2049r
9fa710f75b fix build warnings 2023-04-27 23:58:08 +02:00
m2049r
c53dd300bc update dependencies 2023-04-26 08:39:30 +02:00
m2049r
97f40648be make streetmode label better 2023-04-26 08:25:33 +02:00
m2049r
1ece6bfbeb move status above sum 2023-04-26 08:15:02 +02:00
m2049r
4b3b99ff2a fix colour of service logo & use it for receive qr code 2023-04-26 07:55:26 +02:00
m2049r
ca833d7017 show full subaddress in details 2023-04-26 07:38:14 +02:00
m2049r
f1b6f859de show subaddress info above label 2023-04-26 07:34:18 +02:00
m2049r
61d19c7066 remove next arrow 2023-04-26 07:25:04 +02:00
m2049r
ffda0e965b bump version 2023-01-07 11:07:19 +01:00
m2049r
cc7cdb383c tweak http timeouts so sideshift does not timeout (#881) 2023-01-07 10:22:21 +01:00
m2049r
ac1ea05ef6 add unlockTime (#880)
show lock icon for currently locked txs
2023-01-07 10:19:22 +01:00
m2049r
1ddd4f30b9 use monero v0.18.1.2 (#878) 2022-12-04 21:04:15 +01:00
m2049r
1dc081834f bump version 2022-10-22 11:33:11 +02:00
m2049r
ce084927e1 fix langauge list 2022-10-22 11:32:44 +02:00
Kartal Kaan Bozdoğan
3610781f43 Display the unconfirmed amount in the chosen currency (#844)
Changed the translations accordingly
2022-10-22 10:59:25 +02:00
m2049r
ef3ddbac71 fix versions 2022-08-13 23:24:57 +02:00
m2049r
0512af1496 Monero v0.18.1.0 2022-08-13 10:20:21 +02:00
m2049r
bd2c49669a Feature v18 (#860)
* versions

* remove x86 builds
2022-08-10 16:50:18 +02:00
Kartal Kaan Bozdoğan
ac7831d0f9 Upgrade to 0.18.0.0 Fluorine Fermi (#856)
* Upgrade to Monero wallet 0.18.0.0 Fluorine Fermi
2022-08-05 01:09:56 +02:00
Kartal Kaan Bozdoğan
0f0b9a38c7 Fix new wallet restore height (#858)
* New wallets: set current block height as the restore height.
  Go back 4 days for estimated heights
2022-08-05 01:09:10 +02:00
Kartal Kaan Bozdoğan
807db19603 Fixed zlib hashes (#845) 2022-08-05 01:02:34 +02:00
m2049r
c956f38899 remove S for Nano 2022-05-23 19:47:53 +02:00
m2049r
db68f517d3 bump version 2022-05-23 19:31:22 +02:00
m2049r
d4b293af80 new strings (#839) 2022-05-23 19:20:28 +02:00
m2049r
f7bbfc2fac remove untranslatables (#838) 2022-05-23 19:16:49 +02:00
m2049r
e08964749e Fix entities (#837)
* remove &check;

* resolve nbsp
2022-05-23 19:03:45 +02:00
Dave Scotese
a05fa9d177 Exchange rate was hard to find. (#763)
The FAQ I added uses both "exchange" and "rate," neither of which appeared in the FAQ otherwise.
2022-05-23 18:42:30 +02:00
kivojo
7fe2fbe37d Translation to Farsi/Persian (#815)
* about.xml translated to Farsi

* minor improvements in translation

* one small typo

* help.xml translated to Farsi

* <br/> tags fixed

* better translation of word Mnemonic to Farsi

* strings.xml translated to Farsi
READY for PR!

* oops, my bad! deleted the untranslatable strings.

Co-authored-by: kivojo <user@example.com>
2022-05-23 18:41:06 +02:00
kingoflove819
40e30fed08 Create about.xml (#809)
* Create about.xml

* Update about.xml

* Completed translating about.xml for tamil
2022-05-23 18:39:38 +02:00
kingoflove819
320c7865ff Create help.xml (#810)
* Create help.xml

* Update help.xml

* Update help.xml

* Update help.xml

* Update help.xml
2022-05-23 18:39:23 +02:00
kingoflove819
5e8cf8010e Create strings.xml (#811)
* Create strings.xml

* Update strings.xml

* Update strings.xml

* Update strings.xml

* Update strings.xml

* Completed strings.xml
2022-05-23 18:39:07 +02:00
Age Bosma
e671fa19e0 Specify wallet folder (#835)
* Specify wallet folder

* Update FAQ.md
2022-05-23 18:36:22 +02:00
m2049r
20d5b9a100 fix sweep to be invisible by default 2022-05-15 21:56:38 +02:00
m2049r
5d489a634b bump version 2022-05-15 17:25:28 +02:00
m2049r
59b6f484fd update to monero v0.17.3.2 2022-05-15 17:24:54 +02:00
m2049r
ecaa49d67d upgrade build files 2022-05-15 15:57:11 +02:00
jont4
d2dc53599e Update PT-rBR strings (#813)
* Update pt-rBR

* Update app/src/main/res/values-pt-rBR/strings.xml

Co-authored-by: netrik182 <30935310+netrik182@users.noreply.github.com>

* Update app/src/main/res/values-pt-rBR/strings.xml

Co-authored-by: netrik182 <30935310+netrik182@users.noreply.github.com>

* Update strings.xml

fix as suggested

Co-authored-by: jontaix <31804298+jontaix@users.noreply.github.com>
Co-authored-by: netrik182 <30935310+netrik182@users.noreply.github.com>
Co-authored-by: m2049r <m2049r@monerujo.io>
2022-05-01 11:51:49 +02:00
Лапки
4d8b26f97f Update strings.xml (#826) 2022-05-01 11:44:52 +02:00
Justin Berman
581c76e7be setName uses async network helper in case of reverse DNS lookup (#818, #827) (#828) 2022-05-01 11:44:27 +02:00
AnonimaUzanto
6f66862870 Adding support for Ledger Nano S Plus (#832) 2022-05-01 11:35:01 +02:00
m2049r
dd92f7bb36 bump version 2022-03-13 15:37:28 +01:00
m2049r
46808d306b clean transitions 2022-03-12 23:10:34 +01:00
m2049r
20503d2cbd remove send/receive transitions 2022-03-11 00:25:50 +01:00
m2049r
604691ca7e fix FABs 2022-03-10 21:06:19 +01:00
m2049r
1b626ba2b0 improve transitions 2022-03-10 20:57:57 +01:00
m2049r
0ed7bdfcee remove test Dockerfile 2022-03-10 09:07:14 +01:00
m2049r
524c3dd79f upgrade ci image to 2022.03-ndk (#822) 2022-03-10 09:04:43 +01:00
m2049r
197dffeae1 fix tests 2022-03-10 07:53:52 +01:00
242 changed files with 10501 additions and 3707 deletions

View File

@@ -3,13 +3,11 @@ jobs:
build:
working_directory: ~/code
docker:
- image: circleci/android:api-28-ndk
- image: cimg/android:2023.12-ndk
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- run: yes | sdkmanager --licenses || exit 0
- run: yes | sdkmanager --update || exit 0
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:

10
.gitignore vendored
View File

@@ -8,11 +8,9 @@
.DS_Store
/app/build
/app/release
/app/alpha
/app/prod
/app/alphaMainnet
/app/prodMainnet
/app/alphaStagenet
/app/prodStagenet
/app/alpha*
/app/prod*
/app/.cxx
/monerujo.id
/external-libs/VERSION
/external-libs/include/wallet2_api.h

View File

@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.4.1)
project(monerujo)
message(STATUS ABI_INFO = ${ANDROID_ABI})
add_library( monerujo
@@ -121,7 +122,7 @@ set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION
add_library(unbound STATIC IMPORTED)
set_target_properties(unbound PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/monero/libunbound.a)
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/libunbound.a)
add_library(epee STATIC IMPORTED)
set_target_properties(epee PROPERTIES IMPORTED_LOCATION

View File

@@ -1,15 +1,15 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 31
buildToolsVersion '30.0.3'
ndkVersion '17.2.4988734'
defaultConfig {
applicationId "com.m2049r.xmrwallet"
buildToolsVersion = '35.0.0'
compileSdk 35
minSdkVersion 21
targetSdkVersion 31
versionCode 1303
versionName "2.3.3 'Baldaŭ'"
targetSdkVersion 35
versionCode 4008
versionName "4.0.8 'Sidekick'"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
@@ -24,7 +24,7 @@ android {
}
}
flavorDimensions 'type', 'net'
flavorDimensions = ['type', 'net']
productFlavors {
mainnet {
dimension 'net'
@@ -72,7 +72,7 @@ android {
abi {
enable true
reset()
include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
include 'armeabi-v7a', 'arm64-v8a', 'x86_64'
universalApk true
}
}
@@ -111,6 +111,18 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
namespace 'com.m2049r.xmrwallet'
buildFeatures {
buildConfig true
}
testOptions {
unitTests {
all {
jvmArgs '--add-opens=java.base/java.lang=ALL-UNNAMED'
}
}
}
}
static def getId(name) {
@@ -120,39 +132,40 @@ static def getId(name) {
}
dependencies {
implementation 'androidx.core:core:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.22"))
implementation 'androidx.core:core:1.13.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.preference:preference:1.2.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation "com.squareup.okhttp3:okhttp:4.9.3"
implementation "io.github.rburgst:okhttp-digest:2.6"
implementation "com.squareup.okhttp3:okhttp:4.12.0"
implementation "io.github.rburgst:okhttp-digest:3.1.0"
implementation "com.jakewharton.timber:timber:5.0.1"
implementation 'info.guardianproject.netcipher:netcipher:2.1.0'
//implementation 'info.guardianproject.netcipher:netcipher-okhttp3:2.1.0'
implementation fileTree(dir: 'libs/classes', include: ['*.jar'])
implementation 'com.nulab-inc:zxcvbn:1.5.2'
implementation 'com.nulab-inc:zxcvbn:1.8.2'
implementation 'dnsjava:dnsjava:2.1.9'
implementation 'org.jitsi:dnssecjava:1.2.0'
implementation 'org.slf4j:slf4j-nop:1.7.36'
implementation 'dnsjava:dnsjava:3.5.3'
implementation 'org.slf4j:slf4j-nop:2.0.11'
implementation 'com.github.brnunes:swipeablerecyclerview:1.0.2'
//noinspection GradleDependency
testImplementation "junit:junit:4.13.2"
testImplementation "org.mockito:mockito-all:1.10.19"
testImplementation "com.squareup.okhttp3:mockwebserver:4.9.3"
testImplementation 'org.json:json:20211205'
testImplementation "com.squareup.okhttp3:mockwebserver:4.12.0"
testImplementation 'org.json:json:20231013'
testImplementation 'net.jodah:concurrentunit:0.4.6'
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'
}

View File

@@ -1,15 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.m2049r.xmrwallet">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<queries>
<intent>
@@ -96,7 +104,12 @@
android:name=".service.WalletService"
android:description="@string/service_description"
android:exported="false"
android:label="Monero Wallet Service" />
android:foregroundServiceType="specialUse"
android:label="Monero Wallet Service">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Keeps app in sync with the blockchain" />
</service>
<provider
android:name="androidx.core.content.FileProvider"

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2017 m2049r
* Copyright (c) 2017-2024 m2049r
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
#include <jni.h>
#include <string>
/*
#include <android/log.h>
@@ -28,6 +30,10 @@
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
*/
void ThrowException(JNIEnv *jenv, const char* type, const char* msg) {
jenv->ThrowNew(jenv->FindClass(type), msg);
}
jfieldID getHandleField(JNIEnv *env, jobject obj, const char *fieldName = "handle") {
jclass c = env->GetObjectClass(obj);
return env->GetFieldID(c, fieldName, "J"); // of type long
@@ -35,8 +41,16 @@ jfieldID getHandleField(JNIEnv *env, jobject obj, const char *fieldName = "handl
template<typename T>
T *getHandle(JNIEnv *env, jobject obj, const char *fieldName = "handle") {
return reinterpret_cast<T *>(env->GetLongField(obj, getHandleField(env, obj, fieldName)));
}
template<typename T>
void destroyNativeObject(JNIEnv *env, T nativeObjectHandle, jobject obj, const char *fieldName = "handle") {
jlong handle = env->GetLongField(obj, getHandleField(env, obj, fieldName));
return reinterpret_cast<T *>(handle);
if (handle != 0) {
ThrowException(env, "java/lang/IllegalStateException", "invalid handle (destroy)");
}
delete reinterpret_cast<T *>(nativeObjectHandle);
}
void setHandleFromLong(JNIEnv *env, jobject obj, jlong handle) {
@@ -54,7 +68,7 @@ extern "C"
{
#endif
extern const char* const MONERO_VERSION; // the actual monero core version
extern const char *const MONERO_VERSION; // the actual monero core version
// from monero-core crypto/hash-ops.h - avoid #including monero code here
enum {
@@ -62,18 +76,40 @@ enum {
HASH_DATA_AREA = 136
};
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height);
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed,
uint64_t height);
inline void slow_hash(const void *data, const size_t length, char *hash) {
cn_slow_hash(data, length, hash, 0 /*variant*/, 0 /*prehashed*/, 0 /*height*/);
}
inline void slow_hash_broken(const void *data, char *hash, int variant) {
cn_slow_hash(data, 200 /*sizeof(union hash_state)*/, hash, variant, 1 /*prehashed*/, 0 /*height*/);
cn_slow_hash(data, 200 /*sizeof(union hash_state)*/, hash, variant, 1 /*prehashed*/,
0 /*height*/);
}
#ifdef __cplusplus
}
#endif
namespace Monerujo {
class SidekickWallet {
public:
enum Status {
Status_Ok,
Status_Error,
Status_Critical
};
SidekickWallet(uint8_t networkType, std::string a, std::string b);
~SidekickWallet();
std::string call(int commandId, const std::string &request);
void reset();
Status status() const;
};
}
#endif //XMRWALLET_WALLET_LIB_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -20,8 +20,6 @@
package com.btchip.comm;
import com.btchip.BTChipException;
public interface BTChipTransport {
byte[] exchange(byte[] command);

View File

@@ -28,7 +28,6 @@ import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import com.btchip.BTChipException;
import com.btchip.comm.BTChipTransport;
import com.btchip.comm.LedgerHelper;
import com.btchip.utils.Dump;
@@ -78,7 +77,7 @@ public class BTChipTransportAndroidHID implements BTChipTransport {
}
private static final int VID = 0x2C97;
private static final int[] PID_HIDS = {0x0001, 0x0004};
private static final int[] PID_HIDS = {0x0001, 0x0004, 0x0005};
private UsbDeviceConnection connection;
private UsbInterface dongleInterface;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,11 +16,8 @@
package com.m2049r.xmrwallet;
import androidx.annotation.NonNull;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Editable;
import android.text.Html;
@@ -37,6 +34,7 @@ import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
@@ -44,6 +42,7 @@ import androidx.fragment.app.Fragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.switchmaterial.SwitchMaterial;
import com.google.android.material.textfield.TextInputLayout;
import com.m2049r.xmrwallet.model.NetworkType;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.FingerprintHelper;
@@ -67,8 +66,20 @@ public class GenerateFragment extends Fragment {
static final String TYPE_KEY = "key";
static final String TYPE_SEED = "seed";
static final String TYPE_LEDGER = "ledger";
static final String TYPE_SIDEKICK = "sidekick";
static final String TYPE_VIEWONLY = "view";
static Wallet.Device getDeviceType(String type) {
switch (type) {
case TYPE_SIDEKICK:
return Wallet.Device.Sidekick;
case TYPE_LEDGER:
return Wallet.Device.Ledger;
default:
return Wallet.Device.Software;
}
}
private TextInputLayout etWalletName;
private PasswordEntryView etWalletPassword;
private LinearLayout llFingerprintAuth;
@@ -195,6 +206,7 @@ public class GenerateFragment extends Fragment {
etWalletPassword.getEditText().setImeOptions(EditorInfo.IME_ACTION_UNSPECIFIED);
break;
case TYPE_LEDGER:
case TYPE_SIDEKICK:
etWalletPassword.getEditText().setImeOptions(EditorInfo.IME_ACTION_DONE);
etWalletPassword.getEditText().setOnEditorActionListener((v, actionId, event) -> {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
@@ -308,7 +320,7 @@ public class GenerateFragment extends Fragment {
private boolean checkName() {
String name = etWalletName.getEditText().getText().toString();
boolean ok = true;
if (name.length() == 0) {
if (name.isEmpty()) {
etWalletName.setError(getString(R.string.generate_wallet_name));
ok = false;
} else if (name.charAt(0) == '.') {
@@ -345,21 +357,23 @@ public class GenerateFragment extends Fragment {
String restoreHeight = etWalletRestoreHeight.getEditText().getText().toString().trim();
if (restoreHeight.isEmpty()) return -1;
try {
// is it a date?
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd");
parser.setLenient(false);
height = RestoreHeight.getInstance().getHeight(parser.parse(restoreHeight));
} catch (ParseException ignored) {
}
if ((height < 0) && (restoreHeight.length() == 8))
if (WalletManager.getInstance().getNetworkType() == NetworkType.NetworkType_Mainnet) {
try {
// is it a date without dashes?
SimpleDateFormat parser = new SimpleDateFormat("yyyyMMdd");
// is it a date?
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd");
parser.setLenient(false);
height = RestoreHeight.getInstance().getHeight(parser.parse(restoreHeight));
} catch (ParseException ignored) {
}
if ((height < 0) && (restoreHeight.length() == 8))
try {
// is it a date without dashes?
SimpleDateFormat parser = new SimpleDateFormat("yyyyMMdd");
parser.setLenient(false);
height = RestoreHeight.getInstance().getHeight(parser.parse(restoreHeight));
} catch (ParseException ignored) {
}
}
if (height < 0)
try {
// or is it a height?
@@ -448,11 +462,12 @@ public class GenerateFragment extends Fragment {
activityCallback.onGenerate(name, crazyPass, seed, offset, height);
break;
case TYPE_LEDGER:
case TYPE_SIDEKICK:
bGenerate.setEnabled(false);
if (fingerprintAuthAllowed) {
KeyStoreHelper.saveWalletUserPass(requireActivity(), name, password);
}
activityCallback.onGenerateLedger(name, crazyPass, height);
activityCallback.onGenerateDevice(getDeviceType(type), name, crazyPass, height);
break;
case TYPE_KEY:
case TYPE_VIEWONLY:
@@ -496,6 +511,8 @@ public class GenerateFragment extends Fragment {
return getString(R.string.generate_wallet_type_seed);
case TYPE_LEDGER:
return getString(R.string.generate_wallet_type_ledger);
case TYPE_SIDEKICK:
return getString(R.string.generate_wallet_type_sidekick);
case TYPE_VIEWONLY:
return getString(R.string.generate_wallet_type_view);
default:
@@ -513,7 +530,7 @@ public class GenerateFragment extends Fragment {
void onGenerate(String name, String password, String address, String viewKey, String spendKey, long height);
void onGenerateLedger(String name, String password, long height);
void onGenerateDevice(Wallet.Device device, String name, String password, long height);
void setTitle(String title);
@@ -553,6 +570,9 @@ public class GenerateFragment extends Fragment {
case TYPE_LEDGER:
inflater.inflate(R.menu.create_wallet_ledger, menu);
break;
case TYPE_SIDEKICK:
inflater.inflate(R.menu.create_wallet_sidekick, menu);
break;
case TYPE_VIEWONLY:
inflater.inflate(R.menu.create_wallet_view, menu);
break;
@@ -579,13 +599,11 @@ public class GenerateFragment extends Fragment {
.setCancelable(false)
.setPositiveButton(getString(R.string.label_ok), null)
.setNegativeButton(getString(R.string.label_cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Helper.hideKeyboardAlways(activity);
etWalletMnemonic.getEditText().getText().clear();
dialog.cancel();
ledgerDialog = null;
}
(dialog, id) -> {
Helper.hideKeyboardAlways(activity);
etWalletMnemonic.getEditText().getText().clear();
dialog.cancel();
ledgerDialog = null;
});
ledgerDialog = alertDialogBuilder.create();

View File

@@ -40,6 +40,7 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
@@ -98,6 +99,13 @@ public class GenerateReviewFragment extends Fragment {
private String walletPath;
private String walletName;
private OnBackPressedCallback backPressedCallback = new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
// nothing
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -160,6 +168,9 @@ public class GenerateReviewFragment extends Fragment {
walletPath = args.getString(REQUEST_PATH);
localPassword = args.getString(REQUEST_PASSWORD);
showDetails();
if (type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT)) {
backPressedCallback.setEnabled(true);
}
return view;
}
@@ -243,7 +254,7 @@ public class GenerateReviewFragment extends Fragment {
showProgress();
if ((walletPath != null)
&& (WalletManager.getInstance().queryWalletDevice(walletPath + ".keys", getPassword())
== Wallet.Device.Device_Ledger)
== Wallet.Device.Ledger)
&& (progressCallback != null)) {
progressCallback.showLedgerProgressDialog(LedgerProgressDialog.TYPE_RESTORE);
dialogOpened = true;
@@ -275,10 +286,11 @@ public class GenerateReviewFragment extends Fragment {
height = wallet.getRestoreHeight();
seed = wallet.getSeed(getSeedOffset());
switch (wallet.getDeviceType()) {
case Device_Ledger:
case Ledger:
viewKey = Ledger.Key();
break;
case Device_Software:
case Software:
case Sidekick:
viewKey = wallet.getSecretViewKey();
break;
default:
@@ -420,14 +432,11 @@ public class GenerateReviewFragment extends Fragment {
pbProgress.setVisibility(View.INVISIBLE);
}
boolean backOk() {
return !type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
requireActivity().getOnBackPressedDispatcher().addCallback(this, backPressedCallback);
}
@Override

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2024 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.fragment.app.Fragment;
import timber.log.Timber;
public class LockFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Timber.d("onCreateView");
final FrameLayout frame = new FrameLayout(requireContext());
frame.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return frame;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -29,13 +29,13 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
@@ -46,6 +46,7 @@ import com.google.android.material.progressindicator.CircularProgressIndicator;
import com.m2049r.xmrwallet.data.NodeInfo;
import com.m2049r.xmrwallet.dialog.HelpFragment;
import com.m2049r.xmrwallet.layout.WalletInfoAdapter;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.KeyStoreHelper;
@@ -61,6 +62,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import lombok.Getter;
import timber.log.Timber;
public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInteractionListener,
@@ -115,7 +117,9 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
Set<NodeInfo> getOrPopulateFavourites();
boolean hasLedger();
boolean hasDevice(Wallet.Device type);
boolean isNetworkAvailable();
void runOnNetCipher(Runnable runnable);
}
@@ -146,9 +150,15 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
activityCallback.setToolbarButton(Toolbar.BUTTON_SETTINGS);
activityCallback.showNet();
showNetwork();
//activityCallback.runOnNetCipher(this::pingSelectedNode);
}
private OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
animateFAB();
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -165,6 +175,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabSeed = view.findViewById(R.id.fabSeed);
fabImport = view.findViewById(R.id.fabImport);
fabLedger = view.findViewById(R.id.fabLedger);
fabSidekick = view.findViewById(R.id.fabSidekick);
fabNewL = view.findViewById(R.id.fabNewL);
fabViewL = view.findViewById(R.id.fabViewL);
@@ -172,6 +183,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabSeedL = view.findViewById(R.id.fabSeedL);
fabImportL = view.findViewById(R.id.fabImportL);
fabLedgerL = view.findViewById(R.id.fabLedgerL);
fabSidekickL = view.findViewById(R.id.fabSidekickL);
fab_pulse = AnimationUtils.loadAnimation(getContext(), R.anim.fab_pulse);
fab_open_screen = AnimationUtils.loadAnimation(getContext(), R.anim.fab_open_screen);
@@ -187,6 +199,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabSeed.setOnClickListener(this);
fabImport.setOnClickListener(this);
fabLedger.setOnClickListener(this);
fabSidekick.setOnClickListener(this);
fabScreen.setOnClickListener(this);
RecyclerView recyclerView = view.findViewById(R.id.list);
@@ -195,6 +208,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
recyclerView.setAdapter(adapter);
ViewGroup llNotice = view.findViewById(R.id.llNotice);
Notice.showAll(llNotice, ".*_login");
view.findViewById(R.id.llNode).setOnClickListener(v -> startNodePrefs());
@@ -288,6 +302,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
}
@Override
@@ -296,25 +311,30 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
super.onCreateOptionsMenu(menu, inflater);
}
private boolean isFabOpen = false;
private FloatingActionButton fab, fabNew, fabView, fabKey, fabSeed, fabImport, fabLedger;
@Getter
private boolean fabOpen = false;
private FloatingActionButton fab, fabNew, fabView, fabKey, fabSeed, fabImport, fabLedger, fabSidekick;
private RelativeLayout fabScreen;
private RelativeLayout fabNewL, fabViewL, fabKeyL, fabSeedL, fabImportL, fabLedgerL;
private RelativeLayout fabNewL, fabViewL, fabKeyL, fabSeedL, fabImportL, fabLedgerL, fabSidekickL;
private Animation fab_open, fab_close, rotate_forward, rotate_backward, fab_open_screen, fab_close_screen;
private Animation fab_pulse;
public boolean isFabOpen() {
return isFabOpen;
private void setFabOpen(boolean value) {
fabOpen = value;
onBackPressedCallback.setEnabled(value);
}
public void animateFAB() {
if (isFabOpen) { // close the fab
if (isFabOpen()) { // close the fab
fabScreen.setClickable(false);
fabScreen.startAnimation(fab_close_screen);
fab.startAnimation(rotate_backward);
if (fabLedgerL.getVisibility() == View.VISIBLE) {
fabLedgerL.startAnimation(fab_close);
fabLedger.setClickable(false);
} else if (fabSidekickL.getVisibility() == View.VISIBLE) {
fabSidekickL.startAnimation(fab_close);
fabSidekick.setClickable(false);
} else {
fabNewL.startAnimation(fab_close);
fabNew.setClickable(false);
@@ -327,22 +347,30 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabImportL.startAnimation(fab_close);
fabImport.setClickable(false);
}
isFabOpen = false;
setFabOpen(false);
} else { // open the fab
fabScreen.setClickable(true);
fabScreen.startAnimation(fab_open_screen);
fab.startAnimation(rotate_forward);
if (activityCallback.hasLedger()) {
fabLedgerL.setVisibility(View.VISIBLE);
if ((activityCallback.hasDevice(Wallet.Device.Ledger)
|| activityCallback.hasDevice(Wallet.Device.Sidekick))) {
fabNewL.setVisibility(View.GONE);
fabViewL.setVisibility(View.GONE);
fabKeyL.setVisibility(View.GONE);
fabSeedL.setVisibility(View.GONE);
fabImportL.setVisibility(View.GONE);
fabLedgerL.startAnimation(fab_open);
fabLedger.setClickable(true);
if (activityCallback.hasDevice(Wallet.Device.Ledger)) {
fabLedgerL.setVisibility(View.VISIBLE);
fabLedgerL.startAnimation(fab_open);
fabLedger.setClickable(true);
} else { // Sidekick
fabSidekickL.setVisibility(View.VISIBLE);
fabSidekickL.startAnimation(fab_open);
fabSidekick.setClickable(true);
}
} else {
fabSidekickL.setVisibility(View.GONE);
fabLedgerL.setVisibility(View.GONE);
fabNewL.setVisibility(View.VISIBLE);
fabViewL.setVisibility(View.VISIBLE);
@@ -361,7 +389,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabImportL.startAnimation(fab_open);
fabImport.setClickable(true);
}
isFabOpen = true;
setFabOpen(true);
}
}
@@ -373,7 +401,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
animateFAB();
} else if (id == R.id.fabNew) {
fabScreen.setVisibility(View.INVISIBLE);
isFabOpen = false;
setFabOpen(false);
activityCallback.onAddWallet(GenerateFragment.TYPE_NEW);
} else if (id == R.id.fabView) {
animateFAB();
@@ -391,6 +419,10 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
Timber.d("FAB_LEDGER");
animateFAB();
activityCallback.onAddWallet(GenerateFragment.TYPE_LEDGER);
} else if (id == R.id.fabSidekick) {
Timber.d("FAB_SIDEKICK");
animateFAB();
activityCallback.onAddWallet(GenerateFragment.TYPE_SIDEKICK);
} else if (id == R.id.fabScreen) {
animateFAB();
}

View File

@@ -20,7 +20,6 @@ import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.m2049r.xmrwallet.onboarding.OnBoardingActivity;
import com.m2049r.xmrwallet.onboarding.OnBoardingManager;

View File

@@ -31,6 +31,7 @@ import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
@@ -145,6 +146,13 @@ public class NodeFragment extends Fragment
}
}
private OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
Toast.makeText(requireActivity(), getString(R.string.node_refresh_wait), Toast.LENGTH_LONG).show();
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -187,6 +195,7 @@ public class NodeFragment extends Fragment
private boolean refresh(int type) {
if (asyncFindNodes != null) return false; // ignore refresh request as one is ongoing
onBackPressedCallback.setEnabled(true);
asyncFindNodes = new AsyncFindNodes();
updateRefreshElements();
asyncFindNodes.execute(type);
@@ -197,6 +206,7 @@ public class NodeFragment extends Fragment
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
}
@Override
@@ -279,8 +289,7 @@ public class NodeFragment extends Fragment
} else if (params[0] == SCAN) {
// otherwise scan the network
Timber.d("scanning");
Set<NodeInfo> seedList = new HashSet<>();
seedList.addAll(nodeList);
Set<NodeInfo> seedList = new HashSet<>(nodeList);
nodeList.clear();
Timber.d("seed %d", seedList.size());
Dispatcher d = new Dispatcher(info -> publishProgress(info));
@@ -342,6 +351,7 @@ public class NodeFragment extends Fragment
private void complete() {
asyncFindNodes = null;
onBackPressedCallback.setEnabled(false);
if (!isAdded()) return;
//if (isCancelled()) return;
tvPull.setText(getString(R.string.node_pull_hint));
@@ -415,7 +425,14 @@ public class NodeFragment extends Fragment
}
etNodeHost.setError(null);
nodeInfo.setRpcPort(port);
nodeInfo.setName(etNodeName.getEditText().getText().toString().trim());
// setName() may trigger reverse DNS
Helper.runWithNetwork(new Helper.Action() {
@Override
public boolean run() {
nodeInfo.setName(etNodeName.getEditText().getText().toString().trim());
return true;
}
});
nodeInfo.setUsername(etNodeUser.getEditText().getText().toString().trim());
nodeInfo.setPassword(etNodePass.getEditText().getText().toString()); // no trim for pw
return true;
@@ -568,6 +585,7 @@ public class NodeFragment extends Fragment
}
}
}
}
void restoreDefaultNodes() {

View File

@@ -22,7 +22,6 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.nfc.NfcManager;
import android.os.Bundle;
import android.text.Editable;
import android.text.Html;
@@ -191,11 +190,6 @@ public class ReceiveFragment extends Fragment {
throw new IllegalStateException("no wallet info");
}
View tvNfc = view.findViewById(R.id.tvNfc);
NfcManager manager = (NfcManager) getContext().getSystemService(Context.NFC_SERVICE);
if ((manager != null) && (manager.getDefaultAdapter() != null))
tvNfc.setVisibility(View.VISIBLE);
return view;
}
@@ -403,7 +397,7 @@ public class ReceiveFragment extends Fragment {
private Bitmap getMoneroLogo() {
if (logo == null) {
logo = Helper.getBitmap(getContext(), R.drawable.ic_monero_logo_b);
logo = Helper.getBitmap(getContext(), R.drawable.ic_monerujo_qr);
}
return logo;
}

View File

@@ -19,12 +19,13 @@ package com.m2049r.xmrwallet;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;

View File

@@ -16,6 +16,8 @@
package com.m2049r.xmrwallet;
import static android.view.WindowManager.LayoutParams;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
@@ -29,8 +31,6 @@ import com.m2049r.xmrwallet.util.LocaleHelper;
import java.util.Locale;
import static android.view.WindowManager.LayoutParams;
public abstract class SecureActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 2018 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.m2049r.xmrwallet.data.BluetoothInfo;
import com.m2049r.xmrwallet.layout.BluetoothInfoAdapter;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.util.ArrayList;
import java.util.List;
import timber.log.Timber;
public class SidekickConnectFragment extends Fragment
implements BluetoothInfoAdapter.OnInteractionListener {
private BluetoothAdapter bluetoothAdapter;
private SwipeRefreshLayout pullToRefresh;
private BluetoothInfoAdapter infoAdapter;
private Listener activityCallback;
public interface Listener {
void setToolbarButton(int type);
void setSubtitle(String title);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if (context instanceof Listener) {
this.activityCallback = (Listener) context;
} else {
throw new ClassCastException(context + " must implement Listener");
}
}
@Override
public void onPause() {
Timber.d("onPause()");
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
// the the activity we are connected? why? it can ask the bluetoothservice...
super.onPause();
}
@Override
public void onResume() {
super.onResume();
Timber.d("onResume()");
activityCallback.setSubtitle(getString(R.string.label_bluetooth));
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
final BluetoothFragment btFragment = (BluetoothFragment) getChildFragmentManager().findFragmentById(R.id.bt_fragment);
assert btFragment != null;
btFragment.start();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Timber.d("onCreateView");
View view = inflater.inflate(R.layout.fragment_sidekick_connect, container, false);
RecyclerView recyclerView = view.findViewById(R.id.list);
infoAdapter = new BluetoothInfoAdapter(this);
recyclerView.setAdapter(infoAdapter);
pullToRefresh = view.findViewById(R.id.pullToRefresh);
pullToRefresh.setOnRefreshListener(() -> {
populateList();
pullToRefresh.setRefreshing(false);
});
return view;
}
private void populateList() {
List<BluetoothInfo> items = new ArrayList<>();
for (BluetoothDevice device : bluetoothAdapter.getBondedDevices()) {
final int deviceCLass = device.getBluetoothClass().getDeviceClass();
switch (deviceCLass) {
case BluetoothClass.Device.PHONE_SMART:
//TODO verify these are correct
case BluetoothClass.Device.COMPUTER_HANDHELD_PC_PDA:
case BluetoothClass.Device.COMPUTER_PALM_SIZE_PC_PDA:
items.add(new BluetoothInfo(device));
}
}
infoAdapter.setItems(items);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
Helper.hideKeyboard(getActivity());
// Get the local Bluetooth adapter
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
populateList();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.sidekick_connect_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onDestroy() {
super.onDestroy();
// Make sure we're not doing discovery anymore
if (bluetoothAdapter != null) {
bluetoothAdapter.cancelDiscovery();
}
}
@Override
public void onInteraction(final View view, final BluetoothInfo item) {
Timber.d("onInteraction %s", item);
bluetoothAdapter.cancelDiscovery();
final BluetoothFragment btFragment = (BluetoothFragment) getChildFragmentManager().findFragmentById(R.id.bt_fragment);
assert btFragment != null;
btFragment.connectDevice(item.getAddress());
}
public void allowClick() {
infoAdapter.allowClick(true);
}
}

View File

@@ -30,7 +30,6 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.transition.MaterialElevationScale;
import com.m2049r.xmrwallet.data.Subaddress;
import com.m2049r.xmrwallet.layout.SubaddressInfoAdapter;
import com.m2049r.xmrwallet.ledger.LedgerProgressDialog;
@@ -117,14 +116,6 @@ public class SubaddressFragment extends Fragment implements SubaddressInfoAdapte
managerMode = ((b != null) && (MODE_MANAGER.equals(b.getString(KEY_MODE))));
View view = inflater.inflate(R.layout.fragment_subaddress, container, false);
final MaterialElevationScale exitTransition = new MaterialElevationScale(false);
exitTransition.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
setExitTransition(exitTransition);
final MaterialElevationScale reenterTransition = new MaterialElevationScale(true);
reenterTransition.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
setReenterTransition(reenterTransition);
view.findViewById(R.id.fab).setOnClickListener(this);
if (managerMode) {
@@ -154,11 +145,6 @@ public class SubaddressFragment extends Fragment implements SubaddressInfoAdapte
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
postponeEnterTransition();
view.getViewTreeObserver().addOnPreDrawListener(() -> {
startPostponedEnterTransition();
return true;
});
}
public void loadList() {
@@ -209,7 +195,7 @@ public class SubaddressFragment extends Fragment implements SubaddressInfoAdapte
@Override
protected void onPreExecute() {
super.onPreExecute();
if ((wallet.getDeviceType() == Wallet.Device.Device_Ledger) && (progressCallback != null)) {
if ((wallet.getDeviceType() == Wallet.Device.Ledger) && (progressCallback != null)) {
progressCallback.showLedgerProgressDialog(LedgerProgressDialog.TYPE_SUBADDRESS);
dialogOpened = true;
}
@@ -252,4 +238,5 @@ public class SubaddressFragment extends Fragment implements SubaddressInfoAdapte
activityCallback.showSubaddress(view, subaddress.getAddressIndex());
return false;
}
}

View File

@@ -29,15 +29,15 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.transition.Transition;
import androidx.transition.TransitionInflater;
import com.google.android.material.textfield.TextInputLayout;
import com.google.android.material.transition.MaterialContainerTransform;
import com.m2049r.xmrwallet.data.Subaddress;
import com.m2049r.xmrwallet.layout.TransactionInfoAdapter;
import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.util.ArrayList;
@@ -46,7 +46,7 @@ import java.util.List;
import timber.log.Timber;
public class SubaddressInfoFragment extends Fragment
implements TransactionInfoAdapter.OnInteractionListener, OnBlockUpdateListener {
implements TransactionInfoAdapter.Listener, OnBlockUpdateListener {
private TransactionInfoAdapter adapter;
private Subaddress subaddress;
@@ -76,7 +76,7 @@ public class SubaddressInfoFragment extends Fragment
etName.getEditText().setText(subaddress.getDisplayLabel());
tvAddress.setText(getContext().getString(R.string.subbaddress_info_subtitle,
subaddress.getAddressIndex(), subaddress.getSquashedAddress()));
subaddress.getAddressIndex(), subaddress.getAddress()));
etName.getEditText().setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
@@ -102,10 +102,8 @@ public class SubaddressInfoFragment extends Fragment
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final MaterialContainerTransform transform = new MaterialContainerTransform();
transform.setDrawingViewId(R.id.fragment_container);
transform.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
transform.setAllContainerColors(ThemeHelper.getThemedColor(getContext(), android.R.attr.colorBackground));
Transition transform = TransitionInflater.from(requireContext())
.inflateTransition(R.transition.details);
setSharedElementEnterTransition(transform);
}
@@ -147,6 +145,8 @@ public class SubaddressInfoFragment extends Fragment
void setTitle(String title, String subtitle);
void setSubtitle(String subtitle);
long getDaemonHeight();
}
@Override
@@ -172,4 +172,9 @@ public class SubaddressInfoFragment extends Fragment
public void onPause() {
super.onPause();
}
@Override
public long getDaemonHeight() {
return activityCallback.getDaemonHeight();
}
}

View File

@@ -36,9 +36,9 @@ import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.transition.Transition;
import androidx.transition.TransitionInflater;
import com.google.android.material.transition.MaterialContainerTransform;
import com.google.android.material.transition.MaterialElevationScale;
import com.m2049r.xmrwallet.data.Subaddress;
import com.m2049r.xmrwallet.data.UserNotes;
import com.m2049r.xmrwallet.model.TransactionInfo;
@@ -79,10 +79,14 @@ public class TxFragment extends Fragment {
private TextView tvTxPaymentId;
private TextView tvTxBlockheight;
private TextView tvTxAmount;
private TextView tvTxPocketChangeAmount;
private TextView tvTxFee;
private TextView tvTxTransfers;
private TextView etTxNotes;
private View llWarning;
private TextView tvWarning;
// XMRTO stuff
private View cvXmrTo;
private TextView tvTxXmrToKey;
@@ -96,13 +100,6 @@ public class TxFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tx_info, container, false);
final MaterialElevationScale exitTransition = new MaterialElevationScale(false);
exitTransition.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
setExitTransition(exitTransition);
final MaterialElevationScale reenterTransition = new MaterialElevationScale(true);
reenterTransition.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
setReenterTransition(reenterTransition);
cvXmrTo = view.findViewById(R.id.cvXmrTo);
tvTxXmrToKey = view.findViewById(R.id.tvTxXmrToKey);
tvDestinationBtc = view.findViewById(R.id.tvDestinationBtc);
@@ -120,12 +117,15 @@ public class TxFragment extends Fragment {
tvTxPaymentId = view.findViewById(R.id.tvTxPaymentId);
tvTxBlockheight = view.findViewById(R.id.tvTxBlockheight);
tvTxAmount = view.findViewById(R.id.tvTxAmount);
tvTxPocketChangeAmount = view.findViewById(R.id.tvTxPocketChangeAmount);
tvTxFee = view.findViewById(R.id.tvTxFee);
tvTxTransfers = view.findViewById(R.id.tvTxTransfers);
etTxNotes = view.findViewById(R.id.etTxNotes);
etTxNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
llWarning = view.findViewById(R.id.llWarning);
tvWarning = view.findViewById(R.id.tvWarning);
tvTxXmrToKey.setOnClickListener(v -> {
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_xmrtokey), tvTxXmrToKey.getText().toString());
Toast.makeText(getActivity(), getString(R.string.message_copy_xmrtokey), Toast.LENGTH_SHORT).show();
@@ -251,8 +251,10 @@ public class TxFragment extends Fragment {
}
String sign = (info.direction == TransactionInfo.Direction.Direction_In ? "+" : "-");
long realAmount = info.amount;
tvTxAmount.setText(sign + Wallet.getDisplayAmount(realAmount));
tvTxAmount.setText(sign + Wallet.getDisplayAmount(info.amount));
final long pcAmount = info.getPocketChangeAmount();
tvTxPocketChangeAmount.setVisibility(pcAmount > 0 ? View.VISIBLE : View.GONE);
tvTxPocketChangeAmount.setText(getString(R.string.pocketchange_tx_detail, Wallet.getDisplayAmount(pcAmount)));
if ((info.fee > 0)) {
String fee = Wallet.getDisplayAmount(info.fee);
@@ -306,6 +308,20 @@ public class TxFragment extends Fragment {
tvTxTransfers.setText(sb.toString());
tvDestination.setText(dstSb.toString());
showBtcInfo();
showLock();
}
private void showLock() {
llWarning.setVisibility(View.GONE);
if (info.unlockTime == 0) return;
final long blockheight = activityCallback.getDaemonHeight();
final long blocks = info.unlockTime - blockheight;
final double unlockDays = blocks / (30. * 24);
if (unlockDays > 0) {
llWarning.setVisibility(View.VISIBLE);
tvWarning.setText(getString(R.string.tx_locked, info.unlockTime, blocks, unlockDays));
}
}
@SuppressLint("SetTextI18n")
@@ -347,10 +363,8 @@ public class TxFragment extends Fragment {
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
final MaterialContainerTransform transform = new MaterialContainerTransform();
transform.setDrawingViewId(R.id.fragment_container);
transform.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
transform.setAllContainerColors(ThemeHelper.getThemedColor(getContext(), android.R.attr.colorBackground));
Transition transform = TransitionInflater.from(requireContext())
.inflateTransition(R.transition.details);
setSharedElementEnterTransition(transform);
}
@@ -379,6 +393,7 @@ public class TxFragment extends Fragment {
void showSubaddress(View view, final int subaddressIndex);
long getDaemonHeight();
}
@Override

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,6 @@ import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import com.github.brnunes.swipeablerecyclerview.SwipeableRecyclerViewTouchListener;
import com.google.android.material.transition.MaterialElevationScale;
import com.m2049r.xmrwallet.layout.TransactionInfoAdapter;
import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Wallet;
@@ -63,7 +62,7 @@ import java.util.List;
import timber.log.Timber;
public class WalletFragment extends Fragment
implements TransactionInfoAdapter.OnInteractionListener {
implements TransactionInfoAdapter.Listener {
private TransactionInfoAdapter adapter;
private final NumberFormat formatter = NumberFormat.getInstance();
@@ -113,15 +112,15 @@ public class WalletFragment extends Fragment
flExchange = view.findViewById(R.id.flExchange);
((ProgressBar) view.findViewById(R.id.pbExchange)).getIndeterminateDrawable().
setColorFilter(
ThemeHelper.getThemedColor(getContext(), R.attr.colorPrimaryVariant),
ThemeHelper.getThemedColor(getContext(), com.google.android.material.R.attr.colorPrimaryVariant),
android.graphics.PorterDuff.Mode.MULTIPLY);
tvProgress = view.findViewById(R.id.tvProgress);
pbProgress = view.findViewById(R.id.pbProgress);
tvBalance = view.findViewById(R.id.tvBalance);
showBalance(Helper.getDisplayAmount(0));
showBalance();
tvUnconfirmedAmount = view.findViewById(R.id.tvUnconfirmedAmount);
showUnconfirmed(0);
showUnconfirmed();
ivSynced = view.findViewById(R.id.ivSynced);
sCurrency = view.findViewById(R.id.sCurrency);
@@ -204,14 +203,20 @@ public class WalletFragment extends Fragment
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
postponeEnterTransition();
view.getViewTreeObserver().addOnPreDrawListener(() -> {
startPostponedEnterTransition();
return true;
});
}
void showBalance(String balance) {
String amountToString(double amount) {
if (!Helper.BASE_CRYPTO.equals(balanceCurrency)) { // not XMR
double amountB = amount * balanceRate;
return Helper.getFormattedAmount(amountB, false);
} else { // XMR
return Helper.getFormattedAmount(amount, true);
}
}
void showBalance() {
double amountA = Helper.getDecimalAmount(unlockedBalance).doubleValue();
String balance = amountToString(amountA);
tvBalance.setText(balance);
final boolean streetMode = activityCallback.isStreetMode();
if (!streetMode) {
@@ -224,13 +229,14 @@ public class WalletFragment extends Fragment
setStreetModeBackground(streetMode);
}
void showUnconfirmed(double unconfirmedAmount) {
void showUnconfirmed() {
double unconfirmedAmount = Helper.getDecimalAmount(balance - unlockedBalance).doubleValue();
if (activityCallback.isStreetMode() || unconfirmedAmount == 0) {
tvUnconfirmedAmount.setText(null);
tvUnconfirmedAmount.setVisibility(View.GONE);
} else {
String unconfirmed = Helper.getFormattedAmount(unconfirmedAmount, true);
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, unconfirmed));
String unconfirmed = amountToString(unconfirmedAmount);
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, unconfirmed, balanceCurrency));
tvUnconfirmedAmount.setVisibility(View.VISIBLE);
}
}
@@ -238,15 +244,8 @@ public class WalletFragment extends Fragment
void updateBalance() {
if (isExchanging) return; // wait for exchange to finish - it will fire this itself then.
// at this point selection is XMR in case of error
String displayB;
double amountA = Helper.getDecimalAmount(unlockedBalance).doubleValue();
if (!Helper.BASE_CRYPTO.equals(balanceCurrency)) { // not XMR
double amountB = amountA * balanceRate;
displayB = Helper.getFormattedAmount(amountB, false);
} else { // XMR
displayB = Helper.getFormattedAmount(amountA, true);
}
showBalance(displayB);
showBalance();
showUnconfirmed();
}
String balanceCurrency = Helper.BASE_CRYPTO;
@@ -255,11 +254,11 @@ public class WalletFragment extends Fragment
private final ExchangeApi exchangeApi = ServiceHelper.getExchangeApi();
void refreshBalance() {
double unconfirmedXmr = Helper.getDecimalAmount(balance - unlockedBalance).doubleValue();
showUnconfirmed(unconfirmedXmr);
if (sCurrency.getSelectedItemPosition() == 0) { // XMR
double amountXmr = Helper.getDecimalAmount(unlockedBalance).doubleValue();
showBalance(Helper.getFormattedAmount(amountXmr, true));
balanceCurrency = Helper.BASE_CRYPTO;
balanceRate = 1.0;
showBalance();
showUnconfirmed();
} else { // not XMR
String currency = (String) sCurrency.getSelectedItem();
Timber.d(currency);
@@ -304,8 +303,7 @@ public class WalletFragment extends Fragment
public void exchangeFailed() {
sCurrency.setSelection(0, true); // default to XMR
double amountXmr = Helper.getDecimalAmount(unlockedBalance).doubleValue();
showBalance(Helper.getFormattedAmount(amountXmr, true));
showBalance();
hideExchanging();
}
@@ -333,19 +331,9 @@ public class WalletFragment extends Fragment
// Callbacks from TransactionInfoAdapter
@Override
public void onInteraction(final View view, final TransactionInfo infoItem) {
final MaterialElevationScale exitTransition = new MaterialElevationScale(false);
exitTransition.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
setExitTransition(exitTransition);
final MaterialElevationScale reenterTransition = new MaterialElevationScale(true);
reenterTransition.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
setReenterTransition(reenterTransition);
activityCallback.onTxDetailsRequest(view, infoItem);
}
// called from activity
// if account index has changed scroll to top?
private int accountIndex = 0;
@@ -459,12 +447,13 @@ public class WalletFragment extends Fragment
String sync;
if (!activityCallback.hasBoundService())
throw new IllegalStateException("WalletService not bound.");
ivSynced.setVisibility(View.GONE);
Wallet.ConnectionStatus daemonConnected = activityCallback.getConnectionStatus();
if (daemonConnected == Wallet.ConnectionStatus.ConnectionStatus_Connected) {
if (!wallet.isSynchronized()) {
long daemonHeight = activityCallback.getDaemonHeight();
long walletHeight = wallet.getBlockChainHeight();
long n = daemonHeight - walletHeight;
final long daemonHeight = getDaemonHeight();
final long walletHeight = wallet.getBlockChainHeight();
final long n = daemonHeight - walletHeight;
sync = getString(R.string.status_syncing) + " " + formatter.format(n) + " " + getString(R.string.status_remaining);
if (firstBlock == 0) {
firstBlock = walletHeight;
@@ -472,7 +461,6 @@ public class WalletFragment extends Fragment
int x = 100 - Math.round(100f * n / (1f * daemonHeight - firstBlock));
if (x == 0) x = 101; // indeterminate
setProgress(x);
ivSynced.setVisibility(View.GONE);
} else {
sync = getString(R.string.status_synced) + " " + formatter.format(wallet.getBlockChainHeight());
ivSynced.setVisibility(View.VISIBLE);
@@ -538,8 +526,6 @@ public class WalletFragment extends Fragment
@Override
public void onResume() {
super.onResume();
setExitTransition(null);
setReenterTransition(null);
Timber.d("onResume()");
activityCallback.setTitle(walletTitle, walletSubtitle);
activityCallback.setToolbarButton(Toolbar.BUTTON_NONE);
@@ -574,4 +560,9 @@ public class WalletFragment extends Fragment
} else
ivStreetGunther.setImageDrawable(null);
}
@Override
public long getDaemonHeight() {
return activityCallback.getDaemonHeight();
}
}

View File

@@ -22,8 +22,8 @@ import android.content.res.Configuration;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import com.m2049r.xmrwallet.BuildConfig;
import com.m2049r.xmrwallet.model.NetworkType;
import com.m2049r.xmrwallet.util.LocaleHelper;
import com.m2049r.xmrwallet.util.NetCipherHelper;
@@ -36,7 +36,6 @@ public class XmrWalletApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
FragmentManager.enableNewStateManager(false);
if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2018 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet.data;
import android.bluetooth.BluetoothDevice;
import java.util.Comparator;
import lombok.Data;
import lombok.Getter;
@Data
public class BluetoothInfo {
@Getter
final private String name;
@Getter
final private String address;
@Getter
private boolean bonded;
public BluetoothInfo(BluetoothDevice device) {
name = device.getName().trim();
address = device.getAddress();
bonded = device.getBondState() == BluetoothDevice.BOND_BONDED;
}
static public Comparator<BluetoothInfo> NameComparator = (o1, o2) -> o1.name.compareTo(o2.name);
}

View File

@@ -19,21 +19,26 @@ package com.m2049r.xmrwallet.data;
import lombok.AllArgsConstructor;
import lombok.Getter;
// Nodes stolen from https://moneroworld.com/#nodes
@Getter
@AllArgsConstructor
public enum DefaultNodes {
MONERUJO("nodex.monerujo.io:18081"),
XMRTO("node.xmr.to:18081"),
SUPPORTXMR("node.supportxmr.com:18081"),
HASHVAULT("nodes.hashvault.pro:18081"),
MONEROWORLD("node.moneroworld.com:18089"),
XMRTW("opennode.xmr-tw.org:18089"),
MONERUJO_ONION("monerujods7mbghwe6cobdr6ujih6c22zu5rl7zshmizz2udf7v7fsad.onion:18081/mainnet/monerujo.onion"),
Criminales78("56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion:18089/mainnet/Criminales78.onion"),
xmrfail("mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion:18081/mainnet/xmrfail.onion"),
boldsuck("6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion:18081/mainnet/boldsuck.onion");
AGORIST("xmr.agor.ist:18089/mainnet/agor.ist"),
BOLDSUCK("xmr-de.boldsuck.org:18080/mainnet/boldsuck.org"),
boldsuck("6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion:18081/mainnet/boldsuck.onion"),
CAKE("xmr-node.cakewallet.com:18081/mainnet/cakewallet.com"),
DS_JETZT("monero.ds-jetzt.de:18089/mainnet/ds-jetzt.de"),
ds_jetzt("qvlr4w7yhnjrdg3txa72jwtpnjn4ezsrivzvocbnvpfbdo342fahhoad.onion:18089/mainnet/ds-jetzt.onion"),
MONERODEVS("node.monerodevs.org:18089/mainnet/monerodevs.org"),
MONERUJO("nodex.monerujo.io:18081/mainnet/monerujo.io"),
monerujo("monerujods7mbghwe6cobdr6ujih6c22zu5rl7zshmizz2udf7v7fsad.onion:18081/mainnet/monerujo.onion"),
SETH("node.sethforprivacy.com:18089/mainnet/sethforprivacy.com"),
seth("sfpp2p7wnfjv3lrvfan4jmmkvhnbsbimpa3cqyuf7nt6zd24xhcqcsyd.onion/mainnet/sethforprivacy.onion"),
STACK("monero.stackwallet.com:18081/mainnet/stackwallet.com"),
STORMYCLOUD("xmr.stormycloud.org:18089/mainnet/stormycloud.org"),
TENZ("monero.10z.com.ar:18089/mainnet/10z.com.ar"),
XMRROCKS("node.xmr.rocks:18089/mainnet/xmr.rocks"),
xmrrocks("xqnnz2xmlmtpy2p4cm4cphg2elkwu5oob7b7so5v4wwgt44p6vbx5ryd.onion/mainnet/xmr.rocks.onion"),
XMRTW("opennode.xmr-tw.org:18089/mainnet/xmr-tw.org");
@Getter
private final String uri;
}

View File

@@ -144,7 +144,7 @@ public class Node {
if ((nodeString == null) || nodeString.isEmpty())
throw new IllegalArgumentException("daemon is empty");
String daemonAddress;
String a[] = nodeString.split("@");
String[] a = nodeString.split("@");
if (a.length == 1) { // no credentials
daemonAddress = a[0];
username = "";
@@ -169,7 +169,7 @@ public class Node {
throw new IllegalArgumentException("Too many '/' or too few");
daemonAddress = daParts[0];
String da[] = daemonAddress.split(":");
String[] da = daemonAddress.split(":");
if ((da.length > 2) || (da.length < 1))
throw new IllegalArgumentException("Too many ':' or too few");
String host = da[0];

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