From fdd832746437ded2b29c1f65e19507fd2d30fa67 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Thu, 21 May 2020 11:01:59 +0200 Subject: [PATCH] usb status, key progress timing --- .DS_Store | Bin 6148 -> 6148 bytes drongo | 2 +- .../sparrowwallet/sparrow/AppController.java | 74 ++++++++++++------ .../com/sparrowwallet/sparrow/MainApp.java | 6 ++ .../sparrow/control/DevicePane.java | 2 +- .../sparrow/control/FileWalletExportPane.java | 9 ++- .../sparrow/control/UsbStatusButton.java | 42 ++++++++++ .../sparrow/event/StorageEvent.java | 28 +++++++ .../sparrow/event/TimedEvent.java | 35 +++++++++ .../sparrow/event/TimedWorkerEvent.java | 24 ------ .../sparrow/event/UsbDeviceEvent.java | 17 ++++ .../sparrow/wallet/SettingsController.java | 9 ++- .../sparrow/wallet/WalletController.java | 21 +++-- 13 files changed, 207 insertions(+), 62 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/sparrow/control/UsbStatusButton.java create mode 100644 src/main/java/com/sparrowwallet/sparrow/event/StorageEvent.java create mode 100644 src/main/java/com/sparrowwallet/sparrow/event/TimedEvent.java delete mode 100644 src/main/java/com/sparrowwallet/sparrow/event/TimedWorkerEvent.java create mode 100644 src/main/java/com/sparrowwallet/sparrow/event/UsbDeviceEvent.java diff --git a/.DS_Store b/.DS_Store index 81229e8d26382bd3469cb3d9bb2de3f1954844ac..cae61d60893b5ea2aa48159b551abb63fae27ae4 100644 GIT binary patch literal 6148 zcmeHKv2NQi5PfW%*tG*ROVExQyCgv7E^2BI0g?{Q4>Yn}SAiS_Qi5dE(tqeL^!xe& z?Ykr6l615dMZq)3lc@KOyhlnj0hrVK#R+f#V8kMRFlP0P$#W@N_QJIs(i@3!R@L*O zstevrz+_2*q`<$efV{f{9AkwNchUR%j?doyQqv^HPdH*%xIv8u%ZT$M;!HN2HSr7F zqrwtx$TF`Z)=*guuE-!hLVt_UyF`~nE^!qhe{LZQj-X`BMTmst`rXTQ7aQcFomWL& zSNz0b|4%cHm{5yHcHZJ^6i#ID!}&ZByDv2n!sqQVt%m*FkW+_!7?Hupj(sdgRgt%f zI3kG8+3O#RNMc5wBtsvIhcGgjae$tLXpX1gbVf@|CO%*dagH;5zziR8iCNf(WE`Mh z;uDeYF~tS_G1l?48s-}?UU9CLxZ|%>OFYj_cXD6N+&M50fbzCbvG-Nr9w5sKAcBJ&^r>)_?vFN$D;rkQDf@6flG7 z<@A&(xxIBOIoWG7md`9=g6phT3M;oA>xFE^Z&=j$ERzfR-1*LWw$Rca0hJ+DNrAtr Fz;6O{7)$^F delta 85 zcmZoMXfc=|#>AjHu~3+iaq?YuX$d9<2w((KKrFyeoSc-OpToFWkVA}RvjWE?=FRLJ f{2V|%K#}jvllesyfjUh^lqdW1aBPkdS-}hdzU2`{ diff --git a/drongo b/drongo index 06de1d7e..78504089 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 06de1d7e1458cb00cc242025c5e0d536633083a0 +Subproject commit 785040898babf4b198985531f61af7ce48178b17 diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index e5c5f197..9ae40372 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -12,13 +12,12 @@ import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.psbt.PSBTParseException; import com.sparrowwallet.drongo.wallet.Keystore; +import com.sparrowwallet.drongo.wallet.KeystoreSource; import com.sparrowwallet.drongo.wallet.MnemonicException; import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.event.*; -import com.sparrowwallet.sparrow.io.FileType; -import com.sparrowwallet.sparrow.io.IOUtils; -import com.sparrowwallet.sparrow.io.Storage; +import com.sparrowwallet.sparrow.io.*; import com.sparrowwallet.sparrow.transaction.TransactionController; import com.sparrowwallet.sparrow.wallet.WalletController; import com.sparrowwallet.sparrow.wallet.WalletForm; @@ -30,6 +29,7 @@ import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; +import javafx.scene.Node; import javafx.scene.control.*; import javafx.scene.input.Dragboard; import javafx.scene.input.TransferMode; @@ -263,7 +263,7 @@ public class AppController implements Initializable { SecureString password = optionalPassword.get(); Storage.LoadWalletService loadWalletService = new Storage.LoadWalletService(storage, password); loadWalletService.setOnSucceeded(workerStateEvent -> { - EventManager.get().post(new TimedWorkerEvent("Done")); + EventManager.get().post(new StorageEvent(storage.getWalletFile(), TimedEvent.Action.END, "Done")); Storage.WalletAndKey walletAndKey = loadWalletService.getValue(); try { restorePublicKeysFromSeed(walletAndKey.wallet, walletAndKey.key); @@ -276,7 +276,7 @@ public class AppController implements Initializable { } }); loadWalletService.setOnFailed(workerStateEvent -> { - EventManager.get().post(new TimedWorkerEvent("Failed")); + EventManager.get().post(new StorageEvent(storage.getWalletFile(), TimedEvent.Action.END, "Failed")); Throwable exception = loadWalletService.getException(); if(exception instanceof InvalidPasswordException) { showErrorDialog("Invalid Password", "The wallet password was invalid."); @@ -284,8 +284,8 @@ public class AppController implements Initializable { showErrorDialog("Error Opening Wallet", exception.getMessage()); } }); + EventManager.get().post(new StorageEvent(storage.getWalletFile(), TimedEvent.Action.START, "Decrypting wallet...")); loadWalletService.start(); - EventManager.get().post(new TimedWorkerEvent("Decrypting wallet...", 1000)); } else { throw new IOException("Unsupported file type"); } @@ -379,6 +379,15 @@ public class AppController implements Initializable { WalletForm walletForm = new WalletForm(storage, wallet); controller.setWalletForm(walletForm); + if(!storage.getWalletFile().exists() || wallet.containsSource(KeystoreSource.HW_USB)) { + Hwi.EnumerateService enumerateService = new Hwi.EnumerateService(null); + enumerateService.setOnSucceeded(workerStateEvent -> { + List devices = enumerateService.getValue(); + EventManager.get().post(new UsbDeviceEvent(devices)); + }); + enumerateService.start(); + } + tabs.getTabs().add(tab); return tab; } catch(IOException e) { @@ -501,26 +510,45 @@ public class AppController implements Initializable { } @Subscribe - public void timedWorker(TimedWorkerEvent event) { - if(statusTimeline != null && statusTimeline.getStatus() == Animation.Status.RUNNING) { - if(event.getTimeMills() == 0) { + public void timedWorker(TimedEvent event) { + if(event.getTimeMills() == 0) { + if(statusTimeline != null && statusTimeline.getStatus() == Animation.Status.RUNNING) { statusTimeline.stop(); - statusBar.setText(""); - statusBar.setProgress(0); } - - return; + statusBar.setText(""); + statusBar.setProgress(event.getTimeMills()); + } else if(event.getTimeMills() < 0) { + statusBar.setText(event.getStatus()); + statusBar.setProgress(event.getTimeMills()); + } else { + statusBar.setText(event.getStatus()); + statusTimeline = new Timeline( + new KeyFrame(Duration.ZERO, new KeyValue(statusBar.progressProperty(), 0)), + new KeyFrame(Duration.millis(event.getTimeMills()), e -> { + statusBar.setText(""); + statusBar.setProgress(0); + }, new KeyValue(statusBar.progressProperty(), 1)) + ); + statusTimeline.setCycleCount(1); + statusTimeline.play(); } + } - statusBar.setText(event.getStatus()); - statusTimeline = new Timeline( - new KeyFrame(Duration.ZERO, new KeyValue(statusBar.progressProperty(), 0)), - new KeyFrame(Duration.millis(event.getTimeMills()), e -> { - statusBar.setText(""); - statusBar.setProgress(0); - }, new KeyValue(statusBar.progressProperty(), 1)) - ); - statusTimeline.setCycleCount(1); - statusTimeline.play(); + @Subscribe + public void usbDevicesFound(UsbDeviceEvent event) { + if(event.getDevices().isEmpty()) { + Node usbStatus = null; + for(Node node : statusBar.getRightItems()) { + if(node instanceof UsbStatusButton) { + usbStatus = node; + } + } + if(usbStatus != null) { + statusBar.getRightItems().removeAll(usbStatus); + } + } else { + UsbStatusButton usbStatusButton = new UsbStatusButton(event.getDevices()); + statusBar.getRightItems().add(usbStatusButton); + } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/MainApp.java b/src/main/java/com/sparrowwallet/sparrow/MainApp.java index 25be1815..76802c42 100644 --- a/src/main/java/com/sparrowwallet/sparrow/MainApp.java +++ b/src/main/java/com/sparrowwallet/sparrow/MainApp.java @@ -14,6 +14,9 @@ import javafx.scene.image.Image; import javafx.stage.Stage; import org.controlsfx.glyphfont.GlyphFontRegistry; +import java.nio.file.Path; +import java.nio.file.Paths; + public class MainApp extends Application { @Override @@ -43,6 +46,9 @@ public class MainApp extends Application { // KeystoreImportDialog dlg = new KeystoreImportDialog(wallet); // dlg.showAndWait(); + Path path = Paths.get("").toAbsolutePath(); + System.out.println(path.toFile().getAbsolutePath()); + stage.show(); } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java index 02e09e30..b1982858 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java @@ -300,7 +300,7 @@ public class DevicePane extends TitledDescriptionPane { String xpub = getXpubService.getValue(); Keystore keystore = new Keystore(); - keystore.setLabel(device.getModel().toDisplayString() + " " + device.getFingerprint().toUpperCase()); + keystore.setLabel(device.getModel().toDisplayString()); keystore.setSource(KeystoreSource.HW_USB); keystore.setWalletModel(device.getModel()); keystore.setKeyDerivation(new KeyDerivation(device.getFingerprint(), derivationPath)); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/FileWalletExportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/FileWalletExportPane.java index eae29c9a..182db16e 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/FileWalletExportPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/FileWalletExportPane.java @@ -3,7 +3,8 @@ package com.sparrowwallet.sparrow.control; import com.sparrowwallet.drongo.SecureString; import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.sparrow.EventManager; -import com.sparrowwallet.sparrow.event.TimedWorkerEvent; +import com.sparrowwallet.sparrow.event.StorageEvent; +import com.sparrowwallet.sparrow.event.TimedEvent; import com.sparrowwallet.sparrow.event.WalletExportEvent; import com.sparrowwallet.sparrow.io.Storage; import com.sparrowwallet.sparrow.io.WalletExport; @@ -59,7 +60,7 @@ public class FileWalletExportPane extends TitledDescriptionPane { if(password.isPresent()) { Storage.DecryptWalletService decryptWalletService = new Storage.DecryptWalletService(copy, password.get()); decryptWalletService.setOnSucceeded(workerStateEvent -> { - EventManager.get().post(new TimedWorkerEvent("Done")); + EventManager.get().post(new StorageEvent(file, TimedEvent.Action.END, "Done")); Wallet decryptedWallet = decryptWalletService.getValue(); try { OutputStream outputStream = new FileOutputStream(file); @@ -76,11 +77,11 @@ public class FileWalletExportPane extends TitledDescriptionPane { } }); decryptWalletService.setOnFailed(workerStateEvent -> { - EventManager.get().post(new TimedWorkerEvent("Failed")); + EventManager.get().post(new StorageEvent(file, TimedEvent.Action.END, "Failed")); setError("Export Error", decryptWalletService.getException().getMessage()); }); + EventManager.get().post(new StorageEvent(file, TimedEvent.Action.START, "Decrypting wallet...")); decryptWalletService.start(); - EventManager.get().post(new TimedWorkerEvent("Decrypting wallet...", 1000)); } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/UsbStatusButton.java b/src/main/java/com/sparrowwallet/sparrow/control/UsbStatusButton.java new file mode 100644 index 00000000..37db5a41 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/control/UsbStatusButton.java @@ -0,0 +1,42 @@ +package com.sparrowwallet.sparrow.control; + +import com.sparrowwallet.sparrow.glyphfont.FontAwesome5Brands; +import com.sparrowwallet.sparrow.io.Device; +import javafx.geometry.Side; +import javafx.scene.Node; +import javafx.scene.control.*; +import org.controlsfx.glyphfont.Glyph; + +import java.util.List; + +public class UsbStatusButton extends MenuButton { + private final List devices; + + public UsbStatusButton(List devices) { + super(""); + setGraphic(getIcon()); + this.devices = devices; + + this.setPopupSide(Side.TOP); + + for(Device device : devices) { + MenuItem deviceItem = new MenuItem(device.getModel().toDisplayString()); + getItems().add(deviceItem); + } + } + + private Node getIcon() { + Glyph usb = new Glyph(FontAwesome5Brands.FONT_NAME, FontAwesome5Brands.Glyph.USB); + usb.setFontSize(10); + return usb; + } + + private class UsbStatusContextMenu extends ContextMenu { + public UsbStatusContextMenu() { + for(Device device : devices) { + MenuItem deviceItem = new MenuItem(device.getModel().toDisplayString()); + getItems().add(deviceItem); + } + } + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/event/StorageEvent.java b/src/main/java/com/sparrowwallet/sparrow/event/StorageEvent.java new file mode 100644 index 00000000..985981f3 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/event/StorageEvent.java @@ -0,0 +1,28 @@ +package com.sparrowwallet.sparrow.event; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class StorageEvent extends TimedEvent { + private static boolean firstRunDone = false; + private static int keyDerivationPeriod = -1; + private static final Map eventTime = new HashMap<>(); + + public StorageEvent(File file, Action action, String status) { + super(action, status); + + if(action == Action.START) { + eventTime.put(file, System.currentTimeMillis()); + timeMills = keyDerivationPeriod; + } else if(action == Action.END) { + long start = eventTime.get(file); + if(firstRunDone) { + keyDerivationPeriod = (int)(System.currentTimeMillis() - start); + } + firstRunDone = true; + System.out.println(keyDerivationPeriod); + timeMills = 0; + } + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/event/TimedEvent.java b/src/main/java/com/sparrowwallet/sparrow/event/TimedEvent.java new file mode 100644 index 00000000..cd46f030 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/event/TimedEvent.java @@ -0,0 +1,35 @@ +package com.sparrowwallet.sparrow.event; + +public class TimedEvent { + private final Action action; + private final String status; + protected int timeMills; + + public TimedEvent(Action action, String status) { + this.action = action; + this.status = status; + this.timeMills = 0; + } + + public TimedEvent(Action action, String status, int timeMills) { + this.action = action; + this.status = status; + this.timeMills = timeMills; + } + + public Action getAction() { + return action; + } + + public String getStatus() { + return status; + } + + public int getTimeMills() { + return timeMills; + } + + public enum Action { + START, END; + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/event/TimedWorkerEvent.java b/src/main/java/com/sparrowwallet/sparrow/event/TimedWorkerEvent.java deleted file mode 100644 index 1cf38828..00000000 --- a/src/main/java/com/sparrowwallet/sparrow/event/TimedWorkerEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.sparrowwallet.sparrow.event; - -public class TimedWorkerEvent { - private final String status; - private final int timeMills; - - public TimedWorkerEvent(String status) { - this.status = status; - this.timeMills = 0; - } - - public TimedWorkerEvent(String status, int timeMills) { - this.status = status; - this.timeMills = timeMills; - } - - public String getStatus() { - return status; - } - - public int getTimeMills() { - return timeMills; - } -} diff --git a/src/main/java/com/sparrowwallet/sparrow/event/UsbDeviceEvent.java b/src/main/java/com/sparrowwallet/sparrow/event/UsbDeviceEvent.java new file mode 100644 index 00000000..86939c0d --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/event/UsbDeviceEvent.java @@ -0,0 +1,17 @@ +package com.sparrowwallet.sparrow.event; + +import com.sparrowwallet.sparrow.io.Device; + +import java.util.List; + +public class UsbDeviceEvent { + private List devices; + + public UsbDeviceEvent(List devices) { + this.devices = devices; + } + + public List getDevices() { + return devices; + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java index eedb0710..92f8a7f9 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java @@ -15,7 +15,8 @@ import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.CopyableLabel; import com.sparrowwallet.sparrow.control.WalletPasswordDialog; import com.sparrowwallet.sparrow.event.SettingsChangedEvent; -import com.sparrowwallet.sparrow.event.TimedWorkerEvent; +import com.sparrowwallet.sparrow.event.StorageEvent; +import com.sparrowwallet.sparrow.event.TimedEvent; import com.sparrowwallet.sparrow.event.WalletChangedEvent; import com.sparrowwallet.sparrow.io.Storage; import javafx.beans.property.SimpleIntegerProperty; @@ -276,7 +277,7 @@ public class SettingsController extends WalletFormController implements Initiali } else { Storage.KeyDerivationService keyDerivationService = new Storage.KeyDerivationService(walletForm.getStorage(), password.get()); keyDerivationService.setOnSucceeded(workerStateEvent -> { - EventManager.get().post(new TimedWorkerEvent("Done")); + EventManager.get().post(new StorageEvent(walletForm.getWalletFile(), TimedEvent.Action.END, "Done")); ECKey encryptionFullKey = keyDerivationService.getValue(); Key key = null; @@ -308,13 +309,13 @@ public class SettingsController extends WalletFormController implements Initiali } }); keyDerivationService.setOnFailed(workerStateEvent -> { - EventManager.get().post(new TimedWorkerEvent("Failed")); + EventManager.get().post(new StorageEvent(walletForm.getWalletFile(), TimedEvent.Action.END, "Failed")); AppController.showErrorDialog("Error saving wallet", keyDerivationService.getException().getMessage()); revert.setDisable(false); apply.setDisable(false); }); + EventManager.get().post(new StorageEvent(walletForm.getWalletFile(), TimedEvent.Action.START, "Encrypting wallet...")); keyDerivationService.start(); - EventManager.get().post(new TimedWorkerEvent("Encrypting wallet...", 1000)); } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletController.java index 432f571b..b874cd0b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletController.java @@ -1,7 +1,9 @@ package com.sparrowwallet.sparrow.wallet; +import com.google.common.eventbus.Subscribe; import com.sparrowwallet.sparrow.AppController; import com.sparrowwallet.sparrow.EventManager; +import com.sparrowwallet.sparrow.event.WalletChangedEvent; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; @@ -65,13 +67,17 @@ public class WalletController extends WalletFormController implements Initializa } }); - if(!walletForm.getWallet().isValid()) { - for(Toggle toggle : walletMenu.getToggles()) { - if(toggle.getUserData().equals(Function.SETTINGS)) { + configure(walletForm.getWallet().isValid()); + } + + public void configure(boolean isWalletValid) { + for(Toggle toggle : walletMenu.getToggles()) { + if(toggle.getUserData().equals(Function.SETTINGS)) { + if(!isWalletValid) { toggle.setSelected(true); - } else { - ((ToggleButton)toggle).setDisable(true); } + } else { + ((ToggleButton)toggle).setDisable(!isWalletValid); } } } @@ -85,4 +91,9 @@ public class WalletController extends WalletFormController implements Initializa } }); } + + @Subscribe + public void walletChanged(WalletChangedEvent event) { + configure(walletForm.getWallet().isValid()); + } }