From ec7798cb343d062612ea3703f78ae22727a7b23c Mon Sep 17 00:00:00 2001
From: m2049r <30435443+m2049r@users.noreply.github.com>
Date: Sun, 3 Sep 2017 14:09:27 +0200
Subject: [PATCH] wallet archive/backup
---
.../com/m2049r/xmrwallet/LoginActivity.java | 93 ++++++++++++++++---
.../com/m2049r/xmrwallet/LoginFragment.java | 55 +++++------
.../com/m2049r/xmrwallet/ReceiveFragment.java | 29 +++---
.../main/res/layout/gen_review_fragment.xml | 1 -
app/src/main/res/layout/receive_fragment.xml | 2 +-
app/src/main/res/menu/list_menu.xml | 10 ++
app/src/main/res/values/strings.xml | 14 ++-
7 files changed, 143 insertions(+), 61 deletions(-)
diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java
index 399ff1c..0f06bba 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java
@@ -154,7 +154,7 @@ public class LoginActivity extends AppCompatActivity
@Override
public void onWalletRename(String walletName) {
Log.d(TAG, "rename for wallet ." + walletName + ".");
- final File walletFile = Helper.getWalletFile(LoginActivity.this, walletName);
+ final File walletFile = Helper.getWalletFile(this, walletName);
LayoutInflater li = LayoutInflater.from(this);
View promptsView = li.inflate(R.layout.prompt_rename, null);
@@ -174,7 +174,9 @@ public class LoginActivity extends AppCompatActivity
public void onClick(DialogInterface dialog, int id) {
Helper.hideKeyboardAlways(LoginActivity.this);
String newName = etRename.getText().toString();
- renameWallet(walletFile, newName); //TODO error
+ if (!renameWallet(walletFile, newName)) {
+ Toast.makeText(LoginActivity.this, getString(R.string.rename_failed), Toast.LENGTH_LONG).show();
+ }
reloadWalletList();
}
})
@@ -196,7 +198,9 @@ public class LoginActivity extends AppCompatActivity
Helper.hideKeyboardAlways(LoginActivity.this);
String newName = etRename.getText().toString();
dialog.cancel();
- renameWallet(walletFile, newName); //TODO error
+ if (!renameWallet(walletFile, newName)) {
+ Toast.makeText(LoginActivity.this, getString(R.string.rename_failed), Toast.LENGTH_LONG).show();
+ }
reloadWalletList();
return false;
}
@@ -207,6 +211,63 @@ public class LoginActivity extends AppCompatActivity
dialog.show();
}
+ @Override
+ public boolean onWalletBackup(String walletName) {
+ Log.d(TAG, "backup for wallet ." + 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(this, walletName);
+ File backupFile = new File(backupFolder, walletName);
+ Log.d(TAG, "backup " + walletFile.getAbsolutePath() + " to " + backupFile.getAbsolutePath());
+ if (copyWallet(walletFile, backupFile, true)) {
+ Toast.makeText(this, getString(R.string.backup_success), Toast.LENGTH_SHORT).show();
+ return true;
+ } else {
+ Toast.makeText(this, getString(R.string.backup_failed), Toast.LENGTH_LONG).show();
+ return false;
+ }
+ }
+
+ @Override
+ public void onWalletArchive(final String walletName) {
+ Log.d(TAG, "archive for wallet ." + walletName + ".");
+
+ DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ if (onWalletBackup(walletName)) {
+ if (deleteWallet(Helper.getWalletFile(LoginActivity.this, walletName))) {
+ Toast.makeText(LoginActivity.this, getString(R.string.archive_success), Toast.LENGTH_SHORT).show();
+ reloadWalletList();
+ } else {
+ Toast.makeText(LoginActivity.this, getString(R.string.delete_failed), Toast.LENGTH_LONG).show();
+ }
+ } else {
+ Toast.makeText(LoginActivity.this, getString(R.string.backup_failed), Toast.LENGTH_LONG).show();
+ }
+ 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)
@@ -532,7 +593,7 @@ public class LoginActivity extends AppCompatActivity
final File newWalletFile = new File(new File(getStorageRoot(), ".new"), name);
final File walletFolder = getStorageRoot();
final File walletFile = new File(walletFolder, name);
- final boolean rc = copyWallet(newWalletFile, walletFile)
+ final boolean rc = copyWallet(newWalletFile, walletFile, false)
&&
(testWallet(walletFile.getAbsolutePath(), password) == Wallet.Status.Status_Ok);
if (rc) {
@@ -557,7 +618,7 @@ public class LoginActivity extends AppCompatActivity
}
boolean renameWallet(File walletFile, String newName) {
- if (copyWallet(walletFile, new File(walletFile.getParentFile(), newName))) {
+ if (copyWallet(walletFile, new File(walletFile.getParentFile(), newName), false)) {
deleteWallet(walletFile);
return true;
} else {
@@ -565,7 +626,20 @@ public class LoginActivity extends AppCompatActivity
}
}
- boolean copyWallet(File srcWallet, File dstWallet) {
+ boolean walletExists(File walletFile) {
+ File dir = walletFile.getParentFile();
+ String name = walletFile.getName();
+ boolean exists = new File(dir, name).exists();
+ exists = new File(dir, name + ".keys").exists() && exists;
+ exists = new File(dir, name + ".address.txt").exists() && exists;
+ return exists;
+ }
+
+ boolean copyWallet(File srcWallet, File dstWallet, boolean overwrite) {
+ Log.d(TAG, "src=" + srcWallet.exists() + " dst=" + dstWallet.exists());
+ if (walletExists(dstWallet) && !overwrite) return false;
+ if (!walletExists(srcWallet)) return false;
+
boolean success = false;
File srcDir = srcWallet.getParentFile();
String srcName = srcWallet.getName();
@@ -586,6 +660,7 @@ public class LoginActivity extends AppCompatActivity
// do our best to delete as much as possible of the wallet files
boolean deleteWallet(File walletFile) {
+ Log.d(TAG, "deleteWallet " + walletFile.getAbsolutePath());
if (!walletFile.isFile()) return false;
File dir = walletFile.getParentFile();
String name = walletFile.getName();
@@ -596,12 +671,6 @@ public class LoginActivity extends AppCompatActivity
}
void copyFile(File src, File dst) throws IOException {
- if (dst.exists()) {
- throw new IOException("Destination exists!");
- }
- if (!src.exists()) {
- throw new IOException("Source does not exist!");
- }
FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel();
try {
diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java b/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java
index 4f5f19a..80e75a3 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.StrictMode;
+import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.util.Log;
@@ -90,6 +91,10 @@ public class LoginFragment extends Fragment {
void onWalletRename(String name);
+ boolean onWalletBackup(String name);
+
+ void onWalletArchive(String walletName);
+
void onAddWallet();
void setTitle(String title);
@@ -389,20 +394,25 @@ public class LoginFragment extends Fragment {
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
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()) {
case R.id.action_info:
- showInfo(listItem);
+ showInfo(name);
break;
case R.id.action_receive:
- showReceive(listItem);
+ showReceive(name);
break;
case R.id.action_rename:
- String name = nameFromListItem(listItem, !isMainNet());
- if (name != null) {
- activityCallback.onWalletRename(name);
- } else {
- // TODO do we say something here?
- }
+ activityCallback.onWalletRename(name);
+ break;
+ case R.id.action_backup:
+ activityCallback.onWalletBackup(name);
+ break;
+ case R.id.action_archive:
+ activityCallback.onWalletArchive(name);
break;
default:
return super.onContextItemSelected(item);
@@ -410,37 +420,16 @@ public class LoginFragment extends Fragment {
return true;
}
- private void showInfo(String listItem) {
- if (listItem.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
- Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
- }
-
- 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();
- }
-
+ private void showInfo(@NonNull String name) {
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
- activityCallback.onWalletDetails(wallet);
+ activityCallback.onWalletDetails(name);
}
- 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 = nameFromListItem(listItem, !isMainNet());
- if (wallet == null) {
- 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
- activityCallback.onWalletReceive(wallet);
+ activityCallback.onWalletReceive(name);
return true;
}
diff --git a/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java b/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java
index 49f255b..fe13852 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java
@@ -79,8 +79,6 @@ public class ReceiveFragment extends Fragment {
etPaymentId.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() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
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() {
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()) {
Helper.hideKeyboard(getActivity());
generateQr();
@@ -189,15 +187,18 @@ public class ReceiveFragment extends Fragment {
}
}
-
- private void show(String address) {
- tvAddress.setText(address);
- etPaymentId.setEnabled(true);
- etAmount.setEnabled(true);
- bPaymentId.setEnabled(true);
- bGenerate.setEnabled(true);
- hideProgress();
- generateQr();
+ private void show(final String address) {
+ getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ tvAddress.setText(address);
+ etPaymentId.setEnabled(true);
+ etAmount.setEnabled(true);
+ bPaymentId.setEnabled(true);
+ bGenerate.setEnabled(true);
+ hideProgress();
+ generateQr();
+ }
+ });
}
private void show(final String walletPath, final String password) {
@@ -208,8 +209,9 @@ public class ReceiveFragment extends Fragment {
final Wallet wallet = WalletManager.getInstance().openWallet(walletPath, password);
getActivity().runOnUiThread(new Runnable() {
public void run() {
- show(wallet.getAddress());
+ String address = wallet.getAddress();
wallet.close();
+ show(address);
}
});
}
@@ -259,6 +261,7 @@ public class ReceiveFragment extends Fragment {
etAmount.setText(amount);
qrCode.setImageBitmap(qr);
etDummy.requestFocus();
+ bGenerate.setEnabled(false);
}
}
diff --git a/app/src/main/res/layout/gen_review_fragment.xml b/app/src/main/res/layout/gen_review_fragment.xml
index 56891ac..35fc2b8 100644
--- a/app/src/main/res/layout/gen_review_fragment.xml
+++ b/app/src/main/res/layout/gen_review_fragment.xml
@@ -137,7 +137,6 @@
android:id="@+id/tvWalletSpendKey"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:selectAllOnFocus="true"
android:textAlignment="center"
android:textColor="@color/colorPrimaryDark"
android:textIsSelectable="true"
diff --git a/app/src/main/res/layout/receive_fragment.xml b/app/src/main/res/layout/receive_fragment.xml
index 45f28c8..46b4c3f 100644
--- a/app/src/main/res/layout/receive_fragment.xml
+++ b/app/src/main/res/layout/receive_fragment.xml
@@ -90,7 +90,7 @@
android:layout_weight="7"
android:enabled="false"
android:hint="@string/receive_amount_hint"
- android:imeOptions="actionNext"
+ android:imeOptions="actionDone"
android:inputType="numberDecimal"
android:textAlignment="textStart"
android:textSize="24sp" />
diff --git a/app/src/main/res/menu/list_menu.xml b/app/src/main/res/menu/list_menu.xml
index 4afeb50..d52b7a9 100644
--- a/app/src/main/res/menu/list_menu.xml
+++ b/app/src/main/res/menu/list_menu.xml
@@ -3,14 +3,24 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5a8273a..7bad371 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -4,8 +4,16 @@
Wallet
Details
- Receive
+ QR Receive
Rename
+ Archive
+ Backup
+
+ Backup successful
+ Backup failed!
+ Archive successful
+ Delete failed!
+ Rename failed!
[<user>:<pass>@]<daemon>[:<port>]
Net Selection
@@ -166,6 +174,10 @@
I\'m safe
Take me back!
+ The wallet will be backuped up and then deleted!
+ Yes, do that!
+ No thanks!
+
999999.999999999999