mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 05:06:45 +00:00
add rename wallet menu command
This commit is contained in:
parent
c443bc78d3
commit
7bb22419df
7 changed files with 88 additions and 16 deletions
|
@ -220,6 +220,8 @@ public class AppController implements Initializable {
|
||||||
|
|
||||||
private final Set<Wallet> emptyLoadingWallets = new LinkedHashSet<>();
|
private final Set<Wallet> emptyLoadingWallets = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
private final Map<File, File> renamedWallets = new HashMap<>();
|
||||||
|
|
||||||
private final ChangeListener<Boolean> serverToggleOnlineListener = (observable, oldValue, newValue) -> {
|
private final ChangeListener<Boolean> serverToggleOnlineListener = (observable, oldValue, newValue) -> {
|
||||||
Platform.runLater(() -> setServerToggleTooltip(getCurrentBlockHeight()));
|
Platform.runLater(() -> setServerToggleTooltip(getCurrentBlockHeight()));
|
||||||
};
|
};
|
||||||
|
@ -851,6 +853,10 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void renameWallet(ActionEvent event) {
|
||||||
|
renameWallet(getSelectedWalletForm());
|
||||||
|
}
|
||||||
|
|
||||||
public void deleteWallet(ActionEvent event) {
|
public void deleteWallet(ActionEvent event) {
|
||||||
deleteWallet(getSelectedWalletForm());
|
deleteWallet(getSelectedWalletForm());
|
||||||
}
|
}
|
||||||
|
@ -1548,6 +1554,11 @@ public class AppController implements Initializable {
|
||||||
|
|
||||||
tabs.getTabs().add(tab);
|
tabs.getTabs().add(tab);
|
||||||
tabs.getSelectionModel().select(tab);
|
tabs.getSelectionModel().select(tab);
|
||||||
|
|
||||||
|
File oldWalletFile = renamedWallets.remove(storage.getWalletFile());
|
||||||
|
if(oldWalletFile != null) {
|
||||||
|
deleteStorage(new Storage(oldWalletFile), false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for(Tab walletTab : tabs.getTabs()) {
|
for(Tab walletTab : tabs.getTabs()) {
|
||||||
TabData tabData = (TabData)walletTab.getUserData();
|
TabData tabData = (TabData)walletTab.getUserData();
|
||||||
|
@ -1970,6 +1981,30 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void renameWallet(WalletForm selectedWalletForm) {
|
||||||
|
WalletNameDialog walletNameDialog = new WalletNameDialog(selectedWalletForm.getMasterWallet().getName(), false, null, true);
|
||||||
|
Optional<WalletNameDialog.NameAndBirthDate> optName = walletNameDialog.showAndWait();
|
||||||
|
if(optName.isPresent()) {
|
||||||
|
File walletFile = Storage.getWalletFile(optName.get().getName() + "." + PersistenceType.DB.getExtension());
|
||||||
|
if(walletFile.exists()) {
|
||||||
|
showErrorDialog("Error renaming wallet", "Wallet file " + walletFile.getAbsolutePath() + " already exists.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Storage.CopyWalletService copyWalletService = new Storage.CopyWalletService(selectedWalletForm.getWallet(), walletFile);
|
||||||
|
copyWalletService.setOnSucceeded(event -> {
|
||||||
|
renamedWallets.put(walletFile, selectedWalletForm.getStorage().getWalletFile());
|
||||||
|
tabs.getTabs().remove(tabs.getSelectionModel().getSelectedItem());
|
||||||
|
openWalletFile(walletFile, true);
|
||||||
|
});
|
||||||
|
copyWalletService.setOnFailed(event -> {
|
||||||
|
log.error("Error renaming wallet", event.getSource().getException());
|
||||||
|
showErrorDialog("Error renaming wallet", event.getSource().getException().getMessage());
|
||||||
|
});
|
||||||
|
copyWalletService.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void deleteWallet(WalletForm selectedWalletForm) {
|
private void deleteWallet(WalletForm selectedWalletForm) {
|
||||||
Optional<ButtonType> optButtonType = AppServices.showWarningDialog("Delete " + selectedWalletForm.getWallet().getMasterName() + "?", "The wallet file and any backups will be deleted. Are you sure?", ButtonType.NO, ButtonType.YES);
|
Optional<ButtonType> optButtonType = AppServices.showWarningDialog("Delete " + selectedWalletForm.getWallet().getMasterName() + "?", "The wallet file and any backups will be deleted. Are you sure?", ButtonType.NO, ButtonType.YES);
|
||||||
if(optButtonType.isPresent() && optButtonType.get() == ButtonType.YES) {
|
if(optButtonType.isPresent() && optButtonType.get() == ButtonType.YES) {
|
||||||
|
@ -1985,7 +2020,7 @@ public class AppController implements Initializable {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tabs.getTabs().remove(tabs.getSelectionModel().getSelectedItem());
|
tabs.getTabs().remove(tabs.getSelectionModel().getSelectedItem());
|
||||||
deleteStorage(storage);
|
deleteStorage(storage, true);
|
||||||
} finally {
|
} finally {
|
||||||
encryptionFullKey.clear();
|
encryptionFullKey.clear();
|
||||||
password.get().clear();
|
password.get().clear();
|
||||||
|
@ -2007,15 +2042,15 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tabs.getTabs().remove(tabs.getSelectionModel().getSelectedItem());
|
tabs.getTabs().remove(tabs.getSelectionModel().getSelectedItem());
|
||||||
deleteStorage(storage);
|
deleteStorage(storage, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteStorage(Storage storage) {
|
private void deleteStorage(Storage storage, boolean deleteBackups) {
|
||||||
if(storage.isClosed()) {
|
if(storage.isClosed()) {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
Storage.DeleteWalletService deleteWalletService = new Storage.DeleteWalletService(storage);
|
Storage.DeleteWalletService deleteWalletService = new Storage.DeleteWalletService(storage, deleteBackups);
|
||||||
deleteWalletService.setDelay(Duration.seconds(3));
|
deleteWalletService.setDelay(Duration.seconds(3));
|
||||||
deleteWalletService.setPeriod(Duration.hours(1));
|
deleteWalletService.setPeriod(Duration.hours(1));
|
||||||
deleteWalletService.setOnSucceeded(event -> {
|
deleteWalletService.setOnSucceeded(event -> {
|
||||||
|
@ -2031,7 +2066,7 @@ public class AppController implements Initializable {
|
||||||
deleteWalletService.start();
|
deleteWalletService.start();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Platform.runLater(() -> deleteStorage(storage));
|
Platform.runLater(() -> deleteStorage(storage, deleteBackups));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,13 @@ public class WalletNameDialog extends Dialog<WalletNameDialog.NameAndBirthDate>
|
||||||
}
|
}
|
||||||
|
|
||||||
public WalletNameDialog(String initialName, boolean hasExistingTransactions, Date startDate) {
|
public WalletNameDialog(String initialName, boolean hasExistingTransactions, Date startDate) {
|
||||||
|
this(initialName, hasExistingTransactions, startDate, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WalletNameDialog(String initialName, boolean hasExistingTransactions, Date startDate, boolean rename) {
|
||||||
final DialogPane dialogPane = getDialogPane();
|
final DialogPane dialogPane = getDialogPane();
|
||||||
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
||||||
boolean requestBirthDate = (Config.get().getServerType() == null || Config.get().getServerType() == ServerType.BITCOIN_CORE);
|
boolean requestBirthDate = !rename && (Config.get().getServerType() == null || Config.get().getServerType() == ServerType.BITCOIN_CORE);
|
||||||
|
|
||||||
setTitle("Wallet Name");
|
setTitle("Wallet Name");
|
||||||
dialogPane.setHeaderText("Enter a name for this wallet:");
|
dialogPane.setHeaderText("Enter a name for this wallet:");
|
||||||
|
@ -121,16 +125,16 @@ public class WalletNameDialog extends Dialog<WalletNameDialog.NameAndBirthDate>
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
final ButtonType okButtonType = new javafx.scene.control.ButtonType("Create Wallet", ButtonBar.ButtonData.OK_DONE);
|
final ButtonType okButtonType = new javafx.scene.control.ButtonType((rename ? "Rename" : "Create") + " Wallet", ButtonBar.ButtonData.OK_DONE);
|
||||||
dialogPane.getButtonTypes().addAll(okButtonType);
|
dialogPane.getButtonTypes().addAll(okButtonType);
|
||||||
Button okButton = (Button) dialogPane.lookupButton(okButtonType);
|
Button okButton = (Button) dialogPane.lookupButton(okButtonType);
|
||||||
BooleanBinding isInvalid = Bindings.createBooleanBinding(() ->
|
BooleanBinding isInvalid = Bindings.createBooleanBinding(() ->
|
||||||
name.getText().length() == 0 || Storage.walletExists(name.getText()) || (existingCheck.isSelected() && existingPicker.getValue() == null), name.textProperty(), existingCheck.selectedProperty(), existingPicker.valueProperty());
|
name.getText().trim().length() == 0 || Storage.walletExists(name.getText()) || (existingCheck.isSelected() && existingPicker.getValue() == null), name.textProperty(), existingCheck.selectedProperty(), existingPicker.valueProperty());
|
||||||
okButton.disableProperty().bind(isInvalid);
|
okButton.disableProperty().bind(isInvalid);
|
||||||
|
|
||||||
name.setPromptText("Wallet Name");
|
name.setPromptText("Wallet Name");
|
||||||
Platform.runLater(name::requestFocus);
|
Platform.runLater(name::requestFocus);
|
||||||
setResultConverter(dialogButton -> dialogButton == okButtonType ? new NameAndBirthDate(name.getText(), existingPicker.getValue()) : null);
|
setResultConverter(dialogButton -> dialogButton == okButtonType ? new NameAndBirthDate(name.getText().trim(), existingPicker.getValue()) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NameAndBirthDate {
|
public static class NameAndBirthDate {
|
||||||
|
|
|
@ -39,8 +39,10 @@ public class Sparrow implements WalletImport, WalletExport {
|
||||||
Storage tempStorage = new Storage(persistence, tempFile);
|
Storage tempStorage = new Storage(persistence, tempFile);
|
||||||
tempStorage.setKeyDeriver(storage.getKeyDeriver());
|
tempStorage.setKeyDeriver(storage.getKeyDeriver());
|
||||||
tempStorage.setEncryptionPubKey(storage.getEncryptionPubKey());
|
tempStorage.setEncryptionPubKey(storage.getEncryptionPubKey());
|
||||||
tempStorage.saveWallet(exportedWallet);
|
|
||||||
for(Wallet childWallet : exportedWallet.getChildWallets()) {
|
Wallet copy = exportedWallet.copy();
|
||||||
|
tempStorage.saveWallet(copy);
|
||||||
|
for(Wallet childWallet : copy.getChildWallets()) {
|
||||||
tempStorage.saveWallet(childWallet);
|
tempStorage.saveWallet(childWallet);
|
||||||
}
|
}
|
||||||
persistence.close();
|
persistence.close();
|
||||||
|
|
|
@ -265,8 +265,11 @@ public class Storage {
|
||||||
persistence.copyWallet(walletFile, outputStream);
|
persistence.copyWallet(walletFile, outputStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean delete() {
|
public boolean delete(boolean deleteBackups) {
|
||||||
deleteBackups();
|
if(deleteBackups) {
|
||||||
|
deleteBackups();
|
||||||
|
}
|
||||||
|
|
||||||
return IOUtils.secureDelete(walletFile);
|
return IOUtils.secureDelete(walletFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,18 +738,44 @@ public class Storage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CopyWalletService extends Service<Void> {
|
||||||
|
private final Wallet wallet;
|
||||||
|
private final File newWalletFile;
|
||||||
|
|
||||||
|
public CopyWalletService(Wallet wallet, File newWalletFile) {
|
||||||
|
this.wallet = wallet;
|
||||||
|
this.newWalletFile = newWalletFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Task<Void> createTask() {
|
||||||
|
return new Task<>() {
|
||||||
|
protected Void call() throws IOException, ExportException {
|
||||||
|
Sparrow export = new Sparrow();
|
||||||
|
try(BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(newWalletFile))) {
|
||||||
|
export.exportWallet(wallet, outputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class DeleteWalletService extends ScheduledService<Boolean> {
|
public static class DeleteWalletService extends ScheduledService<Boolean> {
|
||||||
private final Storage storage;
|
private final Storage storage;
|
||||||
|
private final boolean deleteBackups;
|
||||||
|
|
||||||
public DeleteWalletService(Storage storage) {
|
public DeleteWalletService(Storage storage, boolean deleteBackups) {
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
|
this.deleteBackups = deleteBackups;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Task<Boolean> createTask() {
|
protected Task<Boolean> createTask() {
|
||||||
return new Task<>() {
|
return new Task<>() {
|
||||||
protected Boolean call() {
|
protected Boolean call() {
|
||||||
return storage.delete();
|
return storage.delete(deleteBackups);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -583,7 +583,7 @@ public class DbPersistence implements Persistence {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return dataSource.isClosed();
|
return dataSource == null || dataSource.isClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,6 +21,7 @@ public interface MixConfigDao {
|
||||||
|
|
||||||
default void addMixConfig(Wallet wallet) {
|
default void addMixConfig(Wallet wallet) {
|
||||||
if(wallet.getMixConfig() != null) {
|
if(wallet.getMixConfig() != null) {
|
||||||
|
wallet.getMixConfig().setId(null);
|
||||||
addOrUpdate(wallet, wallet.getMixConfig());
|
addOrUpdate(wallet, wallet.getMixConfig());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
<SeparatorMenuItem styleClass="osxHide" />
|
<SeparatorMenuItem styleClass="osxHide" />
|
||||||
<MenuItem styleClass="osxHide" mnemonicParsing="false" text="Preferences..." accelerator="Shortcut+P" onAction="#openPreferences"/>
|
<MenuItem styleClass="osxHide" mnemonicParsing="false" text="Preferences..." accelerator="Shortcut+P" onAction="#openPreferences"/>
|
||||||
<SeparatorMenuItem />
|
<SeparatorMenuItem />
|
||||||
|
<MenuItem fx:id="renameWallet" mnemonicParsing="false" text="Rename Wallet..." onAction="#renameWallet"/>
|
||||||
<MenuItem fx:id="deleteWallet" mnemonicParsing="false" text="Delete Wallet..." onAction="#deleteWallet"/>
|
<MenuItem fx:id="deleteWallet" mnemonicParsing="false" text="Delete Wallet..." onAction="#deleteWallet"/>
|
||||||
<MenuItem fx:id="closeTab" mnemonicParsing="false" text="Close Tab" accelerator="Shortcut+W" onAction="#closeTab"/>
|
<MenuItem fx:id="closeTab" mnemonicParsing="false" text="Close Tab" accelerator="Shortcut+W" onAction="#closeTab"/>
|
||||||
<MenuItem styleClass="osxHide" mnemonicParsing="false" text="Quit" accelerator="Shortcut+Q" onAction="#quit"/>
|
<MenuItem styleClass="osxHide" mnemonicParsing="false" text="Quit" accelerator="Shortcut+Q" onAction="#quit"/>
|
||||||
|
|
Loading…
Reference in a new issue