mirror of
https://github.com/m2049r/xmrwallet
synced 2024-11-22 13:04:00 +01:00
onion stuff (#796)
This commit is contained in:
parent
cdc2b23257
commit
05720e63ab
@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "com.m2049r.xmrwallet"
|
applicationId "com.m2049r.xmrwallet"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 1102
|
versionCode 1201
|
||||||
versionName "2.1.2 'Vertant'"
|
versionName "2.2.1 'René'"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
@ -113,27 +113,30 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getId(name) {
|
static def getId(name) {
|
||||||
def Properties props = new Properties()
|
Properties props = new Properties()
|
||||||
props.load(new FileInputStream(new File('monerujo.id')))
|
props.load(new FileInputStream(new File('monerujo.id')))
|
||||||
return props[name]
|
return props[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'androidx.core:core:1.3.2'
|
implementation 'androidx.core:core:1.6.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||||
implementation 'com.google.android.material:material:1.3.0'
|
implementation 'com.google.android.material:material:1.4.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.2.0'
|
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01'
|
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
|
||||||
|
|
||||||
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
|
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||||
implementation "com.squareup.okhttp3:okhttp:4.9.0"
|
implementation "com.squareup.okhttp3:okhttp:4.9.0"
|
||||||
implementation "io.github.rburgst:okhttp-digest:2.5"
|
implementation "io.github.rburgst:okhttp-digest:2.5"
|
||||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
implementation "com.jakewharton.timber:timber:4.7.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.3.0'
|
||||||
|
|
||||||
implementation 'dnsjava:dnsjava:2.1.9'
|
implementation 'dnsjava:dnsjava:2.1.9'
|
||||||
@ -141,6 +144,7 @@ dependencies {
|
|||||||
implementation 'org.slf4j:slf4j-nop:1.7.30'
|
implementation 'org.slf4j:slf4j-nop:1.7.30'
|
||||||
implementation 'com.github.brnunes:swipeablerecyclerview:1.0.2'
|
implementation 'com.github.brnunes:swipeablerecyclerview:1.0.2'
|
||||||
|
|
||||||
|
//noinspection GradleDependency
|
||||||
testImplementation "junit:junit:$rootProject.ext.junitVersion"
|
testImplementation "junit:junit:$rootProject.ext.junitVersion"
|
||||||
testImplementation "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
|
testImplementation "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
|
||||||
testImplementation "com.squareup.okhttp3:mockwebserver:4.9.0"
|
testImplementation "com.squareup.okhttp3:mockwebserver:4.9.0"
|
||||||
@ -150,3 +154,4 @@ dependencies {
|
|||||||
compileOnly 'org.projectlombok:lombok:1.18.16'
|
compileOnly 'org.projectlombok:lombok:1.18.16'
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.16'
|
annotationProcessor 'org.projectlombok:lombok:1.18.16'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,24 @@
|
|||||||
<uses-permission android:name="android.permission.NFC" />
|
<uses-permission android:name="android.permission.NFC" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
|
<queries>
|
||||||
|
<intent>
|
||||||
|
<action android:name="org.torproject.android.intent.action.START" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="org.torproject.android.intent.action.STATUS" />
|
||||||
|
</intent>
|
||||||
|
|
||||||
|
<intent>
|
||||||
|
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="org.torproject.android.REQUEST_V3_ONION_SERVICE" />
|
||||||
|
</intent>
|
||||||
|
|
||||||
|
<package android:name="org.torproject.android" />
|
||||||
|
</queries>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".XmrWalletApplication"
|
android:name=".XmrWalletApplication"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
|
@ -531,6 +531,17 @@ Java_com_m2049r_xmrwallet_model_WalletManager_resolveOpenAlias(JNIEnv *env, jobj
|
|||||||
return env->NewStringUTF(resolvedAlias.c_str());
|
return env->NewStringUTF(resolvedAlias.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_m2049r_xmrwallet_model_WalletManager_setProxy(JNIEnv *env, jobject instance,
|
||||||
|
jstring address) {
|
||||||
|
const char *_address = env->GetStringUTFChars(address, nullptr);
|
||||||
|
bool rc =
|
||||||
|
Bitmonero::WalletManagerFactory::getWalletManager()->setProxy(std::string(_address));
|
||||||
|
env->ReleaseStringUTFChars(address, _address);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
|
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
@ -727,6 +738,16 @@ Java_com_m2049r_xmrwallet_model_Wallet_getConnectionStatusJ(JNIEnv *env, jobject
|
|||||||
//TODO virtual void setTrustedDaemon(bool arg) = 0;
|
//TODO virtual void setTrustedDaemon(bool arg) = 0;
|
||||||
//TODO virtual bool trustedDaemon() const = 0;
|
//TODO virtual bool trustedDaemon() const = 0;
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_m2049r_xmrwallet_model_Wallet_setProxy(JNIEnv *env, jobject instance,
|
||||||
|
jstring address) {
|
||||||
|
const char *_address = env->GetStringUTFChars(address, nullptr);
|
||||||
|
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
|
||||||
|
bool rc = wallet->setProxy(std::string(_address));
|
||||||
|
env->ReleaseStringUTFChars(address, _address);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL
|
JNIEXPORT jlong JNICALL
|
||||||
Java_com_m2049r_xmrwallet_model_Wallet_getBalance(JNIEnv *env, jobject instance,
|
Java_com_m2049r_xmrwallet_model_Wallet_getBalance(JNIEnv *env, jobject instance,
|
||||||
jint accountIndex) {
|
jint accountIndex) {
|
||||||
|
@ -77,7 +77,7 @@ public class Dispatcher implements PeerRetriever.OnGetPeers {
|
|||||||
final NodeInfo nodeInfo = retrievedPeer.getNodeInfo();
|
final NodeInfo nodeInfo = retrievedPeer.getNodeInfo();
|
||||||
Timber.d("Retrieved %s", nodeInfo);
|
Timber.d("Retrieved %s", nodeInfo);
|
||||||
if ((nodeInfo.isValid() || nodeInfo.isFavourite())) {
|
if ((nodeInfo.isValid() || nodeInfo.isFavourite())) {
|
||||||
nodeInfo.setName();
|
nodeInfo.setDefaultName();
|
||||||
rpcNodes.add(nodeInfo);
|
rpcNodes.add(nodeInfo);
|
||||||
Timber.d("RPC: %s", nodeInfo);
|
Timber.d("RPC: %s", nodeInfo);
|
||||||
// the following is not totally correct but it works (otherwise we need to
|
// the following is not totally correct but it works (otherwise we need to
|
||||||
|
@ -65,6 +65,7 @@ import com.m2049r.xmrwallet.util.KeyStoreHelper;
|
|||||||
import com.m2049r.xmrwallet.util.LegacyStorageHelper;
|
import com.m2049r.xmrwallet.util.LegacyStorageHelper;
|
||||||
import com.m2049r.xmrwallet.util.LocaleHelper;
|
import com.m2049r.xmrwallet.util.LocaleHelper;
|
||||||
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
import com.m2049r.xmrwallet.util.NightmodeHelper;
|
import com.m2049r.xmrwallet.util.NightmodeHelper;
|
||||||
import com.m2049r.xmrwallet.util.ThemeHelper;
|
import com.m2049r.xmrwallet.util.ThemeHelper;
|
||||||
import com.m2049r.xmrwallet.util.ZipBackup;
|
import com.m2049r.xmrwallet.util.ZipBackup;
|
||||||
@ -701,6 +702,7 @@ public class LoginActivity extends BaseActivity
|
|||||||
new AsyncWaitForService().execute();
|
new AsyncWaitForService().execute();
|
||||||
}
|
}
|
||||||
if (!Ledger.isConnected()) attachLedger();
|
if (!Ledger.isConnected()) attachLedger();
|
||||||
|
registerTor();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AsyncWaitForService extends AsyncTask<Void, Void, Void> {
|
private class AsyncWaitForService extends AsyncTask<Void, Void, Void> {
|
||||||
@ -1469,4 +1471,69 @@ public class LoginActivity extends BaseActivity
|
|||||||
}
|
}
|
||||||
return usbManager;
|
return usbManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Tor (Orbot) stuff
|
||||||
|
//
|
||||||
|
|
||||||
|
void torNotify() {
|
||||||
|
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||||
|
if (fragment == null) return;
|
||||||
|
|
||||||
|
if (fragment instanceof LoginFragment) {
|
||||||
|
runOnUiThread(((LoginFragment) fragment)::showNetwork);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deregisterTor() {
|
||||||
|
NetCipherHelper.deregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerTor() {
|
||||||
|
NetCipherHelper.register(new NetCipherHelper.OnStatusChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void connected() {
|
||||||
|
Timber.d("CONNECTED");
|
||||||
|
WalletManager.getInstance().setProxy(NetCipherHelper.getProxy());
|
||||||
|
torNotify();
|
||||||
|
if (waitingUiTask != null) {
|
||||||
|
Timber.d("RUN");
|
||||||
|
runOnUiThread(waitingUiTask);
|
||||||
|
waitingUiTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnected() {
|
||||||
|
Timber.d("DISCONNECTED");
|
||||||
|
WalletManager.getInstance().setProxy("");
|
||||||
|
torNotify();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notInstalled() {
|
||||||
|
Timber.d("NOT INSTALLED");
|
||||||
|
WalletManager.getInstance().setProxy("");
|
||||||
|
torNotify();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notEnabled() {
|
||||||
|
Timber.d("NOT ENABLED");
|
||||||
|
notInstalled();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Runnable waitingUiTask;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runOnNetCipher(Runnable uiTask) {
|
||||||
|
if (waitingUiTask != null) throw new IllegalStateException("only one tor task at a time");
|
||||||
|
if (NetCipherHelper.hasClient()) {
|
||||||
|
runOnUiThread(uiTask);
|
||||||
|
} else {
|
||||||
|
waitingUiTask = uiTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ package com.m2049r.xmrwallet;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.Spanned;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@ -28,22 +30,27 @@ import android.view.ViewGroup;
|
|||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
|
import com.google.android.material.progressindicator.CircularProgressIndicator;
|
||||||
import com.m2049r.xmrwallet.data.NodeInfo;
|
import com.m2049r.xmrwallet.data.NodeInfo;
|
||||||
import com.m2049r.xmrwallet.layout.NodeInfoAdapter;
|
import com.m2049r.xmrwallet.dialog.HelpFragment;
|
||||||
import com.m2049r.xmrwallet.layout.WalletInfoAdapter;
|
import com.m2049r.xmrwallet.layout.WalletInfoAdapter;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.KeyStoreHelper;
|
import com.m2049r.xmrwallet.util.KeyStoreHelper;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
import com.m2049r.xmrwallet.util.NodePinger;
|
import com.m2049r.xmrwallet.util.NodePinger;
|
||||||
import com.m2049r.xmrwallet.util.Notice;
|
import com.m2049r.xmrwallet.util.Notice;
|
||||||
import com.m2049r.xmrwallet.widget.Toolbar;
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
@ -66,9 +73,9 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
private View tvGuntherSays;
|
private View tvGuntherSays;
|
||||||
private ImageView ivGunther;
|
private ImageView ivGunther;
|
||||||
private TextView tvNodeName;
|
private TextView tvNodeName;
|
||||||
private TextView tvNodeAddress;
|
private TextView tvNodeInfo;
|
||||||
private View pbNode;
|
private ImageButton ibNetwork;
|
||||||
private View llNode;
|
private CircularProgressIndicator pbNetwork;
|
||||||
|
|
||||||
private Listener activityCallback;
|
private Listener activityCallback;
|
||||||
|
|
||||||
@ -109,6 +116,8 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
Set<NodeInfo> getOrPopulateFavourites();
|
Set<NodeInfo> getOrPopulateFavourites();
|
||||||
|
|
||||||
boolean hasLedger();
|
boolean hasLedger();
|
||||||
|
|
||||||
|
void runOnNetCipher(Runnable runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -125,6 +134,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
Timber.d("onPause()");
|
Timber.d("onPause()");
|
||||||
|
torStatus = null;
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +145,8 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
activityCallback.setTitle(null);
|
activityCallback.setTitle(null);
|
||||||
activityCallback.setToolbarButton(Toolbar.BUTTON_CREDITS);
|
activityCallback.setToolbarButton(Toolbar.BUTTON_CREDITS);
|
||||||
activityCallback.showNet();
|
activityCallback.showNet();
|
||||||
pingSelectedNode();
|
showNetwork();
|
||||||
|
//activityCallback.runOnNetCipher(this::pingSelectedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -183,12 +194,14 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
ViewGroup llNotice = view.findViewById(R.id.llNotice);
|
ViewGroup llNotice = view.findViewById(R.id.llNotice);
|
||||||
Notice.showAll(llNotice, ".*_login");
|
Notice.showAll(llNotice, ".*_login");
|
||||||
|
|
||||||
pbNode = view.findViewById(R.id.pbNode);
|
view.findViewById(R.id.llNode).setOnClickListener(v -> startNodePrefs());
|
||||||
llNode = view.findViewById(R.id.llNode);
|
|
||||||
llNode.setOnClickListener(v -> startNodePrefs());
|
|
||||||
tvNodeName = view.findViewById(R.id.tvNodeName);
|
tvNodeName = view.findViewById(R.id.tvNodeName);
|
||||||
tvNodeAddress = view.findViewById(R.id.tvNodeAddress);
|
tvNodeInfo = view.findViewById(R.id.tvInfo);
|
||||||
view.findViewById(R.id.ibRenew).setOnClickListener(v -> findBestNode());
|
view.findViewById(R.id.ibRenew).setOnClickListener(v -> findBestNode());
|
||||||
|
ibNetwork = view.findViewById(R.id.ibNetwork);
|
||||||
|
ibNetwork.setOnClickListener(v -> changeNetwork());
|
||||||
|
ibNetwork.setEnabled(false);
|
||||||
|
pbNetwork = view.findViewById(R.id.pbNetwork);
|
||||||
|
|
||||||
Helper.hideKeyboard(getActivity());
|
Helper.hideKeyboard(getActivity());
|
||||||
|
|
||||||
@ -387,15 +400,29 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
return nodeList.get(0);
|
return nodeList.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
status, ""));
|
||||||
|
tvNodeInfo.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
private class AsyncFindBestNode extends AsyncTask<Integer, Void, NodeInfo> {
|
private class AsyncFindBestNode extends AsyncTask<Integer, Void, NodeInfo> {
|
||||||
final static int PING_SELECTED = 0;
|
final static int PING_SELECTED = 0;
|
||||||
final static int FIND_BEST = 1;
|
final static int FIND_BEST = 1;
|
||||||
|
|
||||||
|
private boolean netState;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
super.onPreExecute();
|
super.onPreExecute();
|
||||||
pbNode.setVisibility(View.VISIBLE);
|
tvNodeName.setVisibility(View.GONE);
|
||||||
llNode.setVisibility(View.INVISIBLE);
|
pbNetwork.setVisibility(View.VISIBLE);
|
||||||
|
netState = ibNetwork.isClickable();
|
||||||
|
ibNetwork.setClickable(false);
|
||||||
|
setSubtext(getString(R.string.node_waiting));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -417,8 +444,9 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
}
|
}
|
||||||
if (selectedNode == null) { // autoselect
|
if (selectedNode == null) { // autoselect
|
||||||
selectedNode = autoselect(favourites);
|
selectedNode = autoselect(favourites);
|
||||||
} else
|
} else {
|
||||||
selectedNode.testRpcService();
|
selectedNode.testRpcService();
|
||||||
|
}
|
||||||
} else throw new IllegalStateException();
|
} else throw new IllegalStateException();
|
||||||
if ((selectedNode != null) && selectedNode.isValid()) {
|
if ((selectedNode != null) && selectedNode.isValid()) {
|
||||||
activityCallback.setNode(selectedNode);
|
activityCallback.setNode(selectedNode);
|
||||||
@ -432,16 +460,17 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(NodeInfo result) {
|
protected void onPostExecute(NodeInfo result) {
|
||||||
if (!isAdded()) return;
|
if (!isAdded()) return;
|
||||||
pbNode.setVisibility(View.INVISIBLE);
|
tvNodeName.setVisibility(View.VISIBLE);
|
||||||
llNode.setVisibility(View.VISIBLE);
|
pbNetwork.setVisibility(View.INVISIBLE);
|
||||||
|
ibNetwork.setClickable(netState);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
Timber.d("found a good node %s", result.toString());
|
Timber.d("found a good node %s", result.toString());
|
||||||
showNode(result);
|
showNode(result);
|
||||||
} else {
|
} else {
|
||||||
tvNodeName.setText(getResources().getText(R.string.node_create_hint));
|
tvNodeName.setText(getResources().getText(R.string.node_create_hint));
|
||||||
tvNodeName.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
tvNodeName.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||||
tvNodeAddress.setText(null);
|
tvNodeInfo.setText(null);
|
||||||
tvNodeAddress.setVisibility(View.GONE);
|
tvNodeInfo.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,12 +482,70 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
|
|
||||||
private void showNode(NodeInfo nodeInfo) {
|
private void showNode(NodeInfo nodeInfo) {
|
||||||
tvNodeName.setText(nodeInfo.getName());
|
tvNodeName.setText(nodeInfo.getName());
|
||||||
tvNodeName.setCompoundDrawablesWithIntrinsicBounds(NodeInfoAdapter.getPingIcon(nodeInfo), 0, 0, 0);
|
nodeInfo.showInfo(tvNodeInfo);
|
||||||
Helper.showTimeDifference(tvNodeAddress, nodeInfo.getTimestamp());
|
tvNodeInfo.setVisibility(View.VISIBLE);
|
||||||
tvNodeAddress.setVisibility(View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startNodePrefs() {
|
private void startNodePrefs() {
|
||||||
activityCallback.onNodePrefs();
|
activityCallback.onNodePrefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Network (Tor) stuff
|
||||||
|
|
||||||
|
private void changeNetwork() {
|
||||||
|
Timber.d("S: %s", NetCipherHelper.getStatus());
|
||||||
|
final NetCipherHelper.Status status = NetCipherHelper.getStatus();
|
||||||
|
if (status == NetCipherHelper.Status.NOT_INSTALLED) {
|
||||||
|
HelpFragment.display(requireActivity().getSupportFragmentManager(), R.string.help_tor);
|
||||||
|
} else if (status == NetCipherHelper.Status.NOT_ENABLED) {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.tor_enable_background), Toast.LENGTH_LONG).show();
|
||||||
|
} else {
|
||||||
|
pbNetwork.setVisibility(View.VISIBLE);
|
||||||
|
ibNetwork.setEnabled(false);
|
||||||
|
NetCipherHelper.getInstance().toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NetCipherHelper.Status torStatus = null;
|
||||||
|
|
||||||
|
void showNetwork() {
|
||||||
|
final NetCipherHelper.Status status = NetCipherHelper.getStatus();
|
||||||
|
Timber.d("SHOW %s", status);
|
||||||
|
if (status == torStatus) return;
|
||||||
|
torStatus = status;
|
||||||
|
switch (status) {
|
||||||
|
case ENABLED:
|
||||||
|
ibNetwork.setImageResource(R.drawable.ic_network_tor_on);
|
||||||
|
ibNetwork.setEnabled(true);
|
||||||
|
ibNetwork.setClickable(true);
|
||||||
|
pbNetwork.setVisibility(View.INVISIBLE);
|
||||||
|
break;
|
||||||
|
case NOT_ENABLED:
|
||||||
|
case DISABLED:
|
||||||
|
ibNetwork.setImageResource(R.drawable.ic_network_clearnet);
|
||||||
|
ibNetwork.setEnabled(true);
|
||||||
|
ibNetwork.setClickable(true);
|
||||||
|
pbNetwork.setVisibility(View.INVISIBLE);
|
||||||
|
break;
|
||||||
|
case STARTING:
|
||||||
|
ibNetwork.setImageResource(R.drawable.ic_network_clearnet);
|
||||||
|
ibNetwork.setEnabled(false);
|
||||||
|
pbNetwork.setVisibility(View.VISIBLE);
|
||||||
|
break;
|
||||||
|
case STOPPING:
|
||||||
|
ibNetwork.setImageResource(R.drawable.ic_network_clearnet);
|
||||||
|
ibNetwork.setEnabled(false);
|
||||||
|
pbNetwork.setVisibility(View.VISIBLE);
|
||||||
|
break;
|
||||||
|
case NOT_INSTALLED:
|
||||||
|
ibNetwork.setEnabled(true);
|
||||||
|
ibNetwork.setClickable(true);
|
||||||
|
pbNetwork.setVisibility(View.INVISIBLE);
|
||||||
|
ibNetwork.setImageResource(R.drawable.ic_network_clearnet);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activityCallback.runOnNetCipher(this::pingSelectedNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import android.content.Context;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@ -59,7 +58,6 @@ import java.text.NumberFormat;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
@ -219,8 +217,8 @@ public class NodeFragment extends Fragment
|
|||||||
activityCallback.setNode(nodeItem); // this marks it as selected & saves it as well
|
activityCallback.setNode(nodeItem); // this marks it as selected & saves it as well
|
||||||
nodeItem.setSelecting(false);
|
nodeItem.setSelecting(false);
|
||||||
try {
|
try {
|
||||||
Objects.requireNonNull(getActivity()).runOnUiThread(() -> nodesAdapter.allowClick(true));
|
requireActivity().runOnUiThread(() -> nodesAdapter.allowClick(true));
|
||||||
} catch (NullPointerException ex) {
|
} catch (IllegalStateException ex) {
|
||||||
// it's ok
|
// it's ok
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -403,17 +401,13 @@ public class NodeFragment extends Fragment
|
|||||||
etNodeHost.setError(getString(R.string.node_host_empty));
|
etNodeHost.setError(getString(R.string.node_host_empty));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final boolean setHostSuccess = Helper.runWithNetwork(new Helper.Action() {
|
final boolean setHostSuccess = Helper.runWithNetwork(() -> {
|
||||||
@Override
|
|
||||||
public boolean run() {
|
|
||||||
try {
|
try {
|
||||||
nodeInfo.setHost(host);
|
nodeInfo.setHost(host);
|
||||||
return true;
|
return true;
|
||||||
} catch (UnknownHostException ex) {
|
} catch (UnknownHostException ex) {
|
||||||
etNodeHost.setError(getString(R.string.node_host_unresolved));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
if (!setHostSuccess) {
|
if (!setHostSuccess) {
|
||||||
etNodeHost.setError(getString(R.string.node_host_unresolved));
|
etNodeHost.setError(getString(R.string.node_host_unresolved));
|
||||||
@ -421,14 +415,7 @@ public class NodeFragment extends Fragment
|
|||||||
}
|
}
|
||||||
etNodeHost.setError(null);
|
etNodeHost.setError(null);
|
||||||
nodeInfo.setRpcPort(port);
|
nodeInfo.setRpcPort(port);
|
||||||
// setName() may trigger reverse DNS
|
|
||||||
Helper.runWithNetwork(new Helper.Action() {
|
|
||||||
@Override
|
|
||||||
public boolean run() {
|
|
||||||
nodeInfo.setName(etNodeName.getEditText().getText().toString().trim());
|
nodeInfo.setName(etNodeName.getEditText().getText().toString().trim());
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
nodeInfo.setUsername(etNodeUser.getEditText().getText().toString().trim());
|
nodeInfo.setUsername(etNodeUser.getEditText().getText().toString().trim());
|
||||||
nodeInfo.setPassword(etNodePass.getEditText().getText().toString()); // no trim for pw
|
nodeInfo.setPassword(etNodePass.getEditText().getText().toString()); // no trim for pw
|
||||||
return true;
|
return true;
|
||||||
@ -532,20 +519,10 @@ public class NodeFragment extends Fragment
|
|||||||
@Override
|
@Override
|
||||||
public void onShow(final DialogInterface dialog) {
|
public void onShow(final DialogInterface dialog) {
|
||||||
Button testButton = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_NEUTRAL);
|
Button testButton = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_NEUTRAL);
|
||||||
testButton.setOnClickListener(new View.OnClickListener() {
|
testButton.setOnClickListener(view -> test());
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
test();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
|
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
|
||||||
button.setOnClickListener(new View.OnClickListener() {
|
button.setOnClickListener(view -> apply());
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
apply();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -553,15 +530,13 @@ public class NodeFragment extends Fragment
|
|||||||
editDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
|
editDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
etNodePass.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
etNodePass.getEditText().setOnEditorActionListener((v, actionId, event) -> {
|
||||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
|
||||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||||
editDialog.getButton(DialogInterface.BUTTON_NEUTRAL).requestFocus();
|
editDialog.getButton(DialogInterface.BUTTON_NEUTRAL).requestFocus();
|
||||||
test();
|
test();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,6 +564,7 @@ public class NodeFragment extends Fragment
|
|||||||
} else {
|
} else {
|
||||||
nodesAdapter.setNodes();
|
nodesAdapter.setNodes();
|
||||||
}
|
}
|
||||||
|
nodesAdapter.notifyItemChanged(nodeInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,11 +223,13 @@ public class WalletFragment extends Fragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showUnconfirmed(double unconfirmedAmount) {
|
void showUnconfirmed(double unconfirmedAmount) {
|
||||||
if (!activityCallback.isStreetMode()) {
|
if (activityCallback.isStreetMode() || unconfirmedAmount == 0) {
|
||||||
|
tvUnconfirmedAmount.setText(null);
|
||||||
|
tvUnconfirmedAmount.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
String unconfirmed = Helper.getFormattedAmount(unconfirmedAmount, true);
|
String unconfirmed = Helper.getFormattedAmount(unconfirmedAmount, true);
|
||||||
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, unconfirmed));
|
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, unconfirmed));
|
||||||
} else {
|
tvUnconfirmedAmount.setVisibility(View.VISIBLE);
|
||||||
tvUnconfirmedAmount.setText(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,14 +21,17 @@ import android.content.Context;
|
|||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.BuildConfig;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.model.NetworkType;
|
import com.m2049r.xmrwallet.model.NetworkType;
|
||||||
import com.m2049r.xmrwallet.util.LocaleHelper;
|
import com.m2049r.xmrwallet.util.LocaleHelper;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
import com.m2049r.xmrwallet.util.NightmodeHelper;
|
import com.m2049r.xmrwallet.util.NightmodeHelper;
|
||||||
|
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class XmrWalletApplication extends Application {
|
public class XmrWalletApplication extends Application {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
@ -36,7 +39,10 @@ public class XmrWalletApplication extends Application {
|
|||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Timber.plant(new Timber.DebugTree());
|
Timber.plant(new Timber.DebugTree());
|
||||||
}
|
}
|
||||||
|
|
||||||
NightmodeHelper.setPreferredNightmode(this);
|
NightmodeHelper.setPreferredNightmode(this);
|
||||||
|
|
||||||
|
NetCipherHelper.createInstance(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -45,7 +51,7 @@ public class XmrWalletApplication extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfigurationChanged(Configuration configuration) {
|
public void onConfigurationChanged(@NonNull Configuration configuration) {
|
||||||
super.onConfigurationChanged(configuration);
|
super.onConfigurationChanged(configuration);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
LocaleHelper.updateSystemDefaultLocale(configuration.getLocales().get(0));
|
LocaleHelper.updateSystemDefaultLocale(configuration.getLocales().get(0));
|
||||||
|
@ -28,7 +28,11 @@ public enum DefaultNodes {
|
|||||||
SUPPORTXMR("node.supportxmr.com:18081"),
|
SUPPORTXMR("node.supportxmr.com:18081"),
|
||||||
HASHVAULT("nodes.hashvault.pro:18081"),
|
HASHVAULT("nodes.hashvault.pro:18081"),
|
||||||
MONEROWORLD("node.moneroworld.com:18089"),
|
MONEROWORLD("node.moneroworld.com:18089"),
|
||||||
XMRTW("opennode.xmr-tw.org: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");
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final String uri;
|
private final String uri;
|
||||||
|
@ -18,6 +18,7 @@ package com.m2049r.xmrwallet.data;
|
|||||||
|
|
||||||
import com.m2049r.xmrwallet.model.NetworkType;
|
import com.m2049r.xmrwallet.model.NetworkType;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
|
import com.m2049r.xmrwallet.util.OnionHelper;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@ -35,11 +36,63 @@ public class Node {
|
|||||||
static public final String STAGENET = "stagenet";
|
static public final String STAGENET = "stagenet";
|
||||||
static public final String TESTNET = "testnet";
|
static public final String TESTNET = "testnet";
|
||||||
|
|
||||||
|
static class Address {
|
||||||
|
final private InetAddress inet;
|
||||||
|
final private String onion;
|
||||||
|
|
||||||
|
public boolean isOnion() {
|
||||||
|
return onion != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostName() {
|
||||||
|
if (inet != null) {
|
||||||
|
return inet.getHostName();
|
||||||
|
} else {
|
||||||
|
return onion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostAddress() {
|
||||||
|
if (inet != null) {
|
||||||
|
return inet.getHostAddress();
|
||||||
|
} else {
|
||||||
|
return onion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address(InetAddress address, String onion) {
|
||||||
|
this.inet = address;
|
||||||
|
this.onion = onion;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Address of(InetAddress address) {
|
||||||
|
return new Address(address, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Address of(String host) throws UnknownHostException {
|
||||||
|
if (OnionHelper.isOnionHost(host)) {
|
||||||
|
return new Address(null, host);
|
||||||
|
} else {
|
||||||
|
return new Address(InetAddress.getByName(host), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getHostAddress().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
return (other instanceof Address) && (getHostAddress().equals(((Address) other).getHostAddress()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private String name = null;
|
private String name = null;
|
||||||
@Getter
|
@Getter
|
||||||
final private NetworkType networkType;
|
final private NetworkType networkType;
|
||||||
InetAddress hostAddress;
|
Address hostAddress;
|
||||||
@Getter
|
@Getter
|
||||||
private String host;
|
private String host;
|
||||||
@Getter
|
@Getter
|
||||||
@ -74,6 +127,10 @@ public class Node {
|
|||||||
&& (networkType == anotherNode.networkType));
|
&& (networkType == anotherNode.networkType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOnion() {
|
||||||
|
return hostAddress.isOnion();
|
||||||
|
}
|
||||||
|
|
||||||
static public Node fromString(String nodeString) {
|
static public Node fromString(String nodeString) {
|
||||||
try {
|
try {
|
||||||
return new Node(nodeString);
|
return new Node(nodeString);
|
||||||
@ -205,7 +262,7 @@ public class Node {
|
|||||||
// constructor used for created nodes from retrieved peer lists
|
// constructor used for created nodes from retrieved peer lists
|
||||||
public Node(InetSocketAddress socketAddress) {
|
public Node(InetSocketAddress socketAddress) {
|
||||||
this();
|
this();
|
||||||
this.hostAddress = socketAddress.getAddress();
|
this.hostAddress = Address.of(socketAddress.getAddress());
|
||||||
this.host = socketAddress.getHostString();
|
this.host = socketAddress.getHostString();
|
||||||
this.rpcPort = 0; // unknown
|
this.rpcPort = 0; // unknown
|
||||||
this.levinPort = socketAddress.getPort();
|
this.levinPort = socketAddress.getPort();
|
||||||
@ -225,17 +282,25 @@ public class Node {
|
|||||||
if ((host == null) || (host.isEmpty()))
|
if ((host == null) || (host.isEmpty()))
|
||||||
throw new UnknownHostException("loopback not supported (yet?)");
|
throw new UnknownHostException("loopback not supported (yet?)");
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.hostAddress = InetAddress.getByName(host);
|
this.hostAddress = Address.of(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName() {
|
public void setDefaultName() {
|
||||||
if (name == null)
|
if (name != null) return;
|
||||||
this.name = hostAddress.getHostName();
|
String nodeName = hostAddress.getHostName();
|
||||||
|
if (hostAddress.isOnion()) {
|
||||||
|
nodeName = nodeName.substring(0, nodeName.length() - ".onion".length());
|
||||||
|
if (nodeName.length() > 16) {
|
||||||
|
nodeName = nodeName.substring(0, 8) + "…" + nodeName.substring(nodeName.length() - 6);
|
||||||
|
}
|
||||||
|
nodeName = nodeName + ".onion";
|
||||||
|
}
|
||||||
|
this.name = nodeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
if ((name == null) || (name.isEmpty()))
|
if ((name == null) || (name.isEmpty()))
|
||||||
this.name = hostAddress.getHostName();
|
setDefaultName();
|
||||||
else
|
else
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,19 @@
|
|||||||
|
|
||||||
package com.m2049r.xmrwallet.data;
|
package com.m2049r.xmrwallet.data;
|
||||||
|
|
||||||
import com.burgstaller.okhttp.AuthenticationCacheInterceptor;
|
import android.content.Context;
|
||||||
import com.burgstaller.okhttp.CachingAuthenticatorDecorator;
|
import android.text.Html;
|
||||||
import com.burgstaller.okhttp.digest.CachingAuthenticator;
|
import android.text.Spanned;
|
||||||
import com.burgstaller.okhttp.digest.Credentials;
|
import android.widget.TextView;
|
||||||
import com.burgstaller.okhttp.digest.DigestAuthenticator;
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import com.m2049r.levin.scanner.LevinPeer;
|
import com.m2049r.levin.scanner.LevinPeer;
|
||||||
|
import com.m2049r.xmrwallet.R;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper.Request;
|
||||||
import com.m2049r.xmrwallet.util.NodePinger;
|
import com.m2049r.xmrwallet.util.NodePinger;
|
||||||
import com.m2049r.xmrwallet.util.OkHttpHelper;
|
import com.m2049r.xmrwallet.util.ThemeHelper;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -32,17 +37,12 @@ import java.io.IOException;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
@ -94,7 +94,7 @@ public class NodeInfo extends Node {
|
|||||||
synchronized public SocketAddress getLevinSocketAddress() {
|
synchronized public SocketAddress getLevinSocketAddress() {
|
||||||
if (levinSocketAddress == null) {
|
if (levinSocketAddress == null) {
|
||||||
// use default peer port if not set - very few peers use nonstandard port
|
// use default peer port if not set - very few peers use nonstandard port
|
||||||
levinSocketAddress = new InetSocketAddress(hostAddress, getDefaultLevinPort());
|
levinSocketAddress = new InetSocketAddress(hostAddress.getHostAddress(), getDefaultLevinPort());
|
||||||
}
|
}
|
||||||
return levinSocketAddress;
|
return levinSocketAddress;
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ public class NodeInfo extends Node {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int HTTP_TIMEOUT = OkHttpHelper.HTTP_TIMEOUT;
|
private static final int HTTP_TIMEOUT = 1000; //ms
|
||||||
public static final double PING_GOOD = HTTP_TIMEOUT / 3.0; //ms
|
public static final double PING_GOOD = HTTP_TIMEOUT / 3.0; //ms
|
||||||
public static final double PING_MEDIUM = 2 * PING_GOOD; //ms
|
public static final double PING_MEDIUM = 2 * PING_GOOD; //ms
|
||||||
public static final double PING_BAD = HTTP_TIMEOUT;
|
public static final double PING_BAD = HTTP_TIMEOUT;
|
||||||
@ -196,32 +196,29 @@ public class NodeInfo extends Node {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean testRpcService(int port) {
|
private Request rpcServiceRequest(int port) {
|
||||||
Timber.d("Testing %s", toNodeString());
|
final HttpUrl url = new HttpUrl.Builder()
|
||||||
clear();
|
|
||||||
try {
|
|
||||||
OkHttpClient client = OkHttpHelper.getEagerClient();
|
|
||||||
if (!getUsername().isEmpty()) {
|
|
||||||
final DigestAuthenticator authenticator =
|
|
||||||
new DigestAuthenticator(new Credentials(getUsername(), getPassword()));
|
|
||||||
final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>();
|
|
||||||
client = client.newBuilder()
|
|
||||||
.authenticator(new CachingAuthenticatorDecorator(authenticator, authCache))
|
|
||||||
.addInterceptor(new AuthenticationCacheInterceptor(authCache))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
HttpUrl url = new HttpUrl.Builder()
|
|
||||||
.scheme("http")
|
.scheme("http")
|
||||||
.host(getHostAddress())
|
.host(getHost())
|
||||||
.port(port)
|
.port(port)
|
||||||
.addPathSegment("json_rpc")
|
.addPathSegment("json_rpc")
|
||||||
.build();
|
.build();
|
||||||
final RequestBody reqBody = RequestBody
|
final String json = "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"getlastblockheader\"}";
|
||||||
.create(MediaType.parse("application/json"),
|
return new Request(url, json, getUsername(), getPassword());
|
||||||
"{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"getlastblockheader\"}");
|
}
|
||||||
Request request = OkHttpHelper.getPostRequest(url, reqBody);
|
|
||||||
|
private boolean testRpcService(int port) {
|
||||||
|
Timber.d("Testing %s", toNodeString());
|
||||||
|
clear();
|
||||||
|
if (hostAddress.isOnion() && !NetCipherHelper.isTor()) {
|
||||||
|
tested = true; // sortof
|
||||||
|
responseCode = 418; // I'm a teapot - or I need an Onion - who knows
|
||||||
|
return false; // autofail
|
||||||
|
}
|
||||||
|
try {
|
||||||
long ta = System.nanoTime();
|
long ta = System.nanoTime();
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = rpcServiceRequest(port).execute()) {
|
||||||
|
Timber.d("%s: %s", response.code(), response.request().url());
|
||||||
responseTime = (System.nanoTime() - ta) / 1000000.0;
|
responseTime = (System.nanoTime() - ta) / 1000000.0;
|
||||||
responseCode = response.code();
|
responseCode = response.code();
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
@ -243,7 +240,7 @@ public class NodeInfo extends Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | JSONException ex) {
|
} catch (IOException | JSONException ex) {
|
||||||
Timber.d(ex);
|
Timber.d("EX: %s", ex.getMessage()); //TODO: do something here (show error?)
|
||||||
} finally {
|
} finally {
|
||||||
tested = true;
|
tested = true;
|
||||||
}
|
}
|
||||||
@ -264,4 +261,43 @@ public class NodeInfo extends Node {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public final int STALE_NODE_HOURS = 2;
|
||||||
|
|
||||||
|
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),
|
||||||
|
(hostAddress.isOnion() ? " .onion " : ""), " " + info));
|
||||||
|
view.setText(text);
|
||||||
|
if (isError)
|
||||||
|
view.setTextColor(ThemeHelper.getThemedColor(ctx, R.attr.colorError));
|
||||||
|
else
|
||||||
|
view.setTextColor(ThemeHelper.getThemedColor(ctx, R.attr.colorPrimary));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showInfo(TextView view) {
|
||||||
|
if (!isTested()) {
|
||||||
|
showInfo(view, "", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Context ctx = view.getContext();
|
||||||
|
final long now = Calendar.getInstance().getTimeInMillis() / 1000;
|
||||||
|
final long secs = (now - timestamp);
|
||||||
|
final long mins = secs / 60;
|
||||||
|
final long hours = mins / 60;
|
||||||
|
final long days = hours / 24;
|
||||||
|
String info;
|
||||||
|
if (mins < 2) {
|
||||||
|
info = ctx.getString(R.string.node_updated_now, secs);
|
||||||
|
} else if (hours < 2) {
|
||||||
|
info = ctx.getString(R.string.node_updated_mins, mins);
|
||||||
|
} else if (days < 2) {
|
||||||
|
info = ctx.getString(R.string.node_updated_hours, hours);
|
||||||
|
} else {
|
||||||
|
info = ctx.getString(R.string.node_updated_days, days);
|
||||||
|
}
|
||||||
|
showInfo(view, info, hours >= STALE_NODE_HOURS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,17 @@
|
|||||||
package com.m2049r.xmrwallet.dialog;
|
package com.m2049r.xmrwallet.dialog;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.DialogInterface;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
|
import android.text.Spanned;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
@ -31,15 +35,20 @@ import androidx.fragment.app.FragmentTransaction;
|
|||||||
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
import com.m2049r.xmrwallet.R;
|
import com.m2049r.xmrwallet.R;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
|
|
||||||
public class HelpFragment extends DialogFragment {
|
public class HelpFragment extends DialogFragment {
|
||||||
static final String TAG = "HelpFragment";
|
static final String TAG = "HelpFragment";
|
||||||
private static final String HELP_ID = "HELP_ID";
|
private static final String HELP_ID = "HELP_ID";
|
||||||
|
private static final String TOR_BUTTON = "TOR";
|
||||||
|
|
||||||
public static HelpFragment newInstance(int helpResourceId) {
|
public static HelpFragment newInstance(int helpResourceId) {
|
||||||
HelpFragment fragment = new HelpFragment();
|
HelpFragment fragment = new HelpFragment();
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putInt(HELP_ID, helpResourceId);
|
bundle.putInt(HELP_ID, helpResourceId);
|
||||||
|
// a hack for the tor button
|
||||||
|
if (helpResourceId == R.string.help_tor)
|
||||||
|
bundle.putInt(TOR_BUTTON, 7);
|
||||||
fragment.setArguments(bundle);
|
fragment.setArguments(bundle);
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
@ -54,27 +63,53 @@ public class HelpFragment extends DialogFragment {
|
|||||||
HelpFragment.newInstance(helpResourceId).show(ft, TAG);
|
HelpFragment.newInstance(helpResourceId).show(ft, TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Spanned getHtml(String html, double textSize) {
|
||||||
|
final Html.ImageGetter imageGetter = source -> {
|
||||||
|
final int imageId = getResources().getIdentifier(source.replace("/", ""), "drawable", requireActivity().getPackageName());
|
||||||
|
// Don't die if we don't find the image - use a heart instead
|
||||||
|
final Drawable drawable = ContextCompat.getDrawable(requireActivity(), imageId > 0 ? imageId : R.drawable.ic_favorite_24dp);
|
||||||
|
final double f = textSize / drawable.getIntrinsicHeight();
|
||||||
|
drawable.setBounds(0, 0, (int) (f * drawable.getIntrinsicWidth()), (int) textSize);
|
||||||
|
return drawable;
|
||||||
|
};
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY, imageGetter, null);
|
||||||
|
} else {
|
||||||
|
return Html.fromHtml(html, imageGetter, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_help, null);
|
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_help, null);
|
||||||
|
|
||||||
int helpId = 0;
|
int helpId = 0;
|
||||||
|
boolean torButton = false;
|
||||||
Bundle arguments = getArguments();
|
Bundle arguments = getArguments();
|
||||||
if (arguments != null) {
|
if (arguments != null) {
|
||||||
helpId = arguments.getInt(HELP_ID);
|
helpId = arguments.getInt(HELP_ID);
|
||||||
|
torButton = arguments.getInt(TOR_BUTTON) > 0;
|
||||||
}
|
}
|
||||||
|
final TextView helpTv = view.findViewById(R.id.tvHelp);
|
||||||
if (helpId > 0)
|
if (helpId > 0)
|
||||||
((TextView) view.findViewById(R.id.tvHelp)).setText(Html.fromHtml(getString(helpId)));
|
helpTv.setText(getHtml(getString(helpId), helpTv.getTextSize()));
|
||||||
|
|
||||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getActivity())
|
MaterialAlertDialogBuilder builder =
|
||||||
.setView(view)
|
new MaterialAlertDialogBuilder(requireActivity())
|
||||||
.setNegativeButton(R.string.help_ok,
|
.setView(view);
|
||||||
new DialogInterface.OnClickListener() {
|
if (torButton) {
|
||||||
@Override
|
builder.setNegativeButton(R.string.help_nok,
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
(dialog, id) -> dialog.dismiss())
|
||||||
|
.setPositiveButton(R.string.help_getorbot,
|
||||||
|
(dialog, id) -> {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
}
|
NetCipherHelper.getInstance().installOrbot(requireActivity());
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
builder.setNegativeButton(R.string.help_ok,
|
||||||
|
(dialog, id) -> dialog.dismiss());
|
||||||
|
}
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,6 +22,7 @@ import android.os.Bundle;
|
|||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
|
import android.text.Spanned;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Patterns;
|
import android.util.Patterns;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
@ -91,6 +92,7 @@ public class SendAddressWizardFragment extends SendWizardFragment {
|
|||||||
private TextInputLayout etAddress;
|
private TextInputLayout etAddress;
|
||||||
private TextInputLayout etNotes;
|
private TextInputLayout etNotes;
|
||||||
private TextView tvXmrTo;
|
private TextView tvXmrTo;
|
||||||
|
private TextView tvTor;
|
||||||
private Map<Crypto, ImageButton> ibCrypto;
|
private Map<Crypto, ImageButton> ibCrypto;
|
||||||
final private Set<Crypto> possibleCryptos = new HashSet<>();
|
final private Set<Crypto> possibleCryptos = new HashSet<>();
|
||||||
private Crypto selectedCrypto = null;
|
private Crypto selectedCrypto = null;
|
||||||
@ -117,11 +119,12 @@ public class SendAddressWizardFragment extends SendWizardFragment {
|
|||||||
|
|
||||||
View view = inflater.inflate(R.layout.fragment_send_address, container, false);
|
View view = inflater.inflate(R.layout.fragment_send_address, container, false);
|
||||||
|
|
||||||
if (Helper.ALLOW_SHIFT) {
|
tvTor = view.findViewById(R.id.tvTor);
|
||||||
tvXmrTo = view.findViewById(R.id.tvXmrTo);
|
tvXmrTo = view.findViewById(R.id.tvXmrTo);
|
||||||
ibCrypto = new HashMap<>();
|
ibCrypto = new HashMap<>();
|
||||||
for (Crypto crypto : Crypto.values()) {
|
for (Crypto crypto : Crypto.values()) {
|
||||||
final ImageButton button = view.findViewById(crypto.getButtonId());
|
final ImageButton button = view.findViewById(crypto.getButtonId());
|
||||||
|
if (Helper.ALLOW_SHIFT || (crypto == Crypto.XMR)) {
|
||||||
ibCrypto.put(crypto, button);
|
ibCrypto.put(crypto, button);
|
||||||
button.setOnClickListener(v -> {
|
button.setOnClickListener(v -> {
|
||||||
if (possibleCryptos.contains(crypto)) {
|
if (possibleCryptos.contains(crypto)) {
|
||||||
@ -137,14 +140,21 @@ public class SendAddressWizardFragment extends SendWizardFragment {
|
|||||||
} else {
|
} else {
|
||||||
tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto_help_xmr)));
|
tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto_help_xmr)));
|
||||||
tvXmrTo.setVisibility(View.VISIBLE);
|
tvXmrTo.setVisibility(View.VISIBLE);
|
||||||
|
tvTor.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
button.setImageResource(crypto.getIconDisabledId());
|
||||||
|
button.setImageAlpha(128);
|
||||||
|
button.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!Helper.ALLOW_SHIFT) {
|
||||||
|
tvTor.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
updateCryptoButtons(true);
|
updateCryptoButtons(true);
|
||||||
} else {
|
|
||||||
view.findViewById(R.id.llExchange).setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
etAddress = view.findViewById(R.id.etAddress);
|
etAddress = view.findViewById(R.id.etAddress);
|
||||||
etAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
etAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||||
etAddress.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
etAddress.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||||
@ -455,6 +465,7 @@ public class SendAddressWizardFragment extends SendWizardFragment {
|
|||||||
Timber.d("BUT ONLY XMR SUPPORTED");
|
Timber.d("BUT ONLY XMR SUPPORTED");
|
||||||
barcodeData = null;
|
barcodeData = null;
|
||||||
sendListener.setBarcodeData(barcodeData);
|
sendListener.setBarcodeData(barcodeData);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (barcodeData.address != null) {
|
if (barcodeData.address != null) {
|
||||||
etAddress.getEditText().setText(barcodeData.address);
|
etAddress.getEditText().setText(barcodeData.address);
|
||||||
|
@ -35,7 +35,6 @@ import com.m2049r.xmrwallet.service.shift.sideshift.api.QueryOrderParameters;
|
|||||||
import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
|
import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
|
||||||
import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl;
|
import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.OkHttpHelper;
|
|
||||||
import com.m2049r.xmrwallet.util.ServiceHelper;
|
import com.m2049r.xmrwallet.util.ServiceHelper;
|
||||||
import com.m2049r.xmrwallet.widget.ExchangeOtherEditText;
|
import com.m2049r.xmrwallet.widget.ExchangeOtherEditText;
|
||||||
import com.m2049r.xmrwallet.widget.SendProgressView;
|
import com.m2049r.xmrwallet.widget.SendProgressView;
|
||||||
@ -255,8 +254,7 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
|
|||||||
if (xmrToApi == null) {
|
if (xmrToApi == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (xmrToApi == null) {
|
if (xmrToApi == null) {
|
||||||
xmrToApi = new SideShiftApiImpl(OkHttpHelper.getOkHttpClient(),
|
xmrToApi = new SideShiftApiImpl(ServiceHelper.getXmrToBaseUrl());
|
||||||
ServiceHelper.getXmrToBaseUrl());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ import com.m2049r.xmrwallet.service.shift.sideshift.api.RequestQuote;
|
|||||||
import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
|
import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
|
||||||
import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl;
|
import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.OkHttpHelper;
|
|
||||||
import com.m2049r.xmrwallet.util.ServiceHelper;
|
import com.m2049r.xmrwallet.util.ServiceHelper;
|
||||||
import com.m2049r.xmrwallet.widget.SendProgressView;
|
import com.m2049r.xmrwallet.widget.SendProgressView;
|
||||||
|
|
||||||
@ -543,8 +542,7 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements
|
|||||||
if (xmrToApi == null) {
|
if (xmrToApi == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (xmrToApi == null) {
|
if (xmrToApi == null) {
|
||||||
xmrToApi = new SideShiftApiImpl(OkHttpHelper.getOkHttpClient(),
|
xmrToApi = new SideShiftApiImpl(ServiceHelper.getXmrToBaseUrl());
|
||||||
ServiceHelper.getXmrToBaseUrl());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ import com.m2049r.xmrwallet.service.shift.sideshift.api.QueryOrderStatus;
|
|||||||
import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
|
import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
|
||||||
import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl;
|
import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.OkHttpHelper;
|
|
||||||
import com.m2049r.xmrwallet.util.ServiceHelper;
|
import com.m2049r.xmrwallet.util.ServiceHelper;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
@ -245,8 +244,7 @@ public class SendBtcSuccessWizardFragment extends SendWizardFragment {
|
|||||||
if (xmrToApi == null) {
|
if (xmrToApi == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (xmrToApi == null) {
|
if (xmrToApi == null) {
|
||||||
xmrToApi = new SideShiftApiImpl(OkHttpHelper.getOkHttpClient(),
|
xmrToApi = new SideShiftApiImpl(ServiceHelper.getXmrToBaseUrl());
|
||||||
ServiceHelper.getXmrToBaseUrl());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,28 +23,25 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.recyclerview.widget.DiffUtil;
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.R;
|
import com.m2049r.xmrwallet.R;
|
||||||
import com.m2049r.xmrwallet.data.NodeInfo;
|
import com.m2049r.xmrwallet.data.NodeInfo;
|
||||||
import com.m2049r.xmrwallet.util.ThemeHelper;
|
import com.m2049r.xmrwallet.dialog.HelpFragment;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHolder> {
|
public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHolder> {
|
||||||
private final SimpleDateFormat TS_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
|
||||||
|
|
||||||
public interface OnInteractionListener {
|
public interface OnInteractionListener {
|
||||||
void onInteraction(View view, NodeInfo item);
|
void onInteraction(View view, NodeInfo item);
|
||||||
|
|
||||||
@ -54,14 +51,16 @@ public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHo
|
|||||||
private final List<NodeInfo> nodeItems = new ArrayList<>();
|
private final List<NodeInfo> nodeItems = new ArrayList<>();
|
||||||
private final OnInteractionListener listener;
|
private final OnInteractionListener listener;
|
||||||
|
|
||||||
private final Context context;
|
private final FragmentActivity activity;
|
||||||
|
|
||||||
public NodeInfoAdapter(Context context, OnInteractionListener listener) {
|
public NodeInfoAdapter(FragmentActivity activity, OnInteractionListener listener) {
|
||||||
this.context = context;
|
this.activity = activity;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
Calendar cal = Calendar.getInstance();
|
}
|
||||||
TimeZone tz = cal.getTimeZone(); //get the local time zone.
|
|
||||||
TS_FORMATTER.setTimeZone(tz);
|
public void notifyItemChanged(NodeInfo nodeInfo) {
|
||||||
|
final int pos = nodeItems.indexOf(nodeInfo);
|
||||||
|
if (pos >= 0) notifyItemChanged(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NodeDiff extends DiffCallback<NodeInfo> {
|
private static class NodeDiff extends DiffCallback<NodeInfo> {
|
||||||
@ -142,7 +141,7 @@ public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHo
|
|||||||
final ImageButton ibBookmark;
|
final ImageButton ibBookmark;
|
||||||
final View pbBookmark;
|
final View pbBookmark;
|
||||||
final TextView tvName;
|
final TextView tvName;
|
||||||
final TextView tvIp;
|
final TextView tvInfo;
|
||||||
final ImageView ivPing;
|
final ImageView ivPing;
|
||||||
NodeInfo nodeItem;
|
NodeInfo nodeItem;
|
||||||
|
|
||||||
@ -151,7 +150,7 @@ public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHo
|
|||||||
ibBookmark = itemView.findViewById(R.id.ibBookmark);
|
ibBookmark = itemView.findViewById(R.id.ibBookmark);
|
||||||
pbBookmark = itemView.findViewById(R.id.pbBookmark);
|
pbBookmark = itemView.findViewById(R.id.pbBookmark);
|
||||||
tvName = itemView.findViewById(R.id.tvName);
|
tvName = itemView.findViewById(R.id.tvName);
|
||||||
tvIp = itemView.findViewById(R.id.tvAddress);
|
tvInfo = itemView.findViewById(R.id.tvInfo);
|
||||||
ivPing = itemView.findViewById(R.id.ivPing);
|
ivPing = itemView.findViewById(R.id.ivPing);
|
||||||
ibBookmark.setOnClickListener(v -> {
|
ibBookmark.setOnClickListener(v -> {
|
||||||
nodeItem.toggleFavourite();
|
nodeItem.toggleFavourite();
|
||||||
@ -179,13 +178,12 @@ public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHo
|
|||||||
ivPing.setImageResource(getPingIcon(nodeItem));
|
ivPing.setImageResource(getPingIcon(nodeItem));
|
||||||
if (nodeItem.isTested()) {
|
if (nodeItem.isTested()) {
|
||||||
if (nodeItem.isValid()) {
|
if (nodeItem.isValid()) {
|
||||||
Helper.showTimeDifference(tvIp, nodeItem.getTimestamp());
|
nodeItem.showInfo(tvInfo);
|
||||||
} else {
|
} else {
|
||||||
tvIp.setText(getResponseErrorText(context, nodeItem.getResponseCode()));
|
nodeItem.showInfo(tvInfo, getResponseErrorText(activity, nodeItem.getResponseCode()), true);
|
||||||
tvIp.setTextColor(ThemeHelper.getThemedColor(context, R.attr.colorError));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tvIp.setText(context.getResources().getString(R.string.node_testing, nodeItem.getHostAddress()));
|
nodeItem.showInfo(tvInfo);
|
||||||
}
|
}
|
||||||
itemView.setSelected(nodeItem.isSelected());
|
itemView.setSelected(nodeItem.isSelected());
|
||||||
itemView.setClickable(itemsClickable);
|
itemView.setClickable(itemsClickable);
|
||||||
@ -201,6 +199,16 @@ public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHo
|
|||||||
int position = getAdapterPosition(); // gets item position
|
int position = getAdapterPosition(); // gets item position
|
||||||
if (position != RecyclerView.NO_POSITION) { // Check if an item was deleted, but the user clicked it before the UI removed it
|
if (position != RecyclerView.NO_POSITION) { // Check if an item was deleted, but the user clicked it before the UI removed it
|
||||||
final NodeInfo node = nodeItems.get(position);
|
final NodeInfo node = nodeItems.get(position);
|
||||||
|
if (node.isOnion()) {
|
||||||
|
switch (NetCipherHelper.getStatus()) {
|
||||||
|
case NOT_INSTALLED:
|
||||||
|
HelpFragment.display(activity.getSupportFragmentManager(), R.string.help_tor);
|
||||||
|
return;
|
||||||
|
case DISABLED:
|
||||||
|
HelpFragment.display(activity.getSupportFragmentManager(), R.string.help_tor_enable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
node.setSelecting(true);
|
node.setSelecting(true);
|
||||||
allowClick(false);
|
allowClick(false);
|
||||||
listener.onInteraction(view, node);
|
listener.onInteraction(view, node);
|
||||||
@ -245,6 +253,8 @@ public class NodeInfoAdapter extends RecyclerView.Adapter<NodeInfoAdapter.ViewHo
|
|||||||
return ctx.getResources().getString(R.string.node_general_error);
|
return ctx.getResources().getString(R.string.node_general_error);
|
||||||
} else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
|
} else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
|
||||||
return ctx.getResources().getString(R.string.node_auth_error);
|
return ctx.getResources().getString(R.string.node_auth_error);
|
||||||
|
} else if (responseCode == 418) {
|
||||||
|
return ctx.getResources().getString(R.string.node_tor_error);
|
||||||
} else {
|
} else {
|
||||||
return ctx.getResources().getString(R.string.node_test_error, responseCode);
|
return ctx.getResources().getString(R.string.node_test_error, responseCode);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
final ImageView ivTxType;
|
final ImageView ivTxType;
|
||||||
final TextView tvAmount;
|
final TextView tvAmount;
|
||||||
final TextView tvFee;
|
final TextView tvFailed;
|
||||||
final TextView tvPaymentId;
|
final TextView tvPaymentId;
|
||||||
final TextView tvDateTime;
|
final TextView tvDateTime;
|
||||||
final CircularProgressIndicator pbConfirmations;
|
final CircularProgressIndicator pbConfirmations;
|
||||||
@ -163,7 +163,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
super(itemView);
|
super(itemView);
|
||||||
ivTxType = itemView.findViewById(R.id.ivTxType);
|
ivTxType = itemView.findViewById(R.id.ivTxType);
|
||||||
tvAmount = itemView.findViewById(R.id.tx_amount);
|
tvAmount = itemView.findViewById(R.id.tx_amount);
|
||||||
tvFee = itemView.findViewById(R.id.tx_fee);
|
tvFailed = itemView.findViewById(R.id.tx_failed);
|
||||||
tvPaymentId = itemView.findViewById(R.id.tx_paymentid);
|
tvPaymentId = itemView.findViewById(R.id.tx_paymentid);
|
||||||
tvDateTime = itemView.findViewById(R.id.tx_datetime);
|
tvDateTime = itemView.findViewById(R.id.tx_datetime);
|
||||||
pbConfirmations = itemView.findViewById(R.id.pbConfirmations);
|
pbConfirmations = itemView.findViewById(R.id.pbConfirmations);
|
||||||
@ -203,18 +203,10 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
tvAmount.setText(context.getString(R.string.tx_list_amount_positive, displayAmount));
|
tvAmount.setText(context.getString(R.string.tx_list_amount_positive, displayAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((infoItem.fee > 0)) {
|
tvFailed.setVisibility(View.GONE);
|
||||||
String fee = Helper.getDisplayAmount(infoItem.fee, Helper.DISPLAY_DIGITS_INFO);
|
|
||||||
tvFee.setText(context.getString(R.string.tx_list_fee, fee));
|
|
||||||
tvFee.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
tvFee.setText("");
|
|
||||||
tvFee.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
if (infoItem.isFailed) {
|
if (infoItem.isFailed) {
|
||||||
this.tvAmount.setText(context.getString(R.string.tx_list_amount_failed, displayAmount));
|
this.tvAmount.setText(context.getString(R.string.tx_list_amount_failed, displayAmount));
|
||||||
this.tvFee.setText(context.getString(R.string.tx_list_failed_text));
|
tvFailed.setVisibility(View.VISIBLE);
|
||||||
tvFee.setVisibility(View.VISIBLE);
|
|
||||||
setTxColour(failedColour);
|
setTxColour(failedColour);
|
||||||
pbConfirmations.setVisibility(View.GONE);
|
pbConfirmations.setVisibility(View.GONE);
|
||||||
tvConfirmations.setVisibility(View.GONE);
|
tvConfirmations.setVisibility(View.GONE);
|
||||||
|
@ -75,7 +75,7 @@ public class Wallet {
|
|||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Wallet.Status: (" + status + "/" + errorString + ", " + connectionStatus;
|
return "Wallet.Status: " + status + "/" + errorString + "/" + connectionStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +247,8 @@ public class Wallet {
|
|||||||
//TODO virtual void setTrustedDaemon(bool arg) = 0;
|
//TODO virtual void setTrustedDaemon(bool arg) = 0;
|
||||||
//TODO virtual bool trustedDaemon() const = 0;
|
//TODO virtual bool trustedDaemon() const = 0;
|
||||||
|
|
||||||
|
public native boolean setProxy(String address);
|
||||||
|
|
||||||
public long getBalance() {
|
public long getBalance() {
|
||||||
return getBalance(accountIndex);
|
return getBalance(accountIndex);
|
||||||
}
|
}
|
||||||
|
@ -309,6 +309,8 @@ public class WalletManager {
|
|||||||
|
|
||||||
public native String resolveOpenAlias(String address, boolean dnssec_valid);
|
public native String resolveOpenAlias(String address, boolean dnssec_valid);
|
||||||
|
|
||||||
|
public native boolean setProxy(String address);
|
||||||
|
|
||||||
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
|
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
|
||||||
|
|
||||||
static public native void initLogger(String argv0, String defaultLogBaseName);
|
static public native void initLogger(String argv0, String defaultLogBaseName);
|
||||||
|
@ -45,6 +45,7 @@ import com.m2049r.xmrwallet.model.WalletListener;
|
|||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.LocaleHelper;
|
import com.m2049r.xmrwallet.util.LocaleHelper;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
|
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
@ -531,6 +532,7 @@ public class WalletService extends Service {
|
|||||||
Timber.d("Using daemon %s", WalletManager.getInstance().getDaemonAddress());
|
Timber.d("Using daemon %s", WalletManager.getInstance().getDaemonAddress());
|
||||||
showProgress(55);
|
showProgress(55);
|
||||||
wallet.init(0);
|
wallet.init(0);
|
||||||
|
wallet.setProxy(NetCipherHelper.getProxy());
|
||||||
showProgress(90);
|
showProgress(90);
|
||||||
}
|
}
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -25,6 +25,7 @@ import com.m2049r.xmrwallet.service.exchange.api.ExchangeApi;
|
|||||||
import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
|
import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
|
||||||
import com.m2049r.xmrwallet.service.exchange.api.ExchangeException;
|
import com.m2049r.xmrwallet.service.exchange.api.ExchangeException;
|
||||||
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
|
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@ -48,26 +49,21 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||||||
|
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class ExchangeApiImpl implements ExchangeApi {
|
public class ExchangeApiImpl implements ExchangeApi {
|
||||||
@NonNull
|
|
||||||
private final OkHttpClient okHttpClient;
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final HttpUrl baseUrl;
|
private final HttpUrl baseUrl;
|
||||||
|
|
||||||
//so we can inject the mockserver url
|
//so we can inject the mockserver url
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public ExchangeApiImpl(@NonNull final OkHttpClient okHttpClient, @NonNull final HttpUrl baseUrl) {
|
public ExchangeApiImpl(@NonNull final HttpUrl baseUrl) {
|
||||||
this.okHttpClient = okHttpClient;
|
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExchangeApiImpl(@NonNull final OkHttpClient okHttpClient) {
|
public ExchangeApiImpl() {
|
||||||
this(okHttpClient, HttpUrl.parse("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"));
|
this(HttpUrl.parse("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"));
|
||||||
// data is daily and is refreshed around 16:00 CET every working day
|
// data is daily and is refreshed around 16:00 CET every working day
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,9 +118,8 @@ public class ExchangeApiImpl implements ExchangeApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Request httpRequest = createHttpRequest(baseUrl);
|
final NetCipherHelper.Request httpRequest = new NetCipherHelper.Request(baseUrl);
|
||||||
|
httpRequest.enqueue(new okhttp3.Callback() {
|
||||||
okHttpClient.newCall(httpRequest).enqueue(new okhttp3.Callback() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(final Call call, final IOException ex) {
|
public void onFailure(final Call call, final IOException ex) {
|
||||||
callback.onError(ex);
|
callback.onError(ex);
|
||||||
@ -155,13 +150,6 @@ public class ExchangeApiImpl implements ExchangeApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Request createHttpRequest(final HttpUrl url) {
|
|
||||||
return new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.get()
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
final private Map<String, Double> fxEntries = new HashMap<>();
|
final private Map<String, Double> fxEntries = new HashMap<>();
|
||||||
private Calendar fxDate = null;
|
private Calendar fxDate = null;
|
||||||
private Calendar fetchDate = null;
|
private Calendar fetchDate = null;
|
||||||
|
@ -24,6 +24,7 @@ import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
|
|||||||
import com.m2049r.xmrwallet.service.exchange.api.ExchangeException;
|
import com.m2049r.xmrwallet.service.exchange.api.ExchangeException;
|
||||||
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
|
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
@ -33,27 +34,21 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class ExchangeApiImpl implements ExchangeApi {
|
public class ExchangeApiImpl implements ExchangeApi {
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private final OkHttpClient okHttpClient;
|
|
||||||
|
|
||||||
private final HttpUrl baseUrl;
|
private final HttpUrl baseUrl;
|
||||||
|
|
||||||
//so we can inject the mockserver url
|
//so we can inject the mockserver url
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public ExchangeApiImpl(@NonNull final OkHttpClient okHttpClient, final HttpUrl baseUrl) {
|
public ExchangeApiImpl(final HttpUrl baseUrl) {
|
||||||
this.okHttpClient = okHttpClient;
|
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExchangeApiImpl(@NonNull final OkHttpClient okHttpClient) {
|
public ExchangeApiImpl() {
|
||||||
this(okHttpClient, HttpUrl.parse("https://api.kraken.com/0/public/Ticker"));
|
this(HttpUrl.parse("https://api.kraken.com/0/public/Ticker"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -86,9 +81,8 @@ public class ExchangeApiImpl implements ExchangeApi {
|
|||||||
.addQueryParameter("pair", base + (quote.equals("BTC") ? "XBT" : quote))
|
.addQueryParameter("pair", base + (quote.equals("BTC") ? "XBT" : quote))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
final Request httpRequest = createHttpRequest(url);
|
final NetCipherHelper.Request httpRequest = new NetCipherHelper.Request(url);
|
||||||
|
httpRequest.enqueue(new okhttp3.Callback() {
|
||||||
okHttpClient.newCall(httpRequest).enqueue(new okhttp3.Callback() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(final Call call, final IOException ex) {
|
public void onFailure(final Call call, final IOException ex) {
|
||||||
callback.onError(ex);
|
callback.onError(ex);
|
||||||
@ -127,11 +121,4 @@ public class ExchangeApiImpl implements ExchangeApi {
|
|||||||
callback.onError(ex);
|
callback.onError(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Request createHttpRequest(final HttpUrl url) {
|
|
||||||
return new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.get()
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,6 @@ import timber.log.Timber;
|
|||||||
public class ExchangeApiImpl implements ExchangeApi {
|
public class ExchangeApiImpl implements ExchangeApi {
|
||||||
static public final String BASE_FIAT = "EUR";
|
static public final String BASE_FIAT = "EUR";
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private final OkHttpClient okHttpClient;
|
|
||||||
|
|
||||||
public ExchangeApiImpl(@NonNull final OkHttpClient okHttpClient) {
|
|
||||||
this.okHttpClient = okHttpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void queryExchangeRate(@NonNull final String baseCurrency, @NonNull final String quoteCurrency,
|
public void queryExchangeRate(@NonNull final String baseCurrency, @NonNull final String quoteCurrency,
|
||||||
@NonNull final ExchangeCallback callback) {
|
@NonNull final ExchangeCallback callback) {
|
||||||
@ -61,13 +54,13 @@ public class ExchangeApiImpl implements ExchangeApi {
|
|||||||
final String quote = Helper.BASE_CRYPTO.equals(baseCurrency) ? quoteCurrency : baseCurrency;
|
final String quote = Helper.BASE_CRYPTO.equals(baseCurrency) ? quoteCurrency : baseCurrency;
|
||||||
|
|
||||||
final ExchangeApi krakenApi =
|
final ExchangeApi krakenApi =
|
||||||
new com.m2049r.xmrwallet.service.exchange.kraken.ExchangeApiImpl(okHttpClient);
|
new com.m2049r.xmrwallet.service.exchange.kraken.ExchangeApiImpl();
|
||||||
krakenApi.queryExchangeRate(Helper.BASE_CRYPTO, BASE_FIAT, new ExchangeCallback() {
|
krakenApi.queryExchangeRate(Helper.BASE_CRYPTO, BASE_FIAT, new ExchangeCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final ExchangeRate krakenRate) {
|
public void onSuccess(final ExchangeRate krakenRate) {
|
||||||
Timber.d("kraken = %f", krakenRate.getRate());
|
Timber.d("kraken = %f", krakenRate.getRate());
|
||||||
final ExchangeApi ecbApi =
|
final ExchangeApi ecbApi =
|
||||||
new com.m2049r.xmrwallet.service.exchange.ecb.ExchangeApiImpl(okHttpClient);
|
new com.m2049r.xmrwallet.service.exchange.ecb.ExchangeApiImpl();
|
||||||
ecbApi.queryExchangeRate(BASE_FIAT, quote, new ExchangeCallback() {
|
ecbApi.queryExchangeRate(BASE_FIAT, quote, new ExchangeCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final ExchangeRate ecbRate) {
|
public void onSuccess(final ExchangeRate ecbRate) {
|
||||||
|
@ -30,7 +30,7 @@ import com.m2049r.xmrwallet.service.shift.sideshift.api.QueryOrderParameters;
|
|||||||
import com.m2049r.xmrwallet.service.shift.sideshift.api.QueryOrderStatus;
|
import com.m2049r.xmrwallet.service.shift.sideshift.api.QueryOrderStatus;
|
||||||
import com.m2049r.xmrwallet.service.shift.sideshift.api.RequestQuote;
|
import com.m2049r.xmrwallet.service.shift.sideshift.api.RequestQuote;
|
||||||
import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
|
import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi;
|
||||||
import com.m2049r.xmrwallet.util.OkHttpHelper;
|
import com.m2049r.xmrwallet.util.NetCipherHelper;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -39,22 +39,14 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class SideShiftApiImpl implements SideShiftApi, ShiftApiCall {
|
public class SideShiftApiImpl implements SideShiftApi, ShiftApiCall {
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private final OkHttpClient okHttpClient;
|
|
||||||
|
|
||||||
private final HttpUrl baseUrl;
|
private final HttpUrl baseUrl;
|
||||||
|
|
||||||
public SideShiftApiImpl(@NonNull final OkHttpClient okHttpClient, final HttpUrl baseUrl) {
|
public SideShiftApiImpl(final HttpUrl baseUrl) {
|
||||||
this.okHttpClient = okHttpClient;
|
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,9 +87,9 @@ public class SideShiftApiImpl implements SideShiftApi, ShiftApiCall {
|
|||||||
final HttpUrl url = baseUrl.newBuilder()
|
final HttpUrl url = baseUrl.newBuilder()
|
||||||
.addPathSegments(path)
|
.addPathSegments(path)
|
||||||
.build();
|
.build();
|
||||||
final Request httpRequest = createHttpRequest(request, url);
|
|
||||||
|
|
||||||
okHttpClient.newCall(httpRequest).enqueue(new okhttp3.Callback() {
|
NetCipherHelper.Request httpRequest = new NetCipherHelper.Request(url, request);
|
||||||
|
httpRequest.enqueue(new okhttp3.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(final Call call, final IOException ex) {
|
public void onFailure(final Call call, final IOException ex) {
|
||||||
callback.onError(ex);
|
callback.onError(ex);
|
||||||
@ -127,13 +119,4 @@ public class SideShiftApiImpl implements SideShiftApi, ShiftApiCall {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Request createHttpRequest(final JSONObject request, final HttpUrl url) {
|
|
||||||
if (request != null) {
|
|
||||||
final RequestBody body = RequestBody.create(request.toString(), MediaType.parse("application/json"));
|
|
||||||
return OkHttpHelper.getPostRequest(url, body);
|
|
||||||
} else {
|
|
||||||
return OkHttpHelper.getGetRequest(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ public class Helper {
|
|||||||
static public final long ONE_XMR = Math.round(Math.pow(10, Helper.XMR_DECIMALS));
|
static public final long ONE_XMR = Math.round(Math.pow(10, Helper.XMR_DECIMALS));
|
||||||
|
|
||||||
static public final boolean SHOW_EXCHANGERATES = true;
|
static public final boolean SHOW_EXCHANGERATES = true;
|
||||||
static public final boolean ALLOW_SHIFT = true;
|
static public boolean ALLOW_SHIFT = false;
|
||||||
|
|
||||||
static private final String WALLET_DIR = "wallets";
|
static private final String WALLET_DIR = "wallets";
|
||||||
static private final String MONERO_DIR = "monero";
|
static private final String MONERO_DIR = "monero";
|
||||||
@ -606,30 +606,4 @@ public class Helper {
|
|||||||
static public boolean preventScreenshot() {
|
static public boolean preventScreenshot() {
|
||||||
return !(BuildConfig.DEBUG || BuildConfig.FLAVOR_type.equals("alpha"));
|
return !(BuildConfig.DEBUG || BuildConfig.FLAVOR_type.equals("alpha"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static public final int STALE_NODE_HOURS = 2;
|
|
||||||
|
|
||||||
static public void showTimeDifference(TextView view, long timeInSeconds) {
|
|
||||||
final Context ctx = view.getContext();
|
|
||||||
final long now = Calendar.getInstance().getTimeInMillis() / 1000;
|
|
||||||
final long secs = (now - timeInSeconds);
|
|
||||||
final long mins = secs / 60; // in minutes
|
|
||||||
final long hours = mins / 60;
|
|
||||||
final long days = hours / 24;
|
|
||||||
String msg;
|
|
||||||
if (mins < 2) {
|
|
||||||
msg = ctx.getString(R.string.node_updated_now, secs);
|
|
||||||
} else if (hours < 2) {
|
|
||||||
msg = ctx.getString(R.string.node_updated_mins, mins);
|
|
||||||
} else if (days < 2) {
|
|
||||||
msg = ctx.getString(R.string.node_updated_hours, hours);
|
|
||||||
} else {
|
|
||||||
msg = ctx.getString(R.string.node_updated_days, days);
|
|
||||||
}
|
|
||||||
view.setText(msg);
|
|
||||||
if (hours >= STALE_NODE_HOURS)
|
|
||||||
view.setTextColor(ThemeHelper.getThemedColor(view.getContext(), R.attr.colorError));
|
|
||||||
else
|
|
||||||
view.setTextColor(ThemeHelper.getThemedColor(view.getContext(), android.R.attr.textColorPrimary));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
389
app/src/main/java/com/m2049r/xmrwallet/util/NetCipherHelper.java
Normal file
389
app/src/main/java/com/m2049r/xmrwallet/util/NetCipherHelper.java
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.util;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
|
||||||
|
import com.burgstaller.okhttp.AuthenticationCacheInterceptor;
|
||||||
|
import com.burgstaller.okhttp.CachingAuthenticatorDecorator;
|
||||||
|
import com.burgstaller.okhttp.digest.CachingAuthenticator;
|
||||||
|
import com.burgstaller.okhttp.digest.Credentials;
|
||||||
|
import com.burgstaller.okhttp.digest.DigestAuthenticator;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.client.StrongOkHttpClientBuilder;
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
|
import info.guardianproject.netcipher.proxy.SignatureUtils;
|
||||||
|
import info.guardianproject.netcipher.proxy.StatusCallback;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
import okhttp3.Call;
|
||||||
|
import okhttp3.Callback;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class NetCipherHelper implements StatusCallback {
|
||||||
|
public static final String USER_AGENT = "Monerujo/1.0";
|
||||||
|
public static final int HTTP_TIMEOUT = 1000; //ms
|
||||||
|
public static final int TOR_TIMEOUT_CONNECT = 5000; //ms
|
||||||
|
public static final int TOR_TIMEOUT = 2000; //ms
|
||||||
|
|
||||||
|
public interface OnStatusChangedListener {
|
||||||
|
void connected();
|
||||||
|
|
||||||
|
void disconnected();
|
||||||
|
|
||||||
|
void notInstalled();
|
||||||
|
|
||||||
|
void notEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
final private Context context;
|
||||||
|
final private OrbotHelper orbot;
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
private static NetCipherHelper Instance;
|
||||||
|
|
||||||
|
public static void createInstance(Context context) {
|
||||||
|
if (Instance == null) {
|
||||||
|
synchronized (NetCipherHelper.class) {
|
||||||
|
if (Instance == null) {
|
||||||
|
final Context applicationContext = context.getApplicationContext();
|
||||||
|
Instance = new NetCipherHelper(applicationContext, OrbotHelper.get(context).statusTimeout(5000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetCipherHelper getInstance() {
|
||||||
|
if (Instance == null) throw new IllegalStateException("NetCipherHelper is null");
|
||||||
|
return Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OkHttpClient client;
|
||||||
|
|
||||||
|
private void createTorClient(Intent statusIntent) {
|
||||||
|
String orbotStatus = statusIntent.getStringExtra(OrbotHelper.EXTRA_STATUS);
|
||||||
|
if (orbotStatus == null) throw new IllegalStateException("status is null");
|
||||||
|
if (!orbotStatus.equals(OrbotHelper.STATUS_ON))
|
||||||
|
throw new IllegalStateException("Orbot is not ON");
|
||||||
|
try {
|
||||||
|
final OkHttpClient.Builder okBuilder = new OkHttpClient.Builder()
|
||||||
|
.connectTimeout(TOR_TIMEOUT_CONNECT, TimeUnit.MILLISECONDS)
|
||||||
|
.writeTimeout(TOR_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
.readTimeout(TOR_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||||
|
client = new StrongOkHttpClientBuilder(context)
|
||||||
|
.withSocksProxy()
|
||||||
|
.applyTo(okBuilder, statusIntent)
|
||||||
|
.build();
|
||||||
|
Helper.ALLOW_SHIFT = false; // no shifting with Tor
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalStateException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createClearnetClient() {
|
||||||
|
try {
|
||||||
|
client = new OkHttpClient.Builder()
|
||||||
|
.connectTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
.writeTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
.readTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
.build();
|
||||||
|
Helper.ALLOW_SHIFT = true;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalStateException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnStatusChangedListener onStatusChangedListener;
|
||||||
|
|
||||||
|
public static void deregister() {
|
||||||
|
getInstance().onStatusChangedListener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(OnStatusChangedListener listener) {
|
||||||
|
final NetCipherHelper me = getInstance();
|
||||||
|
me.onStatusChangedListener = listener;
|
||||||
|
|
||||||
|
// NOT_INSTALLED is dealt with through the callbacks
|
||||||
|
me.orbot.removeStatusCallback(me) // make sure we are registered just once
|
||||||
|
.addStatusCallback(me);
|
||||||
|
|
||||||
|
// deal with org.torproject.android.intent.action.STATUS = STARTS_DISABLED
|
||||||
|
me.context.registerReceiver(orbotStatusReceiver, new IntentFilter(OrbotHelper.ACTION_STATUS));
|
||||||
|
|
||||||
|
me.startTor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// for StatusCallback
|
||||||
|
public enum Status {
|
||||||
|
STARTING,
|
||||||
|
ENABLED,
|
||||||
|
STOPPING,
|
||||||
|
DISABLED,
|
||||||
|
NOT_INSTALLED,
|
||||||
|
NOT_ENABLED,
|
||||||
|
UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Status status = Status.UNKNOWN;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStarting() {
|
||||||
|
Timber.d("onStarting");
|
||||||
|
status = Status.STARTING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnabled(Intent statusIntent) {
|
||||||
|
Timber.d("onEnabled");
|
||||||
|
if (getTorPref() != Status.ENABLED) return; // do we want Tor?
|
||||||
|
createTorClient(statusIntent);
|
||||||
|
status = Status.ENABLED;
|
||||||
|
if (onStatusChangedListener != null) {
|
||||||
|
new Thread(() -> onStatusChangedListener.connected()).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopping() {
|
||||||
|
Timber.d("onStopping");
|
||||||
|
status = Status.STOPPING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisabled() {
|
||||||
|
Timber.d("onDisabled");
|
||||||
|
createClearnetClient();
|
||||||
|
status = Status.DISABLED;
|
||||||
|
if (onStatusChangedListener != null) {
|
||||||
|
new Thread(() -> onStatusChangedListener.disconnected()).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStatusTimeout() {
|
||||||
|
Timber.d("onStatusTimeout");
|
||||||
|
createClearnetClient();
|
||||||
|
// (timeout does not not change the status)
|
||||||
|
if (onStatusChangedListener != null) {
|
||||||
|
new Thread(() -> onStatusChangedListener.disconnected()).start();
|
||||||
|
}
|
||||||
|
orbotInit = false; // do init() next time we try to open Tor
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNotYetInstalled() {
|
||||||
|
Timber.d("onNotYetInstalled");
|
||||||
|
// never mind then
|
||||||
|
orbot.removeStatusCallback(this);
|
||||||
|
createClearnetClient();
|
||||||
|
status = Status.NOT_INSTALLED;
|
||||||
|
if (onStatusChangedListener != null) {
|
||||||
|
new Thread(() -> onStatusChangedListener.notInstalled()).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// user has not enabled background Orbot starts
|
||||||
|
public void onNotEnabled() {
|
||||||
|
Timber.d("onNotEnabled");
|
||||||
|
// keep the callback in case they turn it on manually
|
||||||
|
setTorPref(Status.DISABLED);
|
||||||
|
createClearnetClient();
|
||||||
|
status = Status.NOT_ENABLED;
|
||||||
|
if (onStatusChangedListener != null) {
|
||||||
|
new Thread(() -> onStatusChangedListener.notEnabled()).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Status getStatus() {
|
||||||
|
return getInstance().status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggle() {
|
||||||
|
switch (getStatus()) {
|
||||||
|
case ENABLED:
|
||||||
|
onDisabled();
|
||||||
|
setTorPref(Status.DISABLED);
|
||||||
|
break;
|
||||||
|
case DISABLED:
|
||||||
|
setTorPref(Status.ENABLED);
|
||||||
|
startTor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean orbotInit = false;
|
||||||
|
|
||||||
|
private void startTor() {
|
||||||
|
if (!isOrbotInstalled()) {
|
||||||
|
onNotYetInstalled();
|
||||||
|
} else if (getTorPref() == Status.DISABLED) {
|
||||||
|
onDisabled();
|
||||||
|
} else if (!orbotInit) {
|
||||||
|
orbotInit = orbot.init();
|
||||||
|
} else {
|
||||||
|
orbot.requestStart(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extracted from OrbotHelper
|
||||||
|
private boolean isOrbotInstalled() {
|
||||||
|
ArrayList<String> hashes = new ArrayList<>();
|
||||||
|
// Tor Project signing key
|
||||||
|
hashes.add("A4:54:B8:7A:18:47:A8:9E:D7:F5:E7:0F:BA:6B:BA:96:F3:EF:29:C2:6E:09:81:20:4F:E3:47:BF:23:1D:FD:5B");
|
||||||
|
// f-droid.org signing key
|
||||||
|
hashes.add("A7:02:07:92:4F:61:FF:09:37:1D:54:84:14:5C:4B:EE:77:2C:55:C1:9E:EE:23:2F:57:70:E1:82:71:F7:CB:AE");
|
||||||
|
|
||||||
|
return null != SignatureUtils.validateBroadcastIntent(context,
|
||||||
|
OrbotHelper.getOrbotStartIntent(context),
|
||||||
|
hashes, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public boolean hasClient() {
|
||||||
|
return getInstance().client != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public boolean isTor() {
|
||||||
|
return getStatus() == Status.ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public String getProxy() {
|
||||||
|
if (!isTor()) return "";
|
||||||
|
final Proxy proxy = getInstance().client.proxy();
|
||||||
|
if (proxy == null) return "";
|
||||||
|
return proxy.address().toString().substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
static public class Request {
|
||||||
|
final HttpUrl url;
|
||||||
|
final String json;
|
||||||
|
final String username;
|
||||||
|
final String password;
|
||||||
|
|
||||||
|
public Request(final HttpUrl url, final String json, final String username, final String password) {
|
||||||
|
this.url = url;
|
||||||
|
this.json = json;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request(final HttpUrl url, final JSONObject json) {
|
||||||
|
this(url, json == null ? null : json.toString(), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request(final HttpUrl url) {
|
||||||
|
this(url, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enqueue(Callback callback) {
|
||||||
|
newCall().enqueue(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response execute() throws IOException {
|
||||||
|
return newCall().execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Call newCall() {
|
||||||
|
return getClient().newCall(getRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
private OkHttpClient getClient() {
|
||||||
|
final OkHttpClient client = getInstance().client;
|
||||||
|
if ((username != null) && (!username.isEmpty())) {
|
||||||
|
final DigestAuthenticator authenticator = new DigestAuthenticator(new Credentials(username, password));
|
||||||
|
final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>();
|
||||||
|
return client.newBuilder()
|
||||||
|
.authenticator(new CachingAuthenticatorDecorator(authenticator, authCache))
|
||||||
|
.addInterceptor(new AuthenticationCacheInterceptor(authCache))
|
||||||
|
.build();
|
||||||
|
// TODO: maybe cache & reuse the client for these credentials?
|
||||||
|
} else {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private okhttp3.Request getRequest() {
|
||||||
|
final okhttp3.Request.Builder builder =
|
||||||
|
new okhttp3.Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header("User-Agent", USER_AGENT);
|
||||||
|
if (json != null) {
|
||||||
|
builder.post(RequestBody.create(json, MediaType.parse("application/json")));
|
||||||
|
} else {
|
||||||
|
builder.get();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String PREFS_NAME = "tor";
|
||||||
|
private static final String PREFS_STATUS = "status";
|
||||||
|
private Status currentPref = Status.UNKNOWN;
|
||||||
|
|
||||||
|
private Status getTorPref() {
|
||||||
|
if (currentPref != Status.UNKNOWN) return currentPref;
|
||||||
|
currentPref = Status.valueOf(context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||||
|
.getString(PREFS_STATUS, "DISABLED"));
|
||||||
|
return currentPref;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTorPref(Status status) {
|
||||||
|
if (getTorPref() == status) return; // no change
|
||||||
|
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||||
|
.edit()
|
||||||
|
.putString(PREFS_STATUS, status.name())
|
||||||
|
.apply();
|
||||||
|
currentPref = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final BroadcastReceiver orbotStatusReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
Timber.d("%s/%s", intent.getAction(), intent.getStringExtra(OrbotHelper.EXTRA_STATUS));
|
||||||
|
if (OrbotHelper.ACTION_STATUS.equals(intent.getAction())) {
|
||||||
|
if (OrbotHelper.STATUS_STARTS_DISABLED.equals(intent.getStringExtra(OrbotHelper.EXTRA_STATUS))) {
|
||||||
|
getInstance().onNotEnabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void installOrbot(Activity host) {
|
||||||
|
host.startActivity(OrbotHelper.getOrbotInstallIntent(context));
|
||||||
|
}
|
||||||
|
}
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017 m2049r
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.m2049r.xmrwallet.util;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
|
|
||||||
public class OkHttpHelper {
|
|
||||||
static private OkHttpClient Singleton;
|
|
||||||
|
|
||||||
static public OkHttpClient getOkHttpClient() {
|
|
||||||
if (Singleton == null) {
|
|
||||||
synchronized (OkHttpHelper.class) {
|
|
||||||
if (Singleton == null) {
|
|
||||||
Singleton = new OkHttpClient();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final int HTTP_TIMEOUT = 1000; //ms
|
|
||||||
|
|
||||||
static private OkHttpClient EagerSingleton;
|
|
||||||
|
|
||||||
static public OkHttpClient getEagerClient() {
|
|
||||||
if (EagerSingleton == null) {
|
|
||||||
synchronized (OkHttpHelper.class) {
|
|
||||||
if (EagerSingleton == null) {
|
|
||||||
EagerSingleton = new OkHttpClient.Builder()
|
|
||||||
.connectTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS)
|
|
||||||
.writeTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS)
|
|
||||||
.readTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EagerSingleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
static final public String USER_AGENT = "Monerujo/1.0";
|
|
||||||
|
|
||||||
static public Request getPostRequest(HttpUrl url, RequestBody requestBody) {
|
|
||||||
return new Request.Builder().url(url).post(requestBody)
|
|
||||||
.header("User-Agent", USER_AGENT)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
static public Request getGetRequest(HttpUrl url) {
|
|
||||||
return new Request.Builder().url(url).get()
|
|
||||||
.header("User-Agent", USER_AGENT)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
24
app/src/main/java/com/m2049r/xmrwallet/util/OnionHelper.java
Normal file
24
app/src/main/java/com/m2049r/xmrwallet/util/OnionHelper.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.util;
|
||||||
|
|
||||||
|
public class OnionHelper {
|
||||||
|
|
||||||
|
public static boolean isOnionHost(String hostname) {
|
||||||
|
return hostname.endsWith(".onion");
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,6 @@ public class ServiceHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public ExchangeApi getExchangeApi() {
|
static public ExchangeApi getExchangeApi() {
|
||||||
return new com.m2049r.xmrwallet.service.exchange.krakenEcb.ExchangeApiImpl(OkHttpHelper.getOkHttpClient());
|
return new com.m2049r.xmrwallet.service.exchange.krakenEcb.ExchangeApiImpl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,8 +344,8 @@ public class ExchangeEditText extends LinearLayout {
|
|||||||
if (rate > 0) {
|
if (rate > 0) {
|
||||||
tvAmountB.setText(Helper.getFormattedAmount(rate * amount, getCurrencyB() == 0));
|
tvAmountB.setText(Helper.getFormattedAmount(rate * amount, getCurrencyB() == 0));
|
||||||
} else {
|
} else {
|
||||||
tvAmountB.setText(null);
|
tvAmountB.setText("--");
|
||||||
Timber.w("No rate!");
|
Timber.d("No rate!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,23 +321,13 @@ public class ExchangeView extends LinearLayout {
|
|||||||
@Override
|
@Override
|
||||||
public void onSuccess(final ExchangeRate exchangeRate) {
|
public void onSuccess(final ExchangeRate exchangeRate) {
|
||||||
if (isAttachedToWindow())
|
if (isAttachedToWindow())
|
||||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
new Handler(Looper.getMainLooper()).post(() -> exchange(exchangeRate));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
exchange(exchangeRate);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(final Exception e) {
|
public void onError(final Exception e) {
|
||||||
Timber.e(e.getLocalizedMessage());
|
Timber.e(e.getLocalizedMessage());
|
||||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
new Handler(Looper.getMainLooper()).post(() -> exchangeFailed());
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
exchangeFailed();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -362,11 +352,10 @@ public class ExchangeView extends LinearLayout {
|
|||||||
}
|
}
|
||||||
tvAmountB.setText(xmrAmount);
|
tvAmountB.setText(xmrAmount);
|
||||||
} else { // no XMR currency - cannot happen!
|
} else { // no XMR currency - cannot happen!
|
||||||
Timber.e("No XMR currency!");
|
throw new IllegalStateException("No XMR currency!");
|
||||||
setXmr(null);
|
|
||||||
notXmrAmount = null;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (rate == 0)
|
||||||
|
tvAmountB.setText("--");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean prepareExchange() {
|
boolean prepareExchange() {
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2016 Nathan Freitas
|
||||||
|
* Copyright 2015 str4d
|
||||||
|
* Portions Copyright (c) 2016 CommonsWare, LLC
|
||||||
|
*
|
||||||
|
* 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 info.guardianproject.netcipher.client;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an OkHttpClient using NetCipher configuration. Use
|
||||||
|
* build() if you have no other OkHttpClient configuration
|
||||||
|
* that you need to perform. Or, use applyTo() to augment an
|
||||||
|
* existing OkHttpClient.Builder with NetCipher.
|
||||||
|
*/
|
||||||
|
public class StrongOkHttpClientBuilder extends
|
||||||
|
StrongBuilderBase<StrongOkHttpClientBuilder, OkHttpClient> {
|
||||||
|
/**
|
||||||
|
* Creates a StrongOkHttpClientBuilder using the strongest set
|
||||||
|
* of options for security. Use this if the strongest set of
|
||||||
|
* options is what you want; otherwise, create a
|
||||||
|
* builder via the constructor and configure it as you see fit.
|
||||||
|
*
|
||||||
|
* @param context any Context will do
|
||||||
|
* @return a configured StrongOkHttpClientBuilder
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
static public StrongOkHttpClientBuilder forMaxSecurity(Context context)
|
||||||
|
throws Exception {
|
||||||
|
return(new StrongOkHttpClientBuilder(context)
|
||||||
|
.withBestProxy());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a builder instance.
|
||||||
|
*
|
||||||
|
* @param context any Context will do; builder will hold onto
|
||||||
|
* Application context
|
||||||
|
*/
|
||||||
|
public StrongOkHttpClientBuilder(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor.
|
||||||
|
*
|
||||||
|
* @param original builder to clone
|
||||||
|
*/
|
||||||
|
public StrongOkHttpClientBuilder(StrongOkHttpClientBuilder original) {
|
||||||
|
super(original);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OkHttp3 does not support SOCKS proxies:
|
||||||
|
* https://github.com/square/okhttp/issues/2315
|
||||||
|
*
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean supportsSocksProxy() {
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public OkHttpClient build(Intent status) {
|
||||||
|
return(applyTo(new OkHttpClient.Builder(), status).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds NetCipher configuration to an existing OkHttpClient.Builder,
|
||||||
|
* in case you have additional configuration that you wish to
|
||||||
|
* perform.
|
||||||
|
*
|
||||||
|
* @param builder a new or partially-configured OkHttpClient.Builder
|
||||||
|
* @return the same builder
|
||||||
|
*/
|
||||||
|
public OkHttpClient.Builder applyTo(OkHttpClient.Builder builder, Intent status) {
|
||||||
|
SSLSocketFactory factory=buildSocketFactory();
|
||||||
|
|
||||||
|
if (factory!=null) {
|
||||||
|
builder.sslSocketFactory(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(builder
|
||||||
|
.proxy(buildProxy(status)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String get(Intent status, OkHttpClient connection,
|
||||||
|
String url) throws Exception {
|
||||||
|
Request request=new Request.Builder().url(url).build();
|
||||||
|
|
||||||
|
return(connection.newCall(request).execute().body().string());
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:color="?attr/colorSecondary" android:state_enabled="true"/>
|
<item android:color="?attr/colorPrimary" android:state_enabled="true"/>
|
||||||
<item android:color="?attr/colorOnBackground"/>
|
<item android:color="?attr/colorPrimaryVariant"/>
|
||||||
</selector>
|
</selector>
|
||||||
|
9
app/src/main/res/drawable/ic_info_outline_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_info_outline_black_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#2D1A2E"
|
||||||
|
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_network_clearnet.xml
Normal file
9
app/src/main/res/drawable/ic_network_clearnet.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="100"
|
||||||
|
android:viewportHeight="100">
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/btn_color_selector"
|
||||||
|
android:pathData="M50,8.33A41.67,41.67 0,1 0,91.67 50,41.65 41.65,0 0,0 50,8.33ZM78.87,33.33L66.54,33.33A65.26,65.26 0,0 0,60.79 18.5,33.48 33.48,0 0,1 78.83,33.33ZM50,16.83a58.59,58.59 0,0 1,8 16.5L42,33.33A58.72,58.72 0,0 1,50 16.83ZM17.75,58.33a32.66,32.66 0,0 1,0 -16.66L31.83,41.67A69.49,69.49 0,0 0,31.25 50a69.49,69.49 0,0 0,0.58 8.33ZM21.17,66.67L33.46,66.67A64.9,64.9 0,0 0,39.21 81.5,33.26 33.26,0 0,1 21.17,66.67ZM33.46,33.33L21.17,33.33a33.26,33.26 0,0 1,18 -14.83A65.26,65.26 0,0 0,33.46 33.33ZM50,83.17a58.72,58.72 0,0 1,-8 -16.5L58,66.67A58.72,58.72 0,0 1,50 83.17ZM59.75,58.33L40.25,58.33A60.51,60.51 0,0 1,39.58 50a59.88,59.88 0,0 1,0.67 -8.33h19.5A59.88,59.88 0,0 1,60.42 50,60.51 60.51,0 0,1 59.75,58.33ZM60.75,81.5a65.08,65.08 0,0 0,5.75 -14.83L78.83,66.67A33.44,33.44 0,0 1,60.79 81.5ZM68.13,58.33A69.49,69.49 0,0 0,68.75 50a69.49,69.49 0,0 0,-0.58 -8.33L82.25,41.67a32.66,32.66 0,0 1,0 16.66Z" />
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_network_tor_on.xml
Normal file
10
app/src/main/res/drawable/ic_network_tor_on.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="100"
|
||||||
|
android:viewportHeight="100">
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/btn_color_selector"
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:pathData="M50.08,84.36L50.08,79.27a29.27,29.27 0,0 0,0 -58.54L50.08,15.64a34.36,34.36 0,0 1,0 68.72ZM50.08,66.54a16.55,16.55 0,0 0,0 -33.09L50.08,28.36a21.64,21.64 0,0 1,0 43.27ZM50.08,41.09a8.91,8.91 0,0 1,0 17.82ZM8,50A42,42 0,1 0,50 8,42 42,0 0,0 8,50Z" />
|
||||||
|
</vector>
|
@ -7,16 +7,6 @@
|
|||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingEnd="16dp">
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:src="@mipmap/ic_launcher" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvHelp"
|
android:id="@+id/tvHelp"
|
||||||
style="@style/MoneroText"
|
style="@style/MoneroText"
|
||||||
@ -27,6 +17,4 @@
|
|||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
tools:text="@string/menu_help" />
|
tools:text="@string/menu_help" />
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -29,28 +29,49 @@
|
|||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginBottom="8dp">
|
android:layout_marginBottom="8dp">
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:id="@+id/pbNetwork"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_alignStart="@id/ibNetwork"
|
||||||
|
android:layout_alignTop="@+id/ibNetwork"
|
||||||
|
android:layout_alignEnd="@id/ibNetwork"
|
||||||
|
android:layout_alignBottom="@id/ibNetwork"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:progress="100"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:indicatorInset="9dp"
|
||||||
|
app:indicatorSize="30dp"
|
||||||
|
app:trackThickness="2dp" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/ibNetwork"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:src="@drawable/ic_network_clearnet" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignTop="@+id/ibNetwork"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_alignBottom="@id/ibNetwork"
|
||||||
android:layout_toStartOf="@+id/ibRenew">
|
android:layout_toStartOf="@+id/ibRenew"
|
||||||
|
android:layout_toEndOf="@+id/ibNetwork">
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/pbNode"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:visibility="invisible" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/llNode"
|
android:id="@+id/llNode"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:gravity="start|center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -58,17 +79,14 @@
|
|||||||
style="@style/MoneroText.PosAmount"
|
style="@style/MoneroText.PosAmount"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:drawablePadding="8dp"
|
|
||||||
app:drawableStartCompat="@drawable/ic_refresh_black_24dp"
|
|
||||||
tools:text="monero-v9.monerujo.io" />
|
tools:text="monero-v9.monerujo.io" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvNodeAddress"
|
android:id="@+id/tvInfo"
|
||||||
style="@style/MoneroText.Small"
|
style="@style/MoneroText.Small"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="32dp"
|
tools:text="Last Block: 2 minutes ago" />
|
||||||
tools:text="128.130.233.151:18089" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
@ -111,8 +111,9 @@
|
|||||||
android:text="@string/label_receive_info_gen_qr_code"
|
android:text="@string/label_receive_info_gen_qr_code"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:visibility="gone"
|
android:textColor="#2D1A2E"
|
||||||
card_view:drawableStartCompat="@drawable/ic_info_outline_gray_24dp" />
|
android:visibility="visible"
|
||||||
|
card_view:drawableStartCompat="@drawable/ic_info_outline_black_24dp" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/qrCode"
|
android:id="@+id/qrCode"
|
||||||
|
@ -126,23 +126,38 @@
|
|||||||
android:src="@drawable/ic_xmrto_doge_off" />
|
android:src="@drawable/ic_xmrto_doge_off" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<FrameLayout
|
||||||
android:id="@+id/tvXmrTo"
|
|
||||||
style="@style/MoneroText.Info"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvXmrTo"
|
||||||
|
style="@style/MoneroText.Info"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
android:gravity="start"
|
android:gravity="start|center_vertical"
|
||||||
android:singleLine="false"
|
android:singleLine="false"
|
||||||
android:text="@string/label_send_btc_xmrto_key"
|
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
app:drawableStartCompat="@drawable/gunther_24dp"
|
app:drawableStartCompat="@drawable/gunther_24dp"
|
||||||
tools:text="@string/info_xmrto" />
|
tools:text="@string/info_xmrto" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTor"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:drawablePadding="8dp"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:text="@string/tor_noshift"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:drawableStartCompat="@drawable/gunther_24dp" />
|
||||||
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
tools:text="monero-v9.monerujo.io" />
|
tools:text="monero-v9.monerujo.io" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvAddress"
|
android:id="@+id/tvInfo"
|
||||||
style="@style/MoneroText.Small"
|
style="@style/MoneroText.Small"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -73,12 +73,12 @@
|
|||||||
tools:text="+ 999.999999" />
|
tools:text="+ 999.999999" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tx_fee"
|
android:id="@+id/tx_failed"
|
||||||
style="@style/MoneroText.PosFee"
|
style="@style/MoneroText.PosFee"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
tools:text="Fee 0.06817" />
|
android:text="@string/tx_list_failed_text" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
<h1>Crear Portamonedes - New</h1>
|
<h1>Crear Portamonedes - New</h1>
|
||||||
<p>Per si necessiteu una nova adreça de Monero!</p>
|
<p>Per si necessiteu una nova adreça de Monero!</p>
|
||||||
<p>Introduïu un nom i contrasenya únics del portamonedes.
|
<p>Introduïu un nom i contrasenya únics del portamonedes.
|
||||||
La contrasenya s’utilitza per protegir les dades del seu portamonedes en el dispositiu. Utilitzeu una contrasenya sòlida - encara millor si utiliza una frase.</p>
|
La contrasenya s’utilitza per protegir les dades del seu portamonedes en el dispositiu. Utilitzeu una contrasenya sòlida - encara millor si utiliza una frase.</p>
|
||||||
<h2>Apunteu la vostra llavor mnemotècnica!</h2>
|
<h2>Apunteu la vostra llavor mnemotècnica!</h2>
|
||||||
<p>A la pantalla següent trobareu la vostra "Llavor Mnemotècnica" de 25 paraules.
|
<p>A la pantalla següent trobareu la vostra "Llavor Mnemotècnica" de 25 paraules.
|
||||||
Aquestes són les úniques dades necessàries per a recuperar el vostre portamonedes i obtenir accés total als vostres fons.
|
Aquestes són les úniques dades necessàries per a recuperar el vostre portamonedes i obtenir accés total als vostres fons.
|
||||||
Mantenir-la segura i privada és molt important ja que permet que <em> qualsevol persona</em> tingui accés total als vostres fons!.</p>
|
Mantenir-la segura i privada és molt important ja que permet que <em> qualsevol persona</em> tingui accés total als vostres fons!.</p>
|
||||||
<p>Si perdeu la contrasenya del portamonedes encara podrieu recuperar-lo amb la llavor Mnemotècnica.</p>
|
<p>Si perdeu la contrasenya del portamonedes encara podrieu recuperar-lo amb la llavor Mnemotècnica.</p>
|
||||||
<p>La llavor Mnemotècnica tampoc no es pot canviar mai, i si és robada o compromesa d’alguna manera haureu de traslladar els vostres fons a un nou portamonedes (amb una nova llavor mnemotècnica). Per tant, es recomana que feu còpies de seguretat de la vostra llavor mnemotècnica escrivint-la i emmagatzemant-la a <em> múltiple </em> llocs de forma segura.</p>
|
<p>La llavor Mnemotècnica tampoc no es pot canviar mai, i si és robada o compromesa d’alguna manera haureu de traslladar els vostres fons a un nou portamonedes (amb una nova llavor mnemotècnica). Per tant, es recomana que feu còpies de seguretat de la vostra llavor mnemotècnica escrivint-la i emmagatzemant-la a <em> múltiple </em> llocs de forma segura.</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
@ -17,7 +17,7 @@
|
|||||||
<h1>Crear Portamonedes - Llavor</h1>
|
<h1>Crear Portamonedes - Llavor</h1>
|
||||||
<p>Si ja teniu una adreça Monero i voleu recuperar les transaccions de la blockchain!</p>
|
<p>Si ja teniu una adreça Monero i voleu recuperar les transaccions de la blockchain!</p>
|
||||||
<p>Introduïu un nom i contrasenya únics del portamonedes.
|
<p>Introduïu un nom i contrasenya únics del portamonedes.
|
||||||
La contrasenya s’utilitza per protegir les dades del seu portamonedes en el dispositiu. Utilitzeu una contrasenya sòlida - encara millor si utiliza una frase.</p>
|
La contrasenya s’utilitza per protegir les dades del seu portamonedes en el dispositiu. Utilitzeu una contrasenya sòlida - encara millor si utiliza una frase.</p>
|
||||||
<p>Introduïu la Llavor en el camp \"Llavor Mnemotècnica\".<p>
|
<p>Introduïu la Llavor en el camp \"Llavor Mnemotècnica\".<p>
|
||||||
<p>Introduïu el número de bloc de la primera transacció realitzada en aquesta adreça en el camp "Restaurar Alçada". També podeu utilitzar una data en el format AAAA-MM-DD. Si no esteu segurs, introduïu una data / alçada de bloc aproximada <em> abans </em> d’haver fer servir aquesta adreça del portamonedes.</p>
|
<p>Introduïu el número de bloc de la primera transacció realitzada en aquesta adreça en el camp "Restaurar Alçada". També podeu utilitzar una data en el format AAAA-MM-DD. Si no esteu segurs, introduïu una data / alçada de bloc aproximada <em> abans </em> d’haver fer servir aquesta adreça del portamonedes.</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<p>Introduïu un nom i contrasenya únics del portamonedes. La contrasenya s’utilitza per protegir les dades de la seva cartera al dispositiu. Utilitzeu una contrasenya sòlida - encara millor si utiliza una frase.<p>
|
<p>Introduïu un nom i contrasenya únics del portamonedes. La contrasenya s’utilitza per protegir les dades de la seva cartera al dispositiu. Utilitzeu una contrasenya sòlida - encara millor si utiliza una frase.<p>
|
||||||
<p>Introduïu la vostra Adreça Monero en el camp \"Adreça Pública\" i ompliu \"Clau de Visualització\" i \"Clau de Despesa\" </p>
|
<p>Introduïu la vostra Adreça Monero en el camp \"Adreça Pública\" i ompliu \"Clau de Visualització\" i \"Clau de Despesa\" </p>
|
||||||
<p>Introduïu el número de bloc de la primera transacció realitzada en aquesta adreça en el
|
<p>Introduïu el número de bloc de la primera transacció realitzada en aquesta adreça en el
|
||||||
camp "Restaurar Alçada". També podeu utilitzar una data en el format AAAA-MM-DD. Si no esteu segurs, introduïu una data / alçada de bloc aproximada <em> abans </em> d’haver fer servir aquesta adreça del portamonedes.</p>
|
camp "Restaurar Alçada". També podeu utilitzar una data en el format AAAA-MM-DD. Si no esteu segurs, introduïu una data / alçada de bloc aproximada <em> abans </em> d’haver fer servir aquesta adreça del portamonedes.</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_create_view"><![CDATA[
|
<string name="help_create_view"><![CDATA[
|
||||||
@ -53,18 +53,18 @@
|
|||||||
La vostra adreça pública és com el vostre número de compte bancari que podeu compartir amb qualsevol persona sense haver de tenir por de perdre el vostres Monero. La gent enviarà Monero al seu portamonedes mitjançant aquesta adreça.
|
La vostra adreça pública és com el vostre número de compte bancari que podeu compartir amb qualsevol persona sense haver de tenir por de perdre el vostres Monero. La gent enviarà Monero al seu portamonedes mitjançant aquesta adreça.
|
||||||
<h2>Clau Mnemotècnica</h2>
|
<h2>Clau Mnemotècnica</h2>
|
||||||
Aquestes són les úniques dades necessàries per a recuperar el vostre portamonedes i obtenir accés total als vostres fons.
|
Aquestes són les úniques dades necessàries per a recuperar el vostre portamonedes i obtenir accés total als vostres fons.
|
||||||
Mantenir-la segura i privada és molt important ja que permet que <em> qualsevol persona</em> tingui accés total als vostres fons! Si no us heu escrit en cap lloc segur, feu-ho!
|
Mantenir-la segura i privada és molt important ja que permet que <em> qualsevol persona</em> tingui accés total als vostres fons! Si no us heu escrit en cap lloc segur, feu-ho!
|
||||||
<h2>Contrasenya de Recuperació d’Arxius del Portamonedes</h2>
|
<h2>Contrasenya de Recuperació d’Arxius del Portamonedes</h2>
|
||||||
Assegureu-vos que heu escrit aquesta contrasenya. Si restabliu el dispositiu o desinstal·leu l’aplicació, la necessitarà per tornar a accedir al seu portamonedes.<br/>
|
Assegureu-vos que heu escrit aquesta contrasenya. Si restabliu el dispositiu o desinstal·leu l’aplicació, la necessitarà per tornar a accedir al seu portamonedes.<br/>
|
||||||
<h3>CrAzYsenya</h3>
|
<h3>CrAzYsenya</h3>
|
||||||
Si la contrasenya que es mostra aquí és de 52 caràcters alfanumèrics en grups de 4 - felicitats!
|
Si la contrasenya que es mostra aquí és de 52 caràcters alfanumèrics en grups de 4 - felicitats!
|
||||||
Els fitxers del portamonedes estan protegits amb una clau de 256 bits generada per la funció de seguretat del vostre dispositiu basades en la contrasenya que heu triat (durant la creació o al canviar-la). Això ho fa extremadament difícil de piratejar!<br/>
|
Els fitxers del portamonedes estan protegits amb una clau de 256 bits generada per la funció de seguretat del vostre dispositiu basades en la contrasenya que heu triat (durant la creació o al canviar-la). Això ho fa extremadament difícil de piratejar!<br/>
|
||||||
Aquesta opció és obligatoria per a tots els nous portamonedes.
|
Aquesta opció és obligatoria per a tots els nous portamonedes.
|
||||||
<h3>Contrasenya de Llegat</h3>
|
<h3>Contrasenya de Llegat</h3>
|
||||||
Si veieu la vostra contrasenya aquí, els fitxers del portamonedes no estan tan segurs com quan s’utilitza la CrAzYsenya. Per solucionar-ho, seleccioneu \"Canviar Contrasenya\" des del menú. Després d’entrar una nova contrasenya (potser fins i tot la mateixa que abans) l’aplicació generarà una CrAzYsenya per a protegir els vostres arxius del portamonedes. Anoteu-la!
|
Si veieu la vostra contrasenya aquí, els fitxers del portamonedes no estan tan segurs com quan s’utilitza la CrAzYsenya. Per solucionar-ho, seleccioneu \"Canviar Contrasenya\" des del menú. Després d’entrar una nova contrasenya (potser fins i tot la mateixa que abans) l’aplicació generarà una CrAzYsenya per a protegir els vostres arxius del portamonedes. Anoteu-la!
|
||||||
<h3>CrAzYsenya del Portamonedes</h3>
|
<h3>CrAzYsenya del Portamonedes</h3>
|
||||||
Si mai necessiteu tornar a instal·lar Monerujo (per exemple, després de restablir el telèfon o canviar-lo per un de nou) o voleu utilitzar els arxius del portamonedes en un altre dispositiu o PC, cal que ho feu utilitzant aquesta Contrasenya de Recuperació (CrAzYsenya) per tornar a accedir al vostre portamonedes. <br/>
|
Si mai necessiteu tornar a instal·lar Monerujo (per exemple, després de restablir el telèfon o canviar-lo per un de nou) o voleu utilitzar els arxius del portamonedes en un altre dispositiu o PC, cal que ho feu utilitzant aquesta Contrasenya de Recuperació (CrAzYsenya) per tornar a accedir al vostre portamonedes. <br/>
|
||||||
En seleccionar \"Canviar Contrasenya\" des del menú, podeu triar una nova contrasenya. Aneu amb compte que això generarà una nova Contrasenya de Recuperació (CrAzYsenya). Anoteu-la!
|
En seleccionar \"Canviar Contrasenya\" des del menú, podeu triar una nova contrasenya. Aneu amb compte que això generarà una nova Contrasenya de Recuperació (CrAzYsenya). Anoteu-la!
|
||||||
<h2>Clau de Visualització</h2>
|
<h2>Clau de Visualització</h2>
|
||||||
La vostra clau de visualització es pot utilitzar per monitoritzar les transaccions entrants al vostre portamonedes sense donar-ne permís per gastar els fons a dins seu.
|
La vostra clau de visualització es pot utilitzar per monitoritzar les transaccions entrants al vostre portamonedes sense donar-ne permís per gastar els fons a dins seu.
|
||||||
<h2>Clau de Despesa</h2>
|
<h2>Clau de Despesa</h2>
|
||||||
@ -75,13 +75,13 @@
|
|||||||
<h1>Llista de Portamonedes</h1>
|
<h1>Llista de Portamonedes</h1>
|
||||||
<h2>Node</h2>
|
<h2>Node</h2>
|
||||||
<p>Monerujo utilitza un node remot per comunicar-se amb la xarxa Monero sense necessitat
|
<p>Monerujo utilitza un node remot per comunicar-se amb la xarxa Monero sense necessitat
|
||||||
de descarregar i emmagatzemar una còpia de tota la blockchain sencera. Podeu trobar una llista dels nodes remots més populars o aprendre a configurar el vostre propi node remot aquí https://moneroworld.com/<p>
|
de descarregar i emmagatzemar una còpia de tota la blockchain sencera. Podeu trobar una llista dels nodes remots més populars o aprendre a configurar el vostre propi node remot aquí https://moneroworld.com/<p>
|
||||||
<p>Monerujo té alguns Nodes remots incorporats. Se’n recorda dels últims cinc nodes empleats.</p>
|
<p>Monerujo té alguns Nodes remots incorporats. Se’n recorda dels últims cinc nodes empleats.</p>
|
||||||
<h2>Portamonedes</h2>
|
<h2>Portamonedes</h2>
|
||||||
<p>Aquí podeu veure els portamonedes. Es troben a la carpeta <tt> monerujo </tt>
|
<p>Aquí podeu veure els portamonedes. Es troben a la carpeta <tt> monerujo </tt>
|
||||||
dins l’emmagatzematge intern del dispositiu. Podeu utilitzar una aplicació d’exploració d’arxius per veure’ls. Haurieu de fer còpies de seguretat d’aquesta carpeta de manera regular en un emmagatzematge extern al dispositiu en cas que el vostre dispositiu exploti o el robin.</p>
|
dins l’emmagatzematge intern del dispositiu. Podeu utilitzar una aplicació d’exploració d’arxius per veure’ls. Haurieu de fer còpies de seguretat d’aquesta carpeta de manera regular en un emmagatzematge extern al dispositiu en cas que el vostre dispositiu exploti o el robin.</p>
|
||||||
<p>Seleccioneu una portamonedes per obrir-lo o premeu el botó "+" per crear-ne un de nou.
|
<p>Seleccioneu una portamonedes per obrir-lo o premeu el botó "+" per crear-ne un de nou.
|
||||||
O seleccioneu una de les operacions del portamonedes:</p>
|
O seleccioneu una de les operacions del portamonedes:</p>
|
||||||
<h3>Detalls</h3>
|
<h3>Detalls</h3>
|
||||||
<p>Mostra els detalls del portamonedes, la llavor i les seves claus.</p>
|
<p>Mostra els detalls del portamonedes, la llavor i les seves claus.</p>
|
||||||
<h3>Rebre</h3>
|
<h3>Rebre</h3>
|
||||||
@ -90,7 +90,7 @@
|
|||||||
<p>Canvia el nom del portamonedes. El canvi de nom no afecta a les còpies de seguretat.</p>
|
<p>Canvia el nom del portamonedes. El canvi de nom no afecta a les còpies de seguretat.</p>
|
||||||
<h3>Còpia de Seguretat</h3>
|
<h3>Còpia de Seguretat</h3>
|
||||||
<p>Feu una còpia del portamonedes en la carpeta <tt> backups </tt> dins del <tt> monerujo </tt>
|
<p>Feu una còpia del portamonedes en la carpeta <tt> backups </tt> dins del <tt> monerujo </tt>
|
||||||
per a sobreescriure còpies anteriors.</p>
|
per a sobreescriure còpies anteriors.</p>
|
||||||
<h3>Arxiu</h3>
|
<h3>Arxiu</h3>
|
||||||
<p>Feu una còpia de seguretat i a continuació elimineu el portamonedes. La còpia es mantindrà a la carpeta <tt> backups </tt>. Si ja no necessiteu les vostres còpies de seguretat les haureu d’eliminar amb un explorador d’arxius o una aplicació segura.</p>
|
<p>Feu una còpia de seguretat i a continuació elimineu el portamonedes. La còpia es mantindrà a la carpeta <tt> backups </tt>. Si ja no necessiteu les vostres còpies de seguretat les haureu d’eliminar amb un explorador d’arxius o una aplicació segura.</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
@ -122,14 +122,14 @@
|
|||||||
<h1>Enviant BTC</h1>
|
<h1>Enviant BTC</h1>
|
||||||
<h2>SideShift.ai</h2>
|
<h2>SideShift.ai</h2>
|
||||||
<p>SideShift.ai és un servei de tercers que fa proporciona el canvi de Monero a Bitcoin.
|
<p>SideShift.ai és un servei de tercers que fa proporciona el canvi de Monero a Bitcoin.
|
||||||
Nosaltres fem servir l’API SideShift.ai per integrar els pagaments de Bitcoin a Monerujo. Si us plau, doneu un cop d’ull a https://sideshift.ai i decidiu vosaltres mateixos si és una cosa que volgueu utilitzar. L’equip de Monerujo no està associat amb SideShift.ai i no pot oferir assistència amb el seu servei.</p>
|
Nosaltres fem servir l’API SideShift.ai per integrar els pagaments de Bitcoin a Monerujo. Si us plau, doneu un cop d’ull a https://sideshift.ai i decidiu vosaltres mateixos si és una cosa que volgueu utilitzar. L’equip de Monerujo no està associat amb SideShift.ai i no pot oferir assistència amb el seu servei.</p>
|
||||||
<h2>Tipus de Canvi SideShift.ai<h2>
|
<h2>Tipus de Canvi SideShift.ai<h2>
|
||||||
<p>A la pantalla \"Quantitat\" es mostraran els paràmetres actuals del servei SideShift.ai. Aquests
|
<p>A la pantalla \"Quantitat\" es mostraran els paràmetres actuals del servei SideShift.ai. Aquests
|
||||||
inclouen el tipus de canvi actual, així com els límits de BTC superiors i inferiors. Tingueu en compte que la tarifa no està garantida en aquell mateix moment.</p>
|
inclouen el tipus de canvi actual, així com els límits de BTC superiors i inferiors. Tingueu en compte que la tarifa no està garantida en aquell mateix moment.</p>
|
||||||
<h2>Ordre de compra SideShift.ai<h2>
|
<h2>Ordre de compra SideShift.ai<h2>
|
||||||
<p>A la pantalla \"Confirmar\", veureu l’ordre de compra SideShift.ai real. Aquesta comanda és vàlida per a
|
<p>A la pantalla \"Confirmar\", veureu l’ordre de compra SideShift.ai real. Aquesta comanda és vàlida per a
|
||||||
un temps limitat: és possible que veieu un compte enrere en el botó \"Gastar\". El tipus de canvi pot
|
un temps limitat: és possible que veieu un compte enrere en el botó \"Gastar\". El tipus de canvi pot
|
||||||
ser diferent del mostrat en pantalles anteriors.</p>
|
ser diferent del mostrat en pantalles anteriors.</p>
|
||||||
<h2>Clau Secreta SideShift.ai<h2>
|
<h2>Clau Secreta SideShift.ai<h2>
|
||||||
<p>Com que Monerujo només gestiona la part Monero de la vostra transacció, la vostra clau secreta per SideShift.ai es pot utilitzar per fer el seguiment de la part de Bitcoin de la vostra comanda a la pàgina principal de SideShift.ai.</p>
|
<p>Com que Monerujo només gestiona la part Monero de la vostra transacció, la vostra clau secreta per SideShift.ai es pot utilitzar per fer el seguiment de la part de Bitcoin de la vostra comanda a la pàgina principal de SideShift.ai.</p>
|
||||||
<h2>Compte enrere SideShift.ai!</h2>
|
<h2>Compte enrere SideShift.ai!</h2>
|
||||||
@ -140,14 +140,14 @@
|
|||||||
<h1>Enviant BTC</h1>
|
<h1>Enviant BTC</h1>
|
||||||
<h2>SideShift.ai</h2>
|
<h2>SideShift.ai</h2>
|
||||||
<p>SideShift.ai és un servei de tercers que fa proporciona el canvi de Monero a Bitcoin.
|
<p>SideShift.ai és un servei de tercers que fa proporciona el canvi de Monero a Bitcoin.
|
||||||
Nosaltres fem servir l’API SideShift.ai per integrar els pagaments de Bitcoin a Monerujo. Si us plau, doneu un cop d’ull a https://sideshift.ai i decidiu vosaltres mateixos si és una cosa que volgueu utilitzar. L’equip de Monerujo no està associat amb SideShift.ai i no pot oferir assistència amb el seu servei.</p>
|
Nosaltres fem servir l’API SideShift.ai per integrar els pagaments de Bitcoin a Monerujo. Si us plau, doneu un cop d’ull a https://sideshift.ai i decidiu vosaltres mateixos si és una cosa que volgueu utilitzar. L’equip de Monerujo no està associat amb SideShift.ai i no pot oferir assistència amb el seu servei.</p>
|
||||||
<h2>Tipus de Canvi SideShift.ai<h2>
|
<h2>Tipus de Canvi SideShift.ai<h2>
|
||||||
<p>A la pantalla \"Quantitat\" es mostraran els paràmetres actuals del servei SideShift.ai. Aquests
|
<p>A la pantalla \"Quantitat\" es mostraran els paràmetres actuals del servei SideShift.ai. Aquests
|
||||||
inclouen el tipus de canvi actual, així com els límits de BTC superiors i inferiors. Tingueu en compte que la tarifa no està garantida en aquell mateix moment.</p>
|
inclouen el tipus de canvi actual, així com els límits de BTC superiors i inferiors. Tingueu en compte que la tarifa no està garantida en aquell mateix moment.</p>
|
||||||
<h2>Ordre de compra SideShift.ai<h2>
|
<h2>Ordre de compra SideShift.ai<h2>
|
||||||
<p>A la pantalla \"Confirmar\", veureu l’ordre de compra SideShift.ai real. Aquesta comanda és vàlida per a
|
<p>A la pantalla \"Confirmar\", veureu l’ordre de compra SideShift.ai real. Aquesta comanda és vàlida per a
|
||||||
un temps limitat: és possible que veieu un compte enrere en el botó \"Gastar\". El tipus de canvi pot
|
un temps limitat: és possible que veieu un compte enrere en el botó \"Gastar\". El tipus de canvi pot
|
||||||
ser diferent del mostrat en pantalles anteriors.</p>
|
ser diferent del mostrat en pantalles anteriors.</p>
|
||||||
<h2>Clau Secreta SideShift.ai<h2>
|
<h2>Clau Secreta SideShift.ai<h2>
|
||||||
<p>Com que Monerujo només gestiona la part Monero de la vostra transacció, la vostra clau secreta per SideShift.ai es pot utilitzar per fer el seguiment de la part de Bitcoin de la vostra comanda a la pàgina principal de SideShift.ai.</p>
|
<p>Com que Monerujo només gestiona la part Monero de la vostra transacció, la vostra clau secreta per SideShift.ai es pot utilitzar per fer el seguiment de la part de Bitcoin de la vostra comanda a la pàgina principal de SideShift.ai.</p>
|
||||||
<h2>Compte enrere SideShift.ai!</h2>
|
<h2>Compte enrere SideShift.ai!</h2>
|
||||||
@ -164,7 +164,7 @@
|
|||||||
<p><b>Ajuda! El balanç del meu portamonedes ha desaparegut o consta com a no confirmat!</b><br/>
|
<p><b>Ajuda! El balanç del meu portamonedes ha desaparegut o consta com a no confirmat!</b><br/>
|
||||||
No patiu! Quan envieu fons desde el vostre portamonedes part del balanç apareixerà com a no confirmat de forma temporal.
|
No patiu! Quan envieu fons desde el vostre portamonedes part del balanç apareixerà com a no confirmat de forma temporal.
|
||||||
Això succeeix pel fet de com Monero és intercanviat a través de la blockchain i com es produeix el canvi.
|
Això succeeix pel fet de com Monero és intercanviat a través de la blockchain i com es produeix el canvi.
|
||||||
Podeu llegir més sobre el canvi a https://getmonero.org/resources/moneropedia/change.html
|
Podeu llegir més sobre el canvi a https://getmonero.org/resources/moneropedia/change.html
|
||||||
<h2>Llista de Transacció</h2>
|
<h2>Llista de Transacció</h2>
|
||||||
<p>Llistat de les transaccions del portamonedes. Els portamonedes de visualització només mostraran les transaccions entrants.</p>
|
<p>Llistat de les transaccions del portamonedes. Els portamonedes de visualització només mostraran les transaccions entrants.</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
@ -173,49 +173,49 @@
|
|||||||
<h1>Nodes</h1>
|
<h1>Nodes</h1>
|
||||||
<h2>TL;DR</h2>
|
<h2>TL;DR</h2>
|
||||||
<p>Actualitzeu la llista de nodes prement cap avall; marqueu 3–5 nodes per permetre a Monerujo
|
<p>Actualitzeu la llista de nodes prement cap avall; marqueu 3–5 nodes per permetre a Monerujo
|
||||||
triar el millor per a tu!</p>
|
triar el millor per a tu!</p>
|
||||||
<h2>Què és un Node?</h2>
|
<h2>Què és un Node?</h2>
|
||||||
<p>Monerujo utilitza un Node Remot (de vegades també anomenat daemon) per comunicar-se
|
<p>Monerujo utilitza un Node Remot (de vegades també anomenat daemon) per comunicar-se
|
||||||
la xarxa Monero sense haver de descarregar i emmagatzemar una còpia de
|
la xarxa Monero sense haver de descarregar i emmagatzemar una còpia de
|
||||||
tota la blockchain mateixa.<p>
|
tota la blockchain mateixa.<p>
|
||||||
<h2>Llista de Nodes</h2>
|
<h2>Llista de Nodes</h2>
|
||||||
<p>Si la llista està buida, podeu afegir nous nodes manualment o deixar que Monerujo
|
<p>Si la llista està buida, podeu afegir nous nodes manualment o deixar que Monerujo
|
||||||
escanegi la xarxa per vostè. O ambdós. Llegiu …</p>
|
escanegi la xarxa per vostè. O ambdós. Llegiu …</p>
|
||||||
<p>La llista de nodes mostra tots els nodes coneguts. A més, la marca de temps
|
<p>La llista de nodes mostra tots els nodes coneguts. A més, la marca de temps
|
||||||
de l’últim bloc conegut per a cada node es mostra sota el nom del node. La icona
|
de l’últim bloc conegut per a cada node es mostra sota el nom del node. La icona
|
||||||
que representa el temps de resposta del node
|
que representa el temps de resposta del node
|
||||||
(que indica el nivell de connectivitat estimat)
|
(que indica el nivell de connectivitat estimat)
|
||||||
es mostra al costat de cada node.</p>
|
es mostra al costat de cada node.</p>
|
||||||
<p>Es pot marcar qualsevol node de la llista per utilitzar-lo més endevant.
|
<p>Es pot marcar qualsevol node de la llista per utilitzar-lo més endevant.
|
||||||
Es descartaràn els nodes que no hagin estat seleccionats.<p>
|
Es descartaràn els nodes que no hagin estat seleccionats.<p>
|
||||||
<p>Monerujo escollirà el node òptim (marcat) cada vegada que l’utilitzeu.
|
<p>Monerujo escollirà el node òptim (marcat) cada vegada que l’utilitzeu.
|
||||||
Això ho fa mitjançant la comprovació de l’alçada de bloc (com d’actualitzat
|
Això ho fa mitjançant la comprovació de l’alçada de bloc (com d’actualitzat
|
||||||
està el node?), així com el temps de resposta (què tan ràpidament respon el node a les peticions?).</p>
|
està el node?), així com el temps de resposta (què tan ràpidament respon el node a les peticions?).</p>
|
||||||
<p>La llista s’ordena per aquestes característiques, de manera que el node superior seria el que Monerujo
|
<p>La llista s’ordena per aquestes característiques, de manera que el node superior seria el que Monerujo
|
||||||
triaria ara mateix. La part inferior de la llista mostraria els nodes més lents o no disponibles.</p>
|
triaria ara mateix. La part inferior de la llista mostraria els nodes més lents o no disponibles.</p>
|
||||||
<h2>Afegir Node</h2>
|
<h2>Afegir Node</h2>
|
||||||
<p>Si premeu el botó "Afegir Node" a la part inferior, se us demanarà
|
<p>Si premeu el botó "Afegir Node" a la part inferior, se us demanarà
|
||||||
que introduïu els detalls del node al següent diàleg.
|
que introduïu els detalls del node al següent diàleg.
|
||||||
El "Adreça" és el nom del servidor o adreça IP del node - aquesta és la única
|
El "Adreça" és el nom del servidor o adreça IP del node - aquesta és la única
|
||||||
entrada obligatòria.
|
entrada obligatòria.
|
||||||
Introduïu el "Port" si el node s’executa en un port no predeterminat (per exemple, 18089).
|
Introduïu el "Port" si el node s’executa en un port no predeterminat (per exemple, 18089).
|
||||||
També podeu anomenar opcionalment el node, de manera que el pugueu identificar més fàcilment més endavant.
|
També podeu anomenar opcionalment el node, de manera que el pugueu identificar més fàcilment més endavant.
|
||||||
Alguns nodes necessiten credencials per utilitzar-los. Introduïu el nom d’usuari i
|
Alguns nodes necessiten credencials per utilitzar-los. Introduïu el nom d’usuari i
|
||||||
contrasenya proporcionats als camps corresponents. Ara podeu "Test" aquesta configuració.
|
contrasenya proporcionats als camps corresponents. Ara podeu "Test" aquesta configuració.
|
||||||
Els "Resultats de les Proves" mostraran l’alçada de bloc, el temps de resposta i l’IP real.
|
Els "Resultats de les Proves" mostraran l’alçada de bloc, el temps de resposta i l’IP real.
|
||||||
El resultat també pot ser un error - generalment perquè el nom del servidor proporcionat no és
|
El resultat també pot ser un error - generalment perquè el nom del servidor proporcionat no és
|
||||||
accessible dins d’un temps raonable o les credencials són incorrectes.
|
accessible dins d’un temps raonable o les credencials són incorrectes.
|
||||||
O la combinació de nom del servidor/port no apunta cap a un node real de Monero!
|
O la combinació de nom del servidor/port no apunta cap a un node real de Monero!
|
||||||
Un cop aprovada la prova (sense error), ja estás llest per prémer "D’acord" per desar iamp;
|
Un cop aprovada la prova (sense error), ja estás llest per prémer "D’acord" per desar iamp;
|
||||||
marcar aquest node.</p>
|
marcar aquest node.</p>
|
||||||
<h2>Escanejar Nodes</h2>
|
<h2>Escanejar Nodes</h2>
|
||||||
<p>A més, podeu escanejar la xarxa per buscar nodes. Monerujo començarà
|
<p>A més, podeu escanejar la xarxa per buscar nodes. Monerujo començarà
|
||||||
escanejant la xarxa per als nodes remots al port 18089. Començarà per preguntar als vostres
|
escanejant la xarxa per als nodes remots al port 18089. Començarà per preguntar als vostres
|
||||||
nodes marcats per altres companys de la xarxa P2P de Monero, i després continuarà
|
nodes marcats per altres companys de la xarxa P2P de Monero, i després continuarà
|
||||||
preguntant-los per als seus companys, etc. Si no teniu cap node marcat
|
preguntant-los per als seus companys, etc. Si no teniu cap node marcat
|
||||||
(o no ens informen sobre els seus companys),
|
(o no ens informen sobre els seus companys),
|
||||||
Monerujo anirà directament als nodes de llavor de Monero codificats a dins de Monero.
|
Monerujo anirà directament als nodes de llavor de Monero codificats a dins de Monero.
|
||||||
L’escaneig s’atura quan troba un total de 10 nodes remots.</p>
|
L’escaneig s’atura quan troba un total de 10 nodes remots.</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_uri"><![CDATA[
|
<string name="help_uri"><![CDATA[
|
||||||
@ -230,4 +230,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Ja ho tinc!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Ja ho tinc!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<string name="menu_changepw">Canvi de contrasenya</string>
|
<string name="menu_changepw">Canvi de contrasenya</string>
|
||||||
|
|
||||||
<string name="password_weak">Segueix escrivint …</string>
|
<string name="password_weak">Segueix escrivint …</string>
|
||||||
<string name="password_fair">Més o menys... …</string>
|
<string name="password_fair">Més o menys…</string>
|
||||||
<string name="password_good">Vinga, ho pots fer millor!</string>
|
<string name="password_good">Vinga, ho pots fer millor!</string>
|
||||||
<string name="password_strong">Força bé, pero millorbale …</string>
|
<string name="password_strong">Força bé, pero millorbale …</string>
|
||||||
<string name="password_very_strong">Genial, ets tot un hacker!</string>
|
<string name="password_very_strong">Genial, ets tot un hacker!</string>
|
||||||
@ -236,7 +236,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Error creant la transacció</string>
|
<string name="send_create_tx_error_title">Error creant la transacció</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Comissió %1$s</string>
|
<string name="tx_list_fee">Comissió %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">fallit</string>
|
<string name="tx_list_failed_text">fallit</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -425,5 +425,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -290,4 +290,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Hab\'s verstanden!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Hab\'s verstanden!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -232,7 +232,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Fehler bei Transaktionserstellung</string>
|
<string name="send_create_tx_error_title">Fehler bei Transaktionserstellung</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Gebühr %1$s</string>
|
<string name="tx_list_fee">Gebühr %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">fehlgeschlagen</string>
|
<string name="tx_list_failed_text">fehlgeschlagen</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -426,5 +426,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -272,4 +272,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -205,7 +205,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Σφάλμα Δημιουργίας Συναλλαγής</string>
|
<string name="send_create_tx_error_title">Σφάλμα Δημιουργίας Συναλλαγής</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Κόμιστρο %1$s</string>
|
<string name="tx_list_fee">Κόμιστρο %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">απέτυχε</string>
|
<string name="tx_list_failed_text">απέτυχε</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -427,5 +427,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -316,4 +316,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -236,7 +236,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Krei transakci-eraron</string>
|
<string name="send_create_tx_error_title">Krei transakci-eraron</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Kosto %1$s</string>
|
<string name="tx_list_fee">Kosto %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">masukcesis</string>
|
<string name="tx_list_failed_text">masukcesis</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -427,5 +427,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -312,4 +312,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">¡Entendido!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">¡Entendido!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -173,7 +173,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Error creando la transacción</string>
|
<string name="send_create_tx_error_title">Error creando la transacción</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Comisión %1$s</string>
|
<string name="tx_list_fee">Comisión %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">fallido</string>
|
<string name="tx_list_failed_text">fallido</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -418,5 +418,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -292,4 +292,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -231,7 +231,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Viga ülekande genereerimisel</string>
|
<string name="send_create_tx_error_title">Viga ülekande genereerimisel</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- teenustasu %1$s</string>
|
<string name="tx_list_fee">teenustasu %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">ebaõnnestus</string>
|
<string name="tx_list_failed_text">ebaõnnestus</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -425,5 +425,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -310,4 +310,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -233,7 +233,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Erreur de Création de Transaction</string>
|
<string name="send_create_tx_error_title">Erreur de Création de Transaction</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Frais %1$s</string>
|
<string name="tx_list_fee">Frais %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">Echoué</string>
|
<string name="tx_list_failed_text">Echoué</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -431,5 +431,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -294,4 +294,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -230,7 +230,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Tranzakciólétrehozási hiba</string>
|
<string name="send_create_tx_error_title">Tranzakciólétrehozási hiba</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- %1$s díj</string>
|
<string name="tx_list_fee">%1$s díj</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">sikertelen</string>
|
<string name="tx_list_failed_text">sikertelen</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -429,5 +429,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -295,4 +295,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -232,7 +232,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Errore nella creazione della transazione</string>
|
<string name="send_create_tx_error_title">Errore nella creazione della transazione</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Commissione %1$s</string>
|
<string name="tx_list_fee">Commissione %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">fallita</string>
|
<string name="tx_list_failed_text">fallita</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -431,4 +431,9 @@
|
|||||||
|
|
||||||
<string name="menu_deletecache">Resetta portafogli!</string>
|
<string name="menu_deletecache">Resetta portafogli!</string>
|
||||||
<string name="deletecache_alert_message">Il reset del portafogli cancellerà tutte le informazioni locali (note, nomi di account & sottoindirizzi, chiavi di transazione private, ...)! Procedi solo se il portafogli è corrotto e non si carica!</string>
|
<string name="deletecache_alert_message">Il reset del portafogli cancellerà tutte le informazioni locali (note, nomi di account & sottoindirizzi, chiavi di transazione private, ...)! Procedi solo se il portafogli è corrotto e non si carica!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -423,4 +423,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">分かりました!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">分かりました!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -236,7 +236,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">取引作成エラー</string>
|
<string name="send_create_tx_error_title">取引作成エラー</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- 手数料 %1$s</string>
|
<string name="tx_list_fee">手数料 %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">失敗</string>
|
<string name="tx_list_failed_text">失敗</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -430,5 +430,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -292,4 +292,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -230,7 +230,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Error med å lage transaksjon</string>
|
<string name="send_create_tx_error_title">Error med å lage transaksjon</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Avgift %1$s</string>
|
<string name="tx_list_fee">Avgift %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">feila</string>
|
<string name="tx_list_failed_text">feila</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -427,5 +427,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
|
|
||||||
<style name="AppCard" parent="Widget.MaterialComponents.CardView">
|
<style name="AppCard" parent="Widget.MaterialComponents.CardView">
|
||||||
<item name="cardElevation">0dp</item>
|
<item name="cardElevation">0dp</item>
|
||||||
<item name="cardCornerRadius">1dp</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -230,4 +230,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -227,7 +227,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Fout bij transactie maken</string>
|
<string name="send_create_tx_error_title">Fout bij transactie maken</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- kosten %1$s</string>
|
<string name="tx_list_fee">kosten %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">mislukt</string>
|
<string name="tx_list_failed_text">mislukt</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -427,5 +427,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -291,4 +291,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Entendi!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Entendi!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -229,7 +229,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Erro ao criar a transação</string>
|
<string name="send_create_tx_error_title">Erro ao criar a transação</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- taxa de %1$s</string>
|
<string name="tx_list_fee">taxa de %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">falhou</string>
|
<string name="tx_list_failed_text">falhou</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -421,4 +421,9 @@ aqui.</string>
|
|||||||
|
|
||||||
<string name="menu_deletecache">Resetar carteira!</string>
|
<string name="menu_deletecache">Resetar carteira!</string>
|
||||||
<string name="deletecache_alert_message">Esta carteira será resetada, perdendo todos os dados "off-chain" (como notas, contas & nomes de subendereços, chaves de transações privadas, ...)! Use isso SOMENTE se esta carteira estiver corrompida e não carrega!</string>
|
<string name="deletecache_alert_message">Esta carteira será resetada, perdendo todos os dados "off-chain" (como notas, contas & nomes de subendereços, chaves de transações privadas, ...)! Use isso SOMENTE se esta carteira estiver corrompida e não carrega!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -291,4 +291,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Entendido!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Entendido!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -229,7 +229,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Erro ao criar a transacção</string>
|
<string name="send_create_tx_error_title">Erro ao criar a transacção</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Taxa %1$s</string>
|
<string name="tx_list_fee">Taxa %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">falhou</string>
|
<string name="tx_list_failed_text">falhou</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -431,5 +431,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -298,4 +298,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Am înțeles!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Am înțeles!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -205,7 +205,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Eroare creare tranzacție</string>
|
<string name="send_create_tx_error_title">Eroare creare tranzacție</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Comision %1$s</string>
|
<string name="tx_list_fee">Comision %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">eșuat</string>
|
<string name="tx_list_failed_text">eșuat</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -427,5 +427,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -297,4 +297,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Я понял!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Я понял!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -231,7 +231,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Ошибка создания транзакции</string>
|
<string name="send_create_tx_error_title">Ошибка создания транзакции</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Комиссия %1$s</string>
|
<string name="tx_list_fee">Комиссия %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">Не удалось</string>
|
<string name="tx_list_failed_text">Не удалось</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -431,5 +431,10 @@
|
|||||||
<string name="restore_failed">Ошибка импорта!</string>
|
<string name="restore_failed">Ошибка импорта!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Сбросить кошелек</string>
|
<string name="menu_deletecache">Сбросить кошелек</string>
|
||||||
<string name="deletecache_alert_message">Этот кошелек будет сброшен, вы потеряете все данные, которые не находятся в блокчейне (например примечания, имена подадресов, приватные ключи транзакций, ...)! Используйте это ТОЛЬКО если ваш кошелек поврежден и не загружается!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -259,4 +259,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Rozumiem!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Rozumiem!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -228,7 +228,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Vytvor Chybu Transakcie</string>
|
<string name="send_create_tx_error_title">Vytvor Chybu Transakcie</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- poplatok %1$s</string>
|
<string name="tx_list_fee">poplatok %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">zlyhala</string>
|
<string name="tx_list_failed_text">zlyhala</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -428,5 +428,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -290,4 +290,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -237,7 +237,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Kreiraj transakcijsku grešku</string>
|
<string name="send_create_tx_error_title">Kreiraj transakcijsku grešku</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- naknada %1$s</string>
|
<string name="tx_list_fee">naknada %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">neuspelo</string>
|
<string name="tx_list_failed_text">neuspelo</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -426,5 +426,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -279,4 +279,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -218,7 +218,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Ett fel uppstod när transaktion skapades</string>
|
<string name="send_create_tx_error_title">Ett fel uppstod när transaktion skapades</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Avgift %1$s</string>
|
<string name="tx_list_fee">Avgift %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">misslyckades</string>
|
<string name="tx_list_failed_text">misslyckades</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -419,5 +419,10 @@
|
|||||||
<string name="restore_failed">Importeringen misslyckad!</string>
|
<string name="restore_failed">Importeringen misslyckad!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Återställ plånbok!</string>
|
<string name="menu_deletecache">Återställ plånbok!</string>
|
||||||
<string name="deletecache_alert_message">Denna plånbok kommer att återställas och förlorar all off-chain data (som anteckningar, konto- och subadresser, privata transaktionsnycklar, ...)! Använd ENDAST detta om den här plånboken är skadad och inte laddas!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -4,18 +4,18 @@
|
|||||||
<h1>Створити гаманець - Новий</h1>
|
<h1>Створити гаманець - Новий</h1>
|
||||||
<p>Якщо вам потрібна нова адреса Monero!</p>
|
<p>Якщо вам потрібна нова адреса Monero!</p>
|
||||||
<p>Введіть унікальне і\'мя та пароль гаманця.
|
<p>Введіть унікальне і\'мя та пароль гаманця.
|
||||||
Пароль використовується для захисту даних вашого гаманця на Android пристрої.
|
Пароль використовується для захисту даних вашого гаманця на Android пристрої.
|
||||||
Необхідно використовувати надійний пароль. Краще навіть використовувати фразу-пароль.
|
Необхідно використовувати надійний пароль. Краще навіть використовувати фразу-пароль.
|
||||||
</p>
|
</p>
|
||||||
<h2>Запишіть вашу мнемонічну фразу!</h2>
|
<h2>Запишіть вашу мнемонічну фразу!</h2>
|
||||||
<p>Наступний екран буде містити вашу \"мнемонічну фразу\", що складається з 25 слів.
|
<p>Наступний екран буде містити вашу \"мнемонічну фразу\", що складається з 25 слів.
|
||||||
Це єдині дані, які необхідні для відновлення вашого гаманця в
|
Це єдині дані, які необхідні для відновлення вашого гаманця в
|
||||||
майбутньому і отримання доступу до ваших коштів.
|
майбутньому і отримання доступу до ваших коштів.
|
||||||
Підтримувати її безпеку і конфіденційність дуже важливо, так як це
|
Підтримувати її безпеку і конфіденційність дуже важливо, так як це
|
||||||
гарантує, що ніхто не зможе отримати доступ до ваших коштів!</p>
|
гарантує, що ніхто не зможе отримати доступ до ваших коштів!</p>
|
||||||
<p>Якщо ви втратите пароль від вашого гаманця, ви зможете відновити його, використовуючи мнемонічну фразу.</p>
|
<p>Якщо ви втратите пароль від вашого гаманця, ви зможете відновити його, використовуючи мнемонічну фразу.</p>
|
||||||
<p>Спосіб відновлення мнемонічної фрази відсутній. У разі її втрати - будуть втрачені
|
<p>Спосіб відновлення мнемонічної фрази відсутній. У разі її втрати - будуть втрачені
|
||||||
і всі ваші кошти! Також ви ніколи не зможете змінити мнемонічну фразу, і якщо вона
|
і всі ваші кошти! Також ви ніколи не зможете змінити мнемонічну фразу, і якщо вона
|
||||||
буде вкрадена або розкрита будь-яким іншим чином, то вам доведеться перенести ваші кошти
|
буде вкрадена або розкрита будь-яким іншим чином, то вам доведеться перенести ваші кошти
|
||||||
в новий гаманець (з новою мнемонічною фразою). Тому рекомендується створити резервну копію
|
в новий гаманець (з новою мнемонічною фразою). Тому рекомендується створити резервну копію
|
||||||
вашої мнемонічною фрази, записавши її, і зберігати декілька копій в безпечному місці.</p>
|
вашої мнемонічною фрази, записавши її, і зберігати декілька копій в безпечному місці.</p>
|
||||||
@ -61,7 +61,7 @@
|
|||||||
не боячись втратити свої Monero. Monero відправлятимуть на ваш гаманець, використовуючи саме цю адресу.
|
не боячись втратити свої Monero. Monero відправлятимуть на ваш гаманець, використовуючи саме цю адресу.
|
||||||
<h2>Мнемонічна фраза</h2>
|
<h2>Мнемонічна фраза</h2>
|
||||||
Це єдині дані, які необхідні для відновлення вашого гаманця в майбутньому, і отримання
|
Це єдині дані, які необхідні для відновлення вашого гаманця в майбутньому, і отримання
|
||||||
доступу до ваших коштів. Підтримувати її безпеку і конфіденційність дуже важливо,
|
доступу до ваших коштів. Підтримувати її безпеку і конфіденційність дуже важливо,
|
||||||
так як це гарантує, що <em>ніхто</em> не зможе отримати доступ до ваших коштів!
|
так як це гарантує, що <em>ніхто</em> не зможе отримати доступ до ваших коштів!
|
||||||
Якщо ви не записали цю фразу, і не зберегли її в безпечному місці, зробіть це негайно!
|
Якщо ви не записали цю фразу, і не зберегли її в безпечному місці, зробіть це негайно!
|
||||||
<h2>Файли відновлення паролю гаманця</h2>
|
<h2>Файли відновлення паролю гаманця</h2>
|
||||||
@ -207,10 +207,10 @@
|
|||||||
<p>Ваші секретні ключі ніколи не покинуть пристрій Ledger. Вам потрібен
|
<p>Ваші секретні ключі ніколи не покинуть пристрій Ledger. Вам потрібен
|
||||||
пристрій кожен раз, коли ви хочете отримати доступ до свого гаманця.</p>
|
пристрій кожен раз, коли ви хочете отримати доступ до свого гаманця.</p>
|
||||||
<p>Необхідно ввести унікальні і&apos:мя і пароль гаманця. Пароль використовується для захисту даних вашого
|
<p>Необхідно ввести унікальні і&apos:мя і пароль гаманця. Пароль використовується для захисту даних вашого
|
||||||
гаманця на пристрої. Необхідно використовувати надійний пароль. Краще навіть використовувати фразу-пароль.</p>
|
гаманця на пристрої. Необхідно використовувати надійний пароль. Краще навіть використовувати фразу-пароль.</p>
|
||||||
<p>Якщо вам відомий номер блоку першої транзакції, який використовувався з цією адресою, слід
|
<p>Якщо вам відомий номер блоку першої транзакції, який використовувався з цією адресою, слід
|
||||||
ввести його в поле \"Відновити висоту\". Ви також можете використовувати дату в форматі YYYY-MM-DD.
|
ввести його в поле \"Відновити висоту\". Ви також можете використовувати дату в форматі YYYY-MM-DD.
|
||||||
Якщо ви не впевнені, введіть приблизну дату/висоту блоку <em>до</em> того, як ви вперше використали цей гаманець.</p>
|
Якщо ви не впевнені, введіть приблизну дату/висоту блоку <em>до</em> того, як ви вперше використали цей гаманець.</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_wallet"><![CDATA[
|
<string name="help_wallet"><![CDATA[
|
||||||
@ -229,7 +229,7 @@
|
|||||||
<p><b>Допоможіть! Баланс мого гаманця кудись зник або не підтверджений!</b><br/>
|
<p><b>Допоможіть! Баланс мого гаманця кудись зник або не підтверджений!</b><br/>
|
||||||
Не панікуйте! Якщо ви відправляєте кошти з вашого гаманця, ваш баланс тимчасово залишається
|
Не панікуйте! Якщо ви відправляєте кошти з вашого гаманця, ваш баланс тимчасово залишається
|
||||||
непідтвердженим. Це відбувається в результаті процесу обміну Monero в блокчейні, і роботи механізму
|
непідтвердженим. Це відбувається в результаті процесу обміну Monero в блокчейні, і роботи механізму
|
||||||
решти. Подробиці обміну можна дізнатися за посиланням:
|
решти. Подробиці обміну можна дізнатися за посиланням:
|
||||||
https://getmonero.org/resources/moneropedia/change.html
|
https://getmonero.org/resources/moneropedia/change.html
|
||||||
<h2>Список транзакцій</h2>
|
<h2>Список транзакцій</h2>
|
||||||
<p>Список транзакцій, проведених з використанням цього гаманця. У гаманцях перегляду можна побачити
|
<p>Список транзакцій, проведених з використанням цього гаманця. У гаманцях перегляду можна побачити
|
||||||
@ -278,8 +278,6 @@
|
|||||||
Сканування зупиниться, як тільки буде знайдено 10 віддалених вузлів.</p>
|
Сканування зупиниться, як тільки буде знайдено 10 віддалених вузлів.</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<string name="help_uri"><![CDATA[
|
<string name="help_uri"><![CDATA[
|
||||||
<h1>Використання плажіного посилання</h1>
|
<h1>Використання плажіного посилання</h1>
|
||||||
<p>Ви почали використовувати Monerujo з платіжним посиланням. Для надсилання коштів, будь ласка, виконайте найступне:</p>
|
<p>Ви почали використовувати Monerujo з платіжним посиланням. Для надсилання коштів, будь ласка, виконайте найступне:</p>
|
||||||
@ -292,4 +290,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Я зрозумів!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Я зрозумів!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -231,7 +231,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Помилка створення транзакції</string>
|
<string name="send_create_tx_error_title">Помилка створення транзакції</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Комісія %1$s</string>
|
<string name="tx_list_fee">Комісія %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">Не вдалося</string>
|
<string name="tx_list_failed_text">Не вдалося</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -431,5 +431,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -230,4 +230,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">我明白了!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">我明白了!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -182,7 +182,7 @@
|
|||||||
<string name="send_amount">%1$s XMR</string>
|
<string name="send_amount">%1$s XMR</string>
|
||||||
<string name="send_fee">+%1$s 手续费</string>
|
<string name="send_fee">+%1$s 手续费</string>
|
||||||
<string name="send_create_tx_error_title">创建交易发生错误</string>
|
<string name="send_create_tx_error_title">创建交易发生错误</string>
|
||||||
<string name="tx_list_fee">- 手续费 %1$s</string>
|
<string name="tx_list_fee">手续费 %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">失败</string>
|
<string name="tx_list_failed_text">失败</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -351,5 +351,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -231,4 +231,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">我知道了!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">我知道了!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -229,7 +229,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">建立交易錯誤</string>
|
<string name="send_create_tx_error_title">建立交易錯誤</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- 手續費 %1$s</string>
|
<string name="tx_list_fee">手續費 %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">失敗</string>
|
<string name="tx_list_failed_text">失敗</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -426,5 +426,10 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -290,4 +290,25 @@
|
|||||||
]]></string>
|
]]></string>
|
||||||
|
|
||||||
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->
|
||||||
|
|
||||||
|
<string name="help_nok">Nah…</string> <!-- Note: "Nah..." as in "I don't want this" -->
|
||||||
|
<string name="help_getorbot">Get Orbot!</string>
|
||||||
|
<string name="help_tor"><![CDATA[
|
||||||
|
<h1>Tor</h1>
|
||||||
|
<p>Tor, short for The Onion Router, is free and open-source software for enabling anonymous
|
||||||
|
communication.</p>
|
||||||
|
<p>Enabling Tor will route your connection through several relays and hide your IP address
|
||||||
|
from the node. Keep in mind this is more private but also <b>slower</b>.</p>
|
||||||
|
<p>In order to use Tor with Monerujo, you\'ll need Orbot installed on your phone. After
|
||||||
|
installing Orbot, make sure to enable it by clicking the network icon on the wallet list
|
||||||
|
screen.</p>
|
||||||
|
<p>If you have issues connecting with Tor, try to get a new Identity in the Orbot App (icon
|
||||||
|
on the top right).</p>
|
||||||
|
]]></string>
|
||||||
|
|
||||||
|
<string name="help_tor_enable"><![CDATA[
|
||||||
|
<h1>Tor Node</h1>
|
||||||
|
<p>This is an .onion node. In order to use it, you must enable Tor mode by touching the
|
||||||
|
<img src="ic_network_clearnet"/> icon near the top of the Wallet List page.</p>
|
||||||
|
]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
<string name="changepw_failed">Change Password failed!</string>
|
<string name="changepw_failed">Change Password failed!</string>
|
||||||
<string name="changepw_success">Password changed</string>
|
<string name="changepw_success">Password changed</string>
|
||||||
|
|
||||||
<string name="label_daemon">Node</string>
|
<string name="label_daemon">Network</string>
|
||||||
<string name="connect_stagenet" translatable="false">Stagenet</string>
|
<string name="connect_stagenet" translatable="false">Stagenet</string>
|
||||||
<string name="connect_testnet" translatable="false">Testnet</string>
|
<string name="connect_testnet" translatable="false">Testnet</string>
|
||||||
<string name="status_wallet_loading">Loading Wallet …</string>
|
<string name="status_wallet_loading">Loading Wallet …</string>
|
||||||
@ -243,7 +243,7 @@
|
|||||||
|
|
||||||
<string name="send_create_tx_error_title">Create Transaction Error</string>
|
<string name="send_create_tx_error_title">Create Transaction Error</string>
|
||||||
|
|
||||||
<string name="tx_list_fee">- Fee %1$s</string>
|
<string name="tx_list_fee">Fee %1$s</string>
|
||||||
<string name="tx_list_amount_failed">(%1$s)</string>
|
<string name="tx_list_amount_failed">(%1$s)</string>
|
||||||
<string name="tx_list_failed_text">failed</string>
|
<string name="tx_list_failed_text">failed</string>
|
||||||
<string name="tx_list_amount_negative">- %1$s</string>
|
<string name="tx_list_amount_negative">- %1$s</string>
|
||||||
@ -499,5 +499,12 @@
|
|||||||
<string name="restore_failed">Import failed!</string>
|
<string name="restore_failed">Import failed!</string>
|
||||||
|
|
||||||
<string name="menu_deletecache">Reset wallet!</string>
|
<string name="menu_deletecache">Reset wallet!</string>
|
||||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, ...)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||||
|
|
||||||
|
<string name="status" translatable="false"><span style=\"background-color: #%1$s; color: #%2$s;\">%3$s</span>%4$s</string>
|
||||||
|
|
||||||
|
<string name="node_tor_error">Tor required</string>
|
||||||
|
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||||
|
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||||
|
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -36,8 +36,7 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppCard" parent="Widget.MaterialComponents.CardView">
|
<style name="AppCard" parent="Widget.MaterialComponents.CardView">
|
||||||
<item name="cardElevation">4dp</item>
|
<item name="cardElevation">2dp</item>
|
||||||
<item name="cardCornerRadius">1dp</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppButton" parent="@style/Widget.MaterialComponents.Button">
|
<style name="AppButton" parent="@style/Widget.MaterialComponents.Button">
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
Loading…
Reference in New Issue
Block a user