1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-03 08:23:04 +02:00

Compare commits

...

33 Commits

Author SHA1 Message Date
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 ✓

* 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
m2049r
cdb29bbc2e themes (#821)
* Support multiple colour themes
* Fix sharing
* Add settings
* Fantastic UI tweaks
2022-03-09 19:10:30 +01:00
m2049r
7b96baeca7 fix watch only 2022-01-03 12:53:31 +01:00
m2049r
0712efec78 allow seed offset generation & wallet restore (#804) 2022-01-02 20:50:07 +01:00
Katant Savelev
341df6c6a3 Update RU translation (#798)
* Update help.xml

* Update strings.xml
2022-01-02 14:10:33 +01:00
m2049r
ab8fb82c1b fix unit tests (#803) 2022-01-02 14:07:23 +01:00
m2049r
22d9173cea store only through service & setPassword (#802) 2022-01-02 13:05:46 +01:00
200 changed files with 3970 additions and 1042 deletions

View File

@@ -3,13 +3,11 @@ jobs:
build:
working_directory: ~/code
docker:
- image: circleci/android:api-28-ndk
- image: cimg/android:2022.03-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:

View File

@@ -1,15 +1,15 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
compileSdkVersion 31
buildToolsVersion '30.0.3'
ndkVersion '17.2.4988734'
defaultConfig {
applicationId "com.m2049r.xmrwallet"
minSdkVersion 21
targetSdkVersion 30
versionCode 1201
versionName "2.2.1 'René'"
targetSdkVersion 31
versionCode 1403
versionName "2.4.3 'Baldaŭ'"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
@@ -111,6 +111,7 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
namespace 'com.m2049r.xmrwallet'
}
static def getId(name) {
@@ -120,38 +121,39 @@ static def getId(name) {
}
dependencies {
implementation 'androidx.core:core:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.core:core:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.preference:preference:1.2.0'
implementation 'com.google.android.material:material:1.6.0'
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation "com.squareup.okhttp3:okhttp:4.9.0"
implementation "io.github.rburgst:okhttp-digest:2.5"
implementation "com.jakewharton.timber:timber:4.7.1"
implementation "com.squareup.okhttp3:okhttp:4.9.3"
implementation "io.github.rburgst:okhttp-digest:2.6"
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.3.0'
implementation 'com.nulab-inc:zxcvbn:1.5.2'
implementation 'dnsjava:dnsjava:2.1.9'
implementation 'org.jitsi:dnssecjava:1.2.0'
implementation 'org.slf4j:slf4j-nop:1.7.30'
implementation 'org.slf4j:slf4j-nop:1.7.36'
implementation 'com.github.brnunes:swipeablerecyclerview:1.0.2'
//noinspection GradleDependency
testImplementation "junit:junit:$rootProject.ext.junitVersion"
testImplementation "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
testImplementation "com.squareup.okhttp3:mockwebserver:4.9.0"
testImplementation 'org.json:json:20180813'
testImplementation 'net.jodah:concurrentunit:0.4.4'
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 'net.jodah:concurrentunit:0.4.6'
compileOnly 'org.projectlombok:lombok:1.18.16'
annotationProcessor 'org.projectlombok:lombok:1.18.16'
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
}

View File

@@ -1,6 +1,5 @@
<?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-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -18,7 +17,6 @@
<intent>
<action android:name="org.torproject.android.intent.action.STATUS" />
</intent>
<intent>
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
</intent>
@@ -36,15 +34,17 @@
android:label="@string/app_name"
android:preserveLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="@style/MyMaterialTheme"
android:theme="@style/MyMaterialThemeClassic"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|uiMode"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
@@ -56,24 +56,25 @@
android:screenOrientation="behind" />
<activity
android:name=".LoginActivity"
android:configChanges="orientation|keyboardHidden|uiMode"
android:configChanges="orientation|keyboardHidden"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTop"
android:screenOrientation="locked">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<data android:scheme="monero" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<data android:scheme="bitcoin" />
<category android:name="android.intent.category.DEFAULT" />
@@ -106,4 +107,5 @@
android:resource="@xml/filepaths" />
</provider>
</application>
</manifest>
</manifest>

View File

@@ -229,7 +229,7 @@ std::vector<std::string> java2cpp(JNIEnv *env, jobject arrayList) {
return result;
}
jobject cpp2java(JNIEnv *env, const std::vector<std::string>& vector) {
jobject cpp2java(JNIEnv *env, const std::vector<std::string> &vector) {
jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "<init>", "(I)V");
jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add",
@@ -301,12 +301,13 @@ Java_com_m2049r_xmrwallet_model_WalletManager_openWalletJ(JNIEnv *env, jobject i
JNIEXPORT jlong JNICALL
Java_com_m2049r_xmrwallet_model_WalletManager_recoveryWalletJ(JNIEnv *env, jobject instance,
jstring path, jstring password,
jstring mnemonic,
jstring mnemonic, jstring offset,
jint networkType,
jlong restoreHeight) {
const char *_path = env->GetStringUTFChars(path, nullptr);
const char *_password = env->GetStringUTFChars(password, nullptr);
const char *_mnemonic = env->GetStringUTFChars(mnemonic, nullptr);
const char *_offset = env->GetStringUTFChars(offset, nullptr);
Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
Bitmonero::Wallet *wallet =
@@ -315,11 +316,14 @@ Java_com_m2049r_xmrwallet_model_WalletManager_recoveryWalletJ(JNIEnv *env, jobje
std::string(_password),
std::string(_mnemonic),
_networkType,
(uint64_t) restoreHeight);
(uint64_t) restoreHeight,
1, // kdf_rounds
std::string(_offset));
env->ReleaseStringUTFChars(path, _path);
env->ReleaseStringUTFChars(password, _password);
env->ReleaseStringUTFChars(mnemonic, _mnemonic);
env->ReleaseStringUTFChars(offset, _offset);
return reinterpret_cast<jlong>(wallet);
}
@@ -533,7 +537,7 @@ Java_com_m2049r_xmrwallet_model_WalletManager_resolveOpenAlias(JNIEnv *env, jobj
JNIEXPORT jboolean JNICALL
Java_com_m2049r_xmrwallet_model_WalletManager_setProxy(JNIEnv *env, jobject instance,
jstring address) {
jstring address) {
const char *_address = env->GetStringUTFChars(address, nullptr);
bool rc =
Bitmonero::WalletManagerFactory::getWalletManager()->setProxy(std::string(_address));
@@ -570,9 +574,12 @@ Java_com_m2049r_xmrwallet_model_WalletManager_closeJ(JNIEnv *env, jobject instan
/**********************************/
JNIEXPORT jstring JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getSeed(JNIEnv *env, jobject instance) {
Java_com_m2049r_xmrwallet_model_Wallet_getSeed(JNIEnv *env, jobject instance, jstring seedOffset) {
const char *_seedOffset = env->GetStringUTFChars(seedOffset, nullptr);
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return env->NewStringUTF(wallet->seed().c_str());
jstring seed = env->NewStringUTF(wallet->seed(std::string(_seedOffset)).c_str());
env->ReleaseStringUTFChars(seedOffset, _seedOffset);
return seed;
}
JNIEXPORT jstring JNICALL
@@ -740,7 +747,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_getConnectionStatusJ(JNIEnv *env, jobject
JNIEXPORT jboolean JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_setProxy(JNIEnv *env, jobject instance,
jstring address) {
jstring address) {
const char *_address = env->GetStringUTFChars(address, nullptr);
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
bool rc = wallet->setProxy(std::string(_address));
@@ -1262,7 +1269,7 @@ jobject newTransactionInfo(JNIEnv *env, Bitmonero::TransactionInfo *info) {
#include <stdio.h>
#include <stdlib.h>
jobject cpp2java(JNIEnv *env, const std::vector<Bitmonero::TransactionInfo *>& vector) {
jobject cpp2java(JNIEnv *env, const std::vector<Bitmonero::TransactionInfo *> &vector) {
jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "<init>", "(I)V");
jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add",

View File

@@ -78,7 +78,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;

View File

@@ -27,6 +27,7 @@ import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -180,7 +181,7 @@ public class BaseActivity extends SecureActivity
return;
nfcPendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
0);
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0);
}
private void processNfcIntent(Intent intent) {

View File

@@ -36,7 +36,6 @@ import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
@@ -58,7 +57,6 @@ import com.m2049r.xmrwallet.widget.Toolbar;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Objects;
import timber.log.Timber;
@@ -81,6 +79,9 @@ public class GenerateFragment extends Fragment {
private TextInputLayout etWalletRestoreHeight;
private Button bGenerate;
private Button bSeedOffset;
private TextInputLayout etSeedOffset;
private String type = null;
private void clearErrorOnTextEntry(final TextInputLayout textInputLayout) {
@@ -118,6 +119,8 @@ public class GenerateFragment extends Fragment {
etWalletSpendKey = view.findViewById(R.id.etWalletSpendKey);
etWalletRestoreHeight = view.findViewById(R.id.etWalletRestoreHeight);
bGenerate = view.findViewById(R.id.bGenerate);
bSeedOffset = view.findViewById(R.id.bSeedOffset);
etSeedOffset = view.findViewById(R.id.etSeedOffset);
etWalletAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etWalletViewKey.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
@@ -222,6 +225,8 @@ public class GenerateFragment extends Fragment {
}
return false;
});
bSeedOffset.setVisibility(View.VISIBLE);
bSeedOffset.setOnClickListener(v -> toggleSeedOffset());
break;
case TYPE_KEY:
case TYPE_VIEWONLY:
@@ -288,6 +293,18 @@ public class GenerateFragment extends Fragment {
return view;
}
void toggleSeedOffset() {
if (etSeedOffset.getVisibility() == View.VISIBLE) {
etSeedOffset.getEditText().getText().clear();
etSeedOffset.setVisibility(View.GONE);
bSeedOffset.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_keyboard_arrow_down, 0, 0, 0);
} else {
etSeedOffset.setVisibility(View.VISIBLE);
bSeedOffset.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_keyboard_arrow_up, 0, 0, 0);
etSeedOffset.requestFocusFromTouch();
}
}
private boolean checkName() {
String name = etWalletName.getEditText().getText().toString();
boolean ok = true;
@@ -422,12 +439,13 @@ public class GenerateFragment extends Fragment {
break;
case TYPE_SEED:
if (!checkMnemonic()) return;
String seed = etWalletMnemonic.getEditText().getText().toString();
final String seed = etWalletMnemonic.getEditText().getText().toString();
bGenerate.setEnabled(false);
if (fingerprintAuthAllowed) {
KeyStoreHelper.saveWalletUserPass(requireActivity(), name, password);
}
activityCallback.onGenerate(name, crazyPass, seed, height);
final String offset = etSeedOffset.getEditText().getText().toString();
activityCallback.onGenerate(name, crazyPass, seed, offset, height);
break;
case TYPE_LEDGER:
bGenerate.setEnabled(false);
@@ -491,7 +509,7 @@ public class GenerateFragment extends Fragment {
public interface Listener {
void onGenerate(String name, String password);
void onGenerate(String name, String password, String seed, long height);
void onGenerate(String name, String password, String seed, String offset, long height);
void onGenerate(String name, String password, String address, String viewKey, String spendKey, long height);

View File

@@ -26,6 +26,7 @@ import android.content.SharedPreferences;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -39,7 +40,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
@@ -49,24 +49,19 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.m2049r.xmrwallet.data.DefaultNodes;
import com.m2049r.xmrwallet.data.Node;
import com.m2049r.xmrwallet.data.NodeInfo;
import com.m2049r.xmrwallet.dialog.AboutFragment;
import com.m2049r.xmrwallet.dialog.CreditsFragment;
import com.m2049r.xmrwallet.dialog.HelpFragment;
import com.m2049r.xmrwallet.dialog.PrivacyFragment;
import com.m2049r.xmrwallet.ledger.Ledger;
import com.m2049r.xmrwallet.ledger.LedgerProgressDialog;
import com.m2049r.xmrwallet.model.NetworkType;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.WalletService;
import com.m2049r.xmrwallet.util.DayNightMode;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.KeyStoreHelper;
import com.m2049r.xmrwallet.util.LegacyStorageHelper;
import com.m2049r.xmrwallet.util.LocaleHelper;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
import com.m2049r.xmrwallet.util.NetCipherHelper;
import com.m2049r.xmrwallet.util.NightmodeHelper;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.util.ZipBackup;
import com.m2049r.xmrwallet.util.ZipRestore;
@@ -77,12 +72,8 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -90,7 +81,8 @@ import timber.log.Timber;
public class LoginActivity extends BaseActivity
implements LoginFragment.Listener, GenerateFragment.Listener,
GenerateReviewFragment.Listener, GenerateReviewFragment.AcceptListener, NodeFragment.Listener {
GenerateReviewFragment.Listener, GenerateReviewFragment.AcceptListener,
NodeFragment.Listener, SettingsFragment.Listener {
private static final String GENERATE_STACK = "gen";
private static final String NODES_PREFS_NAME = "nodes";
@@ -293,6 +285,7 @@ public class LoginActivity extends BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
Timber.d("onCreate()");
ThemeHelper.setPreferred(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
@@ -308,8 +301,8 @@ public class LoginActivity extends BaseActivity
case Toolbar.BUTTON_CLOSE:
finish();
break;
case Toolbar.BUTTON_CREDITS:
CreditsFragment.display(getSupportFragmentManager());
case Toolbar.BUTTON_SETTINGS:
startSettingsFragment();
break;
case Toolbar.BUTTON_NONE:
break;
@@ -785,6 +778,11 @@ public class LoginActivity extends BaseActivity
Timber.d("NodeFragment placed");
}
void startSettingsFragment() {
replaceFragment(new SettingsFragment(), null, null);
Timber.d("SettingsFragment placed");
}
void replaceFragment(Fragment newFragment, String stackName, Bundle extras) {
if (extras != null) {
newFragment.setArguments(extras);
@@ -929,7 +927,8 @@ public class LoginActivity extends BaseActivity
}
@Override
public void onGenerate(final String name, final String password, final String seed,
public void onGenerate(final String name, final String password,
final String seed, final String offset,
final long restoreHeight) {
createWallet(name, password,
new WalletCreator() {
@@ -941,7 +940,7 @@ public class LoginActivity extends BaseActivity
@Override
public boolean createWallet(File aFile, String password) {
Wallet newWallet = WalletManager.getInstance()
.recoveryWallet(aFile, password, seed, restoreHeight);
.recoveryWallet(aFile, password, seed, offset, restoreHeight);
return checkAndCloseWallet(newWallet);
}
});
@@ -1088,61 +1087,6 @@ public class LoginActivity extends BaseActivity
}
}
public void onChangeLocale() {
final ArrayList<Locale> availableLocales = LocaleHelper.getAvailableLocales(LoginActivity.this);
Collections.sort(availableLocales, (locale1, locale2) -> {
String localeString1 = LocaleHelper.getDisplayName(locale1, true);
String localeString2 = LocaleHelper.getDisplayName(locale2, true);
return localeString1.compareTo(localeString2);
});
String[] localeDisplayNames = new String[1 + availableLocales.size()];
localeDisplayNames[0] = getString(R.string.language_system_default);
for (int i = 1; i < localeDisplayNames.length; i++) {
localeDisplayNames[i] = LocaleHelper.getDisplayName(availableLocales.get(i - 1), true);
}
int currentLocaleIndex = 0;
String currentLocaleTag = LocaleHelper.getPreferredLanguageTag(LoginActivity.this);
if (!currentLocaleTag.isEmpty()) {
Locale currentLocale = Locale.forLanguageTag(currentLocaleTag);
String currentLocaleName = LocaleHelper.getDisplayName(currentLocale, true);
currentLocaleIndex = Arrays.asList(localeDisplayNames).indexOf(currentLocaleName);
if (currentLocaleIndex < 0) currentLocaleIndex = 0;
}
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(LoginActivity.this);
builder.setTitle(getString(R.string.menu_language));
builder.setSingleChoiceItems(localeDisplayNames, currentLocaleIndex, (dialog, i) -> {
dialog.dismiss();
LocaleHelper.setAndSaveLocale(this,
(i == 0) ? "" : availableLocales.get(i - 1).toLanguageTag());
startActivity(getIntent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK));
});
builder.show();
}
public void onChangeTheme() {
final DayNightMode currentDayNightSetting = DayNightMode.getValue(AppCompatDelegate.getDefaultNightMode());
// selection will be empty if UNKNOWN
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(LoginActivity.this);
builder.setTitle(getString(R.string.menu_daynight));
String[] modeNames = getResources().getStringArray(R.array.daynight_themes);
builder.setSingleChoiceItems(modeNames, currentDayNightSetting.ordinal(), (dialog, i) -> {
dialog.dismiss();
final DayNightMode mode = DayNightMode.values()[i];
if (currentDayNightSetting != mode) {
NightmodeHelper.setAndSavePreferredNightmode(LoginActivity.this, mode);
LoginActivity.this.recreate();
}
});
builder.show();
}
@Override
public void onBackPressed() {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
@@ -1191,9 +1135,6 @@ public class LoginActivity extends BaseActivity
} else if (id == R.id.action_details_changepw) {
onWalletChangePassword();
return true;
} else if (id == R.id.action_license_info) {
AboutFragment.display(getSupportFragmentManager());
return true;
} else if (id == R.id.action_help_list) {
HelpFragment.display(getSupportFragmentManager(), R.string.help_list);
return true;
@@ -1207,18 +1148,6 @@ public class LoginActivity extends BaseActivity
((NodeFragment) f).restoreDefaultNodes();
}
return true;
} else if (id == R.id.action_privacy_policy) {
PrivacyFragment.display(getSupportFragmentManager());
return true;
} else if (id == R.id.action_language) {
onChangeLocale();
return true;
} else if (id == R.id.action_theme) {
onChangeTheme();
return true;
} else if (id == R.id.action_restore) {
onWalletRestore();
return true;
} else if (id == R.id.action_ledger_seed) {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (f instanceof GenerateFragment) {
@@ -1332,7 +1261,8 @@ public class LoginActivity extends BaseActivity
registerReceiver(usbPermissionReceiver, new IntentFilter(ACTION_USB_PERMISSION));
usbManager.requestPermission(device,
PendingIntent.getBroadcast(this, 0,
new Intent(ACTION_USB_PERMISSION), 0));
new Intent(ACTION_USB_PERMISSION),
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0));
}
} else {
Timber.d("no ledger device found");

View File

@@ -38,7 +38,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
@@ -53,6 +52,7 @@ import com.m2049r.xmrwallet.util.KeyStoreHelper;
import com.m2049r.xmrwallet.util.NetCipherHelper;
import com.m2049r.xmrwallet.util.NodePinger;
import com.m2049r.xmrwallet.util.Notice;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.io.File;
@@ -143,7 +143,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
super.onResume();
Timber.d("onResume() %s", activityCallback.getFavouriteNodes().size());
activityCallback.setTitle(null);
activityCallback.setToolbarButton(Toolbar.BUTTON_CREDITS);
activityCallback.setToolbarButton(Toolbar.BUTTON_SETTINGS);
activityCallback.showNet();
showNetwork();
//activityCallback.runOnNetCipher(this::pingSelectedNode);
@@ -163,12 +163,14 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabView = view.findViewById(R.id.fabView);
fabKey = view.findViewById(R.id.fabKey);
fabSeed = view.findViewById(R.id.fabSeed);
fabImport = view.findViewById(R.id.fabImport);
fabLedger = view.findViewById(R.id.fabLedger);
fabNewL = view.findViewById(R.id.fabNewL);
fabViewL = view.findViewById(R.id.fabViewL);
fabKeyL = view.findViewById(R.id.fabKeyL);
fabSeedL = view.findViewById(R.id.fabSeedL);
fabImportL = view.findViewById(R.id.fabImportL);
fabLedgerL = view.findViewById(R.id.fabLedgerL);
fab_pulse = AnimationUtils.loadAnimation(getContext(), R.anim.fab_pulse);
@@ -183,6 +185,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabView.setOnClickListener(this);
fabKey.setOnClickListener(this);
fabSeed.setOnClickListener(this);
fabImport.setOnClickListener(this);
fabLedger.setOnClickListener(this);
fabScreen.setOnClickListener(this);
@@ -294,9 +297,9 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
}
private boolean isFabOpen = false;
private FloatingActionButton fab, fabNew, fabView, fabKey, fabSeed, fabLedger;
private FrameLayout fabScreen;
private RelativeLayout fabNewL, fabViewL, fabKeyL, fabSeedL, fabLedgerL;
private FloatingActionButton fab, fabNew, fabView, fabKey, fabSeed, fabImport, fabLedger;
private RelativeLayout fabScreen;
private RelativeLayout fabNewL, fabViewL, fabKeyL, fabSeedL, fabImportL, fabLedgerL;
private Animation fab_open, fab_close, rotate_forward, rotate_backward, fab_open_screen, fab_close_screen;
private Animation fab_pulse;
@@ -321,6 +324,8 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabKey.setClickable(false);
fabSeedL.startAnimation(fab_close);
fabSeed.setClickable(false);
fabImportL.startAnimation(fab_close);
fabImport.setClickable(false);
}
isFabOpen = false;
} else { // open the fab
@@ -333,6 +338,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabViewL.setVisibility(View.GONE);
fabKeyL.setVisibility(View.GONE);
fabSeedL.setVisibility(View.GONE);
fabImportL.setVisibility(View.GONE);
fabLedgerL.startAnimation(fab_open);
fabLedger.setClickable(true);
@@ -342,6 +348,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabViewL.setVisibility(View.VISIBLE);
fabKeyL.setVisibility(View.VISIBLE);
fabSeedL.setVisibility(View.VISIBLE);
fabImportL.setVisibility(View.VISIBLE);
fabNewL.startAnimation(fab_open);
fabNew.setClickable(true);
@@ -351,6 +358,8 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabKey.setClickable(true);
fabSeedL.startAnimation(fab_open);
fabSeed.setClickable(true);
fabImportL.startAnimation(fab_open);
fabImport.setClickable(true);
}
isFabOpen = true;
}
@@ -375,6 +384,9 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
} else if (id == R.id.fabSeed) {
animateFAB();
activityCallback.onAddWallet(GenerateFragment.TYPE_SEED);
} else if (id == R.id.fabImport) {
animateFAB();
activityCallback.onWalletRestore();
} else if (id == R.id.fabLedger) {
Timber.d("FAB_LEDGER");
animateFAB();
@@ -403,8 +415,8 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
private void setSubtext(String status) {
final Context ctx = getContext();
final Spanned text = Html.fromHtml(ctx.getString(R.string.status,
Integer.toHexString(ContextCompat.getColor(ctx, R.color.monerujoGreen) & 0xFFFFFF),
Integer.toHexString(ContextCompat.getColor(ctx, R.color.monerujoBackground) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(ctx, R.attr.positiveColor) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(ctx, android.R.attr.colorBackground) & 0xFFFFFF),
status, ""));
tvNodeInfo.setText(text);
}

View File

@@ -415,7 +415,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;

View File

@@ -46,10 +46,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.ShareActionProvider;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
import com.google.android.material.textfield.TextInputLayout;
@@ -89,6 +86,7 @@ public class ReceiveFragment extends Fragment {
private ImageView ivQrCodeFull;
private EditText etDummy;
private ImageButton bCopyAddress;
private MenuItem shareItem;
private Wallet wallet = null;
private boolean isMyWallet = false;
@@ -128,6 +126,7 @@ public class ReceiveFragment extends Fragment {
evAmount.setOnNewAmountListener(xmr -> {
Timber.d("new amount = %s", xmr);
generateQr();
if (shareRequested && (xmr != null)) share();
});
evAmount.setOnFailedExchangeListener(() -> {
@@ -211,39 +210,38 @@ public class ReceiveFragment extends Fragment {
setSharedElementEnterTransition(transform);
}
private ShareActionProvider shareActionProvider;
private boolean shareRequested = false;
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.receive_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
// Locate MenuItem with ShareActionProvider
MenuItem item = menu.findItem(R.id.menu_item_share);
// Fetch and store ShareActionProvider
shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(item);
shareActionProvider.setOnShareTargetSelectedListener(new ShareActionProvider.OnShareTargetSelectedListener() {
@Override
public boolean onShareTargetSelected(ShareActionProvider shareActionProvider, Intent intent) {
saveQrCode(); // save it only if we need it
return false;
shareItem = menu.findItem(R.id.menu_item_share);
shareItem.setOnMenuItemClickListener(item -> {
if (shareRequested) return true;
shareRequested = true;
if (!qrValid) {
evAmount.doExchange();
} else {
share();
}
return true;
});
}
private void setShareIntent() {
if (shareActionProvider != null) {
if (qrValid) {
shareActionProvider.setShareIntent(getShareIntent());
} else {
shareActionProvider.setShareIntent(null);
}
private void share() {
shareRequested = false;
if (saveQrCode()) {
final Intent sendIntent = getSendIntent();
if (sendIntent != null)
startActivity(Intent.createChooser(sendIntent, null));
} else {
Toast.makeText(getActivity(), getString(R.string.message_qr_failed), Toast.LENGTH_SHORT).show();
}
}
private void saveQrCode() {
private boolean saveQrCode() {
if (!qrValid) throw new IllegalStateException("trying to save null qr code!");
File cachePath = new File(getActivity().getCacheDir(), "images");
@@ -255,33 +253,35 @@ public class ReceiveFragment extends Fragment {
Bitmap qrBitmap = ((BitmapDrawable) ivQrCode.getDrawable()).getBitmap();
qrBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
return true;
} catch (IOException ex) {
Timber.e(ex);
// make sure we don't share an old qr code
if (!png.delete()) throw new IllegalStateException("cannot delete old qr code");
// if we manage to delete it, the URI points to nothing and the user gets a toast with the error
}
return false;
}
private Intent getShareIntent() {
File imagePath = new File(getActivity().getCacheDir(), "images");
private Intent getSendIntent() {
File imagePath = new File(requireActivity().getCacheDir(), "images");
File png = new File(imagePath, "QR.png");
Uri contentUri = FileProvider.getUriForFile(getActivity(),
BuildConfig.APPLICATION_ID + ".fileprovider", png);
Uri contentUri = FileProvider.getUriForFile(requireActivity(), BuildConfig.APPLICATION_ID + ".fileprovider", png);
if (contentUri != null) {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file
shareIntent.setDataAndType(contentUri, getActivity().getContentResolver().getType(contentUri));
shareIntent.setTypeAndNormalize("image/png");
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.putExtra(Intent.EXTRA_TEXT, bcData.getUriString());
if (bcData != null)
shareIntent.putExtra(Intent.EXTRA_TEXT, bcData.getUriString());
return shareIntent;
}
return null;
}
void copyAddress() {
Helper.clipBoardCopy(Objects.requireNonNull(getActivity()), getString(R.string.label_copy_address), subaddress.getAddress());
Helper.clipBoardCopy(requireActivity(), getString(R.string.label_copy_address), subaddress.getAddress());
Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show();
}
@@ -291,7 +291,6 @@ public class ReceiveFragment extends Fragment {
if (qrValid) {
ivQrCode.setImageBitmap(null);
qrValid = false;
setShareIntent();
if (isLoaded)
tvQrCode.setVisibility(View.VISIBLE);
}
@@ -300,7 +299,6 @@ public class ReceiveFragment extends Fragment {
void setQR(Bitmap qr) {
ivQrCode.setImageBitmap(qr);
qrValid = true;
setShareIntent();
tvQrCode.setVisibility(View.GONE);
}
@@ -462,8 +460,8 @@ public class ReceiveFragment extends Fragment {
subaddress = newSubaddress;
final Context context = getContext();
Spanned label = Html.fromHtml(context.getString(R.string.receive_subaddress,
Integer.toHexString(ContextCompat.getColor(context, R.color.monerujoGreen) & 0xFFFFFF),
Integer.toHexString(ContextCompat.getColor(context, R.color.monerujoBackground) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(context, R.attr.positiveColor) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(context, android.R.attr.colorBackground) & 0xFFFFFF),
subaddress.getDisplayLabel(), subaddress.getAddress()));
tvAddress.setText(label);
generateQr();

View File

@@ -66,11 +66,7 @@ public abstract class SecureActivity extends AppCompatActivity {
Locale locale = LocaleHelper.getPreferredLocale(this);
if (locale != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale);
} else {
config.locale = locale;
}
config.setLocale(locale);
}
return config;
}

View File

@@ -0,0 +1,125 @@
package com.m2049r.xmrwallet;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.annotation.StyleRes;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
import com.m2049r.xmrwallet.dialog.AboutFragment;
import com.m2049r.xmrwallet.dialog.CreditsFragment;
import com.m2049r.xmrwallet.dialog.PrivacyFragment;
import com.m2049r.xmrwallet.util.DayNightMode;
import com.m2049r.xmrwallet.util.LocaleHelper;
import com.m2049r.xmrwallet.util.NightmodeHelper;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import timber.log.Timber;
public class SettingsFragment extends PreferenceFragmentCompat
implements SharedPreferences.OnSharedPreferenceChangeListener {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
findPreference(getString(R.string.about_info)).setOnPreferenceClickListener(preference -> {
AboutFragment.display(getParentFragmentManager());
return true;
});
findPreference(getString(R.string.privacy_info)).setOnPreferenceClickListener(preference -> {
PrivacyFragment.display(getParentFragmentManager());
return true;
});
findPreference(getString(R.string.credits_info)).setOnPreferenceClickListener(preference -> {
CreditsFragment.display(getParentFragmentManager());
return true;
});
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(getString(R.string.preferred_locale))) {
activity.recreate();
} else if (key.equals(getString(R.string.preferred_nightmode))) {
NightmodeHelper.setNightMode(DayNightMode.valueOf(sharedPreferences.getString(key, "AUTO")));
} else if (key.equals(getString(R.string.preferred_theme))) {
ThemeHelper.setTheme((Activity) activity, sharedPreferences.getString(key, "Classic"));
activity.recreate();
}
}
private SettingsFragment.Listener activity;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof SettingsFragment.Listener) {
activity = (SettingsFragment.Listener) context;
} else {
throw new ClassCastException(context + " must implement Listener");
}
}
@Override
public void onResume() {
super.onResume();
Timber.d("onResume()");
activity.setSubtitle(getString(R.string.menu_settings));
activity.setToolbarButton(Toolbar.BUTTON_BACK);
populateLanguages();
PreferenceManager.getDefaultSharedPreferences(requireContext())
.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
super.onPause();
PreferenceManager.getDefaultSharedPreferences(requireContext())
.unregisterOnSharedPreferenceChangeListener(this);
}
public interface Listener {
void setToolbarButton(int type);
void setSubtitle(String title);
void recreate();
void setTheme(@StyleRes final int resId);
}
public void populateLanguages() {
ListPreference language = findPreference(getString(R.string.preferred_locale));
assert language != null;
final ArrayList<Locale> availableLocales = LocaleHelper.getAvailableLocales(requireContext());
Collections.sort(availableLocales, (locale1, locale2) -> {
String localeString1 = LocaleHelper.getDisplayName(locale1, true);
String localeString2 = LocaleHelper.getDisplayName(locale2, true);
return localeString1.compareTo(localeString2);
});
String[] localeDisplayNames = new String[1 + availableLocales.size()];
localeDisplayNames[0] = getString(R.string.language_system_default);
for (int i = 1; i < localeDisplayNames.length; i++) {
localeDisplayNames[i] = LocaleHelper.getDisplayName(availableLocales.get(i - 1), true);
}
language.setEntries(localeDisplayNames);
String[] languageTags = new String[1 + availableLocales.size()];
languageTags[0] = "";
for (int i = 1; i < languageTags.length; i++) {
languageTags[i] = availableLocales.get(i - 1).toLanguageTag();
}
language.setEntryValues(languageTags);
}
}

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;
@@ -67,6 +66,8 @@ public class SubaddressFragment extends Fragment implements SubaddressInfoAdapte
void setToolbarButton(int type);
void showSubaddress(View view, final int subaddressIndex);
void saveWallet();
}
public interface ProgressListener {
@@ -115,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) {
@@ -152,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() {
@@ -217,7 +205,9 @@ public class SubaddressFragment extends Fragment implements SubaddressInfoAdapte
protected Boolean doInBackground(Void... params) {
if (params.length != 0) return false;
wallet.getNewSubaddress();
wallet.store();
if (activityCallback != null) {
activityCallback.saveWallet();
}
return true;
}

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;
@@ -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);
}

View File

@@ -35,11 +35,10 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
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;
@@ -97,13 +96,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);
@@ -220,8 +212,8 @@ public class TxFragment extends Fragment {
final Context ctx = getContext();
Spanned label = Html.fromHtml(ctx.getString(R.string.tx_account_formatted,
info.accountIndex, info.addressIndex,
Integer.toHexString(ContextCompat.getColor(ctx, R.color.monerujoGreen) & 0xFFFFFF),
Integer.toHexString(ContextCompat.getColor(ctx, R.color.monerujoBackground) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(ctx, R.attr.positiveColor) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(ctx, android.R.attr.colorBackground) & 0xFFFFFF),
subaddress.getDisplayLabel()));
tvAccount.setText(label);
tvAccount.setOnClickListener(v -> activityCallback.showSubaddress(v, info.addressIndex));
@@ -266,13 +258,13 @@ public class TxFragment extends Fragment {
if (info.isFailed) {
tvTxAmount.setText(getString(R.string.tx_list_amount_failed, Wallet.getDisplayAmount(info.amount)));
tvTxFee.setText(getString(R.string.tx_list_failed_text));
setTxColour(ContextCompat.getColor(getContext(), R.color.tx_failed));
setTxColour(ThemeHelper.getThemedColor(getContext(), R.attr.neutralColor));
} else if (info.isPending) {
setTxColour(ContextCompat.getColor(getContext(), R.color.tx_pending));
setTxColour(ThemeHelper.getThemedColor(getContext(), R.attr.neutralColor));
} else if (info.direction == TransactionInfo.Direction.Direction_In) {
setTxColour(ContextCompat.getColor(getContext(), R.color.tx_plus));
setTxColour(ThemeHelper.getThemedColor(getContext(), R.attr.positiveColor));
} else {
setTxColour(ContextCompat.getColor(getContext(), R.color.tx_minus));
setTxColour(ThemeHelper.getThemedColor(getContext(), R.attr.negativeColor));
}
Set<String> destinations = new HashSet<>();
StringBuilder sb = new StringBuilder();
@@ -348,10 +340,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);
}

View File

@@ -356,6 +356,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override
protected void onCreate(Bundle savedInstanceState) {
Timber.d("onCreate()");
ThemeHelper.setPreferred(this);
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
// activity restarted
@@ -385,7 +386,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
case Toolbar.BUTTON_CLOSE:
finish();
break;
case Toolbar.BUTTON_CREDITS:
case Toolbar.BUTTON_SETTINGS:
Toast.makeText(WalletActivity.this, getString(R.string.label_credits), Toast.LENGTH_SHORT).show();
case Toolbar.BUTTON_NONE:
default:
@@ -505,6 +506,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
Timber.d("onResume()");
}
@Override
public void saveWallet() {
if (mIsBound) { // no point in talking to unbound service
Intent intent = new Intent(getApplicationContext(), WalletService.class);
@@ -537,7 +539,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override
public void onSendRequest(View view) {
replaceFragmentWithTransition(view, SendFragment.newInstance(uri), null, null);
replaceFragment(SendFragment.newInstance(uri), null, null);
uri = null; // only use uri once
}
@@ -609,9 +611,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override
public void onWalletStored(final boolean success) {
runOnUiThread(() -> {
if (success) {
Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_unloaded), Toast.LENGTH_SHORT).show();
} else {
if (!success) {
Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_unload_failed), Toast.LENGTH_LONG).show();
}
});
@@ -800,10 +800,6 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
int transition;
if (newFragment instanceof TxFragment)
transition = R.string.tx_details_transition_name;
else if (newFragment instanceof ReceiveFragment)
transition = R.string.receive_transition_name;
else if (newFragment instanceof SendFragment)
transition = R.string.send_transition_name;
else if (newFragment instanceof SubaddressInfoFragment)
transition = R.string.subaddress_info_transition_name;
else
@@ -941,6 +937,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Timber.d("onRequestPermissionsResult()");
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == Helper.PERMISSIONS_REQUEST_CAMERA) { // If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
@@ -959,7 +956,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
Bundle b = new Bundle();
b.putString("address", address);
b.putString("name", getWalletName());
replaceFragmentWithTransition(view, new ReceiveFragment(), null, b);
replaceFragment(new ReceiveFragment(), null, b);
Timber.d("ReceiveFragment placed");
}

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;
@@ -52,6 +51,7 @@ import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.ServiceHelper;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.text.NumberFormat;
@@ -111,7 +111,8 @@ public class WalletFragment extends Fragment
llBalance = view.findViewById(R.id.llBalance);
flExchange = view.findViewById(R.id.flExchange);
((ProgressBar) view.findViewById(R.id.pbExchange)).getIndeterminateDrawable().
setColorFilter(getResources().getColor(R.color.progress_circle),
setColorFilter(
ThemeHelper.getThemedColor(getContext(), R.attr.colorPrimaryVariant),
android.graphics.PorterDuff.Mode.MULTIPLY);
tvProgress = view.findViewById(R.id.tvProgress);
@@ -202,11 +203,6 @@ 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) {
@@ -331,19 +327,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;
@@ -536,8 +522,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);

View File

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

View File

@@ -267,14 +267,14 @@ public class NodeInfo extends Node {
public void showInfo(TextView view, String info, boolean isError) {
final Context ctx = view.getContext();
final Spanned text = Html.fromHtml(ctx.getString(R.string.status,
Integer.toHexString(ContextCompat.getColor(ctx, R.color.monerujoGreen) & 0xFFFFFF),
Integer.toHexString(ContextCompat.getColor(ctx, R.color.monerujoBackground) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(ctx, R.attr.positiveColor) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(ctx, android.R.attr.colorBackground) & 0xFFFFFF),
(hostAddress.isOnion() ? "&nbsp;.onion&nbsp;&nbsp;" : ""), " " + info));
view.setText(text);
if (isError)
view.setTextColor(ThemeHelper.getThemedColor(ctx, R.attr.colorError));
else
view.setTextColor(ThemeHelper.getThemedColor(ctx, R.attr.colorPrimary));
view.setTextColor(ThemeHelper.getThemedColor(ctx, android.R.attr.textColorSecondary));
}
public void showInfo(TextView view) {

View File

@@ -40,6 +40,7 @@ import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.ServiceHelper;
import com.m2049r.xmrwallet.util.ThemeHelper;
import java.text.NumberFormat;
import java.util.Locale;
@@ -212,19 +213,27 @@ public class SendBtcSuccessWizardFragment extends SendWizardFragment {
if (status.isError()) {
tvXmrToStatus.setText(getString(R.string.info_send_xmrto_error, status.toString()));
statusResource = R.drawable.ic_error_red_24dp;
pbXmrto.getIndeterminateDrawable().setColorFilter(0xff8b0000, android.graphics.PorterDuff.Mode.MULTIPLY);
pbXmrto.getIndeterminateDrawable().setColorFilter(
ThemeHelper.getThemedColor(getContext(), android.R.attr.colorError),
android.graphics.PorterDuff.Mode.MULTIPLY);
} else if (status.isSent() || status.isPaid()) {
tvXmrToStatus.setText(getString(R.string.info_send_xmrto_sent, btcData.getBtcSymbol()));
statusResource = R.drawable.ic_success_green_24dp;
pbXmrto.getIndeterminateDrawable().setColorFilter(0xFF417505, android.graphics.PorterDuff.Mode.MULTIPLY);
statusResource = R.drawable.ic_success;
pbXmrto.getIndeterminateDrawable().setColorFilter(
ThemeHelper.getThemedColor(getContext(), R.attr.positiveColor),
android.graphics.PorterDuff.Mode.MULTIPLY);
} else if (status.isWaiting()) {
tvXmrToStatus.setText(getString(R.string.info_send_xmrto_unpaid));
statusResource = R.drawable.ic_pending_orange_24dp;
pbXmrto.getIndeterminateDrawable().setColorFilter(0xFFFF6105, android.graphics.PorterDuff.Mode.MULTIPLY);
statusResource = R.drawable.ic_pending;
pbXmrto.getIndeterminateDrawable().setColorFilter(
ThemeHelper.getThemedColor(getContext(), R.attr.neutralColor),
android.graphics.PorterDuff.Mode.MULTIPLY);
} else if (status.isPending()) {
tvXmrToStatus.setText(getString(R.string.info_send_xmrto_paid));
statusResource = R.drawable.ic_pending_orange_24dp;
pbXmrto.getIndeterminateDrawable().setColorFilter(0xFFFF6105, android.graphics.PorterDuff.Mode.MULTIPLY);
statusResource = R.drawable.ic_pending;
pbXmrto.getIndeterminateDrawable().setColorFilter(
ThemeHelper.getThemedColor(getContext(), R.attr.neutralColor),
android.graphics.PorterDuff.Mode.MULTIPLY);
} else {
throw new IllegalStateException("status is broken: " + status.toString());
}

View File

@@ -55,7 +55,6 @@ import com.m2049r.xmrwallet.widget.DotBar;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.lang.ref.WeakReference;
import java.util.Objects;
import timber.log.Timber;
@@ -202,14 +201,14 @@ public class SendFragment extends Fragment
CharSequence nextLabel = pagerAdapter.getPageTitle(position + 1);
bNext.setText(nextLabel);
if (nextLabel != null) {
bNext.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_navigate_next_white_24dp, 0);
bNext.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_navigate_next, 0);
} else {
bNext.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
CharSequence prevLabel = pagerAdapter.getPageTitle(position - 1);
bPrev.setText(prevLabel);
if (prevLabel != null) {
bPrev.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_navigate_prev_white_24dp, 0, 0, 0);
bPrev.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_navigate_prev, 0, 0, 0);
} else {
bPrev.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}

View File

@@ -23,7 +23,6 @@ import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
@@ -230,21 +229,21 @@ public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHo
static public int getPingIcon(NodeInfo nodeInfo) {
if (nodeInfo.isUnauthorized()) {
return R.drawable.ic_wifi_lock_black_24dp;
return R.drawable.ic_wifi_lock;
}
if (nodeInfo.isValid()) {
final double ping = nodeInfo.getResponseTime();
if (ping < NodeInfo.PING_GOOD) {
return R.drawable.ic_signal_wifi_4_bar_24dp;
return R.drawable.ic_wifi_4_bar;
} else if (ping < NodeInfo.PING_MEDIUM) {
return R.drawable.ic_signal_wifi_3_bar_24dp;
return R.drawable.ic_wifi_3_bar;
} else if (ping < NodeInfo.PING_BAD) {
return R.drawable.ic_signal_wifi_2_bar_24dp;
return R.drawable.ic_wifi_2_bar;
} else {
return R.drawable.ic_signal_wifi_1_bar_24dp;
return R.drawable.ic_wifi_1_bar;
}
} else {
return R.drawable.ic_signal_wifi_off_24dp;
return R.drawable.ic_wifi_off;
}
}

View File

@@ -36,6 +36,7 @@ import com.m2049r.xmrwallet.data.Crypto;
import com.m2049r.xmrwallet.data.UserNotes;
import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.ThemeHelper;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -67,10 +68,10 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
public TransactionInfoAdapter(Context context, OnInteractionListener listener) {
this.context = context;
inboundColour = ContextCompat.getColor(context, R.color.tx_plus);
outboundColour = ContextCompat.getColor(context, R.color.tx_minus);
pendingColour = ContextCompat.getColor(context, R.color.tx_pending);
failedColour = ContextCompat.getColor(context, R.color.tx_failed);
inboundColour = ThemeHelper.getThemedColor(context, R.attr.positiveColor);
outboundColour = ThemeHelper.getThemedColor(context, R.attr.negativeColor);
pendingColour = ThemeHelper.getThemedColor(context, R.attr.neutralColor);
failedColour = ThemeHelper.getThemedColor(context, R.attr.neutralColor);
infoItems = new ArrayList<>();
this.listener = listener;
Calendar cal = Calendar.getInstance();
@@ -253,8 +254,8 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
tvPaymentId.setText(info);
} else {
Spanned label = Html.fromHtml(context.getString(R.string.tx_details_notes,
Integer.toHexString(ContextCompat.getColor(context, R.color.monerujoGreen) & 0xFFFFFF),
Integer.toHexString(ContextCompat.getColor(context, R.color.monerujoBackground) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(context, R.attr.positiveColor) & 0xFFFFFF),
Integer.toHexString(ThemeHelper.getThemedColor(context, android.R.attr.colorBackground) & 0xFFFFFF),
tag, info.isEmpty() ? "" : ("&nbsp; " + info)));
tvPaymentId.setText(label);
}

View File

@@ -129,7 +129,7 @@ public class Wallet {
ConnectionStatus_WrongVersion
}
public native String getSeed();
public native String getSeed(String offset);
public native String getSeedLanguage();
@@ -147,7 +147,7 @@ public class Wallet {
private native Status statusWithErrorString();
public native boolean setPassword(String password);
public native synchronized boolean setPassword(String password);
public String getAddress() {
return getAddress(accountIndex);
@@ -203,12 +203,10 @@ public class Wallet {
public native String getSecretSpendKey();
public boolean store() {
final boolean ok = store("");
Timber.d("stored");
return ok;
return store("");
}
public native boolean store(String path);
public native synchronized boolean store(String path);
public boolean close() {
disposePendingTransaction();

View File

@@ -124,19 +124,19 @@ public class WalletManager {
private native long openWalletJ(String path, String password, int networkType);
public Wallet recoveryWallet(File aFile, String password, String mnemonic) {
return recoveryWallet(aFile, password, mnemonic, 0);
}
public Wallet recoveryWallet(File aFile, String password, String mnemonic, long restoreHeight) {
long walletHandle = recoveryWalletJ(aFile.getAbsolutePath(), password, mnemonic,
public Wallet recoveryWallet(File aFile, String password,
String mnemonic, String offset,
long restoreHeight) {
long walletHandle = recoveryWalletJ(aFile.getAbsolutePath(), password,
mnemonic, offset,
getNetworkType().getValue(), restoreHeight);
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet);
return wallet;
}
private native long recoveryWalletJ(String path, String password, String mnemonic,
private native long recoveryWalletJ(String path, String password,
String mnemonic, String offset,
int networkType, long restoreHeight);
public Wallet createWalletWithKeys(File aFile, String password, String language, long restoreHeight,

View File

@@ -568,7 +568,8 @@ public class WalletService extends Service {
private void startNotfication() {
Intent notificationIntent = new Intent(this, WalletActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent,
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0);
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? createNotificationChannel() : "";
Notification notification = new NotificationCompat.Builder(this, channelId)

View File

@@ -395,7 +395,7 @@ public class Helper {
final TextView tvOpenPrompt = promptsView.findViewById(R.id.tvOpenPrompt);
final Drawable icFingerprint = context.getDrawable(R.drawable.ic_fingerprint);
final Drawable icError = context.getDrawable(R.drawable.ic_error_red_36dp);
final Drawable icInfo = context.getDrawable(R.drawable.ic_info_green_36dp);
final Drawable icInfo = context.getDrawable(R.drawable.ic_info_white_24dp);
final boolean fingerprintAuthCheck = FingerprintHelper.isFingerPassValid(context, wallet);

View File

@@ -27,7 +27,6 @@ import java.util.ArrayList;
import java.util.Locale;
public class LocaleHelper {
private static final String PREFERRED_LOCALE_KEY = "preferred_locale";
private static Locale SYSTEM_DEFAULT_LOCALE = Locale.getDefault();
public static ArrayList<Locale> getAvailableLocales(Context context) {
@@ -93,12 +92,13 @@ public class LocaleHelper {
public static String getPreferredLanguageTag(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getString(PREFERRED_LOCALE_KEY, "");
.getString("preferred_locale", "");
// cannot access getString here as it's done BEFORE string locale is set
}
@SuppressLint("ApplySharedPref")
private static void savePreferredLangaugeTag(Context context, String locale) {
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putString(PREFERRED_LOCALE_KEY, locale).commit();
.putString(context.getString(R.string.preferred_locale), locale).commit();
}
}

View File

@@ -323,6 +323,7 @@ public class NetCipherHelper implements StatusCallback {
}
private OkHttpClient getClient() {
if (mockClient != null) return mockClient; // Unit-test mode
final OkHttpClient client = getInstance().client;
if ((username != null) && (!username.isEmpty())) {
final DigestAuthenticator authenticator = new DigestAuthenticator(new Credentials(username, password));
@@ -349,6 +350,9 @@ public class NetCipherHelper implements StatusCallback {
}
return builder.build();
}
// for unit tests only
static public OkHttpClient mockClient = null;
}
private static final String PREFS_NAME = "tor";

View File

@@ -16,32 +16,37 @@
package com.m2049r.xmrwallet.util;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import androidx.appcompat.app.AppCompatDelegate;
public class NightmodeHelper {
private static final String PREFERRED_NIGHTMODE_KEY = "preferred_nightmode";
import com.m2049r.xmrwallet.R;
public class NightmodeHelper {
public static DayNightMode getPreferredNightmode(Context context) {
return DayNightMode.valueOf(PreferenceManager.getDefaultSharedPreferences(context)
.getString(PREFERRED_NIGHTMODE_KEY, "UNKNOWN"));
.getString(context.getString(R.string.preferred_nightmode), "UNKNOWN"));
}
public static void setPreferredNightmode(Context context) {
final DayNightMode mode = DayNightMode.valueOf(PreferenceManager.getDefaultSharedPreferences(context)
.getString(PREFERRED_NIGHTMODE_KEY, "UNKNOWN"));
if (mode == DayNightMode.UNKNOWN) setAndSavePreferredNightmode(context, DayNightMode.AUTO);
setNightMode(mode);
.getString(context.getString(R.string.preferred_nightmode), "UNKNOWN"));
if (mode == DayNightMode.UNKNOWN)
setAndSavePreferredNightmode(context, DayNightMode.AUTO);
else
setNightMode(mode);
}
public static void setAndSavePreferredNightmode(Context context, DayNightMode mode) {
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putString(PREFERRED_NIGHTMODE_KEY, mode.name()).apply();
.putString(context.getString(R.string.preferred_nightmode), mode.name()).apply();
setNightMode(mode);
}
@SuppressLint("WrongConstant")
public static void setNightMode(DayNightMode mode) {
AppCompatDelegate.setDefaultNightMode(mode.getNightMode());
}

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