mirror of
https://github.com/m2049r/xmrwallet
synced 2025-05-05 11:57:07 +02:00
rename option in wallet list + tweaks
This commit is contained in:
parent
89ada5b294
commit
20e7d6d065
app/src/main
java/com/m2049r/xmrwallet
res
@ -151,6 +151,71 @@ 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);
|
||||
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) + " " + walletFile.getName());
|
||||
|
||||
// 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();
|
||||
renameWallet(walletFile, newName); //TODO error
|
||||
reloadWalletList();
|
||||
}
|
||||
})
|
||||
.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();
|
||||
renameWallet(walletFile, newName); //TODO error
|
||||
reloadWalletList();
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
void reloadWalletList() {
|
||||
try {
|
||||
LoginFragment loginFragment = (LoginFragment)
|
||||
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
loginFragment.loadList();
|
||||
} catch (ClassCastException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddWallet() {
|
||||
startGenerateFragment();
|
||||
@ -464,18 +529,18 @@ public class LoginActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
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 String walletPath = new File(walletFolder, name).getAbsolutePath();
|
||||
final boolean rc = copyWallet(walletFolder, newWalletFolder, name)
|
||||
final File walletFile = new File(walletFolder, name);
|
||||
final boolean rc = copyWallet(newWalletFile, walletFile)
|
||||
&&
|
||||
(testWallet(walletPath, password) == Wallet.Status.Status_Ok);
|
||||
(testWallet(walletFile.getAbsolutePath(), password) == Wallet.Status.Status_Ok);
|
||||
if (rc) {
|
||||
popFragmentStack(GENERATE_STACK);
|
||||
Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.generate_wallet_created), Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Log.e(TAG, "Wallet store failed to " + walletPath);
|
||||
Log.e(TAG, "Wallet store failed to " + walletFile.getAbsolutePath());
|
||||
Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.generate_wallet_create_failed_2), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
@ -491,30 +556,54 @@ public class LoginActivity extends AppCompatActivity
|
||||
return status;
|
||||
}
|
||||
|
||||
boolean copyWallet(File dstDir, File srcDir, String name) {
|
||||
boolean renameWallet(File walletFile, String newName) {
|
||||
if (copyWallet(walletFile, new File(walletFile.getParentFile(), newName))) {
|
||||
deleteWallet(walletFile);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean copyWallet(File srcWallet, File dstWallet) {
|
||||
boolean success = false;
|
||||
File srcDir = srcWallet.getParentFile();
|
||||
String srcName = srcWallet.getName();
|
||||
File dstDir = dstWallet.getParentFile();
|
||||
String dstName = dstWallet.getName();
|
||||
try {
|
||||
// the cache is corrupt if we recover (!!)
|
||||
// the cache is ok if we immediately do a full refresh()
|
||||
// recoveryheight is ignored but not on watchonly wallet ?! - find out why
|
||||
// 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");
|
||||
copyFile(new File(srcDir, srcName), new File(dstDir, dstName));
|
||||
copyFile(new File(srcDir, srcName + ".keys"), new File(dstDir, dstName + ".keys"));
|
||||
copyFile(new File(srcDir, srcName + ".address.txt"), new File(dstDir, dstName + ".address.txt"));
|
||||
success = true;
|
||||
} catch (IOException ex) {
|
||||
Log.e(TAG, "wallet copy failed: " + ex.getMessage());
|
||||
// try to rollback
|
||||
new File(dstDir, name).delete();
|
||||
new File(dstDir, name + ".keys").delete();
|
||||
new File(dstDir, name + ".address.txt").delete();
|
||||
deleteWallet(dstWallet);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void copyFile(File dstDir, File srcDir, String name) throws IOException {
|
||||
FileChannel inChannel = new FileInputStream(new File(srcDir, name)).getChannel();
|
||||
FileChannel outChannel = new FileOutputStream(new File(dstDir, name)).getChannel();
|
||||
// do our best to delete as much as possible of the wallet files
|
||||
boolean deleteWallet(File walletFile) {
|
||||
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 {
|
||||
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 {
|
||||
inChannel.transferTo(0, inChannel.size(), outChannel);
|
||||
} finally {
|
||||
|
@ -82,11 +82,13 @@ public class LoginFragment extends Fragment {
|
||||
|
||||
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 onAddWallet();
|
||||
|
||||
@ -126,7 +128,7 @@ public class LoginFragment extends Fragment {
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
Log.d(TAG, "onCreateView");
|
||||
View view = inflater.inflate(R.layout.login_fragment, container, false);
|
||||
|
||||
tbMainNet = (ToggleButton) view.findViewById(R.id.tbMainNet);
|
||||
@ -224,31 +226,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();
|
||||
return view;
|
||||
}
|
||||
@ -262,7 +239,8 @@ public class LoginFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadList() {
|
||||
public void loadList() {
|
||||
Log.d(TAG, "loadList()");
|
||||
WalletManager mgr = WalletManager.getInstance();
|
||||
List<WalletManager.WalletInfo> walletInfos =
|
||||
mgr.findWallets(activityCallback.getStorageRoot());
|
||||
@ -413,31 +391,39 @@ public class LoginFragment extends Fragment {
|
||||
String listItem = (String) listView.getItemAtPosition(info.position);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_info:
|
||||
return showInfo(listItem);
|
||||
showInfo(listItem);
|
||||
break;
|
||||
case R.id.action_receive:
|
||||
return showReceive(listItem);
|
||||
showReceive(listItem);
|
||||
break;
|
||||
case R.id.action_rename:
|
||||
String name = nameFromListItem(listItem, !isMainNet());
|
||||
if (name != null) {
|
||||
activityCallback.onWalletRename(name);
|
||||
} else {
|
||||
// TODO do we say something here?
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean showInfo(String listItem) {
|
||||
private void 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;
|
||||
}
|
||||
|
||||
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
|
||||
|
||||
activityCallback.onWalletDetails(wallet);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean showReceive(String listItem) {
|
||||
@ -446,9 +432,8 @@ public class LoginFragment extends Fragment {
|
||||
return true;
|
||||
}
|
||||
|
||||
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
|
||||
String x = isMainNet() ? "4" : "9A";
|
||||
if (x.indexOf(listItem.charAt(1)) < 0) {
|
||||
String wallet = nameFromListItem(listItem, !isMainNet());
|
||||
if (wallet == null) {
|
||||
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
@ -458,4 +443,13 @@ public class LoginFragment extends Fragment {
|
||||
activityCallback.onWalletReceive(wallet);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp" >
|
||||
android:padding="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPasswordLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Wallet Password"
|
||||
android:labelFor="@+id/etPassword"
|
||||
android:text="@string/prompt_password"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
<EditText
|
||||
@ -19,7 +19,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="normal"
|
||||
android:inputType="textPassword" >
|
||||
android:inputType="textPassword">
|
||||
|
||||
|
||||
</EditText>
|
||||
|
24
app/src/main/res/layout/prompt_rename.xml
Normal file
24
app/src/main/res/layout/prompt_rename.xml
Normal file
@ -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_marginBottom="4sp"
|
||||
android:layout_marginTop="4sp"
|
||||
android:textIsSelectable="true"
|
||||
android:selectAllOnFocus="true"
|
||||
android:hint="@string/send_address_hint"
|
||||
android:textAlignment="center"
|
||||
android:textSize="16sp" />
|
||||
|
@ -9,4 +9,8 @@
|
||||
android:id="@+id/action_receive"
|
||||
android:title="@string/menu_receive" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_rename"
|
||||
android:title="@string/menu_rename" />
|
||||
|
||||
</menu>
|
@ -5,6 +5,7 @@
|
||||
|
||||
<string name="menu_info">Details</string>
|
||||
<string name="menu_receive">Receive</string>
|
||||
<string name="menu_rename">Rename</string>
|
||||
|
||||
<string name="prompt_daemon">[<user>:<pass>@]<daemon>[:<port>]</string>
|
||||
<string name="prompt_mainnet">Net Selection</string>
|
||||
@ -25,6 +26,8 @@
|
||||
|
||||
<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="bad_password">Bad password!</string>
|
||||
<string name="bad_wallet">Wallet does not exists!</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user