mirror of
https://github.com/m2049r/xmrwallet
synced 2025-04-12 17:42:05 +02:00
migrate to scoped storage and API 30 (#741)
This commit is contained in:
parent
24fc27b09e
commit
d2f07ba3b6
app
build.gradle
src/main
AndroidManifest.xml
java/com/m2049r/xmrwallet
res
layout
menu
values-cat
values-de
values-el
values-eo
values-es
values-et
values-fr
values-hu
values-it
values-ja
values-nb
values-nl
values-pt-rBR
values-pt
values-ro
values-ru
values-sk
values-sr
values-sv
values-uk
values-zh-rCN
values-zh-rTW
values
@ -1,14 +1,14 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '29.0.3'
|
||||
defaultConfig {
|
||||
applicationId "com.m2049r.xmrwallet"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 801
|
||||
versionName "1.18.1 'ChAdOx1'"
|
||||
targetSdkVersion 30
|
||||
versionCode 900
|
||||
versionName "1.19.0.2 'XXX'"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
|
@ -8,7 +8,6 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
|
@ -23,10 +23,8 @@ import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
@ -39,6 +37,7 @@ import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.fragment.app.Fragment;
|
||||
@ -62,10 +61,13 @@ import com.m2049r.xmrwallet.service.WalletService;
|
||||
import com.m2049r.xmrwallet.util.DayNightMode;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
import com.m2049r.xmrwallet.util.KeyStoreHelper;
|
||||
import com.m2049r.xmrwallet.util.LegacyStorageHelper;
|
||||
import com.m2049r.xmrwallet.util.LocaleHelper;
|
||||
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||
import com.m2049r.xmrwallet.util.NightmodeHelper;
|
||||
import com.m2049r.xmrwallet.util.ThemeHelper;
|
||||
import com.m2049r.xmrwallet.util.ZipBackup;
|
||||
import com.m2049r.xmrwallet.util.ZipRestore;
|
||||
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||
|
||||
import java.io.File;
|
||||
@ -290,9 +292,6 @@ public class LoginActivity extends BaseActivity
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Timber.d("onCreate()");
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
// we don't store anything ourselves
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_login);
|
||||
toolbar = findViewById(R.id.toolbar);
|
||||
@ -319,11 +318,9 @@ public class LoginActivity extends BaseActivity
|
||||
|
||||
loadFavouritesWithNetwork();
|
||||
|
||||
if (Helper.getWritePermission(this)) {
|
||||
if (savedInstanceState == null) startLoginFragment();
|
||||
} else {
|
||||
Timber.i("Waiting for permissions");
|
||||
}
|
||||
LegacyStorageHelper.migrateWallets(this);
|
||||
|
||||
if (savedInstanceState == null) startLoginFragment();
|
||||
|
||||
// try intents
|
||||
Intent intent = getIntent();
|
||||
@ -396,53 +393,25 @@ public class LoginActivity extends BaseActivity
|
||||
.show();
|
||||
}
|
||||
|
||||
private class AsyncRename extends AsyncTask<String, Void, Boolean> {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
showProgressDialog(R.string.rename_progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
if (params.length != 2) return false;
|
||||
String oldName = params[0];
|
||||
String newName = params[1];
|
||||
File walletFile = Helper.getWalletFile(LoginActivity.this, oldName);
|
||||
boolean success = renameWallet(walletFile, newName);
|
||||
try {
|
||||
if (success) {
|
||||
String savedPass = KeyStoreHelper.loadWalletUserPass(LoginActivity.this, oldName);
|
||||
KeyStoreHelper.saveWalletUserPass(LoginActivity.this, newName, savedPass);
|
||||
}
|
||||
} catch (KeyStoreHelper.BrokenPasswordStoreException ex) {
|
||||
Timber.w(ex);
|
||||
} finally {
|
||||
// we have either set a new password or it is broken - kill the old one either way
|
||||
KeyStoreHelper.removeWalletUserPass(LoginActivity.this, oldName);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
super.onPostExecute(result);
|
||||
if (isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
dismissProgressDialog();
|
||||
if (result) {
|
||||
reloadWalletList();
|
||||
} else {
|
||||
Toast.makeText(LoginActivity.this, getString(R.string.rename_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
private void renameWallet(String oldName, String newName) {
|
||||
File walletFile = Helper.getWalletFile(this, oldName);
|
||||
boolean success = renameWallet(walletFile, newName);
|
||||
if (success) {
|
||||
reloadWalletList();
|
||||
} else {
|
||||
Toast.makeText(LoginActivity.this, getString(R.string.rename_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
// copy + delete seems safer than rename because we call rollback easily
|
||||
// copy + delete seems safer than rename because we can rollback easily
|
||||
boolean renameWallet(File walletFile, String newName) {
|
||||
if (copyWallet(walletFile, new File(walletFile.getParentFile(), newName), false, true)) {
|
||||
deleteWallet(walletFile);
|
||||
try {
|
||||
KeyStoreHelper.copyWalletUserPass(this, walletFile.getName(), newName);
|
||||
} catch (KeyStoreHelper.BrokenPasswordStoreException ex) {
|
||||
Timber.w(ex);
|
||||
}
|
||||
deleteWallet(walletFile); // also deletes the keystore entry
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -468,154 +437,123 @@ public class LoginActivity extends BaseActivity
|
||||
alertDialogBuilder
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(getString(R.string.label_ok),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
Helper.hideKeyboardAlways(LoginActivity.this);
|
||||
String newName = etRename.getText().toString();
|
||||
new AsyncRename().execute(walletName, newName);
|
||||
}
|
||||
(dialog, id) -> {
|
||||
Helper.hideKeyboardAlways(LoginActivity.this);
|
||||
String newName = etRename.getText().toString();
|
||||
renameWallet(walletName, newName);
|
||||
})
|
||||
.setNegativeButton(getString(R.string.label_cancel),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
Helper.hideKeyboardAlways(LoginActivity.this);
|
||||
dialog.cancel();
|
||||
}
|
||||
(dialog, id) -> {
|
||||
Helper.hideKeyboardAlways(LoginActivity.this);
|
||||
dialog.cancel();
|
||||
});
|
||||
|
||||
final AlertDialog dialog = alertDialogBuilder.create();
|
||||
Helper.showKeyboard(dialog);
|
||||
|
||||
// accept keyboard "ok"
|
||||
etRename.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
|
||||
|| (actionId == EditorInfo.IME_ACTION_DONE)) {
|
||||
Helper.hideKeyboardAlways(LoginActivity.this);
|
||||
String newName = etRename.getText().toString();
|
||||
dialog.cancel();
|
||||
new AsyncRename().execute(walletName, newName);
|
||||
return false;
|
||||
}
|
||||
etRename.setOnEditorActionListener((v, actionId, event) -> {
|
||||
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
|
||||
|| (actionId == EditorInfo.IME_ACTION_DONE)) {
|
||||
Helper.hideKeyboardAlways(LoginActivity.this);
|
||||
String newName = etRename.getText().toString();
|
||||
dialog.cancel();
|
||||
renameWallet(walletName, newName);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private class AsyncBackup extends AsyncTask<String, Void, Boolean> {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
showProgressDialog(R.string.backup_progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
if (params.length != 1) return false;
|
||||
return backupWallet(params[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
super.onPostExecute(result);
|
||||
if (isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
dismissProgressDialog();
|
||||
if (!result) {
|
||||
Toast.makeText(LoginActivity.this, getString(R.string.backup_failed), Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(LoginActivity.this, getString(R.string.backup_success), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean backupWallet(String walletName) {
|
||||
File backupFolder = new File(getStorageRoot(), "backups");
|
||||
if (!backupFolder.exists()) {
|
||||
if (!backupFolder.mkdir()) {
|
||||
Timber.e("Cannot create backup dir %s", backupFolder.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
// make folder visible over USB/MTP
|
||||
MediaScannerConnection.scanFile(this, new String[]{backupFolder.toString()}, null, null);
|
||||
}
|
||||
File walletFile = Helper.getWalletFile(LoginActivity.this, walletName);
|
||||
File backupFile = new File(backupFolder, walletName);
|
||||
Timber.d("backup " + walletFile.getAbsolutePath() + " to " + backupFile.getAbsolutePath());
|
||||
// TODO probably better to copy to a new file and then rename
|
||||
// then if something fails we have the old backup at least
|
||||
// or just create a new backup every time and keep n old backups
|
||||
boolean success = copyWallet(walletFile, backupFile, true, true);
|
||||
Timber.d("copyWallet is %s", success);
|
||||
return success;
|
||||
}
|
||||
private static final int CREATE_BACKUP_INTENT = 4711;
|
||||
private static final int RESTORE_BACKUP_INTENT = 4712;
|
||||
private ZipBackup zipBackup;
|
||||
|
||||
@Override
|
||||
public void onWalletBackup(String walletName) {
|
||||
Timber.d("backup for wallet ." + walletName + ".");
|
||||
new AsyncBackup().execute(walletName);
|
||||
zipBackup = new ZipBackup(this, walletName);
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("application/zip");
|
||||
intent.putExtra(Intent.EXTRA_TITLE, zipBackup.getBackupName());
|
||||
startActivityForResult(intent, CREATE_BACKUP_INTENT);
|
||||
}
|
||||
|
||||
private class AsyncArchive extends AsyncTask<String, Void, Boolean> {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
showProgressDialog(R.string.archive_progress);
|
||||
}
|
||||
@Override
|
||||
public void onWalletRestore() {
|
||||
Timber.d("restore wallet");
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
if (params.length != 1) return false;
|
||||
String walletName = params[0];
|
||||
if (backupWallet(walletName) && deleteWallet(Helper.getWalletFile(LoginActivity.this, walletName))) {
|
||||
KeyStoreHelper.removeWalletUserPass(LoginActivity.this, walletName);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("application/zip");
|
||||
startActivityForResult(intent, RESTORE_BACKUP_INTENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
super.onPostExecute(result);
|
||||
if (isDestroyed()) {
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == CREATE_BACKUP_INTENT) {
|
||||
if (data == null) {
|
||||
// nothing selected
|
||||
Toast.makeText(this, getString(R.string.backup_failed), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
dismissProgressDialog();
|
||||
if (result) {
|
||||
reloadWalletList();
|
||||
} else {
|
||||
Toast.makeText(LoginActivity.this, getString(R.string.archive_failed), Toast.LENGTH_LONG).show();
|
||||
try {
|
||||
zipBackup.writeTo(data.getData());
|
||||
Toast.makeText(this, getString(R.string.backup_success), Toast.LENGTH_SHORT).show();
|
||||
} catch (IOException ex) {
|
||||
Timber.e(ex);
|
||||
Toast.makeText(this, getString(R.string.backup_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (requestCode == RESTORE_BACKUP_INTENT) {
|
||||
if (data == null) {
|
||||
// nothing selected
|
||||
Toast.makeText(this, getString(R.string.restore_failed), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ZipRestore zipRestore = new ZipRestore(this, data.getData());
|
||||
Toast.makeText(this, getString(R.string.menu_restore), Toast.LENGTH_SHORT).show();
|
||||
if (zipRestore.restore()) {
|
||||
reloadWalletList();
|
||||
} else {
|
||||
Toast.makeText(this, getString(R.string.restore_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Timber.e(ex);
|
||||
Toast.makeText(this, getString(R.string.restore_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalletArchive(final String walletName) {
|
||||
Timber.d("archive for wallet ." + walletName + ".");
|
||||
public void onWalletDelete(final String walletName) {
|
||||
Timber.d("delete for wallet ." + walletName + ".");
|
||||
if (checkServiceRunning()) return;
|
||||
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
new AsyncArchive().execute(walletName);
|
||||
break;
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
DialogInterface.OnClickListener dialogClickListener = (dialog, which) -> {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
if (deleteWallet(Helper.getWalletFile(LoginActivity.this, walletName))) {
|
||||
reloadWalletList();
|
||||
} else {
|
||||
Toast.makeText(LoginActivity.this, getString(R.string.delete_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setMessage(getString(R.string.archive_alert_message))
|
||||
builder.setMessage(getString(R.string.delete_alert_message))
|
||||
.setTitle(walletName)
|
||||
.setPositiveButton(getString(R.string.archive_alert_yes), dialogClickListener)
|
||||
.setNegativeButton(getString(R.string.archive_alert_no), dialogClickListener)
|
||||
.setPositiveButton(getString(R.string.delete_alert_yes), dialogClickListener)
|
||||
.setNegativeButton(getString(R.string.delete_alert_no), dialogClickListener)
|
||||
.show();
|
||||
}
|
||||
|
||||
@ -628,6 +566,7 @@ public class LoginActivity extends BaseActivity
|
||||
loginFragment.loadList();
|
||||
}
|
||||
} catch (ClassCastException ex) {
|
||||
Timber.w(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -774,37 +713,6 @@ public class LoginActivity extends BaseActivity
|
||||
startReviewFragment(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
|
||||
@NonNull int[] grantResults) {
|
||||
Timber.d("onRequestPermissionsResult()");
|
||||
switch (requestCode) {
|
||||
case Helper.PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE:
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
startLoginFragment = true;
|
||||
} else {
|
||||
String msg = getString(R.string.message_strorage_not_permitted);
|
||||
Timber.e(msg);
|
||||
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private boolean startLoginFragment = false;
|
||||
|
||||
@Override
|
||||
protected void onResumeFragments() {
|
||||
super.onResumeFragments();
|
||||
if (startLoginFragment) {
|
||||
startLoginFragment();
|
||||
startLoginFragment = false;
|
||||
}
|
||||
}
|
||||
|
||||
void startLoginFragment() {
|
||||
// we set these here because we cannot be ceratin we have permissions for storage before
|
||||
Helper.setMoneroHome(this);
|
||||
@ -1035,22 +943,12 @@ public class LoginActivity extends BaseActivity
|
||||
});
|
||||
}
|
||||
|
||||
void toast(final String msg) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
private void toast(final String msg) {
|
||||
runOnUiThread(() -> Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_LONG).show());
|
||||
}
|
||||
|
||||
void toast(final int msgId) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(LoginActivity.this, getString(msgId), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
private void toast(final int msgId) {
|
||||
runOnUiThread(() -> Toast.makeText(LoginActivity.this, getString(msgId), Toast.LENGTH_LONG).show());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1058,7 +956,7 @@ public class LoginActivity extends BaseActivity
|
||||
File walletFolder = getStorageRoot();
|
||||
File walletFile = new File(walletFolder, name);
|
||||
Timber.d("New Wallet %s", walletFile.getAbsolutePath());
|
||||
walletFile.delete(); // when recovering wallets, the cache seems corrupt
|
||||
walletFile.delete(); // when recovering wallets, the cache seems corrupt - so remove it
|
||||
|
||||
popFragmentStack(GENERATE_STACK);
|
||||
Toast.makeText(LoginActivity.this,
|
||||
@ -1079,8 +977,7 @@ public class LoginActivity extends BaseActivity
|
||||
}
|
||||
}
|
||||
|
||||
boolean copyWallet(File srcWallet, File dstWallet, boolean overwrite,
|
||||
boolean ignoreCacheError) {
|
||||
boolean copyWallet(File srcWallet, File dstWallet, boolean overwrite, boolean ignoreCacheError) {
|
||||
if (walletExists(dstWallet, true) && !overwrite) return false;
|
||||
boolean success = false;
|
||||
File srcDir = srcWallet.getParentFile();
|
||||
@ -1123,19 +1020,14 @@ public class LoginActivity extends BaseActivity
|
||||
success = addressFile.delete() && success;
|
||||
}
|
||||
Timber.d("deleteWallet is %s", success);
|
||||
KeyStoreHelper.removeWalletUserPass(this, walletFile.getName());
|
||||
return success;
|
||||
}
|
||||
|
||||
void copyFile(File src, File dst) throws IOException {
|
||||
FileChannel inChannel = new FileInputStream(src).getChannel();
|
||||
FileChannel outChannel = new FileOutputStream(dst).getChannel();
|
||||
try {
|
||||
try (FileChannel inChannel = new FileInputStream(src).getChannel();
|
||||
FileChannel outChannel = new FileOutputStream(dst).getChannel()) {
|
||||
inChannel.transferTo(0, inChannel.size(), outChannel);
|
||||
} finally {
|
||||
if (inChannel != null)
|
||||
inChannel.close();
|
||||
if (outChannel != null)
|
||||
outChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1220,63 +1112,64 @@ public class LoginActivity extends BaseActivity
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_create_help_new:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_new);
|
||||
return true;
|
||||
case R.id.action_create_help_keys:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_keys);
|
||||
return true;
|
||||
case R.id.action_create_help_view:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_view);
|
||||
return true;
|
||||
case R.id.action_create_help_seed:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_seed);
|
||||
return true;
|
||||
case R.id.action_create_help_ledger:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_ledger);
|
||||
return true;
|
||||
case R.id.action_details_help:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_details);
|
||||
return true;
|
||||
case R.id.action_details_changepw:
|
||||
onWalletChangePassword();
|
||||
return true;
|
||||
case R.id.action_license_info:
|
||||
AboutFragment.display(getSupportFragmentManager());
|
||||
return true;
|
||||
case R.id.action_help_list:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_list);
|
||||
return true;
|
||||
case R.id.action_help_node:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_node);
|
||||
return true;
|
||||
case R.id.action_default_nodes: {
|
||||
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
if ((WalletManager.getInstance().getNetworkType() == NetworkType.NetworkType_Mainnet) &&
|
||||
(f instanceof NodeFragment)) {
|
||||
((NodeFragment) f).restoreDefaultNodes();
|
||||
}
|
||||
return true;
|
||||
final int id = item.getItemId();
|
||||
if (id == R.id.action_create_help_new) {
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_new);
|
||||
return true;
|
||||
} else if (id == R.id.action_create_help_keys) {
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_keys);
|
||||
return true;
|
||||
} else if (id == R.id.action_create_help_view) {
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_view);
|
||||
return true;
|
||||
} else if (id == R.id.action_create_help_seed) {
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_seed);
|
||||
return true;
|
||||
} else if (id == R.id.action_create_help_ledger) {
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_ledger);
|
||||
return true;
|
||||
} else if (id == R.id.action_details_help) {
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_details);
|
||||
return true;
|
||||
} else if (id == R.id.action_details_changepw) {
|
||||
onWalletChangePassword();
|
||||
return true;
|
||||
} else if (id == R.id.action_license_info) {
|
||||
AboutFragment.display(getSupportFragmentManager());
|
||||
return true;
|
||||
} else if (id == R.id.action_help_list) {
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_list);
|
||||
return true;
|
||||
} else if (id == R.id.action_help_node) {
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_node);
|
||||
return true;
|
||||
} else if (id == R.id.action_default_nodes) {
|
||||
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
if ((WalletManager.getInstance().getNetworkType() == NetworkType.NetworkType_Mainnet) &&
|
||||
(f instanceof NodeFragment)) {
|
||||
((NodeFragment) f).restoreDefaultNodes();
|
||||
}
|
||||
case R.id.action_privacy_policy:
|
||||
PrivacyFragment.display(getSupportFragmentManager());
|
||||
return true;
|
||||
case R.id.action_language:
|
||||
onChangeLocale();
|
||||
return true;
|
||||
case R.id.action_theme:
|
||||
onChangeTheme();
|
||||
return true;
|
||||
case R.id.action_ledger_seed: {
|
||||
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
if (f instanceof GenerateFragment) {
|
||||
((GenerateFragment) f).convertLedgerSeed();
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
} else if (id == R.id.action_privacy_policy) {
|
||||
PrivacyFragment.display(getSupportFragmentManager());
|
||||
return true;
|
||||
} else if (id == R.id.action_language) {
|
||||
onChangeLocale();
|
||||
return true;
|
||||
} else if (id == R.id.action_theme) {
|
||||
onChangeTheme();
|
||||
return true;
|
||||
} else if (id == R.id.action_restore) {
|
||||
onWalletRestore();
|
||||
return true;
|
||||
} else if (id == R.id.action_ledger_seed) {
|
||||
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
if (f instanceof GenerateFragment) {
|
||||
((GenerateFragment) f).convertLedgerSeed();
|
||||
}
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1317,7 +1210,7 @@ public class LoginActivity extends BaseActivity
|
||||
if (result) {
|
||||
Timber.d("selected wallet is .%s.", node.getName());
|
||||
// now it's getting real, onValidateFields if wallet exists
|
||||
promptAndStart(walletName, node, streetmode);
|
||||
promptAndStart(walletName, streetmode);
|
||||
} else {
|
||||
if (node.getResponseCode() == 0) { // IOException
|
||||
Toast.makeText(LoginActivity.this, getString(R.string.status_wallet_node_invalid), Toast.LENGTH_LONG).show();
|
||||
@ -1333,25 +1226,21 @@ public class LoginActivity extends BaseActivity
|
||||
String keyPath = new File(Helper.getWalletRoot(LoginActivity.this),
|
||||
walletName + ".keys").getAbsolutePath();
|
||||
// check if we need connected hardware
|
||||
Wallet.Device device =
|
||||
WalletManager.getInstance().queryWalletDevice(keyPath, password);
|
||||
switch (device) {
|
||||
case Device_Ledger:
|
||||
if (!hasLedger()) {
|
||||
toast(R.string.open_wallet_ledger_missing);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// device could be undefined meaning the password is wrong
|
||||
// this gets dealt with later
|
||||
Wallet.Device device = WalletManager.getInstance().queryWalletDevice(keyPath, password);
|
||||
if (device == Wallet.Device.Device_Ledger) {
|
||||
if (!hasLedger()) {
|
||||
toast(R.string.open_wallet_ledger_missing);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {// device could be undefined meaning the password is wrong
|
||||
// this gets dealt with later
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void promptAndStart(String walletName, Node node, final boolean streetmode) {
|
||||
void promptAndStart(String walletName, final boolean streetmode) {
|
||||
File walletFile = Helper.getWalletFile(this, walletName);
|
||||
if (WalletManager.getInstance().walletExists(walletFile)) {
|
||||
Helper.promptPassword(LoginActivity.this, walletName, false,
|
||||
@ -1418,38 +1307,23 @@ public class LoginActivity extends BaseActivity
|
||||
Ledger.connect(usbManager, usbDevice);
|
||||
if (!Ledger.check()) {
|
||||
Ledger.disconnect();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.toast_ledger_start_app, usbDevice.getProductName()),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
runOnUiThread(() -> Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.toast_ledger_start_app, usbDevice.getProductName()),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show());
|
||||
} else {
|
||||
registerDetachReceiver();
|
||||
onLedgerAction();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.toast_ledger_attached, usbDevice.getProductName()),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
runOnUiThread(() -> Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.toast_ledger_attached, usbDevice.getProductName()),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.open_wallet_ledger_missing),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
runOnUiThread(() -> Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.open_wallet_ledger_missing),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1507,15 +1381,10 @@ public class LoginActivity extends BaseActivity
|
||||
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
||||
Timber.i("Ledger detached!");
|
||||
if (device != null)
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.toast_ledger_detached, device.getProductName()),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
runOnUiThread(() -> Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.toast_ledger_detached, device.getProductName()),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show());
|
||||
Ledger.disconnect();
|
||||
onLedgerAction();
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -62,8 +61,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
|
||||
private WalletInfoAdapter adapter;
|
||||
|
||||
private List<WalletManager.WalletInfo> walletList = new ArrayList<>();
|
||||
private List<WalletManager.WalletInfo> displayedList = new ArrayList<>();
|
||||
private final List<WalletManager.WalletInfo> walletList = new ArrayList<>();
|
||||
|
||||
private View tvGuntherSays;
|
||||
private ImageView ivGunther;
|
||||
@ -86,7 +84,9 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
|
||||
void onWalletBackup(String name);
|
||||
|
||||
void onWalletArchive(String walletName);
|
||||
void onWalletRestore();
|
||||
|
||||
void onWalletDelete(String walletName);
|
||||
|
||||
void onAddWallet(String type);
|
||||
|
||||
@ -110,7 +110,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof Listener) {
|
||||
this.activityCallback = (Listener) context;
|
||||
@ -200,12 +200,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
// Wallet touched
|
||||
@Override
|
||||
public void onInteraction(final View view, final WalletManager.WalletInfo infoItem) {
|
||||
String addressPrefix = WalletManager.getInstance().addressPrefix();
|
||||
if (addressPrefix.indexOf(infoItem.address.charAt(0)) < 0) {
|
||||
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
openWallet(infoItem.name, false);
|
||||
openWallet(infoItem.getName(), false);
|
||||
}
|
||||
|
||||
private void openWallet(String name, boolean streetmode) {
|
||||
@ -214,48 +209,32 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
|
||||
@Override
|
||||
public boolean onContextInteraction(MenuItem item, WalletManager.WalletInfo listItem) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_streetmode:
|
||||
openWallet(listItem.name, true);
|
||||
break;
|
||||
case R.id.action_info:
|
||||
showInfo(listItem.name);
|
||||
break;
|
||||
case R.id.action_rename:
|
||||
activityCallback.onWalletRename(listItem.name);
|
||||
break;
|
||||
case R.id.action_backup:
|
||||
activityCallback.onWalletBackup(listItem.name);
|
||||
break;
|
||||
case R.id.action_archive:
|
||||
activityCallback.onWalletArchive(listItem.name);
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(item);
|
||||
final int id = item.getItemId();
|
||||
if (id == R.id.action_streetmode) {
|
||||
openWallet(listItem.getName(), true);
|
||||
} else if (id == R.id.action_info) {
|
||||
showInfo(listItem.getName());
|
||||
} else if (id == R.id.action_rename) {
|
||||
activityCallback.onWalletRename(listItem.getName());
|
||||
} else if (id == R.id.action_backup) {
|
||||
activityCallback.onWalletBackup(listItem.getName());
|
||||
} else if (id == R.id.action_archive) {
|
||||
activityCallback.onWalletDelete(listItem.getName());
|
||||
} else {
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void filterList() {
|
||||
displayedList.clear();
|
||||
String addressPrefix = WalletManager.getInstance().addressPrefix();
|
||||
for (WalletManager.WalletInfo s : walletList) {
|
||||
if (addressPrefix.indexOf(s.address.charAt(0)) >= 0) displayedList.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadList() {
|
||||
Timber.d("loadList()");
|
||||
WalletManager mgr = WalletManager.getInstance();
|
||||
List<WalletManager.WalletInfo> walletInfos =
|
||||
mgr.findWallets(activityCallback.getStorageRoot());
|
||||
walletList.clear();
|
||||
walletList.addAll(walletInfos);
|
||||
filterList();
|
||||
adapter.setInfos(displayedList);
|
||||
walletList.addAll(mgr.findWallets(activityCallback.getStorageRoot()));
|
||||
adapter.setInfos(walletList);
|
||||
|
||||
// deal with Gunther & FAB animation
|
||||
if (displayedList.isEmpty()) {
|
||||
if (walletList.isEmpty()) {
|
||||
fab.startAnimation(fab_pulse);
|
||||
if (ivGunther.getDrawable() == null) {
|
||||
ivGunther.setImageResource(R.drawable.ic_emptygunther);
|
||||
@ -274,7 +253,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
.getSharedPreferences(KeyStoreHelper.SecurityConstants.WALLET_PASS_PREFS_NAME, Context.MODE_PRIVATE)
|
||||
.getAll().keySet();
|
||||
for (WalletManager.WalletInfo s : walletList) {
|
||||
removedWallets.remove(s.name);
|
||||
removedWallets.remove(s.getName());
|
||||
}
|
||||
for (String name : removedWallets) {
|
||||
KeyStoreHelper.removeWalletUserPass(getActivity(), name);
|
||||
@ -292,7 +271,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.list_menu, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
@ -362,37 +341,29 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int id = v.getId();
|
||||
final int id = v.getId();
|
||||
Timber.d("onClick %d/%d", id, R.id.fabLedger);
|
||||
switch (id) {
|
||||
case R.id.fab:
|
||||
animateFAB();
|
||||
break;
|
||||
case R.id.fabNew:
|
||||
fabScreen.setVisibility(View.INVISIBLE);
|
||||
isFabOpen = false;
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_NEW);
|
||||
break;
|
||||
case R.id.fabView:
|
||||
animateFAB();
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_VIEWONLY);
|
||||
break;
|
||||
case R.id.fabKey:
|
||||
animateFAB();
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_KEY);
|
||||
break;
|
||||
case R.id.fabSeed:
|
||||
animateFAB();
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_SEED);
|
||||
break;
|
||||
case R.id.fabLedger:
|
||||
Timber.d("FAB_LEDGER");
|
||||
animateFAB();
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_LEDGER);
|
||||
break;
|
||||
case R.id.fabScreen:
|
||||
animateFAB();
|
||||
break;
|
||||
if (id == R.id.fab) {
|
||||
animateFAB();
|
||||
} else if (id == R.id.fabNew) {
|
||||
fabScreen.setVisibility(View.INVISIBLE);
|
||||
isFabOpen = false;
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_NEW);
|
||||
} else if (id == R.id.fabView) {
|
||||
animateFAB();
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_VIEWONLY);
|
||||
} else if (id == R.id.fabKey) {
|
||||
animateFAB();
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_KEY);
|
||||
} else if (id == R.id.fabSeed) {
|
||||
animateFAB();
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_SEED);
|
||||
} else if (id == R.id.fabLedger) {
|
||||
Timber.d("FAB_LEDGER");
|
||||
animateFAB();
|
||||
activityCallback.onAddWallet(GenerateFragment.TYPE_LEDGER);
|
||||
} else if (id == R.id.fabScreen) {
|
||||
animateFAB();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
return mOldList.get(oldItemPosition).name.equals(mNewList.get(newItemPosition).name);
|
||||
return mOldList.get(oldItemPosition).getName().equals(mNewList.get(newItemPosition).getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -86,9 +86,9 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_wallet, parent, false);
|
||||
return new ViewHolder(view);
|
||||
return new ViewHolder(
|
||||
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_wallet, parent, false)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -122,7 +122,6 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
final TextView tvName;
|
||||
final TextView tvAddress;
|
||||
final ImageButton ibOptions;
|
||||
WalletManager.WalletInfo infoItem;
|
||||
boolean popupOpen = false;
|
||||
@ -130,7 +129,6 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
tvName = itemView.findViewById(R.id.tvName);
|
||||
tvAddress = itemView.findViewById(R.id.tvAddress);
|
||||
ibOptions = itemView.findViewById(R.id.ibOptions);
|
||||
ibOptions.setOnClickListener(view -> {
|
||||
if (popupOpen) return;
|
||||
@ -160,8 +158,7 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
||||
|
||||
void bind(int position) {
|
||||
infoItem = infoItems.get(position);
|
||||
tvName.setText(infoItem.name);
|
||||
tvAddress.setText(infoItem.address.substring(0, 16) + "...");
|
||||
tvName.setText(infoItem.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,15 +21,13 @@ import com.m2049r.xmrwallet.data.Node;
|
||||
import com.m2049r.xmrwallet.ledger.Ledger;
|
||||
import com.m2049r.xmrwallet.util.RestoreHeight;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class WalletManager {
|
||||
@ -103,7 +101,8 @@ public class WalletManager {
|
||||
wallet.setRestoreHeight(restoreHeight);
|
||||
Timber.d("Changed Restore Height from %d to %d", oldHeight, wallet.getRestoreHeight());
|
||||
wallet.setPassword(password); // this rewrites the keys file (which contains the restore height)
|
||||
}
|
||||
} else
|
||||
Timber.e(wallet.getStatus().toString());
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@ -210,46 +209,22 @@ public class WalletManager {
|
||||
//public native List<String> findWallets(String path); // this does not work - some error in boost
|
||||
|
||||
public class WalletInfo implements Comparable<WalletInfo> {
|
||||
public File path;
|
||||
public String name;
|
||||
public String address;
|
||||
@Getter
|
||||
final private File path;
|
||||
@Getter
|
||||
final private String name;
|
||||
|
||||
public WalletInfo(File wallet) {
|
||||
path = wallet.getParentFile();
|
||||
name = wallet.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(WalletInfo another) {
|
||||
int n = name.toLowerCase().compareTo(another.name.toLowerCase());
|
||||
if (n != 0) {
|
||||
return n;
|
||||
} else { // wallet names are the same
|
||||
return address.compareTo(another.address);
|
||||
}
|
||||
return name.toLowerCase().compareTo(another.name.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
public WalletInfo getWalletInfo(File wallet) {
|
||||
WalletInfo info = new WalletInfo();
|
||||
info.path = wallet.getParentFile();
|
||||
info.name = wallet.getName();
|
||||
File addressFile = new File(info.path, info.name + ".address.txt");
|
||||
//Timber.d(addressFile.getAbsolutePath());
|
||||
info.address = "??????";
|
||||
BufferedReader addressReader = null;
|
||||
try {
|
||||
addressReader = new BufferedReader(new FileReader(addressFile));
|
||||
info.address = addressReader.readLine();
|
||||
} catch (IOException ex) {
|
||||
Timber.d(ex.getLocalizedMessage());
|
||||
} finally {
|
||||
if (addressReader != null) {
|
||||
try {
|
||||
addressReader.close();
|
||||
} catch (IOException ex) {
|
||||
// that's just too bad
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
public List<WalletInfo> findWallets(File path) {
|
||||
List<WalletInfo> wallets = new ArrayList<>();
|
||||
Timber.d("Scanning: %s", path.getAbsolutePath());
|
||||
@ -261,7 +236,7 @@ public class WalletManager {
|
||||
for (int i = 0; i < found.length; i++) {
|
||||
String filename = found[i].getName();
|
||||
File f = new File(found[i].getParent(), filename.substring(0, filename.length() - 5)); // 5 is length of ".keys"+1
|
||||
wallets.add(getWalletInfo(f));
|
||||
wallets.add(new WalletInfo(f));
|
||||
}
|
||||
return wallets;
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Environment;
|
||||
import android.os.StrictMode;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
@ -77,16 +76,12 @@ import javax.net.ssl.HttpsURLConnection;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class Helper {
|
||||
static private final String FLAVOR_SUFFIX =
|
||||
(BuildConfig.FLAVOR.startsWith("prod") ? "" : "." + BuildConfig.FLAVOR)
|
||||
+ (BuildConfig.DEBUG ? "-debug" : "");
|
||||
|
||||
static public final String NOCRAZYPASS_FLAGFILE = ".nocrazypass";
|
||||
|
||||
static public final String BASE_CRYPTO = "XMR";
|
||||
|
||||
static private final String WALLET_DIR = "monerujo" + FLAVOR_SUFFIX;
|
||||
static private final String HOME_DIR = "monero" + FLAVOR_SUFFIX;
|
||||
static private final String WALLET_DIR = "wallets";
|
||||
static private final String MONERO_DIR = "monero";
|
||||
|
||||
static public int DISPLAY_DIGITS_INFO = 5;
|
||||
|
||||
@ -95,12 +90,7 @@ public class Helper {
|
||||
}
|
||||
|
||||
static public File getStorage(Context context, String folderName) {
|
||||
if (!isExternalStorageWritable()) {
|
||||
String msg = context.getString(R.string.message_strorage_not_writable);
|
||||
Timber.e(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
File dir = new File(Environment.getExternalStorageDirectory(), folderName);
|
||||
File dir = new File(context.getFilesDir(), folderName);
|
||||
if (!dir.exists()) {
|
||||
Timber.i("Creating %s", dir.getAbsolutePath());
|
||||
dir.mkdirs(); // try to make it
|
||||
@ -113,24 +103,6 @@ public class Helper {
|
||||
return dir;
|
||||
}
|
||||
|
||||
static public final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
|
||||
|
||||
static public boolean getWritePermission(Activity context) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
if (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
== PackageManager.PERMISSION_DENIED) {
|
||||
Timber.w("Permission denied to WRITE_EXTERNAL_STORAGE - requesting it");
|
||||
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||
context.requestPermissions(permissions, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static public final int PERMISSIONS_REQUEST_CAMERA = 7;
|
||||
|
||||
static public boolean getCameraPermission(Activity context) {
|
||||
@ -156,12 +128,6 @@ public class Helper {
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Checks if external storage is available for read and write */
|
||||
private static boolean isExternalStorageWritable() {
|
||||
String state = Environment.getExternalStorageState();
|
||||
return Environment.MEDIA_MOUNTED.equals(state);
|
||||
}
|
||||
|
||||
static public void showKeyboard(Activity act) {
|
||||
InputMethodManager imm = (InputMethodManager) act.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
final View focus = act.getCurrentFocus();
|
||||
@ -339,7 +305,7 @@ public class Helper {
|
||||
|
||||
static public void setMoneroHome(Context context) {
|
||||
try {
|
||||
String home = getStorage(context, HOME_DIR).getAbsolutePath();
|
||||
String home = getStorage(context, MONERO_DIR).getAbsolutePath();
|
||||
Os.setenv("HOME", home, true);
|
||||
} catch (ErrnoException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
@ -355,7 +321,7 @@ public class Helper {
|
||||
|
||||
// TODO make the log levels refer to the WalletManagerFactory::LogLevel enum ?
|
||||
static public void initLogger(Context context, int level) {
|
||||
String home = getStorage(context, HOME_DIR).getAbsolutePath();
|
||||
String home = getStorage(context, MONERO_DIR).getAbsolutePath();
|
||||
WalletManager.initLogger(home + "/monerujo", "monerujo.log");
|
||||
if (level >= WalletManager.LOGLEVEL_SILENT)
|
||||
WalletManager.setLogLevel(level);
|
||||
|
@ -24,9 +24,10 @@ import android.os.Build;
|
||||
import android.security.KeyPairGeneratorSpec;
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.Base64;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -167,6 +168,11 @@ public class KeyStoreHelper {
|
||||
.remove(wallet).apply();
|
||||
}
|
||||
|
||||
public static void copyWalletUserPass(Context context, String srcWallet, String dstWallet) throws BrokenPasswordStoreException {
|
||||
final String pass = loadWalletUserPass(context, srcWallet);
|
||||
saveWalletUserPass(context, dstWallet, pass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a public and private key and stores it using the Android Key
|
||||
* Store, so that only this application will be able to access the keys.
|
||||
|
@ -0,0 +1,170 @@
|
||||
package com.m2049r.xmrwallet.util;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Environment;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.m2049r.xmrwallet.BuildConfig;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import timber.log.Timber;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class LegacyStorageHelper {
|
||||
final private File srcDir;
|
||||
final private File dstDir;
|
||||
|
||||
static public void migrateWallets(Context context) {
|
||||
try {
|
||||
if (isStorageMigrated(context)) return;
|
||||
if (!hasWritePermission(context)) {
|
||||
// nothing to migrate, so don't try again
|
||||
setStorageMigrated(context);
|
||||
return;
|
||||
}
|
||||
final File oldRoot = getWalletRoot();
|
||||
if (!oldRoot.exists()) {
|
||||
// nothing to migrate, so don't try again
|
||||
setStorageMigrated(context);
|
||||
return;
|
||||
}
|
||||
final File newRoot = Helper.getWalletRoot(context);
|
||||
(new LegacyStorageHelper(oldRoot, newRoot)).migrate();
|
||||
setStorageMigrated(context); // done it once - don't try again
|
||||
} catch (IllegalStateException ex) {
|
||||
Timber.d(ex);
|
||||
// nothing we can do here
|
||||
}
|
||||
}
|
||||
|
||||
public void migrate() {
|
||||
String addressPrefix = WalletManager.getInstance().addressPrefix();
|
||||
File[] wallets = srcDir.listFiles((dir, filename) -> filename.endsWith(".keys"));
|
||||
for (File wallet : wallets) {
|
||||
final String walletName = wallet.getName().substring(0, wallet.getName().length() - ".keys".length());
|
||||
if (addressPrefix.indexOf(getAddress(walletName).charAt(0)) < 0) {
|
||||
Timber.d("skipping %s", walletName);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
copy(walletName);
|
||||
} catch (IOException ex) { // something failed - try to clean up
|
||||
deleteDst(walletName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return "@" by default so we don't need to deal with null stuff
|
||||
private String getAddress(String walletName) {
|
||||
File addressFile = new File(srcDir, walletName + ".address.txt");
|
||||
if (!addressFile.exists()) return "@";
|
||||
try (BufferedReader addressReader = new BufferedReader(new FileReader(addressFile))) {
|
||||
return addressReader.readLine();
|
||||
} catch (IOException ex) {
|
||||
Timber.d(ex.getLocalizedMessage());
|
||||
}
|
||||
return "@";
|
||||
}
|
||||
|
||||
private void copy(String walletName) throws IOException {
|
||||
final String dstName = getUniqueName(dstDir, walletName);
|
||||
copyFile(new File(srcDir, walletName), new File(dstDir, dstName));
|
||||
copyFile(new File(srcDir, walletName + ".keys"), new File(dstDir, dstName + ".keys"));
|
||||
}
|
||||
|
||||
private void deleteDst(String walletName) {
|
||||
// do our best, but if it fails, it fails
|
||||
(new File(dstDir, walletName)).delete();
|
||||
(new File(dstDir, walletName + ".keys")).delete();
|
||||
}
|
||||
|
||||
private void copyFile(File src, File dst) throws IOException {
|
||||
if (!src.exists()) return;
|
||||
Timber.d("%s => %s", src.getAbsolutePath(), dst.getAbsolutePath());
|
||||
try (FileChannel inChannel = new FileInputStream(src).getChannel();
|
||||
FileChannel outChannel = new FileOutputStream(dst).getChannel()) {
|
||||
inChannel.transferTo(0, inChannel.size(), outChannel);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isExternalStorageWritable() {
|
||||
String state = Environment.getExternalStorageState();
|
||||
return Environment.MEDIA_MOUNTED.equals(state);
|
||||
}
|
||||
|
||||
private static File getWalletRoot() {
|
||||
if (!isExternalStorageWritable())
|
||||
throw new IllegalStateException();
|
||||
|
||||
// wallet folder for legacy (pre-Q) installations
|
||||
final String FLAVOR_SUFFIX =
|
||||
(BuildConfig.FLAVOR.startsWith("prod") ? "" : "." + BuildConfig.FLAVOR)
|
||||
+ (BuildConfig.DEBUG ? "-debug" : "");
|
||||
final String WALLET_DIR = "monerujo" + FLAVOR_SUFFIX;
|
||||
|
||||
File dir = new File(Environment.getExternalStorageDirectory(), WALLET_DIR);
|
||||
if (!dir.exists() || !dir.isDirectory())
|
||||
throw new IllegalStateException();
|
||||
return dir;
|
||||
}
|
||||
|
||||
private static boolean hasWritePermission(Context context) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
return context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern WALLET_PATTERN = Pattern.compile("^(.+) \\(([0-9]+)\\).keys$");
|
||||
|
||||
private static String getUniqueName(File root, String name) {
|
||||
if (!(new File(root, name + ".keys")).exists()) // <name> does not exist => it's ok to use
|
||||
return name;
|
||||
|
||||
File[] wallets = root.listFiles(
|
||||
(dir, filename) -> {
|
||||
Matcher m = WALLET_PATTERN.matcher(filename);
|
||||
if (m.find())
|
||||
return m.group(1).equals(name);
|
||||
else return false;
|
||||
});
|
||||
if (wallets.length == 0) return name + " (1)";
|
||||
int maxIndex = 0;
|
||||
for (File wallet : wallets) {
|
||||
try {
|
||||
final Matcher m = WALLET_PATTERN.matcher(wallet.getName());
|
||||
if (!m.find())
|
||||
throw new IllegalStateException("this must match as it did before");
|
||||
final int index = Integer.parseInt(m.group(2));
|
||||
if (index > maxIndex) maxIndex = index;
|
||||
} catch (NumberFormatException ex) {
|
||||
// this cannot happen & we can ignore it if it does
|
||||
}
|
||||
}
|
||||
return name + " (" + (maxIndex + 1) + ")";
|
||||
}
|
||||
|
||||
private static final String MIGRATED_KEY = "migrated_legacy_storage";
|
||||
|
||||
public static boolean isStorageMigrated(Context context) {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(MIGRATED_KEY, false);
|
||||
}
|
||||
|
||||
public static void setStorageMigrated(Context context) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(MIGRATED_KEY, true).apply();
|
||||
}
|
||||
}
|
64
app/src/main/java/com/m2049r/xmrwallet/util/ZipBackup.java
Normal file
64
app/src/main/java/com/m2049r/xmrwallet/util/ZipBackup.java
Normal file
@ -0,0 +1,64 @@
|
||||
package com.m2049r.xmrwallet.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ZipBackup {
|
||||
final private Context context;
|
||||
final private String walletName;
|
||||
|
||||
private ZipOutputStream zip;
|
||||
|
||||
public void writeTo(Uri zipUri) throws IOException {
|
||||
if (zip != null)
|
||||
throw new IllegalStateException("zip already initialized");
|
||||
try {
|
||||
zip = new ZipOutputStream(context.getContentResolver().openOutputStream(zipUri));
|
||||
|
||||
final File walletRoot = Helper.getWalletRoot(context);
|
||||
addFile(new File(walletRoot, walletName + ".keys"));
|
||||
addFile(new File(walletRoot, walletName));
|
||||
|
||||
zip.close();
|
||||
} finally {
|
||||
if (zip != null) zip.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void addFile(File file) throws IOException {
|
||||
if (!file.exists()) return; // ignore missing files (e.g. the cache file might not exist)
|
||||
ZipEntry entry = new ZipEntry(file.getName());
|
||||
zip.putNextEntry(entry);
|
||||
writeFile(file);
|
||||
zip.closeEntry();
|
||||
}
|
||||
|
||||
private void writeFile(File source) throws IOException {
|
||||
try (InputStream is = new FileInputStream(source)) {
|
||||
byte[] buffer = new byte[8192];
|
||||
int length;
|
||||
while ((length = is.read(buffer)) > 0) {
|
||||
zip.write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final SimpleDateFormat DATETIME_FORMATTER =
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss");
|
||||
|
||||
public String getBackupName() {
|
||||
return walletName + " " + DATETIME_FORMATTER.format(new Date());
|
||||
}
|
||||
}
|
139
app/src/main/java/com/m2049r/xmrwallet/util/ZipRestore.java
Normal file
139
app/src/main/java/com/m2049r/xmrwallet/util/ZipRestore.java
Normal file
@ -0,0 +1,139 @@
|
||||
package com.m2049r.xmrwallet.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import timber.log.Timber;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ZipRestore {
|
||||
final private Context context;
|
||||
final private Uri zipUri;
|
||||
|
||||
private File walletRoot;
|
||||
|
||||
private ZipInputStream zip;
|
||||
|
||||
public boolean restore() throws IOException {
|
||||
walletRoot = Helper.getWalletRoot(context);
|
||||
String walletName = testArchive();
|
||||
if (walletName == null) return false;
|
||||
|
||||
walletName = getUniqueName(walletName);
|
||||
|
||||
if (zip != null)
|
||||
throw new IllegalStateException("zip already initialized");
|
||||
try {
|
||||
zip = new ZipInputStream(context.getContentResolver().openInputStream(zipUri));
|
||||
for (ZipEntry entry = zip.getNextEntry(); entry != null; zip.closeEntry(), entry = zip.getNextEntry()) {
|
||||
File destination;
|
||||
final String name = entry.getName();
|
||||
if (name.endsWith(".keys")) {
|
||||
destination = new File(walletRoot, walletName + ".keys");
|
||||
} else if (name.endsWith(".address.txt")) {
|
||||
destination = new File(walletRoot, walletName + ".address.txt");
|
||||
} else {
|
||||
destination = new File(walletRoot, walletName);
|
||||
}
|
||||
writeFile(destination);
|
||||
}
|
||||
} finally {
|
||||
if (zip != null) zip.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void writeFile(File destination) throws IOException {
|
||||
try (OutputStream os = new FileOutputStream(destination)) {
|
||||
byte[] buffer = new byte[8192];
|
||||
int length;
|
||||
while ((length = zip.read(buffer)) > 0) {
|
||||
os.write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test the archive to contain files we expect & return the name of the contained wallet or null
|
||||
private String testArchive() {
|
||||
String walletName = null;
|
||||
boolean keys = false;
|
||||
ZipInputStream zipStream = null;
|
||||
try {
|
||||
zipStream = new ZipInputStream(context.getContentResolver().openInputStream(zipUri));
|
||||
for (ZipEntry entry = zipStream.getNextEntry(); entry != null;
|
||||
zipStream.closeEntry(), entry = zipStream.getNextEntry()) {
|
||||
if (entry.isDirectory())
|
||||
return null;
|
||||
final String name = entry.getName();
|
||||
if ((new File(name)).getParentFile() != null)
|
||||
return null;
|
||||
if (walletName == null) {
|
||||
if (name.endsWith(".keys")) {
|
||||
walletName = name.substring(0, name.length() - ".keys".length());
|
||||
keys = true; // we have they keys
|
||||
} else if (name.endsWith(".address.txt")) {
|
||||
walletName = name.substring(0, name.length() - ".address.txt".length());
|
||||
} else {
|
||||
walletName = name;
|
||||
}
|
||||
} else { // we have a wallet name
|
||||
if (name.endsWith(".keys")) {
|
||||
if (!name.equals(walletName + ".keys")) return null;
|
||||
keys = true; // we have they keys
|
||||
} else if (name.endsWith(".address.txt")) {
|
||||
if (!name.equals(walletName + ".address.txt")) return null;
|
||||
} else if (!name.equals(walletName)) return null;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
if (zipStream != null) zipStream.close();
|
||||
} catch (IOException ex) {
|
||||
Timber.w(ex);
|
||||
}
|
||||
}
|
||||
// we need the keys at least
|
||||
if (keys) return walletName;
|
||||
else return null;
|
||||
}
|
||||
|
||||
final static Pattern WALLET_PATTERN = Pattern.compile("^(.+) \\(([0-9]+)\\).keys$");
|
||||
|
||||
private String getUniqueName(String name) {
|
||||
if (!(new File(walletRoot, name + ".keys")).exists()) // <name> does not exist => it's ok to use
|
||||
return name;
|
||||
|
||||
File[] wallets = walletRoot.listFiles(
|
||||
(dir, filename) -> {
|
||||
Matcher m = WALLET_PATTERN.matcher(filename);
|
||||
if (m.find())
|
||||
return m.group(1).equals(name);
|
||||
else return false;
|
||||
});
|
||||
if (wallets.length == 0) return name + " (1)";
|
||||
int maxIndex = 0;
|
||||
for (File wallet : wallets) {
|
||||
try {
|
||||
final Matcher m = WALLET_PATTERN.matcher(wallet.getName());
|
||||
m.find();
|
||||
final int index = Integer.parseInt(m.group(2));
|
||||
if (index > maxIndex) maxIndex = index;
|
||||
} catch (NumberFormatException ex) {
|
||||
// this cannot happen & we can ignore it if it does
|
||||
}
|
||||
}
|
||||
return name + " (" + (maxIndex + 1) + ")";
|
||||
}
|
||||
}
|
@ -18,19 +18,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="48dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toStartOf="@+id/ibOptions"
|
||||
tools:text="My Wallet" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAddress"
|
||||
style="@style/MoneroText.Small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/tvName"
|
||||
android:layout_marginStart="48dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_toStartOf="@+id/ibOptions"
|
||||
tools:text="4AdkPJox...g3viqCuk" />
|
||||
tools:text="My Wallet" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/ibOptions"
|
||||
|
@ -19,7 +19,7 @@
|
||||
<item
|
||||
android:id="@+id/action_archive"
|
||||
android:orderInCategory="400"
|
||||
android:title="@string/menu_archive" />
|
||||
android:title="@string/menu_delete" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_info"
|
||||
|
@ -33,4 +33,9 @@
|
||||
android:title="@string/menu_daynight"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_restore"
|
||||
android:orderInCategory="600"
|
||||
android:title="@string/menu_restore"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Ajuda</string>
|
||||
<string name="menu_receive">Rebre</string>
|
||||
<string name="menu_rename">Canvi de nom</string>
|
||||
<string name="menu_archive">Arxivar</string>
|
||||
<string name="menu_backup">Còpia de seguretat</string>
|
||||
<string name="menu_changepw">Canvi de contrasenya</string>
|
||||
|
||||
@ -94,7 +93,6 @@
|
||||
|
||||
<string name="backup_success">Còpia de seguretat amb èxit</string>
|
||||
<string name="backup_failed">Còpia de seguretat fallida!</string>
|
||||
<string name="archive_failed">Arxiu fallit!</string>
|
||||
<string name="rename_failed">Canvi de nom fallit!</string>
|
||||
<string name="changepw_failed">Canvi de contrasenya fallit!</string>
|
||||
<string name="changepw_success">La contrasenya ha canviat</string>
|
||||
@ -273,9 +271,8 @@
|
||||
<string name="details_alert_no">Torna\'m enrere!</string>
|
||||
<string name="details_title">Detalls</string>
|
||||
|
||||
<string name="archive_alert_message">Es farà una còpia de seguretat del portamonedes i s\'esborrarà.</string>
|
||||
<string name="archive_alert_yes">Si, fes-ho!</string>
|
||||
<string name="archive_alert_no">No gràcies!</string>
|
||||
<string name="delete_alert_yes">Si, fes-ho!</string>
|
||||
<string name="delete_alert_no">No gràcies!</string>
|
||||
|
||||
<string name="fab_create_new">Crear un nou portamonedes</string>
|
||||
<string name="fab_restore_viewonly">Restablir portamonedes de només lectura</string>
|
||||
@ -420,4 +417,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<string name="menu_help">Hilfe</string>
|
||||
<string name="menu_receive">Empfangen</string>
|
||||
<string name="menu_rename">Umbenennen</string>
|
||||
<string name="menu_archive">Archivieren</string>
|
||||
<string name="menu_delete">Löschen</string>
|
||||
<string name="menu_backup">Backup</string>
|
||||
<string name="menu_changepw">Passwort ändern</string>
|
||||
|
||||
@ -94,7 +94,7 @@
|
||||
|
||||
<string name="backup_success">Backup erfolgreich</string>
|
||||
<string name="backup_failed">Backup fehlgeschlagen!</string>
|
||||
<string name="archive_failed">Archivierung fehlgeschlagen!</string>
|
||||
<string name="delete_failed">Löschen fehlgeschlagen!</string>
|
||||
<string name="rename_failed">Umbenennen fehlgeschlagen!</string>
|
||||
<string name="changepw_failed">Passwort ändern fehlgeschlagen!</string>
|
||||
<string name="changepw_success">Passwort geändert</string>
|
||||
@ -266,9 +266,9 @@
|
||||
<string name="details_alert_no">Nein, doch nicht!</string>
|
||||
<string name="details_title">Details</string>
|
||||
|
||||
<string name="archive_alert_message">Das Wallet wird archiviert und dann gelöscht!</string>
|
||||
<string name="archive_alert_yes">Ja, mach das!</string>
|
||||
<string name="archive_alert_no">Nein, danke!</string>
|
||||
<string name="delete_alert_message">Das Wallet wird gelöscht!</string>
|
||||
<string name="delete_alert_yes">Ja, mach das!</string>
|
||||
<string name="delete_alert_no">Nein, danke!</string>
|
||||
|
||||
<string name="fab_create_new">Neues Wallet erstellen</string>
|
||||
<string name="fab_restore_viewonly">View-Only-Wallet wiederherstellen</string>
|
||||
@ -422,4 +422,6 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Βοήθεια</string>
|
||||
<string name="menu_receive">Λήψη</string>
|
||||
<string name="menu_rename">Μετονομασία</string>
|
||||
<string name="menu_archive">Αρχειοθέτησε</string>
|
||||
<string name="menu_backup">Δημιουργία αντίγραφου ασφαλείας</string>
|
||||
|
||||
<string name="password_weak">Συνέχισε να πληκτρολογείς …</string>
|
||||
@ -92,7 +91,6 @@
|
||||
|
||||
<string name="backup_success">Η δημιουργία αντίγραφου ασφαλείας ήταν επιτυχής</string>
|
||||
<string name="backup_failed">Η δημιουργία αντίγραφου ασφαλείας απέτυχε!</string>
|
||||
<string name="archive_failed">Η αρχειοθέτηση απέτυχε!</string>
|
||||
<string name="rename_failed">Η μετονομασία απέτυχε!</string>
|
||||
|
||||
<string name="label_daemon">Κόμβος(Δαίμονας)</string>
|
||||
@ -241,9 +239,8 @@
|
||||
<string name="details_alert_no">Πήγαινε με πίσω!</string>
|
||||
<string name="details_title">Λεπτομέρειες</string>
|
||||
|
||||
<string name="archive_alert_message">Το πορτοφόλι θα δημιουργήσει αντίγραφο ασφαλείας και στη συνέχεια θα διαγραφεί!</string>
|
||||
<string name="archive_alert_yes">Ναι, κάνε αυτό!</string>
|
||||
<string name="archive_alert_no">Όχι ευχαριστώ!</string>
|
||||
<string name="delete_alert_yes">Ναι, κάνε αυτό!</string>
|
||||
<string name="delete_alert_no">Όχι ευχαριστώ!</string>
|
||||
|
||||
<string name="fab_create_new">Δημιουργία νέου πορτοφολιού</string>
|
||||
<string name="fab_restore_viewonly">Επαναφορά πορτοφολιού προβολής-μόνο</string>
|
||||
@ -422,4 +419,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Helpo</string>
|
||||
<string name="menu_receive">Ricevi</string>
|
||||
<string name="menu_rename">Renomi</string>
|
||||
<string name="menu_archive">Arkivo</string>
|
||||
<string name="menu_backup">Sekurkopio</string>
|
||||
<string name="menu_changepw">Ŝanĝi pasfrazon</string>
|
||||
|
||||
@ -94,7 +93,6 @@
|
||||
|
||||
<string name="backup_success">Sekurkopio sukcesis!</string>
|
||||
<string name="backup_failed">Sekurkopio malsukcesis!</string>
|
||||
<string name="archive_failed">Arkivado malsukcesis!</string>
|
||||
<string name="rename_failed">Renomado malsukcesis!</string>
|
||||
<string name="changepw_failed">Pasvortŝanĝo malsukcesis!</string>
|
||||
<string name="changepw_success">Pasvortŝanĝo sukcesis!</string>
|
||||
@ -273,9 +271,8 @@
|
||||
<string name="details_alert_no">Malantaŭen!</string>
|
||||
<string name="details_title">Detaloj</string>
|
||||
|
||||
<string name="archive_alert_message">La monujo sekurkopiĝos kaj poste forviŝiĝos!</string>
|
||||
<string name="archive_alert_yes">Jes, faru tion!</string>
|
||||
<string name="archive_alert_no">Ne dankon!</string>
|
||||
<string name="delete_alert_yes">Jes, faru tion!</string>
|
||||
<string name="delete_alert_no">Ne dankon!</string>
|
||||
|
||||
<string name="fab_create_new">Krei novan monujon</string>
|
||||
<string name="fab_restore_viewonly">Restaŭri nurvidan monujon</string>
|
||||
@ -422,4 +419,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Ayuda</string>
|
||||
<string name="menu_receive">Recibir</string>
|
||||
<string name="menu_rename">Renombrar</string>
|
||||
<string name="menu_archive">Archivar</string>
|
||||
<string name="menu_backup">Copia de seguridad</string>
|
||||
<string name="menu_changepw">Cambiar contraseña</string>
|
||||
|
||||
@ -49,7 +48,6 @@
|
||||
|
||||
<string name="backup_success">Copia de seguridad exitosa</string>
|
||||
<string name="backup_failed">¡Copia de seguridad fallida!</string>
|
||||
<string name="archive_failed">¡Archivado fallido!</string>
|
||||
<string name="rename_failed">¡Cambio de nombre fallido!</string>
|
||||
<string name="changepw_failed">¡Cambio de contraseña fallido!</string>
|
||||
<string name="changepw_success">Contraseña cambiada</string>
|
||||
@ -209,9 +207,9 @@
|
||||
<string name="details_alert_no">¡Llévame de vuelta!</string>
|
||||
<string name="details_title">Detalles</string>
|
||||
|
||||
<string name="archive_alert_message">¡El monedero será copiado y después borrado!</string>
|
||||
<string name="archive_alert_yes">¡Sí, hazlo!</string>
|
||||
<string name="archive_alert_no">¡No, gracias!</string>
|
||||
<string name="delete_alert_message">¡El monedero será borrado!</string>
|
||||
<string name="delete_alert_yes">¡Sí, hazlo!</string>
|
||||
<string name="delete_alert_no">¡No, gracias!</string>
|
||||
|
||||
<string name="fab_create_new">Crear nuevo monedero</string>
|
||||
<string name="fab_restore_viewonly">Restaurar monedero de sólo vista</string>
|
||||
@ -413,4 +411,9 @@
|
||||
<string name="subaddress_select_label">Elige una subdirección</string>
|
||||
<string name="subaddress_details_hint">Presiona largo para ver detalles</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Abi</string>
|
||||
<string name="menu_receive">Küsi raha</string>
|
||||
<string name="menu_rename">Nimeta ümber</string>
|
||||
<string name="menu_archive">Arhiveeri</string>
|
||||
<string name="menu_backup">Tagavarakoopia</string>
|
||||
<string name="menu_changepw">Vaheta parooli</string>
|
||||
|
||||
@ -93,7 +92,6 @@
|
||||
<string name="service_progress">Teen ettevalmistusi …\nSee võib aega võtta!</string>
|
||||
|
||||
<string name="backup_failed">Tagavarakoopia ebaõnnestus!</string>
|
||||
<string name="archive_failed">Arhiveerimine ebaõnnestus!</string>
|
||||
<string name="rename_failed">Ümber nimetamine ebaõnnestus!</string>
|
||||
<string name="changepw_failed">Parooli vahetamine ebaõnnestus!</string>
|
||||
<string name="changepw_success">Parool vahetatud</string>
|
||||
@ -268,9 +266,8 @@
|
||||
<string name="details_alert_no">Vii mind tagasi!</string>
|
||||
<string name="details_title">Lisainfo</string>
|
||||
|
||||
<string name="archive_alert_message">Rahakotist tehakse tagavarakoopia ja siis see kustutatakse!</string>
|
||||
<string name="archive_alert_yes">Täpselt nii!</string>
|
||||
<string name="archive_alert_no">Ei, tänan!</string>
|
||||
<string name="delete_alert_yes">Täpselt nii!</string>
|
||||
<string name="delete_alert_no">Ei, tänan!</string>
|
||||
|
||||
<string name="fab_create_new">Loo uus rahakott</string>
|
||||
<string name="fab_restore_viewonly">Taasta rahakott vaatamiseks</string>
|
||||
@ -420,4 +417,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Aide</string>
|
||||
<string name="menu_receive">Recevoir</string>
|
||||
<string name="menu_rename">Renommer</string>
|
||||
<string name="menu_archive">Archiver</string>
|
||||
<string name="menu_backup">Sauvegarder</string>
|
||||
<string name="menu_changepw">Modifier Phrase secrète</string>
|
||||
|
||||
@ -95,7 +94,6 @@
|
||||
|
||||
<string name="backup_success">Sauvegarde réussie</string>
|
||||
<string name="backup_failed">Sauvegarde Échouée !</string>
|
||||
<string name="archive_failed">Archivage Échouée !</string>
|
||||
<string name="rename_failed">Renommage Échoué !</string>
|
||||
<string name="changepw_failed">Modification du mot de passe Échouée !</string>
|
||||
<string name="changepw_success">Modification du mot de passe réussie</string>
|
||||
@ -269,9 +267,9 @@
|
||||
<string name="details_alert_no">Non merci !</string>
|
||||
<string name="details_title">Détails</string>
|
||||
|
||||
<string name="archive_alert_message">Le portefeuille sera sauvegardé puis supprimé !</string>
|
||||
<string name="archive_alert_yes">Oui, procéder !</string>
|
||||
<string name="archive_alert_no">Non merci !</string>
|
||||
<string name="delete_alert_message">Le portefeuille sera supprimé !</string>
|
||||
<string name="delete_alert_yes">Oui, procéder !</string>
|
||||
<string name="delete_alert_no">Non merci !</string>
|
||||
|
||||
<string name="fab_create_new">Créer un nouveau portefeuille</string>
|
||||
<string name="fab_restore_viewonly">Restaurer un portefeuille d\'audit</string>
|
||||
@ -426,4 +424,9 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Segítség</string>
|
||||
<string name="menu_receive">Fogadás</string>
|
||||
<string name="menu_rename">Átnevezés</string>
|
||||
<string name="menu_archive">Archiválás</string>
|
||||
<string name="menu_backup">Biztonsági mentés</string>
|
||||
<string name="menu_changepw">Jelszómódosítás</string>
|
||||
|
||||
@ -93,7 +92,6 @@
|
||||
<string name="service_progress">Műveletek befejezése…\nEz eltarthat egy ideig!</string>
|
||||
|
||||
<string name="backup_failed">Sikertelen biztonsági mentés!</string>
|
||||
<string name="archive_failed">Sikertelen archiválás!</string>
|
||||
<string name="rename_failed">Sikertelen átnevezés!</string>
|
||||
<string name="changepw_failed">Sikertelen jelszómódosítás!</string>
|
||||
<string name="changepw_success">Jelszó megváltoztatva</string>
|
||||
@ -266,9 +264,8 @@
|
||||
<string name="details_alert_no">Inkább ne!</string>
|
||||
<string name="details_title">Részletek</string>
|
||||
|
||||
<string name="archive_alert_message">A tárcáról biztonsági másolat készül, majd törlésre fog kerülni!</string>
|
||||
<string name="archive_alert_yes">Igen, mehet!</string>
|
||||
<string name="archive_alert_no">Inkább ne!</string>
|
||||
<string name="delete_alert_yes">Igen, mehet!</string>
|
||||
<string name="delete_alert_no">Inkább ne!</string>
|
||||
|
||||
<string name="fab_create_new">Új tárca létrehozása</string>
|
||||
<string name="fab_restore_viewonly">Figyelőtárca visszaállítása</string>
|
||||
@ -424,4 +421,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Aiuto</string>
|
||||
<string name="menu_receive">Ricevi</string>
|
||||
<string name="menu_rename">Rinomina</string>
|
||||
<string name="menu_archive">Archivia</string>
|
||||
<string name="menu_backup">Backup</string>
|
||||
<string name="menu_changepw">Cambia passphrase</string>
|
||||
|
||||
@ -95,7 +94,6 @@
|
||||
|
||||
<string name="backup_success">Backup effettuato con successo</string>
|
||||
<string name="backup_failed">Backup fallito!</string>
|
||||
<string name="archive_failed">Archiviazione fallita!</string>
|
||||
<string name="rename_failed">Rinomina fallita!</string>
|
||||
<string name="changepw_failed">Modifica password fallita!</string>
|
||||
<string name="changepw_success">Password cambiata</string>
|
||||
@ -268,9 +266,9 @@
|
||||
<string name="details_alert_no">Torna indietro!</string>
|
||||
<string name="details_title">Dettagli</string>
|
||||
|
||||
<string name="archive_alert_message">Il portafoglio verrà archiviato e poi eliminato!</string>
|
||||
<string name="archive_alert_yes">Sì, procedi!</string>
|
||||
<string name="archive_alert_no">No grazie!</string>
|
||||
<string name="delete_alert_message">Il portafoglio verrà eliminato!</string>
|
||||
<string name="delete_alert_yes">Sì, procedi!</string>
|
||||
<string name="delete_alert_no">No grazie!</string>
|
||||
|
||||
<string name="fab_create_new">Crea un nuovo portafoglio</string>
|
||||
<string name="fab_restore_viewonly">Recupera un portafoglio solo-visualizzazione</string>
|
||||
@ -425,4 +423,9 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">ヘルプ</string>
|
||||
<string name="menu_receive">受取り</string>
|
||||
<string name="menu_rename">名前の変更</string>
|
||||
<string name="menu_archive">アーカイブ</string>
|
||||
<string name="menu_backup">バックアップ</string>
|
||||
<string name="menu_changepw">パスフレーズの変更</string>
|
||||
|
||||
@ -93,7 +92,6 @@
|
||||
<string name="service_progress">準備中 …\nしばらく時間がかかるかもしれません!</string>
|
||||
|
||||
<string name="backup_failed">バックアップに失敗しました!</string>
|
||||
<string name="archive_failed">アーカイブに失敗しました!</string>
|
||||
<string name="rename_failed">名前の変更に失敗しました!</string>
|
||||
<string name="changepw_failed">パスワード変更に失敗しました!</string>
|
||||
<string name="changepw_success">パスワードが変更されました</string>
|
||||
@ -273,9 +271,8 @@
|
||||
<string name="details_alert_no">戻ります!</string>
|
||||
<string name="details_title">詳細</string>
|
||||
|
||||
<string name="archive_alert_message">ウォレットはバックアップされてから削除されます!</string>
|
||||
<string name="archive_alert_yes">はい、お願いします!</string>
|
||||
<string name="archive_alert_no">いいえ、結構です!</string>
|
||||
<string name="delete_alert_yes">はい、お願いします!</string>
|
||||
<string name="delete_alert_no">いいえ、結構です!</string>
|
||||
|
||||
<string name="fab_create_new">新しいウォレットの作成</string>
|
||||
<string name="fab_restore_viewonly">閲覧専用ウォレットを復元</string>
|
||||
@ -425,4 +422,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Hjelp</string>
|
||||
<string name="menu_receive">Motta</string>
|
||||
<string name="menu_rename">Gi nytt navn</string>
|
||||
<string name="menu_archive">Arkiver</string>
|
||||
<string name="menu_backup">Backup</string>
|
||||
<string name="menu_changepw">[Forandre passord]</string>
|
||||
|
||||
@ -93,7 +92,6 @@
|
||||
|
||||
<string name="backup_success">Backup suksessfull</string>
|
||||
<string name="backup_failed">Backup feila!</string>
|
||||
<string name="archive_failed">Arkivering feila!</string>
|
||||
<string name="rename_failed">Kunne ikke gi nytt navn!</string>
|
||||
<string name="changepw_failed">[Passordforandring feila!]</string>
|
||||
<string name="changepw_success">[Passord forandra]</string>
|
||||
@ -266,9 +264,8 @@
|
||||
<string name="details_alert_no">Ta meg tilbake!</string>
|
||||
<string name="details_title">Detaljer</string>
|
||||
|
||||
<string name="archive_alert_message">Lommeboka vil bli backa opp og så sletta!</string>
|
||||
<string name="archive_alert_yes">Ja, gjør det!</string>
|
||||
<string name="archive_alert_no">Nei takk!</string>
|
||||
<string name="delete_alert_yes">Ja, gjør det!</string>
|
||||
<string name="delete_alert_no">Nei takk!</string>
|
||||
|
||||
<string name="fab_create_new">Lag ny lommebok</string>
|
||||
<string name="fab_restore_viewonly">Gjenoprett bare-se lommebok</string>
|
||||
@ -422,4 +419,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Help</string>
|
||||
<string name="menu_receive">Ontvangen</string>
|
||||
<string name="menu_rename">Hernoemen</string>
|
||||
<string name="menu_archive">Archiveren</string>
|
||||
<string name="menu_backup">Back-up</string>
|
||||
<string name="menu_changepw">Wachtzin wijzigen</string>
|
||||
|
||||
@ -93,7 +92,6 @@
|
||||
<string name="service_progress">Bezig met voltooien…\nDit kan even duren.</string>
|
||||
|
||||
<string name="backup_failed">Back-up mislukt!</string>
|
||||
<string name="archive_failed">Archiveren mislukt!</string>
|
||||
<string name="rename_failed">Hernoemen mislukt!</string>
|
||||
<string name="changepw_failed">Wachtwoord wijzigen mislukt!</string>
|
||||
<string name="changepw_success">Wachtwoord is gewijzigd</string>
|
||||
@ -263,9 +261,9 @@
|
||||
<string name="details_alert_no">Ga terug!</string>
|
||||
<string name="details_title">Details</string>
|
||||
|
||||
<string name="archive_alert_message">Er wordt een back-up gemaakt en daarna wordt de portemonnee verwijderd!</string>
|
||||
<string name="archive_alert_yes">Ja, doe dat!</string>
|
||||
<string name="archive_alert_no">Nee, niet doen!</string>
|
||||
<string name="delete_alert_message">Er wordt de portemonnee verwijderd!</string>
|
||||
<string name="delete_alert_yes">Ja, doe dat!</string>
|
||||
<string name="delete_alert_no">Nee, niet doen!</string>
|
||||
|
||||
<string name="fab_create_new">Nieuwe portemonnee</string>
|
||||
<string name="fab_restore_viewonly">Alleen-lezen portemonnee herstellen</string>
|
||||
@ -422,4 +420,9 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Ajuda</string>
|
||||
<string name="menu_receive">Receber</string>
|
||||
<string name="menu_rename">Renomear</string>
|
||||
<string name="menu_archive">Arquivar</string>
|
||||
<string name="menu_backup">Backup</string>
|
||||
<string name="menu_changepw">Alterar Senha</string>
|
||||
|
||||
@ -93,7 +92,6 @@
|
||||
<string name="service_progress">Finalizando o processo …\nPode demorar um pouco</string>
|
||||
|
||||
<string name="backup_failed">Erro ao criar backup!</string>
|
||||
<string name="archive_failed">Erro ao arquivar!</string>
|
||||
<string name="rename_failed">Erro ao renomear!</string>
|
||||
<string name="changepw_failed">Erro ao alterar senha!</string>
|
||||
<string name="changepw_success">Senha alterada</string>
|
||||
@ -265,9 +263,8 @@
|
||||
<string name="details_alert_no">Tire-me daqui!</string>
|
||||
<string name="details_title">Detalhes</string>
|
||||
|
||||
<string name="archive_alert_message">Farei um backup da carteira e depois vou deletá-la!</string>
|
||||
<string name="archive_alert_yes">Sim, pode fazer!</string>
|
||||
<string name="archive_alert_no">Não, obrigado!</string>
|
||||
<string name="delete_alert_yes">Sim, pode fazer!</string>
|
||||
<string name="delete_alert_no">Não, obrigado!</string>
|
||||
|
||||
<string name="fab_create_new">Criar nova carteira</string>
|
||||
<string name="fab_restore_viewonly">Restaurar carteira \"Somente leitura\"</string>
|
||||
@ -414,4 +411,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Ajuda</string>
|
||||
<string name="menu_receive">Receber</string>
|
||||
<string name="menu_rename">Renomear</string>
|
||||
<string name="menu_archive">Arquivar</string>
|
||||
<string name="menu_backup">Cópia de segurança</string>
|
||||
<string name="menu_changepw">Alterar palavra passe</string>
|
||||
|
||||
@ -93,7 +92,6 @@
|
||||
<string name="service_progress">A concluir o processamento …\nIsto pode demorar!</string>
|
||||
|
||||
<string name="backup_failed">Cópia de segurança falhou!</string>
|
||||
<string name="archive_failed">Erro ao arquivar!</string>
|
||||
<string name="rename_failed">Erro ao renomear!</string>
|
||||
<string name="changepw_failed">Erro ao alterar a palavra passe!</string>
|
||||
<string name="changepw_success">Palavra passe alterada</string>
|
||||
@ -265,9 +263,8 @@
|
||||
<string name="details_alert_no">Volta atrás!</string>
|
||||
<string name="details_title">Detalhes</string>
|
||||
|
||||
<string name="archive_alert_message">Vai ser feita uma cópia de segurança da carteira e depois será apagada!</string>
|
||||
<string name="archive_alert_yes">Sim, faz isso!</string>
|
||||
<string name="archive_alert_no">Não obrigado!</string>
|
||||
<string name="delete_alert_yes">Sim, faz isso!</string>
|
||||
<string name="delete_alert_no">Não obrigado!</string>
|
||||
|
||||
<string name="fab_create_new">Criar nova carteira</string>
|
||||
<string name="fab_restore_viewonly">Restaurar carteira apenas de visualização</string>
|
||||
@ -426,4 +423,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Ajutor</string>
|
||||
<string name="menu_receive">Primește</string>
|
||||
<string name="menu_rename">Redenumește</string>
|
||||
<string name="menu_archive">Arhivă</string>
|
||||
<string name="menu_backup">Backup</string>
|
||||
|
||||
<string name="password_weak">Continuă …</string>
|
||||
@ -92,7 +91,6 @@
|
||||
|
||||
<string name="backup_success">Copia de rezervă creată cu succes</string>
|
||||
<string name="backup_failed">Copia de rezervă a eșuat!</string>
|
||||
<string name="archive_failed">Arhivarea a eșuat!</string>
|
||||
<string name="rename_failed">Redenumirea a eșuat!</string>
|
||||
|
||||
<string name="label_daemon">Nodul</string>
|
||||
@ -241,9 +239,8 @@
|
||||
<string name="details_alert_no">Du-mă înapoi!</string>
|
||||
<string name="details_title">Detalii</string>
|
||||
|
||||
<string name="archive_alert_message">Voi face o copie de siguranță a portofelului apoi va fi șters!</string>
|
||||
<string name="archive_alert_yes">Da, fă asta!</string>
|
||||
<string name="archive_alert_no">Nu mersi!</string>
|
||||
<string name="delete_alert_yes">Da, fă asta!</string>
|
||||
<string name="delete_alert_no">Nu mersi!</string>
|
||||
|
||||
<string name="fab_create_new">Creeaza portofel nou</string>
|
||||
<string name="fab_restore_viewonly">Restaurează portofel-vizualizare</string>
|
||||
@ -422,4 +419,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Помощь</string>
|
||||
<string name="menu_receive">Получить</string>
|
||||
<string name="menu_rename">Переименовать</string>
|
||||
<string name="menu_archive">Архив</string>
|
||||
<string name="menu_backup">Резервная копия</string>
|
||||
<string name="menu_changepw">Изменить пароль</string>
|
||||
|
||||
@ -94,7 +93,6 @@
|
||||
<string name="service_progress">Для данного действия …\nМожет потребоваться некоторое время!</string>
|
||||
|
||||
<string name="backup_failed">Резервное копирование произошло с ошибкой!</string>
|
||||
<string name="archive_failed">Архивирование произошло с ошибкой!</string>
|
||||
<string name="rename_failed">Переименование произошло с ошибкой!</string>
|
||||
<string name="changepw_failed">Изменение пароля произошло с ошибкой!</string>
|
||||
<string name="changepw_success">Изменение пароля выполено успешно</string>
|
||||
@ -267,9 +265,9 @@
|
||||
<string name="details_alert_no">Верните меня обратно!</string>
|
||||
<string name="details_title">Подробная информация</string>
|
||||
|
||||
<string name="archive_alert_message">Этот кошелек будет скопирован, а затем удален!</string>
|
||||
<string name="archive_alert_yes">Да, сделай это!</string>
|
||||
<string name="archive_alert_no">Нет, спасибо!</string>
|
||||
<string name="delete_alert_message">Этот кошелек будет удален!</string>
|
||||
<string name="delete_alert_yes">Да, сделай это!</string>
|
||||
<string name="delete_alert_no">Нет, спасибо!</string>
|
||||
|
||||
<string name="fab_create_new">Создать новый кошелек</string>
|
||||
<string name="fab_restore_viewonly">Восстановить кошелек только для просмотра</string>
|
||||
@ -426,4 +424,9 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Pomoc</string>
|
||||
<string name="menu_receive">Prijať</string>
|
||||
<string name="menu_rename">Premenovať</string>
|
||||
<string name="menu_archive">Archivovať</string>
|
||||
<string name="menu_backup">Záloha</string>
|
||||
<string name="menu_changepw">Zmena Hesla</string>
|
||||
|
||||
@ -94,7 +93,6 @@
|
||||
<string name="service_progress">Balím si veci …\nMôže to chvíľu trvať!</string>
|
||||
|
||||
<string name="backup_failed">Zálohovanie zlyhalo!</string>
|
||||
<string name="archive_failed">Archivácia zlyhala!</string>
|
||||
<string name="rename_failed">Premenovanie zlyhalo!</string>
|
||||
<string name="changepw_failed">Zmena hesla zlyhala!</string>
|
||||
<string name="changepw_success">Heslo zmenené</string>
|
||||
@ -264,9 +262,9 @@
|
||||
<string name="details_alert_no">Naspäť!</string>
|
||||
<string name="details_title">Detaily</string>
|
||||
|
||||
<string name="archive_alert_message">Peňaženka bude zálohovaná a následne zmazaná!</string>
|
||||
<string name="archive_alert_yes">Áno, poďme na to!</string>
|
||||
<string name="archive_alert_no">Nie, díky!</string>
|
||||
<string name="delete_alert_message">Peňaženka bude zmazaná!</string>
|
||||
<string name="delete_alert_yes">Áno, poďme na to!</string>
|
||||
<string name="delete_alert_no">Nie, díky!</string>
|
||||
|
||||
<string name="fab_create_new">Vytvor novú peňaženku</string>
|
||||
<string name="fab_restore_viewonly">Obnoviť prezeraciu peňaženku</string>
|
||||
@ -423,4 +421,9 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Pomoć</string>
|
||||
<string name="menu_receive">Primi</string>
|
||||
<string name="menu_rename">Preimenuj</string>
|
||||
<string name="menu_archive">Arhiva</string>
|
||||
<string name="menu_backup">Bekap</string>
|
||||
<string name="menu_changepw">Promeni lozinku</string>
|
||||
|
||||
@ -94,7 +93,6 @@
|
||||
|
||||
<string name="backup_success">Bekap uspešan</string>
|
||||
<string name="backup_failed">Bekap neuspeo!</string>
|
||||
<string name="archive_failed">Arhiviranje neuspelo!</string>
|
||||
<string name="rename_failed">Preimenovanje neuspelo!</string>
|
||||
<string name="changepw_failed">Promena lozinke neuspela!</string>
|
||||
<string name="changepw_success">Lozinka promenjena</string>
|
||||
@ -274,9 +272,9 @@
|
||||
<string name="details_alert_no">Vrati me nazad!</string>
|
||||
<string name="details_title">Detalji</string>
|
||||
|
||||
<string name="archive_alert_message">Novčanik će biti bekapovan a potom obrisan!</string>
|
||||
<string name="archive_alert_yes">Da, uradi to!</string>
|
||||
<string name="archive_alert_no">Ne, hvala!</string>
|
||||
<string name="delete_alert_message">Novčanik će biti obrisan!</string>
|
||||
<string name="delete_alert_yes">Da, uradi to!</string>
|
||||
<string name="delete_alert_no">Ne, hvala!</string>
|
||||
|
||||
<string name="fab_create_new">Kreiraj novi novčanik</string>
|
||||
<string name="fab_restore_viewonly">Obnovi novčanik za pregled</string>
|
||||
@ -421,4 +419,9 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Hjälp</string>
|
||||
<string name="menu_receive">Ta emot</string>
|
||||
<string name="menu_rename">Byt namn</string>
|
||||
<string name="menu_archive">Arkivera</string>
|
||||
<string name="menu_backup">Säkerhetskopiera</string>
|
||||
<string name="menu_changepw">Ändra lösenfras</string>
|
||||
|
||||
@ -94,7 +93,6 @@
|
||||
|
||||
<string name="backup_success">Säkerhetskopia sparad</string>
|
||||
<string name="backup_failed">Det gick inte att säkerhetskopiera!</string>
|
||||
<string name="archive_failed">Det gick inte att arkivera!</string>
|
||||
<string name="rename_failed">Det gick inte att byta namn!</string>
|
||||
<string name="changepw_failed">Det gick inte att ändra lösenord!</string>
|
||||
<string name="changepw_success">Lösenordet har ändrats</string>
|
||||
@ -254,9 +252,8 @@
|
||||
<string name="details_alert_no">Ta mig tillbaka!</string>
|
||||
<string name="details_title">Detaljer</string>
|
||||
|
||||
<string name="archive_alert_message">Plånboken kommer att säkerhetskopieras och sedan tas bort!</string>
|
||||
<string name="archive_alert_yes">Ja, gör det!</string>
|
||||
<string name="archive_alert_no">Nej tack!</string>
|
||||
<string name="delete_alert_yes">Ja, gör det!</string>
|
||||
<string name="delete_alert_no">Nej tack!</string>
|
||||
|
||||
<string name="fab_create_new">Skapa ny plånbok</string>
|
||||
<string name="fab_restore_viewonly">Återställ granskningsplånbok</string>
|
||||
@ -414,4 +411,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">Допомога</string>
|
||||
<string name="menu_receive">Отримати</string>
|
||||
<string name="menu_rename">Перейменувати</string>
|
||||
<string name="menu_archive">Архів</string>
|
||||
<string name="menu_backup">Резервна копія</string>
|
||||
<string name="menu_changepw">Змінити пароль</string>
|
||||
|
||||
@ -94,7 +93,6 @@
|
||||
<string name="service_progress">Для даної дії …\nМоже знадобитися деякий час!</string>
|
||||
|
||||
<string name="backup_failed">Резервне копіювання відбулося з помилкою!</string>
|
||||
<string name="archive_failed">Архівування відбулося з помилкою!</string>
|
||||
<string name="rename_failed">Перейменування відбулося з помилкою!</string>
|
||||
<string name="changepw_failed">Зміна паролю відбулася з помилкою!</string>
|
||||
<string name="changepw_success">Зміну паролю виконано успішно</string>
|
||||
@ -267,9 +265,9 @@
|
||||
<string name="details_alert_no">Поверніть мене назад!</string>
|
||||
<string name="details_title">Детальна інформація</string>
|
||||
|
||||
<string name="archive_alert_message">Цей гаманець буде скопійовано, а потім знищено!</string>
|
||||
<string name="archive_alert_yes">Так, зроби це!</string>
|
||||
<string name="archive_alert_no">Ні, дякую!</string>
|
||||
<string name="delete_alert_message">Цей гаманець буде знищено!</string>
|
||||
<string name="delete_alert_yes">Так, зроби це!</string>
|
||||
<string name="delete_alert_no">Ні, дякую!</string>
|
||||
|
||||
<string name="fab_create_new">Створити новий гаманець</string>
|
||||
<string name="fab_restore_viewonly">Відновити гаманець тільки для перегляду</string>
|
||||
@ -426,4 +424,9 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -7,7 +7,6 @@
|
||||
<string name="menu_help">帮助</string>
|
||||
<string name="menu_receive">收款</string>
|
||||
<string name="menu_rename">重命名</string>
|
||||
<string name="menu_archive">存档</string>
|
||||
<string name="menu_backup">备份</string>
|
||||
<string name="menu_changepw">修改密码</string>
|
||||
<string name="password_weak">强度不够哦 …</string>
|
||||
@ -70,7 +69,6 @@
|
||||
<string name="service_progress">整合中…\n这将花上不少时间</string>
|
||||
<string name="backup_success">备份成功</string>
|
||||
<string name="backup_failed">备份失败!</string>
|
||||
<string name="archive_failed">存档失败!</string>
|
||||
<string name="rename_failed">重命名失败!</string>
|
||||
<string name="changepw_failed">密码修改失败!</string>
|
||||
<string name="changepw_success">密码已修改</string>
|
||||
@ -213,9 +211,8 @@
|
||||
<string name="details_alert_yes">安全</string>
|
||||
<string name="details_alert_no">返回上一步</string>
|
||||
<string name="details_title">详情</string>
|
||||
<string name="archive_alert_message">即将开始备份钱包,完成后将删除钱包!</string>
|
||||
<string name="archive_alert_yes">好的,开始吧!</string>
|
||||
<string name="archive_alert_no">不用了,谢谢!</string>
|
||||
<string name="delete_alert_yes">好的,开始吧!</string>
|
||||
<string name="delete_alert_no">不用了,谢谢!</string>
|
||||
<string name="fab_create_new">创建新钱包</string>
|
||||
<string name="fab_restore_viewonly">恢复只读钱包</string>
|
||||
<string name="fab_restore_key">通过私钥恢复钱包</string>
|
||||
@ -346,4 +343,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<string name="menu_help">幫助</string>
|
||||
<string name="menu_receive">收款</string>
|
||||
<string name="menu_rename">重新命名</string>
|
||||
<string name="menu_archive">封存</string>
|
||||
<string name="menu_backup">備份</string>
|
||||
<string name="menu_changepw">更改密碼</string>
|
||||
|
||||
@ -95,7 +94,6 @@
|
||||
|
||||
<string name="backup_success">備份成功</string>
|
||||
<string name="backup_failed">備份失敗!</string>
|
||||
<string name="archive_failed">封存失敗!</string>
|
||||
<string name="rename_failed">重新命名失敗!</string>
|
||||
<string name="changepw_failed">密碼更改失敗!</string>
|
||||
<string name="changepw_success">密碼更改成功</string>
|
||||
@ -265,9 +263,8 @@
|
||||
<string name="details_alert_no">不看了!</string>
|
||||
<string name="details_title">詳細資訊</string>
|
||||
|
||||
<string name="archive_alert_message">錢包檔案將會被備份並且於列表中刪除!</string>
|
||||
<string name="archive_alert_yes">好的!</string>
|
||||
<string name="archive_alert_no">不了!</string>
|
||||
<string name="delete_alert_yes">好的!</string>
|
||||
<string name="delete_alert_no">不了!</string>
|
||||
|
||||
<string name="fab_create_new">建立新錢包</string>
|
||||
<string name="fab_restore_viewonly">回復唯讀錢包</string>
|
||||
@ -421,4 +418,10 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<string name="menu_help">Help</string>
|
||||
<string name="menu_receive">Receive</string>
|
||||
<string name="menu_rename">Rename</string>
|
||||
<string name="menu_archive">Archive</string>
|
||||
<string name="menu_delete">Delete</string>
|
||||
<string name="menu_backup">Backup</string>
|
||||
<string name="menu_changepw">Change Passphrase</string>
|
||||
|
||||
@ -86,16 +86,16 @@
|
||||
<string name="label_send_address">Destination Address</string>
|
||||
<string name="label_send_notes">Notes</string>
|
||||
|
||||
<string name="backup_progress">Backup in progress</string>
|
||||
<string name="archive_progress">Archive in progress</string>
|
||||
<string name="rename_progress">Rename in progress</string>
|
||||
<string name="backup_progress">Backup in progress</string><!--TODO deleteme-->
|
||||
<string name="archive_progress">Archive in progress</string><!--TODO deleteme-->
|
||||
<string name="rename_progress">Rename in progress</string><!--TODO deleteme-->
|
||||
<string name="changepw_progress">Change Password in progress</string>
|
||||
|
||||
<string name="service_progress">Wrapping things up …\nThis can take a while!</string>
|
||||
|
||||
<string name="backup_success">Backup successful</string>
|
||||
<string name="backup_failed">Backup failed!</string>
|
||||
<string name="archive_failed">Archive failed!</string>
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
<string name="rename_failed">Rename failed!</string>
|
||||
<string name="changepw_failed">Change Password failed!</string>
|
||||
<string name="changepw_success">Password changed</string>
|
||||
@ -132,7 +132,7 @@
|
||||
<string name="bad_saved_password">Saved password is incorrect.\nPlease enter password manually.</string>
|
||||
<string name="bad_wallet">Wallet does not exist!</string>
|
||||
<string name="prompt_daemon_missing">Node must be set!</string>
|
||||
<string name="prompt_wrong_net">Wallet does not match selected net</string>
|
||||
<string name="prompt_wrong_net">Wallet does not match selected net</string><!--TODO deleteme-->
|
||||
|
||||
<string name="label_watchonly">(Watch Only)</string>
|
||||
|
||||
@ -278,9 +278,9 @@
|
||||
<string name="details_alert_no">Take me back!</string>
|
||||
<string name="details_title">Details</string>
|
||||
|
||||
<string name="archive_alert_message">The wallet will be backed up and then deleted!</string>
|
||||
<string name="archive_alert_yes">Yes, do that!</string>
|
||||
<string name="archive_alert_no">No thanks!</string>
|
||||
<string name="delete_alert_message">The wallet will be deleted!</string>
|
||||
<string name="delete_alert_yes">Yes, do that!</string>
|
||||
<string name="delete_alert_no">No thanks!</string>
|
||||
|
||||
<string-array name="currency" translatable="false">
|
||||
<item>EUR</item>
|
||||
@ -495,4 +495,6 @@
|
||||
<string name="subaddress_select_label">Select a subaddress</string>
|
||||
<string name="subaddress_details_hint">Long-press for details</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user