mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 13:16:44 +00:00
support saving tapsigner backup as binary file
This commit is contained in:
parent
40a3eb5d4f
commit
258d46a253
2 changed files with 51 additions and 3 deletions
|
@ -11,10 +11,13 @@ import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
|
import javafx.stage.Stage;
|
||||||
import org.controlsfx.glyphfont.Glyph;
|
import org.controlsfx.glyphfont.Glyph;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class TextAreaDialog extends Dialog<String> {
|
public class TextAreaDialog extends Dialog<String> {
|
||||||
|
@ -22,6 +25,8 @@ public class TextAreaDialog extends Dialog<String> {
|
||||||
|
|
||||||
private final TextArea textArea;
|
private final TextArea textArea;
|
||||||
private final String defaultValue;
|
private final String defaultValue;
|
||||||
|
private final String fileName;
|
||||||
|
private final byte[] fileBytes;
|
||||||
|
|
||||||
public TextAreaDialog() {
|
public TextAreaDialog() {
|
||||||
this("");
|
this("");
|
||||||
|
@ -31,7 +36,11 @@ public class TextAreaDialog extends Dialog<String> {
|
||||||
this(defaultValue, true);
|
this(defaultValue, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextAreaDialog(@NamedArg("defaultValue") String defaultValue, @NamedArg("editable") boolean editable) {
|
public TextAreaDialog(String defaultValue, boolean editable) {
|
||||||
|
this(defaultValue, editable, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextAreaDialog(@NamedArg("defaultValue") String defaultValue, @NamedArg("editable") boolean editable, @NamedArg("fileName") String fileName, @NamedArg("fileBytes") byte[] fileBytes) {
|
||||||
final DialogPane dialogPane = new TextAreaDialogPane();
|
final DialogPane dialogPane = new TextAreaDialogPane();
|
||||||
setDialogPane(dialogPane);
|
setDialogPane(dialogPane);
|
||||||
|
|
||||||
|
@ -48,6 +57,8 @@ public class TextAreaDialog extends Dialog<String> {
|
||||||
HBox.setHgrow(this.textArea, Priority.ALWAYS);
|
HBox.setHgrow(this.textArea, Priority.ALWAYS);
|
||||||
|
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.fileBytes = fileBytes;
|
||||||
|
|
||||||
dialogPane.setContent(hbox);
|
dialogPane.setContent(hbox);
|
||||||
dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm());
|
dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm());
|
||||||
|
@ -60,6 +71,9 @@ public class TextAreaDialog extends Dialog<String> {
|
||||||
|
|
||||||
final ButtonType scanButtonType = new javafx.scene.control.ButtonType("Scan QR", ButtonBar.ButtonData.LEFT);
|
final ButtonType scanButtonType = new javafx.scene.control.ButtonType("Scan QR", ButtonBar.ButtonData.LEFT);
|
||||||
dialogPane.getButtonTypes().add(scanButtonType);
|
dialogPane.getButtonTypes().add(scanButtonType);
|
||||||
|
} else if(fileBytes != null) {
|
||||||
|
final ButtonType saveButtonType = new javafx.scene.control.ButtonType("Save File...", ButtonBar.ButtonData.LEFT);
|
||||||
|
dialogPane.getButtonTypes().add(saveButtonType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform.runLater(textArea::requestFocus);
|
Platform.runLater(textArea::requestFocus);
|
||||||
|
@ -86,7 +100,7 @@ public class TextAreaDialog extends Dialog<String> {
|
||||||
@Override
|
@Override
|
||||||
protected Node createButton(ButtonType buttonType) {
|
protected Node createButton(ButtonType buttonType) {
|
||||||
Node button;
|
Node button;
|
||||||
if(buttonType.getButtonData() == ButtonBar.ButtonData.LEFT) {
|
if(buttonType.getButtonData() == ButtonBar.ButtonData.LEFT && buttonType.getText().equals("Scan QR")) {
|
||||||
Button scanButton = new Button(buttonType.getText());
|
Button scanButton = new Button(buttonType.getText());
|
||||||
scanButton.setGraphicTextGap(5);
|
scanButton.setGraphicTextGap(5);
|
||||||
scanButton.setGraphic(getGlyph(FontAwesome5.Glyph.CAMERA));
|
scanButton.setGraphic(getGlyph(FontAwesome5.Glyph.CAMERA));
|
||||||
|
@ -118,6 +132,38 @@ public class TextAreaDialog extends Dialog<String> {
|
||||||
});
|
});
|
||||||
|
|
||||||
button = scanButton;
|
button = scanButton;
|
||||||
|
} else if(buttonType.getButtonData() == ButtonBar.ButtonData.LEFT && buttonType.getText().equals("Save File...")) {
|
||||||
|
Button saveButton = new Button(buttonType.getText());
|
||||||
|
|
||||||
|
final ButtonBar.ButtonData buttonData = buttonType.getButtonData();
|
||||||
|
ButtonBar.setButtonData(saveButton, buttonData);
|
||||||
|
|
||||||
|
saveButton.setOnAction(event -> {
|
||||||
|
Stage window = new Stage();
|
||||||
|
|
||||||
|
FileChooser fileChooser = new FileChooser();
|
||||||
|
fileChooser.setTitle("Save File");
|
||||||
|
|
||||||
|
if(fileName != null) {
|
||||||
|
fileChooser.setInitialFileName(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppServices.moveToActiveWindowScreen(window, 800, 450);
|
||||||
|
File file = fileChooser.showSaveDialog(window);
|
||||||
|
if(file != null) {
|
||||||
|
try {
|
||||||
|
try(OutputStream outputStream = new FileOutputStream(file)) {
|
||||||
|
outputStream.write(fileBytes);
|
||||||
|
outputStream.flush();
|
||||||
|
}
|
||||||
|
} catch(IOException e) {
|
||||||
|
log.error("Error saving file", e);
|
||||||
|
AppServices.showErrorDialog("Error saving file", "Cannot write to " + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
button = saveButton;
|
||||||
} else {
|
} else {
|
||||||
button = super.createButton(buttonType);
|
button = super.createButton(buttonType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import tornadofx.control.Field;
|
||||||
|
|
||||||
import javax.smartcardio.CardException;
|
import javax.smartcardio.CardException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -476,7 +477,8 @@ public class KeystoreController extends WalletFormController implements Initiali
|
||||||
Service<String> backupService = cardApi.getBackupService();
|
Service<String> backupService = cardApi.getBackupService();
|
||||||
backupService.setOnSucceeded(event -> {
|
backupService.setOnSucceeded(event -> {
|
||||||
String backup = backupService.getValue();
|
String backup = backupService.getValue();
|
||||||
TextAreaDialog backupDialog = new TextAreaDialog(backup, false);
|
String filename = fingerprint.getText() + ".aes";
|
||||||
|
TextAreaDialog backupDialog = new TextAreaDialog(backup, false, filename, Base64.getDecoder().decode(backup));
|
||||||
backupDialog.setTitle("Backup Private Key");
|
backupDialog.setTitle("Backup Private Key");
|
||||||
backupDialog.getDialogPane().setHeaderText((requiresBackup ? "Please backup first by saving" : "Save") + " the following text in a safe place. It contains an encrypted copy of the card's private key, and can be decrypted using the backup key written on the back of the card.");
|
backupDialog.getDialogPane().setHeaderText((requiresBackup ? "Please backup first by saving" : "Save") + " the following text in a safe place. It contains an encrypted copy of the card's private key, and can be decrypted using the backup key written on the back of the card.");
|
||||||
backupDialog.showAndWait();
|
backupDialog.showAndWait();
|
||||||
|
|
Loading…
Reference in a new issue