Merge pull request #38 from m2049r/feature_rename_wallet
Rename/Backup/Archive Wallet FIles
This commit is contained in:
commit
fae07ed716
|
@ -1,2 +1,2 @@
|
||||||
workspace.xml
|
workspace.xml
|
||||||
markdown-navigator*
|
markdown-*
|
||||||
|
|
|
@ -461,7 +461,6 @@ Java_com_m2049r_xmrwallet_model_WalletManager_resolveOpenAlias(JNIEnv *env, jobj
|
||||||
|
|
||||||
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
|
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
|
||||||
|
|
||||||
// actually a WalletManager function, but logically in onWalletSelected
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
Java_com_m2049r_xmrwallet_model_WalletManager_closeJ(JNIEnv *env, jobject instance,
|
Java_com_m2049r_xmrwallet_model_WalletManager_closeJ(JNIEnv *env, jobject instance,
|
||||||
jobject walletInstance) {
|
jobject walletInstance) {
|
||||||
|
|
|
@ -295,6 +295,10 @@ public class GenerateFragment extends Fragment {
|
||||||
private void generateWallet() {
|
private void generateWallet() {
|
||||||
String name = etWalletName.getText().toString();
|
String name = etWalletName.getText().toString();
|
||||||
if (name.length() == 0) return;
|
if (name.length() == 0) return;
|
||||||
|
if (name.charAt(0)=='.') {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.generate_wallet_dot), Toast.LENGTH_LONG).show();
|
||||||
|
etWalletName.requestFocus();
|
||||||
|
}
|
||||||
File walletFile = Helper.getWalletFile(getActivity(), name);
|
File walletFile = Helper.getWalletFile(getActivity(), name);
|
||||||
if (WalletManager.getInstance().walletExists(walletFile)) {
|
if (WalletManager.getInstance().walletExists(walletFile)) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.generate_wallet_exists), Toast.LENGTH_LONG).show();
|
Toast.makeText(getActivity(), getString(R.string.generate_wallet_exists), Toast.LENGTH_LONG).show();
|
||||||
|
|
|
@ -16,12 +16,15 @@
|
||||||
|
|
||||||
package com.m2049r.xmrwallet;
|
package com.m2049r.xmrwallet;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
@ -77,12 +80,18 @@ public class LoginActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
boolean checkServiceRunning() {
|
||||||
public void onWalletSelected(final String walletName) {
|
|
||||||
if (WalletService.Running) {
|
if (WalletService.Running) {
|
||||||
Toast.makeText(this, getString(R.string.service_busy), Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, getString(R.string.service_busy), Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWalletSelected(final String walletName) {
|
||||||
|
if (checkServiceRunning()) return;
|
||||||
Log.d(TAG, "selected wallet is ." + walletName + ".");
|
Log.d(TAG, "selected wallet is ." + walletName + ".");
|
||||||
// now it's getting real, check if wallet exists
|
// now it's getting real, check if wallet exists
|
||||||
File walletFile = Helper.getWalletFile(this, walletName);
|
File walletFile = Helper.getWalletFile(this, walletName);
|
||||||
|
@ -101,7 +110,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
@Override
|
@Override
|
||||||
public void onWalletDetails(final String walletName) {
|
public void onWalletDetails(final String walletName) {
|
||||||
Log.d(TAG, "details for wallet ." + walletName + ".");
|
Log.d(TAG, "details for wallet ." + walletName + ".");
|
||||||
|
if (checkServiceRunning()) return;
|
||||||
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
|
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
@ -138,6 +147,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
@Override
|
@Override
|
||||||
public void onWalletReceive(String walletName) {
|
public void onWalletReceive(String walletName) {
|
||||||
Log.d(TAG, "receive for wallet ." + walletName + ".");
|
Log.d(TAG, "receive for wallet ." + walletName + ".");
|
||||||
|
if (checkServiceRunning()) return;
|
||||||
final File walletFile = Helper.getWalletFile(this, walletName);
|
final File walletFile = Helper.getWalletFile(this, walletName);
|
||||||
if (WalletManager.getInstance().walletExists(walletFile)) {
|
if (WalletManager.getInstance().walletExists(walletFile)) {
|
||||||
promptPassword(walletName, new PasswordAction() {
|
promptPassword(walletName, new PasswordAction() {
|
||||||
|
@ -151,8 +161,224 @@ public class LoginActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class AsyncRename extends AsyncTask<String, Void, Boolean> {
|
||||||
|
ProgressDialog progressDialog = new MyProgressDialog(LoginActivity.this, R.string.rename_progress);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
super.onPreExecute();
|
||||||
|
progressDialog.show();
|
||||||
|
LoginActivity.this.asyncWaitTask = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(String... params) {
|
||||||
|
if (params.length != 2) return false;
|
||||||
|
File walletFile = Helper.getWalletFile(LoginActivity.this, params[0]);
|
||||||
|
String newName = params[1];
|
||||||
|
return renameWallet(walletFile, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean result) {
|
||||||
|
super.onPostExecute(result);
|
||||||
|
progressDialog.dismiss();
|
||||||
|
if (result) {
|
||||||
|
reloadWalletList();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(LoginActivity.this, getString(R.string.rename_failed), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
LoginActivity.this.asyncWaitTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy + delete seems safer than rename bevause we call rollback easily
|
||||||
|
boolean renameWallet(File walletFile, String newName) {
|
||||||
|
if (copyWallet(walletFile, new File(walletFile.getParentFile(), newName), false)) {
|
||||||
|
deleteWallet(walletFile);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWalletRename(final String walletName) {
|
||||||
|
Log.d(TAG, "rename for wallet ." + walletName + ".");
|
||||||
|
if (checkServiceRunning()) return;
|
||||||
|
LayoutInflater li = LayoutInflater.from(this);
|
||||||
|
View promptsView = li.inflate(R.layout.prompt_rename, null);
|
||||||
|
|
||||||
|
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
|
||||||
|
alertDialogBuilder.setView(promptsView);
|
||||||
|
|
||||||
|
final EditText etRename = (EditText) promptsView.findViewById(R.id.etRename);
|
||||||
|
final TextView tvRenameLabel = (TextView) promptsView.findViewById(R.id.tvRenameLabel);
|
||||||
|
|
||||||
|
tvRenameLabel.setText(getString(R.string.prompt_rename) + " " + walletName);
|
||||||
|
|
||||||
|
// set dialog message
|
||||||
|
alertDialogBuilder
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton("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);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton("Cancel",
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int 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)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
|
||||||
|
Helper.hideKeyboardAlways(LoginActivity.this);
|
||||||
|
String newName = etRename.getText().toString();
|
||||||
|
dialog.cancel();
|
||||||
|
new AsyncRename().execute(walletName, newName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class AsyncBackup extends AsyncTask<String, Void, Boolean> {
|
||||||
|
ProgressDialog progressDialog = new MyProgressDialog(LoginActivity.this, R.string.backup_progress);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
super.onPreExecute();
|
||||||
|
progressDialog.show();
|
||||||
|
LoginActivity.this.asyncWaitTask = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
progressDialog.dismiss();
|
||||||
|
if (!result) {
|
||||||
|
Toast.makeText(LoginActivity.this, getString(R.string.backup_failed), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
LoginActivity.this.asyncWaitTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean backupWallet(String walletName) {
|
||||||
|
File backupFolder = new File(getStorageRoot(), ".backups");
|
||||||
|
if (!backupFolder.exists()) {
|
||||||
|
if (!backupFolder.mkdir()) {
|
||||||
|
Log.e(TAG, "Cannot create backup dir " + backupFolder.getAbsolutePath());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File walletFile = Helper.getWalletFile(LoginActivity.this, walletName);
|
||||||
|
File backupFile = new File(backupFolder, walletName);
|
||||||
|
Log.d(TAG, "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
|
||||||
|
return copyWallet(walletFile, backupFile, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWalletBackup(String walletName) {
|
||||||
|
Log.d(TAG, "backup for wallet ." + walletName + ".");
|
||||||
|
new AsyncBackup().execute(walletName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AsyncArchive extends AsyncTask<String, Void, Boolean> {
|
||||||
|
ProgressDialog progressDialog = new MyProgressDialog(LoginActivity.this, R.string.archive_progress);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
super.onPreExecute();
|
||||||
|
progressDialog.show();
|
||||||
|
LoginActivity.this.asyncWaitTask = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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))) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean result) {
|
||||||
|
super.onPostExecute(result);
|
||||||
|
progressDialog.dismiss();
|
||||||
|
if (result) {
|
||||||
|
reloadWalletList();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(LoginActivity.this, getString(R.string.archive_failed), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
LoginActivity.this.asyncWaitTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWalletArchive(final String walletName) {
|
||||||
|
Log.d(TAG, "archive 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setMessage(getString(R.string.archive_alert_message))
|
||||||
|
.setTitle(walletName)
|
||||||
|
.setPositiveButton(getString(R.string.archive_alert_yes), dialogClickListener)
|
||||||
|
.setNegativeButton(getString(R.string.archive_alert_no), dialogClickListener)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reloadWalletList() {
|
||||||
|
try {
|
||||||
|
LoginFragment loginFragment = (LoginFragment)
|
||||||
|
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||||
|
loginFragment.loadList();
|
||||||
|
} catch (ClassCastException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAddWallet() {
|
public void onAddWallet() {
|
||||||
|
if (checkServiceRunning()) return;
|
||||||
startGenerateFragment();
|
startGenerateFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,10 +499,64 @@ public class LoginActivity extends AppCompatActivity
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AsyncTask asyncWaitTask = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Log.d(TAG, "onResume()");
|
||||||
|
if (WalletService.Running && (asyncWaitTask == null)) {
|
||||||
|
Log.d(TAG, "new process dialog");
|
||||||
|
new AsyncWaitForService().execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class MyProgressDialog extends ProgressDialog {
|
||||||
|
Activity activity;
|
||||||
|
|
||||||
|
public MyProgressDialog(Activity activity, int msgId) {
|
||||||
|
super(activity);
|
||||||
|
this.activity = activity;
|
||||||
|
setCancelable(false);
|
||||||
|
setMessage(activity.getString(msgId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
//activity.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class AsyncWaitForService extends AsyncTask<Void, Void, Void> {
|
||||||
|
ProgressDialog progressDialog = new MyProgressDialog(LoginActivity.this, R.string.service_progress);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
super.onPreExecute();
|
||||||
|
progressDialog.show();
|
||||||
|
LoginActivity.this.asyncWaitTask = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
try {
|
||||||
|
while (WalletService.Running & !isCancelled()) {
|
||||||
|
Thread.sleep(250);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
// oh well ...
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
super.onPostExecute(result);
|
||||||
|
progressDialog.dismiss();
|
||||||
|
LoginActivity.this.asyncWaitTask = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -403,7 +683,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
Toast.makeText(LoginActivity.this,
|
Toast.makeText(LoginActivity.this,
|
||||||
getString(R.string.generate_wallet_create_failed), Toast.LENGTH_LONG).show();
|
getString(R.string.generate_wallet_create_failed), Toast.LENGTH_LONG).show();
|
||||||
Log.e(TAG, "Could not create new wallet in " + newWalletFile.getAbsolutePath());
|
Log.e(TAG, "Could not create new wallet in " + newWalletFile.getAbsolutePath());
|
||||||
|
genFragment.walletGenerateError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,9 +713,12 @@ public class LoginActivity extends AppCompatActivity
|
||||||
public boolean createWallet(File aFile, String password) {
|
public boolean createWallet(File aFile, String password) {
|
||||||
Wallet newWallet = WalletManager.getInstance().recoveryWallet(aFile, seed, restoreHeight);
|
Wallet newWallet = WalletManager.getInstance().recoveryWallet(aFile, seed, restoreHeight);
|
||||||
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok);
|
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok);
|
||||||
if (!success) Log.e(TAG, newWallet.getErrorString());
|
if (success) {
|
||||||
newWallet.setPassword(password);
|
newWallet.setPassword(password);
|
||||||
success = success && newWallet.store();
|
success = success && newWallet.store();
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, newWallet.getErrorString());
|
||||||
|
}
|
||||||
newWallet.close();
|
newWallet.close();
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -452,9 +735,12 @@ public class LoginActivity extends AppCompatActivity
|
||||||
.createWalletFromKeys(aFile, MNEMONIC_LANGUAGE, restoreHeight,
|
.createWalletFromKeys(aFile, MNEMONIC_LANGUAGE, restoreHeight,
|
||||||
address, viewKey, spendKey);
|
address, viewKey, spendKey);
|
||||||
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok);
|
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok);
|
||||||
if (!success) Log.e(TAG, newWallet.getErrorString());
|
if (success) {
|
||||||
newWallet.setPassword(password);
|
newWallet.setPassword(password);
|
||||||
success = success && newWallet.store();
|
success = success && newWallet.store();
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, newWallet.getErrorString());
|
||||||
|
}
|
||||||
newWallet.close();
|
newWallet.close();
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -464,18 +750,18 @@ public class LoginActivity extends AppCompatActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccept(final String name, final String password) {
|
public void onAccept(final String name, final String password) {
|
||||||
final File newWalletFolder = new File(getStorageRoot(), ".new");
|
final File newWalletFile = new File(new File(getStorageRoot(), ".new"), name);
|
||||||
final File walletFolder = getStorageRoot();
|
final File walletFolder = getStorageRoot();
|
||||||
final String walletPath = new File(walletFolder, name).getAbsolutePath();
|
final File walletFile = new File(walletFolder, name);
|
||||||
final boolean rc = copyWallet(walletFolder, newWalletFolder, name)
|
final boolean rc = copyWallet(newWalletFile, walletFile, false)
|
||||||
&&
|
&&
|
||||||
(testWallet(walletPath, password) == Wallet.Status.Status_Ok);
|
(testWallet(walletFile.getAbsolutePath(), password) == Wallet.Status.Status_Ok);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
popFragmentStack(GENERATE_STACK);
|
popFragmentStack(GENERATE_STACK);
|
||||||
Toast.makeText(LoginActivity.this,
|
Toast.makeText(LoginActivity.this,
|
||||||
getString(R.string.generate_wallet_created), Toast.LENGTH_SHORT).show();
|
getString(R.string.generate_wallet_created), Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Wallet store failed to " + walletPath);
|
Log.e(TAG, "Wallet store failed to " + walletFile.getAbsolutePath());
|
||||||
Toast.makeText(LoginActivity.this,
|
Toast.makeText(LoginActivity.this,
|
||||||
getString(R.string.generate_wallet_create_failed_2), Toast.LENGTH_LONG).show();
|
getString(R.string.generate_wallet_create_failed_2), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -491,30 +777,58 @@ public class LoginActivity extends AppCompatActivity
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean copyWallet(File dstDir, File srcDir, String name) {
|
boolean walletExists(File walletFile, boolean any) {
|
||||||
|
File dir = walletFile.getParentFile();
|
||||||
|
String name = walletFile.getName();
|
||||||
|
if (any) {
|
||||||
|
return new File(dir, name).exists()
|
||||||
|
|| new File(dir, name + ".keys").exists()
|
||||||
|
|| new File(dir, name + ".address.txt").exists();
|
||||||
|
} else {
|
||||||
|
return new File(dir, name).exists()
|
||||||
|
&& new File(dir, name + ".keys").exists()
|
||||||
|
&& new File(dir, name + ".address.txt").exists();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean copyWallet(File srcWallet, File dstWallet, boolean overwrite) {
|
||||||
|
//Log.d(TAG, "src=" + srcWallet.exists() + " dst=" + dstWallet.exists());
|
||||||
|
if (walletExists(dstWallet, true) && !overwrite) return false;
|
||||||
|
if (!walletExists(srcWallet, false)) return false;
|
||||||
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
|
File srcDir = srcWallet.getParentFile();
|
||||||
|
String srcName = srcWallet.getName();
|
||||||
|
File dstDir = dstWallet.getParentFile();
|
||||||
|
String dstName = dstWallet.getName();
|
||||||
try {
|
try {
|
||||||
// the cache is corrupt if we recover (!!)
|
copyFile(new File(srcDir, srcName), new File(dstDir, dstName));
|
||||||
// the cache is ok if we immediately do a full refresh()
|
copyFile(new File(srcDir, srcName + ".keys"), new File(dstDir, dstName + ".keys"));
|
||||||
// recoveryheight is ignored but not on watchonly wallet ?! - find out why
|
copyFile(new File(srcDir, srcName + ".address.txt"), new File(dstDir, dstName + ".address.txt"));
|
||||||
// so we just ignore the cache file and rebuild it on first sync
|
|
||||||
//copyFile(dstDir, srcDir, name);
|
|
||||||
copyFile(dstDir, srcDir, name + ".keys");
|
|
||||||
copyFile(dstDir, srcDir, name + ".address.txt");
|
|
||||||
success = true;
|
success = true;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.e(TAG, "wallet copy failed: " + ex.getMessage());
|
Log.e(TAG, "wallet copy failed: " + ex.getMessage());
|
||||||
// try to rollback
|
// try to rollback
|
||||||
new File(dstDir, name).delete();
|
deleteWallet(dstWallet);
|
||||||
new File(dstDir, name + ".keys").delete();
|
|
||||||
new File(dstDir, name + ".address.txt").delete();
|
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyFile(File dstDir, File srcDir, String name) throws IOException {
|
// do our best to delete as much as possible of the wallet files
|
||||||
FileChannel inChannel = new FileInputStream(new File(srcDir, name)).getChannel();
|
boolean deleteWallet(File walletFile) {
|
||||||
FileChannel outChannel = new FileOutputStream(new File(dstDir, name)).getChannel();
|
Log.d(TAG, "deleteWallet " + walletFile.getAbsolutePath());
|
||||||
|
if (!walletFile.isFile()) return false;
|
||||||
|
File dir = walletFile.getParentFile();
|
||||||
|
String name = walletFile.getName();
|
||||||
|
boolean success = new File(dir, name).delete();
|
||||||
|
success = new File(dir, name + ".keys").delete() && success;
|
||||||
|
success = new File(dir, name + ".address.txt").delete() && success;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFile(File src, File dst) throws IOException {
|
||||||
|
FileChannel inChannel = new FileInputStream(src).getChannel();
|
||||||
|
FileChannel outChannel = new FileOutputStream(dst).getChannel();
|
||||||
try {
|
try {
|
||||||
inChannel.transferTo(0, inChannel.size(), outChannel);
|
inChannel.transferTo(0, inChannel.size(), outChannel);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -82,11 +83,17 @@ public class LoginFragment extends Fragment {
|
||||||
|
|
||||||
File getStorageRoot();
|
File getStorageRoot();
|
||||||
|
|
||||||
void onWalletSelected(final String wallet);
|
void onWalletSelected(String wallet);
|
||||||
|
|
||||||
void onWalletDetails(final String wallet);
|
void onWalletDetails(String wallet);
|
||||||
|
|
||||||
void onWalletReceive(final String wallet);
|
void onWalletReceive(String wallet);
|
||||||
|
|
||||||
|
void onWalletRename(String name);
|
||||||
|
|
||||||
|
void onWalletBackup(String name);
|
||||||
|
|
||||||
|
void onWalletArchive(String walletName);
|
||||||
|
|
||||||
void onAddWallet();
|
void onAddWallet();
|
||||||
|
|
||||||
|
@ -126,7 +133,7 @@ public class LoginFragment extends Fragment {
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
Log.d(TAG, "onCreateView");
|
||||||
View view = inflater.inflate(R.layout.login_fragment, container, false);
|
View view = inflater.inflate(R.layout.login_fragment, container, false);
|
||||||
|
|
||||||
tbMainNet = (ToggleButton) view.findViewById(R.id.tbMainNet);
|
tbMainNet = (ToggleButton) view.findViewById(R.id.tbMainNet);
|
||||||
|
@ -224,31 +231,6 @@ public class LoginFragment extends Fragment {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
// Difference to opening wallet is that we don't need a daemon set
|
|
||||||
String itemValue = (String) listView.getItemAtPosition(position);
|
|
||||||
|
|
||||||
if (itemValue.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
|
|
||||||
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String wallet = itemValue.substring(WALLETNAME_PREAMBLE_LENGTH);
|
|
||||||
String x = isMainNet() ? "4" : "9A";
|
|
||||||
if (x.indexOf(itemValue.charAt(1)) < 0) {
|
|
||||||
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
|
|
||||||
|
|
||||||
activityCallback.onWalletDetails(wallet);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
loadList();
|
loadList();
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +244,8 @@ public class LoginFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadList() {
|
public void loadList() {
|
||||||
|
Log.d(TAG, "loadList()");
|
||||||
WalletManager mgr = WalletManager.getInstance();
|
WalletManager mgr = WalletManager.getInstance();
|
||||||
List<WalletManager.WalletInfo> walletInfos =
|
List<WalletManager.WalletInfo> walletInfos =
|
||||||
mgr.findWallets(activityCallback.getStorageRoot());
|
mgr.findWallets(activityCallback.getStorageRoot());
|
||||||
|
@ -411,51 +394,51 @@ public class LoginFragment extends Fragment {
|
||||||
public boolean onContextItemSelected(MenuItem item) {
|
public boolean onContextItemSelected(MenuItem item) {
|
||||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
||||||
String listItem = (String) listView.getItemAtPosition(info.position);
|
String listItem = (String) listView.getItemAtPosition(info.position);
|
||||||
|
String name = nameFromListItem(listItem, !isMainNet());
|
||||||
|
if (name == null) {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_info:
|
case R.id.action_info:
|
||||||
return showInfo(listItem);
|
showInfo(name);
|
||||||
|
break;
|
||||||
case R.id.action_receive:
|
case R.id.action_receive:
|
||||||
return showReceive(listItem);
|
showReceive(name);
|
||||||
|
break;
|
||||||
|
case R.id.action_rename:
|
||||||
|
activityCallback.onWalletRename(name);
|
||||||
|
break;
|
||||||
|
case R.id.action_backup:
|
||||||
|
activityCallback.onWalletBackup(name);
|
||||||
|
break;
|
||||||
|
case R.id.action_archive:
|
||||||
|
activityCallback.onWalletArchive(name);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return super.onContextItemSelected(item);
|
return super.onContextItemSelected(item);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private boolean showInfo(String listItem) {
|
|
||||||
if (listItem.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
|
|
||||||
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
|
|
||||||
String x = isMainNet() ? "4" : "9A";
|
|
||||||
if (x.indexOf(listItem.charAt(1)) < 0) {
|
|
||||||
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showInfo(@NonNull String name) {
|
||||||
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
|
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
|
||||||
|
|
||||||
activityCallback.onWalletDetails(wallet);
|
activityCallback.onWalletDetails(name);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean showReceive(String listItem) {
|
|
||||||
if (listItem.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
|
|
||||||
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
|
|
||||||
String x = isMainNet() ? "4" : "9A";
|
|
||||||
if (x.indexOf(listItem.charAt(1)) < 0) {
|
|
||||||
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean showReceive(@NonNull String name) {
|
||||||
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
|
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
|
||||||
|
|
||||||
activityCallback.onWalletReceive(wallet);
|
activityCallback.onWalletReceive(name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String nameFromListItem(String listItem, boolean testnet) {
|
||||||
|
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
|
||||||
|
String x = testnet ? "9A" : "4";
|
||||||
|
if (x.indexOf(listItem.charAt(1)) < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return wallet;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,6 @@ public class ReceiveFragment extends Fragment {
|
||||||
etPaymentId.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
etPaymentId.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||||
etDummy.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
etDummy.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||||
|
|
||||||
Helper.showKeyboard(getActivity());
|
|
||||||
etPaymentId.requestFocus();
|
|
||||||
etPaymentId.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
etPaymentId.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||||
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_NEXT)) {
|
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_NEXT)) {
|
||||||
|
@ -114,7 +112,7 @@ public class ReceiveFragment extends Fragment {
|
||||||
|
|
||||||
etAmount.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
etAmount.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||||
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_NEXT)) {
|
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
|
||||||
if (paymentIdOk() && amountOk()) {
|
if (paymentIdOk() && amountOk()) {
|
||||||
Helper.hideKeyboard(getActivity());
|
Helper.hideKeyboard(getActivity());
|
||||||
generateQr();
|
generateQr();
|
||||||
|
@ -189,8 +187,9 @@ public class ReceiveFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void show(final String address) {
|
||||||
private void show(String address) {
|
getActivity().runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
tvAddress.setText(address);
|
tvAddress.setText(address);
|
||||||
etPaymentId.setEnabled(true);
|
etPaymentId.setEnabled(true);
|
||||||
etAmount.setEnabled(true);
|
etAmount.setEnabled(true);
|
||||||
|
@ -199,6 +198,8 @@ public class ReceiveFragment extends Fragment {
|
||||||
hideProgress();
|
hideProgress();
|
||||||
generateQr();
|
generateQr();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void show(final String walletPath, final String password) {
|
private void show(final String walletPath, final String password) {
|
||||||
new Thread(null,
|
new Thread(null,
|
||||||
|
@ -208,8 +209,9 @@ public class ReceiveFragment extends Fragment {
|
||||||
final Wallet wallet = WalletManager.getInstance().openWallet(walletPath, password);
|
final Wallet wallet = WalletManager.getInstance().openWallet(walletPath, password);
|
||||||
getActivity().runOnUiThread(new Runnable() {
|
getActivity().runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
show(wallet.getAddress());
|
String address = wallet.getAddress();
|
||||||
wallet.close();
|
wallet.close();
|
||||||
|
show(address);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -259,6 +261,7 @@ public class ReceiveFragment extends Fragment {
|
||||||
etAmount.setText(amount);
|
etAmount.setText(amount);
|
||||||
qrCode.setImageBitmap(qr);
|
qrCode.setImageBitmap(qr);
|
||||||
etDummy.requestFocus();
|
etDummy.requestFocus();
|
||||||
|
bGenerate.setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,20 +93,21 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startWalletService() {
|
private void startWalletService() {
|
||||||
acquireWakeLock();
|
|
||||||
Bundle extras = getIntent().getExtras();
|
Bundle extras = getIntent().getExtras();
|
||||||
if (extras != null) {
|
if (extras != null) {
|
||||||
|
acquireWakeLock();
|
||||||
String walletId = extras.getString(REQUEST_ID);
|
String walletId = extras.getString(REQUEST_ID);
|
||||||
String walletPassword = extras.getString(REQUEST_PW);
|
String walletPassword = extras.getString(REQUEST_PW);
|
||||||
connectWalletService(walletId, walletPassword);
|
connectWalletService(walletId, walletPassword);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("No extras passed! Panic!");
|
finish();
|
||||||
|
//throw new IllegalStateException("No extras passed! Panic!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopWalletService() {
|
private void stopWalletService() {
|
||||||
releaseWakeLock();
|
|
||||||
disconnectWalletService();
|
disconnectWalletService();
|
||||||
|
releaseWakeLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -238,6 +238,7 @@ public class Wallet {
|
||||||
public native void setDefaultMixin(int mixin);
|
public native void setDefaultMixin(int mixin);
|
||||||
|
|
||||||
public native boolean setUserNote(String txid, String note);
|
public native boolean setUserNote(String txid, String note);
|
||||||
|
|
||||||
public native String getUserNote(String txid);
|
public native String getUserNote(String txid);
|
||||||
|
|
||||||
public native String getTxKey(String txid);
|
public native String getTxKey(String txid);
|
||||||
|
|
|
@ -137,7 +137,6 @@
|
||||||
android:id="@+id/tvWalletSpendKey"
|
android:id="@+id/tvWalletSpendKey"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:selectAllOnFocus="true"
|
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/colorPrimaryDark"
|
android:textColor="@color/colorPrimaryDark"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="10dp" >
|
android:padding="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvPasswordLabel"
|
android:id="@+id/tvPasswordLabel"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Wallet Password"
|
|
||||||
android:labelFor="@+id/etPassword"
|
android:labelFor="@+id/etPassword"
|
||||||
|
android:text="@string/prompt_password"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:imeOptions="normal"
|
android:imeOptions="normal"
|
||||||
android:inputType="textPassword" >
|
android:inputType="textPassword">
|
||||||
|
|
||||||
|
|
||||||
</EditText>
|
</EditText>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/layout_root"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="10dp" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvRenameLabel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/prompt_rename"
|
||||||
|
android:labelFor="@+id/etRename"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etRename"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:imeOptions="normal"
|
||||||
|
android:inputType="text" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -18,6 +18,8 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4sp"
|
android:layout_marginBottom="4sp"
|
||||||
android:layout_marginTop="4sp"
|
android:layout_marginTop="4sp"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:selectAllOnFocus="true"
|
||||||
android:hint="@string/send_address_hint"
|
android:hint="@string/send_address_hint"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
@ -88,7 +90,7 @@
|
||||||
android:layout_weight="7"
|
android:layout_weight="7"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
android:hint="@string/receive_amount_hint"
|
android:hint="@string/receive_amount_hint"
|
||||||
android:imeOptions="actionNext"
|
android:imeOptions="actionDone"
|
||||||
android:inputType="numberDecimal"
|
android:inputType="numberDecimal"
|
||||||
android:textAlignment="textStart"
|
android:textAlignment="textStart"
|
||||||
android:textSize="24sp" />
|
android:textSize="24sp" />
|
||||||
|
|
|
@ -3,10 +3,24 @@
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_info"
|
android:id="@+id/action_info"
|
||||||
|
android:icon="@drawable/ic_info_black_24dp"
|
||||||
android:title="@string/menu_info" />
|
android:title="@string/menu_info" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_receive"
|
android:id="@+id/action_receive"
|
||||||
|
android:icon="@drawable/ic_monero_qr_24dp"
|
||||||
android:title="@string/menu_receive" />
|
android:title="@string/menu_receive" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_rename"
|
||||||
|
android:title="@string/menu_rename" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_backup"
|
||||||
|
android:title="@string/menu_backup" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_archive"
|
||||||
|
android:title="@string/menu_archive" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
|
@ -4,7 +4,23 @@
|
||||||
<string name="wallet_activity_name">Wallet</string>
|
<string name="wallet_activity_name">Wallet</string>
|
||||||
|
|
||||||
<string name="menu_info">Details</string>
|
<string name="menu_info">Details</string>
|
||||||
<string name="menu_receive">Receive</string>
|
<string name="menu_receive">QR Receive</string>
|
||||||
|
<string name="menu_rename">Rename</string>
|
||||||
|
<string name="menu_archive">Archive</string>
|
||||||
|
<string name="menu_backup">Backup</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="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_success">Archive successful</string>
|
||||||
|
<string name="archive_failed">Archive failed!</string>
|
||||||
|
<string name="delete_failed">Delete failed!</string>
|
||||||
|
<string name="rename_failed">Rename failed!</string>
|
||||||
|
|
||||||
<string name="prompt_daemon">[<user>:<pass>@]<daemon>[:<port>]</string>
|
<string name="prompt_daemon">[<user>:<pass>@]<daemon>[:<port>]</string>
|
||||||
<string name="prompt_mainnet">Net Selection</string>
|
<string name="prompt_mainnet">Net Selection</string>
|
||||||
|
@ -25,6 +41,8 @@
|
||||||
|
|
||||||
<string name="service_busy">I am still busy with your last wallet …</string>
|
<string name="service_busy">I am still busy with your last wallet …</string>
|
||||||
|
|
||||||
|
<string name="prompt_rename">Rename</string>
|
||||||
|
|
||||||
<string name="prompt_password">Password for</string>
|
<string name="prompt_password">Password for</string>
|
||||||
<string name="bad_password">Bad password!</string>
|
<string name="bad_password">Bad password!</string>
|
||||||
<string name="bad_wallet">Wallet does not exists!</string>
|
<string name="bad_wallet">Wallet does not exists!</string>
|
||||||
|
@ -77,6 +95,7 @@
|
||||||
<string name="generate_wallet_watchonly"><Watch Only Wallet></string>
|
<string name="generate_wallet_watchonly"><Watch Only Wallet></string>
|
||||||
|
|
||||||
<string name="generate_wallet_exists">Wallet exists! Choose another name</string>
|
<string name="generate_wallet_exists">Wallet exists! Choose another name</string>
|
||||||
|
<string name="generate_wallet_dot">Wallet name may not begin with \'.\'</string>
|
||||||
<string name="generate_wallet_created">Wallet created</string>
|
<string name="generate_wallet_created">Wallet created</string>
|
||||||
<string name="generate_wallet_create_failed">Wallet create failed</string>
|
<string name="generate_wallet_create_failed">Wallet create failed</string>
|
||||||
<string name="generate_wallet_create_failed_1">Wallet create failed (1/2)</string>
|
<string name="generate_wallet_create_failed_1">Wallet create failed (1/2)</string>
|
||||||
|
@ -163,6 +182,10 @@
|
||||||
<string name="details_alert_yes">I\'m safe</string>
|
<string name="details_alert_yes">I\'m safe</string>
|
||||||
<string name="details_alert_no">Take me back!</string>
|
<string name="details_alert_no">Take me back!</string>
|
||||||
|
|
||||||
|
<string name="archive_alert_message">The wallet will be backuped up and then deleted!</string>
|
||||||
|
<string name="archive_alert_yes">Yes, do that!</string>
|
||||||
|
<string name="archive_alert_no">No thanks!</string>
|
||||||
|
|
||||||
<string name="big_amount">999999.999999999999</string>
|
<string name="big_amount">999999.999999999999</string>
|
||||||
|
|
||||||
<string-array name="mixin">
|
<string-array name="mixin">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module external.linked.project.id="xmrwallet" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" version="4">
|
<module external.linked.project.id="xmrwallet" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||||
<component name="FacetManager">
|
<component name="FacetManager">
|
||||||
<facet type="java-gradle" name="Java-Gradle">
|
<facet type="java-gradle" name="Java-Gradle">
|
||||||
<configuration>
|
<configuration>
|
||||||
|
|
Loading…
Reference in New Issue