Craig Raw
5 years ago
19 changed files with 340 additions and 45 deletions
@ -1 +1 @@ |
|||
Subproject commit ed056bc49fb919799f70a6d7ee2dd65a38c25b5d |
|||
Subproject commit d740895bd68f0ded97e382e5944feb26fa759875 |
@ -0,0 +1,153 @@ |
|||
package com.sparrowwallet.sparrow.control; |
|||
|
|||
import com.sparrowwallet.drongo.wallet.Keystore; |
|||
import com.sparrowwallet.drongo.wallet.Wallet; |
|||
import com.sparrowwallet.sparrow.EventManager; |
|||
import com.sparrowwallet.sparrow.event.KeystoreImportEvent; |
|||
import com.sparrowwallet.sparrow.external.KeystoreFileImport; |
|||
import javafx.application.Platform; |
|||
import javafx.geometry.Insets; |
|||
import javafx.geometry.Pos; |
|||
import javafx.scene.Node; |
|||
import javafx.scene.control.Button; |
|||
import javafx.scene.control.Label; |
|||
import javafx.scene.control.TitledPane; |
|||
import javafx.scene.image.Image; |
|||
import javafx.scene.image.ImageView; |
|||
import javafx.scene.layout.HBox; |
|||
import javafx.scene.layout.Priority; |
|||
import javafx.scene.layout.VBox; |
|||
import javafx.stage.FileChooser; |
|||
import javafx.stage.Stage; |
|||
import org.controlsfx.control.HyperlinkLabel; |
|||
|
|||
import java.io.*; |
|||
|
|||
public class KeystoreFileImportPane extends TitledPane { |
|||
private final KeystoreImportAccordion importAccordion; |
|||
private final Wallet wallet; |
|||
private final KeystoreFileImport importer; |
|||
|
|||
private Label mainLabel; |
|||
private HyperlinkLabel descriptionLabel; |
|||
|
|||
public KeystoreFileImportPane(KeystoreImportAccordion importAccordion, Wallet wallet, KeystoreFileImport importer) { |
|||
this.importAccordion = importAccordion; |
|||
this.wallet = wallet; |
|||
this.importer = importer; |
|||
|
|||
setPadding(Insets.EMPTY); |
|||
|
|||
setGraphic(getTitle()); |
|||
getStyleClass().add("importpane"); |
|||
setContent(getContentBox(importer.getKeystoreImportDescription())); |
|||
|
|||
Platform.runLater(() -> { |
|||
Node arrow = this.lookup(".arrow"); |
|||
if(arrow != null) { |
|||
arrow.setVisible(false); |
|||
arrow.setManaged(false); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private Node getTitle() { |
|||
HBox listItem = new HBox(); |
|||
listItem.setPadding(new Insets(10, 20, 10, 10)); |
|||
listItem.setSpacing(10); |
|||
|
|||
HBox imageBox = new HBox(); |
|||
imageBox.setMinWidth(50); |
|||
imageBox.setMinHeight(50); |
|||
listItem.getChildren().add(imageBox); |
|||
|
|||
Image image = new Image("image/" + importer.getWalletModel().getType() + ".png", 50, 50, true, true); |
|||
if (!image.isError()) { |
|||
ImageView imageView = new ImageView(); |
|||
imageView.setImage(image); |
|||
imageBox.getChildren().add(imageView); |
|||
} |
|||
|
|||
VBox labelsBox = new VBox(); |
|||
labelsBox.setSpacing(5); |
|||
labelsBox.setAlignment(Pos.CENTER_LEFT); |
|||
this.mainLabel = new Label(); |
|||
mainLabel.setText(importer.getName()); |
|||
mainLabel.getStyleClass().add("main-label"); |
|||
labelsBox.getChildren().add(mainLabel); |
|||
|
|||
this.descriptionLabel = new HyperlinkLabel(); |
|||
|
|||
labelsBox.getChildren().add(descriptionLabel); |
|||
descriptionLabel.getStyleClass().add("description-label"); |
|||
descriptionLabel.setText("Keystore file import [View Details...]"); |
|||
descriptionLabel.setOnAction(event -> { |
|||
setExpanded(true); |
|||
}); |
|||
listItem.getChildren().add(labelsBox); |
|||
HBox.setHgrow(labelsBox, Priority.ALWAYS); |
|||
|
|||
HBox buttonBox = new HBox(); |
|||
buttonBox.setAlignment(Pos.CENTER_RIGHT); |
|||
|
|||
Button importButton = new Button("Import File..."); |
|||
importButton.setAlignment(Pos.CENTER_RIGHT); |
|||
importButton.setOnAction(event -> { |
|||
importFile(); |
|||
}); |
|||
|
|||
buttonBox.getChildren().add(importButton); |
|||
listItem.getChildren().add(buttonBox); |
|||
|
|||
this.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> { |
|||
listItem.setPrefWidth(newValue.getWidth()); |
|||
}); |
|||
|
|||
return listItem; |
|||
} |
|||
|
|||
private void importFile() { |
|||
Stage window = new Stage(); |
|||
|
|||
FileChooser fileChooser = new FileChooser(); |
|||
fileChooser.setTitle("Open " + importer.getWalletModel().toDisplayString() + " keystore"); |
|||
fileChooser.getExtensionFilters().addAll( |
|||
new FileChooser.ExtensionFilter("All Files", "*.*"), |
|||
new FileChooser.ExtensionFilter("JSON", "*.json") |
|||
); |
|||
|
|||
File file = fileChooser.showOpenDialog(window); |
|||
if(file != null) { |
|||
importFile(file); |
|||
} |
|||
} |
|||
|
|||
private void importFile(File file) { |
|||
if(file.exists()) { |
|||
try { |
|||
InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); |
|||
Keystore keystore = importer.getKeystore(wallet.getScriptType(), inputStream); |
|||
EventManager.get().post(new KeystoreImportEvent(keystore)); |
|||
} catch (Exception e) { |
|||
setExpanded(false); |
|||
descriptionLabel.getStyleClass().remove("description-label"); |
|||
descriptionLabel.getStyleClass().add("description-error"); |
|||
descriptionLabel.setText("Error Importing [View Details...]"); |
|||
setContent(getContentBox(e.getMessage())); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private Node getContentBox(String message) { |
|||
Label details = new Label(message); |
|||
details.setWrapText(true); |
|||
|
|||
HBox contentBox = new HBox(); |
|||
contentBox.setAlignment(Pos.TOP_RIGHT); |
|||
contentBox.getChildren().add(details); |
|||
contentBox.setPadding(new Insets(10, 30, 10, 30)); |
|||
contentBox.setPrefHeight(60); |
|||
|
|||
return contentBox; |
|||
} |
|||
} |
@ -0,0 +1,32 @@ |
|||
package com.sparrowwallet.sparrow.control; |
|||
|
|||
import com.sparrowwallet.drongo.wallet.Wallet; |
|||
import com.sparrowwallet.sparrow.external.KeystoreFileImport; |
|||
import com.sparrowwallet.sparrow.external.KeystoreImport; |
|||
import com.sparrowwallet.sparrow.external.KeystoreMnemonicImport; |
|||
import javafx.collections.ObservableList; |
|||
import javafx.scene.control.Accordion; |
|||
|
|||
import java.util.List; |
|||
|
|||
public class KeystoreImportAccordion extends Accordion { |
|||
private List<KeystoreImport> importers; |
|||
|
|||
public void setKeystoreImporters(Wallet wallet, ObservableList<KeystoreImport> importers) { |
|||
this.importers = importers; |
|||
|
|||
for(KeystoreImport importer : importers) { |
|||
KeystoreFileImportPane importPane = null; |
|||
|
|||
if(importer instanceof KeystoreFileImport) { |
|||
importPane = new KeystoreFileImportPane(this, wallet, (KeystoreFileImport)importer); |
|||
} else if(importer instanceof KeystoreMnemonicImport) { |
|||
//TODO:
|
|||
} else { |
|||
throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass()); |
|||
} |
|||
|
|||
this.getPanes().add(importPane); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,10 @@ |
|||
package com.sparrowwallet.sparrow.external; |
|||
|
|||
import com.sparrowwallet.drongo.protocol.ScriptType; |
|||
import com.sparrowwallet.drongo.wallet.Keystore; |
|||
|
|||
import java.io.InputStream; |
|||
|
|||
public interface KeystoreFileImport extends KeystoreImport { |
|||
Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException; |
|||
} |
@ -1,13 +1,10 @@ |
|||
package com.sparrowwallet.sparrow.external; |
|||
|
|||
import com.sparrowwallet.drongo.policy.PolicyType; |
|||
import com.sparrowwallet.drongo.protocol.ScriptType; |
|||
import com.sparrowwallet.drongo.wallet.Keystore; |
|||
|
|||
import java.io.InputStream; |
|||
import com.sparrowwallet.drongo.wallet.WalletModel; |
|||
|
|||
public interface KeystoreImport extends Import { |
|||
PolicyType getPolicyType(); |
|||
Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException; |
|||
PolicyType getKeystorePolicyType(); |
|||
WalletModel getWalletModel(); |
|||
String getKeystoreImportDescription(); |
|||
} |
|||
|
@ -0,0 +1,8 @@ |
|||
package com.sparrowwallet.sparrow.external; |
|||
|
|||
import com.sparrowwallet.drongo.protocol.ScriptType; |
|||
import com.sparrowwallet.drongo.wallet.Keystore; |
|||
|
|||
public interface KeystoreMnemonicImport extends KeystoreImport { |
|||
Keystore getKeystore(ScriptType scriptType, String[] mnemonicWords, String passphrase) throws ImportException; |
|||
} |
@ -0,0 +1,28 @@ |
|||
package com.sparrowwallet.sparrow.keystoreimport; |
|||
|
|||
import com.sparrowwallet.drongo.policy.PolicyType; |
|||
import com.sparrowwallet.sparrow.control.KeystoreImportAccordion; |
|||
import com.sparrowwallet.sparrow.external.ColdcardMultisig; |
|||
import com.sparrowwallet.sparrow.external.ColdcardSinglesig; |
|||
import com.sparrowwallet.sparrow.external.KeystoreImport; |
|||
import javafx.collections.FXCollections; |
|||
import javafx.fxml.FXML; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
|
|||
public class UsbAirgappedController extends KeystoreImportDetailController { |
|||
@FXML |
|||
private KeystoreImportAccordion importAccordion; |
|||
|
|||
public void initializeView() { |
|||
List<KeystoreImport> importers = Collections.emptyList(); |
|||
if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) { |
|||
importers = List.of(new ColdcardSinglesig()); |
|||
} else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) { |
|||
importers = List.of(new ColdcardMultisig()); |
|||
} |
|||
|
|||
importAccordion.setKeystoreImporters(getMasterController().getWallet(), FXCollections.observableList(importers)); |
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
|
|||
<?import java.lang.*?> |
|||
<?import java.util.*?> |
|||
<?import javafx.scene.*?> |
|||
<?import javafx.scene.control.*?> |
|||
<?import javafx.scene.layout.*?> |
|||
|
|||
<?import com.sparrowwallet.sparrow.control.KeystoreImportAccordion?> |
|||
|
|||
<AnchorPane stylesheets="@keystoreimport.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.UsbAirgappedController"> |
|||
<ScrollPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" fitToWidth="true"> |
|||
<KeystoreImportAccordion fx:id="importAccordion" /> |
|||
</ScrollPane> |
|||
</AnchorPane> |
Loading…
Reference in new issue