|
|
@ -28,13 +28,16 @@ import com.sparrowwallet.sparrow.AppServices; |
|
|
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; |
|
|
|
import com.sparrowwallet.sparrow.io.Config; |
|
|
|
import javafx.application.Platform; |
|
|
|
import javafx.beans.property.DoubleProperty; |
|
|
|
import javafx.beans.property.ObjectProperty; |
|
|
|
import javafx.beans.property.SimpleDoubleProperty; |
|
|
|
import javafx.beans.property.SimpleObjectProperty; |
|
|
|
import javafx.beans.value.ChangeListener; |
|
|
|
import javafx.beans.value.ObservableValue; |
|
|
|
import javafx.geometry.Insets; |
|
|
|
import javafx.scene.Node; |
|
|
|
import javafx.scene.control.*; |
|
|
|
import javafx.scene.layout.StackPane; |
|
|
|
import javafx.scene.layout.*; |
|
|
|
import org.controlsfx.glyphfont.Glyph; |
|
|
|
import org.controlsfx.tools.Borders; |
|
|
|
import org.slf4j.Logger; |
|
|
@ -59,13 +62,14 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> { |
|
|
|
private final WebcamService webcamService; |
|
|
|
private List<String> parts; |
|
|
|
|
|
|
|
private boolean isUr; |
|
|
|
private QRScanDialog.Result result; |
|
|
|
|
|
|
|
private static final Pattern PART_PATTERN = Pattern.compile("p(\\d+)of(\\d+) (.+)"); |
|
|
|
|
|
|
|
private final ObjectProperty<WebcamResolution> webcamResolutionProperty = new SimpleObjectProperty<>(WebcamResolution.VGA); |
|
|
|
|
|
|
|
private final DoubleProperty percentComplete = new SimpleDoubleProperty(0.0); |
|
|
|
|
|
|
|
public QRScanDialog() { |
|
|
|
this.decoder = new URDecoder(); |
|
|
|
this.legacyDecoder = new LegacyURDecoder(); |
|
|
@ -83,8 +87,23 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> { |
|
|
|
|
|
|
|
StackPane stackPane = new StackPane(); |
|
|
|
stackPane.getChildren().add(webcamView.getView()); |
|
|
|
Node wrappedView = Borders.wrap(stackPane).lineBorder().buildAll(); |
|
|
|
|
|
|
|
ProgressBar progressBar = new ProgressBar(); |
|
|
|
progressBar.setMinHeight(20); |
|
|
|
progressBar.setPadding(new Insets(0, 10, 0, 10)); |
|
|
|
progressBar.setPrefWidth(Integer.MAX_VALUE); |
|
|
|
progressBar.progressProperty().bind(percentComplete); |
|
|
|
webcamService.openingProperty().addListener((observable, oldValue, newValue) -> { |
|
|
|
if(percentComplete.get() <= 0.0) { |
|
|
|
Platform.runLater(() -> percentComplete.set(newValue ? 0.0 : -1.0)); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
VBox vBox = new VBox(20); |
|
|
|
vBox.getChildren().addAll(wrappedView, progressBar); |
|
|
|
|
|
|
|
dialogPane.setContent(Borders.wrap(stackPane).lineBorder().buildAll()); |
|
|
|
dialogPane.setContent(vBox); |
|
|
|
|
|
|
|
webcamService.resultProperty().addListener(new QRResultListener()); |
|
|
|
webcamService.setOnFailed(failedEvent -> { |
|
|
@ -111,7 +130,7 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> { |
|
|
|
final ButtonType hdButtonType = new javafx.scene.control.ButtonType("Use HD Capture", ButtonBar.ButtonData.LEFT); |
|
|
|
dialogPane.getButtonTypes().addAll(hdButtonType, cancelButtonType); |
|
|
|
dialogPane.setPrefWidth(646); |
|
|
|
dialogPane.setPrefHeight(webcamResolutionProperty.get() == WebcamResolution.HD ? 450 : 550); |
|
|
|
dialogPane.setPrefHeight(webcamResolutionProperty.get() == WebcamResolution.HD ? 490 : 590); |
|
|
|
|
|
|
|
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? result : null); |
|
|
|
} |
|
|
@ -127,11 +146,10 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> { |
|
|
|
String qrtext = qrResult.getText(); |
|
|
|
Matcher partMatcher = PART_PATTERN.matcher(qrtext); |
|
|
|
|
|
|
|
if(isUr || qrtext.toLowerCase().startsWith(UR.UR_PREFIX)) { |
|
|
|
isUr = true; |
|
|
|
|
|
|
|
if(LegacyURDecoder.isLegacyURFragment(qrtext)) { |
|
|
|
if(qrtext.toLowerCase().startsWith(UR.UR_PREFIX)) { |
|
|
|
if(LegacyURDecoder.isLegacyURFragment(qrtext.toLowerCase())) { |
|
|
|
legacyDecoder.receivePart(qrtext.toLowerCase()); |
|
|
|
Platform.runLater(() -> percentComplete.setValue(legacyDecoder.getPercentComplete())); |
|
|
|
|
|
|
|
if(legacyDecoder.isComplete()) { |
|
|
|
try { |
|
|
@ -143,6 +161,7 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> { |
|
|
|
} |
|
|
|
} else { |
|
|
|
decoder.receivePart(qrtext); |
|
|
|
Platform.runLater(() -> percentComplete.setValue(decoder.getEstimatedPercentComplete())); |
|
|
|
|
|
|
|
if(decoder.getResult() != null) { |
|
|
|
URDecoder.Result urResult = decoder.getResult(); |
|
|
@ -164,6 +183,10 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> { |
|
|
|
} |
|
|
|
parts.set(m - 1, payload); |
|
|
|
|
|
|
|
if(n > 0) { |
|
|
|
Platform.runLater(() -> percentComplete.setValue((double)parts.stream().filter(Objects::nonNull).count() / n)); |
|
|
|
} |
|
|
|
|
|
|
|
if(parts.stream().filter(Objects::nonNull).count() == n) { |
|
|
|
String complete = String.join("", parts); |
|
|
|
try { |
|
|
@ -484,6 +507,7 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> { |
|
|
|
private class QRScanDialogPane extends DialogPane { |
|
|
|
@Override |
|
|
|
protected Node createButton(ButtonType buttonType) { |
|
|
|
Node button = null; |
|
|
|
if(buttonType.getButtonData() == ButtonBar.ButtonData.LEFT) { |
|
|
|
ToggleButton hd = new ToggleButton(buttonType.getText()); |
|
|
|
hd.setSelected(webcamResolutionProperty.get() == WebcamResolution.HD); |
|
|
@ -497,10 +521,13 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> { |
|
|
|
setHdGraphic(hd, newValue); |
|
|
|
}); |
|
|
|
|
|
|
|
return hd; |
|
|
|
button = hd; |
|
|
|
} else { |
|
|
|
button = super.createButton(buttonType); |
|
|
|
} |
|
|
|
|
|
|
|
return super.createButton(buttonType); |
|
|
|
button.disableProperty().bind(webcamService.openingProperty()); |
|
|
|
return button; |
|
|
|
} |
|
|
|
|
|
|
|
private void setHdGraphic(ToggleButton hd, boolean isHd) { |
|
|
|