wallet archive/backup
This commit is contained in:
parent
20e7d6d065
commit
ec7798cb34
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -3,14 +3,24 @@
|
|||
|
||||
<item
|
||||
android:id="@+id/action_info"
|
||||
android:icon="@drawable/ic_info_black_24dp"
|
||||
android:title="@string/menu_info" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_receive"
|
||||
android:icon="@drawable/ic_monero_qr_24dp"
|
||||
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>
|
|
@ -4,8 +4,16 @@
|
|||
<string name="wallet_activity_name">Wallet</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_success">Backup successful</string>
|
||||
<string name="backup_failed">Backup failed!</string>
|
||||
<string name="archive_success">Archive successful</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_mainnet">Net Selection</string>
|
||||
|
@ -166,6 +174,10 @@
|
|||
<string name="details_alert_yes">I\'m safe</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-array name="mixin">
|
||||
|
|
Loading…
Reference in New Issue